Bump version number.

Bump version number.

; Basic setup script for the Inno Setep installer builder.  For more
; information on the free installer builder, see www.jrsoftware.org.
;
; This script was contributed by Tim Peters.

[Setup]
AppName=expat
AppId=expat
AppVersion=1.95.3
AppVerName=expat 1.95.3
AppCopyright=Copyright  1998-2001 Thai Open Source Software Center, Clark Cooper, and the Expat maintainers
DefaultDirName={sd}\Expat-1.95.3
AppPublisher=The Expat Developers
AppPublisherURL=http://expat.sourceforge.net/
AppSupportURL=http://expat.sourceforge.net/
AppUpdatesURL=http://expat.sourceforge.net/
UninstallDisplayName=Expat XML Parser (version 1.95.3)
UninstallFilesDir={app}\Uninstall

CompressLevel=9
SourceDir=..
OutputDir=win32
DisableStartupPrompt=yes
AllowNoIcons=yes
DisableProgramGroupPage=yes
DisableReadyPage=yes

[Files]
CopyMode: alwaysoverwrite; Source: xmlwf\Release\*.exe; DestDir: "{app}"
CopyMode: alwaysoverwrite; Source: win32\MANIFEST.txt;  DestDir: "{app}"
CopyMode: alwaysoverwrite; Source: COPYING;             DestDir: "{app}"; DestName: COPYING.txt
CopyMode: alwaysoverwrite; Source: NEWS;                DestDir: "{app}"; DestName: NEWS.txt
CopyMode: alwaysoverwrite; Source: README;              DestDir: "{app}"; DestName: README.txt
CopyMode: alwaysoverwrite; Source: doc\*.html;          DestDir: "{app}\Doc"
CopyMode: alwaysoverwrite; Source: doc\*.css;           DestDir: "{app}\Doc"
CopyMode: alwaysoverwrite; Source: lib\Release\*.dll;   DestDir: "{app}\Libs"
CopyMode: alwaysoverwrite; Source: lib\Release\*.lib;   DestDir: "{app}\Libs"
CopyMode: alwaysoverwrite; Source: expat.dsw;           DestDir: "{app}\Source"
CopyMode: alwaysoverwrite; Source: lib\*.c;             DestDir: "{app}\Source\lib"
CopyMode: alwaysoverwrite; Source: lib\*.h;             DestDir: "{app}\Source\lib"
CopyMode: alwaysoverwrite; Source: lib\*.dsp;           DestDir: "{app}\Source\lib"
CopyMode: alwaysoverwrite; Source: examples\*.c;        DestDir: "{app}\Source\examples"
CopyMode: alwaysoverwrite; Source: examples\*.dsp;      DestDir: "{app}\Source\examples"
CopyMode: alwaysoverwrite; Source: xmlwf\*.c*;          DestDir: "{app}\Source\xmlwf"
CopyMode: alwaysoverwrite; Source: xmlwf\*.h;           DestDir: "{app}\Source\xmlwf"
CopyMode: alwaysoverwrite; Source: xmlwf\*.dsp;         DestDir: "{app}\Source\xmlwf"

[Messages]
WelcomeLabel1=Welcome to the Expat XML Parser Setup Wizard
WelcomeLabel2=This will install [name/ver] on your computer.%n%nExpat is an XML parser with a C-language API, and is primarily made available to allow developers to build applications which use XML using a portable API and fast implementation.%n%nIt is strongly recommended that you close all other applications you have running before continuing. This will help prevent any conflicts during the installation process.

; Basic setup script for the Inno Setep installer builder.  For more
; information on the free installer builder, see www.jrsoftware.org.
;
; This script was contributed by Tim Peters.

[Setup]
AppName=expat
AppId=expat
AppVersion=1.95.2
AppVerName=expat 1.95.2
AppCopyright=Copyright  1998-2001 Thai Open Source Software Center, Clark Cooper, and the Expat maintainers
DefaultDirName={sd}\Expat-1.95.2
AppPublisher=The Expat Developers
AppPublisherURL=http://expat.sourceforge.net/
AppSupportURL=http://expat.sourceforge.net/
AppUpdatesURL=http://expat.sourceforge.net/
UninstallDisplayName=Expat XML Parser (version 1.95.2)
UninstallFilesDir={app}\Uninstall

CompressLevel=9
SourceDir=..
OutputDir=win32
DisableStartupPrompt=yes
AllowNoIcons=yes
DisableProgramGroupPage=yes
DisableReadyPage=yes

[Files]
CopyMode: alwaysoverwrite; Source: xmlwf\Release\*.exe; DestDir: "{app}"
CopyMode: alwaysoverwrite; Source: win32\MANIFEST.txt;  DestDir: "{app}"
CopyMode: alwaysoverwrite; Source: COPYING;             DestDir: "{app}"; DestName: COPYING.txt
CopyMode: alwaysoverwrite; Source: README;              DestDir: "{app}"; DestName: README.txt
CopyMode: alwaysoverwrite; Source: doc\*.html;          DestDir: "{app}\Doc"
CopyMode: alwaysoverwrite; Source: doc\*.css;           DestDir: "{app}\Doc"
CopyMode: alwaysoverwrite; Source: lib\Release\*.dll;   DestDir: "{app}\Libs"
CopyMode: alwaysoverwrite; Source: lib\Release\*.lib;   DestDir: "{app}\Libs"
CopyMode: alwaysoverwrite; Source: expat.dsw;           DestDir: "{app}\Source"
CopyMode: alwaysoverwrite; Source: lib\*.c;             DestDir: "{app}\Source\lib"
CopyMode: alwaysoverwrite; Source: lib\*.h;             DestDir: "{app}\Source\lib"
CopyMode: alwaysoverwrite; Source: lib\*.dsp;           DestDir: "{app}\Source\lib"
CopyMode: alwaysoverwrite; Source: examples\*.c;        DestDir: "{app}\Source\examples"
CopyMode: alwaysoverwrite; Source: examples\*.dsp;      DestDir: "{app}\Source\examples"
CopyMode: alwaysoverwrite; Source: xmlwf\*.c*;          DestDir: "{app}\Source\xmlwf"
CopyMode: alwaysoverwrite; Source: xmlwf\*.h;           DestDir: "{app}\Source\xmlwf"
CopyMode: alwaysoverwrite; Source: xmlwf\*.dsp;         DestDir: "{app}\Source\xmlwf"

[Messages]
WelcomeLabel1=Welcome to the Expat XML Parser Setup Wizard
WelcomeLabel2=This will install [name/ver] on your computer.%n%nExpat is an XML parser with a C-language API, and is primarily made available to allow developers to build applications which use XML using a portable API and fast implementation.%n%nIt is strongly recommended that you close all other applications you have running before continuing. This will help prevent any conflicts during the installation process.


Now deleting Inspectors and Layouts folders on install so files with changed names are not duplicated.

