diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 85c4fc8458..78542a2942 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -10,6 +10,55 @@ env: CTEST_OUTPUT_ON_FAILURE: 1 jobs: + emscripten: + name: Emscripten + + runs-on: ubuntu-20.04 + container: + # If you change this version, change the number in the cache step too. + image: emscripten/emsdk:2.0.10 + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Setup cache + uses: actions/cache@v2 + with: + path: /emsdk/upstream/emscripten/cache + key: 2.0.10-${{ runner.os }} + + - name: Build (host tools) + run: | + mkdir build-host + cd build-host + + echo "::group::CMake" + cmake .. -DOPTION_TOOLS_ONLY=ON + echo "::endgroup::" + + echo "::group::Build" + echo "Running on $(nproc) cores" + make -j$(nproc) tools + echo "::endgroup::" + + - name: Install GCC problem matcher + uses: ammaraskar/gcc-problem-matcher@master + + - name: Build + run: | + mkdir build + cd build + + echo "::group::CMake" + emcmake cmake .. -DHOST_BINARY_DIR=../build-host + echo "::endgroup::" + + echo "::group::Build" + echo "Running on $(nproc) cores" + emmake make -j$(nproc) + echo "::endgroup::" + linux: name: Linux diff --git a/.github/workflows/preview_build.yml b/.github/workflows/preview_build.yml new file mode 100644 index 0000000000..9aea890bce --- /dev/null +++ b/.github/workflows/preview_build.yml @@ -0,0 +1,133 @@ +name: Preview build + +on: + repository_dispatch: + types: + - Preview* + +jobs: + preview: + name: Build preview + + runs-on: ubuntu-20.04 + container: + # If you change this version, change the number in the cache step too. + image: emscripten/emsdk:2.0.10 + # uid=1001(runner) gid=121(docker) + options: -u 1001:121 + + steps: + - name: Update deployment status to in progress + uses: octokit/request-action@v2.x + with: + route: POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses + mediaType: | + previews: + - ant-man + - flash + owner: ${{ github.event.repository.owner.login }} + repo: ${{ github.event.repository.name }} + deployment_id: ${{ github.event.client_payload.deployment_id }} + state: in_progress + env: + GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }} + + - name: Checkout + uses: actions/checkout@v2 + with: + ref: ${{ github.event.client_payload.sha }} + + - name: Name branch + run: | + name=$(echo "${{ github.event.client_payload.folder }}") + git checkout -b ${name} + + - name: Setup cache + uses: actions/cache@v2 + with: + path: /emsdk/upstream/emscripten/cache + key: 2.0.10-${{ runner.os }} + + - name: Build (host tools) + run: | + mkdir build-host + cd build-host + + echo "::group::CMake" + cmake .. -DOPTION_TOOLS_ONLY=ON + echo "::endgroup::" + + echo "::group::Build" + echo "Running on $(nproc) cores" + make -j$(nproc) tools + echo "::endgroup::" + + - name: Install GCC problem matcher + uses: ammaraskar/gcc-problem-matcher@master + + - name: Build + run: | + mkdir build + cd build + + echo "::group::CMake" + emcmake cmake .. \ + -DHOST_BINARY_DIR=../build-host \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + # EOF + echo "::endgroup::" + + echo "::group::Build" + echo "Running on $(nproc) cores" + emmake make -j$(nproc) + echo "::endgroup::" + + - name: Publish preview + run: | + # setuptools is missing in this Docker image, which breaks installing + # awscli. So we need to do this in two steps to recover sanity. + pip3 install setuptools + pip3 install awscli + + ~/.local/bin/aws s3 cp --only-show-errors build/openttd.data s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/ + ~/.local/bin/aws s3 cp --only-show-errors build/openttd.html s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/ + ~/.local/bin/aws s3 cp --only-show-errors build/openttd.js s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/ + ~/.local/bin/aws s3 cp --only-show-errors build/openttd.wasm s3://${{ secrets.PREVIEW_S3_BUCKET }}/${{ github.event.client_payload.folder }}/ + + # Invalidate the cache of the CloudFront distribution + ~/.local/bin/aws cloudfront create-invalidation --distribution-id ${{ secrets.PREVIEW_CF_DISTRIBUTION_ID }} --paths "/${{ github.event.client_payload.folder }}/*" + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + - name: Update deployment status to success + uses: octokit/request-action@v2.x + with: + route: POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses + mediaType: | + previews: + - ant-man + - flash + owner: ${{ github.event.repository.owner.login }} + repo: ${{ github.event.repository.name }} + deployment_id: ${{ github.event.client_payload.deployment_id }} + state: success + environment_url: https://preview.openttd.org/${{ github.event.client_payload.folder }}/ + env: + GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }} + + - if: failure() + name: Update deployment status to failure + uses: octokit/request-action@v2.x + with: + route: POST /repos/{owner}/{repo}/deployments/{deployment_id}/statuses + mediaType: | + previews: + - ant-man + - flash + owner: ${{ github.event.repository.owner.login }} + repo: ${{ github.event.repository.name }} + deployment_id: ${{ github.event.client_payload.deployment_id }} + state: failure + env: + GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }} diff --git a/.github/workflows/preview_label.yml b/.github/workflows/preview_label.yml new file mode 100644 index 0000000000..6b3e17ea1a --- /dev/null +++ b/.github/workflows/preview_label.yml @@ -0,0 +1,66 @@ +name: Preview label + +on: + pull_request_target: + types: + - labeled + +env: + TEAM_CORE_DEVELOPER: core-developers + +jobs: + check_preview_label: + name: Check for preview label + if: github.event.action == 'labeled' && github.event.label.name == 'preview' + + runs-on: ubuntu-20.04 + + steps: + - name: Check if label was added by core developer + id: core_developer + continue-on-error: true + uses: octokit/request-action@v2.x + with: + route: GET /orgs/OpenTTD/teams/${{ env.TEAM_CORE_DEVELOPER }}/memberships/${{ github.event.sender.login }} + env: + GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }} + + - if: steps.core_developer.outcome == 'failure' + name: Remove preview label if not core developer + uses: octokit/request-action@v2.x + with: + route: DELETE /repos/{owner}/{repo}/issues/{issue_number}/labels/preview + owner: ${{ github.event.repository.owner.login }} + repo: ${{ github.event.repository.name }} + issue_number: ${{ github.event.number }} + env: + GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }} + + - if: steps.core_developer.outcome == 'success' + name: Create deployment + id: deployment + uses: octokit/request-action@v2.x + with: + route: POST /repos/{owner}/{repo}/deployments + mediaType: | + previews: + - ant-man + - flash + owner: ${{ github.event.repository.owner.login }} + repo: ${{ github.event.repository.name }} + ref: ${{ github.event.pull_request.head.sha }} + task: deploy:preview + auto_merge: false + required_contexts: "[]" + environment: preview-pr-${{ github.event.number }} + description: "Preview for Pull Request #${{ github.event.number }}" + env: + GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }} + + - if: steps.core_developer.outcome == 'success' + name: Trigger 'preview build' + uses: peter-evans/repository-dispatch@v1 + with: + token: ${{ secrets.PREVIEW_GITHUB_TOKEN }} + event-type: "Preview build #${{ github.event.number }}" + client-payload: '{"folder": "pr${{ github.event.number }}", "sha": "${{ github.event.pull_request.head.sha }}", "deployment_id": "${{ fromJson(steps.deployment.outputs.data).id }}"}' diff --git a/.github/workflows/preview_push.yml b/.github/workflows/preview_push.yml new file mode 100644 index 0000000000..cb68c8f6ce --- /dev/null +++ b/.github/workflows/preview_push.yml @@ -0,0 +1,66 @@ +name: Preview push + +on: + pull_request_target: + types: + - synchronize + +jobs: + check_new_preview: + name: Check preview needs update + + runs-on: ubuntu-20.04 + + steps: + - name: Check if earlier preview exists + id: earlier_preview + uses: octokit/request-action@v2.x + with: + route: GET /repos/{owner}/{repo}/deployments + owner: ${{ github.event.repository.owner.login }} + repo: ${{ github.event.repository.name }} + environment: preview-pr-${{ github.event.number }} + per_page: 1 + env: + GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }} + + - if: toJson(fromJson(steps.earlier_preview.outputs.data)) != '[]' + name: Check for preview label + id: preview_label + uses: octokit/request-action@v2.x + with: + route: GET /repos/{owner}/{repo}/issues/{issue_number}/labels + owner: ${{ github.event.repository.owner.login }} + repo: ${{ github.event.repository.name }} + issue_number: ${{ github.event.number }} + env: + GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }} + + - if: toJson(fromJson(steps.earlier_preview.outputs.data)) != '[]' && contains(fromJson(steps.preview_label.outputs.data).*.name, 'preview') + name: Create deployment + id: deployment + uses: octokit/request-action@v2.x + with: + route: POST /repos/{owner}/{repo}/deployments + mediaType: | + previews: + - ant-man + - flash + owner: ${{ github.event.repository.owner.login }} + repo: ${{ github.event.repository.name }} + ref: ${{ github.event.pull_request.head.sha }} + task: deploy:preview + auto_merge: false + required_contexts: "[]" + environment: preview-pr-${{ github.event.number }} + description: "Preview for Pull Request #${{ github.event.number }}" + env: + GITHUB_TOKEN: ${{ secrets.PREVIEW_GITHUB_TOKEN }} + + - if: toJson(fromJson(steps.earlier_preview.outputs.data)) != '[]' && contains(fromJson(steps.preview_label.outputs.data).*.name, 'preview') + name: Trigger 'preview build' + uses: peter-evans/repository-dispatch@v1 + with: + token: ${{ secrets.PREVIEW_GITHUB_TOKEN }} + event-type: "Preview build #${{ github.event.number }}" + client-payload: '{"folder": "pr${{ github.event.number }}", "sha": "${{ github.event.pull_request.head.sha }}", "deployment_id": "${{ fromJson(steps.deployment.outputs.data).id }}"}' diff --git a/.gitignore b/.gitignore index 4e0de91823..e6e98437ce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ /.vs -/build*/ +/build* CMakeSettings.json docs/aidocs/* docs/gamedocs/* diff --git a/CMakeLists.txt b/CMakeLists.txt index 3d5ab9d0b7..51f3bfa476 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,10 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR) message(FATAL_ERROR "In-source builds not allowed. Please run \"cmake ..\" from the bin directory") endif() +if (EMSCRIPTEN) + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/os/emscripten/cmake") +endif() + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9) @@ -27,6 +31,61 @@ set_directory_options() include(Static) set_static_if_needed() +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED YES) +set(CMAKE_CXX_EXTENSIONS NO) + +set(CMAKE_EXPORT_COMPILE_COMMANDS YES) + +# An empty target for the tools +add_custom_target(tools) + +include(Endian) +add_endian_definition() + +include(CompileFlags) +compile_flags() + +if(APPLE OR UNIX) + add_definitions(-DUNIX) +endif() + +if(UNIX) + find_package(Doxygen) +endif() + +list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/rev.cpp") +if(WIN32) + list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/ottdres.rc") +endif() + +# Documentation +if(DOXYGEN_EXECUTABLE) + add_custom_target(docs) + add_custom_target(docs_source + ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/docs + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} + COMMENT "Generating documentation for source" + ) + add_dependencies(docs_source + find_version + ) + add_dependencies(docs + docs_source + ) +endif() + +include(AddCustomXXXTimestamp) + +if(OPTION_TOOLS_ONLY) + if(HOST_BINARY_DIR) + unset(HOST_BINARY_DIR CACHE) + endif() + add_subdirectory(${CMAKE_SOURCE_DIR}/src) + return() +endif() + # Prefer -pthread over -lpthread, which is often the better option of the two. set(CMAKE_THREAD_PREFER_PTHREAD YES) # Make sure we have Threads available. @@ -98,10 +157,6 @@ find_package(Xaudio2) find_package(Grfcodec) -if(UNIX) - find_package(Doxygen) -endif() - # IPO is only properly supported from CMake 3.9. Despite the fact we are # CMake 3.5, still enable IPO if we detect we are 3.9+. if(POLICY CMP0069) @@ -129,47 +184,7 @@ if(APPLE) endif() endif() -if(MSVC) - # C++17 for MSVC - set(CMAKE_CXX_STANDARD 17) -else() - # C++11 for all other targets - set(CMAKE_CXX_STANDARD 11) -endif() - -set(CMAKE_CXX_STANDARD_REQUIRED YES) -set(CMAKE_CXX_EXTENSIONS NO) - -set(CMAKE_EXPORT_COMPILE_COMMANDS YES) - -list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/rev.cpp") -if(WIN32) - list(APPEND GENERATED_SOURCE_FILES "${CMAKE_BINARY_DIR}/generated/ottdres.rc") -endif() - -# An empty target for the tools -add_custom_target(tools) - -# Documentation -if(DOXYGEN_EXECUTABLE) - add_custom_target(docs) - add_custom_target(docs_source - ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/docs - COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_BINARY_DIR}/Doxyfile - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - COMMENT "Generating documentation for source" - ) - add_dependencies(docs_source - find_version - ) - add_dependencies(docs - docs_source - ) -endif() - include(SourceList) -include(Endian) -add_endian_definition() # Needed by rev.cpp include_directories(${CMAKE_SOURCE_DIR}/src) @@ -178,9 +193,6 @@ include_directories(${CMAKE_SOURCE_DIR}/src/3rdparty/squirrel/include) include(MSVCFilters) -include(CompileFlags) -compile_flags() - add_executable(openttd WIN32 ${GENERATED_SOURCE_FILES}) set_target_properties(openttd PROPERTIES OUTPUT_NAME "${BINARY_NAME}") # All other files are added via target_sources() @@ -215,7 +227,6 @@ else() ) endif() -include(AddCustomXXXTimestamp) add_subdirectory(${CMAKE_SOURCE_DIR}/src) add_subdirectory(${CMAKE_SOURCE_DIR}/media/baseset) add_subdirectory(${CMAKE_SOURCE_DIR}/bin) @@ -248,10 +259,6 @@ endif() set_target_properties(openttd PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/bin") process_compile_flags() -if(APPLE OR UNIX) - add_definitions(-DUNIX) -endif() - include(LinkPackage) link_package(PNG TARGET PNG::PNG ENCOURAGED) link_package(ZLIB TARGET ZLIB::ZLIB ENCOURAGED) @@ -288,6 +295,39 @@ if(APPLE) ) endif() +if(EMSCRIPTEN) + add_library(WASM::WASM INTERFACE IMPORTED) + + # Allow heap-growth, and start with a bigger memory size. + target_link_libraries(WASM::WASM INTERFACE "-s ALLOW_MEMORY_GROWTH=1") + target_link_libraries(WASM::WASM INTERFACE "-s INITIAL_MEMORY=33554432") + + # Export functions to Javascript. + target_link_libraries(WASM::WASM INTERFACE "-s EXPORTED_FUNCTIONS='[\"_main\", \"_em_openttd_add_server\"]' -s EXTRA_EXPORTED_RUNTIME_METHODS='[\"cwrap\"]'") + + # Preload all the files we generate during build. + # As we do not compile with FreeType / FontConfig, we also have no way to + # render several languages (like Chinese, ..), so where do you draw the + # line what languages to include and which not? In the end, especially as + # the more languages you add the slower downloading becomes, we decided to + # only ship the English language. + target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_BINARY_DIR}/baseset@/baseset") + target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_BINARY_DIR}/lang/english.lng@/lang/english.lng") + target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/bin/ai@/ai") + target_link_libraries(WASM::WASM INTERFACE "--preload-file ${CMAKE_SOURCE_DIR}/bin/game@/game") + + # We use IDBFS for persistent storage. + target_link_libraries(WASM::WASM INTERFACE "-lidbfs.js") + + # Use custom pre-js and shell.html. + target_link_libraries(WASM::WASM INTERFACE "--pre-js ${CMAKE_SOURCE_DIR}/os/emscripten/pre.js") + target_link_libraries(WASM::WASM INTERFACE "--shell-file ${CMAKE_SOURCE_DIR}/os/emscripten/shell.html") + + # Build the .html (which builds the .js, .wasm, and .data too). + set_target_properties(openttd PROPERTIES SUFFIX ".html") + target_link_libraries(openttd WASM::WASM) +endif() + if(NOT PERSONAL_DIR STREQUAL "(not set)") add_definitions( -DWITH_PERSONAL_DIR diff --git a/COMPILING.md b/COMPILING.md index 64f25f9c22..759dd2e9c4 100644 --- a/COMPILING.md +++ b/COMPILING.md @@ -83,9 +83,9 @@ make ## Supported compilers -Every compiler that is supported by CMake and supports C++11, should be +Every compiler that is supported by CMake and supports C++17, should be able to compile OpenTTD. As the exact list of compilers changes constantly, -we refer to the compiler manual to see if it supports C++11, and to CMake +we refer to the compiler manual to see if it supports C++17, and to CMake to see if it supports your compiler. ## Compilation of base sets diff --git a/cmake/Options.cmake b/cmake/Options.cmake index 005bb19cae..c94a193b32 100644 --- a/cmake/Options.cmake +++ b/cmake/Options.cmake @@ -55,8 +55,20 @@ function(set_options) option(OPTION_DEDICATED "Build dedicated server only (no GUI)" OFF) option(OPTION_INSTALL_FHS "Install with Filesystem Hierarchy Standard folders" ${DEFAULT_OPTION_INSTALL_FHS}) option(OPTION_USE_ASSERTS "Use assertions; leave enabled for nightlies, betas, and RCs" ON) - option(OPTION_USE_THREADS "Use threads" ON) + if(EMSCRIPTEN) + # Although pthreads is supported, it is not in a way yet that is + # useful for us. + option(OPTION_USE_THREADS "Use threads" OFF) + else() + option(OPTION_USE_THREADS "Use threads" ON) + endif() option(OPTION_USE_NSIS "Use NSIS to create windows installer; enable only for stable releases" OFF) + option(OPTION_TOOLS_ONLY "Build only tools target" OFF) + option(OPTION_DOCS_ONLY "Build only docs target" OFF) + + if (OPTION_DOCS_ONLY) + set(OPTION_TOOLS_ONLY ON PARENT_SCOPE) + endif() endfunction() # Show the values of the generic options. diff --git a/cmake/PackageBundle.cmake b/cmake/PackageBundle.cmake index a443da3c4b..7f96e05fa8 100644 --- a/cmake/PackageBundle.cmake +++ b/cmake/PackageBundle.cmake @@ -5,6 +5,7 @@ set(CPACK_BUNDLE_ICON "${CMAKE_SOURCE_DIR}/os/macosx/openttd.icns") set(CPACK_BUNDLE_PLIST "${CMAKE_CURRENT_BINARY_DIR}/Info.plist") set(CPACK_BUNDLE_STARTUP_COMMAND "${CMAKE_SOURCE_DIR}/os/macosx/launch.sh") set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/os/macosx/splash.png") +set(CPACK_DMG_FORMAT "UDBZ") # Create a temporary Info.plist.in, where we will fill in the version via # CPackProperties.cmake.in. This because at this point in time the version diff --git a/os/emscripten/Dockerfile b/os/emscripten/Dockerfile new file mode 100644 index 0000000000..1278a088ff --- /dev/null +++ b/os/emscripten/Dockerfile @@ -0,0 +1,4 @@ +FROM emscripten/emsdk + +COPY emsdk-liblzma.patch / +RUN cd /emsdk/upstream/emscripten && patch -p1 < /emsdk-liblzma.patch diff --git a/os/emscripten/README.md b/os/emscripten/README.md new file mode 100644 index 0000000000..4c5d7508cc --- /dev/null +++ b/os/emscripten/README.md @@ -0,0 +1,40 @@ +## How to build with Emscripten + +Building with Emscripten works with emsdk 2.0.10 and above. + +Currently there is no LibLZMA support upstream; for this we suggest to apply +the provided patch in this folder to your emsdk installation. + +For convenience, a Dockerfile is supplied that does this patches for you +against upstream emsdk docker. Best way to use it: + +Build the docker image: +``` + docker build -t emsdk-lzma . +``` + +Build the host tools first: +``` + mkdir build-host + docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build-host emsdk-lzma cmake .. -DOPTION_TOOLS_ONLY=ON + docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build-host emsdk-lzma make -j5 tools +``` + +Next, build the game with emscripten: + +``` + mkdir build + docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build emsdk-lzma emcmake cmake .. -DHOST_BINARY_DIR=$(pwd)/build-host -DCMAKE_BUILD_TYPE=RelWithDebInfo -DOPTION_USE_ASSERTS=OFF + docker run -it --rm -v $(pwd):$(pwd) -u $(id -u):$(id -g) --workdir $(pwd)/build emsdk-lzma emmake make -j5 +``` + +And now you have in your build folder files like "openttd.html". + +To run it locally, you would have to start a local webserver, like: + +``` + cd build + python3 -m http.server +```` + +Now you can play the game via http://127.0.0.1:8000/openttd.html . diff --git a/os/emscripten/cmake/FindLibLZMA.cmake b/os/emscripten/cmake/FindLibLZMA.cmake new file mode 100644 index 0000000000..99d1ca640a --- /dev/null +++ b/os/emscripten/cmake/FindLibLZMA.cmake @@ -0,0 +1,20 @@ +# LibLZMA is a recent addition to the emscripten SDK, so it is possible +# someone hasn't updated his SDK yet. Test out if the SDK supports LibLZMA. +include(CheckCXXSourceCompiles) +set(CMAKE_REQUIRED_FLAGS "-sUSE_LIBLZMA=1") + +check_cxx_source_compiles(" + #include + int main() { return 0; }" + LIBLZMA_FOUND +) + +if (LIBLZMA_FOUND) + add_library(LibLZMA::LibLZMA INTERFACE IMPORTED) + set_target_properties(LibLZMA::LibLZMA PROPERTIES + INTERFACE_COMPILE_OPTIONS "-sUSE_LIBLZMA=1" + INTERFACE_LINK_LIBRARIES "-sUSE_LIBLZMA=1" + ) +else() + message(WARNING "You are using an emscripten SDK without LibLZMA support. Many savegames won't be able to load in OpenTTD. Please apply 'emsdk-liblzma.patch' to your local emsdk installation.") +endif() diff --git a/os/emscripten/cmake/FindPNG.cmake b/os/emscripten/cmake/FindPNG.cmake new file mode 100644 index 0000000000..2616af33d9 --- /dev/null +++ b/os/emscripten/cmake/FindPNG.cmake @@ -0,0 +1,7 @@ +add_library(PNG::PNG INTERFACE IMPORTED) +set_target_properties(PNG::PNG PROPERTIES + INTERFACE_COMPILE_OPTIONS "-sUSE_LIBPNG=1" + INTERFACE_LINK_LIBRARIES "-sUSE_LIBPNG=1" +) + +set(PNG_FOUND on) diff --git a/os/emscripten/cmake/FindSDL2.cmake b/os/emscripten/cmake/FindSDL2.cmake new file mode 100644 index 0000000000..54553958b6 --- /dev/null +++ b/os/emscripten/cmake/FindSDL2.cmake @@ -0,0 +1,7 @@ +add_library(SDL2::SDL2 INTERFACE IMPORTED) +set_target_properties(SDL2::SDL2 PROPERTIES + INTERFACE_COMPILE_OPTIONS "-sUSE_SDL=2" + INTERFACE_LINK_LIBRARIES "-sUSE_SDL=2" +) + +set(SDL2_FOUND on) diff --git a/os/emscripten/cmake/FindZLIB.cmake b/os/emscripten/cmake/FindZLIB.cmake new file mode 100644 index 0000000000..2ade2ba1b0 --- /dev/null +++ b/os/emscripten/cmake/FindZLIB.cmake @@ -0,0 +1,7 @@ +add_library(ZLIB::ZLIB INTERFACE IMPORTED) +set_target_properties(ZLIB::ZLIB PROPERTIES + INTERFACE_COMPILE_OPTIONS "-sUSE_ZLIB=1" + INTERFACE_LINK_LIBRARIES "-sUSE_ZLIB=1" +) + +set(ZLIB_FOUND on) diff --git a/os/emscripten/emsdk-liblzma.patch b/os/emscripten/emsdk-liblzma.patch new file mode 100644 index 0000000000..103adae0cc --- /dev/null +++ b/os/emscripten/emsdk-liblzma.patch @@ -0,0 +1,213 @@ +From 90dd4d4c6b1cedec338ff5b375fffca93700f7bc Mon Sep 17 00:00:00 2001 +From: milek7 +Date: Tue, 8 Dec 2020 01:03:31 +0100 +Subject: [PATCH] Add liblzma port + +--- +Source: https://github.com/emscripten-core/emscripten/pull/12990 + +Modifed by OpenTTD to have the bare minimum needed to work. Otherwise there +are constantly conflicts when trying to apply this patch to different versions +of emsdk. + +diff --git a/embuilder.py b/embuilder.py +index 818262190ed..ab7d5adb7b2 100755 +--- a/embuilder.py ++++ b/embuilder.py +@@ -60,6 +60,7 @@ + 'harfbuzz', + 'icu', + 'libjpeg', ++ 'liblzma', + 'libpng', + 'ogg', + 'regal', +@@ -197,6 +198,8 @@ def main(): + build_port('ogg', libname('libogg')) + elif what == 'libjpeg': + build_port('libjpeg', libname('libjpeg')) ++ elif what == 'liblzma': ++ build_port('liblzma', libname('liblzma')) + elif what == 'libpng': + build_port('libpng', libname('libpng')) + elif what == 'sdl2': +diff --git a/src/settings.js b/src/settings.js +index 61cd98939ba..be6fcb678c6 100644 +--- a/src/settings.js ++++ b/src/settings.js +@@ -1197,6 +1197,9 @@ var USE_BZIP2 = 0; + // 1 = use libjpeg from emscripten-ports + var USE_LIBJPEG = 0; + ++// 1 = use liblzma from emscripten-ports ++var USE_LIBLZMA = 0; ++ + // 1 = use libpng from emscripten-ports + var USE_LIBPNG = 0; + +diff --git a/tools/ports/liblzma.py b/tools/ports/liblzma.py +new file mode 100644 +index 00000000000..e9567ef36ff +--- /dev/null ++++ b/tools/ports/liblzma.py +@@ -0,0 +1,160 @@ ++# Copyright 2020 The Emscripten Authors. All rights reserved. ++# Emscripten is available under two separate licenses, the MIT license and the ++# University of Illinois/NCSA Open Source License. Both these licenses can be ++# found in the LICENSE file. ++ ++import os ++import shutil ++ ++VERSION = '5.2.5' ++HASH = '7443674247deda2935220fbc4dfc7665e5bb5a260be8ad858c8bd7d7b9f0f868f04ea45e62eb17c0a5e6a2de7c7500ad2d201e2d668c48ca29bd9eea5a73a3ce' ++ ++ ++def needed(settings): ++ return settings.USE_LIBLZMA ++ ++ ++def get(ports, settings, shared): ++ libname = ports.get_lib_name('liblzma') ++ ports.fetch_project('liblzma', 'https://tukaani.org/xz/xz-' + VERSION + '.tar.gz', 'xz-' + VERSION, sha512hash=HASH) ++ ++ def create(): ++ ports.clear_project_build('liblzma') ++ ++ source_path = os.path.join(ports.get_dir(), 'liblzma', 'xz-' + VERSION) ++ dest_path = os.path.join(ports.get_build_dir(), 'liblzma') ++ ++ shared.try_delete(dest_path) ++ os.makedirs(dest_path) ++ shutil.rmtree(dest_path, ignore_errors=True) ++ shutil.copytree(source_path, dest_path) ++ ++ build_flags = ['-DHAVE_CONFIG_H', '-DTUKLIB_SYMBOL_PREFIX=lzma_', '-fvisibility=hidden'] ++ exclude_dirs = ['xzdec', 'xz', 'lzmainfo'] ++ exclude_files = ['crc32_small.c', 'crc64_small.c', 'crc32_tablegen.c', 'crc64_tablegen.c', 'price_tablegen.c', 'fastpos_tablegen.c' ++ 'tuklib_exit.c', 'tuklib_mbstr_fw.c', 'tuklib_mbstr_width.c', 'tuklib_open_stdxxx.c', 'tuklib_progname.c'] ++ include_dirs_rel = ['../common', 'api', 'common', 'check', 'lz', 'rangecoder', 'lzma', 'delta', 'simple'] ++ ++ open(os.path.join(dest_path, 'src', 'config.h'), 'w').write(config_h) ++ ++ final = os.path.join(dest_path, libname) ++ include_dirs = [os.path.join(dest_path, 'src', 'liblzma', p) for p in include_dirs_rel] ++ ports.build_port(os.path.join(dest_path, 'src'), final, flags=build_flags, exclude_dirs=exclude_dirs, exclude_files=exclude_files, includes=include_dirs) ++ ++ ports.install_headers(os.path.join(dest_path, 'src', 'liblzma', 'api'), 'lzma.h') ++ ports.install_headers(os.path.join(dest_path, 'src', 'liblzma', 'api', 'lzma'), '*.h', 'lzma') ++ ++ return final ++ ++ return [shared.Cache.get(libname, create, what='port')] ++ ++ ++def clear(ports, settings, shared): ++ shared.Cache.erase_file(ports.get_lib_name('liblzma')) ++ ++ ++def process_args(ports): ++ return [] ++ ++ ++def show(): ++ return 'liblzma (USE_LIBLZMA=1; public domain)' ++ ++ ++config_h = r''' ++#define ASSUME_RAM 128 ++#define ENABLE_NLS 1 ++#define HAVE_CHECK_CRC32 1 ++#define HAVE_CHECK_CRC64 1 ++#define HAVE_CHECK_SHA256 1 ++#define HAVE_CLOCK_GETTIME 1 ++#define HAVE_DCGETTEXT 1 ++#define HAVE_DECL_CLOCK_MONOTONIC 1 ++#define HAVE_DECL_PROGRAM_INVOCATION_NAME 1 ++#define HAVE_DECODERS 1 ++#define HAVE_DECODER_ARM 1 ++#define HAVE_DECODER_ARMTHUMB 1 ++#define HAVE_DECODER_DELTA 1 ++#define HAVE_DECODER_IA64 1 ++#define HAVE_DECODER_LZMA1 1 ++#define HAVE_DECODER_LZMA2 1 ++#define HAVE_DECODER_POWERPC 1 ++#define HAVE_DECODER_SPARC 1 ++#define HAVE_DECODER_X86 1 ++#define HAVE_DLFCN_H 1 ++#define HAVE_ENCODERS 1 ++#define HAVE_ENCODER_ARM 1 ++#define HAVE_ENCODER_ARMTHUMB 1 ++#define HAVE_ENCODER_DELTA 1 ++#define HAVE_ENCODER_IA64 1 ++#define HAVE_ENCODER_LZMA1 1 ++#define HAVE_ENCODER_LZMA2 1 ++#define HAVE_ENCODER_POWERPC 1 ++#define HAVE_ENCODER_SPARC 1 ++#define HAVE_ENCODER_X86 1 ++#define HAVE_FCNTL_H 1 ++#define HAVE_FUTIMENS 1 ++#define HAVE_GETOPT_H 1 ++#define HAVE_GETOPT_LONG 1 ++#define HAVE_GETTEXT 1 ++#define HAVE_IMMINTRIN_H 1 ++#define HAVE_INTTYPES_H 1 ++#define HAVE_LIMITS_H 1 ++#define HAVE_MBRTOWC 1 ++#define HAVE_MEMORY_H 1 ++#define HAVE_MF_BT2 1 ++#define HAVE_MF_BT3 1 ++#define HAVE_MF_BT4 1 ++#define HAVE_MF_HC3 1 ++#define HAVE_MF_HC4 1 ++#define HAVE_OPTRESET 1 ++#define HAVE_POSIX_FADVISE 1 ++#define HAVE_PTHREAD_CONDATTR_SETCLOCK 1 ++#define HAVE_PTHREAD_PRIO_INHERIT 1 ++#define HAVE_STDBOOL_H 1 ++#define HAVE_STDINT_H 1 ++#define HAVE_STDLIB_H 1 ++#define HAVE_STRINGS_H 1 ++#define HAVE_STRING_H 1 ++#define HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC 1 ++#define HAVE_SYS_PARAM_H 1 ++#define HAVE_SYS_STAT_H 1 ++#define HAVE_SYS_TIME_H 1 ++#define HAVE_SYS_TYPES_H 1 ++#define HAVE_UINTPTR_T 1 ++#define HAVE_UNISTD_H 1 ++#define HAVE_VISIBILITY 1 ++#define HAVE_WCWIDTH 1 ++#define HAVE__BOOL 1 ++#define HAVE___BUILTIN_ASSUME_ALIGNED 1 ++#define HAVE___BUILTIN_BSWAPXX 1 ++#define MYTHREAD_POSIX 1 ++#define NDEBUG 1 ++#define PACKAGE "xz" ++#define PACKAGE_BUGREPORT "lasse.collin@tukaani.org" ++#define PACKAGE_NAME "XZ Utils" ++#define PACKAGE_STRING "XZ Utils 5.2.5" ++#define PACKAGE_TARNAME "xz" ++#define PACKAGE_VERSION "5.2.5" ++#define SIZEOF_SIZE_T 4 ++#define STDC_HEADERS 1 ++#define TUKLIB_CPUCORES_SYSCONF 1 ++#define TUKLIB_FAST_UNALIGNED_ACCESS 1 ++#define TUKLIB_PHYSMEM_SYSCONF 1 ++#ifndef _ALL_SOURCE ++# define _ALL_SOURCE 1 ++#endif ++#ifndef _GNU_SOURCE ++# define _GNU_SOURCE 1 ++#endif ++#ifndef _POSIX_PTHREAD_SEMANTICS ++# define _POSIX_PTHREAD_SEMANTICS 1 ++#endif ++#ifndef _TANDEM_SOURCE ++# define _TANDEM_SOURCE 1 ++#endif ++#ifndef __EXTENSIONS__ ++# define __EXTENSIONS__ 1 ++#endif ++#define VERSION "5.2.5" ++''' diff --git a/os/emscripten/loading.png b/os/emscripten/loading.png new file mode 100755 index 0000000000..d4c4aaf75e Binary files /dev/null and b/os/emscripten/loading.png differ diff --git a/os/emscripten/pre.js b/os/emscripten/pre.js new file mode 100644 index 0000000000..5cbd899e04 --- /dev/null +++ b/os/emscripten/pre.js @@ -0,0 +1,93 @@ +Module.arguments.push('-mnull', '-snull', '-vsdl:relative_mode'); +Module['websocket'] = { url: function(host, port, proto) { + /* openttd.org hosts a WebSocket proxy for the content service. */ + if (host == "content.openttd.org" && port == 3978 && proto == "tcp") { + return "wss://content.openttd.org/"; + } + + /* Everything else just tries to make a default WebSocket connection. + * If you run your own server you can setup your own WebSocket proxy in + * front of it and let people connect to your server via the proxy. You + * are best to add another "if" statement as above for this. */ + return null; +} }; + +Module.preRun.push(function() { + personal_dir = '/home/web_user/.openttd'; + content_download_dir = personal_dir + '/content_download' + + /* Because of the "-c" above, all user-data is stored in /user_data. */ + FS.mkdir(personal_dir); + FS.mount(IDBFS, {}, personal_dir); + + Module.addRunDependency('syncfs'); + FS.syncfs(true, function (err) { + /* FS.mkdir() tends to fail if parent folders do not exist. */ + if (!FS.analyzePath(content_download_dir).exists) { + FS.mkdir(content_download_dir); + } + if (!FS.analyzePath(content_download_dir + '/baseset').exists) { + FS.mkdir(content_download_dir + '/baseset'); + } + + /* Check if the OpenGFX baseset is already downloaded. */ + if (!FS.analyzePath(content_download_dir + '/baseset/opengfx-0.6.0.tar').exists) { + window.openttd_downloaded_opengfx = true; + FS.createPreloadedFile(content_download_dir + '/baseset', 'opengfx-0.6.0.tar', 'https://installer.cdn.openttd.org/emscripten/opengfx-0.6.0.tar', true, true); + } else { + /* Fake dependency increase, so the counter is stable. */ + Module.addRunDependency('opengfx'); + Module.removeRunDependency('opengfx'); + } + + Module.removeRunDependency('syncfs'); + }); + + window.openttd_syncfs_shown_warning = false; + window.openttd_syncfs = function() { + /* Copy the virtual FS to the persistent storage. */ + FS.syncfs(false, function (err) { }); + + /* On first time, warn the user about the volatile behaviour of + * persistent storage. */ + if (!window.openttd_syncfs_shown_warning) { + window.openttd_syncfs_shown_warning = true; + Module.onWarningFs(); + } + } + + window.openttd_exit = function() { + Module.onExit(); + } + + window.openttd_abort = function() { + Module.onAbort(); + } + + window.openttd_server_list = function() { + add_server = Module.cwrap("em_openttd_add_server", null, ["string", "number"]); + + /* Add servers that support WebSocket here. Example: + * add_server("localhost", 3979); */ + } + + /* https://github.com/emscripten-core/emscripten/pull/12995 implements this + * properly. Till that time, we use a polyfill. */ + SOCKFS.websocket_sock_ops.createPeer_ = SOCKFS.websocket_sock_ops.createPeer; + SOCKFS.websocket_sock_ops.createPeer = function(sock, addr, port) + { + let func = Module['websocket']['url']; + Module['websocket']['url'] = func(addr, port, (sock.type == 2) ? 'udp' : 'tcp'); + let ret = SOCKFS.websocket_sock_ops.createPeer_(sock, addr, port); + Module['websocket']['url'] = func; + return ret; + } +}); + +Module.postRun.push(function() { + /* Check if we downloaded OpenGFX; if so, sync the virtual FS back to the + * IDBFS so OpenGFX is stored persistent. */ + if (window['openttd_downloaded_opengfx']) { + FS.syncfs(false, function (err) { }); + } +}); diff --git a/os/emscripten/shell.html b/os/emscripten/shell.html new file mode 100644 index 0000000000..17ea5b414f --- /dev/null +++ b/os/emscripten/shell.html @@ -0,0 +1,205 @@ + + + + + + OpenTTD + + + +
+
+
+ Loading ... +
+
+
+
+
+
+
+ Warning: savegames are stored in the Indexed DB of your browser.
Your browser can delete savegames without notice! +
+
+
+ +
+ + + {{{ SCRIPT }}} + + diff --git a/regression/regression/result.txt b/regression/regression/result.txt index cdba81c979..52d957faf9 100644 --- a/regression/regression/result.txt +++ b/regression/regression/result.txt @@ -9075,7 +9075,7 @@ ERROR: IsEnd() is invalid as Begin() is never called --Accounting-- GetCosts(): -5947 Should be: -5947 - GetName(): Road Vehicle 1 + GetName(): Road Vehicle #1 SetName(): true GetName(): MyVehicleName CloneVehicle(): 13 diff --git a/src/3rdparty/optional/LICENSE_1_0.txt b/src/3rdparty/optional/LICENSE_1_0.txt deleted file mode 100644 index 36b7cd93cd..0000000000 --- a/src/3rdparty/optional/LICENSE_1_0.txt +++ /dev/null @@ -1,23 +0,0 @@ -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. diff --git a/src/3rdparty/optional/optional.hpp b/src/3rdparty/optional/optional.hpp deleted file mode 100644 index b77f21bc72..0000000000 --- a/src/3rdparty/optional/optional.hpp +++ /dev/null @@ -1,1066 +0,0 @@ -// Copyright (C) 2011 - 2012 Andrzej Krzemienski. -// -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// The idea and interface is based on Boost.Optional library -// authored by Fernando Luis Cacciola Carballal - -# ifndef ___OPTIONAL_HPP___ -# define ___OPTIONAL_HPP___ - -# include -# include -# include -//# include -# include -# include -# include - -# define TR2_OPTIONAL_REQUIRES(...) typename enable_if<__VA_ARGS__::value, bool>::type = false - -# if defined __GNUC__ // NOTE: GNUC is also defined for Clang -# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8) -# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ -# endif -# -# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7) -# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___ -# endif -# -# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# elif (__GNUC__ > 4) -# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# endif -# endif -# -# if defined __clang_major__ -# if (__clang_major__ == 3 && __clang_minor__ >= 5) -# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# elif (__clang_major__ > 3) -# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# endif -# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ -# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ -# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2) -# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ -# endif -# endif -# -# if defined _MSC_VER -# if (_MSC_VER >= 1900) -# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -# endif -# endif - -# if defined __clang__ -# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9) -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# else -# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 -# endif -# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ -# define OPTIONAL_HAS_THIS_RVALUE_REFS 1 -# else -# define OPTIONAL_HAS_THIS_RVALUE_REFS 0 -# endif - - -# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___ -# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1 -# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr -# else -# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0 -# define OPTIONAL_CONSTEXPR_INIT_LIST -# endif - -# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L) -# define OPTIONAL_HAS_MOVE_ACCESSORS 1 -# else -# define OPTIONAL_HAS_MOVE_ACCESSORS 0 -# endif - -# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr -# if (defined __cplusplus) && (__cplusplus == 201103L) -# define OPTIONAL_MUTABLE_CONSTEXPR -# else -# define OPTIONAL_MUTABLE_CONSTEXPR constexpr -# endif - -namespace std{ - -namespace experimental{ - -// BEGIN workaround for missing is_trivially_destructible -# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ - // leave it: it is already there -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS - // leave it: the user doesn't want it -# else - template - using is_trivially_destructible = std::has_trivial_destructor; -# endif -// END workaround for missing is_trivially_destructible - -# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___) - // leave it; our metafunctions are already defined. -# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ - // leave it; our metafunctions are already defined. -# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___ - // leave it: it is already there -# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS - // leave it: the user doesn't want it -# else - - -// workaround for missing traits in GCC and CLANG -template -struct is_nothrow_move_constructible -{ - constexpr static bool value = std::is_nothrow_constructible::value; -}; - - -template -struct is_assignable -{ - template - constexpr static bool has_assign(...) { return false; } - - template () = std::declval(), true)) > - // the comma operator is necessary for the cases where operator= returns void - constexpr static bool has_assign(bool) { return true; } - - constexpr static bool value = has_assign(true); -}; - - -template -struct is_nothrow_move_assignable -{ - template - struct has_nothrow_move_assign { - constexpr static bool value = false; - }; - - template - struct has_nothrow_move_assign { - constexpr static bool value = noexcept( std::declval() = std::declval() ); - }; - - constexpr static bool value = has_nothrow_move_assign::value>::value; -}; -// end workaround - - -# endif - - - -// 20.5.4, optional for object types -template class optional; - -// 20.5.5, optional for lvalue reference types -template class optional; - - -// workaround: std utility functions aren't constexpr yet -template inline constexpr T&& constexpr_forward(typename std::remove_reference::type& t) noexcept -{ - return static_cast(t); -} - -template inline constexpr T&& constexpr_forward(typename std::remove_reference::type&& t) noexcept -{ - static_assert(!std::is_lvalue_reference::value, "!!"); - return static_cast(t); -} - -template inline constexpr typename std::remove_reference::type&& constexpr_move(T&& t) noexcept -{ - return static_cast::type&&>(t); -} - - -#if defined NDEBUG -# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR) -#else -# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR))) -#endif - - -namespace detail_ -{ - -// static_addressof: a constexpr version of addressof -template -struct has_overloaded_addressof -{ - template - constexpr static bool has_overload(...) { return false; } - - template ().operator&()) > - constexpr static bool has_overload(bool) { return true; } - - constexpr static bool value = has_overload(true); -}; - -template )> -constexpr T* static_addressof(T& ref) -{ - return &ref; -} - -template )> -T* static_addressof(T& ref) -{ - return std::addressof(ref); -} - - -// the call to convert(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A -template -constexpr U convert(U v) { return v; } - - -namespace swap_ns -{ - using std::swap; - - template - void adl_swap(T& t, T& u) noexcept(noexcept(swap(t, u))) - { - swap(t, u); - } - -} // namespace swap_ns - -} // namespace detail - - -constexpr struct trivial_init_t{} trivial_init{}; - - -// 20.5.6, In-place construction -constexpr struct in_place_t{} in_place{}; - - -// 20.5.7, Disengaged state indicator -struct nullopt_t -{ - struct init{}; - constexpr explicit nullopt_t(init){} -}; -constexpr nullopt_t nullopt{nullopt_t::init()}; - - -// 20.5.8, class bad_optional_access -class bad_optional_access : public logic_error { -public: - explicit bad_optional_access(const string& what_arg) : logic_error{what_arg} {} - explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {} -}; - - -template -union storage_t -{ - unsigned char dummy_; - T value_; - - constexpr storage_t( trivial_init_t ) noexcept : dummy_() {}; - - template - constexpr storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} - - ~storage_t(){} -}; - - -template -union constexpr_storage_t -{ - unsigned char dummy_; - T value_; - - constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {}; - - template - constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {} - - ~constexpr_storage_t() = default; -}; - - -template -struct optional_base -{ - bool init_; - storage_t storage_; - - constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {}; - - explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {} - - explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} - - template explicit optional_base(in_place_t, Args&&... args) - : init_(true), storage_(constexpr_forward(args)...) {} - - template >)> - explicit optional_base(in_place_t, std::initializer_list il, Args&&... args) - : init_(true), storage_(il, std::forward(args)...) {} - - ~optional_base() { if (init_) storage_.value_.T::~T(); } -}; - - -template -struct constexpr_optional_base -{ - bool init_; - constexpr_storage_t storage_; - - constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init) {}; - - explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {} - - explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {} - - template explicit constexpr constexpr_optional_base(in_place_t, Args&&... args) - : init_(true), storage_(constexpr_forward(args)...) {} - - template >)> - OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list il, Args&&... args) - : init_(true), storage_(il, std::forward(args)...) {} - - ~constexpr_optional_base() = default; -}; - -template -using OptionalBase = typename std::conditional< - is_trivially_destructible::value, // if possible - constexpr_optional_base::type>, // use base with trivial destructor - optional_base::type> ->::type; - - - -template -class optional : private OptionalBase -{ - static_assert( !std::is_same::type, nullopt_t>::value, "bad T" ); - static_assert( !std::is_same::type, in_place_t>::value, "bad T" ); - - - constexpr bool initialized() const noexcept { return OptionalBase::init_; } - typename std::remove_const::type* dataptr() { return std::addressof(OptionalBase::storage_.value_); } - constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase::storage_.value_); } - -# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 - constexpr const T& contained_val() const& { return OptionalBase::storage_.value_; } -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return std::move(OptionalBase::storage_.value_); } - OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase::storage_.value_; } -# else - T& contained_val() & { return OptionalBase::storage_.value_; } - T&& contained_val() && { return std::move(OptionalBase::storage_.value_); } -# endif -# else - constexpr const T& contained_val() const { return OptionalBase::storage_.value_; } - T& contained_val() { return OptionalBase::storage_.value_; } -# endif - - void clear() noexcept { - if (initialized()) dataptr()->T::~T(); - OptionalBase::init_ = false; - } - - template - void initialize(Args&&... args) noexcept(noexcept(T(std::forward(args)...))) - { - assert(!OptionalBase::init_); - ::new (static_cast(dataptr())) T(std::forward(args)...); - OptionalBase::init_ = true; - } - - template - void initialize(std::initializer_list il, Args&&... args) noexcept(noexcept(T(il, std::forward(args)...))) - { - assert(!OptionalBase::init_); - ::new (static_cast(dataptr())) T(il, std::forward(args)...); - OptionalBase::init_ = true; - } - -public: - typedef T value_type; - - // 20.5.5.1, constructors - constexpr optional() noexcept : OptionalBase() {}; - constexpr optional(nullopt_t) noexcept : OptionalBase() {}; - - optional(const optional& rhs) - : OptionalBase() - { - if (rhs.initialized()) { - ::new (static_cast(dataptr())) T(*rhs); - OptionalBase::init_ = true; - } - } - - optional(optional&& rhs) noexcept(is_nothrow_move_constructible::value) - : OptionalBase() - { - if (rhs.initialized()) { - ::new (static_cast(dataptr())) T(std::move(*rhs)); - OptionalBase::init_ = true; - } - } - - constexpr optional(const T& v) : OptionalBase(v) {} - - constexpr optional(T&& v) : OptionalBase(constexpr_move(v)) {} - - template - explicit constexpr optional(in_place_t, Args&&... args) - : OptionalBase(in_place_t{}, constexpr_forward(args)...) {} - - template >)> - OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, std::initializer_list il, Args&&... args) - : OptionalBase(in_place_t{}, il, constexpr_forward(args)...) {} - - // 20.5.4.2, Destructor - ~optional() = default; - - // 20.5.4.3, assignment - optional& operator=(nullopt_t) noexcept - { - clear(); - return *this; - } - - optional& operator=(const optional& rhs) - { - if (initialized() == true && rhs.initialized() == false) clear(); - else if (initialized() == false && rhs.initialized() == true) initialize(*rhs); - else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs; - return *this; - } - - optional& operator=(optional&& rhs) - noexcept(is_nothrow_move_assignable::value && is_nothrow_move_constructible::value) - { - if (initialized() == true && rhs.initialized() == false) clear(); - else if (initialized() == false && rhs.initialized() == true) initialize(std::move(*rhs)); - else if (initialized() == true && rhs.initialized() == true) contained_val() = std::move(*rhs); - return *this; - } - - template - auto operator=(U&& v) - -> typename enable_if - < - is_same::type, T>::value, - optional& - >::type - { - if (initialized()) { contained_val() = std::forward(v); } - else { initialize(std::forward(v)); } - return *this; - } - - - template - void emplace(Args&&... args) - { - clear(); - initialize(std::forward(args)...); - } - - template - void emplace(initializer_list il, Args&&... args) - { - clear(); - initialize(il, std::forward(args)...); - } - - // 20.5.4.4, Swap - void swap(optional& rhs) noexcept(is_nothrow_move_constructible::value - && noexcept(detail_::swap_ns::adl_swap(declval(), declval()))) - { - if (initialized() == true && rhs.initialized() == false) { rhs.initialize(std::move(**this)); clear(); } - else if (initialized() == false && rhs.initialized() == true) { initialize(std::move(*rhs)); rhs.clear(); } - else if (initialized() == true && rhs.initialized() == true) { using std::swap; swap(**this, *rhs); } - } - - // 20.5.4.5, Observers - - explicit constexpr operator bool() const noexcept { return initialized(); } - constexpr bool has_value() const noexcept { return initialized(); } - - constexpr T const* operator ->() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr()); - } - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - - OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() { - assert (initialized()); - return dataptr(); - } - - constexpr T const& operator *() const& { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); - } - - OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & { - assert (initialized()); - return contained_val(); - } - - OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && { - assert (initialized()); - return constexpr_move(contained_val()); - } - - constexpr T const& value() const& { - return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); - } - - OPTIONAL_MUTABLE_CONSTEXPR T& value() & { - return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); - } - - OPTIONAL_MUTABLE_CONSTEXPR T&& value() && { - if (!initialized()) throw bad_optional_access("bad optional access"); - return std::move(contained_val()); - } - -# else - - T* operator ->() { - assert (initialized()); - return dataptr(); - } - - constexpr T const& operator *() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val()); - } - - T& operator *() { - assert (initialized()); - return contained_val(); - } - - constexpr T const& value() const { - return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); - } - - T& value() { - return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val()); - } - -# endif - -# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1 - - template - constexpr T value_or(V&& v) const& - { - return *this ? **this : detail_::convert(constexpr_forward(v)); - } - -# if OPTIONAL_HAS_MOVE_ACCESSORS == 1 - - template - OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) && - { - return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); - } - -# else - - template - T value_or(V&& v) && - { - return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v)); - } - -# endif - -# else - - template - constexpr T value_or(V&& v) const - { - return *this ? **this : detail_::convert(constexpr_forward(v)); - } - -# endif - - // 20.6.3.6, modifiers - void reset() noexcept { clear(); } -}; - - -template -class optional -{ - static_assert( !std::is_same::value, "bad T" ); - static_assert( !std::is_same::value, "bad T" ); - T* ref; - -public: - - // 20.5.5.1, construction/destruction - constexpr optional() noexcept : ref(nullptr) {} - - constexpr optional(nullopt_t) noexcept : ref(nullptr) {} - - constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {} - - optional(T&&) = delete; - - constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {} - - explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {} - - explicit optional(in_place_t, T&&) = delete; - - ~optional() = default; - - // 20.5.5.2, mutation - optional& operator=(nullopt_t) noexcept { - ref = nullptr; - return *this; - } - - // optional& operator=(const optional& rhs) noexcept { - // ref = rhs.ref; - // return *this; - // } - - // optional& operator=(optional&& rhs) noexcept { - // ref = rhs.ref; - // return *this; - // } - - template - auto operator=(U&& rhs) noexcept - -> typename enable_if - < - is_same::type, optional>::value, - optional& - >::type - { - ref = rhs.ref; - return *this; - } - - template - auto operator=(U&& rhs) noexcept - -> typename enable_if - < - !is_same::type, optional>::value, - optional& - >::type - = delete; - - void emplace(T& v) noexcept { - ref = detail_::static_addressof(v); - } - - void emplace(T&&) = delete; - - - void swap(optional& rhs) noexcept - { - std::swap(ref, rhs.ref); - } - - // 20.5.5.3, observers - constexpr T* operator->() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref); - } - - constexpr T& operator*() const { - return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref); - } - - constexpr T& value() const { - return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref); - } - - explicit constexpr operator bool() const noexcept { - return ref != nullptr; - } - - constexpr bool has_value() const noexcept { - return ref != nullptr; - } - - template - constexpr typename decay::type value_or(V&& v) const - { - return *this ? **this : detail_::convert::type>(constexpr_forward(v)); - } - - // x.x.x.x, modifiers - void reset() noexcept { ref = nullptr; } -}; - - -template -class optional -{ - static_assert( sizeof(T) == 0, "optional rvalue references disallowed" ); -}; - - -// 20.5.8, Relational operators -template constexpr bool operator==(const optional& x, const optional& y) -{ - return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y; -} - -template constexpr bool operator!=(const optional& x, const optional& y) -{ - return !(x == y); -} - -template constexpr bool operator<(const optional& x, const optional& y) -{ - return (!y) ? false : (!x) ? true : *x < *y; -} - -template constexpr bool operator>(const optional& x, const optional& y) -{ - return (y < x); -} - -template constexpr bool operator<=(const optional& x, const optional& y) -{ - return !(y < x); -} - -template constexpr bool operator>=(const optional& x, const optional& y) -{ - return !(x < y); -} - - -// 20.5.9, Comparison with nullopt -template constexpr bool operator==(const optional& x, nullopt_t) noexcept -{ - return (!x); -} - -template constexpr bool operator==(nullopt_t, const optional& x) noexcept -{ - return (!x); -} - -template constexpr bool operator!=(const optional& x, nullopt_t) noexcept -{ - return bool(x); -} - -template constexpr bool operator!=(nullopt_t, const optional& x) noexcept -{ - return bool(x); -} - -template constexpr bool operator<(const optional&, nullopt_t) noexcept -{ - return false; -} - -template constexpr bool operator<(nullopt_t, const optional& x) noexcept -{ - return bool(x); -} - -template constexpr bool operator<=(const optional& x, nullopt_t) noexcept -{ - return (!x); -} - -template constexpr bool operator<=(nullopt_t, const optional&) noexcept -{ - return true; -} - -template constexpr bool operator>(const optional& x, nullopt_t) noexcept -{ - return bool(x); -} - -template constexpr bool operator>(nullopt_t, const optional&) noexcept -{ - return false; -} - -template constexpr bool operator>=(const optional&, nullopt_t) noexcept -{ - return true; -} - -template constexpr bool operator>=(nullopt_t, const optional& x) noexcept -{ - return (!x); -} - - - -// 20.5.10, Comparison with T -template constexpr bool operator==(const optional& x, const T& v) -{ - return bool(x) ? *x == v : false; -} - -template constexpr bool operator==(const T& v, const optional& x) -{ - return bool(x) ? v == *x : false; -} - -template constexpr bool operator!=(const optional& x, const T& v) -{ - return bool(x) ? *x != v : true; -} - -template constexpr bool operator!=(const T& v, const optional& x) -{ - return bool(x) ? v != *x : true; -} - -template constexpr bool operator<(const optional& x, const T& v) -{ - return bool(x) ? *x < v : true; -} - -template constexpr bool operator>(const T& v, const optional& x) -{ - return bool(x) ? v > *x : true; -} - -template constexpr bool operator>(const optional& x, const T& v) -{ - return bool(x) ? *x > v : false; -} - -template constexpr bool operator<(const T& v, const optional& x) -{ - return bool(x) ? v < *x : false; -} - -template constexpr bool operator>=(const optional& x, const T& v) -{ - return bool(x) ? *x >= v : false; -} - -template constexpr bool operator<=(const T& v, const optional& x) -{ - return bool(x) ? v <= *x : false; -} - -template constexpr bool operator<=(const optional& x, const T& v) -{ - return bool(x) ? *x <= v : true; -} - -template constexpr bool operator>=(const T& v, const optional& x) -{ - return bool(x) ? v >= *x : true; -} - - -// Comparison of optional with T -template constexpr bool operator==(const optional& x, const T& v) -{ - return bool(x) ? *x == v : false; -} - -template constexpr bool operator==(const T& v, const optional& x) -{ - return bool(x) ? v == *x : false; -} - -template constexpr bool operator!=(const optional& x, const T& v) -{ - return bool(x) ? *x != v : true; -} - -template constexpr bool operator!=(const T& v, const optional& x) -{ - return bool(x) ? v != *x : true; -} - -template constexpr bool operator<(const optional& x, const T& v) -{ - return bool(x) ? *x < v : true; -} - -template constexpr bool operator>(const T& v, const optional& x) -{ - return bool(x) ? v > *x : true; -} - -template constexpr bool operator>(const optional& x, const T& v) -{ - return bool(x) ? *x > v : false; -} - -template constexpr bool operator<(const T& v, const optional& x) -{ - return bool(x) ? v < *x : false; -} - -template constexpr bool operator>=(const optional& x, const T& v) -{ - return bool(x) ? *x >= v : false; -} - -template constexpr bool operator<=(const T& v, const optional& x) -{ - return bool(x) ? v <= *x : false; -} - -template constexpr bool operator<=(const optional& x, const T& v) -{ - return bool(x) ? *x <= v : true; -} - -template constexpr bool operator>=(const T& v, const optional& x) -{ - return bool(x) ? v >= *x : true; -} - -// Comparison of optional with T -template constexpr bool operator==(const optional& x, const T& v) -{ - return bool(x) ? *x == v : false; -} - -template constexpr bool operator==(const T& v, const optional& x) -{ - return bool(x) ? v == *x : false; -} - -template constexpr bool operator!=(const optional& x, const T& v) -{ - return bool(x) ? *x != v : true; -} - -template constexpr bool operator!=(const T& v, const optional& x) -{ - return bool(x) ? v != *x : true; -} - -template constexpr bool operator<(const optional& x, const T& v) -{ - return bool(x) ? *x < v : true; -} - -template constexpr bool operator>(const T& v, const optional& x) -{ - return bool(x) ? v > *x : true; -} - -template constexpr bool operator>(const optional& x, const T& v) -{ - return bool(x) ? *x > v : false; -} - -template constexpr bool operator<(const T& v, const optional& x) -{ - return bool(x) ? v < *x : false; -} - -template constexpr bool operator>=(const optional& x, const T& v) -{ - return bool(x) ? *x >= v : false; -} - -template constexpr bool operator<=(const T& v, const optional& x) -{ - return bool(x) ? v <= *x : false; -} - -template constexpr bool operator<=(const optional& x, const T& v) -{ - return bool(x) ? *x <= v : true; -} - -template constexpr bool operator>=(const T& v, const optional& x) -{ - return bool(x) ? v >= *x : true; -} - - -// 20.5.12, Specialized algorithms -template -void swap(optional& x, optional& y) noexcept(noexcept(x.swap(y))) -{ - x.swap(y); -} - - -template -constexpr optional::type> make_optional(T&& v) -{ - return optional::type>(constexpr_forward(v)); -} - -template -constexpr optional make_optional(reference_wrapper v) -{ - return optional(v.get()); -} - - -} // namespace experimental -} // namespace std - -namespace std -{ - template - struct hash> - { - typedef typename hash::result_type result_type; - typedef std::experimental::optional argument_type; - - constexpr result_type operator()(argument_type const& arg) const { - return arg ? std::hash{}(*arg) : result_type{}; - } - }; - - template - struct hash> - { - typedef typename hash::result_type result_type; - typedef std::experimental::optional argument_type; - - constexpr result_type operator()(argument_type const& arg) const { - return arg ? std::hash{}(*arg) : result_type{}; - } - }; -} - -# undef TR2_OPTIONAL_REQUIRES -# undef TR2_OPTIONAL_ASSERTED_EXPRESSION - -# endif //___OPTIONAL_HPP___ diff --git a/src/3rdparty/optional/ottd_optional.h b/src/3rdparty/optional/ottd_optional.h deleted file mode 100644 index 19b44c5055..0000000000 --- a/src/3rdparty/optional/ottd_optional.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 . - */ - -/** @file ottd_optional.h Header to select between native. */ - -#ifndef OTTD_OPTIONAL_H -#define OTTD_OPTIONAL_H - -#if defined(__has_include) -# if __has_include() -# include -# endif -#endif - -#if (__cplusplus >= 201703L) || (defined(__cpp_lib_optional) && __cpp_lib_optional >= 201606L) - -/* Native std::optional. */ -#include -namespace opt = std; - -#else - -/* No std::optional, use local copy instead. */ -#include "optional.hpp" -namespace opt = std::experimental; - -#endif - -#endif /* OTTD_OPTIONAL_H */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0f5f94c08e..449b225eae 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,11 @@ +add_subdirectory(script) +add_subdirectory(settingsgen) +add_subdirectory(strgen) + +if(OPTION_TOOLS_ONLY) + return() +endif() + add_subdirectory(3rdparty) add_subdirectory(ai) add_subdirectory(blitter) @@ -11,11 +19,8 @@ add_subdirectory(network) add_subdirectory(os) add_subdirectory(pathfinder) add_subdirectory(saveload) -add_subdirectory(script) -add_subdirectory(settingsgen) add_subdirectory(sound) add_subdirectory(spriteloader) -add_subdirectory(strgen) add_subdirectory(table) add_subdirectory(video) add_subdirectory(widgets) diff --git a/src/base_media_func.h b/src/base_media_func.h index 02c445c21a..c5e2a6da23 100644 --- a/src/base_media_func.h +++ b/src/base_media_func.h @@ -55,15 +55,15 @@ bool BaseSet::FillSetDetails(IniFile *ini, const } fetch_metadata("shortname"); - for (uint i = 0; item->value.value()[i] != '\0' && i < 4; i++) { - this->shortname |= ((uint8)item->value.value()[i]) << (i * 8); + for (uint i = 0; (*item->value)[i] != '\0' && i < 4; i++) { + this->shortname |= ((uint8)(*item->value)[i]) << (i * 8); } fetch_metadata("version"); this->version = atoi(item->value->c_str()); item = metadata->GetItem("fallback", false); - this->fallback = (item != nullptr && item->value && item->value.value() != "0" && item->value.value() != "false"); + this->fallback = (item != nullptr && item->value && *item->value != "0" && *item->value != "false"); /* For each of the file types we want to find the file, MD5 checksums and warning messages. */ IniGroup *files = ini->GetGroup("files"); diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp index 382596302d..af92f250e0 100644 --- a/src/bridge_gui.cpp +++ b/src/bridge_gui.cpp @@ -442,8 +442,7 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo /* Re-check bridge building possibility is initial bridge builindg query indicated a bridge type dependent failure */ if (query_per_bridge_type && DoCommand(end, start, type | brd_type, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)) | DC_QUERY_COST, CMD_BUILD_BRIDGE).Failed()) continue; /* bridge is accepted, add to list */ - /*C++17: BuildBridgeData &item = */ bl->emplace_back(); - BuildBridgeData &item = bl->back(); + BuildBridgeData &item = bl->emplace_back(); item.index = brd_type; item.spec = GetBridgeSpec(brd_type); /* Add to terraforming & bulldozing costs the cost of the diff --git a/src/core/smallmap_type.hpp b/src/core/smallmap_type.hpp index 5c8d437f64..1904016a8c 100644 --- a/src/core/smallmap_type.hpp +++ b/src/core/smallmap_type.hpp @@ -142,8 +142,7 @@ struct SmallMap : std::vector > { for (uint i = 0; i < std::vector::size(); i++) { if (key == std::vector::operator[](i).first) return std::vector::operator[](i).second; } - /*C++17: Pair &n = */ std::vector::emplace_back(); - Pair &n = std::vector::back(); + Pair &n = std::vector::emplace_back(); n.first = key; return n.second; } diff --git a/src/currency.cpp b/src/currency.cpp index b68584f015..5c758c48df 100644 --- a/src/currency.cpp +++ b/src/currency.cpp @@ -26,14 +26,14 @@ * | | | | | | | */ /** The original currency specifications. */ static const CurrencySpec origin_currency_specs[CURRENCY_END] = { - { 1, "", CF_NOEURO, "\xC2\xA3", "", 0, STR_GAME_OPTIONS_CURRENCY_GBP }, ///< british pound + { 1, "", CF_NOEURO, u8"\u00a3", "", 0, STR_GAME_OPTIONS_CURRENCY_GBP }, ///< british pound { 2, "", CF_NOEURO, "$", "", 0, STR_GAME_OPTIONS_CURRENCY_USD }, ///< american dollar - { 2, "", CF_ISEURO, "\xE2\x82\xAC", "", 0, STR_GAME_OPTIONS_CURRENCY_EUR }, ///< euro - { 220, "", CF_NOEURO, "\xC2\xA5", "", 0, STR_GAME_OPTIONS_CURRENCY_JPY }, ///< japanese yen + { 2, "", CF_ISEURO, u8"\u20ac", "", 0, STR_GAME_OPTIONS_CURRENCY_EUR }, ///< euro + { 220, "", CF_NOEURO, u8"\u00a5", "", 0, STR_GAME_OPTIONS_CURRENCY_JPY }, ///< japanese yen { 27, "", 2002, "", NBSP "S.", 1, STR_GAME_OPTIONS_CURRENCY_ATS }, ///< austrian schilling { 81, "", 2002, "BEF" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_BEF }, ///< belgian franc { 2, "", CF_NOEURO, "CHF" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_CHF }, ///< swiss franc - { 41, "", CF_NOEURO, "", NBSP "K\xC4\x8D", 1, STR_GAME_OPTIONS_CURRENCY_CZK }, ///< czech koruna + { 41, "", CF_NOEURO, "", NBSP u8"K\u010d", 1, STR_GAME_OPTIONS_CURRENCY_CZK }, ///< czech koruna { 4, "", 2002, "DM" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_DEM }, ///< deutsche mark { 11, "", CF_NOEURO, "", NBSP "kr", 1, STR_GAME_OPTIONS_CURRENCY_DKK }, ///< danish krone { 333, "", 2002, "Pts" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_ESP }, ///< spanish peseta @@ -45,7 +45,7 @@ static const CurrencySpec origin_currency_specs[CURRENCY_END] = { { 3873, "", 2002, "", NBSP "L.", 1, STR_GAME_OPTIONS_CURRENCY_ITL }, ///< italian lira { 4, "", 2002, "NLG" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_NLG }, ///< dutch gulden { 12, "", CF_NOEURO, "", NBSP "Kr", 1, STR_GAME_OPTIONS_CURRENCY_NOK }, ///< norwegian krone - { 6, "", CF_NOEURO, "", NBSP "z\xC5\x82", 1, STR_GAME_OPTIONS_CURRENCY_PLN }, ///< polish zloty + { 6, "", CF_NOEURO, "", NBSP u8"z\u0142", 1, STR_GAME_OPTIONS_CURRENCY_PLN }, ///< polish zloty { 5, "", CF_NOEURO, "", NBSP "Lei", 1, STR_GAME_OPTIONS_CURRENCY_RON }, ///< romanian leu { 50, "", CF_NOEURO, "", NBSP "p", 1, STR_GAME_OPTIONS_CURRENCY_RUR }, ///< russian rouble { 479, "", 2007, "", NBSP "SIT", 1, STR_GAME_OPTIONS_CURRENCY_SIT }, ///< slovenian tolar @@ -55,7 +55,7 @@ static const CurrencySpec origin_currency_specs[CURRENCY_END] = { { 4, "", CF_NOEURO, "R$" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_BRL }, ///< brazil real { 31, "", 2011, "", NBSP "EEK", 1, STR_GAME_OPTIONS_CURRENCY_EEK }, ///< estonian krooni { 4, "", 2015, "", NBSP "Lt", 1, STR_GAME_OPTIONS_CURRENCY_LTL }, ///< lithuanian litas - { 1850, "", CF_NOEURO, "\xE2\x82\xA9", "", 0, STR_GAME_OPTIONS_CURRENCY_KRW }, ///< south korean won + { 1850, "", CF_NOEURO, u8"\u20a9", "", 0, STR_GAME_OPTIONS_CURRENCY_KRW }, ///< south korean won { 13, "", CF_NOEURO, "R" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_ZAR }, ///< south african rand { 1, "", CF_NOEURO, "", "", 2, STR_GAME_OPTIONS_CURRENCY_CUSTOM }, ///< custom currency (add further languages below) { 3, "", CF_NOEURO, "", NBSP "GEL", 1, STR_GAME_OPTIONS_CURRENCY_GEL }, ///< Georgian Lari @@ -63,9 +63,9 @@ static const CurrencySpec origin_currency_specs[CURRENCY_END] = { { 80, "", CF_NOEURO, "", NBSP "rub", 1, STR_GAME_OPTIONS_CURRENCY_RUB }, ///< New Russian Ruble { 24, "", CF_NOEURO, "$", "", 0, STR_GAME_OPTIONS_CURRENCY_MXN }, ///< Mexican peso { 40, "", CF_NOEURO, "NTD" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_NTD }, ///< new taiwan dollar - { 8, "", CF_NOEURO, "\xC2\xA5", "", 0, STR_GAME_OPTIONS_CURRENCY_CNY }, ///< chinese renminbi + { 8, "", CF_NOEURO, u8"\u00a5", "", 0, STR_GAME_OPTIONS_CURRENCY_CNY }, ///< chinese renminbi { 10, "", CF_NOEURO, "HKD" NBSP, "", 0, STR_GAME_OPTIONS_CURRENCY_HKD }, ///< hong kong dollar - { 90, "", CF_NOEURO, "\xE2\x82\xB9", "", 0, STR_GAME_OPTIONS_CURRENCY_INR }, ///< Indian Rupee + { 90, "", CF_NOEURO, u8"\u20b9", "", 0, STR_GAME_OPTIONS_CURRENCY_INR }, ///< Indian Rupee }; /** Array of currencies used by the system */ diff --git a/src/engine.cpp b/src/engine.cpp index db5ef0e5fe..ec4fab77aa 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -496,8 +496,7 @@ void EngineOverrideManager::ResetToDefaultMapping() this->clear(); for (VehicleType type = VEH_TRAIN; type <= VEH_AIRCRAFT; type++) { for (uint internal_id = 0; internal_id < _engine_counts[type]; internal_id++) { - /*C++17: EngineIDMapping &eid = */ this->emplace_back(); - EngineIDMapping &eid = this->back(); + EngineIDMapping &eid = this->emplace_back(); eid.type = type; eid.grfid = INVALID_GRFID; eid.internal_id = internal_id; diff --git a/src/fios.h b/src/fios.h index b5fb0ffcd7..9aeaa5b961 100644 --- a/src/fios.h +++ b/src/fios.h @@ -126,8 +126,7 @@ public: */ inline FiosItem *Append() { - /*C++17: return &*/ this->files.emplace_back(); - return &this->files.back(); + return &this->files.emplace_back(); } /** diff --git a/src/fontcache.cpp b/src/fontcache.cpp index c4aa32253b..ea5b255be8 100644 --- a/src/fontcache.cpp +++ b/src/fontcache.cpp @@ -26,7 +26,6 @@ #include "safeguards.h" static const int ASCII_LETTERSTART = 32; ///< First printable ASCII letter. -static const int MAX_FONT_SIZE = 72; ///< Maximum font size. /** Default heights for the different sizes of fonts. */ static const int _default_font_height[FS_END] = {10, 6, 18, 10}; @@ -200,6 +199,8 @@ void UpdateFontHeightCache() FreeTypeSettings _freetype; +static const int MAX_FONT_SIZE = 72; ///< Maximum font size. + static const byte FACE_COLOUR = 1; static const byte SHADOW_COLOUR = 2; diff --git a/src/gfx.cpp b/src/gfx.cpp index 1b5af57cd9..84d165f43c 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -2090,6 +2090,30 @@ void SetAnimatedMouseCursor(const AnimCursor *table) SwitchAnimatedCursor(); } +/** + * Update cursor position on mouse movement for relative modes. + * @param delta_x How much change in the X position. + * @param delta_y How much change in the Y position. + */ +void CursorVars::UpdateCursorPositionRelative(int delta_x, int delta_y) +{ + if (this->fix_at) { + this->delta.x = delta_x; + this->delta.y = delta_y; + } else { + int last_position_x = this->pos.x; + int last_position_y = this->pos.y; + + this->pos.x = Clamp(this->pos.x + delta_x, 0, _cur_resolution.width - 1); + this->pos.y = Clamp(this->pos.y + delta_y, 0, _cur_resolution.height - 1); + + this->delta.x = last_position_x - this->pos.x; + this->delta.y = last_position_y - this->pos.y; + + this->dirty = true; + } +} + /** * Update cursor position on mouse movement. * @param x New X position. diff --git a/src/gfx_type.h b/src/gfx_type.h index 3e08001ad9..e07bd9ed53 100644 --- a/src/gfx_type.h +++ b/src/gfx_type.h @@ -144,6 +144,7 @@ struct CursorVars { /* Drag data */ bool vehchain; ///< vehicle chain is dragged + void UpdateCursorPositionRelative(int delta_x, int delta_y); bool UpdateCursorPosition(int x, int y, bool queued_warp); private: @@ -163,7 +164,9 @@ struct DrawPixelInfo { union Colour { uint32 data; ///< Conversion of the channel information to a 32 bit number. struct { -#if TTD_ENDIAN == TTD_BIG_ENDIAN +#if defined(__EMSCRIPTEN__) + uint8 r, g, b, a; ///< colour channels as used in browsers +#elif TTD_ENDIAN == TTD_BIG_ENDIAN uint8 a, r, g, b; ///< colour channels in BE order #else uint8 b, g, r, a; ///< colour channels in LE order @@ -178,7 +181,9 @@ union Colour { * @param a The channel for the alpha/transparency. */ Colour(uint8 r, uint8 g, uint8 b, uint8 a = 0xFF) : -#if TTD_ENDIAN == TTD_BIG_ENDIAN +#if defined(__EMSCRIPTEN__) + r(r), g(g), b(b), a(a) +#elif TTD_ENDIAN == TTD_BIG_ENDIAN a(a), r(r), g(g), b(b) #else b(b), g(g), r(r), a(a) diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp index 7efcb1abfc..ed43004000 100644 --- a/src/gfxinit.cpp +++ b/src/gfxinit.cpp @@ -504,11 +504,11 @@ bool GraphicsSet::FillSetDetails(IniFile *ini, const char *path, const char *ful IniItem *item; fetch_metadata("palette"); - this->palette = (item->value.value()[0] == 'D' || item->value.value()[0] == 'd') ? PAL_DOS : PAL_WINDOWS; + this->palette = ((*item->value)[0] == 'D' || (*item->value)[0] == 'd') ? PAL_DOS : PAL_WINDOWS; /* Get optional blitter information. */ item = metadata->GetItem("blitter", false); - this->blitter = (item != nullptr && item->value.value()[0] == '3') ? BLT_32BPP : BLT_8BPP; + this->blitter = (item != nullptr && (*item->value)[0] == '3') ? BLT_32BPP : BLT_8BPP; } return ret; } diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index 8ec9935dc9..4abb3f2075 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -473,6 +473,8 @@ CommandCost CmdAlterGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 InvalidateWindowData(WC_REPLACE_VEHICLE, g->vehicle_type, 1); InvalidateWindowData(GetWindowClassForVehicleType(g->vehicle_type), VehicleListIdentifier(VL_GROUP_LIST, g->vehicle_type, _current_company).Pack()); InvalidateWindowData(WC_COMPANY_COLOUR, g->owner, g->vehicle_type); + InvalidateWindowClassesData(WC_VEHICLE_VIEW); + InvalidateWindowClassesData(WC_VEHICLE_DETAILS); InvalidateWindowData(WC_TEMPLATEGUI_MAIN, 0, 0, 0); } @@ -609,6 +611,8 @@ CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, u SetWindowDirty(WC_VEHICLE_VIEW, v->index); SetWindowDirty(WC_VEHICLE_DETAILS, v->index); InvalidateWindowData(GetWindowClassForVehicleType(v->type), VehicleListIdentifier(VL_GROUP_LIST, v->type, _current_company).Pack()); + InvalidateWindowData(WC_VEHICLE_VIEW, v->index); + InvalidateWindowData(WC_VEHICLE_DETAILS, v->index); } return CommandCost(); diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 5e156e4f48..c7abd48702 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -2633,8 +2633,7 @@ struct IndustryCargoesWindow : public Window { _displayed_industries.set(it); this->fields.clear(); - /*C++17: CargoesRow &row = */ this->fields.emplace_back(); - CargoesRow &row = this->fields.back(); + CargoesRow &row = this->fields.emplace_back(); row.columns[0].MakeHeader(STR_INDUSTRY_CARGOES_PRODUCERS); row.columns[1].MakeEmpty(CFT_SMALL_EMPTY); row.columns[2].MakeEmpty(CFT_SMALL_EMPTY); @@ -2649,8 +2648,7 @@ struct IndustryCargoesWindow : public Window { int num_cust = CountMatchingAcceptingIndustries(central_sp->produced_cargo, lengthof(central_sp->produced_cargo)) + houses_accept; int num_indrows = max(3, max(num_supp, num_cust)); // One is needed for the 'it' industry, and 2 for the cargo labels. for (int i = 0; i < num_indrows; i++) { - /*C++17: CargoesRow &row = */ this->fields.emplace_back(); - CargoesRow &row = this->fields.back(); + CargoesRow &row = this->fields.emplace_back(); row.columns[0].MakeEmpty(CFT_EMPTY); row.columns[1].MakeCargo(central_sp->accepts_cargo, lengthof(central_sp->accepts_cargo)); row.columns[2].MakeEmpty(CFT_EMPTY); @@ -2713,8 +2711,7 @@ struct IndustryCargoesWindow : public Window { _displayed_industries.reset(); this->fields.clear(); - /*C++17: CargoesRow &row = */ this->fields.emplace_back(); - CargoesRow &row = this->fields.back(); + CargoesRow &row = this->fields.emplace_back(); row.columns[0].MakeHeader(STR_INDUSTRY_CARGOES_PRODUCERS); row.columns[1].MakeEmpty(CFT_SMALL_EMPTY); row.columns[2].MakeHeader(STR_INDUSTRY_CARGOES_CUSTOMERS); @@ -2727,8 +2724,7 @@ struct IndustryCargoesWindow : public Window { int num_cust = CountMatchingAcceptingIndustries(&cid, 1) + houses_accept; int num_indrows = max(num_supp, num_cust); for (int i = 0; i < num_indrows; i++) { - /*C++17: CargoesRow &row = */ this->fields.emplace_back(); - CargoesRow &row = this->fields.back(); + CargoesRow &row = this->fields.emplace_back(); row.columns[0].MakeEmpty(CFT_EMPTY); row.columns[1].MakeCargo(&cid, 1); row.columns[2].MakeEmpty(CFT_EMPTY); diff --git a/src/ini.cpp b/src/ini.cpp index 6948bc1ea3..fc9b1e8fd2 100644 --- a/src/ini.cpp +++ b/src/ini.cpp @@ -13,6 +13,9 @@ #include "string_func.h" #include "fileio_func.h" #include +#ifdef __EMSCRIPTEN__ +# include +#endif #if (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L) || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 500) # include @@ -115,6 +118,10 @@ bool IniFile::SaveToDisk(const char *filename) } #endif +#ifdef __EMSCRIPTEN__ + EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs()); +#endif + return true; } diff --git a/src/ini_type.h b/src/ini_type.h index 17331ccc58..1cfe8e1202 100644 --- a/src/ini_type.h +++ b/src/ini_type.h @@ -12,7 +12,7 @@ #include "fileio_type.h" #include -#include "3rdparty/optional/ottd_optional.h" +#include #include @@ -27,7 +27,7 @@ enum IniGroupType { struct IniItem { IniItem *next; ///< The next item in this group std::string name; ///< The name of this item - opt::optional value; ///< The value of this item + std::optional value; ///< The value of this item std::string comment; ///< The comment associated with this item IniItem(struct IniGroup *parent, const std::string &name); diff --git a/src/lang/english.txt b/src/lang/english.txt index 296e202739..58f3822726 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -5825,10 +5825,10 @@ STR_INDUSTRY_NAME_SUGAR_MINE :Sugar Mine ##id 0x6000 STR_SV_EMPTY : STR_SV_UNNAMED :Unnamed -STR_SV_TRAIN_NAME :Train {COMMA} -STR_SV_ROAD_VEHICLE_NAME :Road Vehicle {COMMA} -STR_SV_SHIP_NAME :Ship {COMMA} -STR_SV_AIRCRAFT_NAME :Aircraft {COMMA} +STR_SV_TRAIN_NAME :Train #{COMMA} +STR_SV_ROAD_VEHICLE_NAME :Road Vehicle #{COMMA} +STR_SV_SHIP_NAME :Ship #{COMMA} +STR_SV_AIRCRAFT_NAME :Aircraft #{COMMA} STR_SV_STNAME :{STRING1} STR_SV_STNAME_NORTH :{STRING1} North @@ -6135,6 +6135,7 @@ STR_FORMAT_BUOY_NAME :{TOWN} Buoy STR_FORMAT_BUOY_NAME_SERIAL :{TOWN} Buoy #{COMMA} STR_FORMAT_COMPANY_NUM :(Company {COMMA}) STR_FORMAT_GROUP_NAME :Group {COMMA} +STR_FORMAT_GROUP_VEHICLE_NAME :{GROUP} #{COMMA} STR_FORMAT_INDUSTRY_NAME :{TOWN} {STRING} STR_FORMAT_WAYPOINT_NAME :{TOWN} Waypoint STR_FORMAT_WAYPOINT_NAME_SERIAL :{TOWN} Waypoint #{COMMA} diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index e5a1b38c59..ec86104ca7 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -450,73 +450,73 @@ static WindowDesc _about_desc( ); static const char * const _credits[] = { - "Original design by Chris Sawyer", - "Original graphics by Simon Foster", - "", - "The OpenTTD team (in alphabetical order):", - " Grzegorz Duczy\xC5\x84ski (adf88) - General coding (since 1.7.2)", - " Albert Hofkamp (Alberth) - GUI expert (since 0.7)", - " Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3)", - " Ulf Hermann (fonsinchen) - Cargo Distribution (since 1.3)", - " Christoph Elsenhans (frosch) - General coding (since 0.6)", - " Lo\xC3\xAF""c Guilloux (glx) - General / Windows Expert (since 0.4.5)", - " Charles Pigott (LordAro) - General / Correctness police (since 1.9)", - " Michael Lutz (michi_cc) - Path based signals (since 0.7)", - " Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)", - " Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)", - " Peter Nelson (peter1138) - Spiritual descendant from NewGRF gods (since 0.4.5)", - " Ingo von Borstel (planetmaker) - General, Support (since 1.1)", - " Remko Bijker (Rubidium) - Lead coder and way more (since 0.4.5)", - " Jos\xC3\xA9 Soler (Terkhen) - General coding (since 1.0)", - " Leif Linse (Zuu) - AI/Game Script (since 1.2)", - "", - "Inactive Developers:", - " Jean-Fran\xC3\xA7ois Claeys (Belugas) - GUI, NewGRF and more (0.4.5 - 1.0)", - " Bjarni Corfitzen (Bjarni) - MacOSX port, coder and vehicles (0.3 - 0.7)", - " Victor Fischer (Celestar) - Programming everywhere you need him to (0.3 - 0.6)", - " Jaroslav Mazanec (KUDr) - YAPG (Yet Another Pathfinder God) ;) (0.4.5 - 0.6)", - " Jonathan Coome (Maedhros) - High priest of the NewGRF Temple (0.5 - 0.6)", - " Attila B\xC3\xA1n (MiHaMiX) - Developer WebTranslator 1 and 2 (0.3 - 0.5)", - " Zden\xC4\x9Bk Sojka (SmatZ) - Bug finder and fixer (0.6 - 1.3)", - " Christoph Mallon (Tron) - Programmer, code correctness police (0.3 - 0.5)", - " Patric Stout (TrueBrain) - NoAI, NoGo, Network (0.3 - 1.2), sys op (active)", - " Thijs Marinussen (Yexo) - AI Framework, General (0.6 - 1.3)", - "", - "Retired Developers:", - " Tam\xC3\xA1s Farag\xC3\xB3 (Darkvater) - Ex-Lead coder (0.3 - 0.5)", - " Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3 - 0.3)", - " Emil Djupfeld (egladil) - MacOSX (0.4.5 - 0.6)", - " Simon Sasburg (HackyKid) - Many bugfixes (0.4 - 0.4.5)", - " Ludvig Strigeus (ludde) - Original author of OpenTTD, main coder (0.1 - 0.3)", - " Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3)", - " Petr Baudi\xC5\xA1 (pasky) - Many patches, NewGRF support (0.3 - 0.3)", - " Benedikt Br\xC3\xBCggemeier (skidd13) - Bug fixer and code reworker (0.6 - 0.7)", - " Serge Paquet (vurlix) - 2nd contributor after ludde (0.1 - 0.3)", - "", - "Special thanks go out to:", - " Josef Drexler - For his great work on TTDPatch", - " Marcin Grzegorczyk - Track foundations and for describing TTD internals", - " Stefan Mei\xC3\x9Fner (sign_de) - For his work on the console", - " Mike Ragsdale - OpenTTD installer", - " Christian Rosentreter (tokai) - MorphOS / AmigaOS port", - " Richard Kempton (richK) - additional airports, initial TGP implementation", - "", - " Alberto Demichelis - Squirrel scripting language \xC2\xA9 2003-2008", - " L. Peter Deutsch - MD5 implementation \xC2\xA9 1999, 2000, 2002", - " Michael Blunck - Pre-signals and semaphores \xC2\xA9 2003", - " George - Canal/Lock graphics \xC2\xA9 2003-2004", - " Andrew Parkhouse (andythenorth) - River graphics", - " David Dallaston (Pikka) - Tram tracks", - " All Translators - Who made OpenTTD a truly international game", - " Bug Reporters - Without whom OpenTTD would still be full of bugs!", - "", - "", - "Developer of this patchpack:", - " Jonathan G. Rennison (JGR)", - "", - "", - "And last but not least:", - " Chris Sawyer - For an amazing game!" + u8"Original design by Chris Sawyer", + u8"Original graphics by Simon Foster", + u8"", + u8"The OpenTTD team (in alphabetical order):", + u8" Grzegorz Duczy\u0144ski (adf88) - General coding (since 1.7.2)", + u8" Albert Hofkamp (Alberth) - GUI expert (since 0.7)", + u8" Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3)", + u8" Ulf Hermann (fonsinchen) - Cargo Distribution (since 1.3)", + u8" Christoph Elsenhans (frosch) - General coding (since 0.6)", + u8" Lo\u00efc Guilloux (glx) - General / Windows Expert (since 0.4.5)", + u8" Charles Pigott (LordAro) - General / Correctness police (since 1.9)", + u8" Michael Lutz (michi_cc) - Path based signals (since 0.7)", + u8" Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)", + u8" Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)", + u8" Peter Nelson (peter1138) - Spiritual descendant from NewGRF gods (since 0.4.5)", + u8" Ingo von Borstel (planetmaker) - General, Support (since 1.1)", + u8" Remko Bijker (Rubidium) - Lead coder and way more (since 0.4.5)", + u8" Jos\u00e9 Soler (Terkhen) - General coding (since 1.0)", + u8" Leif Linse (Zuu) - AI/Game Script (since 1.2)", + u8"", + u8"Inactive Developers:", + u8" Jean-Fran\u00e7ois Claeys (Belugas) - GUI, NewGRF and more (0.4.5 - 1.0)", + u8" Bjarni Corfitzen (Bjarni) - MacOSX port, coder and vehicles (0.3 - 0.7)", + u8" Victor Fischer (Celestar) - Programming everywhere you need him to (0.3 - 0.6)", + u8" Jaroslav Mazanec (KUDr) - YAPG (Yet Another Pathfinder God) ;) (0.4.5 - 0.6)", + u8" Jonathan Coome (Maedhros) - High priest of the NewGRF Temple (0.5 - 0.6)", + u8" Attila B\u00e1n (MiHaMiX) - Developer WebTranslator 1 and 2 (0.3 - 0.5)", + u8" Zden\u011bk Sojka (SmatZ) - Bug finder and fixer (0.6 - 1.3)", + u8" Christoph Mallon (Tron) - Programmer, code correctness police (0.3 - 0.5)", + u8" Patric Stout (TrueBrain) - NoAI, NoGo, Network (0.3 - 1.2), sys op (active)", + u8" Thijs Marinussen (Yexo) - AI Framework, General (0.6 - 1.3)", + u8"", + u8"Retired Developers:", + u8" Tam\u00e1s Farag\u00f3 (Darkvater) - Ex-Lead coder (0.3 - 0.5)", + u8" Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3 - 0.3)", + u8" Emil Djupfeld (egladil) - MacOSX (0.4.5 - 0.6)", + u8" Simon Sasburg (HackyKid) - Many bugfixes (0.4 - 0.4.5)", + u8" Ludvig Strigeus (ludde) - Original author of OpenTTD, main coder (0.1 - 0.3)", + u8" Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3)", + u8" Petr Baudi\u0161 (pasky) - Many patches, NewGRF support (0.3 - 0.3)", + u8" Benedikt Br\u00fcggemeier (skidd13) - Bug fixer and code reworker (0.6 - 0.7)", + u8" Serge Paquet (vurlix) - 2nd contributor after ludde (0.1 - 0.3)", + u8"", + u8"Special thanks go out to:", + u8" Josef Drexler - For his great work on TTDPatch", + u8" Marcin Grzegorczyk - Track foundations and for describing TTD internals", + u8" Stefan Mei\u00dfner (sign_de) - For his work on the console", + u8" Mike Ragsdale - OpenTTD installer", + u8" Christian Rosentreter (tokai) - MorphOS / AmigaOS port", + u8" Richard Kempton (richK) - additional airports, initial TGP implementation", + u8"", + u8" Alberto Demichelis - Squirrel scripting language \u00a9 2003-2008", + u8" L. Peter Deutsch - MD5 implementation \u00a9 1999, 2000, 2002", + u8" Michael Blunck - Pre-signals and semaphores \u00a9 2003", + u8" George - Canal/Lock graphics \u00a9 2003-2004", + u8" Andrew Parkhouse (andythenorth) - River graphics", + u8" David Dallaston (Pikka) - Tram tracks", + u8" All Translators - Who made OpenTTD a truly international game", + u8" Bug Reporters - Without whom OpenTTD would still be full of bugs!", + u8"", + u8"", + u8"Developer of this patchpack:", + u8" Jonathan G. Rennison (JGR)", + u8"", + u8"", + u8"And last but not least:", + u8" Chris Sawyer - For an amazing game!" }; struct AboutWindow : public Window { diff --git a/src/network/core/address.cpp b/src/network/core/address.cpp index 10b0fd9f7a..1f9db029a9 100644 --- a/src/network/core/address.cpp +++ b/src/network/core/address.cpp @@ -265,6 +265,18 @@ SOCKET NetworkAddress::Resolve(int family, int socktype, int flags, SocketList * this->address_length = (int)runp->ai_addrlen; assert(sizeof(this->address) >= runp->ai_addrlen); memcpy(&this->address, runp->ai_addr, runp->ai_addrlen); +#ifdef __EMSCRIPTEN__ + /* Emscripten doesn't zero sin_zero, but as we compare addresses + * to see if they are the same address, we need them to be zero'd. + * Emscripten is, as far as we know, the only OS not doing this. + * + * https://github.com/emscripten-core/emscripten/issues/12998 + */ + if (this->address.ss_family == AF_INET) { + sockaddr_in *address_ipv4 = (sockaddr_in *)&this->address; + memset(address_ipv4->sin_zero, 0, sizeof(address_ipv4->sin_zero)); + } +#endif break; } @@ -297,7 +309,15 @@ static SOCKET ConnectLoopProc(addrinfo *runp) if (!SetNoDelay(sock)) DEBUG(net, 1, "[%s] setting TCP_NODELAY failed", type); - if (connect(sock, runp->ai_addr, (int)runp->ai_addrlen) != 0) { + int err = connect(sock, runp->ai_addr, (int)runp->ai_addrlen); +#ifdef __EMSCRIPTEN__ + /* Emscripten is asynchronous, and as such a connect() is still in + * progress by the time the call returns. */ + if (err != 0 && errno != EINPROGRESS) +#else + if (err != 0) +#endif + { DEBUG(net, 1, "[%s] could not connect %s socket: %s", type, family, strerror(errno)); closesocket(sock); return INVALID_SOCKET; diff --git a/src/network/core/os_abstraction.h b/src/network/core/os_abstraction.h index 7084ad45c1..dee9acd743 100644 --- a/src/network/core/os_abstraction.h +++ b/src/network/core/os_abstraction.h @@ -99,6 +99,16 @@ typedef unsigned long in_addr_t; # include # include # include + +# if defined(__EMSCRIPTEN__) +/* Emscripten doesn't support AI_ADDRCONFIG and errors out on it. */ +# undef AI_ADDRCONFIG +# define AI_ADDRCONFIG 0 +/* Emscripten says it supports FD_SETSIZE fds, but it really only supports 64. + * https://github.com/emscripten-core/emscripten/issues/1711 */ +# undef FD_SETSIZE +# define FD_SETSIZE 64 +# endif #endif /* UNIX */ /* OS/2 stuff */ @@ -160,6 +170,28 @@ typedef unsigned long in_addr_t; #endif /* OS/2 */ +#ifdef __EMSCRIPTEN__ +/** + * Emscripten doesn't set 'addrlen' for accept(), getsockname(), getpeername() + * and recvfrom(), which confuses other functions and causes them to crash. + * This function needs to be called after these four functions to make sure + * 'addrlen' is patched up. + * + * https://github.com/emscripten-core/emscripten/issues/12996 + * + * @param address The address returned by those four functions. + * @return The correct value for addrlen. + */ +static inline socklen_t FixAddrLenForEmscripten(struct sockaddr_storage &address) +{ + switch (address.ss_family) { + case AF_INET6: return sizeof(struct sockaddr_in6); + case AF_INET: return sizeof(struct sockaddr_in); + default: NOT_REACHED(); + } +} +#endif + /** * Try to set the socket into non-blocking mode. * @param d The socket to set the non-blocking more for. @@ -167,12 +199,16 @@ typedef unsigned long in_addr_t; */ static inline bool SetNonBlocking(SOCKET d) { -#ifdef _WIN32 - u_long nonblocking = 1; +#ifdef __EMSCRIPTEN__ + return true; #else +# ifdef _WIN32 + u_long nonblocking = 1; +# else int nonblocking = 1; -#endif +# endif return ioctlsocket(d, FIONBIO, &nonblocking) == 0; +#endif } /** @@ -197,10 +233,14 @@ static inline bool SetBlocking(SOCKET d) */ static inline bool SetNoDelay(SOCKET d) { +#ifdef __EMSCRIPTEN__ + return true; +#else /* XXX should this be done at all? */ int b = 1; /* The (const char*) cast is needed for windows */ return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) == 0; +#endif } diff --git a/src/network/core/tcp_listen.h b/src/network/core/tcp_listen.h index d2982363e6..1f073aa735 100644 --- a/src/network/core/tcp_listen.h +++ b/src/network/core/tcp_listen.h @@ -42,6 +42,9 @@ public: socklen_t sin_len = sizeof(sin); SOCKET s = accept(ls, (struct sockaddr*)&sin, &sin_len); if (s == INVALID_SOCKET) return; +#ifdef __EMSCRIPTEN__ + sin_len = FixAddrLenForEmscripten(sin); +#endif SetNonBlocking(s); // XXX error handling? diff --git a/src/network/core/udp.cpp b/src/network/core/udp.cpp index eb58ec9d50..ba29339af7 100644 --- a/src/network/core/udp.cpp +++ b/src/network/core/udp.cpp @@ -164,6 +164,9 @@ void NetworkUDPSocketHandler::ReceivePackets() /* Did we get the bytes for the base header of the packet? */ if (nbytes <= 0) break; // No data, i.e. no packet if (nbytes <= 2) continue; // Invalid data; try next packet +#ifdef __EMSCRIPTEN__ + client_len = FixAddrLenForEmscripten(client_addr); +#endif NetworkAddress address(client_addr, client_len); p.PrepareToRead(); diff --git a/src/network/network.cpp b/src/network/network.cpp index 7ac0660415..72fc60ab64 100644 --- a/src/network/network.cpp +++ b/src/network/network.cpp @@ -1122,3 +1122,14 @@ bool IsNetworkCompatibleVersion(const char *other, bool extended) { return strncmp(_openttd_revision, other, (extended ? NETWORK_LONG_REVISION_LENGTH : NETWORK_REVISION_LENGTH) - 1) == 0; } + +#ifdef __EMSCRIPTEN__ +extern "C" { + +void CDECL em_openttd_add_server(const char *host, int port) +{ + NetworkUDPQueryServer(NetworkAddress(host, port), true); +} + +} +#endif diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index f45dd760d9..d0160b7d33 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -23,6 +23,10 @@ #include #endif +#ifdef __EMSCRIPTEN__ +# include +#endif + #include "../safeguards.h" extern bool HasScenario(const ContentInfo *ci, bool md5sum); @@ -296,6 +300,13 @@ void ClientNetworkContentSocketHandler::DownloadSelectedContent(uint &files, uin { bytes = 0; +#ifdef __EMSCRIPTEN__ + /* Emscripten is loaded via an HTTPS connection. As such, it is very + * difficult to make HTTP connections. So always use the TCP method of + * downloading content. */ + fallback = true; +#endif + ContentIDList content; for (const ContentInfo *ci : this->infos) { if (!ci->IsSelected() || ci->state == ContentInfo::ALREADY_HERE) continue; @@ -542,6 +553,10 @@ void ClientNetworkContentSocketHandler::AfterDownload() unlink(GetFullFilename(this->curInfo, false)); } +#ifdef __EMSCRIPTEN__ + EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs()); +#endif + this->OnDownloadComplete(this->curInfo->id); } else { ShowErrorMessage(STR_CONTENT_ERROR_COULD_NOT_EXTRACT, INVALID_STRING_ID, WL_ERROR); diff --git a/src/network/network_gui.cpp b/src/network/network_gui.cpp index 0d6470117d..df7892cf5b 100644 --- a/src/network/network_gui.cpp +++ b/src/network/network_gui.cpp @@ -41,6 +41,9 @@ #include "../safeguards.h" +#ifdef __EMSCRIPTEN__ +# include +#endif static void ShowNetworkStartServerWindow(); static void ShowNetworkLobbyWindow(NetworkGameList *ngl); @@ -490,6 +493,14 @@ public: this->filter_editbox.cancel_button = QueryString::ACTION_CLEAR; this->SetFocusedWidget(WID_NG_FILTER); + /* As the master-server doesn't support "websocket" servers yet, we + * let "os/emscripten/pre.js" hardcode a list of servers people can + * join. This means the serverlist is curated for now, but it is the + * best we can offer. */ +#ifdef __EMSCRIPTEN__ + EM_ASM(if (window["openttd_server_list"]) openttd_server_list()); +#endif + this->last_joined = NetworkGameListAddItem(NetworkAddress(_settings_client.network.last_host, _settings_client.network.last_port)); this->server = this->last_joined; if (this->last_joined != nullptr) NetworkUDPQueryServer(this->last_joined->address); @@ -630,6 +641,12 @@ public: this->GetWidget(WID_NG_NEWGRF_SEL)->SetDisplayedPlane(sel == nullptr || !sel->online || sel->info.grfconfig == nullptr); this->GetWidget(WID_NG_NEWGRF_MISSING_SEL)->SetDisplayedPlane(sel == nullptr || !sel->online || sel->info.grfconfig == nullptr || !sel->info.version_compatible || sel->info.compatible); +#ifdef __EMSCRIPTEN__ + this->SetWidgetDisabledState(WID_NG_FIND, true); + this->SetWidgetDisabledState(WID_NG_ADD, true); + this->SetWidgetDisabledState(WID_NG_START, true); +#endif + this->DrawWidgets(); } diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 5303c7c7ba..010ba8e254 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -1951,8 +1951,7 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, cons tmp_layout.clear(); for (;;) { /* no relative bounding box support */ - /*C++17: DrawTileSeqStruct &dtss = */ tmp_layout.emplace_back(); - DrawTileSeqStruct &dtss = tmp_layout.back(); + DrawTileSeqStruct &dtss = tmp_layout.emplace_back(); MemSetT(&dtss, 0); dtss.delta_x = buf->ReadByte(); @@ -5159,8 +5158,7 @@ static void NewSpriteGroup(ByteReader *buf) /* Loop through the var adjusts. Unfortunately we don't know how many we have * from the outset, so we shall have to keep reallocing. */ do { - /*C++17: DeterministicSpriteGroupAdjust &adjust = */ adjusts.emplace_back(); - DeterministicSpriteGroupAdjust &adjust = adjusts.back(); + DeterministicSpriteGroupAdjust &adjust = adjusts.emplace_back(); /* The first var adjust doesn't have an operation specified, so we set it to add. */ adjust.operation = adjusts.size() == 1 ? DSGA_OP_ADD : (DeterministicSpriteGroupAdjustOperation)buf->ReadByte(); diff --git a/src/newgrf_commons.cpp b/src/newgrf_commons.cpp index 8209d675cd..64eed8139a 100644 --- a/src/newgrf_commons.cpp +++ b/src/newgrf_commons.cpp @@ -664,8 +664,7 @@ uint32 NewGRFSpriteLayout::PrepareLayout(uint32 orig_offset, uint32 newgrf_groun /* Create a copy of the spritelayout, so we can modify some values. * Also include the groundsprite into the sequence for easier processing. */ - /*C++17: DrawTileSeqStruct *result = &*/ result_seq.emplace_back(); - DrawTileSeqStruct *result = &result_seq.back(); + DrawTileSeqStruct *result = &result_seq.emplace_back(); result->image = ground; result->delta_x = 0; result->delta_y = 0; @@ -675,8 +674,7 @@ uint32 NewGRFSpriteLayout::PrepareLayout(uint32 orig_offset, uint32 newgrf_groun foreach_draw_tile_seq(dtss, this->seq) { result_seq.push_back(*dtss); } - result_seq.emplace_back() /*C++17: .MakeTerminator()*/; - result_seq.back().MakeTerminator(); + result_seq.emplace_back().MakeTerminator(); /* Determine the var10 values the action-1-2-3 chains needs to be resolved for, * and apply the default sprite offsets (unless disabled). */ const TileLayoutRegisters *regs = this->registers; diff --git a/src/openttd.cpp b/src/openttd.cpp index 0f3419c723..03828b0809 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -87,6 +87,11 @@ #include "safeguards.h" +#ifdef __EMSCRIPTEN__ +# include +# include +#endif + void CallLandscapeTick(); void IncreaseDate(); void MusicLoop(); @@ -123,6 +128,15 @@ void CDECL usererror(const char *s, ...) ShowOSErrorBox(buf, false); if (VideoDriver::GetInstance() != nullptr) VideoDriver::GetInstance()->Stop(); +#ifdef __EMSCRIPTEN__ + emscripten_exit_pointerlock(); + /* In effect, the game ends here. As emscripten_set_main_loop() caused + * the stack to be unwound, the code after MainLoop() in + * openttd_main() is never executed. */ + EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs()); + EM_ASM(if (window["openttd_abort"]) openttd_abort()); +#endif + exit(1); } diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 1626b2e660..3b8f9ab409 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -3293,8 +3293,7 @@ bool AfterLoadGame() cur_skip = prev_tile_skip; } - /*C++17: uint &this_skip = */ skip_frames.push_back(prev_tile_skip); - uint &this_skip = skip_frames.back(); + uint &this_skip = skip_frames.emplace_back(prev_tile_skip); /* The following 3 curves now take longer than before */ switch (u->state) { diff --git a/src/saveload/engine_sl.cpp b/src/saveload/engine_sl.cpp index 20e2596b3d..78f67f9e20 100644 --- a/src/saveload/engine_sl.cpp +++ b/src/saveload/engine_sl.cpp @@ -191,8 +191,7 @@ static void Load_EIDS() _engine_mngr.clear(); while (SlIterateArray() != -1) { - /*C++17: EngineIDMapping *eid = &*/ _engine_mngr.emplace_back(); - EngineIDMapping *eid = &_engine_mngr.back(); + EngineIDMapping *eid = &_engine_mngr.emplace_back(); SlObject(eid, _engine_id_mapping_desc); } } diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 1fa436bd6f..8ede07ed5c 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -46,6 +46,9 @@ #include "../scope.h" #include #include +#ifdef __EMSCRIPTEN__ +# include +#endif #include "../tbtr_template_vehicle.h" @@ -2928,6 +2931,10 @@ static void SaveFileDone() InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SAVELOAD_FINISH); _sl.saveinprogress = false; + +#ifdef __EMSCRIPTEN__ + EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs()); +#endif } /** Set the error message from outside of the actual loading/saving of the game (AfterLoadGame and friends) */ diff --git a/src/saveload/waypoint_sl.cpp b/src/saveload/waypoint_sl.cpp index 390b403e68..ee137c45a3 100644 --- a/src/saveload/waypoint_sl.cpp +++ b/src/saveload/waypoint_sl.cpp @@ -192,8 +192,7 @@ static void Load_WAYP() int index; while ((index = SlIterateArray()) != -1) { - /*C++17: OldWaypoint *wp = &*/ _old_waypoints.emplace_back(); - OldWaypoint *wp = &_old_waypoints.back(); + OldWaypoint *wp = &_old_waypoints.emplace_back(); wp->index = index; SlObject(wp, _old_waypoint_desc); diff --git a/src/script/CMakeLists.txt b/src/script/CMakeLists.txt index e5915332c4..f4b87dc3b8 100644 --- a/src/script/CMakeLists.txt +++ b/src/script/CMakeLists.txt @@ -1,5 +1,9 @@ add_subdirectory(api) +if(OPTION_TOOLS_ONLY) + return() +endif() + add_files( script_config.cpp script_config.hpp diff --git a/src/script/api/CMakeLists.txt b/src/script/api/CMakeLists.txt index 9bc4183f19..c21707d431 100644 --- a/src/script/api/CMakeLists.txt +++ b/src/script/api/CMakeLists.txt @@ -131,6 +131,10 @@ foreach(API "ai;AI" "game;GS" "template;Template") ) endforeach() +if(OPTION_TOOLS_ONLY) + return() +endif() + add_library(openttd::script_api ALIAS script_api) diff --git a/src/settingsgen/settingsgen.cpp b/src/settingsgen/settingsgen.cpp index 764f370bde..b2a3c76f64 100644 --- a/src/settingsgen/settingsgen.cpp +++ b/src/settingsgen/settingsgen.cpp @@ -118,8 +118,7 @@ public: text += stored_size; } while (length > 0) { - /*C++17: OutputBuffer &block =*/ this->output_buffer.emplace_back(); - OutputBuffer &block = this->output_buffer.back(); + OutputBuffer &block = this->output_buffer.emplace_back(); block.Clear(); // Initialize the new block. size_t stored_size = block.Add(text, length); length -= stored_size; diff --git a/src/strgen/CMakeLists.txt b/src/strgen/CMakeLists.txt index c638b5c6e7..08c1223350 100644 --- a/src/strgen/CMakeLists.txt +++ b/src/strgen/CMakeLists.txt @@ -22,6 +22,10 @@ if (NOT HOST_BINARY_DIR) add_dependencies(tools strgen) endif() +if(OPTION_TOOLS_ONLY) + return() +endif() + # Source Files add_files(strgen_base.cpp) diff --git a/src/string_type.h b/src/string_type.h index 1e01631a0a..cb28417d4f 100644 --- a/src/string_type.h +++ b/src/string_type.h @@ -15,10 +15,10 @@ #include /** A non-breaking space. */ -#define NBSP "\xC2\xA0" +#define NBSP u8"\u00a0" /** A left-to-right marker, marks the next character as left-to-right. */ -#define LRM "\xE2\x80\x8E" +#define LRM u8"\u200e" /** * Valid filter types for IsValidChar. diff --git a/src/stringfilter.cpp b/src/stringfilter.cpp index 30876a82d8..4765a880e1 100644 --- a/src/stringfilter.cpp +++ b/src/stringfilter.cpp @@ -74,8 +74,7 @@ void StringFilter::SetFilterTerm(const char *str) /* Add to word */ if (word == nullptr) { - /*C++17: word = &*/ this->word_index.push_back({dest, false}); - word = &this->word_index.back(); + word = &this->word_index.emplace_back(WordState{ dest, false }); } memcpy(dest, pos, len); diff --git a/src/strings.cpp b/src/strings.cpp index fbe6f22663..a558e7c4a0 100644 --- a/src/strings.cpp +++ b/src/strings.cpp @@ -1758,6 +1758,11 @@ static char *FormatString(char *buff, const char *str_arg, StringParameters *arg int64 args_array[] = {(int64)(size_t)v->name.c_str()}; StringParameters tmp_params(args_array); buff = GetStringWithArgs(buff, STR_JUST_RAW_STRING, &tmp_params, last); + } else if (v->group_id != DEFAULT_GROUP) { + /* The vehicle has no name, but is member of a group, so print group name */ + int64 args_array[] = {v->group_id, v->unitnumber}; + StringParameters tmp_params(args_array); + buff = GetStringWithArgs(buff, STR_FORMAT_GROUP_VEHICLE_NAME, &tmp_params, last); } else { int64 args_array[] = {v->unitnumber}; StringParameters tmp_params(args_array); diff --git a/src/table/townname.h b/src/table/townname.h index 6310b19489..03e5a9f6a3 100644 --- a/src/table/townname.h +++ b/src/table/townname.h @@ -314,7 +314,7 @@ static const char * const _name_austrian_a2[] = { "Aus", "Alten", "Braun", - "V\xC3\xB6sl", + u8"V\u00f6sl", "Mittern", "Nuss", "Neu", @@ -336,9 +336,9 @@ static const char * const _name_austrian_a2[] = { "Frauen", "Herren", "Hof", - "H\xC3\xBCtt", + u8"H\u00fctt", "Kaisers", - "K\xC3\xB6nigs", + u8"K\u00f6nigs", "Knittel", "Lang", "Ober", @@ -350,7 +350,7 @@ static const char * const _name_austrian_a2[] = { "Stocker", "Unter", "Utten", - "V\xC3\xB6sen", + u8"V\u00f6sen", "Vill", "Weissen", }; @@ -396,7 +396,7 @@ static const char * const _name_austrian_a5[] = { static const char * const _name_austrian_a6[] = { "Aegyd", - "Andr\xC3\xA4", + u8"Andr\u00e4", "Georgen", "Jakob", "Johann", @@ -409,7 +409,7 @@ static const char * const _name_austrian_a6[] = { "Nikolai", "Oswald", "Peter", - "P\xC3\xB6lten", + u8"P\u00f6lten", "Stefan", "Stephan", "Thomas", @@ -470,10 +470,10 @@ static const char * const _name_german_real[] = { "Gera", "Kassel", "Kiel", - "K\xC3\xB6ln", - "L\xC3\xBC""beck", + u8"K\u00f6ln", + u8"L\u00fcbeck", "Magdeburg", - "M\xC3\xBCnchen", + u8"M\u00fcnchen", "Potsdam", "Stuttgart", "Wiesbaden", @@ -496,7 +496,7 @@ static const char * const _name_german_1[] = { "Cloppen", "Co", "Duis", - "D\xC3\xBCssel", + u8"D\u00fcssel", "Dannen", "Elb", "Els", @@ -510,7 +510,7 @@ static const char * const _name_german_1[] = { "Frei", "Freuden", "Fried", - "F\xC3\xBCrsten", + u8"F\u00fcrsten", "Hahn", "Ham", "Harz", @@ -531,10 +531,10 @@ static const char * const _name_german_1[] = { "Langen", "Lim", "Lohr", - "L\xC3\xBCne", + u8"L\u00fcne", "Mel", "Michels", - "M\xC3\xBChl", + u8"M\u00fchl", "Naum", "Nest", "Nord", @@ -542,7 +542,7 @@ static const char * const _name_german_1[] = { "Nien", "Nidda", "Nieder", - "N\xC3\xBCrn", + u8"N\u00fcrn", "Ober", "Offen", "Osna", @@ -556,18 +556,18 @@ static const char * const _name_german_1[] = { "Regens", "Rott", "Ros", - "R\xC3\xBCssels", + u8"R\u00fcssels", "Saal", "Saar", "Salz", - "Sch\xC3\xB6ne", + u8"Sch\u00f6ne", "Schwein", "Sonder", "Sonnen", "Stein", "Strals", "Straus", - "S\xC3\xBC""d", + u8"S\u00fcd", "Ton", "Unter", "Ur", @@ -578,14 +578,14 @@ static const char * const _name_german_1[] = { "Wester", "Witten", "Wolfs", - "W\xC3\xBCrz", + u8"W\u00fcrz", }; static const char * const _name_german_2[] = { "bach", "berg", - "br\xC3\xBC""ck", - "br\xC3\xBC""cken", + u8"br\u00fcck", + u8"br\u00fccken", "burg", "dorf", "feld", @@ -595,7 +595,7 @@ static const char * const _name_german_2[] = { "heim", "horst", "mund", - "m\xC3\xBCnster", + u8"m\u00fcnster", "stadt", "wald", }; @@ -629,9 +629,9 @@ static const char * const _name_spanish_real[] = { "Morrocoy", "Cata", "Cataito", - "Ciudad Bol\xC3\xADvar", + u8"Ciudad Bol\u00edvar", "Barquisimeto", - "M\xC3\xA9rida", + u8"M\u00e9rida", "Puerto Ordaz", "Santa Elena", "San Juan", @@ -640,58 +640,58 @@ static const char * const _name_spanish_real[] = { "Santiago", "Barcelona", "Barinas", - "San Crist\xC3\xB3""bal", + u8"San Crist\u00f3bal", "San Francisco", - "San Mart\xC3\xADn", + u8"San Mart\u00edn", "Guayana", "San Carlos", - "El Lim\xC3\xB3n", + u8"El Lim\u00f3n", "Coro", "Coro Coro", "Puerto Ayacucho", "Elorza", "Arismendi", "Trujillo", - "Car\xC3\xBApano", + u8"Car\u00fapano", "Anaco", "Lima", "Cuzco", "Iquitos", "Callao", "Huacho", - "Caman\xC3\xA1", + u8"Caman\u00e1", "Puerto Chala", "Santa Cruz", "Quito", "Cuenca", - "Medell\xC3\xADn", - "Tulc\xC3\xA1n", + u8"Medell\u00edn", + u8"Tulc\u00e1n", "Esmeraldas", "Ibarra", "San Lorenzo", "Macas", - "Mora\xC3\xB1""a", + u8"Mora\u00f1a", "Machala", "Zamora", "Latacunga", "Tena", "Cochabamba", - "Ascensi\xC3\xB3n", + u8"Ascensi\u00f3n", "Magdalena", "Santa Ana", "Manoa", "Sucre", "Oruro", "Uyuni", - "Potos\xC3\xAD", + u8"Potos\u00ed", "Tupiza", "La Quiaca", - "Yacu\xC3\xAD""ba", + u8"Yacu\u00edba", "San Borja", "Fuerte Olimpo", - "Fort\xC3\xADn Esteros", + u8"Fort\u00edn Esteros", "Campo Grande", - "Bogot\xC3\xA1", + u8"Bogot\u00e1", "El Banco", "Zaragoza", "Neiva", @@ -719,7 +719,7 @@ static const char * const _name_french_real[] = { "Bordeaux", "Bayonne", "Montpellier", - "Mont\xC3\xA9limar", + u8"Mont\u00e9limar", "Valence", "Digne", "Nice", @@ -727,16 +727,16 @@ static const char * const _name_french_real[] = { "St. Tropez", "Marseille", "Narbonne", - "S\xC3\xA8te", + u8"S\u00e8te", "Aurillac", - "Gu\xC3\xA9ret", + u8"Gu\u00e9ret", "Le Creusot", "Nevers", "Auxerre", "Versailles", "Meaux", - "Ch\xC3\xA2lons", - "Compi\xC3\xA8gne", + u8"Ch\u00e2lons", + u8"Compi\u00e8gne", "Metz", "Chaumont", "Langres", @@ -749,8 +749,8 @@ static const char * const _name_french_real[] = { "Le Mans", "Angers", "Nantes", - "Ch\xC3\xA2teauroux", - "Orl\xC3\xA9""ans", + u8"Ch\u00e2teauroux", + u8"Orl\u00e9ans", "Lisieux", "Cherbourg", "Morlaix", @@ -761,7 +761,7 @@ static const char * const _name_french_real[] = { "Troyes", "Charolles", "Toulouse", - "Chamb\xC3\xA9ry", + u8"Chamb\u00e9ry", "Tours", "St. Brieuc", "St. Malo", @@ -775,11 +775,11 @@ static const char * const _name_french_real[] = { "Albi", "Paris", "Biarritz", - "B\xC3\xA9ziers", - "N\xC3\xAEmes", + u8"B\u00e9ziers", + u8"N\u00eemes", "Chamonix", - "Angoul\xC3\xA8me", - "Alen\xC3\xA7on", + u8"Angoul\u00e8me", + u8"Alen\u00e7on", }; static const char * const _name_silly_1[] = { @@ -907,7 +907,7 @@ static const char * const _name_swedish_2[] = { "Es", "Fin", "Fisk", - "Gr\xC3\xB6n", + u8"Gr\u00f6n", "Hag", "Halm", "Karl", @@ -926,17 +926,17 @@ static const char * const _name_swedish_2[] = { "Skog", "Stock", "Stor", - "Str\xC3\xB6m", + u8"Str\u00f6m", "Sund", - "S\xC3\xB6""der", + u8"S\u00f6der", "Tall", "Tratt", "Troll", "Upp", "Var", - "V\xC3\xA4ster", - "\xC3\x84ngel", - "\xC3\x96ster", + u8"V\u00e4ster", + u8"\u00c4ngel", + u8"\u00d6ster", }; static const char * const _name_swedish_2a[] = { @@ -991,9 +991,9 @@ static const char * const _name_swedish_2b[] = { "o", "u", "y", - "\xC3\xA5", - "\xC3\xA4", - "\xC3\xB6", + u8"\u00e5", + u8"\u00e4", + u8"\u00f6", }; static const char * const _name_swedish_2c[] = { @@ -1039,25 +1039,25 @@ static const char * const _name_swedish_3[] = { "hamn", "holm", "hus", - "h\xC3\xA4ttan", + u8"h\u00e4ttan", "kulle", - "k\xC3\xB6ping", + u8"k\u00f6ping", "lund", - "l\xC3\xB6v", + u8"l\u00f6v", "sala", "skrona", - "sl\xC3\xA4tt", - "sp\xC3\xA5ng", + u8"sl\u00e4tt", + u8"sp\u00e5ng", "stad", "sund", "svall", "svik", - "s\xC3\xA5ker", + u8"s\u00e5ker", "udde", "valla", "viken", - "\xC3\xA4lv", - "\xC3\xA5s", + u8"\u00e4lv", + u8"\u00e5s", }; static const char * const _name_dutch_1[] = { @@ -1224,7 +1224,7 @@ static const char * const _name_finnish_real[] = { "Espoo", "Helsinki", "Tapiola", - "J\xC3\xA4rvel\xC3\xA4", + u8"J\u00e4rvel\u00e4", "Lahti", "Kotka", "Hamina", @@ -1259,26 +1259,26 @@ static const char * const _name_finnish_1[] = { "Sauna", "Uusi", "Vanha", - "Kes\xC3\xA4", + u8"Kes\u00e4", "Kuusi", "Pelto", "Tuomi", "Terva", "Olki", - "Hein\xC3\xA4", - "Sein\xC3\xA4", + u8"Hein\u00e4", + u8"Sein\u00e4", "Rova", "Koivu", "Kokko", - "M\xC3\xA4nty", + u8"M\u00e4nty", "Pihlaja", - "Pet\xC3\xA4j\xC3\xA4", + u8"Pet\u00e4j\u00e4", "Kielo", "Kauha", "Viita", "Kivi", "Riihi", - "\xC3\x84\xC3\xA4ne", + u8"\u00c4\u00e4ne", "Niini", }; @@ -1287,27 +1287,27 @@ static const char * const _name_finnish_2[] = { "Lohjan", "Savon", "Lapin", - "Pit\xC3\xA4j\xC3\xA4n", + u8"Pit\u00e4j\u00e4n", "Martin", "Kuusan", "Kemi", "Keri", - "H\xC3\xA4meen", + u8"H\u00e4meen", "Kangas", }; static const char * const _name_finnish_3[] = { "harju", "linna", - "j\xC3\xA4rvi", + u8"j\u00e4rvi", "kallio", - "m\xC3\xA4ki", + u8"m\u00e4ki", "nummi", "joki", - "kyl\xC3\xA4", + u8"kyl\u00e4", "lampi", "lahti", - "mets\xC3\xA4", + u8"mets\u00e4", "suo", "laakso", "niitty", @@ -1320,56 +1320,56 @@ static const char * const _name_finnish_3[] = { static const char * const _name_polish_1_m[] = { "Wielki ", - "Ma\xC5\x82y ", - "Z\xC5\x82y ", + u8"Ma\u0142y ", + u8"Z\u0142y ", "Dobry ", "Nowy ", "Stary ", - "Z\xC5\x82oty ", + u8"Z\u0142oty ", "Zielony ", - "Bia\xC5\x82y ", + u8"Bia\u0142y ", "Modry ", - "D\xC4\x99""bowy ", + u8"D\u0119bowy ", }; static const char * const _name_polish_1_f[] = { "Wielka ", - "Ma\xC5\x82""a ", - "Z\xC5\x82""a ", + u8"Ma\u0142a ", + u8"Z\u0142a ", "Dobra ", "Nowa ", "Stara ", - "Z\xC5\x82ota ", + u8"Z\u0142ota ", "Zielona ", - "Bia\xC5\x82""a ", + u8"Bia\u0142a ", "Modra ", - "D\xC4\x99""bowa ", + u8"D\u0119bowa ", }; static const char * const _name_polish_1_n[] = { "Wielkie ", - "Ma\xC5\x82""e ", - "Z\xC5\x82""e ", + u8"Ma\u0142e ", + u8"Z\u0142e ", "Dobre ", "Nowe ", "Stare ", - "Z\xC5\x82ote ", + u8"Z\u0142ote ", "Zielone ", - "Bia\xC5\x82""e ", + u8"Bia\u0142e ", "Modre ", - "D\xC4\x99""bowe ", + u8"D\u0119bowe ", }; static const char * const _name_polish_2_o[] = { "Frombork", "Gniezno", "Olsztyn", - "Toru\xC5\x84", + u8"Toru\u0144", "Bydgoszcz", "Terespol", - "Krak\xC3\xB3w", - "Pozna\xC5\x84", - "Wroc\xC5\x82""aw", + u8"Krak\u00f3w", + u8"Pozna\u0144", + u8"Wroc\u0142aw", "Katowice", "Cieszyn", "Bytom", @@ -1380,7 +1380,7 @@ static const char * const _name_polish_2_o[] = { "Malbork", "Sopot", "Sosnowiec", - "Gda\xC5\x84sk", + u8"Gda\u0144sk", "Gdynia", "Sieradz", "Sandomierz", @@ -1388,7 +1388,7 @@ static const char * const _name_polish_2_o[] = { "Szczytno", "Szczecin", "Zakopane", - "Szklarska Por\xC4\x99""ba", + u8"Szklarska Por\u0119ba", "Bochnia", "Golub-Dobrzyn", "Chojnice", @@ -1400,13 +1400,13 @@ static const char * const _name_polish_2_o[] = { static const char * const _name_polish_2_m[] = { "Jarocin", "Gogolin", - "Tomasz\xC3\xB3w", - "Piotrk\xC3\xB3w", + u8"Tomasz\u00f3w", + u8"Piotrk\u00f3w", "Lidzbark", "Rypin", "Radzymin", - "Wo\xC5\x82omin", - "Pruszk\xC3\xB3w", + u8"Wo\u0142omin", + u8"Pruszk\u00f3w", "Olsztynek", "Rypin", "Cisek", @@ -1416,7 +1416,7 @@ static const char * const _name_polish_2_m[] = { "Lubicz", "Milicz", "Targ", - "Ostr\xC3\xB3w", + u8"Ostr\u00f3w", "Ozimek", "Puck", "Rzepin", @@ -1429,7 +1429,7 @@ static const char * const _name_polish_2_m[] = { "Strzepcz", "Strzebielin", "Sochaczew", - "Gr\xC4\x99""bocin", + u8"Gr\u0119bocin", "Gniew", "Lubliniec", "Lubasz", @@ -1451,7 +1451,7 @@ static const char * const _name_polish_2_m[] = { static const char * const _name_polish_2_f[] = { "Szprotawa", "Pogorzelica", - "Mot\xC5\x82""awa", + u8"Mot\u0142awa", "Lubawa", "Nidzica", "Kruszwica", @@ -1505,7 +1505,7 @@ static const char * const _name_polish_2_n[] = { "Braniewo", "Sulinowo", "Chmielno", - "Jastrz\xC4\x99""bie", + u8"Jastrz\u0119bie", "Gryfino", "Koronowo", "Lubichowo", @@ -1514,182 +1514,182 @@ static const char * const _name_polish_2_n[] = { static const char * const _name_polish_3_m[] = { " Wybudowanie", - " \xC5\x9Awi\xC4\x99tokrzyski", - " G\xC3\xB3rski", + u8" \u015awi\u0119tokrzyski", + u8" G\u00f3rski", " Morski", - " Zdr\xC3\xB3j", + u8" Zdr\u00f3j", " Wody", " Bajoro", - " Kraje\xC5\x84ski", - " \xC5\x9Al\xC4\x85ski", + u8" Kraje\u0144ski", + u8" \u015al\u0105ski", " Mazowiecki", " Pomorski", " Wielki", " Maly", - " Warmi\xC5\x84ski", + u8" Warmi\u0144ski", " Mazurski", " Mniejszy", - " Wi\xC4\x99kszy", - " G\xC3\xB3rny", + u8" Wi\u0119kszy", + u8" G\u00f3rny", " Dolny", " Wielki", " Stary", " Nowy", " Wielkopolski", - " Wzg\xC3\xB3rze", + u8" Wzg\u00f3rze", " Mosty", " Kujawski", - " Ma\xC5\x82opolski", + u8" Ma\u0142opolski", " Podlaski", " Lesny", }; static const char * const _name_polish_3_f[] = { " Wybudowanie", - " \xC5\x9Awi\xC4\x99tokrzyska", - " G\xC3\xB3rska", + u8" \u015awi\u0119tokrzyska", + u8" G\u00f3rska", " Morska", - " Zdr\xC3\xB3j", + u8" Zdr\u00f3j", " Woda", " Bajoro", - " Kraje\xC5\x84ska", - " \xC5\x9Al\xC4\x85ska", + u8" Kraje\u0144ska", + u8" \u015al\u0105ska", " Mazowiecka", " Pomorska", " Wielka", - " Ma\xC5\x82""a", - " Warmi\xC5\x84ska", + u8" Ma\u0142a", + u8" Warmi\u0144ska", " Mazurska", " Mniejsza", - " Wi\xC4\x99ksza", - " G\xC3\xB3rna", + u8" Wi\u0119ksza", + u8" G\u00f3rna", " Dolna", " Wielka", " Stara", " Nowa", " Wielkopolska", - " Wzg\xC3\xB3rza", + u8" Wzg\u00f3rza", " Mosty", " Kujawska", " Malopolska", " Podlaska", - " Le\xC5\x9Bna", + u8" Le\u015bna", }; static const char * const _name_polish_3_n[] = { " Wybudowanie", - " \xC5\x9Awietokrzyskie", - " G\xC3\xB3rskie", + u8" \u015awietokrzyskie", + u8" G\u00f3rskie", " Morskie", - " Zdr\xC3\xB3j", + u8" Zdr\u00f3j", " Wody", " Bajoro", - " Kraje\xC5\x84skie", - " \xC5\x9Al\xC4\x85skie", + u8" Kraje\u0144skie", + u8" \u015al\u0105skie", " Mazowieckie", " Pomorskie", " Wielkie", - " Ma\xC5\x82""e", - " Warmi\xC5\x84skie ", + u8" Ma\u0142e", + u8" Warmi\u0144skie ", " Mazurskie ", " Mniejsze", - " Wi\xC4\x99ksze", - " G\xC3\xB3rne", + u8" Wi\u0119ksze", + u8" G\u00f3rne", " Dolne", " Wielkie", " Stare", " Nowe", " Wielkopolskie", - " Wzg\xC3\xB3rze", + u8" Wzg\u00f3rze", " Mosty", " Kujawskie", - " Ma\xC5\x82opolskie", + u8" Ma\u0142opolskie", " Podlaskie", - " Le\xC5\x9Bne", + u8" Le\u015bne", }; static const char * const _name_czech_real[] = { - "A\xC5\xA1", - "Bene\xC5\xA1ov", + u8"A\u0161", + u8"Bene\u0161ov", "Beroun", - "Bezdru\xC5\xBEice", + u8"Bezdru\u017eice", "Blansko", - "B\xC5\x99""eclav", + u8"B\u0159eclav", "Brno", - "Brunt\xC3\xA1l", - "\xC4\x8C""esk\xC3\xA1 L\xC3\xADpa", - "\xC4\x8C""esk\xC3\xA9 Bud\xC4\x9Bjovice", - "\xC4\x8C""esk\xC3\xBD Krumlov", - "D\xC4\x9B\xC4\x8D\xC3\xADn", - "Doma\xC5\xBElice", - "Dub\xC3\xAD", - "Fr\xC3\xBD""dek-M\xC3\xADstek", - "Havl\xC3\xAD\xC4\x8Dk\xC5\xAFv Brod", - "Hodon\xC3\xADn", - "Hradec Kr\xC3\xA1lov\xC3\xA9", + u8"Brunt\u00e1l", + u8"\u010cesk\u00e1 L\u00edpa", + u8"\u010cesk\u00e9 Bud\u011bjovice", + u8"\u010cesk\u00fd Krumlov", + u8"D\u011b\u010d\u00edn", + u8"Doma\u017elice", + u8"Dub\u00ed", + u8"Fr\u00fddek-M\u00edstek", + u8"Havl\u00ed\u010dk\u016fv Brod", + u8"Hodon\u00edn", + u8"Hradec Kr\u00e1lov\u00e9", "Humpolec", "Cheb", "Chomutov", "Chrudim", "Jablonec nad Nisou", - "Jesen\xC3\xADk", - "Ji\xC4\x8D\xC3\xADn", + u8"Jesen\u00edk", + u8"Ji\u010d\u00edn", "Jihlava", - "Jind\xC5\x99ich\xC5\xAFv Hradec", + u8"Jind\u0159ich\u016fv Hradec", "Karlovy Vary", - "Karvin\xC3\xA1", + u8"Karvin\u00e1", "Kladno", "Klatovy", - "Kol\xC3\xADn", + u8"Kol\u00edn", "Kosmonosy", - "Krom\xC4\x9B\xC5\x99\xC3\xAD\xC5\xBE", - "Kutn\xC3\xA1 Hora", + u8"Krom\u011b\u0159\u00ed\u017e", + u8"Kutn\u00e1 Hora", "Liberec", - "Litom\xC4\x9B\xC5\x99ice", + u8"Litom\u011b\u0159ice", "Louny", - "Man\xC4\x9Bt\xC3\xADn", - "M\xC4\x9Bln\xC3\xADk", - "Mlad\xC3\xA1 Boleslav", + u8"Man\u011bt\u00edn", + u8"M\u011bln\u00edk", + u8"Mlad\u00e1 Boleslav", "Most", - "N\xC3\xA1""chod", - "Nov\xC3\xBD Ji\xC4\x8D\xC3\xADn", + u8"N\u00e1chod", + u8"Nov\u00fd Ji\u010d\u00edn", "Nymburk", "Olomouc", "Opava", - "Or\xC3\xA1\xC4\x8Dov", + u8"Or\u00e1\u010dov", "Ostrava", "Pardubice", - "Pelh\xC5\x99imov", - "Pol\xC5\xBEice", - "P\xC3\xADsek", - "Plze\xC5\x88", + u8"Pelh\u0159imov", + u8"Pol\u017eice", + u8"P\u00edsek", + u8"Plze\u0148", "Praha", "Prachatice", - "P\xC5\x99""erov", - "P\xC5\x99\xC3\xAD""bram", - "Prost\xC4\x9Bjov", - "Rakovn\xC3\xADk", + u8"P\u0159erov", + u8"P\u0159\u00edbram", + u8"Prost\u011bjov", + u8"Rakovn\u00edk", "Rokycany", - "Rudn\xC3\xA1", - "Rychnov nad Kn\xC4\x9B\xC5\xBEnou", + u8"Rudn\u00e1", + u8"Rychnov nad Kn\u011b\u017enou", "Semily", "Sokolov", "Strakonice", - "St\xC5\x99""edokluky", - "\xC5\xA0umperk", + u8"St\u0159edokluky", + u8"\u0160umperk", "Svitavy", - "T\xC3\xA1""bor", + u8"T\u00e1bor", "Tachov", "Teplice", - "T\xC5\x99""eb\xC3\xAD\xC4\x8D", + u8"T\u0159eb\u00ed\u010d", "Trutnov", - "Uhersk\xC3\xA9 Hradi\xC5\xA1t\xC4\x9B", - "\xC3\x9Ast\xC3\xAD nad Labem", - "\xC3\x9Ast\xC3\xAD nad Orlic\xC3\xAD", - "Vset\xC3\xADn", - "Vy\xC5\xA1kov", - "\xC5\xBD\xC4\x8F\xC3\xA1r nad S\xC3\xA1zavou", - "Zl\xC3\xADn", + u8"Uhersk\u00e9 Hradi\u0161t\u011b", + u8"\u00dast\u00ed nad Labem", + u8"\u00dast\u00ed nad Orlic\u00ed", + u8"Vset\u00edn", + u8"Vy\u0161kov", + u8"\u017d\u010f\u00e1r nad S\u00e1zavou", + u8"Zl\u00edn", "Znojmo", }; @@ -1723,12 +1723,12 @@ enum CzechPattern { * by this. * XXX: [CZG_SMASC][CZP_PRIVL] needs special handling: -ovX -> -uv. */ static const char * const _name_czech_patmod[][3] = { - /* CZG_SMASC */ { "\xC3\xAD", "\xC3\xBD", "X" }, - /* CZG_SFEM */ { "\xC3\xAD", "\xC3\xA1", "a" }, - /* CZG_SNEUT */ { "\xC3\xAD", "\xC3\xA9", "o" }, - /* CZG_PMASC */ { "\xC3\xAD", "\xC3\xA9", "y" }, - /* CZG_PFEM */ { "\xC3\xAD", "\xC3\xA9", "y" }, - /* CZG_PNEUT */ { "\xC3\xAD", "\xC3\xA1", "a" } + /* CZG_SMASC */ { u8"\u00ed", u8"\u00fd", "X" }, + /* CZG_SFEM */ { u8"\u00ed", u8"\u00e1", "a" }, + /* CZG_SNEUT */ { u8"\u00ed", u8"\u00e9", "o" }, + /* CZG_PMASC */ { u8"\u00ed", u8"\u00e9", "y" }, + /* CZG_PFEM */ { u8"\u00ed", u8"\u00e9", "y" }, + /* CZG_PNEUT */ { u8"\u00ed", u8"\u00e1", "a" } }; /* This way the substantive can choose only some adjectives/endings: @@ -1768,52 +1768,52 @@ struct CzechNameAdj { /* Some of items which should be common are doubled. */ static const CzechNameAdj _name_czech_adj[] = { - { CZP_JARNI, CZC_ANY, "Horn\xC3\xAD" }, - { CZP_JARNI, CZC_ANY, "Horn\xC3\xAD" }, - { CZP_JARNI, CZC_ANY, "Doln\xC3\xAD" }, - { CZP_JARNI, CZC_ANY, "Doln\xC3\xAD" }, - { CZP_JARNI, CZC_ANY, "P\xC5\x99""edn\xC3\xAD" }, - { CZP_JARNI, CZC_ANY, "Zadn\xC3\xAD" }, - { CZP_JARNI, CZC_ANY, "Kosteln\xC3\xAD" }, - { CZP_JARNI, CZC_ANY, "Havran\xC3\xAD" }, - { CZP_JARNI, CZC_ANY, "\xC5\x98\xC3\xAD\xC4\x8Dn\xC3\xAD" }, - { CZP_JARNI, CZC_ANY, "Jezern\xC3\xAD" }, - { CZP_MLADY, CZC_ANY, "Velk\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Velk\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Mal\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Mal\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Vysok\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "\xC4\x8C""esk\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Moravsk\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Slov\xC3\xA1""ck\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Slezsk\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Uhersk\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Star\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Star\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Nov\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Nov\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Mlad\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Kr\xC3\xA1lovsk\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Kamenn\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Cihlov\xC3\xBD" }, - { CZP_MLADY, CZC_ANY, "Divn\xC3\xBD" }, - { CZP_MLADY, CZC_COLOR, "\xC4\x8C""erven\xC3\xA1" }, - { CZP_MLADY, CZC_COLOR, "\xC4\x8C""erven\xC3\xA1" }, - { CZP_MLADY, CZC_COLOR, "\xC4\x8C""erven\xC3\xA1" }, - { CZP_MLADY, CZC_COLOR, "Zelen\xC3\xA1" }, - { CZP_MLADY, CZC_COLOR, "\xC5\xBDlut\xC3\xA1" }, - { CZP_MLADY, CZC_COLOR, "Siv\xC3\xA1" }, - { CZP_MLADY, CZC_COLOR, "\xC5\xA0""ed\xC3\xA1" }, - { CZP_MLADY, CZC_COLOR, "B\xC3\xADl\xC3\xA1" }, - { CZP_MLADY, CZC_COLOR, "B\xC3\xADl\xC3\xA1" }, - { CZP_MLADY, CZC_COLOR, "Modr\xC3\xA1" }, - { CZP_MLADY, CZC_COLOR, "R\xC5\xAF\xC5\xBEov\xC3\xA1" }, - { CZP_MLADY, CZC_COLOR, "\xC4\x8C""ern\xC3\xA1" }, - { CZP_PRIVL, CZC_ANY, "Kr\xC3\xA1lova" }, + { CZP_JARNI, CZC_ANY, u8"Horn\u00ed" }, + { CZP_JARNI, CZC_ANY, u8"Horn\u00ed" }, + { CZP_JARNI, CZC_ANY, u8"Doln\u00ed" }, + { CZP_JARNI, CZC_ANY, u8"Doln\u00ed" }, + { CZP_JARNI, CZC_ANY, u8"P\u0159edn\u00ed" }, + { CZP_JARNI, CZC_ANY, u8"Zadn\u00ed" }, + { CZP_JARNI, CZC_ANY, u8"Kosteln\u00ed" }, + { CZP_JARNI, CZC_ANY, u8"Havran\u00ed" }, + { CZP_JARNI, CZC_ANY, u8"\u0158\u00ed\u010dn\u00ed" }, + { CZP_JARNI, CZC_ANY, u8"Jezern\u00ed" }, + { CZP_MLADY, CZC_ANY, u8"Velk\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Velk\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Mal\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Mal\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Vysok\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"\u010cesk\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Moravsk\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Slov\u00e1ck\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Slezsk\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Uhersk\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Star\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Star\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Nov\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Nov\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Mlad\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Kr\u00e1lovsk\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Kamenn\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Cihlov\u00fd" }, + { CZP_MLADY, CZC_ANY, u8"Divn\u00fd" }, + { CZP_MLADY, CZC_COLOR, u8"\u010cerven\u00e1" }, + { CZP_MLADY, CZC_COLOR, u8"\u010cerven\u00e1" }, + { CZP_MLADY, CZC_COLOR, u8"\u010cerven\u00e1" }, + { CZP_MLADY, CZC_COLOR, u8"Zelen\u00e1" }, + { CZP_MLADY, CZC_COLOR, u8"\u017dlut\u00e1" }, + { CZP_MLADY, CZC_COLOR, u8"Siv\u00e1" }, + { CZP_MLADY, CZC_COLOR, u8"\u0160ed\u00e1" }, + { CZP_MLADY, CZC_COLOR, u8"B\u00edl\u00e1" }, + { CZP_MLADY, CZC_COLOR, u8"B\u00edl\u00e1" }, + { CZP_MLADY, CZC_COLOR, u8"Modr\u00e1" }, + { CZP_MLADY, CZC_COLOR, u8"R\u016f\u017eov\u00e1" }, + { CZP_MLADY, CZC_COLOR, u8"\u010cern\u00e1" }, + { CZP_PRIVL, CZC_ANY, u8"Kr\u00e1lova" }, { CZP_PRIVL, CZC_ANY, "Janova" }, { CZP_PRIVL, CZC_ANY, "Karlova" }, - { CZP_PRIVL, CZC_ANY, "Kry\xC5\xA1tofova" }, - { CZP_PRIVL, CZC_ANY, "Ji\xC5\x99\xC3\xADkova" }, + { CZP_PRIVL, CZC_ANY, u8"Kry\u0161tofova" }, + { CZP_PRIVL, CZC_ANY, u8"Ji\u0159\u00edkova" }, { CZP_PRIVL, CZC_ANY, "Petrova" }, { CZP_PRIVL, CZC_ANY, "Sudovo" }, }; @@ -1823,17 +1823,17 @@ static const CzechNameSubst _name_czech_subst_full[] = { { CZG_SMASC, CZA_ALL, CZC_COLOR, "Sedlec" }, { CZG_SMASC, CZA_ALL, CZC_COLOR, "Brod" }, { CZG_SMASC, CZA_ALL, CZC_COLOR, "Brod" }, - { CZG_SMASC, CZA_ALL, CZC_NONE, "\xC3\x9Aval" }, - { CZG_SMASC, CZA_ALL, CZC_COLOR, "\xC5\xBD\xC4\x8F\xC3\xA1r" }, + { CZG_SMASC, CZA_ALL, CZC_NONE, u8"\u00daval" }, + { CZG_SMASC, CZA_ALL, CZC_COLOR, u8"\u017d\u010f\u00e1r" }, { CZG_SMASC, CZA_ALL, CZC_COLOR, "Smrk" }, { CZG_SFEM, CZA_ALL, CZC_COLOR, "Hora" }, { CZG_SFEM, CZA_ALL, CZC_COLOR, "Lhota" }, { CZG_SFEM, CZA_ALL, CZC_COLOR, "Lhota" }, { CZG_SFEM, CZA_ALL, CZC_COLOR, "Hlava" }, - { CZG_SFEM, CZA_ALL, CZC_COLOR, "L\xC3\xADpa" }, + { CZG_SFEM, CZA_ALL, CZC_COLOR, u8"L\u00edpa" }, { CZG_SNEUT, CZA_ALL, CZC_COLOR, "Pole" }, - { CZG_SNEUT, CZA_ALL, CZC_COLOR, "\xC3\x9A""dol\xC3\xAD" }, - { CZG_PMASC, CZA_ALL, CZC_NONE, "\xC3\x9Avaly" }, + { CZG_SNEUT, CZA_ALL, CZC_COLOR, u8"\u00dadol\u00ed" }, + { CZG_PMASC, CZA_ALL, CZC_NONE, u8"\u00davaly" }, { CZG_PFEM, CZA_ALL, CZC_COLOR, "Luka" }, { CZG_PNEUT, CZA_ALL, CZC_COLOR, "Pole" }, }; @@ -1841,46 +1841,46 @@ static const CzechNameSubst _name_czech_subst_full[] = { /* TODO: More stems needed. --pasky */ static const CzechNameSubst _name_czech_subst_stem[] = { { CZG_SMASC, CZA_MIDDLE, CZC_COLOR, "Kostel" }, - { CZG_SMASC, CZA_MIDDLE, CZC_COLOR, "Kl\xC3\xA1\xC5\xA1ter" }, + { CZG_SMASC, CZA_MIDDLE, CZC_COLOR, u8"Kl\u00e1\u0161ter" }, { CZG_SMASC, CZA_SHORT, CZC_COLOR, "Lhot" }, { CZG_SFEM, CZA_SHORT, CZC_COLOR, "Lhot" }, { CZG_SFEM, CZA_SHORT, CZC_COLOR, "Hur" }, { CZG_FREE, CZA_MIDDLE | CZA_LONG, CZC_NONE, "Sedl" }, { CZG_FREE, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_COLOR, "Hrad" }, { CZG_NFREE, CZA_MIDDLE, CZC_NONE, "Pras" }, - { CZG_NFREE, CZA_MIDDLE, CZC_NONE, "Ba\xC5\xBE" }, + { CZG_NFREE, CZA_MIDDLE, CZC_NONE, u8"Ba\u017e" }, { CZG_NFREE, CZA_MIDDLE, CZC_NONE, "Tes" }, - { CZG_NFREE, CZA_MIDDLE, CZC_NONE, "U\xC5\xBE" }, - { CZG_NFREE, CZA_MIDDLE | CZA_LONG, CZC_POSTFIX, "B\xC5\x99" }, + { CZG_NFREE, CZA_MIDDLE, CZC_NONE, u8"U\u017e" }, + { CZG_NFREE, CZA_MIDDLE | CZA_LONG, CZC_POSTFIX, u8"B\u0159" }, { CZG_NFREE, CZA_MIDDLE | CZA_LONG, CZC_NONE, "Vod" }, { CZG_NFREE, CZA_MIDDLE | CZA_LONG, CZC_NONE, "Jan" }, { CZG_NFREE, CZA_LONG, CZC_NONE, "Prach" }, { CZG_NFREE, CZA_LONG, CZC_NONE, "Kunr" }, { CZG_NFREE, CZA_LONG, CZC_NONE, "Strak" }, - { CZG_NFREE, CZA_LONG, CZC_NONE, "V\xC3\xADt" }, - { CZG_NFREE, CZA_LONG, CZC_NONE, "Vy\xC5\xA1" }, - { CZG_NFREE, CZA_LONG, CZC_NONE, "\xC5\xBD""at" }, - { CZG_NFREE, CZA_LONG, CZC_NONE, "\xC5\xBD""er" }, - { CZG_NFREE, CZA_LONG, CZC_NONE, "St\xC5\x99""ed" }, + { CZG_NFREE, CZA_LONG, CZC_NONE, u8"V\u00edt" }, + { CZG_NFREE, CZA_LONG, CZC_NONE, u8"Vy\u0161" }, + { CZG_NFREE, CZA_LONG, CZC_NONE, u8"\u017dat" }, + { CZG_NFREE, CZA_LONG, CZC_NONE, u8"\u017der" }, + { CZG_NFREE, CZA_LONG, CZC_NONE, u8"St\u0159ed" }, { CZG_NFREE, CZA_LONG, CZC_NONE, "Harv" }, { CZG_NFREE, CZA_LONG, CZC_NONE, "Pruh" }, { CZG_NFREE, CZA_LONG, CZC_NONE, "Tach" }, - { CZG_NFREE, CZA_LONG, CZC_NONE, "P\xC3\xADsn" }, + { CZG_NFREE, CZA_LONG, CZC_NONE, u8"P\u00edsn" }, { CZG_NFREE, CZA_LONG, CZC_NONE, "Jin" }, { CZG_NFREE, CZA_LONG, CZC_NONE, "Jes" }, { CZG_NFREE, CZA_LONG, CZC_NONE, "Jar" }, { CZG_NFREE, CZA_LONG, CZC_NONE, "Sok" }, { CZG_NFREE, CZA_LONG, CZC_NONE, "Hod" }, { CZG_NFREE, CZA_LONG, CZC_NONE, "Net" }, - { CZG_FREE, CZA_LONG, CZC_NONE, "Pra\xC5\xBE" }, + { CZG_FREE, CZA_LONG, CZC_NONE, u8"Pra\u017e" }, { CZG_FREE, CZA_LONG, CZC_NONE, "Nerat" }, { CZG_FREE, CZA_LONG, CZC_NONE, "Kral" }, { CZG_FREE, CZA_LONG, CZC_NONE, "Hut" }, { CZG_FREE, CZA_LONG, CZC_NOPOSTFIX, "Pan" }, - { CZG_FREE, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_NOPOSTFIX, "Odst\xC5\x99""ed" }, + { CZG_FREE, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_NOPOSTFIX, u8"Odst\u0159ed" }, { CZG_FREE, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_COLOR, "Mrat" }, { CZG_FREE, CZA_LONG, CZC_COLOR, "Hlav" }, - { CZG_FREE, CZA_SHORT | CZA_MIDDLE, CZC_NONE, "M\xC4\x9B\xC5\x99" }, + { CZG_FREE, CZA_SHORT | CZA_MIDDLE, CZC_NONE, u8"M\u011b\u0159" }, { CZG_FREE, CZA_MIDDLE | CZA_LONG, CZC_NONE, "Lip" }, }; @@ -1894,47 +1894,47 @@ static const char * const _name_czech_subst_postfix[] = { /* This array must have the both neutral genders at the end! */ static const CzechNameSubst _name_czech_subst_ending[] = { { CZG_SMASC, CZA_SHORT | CZA_MIDDLE, CZC_ANY, "ec" }, - { CZG_SMASC, CZA_SHORT | CZA_MIDDLE, CZC_ANY, "\xC3\xADn" }, + { CZG_SMASC, CZA_SHORT | CZA_MIDDLE, CZC_ANY, u8"\u00edn" }, { CZG_SMASC, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_ANY, "ov" }, { CZG_SMASC, CZA_SHORT | CZA_LONG, CZC_ANY, "kov" }, - { CZG_SMASC, CZA_LONG, CZC_POSTFIX, "\xC3\xADn" }, - { CZG_SMASC, CZA_LONG, CZC_POSTFIX, "n\xC3\xADk" }, + { CZG_SMASC, CZA_LONG, CZC_POSTFIX, u8"\u00edn" }, + { CZG_SMASC, CZA_LONG, CZC_POSTFIX, u8"n\u00edk" }, { CZG_SMASC, CZA_LONG, CZC_ANY, "burk" }, { CZG_SFEM, CZA_SHORT, CZC_ANY, "ka" }, { CZG_SFEM, CZA_MIDDLE, CZC_ANY, "inka" }, - { CZG_SFEM, CZA_MIDDLE, CZC_ANY, "n\xC3\xA1" }, + { CZG_SFEM, CZA_MIDDLE, CZC_ANY, u8"n\u00e1" }, { CZG_SFEM, CZA_LONG, CZC_ANY, "ava" }, - { CZG_PMASC, CZA_LONG, CZC_POSTFIX, "\xC3\xADky" }, + { CZG_PMASC, CZA_LONG, CZC_POSTFIX, u8"\u00edky" }, { CZG_PMASC, CZA_LONG, CZC_ANY, "upy" }, { CZG_PMASC, CZA_LONG, CZC_ANY, "olupy" }, { CZG_PFEM, CZA_LONG, CZC_ANY, "avy" }, { CZG_PFEM, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_ANY, "ice" }, - { CZG_PFEM, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_ANY, "i\xC4\x8Dky" }, + { CZG_PFEM, CZA_SHORT | CZA_MIDDLE | CZA_LONG, CZC_ANY, u8"i\u010dky" }, { CZG_PNEUT, CZA_SHORT | CZA_MIDDLE, CZC_ANY, "na" }, { CZG_SNEUT, CZA_SHORT | CZA_MIDDLE, CZC_ANY, "no" }, - { CZG_SNEUT, CZA_LONG, CZC_ANY, "i\xC5\xA1t\xC4\x9B" }, + { CZG_SNEUT, CZA_LONG, CZC_ANY, u8"i\u0161t\u011b" }, }; static const char * const _name_czech_suffix[] = { "nad Cidlinou", - "nad Dyj\xC3\xAD", + u8"nad Dyj\u00ed", "nad Jihlavou", "nad Labem", "nad Lesy", "nad Moravou", "nad Nisou", "nad Odrou", - "nad Ostravic\xC3\xAD", - "nad S\xC3\xA1zavou", + u8"nad Ostravic\u00ed", + u8"nad S\u00e1zavou", "nad Vltavou", - "pod Prad\xC4\x9B""dem", - "pod Radho\xC5\xA1t\xC4\x9Bm", - "pod \xC5\x98\xC3\xADpem", - "pod Sn\xC4\x9B\xC5\xBEkou", - "pod \xC5\xA0pi\xC4\x8D\xC3\xA1kem", + u8"pod Prad\u011bdem", + u8"pod Radho\u0161t\u011bm", + u8"pod \u0158\u00edpem", + u8"pod Sn\u011b\u017ekou", + u8"pod \u0160pi\u010d\u00e1kem", "pod Sedlem", - "v \xC4\x8C""ech\xC3\xA1""ch", - "na Morav\xC4\x9B", + u8"v \u010cech\u00e1ch", + u8"na Morav\u011b", }; @@ -1944,197 +1944,197 @@ static const char * const _name_romanian_real[] = { "Alba Iulia", "Alexandria", "Babadag", - "Bac\xC4\x83u", + u8"Bac\u0103u", "Baia Mare", - "B\xC4\x83ile Herculane", - "B\xC4\x83ilesti", - "B\xC3\xA2rlad", + u8"B\u0103ile Herculane", + u8"B\u0103ilesti", + u8"B\u00e2rlad", "Bicaz", - "Bistri\xC8\x9B""a", + u8"Bistri\u021ba", "Blaj", "Borsec", - "Boto\xC8\x99""ani", - "Br\xC4\x83ila", - "Bra\xC8\x9Bov", - "Bucure\xC8\x99ti", + u8"Boto\u0219ani", + u8"Br\u0103ila", + u8"Bra\u021bov", + u8"Bucure\u0219ti", "Buftea", - "Buz\xC4\x83u", - "C\xC4\x83l\xC4\x83rasi", - "Caransebe\xC8\x99", - "Cernavod\xC4\x83", + u8"Buz\u0103u", + u8"C\u0103l\u0103rasi", + u8"Caransebe\u0219", + u8"Cernavod\u0103", "Cluj-Napoca", - "Constan\xC8\x9B""a", + u8"Constan\u021ba", "Covasna", "Craiova", "Dej", "Deva", "Dorohoi", "Drobeta-Turnu Severin", - "Dr\xC4\x83g\xC4\x83sani", - "F\xC4\x83g\xC4\x83ras", - "F\xC4\x83lticeni", - "Fete\xC8\x99ti", - "Foc\xC8\x99""ani", - "Gala\xC8\x99i", + u8"Dr\u0103g\u0103sani", + u8"F\u0103g\u0103ras", + u8"F\u0103lticeni", + u8"Fete\u0219ti", + u8"Foc\u0219ani", + u8"Gala\u0219i", "Gheorgheni", "Giurgiu", - "H\xC3\xA2r\xC8\x99ova", + u8"H\u00e2r\u0219ova", "Hunedoara", - "Hu\xC8\x99i", - "Ia\xC8\x99i", + u8"Hu\u0219i", + u8"Ia\u0219i", "Isaccea", "Lugoj", - "M\xC4\x83""cin", + u8"M\u0103cin", "Mangalia", "Medgidia", - "Media\xC8\x99", + u8"Media\u0219", "Miercurea Ciuc", "Mizil", "Motru", - "N\xC4\x83s\xC4\x83ud", - "N\xC4\x83vodari", - "Odobe\xC8\x99ti", - "Olteni\xC8\x9B""a", - "One\xC8\x99ti", + u8"N\u0103s\u0103ud", + u8"N\u0103vodari", + u8"Odobe\u0219ti", + u8"Olteni\u021ba", + u8"One\u0219ti", "Oradea", - "Or\xC8\x99ova", - "Petro\xC8\x99""ani", - "Piatra Neam\xC8\x9B", - "Pite\xC8\x99ti", - "Ploie\xC8\x99ti", + u8"Or\u0219ova", + u8"Petro\u0219ani", + u8"Piatra Neam\u021b", + u8"Pite\u0219ti", + u8"Ploie\u0219ti", "Predeal", - "R\xC3\xA2mnicu V\xC3\xA2lcea", + u8"R\u00e2mnicu V\u00e2lcea", "Reghin", - "Re\xC8\x99i\xC8\x9B""a", + u8"Re\u0219i\u021ba", "Roman", - "Ro\xC8\x99iorii de Vede", + u8"Ro\u0219iorii de Vede", "Satu Mare", - "Sebe\xC8\x99", - "Sf\xC3\xA2ntu Gheorghe", + u8"Sebe\u0219", + u8"Sf\u00e2ntu Gheorghe", "Sibiu", - "Sighi\xC8\x99oara", + u8"Sighi\u0219oara", "Sinaia", "Slatina", "Slobozia", "Sovata", "Suceava", "Sulina", - "T\xC4\x83nd\xC4\x83rei", - "T\xC3\xA2rgoviste", - "T\xC3\xA2rgu Jiu", - "T\xC3\xA2rgu Mures", + u8"T\u0103nd\u0103rei", + u8"T\u00e2rgoviste", + u8"T\u00e2rgu Jiu", + u8"T\u00e2rgu Mures", "Tecuci", - "Timi\xC8\x99oara", + u8"Timi\u0219oara", "Tulcea", "Turda", - "Turnu M\xC4\x83gurele", + u8"Turnu M\u0103gurele", "Urziceni", "Vaslui", "Vatra Dornei", "Victoria", "Videle", - "Zal\xC4\x83u", + u8"Zal\u0103u", }; static const char * const _name_slovak_real[] = { "Bratislava", - "B\xC3\xA1novce nad Bebravou", - "Bansk\xC3\xA1 Bystrica", - "Bansk\xC3\xA1 \xC5\xA0tiavnica", + u8"B\u00e1novce nad Bebravou", + u8"Bansk\u00e1 Bystrica", + u8"Bansk\u00e1 \u0160tiavnica", "Bardejov", "Brezno", "Brezova pod Bradlom", - "Byt\xC4\x8D""a", - "\xC4\x8C""adca", - "\xC4\x8Cierna nad Tisou", + u8"Byt\u010da", + u8"\u010cadca", + u8"\u010cierna nad Tisou", "Detva", - "Pre\xC5\xA1ov", + u8"Pre\u0161ov", "Dolny Kubin", - "Spi\xC5\xA1sk\xC3\xA1 Nov\xC3\xA1 Ves", - "Dunajsk\xC3\xA1 Streda", - "Gab\xC4\x8D\xC3\xADikovo", + u8"Spi\u0161sk\u00e1 Nov\u00e1 Ves", + u8"Dunajsk\u00e1 Streda", + u8"Gab\u010d\u00edikovo", "Galanta", "Gbely", "Gelnica", - "Handlov\xC3\xA1", + u8"Handlov\u00e1", "Hlohovec", - "Hol\xC3\xAD\xC4\x8D", - "Humenn\xC3\xA9", + u8"Hol\u00ed\u010d", + u8"Humenn\u00e9", "Hurbanovo", "Kezmarok", - "Kom\xC3\xA1rno", - "Ko\xC5\xA1ice", + u8"Kom\u00e1rno", + u8"Ko\u0161ice", "Kremnica", "Krompachy", "Kuty", "Leopoldov", - "Levo\xC4\x8D""a", - "Liptovsk\xC3\xBD Mikul\xC3\xA1\xC5\xA1", - "Lu\xC4\x8D""enec", + u8"Levo\u010da", + u8"Liptovsk\u00fd Mikul\u00e1\u0161", + u8"Lu\u010denec", "Malacky", "Martin", "Medzilaborce", "Michalovce", "Modra", "Myjava", - "N\xC3\xA1mestovo", + u8"N\u00e1mestovo", "Nitra", - "Nov\xC3\xA1 Ba\xC5\x88""a", - "Nov\xC3\xA9"" Mesto nad V\xC3\xA1hom", - "Nov\xC3\xA9"" Z\xC3\xA1""mky", - "Partiz\xC3\xA1nske", + u8"Nov\u00e1 Ba\u0148a", + u8"Nov\u00e9 Mesto nad V\u00e1hom", + u8"Nov\u00e9 Z\u00e1mky", + u8"Partiz\u00e1nske", "Pezinok", - "Pie\xC5\xA1\xC5\xA5""any", - "Polt\xC3\xA1r", + u8"Pie\u0161\u0165any", + u8"Polt\u00e1r", "Poprad", - "Pova\xC5\xBEsk\xC3\xA1 Bystrica", + u8"Pova\u017esk\u00e1 Bystrica", "Prievidza", - "P\xC3\xBA""chov", - "Rev\xC3\xBA""ca", - "Rimavsk\xC3\xA1 Sobota", - "Ro\xC5\xBE\xC5\x88""ava", - "Ru\xC5\xBEomberok", + u8"P\u00fachov", + u8"Rev\u00faca", + u8"Rimavsk\u00e1 Sobota", + u8"Ro\u017e\u0148ava", + u8"Ru\u017eomberok", "Sabinov", - "\xC5\xA0""a\xC4\xBE""a", + u8"\u0160a\u013ea", "Senec", "Senica", - "Sere\xC4\x8F", + u8"Sere\u010f", "Skalica", - "Sl\xC3\xA1""dkovi\xC3\x8Dovo", + u8"Sl\u00e1dkovi\u00cdovo", "Smolenice", "Snina", - "Star\xC3\xA1 \xC4\xBDubov\xC5\x88""a", - "Star\xC3\xA1 Tur\xC3\xA1", - "Str\xC3\xA1\xC5\xBEske", + u8"Star\u00e1 \u013dubov\u0148a", + u8"Star\u00e1 Tur\u00e1", + u8"Str\u00e1\u017eske", "Stropkov", "Stupava", - "\xC5\xA0t\xC3\xBArovo", - "\xC4\xA0ulekovo", - "Topo\xC4\xBE\xC4\x8D""any", - "Trebi\xC5\xA1ov", - "Tren\xC4\x8D\xC3\xADn", + u8"\u0160t\u00farovo", + u8"\u0120ulekovo", + u8"Topo\u013e\u010dany", + u8"Trebi\u0161ov", + u8"Tren\u010d\u00edn", "Trnava", - "Tur\xC4\x8Dianske Teplice", - "Tvrdo\xC5\xA1\xC3\xADn", - "Vr\xC3\xA1""ble", - "Vranov nad Top\xC4\xBEou", - "Z\xC3\xA1horsk\xC3\xA1 Bystrica", - "\xC5\xBD""diar", - "\xC4\xBDiar nad Hronom", - "\xC5\xBDilina", - "Zlat\xC3\xA9 Moravce", + u8"Tur\u010dianske Teplice", + u8"Tvrdo\u0161\u00edn", + u8"Vr\u00e1ble", + u8"Vranov nad Top\u013eou", + u8"Z\u00e1horsk\u00e1 Bystrica", + u8"\u017ddiar", + u8"\u013diar nad Hronom", + u8"\u017dilina", + u8"Zlat\u00e9 Moravce", "Zvolen", }; static const char * const _name_norwegian_1[] = { "Arna", "Aust", - "Bj\xC3\xB8rk", - "Bj\xC3\xB8rn", + u8"Bj\u00f8rk", + u8"Bj\u00f8rn", "Brand", - "B\xC3\xB8ver", + u8"B\u00f8ver", "Drag", - "Dr\xC3\xB8", + u8"Dr\u00f8", "Eids", "Egge", "Fager", @@ -2147,12 +2147,12 @@ static const char * const _name_norwegian_1[] = { "Gaus", "Galte", "Geir", - "Gl\xC3\xB8s", + u8"Gl\u00f8s", "Gran", "Grind", "Grims", - "Gr\xC3\xB8n", - "Gr\xC3\xB8t", + u8"Gr\u00f8n", + u8"Gr\u00f8t", "Gulle", "Haka", "Hammer", @@ -2167,7 +2167,7 @@ static const char * const _name_norwegian_1[] = { "Kjerring", "Knatte", "Krok", - "K\xC3\xB8y", + u8"K\u00f8y", "Lang", "Lauv", "Leir", @@ -2175,7 +2175,7 @@ static const char * const _name_norwegian_1[] = { "Logn", "Lo", "Lyng", - "L\xC3\xB8n", + u8"L\u00f8n", "Mesna", "Mel", "Mo", @@ -2195,9 +2195,9 @@ static const char * const _name_norwegian_1[] = { "Sel", "Sol", "Sjur", - "Sk\xC3\xA5r", - "Sl\xC3\xA5tt", - "Stj\xC3\xB8r", + u8"Sk\u00e5r", + u8"Sl\u00e5tt", + u8"Stj\u00f8r", "Stor", "Svart", "Svens", @@ -2210,7 +2210,7 @@ static const char * const _name_norwegian_1[] = { "Vest", "Vesle", "Vik", - "V\xC3\xA5g", + u8"V\u00e5g", }; static const char * const _name_norwegian_2[] = { @@ -2225,7 +2225,7 @@ static const char * const _name_norwegian_2[] = { "bugen", "by", "bygd", - "b\xC3\xB8", + u8"b\u00f8", "dal", "egga", "eid", @@ -2243,10 +2243,10 @@ static const char * const _name_norwegian_2[] = { "heim", "hella", "hovda", - "h\xC3\xB8""a", - "h\xC3\xB8gda", + u8"h\u00f8a", + u8"h\u00f8gda", "kampen", - "kj\xC3\xB8len", + u8"kj\u00f8len", "kollen", "kroken", "land", @@ -2261,7 +2261,7 @@ static const char * const _name_norwegian_2[] = { "rud", "sand", "set", - "sj\xC3\xB8""en", + u8"sj\u00f8en", "skogen", "slette", "snipa", @@ -2270,7 +2270,7 @@ static const char * const _name_norwegian_2[] = { "stulen", "sund", "svingen", - "s\xC3\xA6tra", + u8"s\u00e6tra", "tinden", "tun", "vang", @@ -2278,9 +2278,9 @@ static const char * const _name_norwegian_2[] = { "veid", "vik", "voll", - "v\xC3\xA5g", + u8"v\u00e5g", "um", - "\xC3\xA5sen", + u8"\u00e5sen", }; static const char * const _name_norwegian_real[] = { @@ -2288,12 +2288,12 @@ static const char * const _name_norwegian_real[] = { "Arendal", "Askim", "Bergen", - "Bod\xC3\xB8", + u8"Bod\u00f8", "Brevik", "Bryne", - "Br\xC3\xB8nn\xC3\xB8ysund", + u8"Br\u00f8nn\u00f8ysund", "Drammen", - "Dr\xC3\xB8""bak", + u8"Dr\u00f8bak", "Egersund", "Elverum", "Farsund", @@ -2301,10 +2301,10 @@ static const char * const _name_norwegian_real[] = { "Finnsnes", "Flekkefjord", "Flora", - "Fosnav\xC3\xA5g", + u8"Fosnav\u00e5g", "Fredrikstad", - "F\xC3\xB8rde", - "Gj\xC3\xB8vik", + u8"F\u00f8rde", + u8"Gj\u00f8vik", "Grimstad", "Halden", "Hamar", @@ -2313,13 +2313,13 @@ static const char * const _name_norwegian_real[] = { "Haugesund", "Holmestrand", "Horten", - "J\xC3\xB8rpeland", + u8"J\u00f8rpeland", "Kirkenes", "Kolvereid", "Kongsberg", "Kongsvinger", "Kopervik", - "Krager\xC3\xB8", + u8"Krager\u00f8", "Kristiansand", "Kristiansund", "Langesund", @@ -2329,16 +2329,16 @@ static const char * const _name_norwegian_real[] = { "Levanger", "Lillehammer", "Lillesand", - "Lillestr\xC3\xB8m", + u8"Lillestr\u00f8m", "Lyngdal", - "L\xC3\xB8renskog", + u8"L\u00f8renskog", "Mandal", "Mo i Rana", "Molde", - "Mosj\xC3\xB8""en", + u8"Mosj\u00f8en", "Moss", "Mysen", - "M\xC3\xA5l\xC3\xB8y", + u8"M\u00e5l\u00f8y", "Namsos", "Narvik", "Notodden", @@ -2347,11 +2347,11 @@ static const char * const _name_norwegian_real[] = { "Otta", "Porsgrunn", "Ringerike", - "Ris\xC3\xB8r", + u8"Ris\u00f8r", "Rjukan", "Sandefjord", "Sandnes", - "Sandnessj\xC3\xB8""en", + u8"Sandnessj\u00f8en", "Sandvika", "Sarpsborg", "Sauda", @@ -2362,152 +2362,152 @@ static const char * const _name_norwegian_real[] = { "Stathelle", "Stavanger", "Steinkjer", - "Stj\xC3\xB8rdal", + u8"Stj\u00f8rdal", "Stokmarknes", "Stord", "Svelvik", - "Svolv\xC3\xA6r", - "Troms\xC3\xB8", + u8"Svolv\u00e6r", + u8"Troms\u00f8", "Trondheim", "Tvedestrand", - "T\xC3\xB8nsberg", + u8"T\u00f8nsberg", "Ulsteinvik", - "Vads\xC3\xB8", - "Vard\xC3\xB8", - "Verdals\xC3\xB8ra", - "\xC3\x85krehamn", - "\xC3\x85lesund", - "\xC3\x85ndalsnes", + u8"Vads\u00f8", + u8"Vard\u00f8", + u8"Verdals\u00f8ra", + u8"\u00c5krehamn", + u8"\u00c5lesund", + u8"\u00c5ndalsnes", }; static const char * const _name_hungarian_1[] = { "Nagy-", "Kis-", - "Fels\xC5\x91-", - "Als\xC3\xB3-", - "\xC3\x9Aj-", + u8"Fels\u0151-", + u8"Als\u00f3-", + u8"\u00daj-", }; static const char * const _name_hungarian_2[] = { "Bodrog", - "Dr\xC3\xA1va", + u8"Dr\u00e1va", "Duna", - "Hej\xC5\x91", - "Hern\xC3\xA1""d", - "R\xC3\xA1""ba", - "Saj\xC3\xB3", + u8"Hej\u0151", + u8"Hern\u00e1d", + u8"R\u00e1ba", + u8"Saj\u00f3", "Szamos", "Tisza", "Zala", "Balaton", - "Fert\xC5\x91", + u8"Fert\u0151", "Bakony", - "Cserh\xC3\xA1t", + u8"Cserh\u00e1t", "Bihar", - "Hajd\xC3\xBA", - "J\xC3\xA1sz", + u8"Hajd\u00fa", + u8"J\u00e1sz", "Kun", "Magyar", - "N\xC3\xB3gr\xC3\xA1""d", - "Ny\xC3\xADr", + u8"N\u00f3gr\u00e1d", + u8"Ny\u00edr", "Somogy", - "Sz\xC3\xA9kely", + u8"Sz\u00e9kely", "Buda", - "Gy\xC5\x91r", + u8"Gy\u0151r", "Pest", - "Feh\xC3\xA9r", - "Cser\xC3\xA9p", - "Erd\xC5\x91", + u8"Feh\u00e9r", + u8"Cser\u00e9p", + u8"Erd\u0151", "Hegy", "Homok", - "Mez\xC5\x91", + u8"Mez\u0151", "Puszta", - "S\xC3\xA1r", - "Cs\xC3\xA1sz\xC3\xA1r", + u8"S\u00e1r", + u8"Cs\u00e1sz\u00e1r", "Herceg", - "Kir\xC3\xA1ly", + u8"Kir\u00e1ly", "Nemes", - "P\xC3\xBCsp\xC3\xB6k", + u8"P\u00fcsp\u00f6k", "Szent", - "Alm\xC3\xA1s", - "Szilv\xC3\xA1s", + u8"Alm\u00e1s", + u8"Szilv\u00e1s", "Agg", "Aranyos", - "B\xC3\xA9k\xC3\xA9s", - "Egyh\xC3\xA1zas", + u8"B\u00e9k\u00e9s", + u8"Egyh\u00e1zas", "Gagy", "Heves", "Kapos", - "T\xC3\xA1pi\xC3\xB3", + u8"T\u00e1pi\u00f3", "Torna", "Vas", - "V\xC3\xA1mos", - "V\xC3\xA1s\xC3\xA1ros", + u8"V\u00e1mos", + u8"V\u00e1s\u00e1ros", }; static const char * const _name_hungarian_3[] = { - "ap\xC3\xA1ti", - "b\xC3\xA1""ba", + u8"ap\u00e1ti", + u8"b\u00e1ba", "bikk", "dob", "fa", - "f\xC3\xB6ld", + u8"f\u00f6ld", "hegyes", "kak", "kereszt", - "k\xC3\xBCrt", - "lad\xC3\xA1ny", - "m\xC3\xA9rges", + u8"k\u00fcrt", + u8"lad\u00e1ny", + u8"m\u00e9rges", "szalonta", "telek", "vas", - "v\xC3\xB6lgy", + u8"v\u00f6lgy", }; static const char * const _name_hungarian_4[] = { "alja", - "egyh\xC3\xA1za", - "h\xC3\xA1za", - "\xC3\xBAr", - "v\xC3\xA1r", + u8"egyh\u00e1za", + u8"h\u00e1za", + u8"\u00far", + u8"v\u00e1r", }; static const char * const _name_hungarian_real[] = { "Ajka", - "Asz\xC3\xB3""d", + u8"Asz\u00f3d", "Badacsony", "Baja", "Budapest", "Debrecen", "Eger", - "Fony\xC3\xB3""d", - "G\xC3\xB6""d\xC3\xB6ll\xC5\x91", - "Gy\xC5\x91r", + u8"Fony\u00f3d", + u8"G\u00f6d\u00f6ll\u0151", + u8"Gy\u0151r", "Gyula", "Karcag", - "Kecskem\xC3\xA9t", + u8"Kecskem\u00e9t", "Keszthely", - "Kisk\xC3\xB6re", + u8"Kisk\u00f6re", "Kocsord", - "Kom\xC3\xA1rom", - "K\xC5\x91szeg", - "Mak\xC3\xB3", - "Moh\xC3\xA1""cs", + u8"Kom\u00e1rom", + u8"K\u0151szeg", + u8"Mak\u00f3", + u8"Moh\u00e1cs", "Miskolc", - "\xC3\x93zd", + u8"\u00d3zd", "Paks", - "P\xC3\xA1pa", - "P\xC3\xA9""cs", - "Polg\xC3\xA1r", + u8"P\u00e1pa", + u8"P\u00e9cs", + u8"Polg\u00e1r", "Sarkad", - "Si\xC3\xB3""fok", + u8"Si\u00f3fok", "Szeged", "Szentes", "Szolnok", "Tihany", "Tokaj", - "V\xC3\xA1""c", - "Z\xC3\xA1hony", + u8"V\u00e1c", + u8"Z\u00e1hony", "Zirc", }; @@ -2518,7 +2518,7 @@ static const char * const _name_swiss_real[] = { "Arosa", "Appenzell", "Arbon", - "Altst\xC3\xA4tten", + u8"Altst\u00e4tten", "Baar", "Baden", "Bellinzona", @@ -2529,20 +2529,20 @@ static const char * const _name_swiss_real[] = { "Burgdorf", "Bern", "Basel", - "B\xC3\xBClach", + u8"B\u00fclach", "Carouge", "Cham", "Chiasso", "Chur", "Davos", - "Del\xC3\xA9mont", + u8"Del\u00e9mont", "Dietikon", - "D\xC3\xBC""bendorf", + u8"D\u00fcbendorf", "Emmen", - "Freienbach-Pf\xC3\xA4""ffikon", + u8"Freienbach-Pf\u00e4ffikon", "Fribourg", "Frauenfeld", - "Gen\xC3\xA8ve", + u8"Gen\u00e8ve", "Glarus", "Gossau", "Grenchen", @@ -2554,9 +2554,9 @@ static const char * const _name_swiss_real[] = { "Jona", "Kriens", "Kloten", - "K\xC3\xB6niz", + u8"K\u00f6niz", "Kreuzlingen", - "K\xC3\xBCsnacht", + u8"K\u00fcsnacht", "Agen", "Lancy", "La Chaux-de-Fonds", @@ -2573,7 +2573,7 @@ static const char * const _name_swiss_real[] = { "Lyss", "Luzern", "Martigny", - "M\xC3\xBCnchenstein", + u8"M\u00fcnchenstein", "Meyrin", "Montreux", "Monthey", @@ -2581,7 +2581,7 @@ static const char * const _name_swiss_real[] = { "Murten", "Moutier", "Muttenz", - "Neuch\xC3\xA2tel", + u8"Neuch\u00e2tel", "Neuhausen am Rheinfall", "Nyon", "Olten", @@ -2610,11 +2610,11 @@ static const char * const _name_swiss_real[] = { "St. Moritz", "Sion", "Spiez", - "St\xC3\xA4""fa", + u8"St\u00e4fa", "Sursee", "Schwyz", "Thalwil", - "Th\xC3\xB4nex", + u8"Th\u00f4nex", "Thun", "Uster", "Uzwil", @@ -2622,7 +2622,7 @@ static const char * const _name_swiss_real[] = { "Volketswil", "Versoix", "Vevey", - "W\xC3\xA4""denswil", + u8"W\u00e4denswil", "Wettingen", "Wil", "Wallisellen", @@ -2633,7 +2633,7 @@ static const char * const _name_swiss_real[] = { "Yverdon-les-Bains", "Zollikon", "Zofingen", - "Z\xC3\xBCrich", + u8"Z\u00fcrich", "Zug", }; @@ -2643,12 +2643,12 @@ static const char * const _name_danish_1[] = { "Nye ", "Store ", "Kirke ", - "N\xC3\xB8rre ", + u8"N\u00f8rre ", "Vester ", - "S\xC3\xB8nder ", - "\xC3\x98ster ", + u8"S\u00f8nder ", + u8"\u00d8ster ", "Hvide ", - "H\xC3\xB8je ", + u8"H\u00f8je ", "Kongens ", }; @@ -2660,7 +2660,7 @@ static const char * const _name_danish_2[] = { "Bede", "Birke", "Bjerring", - "Bj\xC3\xA6ver", + u8"Bj\u00e6ver", "Blommens", "Blok", "Bolder", @@ -2673,7 +2673,7 @@ static const char * const _name_danish_2[] = { "Fredens", "Frederiks", "Fugle", - "F\xC3\xA5re", + u8"F\u00e5re", "Gille", "Gis", "Givs", @@ -2690,11 +2690,11 @@ static const char * const _name_danish_2[] = { "Hol", "Horn", "Humle", - "H\xC3\xB8j", - "H\xC3\xB8r", + u8"H\u00f8j", + u8"H\u00f8r", "Is", "Jyde", - "J\xC3\xA6gers", + u8"J\u00e6gers", "Karls", "Klov", "Kokke", @@ -2706,24 +2706,24 @@ static const char * const _name_danish_2[] = { "Ny", "Oks", "Ring", - "R\xC3\xB8""de", + u8"R\u00f8de", "Rung", - "R\xC3\xB8r", + u8"R\u00f8r", "Rud", "Saks", "Salt", "Skam", "Silke", "Skod", - "Sk\xC3\xA6l", - "Sk\xC3\xA6r", + u8"Sk\u00e6l", + u8"Sk\u00e6r", "Sol", "Svend", "Svine", "Strand", "Stubbe", "Ting", - "Tj\xC3\xA6re", + u8"Tj\u00e6re", "Tore", "Uger", "Ulf", @@ -2731,9 +2731,9 @@ static const char * const _name_danish_2[] = { "Vand", "Vej", "Vor", - "V\xC3\xA6r", - "\xC3\x98r", - "\xC3\x85l", + u8"V\u00e6r", + u8"\u00d8r", + u8"\u00c5l", }; static const char * const _name_danish_3[] = { @@ -2746,21 +2746,21 @@ static const char * const _name_danish_3[] = { "strup", "holm", "hus", - "k\xC3\xB8""bing", + u8"k\u00f8bing", "lund", "lunde", "sund", "ovre", - "h\xC3\xB8j", + u8"h\u00f8j", "dal", "sted", "sten", - "l\xC3\xB8se", - "r\xC3\xB8""d", + u8"l\u00f8se", + u8"r\u00f8d", "magle", - "s\xC3\xB8", + u8"s\u00f8", "bjerg", - "b\xC3\xA6k", + u8"b\u00e6k", "drup", "lev", "bo", @@ -2770,32 +2770,32 @@ static const char * const _name_danish_3[] = { }; static const char * const _name_turkish_prefix[] = { - "Ak\xC3\xA7""a", - "Alt\xC4\xB1n", - "Bah\xC3\xA7""e", + u8"Ak\u00e7a", + u8"Alt\u0131n", + u8"Bah\u00e7e", "Boz", - "B\xC3\xBCy\xC3\xBCk", - "\xC3\x87""ay", - "Do\xC4\x9Fu", + u8"B\u00fcy\u00fck", + u8"\u00c7ay", + u8"Do\u011fu", "Eski", - "G\xC3\xBCzel", - "K\xC4\xB1z\xC4\xB1l", - "K\xC3\xBC\xC3\xA7\xC3\xBCk", + u8"G\u00fczel", + u8"K\u0131z\u0131l", + u8"K\u00fc\u00e7\u00fck", "Orta", - "Sar\xC4\xB1", + u8"Sar\u0131", "Sultan", "Ulu", "Yeni", }; static const char * const _name_turkish_middle[] = { - "aga\xC3\xA7", + u8"aga\u00e7", "ayva", - "\xC3\xA7""am", + u8"\u00e7am", "elma", "kurt", "pazar", - "yal\xC4\xB1", + u8"yal\u0131", }; static const char * const _name_turkish_suffix[] = { @@ -2804,10 +2804,10 @@ static const char * const _name_turkish_suffix[] = { "kale", "kaya", "kent", - "k\xC3\xB6y", + u8"k\u00f6y", "ova", - "\xC3\xB6z\xC3\xBC", - "\xC3\xB6ren", + u8"\u00f6z\u00fc", + u8"\u00f6ren", "pazar", "saray", "tepe", @@ -2817,48 +2817,48 @@ static const char * const _name_turkish_suffix[] = { static const char * const _name_turkish_real[] = { "Adana", - "Ad\xC4\xB1yaman", + u8"Ad\u0131yaman", "Afyon", - "A\xC4\x9Fr\xC4\xB1", + u8"A\u011fr\u0131", "Amasya", "Antalya", "Artvin", - "Bal\xC4\xB1kesir", + u8"Bal\u0131kesir", "Bilecik", "Bitlis", "Bolu", "Burdur", "Bursa", - "\xC3\x87""anakkale", - "\xC3\x87""ank\xC4\xB1r\xC4\xB1", + u8"\u00c7anakkale", + u8"\u00c7ank\u0131r\u0131", "Denizli", - "Diyarbak\xC4\xB1r", + u8"Diyarbak\u0131r", "Edirne", - "Elaz\xC4\xB1\xC4\x9F", + u8"Elaz\u0131\u011f", "Erzurum", - "Eski\xC5\x9F""ehir", + u8"Eski\u015fehir", "Giresun", - "G\xC3\xBCm\xC3\xBC\xC5\x9Fhane", + u8"G\u00fcm\u00fc\u015fhane", "Hatay", "Isparta", - "\xC4\xB0\xC3\xA7""el", - "\xC4\xB0stanbul", - "\xC4\xB0zmir", + u8"\u0130\u00e7el", + u8"\u0130stanbul", + u8"\u0130zmir", "Kars", "Kastamonu", "Kayseri", "Kirklareli", "Kocaeli", "Konya", - "K\xC3\xBCtahya", + u8"K\u00fctahya", "Malatya", "Manisa", - "Kahramanmara\xC5\x9F", + u8"Kahramanmara\u015f", "Mardin", - "Mu\xC4\x9Fla", - "Mu\xC5\x9F", - "Nev\xC5\x9F""ehir", - "Ni\xC4\x9F""de", + u8"Mu\u011fla", + u8"Mu\u015f", + u8"Nev\u015fehir", + u8"Ni\u011fde", "Rize", "Sakarya", "Samsun", @@ -2866,21 +2866,21 @@ static const char * const _name_turkish_real[] = { "Sinop", "Sivas", "Trabzon", - "\xC5\x9E""anl\xC4\xB1urfa", + u8"\u015eanl\u0131urfa", "Van", "Yozgat", "Zonguldak", "Aksaray", "Bayburt", "Karaman", - "\xC5\x9E\xC4\xB1rnak", - "Bart\xC4\xB1n", + u8"\u015e\u0131rnak", + u8"Bart\u0131n", "Ardahan", - "I\xC4\x9F""d\xC4\xB1r", + u8"I\u011fd\u0131r", "Yalova", - "Karab\xC3\xBCk", + u8"Karab\u00fck", "Osmaniye", - "D\xC3\xBCzce", + u8"D\u00fczce", }; static const char * const _name_italian_real[] = { @@ -3172,7 +3172,7 @@ static const char * const _name_catalan_real[] = { "Banyoles", "Figueres", "Balaguer", - "Vilafranca del Pened\xC3\xA8s", + u8"Vilafranca del Pened\u00e8s", "La Seu d'Urgell", "El Pont de Suert", "Igualada", @@ -3188,21 +3188,21 @@ static const char * const _name_catalan_real[] = { "Ripoll", "Cervera", "Gandesa", - "Matar\xC3\xB3", + u8"Matar\u00f3", "Montblanc", - "Vilanova i la Geltr\xC3\xBA", - "T\xC3\xA0rrega", + u8"Vilanova i la Geltr\u00fa", + u8"T\u00e0rrega", "Camprodon", - "Campdev\xC3\xA0nol", + u8"Campdev\u00e0nol", "Cambrils", "Begur", "Setcases", "Palafrugell", "Begues", "El Bruc", - "Cadaqu\xC3\xA9s", - "Collbat\xC3\xB3", - "Cervell\xC3\xB3", + u8"Cadaqu\u00e9s", + u8"Collbat\u00f3", + u8"Cervell\u00f3", "Esparreguera", "Abrera", "Alp", @@ -3213,7 +3213,7 @@ static const char * const _name_catalan_real[] = { "Molins de Rei", "Monistrol", "Rocallaura", - "Rub\xC3\xAD", + u8"Rub\u00ed", "Ripollet", "Sitges", "Roses", @@ -3243,14 +3243,14 @@ static const char * const _name_catalan_pref[] = { "Sant Joan de ", "Sant Feliu de ", "Sant Quirze de ", - "Sant Sadurn\xC3\xAD de ", + u8"Sant Sadurn\u00ed de ", "Santa Coloma de ", "Santa Margarida de ", "Santa Maria de ", - "Sant Mart\xC3\xAD de ", + u8"Sant Mart\u00ed de ", "Sant Pere de ", - "Sant Juli\xC3\xA0 de ", - "Sant Vicen\xC3\xA7 de ", + u8"Sant Juli\u00e0 de ", + u8"Sant Vicen\u00e7 de ", }; @@ -3279,10 +3279,10 @@ static const char * const _name_catalan_2m[] = { "baix", "fosc", "pelat", - "vent\xC3\xB3s", + u8"vent\u00f3s", "negre", "roig", - "gr\xC3\xADs", + u8"gr\u00eds", }; static const char * const _name_catalan_2f[] = { @@ -3297,14 +3297,14 @@ static const char * const _name_catalan_2f[] = { }; static const char * const _name_catalan_3[] = { - " Desp\xC3\xAD", + u8" Desp\u00ed", " Desvern", - " del Cam\xC3\xAD", + u8" del Cam\u00ed", " de Mar", " de Dalt", " de Baix", - " del Vall\xC3\xA8s", - " de Bergued\xC3\xA0", + u8" del Vall\u00e8s", + u8" de Bergued\u00e0", " de Conflent", " de la Plana", }; @@ -3315,5 +3315,5 @@ static const char * const _name_catalan_river1[] = { " de Llobregat", " d'Ebre", " de Segre", - " de Francol\xC3\xAD", + u8" de Francol\u00ed", }; diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp index e44d9178d9..3519c27508 100644 --- a/src/textfile_gui.cpp +++ b/src/textfile_gui.cpp @@ -359,7 +359,7 @@ static void Xunzip(byte **bufp, size_t *sizep) } /* Check for the byte-order-mark, and skip it if needed. */ - char *p = this->text + (strncmp("\xEF\xBB\xBF", this->text, 3) == 0 ? 3 : 0); + char *p = this->text + (strncmp(u8"\ufeff", this->text, 3) == 0 ? 3 : 0); /* Make sure the string is a valid UTF-8 sequence. */ str_validate(p, this->text + filesize, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE); diff --git a/src/townname.cpp b/src/townname.cpp index 77dfb448b2..e7999f9a53 100644 --- a/src/townname.cpp +++ b/src/townname.cpp @@ -505,7 +505,7 @@ static char *MakeFinnishTownName(char *buf, const char *last, uint32 seed) strstr(orig, "A") != nullptr || strstr(orig, "O") != nullptr || strstr(orig, "U") != nullptr) { buf = strecpy(buf, "la", last); } else { - buf = strecpy(buf, "l\xC3\xA4", last); + buf = strecpy(buf, u8"l\u00e4", last); } return buf; } diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index e22702d798..17149272d8 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -1013,8 +1013,7 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, * Do this for all tiles (like trees), not only objects. */ ClearedObjectArea *coa = FindClearedObject(end_tile); if (coa == nullptr) { - /*C++17: coa = &*/ _cleared_object_areas.push_back({end_tile, TileArea(end_tile, 1, 1)}); - coa = &_cleared_object_areas.back(); + coa = &_cleared_object_areas.emplace_back(ClearedObjectArea{ end_tile, TileArea(end_tile, 1, 1) }); } /* Hide the tile from the terraforming command */ diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 83c59d9a1c..65e16d1aa3 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -31,6 +31,10 @@ #include "../3rdparty/mingw-std-threads/mingw.mutex.h" #include "../3rdparty/mingw-std-threads/mingw.condition_variable.h" #endif +#ifdef __EMSCRIPTEN__ +# include +# include +#endif #if defined(WITH_FCITX) #include @@ -61,6 +65,11 @@ static volatile bool _draw_continue; static Palette _local_palette; static SDL_Palette *_sdl_palette; +#ifdef __EMSCRIPTEN__ +/** Whether we just had a window-enter event. */ +static bool _cursor_new_in_window = false; +#endif + #define MAX_DIRTY_RECTS 100 static SDL_Rect _dirty_rects[MAX_DIRTY_RECTS]; static int _num_dirty_rects; @@ -578,6 +587,9 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) bool VideoDriver_SDL::ClaimMousePointer() { SDL_ShowCursor(0); +#ifdef __EMSCRIPTEN__ + SDL_SetRelativeMouseMode(SDL_TRUE); +#endif return true; } @@ -796,9 +808,27 @@ int VideoDriver_SDL::PollEvent() switch (ev.type) { case SDL_MOUSEMOTION: +#ifdef __EMSCRIPTEN__ + if (_cursor_new_in_window) { + /* The cursor just moved into the window; this means we don't + * know the absolutely position yet to move relative from. + * Before this time, SDL didn't know it either, and this is + * why we postpone it till now. Update the absolute position + * for this once, and work relative after. */ + _cursor.pos.x = ev.motion.x; + _cursor.pos.y = ev.motion.y; + _cursor.dirty = true; + + _cursor_new_in_window = false; + SDL_SetRelativeMouseMode(SDL_TRUE); + } else { + _cursor.UpdateCursorPositionRelative(ev.motion.xrel, ev.motion.yrel); + } +#else if (_cursor.UpdateCursorPosition(ev.motion.x, ev.motion.y, true)) { SDL_WarpMouseInWindow(_sdl_window, _cursor.pos.x, _cursor.pos.y); } +#endif HandleMouseEvents(); break; @@ -932,6 +962,12 @@ int VideoDriver_SDL::PollEvent() } else if (ev.window.event == SDL_WINDOWEVENT_ENTER) { // mouse entered the window, enable cursor _cursor.in_window = true; +#ifdef __EMSCRIPTEN__ + /* Disable relative mouse mode for the first mouse motion, + * so we can pick up the absolutely position again. */ + _cursor_new_in_window = true; + SDL_SetRelativeMouseMode(SDL_FALSE); +#endif } else if (ev.window.event == SDL_WINDOWEVENT_LEAVE) { // mouse left the window, undraw cursor UndrawMouseCursor(); @@ -968,7 +1004,8 @@ const char *VideoDriver_SDL::Start(const StringList &parm) /* Explicitly disable hardware acceleration. Enabling this causes * UpdateWindowSurface() to update the window's texture instead of * its surface. */ - SDL_SetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION , "0"); + SDL_SetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION, "0"); + SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1"); /* Just on the offchance the audio subsystem started before the video system, * check whether any part of SDL has been initialised before getting here. @@ -1012,19 +1049,114 @@ void VideoDriver_SDL::Stop() } } -void VideoDriver_SDL::MainLoop() +void VideoDriver_SDL::LoopOnce() { - uint32 cur_ticks = SDL_GetTicks(); - uint32 last_cur_ticks = cur_ticks; - uint32 next_tick = cur_ticks + MILLISECONDS_PER_TICK; uint32 mod; int numkeys; const Uint8 *keys; + uint32 prev_cur_ticks = cur_ticks; // to check for wrapping + InteractiveRandom(); // randomness + + while (PollEvent() == -1) {} + if (_exit_game) { +#ifdef __EMSCRIPTEN__ + /* Emscripten is event-driven, and as such the main loop is inside + * the browser. So if _exit_game goes true, the main loop ends (the + * cancel call), but we still have to call the cleanup that is + * normally done at the end of the main loop for non-Emscripten. + * After that, Emscripten just halts, and the HTML shows a nice + * "bye, see you next time" message. */ + emscripten_cancel_main_loop(); + MainLoopCleanup(); +#endif + return; + } + + mod = SDL_GetModState(); + keys = SDL_GetKeyboardState(&numkeys); + +#if defined(_DEBUG) + if (_shift_pressed) +#else + /* Speedup when pressing tab, except when using ALT+TAB + * to switch to another application */ + if (keys[SDL_SCANCODE_TAB] && (mod & KMOD_ALT) == 0) +#endif /* defined(_DEBUG) */ + { + if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; + } else if (_fast_forward & 2) { + _fast_forward = 0; + } + + cur_ticks = SDL_GetTicks(); + if (SDL_TICKS_PASSED(cur_ticks, next_tick) || (_fast_forward && !_pause_mode) || cur_ticks < prev_cur_ticks) { + _realtime_tick += cur_ticks - last_cur_ticks; + last_cur_ticks = cur_ticks; + next_tick = cur_ticks + MILLISECONDS_PER_TICK; + + bool old_ctrl_pressed = _ctrl_pressed; + bool old_shift_pressed = _shift_pressed; + + _ctrl_pressed = !!(mod & KMOD_CTRL) != _invert_ctrl; + _shift_pressed = !!(mod & KMOD_SHIFT) != _invert_shift; + + /* determine which directional keys are down */ + _dirkeys = + (keys[SDL_SCANCODE_LEFT] ? 1 : 0) | + (keys[SDL_SCANCODE_UP] ? 2 : 0) | + (keys[SDL_SCANCODE_RIGHT] ? 4 : 0) | + (keys[SDL_SCANCODE_DOWN] ? 8 : 0); + if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); + if (old_shift_pressed != _shift_pressed) HandleShiftChanged(); + + /* The gameloop is the part that can run asynchronously. The rest + * except sleeping can't. */ + if (_draw_mutex != nullptr) draw_lock.unlock(); + + GameLoop(); + + if (_draw_mutex != nullptr) draw_lock.lock(); + + GameLoopPaletteAnimations(); + + UpdateWindows(); + _local_palette = _cur_palette; + } else { + /* Release the thread while sleeping */ + if (_draw_mutex != nullptr) { + draw_lock.unlock(); + CSleep(1); + draw_lock.lock(); + } else { +/* Emscripten is running an event-based mainloop; there is already some + * downtime between each iteration, so no need to sleep. */ +#ifndef __EMSCRIPTEN__ + CSleep(1); +#endif + } + + NetworkDrawChatMessage(); + DrawMouseCursor(); + } + + /* End of the critical part. */ + if (_draw_mutex != nullptr && !HasModalProgress()) { + _draw_signal->notify_one(); + } else { + /* Oh, we didn't have threads, then just draw unthreaded */ + CheckPaletteAnim(); + DrawSurfaceToScreen(); + } +} + +void VideoDriver_SDL::MainLoop() +{ + cur_ticks = SDL_GetTicks(); + last_cur_ticks = cur_ticks; + next_tick = cur_ticks + MILLISECONDS_PER_TICK; CheckPaletteAnim(); - std::thread draw_thread; - std::unique_lock draw_lock; if (_draw_threaded) { /* Initialise the mutex first, because that's the thing we *need* * directly in the newly created thread. */ @@ -1055,82 +1187,20 @@ void VideoDriver_SDL::MainLoop() DEBUG(driver, 1, "SDL2: using %sthreads", _draw_threaded ? "" : "no "); - for (;;) { - uint32 prev_cur_ticks = cur_ticks; // to check for wrapping - InteractiveRandom(); // randomness - - while (PollEvent() == -1) {} - if (_exit_game) break; - - mod = SDL_GetModState(); - keys = SDL_GetKeyboardState(&numkeys); - -#if defined(_DEBUG) - if (_shift_pressed) +#ifdef __EMSCRIPTEN__ + /* Run the main loop event-driven, based on RequestAnimationFrame. */ + emscripten_set_main_loop_arg(&this->EmscriptenLoop, this, 0, 1); #else - /* Speedup when pressing tab, except when using ALT+TAB - * to switch to another application */ - if (keys[SDL_SCANCODE_TAB] && (mod & KMOD_ALT) == 0) -#endif /* defined(_DEBUG) */ - { - if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2; - } else if (_fast_forward & 2) { - _fast_forward = 0; - } - - cur_ticks = SDL_GetTicks(); - if (SDL_TICKS_PASSED(cur_ticks, next_tick) || (_fast_forward && !_pause_mode) || cur_ticks < prev_cur_ticks) { - _realtime_tick += cur_ticks - last_cur_ticks; - last_cur_ticks = cur_ticks; - next_tick = cur_ticks + MILLISECONDS_PER_TICK; - - bool old_ctrl_pressed = _ctrl_pressed; - bool old_shift_pressed = _shift_pressed; - - _ctrl_pressed = !!(mod & KMOD_CTRL) != _invert_ctrl; - _shift_pressed = !!(mod & KMOD_SHIFT) != _invert_shift; - - /* determine which directional keys are down */ - _dirkeys = - (keys[SDL_SCANCODE_LEFT] ? 1 : 0) | - (keys[SDL_SCANCODE_UP] ? 2 : 0) | - (keys[SDL_SCANCODE_RIGHT] ? 4 : 0) | - (keys[SDL_SCANCODE_DOWN] ? 8 : 0); - if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); - if (old_shift_pressed != _shift_pressed) HandleShiftChanged(); - - /* The gameloop is the part that can run asynchronously. The rest - * except sleeping can't. */ - if (_draw_mutex != nullptr) draw_lock.unlock(); - - GameLoop(); - - if (_draw_mutex != nullptr) draw_lock.lock(); - - GameLoopPaletteAnimations(); - - UpdateWindows(); - _local_palette = _cur_palette; - } else { - /* Release the thread while sleeping */ - if (_draw_mutex != nullptr) draw_lock.unlock(); - CSleep(1); - if (_draw_mutex != nullptr) draw_lock.lock(); - - NetworkDrawChatMessage(); - DrawMouseCursor(); - } - - /* End of the critical part. */ - if (_draw_mutex != nullptr && !HasModalProgress()) { - _draw_signal->notify_one(); - } else { - /* Oh, we didn't have threads, then just draw unthreaded */ - CheckPaletteAnim(); - DrawSurfaceToScreen(); - } + while (!_exit_game) { + LoopOnce(); } + MainLoopCleanup(); +#endif +} + +void VideoDriver_SDL::MainLoopCleanup() +{ if (_draw_mutex != nullptr) { _draw_continue = false; /* Sending signal if there is no thread blocked @@ -1146,6 +1216,15 @@ void VideoDriver_SDL::MainLoop() _draw_mutex = nullptr; _draw_signal = nullptr; } + +#ifdef __EMSCRIPTEN__ + emscripten_exit_pointerlock(); + /* In effect, the game ends here. As emscripten_set_main_loop() caused + * the stack to be unwound, the code after MainLoop() in + * openttd_main() is never executed. */ + EM_ASM(if (window["openttd_syncfs"]) openttd_syncfs()); + EM_ASM(if (window["openttd_exit"]) openttd_exit()); +#endif } bool VideoDriver_SDL::ChangeResolution(int w, int h) diff --git a/src/video/sdl2_v.h b/src/video/sdl2_v.h index 80d4018a77..c2ac87a062 100644 --- a/src/video/sdl2_v.h +++ b/src/video/sdl2_v.h @@ -42,12 +42,26 @@ public: const char *GetName() const override { return "sdl"; } private: int PollEvent(); + void LoopOnce(); + void MainLoopCleanup(); bool CreateMainSurface(uint w, uint h, bool resize); +#ifdef __EMSCRIPTEN__ + /* Convert a constant pointer back to a non-constant pointer to a member function. */ + static void EmscriptenLoop(void *self) { ((VideoDriver_SDL *)self)->LoopOnce(); } +#endif + /** * This is true to indicate that keyboard input is in text input mode, and SDL_TEXTINPUT events are enabled. */ bool edit_box_focused; + + uint32 cur_ticks; + uint32 last_cur_ticks; + uint32 next_tick; + + std::thread draw_thread; + std::unique_lock draw_lock; }; /** Factory for the SDL video driver. */ diff --git a/src/viewport.cpp b/src/viewport.cpp index 42ac4e0a40..9fdbe37380 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -816,8 +816,7 @@ static void AddTileSpriteToDraw(SpriteID image, PaletteID pal, int32 x, int32 y, { assert((image & SPRITE_MASK) < MAX_SPRITES); - /*C++17: TileSpriteToDraw &ts = */ _vd.tile_sprites_to_draw.emplace_back(); - TileSpriteToDraw &ts = _vd.tile_sprites_to_draw.back(); + TileSpriteToDraw &ts = _vd.tile_sprites_to_draw.emplace_back(); ts.image = image; ts.pal = pal; ts.sub = sub; @@ -1038,8 +1037,7 @@ void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int w, return; } - /*C++17: ParentSpriteToDraw &ps = */ _vd.parent_sprites_to_draw.emplace_back(); - ParentSpriteToDraw &ps = _vd.parent_sprites_to_draw.back(); + ParentSpriteToDraw &ps = _vd.parent_sprites_to_draw.emplace_back(); ps.x = tmp_x; ps.y = tmp_y; @@ -1180,8 +1178,7 @@ void AddChildSpriteScreen(SpriteID image, PaletteID pal, int x, int y, bool tran *_vd.last_child = (uint)_vd.child_screen_sprites_to_draw.size(); - /*C++17: ChildScreenSpriteToDraw &cs = */ _vd.child_screen_sprites_to_draw.emplace_back(); - ChildScreenSpriteToDraw &cs = _vd.child_screen_sprites_to_draw.back(); + ChildScreenSpriteToDraw &cs = _vd.child_screen_sprites_to_draw.emplace_back(); cs.image = image; cs.pal = pal; cs.sub = sub; @@ -1201,8 +1198,7 @@ void AddChildSpriteScreen(SpriteID image, PaletteID pal, int x, int y, bool tran static void AddStringToDraw(int x, int y, StringID string, uint64 params_1, uint64 params_2, Colours colour, uint16 width) { assert(width != 0); - /*C++17: StringSpriteToDraw &ss = */ _vd.string_sprites_to_draw.emplace_back(); - StringSpriteToDraw &ss = _vd.string_sprites_to_draw.back(); + StringSpriteToDraw &ss = _vd.string_sprites_to_draw.emplace_back(); ss.string = string; ss.x = x; ss.y = y;