#!/bin/sh
# shellcheck disable=SC2030,SC2031
# SC2030: Modification of WINE is local (to subshell caused by (..) group).
# SC2031: WINE was modified in a subshell. That change might be lost
# This has to be right after the shebang, see: https://github.com/koalaman/shellcheck/issues/779

# Name of this version of winetricks (YYYYMMDD)
# (This doesn't change often, use the sha256sum of the file when reporting problems)
WINETRICKS_VERSION=20170327-libre

# This is a UTF-8 file
# You should see an o with two dots over it here [ö]
# You should see a micro (u with a tail) here [µ]
# You should see a trademark symbol here [™]

#--------------------------------------------------------------------
#
# Winetricks is a package manager for Win32 dlls and applications on POSIX.
# Features:
# - Consists of a single shell script - no installation required
# - Downloads packages automatically from original trusted sources
# - Points out and works around known wine bugs automatically
# - Both command-line and GUI operation
# - Can install many packages in silent (unattended) mode
# - Multiplatform; written for Linux, but supports OS X and Cygwin too
#
# Uses the following non-POSIX system tools:
# - wine is used to execute Win32 apps except on Cygwin.
# - ar, cabextract, unrar, unzip, and 7z are needed by some verbs.
# - aria2c, wget, curl, or fetch is needed for downloading.
# - sha1sum, sha1, or shasum is needed for verifying downloads (or openssl for OSX 10.5)
# - Note: there is a transition to sha256 under way, which requires
# - sha256sum, sha256, or shasum (OSX 10.5 does not support these, and is considered deprecated)
# - zenity is needed by the GUI, though it can limp along somewhat with kdialog/xmessage.
# - xdg-open (if present) or open (for OS X) is used to open download pages
#   for the user when downloads cannot be fully automated.
# - sudo is used to mount .iso images if the user cached them with -k option.
# - perl is used to munge steam config files
# On Ubuntu, the following lines can be used to install all the prerequisites:
#    sudo add-apt-repository ppa:ubuntu-wine/ppa
#    sudo apt-get update
#    sudo apt-get install binutils cabextract p7zip unrar unzip wget wine zenity
#
# See http://winetricks.org for documentation and tutorials, including
# how to contribute changes to winetricks.
#
#--------------------------------------------------------------------
#
# Copyright:
#   Copyright (C) 2007-2014 Dan Kegel <dank!kegel.com>
#   Copyright (C) 2008-2017 Austin English <austinenglish!gmail.com>
#   Copyright (C) 2010-2011 Phil Blankenship <phillip.e.blankenship!gmail.com>
#   Copyright (C) 2010-2015 Shannon VanWagner <shannon.vanwagner!gmail.com>
#   Copyright (C) 2010 Belhorma Bendebiche <amro256!gmail.com>
#   Copyright (C) 2010 Eleazar Galano <eg.galano!gmail.com>
#   Copyright (C) 2010 Travis Athougies <iammisc!gmail.com>
#   Copyright (C) 2010 Andrew Nguyen
#   Copyright (C) 2010 Detlef Riekenberg
#   Copyright (C) 2010 Maarten Lankhorst
#   Copyright (C) 2010 Rico Schüller
#   Copyright (C) 2011 Scott Jackson <sjackson2!gmx.com>
#   Copyright (C) 2011 Trevor Johnson
#   Copyright (C) 2011 Franco Junio
#   Copyright (C) 2011 Craig Sanders
#   Copyright (C) 2011 Matthew Bauer <mjbauer95>
#   Copyright (C) 2011 Giuseppe Dia
#   Copyright (C) 2011 Łukasz Wojniłowicz
#   Copyright (C) 2011 Matthew Bozarth
#   Copyright (C) 2013-2016 Andrey Gusev <andrey.goosev!gmail.com>
#   Copyright (C) 2013-2015 Hillwood Yang <hillwood!opensuse.org>
#   Copyright (C) 2013,2016 André Hentschel <nerv!dawncrow.de>
#
# License:
#   This program is free software; you can redistribute it and/or
#   modify it under the terms of the GNU Lesser General Public
#   License as published by the Free Software Foundation; either
#   version 2.1 of the License, or (at your option) any later
#   version.
#
#   This program 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 Lesser General Public License for more details.
#
#   You should have received a copy of the GNU Lesser General Public
#   License along with this program.  If not, see
#   <https://www.gnu.org/licenses/>.
#
#--------------------------------------------------------------------
# Coding standards:
#
# Portability:
# - Portability matters, as this script is run on many operating systems
# - No bash, zsh, or csh extensions; only use features from
#   the POSIX standard shell and utilities; see
#   http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
# - 'checkbashisms -p -x winetricks' should show no warnings (per Debian policy)
# - Prefer classic sh idioms as described in e.g.
#   "Portable Shell Programming" by Bruce Blinn, ISBN: 0-13-451494-7
# - If there is no universally available program for a needed function,
#   support the two most frequently available programs.
#   e.g. fall back to wget if curl is not available; likewise, support
#   both sha1sum and openssl.
# - When using Unix commands like cp, put options before filenames so it will
#   work on systems like OS X.  e.g. "rm -f foo.dat", not "rm foo.dat -f"
#
# Formatting:
# - Your terminal and editor must be configured for UTF-8
#   If you do not see an o with two dots over it here [ö], stop!
# - Do not use tabs in this file or any verbs.
# - Indent 4 spaces.
# - Try to keep line length below 80 (makes printing easier)
# - Open curly braces ('{') and 'then' at beginning of line,
#   close curlies ('}') and 'fi' should line up with the matching { or if,
#   cases aligned with 'case' and 'esac'.  For instance,
#
#      if test "$FOO" = "bar"
#      then
#         echo "FOO is bar"
#      fi
#      case "$FOO" of
#      bar) echo "FOO is still bar" ;;
#      esac
#
# Commenting:
# - Comments should explain intent in English
# - Keep functions short and well named to reduce need for comments
#
# Naming:
# Public things defined by this script, for use by verbs:
# - Variables have uppercase names starting with W_
# - Functions have lowercase names starting with w_
#
# Private things internal to this script, not for use by verbs:
# - Local variables have lowercase names starting with uppercase _W_
#   (and should not use the local declaration, as it is not POSIX)
# - Global variables have uppercase names starting with WINETRICKS_
# - Functions have lowercase names starting with winetricks_
# FIXME: A few verbs still use winetricks-private functions or variables.
#
# Internationalization / localization:
# - Important or frequently used message should be internationalized
#   so translations can be easily added.  For example:
#     case $LANG in
#     de*) echo "Das ist die deutsche Meldung" ;;
#     *)   echo "This is the English message" ;;
#     esac
#
# Support:
# - Winetricks is maintained by Austin English <austinenglish!$gmail.com>.
# - If winetricks has helped you out, then please consider donating to the FSF/EFF as a thank you
# - If winetricks has helped you out, then please consider donating to the FSF/EFF as a thank you:
#   * EFF - https://supporters.eff.org/donate/button
#   * FSF - https://my.fsf.org/donate
# - Donations towards electricity bill and developer beer fund can be sent via Paypal to above address.
# - I try to actively respond to bugs and pull requests on GitHub:
# - Bugs: https://github.com/Winetricks/winetricks/issues/new
# - Pull Requests: https://github.com/Winetricks/winetricks/pulls
#--------------------------------------------------------------------

# FIXME: XDG_CACHE_HOME is defined twice, clean this up
XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"

W_COUNTRY=""
W_PREFIXES_ROOT="${WINE_PREFIXES:-$XDG_DATA_HOME/wineprefixes}"

# For temp files before $WINEPREFIX is available:
if [ -x "$(which mktemp 2>/dev/null)" ]
then
    W_TMP_EARLY="$(mktemp -d "${TMPDIR:-/tmp}/winetricks.XXXXXXXX")"
elif [ -w "$TMPDIR" ]
then
    W_TMP_EARLY="$TMPDIR"
else
    W_TMP_EARLY="/tmp"
fi

#---- Public Functions ----

# Ask permission to continue
w_askpermission()
{
    echo "------------------------------------------------------"
    echo "$@"
    echo "------------------------------------------------------"

    if test "$W_OPT_UNATTENDED"
    then
        _W_timeout="--timeout 5"
    fi

    case $WINETRICKS_GUI in
    zenity) $WINETRICKS_GUI "$_W_timeout" --question --title=winetricks --text="$(echo "$@" | sed 's,\\\\,\\\\\\\\,g')" --no-wrap;;
    kdialog) $WINETRICKS_GUI --title winetricks --warningcontinuecancel "$@" ;;
    none) printf %s "Press Y or N, then Enter: " ; read -r response ; test "$response" = Y || test "$response" = y;;
    esac

    if test $? -ne 0
    then
        case $LANG in
        uk*) w_die "Операція скасована." ;;
        *) w_die "Operation cancelled, quitting." ;;
        esac
        exec false
    fi

    unset _W_timeout
}

# Display info message.  Time out quickly if user doesn't click.
w_info()
{
    # If $WINETRICKS_SUPER_QUIET is set, w_info is a no-op:
    if [ ! "$WINETRICKS_SUPER_QUIET" ] ; then
        echo "------------------------------------------------------"
        echo "$@"
        echo "------------------------------------------------------"
    fi

    _W_timeout="--timeout 3"

    case $WINETRICKS_GUI in
    zenity) $WINETRICKS_GUI "$_W_timeout" --info --title=winetricks --text="$(echo "$@" | sed 's,\\\\,\\\\\\\\,g')" --no-wrap;;
    kdialog) $WINETRICKS_GUI --title winetricks --msgbox "$@" ;;
    none) ;;
    esac

    unset _W_timeout
}

# Display warning message to stderr (since it is called inside redirected code)
w_warn()
{
    # If $WINETRICKS_SUPER_QUIET is set, w_info is a no-op:
    if [ ! "$WINETRICKS_SUPER_QUIET" ] ; then
        echo "------------------------------------------------------"
        echo "$@"
        echo "------------------------------------------------------"
    fi

    if test "$W_OPT_UNATTENDED"
    then
        _W_timeout="--timeout 5"
    fi

    case $WINETRICKS_GUI in
    zenity) $WINETRICKS_GUI "$_W_timeout" --error --title=winetricks --text="$(echo "$@" | sed 's,\\\\,\\\\\\\\,g')";;
    kdialog) $WINETRICKS_GUI --title winetricks --error "$@" ;;
    none) ;;
    esac

    unset _W_timeout
}

# Display warning message to stderr (since it is called inside redirected code)
# And give gui user option to cancel (for when used in a loop)
# If user cancels, exit status is 1
w_warn_cancel()
{
    echo "------------------------------------------------------" >&2
    echo "$@" >&2
    echo "------------------------------------------------------" >&2

    if test "$W_OPT_UNATTENDED"
    then
        _W_timeout="--timeout 5"
    fi

    # Zenity has no cancel button, but will set status to 1 if you click the go-away X
    case $WINETRICKS_GUI in
    zenity) $WINETRICKS_GUI "$_W_timeout" --error --title=winetricks --text="$(echo "$@" | sed 's,\\\\,\\\\\\\\,g')";;
    kdialog) $WINETRICKS_GUI --title winetricks --warningcontinuecancel "$@" ;;
    none) ;;
    esac

    # can't unset, it clears status
}

# Display fatal error message and terminate script
w_die()
{
    w_warn "$@"

    exit 1
}

# Kill all instances of a process in a safe way (Solaris killall kills _everything_)
w_killall()
{
    # shellcheck disable=SC2046,SC2086
    kill -s KILL $(pgrep $1)
}

# Some packages don't support win64, die with an appropriate message
# Note: this is for packages that natively don't support win64, not packages that are broken on wine64
w_package_unsupported_win64()
{
    if [ "$W_ARCH" = "win64" ]
    then
        w_die "This package does not work on a 64-bit installation. You must use a prefix made with WINEARCH=win32."
    fi
}

# Execute with error checking
# Put this in front of any command that might fail
w_try()
{
    # "VAR=foo w_try cmd" fails to put VAR in the environment
    # with some versions of bash if w_try is a shell function?!
    # This is a problem when trying to pass environment variables to e.g. wine.
    # Adding an explicit export here works around it, so add any we use.
    export WINEDLLOVERRIDES
    printf '%s\n' "Executing $*"

    # On Vista, we need to jump through a few hoops to run commands in Cygwin.
    # First, .exe's need to have the executable bit set.
    # Second, only cmd can run setup programs (presumably for security).
    # If $1 ends in .exe, we know we're running on real Windows, otherwise
    # $1 would be 'wine'.
    case "$1" in
    *.exe)
        chmod +x "$1" || true # don't care if it fails
        cmd /c "$@"
        ;;
    *)
        "$@"
        ;;
    esac
    status=$?
    if test $status -ne 0
    then
        w_die "Note: command $* returned status $status.  Aborting."
    fi
}

w_try_7z()
{
    # $1 - directory to extract to
    # $2 - file to extract
    # Not always installed, use Windows 7-Zip as a fallback:
    if test -x "$(which 7z 2>/dev/null)"
    then
        w_try 7z x "$2" -o"$1"
    else
        w_warn "Cannot find 7z.  Using Windows 7-Zip instead. (You can avoid this by installing 7z, e.g. 'sudo apt-get install p7zip-full' or 'sudo yum install p7zip p7zip-plugins')."
        WINETRICKS_OPT_SHAREDPREFIX=1 w_call 7zip
        # errors out if there is a space between -o and path
        w_try "$WINE" "$W_PROGRAMS_X86_WIN\\7-Zip\\7z.exe" x "$(w_pathconv -w "$2")" -o"$(w_pathconv -w "$1")"
    fi
}

w_try_ar()
{
    # $1 - ar file (.deb) to extract (keeping internal paths, in cwd)
    # $2 - file to extract (optional)

    # Not always installed, use Windows 7-zip as a fallback:
    if test -x "$(which ar 2>/dev/null)"
    then
        w_try ar x "$@"
    else
        w_warn "Cannot find ar.  Using Windows 7-zip instead. (You can avoid this by installing binutils, e.g. 'sudo apt-get install binutils' or 'sudo yum install binutils')."
        WINETRICKS_OPT_SHAREDPREFIX=1 w_call 7zip

        # -t* prevents 7-zip from decompressing .tar.xz to .tar, see
        # https://sourceforge.net/p/sevenzip/discussion/45798/thread/8cd16946/?limit=25
        w_try "$WINE" "$W_PROGRAMS_X86_WIN\\7-Zip\\7z.exe" -t* x "$(w_pathconv -w "$1")"
    fi
}

w_try_cabextract()
{
    # Not always installed, but shouldn't be fatal unless it's being used
    if test ! -x "$(which cabextract 2>/dev/null)"
    then
        w_die "Cannot find cabextract.  Please install it (e.g. 'sudo apt-get install cabextract' or 'sudo yum install cabextract')."
    fi

    w_try cabextract -q "$@"
}

w_try_cd()
{
    w_try cd "$@"
}

w_try_msiexec64()
{
    if test "$W_ARCH" != "win64"
    then
        w_die "bug: 64-bit msiexec called from a $W_ARCH prefix."
    fi

    # shellcheck disable=SC2086
    w_try "$WINE" start /wait "$W_SYSTEM64_DLLS_WIN32/msiexec.exe" $W_UNATTENDED_SLASH_Q "$@"
}

w_try_regedit()
{
    # on windows, doesn't work without cmd /c
    case "$W_PLATFORM" in
    windows_cmd|wine_cmd) cmdc="cmd /c";;
    *) unset cmdc ;;
    esac

    # shellcheck disable=SC2086
    w_try winetricks_early_wine $cmdc regedit $W_UNATTENDED_SLASH_S "$@"
}

w_try_regsvr()
{
    # shellcheck disable=SC2086
    w_try "$WINE" regsvr32 $W_UNATTENDED_SLASH_S "$@"
}

w_try_unrar()
{
    # $1 - zipfile to extract (keeping internal paths, in cwd)

    # Not always installed, use Windows 7-Zip as a fallback:
    if test -x "$(which unrar 2>/dev/null)"
    then
        w_try unrar x "$@"
    else
        w_warn "Cannot find unrar.  Using Windows 7-Zip instead. (You can avoid this by installing unrar, e.g. 'sudo apt-get install unrar' or 'sudo yum install unrar')."
        WINETRICKS_OPT_SHAREDPREFIX=1 w_call 7zip
        w_try "$WINE" "$W_PROGRAMS_X86_WIN\\7-Zip\\7z.exe" x "$(w_pathconv -w "$1")"
    fi
}

w_try_unzip()
{
    # $1 - directory to extract to
    # $2 - zipfile to extract
    # $3 .. $n - files to extract from the archive

    destdir="$1"
    zipfile="$2"
    shift 2

    # Not always installed, use Windows 7-Zip as a fallback:
    if test -x "$(which unzip 2>/dev/null)"
    then
        # FreeBSD ships unzip, but it doesn't support self-compressed executables
        # If it fails, fall back to 7-Zip:
        unzip -o -q -d"$destdir" "$zipfile" "$@"
        ret=$?
        case $ret in
            0) return ;;
            1|*) w_warn "Unzip failed, trying Windows 7-Zip instead." ;;
        esac
    else
        w_warn "Cannot find unzip.  Using Windows 7-Zip instead. (You can avoid this by installing unzip, e.g. 'sudo apt-get install unzip' or 'sudo yum install unzip')."
    fi

    WINETRICKS_OPT_SHAREDPREFIX=1 w_call 7zip
    # errors out if there is a space between -o and path
    w_try "$WINE" "$W_PROGRAMS_X86_WIN\\7-Zip\\7z.exe" x "$(w_pathconv -w "$zipfile")" -o"$(w_pathconv -w "$destdir")" "$@"
}

w_read_key()
{
    if test ! "$W_OPT_UNATTENDED"
    then
        W_KEY=dummy_to_make_autohotkey_happy
        return 0
    fi

    mkdir -p "$W_CACHE/$W_PACKAGE"

    # backwards compatible location
    # Auth doesn't belong in cache, since restoring it requires user input
    _W_keyfile="$W_CACHE/$W_PACKAGE/key.txt"
    if ! test -f "$_W_keyfile"
    then
        _W_keyfile="$WINETRICKS_AUTH/$W_PACKAGE/key.txt"
    fi
    if ! test -f "$_W_keyfile"
    then
        # read key from user
        case $LANG in
        da*) _W_keymsg="Angiv venligst registrerings-nøglen for pakken '$W_PACKAGE'"
            _W_nokeymsg="Ingen nøgle angivet"
            ;;
        de*) _W_keymsg="Bitte einen Key für Paket '$W_PACKAGE' eingeben"
            _W_nokeymsg="Keinen Key eingegeben?"
            ;;
        pl*) _W_keymsg="Proszę podać klucz dla programu '$W_PACKAGE'"
            _W_nokeymsg="Nie podano klucza"
            ;;
        ru*) _W_keymsg="Пожалуйста, введите ключ для приложения '$W_PACKAGE'"
            _W_nokeymsg="Ключ не введён"
            ;;
        uk*) _W_keymsg="Будь ласка, введіть ключ для додатка '$W_PACKAGE'"
            _W_nokeymsg="Ключ не надано"
            ;;
        zh_CN*)  _W_keymsg="按任意键为 '$W_PACKAGE'"
            _W_nokeymsg="No key given"
            ;;
        zh_TW*|zh_HK*)  _W_keymsg="按任意鍵為 '$W_PACKAGE'"
            _W_nokeymsg="No key given"
            ;;
        *)  _W_keymsg="Please enter the key for app '$W_PACKAGE'"
            _W_nokeymsg="No key given"
            ;;
        esac
        case $WINETRICKS_GUI in
        *zenity) W_KEY=$(zenity --entry --text "$_W_keymsg") ;;
        *kdialog) W_KEY=$(kdialog --inputbox "$_W_keymsg") ;;
        *xmessage) w_die "sorry, can't read key from GUI with xmessage" ;;
        none) printf %s "$_W_keymsg": ; read -r W_KEY ;;
        esac
        if test "$W_KEY" = ""
        then
            w_die "$_W_nokeymsg"
        fi
        echo "$W_KEY" > "$_W_keyfile"
    fi
    W_RAW_KEY=$(cat "$_W_keyfile")
    W_KEY=$(echo "$W_RAW_KEY" | tr -d '[:blank:][=-=]')
    unset _W_keyfile _W_keymsg _W_nokeymsg
}

# Convert a Windows path to a Unix path quickly.
# $1 is an absolute Windows path starting with c:\ or C:/
# with no funny business, so we can use the simplest possible
# algorithm.
winetricks_wintounix()
{
    _W_winp_="$1"
    # Remove drive letter and colon
    _W_winp="${_W_winp_#??}"
    # Prepend the location of drive c
    printf %s "$WINEPREFIX"/dosdevices/c:
    # Change backslashes to slashes
    echo "$_W_winp" | sed 's,\\,/,g'
}

# Convert between Unix path and Windows path
# Usage is lowest common denominator of cygpath/winepath
# so -u to convert to Unix, and -w to convert to Windows
w_pathconv()
{
    case "$W_PLATFORM" in
     windows_cmd)
        # for some reason, cygpath turns some spaces into newlines?!
        cygpath "$@" | tr '\012' '\040' | sed 's/ $//'
        ;;
     *)
        case "$@" in
        -u?c:\\*|-u?C:\\*|-u?c:/*|-u?C:/*) winetricks_wintounix "$2" ;;
        *) winetricks_early_wine winepath "$@" ;;
        esac
        ;;
    esac
}

# Expand an environment variable and print it to stdout
w_expand_env()
{
    winetricks_early_wine cmd.exe /c echo "%$1%"
}

# get sha1sum string and set $_W_gotsha1um to it
w_get_sha1sum()
{
    _W_sha1_file="$1"

    # See https://github.com/Winetricks/winetricks/issues/645
    # User is running winetricks from /dev/stdin
    if [ -f "$_W_sha1_file" ] || [ -h "$_W_sha1_file" ]
    then
        _W_gotsha1sum=$($WINETRICKS_SHA1SUM < "$_W_sha1_file" | sed 's/(stdin)= //;s/ .*//')
    else
        w_warn "$_W_sha1_file is not a regular file, not checking sha1sum"
        return
    fi
}

# get sha256sum string and set $_W_gotsha256sum to it
w_get_sha256sum()
{
    _W_sha256_file="$1"

    # See https://github.com/Winetricks/winetricks/issues/645
    # User is running winetricks from /dev/stdin
    if [ -f "$_W_sha256_file" ] || [ -h "$_W_sha256_file" ]
    then
        _W_gotsha256sum=$($WINETRICKS_SHA256SUM < "$_W_sha256_file" | sed 's/(stdin)= //;s/ .*//')
    else
        w_warn "$_W_sha256_file is not a regular file, not checking sha256sum"
        return
    fi
}

w_get_shatype() {
    _W_sum="$1"

    # tr -d " " is for FreeBSD/OS X/Solaris return a leading space:
    # See https://stackoverflow.com/questions/30927590/wc-on-osx-return-includes-spaces/30927885#30927885
    _W_sum_length="$(echo "$_W_sum" | tr -d "\n" | wc -c | tr -d " ")"
    case "$_W_sum_length" in
         0) _W_shatype="none" ;;
         40) _W_shatype="sha1" ;;
         64) _W_shatype="sha256" ;;
         # 128) sha512..
         *) w_die "unsupported shasum..bug" ;;
    esac
}

# verify a sha1sum
w_verify_sha1sum()
{
    _W_vs_wantsum=$1
    _W_vs_file=$2

    w_get_sha1sum "$_W_vs_file"
    if [ "$_W_gotsha1sum"x != "$_W_vs_wantsum"x ]
    then
        w_die "sha1sum mismatch!  Rename $_W_vs_file and try again."
    fi
    unset _W_vs_wantsum _W_vs_file _W_gotsha1sum
}

# verify a sha256sum
w_verify_sha256sum()
{
    _W_vs_wantsum=$1
    _W_vs_file=$2

    w_get_sha256sum "$_W_vs_file"
    if [ "$_W_gotsha256sum"x != "$_W_vs_wantsum"x ]
    then
        w_die "sha256sum mismatch!  Rename $_W_vs_file and try again."
    fi
    unset _W_vs_wantsum _W_vs_file _W_gotsha256sum
}

# verify any kind of shasum (that winetricks supports ;) ):
w_verify_shasum()
{
    _W_vs_wantsum="$1"
    _W_vs_file="$2"

    w_get_shatype "$_W_vs_wantsum"

    case "$_W_shatype" in
        none) w_warn "No checksum provided, not verifying" ;;
        sha1) w_verify_sha1sum "$_W_sum" "$_W_vs_file" ;;
        sha256) w_verify_sha256sum "$_W_sum" "$_W_vs_file" ;;
        # 128) sha512..
        *) w_die "unsupported shasum..bug" ;;
    esac
}

# wget outputs progress messages that look like this:
#      0K .......... .......... .......... .......... ..........  0%  823K 40s
# This function replaces each such line with the pair of lines
# 0%
# # Downloading... 823K (40s)
# It uses minimal buffering, so each line is output immediately
# and the user can watch progress as it happens.

winetricks_parse_wget_progress()
{
    # Parse a percentage, a size, and a time into $1, $2 and $3
    # then use them to create the output line.
    perl -p -e \
       '$| = 1; s/^.* +([0-9]+%) +([0-9,.]+[GMKB]) +([0-9hms,.]+).*$/\1\n# Downloading... \2 (\3)/'
}

# Execute wget, and if in gui mode, also show a graphical progress bar
winetricks_wget_progress()
{
    case $WINETRICKS_GUI in
    zenity)
        # Usa a subshell so if the user clicks 'Cancel',
        # the --auto-kill kills the subshell, not the current shell
        (
            ${torify} wget "$@" 2>&1 |
            winetricks_parse_wget_progress | \
            $WINETRICKS_GUI --progress --width 400 --title="$_W_file" --auto-kill --auto-close
        )
        err=$?
        if test $err -gt 128
        then
            # 129 is 'killed by SIGHUP'
            # Sadly, --auto-kill only applies to parent process,
            # which was the subshell, not all the elements of the pipeline...
            # have to go find and kill the wget.
            # If we ran wget in the background, we could kill it more directly, perhaps...
            if pid=$(pgrep -f ."$_W_file")
            then
                echo User aborted download, killing wget
                # shellcheck disable=SC2086
                kill $pid
            fi
        fi
        return $err
        ;;
    *) ${torify} wget "$@" ;;
    esac
}