git-svn-id: 6df4de2eefc91e66a2e4972022441cb98a34e030@3597 86afb187-6117-0410-83e3-87b601379a31

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#ifndef APP_VERSION
#define APP_VERSION "0.0"
#endif

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{4FD376DB-F23F-4A6E-9736-F216FBD42671}
AppName=Neuroptikon
AppVerName=Neuroptikon {#APP_VERSION}
AppPublisher=HHMI Janelia Farm Research Campus
AppPublisherURL=http://openwiki.janelia.org/wiki/display/neuroptikon
AppSupportURL=http://openwiki.janelia.org/wiki/display/neuroptikon
AppUpdatesURL=http://openwiki.janelia.org/wiki/display/neuroptikon
DefaultDirName={pf}\Neuroptikon
DefaultGroupName=Neuroptikon
OutputBaseFilename=Neuroptikon_{#APP_VERSION}
Compression=lzma
SolidCompression=yes
Uninstallable=yes
UninstallDisplayIcon={app}\Neuroptikon.exe

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
; TODO: Figure out how to make the build path relative to the path of this file.
Source: "C:\Documents and Settings\midgleyf\Desktop\Neuroptikon\Source\build\Neuroptikon {#APP_VERSION}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\Neuroptikon"; Filename: "{app}\Neuroptikon.exe"
Name: "{group}\Sample Scripts"; Filename: "{app}\Scripts"
Name: "{group}\Uninstall Neuroptikon"; Filename: "{uninstallexe}"
Name: "{commondesktop}\Neuroptikon"; Filename: "{app}\Neuroptikon.exe"; Tasks: desktopicon
Name: "{commondesktop}\Neuroptikon Sample Scripts"; Filename: "{app}\Scripts";

[Run]
Filename: "{app}\Neuroptikon.exe"; Description: "{cm:LaunchProgram,Neuroptikon}"; Flags: nowait postinstall skipifsilent

[InstallDelete]
Type: filesandordirs; Name: "{app}\Inspectors"
Type: filesandordirs; Name: "{app}\Layouts"

[UninstallDelete]
Type: filesandordirs; Name: "{app}\Images"
Type: filesandordirs; Name: "{app}\Inspectors"
Type: filesandordirs; Name: "{app}\Layouts"
Type: filesandordirs; Name: "{app}\Shapes"
Type: filesandordirs; Name: "{app}\Textures"

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#ifndef APP_VERSION
#define APP_VERSION "0.0"
#endif

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{4FD376DB-F23F-4A6E-9736-F216FBD42671}
AppName=Neuroptikon
AppVerName=Neuroptikon {#APP_VERSION}
AppPublisher=HHMI Janelia Farm Research Campus
AppPublisherURL=http://openwiki.janelia.org/wiki/display/neuroptikon
AppSupportURL=http://openwiki.janelia.org/wiki/display/neuroptikon
AppUpdatesURL=http://openwiki.janelia.org/wiki/display/neuroptikon
DefaultDirName={pf}\Neuroptikon
DefaultGroupName=Neuroptikon
OutputBaseFilename=Neuroptikon_{#APP_VERSION}
Compression=lzma
SolidCompression=yes
Uninstallable=yes
UninstallDisplayIcon={app}\Neuroptikon.exe

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
; TODO: Figure out how to make the build path relative to the path of this file.
Source: "C:\Documents and Settings\midgleyf\Desktop\Neuroptikon\Source\build\Neuroptikon {#APP_VERSION}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\Neuroptikon"; Filename: "{app}\Neuroptikon.exe"
Name: "{group}\Sample Scripts"; Filename: "{app}\Scripts"
Name: "{group}\Uninstall Neuroptikon"; Filename: "{uninstallexe}"
Name: "{commondesktop}\Neuroptikon"; Filename: "{app}\Neuroptikon.exe"; Tasks: desktopicon
Name: "{commondesktop}\Neuroptikon Sample Scripts"; Filename: "{app}\Scripts";

[Run]
Filename: "{app}\Neuroptikon.exe"; Description: "{cm:LaunchProgram,Neuroptikon}"; Flags: nowait postinstall skipifsilent

[UninstallDelete]
Type: filesandordirs; Name: "{app}\Images"
Type: filesandordirs; Name: "{app}\Inspectors"
Type: filesandordirs; Name: "{app}\Layouts"
Type: filesandordirs; Name: "{app}\Shapes"
Type: filesandordirs; Name: "{app}\Textures"


auto merge of #19725 : vadimcn/rust/inst-path, r=alexcrichton

Change default installation directory to %SYSTEMDRIVE%\Rust.
Modify user PATH, rather than system PATH.

#define CFG_VERSION_WIN GetEnv("CFG_VERSION_WIN")
#define CFG_RELEASE GetEnv("CFG_RELEASE")
#define CFG_PACKAGE_NAME GetEnv("CFG_PACKAGE_NAME")
#define CFG_BUILD GetEnv("CFG_BUILD")

[Setup]

SetupIconFile=rust-logo.ico
AppName=Rust
AppVersion={#CFG_RELEASE}
AppCopyright=Copyright (C) 2006-2014 Mozilla Foundation, MIT license
AppPublisher=Mozilla Foundation
AppPublisherURL=http://www.rust-lang.org
VersionInfoVersion={#CFG_VERSION_WIN}
LicenseFile=LICENSE.txt

PrivilegesRequired=lowest
DisableWelcomePage=true
DisableProgramGroupPage=true
DisableReadyPage=true
DisableStartupPrompt=true

OutputDir=.\dist\
SourceDir=.\
OutputBaseFilename={#CFG_PACKAGE_NAME}-{#CFG_BUILD}
DefaultDirName={sd}\Rust

Compression=lzma2/ultra
InternalCompressLevel=ultra
SolidCompression=true

ChangesEnvironment=true
ChangesAssociations=no
AllowUNCPath=false
AllowNoIcons=true
Uninstallable=yes

[Tasks]
Name: modifypath; Description: &Add {app}\bin to your PATH (recommended)

[Components]
Name: rust; Description: "Rust compiler and standard crates"; Types: full compact custom; Flags: fixed
Name: gcc; Description: "Linker and platform libraries"; Types: full

[Files]
Source: "tmp/dist/win/rust/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rust
Source: "tmp/dist/win/gcc/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: gcc

[Code]
const
	ModPathName = 'modifypath';
	ModPathType = 'user';

function ModPathDir(): TArrayOfString;
begin
	setArrayLength(Result, 1)
	Result[0] := ExpandConstant('{app}\bin');
end;

#include "modpath.iss"
#include "upgrade.iss"

// Both modpath.iss and upgrade.iss want to overload CurStepChanged.
// This version does the overload then delegates to each.

procedure CurStepChanged(CurStep: TSetupStep);
begin
  UpgradeCurStepChanged(CurStep);
  ModPathCurStepChanged(CurStep);
end;

#define CFG_VERSION_WIN GetEnv("CFG_VERSION_WIN")
#define CFG_RELEASE GetEnv("CFG_RELEASE")
#define CFG_PACKAGE_NAME GetEnv("CFG_PACKAGE_NAME")
#define CFG_BUILD GetEnv("CFG_BUILD")

[Setup]

SetupIconFile=rust-logo.ico
AppName=Rust
AppVersion={#CFG_RELEASE}
AppCopyright=Copyright (C) 2006-2014 Mozilla Foundation, MIT license
AppPublisher=Mozilla Foundation
AppPublisherURL=http://www.rust-lang.org
VersionInfoVersion={#CFG_VERSION_WIN}
LicenseFile=LICENSE.txt

PrivilegesRequired=lowest
DisableWelcomePage=true
DisableProgramGroupPage=true
DisableReadyPage=true
DisableStartupPrompt=true

OutputDir=.\dist\
SourceDir=.\
OutputBaseFilename={#CFG_PACKAGE_NAME}-{#CFG_BUILD}
DefaultDirName={pf32}\Rust

Compression=lzma2/ultra
InternalCompressLevel=ultra
SolidCompression=true

ChangesEnvironment=true
ChangesAssociations=no
AllowUNCPath=false
AllowNoIcons=true
Uninstallable=yes

[Tasks]
Name: modifypath; Description: &Add {app}\bin to your PATH (recommended)

[Components]
Name: rust; Description: "Rust compiler and standard crates"; Types: full compact custom; Flags: fixed
Name: gcc; Description: "Linker and platform libraries"; Types: full

[Files]
Source: "tmp/dist/win/rust/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: rust
Source: "tmp/dist/win/gcc/*.*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: gcc

[Code]
const
	ModPathName = 'modifypath';
	ModPathType = 'system';

function ModPathDir(): TArrayOfString;
begin
	setArrayLength(Result, 1)
	Result[0] := ExpandConstant('{app}\bin');
end;

#include "modpath.iss"
#include "upgrade.iss"

// Both modpath.iss and upgrade.iss want to overload CurStepChanged.
// This version does the overload then delegates to each.

procedure CurStepChanged(CurStep: TSetupStep);
begin
  UpgradeCurStepChanged(CurStep);
  ModPathCurStepChanged(CurStep);
end;


Use custom pfm runtime installer

Use custom pfm runtime installer

#define AppName = 'VapourSynth'
#define Version = 'R34'

[Setup]
OutputDir=Compiled
OutputBaseFilename=VapourSynth-{#= Version}
Compression=lzma2/max
InternalCompressLevel=max
SolidCompression=yes
LZMAUseSeparateProcess=yes
VersionInfoDescription={#= AppName} {#= Version} Installer
AppId={#= AppName}
AppName={#= AppName} {#= Version}
AppVersion={#= Version}
AppVerName={#= AppName} {#= Version}
AppPublisher=Fredrik Mellbin
AppPublisherURL=http://www.vapoursynth.com/
AppSupportURL=http://www.vapoursynth.com/
AppUpdatesURL=http://www.vapoursynth.com/
VersionInfoVersion=1.34.0.0
DefaultDirName={pf32}\VapourSynth
DefaultGroupName=VapourSynth
AllowCancelDuringInstall=no
AllowNoIcons=yes
AllowUNCPath=no
MinVersion=6.0
PrivilegesRequired=admin
FlatComponentsList=yes
ArchitecturesAllowed=x86 x64
ArchitecturesInstallIn64BitMode=x64

[Languages]
Name: "en"; MessagesFile: "compiler:Default.isl"

[Types]
Name: Full; Description: Full installation; Flags: iscustom

[Components]
Name: "vs64"; Description: "VapourSynth 64-bit"; Types: Full; Check: HasPython64; Flags: disablenouninstallwarning
Name: "vs32"; Description: "VapourSynth 32-bit"; Types: Full; Check: HasPython32; Flags: disablenouninstallwarning
Name: "sdk"; Description: "VapourSynth SDK"; Flags: fixed disablenouninstallwarning; Types: Full
Name: "pismo"; Description: "Pismo PFM Runtime (required for AVFS)"; Types: Full; Flags: disablenouninstallwarning
Name: "vsruntimes"; Description: "Visual Studio Runtimes (2013 & 2015)"; Types: Full; Flags: disablenouninstallwarning

[Tasks]
Name: newvpyfile; Description: "Add 'New VapourSynth Python Script' option to shell context menu"; GroupDescription: "New File Shortcuts:"; Components: vs32 vs64

[Run]
Filename: "{app}\pismo\pfm-183-vapoursynth-win.exe"; Flags: runhidden; Components: pismo

[Files]
;core binaries
Source: template.vpy; DestDir: {app}; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32 vs64
Source: vapoursynth.pth; DestDir: {code:GetPythonPath32}\Lib\site-packages; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: vapoursynth.pth; DestDir: {code:GetPythonPath64}\Lib\site-packages; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\vapoursynth.cp35-win32.pyd; DestDir: {code:GetPythonPath32}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\vapoursynth.cp35-win_amd64.pyd; DestDir: {code:GetPythonPath64}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vapoursynth.dll; DestDir: {code:GetPythonPath32}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vapoursynth.dll; DestDir: {code:GetPythonPath64}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\Release\vapoursynth.dll; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\vapoursynth.pdb; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vapoursynth.dll; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\vapoursynth.pdb; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\avfs.exe; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\avfs.exe; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vspipe.exe; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vspipe.exe; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vsvfw.dll; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vsvfw.dll; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vsscript.dll; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vsscript.dll; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\Release\vsscript.dll; DestDir: {sys}; Flags: uninsrestartdelete restartreplace 32bit; Components: vs32
Source: ..\msvc_project\x64\Release\vsscript.dll; DestDir: {sys}; Flags: uninsrestartdelete restartreplace 64bit; Components: vs64

;sdk
Source: ..\include\VapourSynth.h; DestDir: {app}\sdk\include\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\include\VSHelper.h; DestDir: {app}\sdk\include\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\include\VSScript.h; DestDir: {app}\sdk\include\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\Release\vsscript.lib; DestDir: {app}\sdk\lib32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\x64\Release\vsscript.lib; DestDir: {app}\sdk\lib64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\Release\vapoursynth.lib; DestDir: {app}\sdk\lib32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\x64\Release\vapoursynth.lib; DestDir: {app}\sdk\lib64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\sdk\filter_skeleton.c; DestDir: {app}\sdk\examples; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\sdk\invert_example.c; DestDir: {app}\sdk\examples; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\sdk\vsscript_example.c; DestDir: {app}\sdk\examples; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk

;bundled plugins
Source: x86\plugins\*; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\AvsCompat.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\EEDI3.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\RemoveGrainVS.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\Vinverse.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\VIVTC.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32

Source: x64\plugins\*; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\AvsCompat.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\EEDI3.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\RemoveGrainVS.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\Vinverse.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\VIVTC.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

;pismo installer
Source: "pfm-183-vapoursynth-win.exe"; DestDir: {app}\pismo; Flags: ignoreversion uninsrestartdelete restartreplace; Components: pismo

; Create the general autoload directory
[Dirs]
Name: "{app}\plugins32"; Flags: uninsalwaysuninstall; Components: vs32
Name: "{app}\plugins64"; Flags: uninsalwaysuninstall; Components: vs64

[Icons]
Name: {group}\VapourSynth Website; Filename: http://www.vapoursynth.com/
Name: {group}\Documentation; Filename: http://www.vapoursynth.com/doc/
Name: {group}\Global Autoload Directory (32bit); Filename: {app}\plugins32; Components: vs32
Name: {group}\Global Autoload Directory (64bit); Filename: {app}\plugins64; Components: vs64
Name: {group}\VapourSynth SDK; Filename: {app}\sdk; Components: sdk

[Registry]
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Version"; ValueData: {#= Version}; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Version"; ValueData: {#= Version}; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Path"; ValueData: "{app}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Path"; ValueData: "{app}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins"; ValueData: "{app}\core32\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins"; ValueData: "{app}\core64\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins"; ValueData: "{app}\plugins32"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins"; ValueData: "{app}\plugins64"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VapourSynthDLL"; ValueData: "{app}\core32\vapoursynth.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VapourSynthDLL"; ValueData: "{app}\core64\vapoursynth.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VSScriptDLL"; ValueData: "{app}\core32\vsscript.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "PythonPath"; ValueData: "{code:GetPythonPath32}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VSScriptDLL"; ValueData: "{app}\core64\vsscript.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "PythonPath"; ValueData: "{code:GetPythonPath64}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

; legacy entries, will one day be removed
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins32"; ValueData: "{app}\core32\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins64"; ValueData: "{app}\core64\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins32"; ValueData: "{app}\plugins32"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins64"; ValueData: "{app}\plugins64"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

; new vpy file shortcut task
Root: HKLM; Subkey: SOFTWARE\Classes\.vpy\ShellNew; ValueType: string; ValueName: "FileName"; ValueData: "{app}\template.vpy"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: newvpyfile

; 32bit vfw
Root: HKLM32; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}; ValueType: string; ValueName: ""; ValueData: "VapourSynth"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: ""; ValueData: "{app}\core32\vsvfw.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: "ThreadingModel"; ValueData: "Apartment"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: ""; ValueData: ""; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: "Source Filter"; ValueData: "{{D3588AB0-0781-11CE-B03A-0020AF0BA770}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\.vpy; ValueType: string; ValueName: ""; ValueData: "vpyfile"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\vpyfile; ValueType: string; ValueName: ""; ValueData: "VapourSynth Python Script"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\vpyfile\DefaultIcon; ValueType: string; ValueName: ""; ValueData: "{app}\core32\vsvfw.dll,0"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\AVIFile\Extensions\VPY; ValueType: string; ValueName: ""; ValueData: "{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32

; 64bit vfw
Root: HKLM64; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}; ValueType: string; ValueName: ""; ValueData: "VapourSynth"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: ""; ValueData: "{app}\core64\vsvfw.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: "ThreadingModel"; ValueData: "Apartment"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: ""; ValueData: ""; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: "Source Filter"; ValueData: "{{D3588AB0-0781-11CE-B03A-0020AF0BA770}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\.vpy; ValueType: string; ValueName: ""; ValueData: "vpyfile"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\vpyfile; ValueType: string; ValueName: ""; ValueData: "VapourSynth Python Script"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\vpyfile\DefaultIcon; ValueType: string; ValueName: ""; ValueData: "{app}\core64\vsvfw.dll,0"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\AVIFile\Extensions\VPY; ValueType: string; ValueName: ""; ValueData: "{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

[Code]
#include "scripts\products.iss"
#include "scripts\products\msiproduct.iss"
#include "scripts\products\vcredist2013.iss"
#include "scripts\products\vcredist2015.iss"

type
  TPythonPath = record
    DisplayName: string;
    InstallPath: string;
    Bitness: Integer;
  end;

var
  Runtimes32Added: Boolean;
  Runtimes64Added: Boolean;
  PythonInstallations: array of TPythonPath;
  PythonPage: TWizardPage;
  PythonList: TNewCheckListBox;
  Python32Path: string;
  Python64Path: string;

function HasPython32: Boolean;
var
  Counter: Integer;
begin
  Result := False;
  for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
    if PythonInstallations[Counter].Bitness = 32 then
      Result := True;
end;

function HasPython64: Boolean;
var
  Counter: Integer;
begin
  Result := False;
  for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
    if PythonInstallations[Counter].Bitness = 64 then
      Result := True;
end;

procedure GetPythonInstallations2(RegRoot: Integer; RegPath: string; AssumeBitness: Integer);
var
  Names, Tags: TArrayOfString;
  Nc, Tc: Integer;
  RegPathTemp: string;
  Temp: string;
  DisplayName, InstallPath: string;
  Bitness: Integer;
begin
  if RegGetSubkeyNames(RegRoot, RegPath, Names) then
  begin
    for Nc := 0 to GetArrayLength(Names) - 1 do
    begin
      if RegGetSubkeyNames(RegRoot, RegPath + '\' + Names[Nc], Tags) then
      begin
        for Tc := 0 to GetArrayLength(Tags) - 1 do
        begin
          RegPathTemp := RegPath + '\' + Names[Nc] + '\' + Tags[Tc];
          Bitness := AssumeBitness;
          if (not RegQueryStringValue(RegRoot, RegPathTemp, 'SysVersion', Temp)) or (Temp <> '3.5') then
            continue;
          if RegQueryStringValue(RegRoot, RegPathTemp, 'SysArchitecture', Temp) then
          begin
            if Temp = '32bit' then
              Bitness := 32
            else if Temp = '64bit' then
              Bitness := 64;
          end;

          if RegQueryStringValue(RegRoot, RegPathTemp, 'DisplayName', DisplayName) and RegQueryStringValue(RegRoot, RegPathTemp + '\InstallPath', '', InstallPath) then
          begin
             SetArrayLEngth(PythonInstallations, GetArrayLength(PythonInstallations) + 1);
             PythonInstallations[GetArrayLength(PythonInstallations) - 1].DisplayName := DisplayName;
             PythonInstallations[GetArrayLength(PythonInstallations) - 1].InstallPath := InstallPath;
             PythonInstallations[GetArrayLength(PythonInstallations) - 1].Bitness := Bitness;
          end;
        end;
      end;
    end;
  end;
end;

procedure GetPythonInstallations;
var
  Success: Boolean;
  PythonPath32: string;
  PythonPath64: string;
begin
  Success := RegQueryStringValue(HKCU32, 'SOFTWARE\Python\PythonCore\3.5-32\InstallPath', '', PythonPath32);
  if not Success then
    RegQueryStringValue(HKLM32, 'SOFTWARE\Python\PythonCore\3.5-32\InstallPath', '', PythonPath32);

  if Is64BitInstallMode then
  begin
    Success := RegQueryStringValue(HKCU, 'SOFTWARE\Python\PythonCore\3.5\InstallPath', '', PythonPath64);
    if not Success then
      RegQueryStringValue(HKLM, 'SOFTWARE\Python\PythonCore\3.5\InstallPath', '', PythonPath64);
  end;

  if PythonPath32 <> '' then
  begin
    SetArrayLEngth(PythonInstallations, GetArrayLength(PythonInstallations) + 1);
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].DisplayName := 'Python 3.5 (32-bit)';
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].InstallPath := PythonPath32;
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].Bitness := 32;
  end;

  if PythonPath64 <> '' then
  begin
    SetArrayLEngth(PythonInstallations, GetArrayLength(PythonInstallations) + 1);
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].DisplayName := 'Python 3.5 (64-bit)';
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].InstallPath := PythonPath64;
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].Bitness := 64;
  end;

  GetPythonInstallations2(HKCU, 'SOFTWARE\Python', 0);
  GetPythonInstallations2(HKLM32, 'SOFTWARE\Python', 32);
  if Is64BitInstallMode then
    GetPythonInstallations2(HKLM, 'SOFTWARE\Python', 64);
end;

procedure PopulatePythonInstallations(List: TNewCheckListBox);
var
  Counter: Integer;
  First: Boolean;
begin
  List.Items.Clear;

  if IsComponentSelected('vs32') then
  begin
    First := True;
    List.AddGroup('Python Environments (32-bit)', '', 0, nil);
    for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
      if PythonInstallations[Counter].Bitness = 32 then
        with PythonInstallations[Counter] do
        begin
          List.AddRadioButton(DisplayName, '(' + InstallPath + ')', 1, First, True, TObject(Counter));
          First := False;
        end;
  end;

  if IsComponentSelected('vs64') then
  begin
    First := True;
    List.AddGroup('Python Environments (64-bit)', '', 0, nil);
    for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
      if PythonInstallations[Counter].Bitness = 64 then
        with PythonInstallations[Counter] do
        begin
          List.AddRadioButton(DisplayName, '(' + InstallPath + ')', 1, First, True, TObject(Counter));
          First := False;
        end;
  end;
end;

function InitializeSetup: Boolean;
begin
  Runtimes32Added := False;
  Runtimes64Added := False;
  PythonList := nil;
  GetPythonInstallations;
  Result := True;
end;

procedure InitializeWizard();
begin
  PythonPage := CreateCustomPage(wpSelectComponents, 'Select Python Installations', 'Select one or more Python installations to use');
  PythonList := TNewCheckListBox.Create(PythonPage);

  with PythonList do
  begin
    Parent := PythonPage.Surface;
    Left := ScaleX(0);
    Top := ScaleY(0);
    Width := PythonPage.Surface.Width - ScaleX(0) * 2;
    Height := PythonPage.Surface.Height;
  end;
end;

function GetPythonPath32(Param: string): String;
begin
  Result := Python32Path;
end;

function GetPythonPath64(Param: String): String;
begin
  Result := Python64Path;
end;

// copied from the internets

/////////////////////////////////////////////////////////////////////
function GetUninstallString: String;
var
  sUnInstPath: String;
  sUnInstallString: String;
begin
  sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
  sUnInstallString := '';
  if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
    RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
  Result := sUnInstallString;
end;

/////////////////////////////////////////////////////////////////////
function IsUpgrade: Boolean;
begin
  Result := (GetUninstallString() <> '');
end;

/////////////////////////////////////////////////////////////////////
function UnInstallOldVersion: Integer;
var
  sUnInstallString: String;
  iResultCode: Integer;
begin
// Return Values:
// 1 - uninstall string is empty
// 2 - error executing the UnInstallString
// 3 - successfully executed the UnInstallString

  // default return value
  Result := 0;

  // get the uninstall string of the old app
  sUnInstallString := GetUninstallString();
  if sUnInstallString <> '' then begin
    sUnInstallString := RemoveQuotes(sUnInstallString);
    if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
      Result := 3
    else
      Result := 2;
  end
  else
    Result := 1;
end;

/////////////////////////////////////////////////////////////////////
procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep=ssInstall then
  begin
    if IsUpgrade() then
      UnInstallOldVersion();
  end;
end;

/////////////////////////////////////////////////////////////////////
function NextButtonClick(CurPageID: Integer): Boolean;
var
  Counter: Integer;
  Idx: Integer;
begin
  Result := True;
  if CurPageID = PythonPage.ID then
  begin
    for Counter := 0 to PythonList.Items.Count - 1 do
    begin
      if (PythonList.Checked[Counter]) and (PythonList.ItemLevel[Counter] = 1) then
      begin
        Idx := Integer(PythonList.ItemObject[Counter]);
        with PythonInstallations[Idx] do
        begin
          if Bitness = 64 then
            Python64Path := InstallPath
          else if Bitness = 32 then
            Python32Path := InstallPath;
        end;
      end;
    end;
  end
  else if CurPageID = wpSelectComponents then
  begin
    if not IsComponentSelected('vs32 or vs64') then
    begin
      Result := False;
      MsgBox('At least one version of the core library has to be installed.', mbCriticalError, MB_OK)
    end;

    PopulatePythonInstallations(PythonList);
  end
  else if CurPageID = wpReady then
  begin
    if IsComponentSelected('vsruntimes') and IsComponentSelected('vs32') and not Runtimes32Added then
    begin
      SetForceX86(True);
      vcredist2013();
      vcredist2015();
      SetForceX86(False);
      Runtimes32Added := True;
    end;
    if IsComponentSelected('vsruntimes') and IsComponentSelected('vs64') and not Runtimes64Added then
    begin
      vcredist2013();
      vcredist2015();
      Runtimes64Added := True;
    end;
    Result := NextButtonClick2(CurPageID);
  end;
end;

#define AppName = 'VapourSynth'
#define Version = 'R34'

[Setup]
OutputDir=Compiled
OutputBaseFilename=VapourSynth-{#= Version}
Compression=lzma2/max
InternalCompressLevel=max
SolidCompression=yes
LZMAUseSeparateProcess=yes
VersionInfoDescription={#= AppName} {#= Version} Installer
AppId={#= AppName}
AppName={#= AppName} {#= Version}
AppVersion={#= Version}
AppVerName={#= AppName} {#= Version}
AppPublisher=Fredrik Mellbin
AppPublisherURL=http://www.vapoursynth.com/
AppSupportURL=http://www.vapoursynth.com/
AppUpdatesURL=http://www.vapoursynth.com/
VersionInfoVersion=1.34.0.0
DefaultDirName={pf32}\VapourSynth
DefaultGroupName=VapourSynth
AllowCancelDuringInstall=no
AllowNoIcons=yes
AllowUNCPath=no
MinVersion=6.0
PrivilegesRequired=admin
FlatComponentsList=yes
ArchitecturesAllowed=x86 x64
ArchitecturesInstallIn64BitMode=x64

[Languages]
Name: "en"; MessagesFile: "compiler:Default.isl"

[Types]
Name: Full; Description: Full installation; Flags: iscustom

[Components]
Name: "vs64"; Description: "VapourSynth 64-bit"; Types: Full; Check: HasPython64; Flags: disablenouninstallwarning
Name: "vs32"; Description: "VapourSynth 32-bit"; Types: Full; Check: HasPython32; Flags: disablenouninstallwarning
Name: "sdk"; Description: "VapourSynth SDK"; Flags: fixed; Types: Full
Name: "vsruntimes"; Description: "Visual Studio Runtimes (2013 & 2015)"; Types: Full; Flags: disablenouninstallwarning

[Tasks]
Name: newvpyfile; Description: "Add 'New VapourSynth Python Script' option to shell context menu"; GroupDescription: "New File Shortcuts:"; Components: vs32 vs64

[Files]
;core binaries
Source: template.vpy; DestDir: {app}; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32 vs64
Source: vapoursynth.pth; DestDir: {code:GetPythonPath32}\Lib\site-packages; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: vapoursynth.pth; DestDir: {code:GetPythonPath64}\Lib\site-packages; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\vapoursynth.cp35-win32.pyd; DestDir: {code:GetPythonPath32}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\vapoursynth.cp35-win_amd64.pyd; DestDir: {code:GetPythonPath64}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vapoursynth.dll; DestDir: {code:GetPythonPath32}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vapoursynth.dll; DestDir: {code:GetPythonPath64}\Lib\site-packages\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\Release\vapoursynth.dll; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\vapoursynth.pdb; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vapoursynth.dll; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\vapoursynth.pdb; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\avfs.exe; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\avfs.exe; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vspipe.exe; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vspipe.exe; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vsvfw.dll; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vsvfw.dll; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

Source: ..\msvc_project\Release\vsscript.dll; DestDir: {app}\core32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\x64\Release\vsscript.dll; DestDir: {app}\core64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\Release\vsscript.dll; DestDir: {sys}; Flags: uninsrestartdelete restartreplace 32bit; Components: vs32
Source: ..\msvc_project\x64\Release\vsscript.dll; DestDir: {sys}; Flags: uninsrestartdelete restartreplace 64bit; Components: vs64

;sdk
Source: ..\include\VapourSynth.h; DestDir: {app}\sdk\include\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\include\VSHelper.h; DestDir: {app}\sdk\include\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\include\VSScript.h; DestDir: {app}\sdk\include\vapoursynth; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\Release\vsscript.lib; DestDir: {app}\sdk\lib32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\x64\Release\vsscript.lib; DestDir: {app}\sdk\lib64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\Release\vapoursynth.lib; DestDir: {app}\sdk\lib32; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\msvc_project\x64\Release\vapoursynth.lib; DestDir: {app}\sdk\lib64; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\sdk\filter_skeleton.c; DestDir: {app}\sdk\examples; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\sdk\invert_example.c; DestDir: {app}\sdk\examples; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk
Source: ..\sdk\vsscript_example.c; DestDir: {app}\sdk\examples; Flags: ignoreversion uninsrestartdelete restartreplace; Components: sdk

;bundled plugins
Source: x86\plugins\*; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\AvsCompat.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\EEDI3.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\RemoveGrainVS.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\Vinverse.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32
Source: ..\msvc_project\Release\VIVTC.dll; DestDir: {app}\core32\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs32

Source: x64\plugins\*; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\AvsCompat.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\EEDI3.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\RemoveGrainVS.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\Vinverse.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64
Source: ..\msvc_project\x64\Release\VIVTC.dll; DestDir: {app}\core64\plugins; Flags: ignoreversion uninsrestartdelete restartreplace; Components: vs64

; Create the general autoload directory
[Dirs]
Name: "{app}\plugins32"; Flags: uninsalwaysuninstall; Components: vs32
Name: "{app}\plugins64"; Flags: uninsalwaysuninstall; Components: vs64

[Icons]
Name: {group}\VapourSynth Website; Filename: http://www.vapoursynth.com/
Name: {group}\Documentation; Filename: http://www.vapoursynth.com/doc/
Name: {group}\Global Autoload Directory (32bit); Filename: {app}\plugins32; Components: vs32
Name: {group}\Global Autoload Directory (64bit); Filename: {app}\plugins64; Components: vs64
Name: {group}\VapourSynth SDK; Filename: {app}\sdk; Components: sdk

[Registry]
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Version"; ValueData: {#= Version}; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Version"; ValueData: {#= Version}; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Path"; ValueData: "{app}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Path"; ValueData: "{app}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins"; ValueData: "{app}\core32\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins"; ValueData: "{app}\core64\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins"; ValueData: "{app}\plugins32"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins"; ValueData: "{app}\plugins64"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VapourSynthDLL"; ValueData: "{app}\core32\vapoursynth.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VapourSynthDLL"; ValueData: "{app}\core64\vapoursynth.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VSScriptDLL"; ValueData: "{app}\core32\vsscript.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "PythonPath"; ValueData: "{code:GetPythonPath32}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "VSScriptDLL"; ValueData: "{app}\core64\vsscript.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "PythonPath"; ValueData: "{code:GetPythonPath64}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

; legacy entries, will one day be removed
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins32"; ValueData: "{app}\core32\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "CorePlugins64"; ValueData: "{app}\core64\plugins"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins32"; ValueData: "{app}\plugins32"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\VapourSynth; ValueType: string; ValueName: "Plugins64"; ValueData: "{app}\plugins64"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

; new vpy file shortcut task
Root: HKLM; Subkey: SOFTWARE\Classes\.vpy\ShellNew; ValueType: string; ValueName: "FileName"; ValueData: "{app}\template.vpy"; Flags: uninsdeletevalue uninsdeletekeyifempty; Tasks: newvpyfile

; 32bit vfw
Root: HKLM32; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}; ValueType: string; ValueName: ""; ValueData: "VapourSynth"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: ""; ValueData: "{app}\core32\vsvfw.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: "ThreadingModel"; ValueData: "Apartment"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: ""; ValueData: ""; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: "Source Filter"; ValueData: "{{D3588AB0-0781-11CE-B03A-0020AF0BA770}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\.vpy; ValueType: string; ValueName: ""; ValueData: "vpyfile"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\vpyfile; ValueType: string; ValueName: ""; ValueData: "VapourSynth Python Script"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\vpyfile\DefaultIcon; ValueType: string; ValueName: ""; ValueData: "{app}\core32\vsvfw.dll,0"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32
Root: HKLM32; Subkey: SOFTWARE\Classes\AVIFile\Extensions\VPY; ValueType: string; ValueName: ""; ValueData: "{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs32

; 64bit vfw
Root: HKLM64; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}; ValueType: string; ValueName: ""; ValueData: "VapourSynth"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: ""; ValueData: "{app}\core64\vsvfw.dll"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\CLSID\{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}\InProcServer32; ValueType: string; ValueName: "ThreadingModel"; ValueData: "Apartment"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: ""; ValueData: ""; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\Media Type\Extensions\.vpy; ValueType: string; ValueName: "Source Filter"; ValueData: "{{D3588AB0-0781-11CE-B03A-0020AF0BA770}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\.vpy; ValueType: string; ValueName: ""; ValueData: "vpyfile"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\vpyfile; ValueType: string; ValueName: ""; ValueData: "VapourSynth Python Script"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\vpyfile\DefaultIcon; ValueType: string; ValueName: ""; ValueData: "{app}\core64\vsvfw.dll,0"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64
Root: HKLM64; Subkey: SOFTWARE\Classes\AVIFile\Extensions\VPY; ValueType: string; ValueName: ""; ValueData: "{{58F74CA0-BD0E-4664-A49B-8D10E6F0C131}"; Flags: uninsdeletevalue uninsdeletekeyifempty; Components: vs64

[Code]
#include "scripts\products.iss"
#include "scripts\products\msiproduct.iss"
#include "scripts\products\vcredist2013.iss"
#include "scripts\products\vcredist2015.iss"

type
  TPythonPath = record
    DisplayName: string;
    InstallPath: string;
    Bitness: Integer;
  end;

var
  Runtimes32Added: Boolean;
  Runtimes64Added: Boolean;
  PythonInstallations: array of TPythonPath;
  PythonPage: TWizardPage;
  PythonList: TNewCheckListBox;
  Python32Path: string;
  Python64Path: string;

function HasPython32: Boolean;
var
  Counter: Integer;
begin
  Result := False;
  for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
    if PythonInstallations[Counter].Bitness = 32 then
      Result := True;
end;

function HasPython64: Boolean;
var
  Counter: Integer;
begin
  Result := False;
  for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
    if PythonInstallations[Counter].Bitness = 64 then
      Result := True;
end;

procedure GetPythonInstallations2(RegRoot: Integer; RegPath: string; AssumeBitness: Integer);
var
  Names, Tags: TArrayOfString;
  Nc, Tc: Integer;
  RegPathTemp: string;
  Temp: string;
  DisplayName, InstallPath: string;
  Bitness: Integer;
begin
  if RegGetSubkeyNames(RegRoot, RegPath, Names) then
  begin
    for Nc := 0 to GetArrayLength(Names) - 1 do
    begin
      if RegGetSubkeyNames(RegRoot, RegPath + '\' + Names[Nc], Tags) then
      begin
        for Tc := 0 to GetArrayLength(Tags) - 1 do
        begin
          RegPathTemp := RegPath + '\' + Names[Nc] + '\' + Tags[Tc];
          Bitness := AssumeBitness;
          if (not RegQueryStringValue(RegRoot, RegPathTemp, 'SysVersion', Temp)) or (Temp <> '3.5') then
            continue;
          if RegQueryStringValue(RegRoot, RegPathTemp, 'SysArchitecture', Temp) then
          begin
            if Temp = '32bit' then
              Bitness := 32
            else if Temp = '64bit' then
              Bitness := 64;
          end;

          if RegQueryStringValue(RegRoot, RegPathTemp, 'DisplayName', DisplayName) and RegQueryStringValue(RegRoot, RegPathTemp + '\InstallPath', '', InstallPath) then
          begin
             SetArrayLEngth(PythonInstallations, GetArrayLength(PythonInstallations) + 1);
             PythonInstallations[GetArrayLength(PythonInstallations) - 1].DisplayName := DisplayName;
             PythonInstallations[GetArrayLength(PythonInstallations) - 1].InstallPath := InstallPath;
             PythonInstallations[GetArrayLength(PythonInstallations) - 1].Bitness := Bitness;
          end;
        end;
      end;
    end;
  end;
end;

procedure GetPythonInstallations;
var
  Success: Boolean;
  PythonPath32: string;
  PythonPath64: string;
begin
  Success := RegQueryStringValue(HKCU32, 'SOFTWARE\Python\PythonCore\3.5-32\InstallPath', '', PythonPath32);
  if not Success then
    RegQueryStringValue(HKLM32, 'SOFTWARE\Python\PythonCore\3.5-32\InstallPath', '', PythonPath32);

  if Is64BitInstallMode then
  begin
    Success := RegQueryStringValue(HKCU, 'SOFTWARE\Python\PythonCore\3.5\InstallPath', '', PythonPath64);
    if not Success then
      RegQueryStringValue(HKLM, 'SOFTWARE\Python\PythonCore\3.5\InstallPath', '', PythonPath64);
  end;

  if PythonPath32 <> '' then
  begin
    SetArrayLEngth(PythonInstallations, GetArrayLength(PythonInstallations) + 1);
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].DisplayName := 'Python 3.5 (32-bit)';
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].InstallPath := PythonPath32;
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].Bitness := 32;
  end;

  if PythonPath64 <> '' then
  begin
    SetArrayLEngth(PythonInstallations, GetArrayLength(PythonInstallations) + 1);
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].DisplayName := 'Python 3.5 (64-bit)';
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].InstallPath := PythonPath64;
    PythonInstallations[GetArrayLength(PythonInstallations) - 1].Bitness := 64;
  end;

  GetPythonInstallations2(HKCU, 'SOFTWARE\Python', 0);
  GetPythonInstallations2(HKLM32, 'SOFTWARE\Python', 32);
  if Is64BitInstallMode then
    GetPythonInstallations2(HKLM, 'SOFTWARE\Python', 64);
end;

procedure PopulatePythonInstallations(List: TNewCheckListBox);
var
  Counter: Integer;
  First: Boolean;
begin
  List.Items.Clear;

  if IsComponentSelected('vs32') then
  begin
    First := True;
    List.AddGroup('Python Environments (32-bit)', '', 0, nil);
    for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
      if PythonInstallations[Counter].Bitness = 32 then
        with PythonInstallations[Counter] do
        begin
          List.AddRadioButton(DisplayName, '(' + InstallPath + ')', 1, First, True, TObject(Counter));
          First := False;
        end;
  end;

  if IsComponentSelected('vs64') then
  begin
    First := True;
    List.AddGroup('Python Environments (64-bit)', '', 0, nil);
    for Counter := 0 to GetArrayLength(PythonInstallations) - 1 do
      if PythonInstallations[Counter].Bitness = 64 then
        with PythonInstallations[Counter] do
        begin
          List.AddRadioButton(DisplayName, '(' + InstallPath + ')', 1, First, True, TObject(Counter));
          First := False;
        end;
  end;
end;

function InitializeSetup: Boolean;
begin
  Runtimes32Added := False;
  Runtimes64Added := False;
  PythonList := nil;
  GetPythonInstallations;
  Result := True;
end;

procedure InitializeWizard();
begin
  PythonPage := CreateCustomPage(wpSelectComponents, 'Select Python Installations', 'Select one or more Python installations to use');
  PythonList := TNewCheckListBox.Create(PythonPage);

  with PythonList do
  begin
    Parent := PythonPage.Surface;
    Left := ScaleX(0);
    Top := ScaleY(0);
    Width := PythonPage.Surface.Width - ScaleX(0) * 2;
    Height := PythonPage.Surface.Height;
  end;
end;

function GetPythonPath32(Param: string): String;
begin
  Result := Python32Path;
end;

function GetPythonPath64(Param: String): String;
begin
  Result := Python64Path;
end;

// copied from the internets

/////////////////////////////////////////////////////////////////////
function GetUninstallString: String;
var
  sUnInstPath: String;
  sUnInstallString: String;
begin
  sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
  sUnInstallString := '';
  if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
    RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
  Result := sUnInstallString;
end;

/////////////////////////////////////////////////////////////////////
function IsUpgrade: Boolean;
begin
  Result := (GetUninstallString() <> '');
end;

/////////////////////////////////////////////////////////////////////
function UnInstallOldVersion: Integer;
var
  sUnInstallString: String;
  iResultCode: Integer;
begin
// Return Values:
// 1 - uninstall string is empty
// 2 - error executing the UnInstallString
// 3 - successfully executed the UnInstallString

  // default return value
  Result := 0;

  // get the uninstall string of the old app
  sUnInstallString := GetUninstallString();
  if sUnInstallString <> '' then begin
    sUnInstallString := RemoveQuotes(sUnInstallString);
    if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
      Result := 3
    else
      Result := 2;
  end
  else
    Result := 1;
end;

/////////////////////////////////////////////////////////////////////
procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep=ssInstall then
  begin
    if IsUpgrade() then
      UnInstallOldVersion();
  end;
end;

/////////////////////////////////////////////////////////////////////
function NextButtonClick(CurPageID: Integer): Boolean;
var
  Counter: Integer;
  Idx: Integer;
begin
  Result := True;
  if CurPageID = PythonPage.ID then
  begin
    for Counter := 0 to PythonList.Items.Count - 1 do
    begin
      if (PythonList.Checked[Counter]) and (PythonList.ItemLevel[Counter] = 1) then
      begin
        Idx := Integer(PythonList.ItemObject[Counter]);
        with PythonInstallations[Idx] do
        begin
          if Bitness = 64 then
            Python64Path := InstallPath
          else if Bitness = 32 then
            Python32Path := InstallPath;
        end;
      end;
    end;
  end
  else if CurPageID = wpSelectComponents then
  begin
    if not IsComponentSelected('vs32 or vs64') then
    begin
      Result := False;
      MsgBox('At least one version of the core library has to be installed.', mbCriticalError, MB_OK)
    end;

    PopulatePythonInstallations(PythonList);
  end
  else if CurPageID = wpReady then
  begin
    if IsComponentSelected('vsruntimes') and IsComponentSelected('vs32') and not Runtimes32Added then
    begin
      SetForceX86(True);
      vcredist2013();
      vcredist2015();
      SetForceX86(False);
      Runtimes32Added := True;
    end;
    if IsComponentSelected('vsruntimes') and IsComponentSelected('vs64') and not Runtimes64Added then
    begin
      vcredist2013();
      vcredist2015();
      Runtimes64Added := True;
    end;
    Result := NextButtonClick2(CurPageID);
  end;
end;


Fixing setup

Fixing setup

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{C5AE352B-3A5A-45E7-855C-623590FB715E}
AppName=Psyche
AppVersion=0.1
;AppVerName=Psyche 0.1
OutputBaseFilename=Psyche_0.1-win32setup
AppPublisher=Qweex
AppPublisherURL=http://www.qweex.com/
AppSupportURL=http://www.qweex.com/
AppUpdatesURL=http://www.qweex.com/
DefaultDirName={pf}\Psyche
DefaultGroupName=Psyche
AllowNoIcons=yes
LicenseFile=C:\Steampunk\Dev\psyche\LICENSE
OutputDir=C:\Steampunk\Dev\psyche\bin
Compression=lzma
SolidCompression=yes

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
Source: "C:\Steampunk\Dev\psyche\bin\psyche.exe"; DestDir: "{app}"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\Psyche"; Filename: "{app}\main.exe"
Name: "{commondesktop}\Psyche"; Filename: "{app}\main.exe"; Tasks: desktopicon

[Run]
Filename: "{app}\main.exe"; Description: "{cm:LaunchProgram,Psyche}"; Flags: nowait postinstall skipifsilent
Filename: "{app}\README.md"; Description: "View the README file"; Flags: postinstall shellexec skipifsilent unchecked

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

[Setup]
; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{C5AE352B-3A5A-45E7-855C-623590FB715E}
AppName=Psyche
AppVersion=0.1
;AppVerName=Psyche 0.1
OutputBaseFilename=Psyche_0.1-win32.setup
AppPublisher=Qweex
AppPublisherURL=http://www.qweex.com/
AppSupportURL=http://www.qweex.com/
AppUpdatesURL=http://www.qweex.com/
DefaultDirName={pf}\Psyche
DefaultGroupName=Psyche
AllowNoIcons=yes
LicenseFile=C:\Steampunk\Dev\psyche\LICENSE
OutputDir=C:\Steampunk\Dev\psyche\bin
Compression=lzma
SolidCompression=yes

[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"

[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked

[Files]
Source: "C:\Steampunk\Dev\psyche\bin\main.exe"; DestDir: "{app}"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Name: "{group}\Psyche"; Filename: "{app}\main.exe"
Name: "{commondesktop}\Psyche"; Filename: "{app}\main.exe"; Tasks: desktopicon

[Run]
Filename: "{app}\main.exe"; Description: "{cm:LaunchProgram,Psyche}"; Flags: nowait postinstall skipifsilent
Filename: "{app}\README.md"; Description: "View the README file"; Flags: postinstall shellexec skipifsilent unchecked


install autoconf support files on Windows, too

git-svn-id: bd2c15cabedda08daa94fbf2043b3f8588072843@1163 34294538-1d18-489e-82e9-bb8ff975a0eb

; This script was first created by ISTool
; http://www.lerstad.com/istool/

#define VERSION          "0.2.3"

[Setup]
OutputBaseFilename=bakefile-{#VERSION}-setup
AppName=Bakefile
AppVerName=Bakefile {#VERSION}

ChangesAssociations=false
AlwaysShowComponentsList=true
SourceDir=.
DefaultDirName={pf}\Bakefile

DefaultGroupName=Bakefile
AllowNoIcons=true

OutputDir=.

Compression=lzma/ultra64

WindowShowCaption=true
WindowStartMaximized=false
FlatComponentsList=true
WindowResizable=false
ShowTasksTreeLines=false
DisableProgramGroupPage=true
LicenseFile=COPYING

SolidCompression=true
InternalCompressLevel=ultra64
ShowLanguageDialog=no
VersionInfoVersion={#VERSION}
PrivilegesRequired=none
AppSupportURL=http://www.bakefile.org
AppUpdatesURL=http://www.bakefile.org/download.html
AppVersion={#VERSION}
AppID={{AD092360-A98A-4CDC-BDAA-5CB09C593AC2}
AppContact=http://www.bakefile.org/wiki
UninstallDisplayName=Bakefile
ChangesEnvironment=true
UninstallFilesDir={app}\uninst
[Files]
Source: bakefile.exe; DestDir: {app}; Components: base
Source: bakefile_gen.exe; DestDir: {app}; Components: base
Source: src\*.py; DestDir: {app}\src; Components: base
Source: src\*.pyd; DestDir: {app}\src; Components: base
Source: src\empy\*; DestDir: {app}\src\empy; Flags: recursesubdirs; Components: base
Source: autoconf\*; DestDir: {app}\autoconf; Flags: recursesubdirs; Components: base
Source: rules\*; DestDir: {app}\rules; Flags: recursesubdirs; Components: base
Source: presets\*; DestDir: {app}\presets; Flags: recursesubdirs; Components: base
Source: output\*; DestDir: {app}\output; Flags: recursesubdirs; Components: base
Source: tests\*; DestDir: {app}\tests; Flags: recursesubdirs; Components: tests
Source: schema\*; DestDir: {app}\schema; Flags: recursesubdirs; Components: base
Source: doc\*; DestDir: {app}\doc; Flags: recursesubdirs; Components: doc
Source: py-runtime\*; DestDir: {app}; Flags: recursesubdirs; Components: python
Source: README; DestDir: {app}; Components: base
Source: NEWS; DestDir: {app}; Components: base; AfterInstall: InstallSetupPath
Source: THANKS; DestDir: {app}; Components: base
Source: COPYING; DestDir: {app}; Components: base
Source: AUTHORS; DestDir: {app}; Components: base

[Registry]

[Icons]

[Run]

[_ISTool]
EnableISX=true
UseAbsolutePaths=false

[Dirs]

[_ISToolPreCompile]

[Components]
Name: base; Description: Bakefile code; Flags: fixed; Types: custom compact full
Name: python; Description: Python runtime; Flags: fixed; Types: custom compact full
Name: doc; Description: Documentation; Types: custom full
Name: tests; Description: Tests and examples; Types: custom full

[Messages]
BeveledLabel=Bakefile

[UninstallDelete]
Name: {app}\src; Type: filesandordirs
Name: {app}\output; Type: filesandordirs
Name: {app}\lib; Type: filesandordirs

[Tasks]
Name: addpath; Description: Add Bakefile to PATH environment variable; Flags: checkedonce
[Code]
// -----------------------------------------------------------------
//                    code for changing PATH
// -----------------------------------------------------------------

//
// Inno Setup Extensions Knowledge Base
// Article 44 - Native ISX procedures for PATH modification
// http://www13.brinkster.com/vincenzog/isxart.asp?idart=44
// Author: Thomas Vedel
//

// Version log:
// 03/31/2003: Initial release (thv@lr.dk)

const
  // Modification method
  pmAddToBeginning = $1;      // Add dir to beginning of Path
  pmAddToEnd = $2;            // Add dir to end of Path
  pmAddAllways = $4;          // Add also if specified dir is already included in existing path
  pmAddOnlyIfDirExists = $8;  // Add only if specified dir actually exists
  pmRemove = $10;             // Remove dir from path
  pmRemoveSubdirsAlso = $20;  // Remove dir and all subdirs from path

  // Scope
  psCurrentUser = 1;          // Modify path for current user
  psAllUsers = 2;             // Modify path for all users

  // Error results
  mpOK = 0;                   // No errors
  mpMissingRights = -1;       // User has insufficient rights
  mpAutoexecNoWriteacc = -2;  // Autoexec can not be written (may be readonly)
  mpBothAddAndRemove = -3;    // User has specified that dir should both be removed from and added to path

{ Helper procedure: Split a path environment variable into individual dirnames }
procedure SplitPath(Path: string; var Dirs: TStringList);
var
  pos: integer;
  s: string;
begin
  Dirs.Clear;
  s := '';
  pos := 1;
  while (pos<=Length(Path)) do
  begin
    if (Path[pos]<>';') then
      s := s + Path[pos];
    if ((Path[pos]=';') or (pos=Length(Path))) then
    begin
      s := Trim(s);
      s := RemoveQuotes(s);
      s := Trim(s);
      if (s <> '') then
        Dirs.Add(s);
      s := '';
    end;
    Pos := Pos + 1;
  end;
end; // procedure SplitPath

{ Helper procedure: Concatenate individual dirnames into a path environment variable }
procedure ConcatPath(Dirs: TStringList; Quotes: boolean; var Path: string);
var
  Index, MaxIndex: integer;
  s: string;
begin
  MaxIndex := Dirs.Count-1;
  Path := '';
  for Index := 0 to MaxIndex do
  begin
    s := Dirs.Strings[Index];
    if ((Quotes) and (pos(' ',s) > 0)) then
      s := AddQuotes(s);
    Path := Path + s;
    if (Index < MaxIndex) then
      Path := Path + ';'
  end;
end; // procedure ConcatPath

{ Helper function: Modifies path environment string }
procedure ModifyPathString(OldPath, DirName: string; Method: integer; Quotes: boolean; var ResultPath: string);
var
  Dirs: TStringList;
  DirNotInPath: Boolean;
  i: integer;
begin
  // Create Dirs variable
  Dirs := TStringList.Create;

  // Remove quotes form DirName
  DirName := Trim(DirName);
  DirName := RemoveQuotes(DirName);
  DirName := Trim(DirName);

  // Split old path in individual directory names
  SplitPath(OldPath, Dirs);

  // Check if dir is allready in path
  DirNotInPath := True;
  for i:=Dirs.Count-1 downto 0 do
  begin
    if (uppercase(Dirs.Strings[i]) = uppercase(DirName)) then
      DirNotInPath := False;
  end;

  // Should dir be removed from existing Path?
  if ((Method and (pmRemove or pmRemoveSubdirsAlso)) > 0) then
  begin
    for i:=Dirs.Count-1 downto 0 do
    begin
      if (((Method and pmRemoveSubdirsAlso) > 0) and (pos(uppercase(DirName)+'\', uppercase(Dirs.Strings[i])) = 1)) or
         (((Method and (pmRemove) or (pmRemoveSubdirsAlso)) > 0) and (uppercase(DirName) = uppercase(Dirs.Strings[i])))
      then
        Dirs.Delete(i);
    end;
  end;

  // Should dir be added to existing Path?
  if ((Method and (pmAddToBeginning or pmAddToEnd)) > 0) then
  begin
    // Add dir to path
    if (((Method and pmAddAllways) > 0) or DirNotInPath) then
    begin
      // Dir is not in path allready or should be added anyway
      if (((Method and pmAddOnlyIfDirExists) = 0) or (DirExists(DirName))) then
      begin
        // Dir actually exsists or should be added anyway
        if ((Method and pmAddToBeginning) > 0) then
          Dirs.Insert(0, DirName)
        else
          Dirs.Append(DirName);
      end;
    end;
  end;

  // Concatenate directory names into one single path variable
  ConcatPath(Dirs, Quotes, ResultPath);
  // Finally free Dirs object
  Dirs.Free;
end; // ModifyPathString

{ Helper function: Modify path on Windows 9x }
function ModifyPath9x(DirName: string; Method: integer): integer;
var
  AutoexecLines: TStringList;
  ActualLine: String;
  PathLineNos: TStringList;
  FirstPathLineNo: Integer;
  OldPath, ResultPath: String;
  LineNo, CharNo, Index: integer;

  TempString: String;
begin
  // Expect everything to be OK
  result := mpOK;

  // Create stringslists
  AutoexecLines := TStringList.Create;
  PathLineNos := TStringList.Create;

  // Read existing path
  OldPath := '';
  LoadStringFromFile('c:\Autoexec.bat', TempString);
  AutoexecLines.Text := TempString;
  PathLineNos.Clear;
  // Read Autoexec line by line
  for LineNo := 0 to AutoexecLines.Count - 1 do begin
    ActualLine := AutoexecLines.Strings[LineNo];
    // Check if line starts with "PATH=" after first stripping spaces and other "fill-chars"
    if Pos('=', ActualLine) > 0 then
    begin
      for CharNo := Pos('=', ActualLine)-1 downto 1 do
        if (ActualLine[CharNo]=' ') or (ActualLine[CharNo]=#9) then
          Delete(ActualLine, CharNo, 1);
      if Pos('@', ActualLine) = 1 then
        Delete(ActualLine, 1, 1);
      if (Pos('PATH=', uppercase(ActualLine))=1) or (Pos('SETPATH=', uppercase(ActualLine))=1) then
      begin
        // Remove 'PATH=' and add path to "OldPath" variable
        Delete(ActualLine, 1, pos('=', ActualLine));
        // Check if an earlier PATH variable is referenced, but there has been no previous PATH defined in Autoexec
        if (pos('%PATH%',uppercase(ActualLine))>0) and (PathLineNos.Count=0) then
          OldPath := ExpandConstant('{win}') + ';' + ExpandConstant('{win}')+'\COMMAND';
        if (pos('%PATH%',uppercase(ActualLine))>0) then
        begin
          ActualLine := Copy(ActualLine, 1, pos('%PATH%',uppercase(ActualLine))-1) +
                        OldPath +
                        Copy(ActualLine, pos('%PATH%',uppercase(ActualLine))+6, Length(ActualLine));
        end;
        OldPath := ActualLine;

        // Update list of line numbers holding path variables
        PathLineNos.Add(IntToStr(LineNo));
      end;
    end;
  end;

  // Save first line number in Autoexec.bat which modifies path environment variable
  if PathLineNos.Count > 0 then
    FirstPathLineNo := StrToInt(PathLineNos.Strings[0])
  else
    FirstPathLineNo := 0;

  // Modify path
  ModifyPathString(OldPath, DirName, Method, True, ResultPath);

  // Write Modified path back to Autoexec.bat
  // First delete all existing path references from Autoexec.bat
  Index := PathLineNos.Count-1;
  while (Index>=0) do
  begin
    AutoexecLines.Delete(StrToInt(PathLineNos.Strings[Index]));
    Index := Index-1;
  end;
  // Then insert new path variable into Autoexec.bat
  AutoexecLines.Insert(FirstPathLineNo, '@PATH='+ResultPath);
  // Delete old Autoexec.bat from disk
  if not DeleteFile('c:\Autoexec.bat') then
    result := mpAutoexecNoWriteAcc;
  Sleep(500);
  // And finally write Autoexec.bat back to disk
  if not (result=mpAutoexecNoWriteAcc) then
    SaveStringToFile('c:\Autoexec.bat', AutoexecLines.Text, false);

  // Free stringlists
  PathLineNos.Free;
  AutoexecLines.Free;
end; // ModifyPath9x

{ Helper function: Modify path on Windows NT, 2000 and XP }
function ModifyPathNT(DirName: string; Method, Scope: integer): integer;
var
  RegRootKey: integer;
  RegSubKeyName: string;
  RegValueName: string;
  OldPath, ResultPath: string;
  OK: boolean;
begin
  // Expect everything to be OK
  result := mpOK;

  // Initialize registry key and value names to reflect if changes should be global or local to current user only
  case Scope of
    psCurrentUser:
      begin
        RegRootKey := HKEY_CURRENT_USER;
        RegSubKeyName := 'Environment';
        RegValueName := 'Path';
      end;
    psAllUsers:
      begin
        RegRootKey := HKEY_LOCAL_MACHINE;
        RegSubKeyName := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
        RegValueName := 'Path';
      end;
  end;

  // Read current path value from registry
  OK := RegQueryStringValue(RegRootKey, RegSubKeyName, RegValueName, OldPath);
  if not OK then
  begin
    result := mpMissingRights;
    Exit;
  end;

  // Modify path
  ModifyPathString(OldPath, DirName, Method, False, ResultPath);

  // Write new path value to registry
  if not RegWriteStringValue(RegRootKey, RegSubKeyName, RegValueName, ResultPath) then
  begin
    result := mpMissingRights;
    Exit;

  end;
end; // ModifyPathNT

{ Main function: Modify path }
function ModifyPath(Path: string; Method, Scope: integer): integer;
begin
  // Check if both add and remove has been specified (= error!)
  if (Method and (pmAddToBeginning or pmAddToEnd) and (pmRemove or pmRemoveSubdirsAlso)) > 0 then
  begin
    result := mpBothAddAndRemove;
    Exit;
  end;

  // Perform directory constant expansion
  Path := ExpandConstantEx(Path, ' ', ' ');

  // Test if Win9x
  if InstallOnThisVersion('4,0','0,0') = irInstall then
    ModifyPath9x(Path, Method);

  // Test if WinNT, 2000 or XP
  if InstallOnThisVersion('0,4','0,0') = irInstall then
    ModifyPathNT(Path, Method, Scope);
end; // ModifyPath

// -----------------------------------------------------------------
//                     install script hooks
// -----------------------------------------------------------------

procedure SetupPATH;
var
  p : string;
  scope : integer;
begin
  p:= ExpandConstant('{app}');
  if IsAdminLoggedOn then
    scope:= psAllUsers
  else
    scope:= psCurrentUser;
  ModifyPath(p, pmAddToEnd, scope);
end;

procedure InstallSetupPath;
begin
    if IsTaskSelected('addpath') then
		SetupPATH;
end;

; This script was first created by ISTool
; http://www.lerstad.com/istool/

#define VERSION          "0.2.3"

[Setup]
OutputBaseFilename=bakefile-{#VERSION}-setup
AppName=Bakefile
AppVerName=Bakefile {#VERSION}

ChangesAssociations=false
AlwaysShowComponentsList=true
SourceDir=.
DefaultDirName={pf}\Bakefile

DefaultGroupName=Bakefile
AllowNoIcons=true

OutputDir=.

Compression=lzma/ultra64

WindowShowCaption=true
WindowStartMaximized=false
FlatComponentsList=true
WindowResizable=false
ShowTasksTreeLines=false
DisableProgramGroupPage=true
LicenseFile=COPYING

SolidCompression=true
InternalCompressLevel=ultra64
ShowLanguageDialog=no
VersionInfoVersion={#VERSION}
PrivilegesRequired=none
AppSupportURL=http://www.bakefile.org
AppUpdatesURL=http://www.bakefile.org/download.html
AppVersion={#VERSION}
AppID={{AD092360-A98A-4CDC-BDAA-5CB09C593AC2}
AppContact=http://www.bakefile.org/wiki
UninstallDisplayName=Bakefile
ChangesEnvironment=true
UninstallFilesDir={app}\uninst
[Files]
Source: bakefile.exe; DestDir: {app}; Components: base
Source: bakefile_gen.exe; DestDir: {app}; Components: base
Source: src\*.py; DestDir: {app}\src; Components: base
Source: src\*.pyd; DestDir: {app}\src; Components: base
Source: src\empy\*; DestDir: {app}\src\empy; Flags: recursesubdirs; Components: base
Source: rules\*; DestDir: {app}\rules; Flags: recursesubdirs; Components: base
Source: presets\*; DestDir: {app}\presets; Flags: recursesubdirs; Components: base
Source: output\*; DestDir: {app}\output; Flags: recursesubdirs; Components: base
Source: tests\*; DestDir: {app}\tests; Flags: recursesubdirs; Components: tests
Source: schema\*; DestDir: {app}\schema; Flags: recursesubdirs; Components: base
Source: doc\*; DestDir: {app}\doc; Flags: recursesubdirs; Components: doc
Source: py-runtime\*; DestDir: {app}; Flags: recursesubdirs; Components: python
Source: README; DestDir: {app}; Components: base
Source: NEWS; DestDir: {app}; Components: base; AfterInstall: InstallSetupPath
Source: THANKS; DestDir: {app}; Components: base
Source: COPYING; DestDir: {app}; Components: base
Source: AUTHORS; DestDir: {app}; Components: base

[Registry]

[Icons]

[Run]

[_ISTool]
EnableISX=true
UseAbsolutePaths=false

[Dirs]

[_ISToolPreCompile]

[Components]
Name: base; Description: Bakefile code; Flags: fixed; Types: custom compact full
Name: python; Description: Python runtime; Flags: fixed; Types: custom compact full
Name: doc; Description: Documentation; Types: custom full
Name: tests; Description: Tests and examples; Types: custom full

[Messages]
BeveledLabel=Bakefile

[UninstallDelete]
Name: {app}\src; Type: filesandordirs
Name: {app}\output; Type: filesandordirs
Name: {app}\lib; Type: filesandordirs

[Tasks]
Name: addpath; Description: Add Bakefile to PATH environment variable; Flags: checkedonce
[Code]
// -----------------------------------------------------------------
//                    code for changing PATH
// -----------------------------------------------------------------

//
// Inno Setup Extensions Knowledge Base
// Article 44 - Native ISX procedures for PATH modification
// http://www13.brinkster.com/vincenzog/isxart.asp?idart=44
// Author: Thomas Vedel
//

// Version log:
// 03/31/2003: Initial release (thv@lr.dk)

const
  // Modification method
  pmAddToBeginning = $1;      // Add dir to beginning of Path
  pmAddToEnd = $2;            // Add dir to end of Path
  pmAddAllways = $4;          // Add also if specified dir is already included in existing path
  pmAddOnlyIfDirExists = $8;  // Add only if specified dir actually exists
  pmRemove = $10;             // Remove dir from path
  pmRemoveSubdirsAlso = $20;  // Remove dir and all subdirs from path

  // Scope
  psCurrentUser = 1;          // Modify path for current user
  psAllUsers = 2;             // Modify path for all users

  // Error results
  mpOK = 0;                   // No errors
  mpMissingRights = -1;       // User has insufficient rights
  mpAutoexecNoWriteacc = -2;  // Autoexec can not be written (may be readonly)
  mpBothAddAndRemove = -3;    // User has specified that dir should both be removed from and added to path

{ Helper procedure: Split a path environment variable into individual dirnames }
procedure SplitPath(Path: string; var Dirs: TStringList);
var
  pos: integer;
  s: string;
begin
  Dirs.Clear;
  s := '';
  pos := 1;
  while (pos<=Length(Path)) do
  begin
    if (Path[pos]<>';') then
      s := s + Path[pos];
    if ((Path[pos]=';') or (pos=Length(Path))) then
    begin
      s := Trim(s);
      s := RemoveQuotes(s);
      s := Trim(s);
      if (s <> '') then
        Dirs.Add(s);
      s := '';
    end;
    Pos := Pos + 1;
  end;
end; // procedure SplitPath

{ Helper procedure: Concatenate individual dirnames into a path environment variable }
procedure ConcatPath(Dirs: TStringList; Quotes: boolean; var Path: string);
var
  Index, MaxIndex: integer;
  s: string;
begin
  MaxIndex := Dirs.Count-1;
  Path := '';
  for Index := 0 to MaxIndex do
  begin
    s := Dirs.Strings[Index];
    if ((Quotes) and (pos(' ',s) > 0)) then
      s := AddQuotes(s);
    Path := Path + s;
    if (Index < MaxIndex) then
      Path := Path + ';'
  end;
end; // procedure ConcatPath

{ Helper function: Modifies path environment string }
procedure ModifyPathString(OldPath, DirName: string; Method: integer; Quotes: boolean; var ResultPath: string);
var
  Dirs: TStringList;
  DirNotInPath: Boolean;
  i: integer;
begin
  // Create Dirs variable
  Dirs := TStringList.Create;

  // Remove quotes form DirName
  DirName := Trim(DirName);
  DirName := RemoveQuotes(DirName);
  DirName := Trim(DirName);

  // Split old path in individual directory names
  SplitPath(OldPath, Dirs);

  // Check if dir is allready in path
  DirNotInPath := True;
  for i:=Dirs.Count-1 downto 0 do
  begin
    if (uppercase(Dirs.Strings[i]) = uppercase(DirName)) then
      DirNotInPath := False;
  end;

  // Should dir be removed from existing Path?
  if ((Method and (pmRemove or pmRemoveSubdirsAlso)) > 0) then
  begin
    for i:=Dirs.Count-1 downto 0 do
    begin
      if (((Method and pmRemoveSubdirsAlso) > 0) and (pos(uppercase(DirName)+'\', uppercase(Dirs.Strings[i])) = 1)) or
         (((Method and (pmRemove) or (pmRemoveSubdirsAlso)) > 0) and (uppercase(DirName) = uppercase(Dirs.Strings[i])))
      then
        Dirs.Delete(i);
    end;
  end;

  // Should dir be added to existing Path?
  if ((Method and (pmAddToBeginning or pmAddToEnd)) > 0) then
  begin
    // Add dir to path
    if (((Method and pmAddAllways) > 0) or DirNotInPath) then
    begin
      // Dir is not in path allready or should be added anyway
      if (((Method and pmAddOnlyIfDirExists) = 0) or (DirExists(DirName))) then
      begin
        // Dir actually exsists or should be added anyway
        if ((Method and pmAddToBeginning) > 0) then
          Dirs.Insert(0, DirName)
        else
          Dirs.Append(DirName);
      end;
    end;
  end;

  // Concatenate directory names into one single path variable
  ConcatPath(Dirs, Quotes, ResultPath);
  // Finally free Dirs object
  Dirs.Free;
end; // ModifyPathString

{ Helper function: Modify path on Windows 9x }
function ModifyPath9x(DirName: string; Method: integer): integer;
var
  AutoexecLines: TStringList;
  ActualLine: String;
  PathLineNos: TStringList;
  FirstPathLineNo: Integer;
  OldPath, ResultPath: String;
  LineNo, CharNo, Index: integer;

  TempString: String;
begin
  // Expect everything to be OK
  result := mpOK;

  // Create stringslists
  AutoexecLines := TStringList.Create;
  PathLineNos := TStringList.Create;

  // Read existing path
  OldPath := '';
  LoadStringFromFile('c:\Autoexec.bat', TempString);
  AutoexecLines.Text := TempString;
  PathLineNos.Clear;
  // Read Autoexec line by line
  for LineNo := 0 to AutoexecLines.Count - 1 do begin
    ActualLine := AutoexecLines.Strings[LineNo];
    // Check if line starts with "PATH=" after first stripping spaces and other "fill-chars"
    if Pos('=', ActualLine) > 0 then
    begin
      for CharNo := Pos('=', ActualLine)-1 downto 1 do
        if (ActualLine[CharNo]=' ') or (ActualLine[CharNo]=#9) then
          Delete(ActualLine, CharNo, 1);
      if Pos('@', ActualLine) = 1 then
        Delete(ActualLine, 1, 1);
      if (Pos('PATH=', uppercase(ActualLine))=1) or (Pos('SETPATH=', uppercase(ActualLine))=1) then
      begin
        // Remove 'PATH=' and add path to "OldPath" variable
        Delete(ActualLine, 1, pos('=', ActualLine));
        // Check if an earlier PATH variable is referenced, but there has been no previous PATH defined in Autoexec
        if (pos('%PATH%',uppercase(ActualLine))>0) and (PathLineNos.Count=0) then
          OldPath := ExpandConstant('{win}') + ';' + ExpandConstant('{win}')+'\COMMAND';
        if (pos('%PATH%',uppercase(ActualLine))>0) then
        begin
          ActualLine := Copy(ActualLine, 1, pos('%PATH%',uppercase(ActualLine))-1) +
                        OldPath +
                        Copy(ActualLine, pos('%PATH%',uppercase(ActualLine))+6, Length(ActualLine));
        end;
        OldPath := ActualLine;

        // Update list of line numbers holding path variables
        PathLineNos.Add(IntToStr(LineNo));
      end;
    end;
  end;

  // Save first line number in Autoexec.bat which modifies path environment variable
  if PathLineNos.Count > 0 then
    FirstPathLineNo := StrToInt(PathLineNos.Strings[0])
  else
    FirstPathLineNo := 0;

  // Modify path
  ModifyPathString(OldPath, DirName, Method, True, ResultPath);

  // Write Modified path back to Autoexec.bat
  // First delete all existing path references from Autoexec.bat
  Index := PathLineNos.Count-1;
  while (Index>=0) do
  begin
    AutoexecLines.Delete(StrToInt(PathLineNos.Strings[Index]));
    Index := Index-1;
  end;
  // Then insert new path variable into Autoexec.bat
  AutoexecLines.Insert(FirstPathLineNo, '@PATH='+ResultPath);
  // Delete old Autoexec.bat from disk
  if not DeleteFile('c:\Autoexec.bat') then
    result := mpAutoexecNoWriteAcc;
  Sleep(500);
  // And finally write Autoexec.bat back to disk
  if not (result=mpAutoexecNoWriteAcc) then
    SaveStringToFile('c:\Autoexec.bat', AutoexecLines.Text, false);

  // Free stringlists
  PathLineNos.Free;
  AutoexecLines.Free;
end; // ModifyPath9x

{ Helper function: Modify path on Windows NT, 2000 and XP }
function ModifyPathNT(DirName: string; Method, Scope: integer): integer;
var
  RegRootKey: integer;
  RegSubKeyName: string;
  RegValueName: string;
  OldPath, ResultPath: string;
  OK: boolean;
begin
  // Expect everything to be OK
  result := mpOK;

  // Initialize registry key and value names to reflect if changes should be global or local to current user only
  case Scope of
    psCurrentUser:
      begin
        RegRootKey := HKEY_CURRENT_USER;
        RegSubKeyName := 'Environment';
        RegValueName := 'Path';
      end;
    psAllUsers:
      begin
        RegRootKey := HKEY_LOCAL_MACHINE;
        RegSubKeyName := 'SYSTEM\CurrentControlSet\Control\Session Manager\Environment';
        RegValueName := 'Path';
      end;
  end;

  // Read current path value from registry
  OK := RegQueryStringValue(RegRootKey, RegSubKeyName, RegValueName, OldPath);
  if not OK then
  begin
    result := mpMissingRights;
    Exit;
  end;

  // Modify path
  ModifyPathString(OldPath, DirName, Method, False, ResultPath);

  // Write new path value to registry
  if not RegWriteStringValue(RegRootKey, RegSubKeyName, RegValueName, ResultPath) then
  begin
    result := mpMissingRights;
    Exit;

  end;
end; // ModifyPathNT

{ Main function: Modify path }
function ModifyPath(Path: string; Method, Scope: integer): integer;
begin
  // Check if both add and remove has been specified (= error!)
  if (Method and (pmAddToBeginning or pmAddToEnd) and (pmRemove or pmRemoveSubdirsAlso)) > 0 then
  begin
    result := mpBothAddAndRemove;
    Exit;
  end;

  // Perform directory constant expansion
  Path := ExpandConstantEx(Path, ' ', ' ');

  // Test if Win9x
  if InstallOnThisVersion('4,0','0,0') = irInstall then
    ModifyPath9x(Path, Method);

  // Test if WinNT, 2000 or XP
  if InstallOnThisVersion('0,4','0,0') = irInstall then
    ModifyPathNT(Path, Method, Scope);
end; // ModifyPath

// -----------------------------------------------------------------
//                     install script hooks
// -----------------------------------------------------------------

procedure SetupPATH;
var
  p : string;
  scope : integer;
begin
  p:= ExpandConstant('{app}');
  if IsAdminLoggedOn then
    scope:= psAllUsers
  else
    scope:= psCurrentUser;
  ModifyPath(p, pmAddToEnd, scope);
end;

procedure InstallSetupPath;
begin
    if IsTaskSelected('addpath') then
		SetupPATH;
end;