1383 lines
		
	
	
		
			52 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1383 lines
		
	
	
		
			52 KiB
		
	
	
	
		
			Bash
		
	
	
		
			Executable File
		
	
	
	
	
| #!/usr/bin/env bash
 | ||
| 
 | ||
| ##### CHECK ROOT #####
 | ||
| if [[ $(id -u) -eq 0 ]] ; then
 | ||
|     echo "Перезапустите скрипт $0 от обычного пользователя!"
 | ||
|     exit 1
 | ||
| fi
 | ||
| 
 | ||
| ##### MESSAGES FUNCTIONS #####
 | ||
| print_error () { printf "\E[31m%s Ошибка: $@ %s\e[0m\n" ;}
 | ||
| print_warning () { printf "\E[33m%s Предупреждение: $@ %s\e[0m\n" ;}
 | ||
| print_info () { printf "\E[36m%s Информация: \"$@\" %s\e[0m\n" ;}
 | ||
| print_ok () { printf "\E[35m%s Успех: $@ %s\e[0m\n" ;}
 | ||
| print_var () { for vp in $@ ; do echo "${vp}=${!vp}" ; done ;}
 | ||
| fatal () {
 | ||
|     print_error "$@"
 | ||
|     [[ -n "$WINESERVER" ]] && "$WINESERVER" -w
 | ||
|     exit 1
 | ||
| }
 | ||
| 
 | ||
| ##### CHECK VARIABLES #####
 | ||
| check_variables () { [[ -z ${!1} ]] && export $1="$2" ;}
 | ||
| 
 | ||
| ##### CHECK DEBUG #####
 | ||
| if [[ "$1" == "--debug" ]] ; then
 | ||
|     export DEBUG="full"
 | ||
|     export LOG_FILE="$HOME/winehelper.log"
 | ||
|     shift
 | ||
|     print_warning "Включен режим подробного логирования работы WINE."
 | ||
|     print_warning "Лог будет сохранен по пути: $LOG_FILE"
 | ||
|     sleep 3
 | ||
| else
 | ||
|     check_variables DEBUG "0"
 | ||
| fi
 | ||
| 
 | ||
| ##### WINETRICKS VERSION #####
 | ||
| WINETRICKS_VERSION="20250102"
 | ||
| 
 | ||
| ##### DEFAULT VARIABLES #####
 | ||
| SCRIPT_NAME="$(basename "$0")"
 | ||
| if [[ "$(realpath "$0")" == "/usr/bin/$SCRIPT_NAME" ]] ; then
 | ||
|     USER_WORK_PATH="$HOME/.local/share/$SCRIPT_NAME"
 | ||
|     RUN_SCRIPT="/usr/bin/$SCRIPT_NAME"
 | ||
|     DATA_PATH="/usr/share/$SCRIPT_NAME"
 | ||
| else
 | ||
|     USER_WORK_PATH="$HOME/test-$SCRIPT_NAME"
 | ||
|     RUN_SCRIPT="$(realpath "$0")"
 | ||
|     DATA_PATH="$(dirname "$RUN_SCRIPT")"
 | ||
| fi
 | ||
| 
 | ||
| WH_VULKAN_LIBDIR="$USER_WORK_PATH/vulkan"
 | ||
| WH_PREFIXES_DIR="$USER_WORK_PATH/prefixes"
 | ||
| WH_DIST_DIR="$USER_WORK_PATH/dist"
 | ||
| WH_TMP_DIR="$USER_WORK_PATH/tmp"
 | ||
| 
 | ||
| WH_IMAGE_PATH="$DATA_PATH/image"
 | ||
| WH_DB_DIR="$DATA_PATH/database"
 | ||
| WH_AUTOINSTALL_DIR="$DATA_PATH/autoinstall"
 | ||
| WH_MANUALINSTALL_DIR="$DATA_PATH/manualinstall"
 | ||
| WH_WINETRICKS="$DATA_PATH/winetricks_$WINETRICKS_VERSION"
 | ||
| 
 | ||
| WH_MENU_DIR="$HOME/.local/share/applications/WineHelper"
 | ||
| WH_MENU_CATEGORY="$HOME/.local/share/desktop-directories/WineHelper.directory"
 | ||
| WH_MENU_CONFIG="$HOME/.config/menus/applications-merged/WineHelper.menu"
 | ||
| 
 | ||
| # export WINEDLLOVERRIDES=mshtml,mscoree="
 | ||
| 
 | ||
| check_variables WINEESYNC "0"
 | ||
| check_variables WINEFSYNC "0"
 | ||
| 
 | ||
| check_variables WINEARCH "win64" # or "win32"
 | ||
| check_variables WH_WINE_USE "wine_x_tkg_10-0_amd64" # or system
 | ||
| 
 | ||
| check_variables WH_USE_CPCSP_PROXY "0"
 | ||
| check_variables CPCSP_PROXY_VER "0.6.1-alt1"
 | ||
| 
 | ||
| check_variables STAGING_SHARED_MEMORY "1"
 | ||
| check_variables WINE_LARGE_ADDRESS_AWARE "1"
 | ||
| check_variables WINE_FULLSCREEN_FSR "1"
 | ||
| check_variables WINE_DO_NOT_CREATE_DXGI_DEVICE_MANAGER "0"
 | ||
| check_variables WINE_HEAP_DELAY_FREE "0"
 | ||
| check_variables WINE_ALLOW_XIM "0"
 | ||
| 
 | ||
| check_variables WH_WINDOWS_VER "10"
 | ||
| # check_variables WH_USE_GSTREAMER "1"
 | ||
| # check_variables WH_USE_D3D_EXTRAS "1"
 | ||
| check_variables WH_USE_SHADER_CACHE "1"
 | ||
| check_variables WH_USE_WINE_DXGI "0"
 | ||
| check_variables WH_DLL_INSTALL ""
 | ||
| 
 | ||
| check_variables WINE_WIN_START "start /wait /high /unix"
 | ||
| 
 | ||
| check_variables WINE_CPU_TOPOLOGY "8"
 | ||
| 
 | ||
| check_variables USE_RENDERER "opengl" # opengl, damavand, proton
 | ||
| 
 | ||
| check_variables DXVK_VER "1.10.3-28"
 | ||
| # check_variables DXVK_CONFIG_FILE "path/to/dxvk.conf"
 | ||
| 
 | ||
| check_variables VKD3D_VER "1.1-2602"
 | ||
| # check_variables VKD3D_LIMIT_TESS_FACTORS 64
 | ||
| # check_variables VKD3D_FEATURE_LEVEL "12_0"
 | ||
| 
 | ||
| export CLOUD_URL="https://cloud.linux-gaming.ru/portproton"
 | ||
| 
 | ||
| ##### CHECK NOEXEC FOR /HOME #####
 | ||
| if mount -l | grep -E "[[:space:]]/home[[:space:]]" | grep -q "noexec" ; then
 | ||
|     fatal "/home примонтирован в /etc/fstab с аргументом noexec.\nЗапуск портативной версии wine не возможен из домашнего каталога."
 | ||
| fi
 | ||
| 
 | ||
| ##### ROOT #####
 | ||
| su_run () {
 | ||
|     print_info "Для продолжения установки введите root пароль..."
 | ||
|     su - -c "$@"
 | ||
| }
 | ||
| 
 | ||
| ##### CHECK DEPENDENCIES #####
 | ||
| if ! rpm -q {i586-,}{wine,glibc-core,libstdc++6,glibc-pthread,glibc-nss,libOSMesa,\
 | ||
| libnss-mdns,libunixODBC2,ocl-icd,libfreetype,libfontconfig1,libgnutls30,libGL,\
 | ||
| libEGL,xorg-dri-swrast,xorg-dri-intel,xorg-dri-radeon,libvulkan1,libcups} 1>/dev/null
 | ||
| then
 | ||
|     if su_run "$DATA_PATH/dependencies.sh"
 | ||
|     then print_info "Зависимости успешно установлены. Продолжаем работу $SCRIPT_NAME"
 | ||
|     else fatal "Не удалось установить зависимости. Работа $SCRIPT_NAME прервана."
 | ||
|     fi
 | ||
| fi
 | ||
| 
 | ||
| ##### HELPER FUNCTIONS #####
 | ||