# Download a file
# Usage: w_download_to (packagename|path to download file) url [sha1sum [filename [cookie jar]]]
# Caches downloads in winetrickscache/$packagename
w_download_to()
{
    winetricks_download_setup

    _W_packagename="$1" # or path to download file to
    _W_url="$2"
    _W_sum="$3"
    _W_file="$4"
    _W_cookiejar="$5"

    case $_W_packagename in
    .) w_die "bug: please do not download packages to top of cache" ;;
    esac

    if echo "$_W_url" | grep ' '
    then
        w_die "bug: please use %20 instead of literal spaces in urls, curl rejects spaces, and they make life harder for linkcheck.sh"
    fi
    if [ "$_W_file"x = ""x ]
    then
        _W_file=$(basename "$_W_url")
    fi

    w_get_shatype "$_W_sum"

    if echo "${_W_packagename}" | grep -q -e '\/-' -e '^-'; then
            w_die "Invalid path ${_W_packagename} given"
    else
        if ! echo "${_W_packagename}" | grep -q '^/' ; then
            _W_cache="$W_CACHE/$_W_packagename"
        else
            _W_cache="$_W_packagename"
        fi
    fi

    if test ! -d "$_W_cache"
    then
        w_try mkdir -p "$_W_cache"
    fi

    # Try download twice
    checksum_ok=""
    tries=0
    while test $tries -lt 2
    do
        # Warn on a second try
        test "$tries" -eq 1 && winetricks_dl_warning
        tries=$((tries + 1))

        if test -s "$_W_cache/$_W_file"
        then
            if test "$_W_sum"
            then
                if test $tries = 1
                then
                    # The cache was full.  If the file is larger than 500 MB,
                    # don't checksum it, that just annoys the user.
                    # shellcheck disable=SC2046
                    if test $(du -k "$_W_cache/$_W_file" | cut -f1) -gt 500000
                    then
                        checksum_ok=1
                        break
                    fi
                fi
                # If checksum matches, declare success and exit loop
                case "$_W_shatype" in
                    none)
                        w_warn "No checksum provided, not verifying"
                        ;;
                    sha1)
                        w_get_sha1sum "$_W_cache/$_W_file"
                        if [ "$_W_gotsha1sum"x = "$_W_sum"x ]
                        then
                            checksum_ok=1
                            break
                        fi
                        ;;
                    sha256)
                        w_get_sha256sum "$_W_cache/$_W_file"
                        if [ "$_W_gotsha256sum"x = "$_W_sum"x ]
                        then
                            checksum_ok=1
                            break
                        fi
                        ;;
                esac

                if test ! "$WINETRICKS_CONTINUE_DOWNLOAD"
                then
                    w_warn "Checksum for $_W_cache/$_W_file did not match, retrying download"
                    mv -f "$_W_cache/$_W_file" "$_W_cache/$_W_file".bak
                fi
            else
                # file exists, no checksum known, declare success and exit loop
                break
            fi
        elif test -f "$_W_cache/$_W_file"
        then
            # zero-length file, just delete before retrying
            rm "$_W_cache/$_W_file"
        fi

        _W_dl_olddir=$(pwd)
        w_try_cd "$_W_cache"
        # Mac folks tend to have curl rather than wget
        # On Mac, 'which' doesn't return good exit status
        echo "Downloading $_W_url to $_W_cache"

        # For sites that prefer Mozilla in the user-agent header, set W_BROWSERAGENT=1
        case "$W_BROWSERAGENT" in
        1) _W_agent="Mozilla/5.0 (compatible; Konqueror/2.1.1; X11)" ;;
        *) _W_agent="" ;;
        esac

        if [ "${WINETRICKS_DOWNLOADER}" = "aria2c" ]
        then
            # Note: aria2c wants = for most options or silently fails

            # (Slightly fancy) aria2c support
            # See https://github.com/Winetricks/winetricks/issues/612
            # --daemon=false --enable-rpc=false to ensure aria2c doesnt go into the background after starting
            #   and prevent any attempts to rebind on the RPC interface specified in someone's config.
            # --input-file='' if the user config has a input-file specified then aria2 will read it and
            #   attempt to download everything in that input file again.
            # --save-session='' if the user has specified save-session in their config, their session will be
            #   ovewritten by the new aria2 process

            # shellcheck disable=SC2086
            $torify aria2c \
                $aria2c_torify_opts \
                --connect-timeout="${WINETRICKS_DOWNLOADER_TIMEOUT}" \
                --continue \
                --daemon=false \
                --dir="$_W_cache" \
                --enable-rpc=false \
                --input-file='' \
                --max-connection-per-server=5 \
                --max-tries="$WINETRICKS_DOWNLOADER_RETRIES" \
                --out="$_W_file" \
                --save-session='' \
                --stream-piece-selector=geom \
                "$_W_url"
        elif [ "${WINETRICKS_DOWNLOADER}" = "wget" ]
        then
           # Use -nd to insulate ourselves from people who set -x in WGETRC
           # [*] --retry-connrefused works around the broken sf.net mirroring
           # system when downloading corefonts
           # [*] --read-timeout is useful on the adobe server that doesn't
           # close the connection unless you tell it to (control-C or closing
           # the socket)

           # shellcheck disable=SC2086
           winetricks_wget_progress \
               -O "$_W_file" \
               -nd \
               -c\
               --read-timeout 300 \
               --retry-connrefused \
               --timeout "${WINETRICKS_DOWNLOADER_TIMEOUT}" \
               --tries "$WINETRICKS_DOWNLOADER_RETRIES" \
               ${_W_cookiejar:+--load-cookies "$_W_cookiejar"} \
               ${_W_agent:+--user-agent="$_W_agent"} \
               "$_W_url"
        elif [ "${WINETRICKS_DOWNLOADER}" = "curl" ]
        then
           # Note: curl does not accept '=' when passing options

           # curl doesn't get filename from the location given by the server!
           # fortunately, we know it

           # shellcheck disable=SC2086
           $torify curl \
               --connect-timeout "${WINETRICKS_DOWNLOADER_TIMEOUT}" \
               -L \
               -o "$_W_file" \
               -C - \
               --retry "$WINETRICKS_DOWNLOADER_RETRIES" \
               ${_W_cookiejar:+--cookie "$_W_cookiejar"} \
               ${_W_agent:+--user-agent "$_W_agent"} \
               "$_W_url"
        elif [ "${WINETRICKS_DOWNLOADER}" = "fetch" ]
        then
           # Note: fetch does not support configurable retry count

           # shellcheck disable=SC2086
           $torify fetch \
               -T "${WINETRICKS_DOWNLOADER_TIMEOUT}" \
               -o "$_W_file" \
               ${_W_agent:+--user-agent="$_W_agent"} \
               "$_W_url"
        else
            w_die "Here be dragons"
        fi
        if test $? = 0
        then
            # Need to decompress .exe's that are compressed, else Cygwin fails
            # Also affects ttf files on github
            # FIXME: gzip hack below may no longer be needed, but need to investigate before removing
            _W_filetype=$(which file 2>/dev/null)
            case $_W_filetype-$_W_file in
            /*-*.exe|/*-*.ttf|/*-*.zip)
                case $(file "$_W_file") in
                *:*gzip*) mv "$_W_file" "$_W_file.gz"; gunzip < "$_W_file.gz" > "$_W_file";;
                esac
            esac

            # On Cygwin, .exe's must be marked +x
            case "$_W_file" in
            *.exe) chmod +x "$_W_file" ;;
            esac

            w_try_cd "$_W_dl_olddir"
            unset _W_dl_olddir
        elif test $tries = 2
        then
            test -f "$_W_file" && rm "$_W_file"
            w_die "Downloading $_W_url failed"
        fi
        # Download from the Wayback Machine on second try
        _W_url="https://web.archive.org/web/$_W_url"
    done

    if test "$_W_sum" && test ! "$checksum_ok" ; then
        w_verify_shasum "$_W_sum" "$_W_cache/$_W_file"
    fi
}

# Open a folder for the user in the specified directory
# Usage: w_open_folder directory
w_open_folder()
{
    for _W_cmd in xdg-open open cygstart true
    do
        _W_cmdpath=$(which $_W_cmd)
        if test -n "$_W_cmdpath"
        then
            break
        fi
    done
    $_W_cmd "$1" &
    unset _W_cmd _W_cmdpath
}

# Open a web browser for the user to the given page
# Usage: w_open_webpage url
w_open_webpage()
{
    # See https://www.dwheeler.com/essays/open-files-urls.html
    for _W_cmd in xdg-open sdtwebclient cygstart open firefox true
    do
        _W_cmdpath=$(which $_W_cmd)
        if test -n "$_W_cmdpath"
        then
            break
        fi
    done
    $_W_cmd "$1" &
    unset _W_cmd _W_cmdpath
}

# Download a file
# Usage: w_download url [sha1sum [filename [cookie jar]]]
# Caches downloads in winetrickscache/$W_PACKAGE
w_download()
{
    w_download_to "$W_PACKAGE" "$@"
}



w_download_manual_to()
{
    _W_packagename="$1"
    _W_url="$2"
    _W_file="$3"
    _W_shasum="$4"

    # shellcheck disable=SC2154
    case "$media" in
        "download") w_info "FAIL: bug: media type is download, but w_download_manual was called.  Programmer, please change verb's media type to manual_download." ;;
    esac

    if ! test -f "$W_CACHE/$_W_packagename/$_W_file"
    then
        case $LANG in
            da*) _W_dlmsg="Hent venligst filen $_W_file fra $_W_url og placér den i $W_CACHE/$_W_packagename, kør derefter dette skript.";;
            de*) _W_dlmsg="Bitte laden Sie $_W_file von $_W_url runter, stellen Sie's in $W_CACHE/$_W_packagename, dann wiederholen Sie dieses Kommando.";;
            pl*) _W_dlmsg="Proszę pobrać plik $_W_file z $_W_url, następnie umieścić go w $W_CACHE/$_W_packagename, a na końcu uruchomić ponownie ten skrypt.";;
            ru*) _W_dlmsg="Пожалуйста, скачайте файл $_W_file по адресу $_W_url, и поместите его в $W_CACHE/$_W_packagename, а затем запустите winetricks заново.";;
            uk*) _W_dlmsg="Будь ласка, звантажте $_W_file з $_W_url, розташуйте в $W_CACHE/$_W_packagename, потім запустіть скрипт знову.";;
            zh_CN*) _W_dlmsg="请从 $_W_url 下载 $_W_file，并置放于 $W_CACHE/$_W_packagename, 然后重新运行 winetricks.";;
            zh_TW*|zh_HK*) _W_dlmsg="請從 $_W_url 下載 $_W_file，并置放於 $W_CACHE/$_W_packagename, 然后重新執行 winetricks.";;
            *) _W_dlmsg="Please download $_W_file from $_W_url, place it in $W_CACHE/$_W_packagename, then re-run this script.";;
        esac

        mkdir -p "$W_CACHE/$_W_packagename"
        w_open_folder "$W_CACHE/$_W_packagename"
        w_open_webpage "$_W_url"
        sleep 3   # give some time for web browser to open
        w_die "$_W_dlmsg"
        # FIXME: wait in loop until file is finished?
    fi

    if test "$_W_shasum"
    then
        w_verify_shasum "$_W_shasum" "$W_CACHE/$_W_packagename/$_W_file"
    fi

    unset _W_dlmsg _W_file _W_sha1sum _W_sha256sum _W_url
}

w_download_manual()
{
    w_download_manual_to "$W_PACKAGE" "$@"
}

#----------------------------------------------------------------


# Usage: w_mount "volume name" [filename-to-check [discnum]]
# Some games have two volumes with identical volume names.
# For these, please specify discnum 1 for first disc, discnum 2 for 2nd, etc.,
# else caching can't work.
# FIXME: should take mount option 'unhide' for poorly mastered discs
w_mount()
{
    if test "$3"
    then
        WINETRICKS_IMG="$W_CACHE/$W_PACKAGE/$1-$3.iso"
    else
        WINETRICKS_IMG="$W_CACHE/$W_PACKAGE/$1.iso"
    fi
    mkdir -p "$W_CACHE/$W_PACKAGE"

    if test -f "$WINETRICKS_IMG"
    then
        winetricks_mount_cached_iso
    else
        if test "$WINETRICKS_OPT_KEEPISOS" = 0 || test "$2"
        then
            while true
            do
                winetricks_mount_real_volume "$1"
                if test "$2" = "" || test -f "$W_ISO_MOUNT_ROOT/$2"
                then
                    break
                else
                    w_warn "Wrong disc inserted, $2 not found."
                fi
            done
        fi

        case "$WINETRICKS_OPT_KEEPISOS" in
        1)
            winetricks_cache_iso "$1"
            winetricks_mount_cached_iso
            ;;
        esac
    fi
}

w_umount()
{
    if test "$WINE" = ""
    then
        # Windows
        winetricks_load_vcdmount
        w_try_cd "$VCD_DIR"
        w_try vcdmount.exe /u
    else
        echo "Running $WINETRICKS_SUDO umount $W_ISO_MOUNT_ROOT"
        case "$WINETRICKS_SUDO" in
        gksudo)
          # -l lazy unmount in case executable still running
          "$WINETRICKS_SUDO" "umount -l $W_ISO_MOUNT_ROOT"
          w_try "$WINETRICKS_SUDO" "rm -rf $W_ISO_MOUNT_ROOT"
          ;;
        *)
          "$WINETRICKS_SUDO" "umount -l $W_ISO_MOUNT_ROOT"
          w_try "$WINETRICKS_SUDO" "rm -rf $W_ISO_MOUNT_ROOT"
          ;;
        esac
        "$WINE" eject "${W_ISO_MOUNT_LETTER}:"
        rm -f "$WINEPREFIX/dosdevices/${W_ISO_MOUNT_LETTER}:"
        rm -f "$WINEPREFIX/dosdevices/${W_ISO_MOUNT_LETTER}::"
    fi
}

w_ahk_do()
{
    if ! test -f "$W_CACHE/ahk/AutoHotkey.exe"
    then
        W_BROWSERAGENT=1 \
        w_download_to ahk https://www.autohotkey.com/download/AutoHotkey104805.zip c8bf1c3dc4622559963b6626316ba1d083bb8a8af605f78382e371e5294d435a
        w_try_unzip "$W_CACHE/ahk" "$W_CACHE/ahk/AutoHotkey104805.zip" AutoHotkey.exe AU3_Spy.exe
        chmod +x "$W_CACHE/ahk/AutoHotkey.exe"
    fi

    # Previously this used printf + sed, but that was broken with BSD sed (FreeBSD/OS X):
    # https://github.com/Winetricks/winetricks/issues/697
    # So now using trying awk instead (next, perl):
    cat <<_EOF_ | awk 'sub("$", "\r")' > "$W_TMP"/tmp.ahk
w_opt_unattended = ${W_OPT_UNATTENDED:-0}
$@
_EOF_
    w_try "$WINE" "$W_CACHE_WIN\\ahk\\AutoHotkey.exe" "$W_TMP_WIN"\\tmp.ahk
}

# Function to protect Wine-specific sections of code.
# Outputs a message to console explaining what's being skipped.
# Usage:
#   if w_skip_windows name-of-operation
#   then
#      return
#   fi
#   ... do something that doesn't make sense on Windows ...

w_skip_windows()
{
    case "$W_PLATFORM" in
     windows_cmd)
        echo "Skipping operation '$1' on Windows"
        return 0
        ;;
    esac
    return 1
}

w_override_dlls()
{
    w_skip_windows w_override_dlls && return

    _W_mode=$1
    case $_W_mode in
    *=*)
        w_die "w_override_dlls: unknown mode $_W_mode.
Usage: 'w_override_dlls mode[,mode] dll ...'." ;;
    disabled)
        _W_mode="" ;;
    esac
    shift
    echo "Using $_W_mode override for following DLLs: $*"
    cat > "$W_TMP"/override-dll.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\DllOverrides]
_EOF_
    while test "$1" != ""
    do
        case "$1" in
        comctl32)
           rm -rf "$W_WINDIR_UNIX"/winsxs/manifests/x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.2600.2982_none_deadbeef.manifest
           ;;
        esac

        if [ "$_W_mode" = default ]
        then
            # To delete a registry key, give an unquoted dash as value
            echo "\"*$1\"=-" >> "$W_TMP"/override-dll.reg
        else
            # Note: if you want to override even DLLs loaded with an absolute
            # path, you need to add an asterisk:
            echo "\"*$1\"=\"$_W_mode\"" >> "$W_TMP"/override-dll.reg
            #echo "\"$1\"=\"$_W_mode\"" >> "$W_TMP"/override-dll.reg
        fi

        shift
    done

    w_try_regedit "$W_TMP_WIN"\\override-dll.reg

    unset _W_mode
}

w_override_no_dlls()
{
    w_skip_windows override && return

    "$WINE" regedit /d 'HKEY_CURRENT_USER\Software\Wine\DllOverrides'
}

w_override_all_dlls()
{
    # Disable all known native Microsoft DLLs in favor of Wine's built-in ones
    # Generated with
    # find ~/wine-git/dlls -maxdepth 1 -type d -print | sed 's,.*/,,' | sort | fmt -50 | sed 's/$/ \\/'
    # Last updated: 2015-09-28
    w_override_dlls builtin \
        acledit aclui activeds actxprxy adsiid advapi32 \
        advpack amstream api-ms-win-core-com-l1-1-0 \
        api-ms-win-core-console-l1-1-0 \
        api-ms-win-core-datetime-l1-1-0 \
        api-ms-win-core-datetime-l1-1-1 \
        api-ms-win-core-debug-l1-1-0 \
        api-ms-win-core-debug-l1-1-1 \
        api-ms-win-core-errorhandling-l1-1-0 \
        api-ms-win-core-errorhandling-l1-1-1 \
        api-ms-win-core-errorhandling-l1-1-2 \
        api-ms-win-core-fibers-l1-1-0 \
        api-ms-win-core-fibers-l1-1-1 \
        api-ms-win-core-file-l1-1-0 \
        api-ms-win-core-file-l1-2-0 \
        api-ms-win-core-file-l2-1-0 \
        api-ms-win-core-file-l2-1-1 \
        api-ms-win-core-handle-l1-1-0 \
        api-ms-win-core-heap-l1-1-0 \
        api-ms-win-core-heap-l1-2-0 \
        api-ms-win-core-heap-obsolete-l1-1-0 \
        api-ms-win-core-interlocked-l1-1-0 \
        api-ms-win-core-interlocked-l1-2-0 \
        api-ms-win-core-io-l1-1-1 \
        api-ms-win-core-kernel32-legacy-l1-1-0 \
        api-ms-win-core-libraryloader-l1-1-0 \
        api-ms-win-core-libraryloader-l1-1-1 \
        api-ms-win-core-localization-l1-2-0 \
        api-ms-win-core-localization-l1-2-1 \
        api-ms-win-core-localization-obsolete-l1-1-0 \
        api-ms-win-core-localregistry-l1-1-0 \
        api-ms-win-core-memory-l1-1-0 \
        api-ms-win-core-memory-l1-1-1 \
        api-ms-win-core-misc-l1-1-0 \
        api-ms-win-core-namedpipe-l1-1-0 \
        api-ms-win-core-namedpipe-l1-2-0 \
        api-ms-win-core-processenvironment-l1-1-0 \
        api-ms-win-core-processenvironment-l1-2-0 \
        api-ms-win-core-processthreads-l1-1-0 \
        api-ms-win-core-processthreads-l1-1-1 \
        api-ms-win-core-processthreads-l1-1-2 \
        api-ms-win-core-profile-l1-1-0 \
        api-ms-win-core-psapi-l1-1-0 \
        api-ms-win-core-registry-l1-1-0 \
        api-ms-win-core-rtlsupport-l1-1-0 \
        api-ms-win-core-rtlsupport-l1-2-0 \
        api-ms-win-core-shlwapi-legacy-l1-1-0 \
        api-ms-win-core-string-l1-1-0 \
        api-ms-win-core-synch-l1-1-0 \
        api-ms-win-core-synch-l1-2-0 \
        api-ms-win-core-sysinfo-l1-1-0 \
        api-ms-win-core-sysinfo-l1-2-0 \
        api-ms-win-core-sysinfo-l1-2-1 \
        api-ms-win-core-threadpool-legacy-l1-1-0 \
        api-ms-win-core-timezone-l1-1-0 \
        api-ms-win-core-url-l1-1-0 \
        api-ms-win-core-util-l1-1-0 \
        api-ms-win-core-winrt-error-l1-1-0 \
        api-ms-win-core-winrt-error-l1-1-1 \
        api-ms-win-core-winrt-l1-1-0 \
        api-ms-win-core-winrt-string-l1-1-0 \
        api-ms-win-core-xstate-l2-1-0 \
        api-ms-win-crt-conio-l1-1-0 \
        api-ms-win-crt-convert-l1-1-0 \
        api-ms-win-crt-environment-l1-1-0 \
        api-ms-win-crt-filesystem-l1-1-0 \
        api-ms-win-crt-heap-l1-1-0 \
        api-ms-win-crt-locale-l1-1-0 \
        api-ms-win-crt-math-l1-1-0 \
        api-ms-win-crt-multibyte-l1-1-0 \
        api-ms-win-crt-private-l1-1-0 \
        api-ms-win-crt-process-l1-1-0 \
        api-ms-win-crt-runtime-l1-1-0 \
        api-ms-win-crt-stdio-l1-1-0 \
        api-ms-win-crt-string-l1-1-0 \
        api-ms-win-crt-time-l1-1-0 \
        api-ms-win-crt-utility-l1-1-0 \
        api-ms-win-downlevel-advapi32-l1-1-0 \
        api-ms-win-downlevel-advapi32-l2-1-0 \
        api-ms-win-downlevel-normaliz-l1-1-0 \
        api-ms-win-downlevel-ole32-l1-1-0 \
        api-ms-win-downlevel-shell32-l1-1-0 \
        api-ms-win-downlevel-shlwapi-l1-1-0 \
        api-ms-win-downlevel-shlwapi-l2-1-0 \
        api-ms-win-downlevel-user32-l1-1-0 \
        api-ms-win-downlevel-version-l1-1-0 \
        api-ms-win-eventing-provider-l1-1-0 \
        api-ms-win-ntuser-dc-access-l1-1-0 \
        api-ms-win-security-base-l1-1-0 \
        api-ms-win-security-base-l1-2-0 \
        api-ms-win-security-sddl-l1-1-0 \
        api-ms-win-service-core-l1-1-1 \
        api-ms-win-service-management-l1-1-0 \
        api-ms-win-service-winsvc-l1-2-0 apphelp \
        appwiz.cpl atl atl100 atl110 atl80 atl90 authz \
        avicap32 avifil32 avifile.dll16 avrt bcrypt \
        browseui cabinet capi2032 cards cfgmgr32 clusapi \
        combase comcat comctl32 comdlg32 commdlg.dll16 \
        comm.drv16 compobj.dll16 compstui comsvcs connect \
        credui crtdll crypt32 cryptdlg cryptdll cryptext \
        cryptnet cryptui ctapi32 ctl3d32 ctl3d.dll16 \
        ctl3dv2.dll16 d2d1 d3d10 d3d10_1 d3d10core \
        d3d11 d3d8 d3d9 d3dcompiler_33 d3dcompiler_34 \
        d3dcompiler_35 d3dcompiler_36 d3dcompiler_37 \
        d3dcompiler_38 d3dcompiler_39 d3dcompiler_40 \
        d3dcompiler_41 d3dcompiler_42 d3dcompiler_43 \
        d3dcompiler_46 d3dcompiler_47 d3dim d3drm \
        d3dx10_33 d3dx10_34 d3dx10_35 d3dx10_36 d3dx10_37 \
        d3dx10_38 d3dx10_39 d3dx10_40 d3dx10_41 d3dx10_42 \
        d3dx10_43 d3dx11_42 d3dx11_43 d3dx9_24 d3dx9_25 \
        d3dx9_26 d3dx9_27 d3dx9_28 d3dx9_29 d3dx9_30 \
        d3dx9_31 d3dx9_32 d3dx9_33 d3dx9_34 d3dx9_35 \
        d3dx9_36 d3dx9_37 d3dx9_38 d3dx9_39 d3dx9_40 \
        d3dx9_41 d3dx9_42 d3dx9_43 d3dxof davclnt \
        dbgeng dbghelp dciman32 ddeml.dll16 ddraw \
        ddrawex devenum dhcpcsvc difxapi dinput \
        dinput8 dispdib.dll16 dispex display.drv16 \
        dlls dmband dmcompos dmime dmloader dmscript \
        dmstyle dmsynth dmusic dmusic32 dnsapi dplay \
        dplayx dpnaddr dpnet dpnhpast dpnlobby dpvoice \
        dpwsockx drmclien dsound dssenh dswave dwmapi \
        dwrite dxdiagn dxerr8 dxerr9 dxgi dxguid dxva2 \
        evr explorerframe ext-ms-win-gdi-devcaps-l1-1-0 \
        faultrep fltlib fntcache fontsub fusion fwpuclnt \
        gameux gdi32 gdi.exe16 gdiplus glu32 gphoto2.ds \
        gpkcsp hal hhctrl.ocx hid hidclass.sys hlink \
        hnetcfg httpapi iccvid icmp ieframe ifsmgr.vxd \
        imaadp32.acm imagehlp imm32 imm.dll16 inetcomm \
        inetcpl.cpl inetmib1 infosoft initpki inkobj \
        inseng iphlpapi itircl itss joy.cpl jscript \
        jsproxy kernel32 keyboard.drv16 krnl386.exe16 \
        ksuser ktmw32 loadperf localspl localui lz32 \
        lzexpand.dll16 mapi32 mapistub mciavi32 mcicda \
        mciqtz32 mciseq mciwave mf mfplat mfreadwrite \
        mgmtapi midimap mlang mmcndmgr mmdevapi \
        mmdevldr.vxd mmsystem.dll16 monodebg.vxd \
        mountmgr.sys mouse.drv16 mpr mprapi msacm32 \
        msacm32.drv msacm.dll16 msadp32.acm msasn1 \
        mscat32 mscms mscoree msctf msctfp msdaps \
        msdmo msftedit msg711.acm msgsm32.acm mshtml \
        mshtml.tlb msi msident msimg32 msimsg msimtf \
        msisip msisys.ocx msls31 msnet32 mspatcha msrle32 \
        msscript.ocx mssign32 mssip32 mstask msvcirt \
        msvcm80 msvcm90 msvcp100 msvcp110 msvcp120 \
        msvcp120_app msvcp60 msvcp70 msvcp71 msvcp80 \
        msvcp90 msvcr100 msvcr110 msvcr120 msvcr120_app \
        msvcr70 msvcr71 msvcr80 msvcr90 msvcrt msvcrt20 \
        msvcrt40 msvcrtd msvfw32 msvidc32 msvideo.dll16 \
        mswsock msxml msxml2 msxml3 msxml4 msxml6 \
        nddeapi ndis.sys netapi32 netcfgx netprofm \
        newdev normaliz npmshtml npptools ntdll ntdsapi \
        ntoskrnl.exe ntprint objsel odbc32 odbccp32 \
        odbccu32 ole2conv.dll16 ole2disp.dll16 ole2.dll16 \
        ole2nls.dll16 ole2prox.dll16 ole2thk.dll16 \
        ole32 oleacc oleaut32 olecli32 olecli.dll16 \
        oledb32 oledlg olepro32 olesvr32 olesvr.dll16 \
        olethk32 openal32 opencl opengl32 packager pdh \
        photometadatahandler pidgen powrprof printui \
        prntvpt propsys psapi pstorec qcap qedit qmgr \
        qmgrprxy quartz query rasapi16.dll16 rasapi32 \
        rasdlg regapi resutils riched20 riched32 \
        rpcrt4 rsabase rsaenh rstrtmgr rtutils \
        samlib sane.ds scarddlg sccbase schannel \
        schedsvc scrrun scsiport.sys secur32 security \
        sensapi serialui setupapi setupx.dll16 sfc \
        sfc_os shdoclc shdocvw shell32 shell.dll16 \
        shfolder shlwapi slbcsp slc snmpapi softpub \
        sound.drv16 spoolss stdole2.tlb stdole32.tlb \
        sti storage.dll16 stress.dll16 strmbase strmiids \
        svrapi sxs system.drv16 t2embed tapi32 taskschd \
        toolhelp.dll16 traffic twain_32 twain.dll16 \
        typelib.dll16 ucrtbase unicows updspapi url \
        urlmon usbd.sys user32 userenv user.exe16 usp10 \
        uuid uxtheme vbscript vcomp vcomp100 vcomp110 \
        vcomp90 vdhcp.vxd vdmdbg ver.dll16 version \
        vmm.vxd vnbt.vxd vnetbios.vxd vssapi vtdapi.vxd \
        vwin32.vxd w32skrnl w32sys.dll16 wbemdisp \
        wbemprox webservices wer wevtapi wiaservc \
        win32s16.dll16 win87em.dll16 winaspi.dll16 \
        windebug.dll16 windowscodecs windowscodecsext \
        winealsa.drv winecoreaudio.drv winecrt0 wined3d \
        winegstreamer winejoystick.drv winemac.drv \
        winemapi winemp3.acm wineoss.drv wineps16.drv16 \
        wineps.drv wineqtdecoder winex11.drv wing32 \
        wing.dll16 winhttp wininet winmm winnls32 \
        winnls.dll16 winscard winsock.dll16 winspool.drv \
        winsta wintab32 wintab.dll16 wintrust wlanapi \
        wldap32 wmi wmiutils wmp wmvcore wnaspi32 wow32 \
        wpcap ws2_32 wshom.ocx wsnmp32 wsock32 wtsapi32 \
        wuapi wuaueng x3daudio1_1 x3daudio1_2 x3daudio1_3 \
        x3daudio1_4 x3daudio1_5 x3daudio1_6 x3daudio1_7 \
        xapofx1_1 xapofx1_3 xapofx1_4 xapofx1_5 xaudio2_7 \
        xaudio2_8 xinput1_1 xinput1_2 xinput1_3 xinput1_4 \
        xinput9_1_0 xmllite xolehlp xpsprint xpssvcs \

        # blank line so you don't have to remove the extra trailing \
}

w_override_app_dlls()
{
    w_skip_windows w_override_app_dlls && return

    _W_app=$1
    shift
    _W_mode=$1
    shift

    # Fixme: handle comma-separated list of modes
    case $_W_mode in
    b|builtin) _W_mode=builtin ;;
    n|native) _W_mode=native ;;
    default) _W_mode=default ;;
    d|disabled) _W_mode="" ;;
    *)
        w_die "w_override_app_dlls: unknown mode $_W_mode.  (want native, builtin, default, or disabled)
Usage: 'w_override_app_dlls app mode dll ...'." ;;
    esac

    echo "Using $_W_mode override for following DLLs when running $_W_app: $*"
    (
    echo REGEDIT4
    echo ""
    echo "[HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\$_W_app\\DllOverrides]"
    ) > "$W_TMP"/override-dll.reg

    while test "$1" != ""
    do
        case "$1" in
        comctl32)
           rm -rf "$W_WINDIR_UNIX"/winsxs/manifests/x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.2600.2982_none_deadbeef.manifest
           ;;
        esac
        if [ "$_W_mode" = default ]
        then
            # To delete a registry key, give an unquoted dash as value
            echo "\"*$1\"=-" >> "$W_TMP"/override-dll.reg
        else
            # Note: if you want to override even DLLs loaded with an absolute
            # path, you need to add an asterisk:
            echo "\"*$1\"=\"$_W_mode\"" >> "$W_TMP"/override-dll.reg
            #echo "\"$1\"=\"$_W_mode\"" >> "$W_TMP"/override-dll.reg
        fi
        shift
    done

    w_try_regedit "$W_TMP_WIN"\\override-dll.reg
    rm "$W_TMP"/override-dll.reg
    unset _W_app _W_mode
}

# Has to be set in a few places...
w_set_winver()
{
    w_skip_windows w_set_winver && return
    # FIXME: This should really be done with winecfg, but it has no CLI options.

    # First, delete any lingering version info, otherwise it may conflict:
    (
    "$WINE" reg delete "HKLM\Software\Microsoft\Windows\CurrentVersion" /v SubVersionNumber /f || true
    "$WINE" reg delete "HKLM\Software\Microsoft\Windows\CurrentVersion" /v VersionNumber /f || true
    "$WINE" reg delete "HKLM\Software\Microsoft\Windows NT\CurrentVersion" /v CSDVersion /f || true
    "$WINE" reg delete "HKLM\Software\Microsoft\Windows NT\CurrentVersion" /v CurrentBuildNumber /f || true
    "$WINE" reg delete "HKLM\Software\Microsoft\Windows NT\CurrentVersion" /v CurrentVersion /f || true
    "$WINE" reg delete "HKLM\System\CurrentControlSet\Control\ProductOptions" /v ProductType /f || true
    "$WINE" reg delete "HKLM\System\CurrentControlSet\Control\ServiceCurrent" /v OS /f || true
    "$WINE" reg delete "HKLM\System\CurrentControlSet\Control\Windows" /v CSDVersion /f || true
    "$WINE" reg delete "HKCU\Software\Wine" /v Version /f || true
    "$WINE" reg delete "HKLM\\System\\CurrentControlSet\\Control\\ProductOptions" /v ProductType /f || true
    ) > /dev/null 2>&1

    case "$1" in
    win31)
        echo "Setting Windows version to $1"
        cat > "$W_TMP"/set-winver.reg <<_EOF_
REGEDIT4

[HKEY_USERS\S-1-5-4\Software\Wine]
"Version"="win31"

_EOF_

        w_try_regedit "$W_TMP_WIN"\\set-winver.reg
        return
        ;;
    win95)
        # This key is only used for Windows 95/98:

        echo "Setting Windows version to $1"
        cat > "$W_TMP"/set-winver.reg <<_EOF_
REGEDIT4

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion]
"ProductName"="Microsoft Windows 95"
"SubVersionNumber"=""
"VersionNumber"="4.0.950"

_EOF_
        w_try_regedit "$W_TMP_WIN"\\set-winver.reg
        return
        ;;
    win98)
        # This key is only used for Windows 95/98:

        echo "Setting Windows version to $1"
        cat > "$W_TMP"/set-winver.reg <<_EOF_
