Remove old files
This commit is contained in:
@@ -1,72 +0,0 @@
|
|||||||
trigger:
|
|
||||||
- master
|
|
||||||
- release/*
|
|
||||||
pr:
|
|
||||||
- master
|
|
||||||
- release/*
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
- job: windows
|
|
||||||
displayName: 'Windows'
|
|
||||||
pool:
|
|
||||||
vmImage: 'VS2017-Win2016'
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
Win32:
|
|
||||||
BuildPlatform: 'Win32'
|
|
||||||
Win64:
|
|
||||||
BuildPlatform: 'x64'
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- template: azure-pipelines/templates/ci-git-rebase.yml
|
|
||||||
- template: azure-pipelines/templates/windows-dependencies.yml
|
|
||||||
- template: azure-pipelines/templates/ci-opengfx.yml
|
|
||||||
- template: azure-pipelines/templates/windows-build.yml
|
|
||||||
parameters:
|
|
||||||
BuildPlatform: $(BuildPlatform)
|
|
||||||
BuildConfiguration: Debug
|
|
||||||
- script: |
|
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x86
|
|
||||||
cd projects
|
|
||||||
call regression.bat
|
|
||||||
displayName: 'Test'
|
|
||||||
|
|
||||||
- job: linux
|
|
||||||
displayName: 'Linux'
|
|
||||||
pool:
|
|
||||||
vmImage: 'ubuntu-16.04'
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
linux-amd64-clang-3.9:
|
|
||||||
Tag: 'linux-amd64-clang-3.9'
|
|
||||||
linux-amd64-gcc-6:
|
|
||||||
Tag: 'linux-amd64-gcc-6'
|
|
||||||
linux-i386-gcc-6:
|
|
||||||
Tag: 'linux-i386-gcc-6'
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- template: azure-pipelines/templates/ci-git-rebase.yml
|
|
||||||
# The dockers already have the dependencies installed
|
|
||||||
# The dockers already have OpenGFX installed
|
|
||||||
- template: azure-pipelines/templates/linux-build.yml
|
|
||||||
parameters:
|
|
||||||
Image: compile-farm-ci
|
|
||||||
Tag: $(Tag)
|
|
||||||
|
|
||||||
- job: macos
|
|
||||||
displayName: 'MacOS'
|
|
||||||
pool:
|
|
||||||
vmImage: 'macOS-10.14'
|
|
||||||
|
|
||||||
variables:
|
|
||||||
MACOSX_DEPLOYMENT_TARGET: 10.9
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- template: azure-pipelines/templates/ci-git-rebase.yml
|
|
||||||
- template: azure-pipelines/templates/osx-dependencies.yml
|
|
||||||
- template: azure-pipelines/templates/ci-opengfx.yml
|
|
||||||
- template: azure-pipelines/templates/osx-build.yml
|
|
||||||
- script: 'make regression'
|
|
||||||
displayName: 'Test'
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
trigger:
|
|
||||||
branches:
|
|
||||||
include:
|
|
||||||
- refs/tags/*
|
|
||||||
pr: none
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
- template: azure-pipelines/templates/release.yml
|
|
||||||
parameters:
|
|
||||||
IsStableRelease: true
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
trigger: none
|
|
||||||
pr: none
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
- template: azure-pipelines/templates/release.yml
|
|
||||||
parameters:
|
|
||||||
IsStableRelease: false
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
tag=$(git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null | sed 's@\^0$@@')
|
|
||||||
|
|
||||||
# If we are a tag, show the part of the changelog till (but excluding) the last stable
|
|
||||||
if [ -n "$tag" ]; then
|
|
||||||
grep='^[0-9]\+\.[0-9]\+\.[0-9]\+[^-]'
|
|
||||||
next=$(cat changelog.txt | grep '^[0-9]' | awk 'BEGIN { show="false" } // { if (show=="true") print $0; if ($1=="'$tag'") show="true"} ' | grep "$grep" | head -n1 | sed 's/ .*//')
|
|
||||||
cat changelog.txt | awk 'BEGIN { show="false" } /^[0-9]+.[0-9]+.[0-9]+/ { if ($1=="'$next'") show="false"; if ($1=="'$tag'") show="true";} // { if (show=="true") print $0 }'
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# In all other cases, show the git log of the last 7 days
|
|
||||||
revdate=$(git log -1 --pretty=format:"%ci")
|
|
||||||
last_week=$(date -d "$revdate -7days" +"%Y-%m-%d %H:%M")
|
|
||||||
git log --after="${last_week}" --pretty=fuller
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
echo "Usage: $0 <folder-with-bundles>"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
FOLDER=$1
|
|
||||||
|
|
||||||
if [ ! -e .version ] || [ ! -e .release_date ]; then
|
|
||||||
echo "This script should be executed in the root of an extracted source tarball"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Find the name based on the version
|
|
||||||
if [ -e .is_stable ]; then
|
|
||||||
isTesting=$(cat .version | grep "RC\|beta" || true)
|
|
||||||
if [ -z "${isTesting}" ]; then
|
|
||||||
NAME="stable"
|
|
||||||
else
|
|
||||||
NAME="testing"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
NAME=$(cat .version | cut -d- -f2 | cut -d- -f-2)
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Convert the date to a YAML date
|
|
||||||
DATE=$(cat .release_date | tr ' ' T | sed 's/TUTC/:00-00:00/')
|
|
||||||
VERSION=$(cat .version)
|
|
||||||
BASE="openttd-${VERSION}"
|
|
||||||
|
|
||||||
echo "name: ${NAME}" > manifest.yaml
|
|
||||||
echo "date: ${DATE}" >> manifest.yaml
|
|
||||||
echo "base: ${BASE}-" >> manifest.yaml
|
|
||||||
|
|
||||||
error=""
|
|
||||||
|
|
||||||
FILES=
|
|
||||||
DEV_FILES=
|
|
||||||
for filename in $(ls ${FOLDER} | grep -v ".txt$\|.md$\|sum$" | sort); do
|
|
||||||
case ${filename} in
|
|
||||||
*docs* |\
|
|
||||||
*source* |\
|
|
||||||
*dbg.deb |\
|
|
||||||
*pdb.xz )
|
|
||||||
DEV_FILES="${DEV_FILES} ${filename}"
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
FILES="${FILES} ${filename}"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# output_files key filename...
|
|
||||||
output_files() {
|
|
||||||
if [ "$#" -lt 2 ]; then return; fi
|
|
||||||
key=$1
|
|
||||||
echo "${key}:" >> manifest.yaml
|
|
||||||
shift
|
|
||||||
while [ "$#" -gt 0 ]; do
|
|
||||||
filename=$1
|
|
||||||
if [ ! -e ${FOLDER}/${filename}.md5sum ] || [ ! -e ${FOLDER}/${filename}.sha1sum ] || [ ! -e ${FOLDER}/${filename}.sha256sum ]; then
|
|
||||||
echo "ERROR: missing checksum file for ${filename}" 1>&2
|
|
||||||
error="y"
|
|
||||||
shift
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "- id: ${filename}" >> manifest.yaml
|
|
||||||
echo " size: $(stat -c"%s" ${FOLDER}/${filename})" >> manifest.yaml
|
|
||||||
echo " md5sum: $(cat ${FOLDER}/${filename}.md5sum | cut -d\ -f1)" >> manifest.yaml
|
|
||||||
echo " sha1sum: $(cat ${FOLDER}/${filename}.sha1sum | cut -d\ -f1)" >> manifest.yaml
|
|
||||||
echo " sha256sum: $(cat ${FOLDER}/${filename}.sha256sum | cut -d\ -f1)" >> manifest.yaml
|
|
||||||
shift
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
output_files files ${FILES}
|
|
||||||
output_files dev_files ${DEV_FILES}
|
|
||||||
|
|
||||||
if [ -n "${error}" ]; then
|
|
||||||
echo "ERROR: exiting due to earlier errors" 1>&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
steps:
|
|
||||||
# Rebase to target branch for every PR. This means users don't have to
|
|
||||||
# rebase every time target branch changes. As long as the PR applies cleanly, we
|
|
||||||
# will validate it.
|
|
||||||
- bash: |
|
|
||||||
git config user.email 'info@openttd.org'
|
|
||||||
git config user.name 'OpenTTD CI'
|
|
||||||
git rebase origin/${SYSTEM_PULLREQUEST_TARGETBRANCH}
|
|
||||||
displayName: 'Rebase to target branch'
|
|
||||||
condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest'))
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
steps:
|
|
||||||
- bash: |
|
|
||||||
set -ex
|
|
||||||
cd bin/baseset
|
|
||||||
curl -L https://cdn.openttd.org/opengfx-releases/0.6.0/opengfx-0.6.0-all.zip > opengfx-all.zip
|
|
||||||
unzip opengfx-all.zip
|
|
||||||
rm -f opengfx-all.zip
|
|
||||||
displayName: 'Install OpenGFX'
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
parameters:
|
|
||||||
Image: ''
|
|
||||||
Tag: ''
|
|
||||||
ContainerCommand: ''
|
|
||||||
|
|
||||||
steps:
|
|
||||||
# 'envVars' in the 'Docker@1' task is a bit funky. When you want to use a
|
|
||||||
# variable, you have to quote it. But the quote is also sent directly to
|
|
||||||
# Docker and ends up in the variable, which you don't want. To work around
|
|
||||||
# this, we set the correct variable first (which becomes an env-variable), and
|
|
||||||
# pass that env-variable through to Docker. We cannot use the normal
|
|
||||||
# 'variables' entry, as we are a template. So that results in this bit of
|
|
||||||
# Bash code. Not because it is pretty, but it is the only way we found that
|
|
||||||
# works.
|
|
||||||
- bash: |
|
|
||||||
echo "##vso[task.setvariable variable=TARGET_BRANCH]${SYSTEM_PULLREQUEST_TARGETBRANCH}"
|
|
||||||
echo "Target branch is ${SYSTEM_PULLREQUEST_TARGETBRANCH}"
|
|
||||||
displayName: "Set target branch"
|
|
||||||
condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest'))
|
|
||||||
|
|
||||||
- task: Docker@1
|
|
||||||
${{ if eq(parameters.Image, 'compile-farm') }}:
|
|
||||||
displayName: 'Build'
|
|
||||||
${{ if eq(parameters.Image, 'compile-farm-ci') }}:
|
|
||||||
displayName: 'Build and test'
|
|
||||||
# Run the commit-checker only if it is a Pull Request
|
|
||||||
condition: and(succeeded(), or(not(contains(variables['Agent.JobName'], 'commit-checker')), eq(variables['Build.Reason'], 'PullRequest')))
|
|
||||||
inputs:
|
|
||||||
command: 'Run an image'
|
|
||||||
imageName: openttd/${{ parameters.Image }}:${{ parameters.Tag }}
|
|
||||||
volumes: '$(Build.SourcesDirectory):$(Build.SourcesDirectory)'
|
|
||||||
workingDirectory: '$(Build.SourcesDirectory)'
|
|
||||||
containerCommand: ${{ parameters.ContainerCommand }}
|
|
||||||
runInBackground: false
|
|
||||||
envVars: |
|
|
||||||
TARGET_BRANCH
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
steps:
|
|
||||||
# Because we run the compile in a docker (under root), we are not owner
|
|
||||||
# of the 'bundles' folder. Fix that by executing a chown on it.
|
|
||||||
- bash: sudo chown -R $(id -u):$(id -g) bundles
|
|
||||||
displayName: 'Claim bundles folder back'
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
steps:
|
|
||||||
- script: './configure PKG_CONFIG_PATH=/usr/local/lib/pkgconfig --enable-static'
|
|
||||||
displayName: 'Configure'
|
|
||||||
- script: 'make -j2'
|
|
||||||
displayName: 'Build'
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
steps:
|
|
||||||
- script: |
|
|
||||||
set -ex
|
|
||||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config lzo xz libpng freetype
|
|
||||||
# Remove the dynamic libraries of these libraries, to ensure we use
|
|
||||||
# the static versions. That is important, as it is unlikely any
|
|
||||||
# end-user has these brew libraries installed.
|
|
||||||
rm /usr/local/Cellar/lzo/*/lib/*.dylib
|
|
||||||
rm /usr/local/Cellar/xz/*/lib/*.dylib
|
|
||||||
rm /usr/local/Cellar/libpng/*/lib/*.dylib
|
|
||||||
rm /usr/local/Cellar/freetype/*/lib/*.dylib
|
|
||||||
displayName: 'Install dependencies'
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
parameters:
|
|
||||||
CalculateChecksums: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- ${{ if eq(parameters.CalculateChecksums, true) }}:
|
|
||||||
- bash: |
|
|
||||||
set -ex
|
|
||||||
cd bundles
|
|
||||||
for i in $(ls); do
|
|
||||||
openssl dgst -r -md5 -hex $i > $i.md5sum
|
|
||||||
openssl dgst -r -sha1 -hex $i > $i.sha1sum
|
|
||||||
openssl dgst -r -sha256 -hex $i > $i.sha256sum
|
|
||||||
done
|
|
||||||
displayName: 'Calculate checksums'
|
|
||||||
- task: PublishBuildArtifacts@1
|
|
||||||
displayName: 'Publish bundles'
|
|
||||||
inputs:
|
|
||||||
PathtoPublish: bundles/
|
|
||||||
ArtifactName: bundles
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
# Fetch the source tarball as prepared by an earlier job. In there is the
|
|
||||||
# version predefined. This ensures we are all going to compile the same
|
|
||||||
# source with the same version.
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- checkout: none
|
|
||||||
- task: DownloadBuildArtifacts@0
|
|
||||||
displayName: 'Download source'
|
|
||||||
inputs:
|
|
||||||
downloadType: specific
|
|
||||||
itemPattern: 'bundles/openttd-*-source.tar.xz'
|
|
||||||
downloadPath: '$(Build.ArtifactStagingDirectory)'
|
|
||||||
- bash: tar --xz -xf ../a/bundles/openttd-*-source.tar.xz --strip-components=1
|
|
||||||
displayName: 'Extracting source'
|
|
||||||
- bash: |
|
|
||||||
set -e
|
|
||||||
VERSION=$(cat .version)
|
|
||||||
echo "${VERSION}"
|
|
||||||
echo "##vso[build.updatebuildnumber]${VERSION}"
|
|
||||||
displayName: 'Change BuildNumber to version'
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
parameters:
|
|
||||||
IsStableRelease: false
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- task: DownloadBuildArtifacts@0
|
|
||||||
displayName: 'Download all bundles'
|
|
||||||
inputs:
|
|
||||||
downloadType: specific
|
|
||||||
itemPattern: 'bundles/*'
|
|
||||||
downloadPath: '$(Build.ArtifactStagingDirectory)'
|
|
||||||
- ${{ if eq(parameters.IsStableRelease, true) }}:
|
|
||||||
- script: |
|
|
||||||
touch .is_stable
|
|
||||||
displayName: 'Mark as stable release'
|
|
||||||
- script: |
|
|
||||||
set -ex
|
|
||||||
./azure-pipelines/manifest.sh ../a/bundles/
|
|
||||||
mkdir -p bundles
|
|
||||||
mv manifest.yaml bundles/
|
|
||||||
displayName: 'Create manifest.yaml'
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
# Set the revisions, and remove the VCS files.
|
|
||||||
# This ensures everything else picks up on the predefined versions, and not
|
|
||||||
# that because of some build process the version all of a sudden changes.
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- script: |
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
if [ -n "${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}" ]; then
|
|
||||||
# We are triggered from a GitHub Pull Request
|
|
||||||
git checkout -B pr${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}
|
|
||||||
elif [ "${BUILD_SOURCEBRANCHNAME}" = "merge" ] || [ "${BUILD_SOURCEBRANCHNAME}" = "head" ]; then
|
|
||||||
# We are manually triggered based on a GitHub Pull Request
|
|
||||||
PULLREQUESTNUMBER=$(echo ${BUILD_SOURCEBRANCH} | cut -d/ -f3)
|
|
||||||
git checkout -B pr${PULLREQUESTNUMBER}
|
|
||||||
else
|
|
||||||
git checkout -B ${BUILD_SOURCEBRANCHNAME}
|
|
||||||
fi
|
|
||||||
|
|
||||||
./findversion.sh > .ottdrev
|
|
||||||
./azure-pipelines/changelog.sh > .changelog
|
|
||||||
TZ='UTC' date +"%Y-%m-%d %H:%M UTC" > .release_date
|
|
||||||
cat .ottdrev | cut -f 1 -d$'\t' > .version
|
|
||||||
echo "Release Date: $(cat .release_date)"
|
|
||||||
echo "Revision: $(cat .ottdrev)"
|
|
||||||
echo "Version: $(cat .version)"
|
|
||||||
displayName: 'Create version files'
|
|
||||||
- script: |
|
|
||||||
set -e
|
|
||||||
VERSION=$(cat .version)
|
|
||||||
echo "${VERSION}"
|
|
||||||
echo "##vso[build.updatebuildnumber]${VERSION}"
|
|
||||||
displayName: 'Change BuildNumber to version'
|
|
||||||
- script: find . -iname .hg -or -iname .git -or -iname .svn | xargs rm -rf
|
|
||||||
displayName: 'Remove VCS information'
|
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
parameters:
|
|
||||||
# If this is false, not all targets are triggered. For example:
|
|
||||||
# The NSIS installer for Windows and the creation of debs only work for
|
|
||||||
# releases. Not for any other type of binary. So they are skilled if this
|
|
||||||
# is set to false.
|
|
||||||
IsStableRelease: false
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
- job: source
|
|
||||||
displayName: 'Source'
|
|
||||||
pool:
|
|
||||||
vmImage: 'ubuntu-16.04'
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- template: release-prepare-source.yml
|
|
||||||
- script: |
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
# Rename the folder to openttd-NNN-source
|
|
||||||
mkdir openttd-$(Build.BuildNumber)
|
|
||||||
find . -maxdepth 1 -not -name . -not -name openttd-$(Build.BuildNumber) -exec mv {} openttd-$(Build.BuildNumber)/ \;
|
|
||||||
# Copy back release_date, as it is needed for the template 'release-bundles'
|
|
||||||
cp openttd-$(Build.BuildNumber)/.release_date .release_date
|
|
||||||
|
|
||||||
mkdir bundles
|
|
||||||
tar --xz -cf bundles/openttd-$(Build.BuildNumber)-source.tar.xz openttd-$(Build.BuildNumber)
|
|
||||||
zip -9 -r -q bundles/openttd-$(Build.BuildNumber)-source.zip openttd-$(Build.BuildNumber)
|
|
||||||
displayName: 'Create bundle'
|
|
||||||
- template: release-bundles.yml
|
|
||||||
|
|
||||||
- job: meta
|
|
||||||
displayName: 'Metadata'
|
|
||||||
pool:
|
|
||||||
vmImage: 'ubuntu-16.04'
|
|
||||||
dependsOn: source
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- template: release-fetch-source.yml
|
|
||||||
- script: |
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
mkdir -p bundles
|
|
||||||
cp .changelog bundles/changelog.txt
|
|
||||||
cp .release_date bundles/released.txt
|
|
||||||
cp README.md bundles/README.md
|
|
||||||
displayName: 'Copy meta files'
|
|
||||||
- template: release-bundles.yml
|
|
||||||
parameters:
|
|
||||||
CalculateChecksums: false
|
|
||||||
|
|
||||||
- job: docs
|
|
||||||
displayName: 'Docs'
|
|
||||||
pool:
|
|
||||||
vmImage: 'ubuntu-16.04'
|
|
||||||
dependsOn: source
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- template: release-fetch-source.yml
|
|
||||||
- template: linux-build.yml
|
|
||||||
parameters:
|
|
||||||
Image: compile-farm
|
|
||||||
ContainerCommand: '$(Build.BuildNumber)'
|
|
||||||
Tag: docs
|
|
||||||
- template: linux-claim-bundles.yml
|
|
||||||
- template: release-bundles.yml
|
|
||||||
|
|
||||||
- job: windows
|
|
||||||
displayName: 'Windows'
|
|
||||||
pool:
|
|
||||||
vmImage: 'VS2017-Win2016'
|
|
||||||
dependsOn: source
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
Win32:
|
|
||||||
BuildPlatform: 'Win32'
|
|
||||||
BundlePlatform: 'win32'
|
|
||||||
Win64:
|
|
||||||
BuildPlatform: 'x64'
|
|
||||||
BundlePlatform: 'win64'
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- template: release-fetch-source.yml
|
|
||||||
- template: windows-dependencies.yml
|
|
||||||
- template: windows-dependency-zip.yml
|
|
||||||
- ${{ if eq(parameters.IsStableRelease, true) }}:
|
|
||||||
- template: windows-dependency-nsis.yml
|
|
||||||
- template: windows-build.yml
|
|
||||||
parameters:
|
|
||||||
BuildPlatform: $(BuildPlatform)
|
|
||||||
BuildConfiguration: Release
|
|
||||||
- bash: |
|
|
||||||
set -ex
|
|
||||||
make -f Makefile.msvc bundle_pdb bundle_zip PLATFORM=$(BundlePlatform) BUNDLE_NAME=openttd-$(Build.BuildNumber)-windows-$(BundlePlatform)
|
|
||||||
displayName: 'Create bundles'
|
|
||||||
- ${{ if eq(parameters.IsStableRelease, true) }}:
|
|
||||||
- bash: |
|
|
||||||
set -ex
|
|
||||||
# NSIS will be part of the Hosted image in the next update. Till then, we set the PATH ourself
|
|
||||||
export PATH="${PATH}:/c/Program Files (x86)/NSIS"
|
|
||||||
make -f Makefile.msvc bundle_exe PLATFORM=$(BundlePlatform) BUNDLE_NAME=openttd-$(Build.BuildNumber)-windows-$(BundlePlatform)
|
|
||||||
displayName: 'Create installer bundle'
|
|
||||||
- template: release-bundles.yml
|
|
||||||
|
|
||||||
- ${{ if eq(parameters.IsStableRelease, true) }}:
|
|
||||||
- job: linux_stable
|
|
||||||
displayName: 'Linux'
|
|
||||||
pool:
|
|
||||||
vmImage: 'ubuntu-16.04'
|
|
||||||
dependsOn: source
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
linux-ubuntu-xenial-i386-gcc:
|
|
||||||
Tag: 'linux-ubuntu-xenial-i386-gcc'
|
|
||||||
linux-ubuntu-xenial-amd64-gcc:
|
|
||||||
Tag: 'linux-ubuntu-xenial-amd64-gcc'
|
|
||||||
linux-ubuntu-bionic-i386-gcc:
|
|
||||||
Tag: 'linux-ubuntu-bionic-i386-gcc'
|
|
||||||
linux-ubuntu-bionic-amd64-gcc:
|
|
||||||
Tag: 'linux-ubuntu-bionic-amd64-gcc'
|
|
||||||
linux-ubuntu-focal-amd64-gcc:
|
|
||||||
Tag: 'linux-ubuntu-focal-amd64-gcc'
|
|
||||||
linux-debian-stretch-i386-gcc:
|
|
||||||
Tag: 'linux-debian-stretch-i386-gcc'
|
|
||||||
linux-debian-stretch-amd64-gcc:
|
|
||||||
Tag: 'linux-debian-stretch-amd64-gcc'
|
|
||||||
linux-debian-buster-i386-gcc:
|
|
||||||
Tag: 'linux-debian-buster-i386-gcc'
|
|
||||||
linux-debian-buster-amd64-gcc:
|
|
||||||
Tag: 'linux-debian-buster-amd64-gcc'
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- template: release-fetch-source.yml
|
|
||||||
- template: linux-build.yml
|
|
||||||
parameters:
|
|
||||||
Image: compile-farm
|
|
||||||
ContainerCommand: '$(Build.BuildNumber)'
|
|
||||||
Tag: $(Tag)
|
|
||||||
- template: linux-claim-bundles.yml
|
|
||||||
- template: release-bundles.yml
|
|
||||||
|
|
||||||
- job: macos
|
|
||||||
displayName: 'MacOS'
|
|
||||||
pool:
|
|
||||||
vmImage: 'macOS-10.14'
|
|
||||||
dependsOn: source
|
|
||||||
|
|
||||||
variables:
|
|
||||||
MACOSX_DEPLOYMENT_TARGET: 10.9
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- template: release-fetch-source.yml
|
|
||||||
- template: osx-dependencies.yml
|
|
||||||
- template: osx-build.yml
|
|
||||||
- script: 'make bundle_zip bundle_dmg BUNDLE_NAME=openttd-$(Build.BuildNumber)-macosx'
|
|
||||||
displayName: 'Create bundles'
|
|
||||||
- template: release-bundles.yml
|
|
||||||
|
|
||||||
- job: manifest
|
|
||||||
displayName: 'Manifest'
|
|
||||||
pool:
|
|
||||||
vmImage: 'ubuntu-16.04'
|
|
||||||
dependsOn:
|
|
||||||
- source
|
|
||||||
- docs
|
|
||||||
- windows
|
|
||||||
- ${{ if eq(parameters.IsStableRelease, true) }}:
|
|
||||||
- linux_stable
|
|
||||||
- macos
|
|
||||||
# "Skipped" is not a status, and is not succeeded. So it seems to be
|
|
||||||
# considered failed. So we trigger if all the earlier jobs are done (which
|
|
||||||
# might be succeeded, failed, or skipped), and run this job. This is not
|
|
||||||
# optimal, but given the rules, it is the only way to get this to work (as
|
|
||||||
# some jobs might be skipped).
|
|
||||||
condition: succeededOrFailed()
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- template: release-fetch-source.yml
|
|
||||||
- template: release-manifest.yml
|
|
||||||
${{ if eq(parameters.IsStableRelease, true) }}:
|
|
||||||
parameters:
|
|
||||||
IsStableRelease: true
|
|
||||||
- template: release-bundles.yml
|
|
||||||
parameters:
|
|
||||||
CalculateChecksums: false
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
parameters:
|
|
||||||
BuildPlatform: ''
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- task: VSBuild@1
|
|
||||||
displayName: 'Build'
|
|
||||||
inputs:
|
|
||||||
solution: 'projects/openttd_vs141.sln'
|
|
||||||
platform: ${{ parameters.BuildPlatform }}
|
|
||||||
configuration: ${{ parameters.BuildConfiguration }}
|
|
||||||
maximumCpuCount: true
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
steps:
|
|
||||||
- bash: |
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
curl -L https://github.com/OpenTTD/CompileFarm/releases/download/latest/windows-dependencies.zip > windows-dependencies.zip
|
|
||||||
unzip windows-dependencies.zip
|
|
||||||
rm -f windows-dependencies.zip
|
|
||||||
|
|
||||||
mv windows-dependencies/installed /c/vcpkg/
|
|
||||||
rm -rf windows-dependencies
|
|
||||||
displayName: 'Install dependencies'
|
|
||||||
workingDirectory: $(Build.ArtifactStagingDirectory)
|
|
||||||
- script: c:\vcpkg\vcpkg.exe integrate install
|
|
||||||
displayName: 'Integrate vcpkg'
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
parameters:
|
|
||||||
condition: true
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- bash: |
|
|
||||||
set -ex
|
|
||||||
|
|
||||||
mkdir nsis-plugin; cd nsis-plugin
|
|
||||||
curl -L https://devs.openttd.org/~truebrain/nsis-plugins/Nsis7z.zip > Nsis7z.zip
|
|
||||||
unzip Nsis7z.zip
|
|
||||||
cp -R Plugins/* "/c/Program Files (x86)/NSIS/Plugins/"
|
|
||||||
cd ..; rm -rf nsis-plugin
|
|
||||||
|
|
||||||
mkdir nsis-plugin; cd nsis-plugin
|
|
||||||
curl -L https://devs.openttd.org/~truebrain/nsis-plugins/NsisGetVersion.zip > NsisGetVersion.zip
|
|
||||||
unzip NsisGetVersion.zip
|
|
||||||
cp -R Plugins/* "/c/Program Files (x86)/NSIS/Plugins/x86-ansi/"
|
|
||||||
cd ..; rm -rf nsis-plugin
|
|
||||||
|
|
||||||
mkdir nsis-plugin; cd nsis-plugin
|
|
||||||
curl -L https://devs.openttd.org/~truebrain/nsis-plugins/NsisFindProc.zip > NsisFindProc.zip
|
|
||||||
unzip NsisFindProc.zip
|
|
||||||
cp -R *.dll "/c/Program Files (x86)/NSIS/Plugins/x86-ansi/"
|
|
||||||
cd ..; rm -rf nsis-plugin
|
|
||||||
displayName: 'Install NSIS with the 7z, GetVersion, and FindProc plugins'
|
|
||||||
condition: and(succeeded(), ${{ parameters.condition }})
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
steps:
|
|
||||||
- bash: |
|
|
||||||
set -ex
|
|
||||||
choco install zip
|
|
||||||
displayName: 'Install zip'
|
|
||||||
@@ -1,11 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#
|
|
||||||
# Awk script to automatically remove duplicate Comment[i]= lines
|
|
||||||
#
|
|
||||||
|
|
||||||
BEGIN { FS = "="; last = "" }
|
|
||||||
{ if (last != $1) { print $0 }; last = $1 }
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
|
|
||||||
[Desktop Entry]
|
|
||||||
Type=Application
|
|
||||||
Version=1.0
|
|
||||||
Name=!!MENU_NAME!!
|
|
||||||
Icon=!!TTD!!
|
|
||||||
Exec=!!TTD!!
|
|
||||||
Terminal=false
|
|
||||||
Categories=!!MENU_GROUP!!
|
|
||||||
Comment=A clone of Transport Tycoon Deluxe
|
|
||||||
Keywords=game;simulation;transport;tycoon;deluxe;economics;multiplayer;money;train;ship;bus;truck;aircraft;cargo;
|
|
||||||
@@ -1,13 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
#
|
|
||||||
# Awk script to automatically generate a comment lines for
|
|
||||||
# a translated desktop shortcut. If it does not exist there
|
|
||||||
# is no output.
|
|
||||||
#
|
|
||||||
|
|
||||||
/##isocode/ { lang = $2; next }
|
|
||||||
/STR_DESKTOP_SHORTCUT_COMMENT/ { sub("^[^:]*:", "", $0); print "Comment[" lang "]=" $0; sub("_.*", "", lang); print "Comment[" lang "]=" $0; next}
|
|
||||||
@@ -1,654 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @file fontdetection.cpp Detection of the right font. */
|
|
||||||
|
|
||||||
#if defined(WITH_FREETYPE) || defined(_WIN32)
|
|
||||||
|
|
||||||
#include "stdafx.h"
|
|
||||||
#include "debug.h"
|
|
||||||
#include "fontdetection.h"
|
|
||||||
#include "string_func.h"
|
|
||||||
#include "strings_func.h"
|
|
||||||
|
|
||||||
#ifdef WITH_FREETYPE
|
|
||||||
extern FT_Library _library;
|
|
||||||
#endif /* WITH_FREETYPE */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the font loaded into a Freetype face by using a font-name.
|
|
||||||
* If no appropriate font is found, the function returns an error
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ========================================================================================
|
|
||||||
* Windows support
|
|
||||||
* ======================================================================================== */
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include "core/alloc_func.hpp"
|
|
||||||
#include "core/math_func.hpp"
|
|
||||||
#include <windows.h>
|
|
||||||
#include <shlobj.h> /* SHGetFolderPath */
|
|
||||||
#include "os/windows/win32.h"
|
|
||||||
|
|
||||||
#include "safeguards.h"
|
|
||||||
|
|
||||||
#ifdef WITH_FREETYPE
|
|
||||||
/**
|
|
||||||
* Get the short DOS 8.3 format for paths.
|
|
||||||
* FreeType doesn't support Unicode filenames and Windows' fopen (as used
|
|
||||||
* by FreeType) doesn't support UTF-8 filenames. So we have to convert the
|
|
||||||
* filename into something that isn't UTF-8 but represents the Unicode file
|
|
||||||
* name. This is the short DOS 8.3 format. This does not contain any
|
|
||||||
* characters that fopen doesn't support.
|
|
||||||
* @param long_path the path in system encoding.
|
|
||||||
* @return the short path in ANSI (ASCII).
|
|
||||||
*/
|
|
||||||
const char *GetShortPath(const TCHAR *long_path)
|
|
||||||
{
|
|
||||||
static char short_path[MAX_PATH];
|
|
||||||
#ifdef UNICODE
|
|
||||||
WCHAR short_path_w[MAX_PATH];
|
|
||||||
GetShortPathName(long_path, short_path_w, lengthof(short_path_w));
|
|
||||||
WideCharToMultiByte(CP_ACP, 0, short_path_w, -1, short_path, lengthof(short_path), nullptr, nullptr);
|
|
||||||
#else
|
|
||||||
/* Technically not needed, but do it for consistency. */
|
|
||||||
GetShortPathName(long_path, short_path, lengthof(short_path));
|
|
||||||
#endif
|
|
||||||
return short_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get the font file to be loaded into Freetype by looping the registry
|
|
||||||
* location where windows lists all installed fonts. Not very nice, will
|
|
||||||
* surely break if the registry path changes, but it works. Much better
|
|
||||||
* solution would be to use CreateFont, and extract the font data from it
|
|
||||||
* by GetFontData. The problem with this is that the font file needs to be
|
|
||||||
* kept in memory then until the font is no longer needed. This could mean
|
|
||||||
* an additional memory usage of 30MB (just for fonts!) when using an eastern
|
|
||||||
* font for all font sizes */
|
|
||||||
#define FONT_DIR_NT "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"
|
|
||||||
#define FONT_DIR_9X "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Fonts"
|
|
||||||
FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
|
|
||||||
{
|
|
||||||
FT_Error err = FT_Err_Cannot_Open_Resource;
|
|
||||||
HKEY hKey;
|
|
||||||
LONG ret;
|
|
||||||
TCHAR vbuffer[MAX_PATH], dbuffer[256];
|
|
||||||
TCHAR *pathbuf;
|
|
||||||
const char *font_path;
|
|
||||||
uint index;
|
|
||||||
size_t path_len;
|
|
||||||
|
|
||||||
/* On windows NT (2000, NT3.5, XP, etc.) the fonts are stored in the
|
|
||||||
* "Windows NT" key, on Windows 9x in the Windows key. To save us having
|
|
||||||
* to retrieve the windows version, we'll just query both */
|
|
||||||
ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(FONT_DIR_NT), 0, KEY_READ, &hKey);
|
|
||||||
if (ret != ERROR_SUCCESS) ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T(FONT_DIR_9X), 0, KEY_READ, &hKey);
|
|
||||||
|
|
||||||
if (ret != ERROR_SUCCESS) {
|
|
||||||
DEBUG(freetype, 0, "Cannot open registry key HKLM\\SOFTWARE\\Microsoft\\Windows (NT)\\CurrentVersion\\Fonts");
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert font name to file system encoding. */
|
|
||||||
TCHAR *font_namep = _tcsdup(OTTD2FS(font_name));
|
|
||||||
|
|
||||||
for (index = 0;; index++) {
|
|
||||||
TCHAR *s;
|
|
||||||
DWORD vbuflen = lengthof(vbuffer);
|
|
||||||
DWORD dbuflen = lengthof(dbuffer);
|
|
||||||
|
|
||||||
ret = RegEnumValue(hKey, index, vbuffer, &vbuflen, nullptr, nullptr, (byte*)dbuffer, &dbuflen);
|
|
||||||
if (ret != ERROR_SUCCESS) goto registry_no_font_found;
|
|
||||||
|
|
||||||
/* The font names in the registry are of the following 3 forms:
|
|
||||||
* - ADMUI3.fon
|
|
||||||
* - Book Antiqua Bold (TrueType)
|
|
||||||
* - Batang & BatangChe & Gungsuh & GungsuhChe (TrueType)
|
|
||||||
* We will strip the font-type '()' if any and work with the font name
|
|
||||||
* itself, which must match exactly; if...
|
|
||||||
* TTC files, font files which contain more than one font are separated
|
|
||||||
* by '&'. Our best bet will be to do substr match for the fontname
|
|
||||||
* and then let FreeType figure out which index to load */
|
|
||||||
s = _tcschr(vbuffer, _T('('));
|
|
||||||
if (s != nullptr) s[-1] = '\0';
|
|
||||||
|
|
||||||
if (_tcschr(vbuffer, _T('&')) == nullptr) {
|
|
||||||
if (_tcsicmp(vbuffer, font_namep) == 0) break;
|
|
||||||
} else {
|
|
||||||
if (_tcsstr(vbuffer, font_namep) != nullptr) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SUCCEEDED(OTTDSHGetFolderPath(nullptr, CSIDL_FONTS, nullptr, SHGFP_TYPE_CURRENT, vbuffer))) {
|
|
||||||
DEBUG(freetype, 0, "SHGetFolderPath cannot return fonts directory");
|
|
||||||
goto folder_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Some fonts are contained in .ttc files, TrueType Collection fonts. These
|
|
||||||
* contain multiple fonts inside this single file. GetFontData however
|
|
||||||
* returns the whole file, so we need to check each font inside to get the
|
|
||||||
* proper font. */
|
|
||||||
path_len = _tcslen(vbuffer) + _tcslen(dbuffer) + 2; // '\' and terminating nul.
|
|
||||||
pathbuf = AllocaM(TCHAR, path_len);
|
|
||||||
_sntprintf(pathbuf, path_len, _T("%s\\%s"), vbuffer, dbuffer);
|
|
||||||
|
|
||||||
/* Convert the path into something that FreeType understands. */
|
|
||||||
font_path = GetShortPath(pathbuf);
|
|
||||||
|
|
||||||
index = 0;
|
|
||||||
do {
|
|
||||||
err = FT_New_Face(_library, font_path, index, face);
|
|
||||||
if (err != FT_Err_Ok) break;
|
|
||||||
|
|
||||||
if (strncasecmp(font_name, (*face)->family_name, strlen((*face)->family_name)) == 0) break;
|
|
||||||
/* Try english name if font name failed */
|
|
||||||
if (strncasecmp(font_name + strlen(font_name) + 1, (*face)->family_name, strlen((*face)->family_name)) == 0) break;
|
|
||||||
err = FT_Err_Cannot_Open_Resource;
|
|
||||||
|
|
||||||
} while ((FT_Long)++index != (*face)->num_faces);
|
|
||||||
|
|
||||||
|
|
||||||
folder_error:
|
|
||||||
registry_no_font_found:
|
|
||||||
free(font_namep);
|
|
||||||
RegCloseKey(hKey);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fonts can have localised names and when the system locale is the same as
|
|
||||||
* one of those localised names Windows will always return that localised name
|
|
||||||
* instead of allowing to get the non-localised (English US) name of the font.
|
|
||||||
* This will later on give problems as freetype uses the non-localised name of
|
|
||||||
* the font and we need to compare based on that name.
|
|
||||||
* Windows furthermore DOES NOT have an API to get the non-localised name nor
|
|
||||||
* can we override the system locale. This means that we have to actually read
|
|
||||||
* the font itself to gather the font name we want.
|
|
||||||
* Based on: http://blogs.msdn.com/michkap/archive/2006/02/13/530814.aspx
|
|
||||||
* @param logfont the font information to get the english name of.
|
|
||||||
* @return the English name (if it could be found).
|
|
||||||
*/
|
|
||||||
static const char *GetEnglishFontName(const ENUMLOGFONTEX *logfont)
|
|
||||||
{
|
|
||||||
static char font_name[MAX_PATH];
|
|
||||||
const char *ret_font_name = nullptr;
|
|
||||||
uint pos = 0;
|
|
||||||
HDC dc;
|
|
||||||
HGDIOBJ oldfont;
|
|
||||||
byte *buf;
|
|
||||||
DWORD dw;
|
|
||||||
uint16 format, count, stringOffset, platformId, encodingId, languageId, nameId, length, offset;
|
|
||||||
|
|
||||||
HFONT font = CreateFontIndirect(&logfont->elfLogFont);
|
|
||||||
if (font == nullptr) goto err1;
|
|
||||||
|
|
||||||
dc = GetDC(nullptr);
|
|
||||||
oldfont = SelectObject(dc, font);
|
|
||||||
dw = GetFontData(dc, 'eman', 0, nullptr, 0);
|
|
||||||
if (dw == GDI_ERROR) goto err2;
|
|
||||||
|
|
||||||
buf = MallocT<byte>(dw);
|
|
||||||
dw = GetFontData(dc, 'eman', 0, buf, dw);
|
|
||||||
if (dw == GDI_ERROR) goto err3;
|
|
||||||
|
|
||||||
format = buf[pos++] << 8;
|
|
||||||
format += buf[pos++];
|
|
||||||
assert(format == 0);
|
|
||||||
count = buf[pos++] << 8;
|
|
||||||
count += buf[pos++];
|
|
||||||
stringOffset = buf[pos++] << 8;
|
|
||||||
stringOffset += buf[pos++];
|
|
||||||
for (uint i = 0; i < count; i++) {
|
|
||||||
platformId = buf[pos++] << 8;
|
|
||||||
platformId += buf[pos++];
|
|
||||||
encodingId = buf[pos++] << 8;
|
|
||||||
encodingId += buf[pos++];
|
|
||||||
languageId = buf[pos++] << 8;
|
|
||||||
languageId += buf[pos++];
|
|
||||||
nameId = buf[pos++] << 8;
|
|
||||||
nameId += buf[pos++];
|
|
||||||
if (nameId != 1) {
|
|
||||||
pos += 4; // skip length and offset
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
length = buf[pos++] << 8;
|
|
||||||
length += buf[pos++];
|
|
||||||
offset = buf[pos++] << 8;
|
|
||||||
offset += buf[pos++];
|
|
||||||
|
|
||||||
/* Don't buffer overflow */
|
|
||||||
length = std::min(length, MAX_PATH - 1);
|
|
||||||
for (uint j = 0; j < length; j++) font_name[j] = buf[stringOffset + offset + j];
|
|
||||||
font_name[length] = '\0';
|
|
||||||
|
|
||||||
if ((platformId == 1 && languageId == 0) || // Macintosh English
|
|
||||||
(platformId == 3 && languageId == 0x0409)) { // Microsoft English (US)
|
|
||||||
ret_font_name = font_name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
err3:
|
|
||||||
free(buf);
|
|
||||||
err2:
|
|
||||||
SelectObject(dc, oldfont);
|
|
||||||
ReleaseDC(nullptr, dc);
|
|
||||||
DeleteObject(font);
|
|
||||||
err1:
|
|
||||||
return ret_font_name == nullptr ? WIDE_TO_MB((const TCHAR*)logfont->elfFullName) : ret_font_name;
|
|
||||||
}
|
|
||||||
#endif /* WITH_FREETYPE */
|
|
||||||
|
|
||||||
class FontList {
|
|
||||||
protected:
|
|
||||||
TCHAR **fonts;
|
|
||||||
uint items;
|
|
||||||
uint capacity;
|
|
||||||
|
|
||||||
public:
|
|
||||||
FontList() : fonts(nullptr), items(0), capacity(0) { };
|
|
||||||
|
|
||||||
~FontList() {
|
|
||||||
if (this->fonts == nullptr) return;
|
|
||||||
|
|
||||||
for (uint i = 0; i < this->items; i++) {
|
|
||||||
free(this->fonts[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(this->fonts);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Add(const TCHAR *font) {
|
|
||||||
for (uint i = 0; i < this->items; i++) {
|
|
||||||
if (_tcscmp(this->fonts[i], font) == 0) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->items == this->capacity) {
|
|
||||||
this->capacity += 10;
|
|
||||||
this->fonts = ReallocT(this->fonts, this->capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->fonts[this->items++] = _tcsdup(font);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EFCParam {
|
|
||||||
FreeTypeSettings *settings;
|
|
||||||
LOCALESIGNATURE locale;
|
|
||||||
MissingGlyphSearcher *callback;
|
|
||||||
FontList fonts;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int CALLBACK EnumFontCallback(const ENUMLOGFONTEX *logfont, const NEWTEXTMETRICEX *metric, DWORD type, LPARAM lParam)
|
|
||||||
{
|
|
||||||
EFCParam *info = (EFCParam *)lParam;
|
|
||||||
|
|
||||||
/* Skip duplicates */
|
|
||||||
if (!info->fonts.Add((const TCHAR*)logfont->elfFullName)) return 1;
|
|
||||||
/* Only use TrueType fonts */
|
|
||||||
if (!(type & TRUETYPE_FONTTYPE)) return 1;
|
|
||||||
/* Don't use SYMBOL fonts */
|
|
||||||
if (logfont->elfLogFont.lfCharSet == SYMBOL_CHARSET) return 1;
|
|
||||||
/* Use monospaced fonts when asked for it. */
|
|
||||||
if (info->callback->Monospace() && (logfont->elfLogFont.lfPitchAndFamily & (FF_MODERN | FIXED_PITCH)) != (FF_MODERN | FIXED_PITCH)) return 1;
|
|
||||||
|
|
||||||
/* The font has to have at least one of the supported locales to be usable. */
|
|
||||||
if ((metric->ntmFontSig.fsCsb[0] & info->locale.lsCsbSupported[0]) == 0 && (metric->ntmFontSig.fsCsb[1] & info->locale.lsCsbSupported[1]) == 0) {
|
|
||||||
/* On win9x metric->ntmFontSig seems to contain garbage. */
|
|
||||||
FONTSIGNATURE fs;
|
|
||||||
memset(&fs, 0, sizeof(fs));
|
|
||||||
HFONT font = CreateFontIndirect(&logfont->elfLogFont);
|
|
||||||
if (font != nullptr) {
|
|
||||||
HDC dc = GetDC(nullptr);
|
|
||||||
HGDIOBJ oldfont = SelectObject(dc, font);
|
|
||||||
GetTextCharsetInfo(dc, &fs, 0);
|
|
||||||
SelectObject(dc, oldfont);
|
|
||||||
ReleaseDC(nullptr, dc);
|
|
||||||
DeleteObject(font);
|
|
||||||
}
|
|
||||||
if ((fs.fsCsb[0] & info->locale.lsCsbSupported[0]) == 0 && (fs.fsCsb[1] & info->locale.lsCsbSupported[1]) == 0) return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char font_name[MAX_PATH];
|
|
||||||
convert_from_fs((const TCHAR *)logfont->elfFullName, font_name, lengthof(font_name));
|
|
||||||
|
|
||||||
#ifdef WITH_FREETYPE
|
|
||||||
/* Add english name after font name */
|
|
||||||
const char *english_name = GetEnglishFontName(logfont);
|
|
||||||
strecpy(font_name + strlen(font_name) + 1, english_name, lastof(font_name));
|
|
||||||
|
|
||||||
/* Check whether we can actually load the font. */
|
|
||||||
bool ft_init = _library != nullptr;
|
|
||||||
bool found = false;
|
|
||||||
FT_Face face;
|
|
||||||
/* Init FreeType if needed. */
|
|
||||||
if ((ft_init || FT_Init_FreeType(&_library) == FT_Err_Ok) && GetFontByFaceName(font_name, &face) == FT_Err_Ok) {
|
|
||||||
FT_Done_Face(face);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
if (!ft_init) {
|
|
||||||
/* Uninit FreeType if we did the init. */
|
|
||||||
FT_Done_FreeType(_library);
|
|
||||||
_library = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) return 1;
|
|
||||||
#else
|
|
||||||
const char *english_name = font_name;
|
|
||||||
#endif /* WITH_FREETYPE */
|
|
||||||
|
|
||||||
PLOGFONT os_data = MallocT<LOGFONT>(1);
|
|
||||||
*os_data = logfont->elfLogFont;
|
|
||||||
info->callback->SetFontNames(info->settings, font_name, os_data);
|
|
||||||
if (info->callback->FindMissingGlyphs()) return 1;
|
|
||||||
DEBUG(freetype, 1, "Fallback font: %s (%s)", font_name, english_name);
|
|
||||||
return 0; // stop enumerating
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback)
|
|
||||||
{
|
|
||||||
DEBUG(freetype, 1, "Trying fallback fonts");
|
|
||||||
EFCParam langInfo;
|
|
||||||
if (GetLocaleInfo(MAKELCID(winlangid, SORT_DEFAULT), LOCALE_FONTSIGNATURE, (LPTSTR)&langInfo.locale, sizeof(langInfo.locale) / sizeof(TCHAR)) == 0) {
|
|
||||||
/* Invalid langid or some other mysterious error, can't determine fallback font. */
|
|
||||||
DEBUG(freetype, 1, "Can't get locale info for fallback font (langid=0x%x)", winlangid);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
langInfo.settings = settings;
|
|
||||||
langInfo.callback = callback;
|
|
||||||
|
|
||||||
LOGFONT font;
|
|
||||||
/* Enumerate all fonts. */
|
|
||||||
font.lfCharSet = DEFAULT_CHARSET;
|
|
||||||
font.lfFaceName[0] = '\0';
|
|
||||||
font.lfPitchAndFamily = 0;
|
|
||||||
|
|
||||||
HDC dc = GetDC(nullptr);
|
|
||||||
int ret = EnumFontFamiliesEx(dc, &font, (FONTENUMPROC)&EnumFontCallback, (LPARAM)&langInfo, 0);
|
|
||||||
ReleaseDC(nullptr, dc);
|
|
||||||
return ret == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__APPLE__) /* end ifdef Win32 */
|
|
||||||
/* ========================================================================================
|
|
||||||
* OSX support
|
|
||||||
* ======================================================================================== */
|
|
||||||
|
|
||||||
#include "os/macosx/macos.h"
|
|
||||||
|
|
||||||
#include "safeguards.h"
|
|
||||||
|
|
||||||
FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
|
|
||||||
{
|
|
||||||
FT_Error err = FT_Err_Cannot_Open_Resource;
|
|
||||||
|
|
||||||
/* Get font reference from name. */
|
|
||||||
UInt8 file_path[PATH_MAX];
|
|
||||||
OSStatus os_err = -1;
|
|
||||||
CFAutoRelease<CFStringRef> name(CFStringCreateWithCString(kCFAllocatorDefault, font_name, kCFStringEncodingUTF8));
|
|
||||||
|
|
||||||
/* Simply creating the font using CTFontCreateWithNameAndSize will *always* return
|
|
||||||
* something, no matter the name. As such, we can't use it to check for existence.
|
|
||||||
* We instead query the list of all font descriptors that match the given name which
|
|
||||||
* does not do this stupid name fallback. */
|
|
||||||
CFAutoRelease<CTFontDescriptorRef> name_desc(CTFontDescriptorCreateWithNameAndSize(name.get(), 0.0));
|
|
||||||
CFAutoRelease<CFSetRef> mandatory_attribs(CFSetCreate(kCFAllocatorDefault, const_cast<const void **>(reinterpret_cast<const void * const *>(&kCTFontNameAttribute)), 1, &kCFTypeSetCallBacks));
|
|
||||||
CFAutoRelease<CFArrayRef> descs(CTFontDescriptorCreateMatchingFontDescriptors(name_desc.get(), mandatory_attribs.get()));
|
|
||||||
|
|
||||||
/* Loop over all matches until we can get a path for one of them. */
|
|
||||||
for (CFIndex i = 0; descs.get() != nullptr && i < CFArrayGetCount(descs.get()) && os_err != noErr; i++) {
|
|
||||||
CFAutoRelease<CTFontRef> font(CTFontCreateWithFontDescriptor((CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), i), 0.0, nullptr));
|
|
||||||
CFAutoRelease<CFURLRef> fontURL((CFURLRef)CTFontCopyAttribute(font.get(), kCTFontURLAttribute));
|
|
||||||
if (CFURLGetFileSystemRepresentation(fontURL.get(), true, file_path, lengthof(file_path))) os_err = noErr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (os_err == noErr) {
|
|
||||||
DEBUG(freetype, 3, "Font path for %s: %s", font_name, file_path);
|
|
||||||
err = FT_New_Face(_library, (const char *)file_path, 0, face);
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback)
|
|
||||||
{
|
|
||||||
/* Determine fallback font using CoreText. This uses the language isocode
|
|
||||||
* to find a suitable font. CoreText is available from 10.5 onwards. */
|
|
||||||
char lang[16];
|
|
||||||
if (strcmp(language_isocode, "zh_TW") == 0) {
|
|
||||||
/* Traditional Chinese */
|
|
||||||
strecpy(lang, "zh-Hant", lastof(lang));
|
|
||||||
} else if (strcmp(language_isocode, "zh_CN") == 0) {
|
|
||||||
/* Simplified Chinese */
|
|
||||||
strecpy(lang, "zh-Hans", lastof(lang));
|
|
||||||
} else {
|
|
||||||
/* Just copy the first part of the isocode. */
|
|
||||||
strecpy(lang, language_isocode, lastof(lang));
|
|
||||||
char *sep = strchr(lang, '_');
|
|
||||||
if (sep != nullptr) *sep = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a font descriptor matching the wanted language and latin (english) glyphs.
|
|
||||||
* Can't use CFAutoRelease here for everything due to the way the dictionary has to be created. */
|
|
||||||
CFStringRef lang_codes[2];
|
|
||||||
lang_codes[0] = CFStringCreateWithCString(kCFAllocatorDefault, lang, kCFStringEncodingUTF8);
|
|
||||||
lang_codes[1] = CFSTR("en");
|
|
||||||
CFArrayRef lang_arr = CFArrayCreate(kCFAllocatorDefault, (const void **)lang_codes, lengthof(lang_codes), &kCFTypeArrayCallBacks);
|
|
||||||
CFAutoRelease<CFDictionaryRef> lang_attribs(CFDictionaryCreate(kCFAllocatorDefault, const_cast<const void **>(reinterpret_cast<const void * const *>(&kCTFontLanguagesAttribute)), (const void **)&lang_arr, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
|
|
||||||
CFAutoRelease<CTFontDescriptorRef> lang_desc(CTFontDescriptorCreateWithAttributes(lang_attribs.get()));
|
|
||||||
CFRelease(lang_arr);
|
|
||||||
CFRelease(lang_codes[0]);
|
|
||||||
|
|
||||||
/* Get array of all font descriptors for the wanted language. */
|
|
||||||
CFAutoRelease<CFSetRef> mandatory_attribs(CFSetCreate(kCFAllocatorDefault, const_cast<const void **>(reinterpret_cast<const void * const *>(&kCTFontLanguagesAttribute)), 1, &kCFTypeSetCallBacks));
|
|
||||||
CFAutoRelease<CFArrayRef> descs(CTFontDescriptorCreateMatchingFontDescriptors(lang_desc.get(), mandatory_attribs.get()));
|
|
||||||
|
|
||||||
bool result = false;
|
|
||||||
for (CFIndex i = 0; descs.get() != nullptr && i < CFArrayGetCount(descs.get()); i++) {
|
|
||||||
CTFontDescriptorRef font = (CTFontDescriptorRef)CFArrayGetValueAtIndex(descs.get(), i);
|
|
||||||
|
|
||||||
/* Get font traits. */
|
|
||||||
CFAutoRelease<CFDictionaryRef> traits((CFDictionaryRef)CTFontDescriptorCopyAttribute(font, kCTFontTraitsAttribute));
|
|
||||||
CTFontSymbolicTraits symbolic_traits;
|
|
||||||
CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(traits.get(), kCTFontSymbolicTrait), kCFNumberIntType, &symbolic_traits);
|
|
||||||
|
|
||||||
/* Skip symbol fonts and vertical fonts. */
|
|
||||||
if ((symbolic_traits & kCTFontClassMaskTrait) == (CTFontStylisticClass)kCTFontSymbolicClass || (symbolic_traits & kCTFontVerticalTrait)) continue;
|
|
||||||
/* Skip bold fonts (especially Arial Bold, which looks worse than regular Arial). */
|
|
||||||
if (symbolic_traits & kCTFontBoldTrait) continue;
|
|
||||||
/* Select monospaced fonts if asked for. */
|
|
||||||
if (((symbolic_traits & kCTFontMonoSpaceTrait) == kCTFontMonoSpaceTrait) != callback->Monospace()) continue;
|
|
||||||
|
|
||||||
/* Get font name. */
|
|
||||||
char name[128];
|
|
||||||
CFAutoRelease<CFStringRef> font_name((CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontDisplayNameAttribute));
|
|
||||||
CFStringGetCString(font_name.get(), name, lengthof(name), kCFStringEncodingUTF8);
|
|
||||||
|
|
||||||
/* There are some special fonts starting with an '.' and the last
|
|
||||||
* resort font that aren't usable. Skip them. */
|
|
||||||
if (name[0] == '.' || strncmp(name, "LastResort", 10) == 0) continue;
|
|
||||||
|
|
||||||
/* Save result. */
|
|
||||||
callback->SetFontNames(settings, name);
|
|
||||||
if (!callback->FindMissingGlyphs()) {
|
|
||||||
DEBUG(freetype, 2, "CT-Font for %s: %s", language_isocode, name);
|
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
/* For some OS versions, the font 'Arial Unicode MS' does not report all languages it
|
|
||||||
* supports. If we didn't find any other font, just try it, maybe we get lucky. */
|
|
||||||
callback->SetFontNames(settings, "Arial Unicode MS");
|
|
||||||
result = !callback->FindMissingGlyphs();
|
|
||||||
}
|
|
||||||
|
|
||||||
callback->FindMissingGlyphs();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(WITH_FONTCONFIG) /* end ifdef __APPLE__ */
|
|
||||||
|
|
||||||
#include <fontconfig/fontconfig.h>
|
|
||||||
|
|
||||||
#include "safeguards.h"
|
|
||||||
|
|
||||||
/* ========================================================================================
|
|
||||||
* FontConfig (unix) support
|
|
||||||
* ======================================================================================== */
|
|
||||||
FT_Error GetFontByFaceName(const char *font_name, FT_Face *face)
|
|
||||||
{
|
|
||||||
FT_Error err = FT_Err_Cannot_Open_Resource;
|
|
||||||
|
|
||||||
if (!FcInit()) {
|
|
||||||
ShowInfoF("Unable to load font configuration");
|
|
||||||
} else {
|
|
||||||
FcPattern *match;
|
|
||||||
FcPattern *pat;
|
|
||||||
FcFontSet *fs;
|
|
||||||
FcResult result;
|
|
||||||
char *font_style;
|
|
||||||
char *font_family;
|
|
||||||
|
|
||||||
/* Split & strip the font's style */
|
|
||||||
font_family = stredup(font_name);
|
|
||||||
font_style = strchr(font_family, ',');
|
|
||||||
if (font_style != nullptr) {
|
|
||||||
font_style[0] = '\0';
|
|
||||||
font_style++;
|
|
||||||
while (*font_style == ' ' || *font_style == '\t') font_style++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Resolve the name and populate the information structure */
|
|
||||||
pat = FcNameParse((FcChar8*)font_family);
|
|
||||||
if (font_style != nullptr) FcPatternAddString(pat, FC_STYLE, (FcChar8*)font_style);
|
|
||||||
FcConfigSubstitute(0, pat, FcMatchPattern);
|
|
||||||
FcDefaultSubstitute(pat);
|
|
||||||
fs = FcFontSetCreate();
|
|
||||||
match = FcFontMatch(0, pat, &result);
|
|
||||||
|
|
||||||
if (fs != nullptr && match != nullptr) {
|
|
||||||
int i;
|
|
||||||
FcChar8 *family;
|
|
||||||
FcChar8 *style;
|
|
||||||
FcChar8 *file;
|
|
||||||
FcFontSetAdd(fs, match);
|
|
||||||
|
|
||||||
for (i = 0; err != FT_Err_Ok && i < fs->nfont; i++) {
|
|
||||||
/* Try the new filename */
|
|
||||||
if (FcPatternGetString(fs->fonts[i], FC_FILE, 0, &file) == FcResultMatch &&
|
|
||||||
FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &family) == FcResultMatch &&
|
|
||||||
FcPatternGetString(fs->fonts[i], FC_STYLE, 0, &style) == FcResultMatch) {
|
|
||||||
|
|
||||||
/* The correct style? */
|
|
||||||
if (font_style != nullptr && strcasecmp(font_style, (char*)style) != 0) continue;
|
|
||||||
|
|
||||||
/* Font config takes the best shot, which, if the family name is spelled
|
|
||||||
* wrongly a 'random' font, so check whether the family name is the
|
|
||||||
* same as the supplied name */
|
|
||||||
if (strcasecmp(font_family, (char*)family) == 0) {
|
|
||||||
err = FT_New_Face(_library, (char *)file, 0, face);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(font_family);
|
|
||||||
FcPatternDestroy(pat);
|
|
||||||
FcFontSetDestroy(fs);
|
|
||||||
FcFini();
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback)
|
|
||||||
{
|
|
||||||
if (!FcInit()) return false;
|
|
||||||
|
|
||||||
bool ret = false;
|
|
||||||
|
|
||||||
/* Fontconfig doesn't handle full language isocodes, only the part
|
|
||||||
* before the _ of e.g. en_GB is used, so "remove" everything after
|
|
||||||
* the _. */
|
|
||||||
char lang[16];
|
|
||||||
seprintf(lang, lastof(lang), ":lang=%s", language_isocode);
|
|
||||||
char *split = strchr(lang, '_');
|
|
||||||
if (split != nullptr) *split = '\0';
|
|
||||||
|
|
||||||
/* First create a pattern to match the wanted language. */
|
|
||||||
FcPattern *pat = FcNameParse((FcChar8*)lang);
|
|
||||||
/* We only want to know the filename. */
|
|
||||||
FcObjectSet *os = FcObjectSetBuild(FC_FILE, FC_SPACING, FC_SLANT, FC_WEIGHT, nullptr);
|
|
||||||
/* Get the list of filenames matching the wanted language. */
|
|
||||||
FcFontSet *fs = FcFontList(nullptr, pat, os);
|
|
||||||
|
|
||||||
/* We don't need these anymore. */
|
|
||||||
FcObjectSetDestroy(os);
|
|
||||||
FcPatternDestroy(pat);
|
|
||||||
|
|
||||||
if (fs != nullptr) {
|
|
||||||
int best_weight = -1;
|
|
||||||
const char *best_font = nullptr;
|
|
||||||
|
|
||||||
for (int i = 0; i < fs->nfont; i++) {
|
|
||||||
FcPattern *font = fs->fonts[i];
|
|
||||||
|
|
||||||
FcChar8 *file = nullptr;
|
|
||||||
FcResult res = FcPatternGetString(font, FC_FILE, 0, &file);
|
|
||||||
if (res != FcResultMatch || file == nullptr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get a font with the right spacing .*/
|
|
||||||
int value = 0;
|
|
||||||
FcPatternGetInteger(font, FC_SPACING, 0, &value);
|
|
||||||
if (callback->Monospace() != (value == FC_MONO) && value != FC_DUAL) continue;
|
|
||||||
|
|
||||||
/* Do not use those that explicitly say they're slanted. */
|
|
||||||
FcPatternGetInteger(font, FC_SLANT, 0, &value);
|
|
||||||
if (value != 0) continue;
|
|
||||||
|
|
||||||
/* We want the fatter font as they look better at small sizes. */
|
|
||||||
FcPatternGetInteger(font, FC_WEIGHT, 0, &value);
|
|
||||||
if (value <= best_weight) continue;
|
|
||||||
|
|
||||||
callback->SetFontNames(settings, (const char*)file);
|
|
||||||
|
|
||||||
bool missing = callback->FindMissingGlyphs();
|
|
||||||
DEBUG(freetype, 1, "Font \"%s\" misses%s glyphs", file, missing ? "" : " no");
|
|
||||||
|
|
||||||
if (!missing) {
|
|
||||||
best_weight = value;
|
|
||||||
best_font = (const char *)file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (best_font != nullptr) {
|
|
||||||
ret = true;
|
|
||||||
callback->SetFontNames(settings, best_font);
|
|
||||||
InitFreeType(callback->Monospace());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clean up the list of filenames. */
|
|
||||||
FcFontSetDestroy(fs);
|
|
||||||
}
|
|
||||||
|
|
||||||
FcFini();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else /* without WITH_FONTCONFIG */
|
|
||||||
FT_Error GetFontByFaceName(const char *font_name, FT_Face *face) {return FT_Err_Cannot_Open_Resource;}
|
|
||||||
bool SetFallbackFont(FreeTypeSettings *settings, const char *language_isocode, int winlangid, MissingGlyphSearcher *callback) { return false; }
|
|
||||||
#endif /* WITH_FONTCONFIG */
|
|
||||||
|
|
||||||
#endif /* WITH_FREETYPE */
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,421 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @file blob.hpp Support for storing random binary data. */
|
|
||||||
|
|
||||||
#ifndef BLOB_HPP
|
|
||||||
#define BLOB_HPP
|
|
||||||
|
|
||||||
#include "../core/alloc_func.hpp"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for simple binary blobs.
|
|
||||||
* Item is byte.
|
|
||||||
* The word 'simple' means:
|
|
||||||
* - no configurable allocator type (always made from heap)
|
|
||||||
* - no smart deallocation - deallocation must be called from the same
|
|
||||||
* module (DLL) where the blob was allocated
|
|
||||||
* - no configurable allocation policy (how big blocks should be allocated)
|
|
||||||
* - no extra ownership policy (i.e. 'copy on write') when blob is copied
|
|
||||||
* - no thread synchronization at all
|
|
||||||
*
|
|
||||||
* Internal member layout:
|
|
||||||
* 1. The only class member is pointer to the first item (see union).
|
|
||||||
* 2. Allocated block contains the blob header (see BlobHeader) followed by the raw byte data.
|
|
||||||
* Always, when it allocates memory the allocated size is:
|
|
||||||
* sizeof(BlobHeader) + <data capacity>
|
|
||||||
* 3. Two 'virtual' members (items and capacity) are stored in the BlobHeader at beginning
|
|
||||||
* of the allocated block.
|
|
||||||
* 4. The pointer of the union pobsize_ts behind the header (to the first data byte).
|
|
||||||
* When memory block is allocated, the sizeof(BlobHeader) it added to it.
|
|
||||||
* 5. Benefits of this layout:
|
|
||||||
* - items are accessed in the simplest possible way - just dereferencing the pointer,
|
|
||||||
* which is good for performance (assuming that data are accessed most often).
|
|
||||||
* - sizeof(blob) is the same as the size of any other pointer
|
|
||||||
* 6. Drawbacks of this layout:
|
|
||||||
* - the fact that a pointer to the allocated block is adjusted by sizeof(BlobHeader) before
|
|
||||||
* it is stored can lead to several confusions:
|
|
||||||
* - it is not a common pattern so the implementation code is bit harder to read.
|
|
||||||
* - valgrind may generate a warning that the allocated block is lost (not accessible).
|
|
||||||
*/
|
|
||||||
class ByteBlob {
|
|
||||||
protected:
|
|
||||||
/** header of the allocated memory block */
|
|
||||||
struct BlobHeader {
|
|
||||||
size_t items; ///< actual blob size in bytes
|
|
||||||
size_t capacity; ///< maximum (allocated) size in bytes
|
|
||||||
};
|
|
||||||
|
|
||||||
/** type used as class member */
|
|
||||||
union {
|
|
||||||
byte *data; ///< ptr to the first byte of data
|
|
||||||
BlobHeader *header; ///< ptr just after the BlobHeader holding items and capacity
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* Just to silence an unsilencable GCC 4.4+ warning
|
|
||||||
* Note: This cannot be 'const' as we do a lot of 'hdrEmpty[0]->items += 0;' and 'hdrEmpty[0]->capacity += 0;'
|
|
||||||
* after const_casting.
|
|
||||||
*/
|
|
||||||
static BlobHeader hdrEmpty[];
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const size_t tail_reserve = 4; ///< four extra bytes will be always allocated and zeroed at the end
|
|
||||||
static const size_t header_size = sizeof(BlobHeader);
|
|
||||||
|
|
||||||
/** default constructor - initializes empty blob */
|
|
||||||
inline ByteBlob()
|
|
||||||
{
|
|
||||||
InitEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** copy constructor */
|
|
||||||
inline ByteBlob(const ByteBlob &src)
|
|
||||||
{
|
|
||||||
InitEmpty();
|
|
||||||
AppendRaw(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** move constructor - take ownership of blob data */
|
|
||||||
inline ByteBlob(BlobHeader * const & src)
|
|
||||||
{
|
|
||||||
assert(src != nullptr);
|
|
||||||
header = src;
|
|
||||||
*const_cast<BlobHeader**>(&src) = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** destructor */
|
|
||||||
inline ~ByteBlob()
|
|
||||||
{
|
|
||||||
Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** all allocation should happen here */
|
|
||||||
static inline BlobHeader *RawAlloc(size_t num_bytes)
|
|
||||||
{
|
|
||||||
return (BlobHeader*)MallocT<byte>(num_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return header pointer to the static BlobHeader with
|
|
||||||
* both items and capacity containing zero
|
|
||||||
*/
|
|
||||||
static inline BlobHeader *Zero()
|
|
||||||
{
|
|
||||||
return const_cast<BlobHeader *>(&ByteBlob::hdrEmpty[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** simple allocation policy - can be optimized later */
|
|
||||||
static inline size_t AllocPolicy(size_t min_alloc)
|
|
||||||
{
|
|
||||||
if (min_alloc < (1 << 9)) {
|
|
||||||
if (min_alloc < (1 << 5)) return (1 << 5);
|
|
||||||
return (min_alloc < (1 << 7)) ? (1 << 7) : (1 << 9);
|
|
||||||
}
|
|
||||||
if (min_alloc < (1 << 15)) {
|
|
||||||
if (min_alloc < (1 << 11)) return (1 << 11);
|
|
||||||
return (min_alloc < (1 << 13)) ? (1 << 13) : (1 << 15);
|
|
||||||
}
|
|
||||||
if (min_alloc < (1 << 20)) {
|
|
||||||
if (min_alloc < (1 << 17)) return (1 << 17);
|
|
||||||
return (min_alloc < (1 << 19)) ? (1 << 19) : (1 << 20);
|
|
||||||
}
|
|
||||||
min_alloc = (min_alloc | ((1 << 20) - 1)) + 1;
|
|
||||||
return min_alloc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** all deallocations should happen here */
|
|
||||||
static inline void RawFree(BlobHeader *p)
|
|
||||||
{
|
|
||||||
/* Just to silence an unsilencable GCC 4.4+ warning. */
|
|
||||||
assert(p != ByteBlob::hdrEmpty);
|
|
||||||
|
|
||||||
/* In case GCC warns about the following, see GCC's PR38509 why it is bogus. */
|
|
||||||
free(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** initialize the empty blob */
|
|
||||||
inline void InitEmpty()
|
|
||||||
{
|
|
||||||
header = Zero();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** initialize blob by attaching it to the given header followed by data */
|
|
||||||
inline void Init(BlobHeader *src)
|
|
||||||
{
|
|
||||||
header = &src[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/** blob header accessor - use it rather than using the pointer arithmetic directly - non-const version */
|
|
||||||
inline BlobHeader& Hdr()
|
|
||||||
{
|
|
||||||
return *(header - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** blob header accessor - use it rather than using the pointer arithmetic directly - const version */
|
|
||||||
inline const BlobHeader& Hdr() const
|
|
||||||
{
|
|
||||||
return *(header - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** return reference to the actual blob size - used when the size needs to be modified */
|
|
||||||
inline size_t& LengthRef()
|
|
||||||
{
|
|
||||||
return Hdr().items;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** return true if blob doesn't contain valid data */
|
|
||||||
inline bool IsEmpty() const
|
|
||||||
{
|
|
||||||
return Length() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** return the number of valid data bytes in the blob */
|
|
||||||
inline size_t Length() const
|
|
||||||
{
|
|
||||||
return Hdr().items;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** return the current blob capacity in bytes */
|
|
||||||
inline size_t Capacity() const
|
|
||||||
{
|
|
||||||
return Hdr().capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** return pointer to the first byte of data - non-const version */
|
|
||||||
inline byte *Begin()
|
|
||||||
{
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** return pointer to the first byte of data - const version */
|
|
||||||
inline const byte *Begin() const
|
|
||||||
{
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** invalidate blob's data - doesn't free buffer */
|
|
||||||
inline void Clear()
|
|
||||||
{
|
|
||||||
LengthRef() = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** free the blob's memory */
|
|
||||||
inline void Free()
|
|
||||||
{
|
|
||||||
if (Capacity() > 0) {
|
|
||||||
RawFree(&Hdr());
|
|
||||||
InitEmpty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** append new bytes at the end of existing data bytes - reallocates if necessary */
|
|
||||||
inline void AppendRaw(const void *p, size_t num_bytes)
|
|
||||||
{
|
|
||||||
assert(p != nullptr);
|
|
||||||
if (num_bytes > 0) {
|
|
||||||
memcpy(Append(num_bytes), p, num_bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** append bytes from given source blob to the end of existing data bytes - reallocates if necessary */
|
|
||||||
inline void AppendRaw(const ByteBlob& src)
|
|
||||||
{
|
|
||||||
if (!src.IsEmpty()) {
|
|
||||||
memcpy(Append(src.Length()), src.Begin(), src.Length());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reallocate if there is no free space for num_bytes bytes.
|
|
||||||
* @return pointer to the new data to be added
|
|
||||||
*/
|
|
||||||
inline byte *Prepare(size_t num_bytes)
|
|
||||||
{
|
|
||||||
size_t new_size = Length() + num_bytes;
|
|
||||||
if (new_size > Capacity()) SmartAlloc(new_size);
|
|
||||||
return data + Length();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Increase Length() by num_bytes.
|
|
||||||
* @return pointer to the new data added
|
|
||||||
*/
|
|
||||||
inline byte *Append(size_t num_bytes)
|
|
||||||
{
|
|
||||||
byte *pNewData = Prepare(num_bytes);
|
|
||||||
LengthRef() += num_bytes;
|
|
||||||
return pNewData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** reallocate blob data if needed */
|
|
||||||
void SmartAlloc(size_t new_size)
|
|
||||||
{
|
|
||||||
if (Capacity() >= new_size) return;
|
|
||||||
/* calculate minimum block size we need to allocate
|
|
||||||
* and ask allocation policy for some reasonable block size */
|
|
||||||
assert(new_size < SIZE_MAX - header_size - tail_reserve);
|
|
||||||
new_size = AllocPolicy(header_size + new_size + tail_reserve);
|
|
||||||
|
|
||||||
/* allocate new block and setup header */
|
|
||||||
BlobHeader *tmp = RawAlloc(new_size);
|
|
||||||
tmp->items = Length();
|
|
||||||
tmp->capacity = new_size - (header_size + tail_reserve);
|
|
||||||
|
|
||||||
/* copy existing data */
|
|
||||||
if (tmp->items != 0) {
|
|
||||||
memcpy(tmp + 1, data, tmp->items);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* replace our block with new one */
|
|
||||||
if (Capacity() > 0) {
|
|
||||||
RawFree(&Hdr());
|
|
||||||
}
|
|
||||||
Init(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** fixing the four bytes at the end of blob data - useful when blob is used to hold string */
|
|
||||||
inline void FixTail() const
|
|
||||||
{
|
|
||||||
if (Capacity() > 0) {
|
|
||||||
byte *p = &data[Length()];
|
|
||||||
for (uint i = 0; i < tail_reserve; i++) {
|
|
||||||
p[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Blob - simple dynamic T array. T (template argument) is a placeholder for any type.
|
|
||||||
* T can be any integral type, pointer, or structure. Using Blob instead of just plain C array
|
|
||||||
* simplifies the resource management in several ways:
|
|
||||||
* 1. When adding new item(s) it automatically grows capacity if needed.
|
|
||||||
* 2. When variable of type Blob comes out of scope it automatically frees the data buffer.
|
|
||||||
* 3. Takes care about the actual data size (number of used items).
|
|
||||||
* 4. Dynamically constructs only used items (as opposite of static array which constructs all items)
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
class CBlobT : public ByteBlob {
|
|
||||||
/* make template arguments public: */
|
|
||||||
public:
|
|
||||||
typedef ByteBlob base;
|
|
||||||
|
|
||||||
static const size_t type_size = sizeof(T);
|
|
||||||
|
|
||||||
struct OnTransfer {
|
|
||||||
typename base::BlobHeader *header;
|
|
||||||
|
|
||||||
OnTransfer(const OnTransfer& src) : header(src.header)
|
|
||||||
{
|
|
||||||
assert(src.header != nullptr);
|
|
||||||
*const_cast<typename base::BlobHeader**>(&src.header) = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
OnTransfer(CBlobT& src) : header(src.header)
|
|
||||||
{
|
|
||||||
src.InitEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
~OnTransfer()
|
|
||||||
{
|
|
||||||
assert(header == nullptr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Default constructor - makes new Blob ready to accept any data */
|
|
||||||
inline CBlobT()
|
|
||||||
: base()
|
|
||||||
{}
|
|
||||||
|
|
||||||
/** Take ownership constructor */
|
|
||||||
inline CBlobT(const OnTransfer& ot)
|
|
||||||
: base(ot.header)
|
|
||||||
{}
|
|
||||||
|
|
||||||
/** Destructor - ensures that allocated memory (if any) is freed */
|
|
||||||
inline ~CBlobT()
|
|
||||||
{
|
|
||||||
Free();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check the validity of item index (only in debug mode) */
|
|
||||||
inline void CheckIdx(size_t index) const
|
|
||||||
{
|
|
||||||
assert(index < Size());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return pointer to the first data item - non-const version */
|
|
||||||
inline T *Data()
|
|
||||||
{
|
|
||||||
return (T*)base::Begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return pointer to the first data item - const version */
|
|
||||||
inline const T *Data() const
|
|
||||||
{
|
|
||||||
return (const T*)base::Begin();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return pointer to the index-th data item - non-const version */
|
|
||||||
inline T *Data(size_t index)
|
|
||||||
{
|
|
||||||
CheckIdx(index);
|
|
||||||
return (Data() + index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return pointer to the index-th data item - const version */
|
|
||||||
inline const T *Data(size_t index) const
|
|
||||||
{
|
|
||||||
CheckIdx(index);
|
|
||||||
return (Data() + index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return number of items in the Blob */
|
|
||||||
inline size_t Size() const
|
|
||||||
{
|
|
||||||
return (base::Length() / type_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return total number of items that can fit in the Blob without buffer reallocation */
|
|
||||||
inline size_t MaxSize() const
|
|
||||||
{
|
|
||||||
return (base::Capacity() / type_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return number of additional items that can fit in the Blob without buffer reallocation */
|
|
||||||
inline size_t GetReserve() const
|
|
||||||
{
|
|
||||||
return ((base::Capacity() - base::Length()) / type_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Grow number of data items in Blob by given number - doesn't construct items */
|
|
||||||
inline T *GrowSizeNC(size_t num_items)
|
|
||||||
{
|
|
||||||
return (T*)base::Append(num_items * type_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ensures that given number of items can be added to the end of Blob. Returns pointer to the
|
|
||||||
* first free (unused) item
|
|
||||||
*/
|
|
||||||
inline T *MakeFreeSpace(size_t num_items)
|
|
||||||
{
|
|
||||||
return (T*)base::Prepare(num_items * type_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline OnTransfer Transfer()
|
|
||||||
{
|
|
||||||
return OnTransfer(*this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* BLOB_HPP */
|
|
||||||
149
src/misc/str.hpp
149
src/misc/str.hpp
@@ -1,149 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @file str.hpp String formatting? */
|
|
||||||
|
|
||||||
#ifndef STR_HPP
|
|
||||||
#define STR_HPP
|
|
||||||
|
|
||||||
#include <errno.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include "blob.hpp"
|
|
||||||
#include "../core/math_func.hpp"
|
|
||||||
#include "../string_func.h"
|
|
||||||
|
|
||||||
/** Blob based case sensitive ANSI/UTF-8 string */
|
|
||||||
struct CStrA : public CBlobT<char>
|
|
||||||
{
|
|
||||||
typedef CBlobT<char> base; ///< base class
|
|
||||||
|
|
||||||
/** Create an empty CStrT */
|
|
||||||
inline CStrA()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Copy constructor */
|
|
||||||
inline CStrA(const CStrA &src) : base(src)
|
|
||||||
{
|
|
||||||
base::FixTail();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Take over ownership constructor */
|
|
||||||
inline CStrA(const OnTransfer &ot)
|
|
||||||
: base(ot)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Grow the actual buffer and fix the trailing zero at the end. */
|
|
||||||
inline char *GrowSizeNC(uint count)
|
|
||||||
{
|
|
||||||
char *ret = base::GrowSizeNC(count);
|
|
||||||
base::FixTail();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Append zero-ended C string. */
|
|
||||||
inline void AppendStr(const char *str)
|
|
||||||
{
|
|
||||||
if (!StrEmpty(str)) {
|
|
||||||
base::AppendRaw(str, strlen(str));
|
|
||||||
base::FixTail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Append another CStrA. */
|
|
||||||
inline void Append(const CStrA &src)
|
|
||||||
{
|
|
||||||
if (src.Length() > 0) {
|
|
||||||
base::AppendRaw(src);
|
|
||||||
base::FixTail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Assignment from C string. */
|
|
||||||
inline CStrA &operator=(const char *src)
|
|
||||||
{
|
|
||||||
base::Clear();
|
|
||||||
AppendStr(src);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Assignment from another CStrA. */
|
|
||||||
inline CStrA &operator=(const CStrA &src)
|
|
||||||
{
|
|
||||||
if (&src != this) {
|
|
||||||
base::Clear();
|
|
||||||
base::AppendRaw(src.Data(), src.Size());
|
|
||||||
base::FixTail();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Lower-than operator (to support stl collections) */
|
|
||||||
inline bool operator<(const CStrA &other) const
|
|
||||||
{
|
|
||||||
return strcmp(base::Data(), other.Data()) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add formatted string (like vsprintf) at the end of existing contents. */
|
|
||||||
int AddFormatL(const char *format, va_list args) WARN_FORMAT(2, 0)
|
|
||||||
{
|
|
||||||
size_t addSize = std::max<size_t>(strlen(format), 16);
|
|
||||||
addSize += addSize / 2;
|
|
||||||
int ret;
|
|
||||||
int err = 0;
|
|
||||||
for (;;) {
|
|
||||||
char *buf = MakeFreeSpace(addSize);
|
|
||||||
ret = vseprintf(buf, buf + base::GetReserve() - 1, format, args);
|
|
||||||
if (ret >= (int)base::GetReserve()) {
|
|
||||||
/* Greater return than given count means needed buffer size. */
|
|
||||||
addSize = ret + 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (ret >= 0) {
|
|
||||||
/* success */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
err = errno;
|
|
||||||
if (err != ERANGE && err != ENOENT && err != 0) {
|
|
||||||
/* some strange failure */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* small buffer (M$ implementation) */
|
|
||||||
addSize *= 2;
|
|
||||||
}
|
|
||||||
if (ret > 0) {
|
|
||||||
GrowSizeNC(ret);
|
|
||||||
} else {
|
|
||||||
base::FixTail();
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Add formatted string (like sprintf) at the end of existing contents. */
|
|
||||||
int CDECL WARN_FORMAT(2, 3) AddFormat(const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
int ret = AddFormatL(format, args);
|
|
||||||
va_end(args);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Assign formatted string (like sprintf). */
|
|
||||||
int CDECL WARN_FORMAT(2, 3) Format(const char *format, ...)
|
|
||||||
{
|
|
||||||
base::Free();
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
int ret = AddFormatL(format, args);
|
|
||||||
va_end(args);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* STR_HPP */
|
|
||||||
@@ -1,57 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file game.h Information about a game that is sent between a
|
|
||||||
* game server, game client and masterserver.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef NETWORK_CORE_GAME_H
|
|
||||||
#define NETWORK_CORE_GAME_H
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "../../newgrf_config.h"
|
|
||||||
#include "../../date_type.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The game information that is not generated on-the-fly and has to
|
|
||||||
* be sent to the clients.
|
|
||||||
*/
|
|
||||||
struct NetworkServerGameInfo {
|
|
||||||
char map_name[NETWORK_NAME_LENGTH]; ///< Map which is played ["random" for a randomized map]
|
|
||||||
byte clients_on; ///< Current count of clients on server
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The game information that is sent from the server to the clients.
|
|
||||||
*/
|
|
||||||
struct NetworkGameInfo : NetworkServerGameInfo {
|
|
||||||
GRFConfig *grfconfig; ///< List of NewGRF files used
|
|
||||||
Date start_date; ///< When the game started
|
|
||||||
Date game_date; ///< Current date
|
|
||||||
uint16 map_width; ///< Map width
|
|
||||||
uint16 map_height; ///< Map height
|
|
||||||
char server_name[NETWORK_NAME_LENGTH]; ///< Server name
|
|
||||||
char hostname[NETWORK_HOSTNAME_LENGTH]; ///< Hostname of the server (if any)
|
|
||||||
char server_revision[NETWORK_REVISION_LENGTH]; ///< The version number the server is using (e.g.: 'r304' or 0.5.0)
|
|
||||||
bool dedicated; ///< Is this a dedicated server?
|
|
||||||
bool version_compatible; ///< Can we connect to this server or not? (based on server_revision)
|
|
||||||
bool compatible; ///< Can we connect to this server or not? (based on server_revision _and_ grf_match
|
|
||||||
bool use_password; ///< Is this server passworded?
|
|
||||||
byte game_info_version; ///< Version of the game info
|
|
||||||
byte server_lang; ///< Language of the server (we should make a nice table for this)
|
|
||||||
byte clients_max; ///< Max clients allowed on server
|
|
||||||
byte companies_on; ///< How many started companies do we have
|
|
||||||
byte companies_max; ///< Max companies allowed on server
|
|
||||||
byte spectators_on; ///< How many spectators do we have?
|
|
||||||
byte spectators_max; ///< Max spectators allowed on server
|
|
||||||
byte map_set; ///< Graphical set
|
|
||||||
};
|
|
||||||
|
|
||||||
const char * GetNetworkRevisionString();
|
|
||||||
|
|
||||||
#endif /* NETWORK_CORE_GAME_H */
|
|
||||||
@@ -1,185 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @file splash.cpp Splash screen support for OSX. */
|
|
||||||
|
|
||||||
#include "../../stdafx.h"
|
|
||||||
#include "../../openttd.h"
|
|
||||||
#include "../../debug.h"
|
|
||||||
#include "../../gfx_func.h"
|
|
||||||
#include "../../fileio_func.h"
|
|
||||||
#include "../../blitter/factory.hpp"
|
|
||||||
#include "../../core/mem_func.hpp"
|
|
||||||
|
|
||||||
#include "splash.h"
|
|
||||||
|
|
||||||
#ifdef WITH_PNG
|
|
||||||
|
|
||||||
#include <png.h>
|
|
||||||
|
|
||||||
#include "../../safeguards.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle pnglib error.
|
|
||||||
*
|
|
||||||
* @param png_ptr Pointer to png struct.
|
|
||||||
* @param message Error message text.
|
|
||||||
*/
|
|
||||||
static void PNGAPI png_my_error(png_structp png_ptr, png_const_charp message)
|
|
||||||
{
|
|
||||||
DEBUG(misc, 0, "[libpng] error: %s - %s", message, (char *)png_get_error_ptr(png_ptr));
|
|
||||||
longjmp(png_jmpbuf(png_ptr), 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle warning in pnglib.
|
|
||||||
*
|
|
||||||
* @param png_ptr Pointer to png struct.
|
|
||||||
* @param message Warning message text.
|
|
||||||
*/
|
|
||||||
static void PNGAPI png_my_warning(png_structp png_ptr, png_const_charp message)
|
|
||||||
{
|
|
||||||
DEBUG(misc, 1, "[libpng] warning: %s - %s", message, (char *)png_get_error_ptr(png_ptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display a splash image shown on startup (WITH_PNG).
|
|
||||||
*/
|
|
||||||
void DisplaySplashImage()
|
|
||||||
{
|
|
||||||
FILE *f = FioFOpenFile(SPLASH_IMAGE_FILE, "r", BASESET_DIR);
|
|
||||||
if (f == nullptr) return;
|
|
||||||
|
|
||||||
png_byte header[8];
|
|
||||||
fread(header, sizeof(png_byte), 8, f);
|
|
||||||
if (png_sig_cmp(header, 0, 8) != 0) {
|
|
||||||
fclose(f);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) nullptr, png_my_error, png_my_warning);
|
|
||||||
|
|
||||||
if (png_ptr == nullptr) {
|
|
||||||
fclose(f);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_infop info_ptr = png_create_info_struct(png_ptr);
|
|
||||||
if (info_ptr == nullptr) {
|
|
||||||
png_destroy_read_struct(&png_ptr, (png_infopp)nullptr, (png_infopp)nullptr);
|
|
||||||
fclose(f);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_infop end_info = png_create_info_struct(png_ptr);
|
|
||||||
if (end_info == nullptr) {
|
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)nullptr);
|
|
||||||
fclose(f);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
|
||||||
fclose(f);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_init_io(png_ptr, f);
|
|
||||||
png_set_sig_bytes(png_ptr, 8);
|
|
||||||
|
|
||||||
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, nullptr);
|
|
||||||
|
|
||||||
uint width = png_get_image_width(png_ptr, info_ptr);
|
|
||||||
uint height = png_get_image_height(png_ptr, info_ptr);
|
|
||||||
uint bit_depth = png_get_bit_depth(png_ptr, info_ptr);
|
|
||||||
uint color_type = png_get_color_type(png_ptr, info_ptr);
|
|
||||||
|
|
||||||
if (color_type != PNG_COLOR_TYPE_PALETTE || bit_depth != 8) {
|
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
|
||||||
fclose(f);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE)) {
|
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
|
||||||
fclose(f);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_colorp palette;
|
|
||||||
int num_palette;
|
|
||||||
png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
|
|
||||||
|
|
||||||
png_bytep *row_pointers = png_get_rows(png_ptr, info_ptr);
|
|
||||||
|
|
||||||
if (width > (uint) _screen.width) width = _screen.width;
|
|
||||||
if (height > (uint) _screen.height) height = _screen.height;
|
|
||||||
|
|
||||||
uint xoff = (_screen.width - width) / 2;
|
|
||||||
uint yoff = (_screen.height - height) / 2;
|
|
||||||
|
|
||||||
switch (BlitterFactory::GetCurrentBlitter()->GetScreenDepth()) {
|
|
||||||
case 8: {
|
|
||||||
uint8 *dst_ptr = (uint8 *)_screen.dst_ptr;
|
|
||||||
/* Initialize buffer */
|
|
||||||
MemSetT(dst_ptr, 0xff, _screen.pitch * _screen.height);
|
|
||||||
|
|
||||||
for (uint y = 0; y < height; y++) {
|
|
||||||
uint8 *src = row_pointers[y];
|
|
||||||
uint8 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff;
|
|
||||||
|
|
||||||
memcpy(dst, src, width);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < num_palette; i++) {
|
|
||||||
_cur_palette.palette[i].a = i == 0 ? 0 : 0xff;
|
|
||||||
_cur_palette.palette[i].r = palette[i].red;
|
|
||||||
_cur_palette.palette[i].g = palette[i].green;
|
|
||||||
_cur_palette.palette[i].b = palette[i].blue;
|
|
||||||
}
|
|
||||||
|
|
||||||
_cur_palette.palette[0xff].a = 0xff;
|
|
||||||
_cur_palette.palette[0xff].r = 0;
|
|
||||||
_cur_palette.palette[0xff].g = 0;
|
|
||||||
_cur_palette.palette[0xff].b = 0;
|
|
||||||
|
|
||||||
_cur_palette.first_dirty = 0;
|
|
||||||
_cur_palette.count_dirty = 256;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 32: {
|
|
||||||
uint32 *dst_ptr = (uint32 *)_screen.dst_ptr;
|
|
||||||
/* Initialize buffer */
|
|
||||||
MemSetT(dst_ptr, 0, _screen.pitch * _screen.height);
|
|
||||||
|
|
||||||
for (uint y = 0; y < height; y++) {
|
|
||||||
uint8 *src = row_pointers[y];
|
|
||||||
uint32 *dst = dst_ptr + (yoff + y) * _screen.pitch + xoff;
|
|
||||||
|
|
||||||
for (uint x = 0; x < width; x++) {
|
|
||||||
dst[x] = palette[src[x]].blue | (palette[src[x]].green << 8) | (palette[src[x]].red << 16) | 0xff000000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
|
|
||||||
fclose(f);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#else /* WITH_PNG */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Empty 'Display a splash image' routine (WITHOUT_PNG).
|
|
||||||
*/
|
|
||||||
void DisplaySplashImage() {}
|
|
||||||
|
|
||||||
#endif /* WITH_PNG */
|
|
||||||
@@ -1,17 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @file splash.h Functions to support splash screens for OSX. */
|
|
||||||
|
|
||||||
#ifndef SPLASH_H
|
|
||||||
#define SPLASH_H
|
|
||||||
|
|
||||||
#define SPLASH_IMAGE_FILE "splash.png"
|
|
||||||
|
|
||||||
void DisplaySplashImage();
|
|
||||||
|
|
||||||
#endif /* SPLASH_H */
|
|
||||||
@@ -1,80 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** @file pf_performance_timer.hpp Performance timer for pathfinders. */
|
|
||||||
|
|
||||||
#ifndef PF_PERFORMANCE_TIMER_HPP
|
|
||||||
#define PF_PERFORMANCE_TIMER_HPP
|
|
||||||
|
|
||||||
#include "../debug.h"
|
|
||||||
|
|
||||||
struct CPerformanceTimer
|
|
||||||
{
|
|
||||||
int64 m_start;
|
|
||||||
int64 m_acc;
|
|
||||||
|
|
||||||
CPerformanceTimer() : m_start(0), m_acc(0) {}
|
|
||||||
|
|
||||||
inline void Start()
|
|
||||||
{
|
|
||||||
m_start = QueryTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Stop()
|
|
||||||
{
|
|
||||||
m_acc += QueryTime() - m_start;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int Get(int64 coef)
|
|
||||||
{
|
|
||||||
return (int)(m_acc * coef / QueryFrequency());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int64 QueryTime()
|
|
||||||
{
|
|
||||||
return ottd_rdtsc();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int64 QueryFrequency()
|
|
||||||
{
|
|
||||||
return ((int64)2200 * 1000000);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CPerfStartReal
|
|
||||||
{
|
|
||||||
CPerformanceTimer *m_pperf;
|
|
||||||
|
|
||||||
inline CPerfStartReal(CPerformanceTimer& perf) : m_pperf(&perf)
|
|
||||||
{
|
|
||||||
if (m_pperf != nullptr) m_pperf->Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ~CPerfStartReal()
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Stop()
|
|
||||||
{
|
|
||||||
if (m_pperf != nullptr) {
|
|
||||||
m_pperf->Stop();
|
|
||||||
m_pperf = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct CPerfStartFake
|
|
||||||
{
|
|
||||||
inline CPerfStartFake(CPerformanceTimer& perf) {}
|
|
||||||
inline ~CPerfStartFake() {}
|
|
||||||
inline void Stop() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef CPerfStartFake CPerfStart;
|
|
||||||
|
|
||||||
#endif /* PF_PERFORMANCE_TIMER_HPP */
|
|
||||||
@@ -1,19 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* THIS FILE IS AUTO-GENERATED; PLEASE DO NOT ALTER MANUALLY */
|
|
||||||
|
|
||||||
#include "../script_priorityqueue.hpp"
|
|
||||||
|
|
||||||
namespace SQConvert {
|
|
||||||
/* Allow ScriptPriorityQueue to be used as Squirrel parameter */
|
|
||||||
template <> inline ScriptPriorityQueue *GetParam(ForceType<ScriptPriorityQueue *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptPriorityQueue *)instance; }
|
|
||||||
template <> inline ScriptPriorityQueue &GetParam(ForceType<ScriptPriorityQueue &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptPriorityQueue *)instance; }
|
|
||||||
template <> inline const ScriptPriorityQueue *GetParam(ForceType<const ScriptPriorityQueue *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return (ScriptPriorityQueue *)instance; }
|
|
||||||
template <> inline const ScriptPriorityQueue &GetParam(ForceType<const ScriptPriorityQueue &>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return *(ScriptPriorityQueue *)instance; }
|
|
||||||
template <> inline int Return<ScriptPriorityQueue *>(HSQUIRRELVM vm, ScriptPriorityQueue *res) { if (res == nullptr) { sq_pushnull(vm); return 1; } res->AddRef(); Squirrel::CreateClassInstanceVM(vm, "PriorityQueue", res, nullptr, DefSQDestructorCallback<ScriptPriorityQueue>, true); return 1; }
|
|
||||||
} // namespace SQConvert
|
|
||||||
@@ -1,143 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
;
|
|
||||||
|
|
||||||
[pre-amble]
|
|
||||||
static bool CheckInterval(int32 p1);
|
|
||||||
static bool InvalidateDetailsWindow(int32 p1);
|
|
||||||
static bool UpdateIntervalTrains(int32 p1);
|
|
||||||
static bool UpdateIntervalRoadVeh(int32 p1);
|
|
||||||
static bool UpdateIntervalShips(int32 p1);
|
|
||||||
static bool UpdateIntervalAircraft(int32 p1);
|
|
||||||
|
|
||||||
static const SettingDesc _company_settings[] = {
|
|
||||||
[post-amble]
|
|
||||||
};
|
|
||||||
[templates]
|
|
||||||
SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDT_END = SDT_END()
|
|
||||||
|
|
||||||
[validation]
|
|
||||||
SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size");
|
|
||||||
|
|
||||||
[defaults]
|
|
||||||
flags = 0
|
|
||||||
guiflags = SGF_PER_COMPANY
|
|
||||||
interval = 0
|
|
||||||
str = STR_NULL
|
|
||||||
strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT
|
|
||||||
strval = STR_NULL
|
|
||||||
proc = nullptr
|
|
||||||
load = nullptr
|
|
||||||
from = SL_MIN_VERSION
|
|
||||||
to = SL_MAX_VERSION
|
|
||||||
cat = SC_ADVANCED
|
|
||||||
extra = 0
|
|
||||||
startup = false
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[SDT_BOOL]
|
|
||||||
base = CompanySettings
|
|
||||||
var = engine_renew
|
|
||||||
def = true
|
|
||||||
str = STR_CONFIG_SETTING_AUTORENEW_VEHICLE
|
|
||||||
strhelp = STR_CONFIG_SETTING_AUTORENEW_VEHICLE_HELPTEXT
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDT_VAR]
|
|
||||||
base = CompanySettings
|
|
||||||
var = engine_renew_months
|
|
||||||
type = SLE_INT16
|
|
||||||
guiflags = SGF_PER_COMPANY | SGF_DISPLAY_ABS
|
|
||||||
def = 6
|
|
||||||
min = -12
|
|
||||||
max = 12
|
|
||||||
str = STR_CONFIG_SETTING_AUTORENEW_MONTHS
|
|
||||||
strhelp = STR_CONFIG_SETTING_AUTORENEW_MONTHS_HELPTEXT
|
|
||||||
strval = STR_CONFIG_SETTING_AUTORENEW_MONTHS_VALUE_BEFORE
|
|
||||||
|
|
||||||
[SDT_VAR]
|
|
||||||
base = CompanySettings
|
|
||||||
var = engine_renew_money
|
|
||||||
type = SLE_UINT
|
|
||||||
guiflags = SGF_PER_COMPANY | SGF_CURRENCY
|
|
||||||
def = 100000
|
|
||||||
min = 0
|
|
||||||
max = 2000000
|
|
||||||
str = STR_CONFIG_SETTING_AUTORENEW_MONEY
|
|
||||||
strhelp = STR_CONFIG_SETTING_AUTORENEW_MONEY_HELPTEXT
|
|
||||||
strval = STR_JUST_CURRENCY_LONG
|
|
||||||
|
|
||||||
[SDT_BOOL]
|
|
||||||
base = CompanySettings
|
|
||||||
var = renew_keep_length
|
|
||||||
def = false
|
|
||||||
|
|
||||||
[SDT_BOOL]
|
|
||||||
base = CompanySettings
|
|
||||||
var = vehicle.servint_ispercent
|
|
||||||
def = false
|
|
||||||
str = STR_CONFIG_SETTING_SERVINT_ISPERCENT
|
|
||||||
strhelp = STR_CONFIG_SETTING_SERVINT_ISPERCENT_HELPTEXT
|
|
||||||
proc = CheckInterval
|
|
||||||
|
|
||||||
[SDT_VAR]
|
|
||||||
base = CompanySettings
|
|
||||||
var = vehicle.servint_trains
|
|
||||||
type = SLE_UINT16
|
|
||||||
guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED
|
|
||||||
def = 150
|
|
||||||
min = 5
|
|
||||||
max = 800
|
|
||||||
str = STR_CONFIG_SETTING_SERVINT_TRAINS
|
|
||||||
strhelp = STR_CONFIG_SETTING_SERVINT_TRAINS_HELPTEXT
|
|
||||||
strval = STR_CONFIG_SETTING_SERVINT_VALUE
|
|
||||||
proc = UpdateIntervalTrains
|
|
||||||
|
|
||||||
[SDT_VAR]
|
|
||||||
base = CompanySettings
|
|
||||||
var = vehicle.servint_roadveh
|
|
||||||
type = SLE_UINT16
|
|
||||||
guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED
|
|
||||||
def = 150
|
|
||||||
min = 5
|
|
||||||
max = 800
|
|
||||||
str = STR_CONFIG_SETTING_SERVINT_ROAD_VEHICLES
|
|
||||||
strhelp = STR_CONFIG_SETTING_SERVINT_ROAD_VEHICLES_HELPTEXT
|
|
||||||
strval = STR_CONFIG_SETTING_SERVINT_VALUE
|
|
||||||
proc = UpdateIntervalRoadVeh
|
|
||||||
|
|
||||||
[SDT_VAR]
|
|
||||||
base = CompanySettings
|
|
||||||
var = vehicle.servint_ships
|
|
||||||
type = SLE_UINT16
|
|
||||||
guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED
|
|
||||||
def = 360
|
|
||||||
min = 5
|
|
||||||
max = 800
|
|
||||||
str = STR_CONFIG_SETTING_SERVINT_SHIPS
|
|
||||||
strhelp = STR_CONFIG_SETTING_SERVINT_SHIPS_HELPTEXT
|
|
||||||
strval = STR_CONFIG_SETTING_SERVINT_VALUE
|
|
||||||
proc = UpdateIntervalShips
|
|
||||||
|
|
||||||
[SDT_VAR]
|
|
||||||
base = CompanySettings
|
|
||||||
var = vehicle.servint_aircraft
|
|
||||||
type = SLE_UINT16
|
|
||||||
guiflags = SGF_PER_COMPANY | SGF_0ISDISABLED
|
|
||||||
def = 100
|
|
||||||
min = 5
|
|
||||||
max = 800
|
|
||||||
str = STR_CONFIG_SETTING_SERVINT_AIRCRAFT
|
|
||||||
strhelp = STR_CONFIG_SETTING_SERVINT_AIRCRAFT_HELPTEXT
|
|
||||||
strval = STR_CONFIG_SETTING_SERVINT_VALUE
|
|
||||||
proc = UpdateIntervalAircraft
|
|
||||||
|
|
||||||
[SDT_END]
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
@@ -1,72 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
;
|
|
||||||
|
|
||||||
[pre-amble]
|
|
||||||
static const SettingDesc _currency_settings[] = {
|
|
||||||
[post-amble]
|
|
||||||
};
|
|
||||||
[templates]
|
|
||||||
SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDT_CHR = SDT_CHR($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDT_STR = SDT_STR($base, $var, $type, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDT_END = SDT_END()
|
|
||||||
|
|
||||||
[validation]
|
|
||||||
SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size");
|
|
||||||
|
|
||||||
[defaults]
|
|
||||||
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
|
|
||||||
guiflags = SGF_NONE
|
|
||||||
interval = 0
|
|
||||||
str = STR_NULL
|
|
||||||
strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT
|
|
||||||
strval = STR_NULL
|
|
||||||
proc = nullptr
|
|
||||||
load = nullptr
|
|
||||||
from = SL_MIN_VERSION
|
|
||||||
to = SL_MAX_VERSION
|
|
||||||
cat = SC_ADVANCED
|
|
||||||
extra = 0
|
|
||||||
startup = false
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[SDT_VAR]
|
|
||||||
base = CurrencySpec
|
|
||||||
var = rate
|
|
||||||
type = SLE_UINT16
|
|
||||||
def = 1
|
|
||||||
min = 0
|
|
||||||
max = UINT16_MAX
|
|
||||||
|
|
||||||
[SDT_CHR]
|
|
||||||
base = CurrencySpec
|
|
||||||
var = separator
|
|
||||||
def = "".""
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDT_VAR]
|
|
||||||
base = CurrencySpec
|
|
||||||
var = to_euro
|
|
||||||
type = SLE_INT32
|
|
||||||
def = 0
|
|
||||||
min = MIN_YEAR
|
|
||||||
max = MAX_YEAR
|
|
||||||
|
|
||||||
[SDT_STR]
|
|
||||||
base = CurrencySpec
|
|
||||||
var = prefix
|
|
||||||
type = SLE_STRBQ
|
|
||||||
def = nullptr
|
|
||||||
|
|
||||||
[SDT_STR]
|
|
||||||
base = CurrencySpec
|
|
||||||
var = suffix
|
|
||||||
type = SLE_STRBQ
|
|
||||||
def = "" credits""
|
|
||||||
|
|
||||||
[SDT_END]
|
|
||||||
|
|
||||||
@@ -1,192 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
;
|
|
||||||
|
|
||||||
[pre-amble]
|
|
||||||
static const uint GAME_DIFFICULTY_NUM = 18;
|
|
||||||
static uint16 _old_diff_custom[GAME_DIFFICULTY_NUM];
|
|
||||||
uint8 _old_diff_level; ///< Old difficulty level from old savegames
|
|
||||||
uint8 _old_units; ///< Old units from old savegames
|
|
||||||
|
|
||||||
/* Most of these strings are used both for gameopt-backward compatibility
|
|
||||||
* and the settings tables. The rest is here for consistency. */
|
|
||||||
static const char *_locale_currencies = "GBP|USD|EUR|YEN|ATS|BEF|CHF|CZK|DEM|DKK|ESP|FIM|FRF|GRD|HUF|ISK|ITL|NLG|NOK|PLN|RON|RUR|SIT|SEK|YTL|SKK|BRL|EEK|custom";
|
|
||||||
static const char *_locale_units = "imperial|metric|si|gameunits";
|
|
||||||
static const char *_town_names = "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovak|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan";
|
|
||||||
static const char *_climates = "temperate|arctic|tropic|toyland";
|
|
||||||
static const char *_autosave_interval = "off|monthly|quarterly|half year|yearly";
|
|
||||||
static const char *_roadsides = "left|right";
|
|
||||||
static const char *_savegame_date = "long|short|iso";
|
|
||||||
static const char *_server_langs = "ANY|ENGLISH|GERMAN|FRENCH|BRAZILIAN|BULGARIAN|CHINESE|CZECH|DANISH|DUTCH|ESPERANTO|FINNISH|HUNGARIAN|ICELANDIC|ITALIAN|JAPANESE|KOREAN|LITHUANIAN|NORWEGIAN|POLISH|PORTUGUESE|ROMANIAN|RUSSIAN|SLOVAK|SLOVENIAN|SPANISH|SWEDISH|TURKISH|UKRAINIAN|AFRIKAANS|CROATIAN|CATALAN|ESTONIAN|GALICIAN|GREEK|LATVIAN";
|
|
||||||
static const char *_osk_activation = "disabled|double|single|immediately";
|
|
||||||
static const char *_settings_profiles = "easy|medium|hard";
|
|
||||||
static const char *_news_display = "off|summarized|full";
|
|
||||||
|
|
||||||
static const SettingDesc _gameopt_settings[] = {
|
|
||||||
/* In version 4 a new difficulty setting has been added to the difficulty settings,
|
|
||||||
* town attitude towards demolishing. Needs special handling because some dimwit thought
|
|
||||||
* it funny to have the GameDifficulty struct be an array while it is a struct of
|
|
||||||
* same-sized members
|
|
||||||
* XXX - To save file-space and since values are never bigger than about 10? only
|
|
||||||
* save the first 16 bits in the savegame. Question is why the values are still int32
|
|
||||||
* and why not byte for example?
|
|
||||||
* 'SLE_FILE_I16 | SLE_VAR_U16' in "diff_custom" is needed to get around SlArray() hack
|
|
||||||
* for savegames version 0 - though it is an array, it has to go through the byteswap process */
|
|
||||||
[post-amble]
|
|
||||||
};
|
|
||||||
[templates]
|
|
||||||
SDTG_GENERAL = SDTG_GENERAL($name, $sdt_cmd, $sle_cmd, $type, $flags, $guiflags, $var, $length, $def, $min, $max, $interval, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDT_NULL = SDT_NULL($length, $from, $to),
|
|
||||||
SDTC_OMANY = SDTC_OMANY( $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDT_OMANY = SDT_OMANY($base, $var, $type, $flags, $guiflags, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $load, $cat, $extra, $startup),
|
|
||||||
SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDT_END = SDT_END()
|
|
||||||
|
|
||||||
[validation]
|
|
||||||
SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size");
|
|
||||||
SDTG_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size");
|
|
||||||
SDTC_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size");
|
|
||||||
SDT_OMANY = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size");
|
|
||||||
SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size");
|
|
||||||
|
|
||||||
[defaults]
|
|
||||||
flags = 0
|
|
||||||
guiflags = SGF_NONE
|
|
||||||
interval = 0
|
|
||||||
str = STR_NULL
|
|
||||||
strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT
|
|
||||||
strval = STR_NULL
|
|
||||||
proc = nullptr
|
|
||||||
load = nullptr
|
|
||||||
from = SL_MIN_VERSION
|
|
||||||
to = SL_MAX_VERSION
|
|
||||||
cat = SC_ADVANCED
|
|
||||||
extra = 0
|
|
||||||
startup = false
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[SDTG_GENERAL]
|
|
||||||
name = ""diff_custom""
|
|
||||||
sdt_cmd = SDT_INTLIST
|
|
||||||
sle_cmd = SL_ARR
|
|
||||||
type = SLE_FILE_I16 | SLE_VAR_U16
|
|
||||||
flags = SLF_NOT_IN_CONFIG
|
|
||||||
var = _old_diff_custom
|
|
||||||
length = 17
|
|
||||||
def = 0
|
|
||||||
min = 0
|
|
||||||
max = 0
|
|
||||||
full = nullptr
|
|
||||||
to = SLV_4
|
|
||||||
|
|
||||||
[SDTG_GENERAL]
|
|
||||||
name = ""diff_custom""
|
|
||||||
sdt_cmd = SDT_INTLIST
|
|
||||||
sle_cmd = SL_ARR
|
|
||||||
type = SLE_UINT16
|
|
||||||
flags = SLF_NOT_IN_CONFIG
|
|
||||||
var = _old_diff_custom
|
|
||||||
length = 18
|
|
||||||
def = 0
|
|
||||||
min = 0
|
|
||||||
max = 0
|
|
||||||
full = nullptr
|
|
||||||
from = SLV_4
|
|
||||||
|
|
||||||
##
|
|
||||||
[SDTG_VAR]
|
|
||||||
name = ""diff_level""
|
|
||||||
var = _old_diff_level
|
|
||||||
type = SLE_UINT8
|
|
||||||
flags = SLF_NOT_IN_CONFIG
|
|
||||||
def = SP_CUSTOM
|
|
||||||
min = SP_EASY
|
|
||||||
max = SP_CUSTOM
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDT_OMANY]
|
|
||||||
base = GameSettings
|
|
||||||
var = locale.currency
|
|
||||||
type = SLE_UINT8
|
|
||||||
flags = SLF_NO_NETWORK_SYNC
|
|
||||||
def = 0
|
|
||||||
max = CURRENCY_END - 1
|
|
||||||
full = _locale_currencies
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_OMANY]
|
|
||||||
name = ""units""
|
|
||||||
var = _old_units
|
|
||||||
type = SLE_UINT8
|
|
||||||
flags = SLF_NOT_IN_CONFIG
|
|
||||||
def = 1
|
|
||||||
max = 2
|
|
||||||
full = _locale_units
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
# There are only 21 predefined town_name values (0-20), but you can have more with newgrf action F so allow
|
|
||||||
# these bigger values (21-255). Invalid values will fallback to english on use and (undefined string) in GUI.
|
|
||||||
[SDT_OMANY]
|
|
||||||
base = GameSettings
|
|
||||||
var = game_creation.town_name
|
|
||||||
type = SLE_UINT8
|
|
||||||
def = 0
|
|
||||||
max = 255
|
|
||||||
full = _town_names
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDT_OMANY]
|
|
||||||
base = GameSettings
|
|
||||||
var = game_creation.landscape
|
|
||||||
type = SLE_UINT8
|
|
||||||
def = 0
|
|
||||||
max = 3
|
|
||||||
full = _climates
|
|
||||||
load = ConvertLandscape
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDT_VAR]
|
|
||||||
base = GameSettings
|
|
||||||
var = game_creation.snow_line_height
|
|
||||||
type = SLE_UINT8
|
|
||||||
def = DEF_SNOWLINE_HEIGHT * TILE_HEIGHT
|
|
||||||
min = MIN_SNOWLINE_HEIGHT * TILE_HEIGHT
|
|
||||||
# "max" used to be MAX_SNOWLINE_HEIGHT * TILE_HEIGHT, but this would overflow the storage.
|
|
||||||
max = UINT8_MAX
|
|
||||||
to = SLV_22
|
|
||||||
|
|
||||||
[SDT_NULL]
|
|
||||||
length = 1
|
|
||||||
from = SLV_22
|
|
||||||
to = SLV_165
|
|
||||||
|
|
||||||
[SDT_NULL]
|
|
||||||
length = 1
|
|
||||||
to = SLV_23
|
|
||||||
|
|
||||||
[SDTC_OMANY]
|
|
||||||
var = gui.autosave
|
|
||||||
type = SLE_UINT8
|
|
||||||
from = SLV_23
|
|
||||||
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
|
|
||||||
def = 1
|
|
||||||
max = 4
|
|
||||||
full = _autosave_interval
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDT_OMANY]
|
|
||||||
base = GameSettings
|
|
||||||
var = vehicle.road_side
|
|
||||||
type = SLE_UINT8
|
|
||||||
def = 1
|
|
||||||
max = 1
|
|
||||||
full = _roadsides
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDT_END]
|
|
||||||
|
|
||||||
@@ -1,359 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
;
|
|
||||||
|
|
||||||
[pre-amble]
|
|
||||||
extern std::string _config_language_file;
|
|
||||||
|
|
||||||
static const char *_support8bppmodes = "no|system|hardware";
|
|
||||||
|
|
||||||
#ifdef WITH_COCOA
|
|
||||||
extern bool _allow_hidpi_window;
|
|
||||||
#endif
|
|
||||||
#ifndef WITH_COCOA
|
|
||||||
#define WITHOUT_COCOA
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static const SettingDescGlobVarList _misc_settings[] = {
|
|
||||||
[post-amble]
|
|
||||||
};
|
|
||||||
[templates]
|
|
||||||
SDTG_LIST = SDTG_LIST($name, $type, $length, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDTG_MMANY = SDTG_MMANY($name, $type, $flags, $guiflags, $var, $def, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDTG_OMANY = SDTG_OMANY($name, $type, $flags, $guiflags, $var, $def, $max, $full, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDTG_STR = SDTG_STR($name, $type, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDTG_SSTR = SDTG_SSTR($name, $type, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDTG_END = SDTG_END()
|
|
||||||
|
|
||||||
[validation]
|
|
||||||
SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size");
|
|
||||||
SDTG_OMANY = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size");
|
|
||||||
|
|
||||||
[defaults]
|
|
||||||
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
|
|
||||||
guiflags = SGF_NONE
|
|
||||||
interval = 0
|
|
||||||
str = STR_NULL
|
|
||||||
strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT
|
|
||||||
strval = STR_NULL
|
|
||||||
proc = nullptr
|
|
||||||
load = nullptr
|
|
||||||
from = SL_MIN_VERSION
|
|
||||||
to = SL_MAX_VERSION
|
|
||||||
cat = SC_ADVANCED
|
|
||||||
extra = 0
|
|
||||||
startup = true
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[SDTG_MMANY]
|
|
||||||
name = ""display_opt""
|
|
||||||
type = SLE_UINT8
|
|
||||||
var = _display_opt
|
|
||||||
def = (1 << DO_SHOW_TOWN_NAMES | 1 << DO_SHOW_STATION_NAMES | 1 << DO_SHOW_SIGNS | 1 << DO_FULL_ANIMATION | 1 << DO_FULL_DETAIL | 1 << DO_SHOW_WAYPOINT_NAMES | 1 << DO_SHOW_COMPETITOR_SIGNS)
|
|
||||||
full = ""SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|FULL_ANIMATION||FULL_DETAIL|WAYPOINTS|SHOW_COMPETITOR_SIGNS""
|
|
||||||
|
|
||||||
[SDTG_BOOL]
|
|
||||||
name = ""fullscreen""
|
|
||||||
var = _fullscreen
|
|
||||||
def = false
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_BOOL]
|
|
||||||
ifdef = WITH_COCOA
|
|
||||||
name = ""video_hw_accel""
|
|
||||||
var = _video_hw_accel
|
|
||||||
def = false
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_BOOL]
|
|
||||||
ifdef = WITHOUT_COCOA
|
|
||||||
name = ""video_hw_accel""
|
|
||||||
var = _video_hw_accel
|
|
||||||
def = true
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_BOOL]
|
|
||||||
name = ""video_vsync""
|
|
||||||
var = _video_vsync
|
|
||||||
def = false
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_OMANY]
|
|
||||||
name = ""support8bpp""
|
|
||||||
type = SLE_UINT8
|
|
||||||
var = _support8bpp
|
|
||||||
def = 0
|
|
||||||
max = 2
|
|
||||||
full = _support8bppmodes
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_SSTR]
|
|
||||||
name = ""graphicsset""
|
|
||||||
type = SLE_STRQ
|
|
||||||
var = BaseGraphics::ini_set
|
|
||||||
def = nullptr
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_SSTR]
|
|
||||||
name = ""soundsset""
|
|
||||||
type = SLE_STRQ
|
|
||||||
var = BaseSounds::ini_set
|
|
||||||
def = nullptr
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_SSTR]
|
|
||||||
name = ""musicset""
|
|
||||||
type = SLE_STRQ
|
|
||||||
var = BaseMusic::ini_set
|
|
||||||
def = nullptr
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_SSTR]
|
|
||||||
name = ""videodriver""
|
|
||||||
type = SLE_STRQ
|
|
||||||
var = _ini_videodriver
|
|
||||||
def = nullptr
|
|
||||||
cat = SC_EXPERT
|
|
||||||
|
|
||||||
[SDTG_SSTR]
|
|
||||||
name = ""musicdriver""
|
|
||||||
type = SLE_STRQ
|
|
||||||
var = _ini_musicdriver
|
|
||||||
def = nullptr
|
|
||||||
cat = SC_EXPERT
|
|
||||||
|
|
||||||
[SDTG_SSTR]
|
|
||||||
name = ""sounddriver""
|
|
||||||
type = SLE_STRQ
|
|
||||||
var = _ini_sounddriver
|
|
||||||
def = nullptr
|
|
||||||
cat = SC_EXPERT
|
|
||||||
|
|
||||||
[SDTG_SSTR]
|
|
||||||
name = ""blitter""
|
|
||||||
type = SLE_STRQ
|
|
||||||
var = _ini_blitter
|
|
||||||
def = nullptr
|
|
||||||
|
|
||||||
[SDTG_SSTR]
|
|
||||||
name = ""language""
|
|
||||||
type = SLE_STR
|
|
||||||
var = _config_language_file
|
|
||||||
def = nullptr
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
; workaround for implicit lengthof() in SDTG_LIST
|
|
||||||
[SDTG_LIST]
|
|
||||||
name = ""resolution""
|
|
||||||
type = SLE_INT
|
|
||||||
length = 2
|
|
||||||
var = _cur_resolution
|
|
||||||
def = ""0,0""
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_STR]
|
|
||||||
name = ""screenshot_format""
|
|
||||||
type = SLE_STRB
|
|
||||||
var = _screenshot_format_name
|
|
||||||
def = nullptr
|
|
||||||
cat = SC_EXPERT
|
|
||||||
|
|
||||||
[SDTG_STR]
|
|
||||||
name = ""savegame_format""
|
|
||||||
type = SLE_STRB
|
|
||||||
var = _savegame_format
|
|
||||||
def = nullptr
|
|
||||||
cat = SC_EXPERT
|
|
||||||
|
|
||||||
[SDTG_BOOL]
|
|
||||||
name = ""rightclick_emulate""
|
|
||||||
var = _rightclick_emulate
|
|
||||||
def = false
|
|
||||||
|
|
||||||
[SDTG_STR]
|
|
||||||
ifdef = HAS_TRUETYPE_FONT
|
|
||||||
name = ""small_font""
|
|
||||||
type = SLE_STRB
|
|
||||||
var = _freetype.small.font
|
|
||||||
def = nullptr
|
|
||||||
|
|
||||||
[SDTG_STR]
|
|
||||||
ifdef = HAS_TRUETYPE_FONT
|
|
||||||
name = ""medium_font""
|
|
||||||
type = SLE_STRB
|
|
||||||
var = _freetype.medium.font
|
|
||||||
def = nullptr
|
|
||||||
|
|
||||||
[SDTG_STR]
|
|
||||||
ifdef = HAS_TRUETYPE_FONT
|
|
||||||
name = ""large_font""
|
|
||||||
type = SLE_STRB
|
|
||||||
var = _freetype.large.font
|
|
||||||
def = nullptr
|
|
||||||
|
|
||||||
[SDTG_STR]
|
|
||||||
ifdef = HAS_TRUETYPE_FONT
|
|
||||||
name = ""mono_font""
|
|
||||||
type = SLE_STRB
|
|
||||||
var = _freetype.mono.font
|
|
||||||
def = nullptr
|
|
||||||
|
|
||||||
[SDTG_VAR]
|
|
||||||
ifdef = HAS_TRUETYPE_FONT
|
|
||||||
name = ""small_size""
|
|
||||||
type = SLE_UINT
|
|
||||||
var = _freetype.small.size
|
|
||||||
def = 0
|
|
||||||
min = 0
|
|
||||||
max = 72
|
|
||||||
|
|
||||||
[SDTG_VAR]
|
|
||||||
ifdef = HAS_TRUETYPE_FONT
|
|
||||||
name = ""medium_size""
|
|
||||||
type = SLE_UINT
|
|
||||||
var = _freetype.medium.size
|
|
||||||
def = 0
|
|
||||||
min = 0
|
|
||||||
max = 72
|
|
||||||
|
|
||||||
[SDTG_VAR]
|
|
||||||
ifdef = HAS_TRUETYPE_FONT
|
|
||||||
name = ""large_size""
|
|
||||||
type = SLE_UINT
|
|
||||||
var = _freetype.large.size
|
|
||||||
def = 0
|
|
||||||
min = 0
|
|
||||||
max = 72
|
|
||||||
|
|
||||||
[SDTG_VAR]
|
|
||||||
ifdef = HAS_TRUETYPE_FONT
|
|
||||||
name = ""mono_size""
|
|
||||||
type = SLE_UINT
|
|
||||||
var = _freetype.mono.size
|
|
||||||
def = 0
|
|
||||||
min = 0
|
|
||||||
max = 72
|
|
||||||
|
|
||||||
[SDTG_BOOL]
|
|
||||||
ifdef = HAS_TRUETYPE_FONT
|
|
||||||
name = ""small_aa""
|
|
||||||
var = _freetype.small.aa
|
|
||||||
def = false
|
|
||||||
|
|
||||||
[SDTG_BOOL]
|
|
||||||
ifdef = HAS_TRUETYPE_FONT
|
|
||||||
name = ""medium_aa""
|
|
||||||
var = _freetype.medium.aa
|
|
||||||
def = false
|
|
||||||
|
|
||||||
[SDTG_BOOL]
|
|
||||||
ifdef = HAS_TRUETYPE_FONT
|
|
||||||
name = ""large_aa""
|
|
||||||
var = _freetype.large.aa
|
|
||||||
def = false
|
|
||||||
|
|
||||||
[SDTG_BOOL]
|
|
||||||
ifdef = HAS_TRUETYPE_FONT
|
|
||||||
name = ""mono_aa""
|
|
||||||
var = _freetype.mono.aa
|
|
||||||
def = false
|
|
||||||
|
|
||||||
[SDTG_VAR]
|
|
||||||
name = ""sprite_cache_size_px""
|
|
||||||
type = SLE_UINT
|
|
||||||
var = _sprite_cache_size
|
|
||||||
def = 128
|
|
||||||
min = 1
|
|
||||||
max = 512
|
|
||||||
cat = SC_EXPERT
|
|
||||||
|
|
||||||
[SDTG_VAR]
|
|
||||||
name = ""player_face""
|
|
||||||
type = SLE_UINT32
|
|
||||||
var = _company_manager_face
|
|
||||||
def = 0
|
|
||||||
min = 0
|
|
||||||
max = 0xFFFFFFFF
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_VAR]
|
|
||||||
name = ""transparency_options""
|
|
||||||
type = SLE_UINT
|
|
||||||
var = _transparency_opt
|
|
||||||
def = 0
|
|
||||||
min = 0
|
|
||||||
max = 0x1FF
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_VAR]
|
|
||||||
name = ""transparency_locks""
|
|
||||||
type = SLE_UINT
|
|
||||||
var = _transparency_lock
|
|
||||||
def = 0
|
|
||||||
min = 0
|
|
||||||
max = 0x1FF
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_VAR]
|
|
||||||
name = ""invisibility_options""
|
|
||||||
type = SLE_UINT
|
|
||||||
var = _invisibility_opt
|
|
||||||
def = 0
|
|
||||||
min = 0
|
|
||||||
max = 0xFF
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_STR]
|
|
||||||
name = ""keyboard""
|
|
||||||
type = SLE_STRB
|
|
||||||
var = _keyboard_opt[0]
|
|
||||||
def = nullptr
|
|
||||||
cat = SC_EXPERT
|
|
||||||
|
|
||||||
[SDTG_STR]
|
|
||||||
name = ""keyboard_caps""
|
|
||||||
type = SLE_STRB
|
|
||||||
var = _keyboard_opt[1]
|
|
||||||
def = nullptr
|
|
||||||
cat = SC_EXPERT
|
|
||||||
|
|
||||||
[SDTG_VAR]
|
|
||||||
name = ""last_newgrf_count""
|
|
||||||
type = SLE_UINT32
|
|
||||||
var = _settings_client.gui.last_newgrf_count
|
|
||||||
def = 100
|
|
||||||
min = 0
|
|
||||||
max = UINT32_MAX
|
|
||||||
cat = SC_EXPERT
|
|
||||||
|
|
||||||
[SDTG_VAR]
|
|
||||||
name = ""gui_zoom""
|
|
||||||
type = SLE_INT8
|
|
||||||
var = _gui_zoom_cfg
|
|
||||||
def = ZOOM_LVL_CFG_AUTO
|
|
||||||
min = ZOOM_LVL_CFG_AUTO
|
|
||||||
max = ZOOM_LVL_OUT_4X
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_VAR]
|
|
||||||
name = ""font_zoom""
|
|
||||||
type = SLE_INT8
|
|
||||||
var = _font_zoom_cfg
|
|
||||||
def = ZOOM_LVL_CFG_AUTO
|
|
||||||
min = ZOOM_LVL_CFG_AUTO
|
|
||||||
max = ZOOM_LVL_OUT_4X
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_BOOL]
|
|
||||||
ifdef = WITH_COCOA
|
|
||||||
name = ""allow_hidpi""
|
|
||||||
var = _allow_hidpi_window
|
|
||||||
def = true
|
|
||||||
|
|
||||||
[SDTG_END]
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,47 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
;
|
|
||||||
|
|
||||||
[pre-amble]
|
|
||||||
/* win32_v.cpp only settings */
|
|
||||||
#if defined(_WIN32) && !defined(DEDICATED)
|
|
||||||
extern bool _window_maximize;
|
|
||||||
|
|
||||||
static const SettingDescGlobVarList _win32_settings[] = {
|
|
||||||
[post-amble]
|
|
||||||
};
|
|
||||||
#endif /* _WIN32 */
|
|
||||||
[templates]
|
|
||||||
SDTG_BOOL = SDTG_BOOL($name, $flags, $guiflags, $var, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDTG_VAR = SDTG_VAR($name, $type, $flags, $guiflags, $var, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDTG_END = SDTG_END()
|
|
||||||
|
|
||||||
[validation]
|
|
||||||
SDTG_VAR = static_assert($max <= MAX_$type, "Maximum value for $var exceeds storage size");
|
|
||||||
|
|
||||||
[defaults]
|
|
||||||
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
|
|
||||||
guiflags = SGF_NONE
|
|
||||||
interval = 0
|
|
||||||
str = STR_NULL
|
|
||||||
strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT
|
|
||||||
strval = STR_NULL
|
|
||||||
proc = nullptr
|
|
||||||
load = nullptr
|
|
||||||
from = SL_MIN_VERSION
|
|
||||||
to = SL_MAX_VERSION
|
|
||||||
cat = SC_ADVANCED
|
|
||||||
extra = 0
|
|
||||||
startup = true
|
|
||||||
|
|
||||||
|
|
||||||
[SDTG_BOOL]
|
|
||||||
name = ""window_maximize""
|
|
||||||
var = _window_maximize
|
|
||||||
def = false
|
|
||||||
cat = SC_BASIC
|
|
||||||
|
|
||||||
[SDTG_END]
|
|
||||||
|
|
||||||
@@ -1,58 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
;
|
|
||||||
|
|
||||||
[pre-amble]
|
|
||||||
|
|
||||||
static const SettingDesc _window_settings[] = {
|
|
||||||
[post-amble]
|
|
||||||
};
|
|
||||||
[templates]
|
|
||||||
SDT_BOOL = SDT_BOOL($base, $var, $flags, $guiflags, $def, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDT_VAR = SDT_VAR($base, $var, $type, $flags, $guiflags, $def, $min, $max, $interval, $str, $strhelp, $strval, $proc, $from, $to, $cat, $extra, $startup),
|
|
||||||
SDT_END = SDT_END()
|
|
||||||
|
|
||||||
[validation]
|
|
||||||
SDT_VAR = static_assert($max <= MAX_$type, "Maximum value for $base.$var exceeds storage size");
|
|
||||||
|
|
||||||
[defaults]
|
|
||||||
base = WindowDesc
|
|
||||||
flags = SLF_NOT_IN_SAVE | SLF_NO_NETWORK_SYNC
|
|
||||||
guiflags = SGF_NONE
|
|
||||||
interval = 0
|
|
||||||
str = STR_NULL
|
|
||||||
strhelp = STR_CONFIG_SETTING_NO_EXPLANATION_AVAILABLE_HELPTEXT
|
|
||||||
strval = STR_NULL
|
|
||||||
proc = nullptr
|
|
||||||
load = nullptr
|
|
||||||
from = SL_MIN_VERSION
|
|
||||||
to = SL_MAX_VERSION
|
|
||||||
cat = SC_ADVANCED
|
|
||||||
extra = 0
|
|
||||||
startup = false
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[SDT_BOOL]
|
|
||||||
var = pref_sticky
|
|
||||||
def = false
|
|
||||||
|
|
||||||
[SDT_VAR]
|
|
||||||
var = pref_width
|
|
||||||
type = SLE_INT16
|
|
||||||
def = 0
|
|
||||||
min = 0
|
|
||||||
max = 32000
|
|
||||||
|
|
||||||
[SDT_VAR]
|
|
||||||
var = pref_height
|
|
||||||
type = SLE_INT16
|
|
||||||
def = 0
|
|
||||||
min = 0
|
|
||||||
max = 32000
|
|
||||||
|
|
||||||
[SDT_END]
|
|
||||||
|
|
||||||
};
|
|
||||||
@@ -1,714 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* Cocoa video driver *
|
|
||||||
* Known things left to do: *
|
|
||||||
* Nothing at the moment. *
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
#ifdef WITH_COCOA
|
|
||||||
|
|
||||||
#include "../../stdafx.h"
|
|
||||||
|
|
||||||
#define Rect OTTDRect
|
|
||||||
#define Point OTTDPoint
|
|
||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
#undef Rect
|
|
||||||
#undef Point
|
|
||||||
|
|
||||||
#include "../../openttd.h"
|
|
||||||
#include "../../debug.h"
|
|
||||||
#include "../../os/macosx/splash.h"
|
|
||||||
#include "../../settings_type.h"
|
|
||||||
#include "../../core/geometry_type.hpp"
|
|
||||||
#include "cocoa_v.h"
|
|
||||||
#include "cocoa_keys.h"
|
|
||||||
#include "../../blitter/factory.hpp"
|
|
||||||
#include "../../gfx_func.h"
|
|
||||||
#include "../../network/network.h"
|
|
||||||
#include "../../core/random_func.hpp"
|
|
||||||
#include "../../core/math_func.hpp"
|
|
||||||
#include "../../texteff.hpp"
|
|
||||||
#include "../../window_func.h"
|
|
||||||
#include "../../thread.h"
|
|
||||||
|
|
||||||
#import <sys/time.h> /* gettimeofday */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Important notice regarding all modifications!!!!!!!
|
|
||||||
* There are certain limitations because the file is objective C++.
|
|
||||||
* gdb has limitations.
|
|
||||||
* C++ and objective C code can't be joined in all cases (classes stuff).
|
|
||||||
* Read http://developer.apple.com/releasenotes/Cocoa/Objective-C++.html for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* Right Mouse Button Emulation enum */
|
|
||||||
enum RightMouseButtonEmulationState {
|
|
||||||
RMBE_COMMAND,
|
|
||||||
RMBE_CONTROL,
|
|
||||||
RMBE_OFF,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static unsigned int _current_mods;
|
|
||||||
static bool _tab_is_down;
|
|
||||||
static bool _emulating_right_button;
|
|
||||||
static float _current_magnification;
|
|
||||||
#ifdef _DEBUG
|
|
||||||
static uint32 _tEvent;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
static uint32 GetTick()
|
|
||||||
{
|
|
||||||
struct timeval tim;
|
|
||||||
|
|
||||||
gettimeofday(&tim, NULL);
|
|
||||||
return tim.tv_usec / 1000 + tim.tv_sec * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void QZ_WarpCursor(int x, int y)
|
|
||||||
{
|
|
||||||
assert(_cocoa_subdriver != NULL);
|
|
||||||
|
|
||||||
/* Only allow warping when in foreground */
|
|
||||||
if (![ NSApp isActive ]) return;
|
|
||||||
|
|
||||||
NSPoint p = NSMakePoint(x, y);
|
|
||||||
CGPoint cgp = _cocoa_subdriver->PrivateLocalToCG(&p);
|
|
||||||
|
|
||||||
/* Do the actual warp */
|
|
||||||
CGWarpMouseCursorPosition(cgp);
|
|
||||||
/* this is the magic call that fixes cursor "freezing" after warp */
|
|
||||||
CGAssociateMouseAndMouseCursorPosition(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void QZ_CheckPaletteAnim()
|
|
||||||
{
|
|
||||||
if (_cur_palette.count_dirty != 0) {
|
|
||||||
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
|
|
||||||
|
|
||||||
switch (blitter->UsePaletteAnimation()) {
|
|
||||||
case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND:
|
|
||||||
_cocoa_subdriver->UpdatePalette(_cur_palette.first_dirty, _cur_palette.count_dirty);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Blitter::PALETTE_ANIMATION_BLITTER:
|
|
||||||
blitter->PaletteAnimate(_cur_palette);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Blitter::PALETTE_ANIMATION_NONE:
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
NOT_REACHED();
|
|
||||||
}
|
|
||||||
_cur_palette.count_dirty = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct VkMapping {
|
|
||||||
unsigned short vk_from;
|
|
||||||
byte map_to;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define AS(x, z) {x, z}
|
|
||||||
|
|
||||||
static const VkMapping _vk_mapping[] = {
|
|
||||||
AS(QZ_BACKQUOTE, WKC_BACKQUOTE), // key left of '1'
|
|
||||||
AS(QZ_BACKQUOTE2, WKC_BACKQUOTE), // some keyboards have it on another scancode
|
|
||||||
|
|
||||||
/* Pageup stuff + up/down */
|
|
||||||
AS(QZ_PAGEUP, WKC_PAGEUP),
|
|
||||||
AS(QZ_PAGEDOWN, WKC_PAGEDOWN),
|
|
||||||
|
|
||||||
AS(QZ_UP, WKC_UP),
|
|
||||||
AS(QZ_DOWN, WKC_DOWN),
|
|
||||||
AS(QZ_LEFT, WKC_LEFT),
|
|
||||||
AS(QZ_RIGHT, WKC_RIGHT),
|
|
||||||
|
|
||||||
AS(QZ_HOME, WKC_HOME),
|
|
||||||
AS(QZ_END, WKC_END),
|
|
||||||
|
|
||||||
AS(QZ_INSERT, WKC_INSERT),
|
|
||||||
AS(QZ_DELETE, WKC_DELETE),
|
|
||||||
|
|
||||||
/* Letters. QZ_[a-z] is not in numerical order so we can't use AM(...) */
|
|
||||||
AS(QZ_a, 'A'),
|
|
||||||
AS(QZ_b, 'B'),
|
|
||||||
AS(QZ_c, 'C'),
|
|
||||||
AS(QZ_d, 'D'),
|
|
||||||
AS(QZ_e, 'E'),
|
|
||||||
AS(QZ_f, 'F'),
|
|
||||||
AS(QZ_g, 'G'),
|
|
||||||
AS(QZ_h, 'H'),
|
|
||||||
AS(QZ_i, 'I'),
|
|
||||||
AS(QZ_j, 'J'),
|
|
||||||
AS(QZ_k, 'K'),
|
|
||||||
AS(QZ_l, 'L'),
|
|
||||||
AS(QZ_m, 'M'),
|
|
||||||
AS(QZ_n, 'N'),
|
|
||||||
AS(QZ_o, 'O'),
|
|
||||||
AS(QZ_p, 'P'),
|
|
||||||
AS(QZ_q, 'Q'),
|
|
||||||
AS(QZ_r, 'R'),
|
|
||||||
AS(QZ_s, 'S'),
|
|
||||||
AS(QZ_t, 'T'),
|
|
||||||
AS(QZ_u, 'U'),
|
|
||||||
AS(QZ_v, 'V'),
|
|
||||||
AS(QZ_w, 'W'),
|
|
||||||
AS(QZ_x, 'X'),
|
|
||||||
AS(QZ_y, 'Y'),
|
|
||||||
AS(QZ_z, 'Z'),
|
|
||||||
/* Same thing for digits */
|
|
||||||
AS(QZ_0, '0'),
|
|
||||||
AS(QZ_1, '1'),
|
|
||||||
AS(QZ_2, '2'),
|
|
||||||
AS(QZ_3, '3'),
|
|
||||||
AS(QZ_4, '4'),
|
|
||||||
AS(QZ_5, '5'),
|
|
||||||
AS(QZ_6, '6'),
|
|
||||||
AS(QZ_7, '7'),
|
|
||||||
AS(QZ_8, '8'),
|
|
||||||
AS(QZ_9, '9'),
|
|
||||||
|
|
||||||
AS(QZ_ESCAPE, WKC_ESC),
|
|
||||||
AS(QZ_PAUSE, WKC_PAUSE),
|
|
||||||
AS(QZ_BACKSPACE, WKC_BACKSPACE),
|
|
||||||
|
|
||||||
AS(QZ_SPACE, WKC_SPACE),
|
|
||||||
AS(QZ_RETURN, WKC_RETURN),
|
|
||||||
AS(QZ_TAB, WKC_TAB),
|
|
||||||
|
|
||||||
/* Function keys */
|
|
||||||
AS(QZ_F1, WKC_F1),
|
|
||||||
AS(QZ_F2, WKC_F2),
|
|
||||||
AS(QZ_F3, WKC_F3),
|
|
||||||
AS(QZ_F4, WKC_F4),
|
|
||||||
AS(QZ_F5, WKC_F5),
|
|
||||||
AS(QZ_F6, WKC_F6),
|
|
||||||
AS(QZ_F7, WKC_F7),
|
|
||||||
AS(QZ_F8, WKC_F8),
|
|
||||||
AS(QZ_F9, WKC_F9),
|
|
||||||
AS(QZ_F10, WKC_F10),
|
|
||||||
AS(QZ_F11, WKC_F11),
|
|
||||||
AS(QZ_F12, WKC_F12),
|
|
||||||
|
|
||||||
/* Numeric part */
|
|
||||||
AS(QZ_KP0, '0'),
|
|
||||||
AS(QZ_KP1, '1'),
|
|
||||||
AS(QZ_KP2, '2'),
|
|
||||||
AS(QZ_KP3, '3'),
|
|
||||||
AS(QZ_KP4, '4'),
|
|
||||||
AS(QZ_KP5, '5'),
|
|
||||||
AS(QZ_KP6, '6'),
|
|
||||||
AS(QZ_KP7, '7'),
|
|
||||||
AS(QZ_KP8, '8'),
|
|
||||||
AS(QZ_KP9, '9'),
|
|
||||||
AS(QZ_KP_DIVIDE, WKC_NUM_DIV),
|
|
||||||
AS(QZ_KP_MULTIPLY, WKC_NUM_MUL),
|
|
||||||
AS(QZ_KP_MINUS, WKC_NUM_MINUS),
|
|
||||||
AS(QZ_KP_PLUS, WKC_NUM_PLUS),
|
|
||||||
AS(QZ_KP_ENTER, WKC_NUM_ENTER),
|
|
||||||
AS(QZ_KP_PERIOD, WKC_NUM_DECIMAL),
|
|
||||||
|
|
||||||
/* Other non-letter keys */
|
|
||||||
AS(QZ_SLASH, WKC_SLASH),
|
|
||||||
AS(QZ_SEMICOLON, WKC_SEMICOLON),
|
|
||||||
AS(QZ_EQUALS, WKC_EQUALS),
|
|
||||||
AS(QZ_LEFTBRACKET, WKC_L_BRACKET),
|
|
||||||
AS(QZ_BACKSLASH, WKC_BACKSLASH),
|
|
||||||
AS(QZ_RIGHTBRACKET, WKC_R_BRACKET),
|
|
||||||
|
|
||||||
AS(QZ_QUOTE, WKC_SINGLEQUOTE),
|
|
||||||
AS(QZ_COMMA, WKC_COMMA),
|
|
||||||
AS(QZ_MINUS, WKC_MINUS),
|
|
||||||
AS(QZ_PERIOD, WKC_PERIOD)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static uint32 QZ_MapKey(unsigned short sym)
|
|
||||||
{
|
|
||||||
uint32 key = 0;
|
|
||||||
|
|
||||||
for (const VkMapping *map = _vk_mapping; map != endof(_vk_mapping); ++map) {
|
|
||||||
if (sym == map->vk_from) {
|
|
||||||
key = map->map_to;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_current_mods & NSShiftKeyMask) key |= WKC_SHIFT;
|
|
||||||
if (_current_mods & NSControlKeyMask) key |= (_settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_CTRL : WKC_META);
|
|
||||||
if (_current_mods & NSAlternateKeyMask) key |= WKC_ALT;
|
|
||||||
if (_current_mods & NSCommandKeyMask) key |= (_settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? WKC_META : WKC_CTRL);
|
|
||||||
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool QZ_KeyEvent(unsigned short keycode, unsigned short unicode, BOOL down)
|
|
||||||
{
|
|
||||||
bool interpret_keys = true;
|
|
||||||
|
|
||||||
switch (keycode) {
|
|
||||||
case QZ_UP: SB(_dirkeys, 1, 1, down); break;
|
|
||||||
case QZ_DOWN: SB(_dirkeys, 3, 1, down); break;
|
|
||||||
case QZ_LEFT: SB(_dirkeys, 0, 1, down); break;
|
|
||||||
case QZ_RIGHT: SB(_dirkeys, 2, 1, down); break;
|
|
||||||
|
|
||||||
case QZ_TAB: _tab_is_down = down; break;
|
|
||||||
|
|
||||||
case QZ_RETURN:
|
|
||||||
case QZ_f:
|
|
||||||
if (down && (_current_mods & NSCommandKeyMask)) {
|
|
||||||
VideoDriver::GetInstance()->ToggleFullscreen(!_fullscreen);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QZ_v:
|
|
||||||
if (down && EditBoxInGlobalFocus() && (_current_mods & (NSCommandKeyMask | NSControlKeyMask))) {
|
|
||||||
HandleKeypress(WKC_CTRL | 'V', unicode);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case QZ_u:
|
|
||||||
if (down && EditBoxInGlobalFocus() && (_current_mods & (NSCommandKeyMask | NSControlKeyMask))) {
|
|
||||||
HandleKeypress(WKC_CTRL | 'U', unicode);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (down) {
|
|
||||||
uint32 pressed_key = QZ_MapKey(keycode);
|
|
||||||
|
|
||||||
static bool console = false;
|
|
||||||
|
|
||||||
/* The second backquote may have a character, which we don't want to interpret. */
|
|
||||||
if (pressed_key == WKC_BACKQUOTE && (console || unicode == 0)) {
|
|
||||||
if (!console) {
|
|
||||||
/* Backquote is a dead key, require a double press for hotkey behaviour (i.e. console). */
|
|
||||||
console = true;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
/* Second backquote, don't interpret as text input. */
|
|
||||||
interpret_keys = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console = false;
|
|
||||||
|
|
||||||
/* Don't handle normal characters if an edit box has the focus. */
|
|
||||||
if (!EditBoxInGlobalFocus() || IsInsideMM(pressed_key & ~WKC_SPECIAL_KEYS, WKC_F1, WKC_PAUSE + 1)) {
|
|
||||||
HandleKeypress(pressed_key, unicode);
|
|
||||||
}
|
|
||||||
DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), down, mapping: %x", keycode, unicode, pressed_key);
|
|
||||||
} else {
|
|
||||||
DEBUG(driver, 2, "cocoa_v: QZ_KeyEvent: %x (%x), up", keycode, unicode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return interpret_keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void QZ_DoUnsidedModifiers(unsigned int newMods)
|
|
||||||
{
|
|
||||||
const int mapping[] = { QZ_CAPSLOCK, QZ_LSHIFT, QZ_LCTRL, QZ_LALT, QZ_LMETA };
|
|
||||||
|
|
||||||
if (_current_mods == newMods) return;
|
|
||||||
|
|
||||||
/* Iterate through the bits, testing each against the current modifiers */
|
|
||||||
for (unsigned int i = 0, bit = NSAlphaShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
|
|
||||||
unsigned int currentMask, newMask;
|
|
||||||
|
|
||||||
currentMask = _current_mods & bit;
|
|
||||||
newMask = newMods & bit;
|
|
||||||
|
|
||||||
if (currentMask && currentMask != newMask) { // modifier up event
|
|
||||||
/* If this was Caps Lock, we need some additional voodoo to make SDL happy (is this needed in ottd?) */
|
|
||||||
if (bit == NSAlphaShiftKeyMask) QZ_KeyEvent(mapping[i], 0, YES);
|
|
||||||
QZ_KeyEvent(mapping[i], 0, NO);
|
|
||||||
} else if (newMask && currentMask != newMask) { // modifier down event
|
|
||||||
QZ_KeyEvent(mapping[i], 0, YES);
|
|
||||||
/* If this was Caps Lock, we need some additional voodoo to make SDL happy (is this needed in ottd?) */
|
|
||||||
if (bit == NSAlphaShiftKeyMask) QZ_KeyEvent(mapping[i], 0, NO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_current_mods = newMods;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void QZ_MouseMovedEvent(int x, int y)
|
|
||||||
{
|
|
||||||
if (_cursor.UpdateCursorPosition(x, y, false)) {
|
|
||||||
QZ_WarpCursor(_cursor.pos.x, _cursor.pos.y);
|
|
||||||
}
|
|
||||||
HandleMouseEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void QZ_MouseButtonEvent(int button, BOOL down)
|
|
||||||
{
|
|
||||||
switch (button) {
|
|
||||||
case 0:
|
|
||||||
if (down) {
|
|
||||||
_left_button_down = true;
|
|
||||||
} else {
|
|
||||||
_left_button_down = false;
|
|
||||||
_left_button_clicked = false;
|
|
||||||
}
|
|
||||||
HandleMouseEvents();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
if (down) {
|
|
||||||
_right_button_down = true;
|
|
||||||
_right_button_clicked = true;
|
|
||||||
} else {
|
|
||||||
_right_button_down = false;
|
|
||||||
}
|
|
||||||
HandleMouseEvents();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static bool QZ_PollEvent()
|
|
||||||
{
|
|
||||||
assert(_cocoa_subdriver != NULL);
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
uint32 et0 = GetTick();
|
|
||||||
#endif
|
|
||||||
NSEvent *event = [ NSApp nextEventMatchingMask:NSAnyEventMask
|
|
||||||
untilDate:[ NSDate distantPast ]
|
|
||||||
inMode:NSDefaultRunLoopMode dequeue:YES ];
|
|
||||||
#ifdef _DEBUG
|
|
||||||
_tEvent += GetTick() - et0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (event == nil) return false;
|
|
||||||
if (!_cocoa_subdriver->IsActive()) {
|
|
||||||
[ NSApp sendEvent:event ];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QZ_DoUnsidedModifiers( [ event modifierFlags ] );
|
|
||||||
|
|
||||||
NSString *chars;
|
|
||||||
NSPoint pt;
|
|
||||||
switch ([ event type ]) {
|
|
||||||
case NSMouseMoved:
|
|
||||||
case NSOtherMouseDragged:
|
|
||||||
case NSLeftMouseDragged:
|
|
||||||
pt = _cocoa_subdriver->GetMouseLocation(event);
|
|
||||||
if (!_cocoa_subdriver->MouseIsInsideView(&pt) && !_emulating_right_button) {
|
|
||||||
[ NSApp sendEvent:event ];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NSRightMouseDragged:
|
|
||||||
pt = _cocoa_subdriver->GetMouseLocation(event);
|
|
||||||
QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NSLeftMouseDown:
|
|
||||||
{
|
|
||||||
uint32 keymask = 0;
|
|
||||||
if (_settings_client.gui.right_mouse_btn_emulation == RMBE_COMMAND) keymask |= NSCommandKeyMask;
|
|
||||||
if (_settings_client.gui.right_mouse_btn_emulation == RMBE_CONTROL) keymask |= NSControlKeyMask;
|
|
||||||
|
|
||||||
pt = _cocoa_subdriver->GetMouseLocation(event);
|
|
||||||
|
|
||||||
if (!([ event modifierFlags ] & keymask) || !_cocoa_subdriver->MouseIsInsideView(&pt)) {
|
|
||||||
[ NSApp sendEvent:event ];
|
|
||||||
}
|
|
||||||
|
|
||||||
QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
|
|
||||||
|
|
||||||
/* Right mouse button emulation */
|
|
||||||
if ([ event modifierFlags ] & keymask) {
|
|
||||||
_emulating_right_button = true;
|
|
||||||
QZ_MouseButtonEvent(1, YES);
|
|
||||||
} else {
|
|
||||||
QZ_MouseButtonEvent(0, YES);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case NSLeftMouseUp:
|
|
||||||
[ NSApp sendEvent:event ];
|
|
||||||
|
|
||||||
pt = _cocoa_subdriver->GetMouseLocation(event);
|
|
||||||
|
|
||||||
QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
|
|
||||||
|
|
||||||
/* Right mouse button emulation */
|
|
||||||
if (_emulating_right_button) {
|
|
||||||
_emulating_right_button = false;
|
|
||||||
QZ_MouseButtonEvent(1, NO);
|
|
||||||
} else {
|
|
||||||
QZ_MouseButtonEvent(0, NO);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NSRightMouseDown:
|
|
||||||
pt = _cocoa_subdriver->GetMouseLocation(event);
|
|
||||||
if (!_cocoa_subdriver->MouseIsInsideView(&pt)) {
|
|
||||||
[ NSApp sendEvent:event ];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
|
|
||||||
QZ_MouseButtonEvent(1, YES);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NSRightMouseUp:
|
|
||||||
pt = _cocoa_subdriver->GetMouseLocation(event);
|
|
||||||
if (!_cocoa_subdriver->MouseIsInsideView(&pt)) {
|
|
||||||
[ NSApp sendEvent:event ];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
|
|
||||||
QZ_MouseButtonEvent(1, NO);
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* This is not needed since openttd currently only use two buttons */
|
|
||||||
case NSOtherMouseDown:
|
|
||||||
pt = QZ_GetMouseLocation(event);
|
|
||||||
if (!QZ_MouseIsInsideView(&pt)) {
|
|
||||||
[ NSApp sendEvent:event ];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
|
|
||||||
QZ_MouseButtonEvent([ event buttonNumber ], YES);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NSOtherMouseUp:
|
|
||||||
pt = QZ_GetMouseLocation(event);
|
|
||||||
if (!QZ_MouseIsInsideView(&pt)) {
|
|
||||||
[ NSApp sendEvent:event ];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
QZ_MouseMovedEvent((int)pt.x, (int)pt.y);
|
|
||||||
QZ_MouseButtonEvent([ event buttonNumber ], NO);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
case NSKeyDown: {
|
|
||||||
/* Quit, hide and minimize */
|
|
||||||
switch ([ event keyCode ]) {
|
|
||||||
case QZ_q:
|
|
||||||
case QZ_h:
|
|
||||||
case QZ_m:
|
|
||||||
if ([ event modifierFlags ] & NSCommandKeyMask) {
|
|
||||||
[ NSApp sendEvent:event ];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
chars = [ event characters ];
|
|
||||||
unsigned short unicode = [ chars length ] > 0 ? [ chars characterAtIndex:0 ] : 0;
|
|
||||||
if (EditBoxInGlobalFocus()) {
|
|
||||||
if (QZ_KeyEvent([ event keyCode ], unicode, YES)) {
|
|
||||||
[ _cocoa_subdriver->cocoaview interpretKeyEvents:[ NSArray arrayWithObject:event ] ];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
QZ_KeyEvent([ event keyCode ], unicode, YES);
|
|
||||||
for (uint i = 1; i < [ chars length ]; i++) {
|
|
||||||
QZ_KeyEvent(0, [ chars characterAtIndex:i ], YES);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case NSKeyUp:
|
|
||||||
/* Quit, hide and minimize */
|
|
||||||
switch ([ event keyCode ]) {
|
|
||||||
case QZ_q:
|
|
||||||
case QZ_h:
|
|
||||||
case QZ_m:
|
|
||||||
if ([ event modifierFlags ] & NSCommandKeyMask) {
|
|
||||||
[ NSApp sendEvent:event ];
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
chars = [ event characters ];
|
|
||||||
QZ_KeyEvent([ event keyCode ], [ chars length ] ? [ chars characterAtIndex:0 ] : 0, NO);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NSScrollWheel:
|
|
||||||
if ([ event deltaY ] > 0.0) { /* Scroll up */
|
|
||||||
_cursor.wheel--;
|
|
||||||
} else if ([ event deltaY ] < 0.0) { /* Scroll down */
|
|
||||||
_cursor.wheel++;
|
|
||||||
} /* else: deltaY was 0.0 and we don't want to do anything */
|
|
||||||
|
|
||||||
/* Update the scroll count for 2D scrolling */
|
|
||||||
CGFloat deltaX;
|
|
||||||
CGFloat deltaY;
|
|
||||||
|
|
||||||
/* Use precise scrolling-specific deltas if they're supported. */
|
|
||||||
if ([event respondsToSelector:@selector(hasPreciseScrollingDeltas)]) {
|
|
||||||
/* No precise deltas indicates a scroll wheel is being used, so we don't want 2D scrolling. */
|
|
||||||
if (![ event hasPreciseScrollingDeltas ]) break;
|
|
||||||
|
|
||||||
deltaX = [ event scrollingDeltaX ] * 0.5f;
|
|
||||||
deltaY = [ event scrollingDeltaY ] * 0.5f;
|
|
||||||
} else {
|
|
||||||
deltaX = [ event deltaX ] * 5;
|
|
||||||
deltaY = [ event deltaY ] * 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
_cursor.h_wheel -= (int)(deltaX * _settings_client.gui.scrollwheel_multiplier);
|
|
||||||
_cursor.v_wheel -= (int)(deltaY * _settings_client.gui.scrollwheel_multiplier);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NSEventTypeMagnify:
|
|
||||||
/* Pinch open or close gesture. */
|
|
||||||
_current_magnification += [ event magnification ] * 5.0f;
|
|
||||||
|
|
||||||
while (_current_magnification >= 1.0f) {
|
|
||||||
_current_magnification -= 1.0f;
|
|
||||||
_cursor.wheel--;
|
|
||||||
HandleMouseEvents();
|
|
||||||
}
|
|
||||||
while (_current_magnification <= -1.0f) {
|
|
||||||
_current_magnification += 1.0f;
|
|
||||||
_cursor.wheel++;
|
|
||||||
HandleMouseEvents();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NSEventTypeEndGesture:
|
|
||||||
/* Gesture ended. */
|
|
||||||
_current_magnification = 0.0f;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case NSCursorUpdate:
|
|
||||||
case NSMouseEntered:
|
|
||||||
case NSMouseExited:
|
|
||||||
/* Catch these events if the cursor is dragging. During dragging, we reset
|
|
||||||
* the mouse position programmatically, which would trigger OS X to show
|
|
||||||
* the default arrow cursor if the events are propagated. */
|
|
||||||
if (_cursor.fix_at) break;
|
|
||||||
FALLTHROUGH;
|
|
||||||
|
|
||||||
default:
|
|
||||||
[ NSApp sendEvent:event ];
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void VideoDriver_Cocoa::GameLoop()
|
|
||||||
{
|
|
||||||
uint32 cur_ticks = GetTick();
|
|
||||||
uint32 last_cur_ticks = cur_ticks;
|
|
||||||
uint32 next_tick = cur_ticks + MILLISECONDS_PER_TICK;
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
uint32 et0 = GetTick();
|
|
||||||
uint32 st = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DisplaySplashImage();
|
|
||||||
QZ_CheckPaletteAnim();
|
|
||||||
_cocoa_subdriver->Draw(true);
|
|
||||||
CSleep(1);
|
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) ::GameLoop();
|
|
||||||
|
|
||||||
UpdateWindows();
|
|
||||||
QZ_CheckPaletteAnim();
|
|
||||||
_cocoa_subdriver->Draw();
|
|
||||||
CSleep(1);
|
|
||||||
|
|
||||||
/* Set the proper OpenTTD palette which got spoilt by the splash
|
|
||||||
* image when using 8bpp blitter */
|
|
||||||
GfxInitPalettes();
|
|
||||||
QZ_CheckPaletteAnim();
|
|
||||||
_cocoa_subdriver->Draw(true);
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
uint32 prev_cur_ticks = cur_ticks; // to check for wrapping
|
|
||||||
InteractiveRandom(); // randomness
|
|
||||||
|
|
||||||
while (QZ_PollEvent()) {}
|
|
||||||
|
|
||||||
if (_exit_game) {
|
|
||||||
/* Restore saved resolution if in fullscreen mode. */
|
|
||||||
if (_cocoa_subdriver->IsFullscreen()) _cur_resolution = this->orig_res;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(_DEBUG)
|
|
||||||
if (_current_mods & NSShiftKeyMask)
|
|
||||||
#else
|
|
||||||
if (_tab_is_down)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (!_networking && _game_mode != GM_MENU) _fast_forward |= 2;
|
|
||||||
} else if (_fast_forward & 2) {
|
|
||||||
_fast_forward = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_ticks = GetTick();
|
|
||||||
if (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;
|
|
||||||
|
|
||||||
_ctrl_pressed = !!(_current_mods & ( _settings_client.gui.right_mouse_btn_emulation != RMBE_CONTROL ? NSControlKeyMask : NSCommandKeyMask));
|
|
||||||
_shift_pressed = !!(_current_mods & NSShiftKeyMask);
|
|
||||||
|
|
||||||
if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged();
|
|
||||||
|
|
||||||
::GameLoop();
|
|
||||||
|
|
||||||
UpdateWindows();
|
|
||||||
QZ_CheckPaletteAnim();
|
|
||||||
_cocoa_subdriver->Draw();
|
|
||||||
} else {
|
|
||||||
#ifdef _DEBUG
|
|
||||||
uint32 st0 = GetTick();
|
|
||||||
#endif
|
|
||||||
CSleep(1);
|
|
||||||
#ifdef _DEBUG
|
|
||||||
st += GetTick() - st0;
|
|
||||||
#endif
|
|
||||||
NetworkDrawChatMessage();
|
|
||||||
DrawMouseCursor();
|
|
||||||
_cocoa_subdriver->Draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _DEBUG
|
|
||||||
uint32 et = GetTick();
|
|
||||||
|
|
||||||
DEBUG(driver, 1, "cocoa_v: nextEventMatchingMask took %i ms total", _tEvent);
|
|
||||||
DEBUG(driver, 1, "cocoa_v: game loop took %i ms total (%i ms without sleep)", et - et0, et - et0 - st);
|
|
||||||
DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop total) is %f%%", (double)_tEvent / (double)(et - et0) * 100);
|
|
||||||
DEBUG(driver, 1, "cocoa_v: (nextEventMatchingMask total)/(game loop without sleep total) is %f%%", (double)_tEvent / (double)(et - et0 - st) * 100);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* WITH_COCOA */
|
|
||||||
10
update.sh
10
update.sh
@@ -9,6 +9,7 @@ ttdir=$dir/openttd-$version
|
|||||||
cp -rT $ttdir $curdir
|
cp -rT $ttdir $curdir
|
||||||
cd $ttdir
|
cd $ttdir
|
||||||
find . -type f > $dir/ttd_files
|
find . -type f > $dir/ttd_files
|
||||||
|
find * > $dir/ttd_all
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake ..
|
||||||
@@ -18,4 +19,11 @@ make -j
|
|||||||
cd $curdir
|
cd $curdir
|
||||||
cp $ttdir/build/generated/rev.cpp src/rev.cpp.in
|
cp $ttdir/build/generated/rev.cpp src/rev.cpp.in
|
||||||
cat $dir/ttd_files | xargs git add
|
cat $dir/ttd_files | xargs git add
|
||||||
rm -rf $dir
|
for i in $(find * -not -path "build*" -not -path "update.sh"); do
|
||||||
|
if ! grep -qxFe "$i" $dir/ttd_all; then
|
||||||
|
echo "Deleting: $i"
|
||||||
|
# the next line is commented out. Test it. Then uncomment to removed the files
|
||||||
|
git rm -f "$i"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
# rm -rf $dir
|
||||||
|
|||||||
Reference in New Issue
Block a user