| add_to_var () {
 | ||
|     if ! echo ${!1} | grep "$2" &>/dev/null
 | ||
|     then export $1="${!1} $2"
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| rm_from_var () {
 | ||
|     if echo ${!1} | grep "$2" &>/dev/null
 | ||
|     then export $1="$(echo "${!1//$2/}" | tr -s " ")"
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| try_remove_file () {
 | ||
|     if [[ -f "$1" ]] || [[ ! -e "$1" ]] ; then
 | ||
|         rm -f "$1"
 | ||
|         [[ "$?" == 0 ]] && return 0 || return 1
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| try_remove_dir () {
 | ||
|     if [[ -d "$1" ]] ; then
 | ||
|         rm -fr "$1"
 | ||
|         [[ "$?" == 0 ]] && return 0 || return 1
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| try_copy_file () {
 | ||
|     if [[ ! -f "$1" ]] ; then print_info "файла $1 не существует для копирования" && return 1
 | ||
|     elif [[ -z "$2" ]] ; then fatal "нет пути для копирования файла $1"
 | ||
|     elif [[ -L "$2" ]] ; then
 | ||
|         try_remove_file "$2"
 | ||
|         cp -f "$1" "$2" && return 0 || return 1
 | ||
|     else
 | ||
|         [[ -e "$2/$(basename "$1")" ]] && rm -f "$2/$(basename "$1")"
 | ||
|         cp -f "$1" "$2" && return 0 || return 1
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| try_copy_dir () {
 | ||
|     if [[ ! -d "$1" ]] ; then print_info "каталога $1 не существует для копирования"
 | ||
|     elif [[ -z "$2" ]] ; then fatal "нет пути для копирования каталога $1"
 | ||
|     else
 | ||
|         cp -fr "$1" "$2"
 | ||
|         [[ "$?" != 0 ]] && print_error "не удалось скопировать каталог $1 в $2" || return 0
 | ||
|     fi
 | ||
|     return 1
 | ||
| }
 | ||
| 
 | ||
| try_force_link_file () {
 | ||
|     if [[ ! -f "$1" ]] ; then
 | ||
|         print_warning "нет файла для создания символьной ссылки: $1"
 | ||
|         if [[ -f "$2" ]] ; then
 | ||
|             try_remove_file "$2"
 | ||
|             print_warning "удаляем символьную ссылку: $2"
 | ||
|         fi
 | ||
|         return 1
 | ||
|     elif [[ -z "$2" ]] ; then fatal "нет пути для создания символьной ссылки на файл $1"
 | ||
|     else
 | ||
|         try_remove_file "$2"
 | ||
|         ln -s -f -r "$1" "$2"
 | ||
|         return 0
 | ||
|     fi
 | ||
|     return 1
 | ||
| }
 | ||
| 
 | ||
| try_force_link_dir () {
 | ||
|     if [[ ! -d "$1" ]] ; then print_info "каталога $1 не существует для создания символьной сссылки"
 | ||
|     elif [[ -z "$2" ]] ; then fatal "не указан путь для создания символьной ссылки на каталог $1"
 | ||
|     else
 | ||
|         ln -s -f -r "$1" "$2"
 | ||
|         [[ "$?" != 0 ]] && print_error "не удалось сделать символьную ссылку на каталог $1 по пути $2" || return 0
 | ||
|     fi
 | ||
|     return 1
 | ||
| }
 | ||
| 
 | ||
| create_new_dir () {
 | ||
|     if [[ ! -d "$1" ]] ; then
 | ||
|         mkdir -p "$1"
 | ||
|     fi
 | ||
|     return 0
 | ||
| }
 | ||
| 
 | ||
| unpack () {
 | ||
|     print_info "Запуск распаковки архива $1"
 | ||
|     case $1 in
 | ||
|          *.tar.xz) local command="tar -Jxhf";;
 | ||
|          *.tar.gz) local command="tar -xhzf" ;;
 | ||
|         *.tar.zst) local command="tar -I zstd -xhf" ;;
 | ||
|             *.tar) local command="tar -xhf" ;;
 | ||
|     esac
 | ||
|     create_new_dir "$2"
 | ||
|     if $command "$1" -C "$2" ; then
 | ||
|         print_ok "Архив $1 распакован."
 | ||
|         return 0
 | ||
|     else
 | ||
|         print_error "Распаковать архив $1 не удалось!"
 | ||
|         return 1
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| try_download () {
 | ||
|     local DOWNLOAD_FILE_URL="$1"
 | ||
|     local OUTPUT_FILE="$2"
 | ||
|     local OUTPUT_FILE_NAME="$(basename "$OUTPUT_FILE")"
 | ||
| 
 | ||
|     print_info "Скачивание файла $OUTPUT_FILE_NAME..."
 | ||
|     if curl -f --progress-bar -A "Mozilla/5.0 (compatible; Konqueror/2.1.1; X11)" \
 | ||
|        -L "$DOWNLOAD_FILE_URL" -o "$OUTPUT_FILE"
 | ||
|     then
 | ||
|         print_ok "Скачивание файла $OUTPUT_FILE_NAME прошло успешно."
 | ||
|         if [[ "$3" == check256sum ]] ; then
 | ||
|             SHA256SUM_EXT=$(sha256sum "$OUTPUT_FILE" | awk '{print $1}')
 | ||
|             SHA256SUM_INT="$(grep "$OUTPUT_FILE_NAME" "$DATA_PATH/sha256sum.list" | awk '{print $1}')"
 | ||
|             if [[ "$SHA256SUM_EXT" == "$SHA256SUM_INT" ]] ; then
 | ||
|                 print_ok "Хэш-сумма файла $OUTPUT_FILE_NAME успешно проверена."
 | ||
|                 return 0
 | ||
|             else
 | ||
|                 fatal "Хэш-сумма файла $OUTPUT_FILE_NAME не совподает!"
 | ||
|                 return 1
 | ||
|             fi
 | ||
|         fi
 | ||
|         return 0
 | ||
|     else
 | ||
|         fatal "Скачивание файла: $OUTPUT_FILE_NAME завершилось с ошибкой!"
 | ||
|         return 1
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| try_copy_other_dll_to_pfx_64 () {
 | ||
|     if [[ "$WINEARCH" == "win64" ]] ; then
 | ||
|         cmp -s "$1" "${WINEPREFIX}/drive_c/windows/system32/$(basename $1)" && return 0
 | ||
|         try_copy_file "$1" "${WINEPREFIX}/drive_c/windows/system32/" && return 0 || return 1
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| try_copy_other_dll_to_pfx_32() {
 | ||
|     if [[ "$WINEARCH" == "win64" ]] ; then
 | ||
|         cmp -s "$1" "${WINEPREFIX}/drive_c/windows/syswow64/$(basename $1)" && return 0
 | ||
|         try_copy_file "$1" "${WINEPREFIX}/drive_c/windows/syswow64/" && return 0 || return 1
 | ||
|     else
 | ||
|         cmp -s "$1" "${WINEPREFIX}/drive_c/windows/system32/$(basename $1)" && return 0
 | ||
|         try_copy_file "$1" "${WINEPREFIX}/drive_c/windows/system32/" && return 0 || return 1
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| try_copy_wine_dll_to_pfx_64 () {
 | ||
|     if [[ "$WINEARCH" == "win64" ]] ; then
 | ||
|         if [[ -d "${WINEDIR}/lib64/wine/x86_64-windows" ]]
 | ||
|         then WINE_BUILD_DLL_64="${WINEDIR}/lib64/wine/x86_64-windows"
 | ||
|         else WINE_BUILD_DLL_64="${WINEDIR}/lib64/wine"
 | ||
|         fi
 | ||
|         cmp -s "$WINE_BUILD_DLL_64/$1" "${WINEPREFIX}/drive_c/windows/system32/$(basename $1)" && return 0
 | ||
|         try_copy_file "$WINE_BUILD_DLL_64/$1" "${WINEPREFIX}/drive_c/windows/system32/" && return 0 || return 1
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| try_copy_wine_dll_to_pfx_32() {
 | ||
|     if [[ -d "${WINEDIR}/lib/wine/i386-windows" ]]
 | ||
|     then WINE_BUILD_DLL_32="${WINEDIR}/lib/wine/i386-windows"
 | ||
|     else WINE_BUILD_DLL_32="${WINEDIR}/lib/wine"
 | ||
|     fi
 | ||
|     if [[ "$WINEARCH" == "win64" ]] ; then
 | ||
|         cmp -s "$WINE_BUILD_DLL_32/$1" "${WINEPREFIX}/drive_c/windows/syswow64/$1" && return 0
 | ||
|         try_copy_file "$WINE_BUILD_DLL_32/$1" "${WINEPREFIX}/drive_c/windows/syswow64/" && return 0 || return 1
 | ||
|     else
 | ||
|         cmp -s "$WINE_BUILD_DLL_32/$1" "${WINEPREFIX}/drive_c/windows/system32/$1" && return 0
 | ||
|         try_copy_file "$WINE_BUILD_DLL_32/$1" "${WINEPREFIX}/drive_c/windows/system32/" && return 0 || return 1
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| var_winedlloverride_update () {
 | ||
|     if [[ -n "${WINEDLLOVERRIDES}" ]]
 | ||
|     then export WINEDLLOVERRIDES="${1};${WINEDLLOVERRIDES}"
 | ||
|     else export WINEDLLOVERRIDES="${1}"
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| var_dxvk_config_update () {
 | ||
|     if [[ -n "${DXVK_CONFIG}" ]]
 | ||
|     then export DXVK_CONFIG="${1};${DXVK_CONFIG}"
 | ||
|     else export DXVK_CONFIG="${1}"
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| var_vkd3d_config_update () {
 | ||
|     if [[ -n "${VKD3D_CONFIG}" ]]
 | ||
|     then export VKD3D_CONFIG="${1};${VKD3D_CONFIG}"
 | ||
|     else export VKD3D_CONFIG="${1}"
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| var_radv_perftest_config_update () {
 | ||
|     if [[ -n "${RADV_PERFTEST}" ]]
 | ||
|     then export RADV_PERFTEST="${1};${RADV_PERFTEST}"
 | ||
|     else export RADV_PERFTEST="${1}"
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| var_vk_istance_layers_config_update () {
 | ||
|     if [[ -n "${VK_INSTANCE_LAYERS}" ]]
 | ||
|     then export VK_INSTANCE_LAYERS="${1}:${VK_INSTANCE_LAYERS}"
 | ||
|     else export VK_INSTANCE_LAYERS="${1}"
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| var_ld_library_path_update () {
 | ||
|     if echo "$LD_LIBRARY_PATH" | grep "$1"
 | ||
|     then return 0
 | ||
|     elif [[ -n "$LD_LIBRARY_PATH" ]]
 | ||
|     then export LD_LIBRARY_PATH="$1:$LD_LIBRARY_PATH"
 | ||
|     else export LD_LIBRARY_PATH="$1"
 | ||
|     fi
 | ||
|     return 0
 | ||
| }
 | ||
| 
 | ||
| create_desktop () {
 | ||
|     local name_desktop="$1"
 | ||
|     local exe_file="$2"
 | ||
|     local desktop_filename="$(basename "$exe_file" .exe | sed "s| |_|")"
 | ||
|     local icon_file="$WH_IMAGE_PATH/$3.png"
 | ||
| 
 | ||
|     if [[ -z "$name_desktop" ]] || [[ -z "$exe_file" ]] ; then
 | ||
|         fatal "Used: $SCRIPT_NAME --desktop \"desktop_name\" \"path_to_exe\" \"name_png_from_image\""
 | ||
|     elif [[ ! -f "$exe_file" ]] ; then
 | ||
|         print_warning "Для создания ярлыка не найден исполняемый файл: $exe_file"
 | ||
| 
 | ||
|         BASENAME_EXE="$(basename "$exe_file")"
 | ||
|         print_info "Запускаем поиск $BASENAME_EXE"
 | ||
|         if [[ -z "$DRIVE_C" ]] || [[ ! -d "$DRIVE_C" ]]
 | ||
|         then FIND_PATH="$WH_PREFIXES_DIR"
 | ||
|         else FIND_PATH="$DRIVE_C"
 | ||
|         fi
 | ||
|         exe_file="$(find "$FIND_PATH" -type f -not -type l \
 | ||
|                     -not -path "*/windows/*" -not -path "*/dosdevices/*" \
 | ||
|                     -iname "$BASENAME_EXE")"
 | ||
|         if [[ -z "$exe_file" ]] || [[ ! -f "$exe_file" ]]
 | ||
|         then fatal "Для создания ярлыка не найден исполняемый файл: $BASENAME_EXE"
 | ||
|         else print_ok "Исполняемый файл $BASENAME_EXE найден по пути $(dirname "$exe_file")/"
 | ||
|         fi
 | ||
|     fi
 | ||
| 
 | ||
|     # создаем .desktop файл
 | ||
|     create_new_dir "$WH_MENU_DIR"
 | ||
|     [[ ! -f "$icon_file" ]] && icon_file=wine
 | ||
|     {
 | ||
|         echo "[Desktop Entry]"
 | ||
|         echo "Name=$name_desktop"
 | ||
|         echo "Exec=env \"$RUN_SCRIPT\" \"$exe_file\" %F"
 | ||
|         echo "Type=Application"
 | ||
|         echo "Categories=WineHelper;"
 | ||
|         echo "StartupNotify=true"
 | ||
|         echo "Path=$DATA_PATH"
 | ||
|         echo "Icon=$icon_file"
 | ||
|     } > "$USER_WORK_PATH/$desktop_filename.desktop"
 | ||
|     chmod +x "$USER_WORK_PATH/$desktop_filename.desktop"
 | ||
| 
 | ||
|     cp -f "$USER_WORK_PATH/$desktop_filename.desktop" "$WH_MENU_DIR/"
 | ||
| 
 | ||
|     # добавляем информацию о приложении в "$WINEPREFIX/desktop.list"
 | ||
|     if [[ -f "$WINEPREFIX/desktop.list" ]] \
 | ||
|     && grep -qe "^${name_desktop}=" "$WINEPREFIX/desktop.list"
 | ||
|     then sed -i "/^$name_desktop=/d" "$WINEPREFIX/desktop.list"
 | ||
|     fi
 | ||
|     create_new_dir "$WINEPREFIX/icons"
 | ||
|     try_copy_file "$icon_file" "$WINEPREFIX/icons/"
 | ||
|     echo "$name_desktop=${exe_file//$WINEPREFIX/}=$(basename "$icon_file")" >> "$WINEPREFIX/desktop.list"
 | ||
| 
 | ||
|     # создаем файл категории для меню
 | ||
|     create_new_dir "$HOME/.local/share/desktop-directories"
 | ||
|     if [[ ! -f "$WH_MENU_CATEGORY" ]] ; then
 | ||
|     cat > "$WH_MENU_CATEGORY" <<EOF
 | ||
| [Desktop Entry]
 | ||
| Type=Directory
 | ||
| Name=WineHelper
 | ||
| Icon=wine
 | ||
| EOF
 | ||
|     fi
 | ||
| 
 | ||
|     # Создаем файл меню для всех приложений
 | ||
|     create_new_dir "$HOME/.config/menus/applications-merged"
 | ||
|     if [[ ! -f "$WH_MENU_CONFIG" ]] ; then
 | ||
|     cat > "$WH_MENU_CONFIG" <<EOF
 | ||
| <!DOCTYPE Menu PUBLIC "-//freedesktop//DTD Menu 1.0//EN"
 | ||
|   "http://www.freedesktop.org/standards/menu-spec/1.0/menu.dtd">
 | ||
| <Menu>
 | ||
|   <Name>Applications</Name>
 | ||
|   <Menu>
 | ||
|     <Name>WineHelper</Name>
 | ||
|     <Directory>WineHelper.directory</Directory>
 | ||
|     <Include>
 | ||
|       <Category>WineHelper</Category>
 | ||
|     </Include>
 | ||
|   </Menu>
 | ||
| </Menu>
 | ||
| EOF
 | ||
|     fi
 | ||
| 
 | ||
|     # Обновляем кэш desktop файлов
 | ||
|     update-desktop-database "$HOME/.local/share/applications"
 | ||
| 
 | ||
|     if [[ $4 != "nocopy" ]] ; then
 | ||
|         if [[ -n $4 ]] ; then
 | ||
|             local desktop_path="$(xdg-user-dir DESKTOP)/$4"
 | ||
|             create_new_dir "$desktop_path"
 | ||
|             print_info "В меню создан $desktop_filename.desktop и скопирован на рабочий стол в каталог $4"
 | ||
|         else
 | ||
|             local desktop_path="$(xdg-user-dir DESKTOP)"
 | ||
|             print_info "В меню и на рабочем столе создан $desktop_filename.desktop"
 | ||
|         fi
 | ||
|         cp -f "$USER_WORK_PATH/$desktop_filename.desktop" "$desktop_path"
 | ||
|     else
 | ||
|         print_info "В меню создан $desktop_filename.desktop"
 | ||
|     fi
 | ||
| 
 | ||
|     if [[ -n "$INSTALL_SCRIPT_NAME" ]] \
 | ||
|     && [[ -f "$exe_file" ]]
 | ||
|     then
 | ||
|         {
 | ||
|             echo '#!/usr/bin/env bash'
 | ||
|             echo "# cmd_name: $INSTALL_SCRIPT_NAME"
 | ||
|         } > "$exe_file".whdb
 | ||
|         grep -e "info_" -e "#####" -e "export" -e "var_" "$INSTALL_SCRIPT" \
 | ||
|         | grep -vE "LAUNCH_PARAMETERS|AUTOINSTALL|WIN_FILE_EXEC|echo" \
 | ||
|         | awk '{$1=$1;print}' >> "$exe_file".whdb
 | ||
|         print_info "Создан файл настроек для $exe_file"
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| remove_desktop () {
 | ||
|     if [[ -n "$1" ]] ; then
 | ||
|         try_remove_file "$USER_WORK_PATH/$1.desktop"
 | ||
|         try_remove_file "$WH_MENU_DIR/$1.desktop"
 | ||
|         try_remove_file "$HOME/.local/share/applications/$1.desktop"
 | ||
|         try_remove_file "$(xdg-user-dir DESKTOP)/$1.desktop"
 | ||
|     fi
 | ||
| 
 | ||
|     # Удаляем категорию если она пуста
 | ||
|     if [[ -d "$WH_MENU_DIR" ]] && [[ -z "$(ls -A "$WH_MENU_DIR")" ]]; then
 | ||
|         try_remove_dir "$WH_MENU_DIR"
 | ||
|         try_remove_file "$WH_MENU_CATEGORY"
 | ||
|         try_remove_file "$WH_MENU_CONFIG"
 | ||
|     fi
 | ||
| 
 | ||
|     # Обновляем кэш desktop файлов
 | ||
|     update-desktop-database "$HOME/.local/share/applications"
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| check_installed_programs () {
 | ||
|     for desktop_file in "$USER_WORK_PATH"/*.desktop ; do
 | ||
|         if [[ ! -f "$desktop_file" ]] ; then
 | ||
|             print_info "Установленные программы не найдены."
 | ||
|             return 1
 | ||
|         fi
 | ||
|         EXE_PATH="$(grep "Exec" "$desktop_file" | awk -F'"' '{print $4}')"
 | ||
|         case "$1" in
 | ||
|             check_only)
 | ||
|                 if [[ -z $2 ]] ; then
 | ||
|                     print_error "Нет аргумента для проверки файла запуска!"
 | ||
|                     print_info "Список установленных программ:"
 | ||
|                     check_installed_programs
 | ||
|                     exit 1
 | ||
|                 elif [[ "$EXE_PATH" =~ ${2}$ ]] ; then
 | ||
|                     export EXE_PATH
 | ||
|                     return 0
 | ||
|                 fi
 | ||
|             ;;
 | ||
|             *)
 | ||
|                 if [[ -f "$EXE_PATH.whdb" ]] ; then
 | ||
|                     WH_INFO_RU="$(grep "info_ru:" "$EXE_PATH.whdb" | awk -F"info_ru: " '{print $2}')"
 | ||
|                     printf "\E[36m%s $SCRIPT_NAME run $(basename "$EXE_PATH") - $(basename "$desktop_file") %s\e[0m\n"
 | ||
|                     echo -e "$WH_INFO_RU\n"
 | ||
|                 fi
 | ||
|             ;;
 | ||
|         esac
 | ||
|     done
 | ||
|     [[ -n $2 ]] && fatal "Не найден файл запуска для $2"
 | ||
| }
 | ||
| 
 | ||
| run_installed_programs () {
 | ||
|     if check_installed_programs check_only "$1" ; then
 | ||
|         /usr/bin/env bash -c "\"$RUN_SCRIPT\" \"$EXE_PATH\"" &
 | ||
|         exit 0
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| init_wined3d () {
 | ||
|     if [[ "$USE_RENDERER" != "proton" ]] ; then
 | ||
|         WINED3D_FILES="d3d8 d3d9 d3d10_1 d3d10 d3d10core d3d11 dxgi d3d12 d3d12core"
 | ||
|         for wined3dfiles in $WINED3D_FILES ; do
 | ||
|             try_copy_wine_dll_to_pfx_64 "$wined3dfiles.dll"
 | ||
|             try_copy_wine_dll_to_pfx_32 "$wined3dfiles.dll"
 | ||
|         done
 | ||
| #         if [[ "$USE_RENDERER" == "damavand" ]]
 | ||
| #         then export WINE_D3D_CONFIG="renderer=vulkan"
 | ||
| #         else export WINE_D3D_CONFIG="renderer=gl"
 | ||
| #         fi
 | ||
|         return 0
 | ||
|     else
 | ||
|         return 1
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| init_dxvk () {
 | ||
|     check_variables USE_DXVK_VER "$1"
 | ||
| 
 | ||
|     get_dxvk () {
 | ||
|         DXVK_URL="$1"
 | ||
|         DXVK_PACKAGE="${WH_VULKAN_LIBDIR}/dxvk-${DXVK_VAR_VER}.tar.$(echo ${DXVK_URL#*.tar.})"
 | ||
|         if try_download "$DXVK_URL" "$DXVK_PACKAGE" check256sum \
 | ||
|         && unpack "$DXVK_PACKAGE" "$WH_VULKAN_LIBDIR"
 | ||
|         then
 | ||
|             try_remove_file "$DXVK_PACKAGE"
 | ||
|             return 0
 | ||
|         fi
 | ||
|         return 1
 | ||
|     }
 | ||
| 
 | ||
|     for DXVK_VAR_VER in "$USE_DXVK_VER" $@ ; do
 | ||
|         if [[ ! -d "${WH_VULKAN_LIBDIR}/dxvk-$DXVK_VAR_VER" ]] ; then
 | ||
|             get_dxvk "$CLOUD_URL/dxvk-${DXVK_VAR_VER}.tar.xz"
 | ||
|         fi
 | ||
|     done
 | ||
| 
 | ||
|     if [[ "${WH_USE_WINE_DXGI}" == 1 ]] ; then
 | ||
|         DXVK_FILES="d3d9 d3d10_1 d3d10 d3d11" # dxvk_config openvr_api_dxvk"
 | ||
|         try_copy_wine_dll_to_pfx_64 "dxgi.dll"
 | ||
|         try_copy_wine_dll_to_pfx_32 "dxgi.dll"
 | ||
|     else
 | ||
|         DXVK_FILES="d3d9 d3d10_1 d3d10 d3d11 dxgi" # dxvk_config openvr_api_dxvk"
 | ||
|     fi
 | ||
| 
 | ||
|     for dxvkfiles in $DXVK_FILES ; do
 | ||
|         try_copy_other_dll_to_pfx_64 "${WH_VULKAN_LIBDIR}/dxvk-$USE_DXVK_VER/x64/$dxvkfiles.dll"
 | ||
|         if try_copy_other_dll_to_pfx_32 "${WH_VULKAN_LIBDIR}/dxvk-$USE_DXVK_VER/x32/$dxvkfiles.dll"
 | ||
|         then var_winedlloverride_update "$dxvkfiles=n"
 | ||
|         fi
 | ||
|     done
 | ||
| }
 | ||
| 
 | ||
| init_vkd3d () {
 | ||
|     check_variables USE_VKD3D_VER "$1"
 | ||
| 
 | ||
|     get_vkd3d () {
 | ||
|         VKD3D_URL="$1"
 | ||
|         VKD3D_PACKAGE="${WH_VULKAN_LIBDIR}/vkd3d-proton-${VKD3D_VAR_VER}.tar.$(echo ${VKD3D_URL#*.tar.})"
 | ||
|         if try_download "$VKD3D_URL" "$VKD3D_PACKAGE" check256sum \
 | ||
|         && unpack "$VKD3D_PACKAGE" "$WH_VULKAN_LIBDIR"
 | ||
|         then
 | ||
|             try_remove_file "$VKD3D_PACKAGE"
 | ||
|             return 0
 | ||
|         fi
 | ||
|         return 1
 | ||
|     }
 | ||
| 
 | ||
|     for VKD3D_VAR_VER in "$USE_VKD3D_VER" $@ ; do
 | ||
|         if [[ ! -d "${WH_VULKAN_LIBDIR}/vkd3d-proton-$VKD3D_VAR_VER" ]] ; then
 | ||
|             get_vkd3d "$CLOUD_URL/vkd3d-proton-${VKD3D_VAR_VER}.tar.xz"
 | ||
|         fi
 | ||
|     done
 | ||
| 
 | ||
|     VKD3D_FILES="d3d12 d3d12core libvkd3d-shader-1 libvkd3d-1" # libvkd3d-proton-utils-3
 | ||
|     for vkd3dfiles in $VKD3D_FILES ; do
 | ||
|         try_copy_other_dll_to_pfx_64 "${WH_VULKAN_LIBDIR}/vkd3d-proton-$USE_VKD3D_VER/x64/$vkd3dfiles.dll"
 | ||
|         if try_copy_other_dll_to_pfx_32 "${WH_VULKAN_LIBDIR}/vkd3d-proton-$USE_VKD3D_VER/x86/$vkd3dfiles.dll"
 | ||
|         then var_winedlloverride_update "$vkd3dfiles=n"
 | ||
|         fi
 | ||
|     done
 | ||
| }
 | ||
| 
 | ||
| init_wine_ver () {
 | ||
|     if [[ "$WH_WINE_USE" != system* ]] ; then
 | ||
|         export WINEDIR="$WH_DIST_DIR/$WH_WINE_USE"
 | ||
| 
 | ||
|         if [[ ! -d "$WINEDIR" ]] ; then
 | ||
|             WINE_URL="$CLOUD_URL/$WH_WINE_USE.tar.xz"
 | ||
|             local WINE_PACKAGE="$WH_TMP_DIR/${WH_WINE_USE}.tar.xz"
 | ||
|             if try_download "$WINE_URL" "$WINE_PACKAGE" check256sum ; then
 | ||
|                 if unpack "$WINE_PACKAGE" "$WH_DIST_DIR/" ; then
 | ||
|                     echo "$WH_WINE_USE" > "$WH_DIST_DIR/$WH_WINE_USE/version"
 | ||
|                     try_remove_file "$WINE_PACKAGE"
 | ||
|                 fi
 | ||
|             fi
 | ||
|         fi
 | ||
| 
 | ||
|         export WINE="${WINEDIR}/bin/wine"
 | ||
|         export WINELOADER="${WINEDIR}/bin/wine"
 | ||
|         export WINESERVER="${WINEDIR}/bin/wineserver"
 | ||
| 
 | ||
|         if [[ -n "${PATH}" ]]
 | ||
|         then export PATH="${WINEDIR}/bin:${PATH}"
 | ||
|         else export PATH="${WINEDIR}/bin"
 | ||
|         fi
 | ||
| 
 | ||
|         if [[ -n "${LD_LIBRARY_PATH}" ]]
 | ||
|         then export LD_LIBRARY_PATH="${WINEDIR}/lib:${LD_LIBRARY_PATH}"
 | ||
|         else export LD_LIBRARY_PATH="${WINEDIR}/lib"
 | ||
|         fi
 | ||
| 
 | ||
|         export WINEDLLPATH="${WINEDIR}/lib/wine"
 | ||
| 
 | ||
|         if [[ -d "${WINEDIR}/lib/gstreamer-1.0" ]] ; then
 | ||
|             export GST_PLUGIN_SYSTEM_PATH_1_0="${WINEDIR}/lib/gstreamer-1.0"
 | ||
|         fi
 | ||
| 
 | ||
|         [[ ! -f "${WINEDIR}/version" ]] && echo "${WH_WINE_USE}" > "${WINEDIR}/version"
 | ||
| 
 | ||
|         if [[ ! -d "${WINEDIR}/lib64/wine" ]] && [[ -d "${WINEDIR}/lib/wine/x86_64-unix" ]] ; then
 | ||
|             create_new_dir "${WINEDIR}/lib64/"
 | ||
|             try_force_link_dir "${WINEDIR}/lib/wine/" "${WINEDIR}/lib64/"
 | ||
|         fi
 | ||
| 
 | ||
|         if [[ -d "${WINEDIR}/lib64" ]] ; then
 | ||
|             export LD_LIBRARY_PATH+=":${WINEDIR}/lib64"
 | ||
|             export WINEDLLPATH+=":${WINEDIR}/lib64/wine"
 | ||
|             if [[ -d "${WINEDIR}/lib64/gstreamer-1.0" ]] ; then
 | ||
|                 export GST_PLUGIN_SYSTEM_PATH_1_0+=":${WINEDIR}/lib64/gstreamer-1.0"
 | ||
|             fi
 | ||
|         fi
 | ||
| 
 | ||
|         if [[ $WH_USE_CPCSP_PROXY == "1" ]] \
 | ||
|         && ! grep -q "$CPCSP_PROXY_VER" "${WINEDIR}/cpcsp_proxy.ver"
 | ||
|         then
 | ||
|             CPCSP_PROXY_NAME="wine-cpcsp_proxy-$CPCSP_PROXY_VER"
 | ||
|             CPCSP_PROXY_URL="$CLOUD_URL/$CPCSP_PROXY_NAME.tar.xz"
 | ||
| 
 | ||
|             if [[ ! -f "$WH_TMP_DIR/$CPCSP_PROXY_NAME" ]] ; then
 | ||
|                 print_info "Загрузка $CPCSP_PROXY_NAME.tar.xz"
 | ||
|                 if try_download "$CPCSP_PROXY_URL" "$WH_TMP_DIR/$CPCSP_PROXY_NAME.tar.xz" check256sum
 | ||
|                 then unpack "$WH_TMP_DIR/$CPCSP_PROXY_NAME.tar.xz" "$WH_TMP_DIR"
 | ||
|                 else try_remove_file "$WH_TMP_DIR/$CPCSP_PROXY_NAME.tar.xz"
 | ||
|                 fi
 | ||
|             else
 | ||
|                 unpack "$WH_TMP_DIR/$CPCSP_PROXY_NAME.tar.xz" "$WH_TMP_DIR"
 | ||
|             fi
 | ||
| 
 | ||
|             cp -fr "$WH_TMP_DIR/$CPCSP_PROXY_NAME/"i386-* "${WINEDIR}/lib/wine/"
 | ||
|             if [[ -d "${WINEDIR}/lib64" ]] ; then
 | ||
|                 cp -fr "$WH_TMP_DIR/$CPCSP_PROXY_NAME/"x86_64-* "${WINEDIR}/lib64/wine/"
 | ||
|             fi
 | ||
|             try_remove_dir "$WH_TMP_DIR/$CPCSP_PROXY_NAME"
 | ||
|             echo "$CPCSP_PROXY_VER" > "${WINEDIR}/cpcsp_proxy.ver"
 | ||
|         fi
 | ||
|     else
 | ||
|         # use system WINE
 | ||
|         if ! command -v "wine" &>/dev/null ; then
 | ||
|             fatal "system WINE - not found."
 | ||
|         fi
 | ||
|         export WINEDIR="/usr"
 | ||
|         export WINELOADER="wine"
 | ||
|         export WINESERVER="wineserver"
 | ||
|     fi
 | ||
| 
 | ||
|     check_variables DXVK_LOG_LEVEL "none"
 | ||
|     check_variables VKD3D_SHADER_DEBUG "none"
 | ||
|     check_variables VKD3D_DEBUG "none"
 | ||
|     check_variables DXVK_LOG_PATH "none"
 | ||
|     check_variables VKBASALT_LOG_LEVEL "none"
 | ||
|     check_variables DXVK_NVAPI_LOG_LEVEL "none"
 | ||
| 
 | ||
|     if [[ $DEBUG == "0" ]] ; then
 | ||
|         check_variables WINEDEBUG "-all"
 | ||
|     elif [[ $DEBUG == "full" ]] ; then
 | ||
|         check_variables WINEDEBUG "+loaddll,+seh"
 | ||
|         export DXVK_LOG_LEVEL="error"
 | ||
|         export VKD3D_DEBUG "error"
 | ||
|         export WINE_MONO_TRACE "E:System.NotImplementedException"
 | ||
|         export VK_LOADER_DEBUG "error"
 | ||
|         export VKBASALT_LOG_LEVEL "error"
 | ||
|         export DXVK_NVAPI_LOG_LEVEL "error"
 | ||
|     else
 | ||
|         check_variables WINEDEBUG "err+all"
 | ||
|     fi
 | ||
| 
 | ||
|     print_info "Используется версия wine: $WH_WINE_USE"
 | ||
| }
 | ||
| 
 | ||
| get_and_set_reg_file () {
 | ||
| 
 | ||
|     convert_dec_and_hex () {
 | ||
|         local type=$1
 | ||
|         local num=$2
 | ||
| 
 | ||
|         case "$type" in
 | ||
|             --dec)
 | ||
|             # Преобразование из десятичного в шестнадцатеричный
 | ||
|             echo -n "$(printf "%08x" "$num")" ;;
 | ||
|             --hex)
 | ||
|             # Преобразование из шестнадцатеричного в десятичный
 | ||
|             echo $(( 0x$num )) ;;
 | ||
|             *)
 | ||
|             echo "Неверный тип преобразования. Используйте --dec или --hex." ;;
 | ||
|         esac
 | ||
|         }
 | ||
| 
 | ||
|     local name_block name_for_find find_block find_file find_line count name_for_new_block name_for_find_old
 | ||
|     local line_reg find_number_line find_check_file name_for_set name_type_reg name_fatal name_add_or_del
 | ||
|     name_add_or_del=$1
 | ||
|     name_block=$2
 | ||
|     name_for_find=$3
 | ||
|     name_type_reg=$4
 | ||
|     name_for_set=$5
 | ||
|     name_for_new_block=$6
 | ||
|     name_for_find_old=$name_for_find
 | ||
|     name_fatal="$name_block $name_for_find"
 | ||
| 
 | ||
|     case $name_type_reg in
 | ||
|         REG_DWORD)
 | ||
|             if [[ $name_for_find != '@=' ]]
 | ||
|             then name_for_find="\"$name_for_find\"=dword:"
 | ||
|             else name_for_find="@=dword:"
 | ||
|             fi
 | ||
|             name_for_set=$(convert_dec_and_hex --dec "$name_for_set") ;;
 | ||
|         REG_SZ)
 | ||
|             if [[ $name_for_find != '@=' ]]
 | ||
|             then name_for_find="\"$name_for_find\"="
 | ||
|             else name_for_find="@="
 | ||
|             fi
 | ||
|             name_for_set="\"$name_for_set\"" ;;
 | ||
|         *)
 | ||
|             if [[ $name_add_or_del == --delete ]] ; then
 | ||
|                 if [[ $name_for_find != '@=' ]]
 | ||
|                 then name_for_find="\"$name_for_find\""
 | ||
|                 else name_for_find="@="
 | ||
|                 fi
 | ||
|             else
 | ||
|                 print_error "не задан тип ветки реестра: $name_fatal"
 | ||
|                 return 1
 | ||
|             fi ;;
 | ||
|     esac
 | ||
|     name_block=${name_block//\\/\\\\\\\\}
 | ||
|     if [[ -n $name_for_new_block ]] ; then
 | ||
|         find_block=$(grep -n "\[$name_block\]" "$WINEPREFIX/$name_for_new_block.reg")
 | ||
|     else
 | ||
|         find_block=$(grep -n "\[$name_block\]" "$WINEPREFIX/"*.reg)
 | ||
|     fi
 | ||
|     if [[ -n $find_block ]] ; then
 | ||
|         if [[ -n $name_for_new_block ]] ; then
 | ||
|             find_file="$WINEPREFIX/$name_for_new_block.reg"
 | ||
|             find_line=${find_block//:*/}
 | ||
|         else
 | ||
|             find_file=${find_block//:*/}
 | ||
|             find_line=${find_block//$find_file:/}
 | ||
|             find_line=${find_line//:*/}
 | ||
|         fi
 | ||
|         count=-1
 | ||
|         while read -r line_reg ; do
 | ||
|             ((count++))
 | ||
|             if [[ $line_reg =~ $name_for_find ]] ; then
 | ||
|                 if [[ $line_reg == $name_for_find$name_for_set ]] ; then
 | ||
|                     return 0
 | ||
|                 fi
 | ||
|                 find_number_line=$(( count + find_line ))
 | ||
|                 find_check_file=1
 | ||
|                 break
 | ||
|             fi
 | ||
|             [[ -z $line_reg ]] && break
 | ||
|         done <<< "$(sed -n "$find_line"',$p' "$find_file")"
 | ||
|     fi
 | ||
|     if [[ $name_add_or_del == --add ]] ; then
 | ||
|         if [[ -z $find_block ]] ; then
 | ||
|             if [[ -n $name_for_new_block ]] ; then
 | ||
|                 sed -i '$a\\n'\["$name_block"\] "$WINEPREFIX/$name_for_new_block.reg"
 | ||
|                 find_file="$WINEPREFIX/$name_for_new_block.reg"
 | ||
|                 find_line=$(wc -l "$find_file" | awk -F" " '{print $1}')
 | ||
|                 find_line=$(( find_line - 1 ))
 | ||
|             else
 | ||
|                 print_error "$name_fatal не найден в файле реестра"
 | ||
|                 return 1
 | ||
|             fi
 | ||
|         fi
 | ||
|         if [[ $find_check_file == 1 ]] ; then
 | ||
|             print_info "Меняем $name_for_find_old в ветке реестра: $name_block"
 | ||
|             sed -i "${find_number_line}s|$name_for_find.*|$name_for_find$name_for_set|" "$find_file"
 | ||
|         else
 | ||
|             print_info "Добавляем $name_for_find_old в ветку реестра: $name_block"
 | ||
|             sed -i "$(( find_line + 1 ))a$name_for_find$name_for_set" "$find_file"
 | ||
|         fi
 | ||
|     elif [[ $name_add_or_del == --delete ]] ; then
 | ||
|         [[ $find_check_file != 1 ]] && return 0
 | ||
|         print_info "Удаляем $name_for_find_old из ветки реестра: $name_block"
 | ||
|         sed -i "${find_number_line}d" "$find_file"
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| wait_wineserver () {
 | ||
|     "$WINESERVER" -w
 | ||
| }
 | ||
| 
 | ||
| get_base_pfx () {
 | ||
|     local FILE_NAME_PFX="$1"
 | ||
|     local PFX_URL="$CLOUD_URL/${FILE_NAME_PFX}.tar.xz"
 | ||
|     local PFX_TMP="$WH_TMP_DIR/pfx"
 | ||
|     create_new_dir "$PFX_TMP"
 | ||
| 
 | ||
|     if [[ ! -f "$PFX_TMP/$FILE_NAME_PFX.tar.xz" ]] ; then
 | ||
|         print_info "Загрузка базового префикса: ${FILE_NAME_PFX}"
 | ||
|         if try_download "$PFX_URL" "$PFX_TMP/$FILE_NAME_PFX.tar.xz" check256sum
 | ||
|         then unpack "$PFX_TMP/$FILE_NAME_PFX.tar.xz" "$WINEPREFIX/"
 | ||
|         else try_remove_file "$PFX_TMP/$FILE_NAME_PFX.tar.xz"
 | ||
|         fi
 | ||
|     else
 | ||
|         if ! unpack "$PFX_TMP/$FILE_NAME_PFX.tar.xz" "$WINEPREFIX/" ; then
 | ||
|             try_remove_file "${PFX_TMP}/${FILE_NAME_PFX}.tar.xz"
 | ||
|             get_base_pfx "$FILE_NAME_PFX"
 | ||
|         fi
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| check_prefix_var () {
 | ||
|     if [[ -z "$WINEPREFIX" ]] ; then
 | ||
|         print_warning "Префикс не выбран."
 | ||
| 
 | ||
|         local prefixes=()
 | ||
|         local count=1
 | ||
|         print_info "Доступные префиксы WineHelper:"
 | ||
|         for prefix in "$WH_PREFIXES_DIR"/*; do
 | ||
|             if [[ -d "$prefix" ]]; then
 | ||
|                 prefixes+=("$prefix")
 | ||
|                 echo "$count. $(basename "$prefix")"
 | ||
|                 ((count++))
 | ||
|             fi
 | ||
|         done
 | ||
| 
 | ||
|         if [[ ${#prefixes[@]} -eq 0 ]]; then
 | ||
|             fatal "Не найдено ни одного префикса!"
 | ||
|         fi
 | ||
| 
 | ||
|         local max_choice=${#prefixes[@]}
 | ||
|         read -p "Выберите префикс (1-$max_choice): " choice
 | ||
| 
 | ||
|         if [[ "$choice" -ge 1 && "$choice" -le "$max_choice" ]]; then
 | ||
|             export WINEPREFIX="${prefixes[$choice-1]}"
 | ||
|         else
 | ||
|             fatal "Неверный выбор."
 | ||
|         fi
 | ||
| 
 | ||
|         print_info "Выбран префикс: $WINEPREFIX"
 | ||
|     fi
 | ||
| 
 | ||
|     if echo "$WINEPREFIX" | grep -qv '/' ; then
 | ||
|         export WINEPREFIX="$WH_PREFIXES_DIR/$WINEPREFIX"
 | ||
|     fi
 | ||
| 
 | ||
|     return 0
 | ||
| }
 | ||
| 
 | ||
| init_wineprefix () {
 | ||
|     check_prefix_var
 | ||
| 
 | ||
|     if [[ "$WINEARCH" == "win32" ]]
 | ||
|     then check_variables BASE_PFX "defpfx_x86_v01"
 | ||
|     else check_variables BASE_PFX "defpfx_x64_v01"
 | ||
|     fi
 | ||
| 
 | ||
|     export DRIVE_C="$WINEPREFIX/drive_c"
 | ||
| 
 | ||
|     if [[ ! -f "$WINEPREFIX/.firstboot" ]] ; then
 | ||
|         create_new_dir "$WINEPREFIX"
 | ||
|         if [[ "$CLEAR_PREFIX" == "1" ]]
 | ||
|         then print_warning "Используется переменная \"CLEAR_PREFIX=1\" что принудительно создает чистый префикс с установкой компонентов с помощью winetricks."
 | ||
|         elif [[ "$BASE_PFX" != "none" ]]
 | ||
|         then get_base_pfx "$BASE_PFX"
 | ||
|         fi
 | ||
|         print_info "Обновление префикса $WINEPREFIX."
 | ||
|         if [[ -d "$WINEPREFIX/drive_c/windows" ]]
 | ||
|         then "$WINELOADER" wineboot -u
 | ||
|         else "$WINELOADER" wineboot -i
 | ||
|         fi
 | ||
|         touch "$WINEPREFIX/.firstboot"
 | ||
|         wait_wineserver
 | ||
|     fi
 | ||
| 
 | ||
|     if [[ -f "$WINEPREFIX/system.reg" ]] \
 | ||
|     && [[ -z $(grep "Windows $WH_WINDOWS_VER" "$WINEPREFIX/system.reg") ]]
 | ||
|     then
 | ||
|         if [[ $(echo "$WH_WINDOWS_VER" | sed 's/.*/\L&/') == "xp" ]] \
 | ||
|         && [[ "$WINEARCH" != "win32" ]]
 | ||
|         then export WH_WINDOWS_VER="xp64"
 | ||
|         fi
 | ||
|         "$WINELOADER" winecfg -v $(echo "win${WH_WINDOWS_VER}" | sed 's/.*/\L&/')
 | ||
|         wait_wineserver
 | ||
|         print_info "Windows версия изменена на win${WH_WINDOWS_VER}"
 | ||
|     fi
 | ||
| 
 | ||
|     if [[ -d "$DRIVE_C/users/xuser" ]] && [[ ! -d "$DRIVE_C/users/$USER" ]]
 | ||
|     then try_force_link_dir "$DRIVE_C/users/xuser" "$DRIVE_C/users/$USER"
 | ||
|     elif [[ ! -d "$DRIVE_C/users/xuser" ]] && [[ -d "$DRIVE_C/users/$USER" ]]
 | ||
|     then try_force_link_dir "$DRIVE_C/users/$USER" "$DRIVE_C/users/xuser"
 | ||
|     fi
 | ||
| 
 | ||
|     if [[ ! -L "$WINEPREFIX/dosdevices/h:" ]]
 | ||
|     then try_force_link_dir "$HOME" "$WINEPREFIX/dosdevices/h:"
 | ||
|     fi
 | ||
| 
 | ||
|     try_remove_file "$DRIVE_C/windows/system32/winemenubuilder.exe"
 | ||
| 
 | ||
|     # хак для XRDP сессии
 | ||
|     if [[ $DISPLAY == *:10.0 ]] ; then
 | ||
|         print_warning "Обнаружена сессия XRDP, настраиваем реестр:"
 | ||
|         get_and_set_reg_file --add 'Software\Wine\X11 Driver' 'UseXRandR' 'REG_SZ' "N" "user"
 | ||
|         get_and_set_reg_file --add 'Software\Wine\X11 Driver' 'UseXVidMode' 'REG_SZ' "N" "user"
 | ||
|     else
 | ||
|         get_and_set_reg_file --delete 'Software\Wine\X11 Driver' 'UseXRandR'
 | ||
|         get_and_set_reg_file --delete 'Software\Wine\X11 Driver' 'UseXVidMode'
 | ||
|     fi
 | ||
| 
 | ||
|     # добавление ассоциаций файлов для запуска нативного приложения из wine
 | ||
|     # пример переменной: WH_XDG_OPEN="txt doc pdf"
 | ||
|     check_variables WH_XDG_OPEN "0"
 | ||
|     local WRAPPER="${WH_TMP_DIR}/wh-xdg-open.sh"
 | ||
|     local XDG_OPEN_REG="Software\Classes\xdg-open\shell\open\command"
 | ||
|     if [[ $WH_XDG_OPEN != "0" ]] ; then
 | ||
|         # проверяем на наличие запрещённых расширений
 | ||
|         local forbidden_extensions="cpl dll exe lnk msi"
 | ||
|         for ext in $WH_XDG_OPEN; do
 | ||
|             if [[ "$forbidden_extensions" =~ $ext ]] ; then
 | ||
|                 fatal "Расширение .$ext запрещено для добавления!"
 | ||
|             fi
 | ||
|         done
 | ||
| 
 | ||
|         # создаем скрипт-обёртку
 | ||
|         {
 | ||
|             echo "#!/usr/bin/env bash"
 | ||
|             echo "unix_path=\$(\"$WINELOADER\" winepath -u \"\$*\")"
 | ||
|             echo "xdg-open \"\$unix_path\""
 | ||
|         } > "$WRAPPER"
 | ||
|         chmod +x "$WRAPPER"
 | ||
| 
 | ||
|         # добавляем новую команду xdg-open в реестр
 | ||
|         get_and_set_reg_file --add "$XDG_OPEN_REG" '@=' 'REG_SZ' "$WRAPPER %1" "system"
 | ||
| 
 | ||
|         # добавляем ассоциации файлов для запуска с помощью xdg-open
 | ||
|         for ext in $WH_XDG_OPEN ; do
 | ||
|             get_and_set_reg_file --add "Software\Classes\.$ext" '@=' 'REG_SZ' "xdg-open" "system"
 | ||
|         done
 | ||
|         print_info "Используется ассоциации с нативными приложениями для файлов: \"$WH_XDG_OPEN\""
 | ||
|     else
 | ||
|         # удаление команды xdg-open из реестра
 | ||
|         get_and_set_reg_file --delete "$XDG_OPEN_REG" '@='
 | ||
|         # удаяем скрипт-обёртку
 | ||
|         try_remove_file "$WRAPPER"
 | ||
|     fi
 | ||
| 
 | ||
|     # настраиваем префикс для работы с cpcsp_proxy
 | ||
|     if [[ $WH_USE_CPCSP_PROXY == "1" ]] ; then
 | ||
|         for cpcsp_proxy_file in "cpcsp_proxy.dll" "cpcsp_proxy_setup.exe" ; do
 | ||
|             try_copy_wine_dll_to_pfx_64 "$cpcsp_proxy_file"
 | ||
|             try_copy_wine_dll_to_pfx_32 "$cpcsp_proxy_file"
 | ||
|         done
 | ||
| 
 | ||
|         if ! grep -q "cpcsp_proxy.dll" "$WINEPREFIX/system.reg" ; then
 | ||
|             if [[ "$WINEARCH" == "win32" ]]
 | ||
|             then cpcsp_proxy_cmd=("$WINELOADER" "cpcsp_proxy_setup.exe")
 | ||
|             else cpcsp_proxy_cmd=("${WINELOADER}64" "cpcsp_proxy_setup.exe")
 | ||
|             fi
 | ||
| 
 | ||
|             print_info "Запускаем настройку cpcsp_proxy..."
 | ||
|             unset CPCSP_PROXY_OK
 | ||
|             set -o pipefail
 | ||
|             for ((i=2; i < 6; i++)) ; do
 | ||
|                 "${cpcsp_proxy_cmd[@]}" | tee "$WINEPREFIX/cpcsp_setup.log"
 | ||
|                 local CPCSP_EXIT_STATUS="${PIPESTATUS[0]}"
 | ||
|                 if grep -q "failed to load /opt/cprocsp/" "$WINEPREFIX/cpcsp_setup.log" ; then
 | ||
|                     fatal "Проверьте правильность установки CryptoPro в системе.\n Инструкция: https://www.altlinux.org/CryptoPro"
 | ||
|                 fi
 | ||
| 
 | ||
|                 if [[ $CPCSP_EXIT_STATUS == "0" ]] ; then
 | ||
|                     print_info "Настройка cpcsp_proxy успешно завершена."
 | ||
|                     CPCSP_PROXY_OK="1"
 | ||
|                     break
 | ||
|                 fi
 | ||
|                 print_warning "Попытка $i из 5..."
 | ||
|                 wait_wineserver
 | ||
|             done
 | ||
|             wait_wineserver
 | ||
|             try_remove_file "$WINEPREFIX/cpcsp_setup.log"
 | ||
|             [[ $CPCSP_PROXY_OK != "1" ]] && fatal "Ошибка во время настройки cpcsp_proxy."
 | ||
|         fi
 | ||
|     fi
 | ||
| 
 | ||
|     echo "# переменные последнего использования префикса:" > "$WINEPREFIX/last.conf"
 | ||
|     for var in WH_WINE_USE BASE_PFX WINEARCH WH_WINDOWS_VER WINEESYNC WINEFSYNC \
 | ||
|     STAGING_SHARED_MEMORY WINE_LARGE_ADDRESS_AWARE WH_USE_SHADER_CACHE WH_USE_WINE_DXGI \
 | ||
|     WINE_CPU_TOPOLOGY USE_RENDERER DXVK_VER VKD3D_VER
 | ||
|     do
 | ||
|         echo "export $var=\"${!var}\"" >> "$WINEPREFIX/last.conf"
 | ||
|     done
 | ||
| }
 | ||
| 
 | ||
| kill_autostart () {
 | ||
|     [[ -z "${1}" ]] && fatal "Нет аргумента для функции kill_autostart."
 | ||
|     [[ -z "${2}" ]] && SWAIT=3 || SWAIT="${2}"
 | ||
|     sleep 5
 | ||
|     while ps aux | grep -m 1 -i "$WINESERVER" | grep -v grep &>/dev/null ; do
 | ||
|         if  [[ -z "$(ps aux | grep -m 1 -i "$1" | grep -v grep | awk '{print $2}')" ]] ; then
 | ||
|             print_info "PID для $1 не найден. Ожидаем окончания установки..."
 | ||
|             sleep "${SWAIT}"
 | ||
|         else
 | ||
|             print_ok "PID для $1 найден. Завершаем работу автозапуска приложения."
 | ||
|             "$WINESERVER" -k
 | ||
|             break
 | ||
|         fi
 | ||
|     done
 | ||
| }
 | ||
| 
 | ||
| use_winetricks () {
 | ||
|     if [[ -n "$INSTALL_DLL" ]] ; then
 | ||
|         WH_DLL_INSTALL="$(echo "$INSTALL_DLL $WH_DLL_INSTALL" | awk '{ for(i=1;i<=NF;i++){a[$i]++} }END{ for(i in a){printf("%s ",i)} }' )"
 | ||
|     fi
 | ||
|     if [[ -n "$WH_DLL_INSTALL" ]] ; then
 | ||
|         WH_DLL_NEED_INSTALL=""
 | ||
|         USE_WT_FROM_DB=0
 | ||
|         [[ ! -f "$WINEPREFIX/winetricks.log" ]] && touch "$WINEPREFIX/winetricks.log"
 | ||
|         for need_install_dll_to_pfx in $WH_DLL_INSTALL "isolate_home" ; do
 | ||
|             if ! grep "$need_install_dll_to_pfx" "$WINEPREFIX/winetricks.log" &>/dev/null ; then
 | ||
|                 if [[ -z "$WH_DLL_NEED_INSTALL" ]]
 | ||
|                 then WH_DLL_NEED_INSTALL="$need_install_dll_to_pfx"
 | ||
|                 else WH_DLL_NEED_INSTALL="$need_install_dll_to_pfx $WH_DLL_NEED_INSTALL"
 | ||
|                 fi
 | ||
|                 USE_WT_FROM_DB=1
 | ||
|             fi
 | ||
|         done
 | ||
|         if [[ "$USE_WT_FROM_DB" == "1" ]] ; then
 | ||
|             print_info "Пробуем установить компоненты: ${WH_DLL_NEED_INSTALL}"
 | ||
|             print_info "Запускаем WINETRICKS..."
 | ||
|             export WINETRICKS_DOWNLOADER="curl"
 | ||
|             "$WH_WINETRICKS" -q ${WH_DLL_NEED_INSTALL}
 | ||
|             wait_wineserver
 | ||
|         fi
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| kill_wine () {
 | ||
|     wine_pids=$(ls -l /proc/*/exe 2>/dev/null | grep -E 'wine(64)?-preloader|wineserver' | awk -F/ '{print $3}')
 | ||
| 
 | ||
|     for pw_kill_pids in ${wine_pids}; do
 | ||
|         if ps cax | grep "${pw_kill_pids}" ; then
 | ||
|             kill -n 9 "${pw_kill_pids}" &>/dev/null
 | ||
|         fi
 | ||
|     done
 | ||
| }
 | ||
| 
 | ||
| init_database () {
 | ||
|     WHDB_FILE="0"
 | ||
|     if [[ -f "$WIN_FILE_EXEC" ]] ; then
 | ||
|         WHDB="$(basename "$WIN_FILE_EXEC" .exe)"
 | ||
|         if [[ -f "$WIN_FILE_EXEC".whdb ]] ; then
 | ||
|             WHDB_FILE="$WIN_FILE_EXEC".whdb
 | ||
|         else
 | ||
|             orig_IFS="$IFS" && IFS=$'\n'
 | ||
|             if WH_FIND_DB_FILE="$(grep -ilw "#$WHDB.exe" "$WH_DB_DIR"/* )" ; then
 | ||
|                 WHDB_FILE="$WH_FIND_DB_FILE"
 | ||
|             fi
 | ||
|             IFS="$orig_IFS"
 | ||
|         fi
 | ||
|     fi
 | ||
| 
 | ||
|     if [[ "$WHDB_FILE" != "0" ]] ; then
 | ||
|         print_info "Используется файл настроек: $WHDB_FILE"
 | ||
|         . "$WHDB_FILE"
 | ||
|     elif check_prefix_var && [[ -f "$WINEPREFIX/last.conf" ]] ; then
 | ||
|         print_info "Найдены настройки из предыдущего использования префикса: $WINEPREFIX"
 | ||
|         cat "$WINEPREFIX/last.conf"
 | ||
|         . "$WINEPREFIX/last.conf"
 | ||
|     else
 | ||
|         print_warning "Файл настроек не найден. Пропускаем."
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| prepair_wine () {
 | ||
|     if [[ -n "$INSTALL_SCRIPT_NAME" ]] \
 | ||
|     && [[ "$FORCE_INSTALL" != "1" ]]
 | ||
|     then
 | ||
|     print_warning "Лицензионные соглашения использования сторонних компонентов:
 | ||
| 
 | ||
| Некоторые компоненты, установленные в префикс и необходимые для запуска приложений, могут
 | ||
| быть защищены авторским правом или лицензионными соглашениями. Вы обязаны самостоятельно
 | ||
| убедиться в законности использования этих компонентов в вашей юрисдикции.
 | ||
| 
 | ||
| Мы не несём ответственности за нарушение лицензионных соглашений, связанное с использованием
 | ||
| подготовленного префикса.
 | ||
| 
 | ||
| Продолжая использовать данное ПО вы подтверждаете, что ознакомились с данным отказом от
 | ||
| ответственности и принимаете все риски, связанные с его использованием.
 | ||
| "
 | ||
|     print_info "Для продолжения нажмите любую клавишу на клавиатуре."
 | ||
|     read -s -n 1
 | ||
|     fi
 | ||
| 
 | ||
|     var_winedlloverride_update "winemenubuilder.exe=d"
 | ||
| 
 | ||
|     if [[ -n "$INSTALL_SCRIPT_NAME" ]]
 | ||
|     then print_info "Используются настройки из скрипта установки: $INSTALL_SCRIPT_NAME"
 | ||
|     else init_database
 | ||
|     fi
 | ||
|     init_wine_ver
 | ||
|     init_wineprefix
 | ||
|     use_winetricks
 | ||
| 
 | ||
|     if init_wined3d ; then
 | ||
|         :
 | ||
|     else
 | ||
|         init_dxvk "$DXVK_VER"
 | ||
|         init_vkd3d "$VKD3D_VER"
 | ||
|     fi
 | ||
|     [[ "$MANGOHUD" == 1 ]] && MANGOHUD_RUN="mangohud"
 | ||
| }
 | ||
| 
 | ||
| wine_run () {
 | ||
|     WIN_FILE_PATH="$(dirname "$WIN_FILE_EXEC")"
 | ||
|     [[ -d "$WIN_FILE_PATH" ]] && cd "$WIN_FILE_PATH"
 | ||
| 
 | ||
|     if [[ $DEBUG == "0" ]] ; then
 | ||
|         $MANGOHUD_RUN "$WINELOADER" "$@" $LAUNCH_PARAMETERS
 | ||
|     else
 | ||
|         print_var WH_WINE_USE WINEARCH WINEPREFIX WINEDLLOVERRIDES WH_WINDOWS_VER | tee "$LOG_FILE"
 | ||
|         $MANGOHUD_RUN "$WINELOADER" "$@" $LAUNCH_PARAMETERS 2>&1 | tee -a "$LOG_FILE"
 | ||
|     fi
 | ||
| 
 | ||
|     wait_wineserver
 | ||
| }
 | ||
| 
 | ||
| wine_run_install () {
 | ||
|     print_info "Запускаем установку приложения $PROG_NAME."
 | ||
|     if [[ "$INSTALL_MODE" == "manual" ]]
 | ||
|     then print_warning "Рекомендуется не менять пути для установки приложения!"
 | ||
|     fi
 | ||
|     [[ ! -f "$1" ]] && fatal "Нет файла для установки: $1"
 | ||
|     case "${1,,}" in
 | ||
|         *.exe) wine_run $WINE_WIN_START "$@" ;;
 | ||
|         *.msi) wine_run msiexec /i "$@" ;;
 | ||
|         *.bat|*.cmd) wine_run "$@" ;;
 | ||
|         *) fatal "Не удалось запустить файл $1. Проверьте расширение файла." ;;
 | ||
|     esac
 | ||
|     wait_wineserver
 | ||
| }
 | ||
| 
 | ||
| run_autoinstall () {
 | ||
|     if [[ $1 == "--clear-pfx" ]] ; then
 | ||
|         export CLEAR_PREFIX="1"
 | ||
|         shift
 | ||
|     elif [[ $2 == "--clear-pfx" ]] ; then
 | ||
|         export CLEAR_PREFIX="1"
 | ||
|     fi
 | ||
| 
 | ||
|     INSTALL_SCRIPT_NAME="${1,,}"
 | ||
|     if [[ -f "$WH_AUTOINSTALL_DIR/$INSTALL_SCRIPT_NAME" ]] ; then
 | ||
|         INSTALL_SCRIPT="$WH_AUTOINSTALL_DIR/$INSTALL_SCRIPT_NAME"
 | ||
|         WH_INSTALL_MODE="auto"
 | ||
|     elif [[ -f "$WH_MANUALINSTALL_DIR/$INSTALL_SCRIPT_NAME" ]] ; then
 | ||
|         INSTALL_SCRIPT="$WH_MANUALINSTALL_DIR/$INSTALL_SCRIPT_NAME"
 | ||
|         WH_INSTALL_MODE="manual"
 | ||
|     else
 | ||
|         INSTALL_SCRIPT="0"
 | ||
|     fi
 | ||
|     export INSTALL_SCRIPT INSTALL_MODE
 | ||
| 
 | ||
|     if [[ $INSTALL_SCRIPT_NAME == "list" ]] || [[ -z "$INSTALL_SCRIPT_NAME" ]] ; then
 | ||
|         print_info "Список программ с возможностью автоматической установки:"
 | ||
|         for list in $(ls "$WH_AUTOINSTALL_DIR") ; do
 | ||
|             AI_INFO="$(grep "info_ru:" "$WH_AUTOINSTALL_DIR/$list" | awk -F"info_ru: " '{print $2}')"
 | ||
|             AI_PROGNAME="$(grep "PROG_NAME=" "$WH_AUTOINSTALL_DIR/$list" | awk -F"PROG_NAME=" '{print $2}')"
 | ||
|             echo -e "\n$list - $AI_PROGNAME"
 | ||
|             echo "$AI_INFO"
 | ||
|         done
 | ||
|         echo
 | ||
|         print_info "Список программ с возможностью установки из существующего дистрибутива:"
 | ||
|         for list in $(ls "$WH_MANUALINSTALL_DIR") ; do
 | ||
|             AI_INFO="$(grep "info_ru:" "$WH_MANUALINSTALL_DIR/$list" | awk -F"info_ru: " '{print $2}')"
 | ||
|             AI_PROGNAME="$(grep "PROG_NAME=" "$WH_MANUALINSTALL_DIR/$list" | awk -F"PROG_NAME=" '{print $2}')"
 | ||
|             echo -e "\n$list - $AI_PROGNAME"
 | ||
|             echo "$AI_INFO"
 | ||
|         done
 | ||
|     elif [[ "$INSTALL_SCRIPT" != "0" ]] ; then
 | ||
|         source "$INSTALL_SCRIPT" "$@"
 | ||
|         print_info "Завершена установка $INSTALL_SCRIPT_NAME"
 | ||
|     else
 | ||
|         fatal "Скрипт автоматической установки для $INSTALL_SCRIPT_NAME не найден!"
 | ||
|     fi
 | ||
|     echo
 | ||
| }
 | ||
| 
 | ||
| remove_prefix() {
 | ||
|     local prefix_name="$1"
 | ||
|     local prefix_path="$WH_PREFIXES_DIR/$prefix_name"
 | ||
| 
 | ||
|     if [[ -z "$prefix_name" ]]; then
 | ||
|         print_error "Не указано имя префикса для удаления."
 | ||
|         echo "Использование: $SCRIPT_NAME remove-prefix [имя_префикса]"
 | ||
|         echo "Доступные префиксы:"
 | ||
|         ls -1 "$WH_PREFIXES_DIR"
 | ||
|         return 1
 | ||
|     fi
 | ||
| 
 | ||
|     if [[ ! -d "$prefix_path" ]]; then
 | ||
|         print_error "Префикс "$prefix_name" не найден."
 | ||
|         return 1
 | ||
|     fi
 | ||
| 
 | ||
|     if [[ ! $2 =~ --force|-y ]] ; then
 | ||
|         echo "======================================================"
 | ||
|         print_warning "Вы собираетесь удалить префикс "$prefix_name"."
 | ||
|         echo "Это приведёт к:"
 | ||
|         echo " - Полному удалению всех данных префикса"
 | ||
|         echo " - Удалению всех программ, установленных в этом префиксе"
 | ||
|         echo " - Удалению связанных ярлыков из меню и рабочего стола"
 | ||
|         echo "======================================================"
 | ||
|         read -p "Продолжить удаление? (y/N): " answer
 | ||
| 
 | ||
|         if [[ ! "$answer" =~ ^[YyДд]$ ]]; then
 | ||
|             print_info "Удаление префикса отменено."
 | ||
|             return 0
 | ||
|         fi
 | ||
|     fi
 | ||
|     try_remove_dir "$prefix_path"
 | ||
| 
 | ||
|     if [[ $? -eq 0 ]]; then
 | ||
|         print_ok "Префикс "$prefix_name" успешно удален."
 | ||
| 
 | ||
|         for desktop_file in "$WH_MENU_DIR"/*.desktop; do
 | ||
|             if grep -q "$prefix_path" "$desktop_file"; then
 | ||
|                 desktop_name=$(basename "$desktop_file")
 | ||
|                 remove_desktop "${desktop_name%.*}"
 | ||
|             fi
 | ||
|         done
 | ||
| 
 | ||
|         return 0
 | ||
|     else
 | ||
|         print_error "Не удалось удалить префикс "$prefix_name"."
 | ||
|         return 1
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| remove_winehelper () {
 | ||
|     local answer
 | ||
|     if [[ $1 =~ --force|-y ]] ; then
 | ||
|         answer="y"
 | ||
|     else
 | ||
|         echo "======================================================"
 | ||
|         print_warning "Вы собираетесь удалить WineHelper и все связанные с ним данные."
 | ||
|         echo " Это удалит:"
 | ||
|         echo " - Все настройки WineHelper"
 | ||
|         echo " - Все приложения/программы, установленные через WineHelper"
 | ||
|         echo " - Все ярлыки из меню и с рабочего стола созданные с помощью WineHelper"
 | ||
|         echo "======================================================"
 | ||
|         echo "Продолжить? (y/N)"
 | ||
|         read -r answer
 | ||
| 
 | ||
|         if [[ "$answer" =~ ^[YyДд]$ ]] ; then
 | ||
|             # Второе подтверждение
 | ||
|             echo "----------------------------------------------"
 | ||
|             print_warning " ВЫ ТОЧНО УВЕРЕНЫ?"
 | ||
|             echo "----------------------------------------------"
 | ||
|             echo "Продолжить? (y/N)"
 | ||
|             read -r answer
 | ||
|         else
 | ||
|             print_info "Удаление отменено."
 | ||
|             return 1
 | ||
|         fi
 | ||
|     fi
 | ||
| 
 | ||
|     if [[ "$answer" =~ ^[YyДд]$ ]] ; then
 | ||
|         # Удаление рабочих каталогов
 | ||
|         try_remove_dir "$USER_WORK_PATH"
 | ||
| 
 | ||
|         # Удаление файлов меню
 | ||
|         try_remove_dir "$WH_MENU_DIR"
 | ||
|         try_remove_file "$WH_MENU_CATEGORY"
 | ||
|         try_remove_file "$WH_MENU_CONFIG"
 | ||
| 
 | ||
|         # Удаление desktop-файлов
 | ||
|         for desktop_file in "$(xdg-user-dir DESKTOP)"/*.desktop; do
 | ||
|             if grep -q "Exec=env \"$RUN_SCRIPT\"" "$desktop_file"; then
 | ||
|                 try_remove_file "$desktop_file"
 | ||
|             fi
 | ||
|         done
 | ||
| 
 | ||
|         # Обновление кэша desktop-файлов
 | ||
|         update-desktop-database "$HOME/.local/share/applications"
 | ||
| 
 | ||
|         # Удаление символических ссылок
 | ||
|         try_remove_file "$HOME/.winehelper"
 | ||
| 
 | ||
|         print_info "WineHelper и все связанные данные успешно удалены."
 | ||
|     else
 | ||
|         print_info "Удаление отменено."
 | ||
|     fi
 | ||
| }
 | ||
| 
 | ||
| wh_info () {
 | ||
|     echo "Использование: $SCRIPT_NAME [команда]
 | ||
| 
 | ||
| Команды:
 | ||
|     install list                  список возможных установочных скриптов
 | ||
|     install [скрипт]              запустить скрипт установки программы
 | ||
|     install [скрипт] --clear-pfx  не использовать подготовленный префикс для установки ПО
 | ||
| 
 | ||
|     installed                     список установленных программ
 | ||
|     run [программа.exe]           запуск программы (отладка)
 | ||
|     remove-all                    удалить WineHelper и все связанные данные
 | ||
|     remove-prefix [имя_префикса]  удалить префикс и все связанные данные
 | ||
| 
 | ||
| Параметры:
 | ||
|     --help                        показать эту справку и выйти
 | ||
|     --version                     показать информацию о пакете и его версии
 | ||
|     --debug [команда]             включить режим логирования работы WINE
 | ||
| 
 | ||
| "
 | ||
| }
 | ||
| 
 | ||
| ##### MAIN #####
 | ||
| create_new_dir "$WH_TMP_DIR"
 | ||
| create_new_dir "$WH_DIST_DIR"
 | ||
| create_new_dir "$WH_PREFIXES_DIR"
 | ||
| create_new_dir "$WH_VULKAN_LIBDIR"
 | ||
| 
 | ||
| if [[ -d "$HOME/.local/share/$SCRIPT_NAME" ]] \
 | ||
| && [[ ! -L "$HOME/.winehelper" ]]
 | ||
| then try_force_link_dir "$HOME/.local/share/$SCRIPT_NAME" "$HOME/.winehelper"
 | ||
| fi
 | ||
| 
 | ||
| case "${1,,}" in
 | ||
|     --version) rpm -qi "$SCRIPT_NAME" ; exit 0 ;;
 | ||
|     --help) wh_info ; exit 0 ;;
 | ||
|     killall) kill_wine ;;
 | ||
|     winecfg) prepair_wine ; wine_run "winecfg" ;;
 | ||
|     winereg|regedit) prepair_wine ; wine_run "regedit" ;;
 | ||
|     winefile|explorer) prepair_wine ; wine_run "winefile" ;;
 | ||
|     wineconsole|cmd) prepair_wine ; wine_run "wineconsole" ;;
 | ||
|     winetricks) shift ; prepair_wine ; "$WINETRICKS" -q "$@" ;;
 | ||
|     desktop) shift ; create_desktop "$@" ; exit 0 ;;
 | ||
|     install|-i) shift ; run_autoinstall "$@" ;;
 | ||
|     installed) shift ; check_installed_programs "$1" ;;
 | ||
|     run|-r) shift ; run_installed_programs "$1" ;;
 | ||
|     remove-all) shift ; remove_winehelper "$@" ;;
 | ||
|     remove-prefix) shift ; remove_prefix "$@" ;;
 | ||
|     *)
 | ||
|         if [[ -f "$1" ]] ; then
 | ||
|             WIN_FILE_EXEC="$(readlink -f "$1")"
 | ||
|             WIN_FILE_NAME="$(basename "$WIN_FILE_EXEC")"
 | ||
|             shift
 | ||
|             case "${WIN_FILE_NAME,,}" in
 | ||
|                 *.exe) prepair_wine ; wine_run $WINE_WIN_START "$WIN_FILE_EXEC" "$@" ;;
 | ||
|                 *.msi) prepair_wine ; wine_run msiexec /i "$WIN_FILE_EXEC" "$@" ;;
 | ||
|                 *.bat|*.cmd) prepair_wine ; wine_run start "$WIN_FILE_EXEC" "$@" ;;
 | ||
|                 *) fatal "Тип файла не поддерживается." ;;
 | ||
|             esac
 | ||
|         else
 | ||
|             wh_info
 | ||
|             exit 1
 | ||
|         fi
 | ||
|         ;;
 | ||
| esac
 |