REGEDIT4

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion]
"ProductName"="Microsoft Windows 98"
"SubVersionNumber"=" A "
"VersionNumber"="4.10.2222"

_EOF_
        w_try_regedit "$W_TMP_WIN"\\set-winver.reg
        return
        ;;
    nt40)
        # Similar to modern version, but sets two extra keys:

        echo "Setting Windows version to $1"
        cat > "$W_TMP"/set-winver.reg <<_EOF_
REGEDIT4

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion]
"CSDVersion"="Service Pack 6a"
"CurrentBuildNumber"="1381"
"CurrentVersion"="4.0"

[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\ProductOptions]
"ProductType"="WinNT"

[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\ServiceCurrent]
"OS"="Windows_NT"

[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Windows]
"CSDVersion"=dword:00000600

_EOF_
        w_try_regedit "$W_TMP_WIN"\\set-winver.reg
        return
        ;;
    win2k)
        csdversion="Service Pack 4"
        currentbuildnumber="2195"
        currentversion="5.0"
        csdversion_hex=dword:00000400
        ;;
    winxp)
        csdversion="Service Pack 3"
        currentbuildnumber="2600"
        currentversion="5.1"
        csdversion_hex=dword:00000300
        ;;
    win2k3)
        csdversion="Service Pack 2"
        currentbuildnumber="3790"
        currentversion="5.2"
        csdversion_hex=dword:00000200
        "$WINE" reg add "HKLM\\System\\CurrentControlSet\\Control\\ProductOptions" /v ProductType /d "ServerNT" /f
        ;;
    vista)
        csdversion="Service Pack 2"
        currentbuildnumber="6002"
        currentversion="6.0"
        csdversion_hex=dword:00000200
        "$WINE" reg add "HKLM\\System\\CurrentControlSet\\Control\\ProductOptions" /v ProductType /d "WinNT" /f
        ;;
    win7)
        csdversion="Service Pack 1"
        currentbuildnumber="7601"
        currentversion="6.1"
        csdversion_hex=dword:00000100
        "$WINE" reg add "HKLM\\System\\CurrentControlSet\\Control\\ProductOptions" /v ProductType /d "WinNT" /f
        ;;
    win2k8)
        csdversion="Service Pack 1"
        currentbuildnumber="7601"
        currentversion="6.1"
        csdversion_hex=dword:00000100
        "$WINE" reg add "HKLM\\System\\CurrentControlSet\\Control\\ProductOptions" /v ProductType /d "ServerNT" /f
        ;;
    win8)
        csdversion=""
        currentbuildnumber="9200"
        currentversion="6.2"
        csdversion_hex=dword:00000000
        "$WINE" reg add "HKLM\\System\\CurrentControlSet\\Control\\ProductOptions" /v ProductType /d "WinNT" /f
        ;;
    win81)
        csdversion=""
        currentbuildnumber="9600"
        currentversion="6.3"
        csdversion_hex=dword:00000000
        "$WINE" reg add "HKLM\\System\\CurrentControlSet\\Control\\ProductOptions" /v ProductType /d "WinNT" /f
        ;;
    win10)
        csdversion=""
        currentbuildnumber="10240"
        currentversion="10.0"
        csdversion_hex=dword:00000000
        "$WINE" reg add "HKLM\\System\\CurrentControlSet\\Control\\ProductOptions" /v ProductType /d "WinNT" /f
        ;;
    *)
        w_die "Invalid Windows version given."
        ;;
    esac

    echo "Setting Windows version to $1"
    cat > "$W_TMP"/set-winver.reg <<_EOF_
REGEDIT4

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion]
"CSDVersion"="$csdversion"
"CurrentBuildNumber"="$currentbuildnumber"
"CurrentVersion"="$currentversion"

[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Windows]
"CSDVersion"=$csdversion_hex

_EOF_
    w_try_regedit "$W_TMP_WIN"\\set-winver.reg

    # Prevent a race when calling from another verb
    "$WINESERVER" -w
}

w_unset_winver()
{
    w_set_winver winxp
}

# Present app $1 with the Windows personality $2
w_set_app_winver()
{
    w_skip_windows w_set_app_winver && return

    _W_app="$1"
    _W_version="$2"
    echo "Setting $_W_app to $_W_version mode"
    (
    echo REGEDIT4
    echo ""
    echo "[HKEY_CURRENT_USER\\Software\\Wine\\AppDefaults\\$_W_app]"
    echo "\"Version\"=\"$_W_version\""
    ) > "$W_TMP"/set-winver.reg

    w_try_regedit "$W_TMP_WIN"\\set-winver.reg
    rm "$W_TMP"/set-winver.reg
    unset _W_app
}

# Usage: w_wine_version OP VALUE
# All the integer comparison operators of 'test' are supported, since 'test' does the work.
# Example:
#  if w_wine_version -gt 1.3.2
#  then
#      ...
#  fi
w_wine_version()
{
    # Note, there are also hacks for major releases (1.6/1.8/2.0/etc. and RCs) in winetricks_init()
    #
    # Parse major/minor/micro/nano fields of VALUE.  Ignore nano.
    case $2 in
    0*|1.0|1.0.*) w_die "bug: $2 is before 1.1, we don't bother with bugs fixed that long ago" ;;
    1.1.*) _W_minor=1; _W_micro=$(echo "$2" | sed 's/.*\.//');;
    1.2) _W_minor=2; _W_micro=0;;
    1.2.*) _W_minor=2; _W_micro=$(echo "$2" | sed 's/.*\.//');;
    1.3.*) _W_minor=3; _W_micro=$(echo "$2" | sed 's/.*\.//');;
    1.4) _W_minor=4; _W_micro=0;;
    1.4.*) _W_minor=4; _W_micro=$(echo "$2" | sed 's/.*\.//');;
    1.5.*) _W_minor=5; _W_micro=$(echo "$2" | sed 's/.*\.//');;
    1.6|1.6-rc*) _W_minor=6; _W_micro=0;;
    1.6.*) _W_minor=6; _W_micro=$(echo "$2" | sed 's/.*\.//');;
    1.7.*) _W_minor=7; _W_micro=$(echo "$2" | sed 's/.*\.//');;
    1.8.*) _W_minor=8; _W_micro=$(echo "$2" | sed 's/.*\.//');;
    1.9.*) _W_minor=9; _W_micro=$(echo "$2" | sed 's/.*\.//');;

    # Rather than rework numbering system to handle both, just consider 2.x+ as 1.10, 1.11, etc.
    2.0|2.0-rc*) _W_minor=10; _W_micro=0;;
    2.0.*|2.*) _W_minor=10; _W_micro=$(echo "$2" | sed 's/.*\.//');;
    3.0|3.0-rc*) _W_minor=11; _W_micro=0;;
    3.0.*|3.*) _W_minor=11; _W_micro=$(echo "$2" | sed 's/.*\.//');;

    *) w_die "bug: unrecognized version $2";;
    esac

    # Comparing current wine version 1.$WINETRICKS_WINE_MINOR.$WINETRICKS_WINE_MICRO against 1.$_W_minor.$_W_micro
    if test "$WINETRICKS_WINE_MINOR" = "$_W_minor"
    then
        test "$WINETRICKS_WINE_MICRO" "$1" "$_W_micro" || return 1
    else
        test "$WINETRICKS_WINE_MINOR" "$1" "$_W_minor" || return 1
    fi
}

# Built-in self test for w_wine_version
#echo Verify that version 1.3.4 is equal to itself
#WINETRICKS_WINE_MINOR=3 WINETRICKS_WINE_MICRO=4 w_wine_version -eq 1.3.4 || w_die "fail test case wine-1.3.4 = 1.3.4"
#echo Verify that version 1.3.4 is greater than 1.2
#WINETRICKS_WINE_MINOR=3 WINETRICKS_WINE_MICRO=4 w_wine_version -gt 1.2 || w_die "fail test case wine-1.3.4 > wine-1.2"
#echo Verify that version 1.6 is greater than 1.2
#WINETRICKS_WINE_MINOR=6 WINETRICKS_WINE_MICRO=0 w_wine_version -gt 1.2 || w_die "fail test case wine-1.6 > wine-1.2"
# FIXME: 2.x tests

# Usage: w_wine_version_in range ...
# True if wine version in any of the given ranges
# 'range' can be
#    val1,   (for >= val1)
#    ,val2   (for <= val2)
#    val1,val2 (for >= val1 && <= val2)
w_wine_version_in()
{
   for _W_range
   do
     _W_val1=$(echo "$_W_range" | sed 's/,.*//')
     _W_val2=$(echo "$_W_range" | sed 's/.*,//')

     # If in this range, return true
     case $_W_range in
     ,*)                                  w_wine_version   -le "$_W_val2" && unset _W_range _W_val1 _W_val2 && return 0;;
     *,) w_wine_version -ge "$_W_val1"                                    && unset _W_range _W_val1 _W_val2 && return 0;;
     *)  w_wine_version -ge "$_W_val1" && w_wine_version   -le "$_W_val2" && unset _W_range _W_val1 _W_val2 && return 0;;
     esac
   done
   unset _W_range _W_val1 _W_val2
   return 1
}

# Built-in self test for w_wine_version_in
#w_wine_version_in_test()
#{
#    WINETRICKS_WINE_MINOR=$1 WINETRICKS_WINE_MICRO=$2 w_wine_version_in $3 $4 $5 $6 || w_die "fail test case wine-1.$1.$2 in $3 $4 $5 $6"
#}
#w_wine_version_not_in_test()
#{
#    WINETRICKS_WINE_MINOR=$1 WINETRICKS_WINE_MICRO=$2 w_wine_version_in $3 $4 $5 $6 && w_die "fail test case wine-1.$1.$2 in $3 $4 $5 $6"
#}
#echo Verify that version 1.2.0 is in the range 1.2,
#w_wine_version_in_test 2 0  1.2,
#echo Verify that version 1.3.4 is in the range 1.2,
#w_wine_version_in_test 3 4  1.2,
#echo Verify that version 1.3 is not in the range ,1.2
#w_wine_version_not_in_test 3 0  ,1.2
#echo Verify that version 1.6-rc1 is in the range 1.2,
#w_wine_version_in_test 6 0  1.2,
#echo test passed

# Usage: workaround_wine_bug bugnumber [message] [good-wine-version-range ...]
# Returns true and outputs given msg if the workaround needs to be applied.
# For debugging: if you want to skip a bug's workaround, put the bug number in
# the environment variable WINETRICKS_BLACKLIST to disable it.
w_workaround_wine_bug()
{
    if test "$WINE" = ""
    then
        echo "No need to work around wine bug $1 on Windows"
        return 1
    fi
    case "$2" in
    [0-9]*) w_die "bug: want message in w_workaround_wine_bug arg 2, got $2" ;;
    "") _W_msg="";;
    *)  _W_msg="-- $2";;
    esac

    # shellcheck disable=SC2086
    if test "$3" && w_wine_version_in $3 $4 $5 $6
    then
        echo "Current Wine does not have Wine bug $1, so not applying workaround"
        return 1
    fi

    case "$1" in
    "$WINETRICKS_BLACKLIST")
        echo "Wine bug $1 workaround blacklisted, skipping"
        return 1
        ;;
    esac
    case $LANG in
    da*) w_warn "Arbejder uden om wine-fejl ${1} $_W_msg" ;;
    de*) w_warn "Wine-Fehler ${1} wird umgegangen $_W_msg" ;;
    pl*) w_warn "Obchodzenie błędu w wine ${1} $_W_msg" ;;
    ru*) w_warn "Обход ошибки ${1} $_W_msg" ;;
    uk*) w_warn "Обхід помилки ${1} $_W_msg" ;;
    zh_CN*)   w_warn "绕过 wine bug ${1} $_W_msg" ;;
    zh_TW*|zh_HK*)   w_warn "繞過 wine bug ${1} $_W_msg" ;;
    *)   w_warn "Working around wine bug ${1} $_W_msg" ;;
    esac
    winetricks_stats_log_command "w_workaround_wine_bug-$1"
    return 0
}

# Function for verbs to register themselves so they show up in the menu.
# Example:
# w_metadata wog games \
#   title="World of Goo Demo" \
#   pub="2D Boy" \
#   year="2008" \
#   media="download" \
#   file1="WorldOfGooDemo.1.0.exe"

w_metadata()
{
    case $WINETRICKS_OPT_VERBOSE in
        2) set -x ;;
        *) set +x ;;
    esac

    # shellcheck disable=SC2154
    if test "$installed_exe1" || test "$installed_file1" || test "$publisher" || test "$year"
    then
        w_die "bug: stray metadata tags set: somebody forgot a backslash in a w_metadata somewhere.  Run with sh -x to see where."
    fi
    if winetricks_metadata_exists "$1"
    then
        w_die "bug: a verb named $1 already exists."
    fi

    _W_md_cmd="$1"
    _W_category="$2"
    file="$WINETRICKS_METADATA/$_W_category/$1.vars"
    shift
    shift
    # Echo arguments to file, with double quotes around the values.
    # Used to use Perl here, but that was too slow on Cygwin.
    for arg
    do
        case "$arg" in
        installed_exe1=/*)
            w_die "bug: w_metadata $_W_md_cmd has a unix path for installed_exe1, should be a windows path";;
        installed_file1=/*)
            w_die "bug: w_metadata $_W_md_cmd has a unix path for installed_file1, should be a windows path";;
        media=download_manual)
            w_die "bug: verb $_W_md_cmd has media=download_manual, should be manual_download" ;;
        esac
        # Use longest match when stripping value,
        # and shortest match when stripping name,
        # so descriptions can have embedded equals signs
        # FIXME: backslashes get interpreted here.  This screws up
        # installed_file1 fairly often.  Fortunately, we can use forward
        # slashes in that variable instead of backslashes.
        echo "${arg%%=*}"=\""${arg#*=}"\"
    done > "$file"
    echo category='"'"$_W_category"'"' >> "$file"
    # If the problem described above happens, you'd see errors like this:
    # /tmp/w.dank.4650/metadata/dlls/comctl32.vars: 6: Syntax error: Unterminated quoted string
    # so check for lines that aren't properly quoted.

    # Do sanity check unless running on Cygwin, where it's way too slow.
    case "$W_PLATFORM" in
     windows_cmd)
        ;;
    *)
        if grep '[^"]$' "$file"
        then
            w_die "bug: w_metadata $_W_md_cmd corrupt, might need forward slashes?"
        fi
        ;;
    esac
    unset _W_md_cmd

    # Restore verbosity:
    case $WINETRICKS_OPT_VERBOSE in
        1|2) set -x ;;
        *) set +x ;;
    esac
}

# Function for verbs to register their main executable [or, if name is given, other executables]
# Deprecated. No-op for backwards compatibility
w_declare_exe()
{
    w_warn "w_declare_exe is deprecated, now a noop"
}

# Checks that a conflicting verb is not already installed in the prefix
# Usage: w_conflicts verb_to_install conflicts
w_conflicts()
{
    for x in $2
    do
        if grep -qw "$x" "$WINEPREFIX/winetricks.log"
        then
            w_die "error: $1 conflicts with $x, which is already installed."
        fi
    done
}

# Call a verb, don't let it affect environment
# Hope that subshell passes through exit status
# Usage: w_do_call foo [bar]       (calls load_foo bar)
# Or: w_do_call foo=bar            (also calls load_foo bar)
# Or: w_do_call foo                (calls load_foo)
w_do_call()
{
    (
        # Hack..
        if test "$cmd" = vd
        then
            load_vd "$arg"
            _W_status=$?
            test "$W_OPT_NOCLEAN" = 1 || rm -rf "$W_TMP"
            mkdir -p "$W_TMP"
            return $_W_status
        fi

        case "$1" in
        *=*) arg=$(echo "$1" | sed 's/.*=//'); cmd=$(echo "$1" | sed 's/=.*//');;
        *) cmd=$1; arg=$2 ;;
        esac

        # Kludge: use Temp instead of temp to avoid \t expansion in w_try
        # but use temp in Unix path because that's what Wine creates, and having both temp and Temp
        # causes confusion (e.g. makes vc2005trial fail)
        # FIXME: W_TMP is also set in winetricks_set_wineprefix, can we avoid the duplication?
        W_TMP="$W_DRIVE_C/windows/temp/_$1"
        W_TMP_WIN="C:\\windows\\Temp\\_$1"
        test "$W_OPT_NOCLEAN" = 1 || rm -rf "$W_TMP"
        mkdir -p "$W_TMP"

        # Unset all known used metadata values, in case this is a nested call
        unset conflicts installed_file1 installed_exe1

        if winetricks_metadata_exists "$1"
        then
            # shellcheck disable=SC1090
            . "$WINETRICKS_METADATA"/*/"${1}.vars"
        elif winetricks_metadata_exists "$cmd"
        then
            # shellcheck disable=SC1090
            . "$WINETRICKS_METADATA"/*/"${cmd}.vars"
        elif test "$cmd" = native || test "$cmd" = disabled || test "$cmd" = builtin || test "$cmd" = default
        then
            # ugly special case - can't have metadata for these verbs until we allow arbitrary parameters
            w_override_dlls "$cmd" "$arg"
            _W_status=$?
            test "$W_OPT_NOCLEAN" = 1 || rm -rf "$W_TMP"
            mkdir -p "$W_TMP"
            return $_W_status
        else
            w_die "No such verb $1"
        fi

        # If needed, set the app's wineprefix
        case "$W_PLATFORM" in
            windows_cmd|wine_cmd)
            ;;
        *)
            # shellcheck disable=SC2154
            case "${category}-${WINETRICKS_OPT_SHAREDPREFIX}" in
            apps-0|benchmarks-0|games-0)
                winetricks_set_wineprefix "$cmd"
                # If it's a new wineprefix, give it metadata
                if test ! -f "$WINEPREFIX"/wrapper.cfg
                then
                    echo ww_name=\""$title"\" > "$WINEPREFIX"/wrapper.cfg
                fi
                ;;
            esac
            ;;
        esac

        test "$W_OPT_NOCLEAN" = 1 || rm -rf "$W_TMP"
        mkdir -p "$W_TMP"

        # Don't install if already installed
        if test "$WINETRICKS_FORCE" != 1 && winetricks_is_installed "$1"
        then
            echo "$1 already installed, skipping"
            return 0
        fi

        # Don't install if a conflicting verb is already installed:
        # shellcheck disable=SC2154
        if test "$WINETRICKS_FORCE" != 1 && test "$conflicts" && test -f "$WINEPREFIX/winetricks.log"
        then
            for x in $conflicts
            do
                w_conflicts "$1" "$x"
            done
        fi

        # We'd like to get rid of W_PACKAGE, but for now, just set it as late as possible.
        W_PACKAGE=$1
        w_try "load_$cmd" "$arg"

        # User-specific postinstall hook.
        # Source it so the script can call w_download() if needed.
        postfile="$WINETRICKS_POST/$1/$1-postinstall.sh"
        if test -f "$postfile"
        then
            chmod +x "$postfile"
            # shellcheck disable=SC1090
            . "$postfile"
        fi

        # Verify install
        if test "$installed_exe1" || test "$installed_file1"
        then
            if ! winetricks_is_installed "$1"
            then
                w_die "$1 install completed, but installed file $_W_file_unix not found"
            fi
        fi

        # If the user specified --verify, also run GUI tests:
        if test "$WINETRICKS_VERIFY" = 1
        then
            # command -v isn't POSIX :(
            "verify_$cmd" 2>/dev/null
            verify_status=$?
            case $verify_status in
                0) w_warn "verify_$cmd succeeded!" ;;
                127) echo "verify_$cmd not found, not verifying $cmd" ;;
                *) w_die "verify_$cmd failed!" ;;
            esac
        fi

        # Clean up after this verb
        test "$W_OPT_NOCLEAN" = 1 || rm -rf "$W_TMP"
        mkdir -p "$W_TMP"

        # Calling subshell must explicitly propagate error code with exit $?
    ) || exit $?
}

# If you want to check exit status yourself, use w_do_call
w_call()
{
    w_try w_do_call "$@"
}

w_register_font()
{
    file=$1
    shift
    font=$1

    case "$file" in
    *.TTF|*.ttf) font="$font (TrueType)";;
    esac

    # Kludge: use _r to avoid \r expansion in w_try
    cat > "$W_TMP"/_register-font.reg <<_EOF_
