diff --git a/build/windows/installer/directories.isi b/build/windows/installer/base_directories.isi similarity index 95% rename from build/windows/installer/directories.isi rename to build/windows/installer/base_directories.isi index b09ef5115e..dd4e8ae57f 100644 --- a/build/windows/installer/directories.isi +++ b/build/windows/installer/base_directories.isi @@ -1,75 +1,75 @@ -//directories to source files from -#if !defined(VERSION) - #error "VERSION must be defined" -#endif - -#define public - -#if !defined(VER_DIR) - #if defined(REVISION) - #define VER_DIR VERSION + "-" + REVISION - #else - #define VER_DIR VERSION - #endif -#endif - -#ifndef DIR32 -#define DIR32 "i686-w64-mingw32" -#endif -#ifndef DIR64 -#define DIR64 "x86_64-w64-mingw32" -#endif -#ifndef DIRA64 -#define DIRA64 "aarch64-w64-mingw32" -#endif - -#ifndef GIMP_DIR - #define GIMP_DIR "N:\gimp\output\" + VER_DIR -#endif -#ifndef DEPS_DIR - #define DEPS_DIR "N:\gimp\deps" -#endif - -//32-bit GIMP base directory (result of make install) -#ifndef GIMP_DIR32 - #define GIMP_DIR32 GIMP_DIR + "\" + DIR32 -#endif -//64-bit GIMP base directory (result of make install) -#ifndef GIMP_DIR64 - #define GIMP_DIR64 GIMP_DIR + "\" + DIR64 -#endif -//AArch64 GIMP base directory (result of make install) -#ifndef GIMP_DIRA64 - #define GIMP_DIRA64 GIMP_DIR + "\" + DIR64 -#endif - -#ifndef DDIR32 - #define DDIR32 DIR32 -#endif -#ifndef DDIR64 - #define DDIR64 DIR64 -#endif -#ifndef DDIRA64 - #define DDIRA64 DIRA64 -#endif - -//32-bit dependencies directory -#ifndef DEPS_DIR32 - #define DEPS_DIR32 DEPS_DIR + "\" + DDIR32 -#endif -//64-bit dependencies directory -#ifndef DEPS_DIR64 - #define DEPS_DIR64 DEPS_DIR + "\" + DDIR64 -#endif -//AArch64 dependencies directory -#ifndef DEPS_DIR64 - #define DEPS_DIRA64 DEPS_DIR + "\" + DDIRA64 -#endif - -#ifdef PYTHON - - //python source directory - #ifndef PY_DIR - #define PY_DIR "N:\common\python2.7" - #endif -#endif +//directories to source files from +#if !defined(VERSION) + #error "VERSION must be defined" +#endif + +#define public + +#if !defined(VER_DIR) + #if defined(REVISION) + #define VER_DIR VERSION + "-" + REVISION + #else + #define VER_DIR VERSION + #endif +#endif + +#ifndef DIR32 +#define DIR32 "i686-w64-mingw32" +#endif +#ifndef DIR64 +#define DIR64 "x86_64-w64-mingw32" +#endif +#ifndef DIRA64 +#define DIRA64 "aarch64-w64-mingw32" +#endif + +#ifndef GIMP_DIR + #define GIMP_DIR "N:\gimp\output\" + VER_DIR +#endif +#ifndef DEPS_DIR + #define DEPS_DIR "N:\gimp\deps" +#endif + +//32-bit GIMP base directory (result of make install) +#ifndef GIMP_DIR32 + #define GIMP_DIR32 GIMP_DIR + "\" + DIR32 +#endif +//64-bit GIMP base directory (result of make install) +#ifndef GIMP_DIR64 + #define GIMP_DIR64 GIMP_DIR + "\" + DIR64 +#endif +//AArch64 GIMP base directory (result of make install) +#ifndef GIMP_DIRA64 + #define GIMP_DIRA64 GIMP_DIR + "\" + DIR64 +#endif + +#ifndef DDIR32 + #define DDIR32 DIR32 +#endif +#ifndef DDIR64 + #define DDIR64 DIR64 +#endif +#ifndef DDIRA64 + #define DDIRA64 DIRA64 +#endif + +//32-bit dependencies directory +#ifndef DEPS_DIR32 + #define DEPS_DIR32 DEPS_DIR + "\" + DDIR32 +#endif +//64-bit dependencies directory +#ifndef DEPS_DIR64 + #define DEPS_DIR64 DEPS_DIR + "\" + DDIR64 +#endif +//AArch64 dependencies directory +#ifndef DEPS_DIR64 + #define DEPS_DIRA64 DEPS_DIR + "\" + DDIRA64 +#endif + +#ifdef PYTHON + + //python source directory + #ifndef PY_DIR + #define PY_DIR "N:\common\python2.7" + #endif +#endif diff --git a/build/windows/installer/base_executables.isi b/build/windows/installer/base_executables.isi new file mode 100644 index 0000000000..968a2a3358 --- /dev/null +++ b/build/windows/installer/base_executables.isi @@ -0,0 +1,54 @@ +//files arch-specific +#if 0 +[Files] +#endif + +#if PLATFORM==X86 + #define DIR DIR32 + #define DDIR DDIR32 + #define COMPONENT "32" +#elif PLATFORM==X64 + #define DIR DIR64 + #define DDIR DDIR64 + #define COMPONENT "64" +#elif PLATFORM==ARM64 + #define DIR DIRA64 + #define DDIR DDIRA64 + #define COMPONENT "ARM64" +#else + #error "Unknown PLATFORM:" + PLATFORM +#endif + + +;Required arch-specific components (minimal install) +Source: "{#GIMP_DIR}\{#DIR}\*.dll"; DestDir: "{app}"; Excludes: "bin\libgs*.dll,bin\lua*.dll,bin\libpython*.dll"; Components: gimp{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete +Source: "{#GIMP_DIR}\{#DIR}\*.exe"; DestDir: "{app}"; Excludes: "\lib\gimp\{#DIR_VER}\plug-ins\file-ps\file-ps.exe,\bin\lua*.exe,\bin\python*.exe,\lib\gimp\{#DIR_VER}\plug-ins\twain\twain.exe"; Components: gimp{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete +Source: "{#GIMP_DIR}\{#DIR}\lib\gimp\{#DIR_VER}\extensions\*.*"; DestDir: "{app}\lib\gimp\{#DIR_VER}\extensions"; Excludes: "*.debug"; Components: gimp{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete +Source: "{#GIMP_DIR}\{#DIR}\lib\girepository-1.0\*.*"; DestDir: "{app}\lib\girepository-1.0"; Components: gimp{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete + +Source: "{#DEPS_DIR}\{#DDIR}\bin\*.dll"; DestDir: "{app}\bin"; Excludes: "libgimp*.dll,libgs*.dll,lua*.dll,libpython*.dll"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete +Source: "{#DEPS_DIR}\{#DDIR}\bin\*.exe"; DestDir: "{app}\bin"; Excludes: "gimp*.exe,lua*.exe,python*.exe"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +Source: "{#DEPS_DIR}\{#DDIR}\lib\*"; DestDir: "{app}\lib"; Excludes: "*.debug,\gimp\*,\lua\*,\python3.11\*"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete + +;Optional arch-specific components (complete install) +#ifdef DEBUG_SYMBOLS +Source: "{#GIMP_DIR}\{#DIR}\*.debug"; DestDir: "{app}"; Components: gimp{#COMPONENT} and debug; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +Source: "{#DEPS_DIR}\{#DDIR}\bin\.debug\*.dll.debug"; DestDir: "{app}\bin\.debug"; Components: deps{#COMPONENT} and debug; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete skipifsourcedoesntexist +Source: "{#GIMP_DIR}\{#DIR}\lib\gimp\{#DIR_VER}\extensions\*.debug"; DestDir: "{app}\lib\gimp\{#DIR_VER}\extensions"; Components: gimp{#COMPONENT} and debug; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete +Source: "{#DEPS_DIR}\{#DDIR}\lib\*.debug"; DestDir: "{app}\lib"; Components: deps{#COMPONENT} and debug; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete skipifsourcedoesntexist +#endif + +Source: "{#DEPS_DIR}\{#DDIR}\bin\libgs*.dll"; DestDir: "{app}\bin"; Components: gs and deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete +Source: "{#GIMP_DIR}\{#DIR}\lib\gimp\{#DIR_VER}\plug-ins\file-ps\file-ps.exe"; DestDir: "{app}\lib\gimp\{#DIR_VER}\plug-ins\file-ps"; Components: gs and gimp{#COMPONENT}; Flags: restartreplace ignoreversion uninsrestartdelete + +#ifdef LUA +Source: "{#DEPS_DIR}\{#DDIR}\bin\lua*.dll"; DestDir: "{app}\bin"; Components: lua and gimp{#COMPONENT}; Flags: restartreplace uninsrestartdelete ignoreversion +Source: "{#DEPS_DIR}\{#DDIR}\bin\lua*.exe"; DestDir: "{app}\bin"; Components: lua and gimp{#COMPONENT}; Flags: restartreplace uninsrestartdelete ignoreversion +Source: "{#DEPS_DIR}\{#DDIR}\lib\lua\*"; DestDir: "{app}\lib\lua"; Excludes: "*.debug"; Components: lua and gimp{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete +#endif + +#ifdef PYTHON +Source: "{#DEPS_DIR}\{#DDIR}\bin\libpython*.dll"; DestDir: "{app}\bin"; Components: py and gimp{#COMPONENT}; Flags: restartreplace uninsrestartdelete ignoreversion +Source: "{#DEPS_DIR}\{#DDIR}\bin\python*.exe"; DestDir: "{app}\bin"; Components: py and gimp{#COMPONENT}; Flags: restartreplace uninsrestartdelete ignoreversion +Source: "{#DEPS_DIR}\{#DDIR}\lib\python3.11\*"; DestDir: "{app}\lib\python3.11"; Excludes: "*.debug"; Components: py and gimp{#COMPONENT}; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +#endif diff --git a/build/windows/installer/gimp3264.iss b/build/windows/installer/base_gimp3264.iss old mode 100755 new mode 100644 similarity index 93% rename from build/windows/installer/gimp3264.iss rename to build/windows/installer/base_gimp3264.iss index 73993b40e8..a1f1e4c59e --- a/build/windows/installer/gimp3264.iss +++ b/build/windows/installer/base_gimp3264.iss @@ -1,1859 +1,1862 @@ -;.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,., -; ; -;Copyright (c) 2002-2010 Jernej Simončič ; -; ; -;This software is provided 'as-is', without any express or implied ; -;warranty. In no event will the authors be held liable for any damages ; -;arising from the use of this software. ; -; ; -;Permission is granted to anyone to use this software for any purpose, ; -;including commercial applications, and to alter it and redistribute it ; -;freely, subject to the following restrictions: ; -; ; -; 1. The origin of this software must not be misrepresented; you must ; -; not claim that you wrote the original software. If you use this ; -; software in a product, an acknowledgment in the product ; -; documentation would be appreciated but is not required. ; -; ; -; 2. Altered source versions must be plainly marked as such, and must ; -; not be misrepresented as being the original software. ; -; ; -; 3. This notice may not be removed or altered from any source ; -; distribution. ; -;.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.; -; -;Install script for GIMP and GTK+ -;requires Inno Setup 6 -; -;See directories.isi -; -;Changelog: -; -;2012-05-05 -;- check for SSE support -;- remove obsolete 2.6 plugins when installing over 2.6.12 combined installer -; -;2011-12-18 -;- display a picture on the first install screen -;- add a development version warning back -;- clean gegl's DLLs on install as some files have changed names -; -;2011-08-30 -;- only uninstall previous GIMP version when installing over existing installation -; TODO: offer the option to uninstall 32bit version when installing on x64 system -;- install 32bit plugins to same directory as 64bit plugins on x64 installs to -; avoid problems when upgrading -; -;2010-07-08 -;- clean up entire Python subdirectory (since the .pyc files are generated when -; scripts are run) -;- use crHand instead of crHandPoint for the billboard URL -; -;2010-07-02 -;- add libraries for compatibility with old 32-bit plug-ins as a component -;- remove a few unused RTF ready-memo related things -;- uninst.inf is now processed as the first step of uninstall, as otherwise the -; uninstaller could leave behind empty directories -; -;2010-06-29 -;- fix SuppressibleMsgBox calls to use proper button ID for default button -;- simplify the wizard - skip Welcome page, and make the Next button from -; InfoBefore/License page invoke install immediately (custom install is still -; possible by clicking the Customize button) -; -;2010-05-15 -;- rewrote script mostly from scratch -;- combine 32 and 64bit GIMP versions to a single installer -; - install enough 32bit support files even with 64bit version to allow running 32bit -; plug-ins on 64bit version (used by Python scriptin support [as there's no 64-bit -; PyGTK+ on Windows available yet] and TWAIN plug-in, which only works in 32-bit -; version) -;- Python with PyGTK is included in the installer now -;- install GIMP to new directory by default ({pf}\GIMP 2 instead of {pf}\GIMP-2.0) -;- uninstall previous GIMP versions as the first step of install (both 32 and 64-bit) -; - require reboot if installing to directory from which GIMP was just uninstalled, -; and this directory wasn't removed by the uninstaller; the installer will continue -; automatically after reboot -;- fixed a long standing bug where "Open with GIMP" menu entries would be left after -; uninstalling -; -#pragma option -e+ - -#ifndef VERSION - #error VERSION must be defined -#endif -#ifndef GIMP_DIR - #error GIMP_DIR must be defined -#endif -#ifndef DIR32 - #error DIR32 must be defined -#endif -#ifndef DIR64 - #error DIR64 must be defined -#endif -#ifndef DEPS_DIR - #error DEPS_DIR must be defined -#endif -#ifndef DDIR32 - #error DDIR32 must be defined -#endif -#ifndef DDIR64 - #error DDIR64 must be defined -#endif - -; Optional: PYTHON, LUA, DEBUG_SYMBOLS, NOCOMPRESSION, NOFILES, DEVEL - -#define X86 1 -#define X64 2 -#define ARM64 3 - -#include "directories.isi" -#include "version.isi" - -[Setup] -AppName=GIMP -#if Defined(DEVEL) && DEVEL != "" -AppID=GIMP-{#MAJOR}.{#MINOR} -#else -AppID=GIMP-{#MAJOR} -#endif -VersionInfoVersion={#VERSION} -#if !defined(REVISION) -AppVerName=GIMP {#VERSION} -#else -AppVerName=GIMP {#VERSION}-{#REVISION} -#endif -AppPublisherURL=https://www.gimp.org/ -AppSupportURL=https://www.gimp.org/docs/ -AppUpdatesURL=https://www.gimp.org/ -AppPublisher=The GIMP Team -AppVersion={#VERSION} -DisableProgramGroupPage=yes -DisableWelcomePage=no -DisableDirPage=auto -AlwaysShowDirOnReadyPage=yes -ChangesEnvironment=yes - -#if Defined(DEVEL) && DEVEL != "" -DefaultDirName={autopf}\GIMP {#MAJOR}.{#MINOR} -LZMANumBlockThreads=4 -LZMABlockSize=76800 -#else -DefaultDirName={autopf}\GIMP {#MAJOR} -#endif - -;AllowNoIcons=true -FlatComponentsList=yes -InfoBeforeFile=gpl+python.rtf -ChangesAssociations=true - -WizardImageFile=windows-installer-intro-big.bmp -WizardImageStretch=yes -WizardSmallImageFile=wilber.bmp - -UninstallDisplayIcon={app}\bin\gimp-{#MAJOR}.{#MINOR}.exe -UninstallFilesDir={app}\uninst - -MinVersion=6.1 -ArchitecturesInstallIn64BitMode=x64 arm64 - -#ifdef NOCOMPRESSION -;UseSetupLdr=no -OutputDir=_Output\unc -Compression=none -;InternalCompressLevel=0 -DiskSpanning=yes -DiskSliceSize=max -#else -OutputDir=_Output -Compression=lzma2/ultra64 -InternalCompressLevel=ultra -SolidCompression=yes -LZMAUseSeparateProcess=yes -LZMANumFastBytes=273 -; Increasing dictionary size may improve compression ratio at the -; expense of memory requirement. We run into "Out of memory" error in -; the CI. -;LZMADictionarySize=524288 - -;SignTool=Default -;SignedUninstaller=yes -;SignedUninstallerDir=_Uninst -#endif //NOCOMPRESSION - -#if !defined(REVISION) -OutputBaseFileName=gimp-{#VERSION}-setup -OutputManifestFile=gimp-{#VERSION}-setup.txt -#else -OutputBaseFileName=gimp-{#VERSION}-{#REVISION}-setup -OutputManifestFile=gimp-{#VERSION}-{#REVISION}-setup.txt -#endif - -PrivilegesRequiredOverridesAllowed=dialog - -[Languages] -Name: "en"; MessagesFile: "compiler:Default.isl,lang\en.setup.isl" -Name: "be"; MessagesFile: "compiler:Languages\Unofficial\Belarusian.isl,lang\be.setup.isl" -Name: "bg"; MessagesFile: "compiler:Languages\Bulgarian.isl,lang\bg.setup.isl" -Name: "ca"; MessagesFile: "compiler:Languages\Catalan.isl,lang\ca.setup.isl" -Name: "cs"; MessagesFile: "compiler:Languages\Czech.isl,lang\cs.setup.isl" -Name: "da"; MessagesFile: "compiler:Languages\Danish.isl,lang\da.setup.isl" -Name: "de"; MessagesFile: "compiler:Languages\German.isl,lang\de.setup.isl" -Name: "el"; MessagesFile: "compiler:Languages\Unofficial\Greek.isl,lang\el.setup.isl" -Name: "en_GB"; MessagesFile: "compiler:Languages\Unofficial\EnglishBritish.isl,lang\en_GB.setup.isl" -Name: "eo"; MessagesFile: "compiler:Languages\Unofficial\Esperanto.isl,lang\eo.setup.isl" -Name: "es"; MessagesFile: "compiler:Languages\Spanish.isl,lang\es.setup.isl" -Name: "eu"; MessagesFile: "compiler:Languages\Unofficial\Basque.isl,lang\eu.setup.isl" -Name: "fi"; MessagesFile: "compiler:Languages\Finnish.isl,lang\fi.setup.isl" -Name: "fr"; MessagesFile: "compiler:Languages\French.isl,lang\fr.setup.isl" -Name: "gl"; MessagesFile: "compiler:Languages\Unofficial\Galician.isl,lang\gl.setup.isl" -Name: "he"; MessagesFile: "compiler:Languages\Hebrew.isl,lang\he.setup.isl" -Name: "hu"; MessagesFile: "compiler:Languages\Hungarian.isl,lang\hu.setup.isl" -;Name: "hr"; MessagesFile: "compiler:Languages\Unofficial\Croatian.isl,lang\hr.setup.isl" -Name: "id"; MessagesFile: "compiler:Languages\Unofficial\Indonesian.isl,lang\id.setup.isl" -Name: "is"; MessagesFile: "compiler:Languages\Icelandic.isl,lang\is.setup.isl" -Name: "it"; MessagesFile: "compiler:Languages\Italian.isl,lang\it.setup.isl" -Name: "ja"; MessagesFile: "compiler:Languages\Japanese.isl,lang\ja.setup.isl" -Name: "ka"; MessagesFile: "compiler:Languages\Unofficial\Georgian.isl,lang\ka.setup.isl" -Name: "kab"; MessagesFile: "compiler:Default.isl,lang\kab.isl,lang\kab.setup.isl" -Name: "ko"; MessagesFile: "compiler:Languages\Korean.isl,lang\ko.setup.isl" -Name: "lt"; MessagesFile: "compiler:Languages\Unofficial\Lithuanian.isl,lang\lt.setup.isl" -Name: "lv"; MessagesFile: "compiler:Languages\Unofficial\Latvian.isl,lang\lv.setup.isl" -Name: "mr"; MessagesFile: "compiler:Languages\Unofficial\Marathi.islu,lang\mr.setup.isl" -Name: "ms"; MessagesFile: "compiler:Languages\Unofficial\Malaysian.isl,lang\ms.setup.isl" -Name: "nl"; MessagesFile: "compiler:Languages\Dutch.isl,lang\nl.setup.isl" -Name: "pl"; MessagesFile: "compiler:Languages\Polish.isl,lang\pl.setup.isl" -Name: "pt"; MessagesFile: "compiler:Languages\Portuguese.isl,lang\pt.setup.isl" -Name: "pt_BR"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl,lang\pt_BR.setup.isl" -Name: "ro"; MessagesFile: "compiler:Languages\Unofficial\Romanian.isl,lang\ro.setup.isl" -Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl,lang\ru.setup.isl" -Name: "sk"; MessagesFile: "compiler:Languages\Slovak.isl,lang\sk.setup.isl" -Name: "sl"; MessagesFile: "compiler:Languages\Slovenian.isl,lang\sl.setup.isl" -Name: "sv"; MessagesFile: "compiler:Languages\Unofficial\Swedish.isl,lang\sv.setup.isl" -Name: "tr"; MessagesFile: "compiler:Languages\Turkish.isl,lang\tr.setup.isl" -Name: "uk"; MessagesFile: "compiler:Languages\Ukrainian.isl,lang\uk.setup.isl" -Name: "vi"; MessagesFile: "compiler:Languages\Unofficial\Vietnamese.isl,lang\vi.setup.isl" -Name: "zh_CN"; MessagesFile: "compiler:Languages\Unofficial\ChineseSimplified.isl,lang\zh_CN.setup.isl" -Name: "zh_TW"; MessagesFile: "compiler:Languages\Unofficial\ChineseTraditional.isl,lang\zh_TW.setup.isl" -;Name: "ro"; MessagesFile: "Romanian.islu,ro.setup.islu" - -[Types] -;Name: normal; Description: "{cm:TypeTypical}" -Name: full; Description: "{cm:TypeFull}" -Name: compact; Description: "{cm:TypeCompact}" -Name: custom; Description: "{cm:TypeCustom}"; Flags: iscustom - -[Components] -Name: gimp32; Description: "{cm:ComponentsGimp,{#VERSION}}"; Types: full compact custom; Flags: fixed; Check: Check3264('32') -Name: gimp64; Description: "{cm:ComponentsGimp,{#VERSION}}"; Types: full compact custom; Flags: fixed; Check: Check3264('x64') -Name: gimpARM64; Description: "{cm:ComponentsGimp,{#VERSION}}"; Types: full compact custom; Flags: fixed; Check: Check3264('arm64') - -Name: deps32; Description: "{cm:ComponentsDeps,{#GTK_VERSION}}"; Types: full compact custom; Flags: checkablealone fixed; Check: Check3264('32') -Name: deps64; Description: "{cm:ComponentsDeps,{#GTK_VERSION}}"; Types: full compact custom; Flags: checkablealone fixed; Check: Check3264('x64') -Name: depsARM64; Description: "{cm:ComponentsDeps,{#GTK_VERSION}}"; Types: full compact custom; Flags: checkablealone fixed; Check: Check3264('arm64') - -#ifdef DEBUG_SYMBOLS -Name: debug; Description: "{cm:ComponentsDebug}"; Types: full custom; Flags: disablenouninstallwarning -#endif - -Name: gs; Description: "{cm:ComponentsGhostscript}"; Types: full custom - -Name: loc; Description: "{cm:ComponentsTranslations}"; Types: full custom - -Name: mypaint; Description: "{cm:ComponentsMyPaint}"; Types: full custom - -#ifdef PYTHON -Name: py; Description: "{cm:ComponentsPython}"; Types: full custom -#endif -#ifdef LUA -Name: lua; Description: "{cm:ComponentsLua}"; Types: full custom -#endif - -Name: gimp32on64; Description: "{cm:ComponentsGimp32}"; Types: full custom; Flags: checkablealone; Check: Check3264('64') - -[Tasks] -Name: desktopicon; Description: "{cm:AdditionalIconsDesktop}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked - -[Icons] -#define ICON_VERSION=MAJOR + "." + MINOR + "." + MICRO -Name: "{autoprograms}\GIMP {#ICON_VERSION}"; Filename: "{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe"; WorkingDir: "%USERPROFILE%"; Comment: "GIMP {#VERSION}" -Name: "{autodesktop}\GIMP {#ICON_VERSION}"; Filename: "{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe"; WorkingDir: "%USERPROFILE%"; Comment: "GIMP {#VERSION}"; Tasks: desktopicon - -[Files] -;setup files -Source: "windows-installer-intro-small.bmp"; Flags: dontcopy -#ifndef DEVEL -Source: "installsplash.bmp"; Flags: dontcopy -Source: "installsplash_small.bmp"; Flags: dontcopy -#else -Source: "installsplash-devel.bmp"; Destname: "installsplash.bmp"; Flags: dontcopy -Source: "installsplash_small-devel.bmp"; Destname: "installsplash_small.bmp"; Flags: dontcopy -#endif - -#ifndef NOFILES -;files common to both 32 and 64-bit versions -Source: "{#GIMP_DIR32}\etc\*"; DestDir: "{app}\etc"; Components: gimp32 or gimp64 or gimpARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -Source: "{#GIMP_DIR32}\lib\gimp\{#DIR_VER}\environ\*"; DestDir: "{app}\lib\gimp\{#DIR_VER}\environ"; Components: gimp32 or gimp64 or gimpARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -Source: "{#GIMP_DIR32}\lib\gimp\{#DIR_VER}\interpreters\*"; DestDir: "{app}\lib\gimp\{#DIR_VER}\interpreters"; Components: gimp32 or gimp64 or gimpARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -Source: "{#GIMP_DIR32}\share\gimp\*"; DestDir: "{app}\share\gimp"; Components: gimp32 or gimp64 or gimpARM64; Flags: recursesubdirs createallsubdirs restartreplace uninsrestartdelete ignoreversion -Source: "{#GIMP_DIR32}\share\metainfo\*"; DestDir: "{app}\share\metainfo"; Components: gimp32 or gimp64 or gimpARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion - -Source: "{#DEPS_DIR32}\share\glib-2.0\schemas\*"; DestDir: "{app}\share\glib-2.0\schemas"; Components: deps32 or deps64 or depsARM64; Flags: recursesubdirs createallsubdirs restartreplace uninsrestartdelete ignoreversion -;Source: "{#DEPS_DIR32}\share\enchant\*"; DestDir: "{app}\share\enchant"; Components: deps32 or deps64 or depsARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -Source: "{#DEPS_DIR32}\share\libwmf\*"; DestDir: "{app}\share\libwmf"; Components: deps32 or deps64 or depsARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -Source: "{#DEPS_DIR32}\share\icons\*"; DestDir: "{app}\share\icons"; Components: deps32 or deps64 or depsARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -Source: "{#DEPS_DIR32}\share\xml\*"; DestDir: "{app}\share\xml"; Components: deps32 or deps64 or depsARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion - -Source: "{#DEPS_DIR32}\share\poppler\*.*"; DestDir: "{app}\share\poppler"; Components: deps32 or deps64 or depsARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -Source: "{#DEPS_DIR32}\share\libthai\*"; DestDir: "{app}\share\libthai"; Components: deps32 or deps64 or depsARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion - -Source: "{#DEPS_DIR32}\share\locale\*"; DestDir: "{app}\share\locale"; Components: loc; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -Source: "{#GIMP_DIR32}\share\locale\*"; DestDir: "{app}\share\locale"; Components: loc; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion - -;configure gimp with --enable-bundled-mypaint-brushes for the correct path to -;be picked by gimp -Source: "{#DEPS_DIR32}\share\mypaint-data\*"; DestDir: "{app}\share\mypaint-data"; Components: mypaint; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion - -Source: "{#DEPS_DIR32}\etc\fonts\*"; DestDir: "{app}\etc\fonts"; Components: deps32 or deps64 or depsARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -Source: "{#DEPS_DIR32}\etc\gtk-3.0\*"; DestDir: "{app}\etc\gtk-3.0"; Components: deps32 or deps64 or depsARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion - -Source: "{#DEPS_DIR32}\share\ghostscript\*"; Excludes: "*\doc\*"; DestDir: "{app}\share\ghostscript"; Components: gs and (gimp32 or gimp64 or gimpARM64); Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion - -#ifdef PYTHON -;*.py files are the same on 32 and 64-bit -Source: "{#GIMP_DIR32}\lib\gimp\{#DIR_VER}\plug-ins\*.py"; DestDir: "{app}\lib\gimp\{#DIR_VER}\plug-ins"; Components: py; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -#endif - -;x86_64 -#define PLATFORM X64 -#include "files.isi" - -;AArch64 -#define PLATFORM ARM64 -#include "files.isi" - -;i686 -#define PLATFORM X86 -#include "files.isi" -;special case, since 64bit version doesn't work, and is excluded in files.isi -Source: "{#GIMP_DIR32}\lib\gimp\{#DIR_VER}\plug-ins\twain.exe"; DestDir: "{app}\lib\gimp\{#DIR_VER}\plug-ins"; Components: gimp32; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion - -;32-on-64bit -#include "32on64.isi" -;prefer 32bit twain plugin over 64bit because 64bit twain drivers are rare -Source: "{#GIMP_DIR32}\lib\gimp\{#DIR_VER}\plug-ins\twain\twain.exe"; DestDir: "{app}\lib\gimp\{#DIR_VER}\plug-ins\twain"; Components: gimp32on64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -Source: "{#GIMP_DIR64}\lib\gimp\{#DIR_VER}\plug-ins\twain\twain.exe"; DestDir: "{app}\lib\gimp\{#DIR_VER}\plug-ins\twain"; Components: (not gimp32on64) and gimp64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -Source: "{#GIMP_DIRA64}\lib\gimp\{#DIR_VER}\plug-ins\twain\twain.exe"; DestDir: "{app}\lib\gimp\{#DIR_VER}\plug-ins\twain"; Components: (not gimp32on64) and gimpARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -;special case due to MS-Windows engine -Source: "{#DEPS_DIR32}\etc\gtk-3.0\*"; DestDir: "{app}\32\etc\gtk-3.0"; Components: gimp32on64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion - -;upgrade zlib1.dll in System32 if it's present there to avoid breaking plugins -;sharedfile flag will ensure that the upgraded file is left behind on uninstall to avoid breaking other programs that use the file -Source: "{#DEPS_DIR32}\bin\zlib1.dll"; DestDir: "{sys}"; Components: gimp32 or gimp64 or gimpARM64; Flags: restartreplace sharedfile 32bit uninsrestartdelete comparetimestamp; Check: BadSysDLL('zlib1.dll',32) -Source: "{#DEPS_DIR64}\bin\zlib1.dll"; DestDir: "{sys}"; Components: gimp64; Flags: restartreplace sharedfile uninsrestartdelete comparetimestamp; Check: BadSysDLL('zlib1.dll',64) - -;overridden configuration files -#include "configoverride.isi" - -#endif //NOFILES - -[InstallDelete] -Type: files; Name: "{app}\bin\gimp-?.?.exe" -Type: files; Name: "{app}\bin\gimp-?.??.exe" -Type: files; Name: "{app}\bin\gimp-console-?.?.exe" -Type: files; Name: "{app}\bin\gimp-console-?.??.exe" -Type: files; Name: "{app}\lib\gegl-0.1\*.dll" -;obsolete plugins from gimp 2.6 -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pdf.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gee.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gee-zoom.exe" -;old Python -Type: filesandordirs; Name: "{app}\Python\*" -Type: dirifempty; Name: "{app}\Python" -;remove incompatible version shipped with 2.8 -Type: files; Name: "{app}\bin\zlib1.dll" -Type: files; Name: "{app}\32\bin\zlib1.dll" -;old ghostscript -Type: filesandordirs; Name: "{app}\share\ghostscript\*" -;obsolete plugins from gimp 2.8 -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\pyconsole.py" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\python-console.py" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\metadata.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-psd-save.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-psd-load.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\alien-map.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\antialias.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\apply-canvas.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\blur-gauss.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\blur-gauss-selective.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\blur-motion.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\bump-map.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\channel-mixer.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\color-exchange.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\color-rotate.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\color-to-alpha.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\contrast-stretch.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\contrast-stretch-hsv.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\convolution-matrix.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\crop-auto.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\cubism.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\deinterlace.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\diffraction.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\displace.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\edge.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\edge-laplace.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\edge-sobel.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\engrave.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-raw.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-tiff-load.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-tiff-save.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-uri.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\illusion.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\iwarp.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\lcms.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\lens-apply.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\lens-distortion.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\lens-flare.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\maze.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\mosaic.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\noise-hsv.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\noise-randomize.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\noise-rgb.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\noise-solid.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\noise-spread.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\nova.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\pixelize.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\plasma.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\polar-coords.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\red-eye-removal.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\ripple.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\rotate.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\semi-flatten.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\shift.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\sinus.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\threshold-alpha.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\tile-glass.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\tile-paper.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\tile-seamless.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\value-invert.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\value-propagate.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\video.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\waves.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\whirl-pinch.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\win-snap.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\wind.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\text-brush.py" -;<2.10.6 plug-ins -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\align-layers.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\animation-optimize.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\animation-play.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\blinds.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\blur.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\border-average.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\busy-dialog.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\cartoon.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\checkerboard.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\cml-explorer.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\color-cube-analyze.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\color-enhance.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\colorify.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\colormap-remap.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\compose.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\contrast-normalize.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\contrast-retinex.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\crop-zealous.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\curve-bend.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\decompose.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\depth-merge.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\despeckle.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\destripe.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\edge-dog.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\edge-neon.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\emboss.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-bmp.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-cel.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-compressor.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-csource.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-darktable.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-desktop-link.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-dicom.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-exr.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-faxg3.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-fits.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-fli.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-gbr.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-gegl.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-gif-load.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-gif-save.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-gih.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-glob.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-header.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-heif.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-html-table.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-ico.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-jp2-load.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-jpeg.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-mng.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pat.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pcx.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pdf-load.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pdf-save.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pix.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-png.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pnm.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-ps.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-psd.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-psp.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-raw-data.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-raw-placeholder.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-rawtherapee.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-sgi.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-sunras.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-svg.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-tga.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-tiff.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-webp.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-wmf.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-xbm.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-xpm.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-xwd.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\film.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\filter-pack.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\flame.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\fractal-explorer.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\fractal-trace.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gfig.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gimpressionist.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\goat-exercise.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gradient-flare.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gradient-map.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\grid.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\guillotine.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\help-browser.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\help.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\hot.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\ifs-compose.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\imagemap.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\jigsaw.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\lighting.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\map-object.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\max-rgb.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\metadata-editor.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\metadata-viewer.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\newsprint.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\nl-filter.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\oilify.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\pagecurl.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\photocopy.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\plugin-browser.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\print.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\procedure-browser.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\qbist.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\sample-colorize.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\screenshot.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\script-fu.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\selection-to-path.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\sharpen.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\smooth-palette.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\softglow.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\sparkle.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\sphere-designer.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\tile-small.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\tile.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\twain.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\unit-editor.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\unsharp-mask.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\van-gogh-lic.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\warp.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\wavelet-decompose.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\web-browser.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\web-page.exe" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\colorxhtml.py" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-openraster.py" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\foggify.py" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gradients-save-as-css.py" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\histogram-export.py" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\palette-offset.py" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\palette-sort.py" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\palette-to-gradient.py" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\py-slice.py" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\python-eval.py" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\python-console\pyconsole.py" -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\python-console\python-console.py" -;<2.99.14 plug-ins and modules -Type: files; Name: "{app}\lib\gimp\2.99\plug-ins\py-slice\py-slice.py" -Type: files; Name: "{app}\lib\gimp\2.99\plug-ins\benchmark-foreground-extract\benchmark-foreground-extract.py" -;Some typo in meson which we used for GIMP 2.99.12 installer. -Type: files; Name: "{app}\lib\gimp\2.99\modules\libcontroller-dx-input.dll" -;DLLs in plug-ins directory (see bug 796225) -Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\*.dll" -;gegl 0.2 -Type: filesandordirs; Name: "{app}\lib\gegl-0.2" -;old icons -#ifndef DEVEL -Type: files; Name: "{autoprograms}\GIMP 2.lnk" -Type: files; Name: "{autodesktop}\GIMP 2.lnk" -#endif -;get previous GIMP icon name from uninstall name in Registry -#if Defined(DEVEL) && DEVEL != "" -Type: files; Name: "{autoprograms}\GIMP {reg:HKA\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}.{#MINOR}_is1,DisplayVersion|GIMP {#MAJOR}.{#MINOR}}.lnk"; Check: CheckRegValueExists('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}.{#MINOR}_is1','DisplayVersion') -Type: files; Name: "{autodesktop}\GIMP {reg:HKA\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}.{#MINOR}_is1,DisplayVersion|GIMP {#MAJOR}.{#MINOR}}.lnk"; Check: CheckRegValueExists('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}.{#MINOR}_is1','DisplayVersion') -#else -Type: files; Name: "{autoprograms}\GIMP {reg:HKA\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}_is1,DisplayVersion|GIMP {#MAJOR}}.lnk"; Check: CheckRegValueExists('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}_is1','DisplayVersion') -Type: files; Name: "{autodesktop}\GIMP {reg:HKA\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}_is1,DisplayVersion|GIMP {#MAJOR}}.lnk"; Check: CheckRegValueExists('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}_is1','DisplayVersion') -#endif -;32-bit Python -Type: filesandordirs; Name: "{app}\32\lib\gimp\2.0\python" -Type: files; Name: "{app}\32\bin\python2w.exe" -Type: files; Name: "{app}\32\bin\python2.exe" -Type: files; Name: "{app}\32\bin\libpython2.7.dll" -Type: filesandordirs; Name: "{app}\32\lib\python2.7" -;remove old babl and gegl plugins -Type: filesandordirs; Name: "{app}\lib\babl-0.1" -Type: filesandordirs; Name: "{app}\lib\gegl-0.4" - -[Registry] -;remove LIBTHAI_DICTDIR variable set by original 2.10.8 installer -Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: none; ValueName: "LIBTHAI_DICTDIR"; Flags: deletevalue uninsdeletevalue noerror -#include "associations.isi" - -[UninstallDelete] -Type: files; Name: "{app}\uninst\uninst.inf" -Type: files; Name: "{app}\lib\gimp\{#DIR_VER}\interpreters\lua.interp" -Type: files; Name: "{app}\lib\gimp\{#DIR_VER}\environ\pygimp.env" -;need to clean out all the generated .pyc files -Type: filesandordirs; Name: "{app}\Python\*" - -[Code] - -function WideCharToMultiByte(CodePage: Cardinal; dwFlags: DWORD; lpWideCharStr: String; cchWideCharStr: Integer; - lpMultiByteStr: PAnsiChar; cbMultiByte: Integer; lpDefaultChar: Integer; - lpUsedDefaultChar: Integer): Integer; external 'WideCharToMultiByte@Kernel32 stdcall'; - -function MultiByteToWideChar(CodePage: Cardinal; dwFlags: DWORD; lpMultiByteStr: PAnsiChar; cbMultiByte: Integer; - lpWideCharStr: String; cchWideChar: Integer): Integer; - external 'MultiByteToWideChar@Kernel32 stdcall'; - -function GetLastError(): DWORD; external 'GetLastError@Kernel32 stdcall'; - -function GetSysColor(nIndex: Integer): DWORD; external 'GetSysColor@user32.dll stdcall'; - -function IsProcessorFeaturePresent(ProcessorFeature: DWORD): LongBool; external 'IsProcessorFeaturePresent@kernel32 stdcall'; - -//functions needed to get BPP -function GetDC(hWnd: Integer): Integer; external 'GetDC@User32 stdcall'; -function ReleaseDC(hWnd, hDC: Integer): Integer; external 'ReleaseDC@User32 stdcall'; -function GetDeviceCaps(hDC, nIndex: Integer): Integer; external 'GetDeviceCaps@GDI32 stdcall'; - - -procedure ComponentsListOnClick(pSender: TObject); forward; -procedure SaveToUninstInf(const pText: AnsiString); forward; -procedure CreateRunOnceEntry; forward; -function RestartSetupAfterReboot(): Boolean; forward; -procedure AssociationsCleanUp(); forward; - -const - CP_ACP = 0; - CP_UTF8 = 65001; - - COLOR_HOTLIGHT = 26; - - PF_XMMI_INSTRUCTIONS_AVAILABLE = 6; - - BITSPIXEL = 12; - PLANES = 14; - - GIMP_URL = 'https://www.gimp.org/'; - - RTFHeader = '{\rtf1\deff0{\fonttbl{\f0\fswiss\fprq2\fcharset0 Tahoma;}{\f1\fnil\fcharset2 Symbol;}}\viewkind4\uc1\fs16'; - //RTFBullet = '{\pntext\f1\''B7\tab}'; - RTFPara = '\par '; - - RunOnceName = 'Resume GIMP {#VERSION} install'; - - CONFIG_OVERRIDE_PARAM = 'configoverride'; - - UNINSTALL_MAX_WAIT_TIME = 10000; - UNINSTALL_CHECK_TIME = 250; - -type - TRemoveOldGIMPResult = (rogContinue, rogRestartRequired, rogUninstallFailed, rogCantUninstall); - -var - lblComponentDescription: TNewStaticText; - - ReadyMemoRichText: String; - - WelcomeBitmapBottom: TBitmapImage; - - //pgSimple: TWizardPage; - btnInstall, btnCustomize: TNewButton; - - InstallMode: (imNone, imSimple, imCustom, imRebootContinue); - - ConfigOverride: (coUndefined, coOverride, coDontOverride); - - Force32bitInstall: Boolean; - - asUninstInf: TArrayOfString; //uninst.inf contents (loaded at start of uninstall, executed at the end) - - -#include "MessageWithURL.isi" - -function Check3264(const pWhich: String): Boolean; -begin - if pWhich = '64' then //x64 or arm64 - Result := Is64BitInstallMode() and (not Force32bitInstall) - else if pWhich = '32' then - Result := (not Is64BitInstallMode()) or Force32bitInstall - else if pWhich = 'x64' then - Result := Is64BitInstallMode() and IsX64 and (not Force32bitInstall) - else if pWhich = 'arm64' then - Result := Is64BitInstallMode() and IsARM64 and (not Force32bitInstall) - else - RaiseException('Unknown check'); -end; - - -#include "utils.isi" - - -//some programs improperly install libraries to the System32 directory, which then causes problems with plugins -//this function checks if such file exists in System32, and lets setup update the file when it exists -function BadSysDLL(const pFile: String; const pPlatform: Integer): Boolean; -var OldRedir: Boolean; -begin - Result := False; - - if pPlatform = 64 then - begin - if Is64BitInstallMode() then //only check when installing in 64bit mode - begin - OldRedir := EnableFsRedirection(False); - DebugMsg('BadSysDLL','64: ' + ExpandConstant('{sys}\' + pFile)); - Result := FileExists(ExpandConstant('{sys}\' + pFile)); - EnableFsRedirection(OldRedir); - end; - end - else if pPlatform = 32 then - begin - if Is64BitInstallMode() then //check 32bit system directory on x64 windows - begin - DebugMsg('BadSysDLL','32on64: ' + ExpandConstant('{syswow64}\' + pFile)); - Result := FileExists(ExpandConstant('{syswow64}\' + pFile)); - end - else - begin - DebugMsg('BadSysDLL','32: ' + ExpandConstant('{sys}\' + pFile)); - Result := FileExists(ExpandConstant('{sys}\' + pFile)); - end; - end - else - begin - RaiseException('Unsupported platform'); - end; - - DebugMsg('BadSysDLL','Result: ' + BoolToStr(Result)); -end; - - -function CheckRegValueExists(const SubKeyName, ValueName: String): Boolean; -begin - Result := RegValueExists(HKEY_AUTO, SubKeyName, ValueName); - DebugMsg('CheckRegValueExists',SubKeyName + ', ' + ValueName + ': ' + BoolToStr(Result)); -end; - - -function DoConfigOverride: Boolean; -var i: Integer; -begin - - if ConfigOverride = coUndefined then - begin - - DebugMsg('DoConfigOverride', 'First call'); - - Result := False; - ConfigOverride := coDontOverride; - - for i := 0 to ParamCount() do //use ParamCount/ParamStr to allow specifying /configoverride without any parameters - if LowerCase(Copy(ParamStr(i),1,15)) = '/' + CONFIG_OVERRIDE_PARAM then - begin - Result := True; - ConfigOverride := coOverride; - break; - end; - - end - else if ConfigOverride = coOverride then - Result := True - else - Result := False; - - DebugMsg('DoConfigOverride', BoolToStr(Result)); -end; - -function GetExternalConfDir(Unused: String): String; -begin - if ExpandConstant('{param:' + CONFIG_OVERRIDE_PARAM + '|<>}') = '<>' then - Result := ExpandConstant('{src}\') - else - Result := ExpandConstant('{param:' + CONFIG_OVERRIDE_PARAM + '|<>}\'); - DebugMsg('GetExternalConfDir', Result); -end; - -function CheckExternalConf(const pFile: String): Boolean; -begin - - if not DoConfigOverride then //no config override - Result := False - else - begin - if FileExists(GetExternalConfDir('') + pFile) then //config file override only applies when that file exists - Result := True - else - Result := False; - end; - DebugMsg('CheckExternalConf', pFile + ': ' + BoolToStr(Result)); -end; - - -procedure PrepareInterp(); -var InterpFile,InterpContent,LuaBin: String; -begin -#ifdef PYTHON - if IsComponentSelected('py') then - begin - StatusLabel(CustomMessage('SettingUpPyGimp'),''); - - InterpFile := ExpandConstant('{app}\lib\gimp\{#DIR_VER}\interpreters\pygimp.interp'); - DebugMsg('PrepareInterp','Writing interpreter file for gimp-python: ' + InterpFile); - -#ifdef DEVEL - #define PYTHON="python.exe" -#else - #define PYTHON="pythonw.exe" -#endif - - InterpContent := 'python=' + ExpandConstant('{app}\bin\{#PYTHON}') + #10 + - 'python3=' + ExpandConstant('{app}\bin\{#PYTHON}') + #10 + - '/usr/bin/python=' + ExpandConstant('{app}\bin\{#PYTHON}') + #10 + - '/usr/bin/python3=' + ExpandConstant('{app}\bin\{#PYTHON}') + #10 + - ':Python:E::py::python:'#10; - - if not SaveStringToUTF8File(InterpFile,InterpContent,False) then - begin - DebugMsg('PrepareInterp','Problem writing the file. [' + InterpContent + ']'); - SuppressibleMsgBox(CustomMessage('ErrorUpdatingPython') + ' (2)',mbInformation,mb_ok,IDOK); - end; - - end; -#endif - -#ifdef LUA - if IsComponentSelected('lua') then - begin - InterpFile := ExpandConstant('{app}\lib\gimp\{#DIR_VER}\interpreters\lua.interp'); - DebugMsg('PrepareInterp','Writing interpreter file for lua: ' + InterpFile); - - if IsComponentSelected('gimpARM64') then - begin - LuaBin := 'lua5.1.exe' - end else - begin - LuaBin := 'luajit.exe' - end; - - InterpContent := 'lua=' + ExpandConstant('{app}\bin\') + LuaBin + #10 + - 'luajit=' + ExpandConstant('{app}\bin\') + LuaBin + #10 + - '/usr/bin/luajit=' + ExpandConstant('{app}\bin\') + LuaBin + #10 + - '/usr/bin/lua=' + ExpandConstant('{app}\bin\') + LuaBin + #10 + - ':Lua:E::lua::' + LuaBin + ':'#10; - - if not SaveStringToUTF8File(InterpFile,InterpContent,False) then - begin - DebugMsg('PrepareInterp','Problem writing the file. [' + InterpContent + ']'); - SuppressibleMsgBox(CustomMessage('ErrorUpdatingPython') + ' (2)',mbInformation,mb_ok,IDOK); - end; - - end; -#endif - -// not optional -// !!! use comma for binfmt delimiter and full Windows path in interpreter field of binfmt -begin - InterpFile := ExpandConstant('{app}\lib\gimp\{#DIR_VER}\interpreters\gimp-script-fu-interpreter.interp'); - DebugMsg('PrepareInterp','Writing interpreter file for gimp-script-fu-interpreter: ' + InterpFile); - - InterpContent := 'gimp-script-fu-interpreter=' + ExpandConstant('{app}\bin\gimp-script-fu-interpreter-3.0.exe') + #10 + - 'gimp-script-fu-interpreter-3.0=' + ExpandConstant('{app}\bin\gimp-script-fu-interpreter-3.0.exe') + #10 + - '/usr/bin/gimp-script-fu-interpreter=' + ExpandConstant('{app}\bin\gimp-script-fu-interpreter-3.0.exe') + #10 + - ',ScriptFu,E,,scm,,' + ExpandConstant('{app}\bin\gimp-script-fu-interpreter-3.0.exe') + ','#10; - - if not SaveStringToUTF8File(InterpFile,InterpContent,False) then - begin - DebugMsg('PrepareInterp','Problem writing the file. [' + InterpContent + ']'); - SuppressibleMsgBox(CustomMessage('ErrorUpdatingScriptFu') + ' (2)',mbInformation,mb_ok,IDOK); - end; -end; - -end; - - -procedure PrepareGimpEnvironment(); -var EnvFile,Env: String; -begin - - StatusLabel(CustomMessage('SettingUpEnvironment'),''); - - //set PATH to be used by plug-ins - EnvFile := ExpandConstant('{app}\lib\gimp\{#DIR_VER}\environ\default.env'); - DebugMsg('PrepareGimpEnvironment','Setting environment in ' + EnvFile); - - Env := #10'PATH=${gimp_installation_dir}\bin'; - - if IsComponentSelected('gimp32on64') then - begin - - Env := Env + ';${gimp_installation_dir}\32\bin' + #10; - - end else - begin - - Env := Env + #10; - - end; - - DebugMsg('PrepareGimpEnvironment','Appending ' + Env); - - if not SaveStringToUTF8File(EnvFile,Env,True) then - begin - DebugMsg('PrepareGimpEnvironment','Problem appending'); - SuppressibleMsgBox(FmtMessage(CustomMessage('ErrorChangingEnviron'),[EnvFile]),mbInformation,mb_ok,IDOK); - end; - - //workaround for high-DPI awareness of Python plug-ins - if IsComponentSelected('py') then - begin - EnvFile := ExpandConstant('{app}\lib\gimp\{#DIR_VER}\environ\pygimp.env'); - DebugMsg('PrepareGimpEnvironment','Setting environment in ' + EnvFile); - - Env := '__COMPAT_LAYER=HIGHDPIAWARE' + #10 - - if not SaveStringToUTF8File(EnvFile,Env,True) then - begin - DebugMsg('PrepareGimpEnvironment','Problem appending'); - SuppressibleMsgBox(FmtMessage(CustomMessage('ErrorChangingEnviron'),[EnvFile]),mbInformation,mb_ok,IDOK); - end; - end; - - // Disable check-update when run with specific option - if ExpandConstant('{param:disablecheckupdate|false}') = 'true' then - begin - EnvFile := ExpandConstant('{app}\share\gimp\{#DIR_VER}\gimp-release'); - DebugMsg('DisableCheckUpdate','Disabling check-update in ' + EnvFile); - - Env := 'check-update=false' - - if not SaveStringToUTF8File(EnvFile,Env,True) then - begin - DebugMsg('PrepareGimpEnvironment','Problem appending'); - SuppressibleMsgBox(FmtMessage(CustomMessage('ErrorChangingEnviron'),[EnvFile]),mbInformation,mb_ok,IDOK); - end; - end; -end; - - -procedure CleanUpCustomWelcome(); -begin - WizardForm.NextButton.Visible := True; - btnInstall.Visible := False; - btnCustomize.Visible := False; - - WizardForm.Bevel.Visible := True; - WelcomeBitmapBottom.Visible := False; -end; - - -procedure InstallOnClick(Sender: TObject); -begin - DebugMsg('Install mode','Simple'); - InstallMode := imSimple; - - CleanUpCustomWelcome(); - - WizardForm.NextButton.OnClick(TNewButton(Sender).Parent); -end; - - -procedure CustomizeOnClick(Sender: TObject); -begin - DebugMsg('Install mode','Custom'); - InstallMode := imCustom; - - CleanUpCustomWelcome(); - - WizardForm.NextButton.OnClick(TNewButton(Sender).Parent); -end; - - -function GetButtonWidth(const Texts: TArrayOfString; const Minimum: Integer): Integer; -var MeasureLabel: TNewStaticText; - i: Integer; -begin - MeasureLabel := TNewStaticText.Create(WizardForm); - with MeasureLabel do - begin - Parent := WizardForm; - Left := 0; - Top := 0; - AutoSize := True; - end; - - Result := Minimum; - - for i := 0 to GetArrayLength(Texts) - 1 do - begin - MeasureLabel.Caption := Texts[i]; - if (MeasureLabel.Width + ScaleX(16)) > Result then - Result := (MeasureLabel.Width + ScaleX(16)); - end; - - MeasureLabel.Free; -end; - - -procedure InitCustomPages(); -var i,ButtonWidth: Integer; - ButtonText: TArrayOfString; - MeasureLabel: TNewStaticText; - //lblInfo: TNewStaticText; -begin - DebugMsg('InitCustomPages','wpLicense'); - - btnInstall := TNewButton.Create(WizardForm); - with btnInstall do - begin - Parent := WizardForm; - Width := WizardForm.NextButton.Width; - Height := WizardForm.NextButton.Height; - Left := WizardForm.NextButton.Left; - Top := WizardForm.NextButton.Top; - Caption := CustomMessage('Install'); - Default := True; - Visible := False; - - OnClick := @InstallOnClick; - end; - - //used to measure text width - MeasureLabel := TNewStaticText.Create(WizardForm); - with MeasureLabel do - begin - Parent := WizardForm; - Left := 0; - Top := 0; - AutoSize := True; - Caption := CustomMessage('Customize'); - end; - - btnCustomize := TNewButton.Create(WizardForm); - with btnCustomize do - begin - Parent := WizardForm; - Width := WizardForm.NextButton.Width; - - if Width < (MeasureLabel.Width + ScaleX(8)) then - Width := MeasureLabel.Width + ScaleX(8); - - Height := WizardForm.NextButton.Height; - Left := WizardForm.ClientWidth - (WizardForm.CancelButton.Left + WizardForm.CancelButton.Width); - //Left := WizardForm.BackButton.Left; - Top := WizardForm.NextButton.Top; - Visible := False; - - Caption := CustomMessage('Customize'); - - OnClick := @CustomizeOnClick; - end; - - MeasureLabel.Free; - -end; - - -procedure SelectComponentsFaceLift(); -var pnlDescription: TPanel; - lblDescription: TNewStaticText; -begin - DebugMsg('SelectComponentsFaceLift',''); - - if WizardForm.ComponentsList.Width = WizardForm.SelectComponentsPage.Width then - WizardForm.ComponentsList.Width := Round(WizardForm.ComponentsList.Width * 0.6) - else - exit; - DebugMsg('SelectComponentsFaceLift','2'); - - WizardForm.ComponentsList.OnClick := @ComponentsListOnClick; - - lblDescription := TNewStaticText.Create(WizardForm.ComponentsList.Parent) - with lblDescription do - begin - Left := WizardForm.ComponentsList.Left + WizardForm.ComponentsList.Width + ScaleX(16); - Top := WizardForm.ComponentsList.Top; - AutoSize := True; - Caption := CustomMessage('ComponentsDescription'); - end; - - pnlDescription := TPanel.Create(WizardForm.ComponentsList.Parent); - with pnlDescription do - begin - Parent := WizardForm.ComponentsList.Parent; - Left := WizardForm.ComponentsList.Left + WizardForm.ComponentsList.Width + ScaleX(8); - Width := WizardForm.TypesCombo.Width - WizardForm.ComponentsList.Width - ScaleX(8); - BevelOuter := bvLowered; - BevelInner := bvRaised; - Top := WizardForm.ComponentsList.Top + Round(lblDescription.Height * 0.4); - Height := WizardForm.ComponentsList.Height - Round(lblDescription.Height * 0.4); - end; - - lblDescription.Parent := WizardForm.ComponentsList.Parent; //place lblDescription above pnlDescription - - lblComponentDescription := TNewStaticText.Create(pnlDescription); - with lblComponentDescription do - begin - Parent := pnlDescription; - Left := ScaleX(8); - WordWrap := True; - AutoSize := False; - Width := Parent.Width - ScaleX(16); - Height := Parent.Height - ScaleY(20); - Top := ScaleY(12); - end; - -end; - - -procedure ReadyFaceLift(); -var rtfNewReadyMemo: TRichEditViewer; -begin - DebugMsg('ReadyFaceLift',''); - WizardForm.ReadyMemo.Visible := False; - - rtfNewReadyMemo := TRichEditViewer.Create(WizardForm.ReadyMemo.Parent); - with rtfNewReadyMemo do - begin - Parent := WizardForm.ReadyMemo.Parent; - Scrollbars := ssVertical; - Color := WizardForm.Color; - UseRichEdit := True; - RTFText := ReadyMemoRichText; - ReadOnly := True; - Left := WizardForm.ReadyMemo.Left; - Top := WizardForm.ReadyMemo.Top; - Width := WizardForm.ReadyMemo.Width; - Height := WizardForm.ReadyMemo.Height; - Visible := True; - end; -end; - - -procedure lblURL_OnClick(Sender: TObject); -var ErrorCode: Integer; -begin - ShellExecAsOriginalUser('',GIMP_URL,'','',SW_SHOW,ewNoWait,ErrorCode); -end; - - -function MeasureLabel(const pText: String): Integer; //WordWrap + AutoSize works better with TNewStaticText than with TLabel, -var lblMeasure: TNewStaticText; //abuse this -begin - lblMeasure := TNewStaticText.Create(WizardForm.InstallingPage); - with lblMeasure do - begin - Parent := WizardForm.InstallingPage; - - AutoSize := True; - WordWrap := True; - Width := Parent.ClientWidth; - - Caption := pText; - - Result := Height; - end; - lblMeasure.Free; -end; - - -procedure InstallingFaceLift(); -var lblMessage1,lblURL,lblMessage2: TLabel; //TNewStaticText doesn't support alignment -begin - with WizardForm.ProgressGauge do - begin - Height := ScaleY(16); - Top := WizardForm.InstallingPage.ClientHeight - Top - Height; - - WizardForm.StatusLabel.Top := Top - WizardForm.FilenameLabel.Height - ScaleY(4); - WizardForm.FilenameLabel.Top := Top + Height + ScaleY(4); - end; - - lblMessage1 := TLabel.Create(WizardForm.InstallingPage); - with lblMessage1 do - begin - Parent := WizardForm.InstallingPage; - - Alignment := taCenter; - WordWrap := True; - AutoSize := False; - Width := WizardForm.InstallingPage.ClientWidth; - Height := MeasureLabel(CustomMessage('Billboard1')); - - Caption := CustomMessage('Billboard1'); - end; - - lblURL := TLabel.Create(WizardForm.InstallingPage); - with lblURL do - begin - Parent := WizardForm.InstallingPage; - - AutoSize := True; - WordWrap := False; - - Font.Color := GetSysColor(COLOR_HOTLIGHT); - Font.Style := [fsUnderline]; - Font.Size := 12; - - Cursor := crHand; - - OnClick := @lblURL_OnClick; - - Caption := GIMP_URL; - - Left := Integer(WizardForm.InstallingPage.ClientWidth / 2 - Width / 2); - end; - - lblMessage2 := TLabel.Create(WizardForm.InstallingPage); - with lblMessage2 do - begin - Parent := WizardForm.InstallingPage; - - Alignment := taCenter; - WordWrap := True; - AutoSize := False; - Width := WizardForm.InstallingPage.ClientWidth; - Height := MeasureLabel(CustomMessage('Billboard2')); - - Caption := CustomMessage('Billboard2'); - end; - - lblMessage1.Top := Integer(WizardForm.StatusLabel.Top / 2 - - (lblMessage1.Height + ScaleY(4) + lblURL.Height + ScaleY(4) + lblMessage2.Height) / 2); - lblURL.Top := lblMessage1.Top + lblMessage1.Height + ScaleY(4); - lblMessage2.Top := lblURL.Top + lblURL.Height + ScaleY(4); - -end; - - -procedure ComponentsListOnClick(pSender: TObject); -var i,j: Integer; - Components: TArrayOfString; - ComponentDesc: String; -begin - DebugMsg('ComponentsListOnClick',''); - - Components := ['Gimp','Deps','Debug','Translations','MyPaint','Python','Ghostscript','Lua','Gimp32']; - ComponentDesc := ''; - - for i := 0 to TNewCheckListBox(pSender).Items.Count - 1 do - if TNewCheckListBox(pSender).Selected[i] then - begin - for j := 0 to Length(Components) - 1 do - begin - if TNewCheckListBox(pSender).Items.Strings[i] = CustomMessage('Components' + Components[j]) then - ComponentDesc := CustomMessage('Components' + Components[j] + 'Description'); - end; - - if ComponentDesc <> '' then - break; - end; - - lblComponentDescription.Caption := ComponentDesc; - -end; - - -function CopyW(const S: String; const Start, Len: Integer): String; //work-around for unicode-related bug in Copy -begin - Result := Copy(S, Start, Len); -end; - -function Unicode2RTF(const pIn: String): String; //convert to RTF-compatible unicode -var i: Integer; - c: SmallInt; -begin - Result := ''; - for i := 1 to Length(pIn) do - if Ord(pIn[i]) <= 127 then - begin - Result := Result + pIn[i]; - end else - begin - c := Ord(pIn[i]); //code points above 7FFF must be expressed as negative numbers - Result := Result + '\u' + IntToStr(c) + '?'; - end; -end; - -function ParseReadyMemoText(pSpaces,pText: String): String; -var sTemp: String; -begin - - sTemp := CopyW(pText,Pos(#10,pText)+1,Length(pText)); - sTemp := Replace('{','\{',sTemp); - sTemp := Replace('\','\\',sTemp); - sTemp := Replace(#13#10,RTFpara,sTemp); - sTemp := Replace(pSpaces,'',sTemp); - sTemp := '\b ' + CopyW(pText,1,Pos(#13,pText)-1) + '\par\sb0' + - '\li284\b0 ' + sTemp + '\par \pard'; - - Result := Unicode2RTF(sTemp); -end; - - -function UpdateReadyMemo(pSpace, pNewLine, pMemoUserInfo, pMemoDirInfo, pMemoTypeInfo, pMemoComponentsInfo, pMemoGroupInfo, pMemoTasksInfo: String): String; -var sText: String; - bShowAssoc: Boolean; - i,j: Integer; -begin - DebugMsg('UpdateReadyMemo',''); - (* Prepare the text for new Ready Memo *) - - sText := RTFHeader; - if pMemoDirInfo <> '' then - sText := sText + ParseReadyMemoText(pSpace,pMemoDirInfo) + '\sb100'; - sText := sText + ParseReadyMemoText(pSpace,pMemoTypeInfo); - sText := sText + '\sb100' + ParseReadyMemoText(pSpace,pMemoComponentsInfo); - - If pMemoTasksInfo<>'' then - sText := sText + '\sb100' + ParseReadyMemoText(pSpace,pMemoTasksInfo); - - ReadyMemoRichText := Copy(sText,1,Length(sText)-6) + '}'; - - Result := 'If you see this, something went wrong'; -end; - - - -procedure UpdateWizardImages(); -var NewBitmap1,NewBitmap2: TFileStream; -begin - WelcomeBitmapBottom := TBitmapImage.Create(WizardForm); - with WelcomeBitmapBottom do - begin - Left := 0; - Top := 0; - Parent := WizardForm; - Width := WizardForm.ClientWidth; - Height := WizardForm.ClientHeight; - Stretch := True; - end; - - DebugMsg('UpdateWizardImages','Height: ' + IntToStr(WizardForm.WizardBitmapImage.Height)); - - if WizardForm.WizardBitmapImage.Height < 386 then //use smaller image when not using Large Fonts - begin - try - NewBitmap1 := TFileStream.Create(ExpandConstant('{tmp}\installsplash_small.bmp'),fmOpenRead); - WizardForm.WizardBitmapImage.Bitmap.LoadFromStream(NewBitmap1); - WelcomeBitmapBottom.Bitmap := WizardForm.WizardBitmapImage.Bitmap; - try - NewBitmap2 := TFileStream.Create(ExpandConstant('{tmp}\windows-installer-intro-small.bmp'),fmOpenRead); - WizardForm.WizardBitmapImage2.Bitmap.LoadFromStream(NewBitmap2); - except - DebugMsg('UpdateWizardImages','Error loading image: ' + GetExceptionMessage); - finally - if NewBitmap2 <> nil then - NewBitmap2.Free; - end; - except - DebugMsg('UpdateWizardImages','Error loading image: ' + GetExceptionMessage); - finally - if NewBitmap1 <> nil then - NewBitmap1.Free; - end; - end - else - begin - try - NewBitmap1 := TFileStream.Create(ExpandConstant('{tmp}\installsplash.bmp'),fmOpenRead); - WizardForm.WizardBitmapImage.Bitmap.LoadFromStream(NewBitmap1); - WelcomeBitmapBottom.Bitmap := WizardForm.WizardBitmapImage.Bitmap; - except - DebugMsg('UpdateWizardImages','Error loading image: ' + GetExceptionMessage); - finally - if NewBitmap1 <> nil then - NewBitmap1.Free; - end; - end; - WizardForm.WizardBitmapImage.Width := WizardForm.ClientWidth; - WizardForm.WizardBitmapImage.Height := WizardForm.ClientHeight; -end; - - -procedure DoUninstall(const UninstStr, InstallDir: String; const pInfoLabel: TNewStaticText; var oResult: TRemoveOldGIMPResult); -var InResult: TRemoveOldGIMPResult; - ResultCode, i: Integer; -begin - InResult := oResult; - - DebugMsg('DoUninstall','Uninstall string: ' + UninstStr); - - //when installing to same directory, assume that restart is required by default ... - if LowerCase(RemoveBackslashUnlessRoot(InstallDir)) = LowerCase(RemoveBackslashUnlessRoot(ExpandConstant('{app}'))) then - oResult := rogRestartRequired - else - oResult := InResult; - - pInfoLabel.Caption := InstallDir; - - if not Exec('>',UninstStr,'',SW_SHOW,ewWaitUntilTerminated,ResultCode) then - begin - DebugMsg('DoUninstall','Exec('+UninstStr+') failed: ' + IntToStr(ResultCode)); - - if not DirExists(InstallDir) then //old install directory doesn't exist, assume it was deleted, and Registry info is orphaned - begin - DebugMsg('DoUninstall','Install directory doesn'#39't exist: ' + InstallDir + ', resuming install'); - oResult := InResult - end else - begin - oResult := rogUninstallFailed; - end; - - exit; - end; - - DebugMsg('DoUninstall','Exec succeeded, uninstaller result: ' + IntToStr(ResultCode)); - - //... unless the complete installation directory was removed on uninstall - i := 0; - while i < (UNINSTALL_MAX_WAIT_TIME / UNINSTALL_CHECK_TIME) do - begin - if not DirExists(ExpandConstant('{app}')) then - begin - DebugMsg('DoUninstall','Existing GIMP directory removed, restoring previous restart requirement'); - oResult := InResult; //restore previous result - break; - end; - DebugMsg('DoUninstall','Waiting for ' + ExpandConstant('{app}') + ' to disappear [' + IntToStr(i) + ']'); - Sleep(UNINSTALL_CHECK_TIME); //it may take a few seconds for the uninstaller to remove the directory after it's exited - Inc(i); - end; -end; - - -function RemoveOldGIMPVersions(): TRemoveOldGIMPResult; -var lblInfo1,lblInfo2: TNewStaticText; - RootKey: Integer; - OldPath, UninstallString, WhichStr: String; -begin - Result := rogContinue; - - lblInfo1 := TNewStaticText.Create(WizardForm.PreparingPage); - with lblInfo1 do - begin - Parent := WizardForm.PreparingPage; - Left := 0; - Top := 0; - AutoSize := True; - WordWrap := True; - Width := WizardForm.PreparingPage.ClientWidth; - - Caption := CustomMessage('RemovingOldVersion'); - end; - lblInfo2 := TNewStaticText.Create(WizardForm.PreparingPage); - with lblInfo2 do - begin - Parent := WizardForm.PreparingPage; - Left := 0; - AutoSize := True; - WordWrap := True; - Width := WizardForm.PreparingPage.ClientWidth; - Top := lblInfo1.Height + ScaleY(8); - end; - - if ExpandConstant('{param:debugresume|0}') = '1' then - Result := rogRestartRequired; //for testing - - if Is64BitInstallMode() then - RootKey := HKLM32 - else - RootKey := HKLM; - - if RegValueExists(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1', - 'Inno Setup: App Path') then - begin - if RegQueryStringValue(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1', - 'Inno Setup: App Path',OldPath) then - begin - DebugMsg('RemoveOldGIMPVersions','Found legacy GIMP install, removing'); - - if RegValueExists(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1', - 'QuietUninstallString') then - WhichStr := 'QuietUninstallString' - else if RegValueExists(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1', - 'UninstallString') then - WhichStr := 'UninstallString' - else - begin - Result := rogCantUninstall; - exit; - end; - - if not RegQueryStringValue(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1', - WhichStr,UninstallString) then - begin - Result := rogCantUninstall; - exit; - end; - - if WhichStr = 'UninstallString' then - UninstallString := UninstallString + ' /SILENT'; - - UninstallString := UninstallString + ' /NORESTART'; - - DoUninstall(UninstallString, OldPath, lblInfo2, Result); - - end; - - end; - - lblInfo1.Free; - lblInfo2.Free; -end; - - -procedure InfoBeforeLikeLicense(); -begin - WizardForm.InfoBeforeClickLabel.Visible := False; - WizardForm.InfoBeforeMemo.Height := WizardForm.InfoBeforeMemo.Height + WizardForm.InfoBeforeMemo.Top - WizardForm.InfoBeforeClickLabel.Top; - WizardForm.InfoBeforeMemo.Top := WizardForm.InfoBeforeClickLabel.Top; -end; - - -procedure PrepareWelcomePage(); -begin - if not WizardSilent then - begin - WizardForm.NextButton.Visible := False; - - btnInstall.Visible := True; - btnInstall.TabOrder := 1; - btnCustomize.Visible := True; - - WizardForm.Bevel.Visible := False; - WizardForm.WelcomeLabel1.Visible := False; - WizardForm.WelcomeLabel2.Visible := False; - - WelcomeBitmapBottom.Visible := True; - end; -end; - - -procedure CurPageChanged(pCurPageID: Integer); -begin - DebugMsg('CurPageChanged','ID: '+IntToStr(pCurPageID)); - case pCurPageID of - wpWelcome: - PrepareWelcomePage(); - wpInfoBefore: - InfoBeforeLikeLicense(); - wpSelectComponents: - SelectComponentsFaceLift(); - wpReady: - ReadyFaceLift(); - wpInstalling: - InstallingFaceLift(); - end; -end; - - -function ShouldSkipPage(pPageID: Integer): Boolean; -begin - DebugMsg('ShouldSkipPage','ID: '+IntToStr(pPageID)); - - Result := ((InstallMode = imSimple) or (InstallMode = imRebootContinue)) and (pPageID <> wpFinished); - //skip all pages except for the finished one if using simple - //install mode - if Result then - DebugMsg('ShouldSkipPage','Yes') - else - DebugMsg('ShouldSkipPage','No'); - -end; - - -procedure RemoveDebugFilesFromDir(pDir: String; var pDirectories: TArrayOfString); -var FindRec: TFindRec; -begin - DebugMsg('RemoveDebugFilesFromDir', pDir); - WizardForm.FilenameLabel.Caption := pDir; - if FindFirst(AddBackSlash(pDir) + '*', FindRec) then - begin - try - repeat - if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then - begin - if (Length(FindRec.Name) > 6) and (LowerCase(Copy(FindRec.Name, Length(FindRec.Name) - 5, 6)) = '.debug') then - begin - DebugMsg('RemoveDebugFilesFromDir', '> ' + FindRec.Name); - DeleteFile(AddBackSlash(pDir) + FindRec.Name); - end; - end else - begin - if (FindRec.Name <> '.') and (FindRec.Name <> '..') then - begin - SetArrayLength(pDirectories, GetArrayLength(pDirectories) + 1); - pDirectories[GetArrayLength(pDirectories) - 1] := AddBackSlash(pDir) + FindRec.Name; - end; - end; - until not FindNext(FindRec); - finally - FindClose(FindRec); - end; - end; -end; - -//remove .debug files from previous installs -//there's no built-in way in Inno to recursively delete files with wildcard+extension -procedure RemoveDebugFiles(); -var Directories: TArrayOfString; - Index: Integer; -begin - SetArrayLength(Directories, 1); - Directories[0] := ExpandConstant('{app}'); - Index := 0; - - WizardForm.StatusLabel.Caption := CustomMessage('RemovingOldFiles'); - - repeat - RemoveDebugFilesFromDir(Directories[Index], Directories); - Inc(Index); - until Index = GetArrayLength(Directories); -end; - - -procedure CurStepChanged(pCurStep: TSetupStep); -begin - case pCurStep of - ssInstall: - begin - RemoveDebugFiles(); - AssociationsCleanup(); - end; - ssPostInstall: - begin - PrepareInterp(); - PrepareGimpEnvironment(); - end; - end; -end; - - -function PrepareToInstall(var pNeedsRestart: Boolean): String; -var ChecksumBefore, ChecksumAfter: String; - RemoveResult: TRemoveOldGIMPResult; -begin - - ChecksumBefore := MakePendingFileRenameOperationsChecksum; - - RemoveResult := RemoveOldGIMPVersions; - - if RemoveResult = rogRestartRequired then //old version was uninstalled, but something was left behind, so to be safe a reboot - begin //is enforced - this can only happen when reusing install directory - - DebugMsg('PrepareToInstall','RemoveOldGIMPVersions requires restart'); - - ChecksumAfter := MakePendingFileRenameOperationsChecksum; - if (ChecksumBefore <> ChecksumAfter) or (ExpandConstant('{param:debugresume|0}') = '1') then - begin //this check is most likely redundant, since the uninstaller will be added to pending rename operations - CreateRunOnceEntry; - pNeedsRestart := True; - Result := CustomMessage('RebootRequiredFirst'); - end; - end else - if RemoveResult = rogContinue then - begin - DebugMsg('PrepareToInstall','RemoveOldGIMPVersions finished successfully'); - Result := ''; //old version was uninstalled successfully, nothing was left behind, so install can continue immediately - end else - if RemoveResult = rogUninstallFailed then - begin - DebugMsg('PrepareToInstall','RemoveOldGIMPVersions failed to uninstall old GIMP version'); - Result := FmtMessage(CustomMessage('RemovingOldVersionFailed'),['{#VERSION}',ExpandConstant('{app}')]); - end else - if RemoveResult = rogCantUninstall then - begin - DebugMsg('PrepareToInstall','RemoveOldGIMPVersions failed to uninstall old GIMP version [1]'); - Result := FmtMessage(CustomMessage('RemovingOldVersionCantUninstall'),['{#VERSION}',ExpandConstant('{app}')]); - end else - begin - DebugMsg('PrepareToInstall','Internal error 11'); - Result := FmtMessage(CustomMessage('InternalError'),['11']); //should never happen - end; - -end; - - -procedure InitializeWizard(); -begin - UpdateWizardImages(); - InitCustomPages(); -end; - - -function BPPTooLowWarning(): Boolean; -var hDC, bpp, pl: Integer; - Message,Buttons: TArrayOfString; -begin - hDC := GetDC(0); - pl := GetDeviceCaps(hDC, PLANES); - bpp := GetDeviceCaps(hDC, BITSPIXEL); - ReleaseDC(0,hDC); - - bpp := pl * bpp; - - if bpp < 32 then - begin - SetArrayLength(Message,1); - SetArrayLength(Buttons,2); - Message[0] := CustomMessage('Require32BPP'); - Buttons[0] := CustomMessage('Require32BPPContinue'); - Buttons[1] := CustomMessage('Require32BPPExit'); - if (not WizardSilent) and - (MessageWithURL(Message, CustomMessage('Require32BPPTitle'), Buttons, mbError, 2, 2) = 2) then - Result := False - else - Result := True; - end - else - Result := True; -end; - - -procedure Check32bitOverride; -var i: Integer; - old: String; -begin - Force32bitInstall := False; - - old := LowerCase(GetPreviousData('32bitMode','')); - - if old = 'true' then //ignore command line if previous install is already present - Force32bitInstall := True - else if old = 'false' then - Force32bitInstall := False - else - for i := 0 to ParamCount do //not a bug (in script anyway) - ParamCount returns the index of last ParamStr element, not the actual count - if ParamStr(i) = '/32' then - begin - Force32bitInstall := True; - break; - end; - - DebugMsg('Check32bitOverride',BoolToStr(Force32bitInstall) + '[' + old + ']'); -end; - - -function InitializeSetup(): Boolean; -#if (Defined(DEVEL) && DEVEL != "") || Defined(DEVEL_WARNING) -var Message,Buttons: TArrayOfString; -#endif -begin - ConfigOverride := coUndefined; - - if not IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE) then - begin - SuppressibleMsgBox(CustomMessage('SSERequired'), mbCriticalError, MB_OK, 0); - Result := false; - exit; - end; - - Check32bitOverride; - - Result := RestartSetupAfterReboot(); //resume install after reboot - skip all setting pages, and install directly - - if Result then - Result := BPPTooLowWarning(); - - if not Result then //no need to do anything else - exit; - -#if (Defined(DEVEL) && DEVEL != "") || Defined(DEVEL_WARNING) - Explode(Message, CustomMessage('DevelopmentWarning'), #13#10); - SetArrayLength(Buttons,2); - Buttons[0] := CustomMessage('DevelopmentButtonContinue'); - Buttons[1] := CustomMessage('DevelopmentButtonExit'); - if (not WizardSilent) and - (MessageWithURL(Message, CustomMessage('DevelopmentWarningTitle'), Buttons, mbError, 2, 2) = 2) then - begin - Result := False; - Exit; - end; -#endif - - try - ExtractTemporaryFile('windows-installer-intro-small.bmp'); - ExtractTemporaryFile('installsplash.bmp'); - ExtractTemporaryFile('installsplash_small.bmp'); - except - DebugMsg('InitializeSetup','Error extracting temporary file: ' + GetExceptionMessage); - MsgBox(CustomMessage('ErrorExtractingTemp') + #13#13 + GetExceptionMessage,mbError,MB_OK); - Result := False; - exit; - end; - - //if InstallMode <> imRebootContinue then - // SuppressibleMsgBox(CustomMessage('UninstallWarning'),mbError,MB_OK,IDOK); - -end; - - -procedure RegisterPreviousData(PreviousDataKey: Integer); -begin - if Is64BitInstallMode() then - SetPreviousData(PreviousDataKey,'32BitMode',BoolToStr(Force32bitInstall)); -end; - - -procedure SaveToUninstInf(const pText: AnsiString); -var sUnInf: String; - sOldContent: String; -begin - sUnInf := ExpandConstant('{app}\uninst\uninst.inf'); - - if not FileExists(sUnInf) then //save small header - SaveStringToUTF8File(sUnInf,#$feff+'#Additional uninstall tasks'#13#10+ //#$feff BOM is required for LoadStringsFromFile - '#This file uses UTF-8 encoding'#13#10+ - '#'#13#10+ - '#Empty lines and lines beginning with # are ignored'#13#10+ - '#'#13#10+ - '#Add uninstallers for GIMP add-ons that should be removed together with GIMP like this:'#13#10+ - '#Run://'#13#10+ - '#'#13#10+ - '#The file is parsed in reverse order' + #13#10 + - '' + #13#10 //needs '' in front, otherwise preprocessor complains - ,False) - else - begin - LoadStringFromUTF8File(sUnInf,sOldContent); - if Pos(#13#10+pText+#13#10,sOldContent) > 0 then //don't write duplicate lines - exit; - end; - - SaveStringToUTF8File(sUnInf,pText+#13#10,True); -end; - -#include "rebootcontinue.isi" - -#include "uninst.isi" - -#expr SaveToFile(AddBackslash(SourcePath) + "Preprocessed.iss") +;.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,., +; ; +;Copyright (c) 2002-2010 Jernej Simončič ; +; ; +;This software is provided 'as-is', without any express or implied ; +;warranty. In no event will the authors be held liable for any damages ; +;arising from the use of this software. ; +; ; +;Permission is granted to anyone to use this software for any purpose, ; +;including commercial applications, and to alter it and redistribute it ; +;freely, subject to the following restrictions: ; +; ; +; 1. The origin of this software must not be misrepresented; you must ; +; not claim that you wrote the original software. If you use this ; +; software in a product, an acknowledgment in the product ; +; documentation would be appreciated but is not required. ; +; ; +; 2. Altered source versions must be plainly marked as such, and must ; +; not be misrepresented as being the original software. ; +; ; +; 3. This notice may not be removed or altered from any source ; +; distribution. ; +;.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.; +; +;Install script for GIMP and GTK+ +;requires Inno Setup 6 +; +;See base_directories.isi +; +;Changelog: +; +;2012-05-05 +;- check for SSE support +;- remove obsolete 2.6 plugins when installing over 2.6.12 combined installer +; +;2011-12-18 +;- display a picture on the first install screen +;- add a development version warning back +;- clean gegl's DLLs on install as some files have changed names +; +;2011-08-30 +;- only uninstall previous GIMP version when installing over existing installation +; TODO: offer the option to uninstall 32bit version when installing on x64 system +;- install 32bit plugins to same directory as 64bit plugins on x64 installs to +; avoid problems when upgrading +; +;2010-07-08 +;- clean up entire Python subdirectory (since the .pyc files are generated when +; scripts are run) +;- use crHand instead of crHandPoint for the billboard URL +; +;2010-07-02 +;- add libraries for compatibility with old 32-bit plug-ins as a component +;- remove a few unused RTF ready-memo related things +;- uninst.inf is now processed as the first step of uninstall, as otherwise the +; uninstaller could leave behind empty directories +; +;2010-06-29 +;- fix SuppressibleMsgBox calls to use proper button ID for default button +;- simplify the wizard - skip Welcome page, and make the Next button from +; InfoBefore/License page invoke install immediately (custom install is still +; possible by clicking the Customize button) +; +;2010-05-15 +;- rewrote script mostly from scratch +;- combine 32 and 64bit GIMP versions to a single installer +; - install enough 32bit support files even with 64bit version to allow running 32bit +; plug-ins on 64bit version (used by Python scriptin support [as there's no 64-bit +; PyGTK+ on Windows available yet] and TWAIN plug-in, which only works in 32-bit +; version) +;- Python with PyGTK is included in the installer now +;- install GIMP to new directory by default ({pf}\GIMP 2 instead of {pf}\GIMP-2.0) +;- uninstall previous GIMP versions as the first step of install (both 32 and 64-bit) +; - require reboot if installing to directory from which GIMP was just uninstalled, +; and this directory wasn't removed by the uninstaller; the installer will continue +; automatically after reboot +;- fixed a long standing bug where "Open with GIMP" menu entries would be left after +; uninstalling +; +#pragma option -e+ + +#ifndef VERSION + #error VERSION must be defined +#endif +#ifndef GIMP_DIR + #error GIMP_DIR must be defined +#endif +#ifndef DIR32 + #error DIR32 must be defined +#endif +#ifndef DIR64 + #error DIR64 must be defined +#endif +#ifndef DEPS_DIR + #error DEPS_DIR must be defined +#endif +#ifndef DDIR32 + #error DDIR32 must be defined +#endif +#ifndef DDIR64 + #error DDIR64 must be defined +#endif + +; Optional: DEBUG_SYMBOLS, LUA, PYTHON, NOCOMPRESSION, NOFILES, DEVEL + +#define X86 1 +#define X64 2 +#define ARM64 3 + +#include "base_directories.isi" +#include "util_version.isi" + +[Setup] +AppName=GIMP +#if Defined(DEVEL) && DEVEL != "" +AppID=GIMP-{#MAJOR}.{#MINOR} +#else +AppID=GIMP-{#MAJOR} +#endif +VersionInfoVersion={#VERSION} +#if !defined(REVISION) +AppVerName=GIMP {#VERSION} +#else +AppVerName=GIMP {#VERSION}-{#REVISION} +#endif +AppPublisherURL=https://www.gimp.org/ +AppSupportURL=https://www.gimp.org/docs/ +AppUpdatesURL=https://www.gimp.org/ +AppPublisher=The GIMP Team +AppVersion={#VERSION} +DisableProgramGroupPage=yes +DisableWelcomePage=no +DisableDirPage=auto +AlwaysShowDirOnReadyPage=yes +ChangesEnvironment=yes + +#if Defined(DEVEL) && DEVEL != "" +DefaultDirName={autopf}\GIMP {#MAJOR}.{#MINOR} +LZMANumBlockThreads=4 +LZMABlockSize=76800 +#else +DefaultDirName={autopf}\GIMP {#MAJOR} +#endif + +;AllowNoIcons=true +FlatComponentsList=yes +InfoBeforeFile=gpl+python.rtf +ChangesAssociations=true + +WizardImageFile=windows-installer-intro-big.bmp +WizardImageStretch=yes +WizardSmallImageFile=wilber.bmp + +UninstallDisplayIcon={app}\bin\gimp-{#MAJOR}.{#MINOR}.exe +UninstallFilesDir={app}\uninst + +MinVersion=10.0 +ArchitecturesInstallIn64BitMode=x64 arm64 + +#ifdef NOCOMPRESSION +;UseSetupLdr=no +OutputDir=_Output\unc +Compression=none +;InternalCompressLevel=0 +DiskSpanning=yes +DiskSliceSize=max +#else +OutputDir=_Output +Compression=lzma2/ultra64 +InternalCompressLevel=ultra +SolidCompression=yes +LZMAUseSeparateProcess=yes +LZMANumFastBytes=273 +; Increasing dictionary size may improve compression ratio at the +; expense of memory requirement. We run into "Out of memory" error in +; the CI. +;LZMADictionarySize=524288 + +;SignTool=Default +;SignedUninstaller=yes +;SignedUninstallerDir=_Uninst +#endif //NOCOMPRESSION + +#if !defined(REVISION) +OutputBaseFileName=gimp-{#VERSION}-setup +OutputManifestFile=gimp-{#VERSION}-setup.txt +#else +OutputBaseFileName=gimp-{#VERSION}-{#REVISION}-setup +OutputManifestFile=gimp-{#VERSION}-{#REVISION}-setup.txt +#endif + +PrivilegesRequiredOverridesAllowed=dialog + +[Languages] +Name: "en"; MessagesFile: "compiler:Default.isl,lang\en.setup.isl" +Name: "be"; MessagesFile: "compiler:Languages\Unofficial\Belarusian.isl,lang\be.setup.isl" +Name: "bg"; MessagesFile: "compiler:Languages\Bulgarian.isl,lang\bg.setup.isl" +Name: "ca"; MessagesFile: "compiler:Languages\Catalan.isl,lang\ca.setup.isl" +Name: "cs"; MessagesFile: "compiler:Languages\Czech.isl,lang\cs.setup.isl" +Name: "da"; MessagesFile: "compiler:Languages\Danish.isl,lang\da.setup.isl" +Name: "de"; MessagesFile: "compiler:Languages\German.isl,lang\de.setup.isl" +Name: "el"; MessagesFile: "compiler:Languages\Unofficial\Greek.isl,lang\el.setup.isl" +Name: "en_GB"; MessagesFile: "compiler:Languages\Unofficial\EnglishBritish.isl,lang\en_GB.setup.isl" +Name: "eo"; MessagesFile: "compiler:Languages\Unofficial\Esperanto.isl,lang\eo.setup.isl" +Name: "es"; MessagesFile: "compiler:Languages\Spanish.isl,lang\es.setup.isl" +Name: "eu"; MessagesFile: "compiler:Languages\Unofficial\Basque.isl,lang\eu.setup.isl" +Name: "fi"; MessagesFile: "compiler:Languages\Finnish.isl,lang\fi.setup.isl" +Name: "fr"; MessagesFile: "compiler:Languages\French.isl,lang\fr.setup.isl" +Name: "gl"; MessagesFile: "compiler:Languages\Unofficial\Galician.isl,lang\gl.setup.isl" +Name: "he"; MessagesFile: "compiler:Languages\Hebrew.isl,lang\he.setup.isl" +Name: "hu"; MessagesFile: "compiler:Languages\Hungarian.isl,lang\hu.setup.isl" +;Name: "hr"; MessagesFile: "compiler:Languages\Unofficial\Croatian.isl,lang\hr.setup.isl" +Name: "id"; MessagesFile: "compiler:Languages\Unofficial\Indonesian.isl,lang\id.setup.isl" +Name: "is"; MessagesFile: "compiler:Languages\Icelandic.isl,lang\is.setup.isl" +Name: "it"; MessagesFile: "compiler:Languages\Italian.isl,lang\it.setup.isl" +Name: "ja"; MessagesFile: "compiler:Languages\Japanese.isl,lang\ja.setup.isl" +Name: "ka"; MessagesFile: "compiler:Languages\Unofficial\Georgian.isl,lang\ka.setup.isl" +Name: "kab"; MessagesFile: "compiler:Default.isl,lang\kab.isl,lang\kab.setup.isl" +Name: "ko"; MessagesFile: "compiler:Languages\Korean.isl,lang\ko.setup.isl" +Name: "lt"; MessagesFile: "compiler:Languages\Unofficial\Lithuanian.isl,lang\lt.setup.isl" +Name: "lv"; MessagesFile: "compiler:Languages\Unofficial\Latvian.isl,lang\lv.setup.isl" +Name: "mr"; MessagesFile: "compiler:Languages\Unofficial\Marathi.islu,lang\mr.setup.isl" +Name: "ms"; MessagesFile: "compiler:Languages\Unofficial\Malaysian.isl,lang\ms.setup.isl" +Name: "nl"; MessagesFile: "compiler:Languages\Dutch.isl,lang\nl.setup.isl" +Name: "pl"; MessagesFile: "compiler:Languages\Polish.isl,lang\pl.setup.isl" +Name: "pt"; MessagesFile: "compiler:Languages\Portuguese.isl,lang\pt.setup.isl" +Name: "pt_BR"; MessagesFile: "compiler:Languages\BrazilianPortuguese.isl,lang\pt_BR.setup.isl" +Name: "ro"; MessagesFile: "compiler:Languages\Unofficial\Romanian.isl,lang\ro.setup.isl" +Name: "ru"; MessagesFile: "compiler:Languages\Russian.isl,lang\ru.setup.isl" +Name: "sk"; MessagesFile: "compiler:Languages\Slovak.isl,lang\sk.setup.isl" +Name: "sl"; MessagesFile: "compiler:Languages\Slovenian.isl,lang\sl.setup.isl" +Name: "sv"; MessagesFile: "compiler:Languages\Unofficial\Swedish.isl,lang\sv.setup.isl" +Name: "tr"; MessagesFile: "compiler:Languages\Turkish.isl,lang\tr.setup.isl" +Name: "uk"; MessagesFile: "compiler:Languages\Ukrainian.isl,lang\uk.setup.isl" +Name: "vi"; MessagesFile: "compiler:Languages\Unofficial\Vietnamese.isl,lang\vi.setup.isl" +Name: "zh_CN"; MessagesFile: "compiler:Languages\Unofficial\ChineseSimplified.isl,lang\zh_CN.setup.isl" +Name: "zh_TW"; MessagesFile: "compiler:Languages\Unofficial\ChineseTraditional.isl,lang\zh_TW.setup.isl" +;Name: "ro"; MessagesFile: "Romanian.islu,ro.setup.islu" + +[Types] +;Name: normal; Description: "{cm:TypeTypical}" +Name: full; Description: "{cm:TypeFull}" +Name: compact; Description: "{cm:TypeCompact}" +Name: custom; Description: "{cm:TypeCustom}"; Flags: iscustom + +[Components] +;Required components (minimal install) +Name: gimp32; Description: "{cm:ComponentsGimp,{#VERSION}}"; Types: full compact custom; Flags: fixed; Check: Check3264('32') +Name: gimp64; Description: "{cm:ComponentsGimp,{#VERSION}}"; Types: full compact custom; Flags: fixed; Check: Check3264('x64') +Name: gimpARM64; Description: "{cm:ComponentsGimp,{#VERSION}}"; Types: full compact custom; Flags: fixed; Check: Check3264('arm64') + +Name: deps32; Description: "{cm:ComponentsDeps,{#GTK_VERSION}}"; Types: full compact custom; Flags: checkablealone fixed; Check: Check3264('32') +Name: deps64; Description: "{cm:ComponentsDeps,{#GTK_VERSION}}"; Types: full compact custom; Flags: checkablealone fixed; Check: Check3264('x64') +Name: depsARM64; Description: "{cm:ComponentsDeps,{#GTK_VERSION}}"; Types: full compact custom; Flags: checkablealone fixed; Check: Check3264('arm64') + +;Optional components (complete install) +#ifdef DEBUG_SYMBOLS +Name: debug; Description: "{cm:ComponentsDebug}"; Types: full custom; Flags: disablenouninstallwarning +#endif + +;Ghostscript +Name: gs; Description: "{cm:ComponentsGhostscript}"; Types: full custom + +;Locales +Name: loc; Description: "{cm:ComponentsTranslations}"; Types: full custom + +#ifdef LUA +Name: lua; Description: "{cm:ComponentsLua}"; Types: full custom +#endif + +;MyPaint Brushes +Name: mypaint; Description: "{cm:ComponentsMyPaint}"; Types: full custom + +#ifdef PYTHON +Name: py; Description: "{cm:ComponentsPython}"; Types: full custom +#endif + +;32-bit TWAIN support +Name: gimp32on64; Description: "{cm:ComponentsGimp32}"; Types: full custom; Flags: checkablealone; Check: Check3264('64') + +[Tasks] +Name: desktopicon; Description: "{cm:AdditionalIconsDesktop}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked + +[Icons] +#define ICON_VERSION=MAJOR + "." + MINOR + "." + MICRO +Name: "{autoprograms}\GIMP {#ICON_VERSION}"; Filename: "{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe"; WorkingDir: "%USERPROFILE%"; Comment: "GIMP {#VERSION}" +Name: "{autodesktop}\GIMP {#ICON_VERSION}"; Filename: "{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe"; WorkingDir: "%USERPROFILE%"; Comment: "GIMP {#VERSION}"; Tasks: desktopicon + + +[Files] +;setup files +Source: "windows-installer-intro-small.bmp"; Flags: dontcopy +#ifndef DEVEL +Source: "installsplash.bmp"; Flags: dontcopy +Source: "installsplash_small.bmp"; Flags: dontcopy +#else +Source: "installsplash-devel.bmp"; Destname: "installsplash.bmp"; Flags: dontcopy +Source: "installsplash_small-devel.bmp"; Destname: "installsplash_small.bmp"; Flags: dontcopy +#endif + +#ifndef NOFILES +;Required neutral components (minimal install) +#define GIMP_ARCHS="gimp32 or gimp64 or gimpARM64" +Source: "{#GIMP_DIR32}\etc\*"; DestDir: "{app}\etc"; Components: {#GIMP_ARCHS}; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +Source: "{#GIMP_DIR32}\lib\gimp\{#DIR_VER}\environ\*"; DestDir: "{app}\lib\gimp\{#DIR_VER}\environ"; Components: {#GIMP_ARCHS}; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +Source: "{#GIMP_DIR32}\lib\gimp\{#DIR_VER}\interpreters\*"; DestDir: "{app}\lib\gimp\{#DIR_VER}\interpreters"; Components: {#GIMP_ARCHS}; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +Source: "{#GIMP_DIR32}\share\gimp\*"; DestDir: "{app}\share\gimp"; Components: {#GIMP_ARCHS}; Flags: recursesubdirs createallsubdirs restartreplace uninsrestartdelete ignoreversion +Source: "{#GIMP_DIR32}\share\metainfo\*"; DestDir: "{app}\share\metainfo"; Components: {#GIMP_ARCHS}; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion + +#define DEPS_ARCHS="deps32 or deps64 or depsARM64" +#define OMISSIONS="\gir-1.0,\man,\vala" +Source: "{#DEPS_DIR32}\etc\*"; DestDir: "{app}\etc"; Excludes: "\gimp"; Components: {#DEPS_ARCHS}; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +Source: "{#DEPS_DIR32}\share\*"; DestDir: "{app}\share"; Excludes: "{#OMISSIONS},\gimp\*,\metainfo\*,ghostscript\*,\locale\*,\lua\*,\mypaint-data\*,"; Components: {#DEPS_ARCHS}; Flags: recursesubdirs createallsubdirs restartreplace uninsrestartdelete ignoreversion + +;Optional neutral components (complete install) +Source: "{#DEPS_DIR32}\share\ghostscript\*"; DestDir: "{app}\share\ghostscript"; Components: gs and ({#GIMP_ARCHS}); Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +Source: "{#GIMP_DIR32}\share\locale\*"; DestDir: "{app}\share\locale"; Components: loc; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +Source: "{#DEPS_DIR32}\share\locale\*"; DestDir: "{app}\share\locale"; Components: loc; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +#ifdef LUA +Source: "{#DEPS_DIR32}\share\lua\*"; DestDir: "{app}\share\lua"; Components: lua and ({#GIMP_ARCHS}); Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete +#endif +Source: "{#DEPS_DIR32}\share\mypaint-data\*"; DestDir: "{app}\share\mypaint-data"; Components: mypaint; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +#ifdef PYTHON +Source: "{#GIMP_DIR32}\lib\gimp\{#DIR_VER}\plug-ins\*.py"; DestDir: "{app}\lib\gimp\{#DIR_VER}\plug-ins"; Components: py; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +#endif + + +;files arch specific +;i686 +#define PLATFORM X86 +#include "base_executables.isi" +;special case, since 64bit version doesn't work, and is excluded in base_executables.isi +Source: "{#GIMP_DIR32}\lib\gimp\{#DIR_VER}\plug-ins\twain.exe"; DestDir: "{app}\lib\gimp\{#DIR_VER}\plug-ins"; Components: gimp32; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion + +;x86_64 +#define PLATFORM X64 +#include "base_executables.isi" + +;AArch64 +#define PLATFORM ARM64 +#include "base_executables.isi" + +;32-on-64bit +#include "base_twain32on64.isi" +;prefer 32bit twain plugin over 64bit because 64bit twain drivers are rare +Source: "{#GIMP_DIR32}\lib\gimp\{#DIR_VER}\plug-ins\twain\twain.exe"; DestDir: "{app}\lib\gimp\{#DIR_VER}\plug-ins\twain"; Components: gimp32on64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +Source: "{#GIMP_DIR64}\lib\gimp\{#DIR_VER}\plug-ins\twain\twain.exe"; DestDir: "{app}\lib\gimp\{#DIR_VER}\plug-ins\twain"; Components: (not gimp32on64) and gimp64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion +Source: "{#GIMP_DIRA64}\lib\gimp\{#DIR_VER}\plug-ins\twain\twain.exe"; DestDir: "{app}\lib\gimp\{#DIR_VER}\plug-ins\twain"; Components: (not gimp32on64) and gimpARM64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion + +;special case due to MS-Windows engine +Source: "{#DEPS_DIR32}\etc\gtk-3.0\*"; DestDir: "{app}\32\etc\gtk-3.0"; Components: gimp32on64; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion + +;upgrade zlib1.dll in System32 if it's present there to avoid breaking plugins +;sharedfile flag will ensure that the upgraded file is left behind on uninstall to avoid breaking other programs that use the file +Source: "{#DEPS_DIR32}\bin\zlib1.dll"; DestDir: "{sys}"; Components: {#GIMP_ARCHS}; Flags: restartreplace sharedfile 32bit uninsrestartdelete comparetimestamp; Check: BadSysDLL('zlib1.dll',32) +Source: "{#DEPS_DIR64}\bin\zlib1.dll"; DestDir: "{sys}"; Components: gimp64; Flags: restartreplace sharedfile uninsrestartdelete comparetimestamp; Check: BadSysDLL('zlib1.dll',64) + +;overridden configuration files +#include "data_configoverride.isi" + +#endif //NOFILES + + +[InstallDelete] +Type: files; Name: "{app}\bin\gimp-?.?.exe" +Type: files; Name: "{app}\bin\gimp-?.??.exe" +Type: files; Name: "{app}\bin\gimp-console-?.?.exe" +Type: files; Name: "{app}\bin\gimp-console-?.??.exe" +Type: files; Name: "{app}\lib\gegl-0.1\*.dll" +;obsolete plugins from gimp 2.6 +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pdf.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gee.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gee-zoom.exe" +;old Python +Type: filesandordirs; Name: "{app}\Python\*" +Type: dirifempty; Name: "{app}\Python" +;remove incompatible version shipped with 2.8 +Type: files; Name: "{app}\bin\zlib1.dll" +Type: files; Name: "{app}\32\bin\zlib1.dll" +;old ghostscript +Type: filesandordirs; Name: "{app}\share\ghostscript\*" +;obsolete plugins from gimp 2.8 +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\pyconsole.py" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\python-console.py" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\metadata.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-psd-save.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-psd-load.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\alien-map.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\antialias.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\apply-canvas.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\blur-gauss.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\blur-gauss-selective.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\blur-motion.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\bump-map.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\channel-mixer.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\color-exchange.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\color-rotate.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\color-to-alpha.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\contrast-stretch.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\contrast-stretch-hsv.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\convolution-matrix.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\crop-auto.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\cubism.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\deinterlace.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\diffraction.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\displace.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\edge.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\edge-laplace.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\edge-sobel.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\engrave.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-raw.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-tiff-load.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-tiff-save.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-uri.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\illusion.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\iwarp.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\lcms.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\lens-apply.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\lens-distortion.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\lens-flare.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\maze.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\mosaic.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\noise-hsv.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\noise-randomize.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\noise-rgb.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\noise-solid.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\noise-spread.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\nova.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\pixelize.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\plasma.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\polar-coords.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\red-eye-removal.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\ripple.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\rotate.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\semi-flatten.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\shift.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\sinus.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\threshold-alpha.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\tile-glass.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\tile-paper.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\tile-seamless.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\value-invert.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\value-propagate.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\video.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\waves.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\whirl-pinch.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\win-snap.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\wind.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\text-brush.py" +;<2.10.6 plug-ins +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\align-layers.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\animation-optimize.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\animation-play.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\blinds.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\blur.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\border-average.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\busy-dialog.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\cartoon.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\checkerboard.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\cml-explorer.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\color-cube-analyze.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\color-enhance.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\colorify.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\colormap-remap.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\compose.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\contrast-normalize.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\contrast-retinex.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\crop-zealous.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\curve-bend.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\decompose.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\depth-merge.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\despeckle.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\destripe.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\edge-dog.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\edge-neon.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\emboss.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-bmp.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-cel.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-compressor.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-csource.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-darktable.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-desktop-link.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-dicom.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-exr.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-faxg3.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-fits.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-fli.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-gbr.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-gegl.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-gif-load.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-gif-save.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-gih.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-glob.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-header.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-heif.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-html-table.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-ico.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-jp2-load.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-jpeg.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-mng.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pat.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pcx.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pdf-load.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pdf-save.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pix.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-png.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pnm.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-ps.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-psd.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-psp.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-raw-data.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-raw-placeholder.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-rawtherapee.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-sgi.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-sunras.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-svg.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-tga.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-tiff.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-webp.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-wmf.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-xbm.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-xpm.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-xwd.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\film.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\filter-pack.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\flame.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\fractal-explorer.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\fractal-trace.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gfig.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gimpressionist.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\goat-exercise.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gradient-flare.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gradient-map.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\grid.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\guillotine.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\help-browser.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\help.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\hot.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\ifs-compose.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\imagemap.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\jigsaw.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\lighting.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\map-object.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\max-rgb.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\metadata-editor.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\metadata-viewer.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\newsprint.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\nl-filter.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\oilify.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\pagecurl.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\photocopy.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\plugin-browser.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\print.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\procedure-browser.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\qbist.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\sample-colorize.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\screenshot.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\script-fu.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\selection-to-path.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\sharpen.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\smooth-palette.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\softglow.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\sparkle.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\sphere-designer.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\tile-small.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\tile.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\twain.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\unit-editor.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\unsharp-mask.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\van-gogh-lic.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\warp.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\wavelet-decompose.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\web-browser.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\web-page.exe" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\colorxhtml.py" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-openraster.py" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\foggify.py" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gradients-save-as-css.py" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\histogram-export.py" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\palette-offset.py" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\palette-sort.py" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\palette-to-gradient.py" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\py-slice.py" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\python-eval.py" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\python-console\pyconsole.py" +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\python-console\python-console.py" +;<2.99.14 plug-ins and modules +Type: files; Name: "{app}\lib\gimp\2.99\plug-ins\py-slice\py-slice.py" +Type: files; Name: "{app}\lib\gimp\2.99\plug-ins\benchmark-foreground-extract\benchmark-foreground-extract.py" +;Some typo in meson which we used for GIMP 2.99.12 installer. +Type: files; Name: "{app}\lib\gimp\2.99\modules\libcontroller-dx-input.dll" +;DLLs in plug-ins directory (see bug 796225) +Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\*.dll" +;gegl 0.2 +Type: filesandordirs; Name: "{app}\lib\gegl-0.2" +;old icons +#ifndef DEVEL +Type: files; Name: "{autoprograms}\GIMP 2.lnk" +Type: files; Name: "{autodesktop}\GIMP 2.lnk" +#endif +;get previous GIMP icon name from uninstall name in Registry +#if Defined(DEVEL) && DEVEL != "" +Type: files; Name: "{autoprograms}\GIMP {reg:HKA\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}.{#MINOR}_is1,DisplayVersion|GIMP {#MAJOR}.{#MINOR}}.lnk"; Check: CheckRegValueExists('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}.{#MINOR}_is1','DisplayVersion') +Type: files; Name: "{autodesktop}\GIMP {reg:HKA\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}.{#MINOR}_is1,DisplayVersion|GIMP {#MAJOR}.{#MINOR}}.lnk"; Check: CheckRegValueExists('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}.{#MINOR}_is1','DisplayVersion') +#else +Type: files; Name: "{autoprograms}\GIMP {reg:HKA\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}_is1,DisplayVersion|GIMP {#MAJOR}}.lnk"; Check: CheckRegValueExists('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}_is1','DisplayVersion') +Type: files; Name: "{autodesktop}\GIMP {reg:HKA\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}_is1,DisplayVersion|GIMP {#MAJOR}}.lnk"; Check: CheckRegValueExists('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\GIMP-{#MAJOR}_is1','DisplayVersion') +#endif +;32-bit Python +Type: filesandordirs; Name: "{app}\32\lib\gimp\2.0\python" +Type: files; Name: "{app}\32\bin\python2w.exe" +Type: files; Name: "{app}\32\bin\python2.exe" +Type: files; Name: "{app}\32\bin\libpython2.7.dll" +Type: filesandordirs; Name: "{app}\32\lib\python2.7" +;remove old babl and gegl plugins +Type: filesandordirs; Name: "{app}\lib\babl-0.1" +Type: filesandordirs; Name: "{app}\lib\gegl-0.4" + +[Registry] +;remove LIBTHAI_DICTDIR variable set by original 2.10.8 installer +Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; ValueType: none; ValueName: "LIBTHAI_DICTDIR"; Flags: deletevalue uninsdeletevalue noerror +#include "data_associations.isi" + +[UninstallDelete] +Type: files; Name: "{app}\uninst\uninst.inf" +Type: files; Name: "{app}\lib\gimp\{#DIR_VER}\interpreters\lua.interp" +Type: files; Name: "{app}\lib\gimp\{#DIR_VER}\environ\pygimp.env" +;need to clean out all the generated .pyc files +Type: filesandordirs; Name: "{app}\Python\*" + +[Code] + +function WideCharToMultiByte(CodePage: Cardinal; dwFlags: DWORD; lpWideCharStr: String; cchWideCharStr: Integer; + lpMultiByteStr: PAnsiChar; cbMultiByte: Integer; lpDefaultChar: Integer; + lpUsedDefaultChar: Integer): Integer; external 'WideCharToMultiByte@Kernel32 stdcall'; + +function MultiByteToWideChar(CodePage: Cardinal; dwFlags: DWORD; lpMultiByteStr: PAnsiChar; cbMultiByte: Integer; + lpWideCharStr: String; cchWideChar: Integer): Integer; + external 'MultiByteToWideChar@Kernel32 stdcall'; + +function GetLastError(): DWORD; external 'GetLastError@Kernel32 stdcall'; + +function GetSysColor(nIndex: Integer): DWORD; external 'GetSysColor@user32.dll stdcall'; + +function IsProcessorFeaturePresent(ProcessorFeature: DWORD): LongBool; external 'IsProcessorFeaturePresent@kernel32 stdcall'; + +//functions needed to get BPP +function GetDC(hWnd: Integer): Integer; external 'GetDC@User32 stdcall'; +function ReleaseDC(hWnd, hDC: Integer): Integer; external 'ReleaseDC@User32 stdcall'; +function GetDeviceCaps(hDC, nIndex: Integer): Integer; external 'GetDeviceCaps@GDI32 stdcall'; + + +procedure ComponentsListOnClick(pSender: TObject); forward; +procedure SaveToUninstInf(const pText: AnsiString); forward; +procedure CreateRunOnceEntry; forward; +function RestartSetupAfterReboot(): Boolean; forward; +procedure AssociationsCleanUp(); forward; + +const + CP_ACP = 0; + CP_UTF8 = 65001; + + COLOR_HOTLIGHT = 26; + + PF_XMMI_INSTRUCTIONS_AVAILABLE = 6; + + BITSPIXEL = 12; + PLANES = 14; + + GIMP_URL = 'https://www.gimp.org/'; + + RTFHeader = '{\rtf1\deff0{\fonttbl{\f0\fswiss\fprq2\fcharset0 Tahoma;}{\f1\fnil\fcharset2 Symbol;}}\viewkind4\uc1\fs16'; + //RTFBullet = '{\pntext\f1\''B7\tab}'; + RTFPara = '\par '; + + RunOnceName = 'Resume GIMP {#VERSION} install'; + + CONFIG_OVERRIDE_PARAM = 'configoverride'; + + UNINSTALL_MAX_WAIT_TIME = 10000; + UNINSTALL_CHECK_TIME = 250; + +type + TRemoveOldGIMPResult = (rogContinue, rogRestartRequired, rogUninstallFailed, rogCantUninstall); + +var + lblComponentDescription: TNewStaticText; + + ReadyMemoRichText: String; + + WelcomeBitmapBottom: TBitmapImage; + + //pgSimple: TWizardPage; + btnInstall, btnCustomize: TNewButton; + + InstallMode: (imNone, imSimple, imCustom, imRebootContinue); + + ConfigOverride: (coUndefined, coOverride, coDontOverride); + + Force32bitInstall: Boolean; + + asUninstInf: TArrayOfString; //uninst.inf contents (loaded at start of uninstall, executed at the end) + + +#include "util_MessageWithURL.isi" + +function Check3264(const pWhich: String): Boolean; +begin + if pWhich = '64' then //x64 or arm64 + Result := Is64BitInstallMode() and (not Force32bitInstall) + else if pWhich = '32' then + Result := (not Is64BitInstallMode()) or Force32bitInstall + else if pWhich = 'x64' then + Result := Is64BitInstallMode() and IsX64 and (not Force32bitInstall) + else if pWhich = 'arm64' then + Result := Is64BitInstallMode() and IsARM64 and (not Force32bitInstall) + else + RaiseException('Unknown check'); +end; + + +#include "util_general.isi" + +//some programs improperly install libraries to the System32 directory, which then causes problems with plugins +//this function checks if such file exists in System32, and lets setup update the file when it exists +function BadSysDLL(const pFile: String; const pPlatform: Integer): Boolean; +var OldRedir: Boolean; +begin + Result := False; + + if pPlatform = 64 then + begin + if Is64BitInstallMode() then //only check when installing in 64bit mode + begin + OldRedir := EnableFsRedirection(False); + DebugMsg('BadSysDLL','64: ' + ExpandConstant('{sys}\' + pFile)); + Result := FileExists(ExpandConstant('{sys}\' + pFile)); + EnableFsRedirection(OldRedir); + end; + end + else if pPlatform = 32 then + begin + if Is64BitInstallMode() then //check 32bit system directory on x64 windows + begin + DebugMsg('BadSysDLL','32on64: ' + ExpandConstant('{syswow64}\' + pFile)); + Result := FileExists(ExpandConstant('{syswow64}\' + pFile)); + end + else + begin + DebugMsg('BadSysDLL','32: ' + ExpandConstant('{sys}\' + pFile)); + Result := FileExists(ExpandConstant('{sys}\' + pFile)); + end; + end + else + begin + RaiseException('Unsupported platform'); + end; + + DebugMsg('BadSysDLL','Result: ' + BoolToStr(Result)); +end; + + +function CheckRegValueExists(const SubKeyName, ValueName: String): Boolean; +begin + Result := RegValueExists(HKEY_AUTO, SubKeyName, ValueName); + DebugMsg('CheckRegValueExists',SubKeyName + ', ' + ValueName + ': ' + BoolToStr(Result)); +end; + + +function DoConfigOverride: Boolean; +var i: Integer; +begin + + if ConfigOverride = coUndefined then + begin + + DebugMsg('DoConfigOverride', 'First call'); + + Result := False; + ConfigOverride := coDontOverride; + + for i := 0 to ParamCount() do //use ParamCount/ParamStr to allow specifying /configoverride without any parameters + if LowerCase(Copy(ParamStr(i),1,15)) = '/' + CONFIG_OVERRIDE_PARAM then + begin + Result := True; + ConfigOverride := coOverride; + break; + end; + + end + else if ConfigOverride = coOverride then + Result := True + else + Result := False; + + DebugMsg('DoConfigOverride', BoolToStr(Result)); +end; + +function GetExternalConfDir(Unused: String): String; +begin + if ExpandConstant('{param:' + CONFIG_OVERRIDE_PARAM + '|<>}') = '<>' then + Result := ExpandConstant('{src}\') + else + Result := ExpandConstant('{param:' + CONFIG_OVERRIDE_PARAM + '|<>}\'); + DebugMsg('GetExternalConfDir', Result); +end; + +function CheckExternalConf(const pFile: String): Boolean; +begin + + if not DoConfigOverride then //no config override + Result := False + else + begin + if FileExists(GetExternalConfDir('') + pFile) then //config file override only applies when that file exists + Result := True + else + Result := False; + end; + DebugMsg('CheckExternalConf', pFile + ': ' + BoolToStr(Result)); +end; + + +procedure PrepareInterp(); +var InterpFile,InterpContent,LuaBin: String; +begin +#ifdef PYTHON + if IsComponentSelected('py') then + begin + StatusLabel(CustomMessage('SettingUpPyGimp'),''); + + InterpFile := ExpandConstant('{app}\lib\gimp\{#DIR_VER}\interpreters\pygimp.interp'); + DebugMsg('PrepareInterp','Writing interpreter file for gimp-python: ' + InterpFile); + +#ifdef DEVEL + #define PYTHON="python.exe" +#else + #define PYTHON="pythonw.exe" +#endif + + InterpContent := 'python=' + ExpandConstant('{app}\bin\{#PYTHON}') + #10 + + 'python3=' + ExpandConstant('{app}\bin\{#PYTHON}') + #10 + + '/usr/bin/python=' + ExpandConstant('{app}\bin\{#PYTHON}') + #10 + + '/usr/bin/python3=' + ExpandConstant('{app}\bin\{#PYTHON}') + #10 + + ':Python:E::py::python:'#10; + + if not SaveStringToUTF8File(InterpFile,InterpContent,False) then + begin + DebugMsg('PrepareInterp','Problem writing the file. [' + InterpContent + ']'); + SuppressibleMsgBox(CustomMessage('ErrorUpdatingPython') + ' (2)',mbInformation,mb_ok,IDOK); + end; + + end; +#endif + +#ifdef LUA + if IsComponentSelected('lua') then + begin + InterpFile := ExpandConstant('{app}\lib\gimp\{#DIR_VER}\interpreters\lua.interp'); + DebugMsg('PrepareInterp','Writing interpreter file for lua: ' + InterpFile); + + if IsComponentSelected('gimpARM64') then + begin + LuaBin := 'lua5.1.exe' + end else + begin + LuaBin := 'luajit.exe' + end; + + InterpContent := 'lua=' + ExpandConstant('{app}\bin\') + LuaBin + #10 + + 'luajit=' + ExpandConstant('{app}\bin\') + LuaBin + #10 + + '/usr/bin/luajit=' + ExpandConstant('{app}\bin\') + LuaBin + #10 + + '/usr/bin/lua=' + ExpandConstant('{app}\bin\') + LuaBin + #10 + + ':Lua:E::lua::' + LuaBin + ':'#10; + + if not SaveStringToUTF8File(InterpFile,InterpContent,False) then + begin + DebugMsg('PrepareInterp','Problem writing the file. [' + InterpContent + ']'); + SuppressibleMsgBox(CustomMessage('ErrorUpdatingPython') + ' (2)',mbInformation,mb_ok,IDOK); + end; + + end; +#endif + +// not optional +// !!! use comma for binfmt delimiter and full Windows path in interpreter field of binfmt +begin + InterpFile := ExpandConstant('{app}\lib\gimp\{#DIR_VER}\interpreters\gimp-script-fu-interpreter.interp'); + DebugMsg('PrepareInterp','Writing interpreter file for gimp-script-fu-interpreter: ' + InterpFile); + + InterpContent := 'gimp-script-fu-interpreter=' + ExpandConstant('{app}\bin\gimp-script-fu-interpreter-3.0.exe') + #10 + + 'gimp-script-fu-interpreter-3.0=' + ExpandConstant('{app}\bin\gimp-script-fu-interpreter-3.0.exe') + #10 + + '/usr/bin/gimp-script-fu-interpreter=' + ExpandConstant('{app}\bin\gimp-script-fu-interpreter-3.0.exe') + #10 + + ',ScriptFu,E,,scm,,' + ExpandConstant('{app}\bin\gimp-script-fu-interpreter-3.0.exe') + ','#10; + + if not SaveStringToUTF8File(InterpFile,InterpContent,False) then + begin + DebugMsg('PrepareInterp','Problem writing the file. [' + InterpContent + ']'); + SuppressibleMsgBox(CustomMessage('ErrorUpdatingScriptFu') + ' (2)',mbInformation,mb_ok,IDOK); + end; +end; + +end; + + +procedure PrepareGimpEnvironment(); +var EnvFile,Env: String; +begin + + StatusLabel(CustomMessage('SettingUpEnvironment'),''); + + //set PATH to be used by plug-ins + EnvFile := ExpandConstant('{app}\lib\gimp\{#DIR_VER}\environ\default.env'); + DebugMsg('PrepareGimpEnvironment','Setting environment in ' + EnvFile); + + Env := #10'PATH=${gimp_installation_dir}\bin'; + + if IsComponentSelected('gimp32on64') then + begin + + Env := Env + ';${gimp_installation_dir}\32\bin' + #10; + + end else + begin + + Env := Env + #10; + + end; + + DebugMsg('PrepareGimpEnvironment','Appending ' + Env); + + if not SaveStringToUTF8File(EnvFile,Env,True) then + begin + DebugMsg('PrepareGimpEnvironment','Problem appending'); + SuppressibleMsgBox(FmtMessage(CustomMessage('ErrorChangingEnviron'),[EnvFile]),mbInformation,mb_ok,IDOK); + end; + + //workaround for high-DPI awareness of Python plug-ins + if IsComponentSelected('py') then + begin + EnvFile := ExpandConstant('{app}\lib\gimp\{#DIR_VER}\environ\pygimp.env'); + DebugMsg('PrepareGimpEnvironment','Setting environment in ' + EnvFile); + + Env := '__COMPAT_LAYER=HIGHDPIAWARE' + #10 + + if not SaveStringToUTF8File(EnvFile,Env,True) then + begin + DebugMsg('PrepareGimpEnvironment','Problem appending'); + SuppressibleMsgBox(FmtMessage(CustomMessage('ErrorChangingEnviron'),[EnvFile]),mbInformation,mb_ok,IDOK); + end; + end; + + // Disable check-update when run with specific option + if ExpandConstant('{param:disablecheckupdate|false}') = 'true' then + begin + EnvFile := ExpandConstant('{app}\share\gimp\{#DIR_VER}\gimp-release'); + DebugMsg('DisableCheckUpdate','Disabling check-update in ' + EnvFile); + + Env := 'check-update=false' + + if not SaveStringToUTF8File(EnvFile,Env,True) then + begin + DebugMsg('PrepareGimpEnvironment','Problem appending'); + SuppressibleMsgBox(FmtMessage(CustomMessage('ErrorChangingEnviron'),[EnvFile]),mbInformation,mb_ok,IDOK); + end; + end; +end; + + +procedure CleanUpCustomWelcome(); +begin + WizardForm.NextButton.Visible := True; + btnInstall.Visible := False; + btnCustomize.Visible := False; + + WizardForm.Bevel.Visible := True; + WelcomeBitmapBottom.Visible := False; +end; + + +procedure InstallOnClick(Sender: TObject); +begin + DebugMsg('Install mode','Simple'); + InstallMode := imSimple; + + CleanUpCustomWelcome(); + + WizardForm.NextButton.OnClick(TNewButton(Sender).Parent); +end; + + +procedure CustomizeOnClick(Sender: TObject); +begin + DebugMsg('Install mode','Custom'); + InstallMode := imCustom; + + CleanUpCustomWelcome(); + + WizardForm.NextButton.OnClick(TNewButton(Sender).Parent); +end; + + +function GetButtonWidth(const Texts: TArrayOfString; const Minimum: Integer): Integer; +var MeasureLabel: TNewStaticText; + i: Integer; +begin + MeasureLabel := TNewStaticText.Create(WizardForm); + with MeasureLabel do + begin + Parent := WizardForm; + Left := 0; + Top := 0; + AutoSize := True; + end; + + Result := Minimum; + + for i := 0 to GetArrayLength(Texts) - 1 do + begin + MeasureLabel.Caption := Texts[i]; + if (MeasureLabel.Width + ScaleX(16)) > Result then + Result := (MeasureLabel.Width + ScaleX(16)); + end; + + MeasureLabel.Free; +end; + + +procedure InitCustomPages(); +var i,ButtonWidth: Integer; + ButtonText: TArrayOfString; + MeasureLabel: TNewStaticText; + //lblInfo: TNewStaticText; +begin + DebugMsg('InitCustomPages','wpLicense'); + + btnInstall := TNewButton.Create(WizardForm); + with btnInstall do + begin + Parent := WizardForm; + Width := WizardForm.NextButton.Width; + Height := WizardForm.NextButton.Height; + Left := WizardForm.NextButton.Left; + Top := WizardForm.NextButton.Top; + Caption := CustomMessage('Install'); + Default := True; + Visible := False; + + OnClick := @InstallOnClick; + end; + + //used to measure text width + MeasureLabel := TNewStaticText.Create(WizardForm); + with MeasureLabel do + begin + Parent := WizardForm; + Left := 0; + Top := 0; + AutoSize := True; + Caption := CustomMessage('Customize'); + end; + + btnCustomize := TNewButton.Create(WizardForm); + with btnCustomize do + begin + Parent := WizardForm; + Width := WizardForm.NextButton.Width; + + if Width < (MeasureLabel.Width + ScaleX(8)) then + Width := MeasureLabel.Width + ScaleX(8); + + Height := WizardForm.NextButton.Height; + Left := WizardForm.ClientWidth - (WizardForm.CancelButton.Left + WizardForm.CancelButton.Width); + //Left := WizardForm.BackButton.Left; + Top := WizardForm.NextButton.Top; + Visible := False; + + Caption := CustomMessage('Customize'); + + OnClick := @CustomizeOnClick; + end; + + MeasureLabel.Free; + +end; + + +procedure SelectComponentsFaceLift(); +var pnlDescription: TPanel; + lblDescription: TNewStaticText; +begin + DebugMsg('SelectComponentsFaceLift',''); + + if WizardForm.ComponentsList.Width = WizardForm.SelectComponentsPage.Width then + WizardForm.ComponentsList.Width := Round(WizardForm.ComponentsList.Width * 0.6) + else + exit; + DebugMsg('SelectComponentsFaceLift','2'); + + WizardForm.ComponentsList.OnClick := @ComponentsListOnClick; + + lblDescription := TNewStaticText.Create(WizardForm.ComponentsList.Parent) + with lblDescription do + begin + Left := WizardForm.ComponentsList.Left + WizardForm.ComponentsList.Width + ScaleX(16); + Top := WizardForm.ComponentsList.Top; + AutoSize := True; + Caption := CustomMessage('ComponentsDescription'); + end; + + pnlDescription := TPanel.Create(WizardForm.ComponentsList.Parent); + with pnlDescription do + begin + Parent := WizardForm.ComponentsList.Parent; + Left := WizardForm.ComponentsList.Left + WizardForm.ComponentsList.Width + ScaleX(8); + Width := WizardForm.TypesCombo.Width - WizardForm.ComponentsList.Width - ScaleX(8); + BevelOuter := bvLowered; + BevelInner := bvRaised; + Top := WizardForm.ComponentsList.Top + Round(lblDescription.Height * 0.4); + Height := WizardForm.ComponentsList.Height - Round(lblDescription.Height * 0.4); + end; + + lblDescription.Parent := WizardForm.ComponentsList.Parent; //place lblDescription above pnlDescription + + lblComponentDescription := TNewStaticText.Create(pnlDescription); + with lblComponentDescription do + begin + Parent := pnlDescription; + Left := ScaleX(8); + WordWrap := True; + AutoSize := False; + Width := Parent.Width - ScaleX(16); + Height := Parent.Height - ScaleY(20); + Top := ScaleY(12); + end; + +end; + + +procedure ReadyFaceLift(); +var rtfNewReadyMemo: TRichEditViewer; +begin + DebugMsg('ReadyFaceLift',''); + WizardForm.ReadyMemo.Visible := False; + + rtfNewReadyMemo := TRichEditViewer.Create(WizardForm.ReadyMemo.Parent); + with rtfNewReadyMemo do + begin + Parent := WizardForm.ReadyMemo.Parent; + Scrollbars := ssVertical; + Color := WizardForm.Color; + UseRichEdit := True; + RTFText := ReadyMemoRichText; + ReadOnly := True; + Left := WizardForm.ReadyMemo.Left; + Top := WizardForm.ReadyMemo.Top; + Width := WizardForm.ReadyMemo.Width; + Height := WizardForm.ReadyMemo.Height; + Visible := True; + end; +end; + + +procedure lblURL_OnClick(Sender: TObject); +var ErrorCode: Integer; +begin + ShellExecAsOriginalUser('',GIMP_URL,'','',SW_SHOW,ewNoWait,ErrorCode); +end; + + +function MeasureLabel(const pText: String): Integer; //WordWrap + AutoSize works better with TNewStaticText than with TLabel, +var lblMeasure: TNewStaticText; //abuse this +begin + lblMeasure := TNewStaticText.Create(WizardForm.InstallingPage); + with lblMeasure do + begin + Parent := WizardForm.InstallingPage; + + AutoSize := True; + WordWrap := True; + Width := Parent.ClientWidth; + + Caption := pText; + + Result := Height; + end; + lblMeasure.Free; +end; + + +procedure InstallingFaceLift(); +var lblMessage1,lblURL,lblMessage2: TLabel; //TNewStaticText doesn't support alignment +begin + with WizardForm.ProgressGauge do + begin + Height := ScaleY(16); + Top := WizardForm.InstallingPage.ClientHeight - Top - Height; + + WizardForm.StatusLabel.Top := Top - WizardForm.FilenameLabel.Height - ScaleY(4); + WizardForm.FilenameLabel.Top := Top + Height + ScaleY(4); + end; + + lblMessage1 := TLabel.Create(WizardForm.InstallingPage); + with lblMessage1 do + begin + Parent := WizardForm.InstallingPage; + + Alignment := taCenter; + WordWrap := True; + AutoSize := False; + Width := WizardForm.InstallingPage.ClientWidth; + Height := MeasureLabel(CustomMessage('Billboard1')); + + Caption := CustomMessage('Billboard1'); + end; + + lblURL := TLabel.Create(WizardForm.InstallingPage); + with lblURL do + begin + Parent := WizardForm.InstallingPage; + + AutoSize := True; + WordWrap := False; + + Font.Color := GetSysColor(COLOR_HOTLIGHT); + Font.Style := [fsUnderline]; + Font.Size := 12; + + Cursor := crHand; + + OnClick := @lblURL_OnClick; + + Caption := GIMP_URL; + + Left := Integer(WizardForm.InstallingPage.ClientWidth / 2 - Width / 2); + end; + + lblMessage2 := TLabel.Create(WizardForm.InstallingPage); + with lblMessage2 do + begin + Parent := WizardForm.InstallingPage; + + Alignment := taCenter; + WordWrap := True; + AutoSize := False; + Width := WizardForm.InstallingPage.ClientWidth; + Height := MeasureLabel(CustomMessage('Billboard2')); + + Caption := CustomMessage('Billboard2'); + end; + + lblMessage1.Top := Integer(WizardForm.StatusLabel.Top / 2 - + (lblMessage1.Height + ScaleY(4) + lblURL.Height + ScaleY(4) + lblMessage2.Height) / 2); + lblURL.Top := lblMessage1.Top + lblMessage1.Height + ScaleY(4); + lblMessage2.Top := lblURL.Top + lblURL.Height + ScaleY(4); + +end; + + +procedure ComponentsListOnClick(pSender: TObject); +var i,j: Integer; + Components: TArrayOfString; + ComponentDesc: String; +begin + DebugMsg('ComponentsListOnClick',''); + + Components := ['Gimp','Deps','Debug','Translations','MyPaint','Python','Ghostscript','Lua','Gimp32']; + ComponentDesc := ''; + + for i := 0 to TNewCheckListBox(pSender).Items.Count - 1 do + if TNewCheckListBox(pSender).Selected[i] then + begin + for j := 0 to Length(Components) - 1 do + begin + if TNewCheckListBox(pSender).Items.Strings[i] = CustomMessage('Components' + Components[j]) then + ComponentDesc := CustomMessage('Components' + Components[j] + 'Description'); + end; + + if ComponentDesc <> '' then + break; + end; + + lblComponentDescription.Caption := ComponentDesc; + +end; + + +function CopyW(const S: String; const Start, Len: Integer): String; //work-around for unicode-related bug in Copy +begin + Result := Copy(S, Start, Len); +end; + +function Unicode2RTF(const pIn: String): String; //convert to RTF-compatible unicode +var i: Integer; + c: SmallInt; +begin + Result := ''; + for i := 1 to Length(pIn) do + if Ord(pIn[i]) <= 127 then + begin + Result := Result + pIn[i]; + end else + begin + c := Ord(pIn[i]); //code points above 7FFF must be expressed as negative numbers + Result := Result + '\u' + IntToStr(c) + '?'; + end; +end; + +function ParseReadyMemoText(pSpaces,pText: String): String; +var sTemp: String; +begin + + sTemp := CopyW(pText,Pos(#10,pText)+1,Length(pText)); + sTemp := Replace('{','\{',sTemp); + sTemp := Replace('\','\\',sTemp); + sTemp := Replace(#13#10,RTFpara,sTemp); + sTemp := Replace(pSpaces,'',sTemp); + sTemp := '\b ' + CopyW(pText,1,Pos(#13,pText)-1) + '\par\sb0' + + '\li284\b0 ' + sTemp + '\par \pard'; + + Result := Unicode2RTF(sTemp); +end; + + +function UpdateReadyMemo(pSpace, pNewLine, pMemoUserInfo, pMemoDirInfo, pMemoTypeInfo, pMemoComponentsInfo, pMemoGroupInfo, pMemoTasksInfo: String): String; +var sText: String; + bShowAssoc: Boolean; + i,j: Integer; +begin + DebugMsg('UpdateReadyMemo',''); + (* Prepare the text for new Ready Memo *) + + sText := RTFHeader; + if pMemoDirInfo <> '' then + sText := sText + ParseReadyMemoText(pSpace,pMemoDirInfo) + '\sb100'; + sText := sText + ParseReadyMemoText(pSpace,pMemoTypeInfo); + sText := sText + '\sb100' + ParseReadyMemoText(pSpace,pMemoComponentsInfo); + + If pMemoTasksInfo<>'' then + sText := sText + '\sb100' + ParseReadyMemoText(pSpace,pMemoTasksInfo); + + ReadyMemoRichText := Copy(sText,1,Length(sText)-6) + '}'; + + Result := 'If you see this, something went wrong'; +end; + + + +procedure UpdateWizardImages(); +var NewBitmap1,NewBitmap2: TFileStream; +begin + WelcomeBitmapBottom := TBitmapImage.Create(WizardForm); + with WelcomeBitmapBottom do + begin + Left := 0; + Top := 0; + Parent := WizardForm; + Width := WizardForm.ClientWidth; + Height := WizardForm.ClientHeight; + Stretch := True; + end; + + DebugMsg('UpdateWizardImages','Height: ' + IntToStr(WizardForm.WizardBitmapImage.Height)); + + if WizardForm.WizardBitmapImage.Height < 386 then //use smaller image when not using Large Fonts + begin + try + NewBitmap1 := TFileStream.Create(ExpandConstant('{tmp}\installsplash_small.bmp'),fmOpenRead); + WizardForm.WizardBitmapImage.Bitmap.LoadFromStream(NewBitmap1); + WelcomeBitmapBottom.Bitmap := WizardForm.WizardBitmapImage.Bitmap; + try + NewBitmap2 := TFileStream.Create(ExpandConstant('{tmp}\windows-installer-intro-small.bmp'),fmOpenRead); + WizardForm.WizardBitmapImage2.Bitmap.LoadFromStream(NewBitmap2); + except + DebugMsg('UpdateWizardImages','Error loading image: ' + GetExceptionMessage); + finally + if NewBitmap2 <> nil then + NewBitmap2.Free; + end; + except + DebugMsg('UpdateWizardImages','Error loading image: ' + GetExceptionMessage); + finally + if NewBitmap1 <> nil then + NewBitmap1.Free; + end; + end + else + begin + try + NewBitmap1 := TFileStream.Create(ExpandConstant('{tmp}\installsplash.bmp'),fmOpenRead); + WizardForm.WizardBitmapImage.Bitmap.LoadFromStream(NewBitmap1); + WelcomeBitmapBottom.Bitmap := WizardForm.WizardBitmapImage.Bitmap; + except + DebugMsg('UpdateWizardImages','Error loading image: ' + GetExceptionMessage); + finally + if NewBitmap1 <> nil then + NewBitmap1.Free; + end; + end; + WizardForm.WizardBitmapImage.Width := WizardForm.ClientWidth; + WizardForm.WizardBitmapImage.Height := WizardForm.ClientHeight; +end; + + +procedure DoUninstall(const UninstStr, InstallDir: String; const pInfoLabel: TNewStaticText; var oResult: TRemoveOldGIMPResult); +var InResult: TRemoveOldGIMPResult; + ResultCode, i: Integer; +begin + InResult := oResult; + + DebugMsg('DoUninstall','Uninstall string: ' + UninstStr); + + //when installing to same directory, assume that restart is required by default ... + if LowerCase(RemoveBackslashUnlessRoot(InstallDir)) = LowerCase(RemoveBackslashUnlessRoot(ExpandConstant('{app}'))) then + oResult := rogRestartRequired + else + oResult := InResult; + + pInfoLabel.Caption := InstallDir; + + if not Exec('>',UninstStr,'',SW_SHOW,ewWaitUntilTerminated,ResultCode) then + begin + DebugMsg('DoUninstall','Exec('+UninstStr+') failed: ' + IntToStr(ResultCode)); + + if not DirExists(InstallDir) then //old install directory doesn't exist, assume it was deleted, and Registry info is orphaned + begin + DebugMsg('DoUninstall','Install directory doesn'#39't exist: ' + InstallDir + ', resuming install'); + oResult := InResult + end else + begin + oResult := rogUninstallFailed; + end; + + exit; + end; + + DebugMsg('DoUninstall','Exec succeeded, uninstaller result: ' + IntToStr(ResultCode)); + + //... unless the complete installation directory was removed on uninstall + i := 0; + while i < (UNINSTALL_MAX_WAIT_TIME / UNINSTALL_CHECK_TIME) do + begin + if not DirExists(ExpandConstant('{app}')) then + begin + DebugMsg('DoUninstall','Existing GIMP directory removed, restoring previous restart requirement'); + oResult := InResult; //restore previous result + break; + end; + DebugMsg('DoUninstall','Waiting for ' + ExpandConstant('{app}') + ' to disappear [' + IntToStr(i) + ']'); + Sleep(UNINSTALL_CHECK_TIME); //it may take a few seconds for the uninstaller to remove the directory after it's exited + Inc(i); + end; +end; + + +function RemoveOldGIMPVersions(): TRemoveOldGIMPResult; +var lblInfo1,lblInfo2: TNewStaticText; + RootKey: Integer; + OldPath, UninstallString, WhichStr: String; +begin + Result := rogContinue; + + lblInfo1 := TNewStaticText.Create(WizardForm.PreparingPage); + with lblInfo1 do + begin + Parent := WizardForm.PreparingPage; + Left := 0; + Top := 0; + AutoSize := True; + WordWrap := True; + Width := WizardForm.PreparingPage.ClientWidth; + + Caption := CustomMessage('RemovingOldVersion'); + end; + lblInfo2 := TNewStaticText.Create(WizardForm.PreparingPage); + with lblInfo2 do + begin + Parent := WizardForm.PreparingPage; + Left := 0; + AutoSize := True; + WordWrap := True; + Width := WizardForm.PreparingPage.ClientWidth; + Top := lblInfo1.Height + ScaleY(8); + end; + + if ExpandConstant('{param:debugresume|0}') = '1' then + Result := rogRestartRequired; //for testing + + if Is64BitInstallMode() then + RootKey := HKLM32 + else + RootKey := HKLM; + + if RegValueExists(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1', + 'Inno Setup: App Path') then + begin + if RegQueryStringValue(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1', + 'Inno Setup: App Path',OldPath) then + begin + DebugMsg('RemoveOldGIMPVersions','Found legacy GIMP install, removing'); + + if RegValueExists(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1', + 'QuietUninstallString') then + WhichStr := 'QuietUninstallString' + else if RegValueExists(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1', + 'UninstallString') then + WhichStr := 'UninstallString' + else + begin + Result := rogCantUninstall; + exit; + end; + + if not RegQueryStringValue(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1', + WhichStr,UninstallString) then + begin + Result := rogCantUninstall; + exit; + end; + + if WhichStr = 'UninstallString' then + UninstallString := UninstallString + ' /SILENT'; + + UninstallString := UninstallString + ' /NORESTART'; + + DoUninstall(UninstallString, OldPath, lblInfo2, Result); + + end; + + end; + + lblInfo1.Free; + lblInfo2.Free; +end; + + +procedure InfoBeforeLikeLicense(); +begin + WizardForm.InfoBeforeClickLabel.Visible := False; + WizardForm.InfoBeforeMemo.Height := WizardForm.InfoBeforeMemo.Height + WizardForm.InfoBeforeMemo.Top - WizardForm.InfoBeforeClickLabel.Top; + WizardForm.InfoBeforeMemo.Top := WizardForm.InfoBeforeClickLabel.Top; +end; + + +procedure PrepareWelcomePage(); +begin + if not WizardSilent then + begin + WizardForm.NextButton.Visible := False; + + btnInstall.Visible := True; + btnInstall.TabOrder := 1; + btnCustomize.Visible := True; + + WizardForm.Bevel.Visible := False; + WizardForm.WelcomeLabel1.Visible := False; + WizardForm.WelcomeLabel2.Visible := False; + + WelcomeBitmapBottom.Visible := True; + end; +end; + + +procedure CurPageChanged(pCurPageID: Integer); +begin + DebugMsg('CurPageChanged','ID: '+IntToStr(pCurPageID)); + case pCurPageID of + wpWelcome: + PrepareWelcomePage(); + wpInfoBefore: + InfoBeforeLikeLicense(); + wpSelectComponents: + SelectComponentsFaceLift(); + wpReady: + ReadyFaceLift(); + wpInstalling: + InstallingFaceLift(); + end; +end; + + +function ShouldSkipPage(pPageID: Integer): Boolean; +begin + DebugMsg('ShouldSkipPage','ID: '+IntToStr(pPageID)); + + Result := ((InstallMode = imSimple) or (InstallMode = imRebootContinue)) and (pPageID <> wpFinished); + //skip all pages except for the finished one if using simple + //install mode + if Result then + DebugMsg('ShouldSkipPage','Yes') + else + DebugMsg('ShouldSkipPage','No'); + +end; + + +procedure RemoveDebugFilesFromDir(pDir: String; var pDirectories: TArrayOfString); +var FindRec: TFindRec; +begin + DebugMsg('RemoveDebugFilesFromDir', pDir); + WizardForm.FilenameLabel.Caption := pDir; + if FindFirst(AddBackSlash(pDir) + '*', FindRec) then + begin + try + repeat + if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then + begin + if (Length(FindRec.Name) > 6) and (LowerCase(Copy(FindRec.Name, Length(FindRec.Name) - 5, 6)) = '.debug') then + begin + DebugMsg('RemoveDebugFilesFromDir', '> ' + FindRec.Name); + DeleteFile(AddBackSlash(pDir) + FindRec.Name); + end; + end else + begin + if (FindRec.Name <> '.') and (FindRec.Name <> '..') then + begin + SetArrayLength(pDirectories, GetArrayLength(pDirectories) + 1); + pDirectories[GetArrayLength(pDirectories) - 1] := AddBackSlash(pDir) + FindRec.Name; + end; + end; + until not FindNext(FindRec); + finally + FindClose(FindRec); + end; + end; +end; + +//remove .debug files from previous installs +//there's no built-in way in Inno to recursively delete files with wildcard+extension +procedure RemoveDebugFiles(); +var Directories: TArrayOfString; + Index: Integer; +begin + SetArrayLength(Directories, 1); + Directories[0] := ExpandConstant('{app}'); + Index := 0; + + WizardForm.StatusLabel.Caption := CustomMessage('RemovingOldFiles'); + + repeat + RemoveDebugFilesFromDir(Directories[Index], Directories); + Inc(Index); + until Index = GetArrayLength(Directories); +end; + + +procedure CurStepChanged(pCurStep: TSetupStep); +begin + case pCurStep of + ssInstall: + begin + RemoveDebugFiles(); + AssociationsCleanup(); + end; + ssPostInstall: + begin + PrepareInterp(); + PrepareGimpEnvironment(); + end; + end; +end; + + +function PrepareToInstall(var pNeedsRestart: Boolean): String; +var ChecksumBefore, ChecksumAfter: String; + RemoveResult: TRemoveOldGIMPResult; +begin + + ChecksumBefore := MakePendingFileRenameOperationsChecksum; + + RemoveResult := RemoveOldGIMPVersions; + + if RemoveResult = rogRestartRequired then //old version was uninstalled, but something was left behind, so to be safe a reboot + begin //is enforced - this can only happen when reusing install directory + + DebugMsg('PrepareToInstall','RemoveOldGIMPVersions requires restart'); + + ChecksumAfter := MakePendingFileRenameOperationsChecksum; + if (ChecksumBefore <> ChecksumAfter) or (ExpandConstant('{param:debugresume|0}') = '1') then + begin //this check is most likely redundant, since the uninstaller will be added to pending rename operations + CreateRunOnceEntry; + pNeedsRestart := True; + Result := CustomMessage('RebootRequiredFirst'); + end; + end else + if RemoveResult = rogContinue then + begin + DebugMsg('PrepareToInstall','RemoveOldGIMPVersions finished successfully'); + Result := ''; //old version was uninstalled successfully, nothing was left behind, so install can continue immediately + end else + if RemoveResult = rogUninstallFailed then + begin + DebugMsg('PrepareToInstall','RemoveOldGIMPVersions failed to uninstall old GIMP version'); + Result := FmtMessage(CustomMessage('RemovingOldVersionFailed'),['{#VERSION}',ExpandConstant('{app}')]); + end else + if RemoveResult = rogCantUninstall then + begin + DebugMsg('PrepareToInstall','RemoveOldGIMPVersions failed to uninstall old GIMP version [1]'); + Result := FmtMessage(CustomMessage('RemovingOldVersionCantUninstall'),['{#VERSION}',ExpandConstant('{app}')]); + end else + begin + DebugMsg('PrepareToInstall','Internal error 11'); + Result := FmtMessage(CustomMessage('InternalError'),['11']); //should never happen + end; + +end; + + +procedure InitializeWizard(); +begin + UpdateWizardImages(); + InitCustomPages(); +end; + + +function BPPTooLowWarning(): Boolean; +var hDC, bpp, pl: Integer; + Message,Buttons: TArrayOfString; +begin + hDC := GetDC(0); + pl := GetDeviceCaps(hDC, PLANES); + bpp := GetDeviceCaps(hDC, BITSPIXEL); + ReleaseDC(0,hDC); + + bpp := pl * bpp; + + if bpp < 32 then + begin + SetArrayLength(Message,1); + SetArrayLength(Buttons,2); + Message[0] := CustomMessage('Require32BPP'); + Buttons[0] := CustomMessage('Require32BPPContinue'); + Buttons[1] := CustomMessage('Require32BPPExit'); + if (not WizardSilent) and + (MessageWithURL(Message, CustomMessage('Require32BPPTitle'), Buttons, mbError, 2, 2) = 2) then + Result := False + else + Result := True; + end + else + Result := True; +end; + + +procedure Check32bitOverride; +var i: Integer; + old: String; +begin + Force32bitInstall := False; + + old := LowerCase(GetPreviousData('32bitMode','')); + + if old = 'true' then //ignore command line if previous install is already present + Force32bitInstall := True + else if old = 'false' then + Force32bitInstall := False + else + for i := 0 to ParamCount do //not a bug (in script anyway) - ParamCount returns the index of last ParamStr element, not the actual count + if ParamStr(i) = '/32' then + begin + Force32bitInstall := True; + break; + end; + + DebugMsg('Check32bitOverride',BoolToStr(Force32bitInstall) + '[' + old + ']'); +end; + + +function InitializeSetup(): Boolean; +#if (Defined(DEVEL) && DEVEL != "") || Defined(DEVEL_WARNING) +var Message,Buttons: TArrayOfString; +#endif +begin + ConfigOverride := coUndefined; + + if not IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE) then + begin + SuppressibleMsgBox(CustomMessage('SSERequired'), mbCriticalError, MB_OK, 0); + Result := false; + exit; + end; + + Check32bitOverride; + + Result := RestartSetupAfterReboot(); //resume install after reboot - skip all setting pages, and install directly + + if Result then + Result := BPPTooLowWarning(); + + if not Result then //no need to do anything else + exit; + +#if (Defined(DEVEL) && DEVEL != "") || Defined(DEVEL_WARNING) + Explode(Message, CustomMessage('DevelopmentWarning'), #13#10); + SetArrayLength(Buttons,2); + Buttons[0] := CustomMessage('DevelopmentButtonContinue'); + Buttons[1] := CustomMessage('DevelopmentButtonExit'); + if (not WizardSilent) and + (MessageWithURL(Message, CustomMessage('DevelopmentWarningTitle'), Buttons, mbError, 2, 2) = 2) then + begin + Result := False; + Exit; + end; +#endif + + try + ExtractTemporaryFile('windows-installer-intro-small.bmp'); + ExtractTemporaryFile('installsplash.bmp'); + ExtractTemporaryFile('installsplash_small.bmp'); + except + DebugMsg('InitializeSetup','Error extracting temporary file: ' + GetExceptionMessage); + MsgBox(CustomMessage('ErrorExtractingTemp') + #13#13 + GetExceptionMessage,mbError,MB_OK); + Result := False; + exit; + end; + + //if InstallMode <> imRebootContinue then + // SuppressibleMsgBox(CustomMessage('UninstallWarning'),mbError,MB_OK,IDOK); + +end; + + +procedure RegisterPreviousData(PreviousDataKey: Integer); +begin + if Is64BitInstallMode() then + SetPreviousData(PreviousDataKey,'32BitMode',BoolToStr(Force32bitInstall)); +end; + + +procedure SaveToUninstInf(const pText: AnsiString); +var sUnInf: String; + sOldContent: String; +begin + sUnInf := ExpandConstant('{app}\uninst\uninst.inf'); + + if not FileExists(sUnInf) then //save small header + SaveStringToUTF8File(sUnInf,#$feff+'#Additional uninstall tasks'#13#10+ //#$feff BOM is required for LoadStringsFromFile + '#This file uses UTF-8 encoding'#13#10+ + '#'#13#10+ + '#Empty lines and lines beginning with # are ignored'#13#10+ + '#'#13#10+ + '#Add uninstallers for GIMP add-ons that should be removed together with GIMP like this:'#13#10+ + '#Run://'#13#10+ + '#'#13#10+ + '#The file is parsed in reverse order' + #13#10 + + '' + #13#10 //needs '' in front, otherwise preprocessor complains + ,False) + else + begin + LoadStringFromUTF8File(sUnInf,sOldContent); + if Pos(#13#10+pText+#13#10,sOldContent) > 0 then //don't write duplicate lines + exit; + end; + + SaveStringToUTF8File(sUnInf,pText+#13#10,True); +end; + +#include "util_rebootcontinue.isi" + +#include "util_uninst.isi" + +#expr SaveToFile(AddBackslash(SourcePath) + "Preprocessed.iss") diff --git a/build/windows/installer/32on64.isi b/build/windows/installer/base_twain32on64.isi similarity index 88% rename from build/windows/installer/32on64.isi rename to build/windows/installer/base_twain32on64.isi index 827a2a0f77..4c2f99180c 100644 --- a/build/windows/installer/32on64.isi +++ b/build/windows/installer/base_twain32on64.isi @@ -1,60 +1,60 @@ -#if 0 -[Files] -#endif -//process list of 32bit GIMP files that are installed on x64 (for TWAIN support) -#pragma option -e- - -#define protected - -#define FileHandle -#define FileLine - -#define ReplPos -#define ReplStr - -#define Line=0 -#define SRC_DIR GIMP_DIR32 - -//avoid too much nesting -#sub DoActualWork - #if Copy(FileLine,Len(FileLine),1)=="\" - //include whole directory -Source: "{#SRC_DIR}\{#FileLine}*"; DestDir: "{app}\32\{#Copy(FileLine,1,Len(FileLine)-1)}"; Components: gimp32on64; Flags: recursesubdirs restartreplace replacesameversion uninsrestartdelete ignoreversion - #else - //include files from a certain directory - #define OutputDir Copy(FileLine,1,RPos("\",FileLine)-1) -Source: "{#SRC_DIR}\{#FileLine}"; DestDir: "{app}\32\{#OutputDir}"; Components: gimp32on64; Flags: restartreplace replacesameversion uninsrestartdelete ignoreversion - #endif -#endsub - -#sub Process32on64Line - #if !defined(Finished) - //show that something's happening - #expr Line=Line+1 - #pragma message "Processing 32on64.list line " + Str(Line) - - #if Copy(FileLine,1,1)=="#" || FileLine=="" - //skip comments and empty lines - #elif Copy(FileLine,1,1)=="!" - #if Copy(FileLine,2)=="GIMP" - #expr SRC_DIR=GIMP_DIR32 - #elif Copy(FileLine,2)=="GTK" - #expr SRC_DIR=DEPS_DIR32 - #elif Copy(FileLine,2)=="end" - #define public Finished 1 - //finished - #else - #error "Unknown command: "+FileLine - #endif - #else - #expr DoActualWork - #endif - #endif -#endsub - -#for {FileHandle = FileOpen(AddBackslash(SourcePath)+"32on64.list"); \ - FileHandle && !FileEof(FileHandle); FileLine = FileRead(FileHandle)} \ - Process32on64Line -#if FileHandle - #expr FileClose(FileHandle) -#endif +#if 0 +[Files] +#endif +//process list of 32bit GIMP files that are installed on x64 (for TWAIN support) +#pragma option -e- + +#define protected + +#define FileHandle +#define FileLine + +#define ReplPos +#define ReplStr + +#define Line=0 +#define SRC_DIR GIMP_DIR32 + +//avoid too much nesting +#sub DoActualWork + #if Copy(FileLine,Len(FileLine),1)=="\" + //include whole directory +Source: "{#SRC_DIR}\{#FileLine}*"; DestDir: "{app}\32\{#Copy(FileLine,1,Len(FileLine)-1)}"; Components: gimp32on64; Flags: recursesubdirs restartreplace replacesameversion uninsrestartdelete ignoreversion + #else + //include files from a certain directory + #define OutputDir Copy(FileLine,1,RPos("\",FileLine)-1) +Source: "{#SRC_DIR}\{#FileLine}"; DestDir: "{app}\32\{#OutputDir}"; Components: gimp32on64; Flags: restartreplace replacesameversion uninsrestartdelete ignoreversion + #endif +#endsub + +#sub Process32on64Line + #if !defined(Finished) + //show that something's happening + #expr Line=Line+1 + #pragma message "Processing base_twain32on64.list line " + Str(Line) + + #if Copy(FileLine,1,1)=="#" || FileLine=="" + //skip comments and empty lines + #elif Copy(FileLine,1,1)=="!" + #if Copy(FileLine,2)=="GIMP" + #expr SRC_DIR=GIMP_DIR32 + #elif Copy(FileLine,2)=="GTK" + #expr SRC_DIR=DEPS_DIR32 + #elif Copy(FileLine,2)=="end" + #define public Finished 1 + //finished + #else + #error "Unknown command: "+FileLine + #endif + #else + #expr DoActualWork + #endif + #endif +#endsub + +#for {FileHandle = FileOpen(AddBackslash(SourcePath)+"base_twain32on64.list"); \ + FileHandle && !FileEof(FileHandle); FileLine = FileRead(FileHandle)} \ + Process32on64Line +#if FileHandle + #expr FileClose(FileHandle) +#endif diff --git a/build/windows/installer/32on64.list b/build/windows/installer/base_twain32on64.list similarity index 70% rename from build/windows/installer/32on64.list rename to build/windows/installer/base_twain32on64.list index 115a476569..a89fda3d62 100644 --- a/build/windows/installer/32on64.list +++ b/build/windows/installer/base_twain32on64.list @@ -1,15 +1,13 @@ -#list of 32bit files to install on x64 -!GTK -etc\fonts\ -#lib\gtk-2.0\2.10.0\loaders\*.dll -#lib\gtk-2.0\modules\*.dll -lib\gdk-pixbuf-2.0\2.10.0\loaders\*.dll -lib\gdk-pixbuf-2.0\2.10.0\loaders.cache -lib\babl-0.1\*.dll -lib\gegl-0.4\*.dll -share\themes\ -bin\gspawn*.exe -bin\*.dll -!GIMP -bin\*.dll -!end +#list of 32bit files to install on x64 +!GTK +etc\fonts\ +lib\gdk-pixbuf-2.0\2.10.0\loaders\*.dll +lib\gdk-pixbuf-2.0\2.10.0\loaders.cache +lib\babl-0.1\*.dll +lib\gegl-0.4\*.dll +share\locale\ +bin\gspawn*.exe +bin\*.dll +!GIMP +bin\*.dll +!end diff --git a/build/windows/installer/compile.bat b/build/windows/installer/compile.bat index 3a1473044a..e4baa3258a 100755 --- a/build/windows/installer/compile.bat +++ b/build/windows/installer/compile.bat @@ -43,7 +43,7 @@ shift goto doparams :paramsdone -"%INNOPATH%\iscc.exe" -DVERSION="%VER%" -DGIMP_DIR="%GIMP_BASE%" -DDIR32="%GIMP32%" -DDIR64="%GIMP64%" -DDEPS_DIR="%DEPS_BASE%" -DDDIR32="%DEPS32%" -DDDIR64="%DEPS64%" -DDIRA64="%GIMPA64%" -DDDIRA64="%DEPSA64%" -DDEBUG_SYMBOLS -DPYTHON -DLUA %PARAMS% gimp3264.iss +"%INNOPATH%\iscc.exe" -DVERSION="%VER%" -DGIMP_DIR="%GIMP_BASE%" -DDIR32="%GIMP32%" -DDIR64="%GIMP64%" -DDEPS_DIR="%DEPS_BASE%" -DDDIR32="%DEPS32%" -DDDIR64="%DEPS64%" -DDIRA64="%GIMPA64%" -DDDIRA64="%DEPSA64%" -DDEBUG_SYMBOLS -DPYTHON -DLUA %PARAMS% base_gimp3264.iss goto :eof :help diff --git a/build/windows/installer/associations.isi b/build/windows/installer/data_associations.isi old mode 100755 new mode 100644 similarity index 95% rename from build/windows/installer/associations.isi rename to build/windows/installer/data_associations.isi index e88d078f41..99cab0f54e --- a/build/windows/installer/associations.isi +++ b/build/windows/installer/data_associations.isi @@ -1,52 +1,52 @@ -[Registry] -#pragma option -e- - -#define protected - -Root: HKA; Subkey: "Software\Classes\Applications\gimp-{#MAJOR}.{#MINOR}.exe"; Flags: uninsdeletekey -Root: HKA; Subkey: "Software\Classes\Applications\gimp-{#MAJOR}.{#MINOR}.exe"; ValueType: string; ValueName: "FriendlyAppName"; ValueData: "GIMP" -Root: HKA; Subkey: "Software\Classes\Applications\gimp-{#MAJOR}.{#MINOR}.exe\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe,1" -Root: HKA; Subkey: "Software\Classes\Applications\gimp-{#MAJOR}.{#MINOR}.exe\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe"" ""%1""" - -Root: HKA; Subkey: "Software\GIMP {#MAJOR}.{#MINOR}"; Flags: uninsdeletekey -Root: HKA; Subkey: "Software\GIMP {#MAJOR}.{#MINOR}\Capabilities"; ValueType: string; ValueName: "ApplicationName"; ValueData: "GIMP" -Root: HKA; Subkey: "Software\GIMP {#MAJOR}.{#MINOR}\Capabilities"; ValueType: string; ValueName: "ApplicationIcon"; ValueData: "{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe,0" -Root: HKA; Subkey: "Software\GIMP {#MAJOR}.{#MINOR}\Capabilities"; ValueType: string; ValueName: "ApplicationDescription"; ValueData: "GIMP is a free raster graphics editor used for image retouching and editing, free-form drawing, converting between different image formats, and more specialized tasks." - -Root: HKA; Subkey: "Software\RegisteredApplications"; ValueType: string; ValueName: "GIMP {#MAJOR}.{#MINOR}"; ValueData: "Software\GIMP {#MAJOR}.{#MINOR}\Capabilities"; Flags: uninsdeletevalue - -#define FileHandle -#define FileLine - -#define Line=0 - -#sub ProcessAssociation - #if !defined(Finished) - #if Copy(FileLine,1,1)=="#" || FileLine=="" - //skip comments and empty lines - #else - #pragma message "Processing associations.list: " + FileLine -; -Root: HKA; Subkey: "Software\Classes\.{#FileLine}\OpenWithProgids"; ValueType: string; ValueName: "GIMP2.{#FileLine}"; ValueData: ""; Flags: uninsdeletevalue -Root: HKA; Subkey: "Software\Classes\GIMP2.{#FileLine}"; ValueType: string; ValueName: ""; ValueData: "GIMP {#ICON_VERSION} {#UpperCase(FileLine)}"; Flags: uninsdeletekey -Root: HKA; Subkey: "Software\Classes\GIMP2.{#FileLine}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe,1" -Root: HKA; Subkey: "Software\Classes\GIMP2.{#FileLine}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe"" ""%1""" -Root: HKA; Subkey: "Software\Classes\Applications\gimp-{#MAJOR}.{#MINOR}.exe\SupportedTypes"; ValueType: string; ValueName: ".{#FileLine}"; ValueData: "" -Root: HKA; Subkey: "Software\GIMP {#MAJOR}.{#MINOR}\Capabilities\FileAssociations"; ValueType: string; ValueName: ".{#FileLine}"; ValueData: "GIMP2.{#FileLine}" - #endif - #endif -#endsub - -#for {FileHandle = FileOpen(AddBackslash(SourcePath)+"associations.list"); \ - FileHandle && !FileEof(FileHandle); FileLine = FileRead(FileHandle)} \ - ProcessAssociation -#if FileHandle - #expr FileClose(FileHandle) -#endif -;special case for .ico files -Root: HKA; Subkey: "Software\Classes\.ico\OpenWithProgids"; ValueType: string; ValueName: "GIMP2.ico"; ValueData: ""; Flags: uninsdeletevalue -Root: HKA; Subkey: "Software\Classes\GIMP2.ico"; ValueType: string; ValueName: ""; ValueData: "GIMP {#ICON_VERSION}"; Flags: uninsdeletekey -Root: HKA; Subkey: "Software\Classes\GIMP2.ico\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "%1" -Root: HKA; Subkey: "Software\Classes\GIMP2.ico\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe"" ""%1""" -Root: HKA; Subkey: "Software\Classes\Applications\gimp-{#MAJOR}.{#MINOR}.exe\SupportedTypes"; ValueType: string; ValueName: ".ico"; ValueData: "" -Root: HKA; Subkey: "Software\GIMP {#MAJOR}.{#MINOR}\Capabilities\FileAssociations"; ValueType: string; ValueName: ".ico"; ValueData: "GIMP2.{#FileLine}" +[Registry] +#pragma option -e- + +#define protected + +Root: HKA; Subkey: "Software\Classes\Applications\gimp-{#MAJOR}.{#MINOR}.exe"; Flags: uninsdeletekey +Root: HKA; Subkey: "Software\Classes\Applications\gimp-{#MAJOR}.{#MINOR}.exe"; ValueType: string; ValueName: "FriendlyAppName"; ValueData: "GIMP" +Root: HKA; Subkey: "Software\Classes\Applications\gimp-{#MAJOR}.{#MINOR}.exe\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe,1" +Root: HKA; Subkey: "Software\Classes\Applications\gimp-{#MAJOR}.{#MINOR}.exe\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe"" ""%1""" + +Root: HKA; Subkey: "Software\GIMP {#MAJOR}.{#MINOR}"; Flags: uninsdeletekey +Root: HKA; Subkey: "Software\GIMP {#MAJOR}.{#MINOR}\Capabilities"; ValueType: string; ValueName: "ApplicationName"; ValueData: "GIMP" +Root: HKA; Subkey: "Software\GIMP {#MAJOR}.{#MINOR}\Capabilities"; ValueType: string; ValueName: "ApplicationIcon"; ValueData: "{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe,0" +Root: HKA; Subkey: "Software\GIMP {#MAJOR}.{#MINOR}\Capabilities"; ValueType: string; ValueName: "ApplicationDescription"; ValueData: "GIMP is a free raster graphics editor used for image retouching and editing, free-form drawing, converting between different image formats, and more specialized tasks." + +Root: HKA; Subkey: "Software\RegisteredApplications"; ValueType: string; ValueName: "GIMP {#MAJOR}.{#MINOR}"; ValueData: "Software\GIMP {#MAJOR}.{#MINOR}\Capabilities"; Flags: uninsdeletevalue + +#define FileHandle +#define FileLine + +#define Line=0 + +#sub ProcessAssociation + #if !defined(Finished) + #if Copy(FileLine,1,1)=="#" || FileLine=="" + //skip comments and empty lines + #else + #pragma message "Processing data_associations.list: " + FileLine +; +Root: HKA; Subkey: "Software\Classes\.{#FileLine}\OpenWithProgids"; ValueType: string; ValueName: "GIMP2.{#FileLine}"; ValueData: ""; Flags: uninsdeletevalue +Root: HKA; Subkey: "Software\Classes\GIMP2.{#FileLine}"; ValueType: string; ValueName: ""; ValueData: "GIMP {#ICON_VERSION} {#UpperCase(FileLine)}"; Flags: uninsdeletekey +Root: HKA; Subkey: "Software\Classes\GIMP2.{#FileLine}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe,1" +Root: HKA; Subkey: "Software\Classes\GIMP2.{#FileLine}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe"" ""%1""" +Root: HKA; Subkey: "Software\Classes\Applications\gimp-{#MAJOR}.{#MINOR}.exe\SupportedTypes"; ValueType: string; ValueName: ".{#FileLine}"; ValueData: "" +Root: HKA; Subkey: "Software\GIMP {#MAJOR}.{#MINOR}\Capabilities\FileAssociations"; ValueType: string; ValueName: ".{#FileLine}"; ValueData: "GIMP2.{#FileLine}" + #endif + #endif +#endsub + +#for {FileHandle = FileOpen(AddBackslash(SourcePath)+"data_associations.list"); \ + FileHandle && !FileEof(FileHandle); FileLine = FileRead(FileHandle)} \ + ProcessAssociation +#if FileHandle + #expr FileClose(FileHandle) +#endif +;special case for .ico files +Root: HKA; Subkey: "Software\Classes\.ico\OpenWithProgids"; ValueType: string; ValueName: "GIMP2.ico"; ValueData: ""; Flags: uninsdeletevalue +Root: HKA; Subkey: "Software\Classes\GIMP2.ico"; ValueType: string; ValueName: ""; ValueData: "GIMP {#ICON_VERSION}"; Flags: uninsdeletekey +Root: HKA; Subkey: "Software\Classes\GIMP2.ico\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "%1" +Root: HKA; Subkey: "Software\Classes\GIMP2.ico\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe"" ""%1""" +Root: HKA; Subkey: "Software\Classes\Applications\gimp-{#MAJOR}.{#MINOR}.exe\SupportedTypes"; ValueType: string; ValueName: ".ico"; ValueData: "" +Root: HKA; Subkey: "Software\GIMP {#MAJOR}.{#MINOR}\Capabilities\FileAssociations"; ValueType: string; ValueName: ".ico"; ValueData: "GIMP2.{#FileLine}" diff --git a/build/windows/installer/associations.list b/build/windows/installer/data_associations.list similarity index 100% rename from build/windows/installer/associations.list rename to build/windows/installer/data_associations.list diff --git a/build/windows/installer/configoverride.isi b/build/windows/installer/data_configoverride.isi similarity index 97% rename from build/windows/installer/configoverride.isi rename to build/windows/installer/data_configoverride.isi index af663771ee..7e37a01184 100644 --- a/build/windows/installer/configoverride.isi +++ b/build/windows/installer/data_configoverride.isi @@ -1,36 +1,36 @@ -;allow specific configuration files to be overridden by files in a specific directory -#if 0 -[Files] -#endif - -#define FindHandle -#define FindResult - -#sub ProcessConfigFile - #define FileName FindGetFileName(FindHandle) -Source: "{code:GetExternalConfDir}\{#FileName}"; DestDir: "{app}\{#ConfigDir}"; Flags: external restartreplace; Check: CheckExternalConf('{#FileName}') - #if BaseDir != GIMP_DIR32 -Source: "{code:GetExternalConfDir}\{#FileName}"; DestDir: "{app}\32\{#ConfigDir}"; Components: gimp32on64; Flags: external restartreplace; Check: CheckExternalConf('{#FileName}') - #endif -#endsub - -#sub ProcessConfigDir - #emit ';; ' + ConfigDir - #emit ';; ' + BaseDir - #for {FindHandle = FindResult = FindFirst(AddBackslash(BaseDir) + AddBackSlash(ConfigDir) + "*", 0); \ - FindResult; FindResult = FindNext(FindHandle)} ProcessConfigFile - #if FindHandle - #expr FindClose(FindHandle) - #endif -#endsub - -#define public BaseDir GIMP_DIR32 -#define public ConfigDir "etc\gimp\2.0" -#expr ProcessConfigDir - -#define public BaseDir DEPS_DIR32 -#define public ConfigDir "etc\gtk-2.0" -#expr ProcessConfigDir - -#define public ConfigDir "etc\fonts" -#expr ProcessConfigDir +;allow specific configuration files to be overridden by files in a specific directory +#if 0 +[Files] +#endif + +#define FindHandle +#define FindResult + +#sub ProcessConfigFile + #define FileName FindGetFileName(FindHandle) +Source: "{code:GetExternalConfDir}\{#FileName}"; DestDir: "{app}\{#ConfigDir}"; Flags: external restartreplace; Check: CheckExternalConf('{#FileName}') + #if BaseDir != GIMP_DIR32 +Source: "{code:GetExternalConfDir}\{#FileName}"; DestDir: "{app}\32\{#ConfigDir}"; Components: gimp32on64; Flags: external restartreplace; Check: CheckExternalConf('{#FileName}') + #endif +#endsub + +#sub ProcessConfigDir + #emit ';; ' + ConfigDir + #emit ';; ' + BaseDir + #for {FindHandle = FindResult = FindFirst(AddBackslash(BaseDir) + AddBackSlash(ConfigDir) + "*", 0); \ + FindResult; FindResult = FindNext(FindHandle)} ProcessConfigFile + #if FindHandle + #expr FindClose(FindHandle) + #endif +#endsub + +#define public BaseDir GIMP_DIR32 +#define public ConfigDir "etc\gimp\2.0" +#expr ProcessConfigDir + +#define public BaseDir DEPS_DIR32 +#define public ConfigDir "etc\gtk-2.0" +#expr ProcessConfigDir + +#define public ConfigDir "etc\fonts" +#expr ProcessConfigDir diff --git a/build/windows/installer/files.isi b/build/windows/installer/files.isi deleted file mode 100644 index 7ec33ef2b6..0000000000 --- a/build/windows/installer/files.isi +++ /dev/null @@ -1,70 +0,0 @@ -#if 0 -[Files] -#endif - -#if PLATFORM==X86 - #define DIR DIR32 - #define DDIR DDIR32 - #define COMPONENT "32" -#elif PLATFORM==X64 - #define DIR DIR64 - #define DDIR DDIR64 - #define COMPONENT "64" -#elif PLATFORM==ARM64 - #define DIR DIRA64 - #define DDIR DDIRA64 - #define COMPONENT "ARM64" -#else - #error "Unknown PLATFORM:" + PLATFORM -#endif - -Source: "{#GIMP_DIR}\{#DIR}\*.dll"; DestDir: "{app}"; Components: gimp{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -Source: "{#GIMP_DIR}\{#DIR}\*.exe"; DestDir: "{app}"; Excludes: "\lib\gimp\{#DIR_VER}\plug-ins\twain\twain.exe,\lib\gimp\{#DIR_VER}\plug-ins\file-ps\file-ps.exe,\bin\gimp.exe,\bin\gimp-console.exe"; Components: gimp{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -#ifdef DEBUG_SYMBOLS -Source: "{#GIMP_DIR}\{#DIR}\*.debug"; DestDir: "{app}"; Components: gimp{#COMPONENT} and debug; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -#endif -Source: "{#GIMP_DIR}\{#DIR}\lib\gimp\{#DIR_VER}\extensions\*.*"; Excludes: "*.debug"; DestDir: "{app}\lib\gimp\{#DIR_VER}\extensions"; Components: gimp{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -#ifdef DEBUG_SYMBOLS -Source: "{#GIMP_DIR}\{#DIR}\lib\gimp\{#DIR_VER}\extensions\*.debug"; DestDir: "{app}\lib\gimp\{#DIR_VER}\extensions"; Components: gimp{#COMPONENT} and debug; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -#endif - -Source: "{#GIMP_DIR}\{#DIR}\lib\gimp\{#DIR_VER}\plug-ins\file-ps\file-ps.exe"; DestDir: "{app}\lib\gimp\{#DIR_VER}\plug-ins\file-ps"; Components: gs and gimp{#COMPONENT}; Flags: restartreplace ignoreversion uninsrestartdelete - -Source: "{#GIMP_DIR}\{#DIR}\lib\girepository-1.0\*.*"; DestDir: "{app}\lib\girepository-1.0"; Components: gimp{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -Source: "{#DEPS_DIR}\{#DDIR}\lib\girepository-1.0\*.*"; DestDir: "{app}\lib\girepository-1.0"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete - -Source: "{#DEPS_DIR}\{#DDIR}\bin\*.dll"; DestDir: "{app}\bin"; Excludes: "\bin\libgs*.dll,\bin\lua*.dll"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -Source: "{#DEPS_DIR}\{#DDIR}\bin\libgs*.dll"; DestDir: "{app}\bin"; Components: gs and deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -#ifdef DEBUG_SYMBOLS -Source: "{#DEPS_DIR}\{#DDIR}\bin\.debug\*.dll.debug"; DestDir: "{app}\bin\.debug"; Components: deps{#COMPONENT} and debug; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete skipifsourcedoesntexist -Source: "{#DEPS_DIR}\{#DDIR}\lib\*.debug"; DestDir: "{app}\lib"; Components: deps{#COMPONENT} and debug; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete skipifsourcedoesntexist -#endif - -Source: "{#DEPS_DIR}\{#DDIR}\bin\gspawn-win*.exe"; DestDir: "{app}\bin"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -Source: "{#DEPS_DIR}\{#DDIR}\bin\gdk-pixbuf-query-loaders.exe"; DestDir: "{app}\bin"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -Source: "{#DEPS_DIR}\{#DDIR}\bin\bzip2.exe"; DestDir: "{app}\bin"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -Source: "{#DEPS_DIR}\{#DDIR}\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache"; DestDir: "{app}\lib\gdk-pixbuf-2.0\2.10.0\"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -Source: "{#DEPS_DIR}\{#DDIR}\lib\babl-0.1\*.dll"; DestDir: "{app}\lib\babl-0.1"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -Source: "{#DEPS_DIR}\{#DDIR}\lib\gdk-pixbuf-2.0\*.dll"; DestDir: "{app}\lib\gdk-pixbuf-2.0"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -Source: "{#DEPS_DIR}\{#DDIR}\lib\gegl-0.4\*.dll"; DestDir: "{app}\lib\gegl-0.4"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -Source: "{#DEPS_DIR}\{#DDIR}\lib\gio\*.dll"; DestDir: "{app}\lib\gio"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -;Source: "{#DEPS_DIR}\{#DDIR}\lib\gtk-3.0\*.dll"; DestDir: "{app}\lib\gtk-3.0"; Components: deps{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete - -;python scripts -#ifdef PYTHON -Source: "{#DEPS_DIR}\{#DDIR}\bin\python3w.exe"; DestDir: "{app}\bin"; DestName: "pythonw.exe"; Components: py and gimp{#COMPONENT}; Flags: restartreplace uninsrestartdelete ignoreversion -Source: "{#DEPS_DIR}\{#DDIR}\bin\python3.exe"; DestDir: "{app}\bin"; DestName: "python.exe"; Components: py and gimp{#COMPONENT}; Flags: restartreplace uninsrestartdelete ignoreversion -Source: "{#DEPS_DIR}\{#DDIR}\bin\libpython3.11.dll"; DestDir: "{app}\bin"; Components: py and gimp{#COMPONENT}; Flags: restartreplace uninsrestartdelete ignoreversion -Source: "{#DEPS_DIR}\{#DDIR}\lib\python3.11\*"; DestDir: "{app}\lib\python3.11"; Components: py and gimp{#COMPONENT}; Flags: recursesubdirs restartreplace uninsrestartdelete ignoreversion -#endif - -#ifdef LUA -#if PLATFORM==ARM64 -Source: "{#DEPS_DIR}\{#DDIR}\bin\lua5.1.exe"; DestDir: "{app}\bin"; Components: lua and gimp{#COMPONENT}; Flags: restartreplace uninsrestartdelete ignoreversion -#else -Source: "{#DEPS_DIR}\{#DDIR}\bin\luajit.exe"; DestDir: "{app}\bin"; Components: lua and gimp{#COMPONENT}; Flags: restartreplace uninsrestartdelete ignoreversion -#endif -Source: "{#DEPS_DIR}\{#DDIR}\bin\lua51.dll"; DestDir: "{app}\bin"; Components: lua and gimp{#COMPONENT}; Flags: restartreplace uninsrestartdelete ignoreversion -Source: "{#DEPS_DIR}\{#DDIR}\share\lua\*"; DestDir: "{app}\share\lua"; Components: lua and gimp{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -Source: "{#DEPS_DIR}\{#DDIR}\lib\lua\*"; DestDir: "{app}\lib\lua"; Components: lua and gimp{#COMPONENT}; Flags: recursesubdirs restartreplace ignoreversion uninsrestartdelete -#endif diff --git a/build/windows/installer/lang/test-installer-langs.sh b/build/windows/installer/lang/test-installer-langs.sh index 2719fdee0b..3d24f83de4 100755 --- a/build/windows/installer/lang/test-installer-langs.sh +++ b/build/windows/installer/lang/test-installer-langs.sh @@ -4,7 +4,7 @@ # translations present. This check step is necessary to not forget new # installer translations because we have a manual step. -INSTALLER_LANGS=`grep -rI '^Name:.*MessagesFile' ${GIMP_TESTING_ABS_TOP_SRCDIR}/build/windows/installer/gimp3264.iss | \ +INSTALLER_LANGS=`grep -rI '^Name:.*MessagesFile' ${GIMP_TESTING_ABS_TOP_SRCDIR}/build/windows/installer/base_gimp3264.iss | \ sed 's/^Name: *"\([a-zA-Z_]*\)".*$/\1/' | sort` # 'en' doesn't have a gettext file because it is the default. INSTALLER_LANGS=`echo "$INSTALLER_LANGS" | tr '\n\r' ' ' | sed 's/\ //'` @@ -17,7 +17,7 @@ if [ "$PO_LANGS" != "$INSTALLER_LANGS" ]; then echo "Error: languages listed in the Windows installer script do not match the .po files in po-windows-installer/." echo "- PO languages: $PO_LANGS" echo "- Installer languages: $INSTALLER_LANGS" - echo "Please verify: build/windows/installer/gimp3264.iss" + echo "Please verify: build/windows/installer/base_gimp3264.iss" echo "Base language files can be found in: https://github.com/jrsoftware/issrc/tree/main/Files/Languages" echo "If a new language is in Unofficial/, also edit/download it from:" echo "build/windows/gitlab-ci/4_installer-gimp-msys2.sh" @@ -36,7 +36,7 @@ if [ "$PO_LANGS" != "$MESON_LANGS" ]; then exit 1 fi -INSTALLER_LANGS=`grep -rI '^Name:.*MessagesFile.*Unofficial' ${GIMP_TESTING_ABS_TOP_SRCDIR}/build/windows/installer/gimp3264.iss | \ +INSTALLER_LANGS=`grep -rI '^Name:.*MessagesFile.*Unofficial' ${GIMP_TESTING_ABS_TOP_SRCDIR}/build/windows/installer/base_gimp3264.iss | \ sed 's/^.*Unofficial\\\\\([a-zA-Z_.]*\),.*$/\1/' | sort` INSTALLER_LANGS=`echo "$INSTALLER_LANGS" | tr '\n\r' ' '` diff --git a/build/windows/installer/MessageWithURL.isi b/build/windows/installer/util_MessageWithURL.isi similarity index 96% rename from build/windows/installer/MessageWithURL.isi rename to build/windows/installer/util_MessageWithURL.isi index 5e5842bc0d..407294d8d3 100644 --- a/build/windows/installer/MessageWithURL.isi +++ b/build/windows/installer/util_MessageWithURL.isi @@ -1,504 +1,504 @@ -[Code] -(* MessageWithURL - * - * Copyright (c) 2010-2011 Jernej Simončič - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must - * not claim that you wrote the original software. If you use this - * software in a product, an acknowledgment in the product - * documentation would be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must - * not be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - *) - -(* * * * * * * * * * - * MessageWithURL(Message: TArrayOfString; Title: String: ButtonText: TArrayOfString; Typ: TMsgBoxType; - * DefaultButton, CancelButton: Integer): Integer; - * - * Parameters: - * Title dialog box caption - * Message messages to display; if a message starts with _, the text following it up to the first space character - * is interpreted as URL, and the rest of the message is used as clickable text for that URL - * Typ icon to show - * ButtonText buttons to show under the text - * DefaultButton default button (first button = 1) - * CancelButton cancel button (first button = 1) - * - * Return value button that was clicked (first button = 1); if running in silent mode, DefaultButton is returned - *) -function MessageWithURL(Message: TArrayOfString; const Title: String; ButtonText: TArrayOfString; const Typ: TMsgBoxType; - const DefaultButton, CancelButton: Integer): Integer; forward; - -function GetSystemMetrics(nIndex: Integer): Integer; external 'GetSystemMetrics@User32 stdcall'; -function GetDialogBaseUnits(): Integer; external 'GetDialogBaseUnits@User32 stdcall'; - -//function GetSysColor(nIndex: Integer): DWORD; external 'GetSysColor@user32.dll stdcall'; - -function LoadIcon(hInstance: Integer; lpIconName: Integer): Integer; external 'LoadIconW@user32 stdcall'; -//function LoadImage(hinst: Integer; lpszName: Integer; uType: Cardinal; cxDesired, cyDesired: Integer; fuLoad: Cardinal): Integer; external 'LoadImageW@user32 stdcall'; -function DrawIcon(hdc: HBitmap; x,y: Integer; hIcon: Integer): Integer; external 'DrawIcon@user32 stdcall'; -//function DrawIconEx(hdc: HBitmap; xLeft,yTop: Integer; hIcon: Integer; cxWidth, cyWidth: Integer; istepIfAniCur: Cardinal; hbrFlickerFreeDraw: Integer; diFlags: Cardinal): Integer; external 'DrawIconEx@user32 stdcall'; -//function DestroyIcon(hIcon: Integer): Integer; external 'DestroyIcon@user32 stdcall'; - -function DrawFocusRect(hDC: Integer; var lprc: TRect): BOOL; external 'DrawFocusRect@user32 stdcall'; - -type - TArrayOfButton = Array of TNewButton; - -const - //borders around message - MWU_LEFTBORDER = 25; - MWU_RIGHTBORDER = MWU_LEFTBORDER; - MWU_TOPBORDER = 26; - MWU_BOTTOMBORDER = MWU_TOPBORDER; - //space between elements (icon-text and between buttons) - MWU_HORZSPACING = 8; - //space between labels - MWU_VERTSPACING = 4; - //button sizes - MWU_BUTTONHEIGHT = 24; - MWU_MINBUTTONWIDTH = 86; - //height of area where buttons are placed - MWU_BUTTONAREAHEIGHT = 45; - - SM_CXSCREEN = 0; - SM_CXICON = 11; - SM_CYICON = 12; - SM_CXICONSPACING = 38; - SM_CYICONSPACING = 39; - - //COLOR_HOTLIGHT = 26; - - OIC_HAND = 32513; - OIC_QUES = 32514; - OIC_BANG = 32515; - OIC_NOTE = 32516; - - LR_DEFAULTSIZE = $00000040; - LR_SHARED = $00008000; - - IMAGE_BITMAP = 0; - IMAGE_ICON = 1; - IMAGE_CURSOR = 2; - - DI_IMAGE = 1; - DI_MASK = 2; - DI_NORMAL = DI_IMAGE or DI_MASK; - DI_DEFAULTSIZE = 8; - -var - URLList: TArrayOfString; - TextLabel: Array of TNewStaticText; - URLFocusImg: Array of TBitmapImage; - SingleLineHeight: Integer; - - -procedure UrlClick(Sender: TObject); -var ErrorCode: Integer; -begin - ShellExecAsOriginalUser('open',URLList[TNewStaticText(Sender).Tag],'','',SW_SHOWNORMAL,ewNoWait,ErrorCode); -end; - - -// calculates maximum width of text labels -// also counts URLs, and sets the length of URLList accordingly -function Message_CalcLabelWidth(var Message: TArrayOfString; MessageForm: TSetupForm): Integer; -var MeasureLabel: TNewStaticText; - i,URLCount,DlgUnit,ScreenWidth: Integer; -begin - MeasureLabel := TNewStaticText.Create(MessageForm); - with MeasureLabel do - begin - Parent := MessageForm; - Left := 0; - Top := 0; - AutoSize := True; - end; - - MeasureLabel.Caption := 'X'; - SingleLineHeight := MeasureLabel.Height; - - Result := 0; //minimum width - URLCount := 0; - for i := 0 to GetArrayLength(Message) - 1 do - begin - if Length(Message[i]) < 1 then //simplifies things - Message[i] := ' '; - - if Message[i][1] <> '_' then - MeasureLabel.Caption := Message[i] //not an URL - else - begin //URL - check only the displayed text - if Pos(' ',Message[i]) > 0 then - MeasureLabel.Caption := Copy(Message[i],Pos(' ',Message[i])+1,Length(Message[i])) - else - MeasureLabel.Caption := Copy(Message[i],2,Length(Message[i])); - - URLCount := URLCount + 1; - end; - - if MeasureLabel.Width > Result then - Result := MeasureLabel.Width; - end; - MeasureLabel.Free; - - SetArrayLength(URLList,URLCount); //needed later - no need to do a special loop just for this - SetArrayLength(URLFocusImg,URLCount); - - DlgUnit := GetDialogBaseUnits() and $FFFF; //ensure the dialog isn't too wide - ScreenWidth := GetSystemMetrics(SM_CXSCREEN); - if Result > ((278 * DlgUnit) div 4) then //278 is from http://blogs.msdn.com/b/oldnewthing/archive/2011/06/24/10178386.aspx - Result := ((278 * DlgUnit) div 4); - if Result > (ScreenWidth * 3) div 4 then - Result := (ScreenWidth * 3) div 4; - -end; - - -//find the longest button -function Message_CalcButtonWidth(const ButtonText: TArrayOfString; MessageForm: TSetupForm): Integer; -var MeasureLabel: TNewStaticText; - i: Integer; -begin - MeasureLabel := TNewStaticText.Create(MessageForm); - with MeasureLabel do - begin - Parent := MessageForm; - Left := 0; - Top := 0; - AutoSize := True; - end; - - Result := ScaleX(MWU_MINBUTTONWIDTH - MWU_HORZSPACING * 2); //minimum width - for i := 0 to GetArrayLength(ButtonText) - 1 do - begin - MeasureLabel.Caption := ButtonText[i] - - if MeasureLabel.Width > Result then - Result := MeasureLabel.Width; - end; - MeasureLabel.Free; - - Result := Result + ScaleX(MWU_HORZSPACING * 2); //account for borders -end; - - -procedure Message_Icon(const Typ: TMsgBoxType; TypImg: TBitmapImage); -var TypRect: TRect; - Icon: THandle; - TypIcon: Integer; -begin - TypRect.Left := 0; - TypRect.Top := 0; - TypRect.Right := GetSystemMetrics(SM_CXICON); - TypRect.Bottom := GetSystemMetrics(SM_CYICON); - - case Typ of - mbInformation: - TypIcon := OIC_NOTE; - mbConfirmation: - TypIcon := OIC_QUES; - mbError: - TypIcon := OIC_BANG; - else - TypIcon := OIC_HAND; - end; - - //TODO: icon loads with wrong size when using Large Fonts (SM_CXICON/CYICON is 40, but 32x32 icon loads - find out how to get the right size) - Icon := LoadIcon(0,TypIcon); - //Icon := LoadImage(0,TypIcon,IMAGE_ICON,0,0,LR_SHARED or LR_DEFAULTSIZE); - with TypImg do - begin - Left := ScaleX(MWU_LEFTBORDER); - Top := ScaleY(MWU_TOPBORDER); - Center := False; - Stretch := False; - AutoSize := True; - Bitmap.Width := GetSystemMetrics(SM_CXICON); - Bitmap.Height := GetSystemMetrics(SM_CYICON); - Bitmap.Canvas.Brush.Color := TPanel(Parent).Color; - Bitmap.Canvas.FillRect(TypRect); - DrawIcon(Bitmap.Canvas.Handle,0,0,Icon); //draws icon scaled - //DrawIconEx(Bitmap.Canvas.Handle,0,0,Icon,0,0,0,0,DI_NORMAL {or DI_DEFAULTSIZE}); //draws icon without scaling - end; - //DestroyIcon(Icon); //not needed with LR_SHARED or with LoadIcon -end; - - -procedure Message_SetUpURLLabel(URLLabel: TNewStaticText; const Msg: String; const URLNum: Integer); -var Blank: TRect; -begin - with URLLabel do - begin - if Pos(' ',Msg) > 0 then - begin - Caption := Copy(Msg,Pos(' ',Msg)+1,Length(Msg)); - URLList[URLNum] := Copy(Msg, 2, Pos(' ',Msg)-1); - end - else - begin //no text after URL - display just URL - URLList[URLNum] := Copy(Msg, 2, Length(Msg)); - Caption := URLList[URLNum]; - end; - - Hint := URLList[URLNum]; - ShowHint := True; - - Font.Color := GetSysColor(COLOR_HOTLIGHT); - Font.Style := [fsUnderline]; - Cursor := crHand; - OnClick := @UrlClick; - - Tag := URLNum; //used to find the URL to open and bitmap to draw focus rectangle on - - if Height = SingleLineHeight then //shrink label to actual text width - WordWrap := False; - - TabStop := True; //keyboard accessibility - TabOrder := URLNum; - end; - - URLFocusImg[URLNum] := TBitmapImage.Create(URLLabel.Parent); //focus rectangle needs a bitmap - prepare it here - with URLFocusImg[URLNum] do - begin - Left := URLLabel.Left - 1; - Top := URLLabel.Top - 1; - Stretch := False; - AutoSize := True; - Parent := URLLabel.Parent; - Bitmap.Width := URLLabel.Width + 2; - Bitmap.Height := URLLabel.Height + 2; - - SendToBack; - - Blank.Left := 0; - Blank.Top := 0; - Blank.Right := Width; - Blank.Bottom := Height; - Bitmap.Canvas.Brush.Color := TPanel(Parent).Color; - Bitmap.Canvas.FillRect(Blank); - end; -end; - - -procedure Message_SetUpLabels(Message: TArrayOfString; TypImg: TBitmapImage; - const DialogTextWidth: Integer; MessagePanel: TPanel); -var i,URLNum,dy: Integer; -begin - SetArrayLength(TextLabel,GetArrayLength(Message)); - URLNum := 0; - for i := 0 to GetArrayLength(TextLabel) - 1 do - begin - TextLabel[i] := TNewStaticText.Create(MessagePanel); - with TextLabel[i] do - begin - Parent := MessagePanel; - Left := TypImg.Left + TypImg.Width + ScaleX(MWU_HORZSPACING); - if i = 0 then - Top := TypImg.Top - else - Top := TextLabel[i-1].Top + TextLabel[i-1].Height + ScaleY(MWU_VERTSPACING); - - WordWrap := True; - AutoSize := True; - Width := DialogTextWidth; - - if Message[i][1] <> '_' then - Caption := Message[i] - else - begin // apply URL formatting - Message_SetUpURLLabel(TextLabel[i], Message[i], URLNum); - URLNum := URLNum + 1; - end; - - end; - end; - - i := GetArrayLength(TextLabel) - 1; - if TextLabel[i].Top + TextLabel[i].Height < TypImg.Top + TypImg.Height then //center labels vertically - begin - dy := (TypImg.Top + TypImg.Height - TextLabel[i].Top - TextLabel[i].Height) div 2; - for i := 0 to GetArrayLength(TextLabel) - 1 do - TextLabel[i].Top := TextLabel[i].Top + dy; - end; -end; - - -procedure Message_SetUpButtons(var Button: TArrayOfButton; ButtonText: TArrayOfString; - const ButtonWidth, DefaultButton, CancelButton: Integer; MessageForm: TSetupForm); -var i: Integer; -begin - SetArrayLength(Button,GetArrayLength(ButtonText)); - for i := 0 to GetArrayLength(Button) - 1 do - begin - Button[i] := TNewButton.Create(MessageForm); - with Button[i] do - begin - Parent := MessageForm; - Width := ButtonWidth; - Height := ScaleY(MWU_BUTTONHEIGHT); - - if i = 0 then - begin - Left := MessageForm.ClientWidth - (ScaleX(MWU_HORZSPACING) + ButtonWidth) * GetArrayLength(ButtonText); - Top := MessageForm.ClientHeight - ScaleY(MWU_BUTTONAREAHEIGHT) + - ScaleY(MWU_BUTTONAREAHEIGHT - MWU_BUTTONHEIGHT) div 2; - end else - begin - Left := Button[i-1].Left + ScaleX(MWU_HORZSPACING) + ButtonWidth; - Top := Button[i-1].Top; - end; - - Caption := ButtonText[i]; - ModalResult := i + 1; - - //set the initial focus to the default button - TabOrder := ((i - (DefaultButton - 1)) + GetArrayLength(Button)) mod (GetArrayLength(Button)); - - if DefaultButton = i + 1 then - Default := True; - - if CancelButton = i + 1 then - Cancel := True; - - end; - end; -end; - - -//find out if URL label has focus -//draw focus rectangle around it if so and return index of focused label -function Message_FocusLabel(): Integer; -var i: Integer; - FocusRect: TRect; -begin - Result := -1; - - for i := 0 to GetArrayLength(URLFocusImg) - 1 do //clear existing focus rectangle - begin - FocusRect.Left := 0; - FocusRect.Top := 0; - FocusRect.Right := URLFocusImg[i].Bitmap.Width; - FocusRect.Bottom := URLFocusImg[i].Bitmap.Height; - URLFocusImg[i].Bitmap.Canvas.FillRect(FocusRect); - end; - - for i := 0 to GetArrayLength(TextLabel) - 1 do - begin - if TextLabel[i].Focused then - begin - Result := i; - - FocusRect.Left := 0; - FocusRect.Top := 0; - FocusRect.Right := URLFocusImg[TextLabel[i].Tag].Bitmap.Width; - FocusRect.Bottom := URLFocusImg[TextLabel[i].Tag].Bitmap.Height; - - DrawFocusRect(URLFocusImg[TextLabel[i].Tag].Bitmap.Canvas.Handle, FocusRect); - end; - end; -end; - - -//TNewStaticText doesn't have OnFocus - handle that here -//(not perfect - if you focus label with keyboard, then focus a button with mouse, the label keeps it's underline) -procedure Message_KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); -var URLIdx: Integer; -begin - case Key of - 9,37..40: //tab, arrow keys - begin - Message_FocusLabel(); - end; - 13,32: //enter, spacebar - begin - URLIdx := Message_FocusLabel(); //get focused label - if URLIdx > -1 then - UrlClick(TextLabel[URLIdx]); - end; - end; -end; - - -function MessageWithURL(Message: TArrayOfString; const Title: String; ButtonText: TArrayOfString; const Typ: TMsgBoxType; - const DefaultButton, CancelButton: Integer): Integer; -var MessageForm: TSetupForm; - Button: TArrayOfButton; - DialogTextWidth, ButtonWidth: Integer; - MessagePanel: TPanel; - TypImg: TBitmapImage; - i: Integer; -begin - if (not IsUninstaller and WizardSilent) or (IsUninstaller and UninstallSilent) then - begin - Result := DefaultButton; - exit; - end; - - MessageForm := CreateCustomForm(); - - MessageForm.Caption := Title; - if (CancelButton = 0) or (CancelButton > GetArrayLength(ButtonText)) then //no cancel button - remove close button - MessageForm.BorderIcons := MessageForm.BorderIcons - [biSystemMenu]; - - MessagePanel := TPanel.Create(MessageForm); //Vista-style background - with MessagePanel do - begin - Parent := MessageForm; - BevelInner := bvNone; - BevelOuter := bvNone; - BevelWidth := 0; - ParentBackground := False; - Color := clWindow; - Left := 0; - Top := 0; - end; - - DialogTextWidth := Message_CalcLabelWidth(Message, MessageForm); - ButtonWidth := Message_CalcButtonWidth(ButtonText, MessageForm); - - TypImg := TBitmapImage.Create(MessagePanel); - TypImg.Parent := MessagePanel; - Message_Icon(Typ, TypImg); - - Message_SetUpLabels(Message, TypImg, DialogTextWidth, MessagePanel); - - i := GetArrayLength(TextLabel) - 1; - MessagePanel.ClientHeight := TextLabel[i].Top + TextLabel[i].Height + ScaleY(MWU_BOTTOMBORDER); - - MessagePanel.ClientWidth := DialogTextWidth + TypImg.Width + TypImg.Left + ScaleX(MWU_HORZSPACING + MWU_RIGHTBORDER); - if MessagePanel.ClientWidth < - (ButtonWidth + ScaleX(MWU_HORZSPACING)) * GetArrayLength(ButtonText) + ScaleX(MWU_HORZSPACING) then //ensure buttons fit - MessagePanel.ClientWidth := (ButtonWidth + ScaleX(MWU_HORZSPACING)) * GetArrayLength(ButtonText) + ScaleX(MWU_HORZSPACING); - - MessageForm.ClientWidth := MessagePanel.Width; - MessageForm.ClientHeight := MessagePanel.Height + ScaleY(MWU_BUTTONAREAHEIGHT); - - Message_SetUpButtons(Button, ButtonText, ButtonWidth, DefaultButton, CancelButton, MessageForm); - - MessageForm.OnKeyUp := @Message_KeyUp; //needed for keyboard access of URL labels - MessageForm.KeyPreView := True; - - Result := MessageForm.ShowModal; - - for i := 0 to GetArrayLength(TextLabel) - 1 do - TextLabel[i].Free; - SetArrayLength(TextLabel,0); - for i := 0 to GetArrayLength(URLFocusImg) - 1 do - URLFocusImg[i].Free; - SetArrayLength(URLFocusImg,0); - - MessageForm.Release; -end; +[Code] +(* MessageWithURL + * + * Copyright (c) 2010-2011 Jernej Simončič + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you must + * not claim that you wrote the original software. If you use this + * software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and must + * not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + *) + +(* * * * * * * * * * + * MessageWithURL(Message: TArrayOfString; Title: String: ButtonText: TArrayOfString; Typ: TMsgBoxType; + * DefaultButton, CancelButton: Integer): Integer; + * + * Parameters: + * Title dialog box caption + * Message messages to display; if a message starts with _, the text following it up to the first space character + * is interpreted as URL, and the rest of the message is used as clickable text for that URL + * Typ icon to show + * ButtonText buttons to show under the text + * DefaultButton default button (first button = 1) + * CancelButton cancel button (first button = 1) + * + * Return value button that was clicked (first button = 1); if running in silent mode, DefaultButton is returned + *) +function MessageWithURL(Message: TArrayOfString; const Title: String; ButtonText: TArrayOfString; const Typ: TMsgBoxType; + const DefaultButton, CancelButton: Integer): Integer; forward; + +function GetSystemMetrics(nIndex: Integer): Integer; external 'GetSystemMetrics@User32 stdcall'; +function GetDialogBaseUnits(): Integer; external 'GetDialogBaseUnits@User32 stdcall'; + +//function GetSysColor(nIndex: Integer): DWORD; external 'GetSysColor@user32.dll stdcall'; + +function LoadIcon(hInstance: Integer; lpIconName: Integer): Integer; external 'LoadIconW@user32 stdcall'; +//function LoadImage(hinst: Integer; lpszName: Integer; uType: Cardinal; cxDesired, cyDesired: Integer; fuLoad: Cardinal): Integer; external 'LoadImageW@user32 stdcall'; +function DrawIcon(hdc: HBitmap; x,y: Integer; hIcon: Integer): Integer; external 'DrawIcon@user32 stdcall'; +//function DrawIconEx(hdc: HBitmap; xLeft,yTop: Integer; hIcon: Integer; cxWidth, cyWidth: Integer; istepIfAniCur: Cardinal; hbrFlickerFreeDraw: Integer; diFlags: Cardinal): Integer; external 'DrawIconEx@user32 stdcall'; +//function DestroyIcon(hIcon: Integer): Integer; external 'DestroyIcon@user32 stdcall'; + +function DrawFocusRect(hDC: Integer; var lprc: TRect): BOOL; external 'DrawFocusRect@user32 stdcall'; + +type + TArrayOfButton = Array of TNewButton; + +const + //borders around message + MWU_LEFTBORDER = 25; + MWU_RIGHTBORDER = MWU_LEFTBORDER; + MWU_TOPBORDER = 26; + MWU_BOTTOMBORDER = MWU_TOPBORDER; + //space between elements (icon-text and between buttons) + MWU_HORZSPACING = 8; + //space between labels + MWU_VERTSPACING = 4; + //button sizes + MWU_BUTTONHEIGHT = 24; + MWU_MINBUTTONWIDTH = 86; + //height of area where buttons are placed + MWU_BUTTONAREAHEIGHT = 45; + + SM_CXSCREEN = 0; + SM_CXICON = 11; + SM_CYICON = 12; + SM_CXICONSPACING = 38; + SM_CYICONSPACING = 39; + + //COLOR_HOTLIGHT = 26; + + OIC_HAND = 32513; + OIC_QUES = 32514; + OIC_BANG = 32515; + OIC_NOTE = 32516; + + LR_DEFAULTSIZE = $00000040; + LR_SHARED = $00008000; + + IMAGE_BITMAP = 0; + IMAGE_ICON = 1; + IMAGE_CURSOR = 2; + + DI_IMAGE = 1; + DI_MASK = 2; + DI_NORMAL = DI_IMAGE or DI_MASK; + DI_DEFAULTSIZE = 8; + +var + URLList: TArrayOfString; + TextLabel: Array of TNewStaticText; + URLFocusImg: Array of TBitmapImage; + SingleLineHeight: Integer; + + +procedure UrlClick(Sender: TObject); +var ErrorCode: Integer; +begin + ShellExecAsOriginalUser('open',URLList[TNewStaticText(Sender).Tag],'','',SW_SHOWNORMAL,ewNoWait,ErrorCode); +end; + + +// calculates maximum width of text labels +// also counts URLs, and sets the length of URLList accordingly +function Message_CalcLabelWidth(var Message: TArrayOfString; MessageForm: TSetupForm): Integer; +var MeasureLabel: TNewStaticText; + i,URLCount,DlgUnit,ScreenWidth: Integer; +begin + MeasureLabel := TNewStaticText.Create(MessageForm); + with MeasureLabel do + begin + Parent := MessageForm; + Left := 0; + Top := 0; + AutoSize := True; + end; + + MeasureLabel.Caption := 'X'; + SingleLineHeight := MeasureLabel.Height; + + Result := 0; //minimum width + URLCount := 0; + for i := 0 to GetArrayLength(Message) - 1 do + begin + if Length(Message[i]) < 1 then //simplifies things + Message[i] := ' '; + + if Message[i][1] <> '_' then + MeasureLabel.Caption := Message[i] //not an URL + else + begin //URL - check only the displayed text + if Pos(' ',Message[i]) > 0 then + MeasureLabel.Caption := Copy(Message[i],Pos(' ',Message[i])+1,Length(Message[i])) + else + MeasureLabel.Caption := Copy(Message[i],2,Length(Message[i])); + + URLCount := URLCount + 1; + end; + + if MeasureLabel.Width > Result then + Result := MeasureLabel.Width; + end; + MeasureLabel.Free; + + SetArrayLength(URLList,URLCount); //needed later - no need to do a special loop just for this + SetArrayLength(URLFocusImg,URLCount); + + DlgUnit := GetDialogBaseUnits() and $FFFF; //ensure the dialog isn't too wide + ScreenWidth := GetSystemMetrics(SM_CXSCREEN); + if Result > ((278 * DlgUnit) div 4) then //278 is from http://blogs.msdn.com/b/oldnewthing/archive/2011/06/24/10178386.aspx + Result := ((278 * DlgUnit) div 4); + if Result > (ScreenWidth * 3) div 4 then + Result := (ScreenWidth * 3) div 4; + +end; + + +//find the longest button +function Message_CalcButtonWidth(const ButtonText: TArrayOfString; MessageForm: TSetupForm): Integer; +var MeasureLabel: TNewStaticText; + i: Integer; +begin + MeasureLabel := TNewStaticText.Create(MessageForm); + with MeasureLabel do + begin + Parent := MessageForm; + Left := 0; + Top := 0; + AutoSize := True; + end; + + Result := ScaleX(MWU_MINBUTTONWIDTH - MWU_HORZSPACING * 2); //minimum width + for i := 0 to GetArrayLength(ButtonText) - 1 do + begin + MeasureLabel.Caption := ButtonText[i] + + if MeasureLabel.Width > Result then + Result := MeasureLabel.Width; + end; + MeasureLabel.Free; + + Result := Result + ScaleX(MWU_HORZSPACING * 2); //account for borders +end; + + +procedure Message_Icon(const Typ: TMsgBoxType; TypImg: TBitmapImage); +var TypRect: TRect; + Icon: THandle; + TypIcon: Integer; +begin + TypRect.Left := 0; + TypRect.Top := 0; + TypRect.Right := GetSystemMetrics(SM_CXICON); + TypRect.Bottom := GetSystemMetrics(SM_CYICON); + + case Typ of + mbInformation: + TypIcon := OIC_NOTE; + mbConfirmation: + TypIcon := OIC_QUES; + mbError: + TypIcon := OIC_BANG; + else + TypIcon := OIC_HAND; + end; + + //TODO: icon loads with wrong size when using Large Fonts (SM_CXICON/CYICON is 40, but 32x32 icon loads - find out how to get the right size) + Icon := LoadIcon(0,TypIcon); + //Icon := LoadImage(0,TypIcon,IMAGE_ICON,0,0,LR_SHARED or LR_DEFAULTSIZE); + with TypImg do + begin + Left := ScaleX(MWU_LEFTBORDER); + Top := ScaleY(MWU_TOPBORDER); + Center := False; + Stretch := False; + AutoSize := True; + Bitmap.Width := GetSystemMetrics(SM_CXICON); + Bitmap.Height := GetSystemMetrics(SM_CYICON); + Bitmap.Canvas.Brush.Color := TPanel(Parent).Color; + Bitmap.Canvas.FillRect(TypRect); + DrawIcon(Bitmap.Canvas.Handle,0,0,Icon); //draws icon scaled + //DrawIconEx(Bitmap.Canvas.Handle,0,0,Icon,0,0,0,0,DI_NORMAL {or DI_DEFAULTSIZE}); //draws icon without scaling + end; + //DestroyIcon(Icon); //not needed with LR_SHARED or with LoadIcon +end; + + +procedure Message_SetUpURLLabel(URLLabel: TNewStaticText; const Msg: String; const URLNum: Integer); +var Blank: TRect; +begin + with URLLabel do + begin + if Pos(' ',Msg) > 0 then + begin + Caption := Copy(Msg,Pos(' ',Msg)+1,Length(Msg)); + URLList[URLNum] := Copy(Msg, 2, Pos(' ',Msg)-1); + end + else + begin //no text after URL - display just URL + URLList[URLNum] := Copy(Msg, 2, Length(Msg)); + Caption := URLList[URLNum]; + end; + + Hint := URLList[URLNum]; + ShowHint := True; + + Font.Color := GetSysColor(COLOR_HOTLIGHT); + Font.Style := [fsUnderline]; + Cursor := crHand; + OnClick := @UrlClick; + + Tag := URLNum; //used to find the URL to open and bitmap to draw focus rectangle on + + if Height = SingleLineHeight then //shrink label to actual text width + WordWrap := False; + + TabStop := True; //keyboard accessibility + TabOrder := URLNum; + end; + + URLFocusImg[URLNum] := TBitmapImage.Create(URLLabel.Parent); //focus rectangle needs a bitmap - prepare it here + with URLFocusImg[URLNum] do + begin + Left := URLLabel.Left - 1; + Top := URLLabel.Top - 1; + Stretch := False; + AutoSize := True; + Parent := URLLabel.Parent; + Bitmap.Width := URLLabel.Width + 2; + Bitmap.Height := URLLabel.Height + 2; + + SendToBack; + + Blank.Left := 0; + Blank.Top := 0; + Blank.Right := Width; + Blank.Bottom := Height; + Bitmap.Canvas.Brush.Color := TPanel(Parent).Color; + Bitmap.Canvas.FillRect(Blank); + end; +end; + + +procedure Message_SetUpLabels(Message: TArrayOfString; TypImg: TBitmapImage; + const DialogTextWidth: Integer; MessagePanel: TPanel); +var i,URLNum,dy: Integer; +begin + SetArrayLength(TextLabel,GetArrayLength(Message)); + URLNum := 0; + for i := 0 to GetArrayLength(TextLabel) - 1 do + begin + TextLabel[i] := TNewStaticText.Create(MessagePanel); + with TextLabel[i] do + begin + Parent := MessagePanel; + Left := TypImg.Left + TypImg.Width + ScaleX(MWU_HORZSPACING); + if i = 0 then + Top := TypImg.Top + else + Top := TextLabel[i-1].Top + TextLabel[i-1].Height + ScaleY(MWU_VERTSPACING); + + WordWrap := True; + AutoSize := True; + Width := DialogTextWidth; + + if Message[i][1] <> '_' then + Caption := Message[i] + else + begin // apply URL formatting + Message_SetUpURLLabel(TextLabel[i], Message[i], URLNum); + URLNum := URLNum + 1; + end; + + end; + end; + + i := GetArrayLength(TextLabel) - 1; + if TextLabel[i].Top + TextLabel[i].Height < TypImg.Top + TypImg.Height then //center labels vertically + begin + dy := (TypImg.Top + TypImg.Height - TextLabel[i].Top - TextLabel[i].Height) div 2; + for i := 0 to GetArrayLength(TextLabel) - 1 do + TextLabel[i].Top := TextLabel[i].Top + dy; + end; +end; + + +procedure Message_SetUpButtons(var Button: TArrayOfButton; ButtonText: TArrayOfString; + const ButtonWidth, DefaultButton, CancelButton: Integer; MessageForm: TSetupForm); +var i: Integer; +begin + SetArrayLength(Button,GetArrayLength(ButtonText)); + for i := 0 to GetArrayLength(Button) - 1 do + begin + Button[i] := TNewButton.Create(MessageForm); + with Button[i] do + begin + Parent := MessageForm; + Width := ButtonWidth; + Height := ScaleY(MWU_BUTTONHEIGHT); + + if i = 0 then + begin + Left := MessageForm.ClientWidth - (ScaleX(MWU_HORZSPACING) + ButtonWidth) * GetArrayLength(ButtonText); + Top := MessageForm.ClientHeight - ScaleY(MWU_BUTTONAREAHEIGHT) + + ScaleY(MWU_BUTTONAREAHEIGHT - MWU_BUTTONHEIGHT) div 2; + end else + begin + Left := Button[i-1].Left + ScaleX(MWU_HORZSPACING) + ButtonWidth; + Top := Button[i-1].Top; + end; + + Caption := ButtonText[i]; + ModalResult := i + 1; + + //set the initial focus to the default button + TabOrder := ((i - (DefaultButton - 1)) + GetArrayLength(Button)) mod (GetArrayLength(Button)); + + if DefaultButton = i + 1 then + Default := True; + + if CancelButton = i + 1 then + Cancel := True; + + end; + end; +end; + + +//find out if URL label has focus +//draw focus rectangle around it if so and return index of focused label +function Message_FocusLabel(): Integer; +var i: Integer; + FocusRect: TRect; +begin + Result := -1; + + for i := 0 to GetArrayLength(URLFocusImg) - 1 do //clear existing focus rectangle + begin + FocusRect.Left := 0; + FocusRect.Top := 0; + FocusRect.Right := URLFocusImg[i].Bitmap.Width; + FocusRect.Bottom := URLFocusImg[i].Bitmap.Height; + URLFocusImg[i].Bitmap.Canvas.FillRect(FocusRect); + end; + + for i := 0 to GetArrayLength(TextLabel) - 1 do + begin + if TextLabel[i].Focused then + begin + Result := i; + + FocusRect.Left := 0; + FocusRect.Top := 0; + FocusRect.Right := URLFocusImg[TextLabel[i].Tag].Bitmap.Width; + FocusRect.Bottom := URLFocusImg[TextLabel[i].Tag].Bitmap.Height; + + DrawFocusRect(URLFocusImg[TextLabel[i].Tag].Bitmap.Canvas.Handle, FocusRect); + end; + end; +end; + + +//TNewStaticText doesn't have OnFocus - handle that here +//(not perfect - if you focus label with keyboard, then focus a button with mouse, the label keeps it's underline) +procedure Message_KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState); +var URLIdx: Integer; +begin + case Key of + 9,37..40: //tab, arrow keys + begin + Message_FocusLabel(); + end; + 13,32: //enter, spacebar + begin + URLIdx := Message_FocusLabel(); //get focused label + if URLIdx > -1 then + UrlClick(TextLabel[URLIdx]); + end; + end; +end; + + +function MessageWithURL(Message: TArrayOfString; const Title: String; ButtonText: TArrayOfString; const Typ: TMsgBoxType; + const DefaultButton, CancelButton: Integer): Integer; +var MessageForm: TSetupForm; + Button: TArrayOfButton; + DialogTextWidth, ButtonWidth: Integer; + MessagePanel: TPanel; + TypImg: TBitmapImage; + i: Integer; +begin + if (not IsUninstaller and WizardSilent) or (IsUninstaller and UninstallSilent) then + begin + Result := DefaultButton; + exit; + end; + + MessageForm := CreateCustomForm(); + + MessageForm.Caption := Title; + if (CancelButton = 0) or (CancelButton > GetArrayLength(ButtonText)) then //no cancel button - remove close button + MessageForm.BorderIcons := MessageForm.BorderIcons - [biSystemMenu]; + + MessagePanel := TPanel.Create(MessageForm); //Vista-style background + with MessagePanel do + begin + Parent := MessageForm; + BevelInner := bvNone; + BevelOuter := bvNone; + BevelWidth := 0; + ParentBackground := False; + Color := clWindow; + Left := 0; + Top := 0; + end; + + DialogTextWidth := Message_CalcLabelWidth(Message, MessageForm); + ButtonWidth := Message_CalcButtonWidth(ButtonText, MessageForm); + + TypImg := TBitmapImage.Create(MessagePanel); + TypImg.Parent := MessagePanel; + Message_Icon(Typ, TypImg); + + Message_SetUpLabels(Message, TypImg, DialogTextWidth, MessagePanel); + + i := GetArrayLength(TextLabel) - 1; + MessagePanel.ClientHeight := TextLabel[i].Top + TextLabel[i].Height + ScaleY(MWU_BOTTOMBORDER); + + MessagePanel.ClientWidth := DialogTextWidth + TypImg.Width + TypImg.Left + ScaleX(MWU_HORZSPACING + MWU_RIGHTBORDER); + if MessagePanel.ClientWidth < + (ButtonWidth + ScaleX(MWU_HORZSPACING)) * GetArrayLength(ButtonText) + ScaleX(MWU_HORZSPACING) then //ensure buttons fit + MessagePanel.ClientWidth := (ButtonWidth + ScaleX(MWU_HORZSPACING)) * GetArrayLength(ButtonText) + ScaleX(MWU_HORZSPACING); + + MessageForm.ClientWidth := MessagePanel.Width; + MessageForm.ClientHeight := MessagePanel.Height + ScaleY(MWU_BUTTONAREAHEIGHT); + + Message_SetUpButtons(Button, ButtonText, ButtonWidth, DefaultButton, CancelButton, MessageForm); + + MessageForm.OnKeyUp := @Message_KeyUp; //needed for keyboard access of URL labels + MessageForm.KeyPreView := True; + + Result := MessageForm.ShowModal; + + for i := 0 to GetArrayLength(TextLabel) - 1 do + TextLabel[i].Free; + SetArrayLength(TextLabel,0); + for i := 0 to GetArrayLength(URLFocusImg) - 1 do + URLFocusImg[i].Free; + SetArrayLength(URLFocusImg,0); + + MessageForm.Release; +end; diff --git a/build/windows/installer/utils.isi b/build/windows/installer/util_general.isi similarity index 95% rename from build/windows/installer/utils.isi rename to build/windows/installer/util_general.isi index 1dbc0f163a..82292f5668 100644 --- a/build/windows/installer/utils.isi +++ b/build/windows/installer/util_general.isi @@ -1,177 +1,177 @@ -#if 0 -[Code] -#endif - -procedure DebugMsg(Const pProc,pMsg: String); -begin - Log('[Code] ' + pProc + #9 + pMsg); -end; - - -function BoolToStr(const b: Boolean): String; -begin - if b then - Result := 'True' - else - Result := 'False'; -end; - - -function RevPos(const SearchStr, Str: string): Integer; -var i: Integer; -begin - - if Length(SearchStr) < Length(Str) then - for i := (Length(Str) - Length(SearchStr) + 1) downto 1 do - begin - - if Copy(Str, i, Length(SearchStr)) = SearchStr then - begin - Result := i; - exit; - end; - - end; - - Result := 0; -end; - - -function Replace(pSearchFor, pReplaceWith, pText: String): String; -begin - StringChangeEx(pText,pSearchFor,pReplaceWith,True); - - Result := pText; -end; - - -function Count(What, Where: String): Integer; -begin - Result := 0; - if Length(What) = 0 then - exit; - - while Pos(What,Where)>0 do - begin - Where := Copy(Where,Pos(What,Where)+Length(What),Length(Where)); - Result := Result + 1; - end; -end; - - -//split text to array -procedure Explode(var ADest: TArrayOfString; aText, aSeparator: String); -var tmp: Integer; -begin - if aSeparator='' then - exit; - - SetArrayLength(ADest,Count(aSeparator,aText)+1) - - tmp := 0; - repeat - if Pos(aSeparator,aText)>0 then - begin - - ADest[tmp] := Copy(aText,1,Pos(aSeparator,aText)-1); - aText := Copy(aText,Pos(aSeparator,aText)+Length(aSeparator),Length(aText)); - tmp := tmp + 1; - - end else - begin - - ADest[tmp] := aText; - aText := ''; - - end; - until Length(aText)=0; -end; - - -function String2Utf8(const pInput: String): AnsiString; -var Output: AnsiString; - ret, outLen, nulPos: Integer; -begin - outLen := WideCharToMultiByte(CP_UTF8, 0, pInput, -1, Output, 0, 0, 0); - Output := StringOfChar(#0,outLen); - ret := WideCharToMultiByte(CP_UTF8, 0, pInput, -1, Output, outLen, 0, 0); - - if ret = 0 then - RaiseException('WideCharToMultiByte failed: ' + IntToStr(GetLastError)); - - nulPos := Pos(#0,Output) - 1; - if nulPos = -1 then - nulPos := Length(Output); - - Result := Copy(Output,1,nulPos); -end; - - -function Utf82String(const pInput: AnsiString): String; -var Output: AnsiString; - ret, outLen, nulPos: Integer; -begin - outLen := MultiByteToWideChar(CP_UTF8, 0, pInput, -1, Output, 0); - Output := StringOfChar(#0,outLen); - ret := MultiByteToWideChar(CP_UTF8, 0, pInput, -1, Output, outLen); - - if ret = 0 then - RaiseException('MultiByteToWideChar failed: ' + IntToStr(GetLastError)); - - nulPos := Pos(#0,Output) - 1; - if nulPos = -1 then - nulPos := Length(Output); - - Result := Copy(Output,1,nulPos); -end; - - -function SaveStringToUTF8File(const pFileName, pS: String; const pAppend: Boolean): Boolean; -begin - Result := SaveStringToFile(pFileName, String2Utf8(pS), pAppend); -end; - - -function LoadStringFromUTF8File(const pFileName: String; var oS: String): Boolean; -var Utf8String: AnsiString; -begin - Result := LoadStringFromFile(pFileName, Utf8String); - oS := Utf82String(Utf8String); -end; - - -procedure StatusLabel(const Status1,Status2: string); -begin - WizardForm.StatusLabel.Caption := Status1; - WizardForm.FilenameLabel.Caption := Status2; - WizardForm.Refresh(); -end; - - -//reverse encoding done by Encode -function Decode(pText: String): String; -var p: Integer; - tmp: String; -begin - if Pos('%',pText) = 0 then - Result := pText - else - begin - Result := ''; - while Length(pText) > 0 do - begin - p := Pos('%',pText); - if p = 0 then - begin - Result := Result + pText; - break; - end; - Result := Result + Copy(pText,1,p-1); - tmp := '$' + Copy(pText,p+1,2); - Result := Result + Chr(StrToIntDef(tmp,32)); - pText := Copy(pText,p+3,Length(pText)); - end; - end; -end; - - +#if 0 +[Code] +#endif + +procedure DebugMsg(Const pProc,pMsg: String); +begin + Log('[Code] ' + pProc + #9 + pMsg); +end; + + +function BoolToStr(const b: Boolean): String; +begin + if b then + Result := 'True' + else + Result := 'False'; +end; + + +function RevPos(const SearchStr, Str: string): Integer; +var i: Integer; +begin + + if Length(SearchStr) < Length(Str) then + for i := (Length(Str) - Length(SearchStr) + 1) downto 1 do + begin + + if Copy(Str, i, Length(SearchStr)) = SearchStr then + begin + Result := i; + exit; + end; + + end; + + Result := 0; +end; + + +function Replace(pSearchFor, pReplaceWith, pText: String): String; +begin + StringChangeEx(pText,pSearchFor,pReplaceWith,True); + + Result := pText; +end; + + +function Count(What, Where: String): Integer; +begin + Result := 0; + if Length(What) = 0 then + exit; + + while Pos(What,Where)>0 do + begin + Where := Copy(Where,Pos(What,Where)+Length(What),Length(Where)); + Result := Result + 1; + end; +end; + + +//split text to array +procedure Explode(var ADest: TArrayOfString; aText, aSeparator: String); +var tmp: Integer; +begin + if aSeparator='' then + exit; + + SetArrayLength(ADest,Count(aSeparator,aText)+1) + + tmp := 0; + repeat + if Pos(aSeparator,aText)>0 then + begin + + ADest[tmp] := Copy(aText,1,Pos(aSeparator,aText)-1); + aText := Copy(aText,Pos(aSeparator,aText)+Length(aSeparator),Length(aText)); + tmp := tmp + 1; + + end else + begin + + ADest[tmp] := aText; + aText := ''; + + end; + until Length(aText)=0; +end; + + +function String2Utf8(const pInput: String): AnsiString; +var Output: AnsiString; + ret, outLen, nulPos: Integer; +begin + outLen := WideCharToMultiByte(CP_UTF8, 0, pInput, -1, Output, 0, 0, 0); + Output := StringOfChar(#0,outLen); + ret := WideCharToMultiByte(CP_UTF8, 0, pInput, -1, Output, outLen, 0, 0); + + if ret = 0 then + RaiseException('WideCharToMultiByte failed: ' + IntToStr(GetLastError)); + + nulPos := Pos(#0,Output) - 1; + if nulPos = -1 then + nulPos := Length(Output); + + Result := Copy(Output,1,nulPos); +end; + + +function Utf82String(const pInput: AnsiString): String; +var Output: AnsiString; + ret, outLen, nulPos: Integer; +begin + outLen := MultiByteToWideChar(CP_UTF8, 0, pInput, -1, Output, 0); + Output := StringOfChar(#0,outLen); + ret := MultiByteToWideChar(CP_UTF8, 0, pInput, -1, Output, outLen); + + if ret = 0 then + RaiseException('MultiByteToWideChar failed: ' + IntToStr(GetLastError)); + + nulPos := Pos(#0,Output) - 1; + if nulPos = -1 then + nulPos := Length(Output); + + Result := Copy(Output,1,nulPos); +end; + + +function SaveStringToUTF8File(const pFileName, pS: String; const pAppend: Boolean): Boolean; +begin + Result := SaveStringToFile(pFileName, String2Utf8(pS), pAppend); +end; + + +function LoadStringFromUTF8File(const pFileName: String; var oS: String): Boolean; +var Utf8String: AnsiString; +begin + Result := LoadStringFromFile(pFileName, Utf8String); + oS := Utf82String(Utf8String); +end; + + +procedure StatusLabel(const Status1,Status2: string); +begin + WizardForm.StatusLabel.Caption := Status1; + WizardForm.FilenameLabel.Caption := Status2; + WizardForm.Refresh(); +end; + + +//reverse encoding done by Encode +function Decode(pText: String): String; +var p: Integer; + tmp: String; +begin + if Pos('%',pText) = 0 then + Result := pText + else + begin + Result := ''; + while Length(pText) > 0 do + begin + p := Pos('%',pText); + if p = 0 then + begin + Result := Result + pText; + break; + end; + Result := Result + Copy(pText,1,p-1); + tmp := '$' + Copy(pText,p+1,2); + Result := Result + Chr(StrToIntDef(tmp,32)); + pText := Copy(pText,p+3,Length(pText)); + end; + end; +end; + + diff --git a/build/windows/installer/rebootcontinue.isi b/build/windows/installer/util_rebootcontinue.isi similarity index 97% rename from build/windows/installer/rebootcontinue.isi rename to build/windows/installer/util_rebootcontinue.isi index 0cec212434..cb00079d70 100644 --- a/build/windows/installer/rebootcontinue.isi +++ b/build/windows/installer/util_rebootcontinue.isi @@ -1,130 +1,130 @@ -#if 0 -[Code] -#endif - -function Quote(const S: String): String; -begin - Result := '"' + S + '"'; -end; - - -function AddParam(const S, P, V: String): String; -begin - if V <> '""' then - Result := S + ' /' + P + '=' + V; -end; - - -function AddSimpleParam(const S, P: String): String; -begin - Result := S + ' /' + P; -end; - - -procedure CreateRunOnceEntry; -var RunOnceData, SetupRestartData: String; - i: Integer; -begin - DebugMsg('CreateRunOnceEntry','Preparing for restart'); - - //RunOnce command-line is limited to 256 characters, so keep it to the bare minimum required to start setup - RunOnceData := Quote(ExpandConstant('{srcexe}')) + ' /resumeinstall=1'; - RunOnceData := AddParam(RunOnceData, 'LANG', ExpandConstant('{language}')); - - SetupRestartData := Quote(ExpandConstant('{srcexe}')) + ' /resumeinstall=2'; - SetupRestartData := AddParam(SetupRestartData, 'LANG', ExpandConstant('{language}')); - SetupRestartData := AddParam(SetupRestartData, 'DIR', Quote(WizardDirValue)); - //SetupRestartData := AddParam(SetupRestartData, 'GROUP', Quote(WizardGroupValue)); - //if WizardNoIcons then - // SetupRestartData := AddSimpleParam(SetupRestartData, 'NOICONS'); - SetupRestartData := AddParam(SetupRestartData, 'TYPE', Quote(WizardSetupType(False))); - SetupRestartData := AddParam(SetupRestartData, 'COMPONENTS', Quote(WizardSelectedComponents(False))); - SetupRestartData := AddParam(SetupRestartData, 'TASKS', Quote(WizardSelectedTasks(False))); - - if Force32bitInstall then - SetupRestartData := AddSimpleParam(SetupRestartData, '32'); - - if ExpandConstant('{param:log|*}') <> '*' then - begin - SetupRestartData := AddParam(SetupRestartData, 'LOG', Quote(ExpandConstant('{param:log|*}'))); - end else - begin - for i := 0 to ParamCount() do - if LowerCase(ParamStr(i)) = '/log' then - begin - RunOnceData := AddSimpleParam(RunOnceData,'LOG'); //multiple logs are created in %TEMP% when no filename is given - SetupRestartData := AddSimpleParam(SetupRestartData,'LOG'); - break; - end; - end; - - DebugMsg('CreateRunOnceEntry','RunOnce: ' + RunOnceData); - RegWriteStringValue(HKLM, 'Software\Microsoft\Windows\CurrentVersion\RunOnce', RunOnceName, RunOnceData); - - DebugMsg('CreateRunOnceEntry','RunOnce: ' + SetupRestartData); - RegWriteStringValue(HKLM, 'Software\' + RunOnceName, '', SetupRestartData); -end; - - -procedure RestartMyself(); -var CmdLine: String; - ResultCode: Integer; -begin - DebugMsg('RestartMyself','Continuing install after reboot (reexecuting setup)'); - - if RegValueExists(HKLM, 'Software\' + RunOnceName, '') then - begin - if RegQueryStringValue(HKLM, 'Software\' + RunOnceName, '', CmdLine) then - begin - RegDeleteKeyIncludingSubkeys(HKLM, 'Software\' + RunOnceName); //clean up - if not Exec('>',CmdLine,'',SW_SHOW,ewNoWait,ResultCode) then //bonus: don't block shell from loading, since RunOnce installer exits immediately - MsgBox(FmtMessage(CustomMessage('ErrorRestartingSetup'),[IntToStr(ResultCode)]), mbError, mb_Ok); - - DebugMsg('RestartMyself','Result of running ' + CmdLine + ': ' + IntToStr(ResultCode)); - - end else - begin - MsgBox(FmtMessage(CustomMessage('ErrorRestartingSetup'),['-2']), mbError, mb_Ok); - DebugMsg('RestartMyself','Error reading HKLM\'+RunOnceName); - end; - end else - begin - MsgBox(FmtMessage(CustomMessage('ErrorRestartingSetup'),['-1']), mbError, mb_Ok); - DebugMsg('RestartMyself','HKLM\'+RunOnceName + ' not found in Registy'); - end; -end; - - -function RestartSetupAfterReboot(): Boolean; -begin - - if ExpandConstant('{param:resumeinstall|0}') = '1' then //called from RunOnce - begin - Result := False; //setup will just re-execute itself in this run - - RestartMyself(); - - DebugMsg('RestartSetupAfterReboot','Phase 1 complete, exiting'); - exit; - - end else - if ExpandConstant('{param:resumeinstall|0}') = '2' then //setup re-executed itself - begin - - Result := True; - InstallMode := imRebootContinue; - DebugMsg('RestartSetupAfterReboot','Continuing install after reboot'); - - end else - begin - Result := True; //normal install - end; - - if InstallMode <> imRebootContinue then - if RegValueExists(HKLM, 'Software\Microsoft\Windows\CurrentVersion\RunOnce', RunOnceName) then - begin - DebugMsg('RestartSetupAfterReboot','System must be restarted first'); - MsgBox(CustomMessage('RebootRequiredFirst'), mbError, mb_Ok); - Result := False; - end; -end; +#if 0 +[Code] +#endif + +function Quote(const S: String): String; +begin + Result := '"' + S + '"'; +end; + + +function AddParam(const S, P, V: String): String; +begin + if V <> '""' then + Result := S + ' /' + P + '=' + V; +end; + + +function AddSimpleParam(const S, P: String): String; +begin + Result := S + ' /' + P; +end; + + +procedure CreateRunOnceEntry; +var RunOnceData, SetupRestartData: String; + i: Integer; +begin + DebugMsg('CreateRunOnceEntry','Preparing for restart'); + + //RunOnce command-line is limited to 256 characters, so keep it to the bare minimum required to start setup + RunOnceData := Quote(ExpandConstant('{srcexe}')) + ' /resumeinstall=1'; + RunOnceData := AddParam(RunOnceData, 'LANG', ExpandConstant('{language}')); + + SetupRestartData := Quote(ExpandConstant('{srcexe}')) + ' /resumeinstall=2'; + SetupRestartData := AddParam(SetupRestartData, 'LANG', ExpandConstant('{language}')); + SetupRestartData := AddParam(SetupRestartData, 'DIR', Quote(WizardDirValue)); + //SetupRestartData := AddParam(SetupRestartData, 'GROUP', Quote(WizardGroupValue)); + //if WizardNoIcons then + // SetupRestartData := AddSimpleParam(SetupRestartData, 'NOICONS'); + SetupRestartData := AddParam(SetupRestartData, 'TYPE', Quote(WizardSetupType(False))); + SetupRestartData := AddParam(SetupRestartData, 'COMPONENTS', Quote(WizardSelectedComponents(False))); + SetupRestartData := AddParam(SetupRestartData, 'TASKS', Quote(WizardSelectedTasks(False))); + + if Force32bitInstall then + SetupRestartData := AddSimpleParam(SetupRestartData, '32'); + + if ExpandConstant('{param:log|*}') <> '*' then + begin + SetupRestartData := AddParam(SetupRestartData, 'LOG', Quote(ExpandConstant('{param:log|*}'))); + end else + begin + for i := 0 to ParamCount() do + if LowerCase(ParamStr(i)) = '/log' then + begin + RunOnceData := AddSimpleParam(RunOnceData,'LOG'); //multiple logs are created in %TEMP% when no filename is given + SetupRestartData := AddSimpleParam(SetupRestartData,'LOG'); + break; + end; + end; + + DebugMsg('CreateRunOnceEntry','RunOnce: ' + RunOnceData); + RegWriteStringValue(HKLM, 'Software\Microsoft\Windows\CurrentVersion\RunOnce', RunOnceName, RunOnceData); + + DebugMsg('CreateRunOnceEntry','RunOnce: ' + SetupRestartData); + RegWriteStringValue(HKLM, 'Software\' + RunOnceName, '', SetupRestartData); +end; + + +procedure RestartMyself(); +var CmdLine: String; + ResultCode: Integer; +begin + DebugMsg('RestartMyself','Continuing install after reboot (reexecuting setup)'); + + if RegValueExists(HKLM, 'Software\' + RunOnceName, '') then + begin + if RegQueryStringValue(HKLM, 'Software\' + RunOnceName, '', CmdLine) then + begin + RegDeleteKeyIncludingSubkeys(HKLM, 'Software\' + RunOnceName); //clean up + if not Exec('>',CmdLine,'',SW_SHOW,ewNoWait,ResultCode) then //bonus: don't block shell from loading, since RunOnce installer exits immediately + MsgBox(FmtMessage(CustomMessage('ErrorRestartingSetup'),[IntToStr(ResultCode)]), mbError, mb_Ok); + + DebugMsg('RestartMyself','Result of running ' + CmdLine + ': ' + IntToStr(ResultCode)); + + end else + begin + MsgBox(FmtMessage(CustomMessage('ErrorRestartingSetup'),['-2']), mbError, mb_Ok); + DebugMsg('RestartMyself','Error reading HKLM\'+RunOnceName); + end; + end else + begin + MsgBox(FmtMessage(CustomMessage('ErrorRestartingSetup'),['-1']), mbError, mb_Ok); + DebugMsg('RestartMyself','HKLM\'+RunOnceName + ' not found in Registy'); + end; +end; + + +function RestartSetupAfterReboot(): Boolean; +begin + + if ExpandConstant('{param:resumeinstall|0}') = '1' then //called from RunOnce + begin + Result := False; //setup will just re-execute itself in this run + + RestartMyself(); + + DebugMsg('RestartSetupAfterReboot','Phase 1 complete, exiting'); + exit; + + end else + if ExpandConstant('{param:resumeinstall|0}') = '2' then //setup re-executed itself + begin + + Result := True; + InstallMode := imRebootContinue; + DebugMsg('RestartSetupAfterReboot','Continuing install after reboot'); + + end else + begin + Result := True; //normal install + end; + + if InstallMode <> imRebootContinue then + if RegValueExists(HKLM, 'Software\Microsoft\Windows\CurrentVersion\RunOnce', RunOnceName) then + begin + DebugMsg('RestartSetupAfterReboot','System must be restarted first'); + MsgBox(CustomMessage('RebootRequiredFirst'), mbError, mb_Ok); + Result := False; + end; +end; diff --git a/build/windows/installer/uninst.isi b/build/windows/installer/util_uninst.isi similarity index 96% rename from build/windows/installer/uninst.isi rename to build/windows/installer/util_uninst.isi index 29231cd0df..f94caf3208 100644 --- a/build/windows/installer/uninst.isi +++ b/build/windows/installer/util_uninst.isi @@ -1,335 +1,335 @@ -#if 0 -[Code] -#endif - -function SplitRegParams(const pInf: String; var oRootKey: Integer; var oKey,oValue: String): Boolean; -var sRootKey: String; - d: Integer; -begin - Result := False; - - d := Pos('/',pInf); - if d = 0 then - begin - DebugMsg('SplitRegParams','Malformed line (missing /): ' + pInf); - exit; - end; - - sRootKey := Copy(pInf,1,d - 1); - oKey := Copy(pInf,d + 1,Length(pInf)); - - if oValue <> 'nil' then - begin - d := RevPos('\',oKey); - if d = 0 then - begin - DebugMsg('SplitRegParams','Malformed line (missing \): ' + pInf); - exit; - end; - - oValue := Decode(Copy(oKey,d+1,Length(oKey))); - oKey := Copy(oKey,1,d-1); - end; - - DebugMsg('SplitRegParams','Root: '+sRootKey+', Key:'+oKey + ', Value:'+oValue); - - case sRootKey of - 'HKCR': oRootKey := HKCR; - 'HKLM': oRootKey := HKLM; - 'HKU': oRootKey := HKU; - 'HKCU': oRootKey := HKCU; - else - begin - DebugMsg('SplitRegParams','Unrecognised root key: ' + sRootKey); - exit; - end; - end; - - Result := True; -end; - - -procedure UninstInfRegKey(const pInf: String; const pIfEmpty: Boolean); -var sKey,sVal: String; - iRootKey: Integer; -begin - sVal := 'nil'; - if not SplitRegParams(pInf,iRootKey,sKey,sVal) then - exit; - - if pIfEmpty then - begin - if not RegDeleteKeyIfEmpty(iRootKey,sKey) then - DebugMsg('UninstInfRegKey','RegDeleteKeyIfEmpty failed'); - end - else - begin - if not RegDeleteKeyIncludingSubkeys(iRootKey,sKey) then - DebugMsg('UninstInfRegKey','RegDeleteKeyIncludingSubkeys failed'); - end; -end; - - -procedure UninstInfRegVal(const pInf: String); -var sKey,sVal: String; - iRootKey: Integer; -begin - if not SplitRegParams(pInf,iRootKey,sKey,sVal) then - exit; - - if not RegDeleteValue(iRootKey,sKey,sVal) then - DebugMsg('UninstInfREG','RegDeleteKeyIncludingSubkeys failed'); -end; - - -procedure UninstInfFile(const pFile: String); -begin - DebugMsg('UninstInfFile','File: '+pFile); - - if not DeleteFile(pFile) then - DebugMsg('UninstInfFile','DeleteFile failed'); -end; - - -procedure UninstInfDir(const pDir: String); -begin - DebugMsg('UninstInfDir','Dir: '+pDir); - - if not RemoveDir(pDir) then - DebugMsg('UninstInfDir','RemoveDir failed'); -end; - - -procedure CreateMessageForm(var frmMessage: TForm; const pMessage: String); -var lblMessage: TNewStaticText; -begin - frmMessage := CreateCustomForm(); - with frmMessage do - begin - BorderStyle := bsDialog; - - ClientWidth := ScaleX(300); - ClientHeight := ScaleY(48); - - Caption := CustomMessage('UninstallingAddOnCaption'); - - Position := poScreenCenter; - - BorderIcons := []; - end; - - lblMessage := TNewStaticText.Create(frmMessage); - with lblMessage do - begin - Parent := frmMessage; - AutoSize := True; - Caption := pMessage; - Top := (frmMessage.ClientHeight - Height) div 2; - Left := (frmMessage.ClientWidth - Width) div 2; - Visible := True; - end; - - frmMessage.Show(); - - frmMessage.Refresh(); -end; - - -procedure UninstInfRun(const pInf: String); -var Description,Prog,Params: String; - Split, ResultCode, Ctr: Integer; - frmMessage: TForm; -begin - DebugMsg('UninstInfRun',pInf); - - Split := Pos('/',pInf); - if Split <> 0 then - begin - Description := Copy(pInf, 1, Split - 1); - Prog := Copy(pInf, Split + 1, Length(pInf)); - end else - begin - Prog := pInf; - Description := ''; - end; - - Split := Pos('/',Prog); - if Split <> 0 then - begin - Params := Copy(Prog, Split + 1, Length(Prog)); - Prog := Copy(Prog, 1, Split - 1); - end else - begin - Params := ''; - end; - - if not UninstallSilent then //can't manipulate uninstaller messages, so create a form instead - CreateMessageForm(frmMessage,Description); - - DebugMsg('UninstInfRun','Running: ' + Prog + '; Params: ' + Params); - - if Exec(Prog,Params,'',SW_SHOW,ewWaitUntilTerminated,ResultCode) then - begin - DebugMsg('UninstInfRun','Exec result: ' + IntToStr(ResultCode)); - - Ctr := 0; - while FileExists(Prog) do //wait a few seconds for the uninstaller to be deleted - since this is done by a program - begin //running from a temporary directory, the uninstaller we ran above will exit some time before - Sleep(UNINSTALL_CHECK_TIME); //it's removed from disk - Inc(Ctr); - if Ctr = (UNINSTALL_MAX_WAIT_TIME/UNINSTALL_CHECK_TIME) then //don't wait more than 5 seconds - break; - end; - - end else - DebugMsg('UninstInfRun','Exec failed: ' + IntToStr(ResultCode) + ' (' + SysErrorMessage(ResultCode) + ')'); - - if not UninstallSilent then - frmMessage.Free(); -end; - -(* -uninst.inf documentation: - -- Delete Registry keys (with all subkeys): - RegKey:/ - RootKey = HKCR, HKLM, HKCU, HKU - SubKey = subkey to delete (warning: this will delete all keys under subkey, so be very careful with it) - -- Delete empty registry keys: - RegKeyEmpty:/ - RootKey = HKCR, HKLM, HKCU, HKU - SubKey = subkey to delete if empty - -- Delete values from registry: - RegVal://Value - RootKey = HKCR, HKLM, HKCU, HKU - SubKey = subkey to delete Value from - Value = value to delete; \ and % must be escaped as %5c and %25 - -- Delete files: - File: - Path = full path to file - -- Delete empty directories: - Dir: - -- Run program with parameters: - Run:// - -Directives are parsed from the end of the file backwards as the first step of uninstall. - -IMPORTANT: From GIMP 2.10.12 onwards (Inno Setup 6 with support for per-user install), Registry keys referring to HKCR will be -processed by the installer as the first step of install (and the entries will be removed from uninst.inf), since file associations -code was rewritten. - -*) -procedure ParseUninstInf(); -var i,d: Integer; - sWhat: String; -begin - for i := GetArrayLength(asUninstInf) - 1 downto 0 do - begin - - DebugMsg('ParseUninstInf',asUninstInf[i]); - - if (Length(asUninstInf[i]) = 0) or (asUninstInf[i][1] = '#') then //skip comments and empty lines - continue; - - d := Pos(':',asUninstInf[i]); - if d = 0 then - begin - DebugMsg('ParseUninstInf','Malformed line: ' + asUninstInf[i]); - continue; - end; - - sWhat := Copy(asUninstInf[i],d+1,Length(asUninstInf[i])); - - case Copy(asUninstInf[i],1,d) of - 'RegKey:': UninstInfRegKey(sWhat,False); - 'RegKeyEmpty:': UninstInfRegKey(sWhat,True); - 'RegVal:': UninstInfRegVal(sWhat); - 'File:': UninstInfFile(sWhat); - 'Dir:': UninstInfDir(sWhat); - 'Run:': UninstInfRun(sWhat); - end; - - end; - -end; - -procedure CurUninstallStepChanged(CurStep: TUninstallStep); -begin - DebugMsg('CurUninstallStepChanged',''); - case CurStep of - usUninstall: - begin - LoadStringsFromFile(ExpandConstant('{app}\uninst\uninst.inf'),asUninstInf); - ParseUninstInf(); - end; - //usPostUninstall: - end; -end; - - -procedure AssociationsCleanUp(); -var i, d, countNew,countUI: Integer; - asTemp, asNew: TArrayOfString; - sKey,sVal: String; - iRootKey: Integer; -begin - if FileExists(ExpandConstant('{app}\uninst\uninst.inf')) then - begin - DebugMsg('AssociationsCleanUp','Parsing old uninst.inf'); - LoadStringsFromFile(ExpandConstant('{app}\uninst\uninst.inf'),asTemp); - - countNew := 0; - countUI := 0; - SetArrayLength(asNew, GetArrayLength(asTemp)); - SetArrayLength(asUninstInf, GetArrayLength(asTemp)); - - for i := 0 to GetArrayLength(asTemp) - 1 do //extract associations-related entries from uninst.inf - begin - - if (Length(asTemp[i]) = 0) or (asTemp[i][1] = '#') then //comment/empty line - begin - asNew[countNew] := asTemp[i]; - Inc(countNew); - continue; - end; - - d := Pos(':',asTemp[i]); - if d = 0 then //something wrong, ignore - continue; - - if Copy(asTemp[i],1,3) = 'Reg' then - begin - - sVal := 'nil'; - if not SplitRegParams(Copy(asTemp[i], d + 1, Length(asTemp[i])),iRootKey,sKey,sVal) then - continue; //malformed line, ignore - - if iRootKey = HKCR then //old association, prepare for cleanup - begin - DebugMsg('AssociationsCleanUp','Preparing for cleanup: '+asTemp[i]); - asUninstInf[countUI] := asTemp[i]; - Inc(countUI); - continue; - end; - - end; - - //something else, keep for new uninst.inf - asNew[countNew] := asTemp[i]; - Inc(countNew); - - end; - - SetArrayLength(asNew, countNew); - SetArrayLength(asUninstInf, countUI); - - SaveStringsToUTF8File(ExpandConstant('{app}\uninst\uninst.inf'), asNew, False); //replace uninst.inf with a cleaned one - - ParseUninstInf(); //remove old associations - end; -end; +#if 0 +[Code] +#endif + +function SplitRegParams(const pInf: String; var oRootKey: Integer; var oKey,oValue: String): Boolean; +var sRootKey: String; + d: Integer; +begin + Result := False; + + d := Pos('/',pInf); + if d = 0 then + begin + DebugMsg('SplitRegParams','Malformed line (missing /): ' + pInf); + exit; + end; + + sRootKey := Copy(pInf,1,d - 1); + oKey := Copy(pInf,d + 1,Length(pInf)); + + if oValue <> 'nil' then + begin + d := RevPos('\',oKey); + if d = 0 then + begin + DebugMsg('SplitRegParams','Malformed line (missing \): ' + pInf); + exit; + end; + + oValue := Decode(Copy(oKey,d+1,Length(oKey))); + oKey := Copy(oKey,1,d-1); + end; + + DebugMsg('SplitRegParams','Root: '+sRootKey+', Key:'+oKey + ', Value:'+oValue); + + case sRootKey of + 'HKCR': oRootKey := HKCR; + 'HKLM': oRootKey := HKLM; + 'HKU': oRootKey := HKU; + 'HKCU': oRootKey := HKCU; + else + begin + DebugMsg('SplitRegParams','Unrecognised root key: ' + sRootKey); + exit; + end; + end; + + Result := True; +end; + + +procedure UninstInfRegKey(const pInf: String; const pIfEmpty: Boolean); +var sKey,sVal: String; + iRootKey: Integer; +begin + sVal := 'nil'; + if not SplitRegParams(pInf,iRootKey,sKey,sVal) then + exit; + + if pIfEmpty then + begin + if not RegDeleteKeyIfEmpty(iRootKey,sKey) then + DebugMsg('UninstInfRegKey','RegDeleteKeyIfEmpty failed'); + end + else + begin + if not RegDeleteKeyIncludingSubkeys(iRootKey,sKey) then + DebugMsg('UninstInfRegKey','RegDeleteKeyIncludingSubkeys failed'); + end; +end; + + +procedure UninstInfRegVal(const pInf: String); +var sKey,sVal: String; + iRootKey: Integer; +begin + if not SplitRegParams(pInf,iRootKey,sKey,sVal) then + exit; + + if not RegDeleteValue(iRootKey,sKey,sVal) then + DebugMsg('UninstInfREG','RegDeleteKeyIncludingSubkeys failed'); +end; + + +procedure UninstInfFile(const pFile: String); +begin + DebugMsg('UninstInfFile','File: '+pFile); + + if not DeleteFile(pFile) then + DebugMsg('UninstInfFile','DeleteFile failed'); +end; + + +procedure UninstInfDir(const pDir: String); +begin + DebugMsg('UninstInfDir','Dir: '+pDir); + + if not RemoveDir(pDir) then + DebugMsg('UninstInfDir','RemoveDir failed'); +end; + + +procedure CreateMessageForm(var frmMessage: TForm; const pMessage: String); +var lblMessage: TNewStaticText; +begin + frmMessage := CreateCustomForm(); + with frmMessage do + begin + BorderStyle := bsDialog; + + ClientWidth := ScaleX(300); + ClientHeight := ScaleY(48); + + Caption := CustomMessage('UninstallingAddOnCaption'); + + Position := poScreenCenter; + + BorderIcons := []; + end; + + lblMessage := TNewStaticText.Create(frmMessage); + with lblMessage do + begin + Parent := frmMessage; + AutoSize := True; + Caption := pMessage; + Top := (frmMessage.ClientHeight - Height) div 2; + Left := (frmMessage.ClientWidth - Width) div 2; + Visible := True; + end; + + frmMessage.Show(); + + frmMessage.Refresh(); +end; + + +procedure UninstInfRun(const pInf: String); +var Description,Prog,Params: String; + Split, ResultCode, Ctr: Integer; + frmMessage: TForm; +begin + DebugMsg('UninstInfRun',pInf); + + Split := Pos('/',pInf); + if Split <> 0 then + begin + Description := Copy(pInf, 1, Split - 1); + Prog := Copy(pInf, Split + 1, Length(pInf)); + end else + begin + Prog := pInf; + Description := ''; + end; + + Split := Pos('/',Prog); + if Split <> 0 then + begin + Params := Copy(Prog, Split + 1, Length(Prog)); + Prog := Copy(Prog, 1, Split - 1); + end else + begin + Params := ''; + end; + + if not UninstallSilent then //can't manipulate uninstaller messages, so create a form instead + CreateMessageForm(frmMessage,Description); + + DebugMsg('UninstInfRun','Running: ' + Prog + '; Params: ' + Params); + + if Exec(Prog,Params,'',SW_SHOW,ewWaitUntilTerminated,ResultCode) then + begin + DebugMsg('UninstInfRun','Exec result: ' + IntToStr(ResultCode)); + + Ctr := 0; + while FileExists(Prog) do //wait a few seconds for the uninstaller to be deleted - since this is done by a program + begin //running from a temporary directory, the uninstaller we ran above will exit some time before + Sleep(UNINSTALL_CHECK_TIME); //it's removed from disk + Inc(Ctr); + if Ctr = (UNINSTALL_MAX_WAIT_TIME/UNINSTALL_CHECK_TIME) then //don't wait more than 5 seconds + break; + end; + + end else + DebugMsg('UninstInfRun','Exec failed: ' + IntToStr(ResultCode) + ' (' + SysErrorMessage(ResultCode) + ')'); + + if not UninstallSilent then + frmMessage.Free(); +end; + +(* +uninst.inf documentation: + +- Delete Registry keys (with all subkeys): + RegKey:/ + RootKey = HKCR, HKLM, HKCU, HKU + SubKey = subkey to delete (warning: this will delete all keys under subkey, so be very careful with it) + +- Delete empty registry keys: + RegKeyEmpty:/ + RootKey = HKCR, HKLM, HKCU, HKU + SubKey = subkey to delete if empty + +- Delete values from registry: + RegVal://Value + RootKey = HKCR, HKLM, HKCU, HKU + SubKey = subkey to delete Value from + Value = value to delete; \ and % must be escaped as %5c and %25 + +- Delete files: + File: + Path = full path to file + +- Delete empty directories: + Dir: + +- Run program with parameters: + Run:// + +Directives are parsed from the end of the file backwards as the first step of uninstall. + +IMPORTANT: From GIMP 2.10.12 onwards (Inno Setup 6 with support for per-user install), Registry keys referring to HKCR will be +processed by the installer as the first step of install (and the entries will be removed from uninst.inf), since file associations +code was rewritten. + +*) +procedure ParseUninstInf(); +var i,d: Integer; + sWhat: String; +begin + for i := GetArrayLength(asUninstInf) - 1 downto 0 do + begin + + DebugMsg('ParseUninstInf',asUninstInf[i]); + + if (Length(asUninstInf[i]) = 0) or (asUninstInf[i][1] = '#') then //skip comments and empty lines + continue; + + d := Pos(':',asUninstInf[i]); + if d = 0 then + begin + DebugMsg('ParseUninstInf','Malformed line: ' + asUninstInf[i]); + continue; + end; + + sWhat := Copy(asUninstInf[i],d+1,Length(asUninstInf[i])); + + case Copy(asUninstInf[i],1,d) of + 'RegKey:': UninstInfRegKey(sWhat,False); + 'RegKeyEmpty:': UninstInfRegKey(sWhat,True); + 'RegVal:': UninstInfRegVal(sWhat); + 'File:': UninstInfFile(sWhat); + 'Dir:': UninstInfDir(sWhat); + 'Run:': UninstInfRun(sWhat); + end; + + end; + +end; + +procedure CurUninstallStepChanged(CurStep: TUninstallStep); +begin + DebugMsg('CurUninstallStepChanged',''); + case CurStep of + usUninstall: + begin + LoadStringsFromFile(ExpandConstant('{app}\uninst\uninst.inf'),asUninstInf); + ParseUninstInf(); + end; + //usPostUninstall: + end; +end; + + +procedure AssociationsCleanUp(); +var i, d, countNew,countUI: Integer; + asTemp, asNew: TArrayOfString; + sKey,sVal: String; + iRootKey: Integer; +begin + if FileExists(ExpandConstant('{app}\uninst\uninst.inf')) then + begin + DebugMsg('AssociationsCleanUp','Parsing old uninst.inf'); + LoadStringsFromFile(ExpandConstant('{app}\uninst\uninst.inf'),asTemp); + + countNew := 0; + countUI := 0; + SetArrayLength(asNew, GetArrayLength(asTemp)); + SetArrayLength(asUninstInf, GetArrayLength(asTemp)); + + for i := 0 to GetArrayLength(asTemp) - 1 do //extract associations-related entries from uninst.inf + begin + + if (Length(asTemp[i]) = 0) or (asTemp[i][1] = '#') then //comment/empty line + begin + asNew[countNew] := asTemp[i]; + Inc(countNew); + continue; + end; + + d := Pos(':',asTemp[i]); + if d = 0 then //something wrong, ignore + continue; + + if Copy(asTemp[i],1,3) = 'Reg' then + begin + + sVal := 'nil'; + if not SplitRegParams(Copy(asTemp[i], d + 1, Length(asTemp[i])),iRootKey,sKey,sVal) then + continue; //malformed line, ignore + + if iRootKey = HKCR then //old association, prepare for cleanup + begin + DebugMsg('AssociationsCleanUp','Preparing for cleanup: '+asTemp[i]); + asUninstInf[countUI] := asTemp[i]; + Inc(countUI); + continue; + end; + + end; + + //something else, keep for new uninst.inf + asNew[countNew] := asTemp[i]; + Inc(countNew); + + end; + + SetArrayLength(asNew, countNew); + SetArrayLength(asUninstInf, countUI); + + SaveStringsToUTF8File(ExpandConstant('{app}\uninst\uninst.inf'), asNew, False); //replace uninst.inf with a cleaned one + + ParseUninstInf(); //remove old associations + end; +end; diff --git a/build/windows/installer/version.isi b/build/windows/installer/util_version.isi similarity index 96% rename from build/windows/installer/version.isi rename to build/windows/installer/util_version.isi index ede6d5c232..706109446f 100644 --- a/build/windows/installer/version.isi +++ b/build/windows/installer/util_version.isi @@ -1,26 +1,26 @@ -//set the version string - -#define public - -#if !Defined(VERSION) - #error "VERSION must be defined" -#endif - -#define GTK_VER=GetFileVersion(AddBackslash(DEPS_DIR64) + "bin\libgtk-win32-2.0-0.dll") - -#define public -//used in the component list -#define GTK_VERSION=Copy(GTK_VER,1,RPos(".",GTK_VER)-1) - -#define MAJOR=Copy(VERSION,1,Pos(".",VERSION)-1) -#define MINOR=Copy(VERSION,Pos(".",VERSION)+1) -#define MICRO=Copy(MINOR,Pos(".",MINOR)+1) -#expr MINOR=Copy(MINOR,1,Pos(".",MINOR)-1) - -#if Int(MINOR) % 2 == 1 - #define DEVEL="-dev" - #define DIR_VER=MAJOR + "." + MINOR -#else - #define DEVEL="" - #define DIR_VER=MAJOR + ".0" -#endif +//set the version string + +#define public + +#if !Defined(VERSION) + #error "VERSION must be defined" +#endif + +#define GTK_VER=GetFileVersion(AddBackslash(DEPS_DIR64) + "bin\libgtk-win32-2.0-0.dll") + +#define public +//used in the component list +#define GTK_VERSION=Copy(GTK_VER,1,RPos(".",GTK_VER)-1) + +#define MAJOR=Copy(VERSION,1,Pos(".",VERSION)-1) +#define MINOR=Copy(VERSION,Pos(".",VERSION)+1) +#define MICRO=Copy(MINOR,Pos(".",MINOR)+1) +#expr MINOR=Copy(MINOR,1,Pos(".",MINOR)-1) + +#if Int(MINOR) % 2 == 1 + #define DEVEL="-dev" + #define DIR_VER=MAJOR + "." + MINOR +#else + #define DEVEL="" + #define DIR_VER=MAJOR + ".0" +#endif diff --git a/devel-docs/interpreters.txt b/devel-docs/interpreters.txt index dd4a57c794..454fddcc38 100644 --- a/devel-docs/interpreters.txt +++ b/devel-docs/interpreters.txt @@ -68,7 +68,7 @@ On Linux and MacOS, you simply need a shebang in a plugin text file. On Windows, you must also define an .interp file. The .interp files are part of GIMP's installation on Windows. The .interp files are built when the Windows installer is built. -See the source file: /build/windows/installer/gimp3264.iss . +See the source file: /build/windows/installer/base_gimp3264.iss . A user can optionally create .interp files on Linux and MacOS. But they are not usually part of a Linux installation. @@ -196,7 +196,7 @@ If a GIMP developer adds an interpreter to the GIMP package, they must modify GIMP's build for Windows to ensure proper .interp files are installed. -See the repo file: /build/windows/installer/gimp3264.iss . +See the repo file: /build/windows/installer/base_gimp3264.iss . For the convenience of users, we usually install an .interp file having many lines. Only one "program" line is needed if users only install canonical plugin text files