REGEDIT4

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Fonts]
"$font"="$file"
_EOF_
    # too verbose
    w_try_regedit "$W_TMP_WIN"\\_register-font.reg
    # shellcheck disable=SC1037
    cp "$W_TMP"/*.reg "$W_TMP_EARLY"/_reg$$.reg

    # Wine also updates the win9x fonts key, so let's do that, too
    cat > "$W_TMP"/_register-font.reg <<_EOF_
REGEDIT4

[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Fonts]
"$font"="$file"
_EOF_
    w_try_regedit "$W_TMP_WIN"\\_register-font.reg
    # shellcheck disable=SC1037
    cp "$W_TMP"/*.reg "$W_TMP_EARLY"/_reg$$-2.reg
}

w_register_font_replacement()
{
    _W_alias=$1
    shift
    _W_font=$1
    # Kludge: use _r to avoid \r expansion in w_try
    cat > "$W_TMP"/_register-font-replacements.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\Fonts\Replacements]
"$_W_alias"="$_W_font"
_EOF_
    w_try_regedit "$W_TMP_WIN"\\_register-font-replacements.reg
    unset _W_alias _W_font
}

w_append_path()
{
    # Prepend $1 to the Windows path in the registry.
    # Use printf %s to avoid interpreting backslashes.
    _W_NEW_PATH="$(printf %s "$1" | sed 's,\\\\,\\\\\\\\,g')"
    _W_WIN_PATH="$(w_expand_env PATH | sed 's,\\\\,\\\\\\\\,g')"

    # FIXME: OS X? https://github.com/Winetricks/winetricks/issues/697
    sed 's/$/\r/' > "$W_TMP"/path.reg <<_EOF_
REGEDIT4

[HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Control\\Session Manager\\Environment]
"PATH"="$_W_NEW_PATH;$_W_WIN_PATH"
_EOF_

    w_try_regedit "$W_TMP_WIN"\\path.reg
    rm -f "$W_TMP"/path.reg
    unset _W_NEW_PATH _W_WIN_PATH
}

#---- Private Functions ----

# Determines downloader to use, etc.
# I.e., things common to w_download_to(), winetricks_download_to_stdout(), and winetricks_stats_report())
winetricks_download_setup()
{
    # shellcheck disable=SC2104
    case "${WINETRICKS_DOWNLOADER}" in
        aria2c|curl|wget|fetch) : ;;
        "") if [ -x "$(which aria2c 2>/dev/null)" ] ; then
                WINETRICKS_DOWNLOADER="aria2c"
            elif [ -x "$(which wget 2>/dev/null)" ] ; then
                WINETRICKS_DOWNLOADER="wget"
            elif [ -x "$(which curl 2>/dev/null)" ] ; then
                WINETRICKS_DOWNLOADER="curl"
            elif [ -x "$(which fetch 2>/dev/null)" ] ; then
                WINETRICKS_DOWNLOADER="fetch"
            else
                w_die "Please install wget or aria2c (or, if those aren't available, curl)"
            fi
            ;;
        *) w_die "Invalid value ${WINETRICKS_DOWNLOADER} given for WINETRICKS_DOWNLOADER. Possible values: aria2c, curl, wget, fetch"
    esac

    # Common values for aria2c/curl/fetch/wget
    # Number of retry attempts (not supported by fetch):
    WINETRICKS_DOWNLOADER_RETRIES=${WINETRICKS_DOWNLOADER_RETRIES:-3}
    # Connection timeout time (in seconds):
    WINETRICKS_DOWNLOADER_TIMEOUT=${WINETRICKS_DOWNLOADER_TIMEOUT:-15}

    case "$WINETRICKS_OPT_TORIFY" in
    1) torify=torify
       # torify needs --async-dns=false, see https://github.com/tatsuhiro-t/aria2/issues/613
       aria2c_torify_opts="--async-dns=false"
       if [ ! -x "$(which torify 2>/dev/null)" ]
       then
           w_die "--torify was used, but torify is not installed, please install it." ; exit 1
       fi ;;
    *) torify=
       aria2c_torify_opts="" ;;
    esac
}


winetricks_dl_url_to_stdout()
{
    winetricks_download_setup

    # Not using w_try here as it adds extra output, breaking things.
    # FIXME: add a w_try_quiet() wrapper around w_try() that doesn't print the
    # Executing ... stuff, but still does error checking
    if [ "${WINETRICKS_DOWNLOADER}" = "wget" ] ; then
        $torify wget -q -O - --timeout "${WINETRICKS_DOWNLOADER_TIMEOUT}" \
            --tries "$WINETRICKS_DOWNLOADER_RETRIES" "$1"
    elif [ "${WINETRICKS_DOWNLOADER}" = "curl" ] ; then
        $torify curl -s --connect-timeout "${WINETRICKS_DOWNLOADER_TIMEOUT}" \
               --retry "$WINETRICKS_DOWNLOADER_RETRIES" "$1"
    elif [ "${WINETRICKS_DOWNLOADER}" = "aria2c" ] ; then
        # aria2c doesn't have support downloading to stdout:
        # https://github.com/aria2/aria2/issues/190
        # So instead, download to a temporary directory and cat the file:
        stdout_tmpfile="${W_TMP_EARLY}/stdout.tmp"

        if [ -e "${stdout_tmpfile}" ] ; then
            rm "${stdout_tmpfile}"
        fi
                $torify aria2c \
                $aria2c_torify_opts \
                --continue \
                --daemon=false \
                --dir="${W_TMP_EARLY}" \
                --enable-rpc=false \
                --input-file='' \
                --max-connection-per-server=5 \
                --out="stdout.tmp" \
                --save-session='' \
                --stream-piece-selector=geom \
                --connect-timeout="${WINETRICKS_DOWNLOADER_TIMEOUT}" \
                --max-tries="$WINETRICKS_DOWNLOADER_RETRIES" \
                "$1" > /dev/null
        cat "${stdout_tmpfile}"
        rm "${stdout_tmpfile}"
    elif [ "${WINETRICKS_DOWNLOADER}" = "fetch" ] ; then
        # fetch does not support retry count
        $torify fetch -o - -T "${WINETRICKS_DOWNLOADER_TIMEOUT}" "$1" 2>/dev/null
    else
        w_die "Please install aria2c, curl, or wget"
    fi
}

winetricks_dl_warning() {
    case $LANG in
        ru*) _W_countrymsg="Скрипт определил, что ваш IP адрес принадлежит России. Если во время загрузки файлов вы увидите ошибки несоответствия сертификата, перезапустите скрипт с опцией '--torify' или скачайте файлы вручную, например, используя VPN." ;;
        *)  _W_countrymsg="Your IP address has been determined to belong to Russia. If you encounter a certificate error while downloading, please relaunch with the '--torify' option, or download files manually, for instance using VPN." ;;
    esac

    # Lookup own country via IP address only once (i.e. don't run this function for every download invocation)
    if [ -z "$W_COUNTRY" ] ; then
        W_COUNTRY="$(winetricks_dl_url_to_stdout "https://ipinfo.io/$(winetricks_dl_url_to_stdout "https://ipinfo.io/ip")" | awk -F '"' '/country/{print $4}')"
        export W_COUNTRY

        if [ -z "$W_COUNTRY" ] ; then
            export W_COUNTRY="unknown"
        fi
    fi

    # TODO: Resolve a full country name via https://github.com/umpirsky/country-list/tree/master/data
    case "$W_COUNTRY" in
        "RU") w_warn "$_W_countrymsg" ;;
        *) : ;;
    esac
}

winetricks_get_sha1sum_prog() {
    # Linux/Solaris:
    if [ -x "$(which sha1sum 2>/dev/null)" ] ; then
        WINETRICKS_SHA1SUM="sha1sum"
    # FreeBSD/NetBSD:
    elif [ -x "$(which sha1 2>/dev/null)" ] ; then
        WINETRICKS_SHA1SUM="sha1"
    # OSX 10.6+:
    elif [ -x "$(which shasum 2>/dev/null)" ] ; then
        WINETRICKS_SHA1SUM="shasum -a 1"
    # OSX 10.5:
    elif [ -x "$(which openssl 2>/dev/null)" ] ; then
        WINETRICKS_SHA1SUM="openssl dgst -sha1"
    else
        w_die "No sha1sum utility available."
    fi
}

winetricks_get_sha256sum_prog() {
    # Linux/Solaris:
    if [ -x "$(which sha256sum 2>/dev/null)" ] ; then
        WINETRICKS_SHA256SUM="sha256sum"
    # FreeBSD/NetBSD:
    elif [ -x "$(which sha256 2>/dev/null)" ] ; then
        WINETRICKS_SHA256SUM="sha256"
    # OSX (10.6+), 10.5 doesn't support at all: https://stackoverflow.com/questions/7500691/rvm-sha256sum-nor-shasum-found
    elif [ -x "$(which shasum 2>/dev/null)" ] ; then
        WINETRICKS_SHA256SUM="shasum -a 256"
    else
        w_die "No sha256um utility available."
    fi
}

winetricks_get_platform()
{
    if [ "${OS}" = "Windows_NT" ]
    then
        if [ ! -v "${WINELOADERNOEXEC}" ]
        then
            export W_PLATFORM="windows_cmd"
        else
            export W_PLATFORM="wine_cmd"
        fi
    else
        export W_PLATFORM="wine"
    fi
}

winetricks_latest_version_check()
{
    if [ "$WINETRICKS_LATEST_VERSION_CHECK" = 'disabled' ] || [ -f "${WINETRICKS_CONFIG}/disable-latest-version-check" ] ; then
        w_info "winetricks latest version check update disabled"
        return
    fi

    latest_version="$(winetricks_dl_url_to_stdout https://raw.githubusercontent.com/Winetricks/winetricks/master/files/LATEST)"

    # Check that $latest_version is an actual number in case github is down
    if ! echo "${latest_version}" | grep -E "[0-9]{8}" || [ -z "${latest_version}" ] ; then
        w_warn "Github down? version '${latest_version}' doesn't appear to be a valid version"
    fi

    if [ ! "$WINETRICKS_VERSION" = "${latest_version}" ] && [ ! "$WINETRICKS_VERSION" = "${latest_version}-next" ]; then
        if [ -f "${WINETRICKS_CONFIG}/enable-auto-update" ] ; then
            w_info "You are running winetricks-${WINETRICKS_VERSION}."
            w_info "New upstream release winetricks-${latest_version} is available."
            w_info "auto-update enabled: running winetricks_selfupdate"
            winetricks_selfupdate
        else
            w_warn "You are running winetricks-${WINETRICKS_VERSION}, latest upstream is winetricks-${latest_version}!"
            w_warn "You should update using your distribution's package manager, --self-update, or manually."
        fi
    fi
}

winetricks_print_version()
{
    # Normally done by winetricks_init, but we don't want to set up the WINEPREFIX
    # just to get the winetricks version:

    winetricks_get_sha256sum_prog

    w_get_sha256sum "$0"
    echo "$WINETRICKS_VERSION - sha256sum: $_W_gotsha256sum"
}

# Run a small wine command for internal use
# Handy place to put small workarounds
winetricks_early_wine()
{
    # The sed works around https://bugs.winehq.org/show_bug.cgi?id=25838
    # which unfortunately got released in wine-1.3.12
    # We would like to use DISPLAY= to prevent virtual desktops from
    # popping up, but that causes AutoHotKey's tray icon to not show up.
    # We used to use WINEDLLOVERRIDES=mshtml= here to suppress the Gecko
    # autoinstall, but that yielded wineprefixes that *never* autoinstalled
    # Gecko (winezeug bug 223).
    # The tr removes carriage returns so expanded variables don't have crud on the end
    # The grep works around using new wineprefixes with old wine
    WINEDEBUG=-all "$WINE" "$@" 2> "$W_TMP_EARLY"/early_wine.err.txt | ( sed 's/.*1h.=//' | tr -d '\r' | grep -v "Module not found" || true)
}

winetricks_detect_gui()
{
    if test -x "$(which zenity 2>/dev/null)"
    then
        WINETRICKS_GUI=zenity

        WINETRICKS_MENU_HEIGHT=500
        WINETRICKS_MENU_WIDTH=1010
    elif test -x "$(which kdialog 2>/dev/null)"
    then
        echo "Zenity not found!  Using kdialog as poor substitute."
        WINETRICKS_GUI=kdialog
    else
        echo "No arguments given, so tried to start GUI, but zenity not found."
        echo "Please install zenity if you want a graphical interface, or "
        echo "run with --help for more options."
        exit 1
    fi
}

# Detect which sudo to use
winetricks_detect_sudo()
{
    WINETRICKS_SUDO=sudo
    if test "$WINETRICKS_GUI" = "none"
    then
        return
    fi
    if test x"$DISPLAY" != x""
    then
        if test -x "$(which gksudo 2>/dev/null)"
        then
            WINETRICKS_SUDO=gksudo
        elif test -x "$(which kdesudo 2>/dev/null)"
        then
            WINETRICKS_SUDO=kdesudo
        # fall back to the su versions if sudo isn't available (Fedora, etc.):
        elif test -x "$(which gksu 2>/dev/null)"
        then
            WINETRICKS_SUDO=gksu
        elif test -x "$(which kdesu 2>/dev/null)"
        then
            WINETRICKS_SUDO=kdesu
        fi
    fi
}

winetricks_get_prefix_var()
{
    (
        # shellcheck disable=SC1090
        . "$W_PREFIXES_ROOT/$p/wrapper.cfg"
        # The cryptic sed is there to turn ' into '\''
        eval echo \$ww_"$1" | sed "s/'/'\\\''/"
    )
}

# Display prefix menu, get which wineprefix the user wants to work with
winetricks_prefixmenu()
{
    case $LANG in
    ru*) _W_msg_title="Winetricks - выберите путь wine (wineprefix)"
         _W_msg_body='Что вы хотите сделать?'
         _W_msg_apps='Установить программу'
         _W_msg_games='Установить игру'
         _W_msg_benchmarks='Установить приложение для оценки производительности'
         _W_msg_default="Выберите путь для wine по умолчанию"
         _W_msg_unattended0="Отключить автоматическую установку"
         _W_msg_unattended1="Включить автоматическую установку"
         _W_msg_showbroken0="Спрятать нерабочие программы (например, использующие DRM)"
         _W_msg_showbroken1="Отобразить нерабочие программы (например, использующие DRM)"
         _W_msg_help="Просмотр справки (в веб браузере)"
         ;;
    uk*) _W_msg_title="Winetricks - виберіть wineprefix"
         _W_msg_body='Що Ви хочете зробити?'
         _W_msg_apps='Встановити додаток'
         _W_msg_games='Встановити гру'
         _W_msg_benchmarks='Встановити benchmark'
         _W_msg_default="Вибрати wineprefix за замовчуванням"
         _W_msg_unattended0="Вимкнути автоматичну установку"
         _W_msg_unattended1="Включити автоматичну установку"
         _W_msg_showbroken0="Сховати нестабільні додатки (наприклад з проблемами з DRM)"
         _W_msg_showbroken1="Показати нестабільні додатки (наприклад з проблемами з DRM)"
         _W_msg_help="Переглянути довідку"
         ;;
    zh_CN*)   _W_msg_title="Windows 应用安装向导 - 选择一个 wine 容器"
         _W_msg_body='君欲何为？'
         _W_msg_apps='安装一个 windows 应用'
         _W_msg_games='安装一个游戏'
         _W_msg_benchmarks='安装一个基准测试软件'
         _W_msg_default="选择默认的 wine 容器"
         _W_msg_unattended0="禁用静默安装"
         _W_msg_unattended1="启用静默安装"
         _W_msg_showbroken0="隐藏有问题的程序 (例如那些有数字版权问题)"
         _W_msg_showbroken1="有问题的程序 (例如那些有数字版权问题)"
         _W_msg_help="查看帮助"
         ;;
    zh_TW*|zh_HK*)   _W_msg_title="Windows 應用安裝向導 - 選取一個 wine 容器"
         _W_msg_body='君欲何為？'
         _W_msg_apps='安裝一個 windows 應用'
         _W_msg_games='安裝一個游戲'
         _W_msg_benchmarks='安裝一個基准測試軟體'
         _W_msg_default="選取預設的 wine 容器"
         _W_msg_unattended0="禁用靜默安裝"
         _W_msg_unattended1="啟用靜默安裝"
         _W_msg_showbroken0="隱藏有問題的程式 (例如那些有數字版權問題)"
         _W_msg_showbroken1="有問題的程式 (例如那些有數字版權問題)"
         _W_msg_help="檢視輔助說明"
         ;;
    de*) _W_msg_title="Winetricks - wineprefix auswählen"
         _W_msg_body='Was möchten Sie tun?'
         _W_msg_apps='Eine Programm installieren'
         _W_msg_games='Ein Spiel installieren'
         _W_msg_benchmarks='Ein Benchmark installieren'
         _W_msg_default="Standard wineprefix auswählen"
         _W_msg_unattended0="Automatische Installation deaktivieren"
         _W_msg_unattended1="Automatische Installation aktivieren"
         _W_msg_showbroken0="Defekte Programme nicht anzeigen (z.B. solche mit DRM Problemen)"
         _W_msg_showbroken1="Defekte Programme anzeigen (z.B. solche mit DRM Problemen)"
         _W_msg_help="Hilfe anzeigen"
         ;;
    *)   _W_msg_title="Winetricks - choose a wineprefix"
         _W_msg_body='What do you want to do?'
         _W_msg_apps='Install an application'
         _W_msg_games='Install a game'
         _W_msg_benchmarks='Install a benchmark'
         _W_msg_default="Select the default wineprefix"
         _W_msg_unattended0="Disable silent install"
         _W_msg_unattended1="Enable silent install"
         _W_msg_showbroken0="Hide broken apps (e.g. those with DRM problems)"
         _W_msg_showbroken1="Show broken apps (e.g. those with DRM problems)"
         _W_msg_help="View help"
         ;;
    esac
    case "$W_OPT_UNATTENDED" in
    1) _W_cmd_unattended=attended; _W_msg_unattended="$_W_msg_unattended0" ;;
    *) _W_cmd_unattended=unattended; _W_msg_unattended="$_W_msg_unattended1" ;;
    esac
    case "$W_OPT_SHOWBROKEN" in
    1) _W_cmd_showbroken=hidebroken; _W_msg_showbroken="$_W_msg_showbroken0" ;;
    *) _W_cmd_showbroken=showbroken; _W_msg_showbroken="$_W_msg_showbroken1" ;;
    esac

    case $WINETRICKS_GUI in
    zenity)
        printf %s "zenity \
            --title '$_W_msg_title' \
            --text '$_W_msg_body' \
            --list \
            --radiolist \
            --column '' \
            --column '' \
            --column '' \
            --height $WINETRICKS_MENU_HEIGHT \
            --width $WINETRICKS_MENU_WIDTH \
            --hide-column 2 \
            FALSE help       '$_W_msg_help' \
            FALSE apps       '$_W_msg_apps' \
            FALSE benchmarks '$_W_msg_benchmarks' \
            FALSE games      '$_W_msg_games' \
            TRUE  main       '$_W_msg_default' \
            " \
            > "$WINETRICKS_WORKDIR"/zenity.sh

        if ls -d "$W_PREFIXES_ROOT"/*/dosdevices > /dev/null 2>&1
        then
            for prefix in "$W_PREFIXES_ROOT"/*/dosdevices
            do
                q="${prefix%%/dosdevices}"
                p="${q##*/}"
                if test -f "$W_PREFIXES_ROOT/$p/wrapper.cfg"
                then
                    _W_msg_name="$p ($(winetricks_get_prefix_var name))"
                else
                    _W_msg_name="$p"
                fi
            case $LANG in
            zh_CN*) printf %s " FALSE prefix='$p' '选择管理 $_W_msg_name' " ;;
            zh_TW*|zh_HK*) printf %s " FALSE prefix='$p' '選擇管理 $_W_msg_name' " ;;
            de*) printf %s " FALSE prefix='$p' '$_W_msg_name auswählen' " ;;
            *) printf %s " FALSE prefix='$p' 'Select $_W_msg_name' " ;;
            esac
            done >> "$WINETRICKS_WORKDIR"/zenity.sh
        fi
        printf %s " FALSE $_W_cmd_unattended '$_W_msg_unattended'" >> "$WINETRICKS_WORKDIR"/zenity.sh
        printf %s " FALSE $_W_cmd_showbroken '$_W_msg_showbroken'" >> "$WINETRICKS_WORKDIR"/zenity.sh

        sh "$WINETRICKS_WORKDIR"/zenity.sh | tr '|' ' '
        ;;

    kdialog)
        (
        printf %s "kdialog \
            --geometry 600x400+100+100 \
            --title '$_W_msg_title' \
            --separate-output \
            --radiolist '$_W_msg_body' \
            help       '$_W_msg_help'       off \
            games      '$_W_msg_games'      off \
            benchmarks '$_W_msg_benchmarks' off \
            apps       '$_W_msg_apps'       off \
            main       '$_W_msg_default'    on "
        if ls -d "$W_PREFIXES_ROOT"/*/dosdevices > /dev/null 2>&1
        then
            for prefix in "$W_PREFIXES_ROOT"/*/dosdevices
            do
                q="${prefix%%/dosdevices}"
                p="${q##*/}"
                if test -f "$W_PREFIXES_ROOT/$p/wrapper.cfg"
                then
                    _W_msg_name="$p ($(winetricks_get_prefix_var name))"
                else
                    _W_msg_name="$p"
                fi
                printf %s "prefix='$p' 'Select $_W_msg_name' off "
            done
        fi
        ) > "$WINETRICKS_WORKDIR"/kdialog.sh
        sh "$WINETRICKS_WORKDIR"/kdialog.sh
        ;;
    esac
    unset _W_msg_help _W_msg_body _W_msg_title _W_msg_new _W_msg_default _W_msg_name
}

# Display main menu, get which submenu the user wants
winetricks_mainmenu()
{
    case $LANG in
    da*) _W_msg_title='Vælg en pakke-kategori'
         _W_msg_body='Hvad ønsker du at gøre?'
         _W_msg_dlls="Install a Windows DLL"
         _W_msg_fonts='Install a font'
         _W_msg_settings='Change Wine settings'
         _W_msg_winecfg='Run winecfg'
         _W_msg_regedit='Run regedit'
         _W_msg_taskmgr='Run taskmgr'
         _W_msg_uninstaller='Run uninstaller'
         _W_msg_shell='Run a commandline shell (for debugging)'
         _W_msg_folder='Browse files'
         _W_msg_annihilate="Delete ALL DATA AND APPLICATIONS INSIDE THIS WINEPREFIX"
         ;;
    de*) _W_msg_title='Pakettyp auswählen'
         _W_msg_body='Was möchten Sie tun?'
         _W_msg_dlls="Windows-DLL installieren"
         _W_msg_fonts='Schriftart installieren'
         _W_msg_settings='Wine Einstellungen ändern'
         _W_msg_winecfg='winecfg starten'
         _W_msg_regedit='regedit starten'
         _W_msg_taskmgr='taskmgr starten'
         _W_msg_uninstaller='uninstaller starten'
         _W_msg_shell='Eine Kommandozeile zum debuggen starten'
         _W_msg_folder='Ordner durchsuchen'
         _W_msg_annihilate="ALLE DATEIEN UND PROGRAMME IN DIESEM WINEPREFIX Löschen"
         ;;
    pl*) _W_msg_title="Winetricks - obecny prefiks to \"$WINEPREFIX\""
         _W_msg_body='What would you like to do to this wineprefix?'
         _W_msg_dlls="Zainstaluj Windowsową bibliotekę DLL lub komponent"
         _W_msg_fonts='Zainstaluj czcionkę'
         _W_msg_settings='Zmień ustawienia'
         _W_msg_winecfg='Uruchom winecfg'
         _W_msg_regedit='Uruchom regedit'
         _W_msg_taskmgr='Uruchom taskmgr'
         _W_msg_uninstaller='Run uninstaller'
         _W_msg_shell='Uruchom powłokę wiersza poleceń (dla debugowania)'
         _W_msg_folder='Przeglądaj pliki'
         _W_msg_annihilate="Usuń WSZYSTKIE DANE I APLIKACJE WEWNĄTRZ TEGO WINEPREFIXA"
         ;;
    ru*) _W_msg_title="Winetricks - текущий путь для wine (wineprefix) \"$WINEPREFIX\""
         _W_msg_body='Что вы хотите сделать с этим wineprefix?'
         _W_msg_dlls="Установить DLL библиотеку или компонент Windows"
         _W_msg_fonts='Установить шрифт'
         _W_msg_settings='Поменять настройки'
         _W_msg_winecfg='Запустить winecfg (редактор настроек wine)'
         _W_msg_regedit='Запустить regedit (редактор рееста)'
         _W_msg_taskmgr='Запустить taskmgr (менеджер задач)'
         _W_msg_uninstaller='Запустить uninstaller (деинсталятор)'
         _W_msg_shell='Запустить графический терминал (для отладки)'
         _W_msg_folder='Проводник файлов'
         _W_msg_annihilate="Удалить ВСЕ ДАННЫЕ И ПРИЛОЖЕНИЯ В ЭТОМ WINEPREFIX"
         ;;
    uk*) _W_msg_title="Winetricks - поточний prefix \"$WINEPREFIX\""
         _W_msg_body='Що Ви хочете зробити для цього wineprefix?'
         _W_msg_dlls="Встановити Windows DLL чи компонент(и)"
         _W_msg_fonts='Встановити шрифт'
         _W_msg_settings='Змінити налаштування'
         _W_msg_winecfg='Запустити winecfg'
         _W_msg_regedit='Запустити regedit'
         _W_msg_taskmgr='Запустити taskmgr'
         _W_msg_uninstaller='Встановлення/видалення програм'
         _W_msg_shell='Запуск командної оболонки (для налагодження)'
         _W_msg_folder='Перегляд файлів'
         _W_msg_annihilate="Видалити УСІ ДАНІ ТА ПРОГРАМИ З ЦЬОГО WINEPREFIX"
         ;;
    zh_CN*)   _W_msg_title="Windows 应用安装向导 - 当前容器路径是 \"$WINEPREFIX\""
         _W_msg_body='管理当前容器'
         _W_msg_dlls="安装 Windows DLL 或组件"
         _W_msg_fonts='安装字体'
         _W_msg_settings='修改设置'
         _W_msg_winecfg='运行 winecfg'
         _W_msg_regedit='运行注册表'
         _W_msg_taskmgr='运行任务管理器'
         _W_msg_uninstaller='运行卸载程序'
         _W_msg_shell='运行命令提示窗口 (作为调试)'
         _W_msg_folder='浏览容器中的文件'
         _W_msg_annihilate="删除当前容器所有相关文件，包括启动器，完全卸载"
         ;;
    zh_TW*|zh_HK*)   _W_msg_title="Windows 應用裝載向導 - 目前容器路徑是 \"$WINEPREFIX\""
         _W_msg_body='管理目前容器'
         _W_msg_dlls="裝載 Windows DLL 或套件"
         _W_msg_fonts='裝載字型'
         _W_msg_settings='修改設定'
         _W_msg_winecfg='執行 winecfg'
         _W_msg_regedit='執行註冊表'
         _W_msg_taskmgr='執行工作管理者'
         _W_msg_uninstaller='執行反安裝程式'
         _W_msg_shell='執行指令輔助說明視窗 (作為除錯)'
         _W_msg_folder='瀏覽容器中的檔案'
         _W_msg_annihilate="移除目前容器所有相依檔案，包括啟動器，完全卸載"
         ;;
    *)   _W_msg_title="Winetricks - current prefix is \"$WINEPREFIX\""
         _W_msg_body='What would you like to do to this wineprefix?'
         _W_msg_dlls="Install a Windows DLL or component"
         _W_msg_fonts='Install a font'
         _W_msg_settings='Change settings'
         _W_msg_winecfg='Run winecfg'
         _W_msg_regedit='Run regedit'
         _W_msg_taskmgr='Run taskmgr'
         _W_msg_uninstaller='Run uninstaller'
         _W_msg_shell='Run a commandline shell (for debugging)'
         _W_msg_folder='Browse files'
         _W_msg_annihilate="Delete ALL DATA AND APPLICATIONS INSIDE THIS WINEPREFIX"
         ;;
    esac

    case $WINETRICKS_GUI in
    zenity)
        (
          printf %s "zenity \
            --title '$_W_msg_title' \
            --text '$_W_msg_body' \
            --list \
            --radiolist \
            --column '' \
            --column '' \
            --column '' \
            --height $WINETRICKS_MENU_HEIGHT \
            --width $WINETRICKS_MENU_WIDTH \
            --hide-column 2 \
            FALSE dlls        '$_W_msg_dlls' \
            FALSE fonts       '$_W_msg_fonts' \
            FALSE settings    '$_W_msg_settings' \
            FALSE winecfg     '$_W_msg_winecfg' \
            FALSE regedit     '$_W_msg_regedit' \
            FALSE taskmgr     '$_W_msg_taskmgr' \
            FALSE uninstaller '$_W_msg_uninstaller' \
            FALSE shell       '$_W_msg_shell' \
            FALSE folder      '$_W_msg_folder' \
            FALSE annihilate  '$_W_msg_annihilate' \
         "
         ) > "$WINETRICKS_WORKDIR"/zenity.sh
        sh "$WINETRICKS_WORKDIR"/zenity.sh | tr '|' ' '
        ;;

    kdialog)
        $WINETRICKS_GUI --geometry 600x400+100+100 \
                --title "$_W_msg_title" \
                --separate-output \
                --radiolist \
                "$_W_msg_body"\
                dlls        "$_W_msg_dlls" off \
                fonts       "$_W_msg_fonts" off \
                settings    "$_W_msg_settings" off \
                winecfg     "$_W_msg_winecfg" off \
                regedit     "$_W_msg_regedit" off \
                taskmgr     "$_W_msg_taskmgr" off \
                uninstaller "$_W_msg_uninstaller" off \
                shell       "$_W_msg_shell" off \
                folder      "$_W_msg_folder" off \
                annihilate  "$_W_msg_annihilate" off \
                $_W_cmd_unattended "$_W_msg_unattended" off \

        ;;
    esac
    unset _W_msg_body _W_msg_title _W_msg_apps _W_msg_benchmarks _W_msg_dlls _W_msg_games _W_msg_settings
}

winetricks_settings_menu()
{
    # FIXME: these translations should really be centralized/reused:
    case $LANG in
    da*) _W_msg_title='Vælg en pakke'
         _W_msg_body='Which settings would you like to change?'
         ;;
    de*) _W_msg_title="Winetricks - Aktueller Prefix ist \"$WINEPREFIX\""
         _W_msg_body='Welche Einstellungen möchten Sie ändern?'
         ;;
    pl*) _W_msg_title="Winetricks - obecny prefiks to \"$WINEPREFIX\""
         _W_msg_body='Which settings would you like to change?'
         ;;
    ru*) _W_msg_title="Winetricks - текущий путь wine (wineprefix) \"$WINEPREFIX\""
         _W_msg_body='Какие настройки вы хотите изменить?'
         ;;
    uk*) _W_msg_title="Winetricks - поточний prefix \"$WINEPREFIX\""
         _W_msg_body='Які налаштування Ви хочете змінити?'
         ;;
    zh_CN*)   _W_msg_title="Windows 应用安装向导 - 当前容器路径是 \"$WINEPREFIX\""
         _W_msg_body='君欲更改哪项设置？'
         ;;
    zh_TW*|zh_HK*)   _W_msg_title="Windows 應用裝載向導 - 目前容器路徑是 \"$WINEPREFIX\""
         _W_msg_body='君欲變更哪項設定？'
         ;;
    *)   _W_msg_title="Winetricks - current prefix is \"$WINEPREFIX\""
         _W_msg_body='Which settings would you like to change?'
         ;;
    esac

    case $WINETRICKS_GUI in
    zenity)
        case $LANG in
        da*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column Pakke \
                --column Navn \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
            ;;
        de*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column Einstellung \
                --column Name \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
            ;;
        pl*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column Ustawienie \
                --column Nazwa \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
            ;;
        ru*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column Установка \
                --column Имя \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
            ;;
        uk*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column Установка \
                --column Назва \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
            ;;
        zh_CN*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column 设置 \
                --column 标题 \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
            ;;
        zh_TW*|zh_HK*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column 設定 \
                --column 標題 \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
            ;;
        *) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column Setting \
                --column Title \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
            ;;
        esac > "$WINETRICKS_WORKDIR"/zenity.sh

        for metadatafile in "$WINETRICKS_METADATA"/$WINETRICKS_CURMENU/*.vars
        do
            code=$(winetricks_metadata_basename "$metadatafile")
            (
            title='?'
            # shellcheck disable=SC1090
            . "$metadatafile"
          # Begin 'title' strings localization code
            # shellcheck disable=SC2154
            case $LANG in
            uk*) case "$title_uk" in
                 "") ;;
                 *) title="$title_uk";;
                 esac
            esac
          # End of code
            printf "%s %s %s %s" " " FALSE \
                    "$code" \
                    "\"$title\""
            )
        done >> "$WINETRICKS_WORKDIR"/zenity.sh

        sh "$WINETRICKS_WORKDIR"/zenity.sh | tr '|' ' '
        ;;

    kdialog)
        (
        printf %s "kdialog --geometry 600x400+100+100 --title '$_W_msg_title' --separate-output --checklist '$_W_msg_body' "
        winetricks_list_all | sed 's/\([^ ]*\)  *\(.*\)/\1 "\1 - \2" off /' | tr '\012' ' '
        ) > "$WINETRICKS_WORKDIR"/kdialog.sh
        sh "$WINETRICKS_WORKDIR"/kdialog.sh
        ;;
    esac

    unset _W_msg_body _W_msg_title
}

# Display the current menu, output list of verbs to execute to stdout
winetricks_showmenu()
{
    case $LANG in
    da*) _W_msg_title='Vælg en pakke'
         _W_msg_body='Vilken pakke vil du installere?'
         _W_cached="cached"
         ;;
    de*) _W_msg_title="Winetricks - Aktueller Prefix ist \"$WINEPREFIX\""
         _W_msg_body='Welche Paket(e) möchten Sie installieren?'
         _W_cached="gecached"
         ;;
    pl*) _W_msg_title="Winetricks - obecny prefiks to \"$WINEPREFIX\""
         _W_msg_body='Które paczki chesz zainstalować?'
         _W_cached="zarchiwizowane"
         ;;
    ru*) _W_msg_title="Winetricks - текущий путь wine (wineprefix) \"$WINEPREFIX\""
         _W_msg_body='Какое приложение(я) вы хотите установить?'
         _W_cached="в кэше"
         ;;
    uk*) _W_msg_title="Winetricks - поточний prefix \"$WINEPREFIX\""
         _W_msg_body='Які пакунки Ви хочете встановити?'
         _W_cached="кешовано"
         ;;
    zh_CN*)   _W_msg_title="Windows 应用安装向导 - 当前容器路径是 \"$WINEPREFIX\""
         _W_msg_body='君欲安装何种应用？'
         _W_cached="已缓存"
         ;;
    zh_TW*|zh_HK*)   _W_msg_title="Windows 應用裝載向導 - 目前容器路徑是 \"$WINEPREFIX\""
         _W_msg_body='君欲裝載何種應用？'
         _W_cached="已緩存"
         ;;
    *)   _W_msg_title="Winetricks - current prefix is \"$WINEPREFIX\""
         _W_msg_body='Which package(s) would you like to install?'
         _W_cached="cached"
         ;;
    esac


    case $WINETRICKS_GUI in
    zenity)
        case $LANG in
        da*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column Pakke \
                --column Navn \
                --column Udgiver \
                --column År \
                --column Medie \
                --column Status \
                --column 'Size (MB)' \
                --column 'Time (sec)' \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
            ;;
        de*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column Paket \
                --column Name \
                --column Herausgeber \
                --column Jahr \
                --column Media \
                --column Status \
                --column 'Größe (MB)' \
                --column 'Zeit (sec)' \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
             ;;
        pl*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column Paczka \
                --column Nazwa \
                --column Wydawca \
                --column Rok \
                --column Media \
                --column Status \
                --column 'Rozmiar (MB)' \
                --column 'Czas (sek)' \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
             ;;
        ru*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column Пакет \
                --column Название \
                --column Издатель \
                --column Год \
                --column Источник \
                --column Статус \
                --column 'Размер (МБ)' \
                --column 'Время (сек)' \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
             ;;
        uk*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column Пакунок \
                --column Назва \
                --column Видавець \
                --column Рік \
                --column Медіа \
                --column Статус \
                --column 'Розмір (МБ)' \
                --column 'Час (сек)' \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
             ;;
        zh_CN*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column 包名 \
                --column 软件名 \
                --column 发行商 \
                --column 发行年 \
                --column 媒介 \
                --column 状态 \
                --column '文件大小 (MB)' \
                --column '时间 (秒)' \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
             ;;
        zh_TW*|zh_HK*) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column 包名 \
                --column 軟體名 \
                --column 發行商 \
                --column 發行年 \
                --column 媒介 \
                --column 狀態 \
                --column '檔案大小 (MB)' \
                --column '時間 (秒)' \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
             ;;
        *) printf %s "zenity \
                --title '$_W_msg_title' \
                --text '$_W_msg_body' \
                --list \
                --checklist \
                --column '' \
                --column Package \
                --column Title \
                --column Publisher \
                --column Year \
                --column Media \
                --column Status \
                --column 'Size (MB)' \
                --column 'Time (sec)' \
                --height $WINETRICKS_MENU_HEIGHT \
                --width $WINETRICKS_MENU_WIDTH \
                "
             ;;
        esac > "$WINETRICKS_WORKDIR"/zenity.sh

        true > "$WINETRICKS_WORKDIR"/installed.txt
        for metadatafile in "$WINETRICKS_METADATA"/$WINETRICKS_CURMENU/*.vars
        do
            code=$(winetricks_metadata_basename "$metadatafile")
            (
            title='?'
            # shellcheck disable=SC1090
            . "$metadatafile"
            # shellcheck disable=SC2154
            if test "$W_OPT_SHOWBROKEN" = 1 || test "$wine_showstoppers" = ""
            then
                # Compute cached and downloadable flags
                flags=""
                winetricks_is_cached "$code" && flags="$_W_cached"
                installed=FALSE
                if winetricks_is_installed "$code"
                then
                    installed=TRUE
                    echo "$code" >> "$WINETRICKS_WORKDIR"/installed.txt
                fi
                printf %s " $installed \
                    $code \
                    \"$title\" \
                    \"$publisher\" \
                    \"$year\" \
                    \"$media\" \
                    \"$flags\" \
                    \"$size_MB\" \
                    \"$time_sec\" \
                "
            fi
            )
        done >> "$WINETRICKS_WORKDIR"/zenity.sh

        # Filter out any verb that's already installed
        sh "$WINETRICKS_WORKDIR"/zenity.sh |
            tr '|' '\012' |
            grep -F -v -x -f "$WINETRICKS_WORKDIR"/installed.txt |
            tr '\012' ' '
        ;;

    kdialog)
        (
        printf %s "kdialog --geometry 600x400+100+100 --title '$_W_msg_title' --separate-output --checklist '$_W_msg_body' "
        winetricks_list_all | sed 's/\([^ ]*\)  *\(.*\)/\1 "\1 - \2" off /' | tr '\012' ' '
        ) > "$WINETRICKS_WORKDIR"/kdialog.sh
        sh "$WINETRICKS_WORKDIR"/kdialog.sh
        ;;
    esac

    unset _W_msg_body _W_msg_title
}

# Converts a metadata abolute path to its app code
winetricks_metadata_basename()
{
    # Classic, but too slow on cygwin
    #basename $1 .vars

    # first, remove suffix .vars
    _W_mb_tmp="${1%.vars}"
    # second, remove any directory prefix
    echo "${_W_mb_tmp##*/}"
    unset _W_mb_tmp
}

# Returns true if given verb has been registered
winetricks_metadata_exists()
{
    test -f "$WINETRICKS_METADATA"/*/"${1}.vars"
}

# Returns true if given verb has been cached
# You must have already loaded its metadata before calling
winetricks_is_cached()
{
    # FIXME: also check file2... if given
    # shellcheck disable=SC2154
    _W_path="$W_CACHE/$1/$file1"
    case "$_W_path" in
    *..*)
        # Remove /foo/.. so verbs that don't have their own cache directories
        # can refer to siblings
        _W_path="$(echo "$_W_path" | sed 's,/[^/]*/\.\.,,')"
        ;;
    esac
    if test -f "$_W_path"
    then
        unset _W_path
        return 0
    fi
    unset _W_path
    return 1
}

# Returns true if given verb has been installed
# You must have already loaded its metadata before calling
winetricks_is_installed()
{
    unset _W_file _W_file_unix
    if test "$installed_exe1"
    then
        _W_file="$installed_exe1"
    elif test "$installed_file1"
    then
        _W_file="$installed_file1"
    else
        return 1  # not installed
    fi

    case "$W_PLATFORM" in
    windows_cmd|wine_cmd)
        # On Windows, there's no wineprefix, just check if file's there
        _W_file_unix="$(w_pathconv -u "$_W_file")"
        if test -f "$_W_file_unix"
        then
            unset _W_file _W_file_unix _W_prefix
            return 0  # installed
        fi
        ;;
    *)
        # Compute wineprefix for this app
        case "${category}-${WINETRICKS_OPT_SHAREDPREFIX}" in
        apps-0|benchmarks-0|games-0)
            _W_prefix="$W_PREFIXES_ROOT/$1"
            ;;
        *)
            _W_prefix="$WINEPREFIX"
            ;;
        esac
        if test -d "$_W_prefix/dosdevices"
        then
          # 'win7 vcrun2005' creates different file than 'winxp vcrun2005'
          # so let it specify multiple, separated by |
          _W_IFS="$IFS"
          IFS='|'
          for _W_file_ in $_W_file
          do
            _W_file_unix="$(WINEPREFIX="$_W_prefix" w_pathconv -u "$_W_file_")"
            if test -f "$_W_file_unix" && ! grep -q "Wine placeholder DLL" "$_W_file_unix"
            then
                IFS="$_W_IFS"
                unset _W_file _W_file_ _W_file_unix _W_prefix _W_IFS
                return 0  # installed
            fi
          done
         IFS="$_W_IFS"
        fi
        ;;
    esac
    unset _W_file _W_prefix  # leak _W_file_unix for caller.  Is this wise?
    unset _W_IFS _W_file_
    return 1  # not installed
}

# List verbs which are already fully cached locally
winetricks_list_cached()
{
    for _W_metadatafile in "$WINETRICKS_METADATA"/*/*.vars
    do
        # Use a subshell to avoid putting metadata in global space
        # If this is too slow, we can unset known metadata by hand
        (
        code=$(winetricks_metadata_basename "$_W_metadatafile")
        # shellcheck disable=SC1090
        . "$_W_metadatafile"
        if winetricks_is_cached "$code"
        then
            echo "$code"
        fi
        )
    done | sort
    unset _W_metadatafile
}

# List verbs which are automatically downloadable, regardless of whether they're cached yet
winetricks_list_download()
{
    # Piping output of w_try_cd to /dev/null since winetricks-test parses it:
    w_try_cd "$WINETRICKS_METADATA" >/dev/null
    grep -l 'media=.download' ./*/*.vars | sed 's,.*/,,;s/\.vars//' | sort -u
}

# List verbs which are downloadable with user intervention, regardless of whether they're cached yet
winetricks_list_manual_download()
{
    # Piping output of w_try_cd to /dev/null since winetricks-test parses it:
    w_try_cd "$WINETRICKS_METADATA" >/dev/null
    grep -l 'media=.manual_download' ./*/*.vars | sed 's,.*/,,;s/\.vars//' | sort -u
}

winetricks_list_installed()
{
    (
    # Jump through a couple hoops to evaluate the verbs in alphabetical order
    # Assume that no filename contains '|'

    # Piping output of w_try_cd to /dev/null since winetricks-test parses it:
    w_try_cd "$WINETRICKS_METADATA" >/dev/null
    for _W_metadatafile in $(find . -iname \*.vars | sed 's,^\(.*\)/,\1|,' | sort -t\| -k 2 | tr '|' /)
    do
        # Use a subshell to avoid putting metadata in global space
        # If this is too slow, we can unset known metadata by hand
        (
        code=$(winetricks_metadata_basename "$_W_metadatafile")
        # shellcheck disable=SC1090
        . "$_W_metadatafile"
        if winetricks_is_installed "$code"
        then
            echo "$code"
        fi
        )
    done
    )
    unset _W_metadatafile
}

# Helper for adding a string to a list of flags
winetricks_append_to_flags()
{
    if test "$flags"
    then
        flags="$flags,"
    fi
    flags="${flags}$1"
}

# List all verbs in category WINETRICKS_CURMENU verbosely
# Format is "verb  title  (publisher, year) [flags]"
winetricks_list_all()
{
    # Note: doh123 relies on 'winetricks list' to list main menu categories
    case $WINETRICKS_CURMENU in
    prefix|main) echo "$WINETRICKS_CATEGORIES" | tr ' ' '\012' ; return;;
    esac

    case $LANG in
    da*) _W_cached="cached"   ; _W_download="kan hentes"    ;;
    de*) _W_cached="gecached" ; _W_download="herunterladbar";;
    pl*) _W_cached="zarchiwizowane"   ; _W_download="do pobrania"  ;;
    ru*) _W_cached="в кэше"   ; _W_download="доступно для скачивания"  ;;
    uk*) _W_cached="кешовано"   ; _W_download="завантажуване"  ;;
    zh_CN*)   _W_cached="已缓存"   ; _W_download="可下载"  ;;
    zh_TW*|zh_HK*)   _W_cached="已緩存"   ; _W_download="可下載"  ;;
    *)   _W_cached="cached"   ; _W_download="downloadable"  ;;
    esac

    for _W_metadatafile in "$WINETRICKS_METADATA"/$WINETRICKS_CURMENU/*.vars
    do
        # Use a subshell to avoid putting metadata in global space
        # If this is too slow, we can unset known metadata by hand
        (
        code=$(winetricks_metadata_basename "$_W_metadatafile")
        # shellcheck disable=SC1090
        . "$_W_metadatafile"

        # Compute cached and downloadable flags
        flags=""
        test "$media" = "download" && winetricks_append_to_flags "$_W_download"
        winetricks_is_cached "$code" && winetricks_append_to_flags "$_W_cached"
        test "$flags" && flags="[$flags]"

        if ! test "$year" && ! test "$publisher"
        then
            printf "%-24s %s %s\n" "$code" "$title" "$flags"
        else
            printf "%-24s %s (%s, %s) %s\n" "$code" "$title" "$publisher" "$year" "$flags"
        fi
        )
    done
    unset _W_cached _W_metadatafile
}

# Abort if user doesn't own the given directory (or its parent, if it doesn't exist yet)
winetricks_die_if_user_not_dirowner()
{
    if test -d "$1"
    then
        _W_checkdir="$1"
    else
        # fixme: quoting problem?
        _W_checkdir=$(dirname "$1")
    fi
    _W_nuser=$(id -u)
    _W_nowner=$(stat -c '%u' "$_W_checkdir")
    if test x"$_W_nuser" != x"$_W_nowner"
    then
        w_die "You ($(id -un)) don't own $_W_checkdir.  Don't run this tool as another user!"
    fi
}

# See
# https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-119.pdf (iso9660)
# https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-167.pdf
# http://www.osta.org/specs/pdf/udf102.pdf
# https://www.ecma-international.org/publications/techreports/E-TR-071.htm

# Usage: read_bytes offset count device
winetricks_read_bytes()
{
    dd status=noxfer if="$3" bs=1 skip="$1" count="$2" 2>/dev/null
}

# Usage: read_hex offset count device
winetricks_read_hex()
{
    od -j "$1" -N "$2" -t x1 "$3"     | # offset $1, count $2, single byte hex format, file $3
        sed 's/^[^ ]* //'             | # remove address
        sed '$d'                        # remove final line which is just final offset
}

# Usage: read_decimal offset device
# Reads single four byte word, outputs in decimal.
# Uses default endianness.
# udf uses little endian words, so this only works on little endian machines.
winetricks_read_decimal()
{
    od -j "$1" -N 4  -t u4 "$2"          | # offset $1, byte count 4, four byte decimal format, file $2
        sed 's/^[^ ]* //'             | # remove address
        sed '$d'                        # remove final line which is just final offset
}

winetricks_read_udf_volume_name()
{
    # "Anchor volume descriptor pointer" starts at sector 256

    # AVDP Layout (ECMA-167 3/10.2):
    # size   offset   contents
    # 16     0        descriptor tag (id = 2)
    # 16     8        main (primary?) volume descriptor sequence extent
    # ...

    # descriptor tag layout (ECMA-167 3/7.2):
    # size   offset   contents
    # 2      0        TagIdentifier
    # ...

    # extent layout (ECMA-167 3/7.1):
    # size   offset   contents
    # 4      0        length (in bytes)
    # 8      4        location (in 2k sectors)

    # primary volume descriptor layout (ECMA-167 3/10.1):
    # size   offset   contents
    # 16     0        descriptor tag (id = 1)
    # ...
    # 32     24       volume identifier (dstring)

    # 1. check the 16 bit TagIdentifier of the descriptor tag, make sure it's 2
    tagid=$(winetricks_read_hex 524288 2 "$1")
    : echo "tagid is $tagid"
    case "$tagid" in
    "02 00") : echo "Found AVDP" ;;
    *) echo "Did not find AVDP (tagid was $tagid)"; exit 1;;
    esac

    # 2. read the location of the main volume descriptor:
    offset=$(winetricks_read_decimal 524308 "$1")
    : echo "MVD is at sector $offset"
    offset=$((offset * 2048))
    : echo "MVD is at byte $offset"

    # 3. check the TagIdentifier of the MVD's descriptor tag, make sure it's 1
    tagid=$(winetricks_read_hex $offset 2 "$1")
    : echo "tagid is $tagid"
    case "$tagid" in
    "01 00") : echo Found MVD ;;
    *) echo Did not find MVD; exit 1;;
    esac

    # 4. Read whether the name is in 8 or 16 bit chars
    offset=$((offset + 24))
    width=$(winetricks_read_hex $offset 1 "$1")

    offset=$((offset + 1))

    # 5. Profit!
    case $width in
    08)   winetricks_read_bytes $offset 30 "$1" | sed 's/  *$//' ;;
    10)  winetricks_read_bytes $offset 30 "$1" | tr -d '\000' | sed 's/  *$//' ;;
    *) echo "Unhandled dvd volname character width '$width'"; exit 1;;
    esac

    echo ""
}

winetricks_read_iso9660_volume_name()
{
    winetricks_read_bytes 32808 30 "$1" | sed 's/  *$//'
}

winetricks_read_volume_name()
{
    # ECMA-119 says that CD-ROMs have sector size 2k, and at sector 16 have:
    # size  offset contents
    #  1    0      Volume descriptor type (1 for primary volume descriptor)
    #  5    1      Standard identifier ("CD001" for iso9660)
    # ECMA-167, section 9.1.2, has a table of standard identifiers:
    # "BEA01": ecma-167 9.2, Beginning Extended Area Descriptor
    # "CD001": ecma-119
    # "CDW02": ecma-168

    std_id=$(winetricks_read_bytes 32769 5 "$1")
    : echo "std_id is $std_id"

    case $std_id in
    CD001) winetricks_read_iso9660_volume_name "$1" ;;
    BEA01) winetricks_read_udf_volume_name "$1" ;;
    *) echo "Unrecognized disk type $std_id"; exit 1 ;;
    esac
}

winetricks_volname()
{
    x=$(volname "$1" 2> /dev/null| sed 's/  *$//')
    if test "x$x" = "x"
    then
        # UDF?  See https://bugs.launchpad.net/bugs/678419
        x=$(winetricks_read_volume_name "$1")
    fi
    echo "$x"
}

# Really, should take a volume name as argument, and use 'mount' to get
# mount point if system automounted it.
winetricks_detect_optical_drive()
{
    case "$WINETRICKS_DEV" in
    "") ;;
    *) return ;;
    esac

    for WINETRICKS_DEV in /dev/cdrom /dev/dvd /dev/sr0
    do
        test -b $WINETRICKS_DEV && break
    done

    case "$WINETRICKS_DEV" in
    "x") w_die "can't find cd/dvd drive" ;;
    esac
}

winetricks_cache_iso()
{
    # WINETRICKS_IMG has already been set by w_mount
    _W_expected_volname="$1"

    winetricks_die_if_user_not_dirowner "$W_CACHE"
    winetricks_detect_optical_drive

    # Horrible hack for Gentoo - make sure we can read from the drive
    if ! test -r $WINETRICKS_DEV
    then
        case "$WINETRICKS_SUDO" in
        gksudo) $WINETRICKS_SUDO "chmod 666 $WINETRICKS_DEV" ;;
        *) $WINETRICKS_SUDO chmod 666 $WINETRICKS_DEV ;;
        esac
    fi

    while true
    do
        # Wait for user to insert disc.
        # Sleep long to make it less likely to close the drive during insertion.
        while ! dd if=$WINETRICKS_DEV of=/dev/null count=1
        do
            sleep 5
        done

        # Some distributions automount discs in /media, take advantage of that
        if test -d "/media/_W_expected_volname"
        then
            break
        fi
        # Otherwise try and read it straight from unmounted volume
        _W_volname=$(winetricks_volname $WINETRICKS_DEV)
        if test "$_W_expected_volname" != "$_W_volname"
        then
            case $LANG in
            da*)  w_warn "Forkert disk [$_W_volname] indsat. Indsæt venligst disken [$_W_expected_volname]" ;;
            de*)  w_warn "Falsche Disk [$_W_volname] eingelegt. Bitte legen Sie Disk [$_W_expected_volname] ein!" ;;
            pl*)  w_warn "Włożono zły dysk [$_W_volname]. Proszę włożyć dysk [$_W_expected_volname]" ;;
            ru*)  w_warn "Неверный диск [$_W_volname]. Пожалуйста, вставьте диск [$_W_expected_volname]" ;;
            uk*)  w_warn "Неправильний диск [$_W_volname]. Будь ласка, вставте диск [$_W_expected_volname]" ;;
            zh_CN*)    w_warn " [$_W_volname] 光盘插入错误，请插入光盘 [$_W_expected_volname]" ;;
            zh_TW*|zh_HK*)    w_warn " [$_W_volname] 光碟插入錯誤，請插入光碟 [$_W_expected_volname]" ;;
            *)    w_warn "Wrong disc [$_W_volname] inserted.  Please insert disc [$_W_expected_volname]" ;;
            esac

            sleep 10
        else
            break
        fi
    done

    # Copy disc to .iso file, display progress every 5 seconds
    # Use conv=noerror,sync to replace unreadable blocks with zeroes
    case $WINETRICKS_OPT_DD in
    dd)
      $WINETRICKS_OPT_DD if=$WINETRICKS_DEV of="$W_CACHE"/temp.iso bs=2048 conv=noerror,sync &
      WINETRICKS_DD_PID=$!
      ;;
    ddrescue)
      if test "$(which ddrescue)" = ""
      then
          w_die "Please install ddrescue first."
      fi
      $WINETRICKS_OPT_DD -v -b 2048 $WINETRICKS_DEV "$W_CACHE"/temp.iso &
      WINETRICKS_DD_PID=$!
      ;;
    esac
    echo "$WINETRICKS_DD_PID" > "$WINETRICKS_WORKDIR"/dd-pid

    # Note: if user presses ^C, winetricks_cleanup will call winetricks_iso_cleanup
    # FIXME: add progress bar for kde, too
    case $WINETRICKS_GUI in
    none|kdialog)
        while ps -p "$WINETRICKS_DD_PID" > /dev/null 2>&1
        do
          sleep 5
          ls -l "$W_CACHE"/temp.iso
        done
        ;;
    zenity)
        while ps -p "$WINETRICKS_DD_PID" > /dev/null 2>&1
        do
          echo 1
          sleep 2
        done | $WINETRICKS_GUI --title "Copying to $_W_expected_volname.iso" --progress --pulsate --auto-kill
        ;;
    esac
    rm "$WINETRICKS_WORKDIR"/dd-pid

    mv "$W_CACHE"/temp.iso "$WINETRICKS_IMG"

    eject $WINETRICKS_DEV || true    # punt if eject not found (as on cygwin)
}

winetricks_load_vcdmount()
{
    if test "$WINE" != ""
    then
        return
    fi
}

winetricks_mount_cached_iso()
{
    # On entry, WINETRICKS_IMG is already set
    w_umount

    if test "$WINE" = ""
    then
        winetricks_load_vcdmount
        my_img_win="$(w_pathconv -w "$WINETRICKS_IMG" | tr '\012' ' ' | sed 's/ $//')"
        w_try_cd "$VCD_DIR"
        w_try vcdmount.exe /l="$letter" "$my_img_win"

        tries=0
        while test $tries -lt 20
        do
            for W_ISO_MOUNT_LETTER in e f g h i j k
            do
                # let user blacklist drive letters
                echo "$WINETRICKS_MOUNT_LETTER_IGNORE" | grep -q "$W_ISO_MOUNT_LETTER" && continue
                W_ISO_MOUNT_ROOT=/cygdrive/$W_ISO_MOUNT_LETTER
                if find $W_ISO_MOUNT_ROOT -iname 'setup*' -o -iname '*.exe' -o -iname '*.msi'
                then
                    break 2
                fi
            done
            tries=$((tries + 1))
            echo "Waiting for mount to finish mounting"
            sleep 1
        done
    else
        # Linux
        # FIXME: find a way to mount or copy from image without sudo
        _W_USERID=$(id -u)
        case "$WINETRICKS_SUDO" in
        gksudo)
          w_try $WINETRICKS_SUDO "mkdir -p $W_ISO_MOUNT_ROOT"
          w_try $WINETRICKS_SUDO "mount -o ro,loop,uid=$_W_USERID,unhide $WINETRICKS_IMG $W_ISO_MOUNT_ROOT"
          ;;
        *)
          w_try $WINETRICKS_SUDO mkdir -p $W_ISO_MOUNT_ROOT
          w_try $WINETRICKS_SUDO mount -o ro,loop,uid="$_W_USERID",unhide "$WINETRICKS_IMG" $W_ISO_MOUNT_ROOT
          ;;
        esac

        echo "Mounting as drive ${W_ISO_MOUNT_LETTER}:"
        # Gotta provide a symlink to the raw disc, else installers that check volume names will fail
        rm -f "$WINEPREFIX/dosdevices/${W_ISO_MOUNT_LETTER}:"*
        ln -sf "$WINETRICKS_IMG" "$WINEPREFIX/dosdevices/${W_ISO_MOUNT_LETTER}::"
        ln -sf "$W_ISO_MOUNT_ROOT" "$WINEPREFIX/dosdevices/${W_ISO_MOUNT_LETTER}:"
        unset _W_USERID
    fi
}

# List the currently mounted UDF or iso9660 filesystems that match the given pattern
# Output format:
#   dev mountpoint
#   dev mountpoint
#   ...
# Mount points may contain spaces.

winetricks_list_mounts()
{
    mount | grep -E 'udf|iso9660' | sed 's,^\([^ ]*\) on \(.*\) type .*,\1 \2,'| grep "$1\$"
}

# Return success and set _W_dev _W_mountpoint if volume $1 is mounted
# Note: setting variables as a way of returning results from a
# shell function exposed several bugs in most shells (except ksh!)
# related to implicit subshells.  It would be better to output
# one string to stdout instead.
winetricks_is_mounted()
{
    # First, check for matching mountpoint
    _W_tmp="$(winetricks_list_mounts "$1")"
    if test "$_W_tmp"
    then
        _W_dev=$(echo "$_W_tmp" | sed 's/ .*//')
        _W_mountpoint="$(echo "$_W_tmp" | sed 's/^[^ ]* //')"
        # Volume found!
        return 0
    fi

    # If that fails, read volume name the hard way for each volume
    # Have to use file to return results from implicit subshell
    rm -f "$W_TMP_EARLY/_W_tmp.$LOGNAME"
    winetricks_list_mounts . | while true
    do
        IFS= read -r _W_tmp

        _W_dev=$(echo "$_W_tmp" | sed 's/ .*//')
        test "$_W_dev" || break
        _W_mountpoint="$(echo "$_W_tmp" | sed 's/^[^ ]* //')"
        _W_volname=$(winetricks_volname "$_W_dev")
        if test "$1" = "$_W_volname"
        then
            # Volume found!  Want to return from function here, but can't
            echo "$_W_tmp" > "$W_TMP_EARLY/_W_tmp.$LOGNAME"
            break
        fi
    done

    if test -f "$W_TMP_EARLY/_W_tmp.$LOGNAME"
    then
        # Volume found!  Return from function.
        _W_dev=$(sed 's/ .*//' "$W_TMP_EARLY/_W_tmp.$LOGNAME")
        _W_mountpoint="$(sed 's/^[^ ]* //' "$W_TMP_EARLY/_W_tmp.$LOGNAME")"
        rm -f "$W_TMP_EARLY/_W_tmp.$LOGNAME"
        return 0
    fi

    # Volume not found
    unset _W_dev _W_mountpoint _W_volname
    return 1
}

winetricks_mount_real_volume()
{
    _W_expected_volname="$1"

    # Wait for user to insert disc.

    case $LANG in
    da*)_W_mountmsg="Indsæt venligst disken '$_W_expected_volname' (krævet af pakken '$W_PACKAGE')" ;;
    de*)_W_mountmsg="Bitte Disk '$_W_expected_volname' einlegen (für Paket '$W_PACKAGE')" ;;
    pl*)  _W_mountmsg="Proszę włożyć dysk '$_W_expected_volname' (potrzebny paczce '$W_PACKAGE')" ;;
    ru*)  _W_mountmsg="Пожалуйста, вставьте том '$_W_expected_volname' (требуется для пакета '$W_PACKAGE')" ;;
    uk*)  _W_mountmsg="Будь ласка, вставте том '$_W_expected_volname' (потрібний для пакунка '$W_PACKAGE')" ;;
    zh_CN*)  _W_mountmsg="请插入卷 '$_W_expected_volname' (为包 '$W_PACKAGE 所需')" ;;
    zh_TW*|zh_HK*)  _W_mountmsg="請插入卷 '$_W_expected_volname' (為包 '$W_PACKAGE 所需')" ;;
    *)  _W_mountmsg="Please insert volume '$_W_expected_volname' (needed for package '$W_PACKAGE')" ;;
    esac

    if test "$WINE" = ""
    then
        # Assume already mounted, just get drive letter
        W_ISO_MOUNT_LETTER=$(awk '/iso/ {print $1}' < /proc/mounts | tr -d :)
        W_ISO_MOUNT_ROOT=$(awk '/iso/ {print $2}' < /proc/mounts)
    else
        while ! winetricks_is_mounted "$_W_expected_volname"
        do
            w_try w_warn_cancel "$_W_mountmsg"
            # In non-gui case, give user two seconds to futz with disc drive before spamming him again
            sleep 2
        done
        WINETRICKS_DEV=$_W_dev
        W_ISO_MOUNT_ROOT="$_W_mountpoint"

        # Gotta provide a symlink to the raw disc, else installers that check volume names will fail
        rm -f "$WINEPREFIX/dosdevices/${W_ISO_MOUNT_LETTER}:"*
        ln -sf "$WINETRICKS_DEV" "$WINEPREFIX/dosdevices/${W_ISO_MOUNT_LETTER}::"
        ln -sf "$W_ISO_MOUNT_ROOT" "$WINEPREFIX/dosdevices/${W_ISO_MOUNT_LETTER}:"
    fi

    # FIXME: need to remount some discs with unhide option,
    # add that as option to w_mount

    unset _W_mountmsg
}

winetricks_cleanup()
{
    # We don't want to run this multiple times, so unfortunately we have to run it here:
    if test "$W_NGEN_CMD"
    then
        "$W_NGEN_CMD"
    fi

    set +e
    if test -f "$WINETRICKS_WORKDIR/dd-pid"
    then
        # shellcheck disable=SC2046
        kill $(cat "$WINETRICKS_WORKDIR/dd-pid")
    fi
    test "$WINETRICKS_CACHE_SYMLINK" && rm -f "$WINETRICKS_CACHE_SYMLINK"
    test "$W_OPT_NOCLEAN" = 1 || rm -rf "$WINETRICKS_WORKDIR"
    # if $W_TMP_EARLY was created by mktemp, remove it (but not if W_OPT_NOCLEAN is set to 1):
    test "$W_OPT_NOCLEAN" = 1 || rm -rf "$W_TMP_EARLY"
}

winetricks_set_unattended()
{
    # We shouldn't use all these extra variables.  Instead, we should
    # use ${foo:+bar} to jam in commandline options for silent install
    # only if W_OPT_UNATTENDED is nonempty.  See
    # http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_02
    # So in attended mode, W_OPT_UNATTENDED should be empty.

    case "$1" in
    1)
        W_OPT_UNATTENDED=1
        # Might want to trim our stable of variables here a bit...
        W_UNATTENDED_DASH_Q="-q"
        W_UNATTENDED_SLASH_Q="/q"
        W_UNATTENDED_SLASH_QB="/qb"
        W_UNATTENDED_SLASH_QN="/qn"
        W_UNATTENDED_SLASH_QNT="/qnt"
        W_UNATTENDED_SLASH_QT="/qt"
        W_UNATTENDED_SLASH_QUIET="/quiet"
        W_UNATTENDED_SLASH_S="/S"
        W_UNATTENDED_DASH_SILENT="-silent"
        W_UNATTENDED_SLASH_SILENT="/silent"
        ;;
    *)
        W_OPT_UNATTENDED=""
        W_UNATTENDED_DASH_Q=""
        W_UNATTENDED_SLASH_Q=""
        W_UNATTENDED_SLASH_QB=""
        W_UNATTENDED_SLASH_QN=""
        W_UNATTENDED_SLASH_QNT=""
        W_UNATTENDED_SLASH_QT=""
        W_UNATTENDED_SLASH_QUIET=""
        W_UNATTENDED_SLASH_S=""
        W_UNATTENDED_DASH_SILENT=""
        W_UNATTENDED_SLASH_SILENT=""
        ;;
    esac
}

# Usage: winetricks_set_wineprefix [bottlename]
# Bottlename must not contain spaces, slashes, or other special characters
# If bottlename is omitted, the default bottle (~/.wine) is used.
winetricks_set_wineprefix()
{
    if ! test "$1"
    then
        WINEPREFIX="$WINETRICKS_ORIGINAL_WINEPREFIX"
    else
        WINEPREFIX="$W_PREFIXES_ROOT/$1"
    fi
    export WINEPREFIX
    #echo "WINEPREFIX is now $WINEPREFIX" >&2
    mkdir -p "$(dirname "$WINEPREFIX")"

    # Run wine here to force creation of the wineprefix so it's there when we want to make the cache symlink a bit later.
    # The folder-name is localized!
    W_PROGRAMS_WIN="$(w_expand_env ProgramFiles)"
    case "$W_PROGRAMS_WIN" in
    "") w_die "$WINE cmd.exe /c echo '%ProgramFiles%' returned empty string, error message \"$(cat $W_TMP_EARLY/early_wine.err.txt)\" ";;
    %*) w_die "$WINE cmd.exe /c echo '%ProgramFiles%' returned unexpanded string '$W_PROGRAMS_WIN' ... this can be caused by a corrupt wineprefix, by an old wine, or by not owning $WINEPREFIX" ;;
    *unknown*) w_die "$WINE cmd.exe /c echo '%ProgramFiles%' returned a string containing the word 'unknown', as if a voice had cried out in terror, and was suddenly silenced." ;;
    esac

    case "$W_PLATFORM" in
    windows_cmd)
        W_DRIVE_C="/cygdrive/c" ;;
    *)
        W_DRIVE_C="$WINEPREFIX/dosdevices/c:" ;;
    esac

    # Kludge: use Temp instead of temp to avoid \t expansion in w_try
    # but use temp in Unix path because that's what Wine creates, and having both temp and Temp
    # causes confusion (e.g. makes vc2005trial fail)
    if ! test "$1"
    then
        W_TMP="$W_DRIVE_C/windows/temp"
        W_TMP_WIN="C:\\windows\\Temp"
    else
        # Verbs can rely on W_TMP being empty at entry, deleted after return, and a subdir of C:
        W_TMP="$W_DRIVE_C/windows/temp/_$1"
        W_TMP_WIN="C:\\windows\\Temp\\_$1"
    fi

    case "$W_PLATFORM" in
     "windows_cmd|wine_cmd")
        W_CACHE_WIN="$(w_pathconv -w "$W_CACHE")"
        ;;
     *)
        # For case where Z: doesn't exist or / is writable (!),
        # make a drive letter for W_CACHE.  Clean it up on exit.
        test "$WINETRICKS_CACHE_SYMLINK" && rm -f "$WINETRICKS_CACHE_SYMLINK"
        for letter in y x w v u t s r q p o n m
        do
            if ! test -d "$WINEPREFIX"/dosdevices/${letter}:
            then
                mkdir -p "$WINEPREFIX"/dosdevices
                WINETRICKS_CACHE_SYMLINK="$WINEPREFIX"/dosdevices/${letter}:
                ln -sf "$W_CACHE" "$WINETRICKS_CACHE_SYMLINK"
                break
            fi
        done
        W_CACHE_WIN="${letter}:"
        ;;
    esac

    # FIXME: wrong on 64-bit Windows for now
    W_COMMONFILES_X86_WIN="$(w_expand_env CommonProgramFiles)"

    W_WINDIR_UNIX="$W_DRIVE_C/windows"

    # FIXME: move that tr into w_pathconv, if it's still needed?
    W_PROGRAMS_UNIX="$(w_pathconv -u "$W_PROGRAMS_WIN")"

    # 64-bit Windows has a second directory for program files
    W_PROGRAMS_X86_WIN="${W_PROGRAMS_WIN} (x86)"
    W_PROGRAMS_X86_UNIX="${W_PROGRAMS_UNIX} (x86)"
    if ! test -d "$W_PROGRAMS_X86_UNIX"
    then
        W_PROGRAMS_X86_WIN="${W_PROGRAMS_WIN}"
        W_PROGRAMS_X86_UNIX="${W_PROGRAMS_UNIX}"
    fi

    W_APPDATA_WIN="$(w_expand_env AppData)"
    # shellcheck disable=SC2034
    W_APPDATA_UNIX="$(w_pathconv -u "$W_APPDATA_WIN")"

    # FIXME: get fonts path from SHGetFolderPath
    # See also https://blogs.msdn.microsoft.com/oldnewthing/20031103-00/?p=41973/
    W_FONTSDIR_WIN="c:\\windows\\Fonts"

    # FIXME: just convert path from Windows to Unix?
    # Did the user rename Fonts to fonts?
    if test ! -d "$W_WINDIR_UNIX"/Fonts && test -d "$W_WINDIR_UNIX"/fonts
    then
        W_FONTSDIR_UNIX="$W_WINDIR_UNIX"/fonts
    else
        W_FONTSDIR_UNIX="$W_WINDIR_UNIX"/Fonts
    fi
    mkdir -p "${W_FONTSDIR_UNIX}"

    # Win(e) 32/64?
    # Using the variable W_SYSTEM32_DLLS instead of SYSTEM32 because some stuff does go under system32 for both arch's
    # e.g., spool/drivers/color
    if test -d "$W_DRIVE_C/windows/syswow64"
    then
        W_ARCH=win64
        W_SYSTEM32_DLLS="$W_WINDIR_UNIX/syswow64"
        W_SYSTEM32_DLLS_WIN="C:\\windows\\syswow64"
        W_SYSTEM64_DLLS="$W_WINDIR_UNIX/system32"
        # shellcheck disable=SC2034
        W_SYSTEM64_DLLS_WIN32="C:\\windows\\sysnative" # path to access 64-bit dlls from 32-bit apps
        # shellcheck disable=SC2034
        W_SYSTEM64_DLLS_WIN64="C:\\windows\\system32"  # path to access 64-bit dlls from 64-bit apps
        # 64-bit prefixes still have plenty of issues:
        w_warn "You are using a 64-bit WINEPREFIX. If you encounter problems, please retest in a clean 32-bit WINEPREFIX before reporting a bug."
    else
        W_ARCH=win32
        W_SYSTEM32_DLLS="$W_WINDIR_UNIX/system32"
        W_SYSTEM32_DLLS_WIN="C:\\windows\\system32"
    fi
}

winetricks_annihilate_wineprefix()
{
    w_skip_windows "No wineprefix to delete on windows" && return

    case $LANG in
    uk*) w_askpermission "Бажаєте видалити '$WINEPREFIX'?" ;;
    *) w_askpermission "Delete $WINEPREFIX, its apps, icons, and menu items?" ;;
    esac
    rm -rf "$WINEPREFIX"

    # Also remove menu items.
    find "$XDG_DATA_HOME/applications/wine" -type f -name '*.desktop' -exec grep -q -l "$WINEPREFIX" '{}' ';' -exec rm '{}' ';'

    # Also remove desktop items.
    # Desktop might be synonym for home directory, so only go one level
    # deep to avoid extreme slowdown if user has lots of files
    (
    if ! test "$XDG_DESKTOP_DIR" && test -f "$XDG_CONFIG_HOME/user-dirs.dirs"
    then
        # shellcheck disable=SC1090
        . "$XDG_CONFIG_HOME/user-dirs.dirs"
    fi
    find "$XDG_DESKTOP_DIR" -maxdepth 1 -type f -name '*.desktop' -exec grep -q -l "$WINEPREFIX" '{}' ';' -exec rm '{}' ';'
    )

    # FIXME: recover more nicely.  At moment, have to restart to avoid trouble.
    exit 0
}

winetricks_init()
{
    #---- Private Variables ----

    if ! test "$USERNAME"
    then
        # Posix only requires LOGNAME to be defined, and sure enough, when
        # logging in via console and startx in Ubuntu 11.04, USERNAME isn't set!
        # And even normal logins in Ubuntu 13.04 doesn't set it.
        # I tried using only LOGNAME in this script, but it's so easy to slip
        # and use USERNAME, so define it here if needed.
        USERNAME="$LOGNAME"
    fi

    # Ephemeral files for this run
    WINETRICKS_WORKDIR="$W_TMP_EARLY/w.$LOGNAME.$$"
    test "$W_OPT_NOCLEAN" = 1 || rm -rf "$WINETRICKS_WORKDIR"

    # Registering a verb creates a file in WINETRICKS_METADATA
    WINETRICKS_METADATA="$WINETRICKS_WORKDIR/metadata"

    # The list of categories is also hardcoded in winetricks_mainmenu() :-(
    WINETRICKS_CATEGORIES="apps benchmarks dlls fonts games settings"
    for _W_cat in $WINETRICKS_CATEGORIES
    do
        mkdir -p "$WINETRICKS_METADATA/$_W_cat"
    done

    # Which subdirectory of WINETRICKS_METADATA is currently active (or main, if none)
    WINETRICKS_CURMENU=prefix

    # Delete work directory after each run, on exit either graceful or abrupt
    trap winetricks_cleanup EXIT HUP INT QUIT ABRT

    # Whether to always cache cached iso's (1) or only use cache if present (0)
    # Can be inherited from environment or set via -k, defaults to off
    WINETRICKS_OPT_KEEPISOS=${WINETRICKS_OPT_KEEPISOS:-0}

    # what program to use to make disc image (dd or ddrescue)
    WINETRICKS_OPT_DD=${WINETRICKS_OPT_DD:-dd}

    # whether to use shared wineprefix (1) or unique wineprefix for each app (0)
    WINETRICKS_OPT_SHAREDPREFIX=${WINETRICKS_OPT_SHAREDPREFIX:-0}

    WINETRICKS_SOURCEFORGE=https://downloads.sourceforge.net

    winetricks_get_sha1sum_prog
    winetricks_get_sha256sum_prog

    winetricks_get_platform

    #---- Public Variables ----

    # Where application installers are cached
    # See https://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
    # OSX: https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/MacOSXDirectories/MacOSXDirectories.html

    if test -d "$HOME/Library"
    then
        # OS X
        XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/Library/Caches}"
        XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/Library/Preferences}"
    else
        XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
        XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"
    fi

    # shellcheck disable=SC2153
    if test "$WINETRICKS_DIR"
    then
        # For backwards compatibility
        W_CACHE="${W_CACHE:-$WINETRICKS_DIR/cache}"
        WINETRICKS_POST="${WINETRICKS_POST:-$WINETRICKS_DIR/postinstall}"
    else
        W_CACHE="${W_CACHE:-$XDG_CACHE_HOME/winetricks}"
        WINETRICKS_POST="${WINETRICKS_POST:-$XDG_DATA_HOME/winetricks/postinstall}"
    fi

    WINETRICKS_AUTH="${WINETRICKS_AUTH:-$XDG_DATA_HOME/winetricks/auth}"

    # Config options are currently opt-in and not required, so not creating the config
    # directory unless there's demand:
    WINETRICKS_CONFIG="${XDG_CONFIG_HOME}/winetricks"
    #test -d "$WINETRICKS_CONFIG" || mkdir -p "$WINETRICKS_CONFIG"

    # System-specific variables
    case "$W_PLATFORM" in
     windows_cmd)
        WINE=""
        WINESERVER=""
        W_DRIVE_C="C:/"
        ;;
     *)
        WINE="${WINE:-wine}"
        # Find wineserver.
        # Some distributions (Debian before wine 1.8-2) don't have it on the path.
        for x in \
            "$WINESERVER" \
            "${WINE}server" \
            "$(which wineserver 2> /dev/null)" \
            "$(dirname $WINE)/server/wineserver" \
            /usr/bin/wineserver-development \
            /usr/lib/wine/wineserver \
            /usr/lib/i386-kfreebsd-gnu/wine/wineserver \
            /usr/lib/i386-linux-gnu/wine/wineserver \
            /usr/lib/powerpc-linux-gnu/wine/wineserver \
            /usr/lib/i386-kfreebsd-gnu/wine/bin/wineserver \
            /usr/lib/i386-linux-gnu/wine/bin/wineserver \
            /usr/lib/powerpc-linux-gnu/wine/bin/wineserver \
            /usr/lib/x86_64-linux-gnu/wine/bin/wineserver \
            /usr/lib/i386-kfreebsd-gnu/wine-development/wineserver \
            /usr/lib/i386-linux-gnu/wine-development/wineserver \
            /usr/lib/powerpc-linux-gnu/wine-development/wineserver \
            /usr/lib/x86_64-linux-gnu/wine-development/wineserver \
            file-not-found
        do
            if test -x "$x"
            then
                case "$x" in
                 /usr/lib/*/wine-development/wineserver|/usr/bin/wineserver-development)
                    if test -x /usr/bin/wine-development
                    then
                        WINE="/usr/bin/wine-development"
                    fi
                    ;;
                esac
                break
            fi
        done
        case "$x" in
        file-not-found)
            w_die "wineserver not found!" ;;
        *)
            WINESERVER="$x" ;;
        esac

        if test "$WINEPREFIX"
        then
            WINETRICKS_ORIGINAL_WINEPREFIX="$WINEPREFIX"
        else
            WINETRICKS_ORIGINAL_WINEPREFIX="$HOME/.wine"
        fi
        _abswine="$(which "$WINE" 2>/dev/null)"
        if ! test -x "$_abswine" || ! test -f "$_abswine"
        then
            w_die "WINE is $WINE, which is neither on the path nor an executable file"
        fi
        unset _abswine
        ;;
    esac
    winetricks_set_wineprefix "$1"

    # Whether to automate installs (0=no, 1=yes)
    winetricks_set_unattended ${W_OPT_UNATTENDED:-0}

    # Overridden for windows
    W_ISO_MOUNT_ROOT=/mnt/winetricks
    W_ISO_MOUNT_LETTER=i

    WINETRICKS_WINE_VERSION=$(winetricks_early_wine --version | sed 's/.*wine/wine/')
    WINETRICKS_ORIG_WINE_VERSION="${WINETRICKS_WINE_VERSION}"
    # See also w_wine_version()
    # A small hack...
    case "$WINETRICKS_WINE_VERSION" in
        wine-1.4-*) WINETRICKS_WINE_VERSION="wine-1.4.40"; export WINETRICKS_WINE_VERSION;;
        wine-1.4) WINETRICKS_WINE_VERSION="wine-1.4.0"; export WINETRICKS_WINE_VERSION;;
        wine-1.6-*) WINETRICKS_WINE_VERSION="wine-1.6.0"; export WINETRICKS_WINE_VERSION;;
        wine-1.6) WINETRICKS_WINE_VERSION="wine-1.6.0"; export WINETRICKS_WINE_VERSION;;
        wine-1.8-*) WINETRICKS_WINE_VERSION="wine-1.8.0"; export WINETRICKS_WINE_VERSION;;
        wine-1.8) WINETRICKS_WINE_VERSION="wine-1.8.0"; export WINETRICKS_WINE_VERSION;;
        wine-2.0-*) WINETRICKS_WINE_VERSION="wine-1.10.0"; export WINETRICKS_WINE_VERSION;;
        wine-2.0) WINETRICKS_WINE_VERSION="wine-1.10.0"; export WINETRICKS_WINE_VERSION;;
        wine-3.0-*) WINETRICKS_WINE_VERSION="wine-1.11.0"; export WINETRICKS_WINE_VERSION;;
        wine-3.0) WINETRICKS_WINE_VERSION="wine-1.11.0"; export WINETRICKS_WINE_VERSION;;
    esac
    WINETRICKS_WINE_MINOR=$(echo $WINETRICKS_WINE_VERSION | sed 's/wine-1\.\([0-9]*\)\..*/\1/')
    WINETRICKS_WINE_MICRO=$(echo $WINETRICKS_WINE_VERSION | sed 's/wine-1.[0-9][0-9]*\.\([0-9]*\).*/\1/')

    if [ ! "$WINETRICKS_SUPER_QUIET" ] ; then
        echo "Using winetricks $(winetricks_print_version) with ${WINETRICKS_ORIG_WINE_VERSION} and WINEARCH=${W_ARCH}"
    fi

    winetricks_latest_version_check
}

winetricks_usage()
{
    case $LANG in
    da*)
        cat <<_EOF_
Brug: $0 [tilvalg] [verbum|sti-til-verbum] ...
Kører de angivne verber.  Hvert verbum installerer et program eller ændrer en indstilling.
Tilvalg:
-k|--keep_isos: lagr iso'er lokalt (muliggør senere installation uden disk)
-q|--unattended: stil ingen spørgsmål, installér bare automatisk
-r|--ddrescue: brug alternativ disk-tilgangsmetode (hjælper i tilfælde af en ridset disk)
-t|--torify: Run downloads under torify, if available
-v|--verbose: vis alle kommandoer som de bliver udført
-V|--version: vis programversionen og afslut
-h|--help: vis denne besked og afslut
Diverse verber:
list: vis en liste over alle verber
list-cached: vis en liste over verber for allerede-hentede installationsprogrammer
list-download: vis en liste over verber for programmer der kan hentes
list-manual-download: list applications which can be downloaded with some help from the user
list-installed: list already-installed applications
_EOF_
        ;;
    de*)
        cat <<_EOF_
Benutzung: $0 [options] [Kommando|Verb|Pfad-zu-Verb] ...
Angegebene Verben ausführen.
Jedes Verb installiert eine Anwendung oder ändert eine Einstellung.

Optionen:
    --force           Nicht prüfen ob Pakete bereits installiert wurden
    --gui             GUI Diagnosen anzeigen, auch wenn von der Kommandozeile gestartet
    --isolate         Jedes Programm oder Spiel in eigener Bottle (WINEPREFIX) installieren
-k, --keep_isos       ISOs local speichern (erlaubt spätere Installation ohne Disk)
    --no-clean        Temp Verzeichnisse nicht löschen (nützlich beim debuggen)
-q, --unattended      Keine Fragen stellen, alles automatisch installieren
-r, --ddrescue        Alternativer Zugriffsmodus (hilft bei zerkratzten Disks)
    --showbroken      Auch Verben anzeigen die momentan in Wine nicht funktionieren
-t  --torify          Run downloads under torify, if available
    --verify          Wenn Möglisch automatische GUI Tests für Verben starten
-v, --verbose         Alle ausgeführten Kommandos anzeigen
-h, --help            Diese Hilfemeldung anzeigen
-V, --version         Programmversion anzeigen und Beenden

Kommandos:
list                  Kategorien auflisten
list-all              Alle Kategorien und deren Verben auflisten
apps list             Verben der Kategorie 'Anwendungen' auflisten
benchmarks list       Verben der Kategorie 'Benchmarks' auflisten
dlls list             Verben der Kategorie 'DLLs' auflisten
games list            Verben der Kategorie 'Spiele' auflisten
settings list         Verben der Kategorie 'Einstellungen' auflisten
list-cached           Verben für bereits gecachte Installers auflisten
list-download         Verben für automatisch herunterladbare Anwendungen auflisten
list-manual-download  Verben für vom Benutzer herunterladbare Anwendungen auflisten
list-installed        Bereits installierte Verben auflisten
prefix=foobar         WINEPREFIX=$W_PREFIXES_ROOT/foobar auswählen
_EOF_
        ;;
    *)
        cat <<_EOF_
Usage: $0 [options] [command|verb|path-to-verb] ...
Executes given verbs.  Each verb installs an application or changes a setting.

Options:
    --force           Don't check whether packages were already installed
    --gui             Show gui diagnostics even when driven by commandline
    --isolate         Install each app or game in its own bottle (WINEPREFIX)
    --self-update     Update this application to the last version
    --update-rollback Rollback the last self update
-k, --keep_isos       Cache isos (allows later installation without disc)
    --no-clean        Don't delete temp directories (useful during debugging)
-q, --unattended      Don't ask any questions, just install automatically
-r, --ddrescue        Retry hard when caching scratched discs
    --showbroken      Even show verbs that are currently broken in wine
-t  --torify          Run downloads under torify, if available
    --verify          Run (automated) GUI tests for verbs, if available
-v, --verbose         Echo all commands as they are executed
-h, --help            Display this message and exit
-V, --version         Display version and exit

Commands:
list                  list categories
list-all              list all categories and their verbs
apps list             list verbs in category 'applications'
benchmarks list       list verbs in category 'benchmarks'
dlls list             list verbs in category 'dlls'
games list            list verbs in category 'games'
settings list         list verbs in category 'settings'
list-cached           list cached-and-ready-to-install verbs
list-download         list verbs which download automatically
list-manual-download  list verbs which download with some help from the user
list-installed        list already-installed verbs
prefix=foobar         select WINEPREFIX=$W_PREFIXES_ROOT/foobar
_EOF_
        ;;
    esac
}

winetricks_handle_option()
{
    case "$1" in
    --force) WINETRICKS_FORCE=1;;
    --gui) winetricks_detect_gui;;
    -h|--help) winetricks_usage ; exit 0 ;;
    --isolate) WINETRICKS_OPT_SHAREDPREFIX=0 ;;
    -k|--keep_isos) WINETRICKS_OPT_KEEPISOS=1 ;;
    --no-clean) W_OPT_NOCLEAN=1 ;;
    --no-isolate) WINETRICKS_OPT_SHAREDPREFIX=1 ;;
    --optin) WINETRICKS_STATS_REPORT=1;;
    --optout) WINETRICKS_STATS_REPORT=0;;
    -q|--unattended) winetricks_set_unattended 1 ;;
    -r|--ddrescue) WINETRICKS_OPT_DD=ddrescue ;;
    --self-update) winetricks_selfupdate;;
    --showbroken) W_OPT_SHOWBROKEN=1 ;;
    -t|--torify)  WINETRICKS_OPT_TORIFY=1 ;;
    --update-rollback) winetricks_selfupdate_rollback;;
    -v|--verbose) WINETRICKS_OPT_VERBOSE=1 ; set -x;;
    -V|--version) winetricks_print_version ; exit 0;;
    --verify) WINETRICKS_VERIFY=1 ;;
    -vv|--really-verbose) WINETRICKS_OPT_VERBOSE=2 ; set -x ;;
    -*) w_die "unknown option $1" ;;
    *) return 1 ;;
    esac
    return 0
}

# Must initialize variables before calling w_metadata
if ! test "$WINETRICKS_LIB"
then
    WINETRICKS_SRCDIR=$(dirname "$0")
    WINETRICKS_SRCDIR=$(w_try_cd "$WINETRICKS_SRCDIR"; pwd)

    # Which GUI helper to use (none/zenity/kdialog).  See winetricks_detect_gui.
    WINETRICKS_GUI=none
    # Default to a shared prefix:
    WINETRICKS_OPT_SHAREDPREFIX=${WINETRICKS_OPT_SHAREDPREFIX:-1}

    # Handle options before init, to avoid starting wine for --help or --version
    while winetricks_handle_option "$1"
    do
        shift
    done

    # Workaround for https://github.com/Winetricks/winetricks/issues/599
    # If --isolate is used, pass verb to winetricks_init, so it can set the wineprefix using winetricks_set_wineprefix()
    # Otherwise, an arch mismatch between ${WINEPREFIX:-$HOME/.wine} and the prefix to be made for the isolated app would cause it to fail
    case $WINETRICKS_OPT_SHAREDPREFIX in
        0) winetricks_init "$1" ;;
        *) winetricks_init ;;
    esac
fi

winetricks_install_app()
{
    case $LANG in
    da*) fail_msg="Installationen af pakken $1 fejlede" ;;
    de*) fail_msg="Installieren von Paket $1 gescheitert" ;;
    pl*) fail_msg="Niepowodzenie przy instalacji paczki $1" ;;
    ru*) fail_msg="Ошибка установки пакета $1" ;;
    uk*) fail_msg="Помилка встановлення пакунка $1" ;;
    zh_CN*)   fail_msg="$1 安装失败" ;;
    zh_TW*|zh_HK*)   fail_msg="$1 安裝失敗" ;;
    *)   fail_msg="Failed to install package $1" ;;
    esac

    # FIXME: initialize a new wineprefix for this app, set lots of global variables
    if ! w_do_call "$1" "$2"
    then
        w_die "$fail_msg"
    fi
}

#---- Builtin Verbs ----

#----------------------------------------------------------------
# Runtimes
#----------------------------------------------------------------

#----- common download for several verbs

#----------------------------------------------------------------
## Mozilla Public License
w_metadata gecko dlls \
    title="Gecko (usually installed by distro)" \
    publisher="WineHQ/Mozilla"

load_gecko()
{
    if test -f /usr/share/wine/gecko/wine_gecko-1.0.0-x86.cab && test -f /usr/share/wine/gecko/wine_gecko-1.1.0-x86.cab && test -f /usr/share/wine/gecko/wine_gecko-1.2.0-x86.msi
    then
        w_warn "gecko is already installed in /usr/share/wine"
    else
        w_warn "Please install gecko in /usr/share/wine per http://wiki.winehq.org/Gecko.  http://winezeug.googlecode.com/svn/trunk/install-gecko.sh is an easy script to do that.  Then you should never need to do 'winetricks gecko' again."
    fi
}

#----------------------------------------------------------------
##Mozilla Public License
w_metadata gecko110 dlls \
    title="Gecko 1.1.0 (not normally needed)" \
    publisher="WineHQ/Mozilla" \
    year="2010" \
    media="download" \
    file1="wine_gecko-1.1.0-x86.cab" \
    installed_file1="$W_SYSTEM32_DLLS_WIN/gecko/1.1.0/wine_gecko/nspr4.dll"

load_gecko110()
{
    w_skip_windows gecko110 && return

    w_warn "You should probably not be using the gecko110 verb, see http://wiki.winehq.org/Gecko"
    case `$WINE --version` in
        wine-1.3.[2-9]|wine-1.3.[2-9]-*|wine-1.3.1[0-5]*)
        ;;
    *)
        w_die "This verb only supports wine-1.3.2 to wine-1.3.15"
        ;;
    esac

    w_download http://downloads.sourceforge.net/project/wine/Wine%20Gecko/1.1.0/wine_gecko-1.1.0-x86.cab 1b6c637207b6f032ae8a52841db9659433482714

    mkdir -p "$W_SYSTEM32_DLLS/gecko/1.1.0"
    cd "$W_SYSTEM32_DLLS/gecko/1.1.0"
    w_try_cabextract $W_UNATTENDED_DASH_Q "$W_CACHE/gecko110/wine_gecko-1.1.0-x86.cab"

    cat > "$W_TMP"/geckopath.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\MSHTML\1.1.0]
"GeckoPath"="c:\\\\windows\\\\system32\\\\gecko\\\\1.1.0\\\\wine_gecko\\\\"
_EOF_
    w_try_regedit "$W_TMP_WIN"\\geckopath.reg

    w_try_regsvr mshtml
}

w_metadata gecko120 dlls \
    title="Gecko 1.2.0 (not normally needed)" \
    publisher="WineHQ/Mozilla" \
    year="2011" \
    media="download" \
    file1="wine_gecko-1.2.0-x86.msi" \
    installed_file1="$W_SYSTEM32_DLLS_WIN/gecko/1.2.0/wine_gecko/nspr4.dll"

load_gecko120()
{
    w_skip_windows gecko120 && return

    w_warn "You should probably not be using the gecko120 verb, see http://wiki.winehq.org/Gecko"
    case `$WINE --version` in
    wine-0*|wine-1.[012]*|wine-1.3|wine-1.3.[0-9]|wine-1.3.1[0-4])
        w_die "This verb only supports wine-1.3.15 and higher at the moment"
        ;;
    esac

    w_download http://downloads.sourceforge.net/project/wine/Wine%20Gecko/1.2.0/wine_gecko-1.2.0-x86.msi 6964d1877668ab7da07a60f6dcf23fb0e261a808

    w_try "$WINE" msiexec /i "$W_CACHE"/gecko120/wine_gecko-1.2.0-x86.msi $W_UNATTENDED_SLASH_Q
}

#----------------------------------------------------------------
# um, codecs are kind of clustered here.  They probably deserve their own real category.

w_metadata allcodecs dlls \
    title="All codecs (dirac, ffdshow, xvid)" \
    publisher="various" \
    year="1998-2009" \
    media="download"

load_allcodecs()
{
    w_call dirac
    w_call ffdshow
    w_call xvid
}

#----------------------------------------------------------------
##MPL 1.1, GNU GPL 2, GNU LGPL 2, MIT License
w_metadata dirac dlls \
    title="The Dirac directshow filter v1.0.2" \
    publisher="Dirac" \
    year="2009" \
    media="download" \
    file1="DiracDirectShowFilter-1.0.2.exe" \
    installed_file1="$W_PROGRAMS_X86_WIN/Dirac/DiracDecoder.dll"

load_dirac()
{
    w_download $WINETRICKS_SOURCEFORGE/dirac/DiracDirectShowFilter-1.0.2.exe c912d30a8fa500c7841444559feb1f49301611c4

    # Avoid mfc90 not found error.  (DiracSplitter-libschroedinger.ax needs mfc90 to register itself, I think.)
    w_call vcrun2008

    cd "$W_CACHE"/dirac
    w_ahk_do "
        SetTitleMatchMode, 2
        run DiracDirectShowFilter-1.0.2.exe
        WinWait, Dirac, Welcome
        if ( w_opt_unattended > 0 ) {
            ControlClick, Button2
            WinWait, Dirac, License
            ControlClick, Button2
            WinWait, Dirac, Location
            ControlClick, Button2
            WinWait, Dirac, Components
            ControlClick, Button2
            WinWait, Dirac, environment
            ControlCLick, Button1
            WinWait, Dirac, installed
            ControlClick, Button2
        }
        WinWaitClose
    "
}

#----------------------------------------------------------------
##GPLv2 license
w_metadata ffdshow dlls \
    title="ffdshow video codecs" \
    publisher="doom9 folks" \
    year="2010" \
    media="download" \
    file1="ffdshow_beta7_rev3154_20091209.exe" \
    installed_file1="$W_PROGRAMS_X86_WIN/ffdshow/ff_liba52.dll" \
    homepage="http://ffdshow-tryout.sourceforge.net"

load_ffdshow()
{
    w_download $WINETRICKS_SOURCEFORGE/ffdshow-tryout/ffdshow_beta7_rev3154_20091209.exe 8534c31489e51df70ee9583438d6211e6f0696d0
    cd "$W_CACHE"/ffdshow
    w_try "$WINE" ffdshow_beta7_rev3154_20091209.exe $W_UNATTENDED_SLASH_SILENT
}

#----------------------------------------------------------------
##LGPLv2 license
w_metadata kde apps \
    title="KDE on Windows" \
    publisher="various" \
    year="2011" \
    media="download" \
    file1="kdewin-installer-gui-0.9.8-1.exe" \
    installed_exe1="$W_PROGRAMS_WIN/kde/etc/installer.ini" \
    homepage="http://windows.kde.org" \
    unattended="no"

load_kde()
{
    w_download http://www.winkde.org/pub/kde/ports/win32/installer/kdewin-installer-gui-0.9.8-1.exe b31aaf24d23b9f289bf56aa21e1571efc6bea58a

    mkdir -p "$W_PROGRAMS_UNIX/kde"
    w_try cp "$W_CACHE"/kde/kdewin-installer-gui-0.9.8-1.exe "$W_PROGRAMS_UNIX/kde"
    cd "$W_PROGRAMS_UNIX/kde"
    # There's no unattended option, probably because there are so many choices,
    # it's like cygwin
    w_try "$WINE" kdewin-installer-gui-0.9.8-1.exe
}

#----------------------------------------------------------------
##New BSD License, GPL-compatible
w_metadata ogg dlls \
    title="OpenCodecs 0.85: flac, speex, theora, vorbis, WebM" \
    publisher="xiph.org" \
    year="2011" \
    media="download" \
    file1="opencodecs_0.85.17777.exe" \
    installed_file1="$W_PROGRAMS_X86_WIN/Xiph.Org/Open Codecs/AxPlayer.dll" \
    homepage="http://xiph.org/dshow"

load_ogg()
{
    w_download http://downloads.xiph.org/releases/oggdsf/opencodecs_0.85.17777.exe 386cf7cd29ffcbf8705eff8c8233de448ecf33ab
    cd "$W_CACHE"/ogg
    w_try "$WINE" $file1 $W_UNATTENDED_SLASH_S
}

#----------------------------------------------------------------

w_metadata remove_mono settings \
    title_uk="Видалити вбудоване wine-mono" \
    title="Remove builtin wine-mono"

load_remove_mono()
{
    # FIXME: fold other .NET cleanups here (registry entries).
    # Probably should only do that for wine >= 1.5.6
    mono_uuid="`$WINE uninstaller --list | grep Mono | cut -f1 -d\|`"
    if test "$mono_uuid"
    then
         "$WINE" uninstaller --remove $mono_uuid
    else
        w_warn "Mono does not appear to be installed."
    fi
}


#----------------------------------------------------------------
##zlib license, GPL-compatible
w_metadata sdl dlls \
    title="Simple DirectMedia Layer" \
    publisher="Sam Lantinga" \
    year="2009" \
    media="download" \
    file1="SDL-1.2.14-win32.zip" \
    installed_file1="$W_SYSTEM32_DLLS_WIN/SDL.dll"

load_sdl()
{
    # http://www.libsdl.org/download-1.2.php
    w_download http://www.libsdl.org/release/SDL-1.2.14-win32.zip d22c71d1c2bdf283548187c4b0bd7ef9d0c1fb23
    w_try_unzip "$W_CACHE"/sdl/SDL-1.2.14-win32.zip -d "$W_SYSTEM32_DLLS" SDL.dll
}

#----------------------------------------------------------------
##GPL
w_metadata xvid dlls \
    title="Xvid Video Codec" \
    publisher="xvid.org" \
    year="2009" \
    media="download" \
    file1="Xvid-1.3.2-20110601.exe" \
    installed_file1="$W_PROGRAMS_X86_WIN/Xvid/xvid.ico"

load_xvid()
{
    w_call vcrun6
    w_download http://www.koepi.info/Xvid-1.3.2-20110601.exe 74b23965cebe59e388eab6dba224b6b751ef4519454cc12086ade51c81f0a33c
    w_try_cd "$W_CACHE/$W_PACKAGE"
    w_try "$WINE" "$file1" ${W_OPT_UNATTENDED:+ --mode unattended --decode_divx 1 --decode_3ivx 1 --decode_other 1}
}

#----------------------------------------------------------------
# Fonts
#----------------------------------------------------------------
##BSD
w_metadata baekmuk fonts \
    title="Baekmuk Korean fonts" \
    publisher="Wooderart Inc. / kldp.net" \
    year="1999" \
    media="download" \
    file1="fonts-baekmuk_2.2.orig.tar.gz" \
    installed_file1="$W_FONTSDIR_WIN/batang.ttf"

load_baekmuk()
{
    # See http://kldp.net/projects/baekmuk for project page
    # Need to download from Debian as the project page has unique captcha tokens per visitor
    w_download http://http.debian.net/debian/pool/main/f/fonts-baekmuk/fonts-baekmuk_2.2.orig.tar.gz 08ab7dffb55d5887cc942ce370f5e33b756a55fbb4eaf0b90f244070e8d51882

    w_try_cd "$W_TMP"
    tar zxvf "$W_CACHE/$W_PACKAGE/$file1" baekmuk-ttf-2.2/ttf
    w_try mv baekmuk-ttf-2.2/ttf/*.ttf "$W_FONTSDIR_UNIX"
    w_register_font batang.ttf "Baekmuk Batang"
    w_register_font gulim.ttf "Baekmuk Gulim"
    w_register_font dotum.ttf "Baekmuk Dotum"
    w_register_font hline.ttf "Baekmuk Headline"
}

#----------------------------------------------------------------

w_metadata cjkfonts fonts \
    title="All Chinese, Japanese, Korean fonts and aliases" \
    publisher="various" \
    date="1999-2010" \
    media="download"

load_cjkfonts()
{
    w_call fakechinese
    w_call fakejapanese
    w_call fakekorean
    w_call unifont
}

#----------------------------------------------------------------


#----------------------------------------------------------------
w_metadata fakechinese fonts \
    title="Creates aliases for Chinese fonts using WenQuanYi fonts" \
    publisher="wenq.org" \
    year="2009"

load_fakechinese()
{
    w_call wenquanyi
    # Loads Wenquanyi fonts and sets aliases for Microsoft Chinese fonts
    # Reference : https://en.wikipedia.org/wiki/List_of_Microsoft_Windows_fonts

    w_register_font_replacement "Microsoft JhengHei" "WenQuanYi Micro Hei"
    w_register_font_replacement "Microsoft YaHei" "WenQuanYi Micro Hei"
    w_register_font_replacement "SimHei" "WenQuanYi Micro Hei"
    w_register_font_replacement "DFKai-SB" "WenQuanYi Micro Hei"
    w_register_font_replacement "FangSong" "WenQuanYi Micro Hei"
    w_register_font_replacement "KaiTi" "WenQuanYi Micro Hei"
    w_register_font_replacement "PMingLiU" "WenQuanYi Micro Hei"
    w_register_font_replacement "MingLiU" "WenQuanYi Micro Hei"
    w_register_font_replacement "NSimSun" "WenQuanYi Micro Hei"
    w_register_font_replacement "SimKai" "WenQuanYi Micro Hei"
    w_register_font_replacement "SimSun" "WenQuanYi Micro Hei"
}

#----------------------------------------------------------------

w_metadata fakejapanese fonts \
    title="Creates aliases for Japanese fonts using Takao fonts" \
    publisher="Jun Kobayashi" \
    year="2010"

load_fakejapanese()
{
    w_call takao
    # Loads Takao fonts and sets aliases for MS Gothic, MS UI Gothic, and MS PGothic, mainly for Japanese language support
    # Aliases to set:
    # MS Gothic --> TakaoGothic
    # MS UI Gothic --> TakaoGothic
    # MS PGothic --> TakaoPGothic
    # MS Mincho --> TakaoMincho
    # MS PMincho --> TakaoPMincho
    # These aliases were taken from what was listed in Ubuntu's fontconfig definitions.

    w_register_font_replacement "MS Gothic" "TakaoGothic"
    w_register_font_replacement "MS UI Gothic" "TakaoGothic"
    w_register_font_replacement "MS PGothic" "TakaoPGothic"
    w_register_font_replacement "MS Mincho" "TakaoMincho"
    w_register_font_replacement "MS PMincho" "TakaoPMincho"
}

#----------------------------------------------------------------

w_metadata fakejapanese_ipamona fonts \
    title="Creates aliases for Japanese fonts using IPAMona fonts" \
    publisher="Jun Kobayashi" \
    year="2008"

load_fakejapanese_ipamona()
{
    w_call ipamona

    # Aliases to set:
    # MS UI Gothic --> IPAMonaUIGothic
    # MS Gothic (ＭＳ ゴシック) --> IPAMonaGothic
    # MS PGothic (ＭＳ Ｐゴシック) --> IPAMonaPGothic
    # MS Mincho (ＭＳ 明朝) --> IPAMonaMincho
    # MS PMincho (ＭＳ Ｐ明朝) --> IPAMonaPMincho

    jpname_msgothic="$(echo "ＭＳ ゴシック" | iconv -f utf8 -t cp932)"
    jpname_mspgothic="$(echo "ＭＳ Ｐゴシック" | iconv -f utf8 -t cp932)"
    jpname_msmincho="$(echo "ＭＳ 明朝" | iconv -f utf8 -t cp932)"
    jpname_mspmincho="$(echo "ＭＳ Ｐ明朝" | iconv -f utf8 -t cp932)"

    w_register_font_replacement "MS UI Gothic" "IPAMonaUIGothic"
    w_register_font_replacement "MS Gothic" "IPAMonaGothic"
    w_register_font_replacement "MS PGothic" "IPAMonaPGothic"
    w_register_font_replacement "MS Mincho" "IPAMonaMincho"
    w_register_font_replacement "MS PMincho" "IPAMonaPMincho"
    w_register_font_replacement "$jpname_msgothic" "IPAMonaGothic"
    w_register_font_replacement "$jpname_mspgothic" "IPAMonaPGothic"
    w_register_font_replacement "$jpname_msmincho" "IPAMonaMincho"
    w_register_font_replacement "$jpname_mspmincho" "IPAMonaPMincho"
}

#----------------------------------------------------------------

w_metadata fakekorean fonts \
    title="Creates aliases for Korean fonts using Baekmuk fonts" \
    publisher="Wooderart Inc. / kldp.net" \
    year="1999"

load_fakekorean()
{
    w_call baekmuk
    # Loads Baekmuk fonts and sets as an alias for Gulim, Dotum, and Batang for Korean language support
    # Aliases to set:
    # Gulim --> Baekmuk Gulim
    # GulimChe --> Baekmuk Gulim
    # Batang --> Baekmuk Batang
    # BatangChe --> Baekmuk Batang
    # Dotum --> Baekmuk Dotum
    # DotumChe --> Baekmuk Dotum

    w_register_font_replacement "Gulim" "Baekmuk Gulim"
    w_register_font_replacement "GulimChe" "Baekmuk Gulim"
    w_register_font_replacement "Batang" "Baekmuk Batang"
    w_register_font_replacement "BatangChe" "Baekmuk Batang"
    w_register_font_replacement "Dotum" "Baekmuk Dotum"
    w_register_font_replacement "DotumChe" "Baekmuk Dotum"
}

#----------------------------------------------------------------
#----------------------------------------------------------------

w_metadata fontfix settings \
    title="Check for broken fonts"

load_fontfix()
{
    # Focht says Samyak is bad news, and font substitution isn't a good workaround.
    # I've seen psdkwin7 setup crash because of this; the symptom was a messagebox saying
    # SDKSetup encountered an error: The type initializer for 'Microsoft.WizardFramework.WizardSettings' threw an exception
    # and WINEDEBUG=+relay,+seh shows an exception very quickly after
    # Call KERNEL32.CreateFileW(0c83b36c L"Z:\\USR\\SHARE\\FONTS\\TRUETYPE\\TTF-ORIYA-FONTS\\SAMYAK-ORIYA.TTF",80000000,00000001,00000000,00000003,00000080,00000000) ret=70d44091
    if xlsfonts 2>/dev/null | grep -E -i "samyak.*oriya"
    then
        w_die "Please uninstall the Samyak/Oriya font, e.g. 'sudo dpkg -r ttf-oriya-fonts', then log out and log in again.  That font causes strange crashes in .net programs."
    fi
}

#----------------------------------------------------------------

w_metadata liberation fonts \
    title="Red Hat Liberation fonts (Sans, Serif, Mono)" \
    publisher="Red Hat" \
    year="2008" \
    media="download" \
    file1="liberation-fonts-1.04.tar.gz" \
    installed_file1="$W_FONTSDIR_WIN/LiberationMono-BoldItalic.ttf"

load_liberation()
{
    # https://www.redhat.com/en/about/blog/liberation-fonts
    case $(uname -s) in
    SunOS|Solaris)
      echo "If you get 'ERROR: Certificate verification error for fedorahosted.org: unable to get local issuer certificate':"
      echo "Then you need to add Verisign root certificates to your local keystore."
      echo "OpenSolaris users, see: https://www.linuxtopia.org/online_books/opensolaris_2008/SYSADV1/html/swmgrpatchtasks-14.html"
      echo "Or edit winetricks's download function, and add '--no-check-certificate' to the command."
      ;;
    esac

    w_download https://fedorahosted.org/releases/l/i/liberation-fonts/liberation-fonts-1.04.tar.gz 0e0d0957c85b758561a3d4aef4ebcd2c39959e5328429d96ae106249d83531a1
    w_try_cd "$W_TMP"
    # FIXME: w_try doesn't work here, presumably because of the pipe?
    gunzip -dc "$W_CACHE/$W_PACKAGE/$file1" | tar -xf -
    w_try mv liberation-fonts-1.04/*.ttf "$W_FONTSDIR_UNIX"

    w_register_font LiberationMono-BoldItalic.ttf "LiberationMono-BoldItalic"
    w_register_font LiberationMono-Bold.ttf "LiberationMono-Bold"
    w_register_font LiberationMono-Italic.ttf "LiberationMono-Italic"
    w_register_font LiberationMono-Regular.ttf "LiberationMono-Regular"
    w_register_font LiberationSans-BoldItalic.ttf "LiberationSans-BoldItalic"
    w_register_font LiberationSans-Bold.ttf "LiberationSans-Bold"
    w_register_font LiberationSans-Italic.ttf "LiberationSans-Italic"
    w_register_font LiberationSans-Regular.ttf "LiberationSans-Regular"
    w_register_font LiberationSerif-BoldItalic.ttf "LiberationSerif-BoldItalic"
    w_register_font LiberationSerif-Bold.ttf "LiberationSerif-Bold"
    w_register_font LiberationSerif-Italic.ttf "LiberationSerif-Italic"
    w_register_font LiberationSerif-Regular.ttf "LiberationSerif-Regular"
}

#----------------------------------------------------------------

w_metadata opensymbol fonts \
    title="OpenSymbol fonts (replacement for Wingdings)" \
    publisher="OpenOffice.org" \
    year="2016" \
    media="download" \
    file1="fonts-opensymbol_102.2+LibO3.5.4+dfsg2-0+deb7u8_all.deb" \
    installed_file1="$W_FONTSDIR_WIN/opens___.ttf"

load_opensymbol()
{
    # The OpenSymbol fonts are a replacement for the Windows Wingdings font from OpenOffice.org.
    # Need to w_download Debian since I can't find a standalone download from OpenOffice
    # Note: The source download package on debian is for _all_ of OpenOffice, which is 266 MB.
    w_download http://security.debian.org/debian-security/pool/updates/main/libr/libreoffice/fonts-opensymbol_102.2+LibO3.5.4+dfsg2-0+deb7u8_all.deb 3b7ad433cf8944789be1f1b7cf14aed5c2f9dab26f04824eebea2a3a8544a777

    w_try_cd "$W_TMP"
    w_try_ar "$W_CACHE/$W_PACKAGE/$file1" data.tar.xz
    w_try tar Jvxf "$W_TMP/data.tar.xz" ./usr/share/fonts/truetype/openoffice/opens___.ttf
    w_try mv "$W_TMP/usr/share/fonts/truetype/openoffice/opens___.ttf" "$W_FONTSDIR_UNIX"
    w_register_font opens___.ttf "OpenSymbol"
}

#----------------------------------------------------------------
#----------------------------------------------------------------
##IPA Font License
w_metadata takao fonts \
    title="Takao Japanese fonts" \
    publisher="Jun Kobayashi" \
    year="2010" \
    media="download" \
    file1="takao-fonts-ttf-003.02.01.zip" \
    installed_file1="$W_FONTSDIR_WIN/TakaoGothic.ttf"

load_takao()
{
    # The Takao font provides Japanese glyphs.  May also be needed with fakejapanese function above.
    # See https://launchpad.net/takao-fonts for project page
    w_download https://launchpad.net/takao-fonts/trunk/003.02.01/+download/takao-fonts-ttf-003.02.01.zip 2f526a16c7931958f560697d494d8304949b3ce0aef246fb0c727fbbcc39089e
    cp -f "$W_CACHE"/takao/takao-fonts-ttf-003.02.01.zip "$W_TMP"
    w_try_unzip "$W_TMP" "$W_TMP"/takao-fonts-ttf-003.02.01.zip
    w_try cp -f "$W_TMP"/takao-fonts-ttf-003.02.01/*.ttf "$W_FONTSDIR_UNIX"

    w_register_font TakaoGothic.ttf "TakaoGothic"
    w_register_font TakaoPGothic.ttf "TakaoPGothic"
    w_register_font TakaoMincho.ttf "TakaoMincho"
    w_register_font TakaoPMincho.ttf "TakaoPMincho"
    w_register_font TakaoExGothic.ttf "TakaoExGothic"
    w_register_font TakaoExMincho.ttf "TakaoExMincho"
}

#----------------------------------------------------------------
#----------------------------------------------------------------

w_metadata wenquanyi fonts \
    title="WenQuanYi CJK font" \
    publisher="wenq.org" \
    year="2009" \
    media="download" \
    file1="wqy-microhei-0.2.0-beta.tar.gz" \
    installed_file1="$W_FONTSDIR_WIN/wqy-microhei.ttc"

load_wenquanyi()
{
    # See http://wenq.org/enindex.cgi
    # Donate at http://wenq.org/enindex.cgi?Download(en)#MicroHei_Beta if you want to help support free CJK font development
    w_download $WINETRICKS_SOURCEFORGE/wqy/wqy-microhei-0.2.0-beta.tar.gz 2802ac8023aa36a66ea6e7445854e3a078d377ffff42169341bd237871f7213e
    w_try_cd "$W_TMP/"
    gunzip -dc "$W_CACHE/wenquanyi/wqy-microhei-0.2.0-beta.tar.gz" | tar -xf -
    w_try mv wqy-microhei/wqy-microhei.ttc "$W_FONTSDIR_UNIX"
    w_register_font wqy-microhei.ttc "WenQuanYi Micro Hei"
}

#----------------------------------------------------------------
##GPLv2
w_metadata unifont fonts \
    title="Unifont alternative to Arial Unicode MS" \
    publisher="Roman Czyborra / GNU" \
    year="2008" \
    media="download" \
    file1="unifont-5.1.20080907.zip" \
    installed_file1="$W_FONTSDIR_WIN/unifont.ttf"

load_unifont()
{
    # The GNU Unifont provides glyphs for just about everything in common language.  It is intended for multilingual usage.
    # See http://unifoundry.com/unifont.html for project page
    w_download http://unifoundry.com/unifont-5.1.20080907.zip 6ec1176f83769072b09de2bc1fff68ec5d802183304756a372e2419236f5b5ba
    cp -f "$W_CACHE"/unifont/unifont-5.1.20080907.zip "$W_TMP"
    w_try_unzip "$W_TMP" "$W_TMP"/unifont-5.1.20080907.zip
    w_try cp -f "$W_TMP"/unifont-5.1.20080907.ttf "$W_FONTSDIR_UNIX/unifont.ttf"

    w_register_font unifont.ttf "Unifont"
    w_register_font_replacement "Arial Unicode MS" "Unifont"
}

#----------------------------------------------------------------

w_metadata allfonts fonts \
    title="All fonts" \
    publisher="various" \
    year="1998-2010" \
    media="download"

load_allfonts()
{
    # This verb uses reflection, should probably do it portably instead, but that would require keeping it up to date
    for file in "$WINETRICKS_METADATA"/fonts/*.vars
    do
        cmd=$(basename "$file" .vars)
        case $cmd in
        allfonts|cjkfonts) ;;
        *) w_call "$cmd";;
        esac
    done
}

#----------------------------------------------------------------
# Apps
#----------------------------------------------------------------

#----------------------------------------------------------------
##AutoHotKey is under GPL license
w_metadata autohotkey apps \
    title="AutoHotKey" \
    publisher="autohotkey.org" \
    year="2010" \
    media="download" \
    file1="AutoHotkey104805_Install.exe" \
    installed_exe1="$W_PROGRAMS_X86_WIN/AutoHotkey/AutoHotkey.exe"

load_autohotkey()
{
    W_BROWSERAGENT=1 \
    w_download https://www.autohotkey.com/download/AutoHotkey104805_Install.exe 4311c3e7c29ed2d67f415138360210bc2f55ff78758b20b003b91d775ee207b9
    w_try_cd "$W_CACHE/$W_PACKAGE"
    w_try "$WINE" AutoHotkey104805_Install.exe $W_UNATTENDED_SLASH_S
}

#----------------------------------------------------------------
##CMake is under New BSD License and GPL-compatible
w_metadata cmake apps \
    title="CMake 2.8" \
    publisher="Kitware" \
    year="2013" \
    media="download" \
    file1="cmake-2.8.11.2-win32-x86.exe" \
    installed_exe1="$W_PROGRAMS_X86_WIN/CMake 2.8/bin/cmake-gui.exe"

load_cmake()
{
    w_download https://www.cmake.org/files/v2.8/cmake-2.8.11.2-win32-x86.exe cb6a7df8fd6f2eca66512279991f3c2349e3f788477c3be8eaa362d46c21dbf0
    w_try_cd "$W_CACHE/$W_PACKAGE"
    w_try "$WINE" cmake-2.8.11.2-win32-x86.exe $W_UNATTENDED_SLASH_S
}

#----------------------------------------------------------------

w_metadata iceweasel apps \
    title="GNU Icecat 31.7.0" \
    publisher="GNU Foundation" \
    year="2015" \
    media="download" \
    file1="icecat-31.7.0.en-US.win32.zip" \
    installed_exe1="$W_PROGRAMS_X86_WIN/icecat/icecat.exe"

load_iceweasel()
{
    w_download https://ftp.gnu.org/gnu/gnuzilla/31.7.0/icecat-31.7.0.en-US.win32.zip 27d10e63ab9ea4e6995c235b92258b379f79433a06a12e4ad16811801cf81e36
    w_try_unzip "${W_PROGRAMS_X86_UNIX}" "${W_CACHE}/${W_PACKAGE}/${file1}"
}


#----------------------------------------------------------------
##MingW is under GPL license
w_metadata mingw apps \
    title="Minimalist GNU for Windows, including GCC for Windows" \
    publisher="GNU" \
    year="2013" \
    media="download" \
    file1="mingw-get-setup.exe" \
    installed_exe1="c:/MinGW/bin/gcc.exe" \
    homepage="http://mingw.org/wiki/Getting_Started"

load_mingw()
{
    w_download "$WINETRICKS_SOURCEFORGE/mingw/files/mingw-get-setup.exe" aab27bd5547d35dc159288f3b5b8760f21b0cfec86e8f0032b49dd0410f232bc

    w_try_cd "$W_CACHE/mingw"
    w_try "$WINE" "$file1"

    w_append_path 'C:\MinGW\bin'
    w_try "$WINE" mingw-get update
    w_try "$WINE" mingw-get install gcc msys-base
}

#----------------------------------------------------------------
#Python Software Foundation License, GPL-compatibile
w_metadata python26 dlls \
    title="Python interpreter 2.6.2" \
    publisher="Python Software Foundaton" \
    year="2009" \
    media="download" \
    file1="python-2.6.2.msi" \
    installed_exe1="c:/Python26/python.exe"

load_python26()
{
    w_download https://www.python.org/ftp/python/2.6.2/python-2.6.2.msi c2276b398864b822c25a7c240cb12ddb178962afd2e12d602f1a961e31ad52ff
    w_download $WINETRICKS_SOURCEFORGE/project/pywin32/pywin32/Build%20214/pywin32-214.win32-py2.6.exe dc311bbdc5868e3dd139dfc46136221b7f55c5613a98a5a48fa725a6c681cd40

    w_try_cd "$W_CACHE/$W_PACKAGE"
    w_try "$WINE" msiexec /i python-2.6.2.msi ALLUSERS=1 $W_UNATTENDED_SLASH_Q

    w_ahk_do "
        SetTitleMatchMode, 2
        run pywin32-214.win32-py2.6.exe
        WinWait, Setup, Wizard will install pywin32
        if ( w_opt_unattended > 0 ) {
             ControlClick Button2   ; next
             WinWait, Setup, Python 2.6 is required
             ControlClick Button3   ; next
             WinWait, Setup, Click Next to begin
             ControlClick Button3   ; next
             WinWait, Setup, finished
             ControlClick Button4   ; Finish
        }
        WinWaitClose
        "
}

#----------------------------------------------------------------
##MIT License, GPL-compatible.
w_metadata python26_comtypes dlls \
    title="Comtypes 0.6.2 for Python 2.6" \
    publisher="theller" \
    year="2010" \
    media="download" \
    file1="comtypes-0.6.2.zip" \
    installed_file1="c:/Python26/Lib/site-packages/comtypes-0.6.2-py2.6.egg-info" \
    homepage="http://sourceforge.net/projects/comtypes"

load_python26_comtypes()
{
    w_call python26

    w_download $WINETRICKS_SOURCEFORGE/comtypes/0.6.2/comtypes-0.6.2.zip b84f4e3050652d494e8c8d9d6d6f221c124ffba9

    cd "$W_TMP"
    w_try_unzip "$W_CACHE/$W_PACKAGE"/comtypes-0.6.2.zip
    cd comtypes-0.6.2
    w_try "$WINE" "C:\Python26\python.exe" setup.py install
}

#----------------------------------------------------------------

w_metadata vlc apps \
    title="VLC media player 2.2.1" \
    publisher="VideoLAN" \
    year="2015" \
    media="download" \
    file1="vlc-2.2.1-win32.exe" \
    installed_file1="$W_PROGRAMS_X86_WIN/VideoLAN/VLC/vlc.exe" \
    homepage="https://www.videolan.org/vlc/"

load_vlc()
{
    w_download https://get.videolan.org/vlc/2.2.1/win32/vlc-2.2.1-win32.exe 2eaa3881b01a2464d2a155ad49cc78162571dececcef555400666c719a60794d
    w_try_cd "$W_CACHE/$W_PACKAGE"
    w_try "$WINE" "$file1" ${W_OPT_UNATTENDED:+ /S}
}

#----------------------------------------------------------------
# Benchmarks
#----------------------------------------------------------------

##TODO: Find Free Applications to put here.

#----------------------------------------------------------------
# Games
#----------------------------------------------------------------

##TODO: Find Free Games to put here.

#----------------------------------------------------------------
# Settings
#----------------------------------------------------------------
# Direct3D settings

winetricks_set_wined3d_var()
{
    # Filter out/correct bad or partial values
    # Confusing because dinput uses 'disable', but d3d uses 'disabled'
    # see wined3d_dll_init() in dlls/wined3d/wined3d_main.c
    # and DllMain() in dlls/ddraw/main.c
    case $2 in
    disable*) arg=disabled;;
    enable*) arg=enabled;;
    hard*) arg=hardware;;
    repack) arg=repack;;
    backbuffer|fbo|gdi|none|opengl|readdraw|readtex|texdraw|textex|auto) arg=$2;;
    [0-9]*) arg=$2;;
    *) w_die "illegal value $2 for $1";;
    esac

    echo "Setting Direct3D/$1 to $arg"
    cat > "$W_TMP"/set-wined3d.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\Direct3D]
"$1"="$arg"

_EOF_
    w_try_regedit "$W_TMP_WIN"\\set-wined3d.reg
}

#----------------------------------------------------------------

w_metadata glsl=enabled settings \
    title_uk="Включити GLSL шейдери (за замовчуванням)" \
    title="Enable GLSL shaders (default)"
w_metadata glsl=disabled settings \
    title_uk="Вимкнути GLSL шейдери та використовувати ARB шейдери (швидше, але іноді з перервами)" \
    title="Disable GLSL shaders, use ARB shaders (faster, but sometimes breaks)"

load_glsl()
{
    winetricks_set_wined3d_var UseGLSL "$1"
}

#----------------------------------------------------------------

w_metadata multisampling=enabled settings \
    title_uk="Включити Direct3D мультисемплінг" \
    title="Enable Direct3D multisampling"
w_metadata multisampling=disabled settings \
    title_uk="Вимкнути Direct3D мультисемплінг" \
    title="Disable Direct3D multisampling"

load_multisampling()
{
    winetricks_set_wined3d_var Multisampling "$1"
}

#----------------------------------------------------------------

w_metadata npm=repack settings \
    title_uk="Поставити NonPower2Mode на repack" \
    title="Set NonPower2Mode to repack"

load_npm()
{
    winetricks_set_wined3d_var NonPower2Mode "$1"
}

#----------------------------------------------------------------

w_metadata orm=fbo settings \
    title_uk="Поставити OffscreenRenderingMode=fbo (за замовчуванням)" \
    title="Set OffscreenRenderingMode=fbo (default)"
w_metadata orm=backbuffer settings \
    title_uk="Поставити OffscreenRenderingMode=backbuffer" \
    title="Set OffscreenRenderingMode=backbuffer"

load_orm()
{
    winetricks_set_wined3d_var OffscreenRenderingMode "$1"
}

#----------------------------------------------------------------

w_metadata strictdrawordering=enabled settings \
    title_uk="Включити StrictDrawOrdering" \
    title="Enable StrictDrawOrdering"
w_metadata strictdrawordering=disabled settings \
    title_uk="Вимкнути StrictDrawOrdering (за замовчуванням)" \
    title="Disable StrictDrawOrdering (default)"

load_strictdrawordering()
{
    winetricks_set_wined3d_var StrictDrawOrdering "$1"
}

#----------------------------------------------------------------

w_metadata rtlm=auto settings \
    title_uk="Поставити RenderTargetLockMode на авто (за замовчуванням)" \
    title="Set RenderTargetLockMode to auto (default)"
w_metadata rtlm=disabled settings \
    title_uk="Вимкнути RenderTargetLockMode" \
    title="Set RenderTargetLockMode to disabled"
w_metadata rtlm=readdraw settings \
    title_uk="Поставити RenderTargetLockMode на readdraw" \
    title="Set RenderTargetLockMode to readdraw"
w_metadata rtlm=readtex settings \
    title_uk="Поставити RenderTargetLockMode на readtex" \
    title="Set RenderTargetLockMode to readtex"
w_metadata rtlm=texdraw settings \
    title_uk="Поставити RenderTargetLockMode на texdraw" \
    title="Set RenderTargetLockMode to texdraw"
w_metadata rtlm=textex settings \
    title_uk="Поставити RenderTargetLockMode на textex" \
    title="Set RenderTargetLockMode to textex"

load_rtlm()
{
    winetricks_set_wined3d_var RenderTargetLockMode "$1"
}

#----------------------------------------------------------------
# AlwaysOffscreen settings

w_metadata ao=enabled settings \
    title_uk="Включити AlwaysOffscreen" \
    title="Enable AlwaysOffscreen"
w_metadata ao=disabled settings \
    title_uk="Вимкнути AlwaysOffscreen (за замовчуванням)" \
    title="Disable AlwaysOffscreen (default)"

load_ao()
{
    winetricks_set_wined3d_var AlwaysOffscreen "$1"
}

#----------------------------------------------------------------
# CheckFloatConstants settings

w_metadata cfc=enabled settings \
    title_uk="Включити CheckFloatConstants" \
    title="Enable CheckFloatConstants"
w_metadata cfc=disable settings \
    title_uk="Вимкнути CheckFloatConstants (за замовчуванням)" \
    title="Disable CheckFloatConstants (default)"

load_cfc()
{
    winetricks_set_wined3d_var CheckFloatConstants "$1"
}

#----------------------------------------------------------------
# DirectDraw settings

w_metadata ddr=gdi settings \
    title_uk="Поставити DirectDrawRenderer на gdi" \
    title="Set DirectDrawRenderer to gdi"
w_metadata ddr=opengl settings \
    title_uk="Поставити DirectDrawRenderer на opengl" \
    title="Set DirectDrawRenderer to opengl"

load_ddr()
{
    winetricks_set_wined3d_var DirectDrawRenderer "$1"
}

#----------------------------------------------------------------
# DirectInput settings

w_metadata mwo=force settings \
    title_uk="Поставити примусове DirectInput MouseWarpOverride (необхідно для деяких ігор)" \
    title="Set DirectInput MouseWarpOverride to force (needed by some games)"
w_metadata mwo=enabled settings \
    title_uk="Включити DirectInput MouseWarpOverride (за замовчуванням)" \
    title="Set DirectInput MouseWarpOverride to enabled (default)"
w_metadata mwo=disable settings \
    title_uk="Вимкнути DirectInput MouseWarpOverride" \
    title="Set DirectInput MouseWarpOverride to disable"

load_mwo()
{
    # Filter out/correct bad or partial values
    # Confusing because dinput uses 'disable', but d3d uses 'disabled'
    # see alloc_device() in dlls/dinput/mouse.c
    case "$1" in
    enable*) arg=enabled;;
    disable*) arg=disable;;
    force) arg=force;;
    *) w_die "illegal value $1 for MouseWarpOverride";;
    esac

    echo "Setting MouseWarpOverride to $arg"
    cat > "$W_TMP"/set-mwo.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\DirectInput]
"MouseWarpOverride"="$arg"

_EOF_
    w_try_regedit "$W_TMP"/set-mwo.reg
}

#----------------------------------------------------------------
# Mac Driver settings

w_metadata macdriver=mac settings \
    title_uk="Включити рідний Mac Quartz драйвер (за замовчуванням)" \
    title="Enable the Mac native Quartz driver (default)"
w_metadata macdriver=x11 settings \
    title_uk="Вимкнути рідний Mac Quartz драйвер та використовувати замість нього X11" \
    title="Disable the Mac native Quartz driver, use X11 instead"

load_macdriver()
{
    echo "Setting MacDriver to $arg"
    cat > "$W_TMP"/set-mac.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\Drivers]
"Graphics"="$arg"

_EOF_
    w_try_regedit "$W_TMP"/set-mac.reg
}

#----------------------------------------------------------------
# X11 Driver settings

w_metadata grabfullscreen=y settings \
    title_uk="Примусове захоплення курсору для повноекранних вікон (необхідно для деяких ігор)" \
    title="Force cursor clipping for full-screen windows (needed by some games)"
w_metadata grabfullscreen=n settings \
    title_uk="Вимкнути примусове захоплення курсору для повноекранних вікон (за замовчуванням)" \
    title="Disable cursor clipping for full-screen windows (default)"

load_grabfullscreen()
{
    case "$1" in
    y|n) arg=$1;;
    *) w_die "illegal value $1 for GrabFullscreen";;
    esac

    echo "Setting GrabFullscreen to $arg"
    cat > "$W_TMP"/set-gfs.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\X11 Driver]
"GrabFullscreen"="$arg"

_EOF_
    w_try_regedit "$W_TMP"/set-gfs.reg
}

w_metadata windowmanagerdecorated=y settings \
    title_uk="Дозволити менеджеру вікон декорувати вікна (за замовчуванням)" \
    title="Allow the window manager to decorate windows (default)"
w_metadata windowmanagerdecorated=n settings \
    title_uk="Не дозволяти менеджеру вікон декорувати вікна" \
    title="Prevent the window manager from decorating windows"

load_windowmanagerdecorated()
{
    case "$1" in
    y|n) arg=$1;;
    *) w_die "illegal value $1 for Decorated";;
    esac

    echo "Setting Decorated to $arg"
    cat > "$W_TMP"/set-wmd.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\X11 Driver]
"Decorated"="$arg"

_EOF_
    w_try_regedit "$W_TMP"/set-wmd.reg
}

w_metadata windowmanagermanaged=y settings \
    title_uk="Дозволити менеджеру вікон керування вікнами (за замовчуванням)" \
    title="Allow the window manager to control windows (default)"
w_metadata windowmanagermanaged=n settings \
    title_uk="Не дозволяти менеджеру вікон керування вікнами" \
    title="Prevent the window manager from controling windows"

load_windowmanagermanaged()
{
    case "$1" in
    y|n) arg=$1;;
    *) w_die "illegal value $1 for Managed";;
    esac

    echo "Setting Managed to $arg"
    cat > "$W_TMP"/set-wmm.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\X11 Driver]
"Managed"="$arg"

_EOF_
    w_try_regedit "$W_TMP"/set-wmm.reg
}

#----------------------------------------------------------------
# Other settings

#----------------------------------------------------------------

w_metadata alldlls=default settings \
    title_uk="Видалити всі перевизначення DLL" \
    title="Remove all DLL overrides"
w_metadata alldlls=builtin settings \
    title_uk="Перевизначити найбільш поширені DLL на вбудовані" \
    title="Override most common DLLs to builtin"

load_alldlls()
{
    case "$1" in
    default) w_override_no_dlls ;;
    builtin) w_override_all_dlls ;;
    esac
}

w_metadata fontsmooth=disable settings \
    title_uk="Вимкнути згладжування шрифту" \
    title="Disable font smoothing"
w_metadata fontsmooth=bgr settings \
    title_uk="Включити субпіксельне згладжування шрифту для BGR LCD моніторів" \
    title="Enable subpixel font smoothing for BGR LCDs"
w_metadata fontsmooth=rgb settings \
    title_uk="Включити субпіксельне згладжування шрифту для RGB LCD моніторів" \
    title="Enable subpixel font smoothing for RGB LCDs"
w_metadata fontsmooth=gray settings \
    title_uk="Включити субпіксельне згладжування шрифту" \
    title="Enable subpixel font smoothing"

load_fontsmooth()
{
    case "$1" in
    disable)   FontSmoothing=0; FontSmoothingOrientation=1; FontSmoothingType=0;;
    gray|grey) FontSmoothing=2; FontSmoothingOrientation=1; FontSmoothingType=1;;
    bgr)       FontSmoothing=2; FontSmoothingOrientation=0; FontSmoothingType=2;;
    rgb)       FontSmoothing=2; FontSmoothingOrientation=1; FontSmoothingType=2;;
    *) w_die "unknown font smoothing type $1";;
    esac

    echo "Setting font smoothing to $1"

    cat > "$W_TMP"/fontsmooth.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Control Panel\Desktop]
"FontSmoothing"="$FontSmoothing"
"FontSmoothingGamma"=dword:00000578
"FontSmoothingOrientation"=dword:0000000$FontSmoothingOrientation
"FontSmoothingType"=dword:0000000$FontSmoothingType

_EOF_
    w_try_regedit "$W_TMP_WIN"\\fontsmooth.reg
}

#----------------------------------------------------------------

w_metadata forcemono settings \
    title_uk="Примусове використання mono замість .NET (для налогодження)" \
    title="Force using Mono instead of .NET (for debugging)"

load_forcemono()
{
    w_override_dlls native mscoree
    w_override_dlls disabled mscorsvw.exe
}

#----------------------------------------------------------------

w_metadata gsm=0 settings \
    title="Set MaxShaderModelGS to 0"
w_metadata gsm=1 settings \
    title="Set MaxShaderModelGS to 1"
w_metadata gsm=2 settings \
    title="Set MaxShaderModelGS to 2"
w_metadata gsm=3 settings \
    title="Set MaxShaderModelGS to 3"

load_gsm()
{
    winetricks_set_wined3d_var MaxShaderModelGS "$1"
}

#----------------------------------------------------------------

w_metadata heapcheck settings \
    title_uk="Включити накопичувальну перевірку GlobalFlag" \
    title="Enable heap checking with GlobalFlag"

load_heapcheck()
{
    cat > "$W_TMP"/heapcheck.reg <<_EOF_
REGEDIT4

[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager]
"GlobalFlag"=dword:00200030

_EOF_
    w_try_regedit "$W_TMP_WIN"\\heapcheck.reg
}

#----------------------------------------------------------------

w_metadata hidewineexports=enable settings \
    title="Enable hiding Wine exports from applications (wine-staging)"
w_metadata hidewineexports=disable settings \
    title="Disable hiding Wine exports from applications (wine-staging)"

load_hidewineexports()
{
    # Wine exports some functions allowing apps to query the Wine version and
    # information about the host environment. Using these functions, some apps
    # will intentionally terminate if they can detect that they are running in
    # a Wine environment.
    #
    # Hiding these Wine exports is only available in wine-staging.
    # See https://bugs.winehq.org/show_bug.cgi?id=38656
    case $arg in
        enable)
            _W_registry_value="\"Y\""
            ;;
        disable)
            _W_registry_value="-"
            ;;
        *) w_die "Unexpected argument, $arg";;
    esac

    cat > "$W_TMP"/set-wineexports.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine]
"HideWineExports"=$_W_registry_value

_EOF_
    w_try_regedit "$W_TMP"/set-wineexports.reg
}

#----------------------------------------------------------------

w_metadata hosts settings \
    title_uk="Додати порожні файли у C:\windows\system32\drivers\etc\{hosts,services}" \
    title="Add empty C:\windows\system32\drivers\etc\{hosts,services} files"

load_hosts()
{
    # Create fake system32\drivers\etc\hosts and system32\drivers\etc\services files.
    # The hosts file is used to map network names to IP addresses without DNS.
    # The services file is used map service names to network ports.
    # Some apps depend on these files, but they're not implemented in Wine.
    # Fortunately, empty files in the correct location satisfy those apps.
    # See https://bugs.winehq.org/show_bug.cgi?id=12076

    # It's in system32 for both win32/win64
    mkdir -p "$W_WINDIR_UNIX"/system32/drivers/etc
    touch "$W_WINDIR_UNIX"/system32/drivers/etc/hosts
    touch "$W_WINDIR_UNIX"/system32/drivers/etc/services
}

#----------------------------------------------------------------

w_metadata native_mdac settings \
    title_uk="Перевизначити odbc32, odbccp32 та oledb32" \
    title="Override odbc32, odbccp32 and oledb32"

load_native_mdac()
{
    # Set those overrides globally so user programs get MDAC's ODBC
    # instead of Wine's unixodbc
    w_override_dlls native,builtin odbc32 odbccp32 oledb32
}

#----------------------------------------------------------------

w_metadata native_oleaut32 settings \
    title_uk="Перевизначити oleaut32" \
    title="Override oleaut32"

load_native_oleaut32()
{
    w_override_dlls native,builtin oleaut32
}

#----------------------------------------------------------------

w_metadata nocrashdialog settings \
    title_uk="Вимкнути діалог про помилку" \
    title="Disable crash dialog"

load_nocrashdialog()
{
    echo "Disabling graphical crash dialog"
    cat > "$W_TMP"/crashdialog.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\WineDbg]
"ShowCrashDialog"=dword:00000000

_EOF_
    w_try_cd "$W_TMP"
    w_try_regedit crashdialog.reg
}

#----------------------------------------------------------------

w_metadata nt40 settings \
    title_uk="Поставити версію Windows NT 4.0" \
    title="Set windows version to Windows NT 4.0"

load_nt40()
{
    w_set_winver nt40
}

#----------------------------------------------------------------

w_metadata psm=0 settings \
    title="Set MaxShaderModelPS to 0"
w_metadata psm=1 settings \
    title="Set MaxShaderModelPS to 1"
w_metadata psm=2 settings \
    title="Set MaxShaderModelPS to 2"
w_metadata psm=3 settings \
    title="Set MaxShaderModelPS to 3"

load_psm()
{
    winetricks_set_wined3d_var MaxShaderModelPS "$1"
}

#----------------------------------------------------------------

w_metadata sandbox settings \
    title_uk="Пісочниця wineprefix - видалити посилання до HOME" \
    title="Sandbox the wineprefix - remove links to \$HOME"

load_sandbox()
{
    w_skip_windows sandbox && return

    # Unmap drive Z
    rm -f "$WINEPREFIX/dosdevices/z:"

    _olddir="$(pwd)"
    w_try_cd "$WINEPREFIX/drive_c/users/$USER"
    for x in *
    do
        if test -h "$x" && test -d "$x"
        then
            rm -f "$x"
            mkdir -p "$x"
        fi
    done
    w_try_cd "$_olddir"
    unset _olddir

    # Disable unixfs
    # Unfortunately, when you run with a different version of Wine, Wine will recreate this key.
    # See https://bugs.winehq.org/show_bug.cgi?id=22450
    "$WINE" regedit /d 'HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\Desktop\Namespace\{9D20AAE8-0625-44B0-9CA7-71889C2254D9}'

    # Disable recreation of the above key - or any updating of the registry - when running with a newer version of Wine.
    echo disable > "$WINEPREFIX/.update-timestamp"
}

#----------------------------------------------------------------

w_metadata sound=alsa settings \
    title_uk="Поставити звуковий драйвер ALSA" \
    title="Set sound driver to ALSA"
w_metadata sound=coreaudio settings \
    title_uk="Поставити звуковий драйвер Mac CoreAudio" \
    title="Set sound driver to Mac CoreAudio"
w_metadata sound=disabled settings \
    title_uk="Вимкнути звуковий драйвер" \
    title="Set sound driver to disabled"
w_metadata sound=oss settings \
    title_uk="Поставити звуковий драйвер OSS" \
    title="Set sound driver to OSS"
w_metadata sound=pulse settings \
    title_uk="Поставити звуковий драйвер PulseAudio" \
    title="Set sound driver to PulseAudio"

load_sound()
{
    echo "Setting sound driver to $1"
    cat > "$W_TMP"/set-sound.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\Drivers]
"Audio"="$1"

_EOF_
    w_try_regedit "$W_TMP_WIN"\\set-sound.reg
}

#----------------------------------------------------------------

w_metadata vd=off settings \
    title_uk="Вимкнути віртуальний робочий стіл" \
    title="Disable virtual desktop"
w_metadata vd=640x480 settings \
    title_uk="Включити віртуальний робочий стіл та поставити розмір 640x480" \
    title="Enable virtual desktop, set size to 640x480"
w_metadata vd=800x600 settings \
    title_uk="Включити віртуальний робочий стіл та поставити розмір 800x600" \
    title="Enable virtual desktop, set size to 800x600"
w_metadata vd=1024x768 settings \
    title_uk="Включити віртуальний робочий стіл та поставити розмір 1024x768" \
    title="Enable virtual desktop, set size to 1024x768"
w_metadata vd=1280x1024 settings \
    title_uk="Включити віртуальний робочий стіл та поставити розмір 1280x1024" \
    title="Enable virtual desktop, set size to 1280x1024"
w_metadata vd=1440x900 settings \
    title_uk="Включити віртуальний робочий стіл та поставити розмір 1440x900" \
    title="Enable virtual desktop, set size to 1440x900"

load_vd()
{
    size="$1"
    case $size in
    off|disabled)
        cat > "$W_TMP"/vd.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\Explorer]
"Desktop"=-
[HKEY_CURRENT_USER\Software\Wine\Explorer\Desktops]
"Default"=-

_EOF_
        ;;
    [1-9]*x[1-9]*)
        cat > "$W_TMP"/vd.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\Explorer]
"Desktop"="Default"
[HKEY_CURRENT_USER\Software\Wine\Explorer\Desktops]
"Default"="$size"

_EOF_
        ;;
    *)
        w_die "you want a virtual desktop of $size?  I don't understand."
        ;;
    esac
    w_try_regedit "$W_TMP_WIN"/vd.reg
}

#----------------------------------------------------------------

w_metadata videomemorysize=default settings \
    title_uk="Дати можливість Wine визначити розмір відеопам'яті" \
    title="Let Wine detect amount of video card memory"
w_metadata videomemorysize=512 settings \
    title_uk="Повідомити Wine про 512МБ відеопам'яті" \
    title="Tell Wine your video card has 512MB RAM"
w_metadata videomemorysize=1024 settings \
    title_uk="Повідомити Wine про 1024МБ відеопам'яті" \
    title="Tell Wine your video card has 1024MB RAM"
w_metadata videomemorysize=2048 settings \
    title_uk="Повідомити Wine про 2048МБ відеопам'яті" \
    title="Tell Wine your video card has 2048MB RAM"

load_videomemorysize()
{
    size="$1"
    echo "Setting video memory size to $size"

    case $size in
    default)

    cat > "$W_TMP"/set-video.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\Direct3D]
"VideoMemorySize"=-

_EOF_
    ;;
    *)
    cat > "$W_TMP"/set-video.reg <<_EOF_
REGEDIT4

[HKEY_CURRENT_USER\Software\Wine\Direct3D]
"VideoMemorySize"="$size"

_EOF_
    esac
    w_try_regedit "$W_TMP_WIN"\\set-video.reg
}

#----------------------------------------------------------------

w_metadata vista settings \
    title_uk="Поставити версію Windows Vista" \
    title="Set Windows version to Windows Vista"

load_vista()
{
    w_set_winver vista
}

#----------------------------------------------------------------

w_metadata vsm=0 settings \
    title="Set MaxShaderModelVS to 0"
w_metadata vsm=1 settings \
    title="Set MaxShaderModelVS to 1"
w_metadata vsm=2 settings \
    title="Set MaxShaderModelVS to 2"
w_metadata vsm=3 settings \
    title="Set MaxShaderModelVS to 3"

load_vsm()
{
    winetricks_set_wined3d_var MaxShaderModelVS "$1"
}

#----------------------------------------------------------------

w_metadata win2k settings \
    title_uk="Поставити версію Windows 2000" \
    title="Set Windows version to Windows 2000"

load_win2k()
{
    w_set_winver win2k
}

#----------------------------------------------------------------

w_metadata win2k3 settings \
    title_uk="Поставити версію Windows 2003" \
    title="Set Windows version to Windows 2003"

load_win2k3()
{
    w_set_winver win2k3
}


#----------------------------------------------------------------

w_metadata win2k8 settings \
    title_uk="Поставити версію Windows 2008 R2" \
    title="Set Windows version to Windows 2008 R2"

load_win2k8()
{
    w_set_winver win2k8
}

#----------------------------------------------------------------

w_metadata win31 settings \
    title_uk="Поставити версію Windows 3.1" \
    title="Set Windows version to Windows 3.1"

load_win31()
{
    w_set_winver win31
}

#----------------------------------------------------------------

w_metadata win7 settings \
    title_uk="Поставити версію Windows 7" \
    title="Set Windows version to Windows 7"

load_win7()
{
    w_set_winver win7
}

#----------------------------------------------------------------

w_metadata win8 settings \
    title_uk="Поставити версію Windows 8" \
    title="Set Windows version to Windows 8"

load_win8()
{
    w_set_winver win8
}

#----------------------------------------------------------------

w_metadata win81 settings \
    title_uk="Поставити версію Windows 8.1" \
    title="Set Windows version to Windows 8.1"

load_win81()
{
    w_set_winver win81
}

#----------------------------------------------------------------

w_metadata win10 settings \
    title_uk="Поставити версію Windows 10" \
    title="Set Windows version to Windows 10"

load_win10()
{
    w_set_winver win10
}

#----------------------------------------------------------------

w_metadata win95 settings \
    title_uk="Поставити версію Windows 95" \
    title="Set Windows version to Windows 95"

load_win95()
{
    w_set_winver win95
}

#----------------------------------------------------------------

w_metadata win98 settings \
    title_uk="Поставити версію Windows 98" \
    title="Set Windows version to Windows 98"

load_win98()
{
    w_set_winver win98
}

#----------------------------------------------------------------

# Really, we should support other values, since winetricks did
w_metadata winver= settings \
    title_uk="Поставити версію Windows за замовчуванням (win7)" \
    title="Set Windows version to default (win7)"

load_winver()
{
    w_set_winver win7
}

#----------------------------------------------------------------

w_metadata winxp settings \
    title_uk="Поставити версію Windows XP" \
    title="Set Windows version to Windows XP"

load_winxp()
{
    w_set_winver winxp
}

#----------------------------------------------------------------

# Not really a setting, just a fake verb, that shouldn't count as 'installed',
# that always works

w_metadata good settings \
    title="Fake verb that always returns true"

load_good()
{
    w_info "$W_PACKAGE succeeded!"
}

#----------------------------------------------------------------

# Not really a setting, just a fake verb, that shouldn't count as 'installed',
# that always fails

w_metadata bad settings \
    title="Fake verb that always returns false"

load_bad()
{
    w_die "$W_PACKAGE failed!"
}

#---- Derived Metadata ----
# Generated automatically by measuring time and space requirements of all verbs
# size_MB includes size of virgin wineprefix, but not the cached installer
case $WINETRICKS_OPT_VERBOSE in
    2) set -x ;;
    *) set +x ;;
esac

for data in \
    allcodecs:size_MB=48,time_sec=3 \
    allfonts:size_MB=132,time_sec=114 \
    autohotkey:size_MB=53,time_sec=4 \
    baekmuk:size_MB=138,time_sec=3 \
    cjkfonts:size_MB=48,time_sec=4 \
    cmake:size_MB=85,time_sec=8 \
    dirac:size_MB=50,time_sec=4 \
    ogg:size_MB=54,time_sec=1 \
    opensymbol:size_MB=49,time_sec=1 \
    python26:size_MB=160,time_sec=9 \
    takao:size_MB=176,time_sec=3 \
    unifont:size_MB=51,time_sec=0 \
    vlc:size_MB=221,time_sec=7 \
    wenquanyi:size_MB=50,time_sec=0 \
    xvid:size_MB=54,time_sec=2 \

do
    cmd=${data%%:*}
    file="$(echo "$WINETRICKS_METADATA"/*/$cmd.vars)"
    if test -f "$file"
    then
        case $data in
        *size_MB*)
            size_MB=${data##*size_MB=}       # remove anything before value
            size_MB=${size_MB%%,*}           # remove anything after value
            echo size_MB=$size_MB >> "$file"
            ;;
        esac

        case $data in
        *time_sec*)
            time_sec=${data##*time_sec=}
            time_sec=${time_sec%%,*}
            echo time_sec=$time_sec >> "$file"
        esac
    fi
    unset size_MB time_sec
done

# Restore verbosity:
case $WINETRICKS_OPT_VERBOSE in
    1|2) set -x ;;
    *) set +x ;;
esac

#---- Main Program ----

# Launch a new terminal window if in GUI, or
# spawn a shell in the current window if command line.
# New shell contains proper WINEPREFIX and WINE environment variables.
# May be useful when debugging verbs.
winetricks_shell()
{
    (
    w_try_cd "$W_DRIVE_C"
    export WINE

    case $WINETRICKS_GUI in
    none)
        $SHELL
        ;;
    *)
        for term in gnome-terminal konsole Terminal xterm
        do
            if test "$(which $term 2>/dev/null)"
            then
                $term
                break
            fi
        done
        ;;
    esac
    )
}

# Usage: execute_command verb[=argument]
execute_command()
{
    case "$1" in
    *=*) arg=$(echo "$1" | sed 's/.*=//'); cmd=$(echo "$1" | sed 's/=.*//');;
    *) cmd="$1"; arg="" ;;
    esac

    case "$1" in

    # FIXME: avoid duplicated code
    apps|benchmarks|dlls|fonts|games|prefix|settings)
        WINETRICKS_CURMENU="$1"
        ;;

    # Late options
    -*)
        if ! winetricks_handle_option "$1"
        then
            winetricks_usage
            exit 1
        fi
        ;;

    # Hard-coded verbs
    main) WINETRICKS_CURMENU=main ;;
    help) w_open_webpage https://code.google.com/archive/p/winetricks/wikis ;;
    list) winetricks_list_all ;;
    list-cached) winetricks_list_cached ;;
    list-download) winetricks_list_download ;;
    list-manual-download) winetricks_list_manual_download ;;
    list-installed) winetricks_list_installed ;;
    list-all)
        old_menu="$WINETRICKS_CURMENU"
        for WINETRICKS_CURMENU in apps benchmarks dlls fonts games prefix settings
        do
            echo "===== $WINETRICKS_CURMENU ====="
            winetricks_list_all
        done
        WINETRICKS_CURMENU="$old_menu"
        ;;
    unattended) winetricks_set_unattended 1 ;;
    attended) winetricks_set_unattended 0 ;;
    showbroken) W_OPT_SHOWBROKEN=1 ;;
    hidebroken) W_OPT_SHOWBROKEN=0 ;;
    prefix=*) winetricks_set_wineprefix "$arg" ;;
    annihilate) winetricks_annihilate_wineprefix ;;
    folder) w_open_folder "$WINEPREFIX" ;;
    winecfg) "$WINE" winecfg ;;
    regedit) "$WINE" regedit ;;
    taskmgr) "$WINE" taskmgr & ;;
    uninstaller) "$WINE" uninstaller ;;
    shell) winetricks_shell ;;

    # These have to come before *=disabled to avoid looking like DLLs
    fontsmooth=disable*) w_call fontsmooth=disable ;;
    glsl=disable*) w_call glsl=disabled ;;
    multisampling=disable*) w_call multisampling=disabled ;;
    mwo=disable*) w_call mwo=disable ;;   # FIXME: relax matching so we can handle these spelling differences in verb instead of here
    rtlm=disable*) w_call rtlm=disabled ;;
    sound=disable*) w_call sound=disabled ;;
    ao=disable*) w_call ao=disabled ;;
    strictdrawordering=disable*) w_call strictdrawordering=disabled ;;

    # Use winecfg if you want a GUI for plain old DLL overrides
    alldlls=*) w_call "$1" ;;
    *=native) w_do_call native "$cmd";;
    *=builtin) w_do_call builtin "$cmd";;
    *=default) w_do_call default "$cmd";;
    *=disabled) w_do_call disabled "$cmd";;
    vd=*) w_do_call "$cmd";;

    # Hacks for backwards compatibility (Deprecation notices added 2017/03/22)
    cc580) w_warn "Calling cc580 is deprecated, please use comctl32 instead" ; w_call comctl32 ;;
    comdlg32.ocx) w_warn "Calling comdlg32.ocx is deprecated, please use comdlg32ocx instead" ; w_call comdlg32ocx ;;
    dotnet1) w_warn "Calling dotnet1 is deprecated, please use dotnet11 instead" ; w_call dotnet11 ;;
    dotnet2) w_warn "Calling dotnet2 is deprecated, please use dotnet20 instead" ; w_call dotnet20 ;;
    flash11) w_warn "Calling flash11 is deprecated, please use flash instead" ; w_call flash ;;
    # art2kmin also comes with fm20.dll
    fm20) w_warn "Calling fm20 is deprecated, please use controlpad instead" ; w_call controlpad ;;
    fontsmooth-bgr) w_warn "Calling fontsmooth-bgr is deprecated, please use fontsmooth=bgr instead" ; w_call fontsmooth=bgr ;;
    fontsmooth-disable) w_warn "Calling fontsmooth-disable is deprecated, please use fontsmooth=disable instead" ; w_call fontsmooth=disable ;;
    fontsmooth-gray) w_warn "Calling fontsmooth-gray is deprecated, please use fontsmooth=gray instead" ; w_call fontsmooth=gray ;;
    fontsmooth-rgb) w_warn "Calling fontsmooth-rgb is deprecated, please use fontsmooth=rgb instead" ; w_call fontsmooth=rgb ;;
    glsl-disable) w_warn "Calling glsl-disable is deprecated, please use glsl=disabled instead" ; w_call glsl=disabled ;;
    glsl-enable) w_warn "Calling glsl-enable is deprecated, please use glsl=enabled instead" ; w_call glsl=enabled ;;
    ie6_full) w_warn "Calling ie6_full is deprecated, please use ie6 instead" ; w_call ie6 ;;
    # FIXME: use wsh57 instead?
    jscript) w_warn "Calling jscript is deprecated, please use wsh56js instead" ; w_call wsh56js ;;
    npm-repack) w_warn "Calling npm-repack is deprecated, please use npm=repack instead" ; w_call npm=repack ;;
    oss) w_warn "Calling oss is deprecated, please use sound=oss instead" ; w_call sound=oss ;;
    python) w_warn "Calling python is deprecated, please use python26 instead" ; w_call python26 ;;
    vbrun60) w_warn "Calling vbrun60 is deprecated, please use vb6run instead" ; w_call vb6run ;;
    vcrun2005sp1) w_warn "Calling vcrun2005sp1 is deprecated, please use vcrun2005 instead" ; w_call vcrun2005 ;;
    vcrun2008sp1) w_warn "Calling vcrun2008sp1 is deprecated, please use vcrun2008 instead" ; w_call vcrun2008 ;;
    wsh56) w_warn "Calling wsh56 is deprecated, please use wsh57 instead" ; w_call wsh57 ;;
    # See https://github.com/Winetricks/winetricks/issues/747
    xact_jun2010) w_warn "Calling xact_jun2010 is deprecated, please use xact instead" ; w_call xact ;;
    xlive) w_warn "Calling xlive is deprecated, please use gfw instead" ; w_call gfw ;;

    # Normal verbs, with metadata and load_ functions
    *)
        if winetricks_metadata_exists "$1"
        then
            w_call "$1"
        else
            echo "Unknown arg $1"
            winetricks_usage
            exit 1
        fi
        ;;
    esac
}

if ! test "$WINETRICKS_LIB"
then

    # If user specifies menu on command line, execute that command, but don't commit to command-line mode
    # FIXME: this code is duplicated several times; unify it
    if echo "$WINETRICKS_CATEGORIES" | grep -w "$1" > /dev/null
    then
        WINETRICKS_CURMENU=$1
        shift
    fi

    case "$1" in
    die) w_die "we who are about to die salute you." ;;
    volnameof=*)
        # Debug code.  Remove later?
        # Since Linux's volname command can't handle DVDs, winetricks has its own,
        # implemented using dd, old gum, and some string I had laying around.
        # You can try it like this:
        #  winetricks volnameof=/dev/sr0
        # or
        #  winetricks volnameof=foo.iso
        # This will read the volname from the given image and put it to stdout.
        winetricks_volname "${1#volnameof=}"
        ;;
    "")
        if test x"$DISPLAY" = x""
        then
            echo "DISPLAY not set, not defaulting to gui"
            winetricks_usage
            exit 0
        fi
        # GUI case
        # No non-option arguments given, so read them from GUI, and loop until user quits
        winetricks_detect_gui
        winetricks_detect_sudo
        while true
        do
            case $WINETRICKS_CURMENU in
            main) verbs=$(winetricks_mainmenu) ;;
            prefix)
                verbs=$(winetricks_prefixmenu);
                # Cheezy hack: choosing 'attended' or 'unattended' leaves you in same menu
                case "$verbs" in
                attended) winetricks_set_unattended 0 ; continue;;
                unattended) winetricks_set_unattended 1 ; continue;;
                esac
                ;;
            settings) verbs=$(winetricks_settings_menu) ;;
            *) verbs="$(winetricks_showmenu)" ;;
            esac

            if test "$verbs" = ""
            then
                # "user didn't pick anything, back up a level in the menu"
                case "${WINETRICKS_CURMENU}-${WINETRICKS_OPT_SHAREDPREFIX}" in
                apps-0|benchmarks-0|games-0|main-*) WINETRICKS_CURMENU=prefix ;;
                prefix-*) break ;;
                *)    WINETRICKS_CURMENU=main ;;
                esac
            elif echo "$WINETRICKS_CATEGORIES" | grep -w "$verbs" > /dev/null
            then
                WINETRICKS_CURMENU=$verbs
            else

                # Otherwise user picked one or more real verbs.
                case "$verbs" in
                prefix=*)
                    # prefix menu is special, it only returns one verb, and the
                    # verb can contain spaces
                    execute_command "$verbs"
                    # after picking a prefix, want to land in main.
                    WINETRICKS_CURMENU=main ;;
                *)
                    for verb in $verbs
                    do
                        execute_command "$verb"
                    done
                    case "${WINETRICKS_CURMENU}-${WINETRICKS_OPT_SHAREDPREFIX}" in
                    prefix-*|apps-0|benchmarks-0|games-0)
                        # After installing isolated app, return to prefix picker
                        WINETRICKS_CURMENU=prefix
                        ;;
                    *)
                        # Otherwise go to main menu.
                        WINETRICKS_CURMENU=main
                        ;;
                    esac
                    ;;
                esac
            fi
        done
        ;;
    *)
        # Command-line case
        winetricks_detect_sudo
        # User gave command-line arguments, so just run those verbs and exit
        for verb
        do
            case $verb in
            *.verb)
                # Load the verb file
                # shellcheck disable=SC1090
                case $verb in
                    */*) . "$verb" ;;
                    *) . ./"$verb" ;;
                esac
                # And forget that the verb comes from a file
                verb="$(echo "$verb" | sed 's,.*/,,;s,.verb,,')"
                ;;
            esac
            execute_command "$verb"
        done
        ;;

    esac
fi

