[gimp/gimp-2-8] Windows installer - initial import



commit 70ca141159613d40d251a65f3ff7b591eba9e027
Author: Jernej SimonÄiÄ <jernej|s-cccp eternallybored org>
Date:   Mon May 14 00:01:17 2012 +0200

    Windows installer - initial import

 build/windows/installer/32on64.isi                 |   60 +
 build/windows/installer/32on64.list                |   48 +
 build/windows/installer/MessageWithURL.isi         |  505 +++++++
 build/windows/installer/associations.isi           |  318 +++++
 build/windows/installer/directories.isi            |   36 +
 build/windows/installer/en.setup.isl               |  108 ++
 build/windows/installer/files.isi                  |   27 +
 build/windows/installer/gimp3264.iss               | 1382 ++++++++++++++++++++
 build/windows/installer/gpl+python.rtf             |  123 ++
 build/windows/installer/installsplash.bmp          |  Bin 0 -> 770874 bytes
 build/windows/installer/installsplash_small.bmp    |  Bin 0 -> 537174 bytes
 build/windows/installer/rebootcontinue.isi         |  128 ++
 build/windows/installer/setup.ini                  |   29 +
 build/windows/installer/sl.setup.isl               |  100 ++
 build/windows/installer/uninst.isi                 |  269 ++++
 build/windows/installer/utils.isi                  |  139 ++
 build/windows/installer/version.isi                |   28 +
 build/windows/installer/wilber.bmp                 |  Bin 0 -> 4158 bytes
 .../installer/windows-installer-intro-big.bmp      |  Bin 0 -> 221814 bytes
 .../installer/windows-installer-intro-small.bmp    |  Bin 0 -> 154542 bytes
 20 files changed, 3300 insertions(+), 0 deletions(-)
---
diff --git a/build/windows/installer/32on64.isi b/build/windows/installer/32on64.isi
new file mode 100755
index 0000000..c65e7f9
--- /dev/null
+++ b/build/windows/installer/32on64.isi
@@ -0,0 +1,60 @@
+#if 0
+[Files]
+#endif
+//process list of 32bit GIMP files that are installed on x64 (for TWAIN and Python support)
+#pragma option -e-
+
+#define protected
+
+#define FileHandle
+#define FileLine
+
+#define ReplPos
+#define ReplStr
+
+#define Line=0
+#define SRC_DIR GIMP_DIR32
+
+//avoid too much nesting
+#sub DoActualWork
+	#if Copy(FileLine,Len(FileLine),1)=="\"
+		//include whole directory
+Source: "{#SRC_DIR}\{#FileLine}*"; DestDir: "{app}\32\{#Copy(FileLine,1,Len(FileLine)-1)}"; Components: gimp32on64; Flags: recursesubdirs restartreplace comparetimestamp
+	#else
+		//include files from a certain directory
+		#define OutputDir Copy(FileLine,1,RPos("\",FileLine)-1)
+Source: "{#SRC_DIR}\{#FileLine}"; DestDir: "{app}\32\{#OutputDir}"; Components: gimp32on64; Flags: restartreplace comparetimestamp
+	#endif
+#endsub
+
+#sub Process32on64Line
+	#if !defined(Finished)
+		//show that something's happening
+		#expr Line=Line+1
+		#pragma message "Processing 32on64.list line " + Str(Line)
+
+		#if Copy(FileLine,1,1)=="#" || FileLine==""
+			//skip comments and empty lines
+		#elif Copy(FileLine,1,1)=="!"
+			#if Copy(FileLine,2)=="GIMP"
+				#expr SRC_DIR=GIMP_DIR32
+			#elif Copy(FileLine,2)=="GTK"
+				#expr SRC_DIR=DEPS_DIR32
+			#elif Copy(FileLine,2)=="end"
+				#define public Finished 1
+				//finished
+			#else
+				#error "Unknown command: "+FileLine
+			#endif
+		#else
+			#expr DoActualWork
+		#endif
+	#endif
+#endsub
+
+#for {FileHandle = FileOpen(AddBackslash(SourcePath)+"32on64.list"); \
+  FileHandle && !FileEof(FileHandle); FileLine = FileRead(FileHandle)} \
+  Process32on64Line
+#if FileHandle
+  #expr FileClose(FileHandle)
+#endif
diff --git a/build/windows/installer/32on64.list b/build/windows/installer/32on64.list
new file mode 100755
index 0000000..a2f8390
--- /dev/null
+++ b/build/windows/installer/32on64.list
@@ -0,0 +1,48 @@
+#list of 32bit files to install on x64
+!GTK
+etc\fonts\
+lib\gtk-2.0\2.10.0\engines\libpixmap.dll
+lib\gtk-2.0\2.10.0\engines\libwimp.dll
+lib\gtk-2.0\modules\libgail.dll
+share\themes\
+bin\gspawn-win32-helper-console.exe
+bin\gspawn-win32-helper.exe
+bin\libatk-*.dll
+bin\libcairo-*.dll
+bin\libffi-*.dll
+bin\libfontconfig-*.dll
+bin\libfreetype-*.dll
+bin\libgailutil-*.dll
+bin\libgdk-win32-*.dll
+bin\libgdk_pixbuf-*.dll
+bin\libgio-*.dll
+bin\libglib-*.dll
+bin\libgmodule-*.dll
+bin\libgobject-*.dll
+bin\libgthread-*.dll
+bin\libgtk-win32-*.dll
+bin\libintl-*.dll
+bin\libjasper-*.dll
+bin\libjpeg-*.dll
+bin\liblzma-*.dll
+bin\libpango-*.dll
+bin\libpangocairo-*.dll
+bin\libpangoft2-*.dll
+bin\libpangowin32-*.dll
+bin\libpixman-*.dll
+bin\libpng*.dll
+bin\libxml2-*.dll
+bin\libtiff-*.dll
+bin\zlib1.dll
+bin\libgcc_s_sjlj-1.dll
+!GIMP
+bin\libgimp-*.dll
+bin\libgimpbase-*.dll
+bin\libgimpcolor-*.dll
+bin\libgimpconfig-*.dll
+bin\libgimpmath-*.dll
+bin\libgimpmodule-*.dll
+bin\libgimpthumb-*.dll
+bin\libgimpui-*.dll
+bin\libgimpwidgets-*.dll
+!end
diff --git a/build/windows/installer/MessageWithURL.isi b/build/windows/installer/MessageWithURL.isi
new file mode 100755
index 0000000..15d9f25
--- /dev/null
+++ b/build/windows/installer/MessageWithURL.isi
@@ -0,0 +1,505 @@
+[Code]
+(* MessageWithURL
+ *
+ * Copyright (c) 2010-2011 Jernej SimonŸiŸ
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ *    1. The origin of this software must not be misrepresented; you must
+ *       not claim that you wrote the original software. If you use this
+ *       software in a product, an acknowledgment in the product
+ *       documentation would be appreciated but is not required.
+ *
+ *    2. Altered source versions must be plainly marked as such, and must
+ *       not be misrepresented as being the original software.
+ *
+ *    3. This notice may not be removed or altered from any source
+ *       distribution.
+ *)
+
+(* * * * * * * * * *
+ * MessageWithURL(Message: TArrayOfString; Title: String: ButtonText: TArrayOfString; Typ: TMsgBoxType;
+ *                DefaultButton, CancelButton: Integer): Integer;
+ *
+ * Parameters:
+ *   Title          dialog box caption
+ *   Message        messages to display; if a message starts with _, the text following it up to the first space character
+ *                  is interpreted as URL, and the rest of the message is used as clickable text for that URL
+ *   Typ            icon to show
+ *   ButtonText     buttons to show under the text
+ *   DefaultButton  default button (first button = 1)
+ *   CancelButton   cancel button (first button = 1)
+ *
+ * Return value     button that was clicked (first button = 1); if running in silent mode, DefaultButton is returned
+ *)
+function MessageWithURL(Message: TArrayOfString; const Title: String; ButtonText: TArrayOfString; const Typ: TMsgBoxType;
+                        const DefaultButton, CancelButton: Integer): Integer; forward;
+
+function GetSystemMetrics(nIndex: Integer): Integer; external 'GetSystemMetrics User32 stdcall';
+function GetDialogBaseUnits(): Integer; external 'GetDialogBaseUnits User32 stdcall';
+
+//function GetSysColor(nIndex: Integer): DWORD; external 'GetSysColor user32 dll stdcall';
+
+function LoadIcon(hInstance: Integer; lpIconName: Integer): Integer; external 'LoadIconW user32 stdcall';
+//function LoadImage(hinst: Integer; lpszName: Integer; uType: Cardinal; cxDesired, cyDesired: Integer; fuLoad: Cardinal): Integer; external 'LoadImageW user32 stdcall';
+function DrawIcon(hdc: HBitmap; x,y: Integer; hIcon: Integer): Integer; external 'DrawIcon user32 stdcall';
+//function DrawIconEx(hdc: HBitmap; xLeft,yTop: Integer; hIcon: Integer; cxWidth, cyWidth: Integer; istepIfAniCur: Cardinal; hbrFlickerFreeDraw: Integer; diFlags: Cardinal): Integer; external 'DrawIconEx user32 stdcall';
+//function DestroyIcon(hIcon: Integer): Integer; external 'DestroyIcon user32 stdcall';
+
+function DrawFocusRect(hDC: Integer; var lprc: TRect): BOOL; external 'DrawFocusRect user32 stdcall';
+
+type
+	TArrayOfButton = Array of TButton;
+
+const
+	//borders around message
+	MWU_LEFTBORDER = 25;
+	MWU_RIGHTBORDER = MWU_LEFTBORDER;
+	MWU_TOPBORDER = 26;
+	MWU_BOTTOMBORDER = MWU_TOPBORDER;
+    //space between elements (icon-text and between buttons)
+	MWU_HORZSPACING = 8;
+    //space between labels
+	MWU_VERTSPACING = 4;
+    //button sizes
+	MWU_BUTTONHEIGHT = 24;
+	MWU_MINBUTTONWIDTH = 86;
+    //height of area where buttons are placed
+	MWU_BUTTONAREAHEIGHT = 45;
+
+	SM_CXSCREEN = 0;
+	SM_CXICON = 11;
+	SM_CYICON = 12;
+	SM_CXICONSPACING = 38;
+	SM_CYICONSPACING = 39;
+
+	//COLOR_HOTLIGHT = 26;
+
+	OIC_HAND = 32513;
+	OIC_QUES = 32514;
+	OIC_BANG = 32515;
+	OIC_NOTE = 32516;
+
+	LR_DEFAULTSIZE = $00000040;
+	LR_SHARED = $00008000;
+
+	IMAGE_BITMAP = 0;
+	IMAGE_ICON = 1;
+	IMAGE_CURSOR = 2;
+
+	DI_IMAGE = 1;
+	DI_MASK = 2;
+	DI_NORMAL = DI_IMAGE or DI_MASK;
+	DI_DEFAULTSIZE = 8;
+
+var
+	URLList: TArrayOfString;
+	TextLabel: Array of TNewStaticText;
+	URLFocusImg: Array of TBitmapImage;
+	SingleLineHeight: Integer;
+
+
+procedure UrlClick(Sender: TObject);
+var ErrorCode: Integer;
+begin
+	ShellExecAsOriginalUser('open',URLList[TNewStaticText(Sender).Tag],'','',SW_SHOWNORMAL,ewNoWait,ErrorCode);
+end;
+
+
+// calculates maximum width of text labels
+// also counts URLs, and sets the length of URLList accordingly
+function Message_CalcLabelWidth(var Message: TArrayOfString; MessageForm: TSetupForm): Integer;
+var	MeasureLabel: TNewStaticText;
+	i,URLCount,DlgUnit,ScreenWidth: Integer;
+begin
+	MeasureLabel := TNewStaticText.Create(MessageForm);
+	with MeasureLabel do
+	begin
+		Parent := MessageForm;
+		Left := 0;
+		Top := 0;
+		AutoSize := True;
+	end;
+
+	MeasureLabel.Caption := 'X';
+	SingleLineHeight := MeasureLabel.Height;
+
+	Result := 0; //minimum width
+	URLCount := 0;
+	for i := 0 to GetArrayLength(Message) - 1 do
+	begin
+		if Length(Message[i]) < 1 then //simplifies things
+			Message[i] := ' ';
+
+		if Message[i][1] <> '_' then
+			MeasureLabel.Caption := Message[i] //not an URL
+		else
+		begin //URL - check only the displayed text
+			if Pos(' ',Message[i]) > 0 then
+				MeasureLabel.Caption := Copy(Message[i],Pos(' ',Message[i])+1,Length(Message[i]))
+			else
+				MeasureLabel.Caption := Copy(Message[i],2,Length(Message[i]));
+
+			URLCount := URLCount + 1;
+		end;
+
+		if MeasureLabel.Width > Result then
+			Result := MeasureLabel.Width;
+	end;
+	MeasureLabel.Free;
+
+	SetArrayLength(URLList,URLCount); //needed later - no need to do a special loop just for this
+	SetArrayLength(URLFocusImg,URLCount);
+
+	DlgUnit := GetDialogBaseUnits() and $FFFF;  //ensure the dialog isn't too wide
+	ScreenWidth := GetSystemMetrics(SM_CXSCREEN);
+	if Result > ((278 * DlgUnit) div 4) then //278 is from http://blogs.msdn.com/b/oldnewthing/archive/2011/06/24/10178386.aspx
+		Result := ((278 * DlgUnit) div 4);
+	if Result > (ScreenWidth * 3) div 4 then
+		Result := (ScreenWidth * 3) div 4;
+
+end;
+
+
+//find the longest button
+function Message_CalcButtonWidth(const ButtonText: TArrayOfString; MessageForm: TSetupForm): Integer;
+var	MeasureLabel: TNewStaticText;
+	i: Integer;
+begin
+	MeasureLabel := TNewStaticText.Create(MessageForm);
+	with MeasureLabel do
+	begin
+		Parent := MessageForm;
+		Left := 0;
+		Top := 0;
+		AutoSize := True;
+	end;
+
+	Result := ScaleX(MWU_MINBUTTONWIDTH - MWU_HORZSPACING * 2); //minimum width
+	for i := 0 to GetArrayLength(ButtonText) - 1 do
+	begin
+		MeasureLabel.Caption := ButtonText[i]
+
+		if MeasureLabel.Width > Result then
+			Result := MeasureLabel.Width;
+	end;
+	MeasureLabel.Free;
+
+	Result := Result + ScaleX(MWU_HORZSPACING * 2); //account for borders
+end;
+
+
+procedure Message_Icon(const Typ: TMsgBoxType; TypImg: TBitmapImage);
+var	TypRect: TRect;
+	Icon: THandle;
+	TypIcon: Integer;
+begin
+	TypRect.Left := 0;
+	TypRect.Top := 0;
+	TypRect.Right := GetSystemMetrics(SM_CXICON);
+	TypRect.Bottom := GetSystemMetrics(SM_CYICON);
+
+	case Typ of
+	mbInformation:
+		TypIcon := OIC_NOTE;
+	mbConfirmation:
+		TypIcon := OIC_QUES;
+	mbError:
+		TypIcon := OIC_BANG;
+	else
+		TypIcon := OIC_HAND;
+	end;
+
+	//TODO: icon loads with wrong size when using Large Fonts (SM_CXICON/CYICON is 40, but 32x32 icon loads - find out how to get the right size)
+	Icon := LoadIcon(0,TypIcon);
+	//Icon := LoadImage(0,TypIcon,IMAGE_ICON,0,0,LR_SHARED or LR_DEFAULTSIZE);
+	with TypImg do
+	begin
+		Left := ScaleX(MWU_LEFTBORDER);
+		Top := ScaleY(MWU_TOPBORDER);
+		Center := False;
+		Stretch := False;
+		AutoSize := True;
+		Bitmap.Width := GetSystemMetrics(SM_CXICON);
+		Bitmap.Height := GetSystemMetrics(SM_CYICON);
+		Bitmap.Canvas.Brush.Color := TPanel(Parent).Color;
+		Bitmap.Canvas.FillRect(TypRect);
+		DrawIcon(Bitmap.Canvas.Handle,0,0,Icon); //draws icon scaled
+		//DrawIconEx(Bitmap.Canvas.Handle,0,0,Icon,0,0,0,0,DI_NORMAL {or DI_DEFAULTSIZE}); //draws icon without scaling
+	end;
+	//DestroyIcon(Icon); //not needed with LR_SHARED or with LoadIcon
+end;
+
+
+procedure Message_SetUpURLLabel(URLLabel: TNewStaticText; const Msg: String; const URLNum: Integer);
+var Blank: TRect;
+begin
+	with URLLabel do
+	begin
+		if Pos(' ',Msg) > 0 then
+		begin
+			Caption := Copy(Msg,Pos(' ',Msg)+1,Length(Msg));
+			URLList[URLNum] := Copy(Msg, 2, Pos(' ',Msg)-1);
+		end
+		else
+		begin //no text after URL - display just URL
+			URLList[URLNum] := Copy(Msg, 2, Length(Msg));
+			Caption := URLList[URLNum];
+		end;
+
+		Hint := URLList[URLNum];
+		ShowHint := True;
+
+		Font.Color := GetSysColor(COLOR_HOTLIGHT);
+		Font.Style := [fsUnderline];
+		Cursor := crHand;
+		OnClick := @UrlClick;
+
+		Tag := URLNum; //used to find the URL to open and bitmap to draw focus rectangle on
+
+		if Height = SingleLineHeight then //shrink label to actual text width
+			WordWrap := False;
+
+		TabStop := True; //keyboard accessibility
+		TabOrder := URLNum;
+	end;
+
+  	URLFocusImg[URLNum] := TBitmapImage.Create(URLLabel.Parent); //focus rectangle needs a bitmap - prepare it here
+	with URLFocusImg[URLNum] do
+	begin
+		Left := URLLabel.Left - 1;
+		Top := URLLabel.Top - 1;
+		Stretch := False;
+		AutoSize := True;
+		Parent := URLLabel.Parent;
+		Bitmap.Width := URLLabel.Width + 2;
+		Bitmap.Height := URLLabel.Height + 2;
+
+		SendToBack;
+
+		Blank.Left := 0;
+		Blank.Top := 0;
+		Blank.Right := Width;
+		Blank.Bottom := Height;
+		Bitmap.Canvas.Brush.Color := TPanel(Parent).Color;
+		Bitmap.Canvas.FillRect(Blank);		
+	end;
+end;
+
+
+procedure Message_SetUpLabels(Message: TArrayOfString; TypImg: TBitmapImage;
+                              const DialogTextWidth: Integer; MessagePanel: TPanel);
+var	i,URLNum,dy: Integer;
+begin
+	SetArrayLength(TextLabel,GetArrayLength(Message));
+	URLNum := 0;
+	for i := 0 to GetArrayLength(TextLabel) - 1 do
+	begin
+		TextLabel[i] := TNewStaticText.Create(MessagePanel);
+		with TextLabel[i] do
+		begin
+			Parent := MessagePanel;
+			Left := TypImg.Left + TypImg.Width + ScaleX(MWU_HORZSPACING);
+			if i = 0 then
+				Top := TypImg.Top
+			else
+				Top := TextLabel[i-1].Top + TextLabel[i-1].Height + ScaleY(MWU_VERTSPACING);
+			
+			WordWrap := True;
+			AutoSize := True;
+			Width := DialogTextWidth;
+
+			if Message[i][1] <> '_' then
+				Caption := Message[i]
+			else
+			begin // apply URL formatting
+				Message_SetUpURLLabel(TextLabel[i], Message[i], URLNum);
+				URLNum := URLNum + 1;
+			end;
+
+		end;
+	end;
+
+	i := GetArrayLength(TextLabel) - 1;
+	if TextLabel[i].Top + TextLabel[i].Height < TypImg.Top + TypImg.Height then //center labels vertically
+	begin
+		dy := (TypImg.Top + TypImg.Height - TextLabel[i].Top - TextLabel[i].Height) div 2;
+		for i := 0 to GetArrayLength(TextLabel) - 1 do
+			TextLabel[i].Top := TextLabel[i].Top + dy;
+	end;
+end;
+
+
+procedure Message_SetUpButtons(var Button: TArrayOfButton; ButtonText: TArrayOfString;
+                              const ButtonWidth, DefaultButton, CancelButton: Integer; MessageForm: TSetupForm);
+var	i: Integer;
+begin
+	SetArrayLength(Button,GetArrayLength(ButtonText));
+	for i := 0 to GetArrayLength(Button) - 1 do
+	begin
+		Button[i] := TButton.Create(MessageForm);
+		with Button[i] do
+		begin
+			Parent := MessageForm;
+			Width := ButtonWidth;
+			Height := ScaleY(MWU_BUTTONHEIGHT);
+
+			if i = 0 then
+			begin
+				Left := MessageForm.ClientWidth - (ScaleX(MWU_HORZSPACING) + ButtonWidth) * GetArrayLength(ButtonText);
+				Top := MessageForm.ClientHeight - ScaleY(MWU_BUTTONAREAHEIGHT) +
+				       ScaleY(MWU_BUTTONAREAHEIGHT - MWU_BUTTONHEIGHT) div 2;
+			end else
+			begin
+				Left := Button[i-1].Left + ScaleX(MWU_HORZSPACING) + ButtonWidth;
+				Top := Button[i-1].Top;
+			end;
+
+			Caption := ButtonText[i];
+			ModalResult := i + 1;
+
+			//set the initial focus to the default button
+			TabOrder := ((i - (DefaultButton - 1)) + GetArrayLength(Button)) mod (GetArrayLength(Button));
+
+			if DefaultButton = i + 1 then
+				Default := True;
+
+			if CancelButton = i + 1 then
+				Cancel := True;
+
+		end;
+	end;
+end;
+
+
+//find out if URL label has focus, draw focus rectange around it if it is, and return index of focused label
+function Message_FocusLabel(): Integer;
+var	i: Integer;
+	FocusRect: TRect;
+begin
+	Result := -1;
+
+	for i := 0 to GetArrayLength(URLFocusImg) - 1 do //clear existing focus rectangle
+	begin
+		FocusRect.Left := 0;
+		FocusRect.Top := 0;
+		FocusRect.Right := URLFocusImg[i].Bitmap.Width;
+		FocusRect.Bottom := URLFocusImg[i].Bitmap.Height;
+		URLFocusImg[i].Bitmap.Canvas.FillRect(FocusRect);
+	end;
+
+	for i := 0 to GetArrayLength(TextLabel) - 1 do
+	begin
+		if TextLabel[i].Focused then
+		begin
+			Result := i;
+
+			FocusRect.Left := 0;
+			FocusRect.Top := 0;
+			FocusRect.Right := URLFocusImg[TextLabel[i].Tag].Bitmap.Width;
+			FocusRect.Bottom := URLFocusImg[TextLabel[i].Tag].Bitmap.Height;
+
+			DrawFocusRect(URLFocusImg[TextLabel[i].Tag].Bitmap.Canvas.Handle, FocusRect);
+		end;
+	end;
+end;
+
+
+//TNewStaticText doesn't have OnFocus - handle that here
+//(not perfect - if you focus label with keyboard, then focus a button with mouse, the label keeps it's underline)
+procedure Message_KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+var URLIdx: Integer;
+begin
+	case Key of
+	9,37..40: //tab, arrow keys
+		begin
+			Message_FocusLabel();
+		end;
+	13,32: //enter, spacebar
+		begin
+			URLIdx := Message_FocusLabel(); //get focused label
+			if URLIdx > -1 then
+				UrlClick(TextLabel[URLIdx]);
+		end;
+	end;
+end;
+
+
+function MessageWithURL(Message: TArrayOfString; const Title: String; ButtonText: TArrayOfString; const Typ: TMsgBoxType;
+                        const DefaultButton, CancelButton: Integer): Integer;
+var MessageForm: TSetupForm;
+	Button: TArrayOfButton;
+	DialogTextWidth, ButtonWidth: Integer;
+	MessagePanel: TPanel;
+	TypImg: TBitmapImage;
+	i: Integer;
+begin
+	if (not IsUninstaller and WizardSilent) or (IsUninstaller and UninstallSilent) then
+	begin
+		Result := DefaultButton;
+		exit;
+	end;
+
+	MessageForm := CreateCustomForm();
+
+	MessageForm.Caption := Title;
+	if (CancelButton = 0) or (CancelButton > GetArrayLength(ButtonText)) then //no cancel button - remove close button
+		MessageForm.BorderIcons := MessageForm.BorderIcons - [biSystemMenu];
+
+	MessagePanel := TPanel.Create(MessageForm); //Vista-style background
+	with MessagePanel do
+	begin
+		Parent := MessageForm;
+		BevelInner := bvNone;
+		BevelOuter := bvNone;
+		BevelWidth := 0;
+		ParentBackground := False;
+		Color := clWindow;
+		Left := 0;
+		Top := 0;
+	end;
+
+	DialogTextWidth := Message_CalcLabelWidth(Message, MessageForm);
+	ButtonWidth := Message_CalcButtonWidth(ButtonText, MessageForm);
+
+	TypImg := TBitmapImage.Create(MessagePanel);
+	TypImg.Parent := MessagePanel;
+	Message_Icon(Typ, TypImg);
+
+	Message_SetUpLabels(Message, TypImg, DialogTextWidth, MessagePanel);
+
+	i := GetArrayLength(TextLabel) - 1;
+	MessagePanel.ClientHeight := TextLabel[i].Top + TextLabel[i].Height + ScaleY(MWU_BOTTOMBORDER);
+
+	MessagePanel.ClientWidth := DialogTextWidth + TypImg.Width + TypImg.Left + ScaleX(MWU_HORZSPACING + MWU_RIGHTBORDER);
+	if MessagePanel.ClientWidth <
+	   (ButtonWidth + ScaleX(MWU_HORZSPACING)) * GetArrayLength(ButtonText) + ScaleX(MWU_HORZSPACING) then //ensure buttons fit
+		MessagePanel.ClientWidth := (ButtonWidth + ScaleX(MWU_HORZSPACING)) * GetArrayLength(ButtonText) + ScaleX(MWU_HORZSPACING);
+
+	MessageForm.ClientWidth := MessagePanel.Width;
+	MessageForm.ClientHeight := MessagePanel.Height + ScaleY(MWU_BUTTONAREAHEIGHT);
+
+	Message_SetUpButtons(Button, ButtonText, ButtonWidth, DefaultButton, CancelButton, MessageForm);
+
+	MessageForm.Center;
+
+	MessageForm.OnKeyUp := @Message_KeyUp; //needed for keyboard access of URL labels
+	MessageForm.KeyPreView := True;
+
+	Result := MessageForm.ShowModal;
+
+	for i := 0 to GetArrayLength(TextLabel) - 1 do
+		TextLabel[i].Free;
+	SetArrayLength(TextLabel,0);
+	for i := 0 to GetArrayLength(URLFocusImg) - 1 do
+		URLFocusImg[i].Free;
+	SetArrayLength(URLFocusImg,0);
+
+	MessageForm.Release;
+end;
diff --git a/build/windows/installer/associations.isi b/build/windows/installer/associations.isi
new file mode 100755
index 0000000..c82e17e
--- /dev/null
+++ b/build/windows/installer/associations.isi
@@ -0,0 +1,318 @@
+#if 0
+//for syntax hilighting
+[Code]
+#endif
+
+//Encode registry keys saved to uninst.inf
+function Encode(pText: String): String;
+begin
+	pText := Replace('%','%25', pText);
+	Result := Replace('\','%5c', pText);
+end;
+
+//reverse encoding done by Encode
+function Decode(pText: String): String;
+var p: Integer;
+	tmp: String;
+begin
+	if Pos('%',pText) = 0 then
+		Result := pText
+	else
+	begin		
+		Result := '';
+		while Length(pText) > 0 do
+		begin
+			p := Pos('%',pText);
+			if p = 0 then
+			begin
+				Result := Result + pText;
+				break;
+			end;
+			Result := Result + Copy(pText,1,p-1);
+			tmp := '$' + Copy(pText,p+1,2);
+			Result := Result + Chr(StrToIntDef(tmp,32));
+			pText := Copy(pText,p+3,Length(pText));
+		end;
+	end;
+end;
+
+
+function Associations_Write(const pSubKey,pValue,pData: String): Boolean;
+begin
+	Result := RegWriteStringValue(HKCR,pSubKey,pValue,pData)
+	SaveToUninstInf('RegVal:HKCR/'+pSubKey+'\'+Encode(pValue));
+end;
+
+
+function Associations_Read(const pSubKey,pValue: String; var pData: String): Boolean;
+begin
+	Result := RegQueryStringValue(HKCR,pSubKey,pValue,pData)
+end;
+
+
+procedure Association_Fix(const pKey: String);
+begin
+	if RegKeyExists(HKCR,pKey+'\shell\Open with GIMP') then
+	begin
+		if RegDeleteKeyIncludingSubkeys(HKCR,pKey+'\shell\Open with GIMP') then
+			DebugMsg('Association_Fix','Removed leftover Open with GIMP from ' + pKey)
+		else
+			DebugMsg('Association_Fix','Failed removing leftover Open with GIMP from ' + pKey)
+	end;
+end;
+
+
+procedure Associations_Create();
+var i,j: Integer;
+	sIconFile: String;
+begin
+
+	for i := 0 to GetArrayLength(Associations.Association) - 1 do
+	begin
+		for j := 0 to GetArrayLength(Associations.Association[i].Extensions) - 1 do
+		begin			
+
+			if Associations.Association[i].Selected then //user wants to use the GIMP as default program for this type of image
+			begin
+
+				DebugMsg('Create associations',Associations.Association[i].Extensions[j]);
+
+				StatusLabel(CustomMessage('SettingUpAssociations'), Associations.Association[i].Description + ' ('
+				            + Associations.Association[i].Extensions[j]+')');
+
+				SaveToUninstInf('RegKeyEmpty:HKCR/GIMP-{#ASSOC_VERSION}-'+
+				                Associations.Association[i].Extensions[0]);
+				SaveToUninstInf('RegKeyEmpty:HKCR/GIMP-{#ASSOC_VERSION}-'+
+				                Associations.Association[i].Extensions[0]+'\DefaultIcon');
+				SaveToUninstInf('RegKeyEmpty:HKCR/GIMP-{#ASSOC_VERSION}-'+
+				                Associations.Association[i].Extensions[0]+'\shell');
+				SaveToUninstInf('RegKeyEmpty:HKCR/GIMP-{#ASSOC_VERSION}-'+
+				                Associations.Association[i].Extensions[0]+'\shell\open');
+				SaveToUninstInf('RegKeyEmpty:HKCR/GIMP-{#ASSOC_VERSION}-'+
+				                Associations.Association[i].Extensions[0]+'\shell\open\command');
+				SaveToUninstInf('RegKeyEmpty:HKCR/.'+Associations.Association[i].Extensions[j]);
+
+				if not Associations_Write('GIMP-{#ASSOC_VERSION}-'+Associations.Association[i].Extensions[0],'',
+				                          Associations.Association[i].Description) then
+					continue; //something's very wrong in user's registry if any of these continues are called
+
+				if Associations.Association[i].Extensions[0] <> 'ico' then //special case for icons
+					sIconFile := ExpandConstant('{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe')+',1'
+				else
+					sIconFile := '%1';
+
+				if not Associations_Write('GIMP-{#ASSOC_VERSION}-'+Associations.Association[i].Extensions[0]+'\DefaultIcon',
+				                          '',sIconFile) then
+					continue;
+
+				if not Associations_Write('GIMP-{#ASSOC_VERSION}-'+Associations.Association[i].Extensions[0]+'\shell\open\command',
+							  '','"'+ExpandConstant('{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe')+'" "%1"') then
+					continue;
+
+				if not Associations_Write('.'+Associations.Association[i].Extensions[j],'',
+				                          'GIMP-{#ASSOC_VERSION}-'+Associations.Association[i].Extensions[0]) then
+					continue;
+
+			end else //add "Open with GIMP" to another program's association
+			begin
+
+				if Associations.Association[i].AssociatedElsewhere <> '' then
+				begin
+
+					DebugMsg('Adding Open with GIMP',Associations.Association[i].Extensions[j]);
+
+					SaveToUninstInf('RegKey:HKCR/'+Associations.Association[i].AssociatedElsewhere+
+					                '\shell\'+CustomMessage('OpenWithGIMP'));
+
+					if not Associations_Write(Associations.Association[i].AssociatedElsewhere+'\shell\'+
+					                          CustomMessage('OpenWithGIMP'),
+					                          '',CustomMessage('OpenWithGimp')) then
+						continue;
+
+					if not Associations_Write(Associations.Association[i].AssociatedElsewhere+'\shell\'+
+					                          CustomMessage('OpenWithGIMP')+'\command','',
+					                          '"'+ExpandConstant('{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe')+'" "%1"') then
+						continue;
+				end else
+				begin
+					DebugMsg('Skipping association',Associations.Association[i].Extensions[j]);
+					//TODO: decide what to do here (user doesn't want to associate file type with GIMP, and there's no existing assoc.)
+				end;
+
+			end;
+
+		end;
+	end;
+end;
+
+
+procedure Associations_Init();
+var i,j,c,d,iNumAssoc: Integer;
+	sAssociation,sExt,sCheck: String;
+	CmdLineAssoc: TArrayOfString;
+	CmdLine: String;
+begin
+	iNumAssoc := 0;
+	while IniKeyExists('File Associations', IntToStr(iNumAssoc + 1), SetupINI) do
+		iNumAssoc := iNumAssoc + 1;
+
+	DebugMsg('Associations_Init','Found ' + IntToStr(iNumAssoc) + ' associations');
+
+	SetArrayLength(Associations.Association,iNumAssoc);
+
+	CmdLine := ExpandConstant('{param:assoc|}');
+	if CmdLine <> '' then
+	begin
+		DebugMsg('Associations_Init','Associations requested through command-line: ' + CmdLine);
+		Explode(CmdLineAssoc,LowerCase(CmdLine),',');
+	end;
+	
+	for i := 1 to iNumAssoc do
+	begin
+		sAssociation := GetIniString('File Associations',IntToStr(i),'',SetupINI);
+
+		DebugMsg('Associations Init',sAssociation);
+		
+		d := Pos(':',sAssociation);
+		if d = 0 then
+		begin
+			DebugMsg('InitAssociations',': not found');
+			MsgBox(FmtMessage(CustomMessage('InternalError'),['10']),mbError,MB_OK);
+			exit;
+		end;
+
+		Associations.Association[i-1].Description := Copy(sAssociation,1,d-1); //split description
+		sAssociation := Copy(sAssociation,d+1,Length(sAssociation));
+
+		Explode(Associations.Association[i-1].Extensions, LowerCase(sAssociation), ':'); //split extensions
+
+		Associations.Association[i-1].Associated := False; //initialize structure (not sure if needed, but better safe than sorry)
+		Associations.Association[i-1].Selected := False;
+		Associations.Association[i-1].AssociatedElsewhere := '';
+
+		for j := 0 to GetArrayLength(Associations.Association[i - 1].Extensions) - 1 do
+		begin
+			sExt := LowerCase(Associations.Association[i-1].Extensions[j]);
+
+			for c := 0 to GetArrayLength(CmdLineAssoc) - 1 do //association requested through command line
+				if CmdLineAssoc[c] = sExt then
+					Associations.Association[i-1].Selected := True;
+	
+			sCheck := '';
+			if Associations_Read('.'+sExt,'',sCheck) then //check if anything else claims this association
+			begin
+				if (Pos('GIMP-{#ASSOC_VERSION}',sCheck) = 1) //already associated by this version of GIMP
+				   or (Pos('GIMP-2.0',sCheck) = 1) //associated by previous GIMP version
+				   then 
+				begin
+					Associations.Association[i-1].Associated := True;
+					Associations.Association[i-1].Selected := True;
+					DebugMsg('InitAssociations','Associated in registry:'+Associations.Association[i-1].Extensions[0]);
+				end else
+				begin                                      //associated by something else
+					if RegKeyExists(HKCR,sCheck) or RegKeyExists(HKCU,'SOFTWARE\Classes\'+sCheck) then //ensure that "something else"
+					begin                                                                              //still actually exists
+						Associations.Association[i-1].AssociatedElsewhere := sCheck;
+						Association_Fix(sCheck);  //clean up after old broken installers
+					end;
+				end;
+			end else
+			begin
+			
+				if Pos('GIMP',Associations.Association[i-1].Description) > 0 then
+					Associations.Association[i-1].Selected := True; //select GIMP's types by default if it's not associated by anything yet
+
+			end;
+		end;
+	end;
+end;
+
+
+procedure Associations_OnClick(Sender: TObject);
+var i,j: Integer;
+	ext: String;
+begin
+	DebugMsg('Associations_OnClick','');
+
+	for i := 0 to GetArrayLength(Associations.Association) - 1 do
+	begin
+		if TNewCheckListbox(Sender).Selected[i] then
+		begin
+			ext := '';
+			for j := 0 to GetArrayLength(Associations.Association[i].Extensions) - 1 do
+				ext := ext + LowerCase(Associations.Association[i].Extensions[j]) + ', ';
+			ext := Copy(ext, 1, Length(ext) - 2);
+			
+			Associations.AssociationsPage.lblAssocInfo2.Caption := #13+CustomMessage('SelectAssociationsExtensions')+' ' + ext;
+
+		end;
+		if TNewCheckListbox(Sender).Checked[i] then
+			Associations.Association[i].Selected := True
+		else
+			Associations.Association[i].Selected := False;
+	end;
+end;
+
+
+procedure Associations_SelectAll(Sender: TObject);
+var i: Integer;
+	SelAll, UnSelAll: String;
+begin
+
+	SelAll := CustomMessage('SelectAssociationsSelectAll')
+	UnselAll := CustomMessage('SelectAssociationsUnselectAll');
+
+	if TButton(Sender).Caption = SelAll then
+	begin
+	
+		for i := 0 to GetArrayLength(Associations.Association) - 1 do
+			Associations.AssociationsPage.clbAssociations.Checked[i] := True;
+
+		TButton(Sender).Caption := UnselAll;
+
+	end else
+	begin
+
+		for i := 0 to GetArrayLength(Associations.Association) - 1 do
+			if Associations.Association[i].Associated = False then //don't uncheck associations that are already active
+				Associations.AssociationsPage.clbAssociations.Checked[i] := False;
+
+		TButton(Sender).Caption := SelAll;
+
+	end;
+
+	Associations_OnClick(Associations.AssociationsPage.clbAssociations);
+
+end;
+
+
+procedure Associations_SelectUnused(Sender: TObject);
+var i: Integer;
+begin
+
+	for i := 0 to GetArrayLength(Associations.Association) - 1 do
+		if Associations.Association[i].AssociatedElsewhere = '' then
+			Associations.AssociationsPage.clbAssociations.Checked[i] := True;
+
+	Associations_OnClick(Associations.AssociationsPage.clbAssociations);
+
+end;
+
+
+function Associations_GetSelected(): String;
+var Selected: String;
+	i: Integer;
+begin
+
+	Selected := '';
+
+	for i := 0 to GetArrayLength(Associations.Association) - 1 do
+		if Associations.Association[i].Selected then
+			if Selected = '' then
+				Selected := Associations.Association[i].Extensions[0]
+			else
+				Selected := Selected + ',' + Associations.Association[i].Extensions[0];
+
+	Result := Selected;
+
+end;
diff --git a/build/windows/installer/directories.isi b/build/windows/installer/directories.isi
new file mode 100755
index 0000000..2f3c230
--- /dev/null
+++ b/build/windows/installer/directories.isi
@@ -0,0 +1,36 @@
+//directories to source files from
+#if !Defined(VERSION)
+  #error "VERSION must be defined"
+#endif
+
+#define public
+
+#if !defined(VER_DIR)
+	#if defined(REVISION)
+		#define VER_DIR VERSION + "-" + REVISION
+	#else
+		#define VER_DIR VERSION
+	#endif
+#endif
+
+#define DIR32 "i686"
+#define DIR64 "amd64"
+
+#ifndef GIMP_DIR
+	#define GIMP_DIR "N:\_newdev\output\gimp\" + VER_DIR
+#endif
+#ifndef DEPS_DIR
+	#define DEPS_DIR "N:\_newdev\deps-mgw\usr"
+#endif
+
+#define GIMP_DIR32 GIMP_DIR + "\" + DIR32
+#define GIMP_DIR64 GIMP_DIR + "\" + DIR64
+
+#define DDIR32 DIR32 + "-w64-mingw32\sys-root\mingw"
+#define DDIR64 DIR64 + "-w64-mingw32\sys-root\mingw"
+
+#define DEPS_DIR32 DEPS_DIR + "\" + DDIR32
+#define DEPS_DIR64 DEPS_DIR + "\" + DDIR64
+
+//#define PY_DIR DEPS_DIR + "\python"
+#define PY_DIR "N:\_newdev\deps\gimp\python"
\ No newline at end of file
diff --git a/build/windows/installer/en.setup.isl b/build/windows/installer/en.setup.isl
new file mode 100755
index 0000000..a157bd4
--- /dev/null
+++ b/build/windows/installer/en.setup.isl
@@ -0,0 +1,108 @@
+[Messages]
+;InfoBefore page is used instead of license page because the GPL only concerns distribution, not use, and as such doesn't have to be accepted
+WizardInfoBefore=License Agreement
+AboutSetupNote=Setup built by Jernej Simonè, jernej-gimp ena si%n%nImage on opening page of Setup by Alexia_Death%nImage on closing page of Setup by Jakub Steiner
+WinVersionTooLowError=This version of GIMP requires Windows XP with Service Pack 2, or a newer version of Windows.
+
+[CustomMessages]
+;shown before the wizard starts on development versions of GIMP
+DevelopmentWarningTitle=Development version
+;DevelopmentWarning=This is a development version of GIMP. As such, some features aren't finished, and it may be unstable. If you encounter any problems, first verify that they haven't already been fixed in GIT before you contact the developers.%nThis version of GIMP is not intended for day-to-day work, as it may be unstable, and you could lose your work. Do you wish to continue with installation anyway?
+DevelopmentWarning=This is a development version of GIMP installer. It hasn't been tested as much as the stable installer, which can result in GIMP not working properly. Please report any problems you encounter in the GIMP bugzilla (Installer component):%n_https://bugzilla.gnome.org/enter_bug.cgi?product=GIMP%n%nThere are some known problems in this installer:%n- loading of TIFF files doesn't work%n- file sizes are not displayed properly%nPlease don't report these problems, as we're already aware of them.%n%nDo you wish to continue with installation anyway?
+DevelopmentButtonContinue=&Continue
+DevelopmentButtonExit=Exit
+
+;XPSP3Recommended=Warning: you are running an unsupported version of Windows. Please update to at least Windows XP with Service Pack 3 before reporting any problems.
+SSERequired=This version of GIMP requires a processor that supports SSE instructions.
+
+InstallOrCustomize=GIMP is now ready to be installed. Click the Install now button to install using the default settings, or click the Customize button if you'd like to have more control over what gets installed.
+Install=&Install
+Customize=&Customize
+
+;setup types
+TypeCompact=Compact installation
+TypeCustom=Custom installation
+TypeFull=Full installation
+
+;text above component description
+ComponentsDescription=Description
+;components
+ComponentsGimp=GIMP
+ComponentsGimpDescription=GIMP and all default plug-ins
+ComponentsDeps=Run-time libraries
+ComponentsDepsDescription=Run-time libraries used by GIMP, including GTK+ Run-time Environment
+ComponentsGtkWimp=MS-Windows engine for GTK+
+ComponentsGtkWimpDescription=Native Windows look for GIMP
+ComponentsCompat=Support for old plug-ins
+ComponentsCompatDescription=Install libraries needed by old third-party plug-ins
+ComponentsTranslations=Translations
+ComponentsTranslationsDescription=Translations
+ComponentsPython=Python scripting
+ComponentsPythonDescription=Allows you to use GIMP plugins written in Python scripting language.
+ComponentsGhostscript=PostScript support
+ComponentsGhostscriptDescription=Allow GIMP to load PostScript files
+;only when installing on x64 Windows
+ComponentsGimp32=Support for 32-bit plug-ins
+ComponentsGimp32Description=Include files necessary for using 32-bit plug-ins.%nRequired for Python support.
+
+;additional installation tasks
+AdditionalIcons=Additional icons:
+AdditionalIconsDesktop=Create a &desktop icon
+AdditionalIconsQuickLaunch=Create a &Quick Launch icon
+
+RemoveOldGIMP=Remove previous GIMP version
+
+;%1 is replaced by file name; these messages should never appear (unless user runs out of disk space at the exact right moment)
+ErrorChangingEnviron=There was a problem updating GIMP's environment in %1. If you get any errors loading the plug-ins, try uninstalling and re-installing GIMP.
+ErrorExtractingTemp=Error extracting temporary data.
+ErrorUpdatingPython=Error updating Python interpreter info.
+ErrorReadingGimpRC=There was an error updating %1.
+ErrorUpdatingGimpRC=There was an error updating GIMP's configuration file %1.
+
+;displayed in Explorer's right-click menu
+OpenWithGimp=Edit with GIMP
+
+;file associations page
+SelectAssociationsCaption=Select file associations
+SelectAssociationsExtensions=Extensions:
+SelectAssociationsInfo1=Select the file types you wish to associate with GIMP
+SelectAssociationsInfo2=This will make selected files open in GIMP when you double-click them in Explorer.
+SelectAssociationsSelectAll=Select &All
+SelectAssociationsUnselectAll=Unselect &All
+SelectAssociationsSelectUnused=Select &Unused
+
+;shown on summary screen just before starting the install
+ReadyMemoAssociations=File types to associate with GIMP:
+
+RemovingOldVersion=Removing previous version of GIMP:
+;%1 = version, %2 = installation directory
+;ran uninstaller, but it returned an error, or didn't remove everything
+RemovingOldVersionFailed=GIMP %1 cannot be installed over your currently installed GIMP version, and the automatic uninstall of old version has failed.%n%nPlease remove the previous version of GIMP yourself before installing this version in %2, or choose a Custom install, and select a different installation folder.%n%nThe Setup will now exit.
+;couldn't find an uninstaller, or found several uninstallers
+RemovingOldVersionCantUninstall=GIMP %1 cannot be installed over your currently installed GIMP version, and Setup couldn't determine how to remove the old version automatically.%n%nPlease remove the previous version of GIMP and any add-ons yourself before installing this version in %2, or choose a Custom install, and select a different installation folder.%n%nThe Setup will now exit.
+
+RebootRequiredFirst=Previous GIMP version was removed successfully, but Windows has to be restarted before the Setup can continue.%n%nAfter restarting your computer, Setup will continue next time an administrator logs in.
+
+;displayed if restart settings couldn't be read, or if the setup couldn't re-run itself
+ErrorRestartingSetup=There was an error restarting the Setup. (%1)
+
+;displayed while the files are being extracted; note the capitalisation!
+Billboard1=Remember: GIMP is Free Software.%n%nPlease visit
+;www.gimp.org (displayed between Billboard1 and Billboard2)
+Billboard2=for free updates.
+
+SettingUpAssociations=Setting up file associations...
+SettingUpPyGimp=Setting up environment for GIMP Python extension...
+SettingUpEnvironment=Setting up GIMP environment...
+SettingUpGimpRC=Setting up GIMP configuration for 32-bit plug-in support...
+
+;displayed on last page
+LaunchGimp=Launch GIMP
+
+;shown during uninstall when removing add-ons
+UninstallingAddOnCaption=Removing add-on
+
+InternalError=Internal error (%1).
+
+;used by installer for add-ons (currently only help)
+DirNotGimp=GIMP does not appear to be installed in the selected directory. Continue anyway?
diff --git a/build/windows/installer/files.isi b/build/windows/installer/files.isi
new file mode 100755
index 0000000..65e7335
--- /dev/null
+++ b/build/windows/installer/files.isi
@@ -0,0 +1,27 @@
+#if 0
+[Files]
+#endif
+
+#if PLATFORM==32
+	#define DIR DIR32
+	#define DDIR DDIR32
+#elif PLATFORM==64
+	#define DIR DIR64
+	#define DDIR DDIR64
+#else
+	#error "Unknown PLATFORM:" + PLATFORM
+#endif
+
+Source: "{#GIMP_DIR}\{#DIR}\*.dll"; DestDir: "{app}"; Components: gimp{#PLATFORM}; Flags: recursesubdirs restartreplace comparetimestamp
+Source: "{#GIMP_DIR}\{#DIR}\*.exe"; DestDir: "{app}"; Excludes: "\lib\gimp\2.0\plug-ins\twain.exe,\lib\gimp\2.0\plug-ins\file-ps.exe,\bin\gimp.exe,\bin\gimp-console.exe"; Components: gimp{#PLATFORM}; Flags: recursesubdirs restartreplace comparetimestamp
+
+Source: "{#GIMP_DIR}\{#DIR}\lib\gimp\2.0\plug-ins\file-ps.exe"; DestDir: "{app}\lib\gimp\2.0\plug-ins"; Components: gimp{#PLATFORM} and gs; Flags: restartreplace comparetimestamp
+
+Source: "{#DEPS_DIR}\{#DDIR}\*.dll"; DestDir: "{app}"; Excludes: "\bin\libgs-8.dll"; Components: deps{#PLATFORM}; Flags: recursesubdirs restartreplace comparetimestamp
+Source: "{#DEPS_DIR}\{#DDIR}\bin\libgs-8.dll"; DestDir: "{app}\bin"; Components: gs and deps{#PLATFORM}; Flags: recursesubdirs restartreplace comparetimestamp
+
+Source: "{#DEPS_DIR}\{#DDIR}\bin\gspawn-win*.exe"; DestDir: "{app}\bin"; Components: deps{#PLATFORM}; Flags: recursesubdirs restartreplace comparetimestamp
+;Source: "{#DEPS_DIR}\{#DDIR}\bin\bzip2.exe"; DestDir: "{app}\bin"; Components: deps{#PLATFORM}; Flags: recursesubdirs restartreplace
+Source: "{#DEPS_DIR}\{#DDIR}\lib\*.dll"; DestDir: "{app}\lib"; Components: deps{#PLATFORM}; Flags: recursesubdirs restartreplace comparetimestamp
+;Source: "{#DEPS_DIR}\{#DDIR}\lib\bonobo\servers\*"; DestDir: "{app}\lib\bonobo\servers"; Components: deps{#PLATFORM}; Flags: recursesubdirs restartreplace
+Source: "{#DEPS_DIR}\{#DDIR}\libexec\*.exe"; DestDir: "{app}\libexec"; Components: deps{#PLATFORM}; Flags: recursesubdirs restartreplace comparetimestamp
diff --git a/build/windows/installer/gimp3264.iss b/build/windows/installer/gimp3264.iss
new file mode 100755
index 0000000..196304d
--- /dev/null
+++ b/build/windows/installer/gimp3264.iss
@@ -0,0 +1,1382 @@
+ï;.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,
+;                                                                       ;
+;Copyright (c) 2002-2010 Jernej SimonÄiÄ                                ;
+;                                                                       ;
+;This software is provided 'as-is', without any express or implied      ;
+;warranty. In no event will the authors be held liable for any damages  ;
+;arising from the use of this software.                                 ;
+;                                                                       ;
+;Permission is granted to anyone to use this software for any purpose,  ;
+;including commercial applications, and to alter it and redistribute it ;
+;freely, subject to the following restrictions:                         ;
+;                                                                       ;
+;   1. The origin of this software must not be misrepresented; you must ;
+;      not claim that you wrote the original software. If you use this  ;
+;      software in a product, an acknowledgment in the product          ;
+;      documentation would be appreciated but is not required.          ;
+;                                                                       ;
+;   2. Altered source versions must be plainly marked as such, and must ;
+;      not be misrepresented as being the original software.            ;
+;                                                                       ;
+;   3. This notice may not be removed or altered from any source        ;
+;      distribution.                                                    ;
+;.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.;
+;
+;Install script for GIMP and GTK+
+;requires Inno Setup 5.4.2 unicode + ISPP
+;
+;See directories.isi 
+;
+;Changelog:
+;
+;2012-05-05
+;- check for SSE support
+;- remove obsolete 2.6 plugins when installing over 2.6.12 combined installer
+;
+;2011-12-18
+;- display a picture on the first install screen
+;- add a development version warning back
+;- clean gegl's DLLs on install as some files have changed names
+;
+;2011-08-30
+;- only uninstall previous GIMP version when installing over existing installation
+;  TODO: offer the option to uninstall 32bit version when installing on x64 system
+;- install 32bit plugins to same directory as 64bit plugins on x64 installs to
+;  avoid problems when upgrading
+;
+;2010-07-08
+;- clean up entire Python subdirectory (since the .pyc files are generated when
+;  scripts are run)
+;- use crHand instead of crHandPoint for the billboard URL
+;
+;2010-07-02
+;- add libraries for compatibility with old 32-bit plug-ins as a component
+;- remove a few unused RTF ready-memo related things
+;- uninst.inf is now processed as the first step of uninstall, as otherwise the
+;  uninstaller could leave behind empty directories
+;
+;2010-06-29
+;- fix SuppressibleMsgBox calls to use proper button ID for default button
+;- simplify the wizard - skip Welcome page, and make the Next button from
+;  InfoBefore/License page invoke install immediately (custom install is still
+;  possible by clicking the Customize button)
+;
+;2010-05-15
+;- rewrote script mostly from scratch
+;- combine 32 and 64bit GIMP versions to a single installer
+;  - install enough 32bit support files even with 64bit version to allow running 32bit
+;    plug-ins on 64bit version (used by Python scriptin support [as there's no 64-bit
+;    PyGTK+ on Windows available yet] and TWAIN plug-in, which only works in 32-bit
+;    version)
+;- Python with PyGTK is included in the installer now
+;- install GIMP to new directory by default ({pf}\GIMP 2 instead of {pf}\GIMP-2.0)
+;- uninstall previous GIMP versions as the first step of install (both 32 and 64-bit)
+;  - require reboot if installing to directory from which GIMP was just uninstalled,
+;    and this directory wasn't removed by the uninstaller; the installer will continue
+;    automatically after reboot
+;- fixed a long standing bug where "Open with GIMP" menu entries would be left after
+;  uninstalling
+;
+#pragma option -e+
+
+#ifndef VERSION
+	#define VERSION "2.7.0"
+	#define REVISION "20100414"
+	#define NOFILES
+#endif
+
+#include "directories.isi"
+#include "version.isi"
+
+[Setup]
+AppName=GIMP
+#if Defined(DEVEL) && DEVEL != ""
+AppID=GIMP-{#MAJOR}.{#MINOR}
+#else
+AppID=GIMP-{#MAJOR}
+#endif
+VersionInfoVersion={#VERSION}
+#if !defined(REVISION)
+AppVerName=GIMP {#VERSION}
+#else
+AppVerName=GIMP {#VERSION}-{#REVISION}
+#endif
+AppPublisherURL=http://gimp-win.sourceforge.net/
+AppSupportURL=http://www.gimp.org/docs/
+AppUpdatesURL=http://gimp-win.sourceforge.net/
+AppPublisher=The GIMP Team
+AppVersion={#VERSION}
+DisableProgramGroupPage=yes
+DisableWelcomePage=no
+
+#if Defined(DEVEL) && DEVEL != ""
+DefaultDirName={pf}\GIMP {#MAJOR}.{#MINOR}
+LZMANumBlockThreads=4
+LZMABlockSize=76800
+#else
+DefaultDirName={pf}\GIMP {#MAJOR}
+#endif
+
+;AllowNoIcons=true
+FlatComponentsList=yes
+InfoBeforeFile=gpl+python.rtf
+ChangesAssociations=true
+
+WizardImageFile=windows-installer-intro-big.bmp
+WizardImageBackColor=$6f5a13
+WizardImageStretch=yes
+WizardSmallImageFile=wilber.bmp
+
+UninstallDisplayIcon={app}\bin\gimp-{#MAJOR}.{#MINOR}.exe
+UninstallFilesDir={app}\uninst
+
+MinVersion=0,5.01sp3
+//MinVersion=0,5.0
+
+#ifdef NOCOMPRESSION
+UseSetupLdr=no
+OutputDir=_Output\unc
+Compression=none
+InternalCompressLevel=0
+#else
+OutputDir=_Output
+Compression=lzma2/ultra64
+InternalCompressLevel=ultra
+SolidCompression=yes
+LZMAUseSeparateProcess=yes
+LZMANumFastBytes=256
+
+#if !defined(REVISION)
+OutputBaseFileName=gimp-{#VERSION}-setup
+#else
+OutputBaseFileName=gimp-{#VERSION}-{#REVISION}-setup
+#endif
+ArchitecturesInstallIn64BitMode=x64
+
+;SignTool=Default
+SignedUninstaller=yes
+SignedUninstallerDir=_Uninst
+
+#endif //NOCOMPRESSION
+
+[Languages]
+Name: "en"; MessagesFile: "compiler:Default.isl,en.setup.isl"
+Name: "sl"; MessagesFile: "compiler:Languages\Slovenian.isl,sl.setup.isl"
+;Name: "ro"; MessagesFile: "Romanian.islu,ro.setup.islu"
+
+[Types]
+;Name: normal; Description: "{cm:TypeTypical}"
+Name: full; Description: "{cm:TypeFull}"
+Name: compact; Description: "{cm:TypeCompact}"
+Name: custom; Description: "{cm:TypeCustom}"; Flags: iscustom
+
+[Components]
+Name: gimp32; Description: "{cm:ComponentsGimp,{#VERSION}}"; Types: full compact custom; Flags: fixed; Check: Check3264('32')
+Name: gimp64; Description: "{cm:ComponentsGimp,{#VERSION}}"; Types: full compact custom; Flags: fixed; Check: Check3264('64')
+
+Name: deps32; Description: "{cm:ComponentsDeps,{#GTK_VERSION}}"; Types: full compact custom; Flags: checkablealone fixed; Check: Check3264('32')
+Name: deps32\wimp; Description: "{cm:ComponentsGtkWimp}"; Types: full custom; Flags: dontinheritcheck disablenouninstallwarning; Check: Check3264('32')
+Name: deps32\compat; Description: "{cm:ComponentsCompat}"; Types: full custom; Flags: dontinheritcheck; Check: Check3264('32')
+Name: deps64; Description: "{cm:ComponentsDeps,{#GTK_VERSION}}"; Types: full compact custom; Flags: checkablealone fixed; Check: Check3264('64')
+Name: deps64\wimp; Description: "{cm:ComponentsGtkWimp}"; Types: full custom; Flags: dontinheritcheck disablenouninstallwarning; Check: Check3264('64')
+
+Name: loc; Description: "{cm:ComponentsTranslations}"; Types: full custom
+
+Name: py; Description: "{cm:ComponentsPython}"; Types: full custom; Check: Check3264('32')
+
+Name: gs; Description: "{cm:ComponentsGhostscript}"; Types: full custom
+
+Name: gimp32on64; Description: "{cm:ComponentsGimp32}"; Types: full custom; Flags: checkablealone; Check: Check3264('64')
+Name: gimp32on64\py; Description: "{cm:ComponentsPython}"; Types: full custom; Check: Check3264('64')
+Name: gimp32on64\compat; Description: "{cm:ComponentsCompat}"; Types: full custom; Flags: dontinheritcheck; Check: Check3264('64')
+
+[Tasks]
+Name: desktopicon; Description: "{cm:AdditionalIconsDesktop}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
+Name: quicklaunchicon; Description: "{cm:AdditionalIconsQuickLaunch}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
+
+[Icons]
+Name: "{commonprograms}\GIMP 2"; Filename: "{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe"; WorkingDir: "%USERPROFILE%"; Comment: "GIMP {#VERSION}"
+Name: "{commondesktop}\GIMP 2"; Filename: "{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe"; WorkingDir: "%USERPROFILE%"; Comment: "GIMP {#VERSION}"; Tasks: desktopicon
+Name: "{userappdata}\Microsoft\Internet Explorer\Quick Launch\GIMP 2"; Filename: "{app}\bin\gimp-{#MAJOR}.{#MINOR}.exe"; WorkingDir: "%USERPROFILE%"; Comment: "GIMP {#VERSION}"; Tasks: quicklaunchicon
+
+[Files]
+;setup files
+Source: "setup.ini"; Flags: dontcopy
+Source: "windows-installer-intro-small.bmp"; Flags: dontcopy
+Source: "installsplash.bmp"; Flags: dontcopy
+Source: "installsplash_small.bmp"; Flags: dontcopy
+
+#ifndef NOFILES
+;files common to both 32 and 64-bit versions
+Source: "{#GIMP_DIR32}\etc\*"; DestDir: "{app}\etc"; Components: gimp32 or gimp64; Flags: recursesubdirs restartreplace
+Source: "{#GIMP_DIR32}\lib\gimp\2.0\environ\*"; DestDir: "{app}\lib\gimp\2.0\environ"; Components: gimp32 or gimp64; Flags: recursesubdirs restartreplace
+Source: "{#GIMP_DIR32}\lib\gimp\2.0\interpreters\*"; DestDir: "{app}\lib\gimp\2.0\interpreters"; Components: gimp32 or gimp64; Flags: recursesubdirs restartreplace
+Source: "{#GIMP_DIR32}\share\gimp\*"; DestDir: "{app}\share\gimp"; Components: gimp32 or gimp64; Flags: recursesubdirs restartreplace
+Source: "{#DEPS_DIR32}\share\enchant\*"; DestDir: "{app}\share\enchant"; Components: deps32 or deps64; Flags: recursesubdirs restartreplace
+Source: "{#DEPS_DIR32}\share\libwmf\*"; DestDir: "{app}\share\libwmf"; Components: deps32 or deps64; Flags: recursesubdirs restartreplace
+Source: "{#DEPS_DIR32}\share\themes\*"; DestDir: "{app}\share\themes"; Components: deps32 or deps64; Flags: recursesubdirs restartreplace
+Source: "{#DEPS_DIR32}\share\xml\*"; DestDir: "{app}\share\xml"; Components: deps32 or deps64; Flags: recursesubdirs restartreplace
+Source: "{#DEPS_DIR32}\share\locale\*"; DestDir: "{app}\share\locale"; Components: loc; Flags: recursesubdirs restartreplace
+Source: "{#GIMP_DIR32}\share\locale\*"; DestDir: "{app}\share\locale"; Components: loc; Flags: recursesubdirs restartreplace
+
+Source: "{#DEPS_DIR32}\etc\fonts\*"; DestDir: "{app}\etc\fonts"; Components: deps32 or deps64; Flags: recursesubdirs restartreplace
+Source: "{#DEPS_DIR32}\etc\gtk-2.0\*"; DestDir: "{app}\etc\gtk-2.0"; Excludes: gtkrc; Components: deps32 or deps64; Flags: recursesubdirs restartreplace
+Source: "{#DEPS_DIR32}\etc\gtk-2.0\gtkrc"; DestDir: "{app}\etc\gtk-2.0"; Components: deps32\wimp or deps64\wimp; Flags: recursesubdirs restartreplace
+
+;ghostscript TODO: detect version automatically
+Source: "{#DEPS_DIR32}\share\ghostscript\8.71\lib\*.*"; DestDir: "{app}\share\ghostscript\8.71\lib"; Components: gs; Flags: recursesubdirs restartreplace
+Source: "{#DEPS_DIR32}\share\ghostscript\8.71\Resource\*.*"; DestDir: "{app}\share\ghostscript\8.71\Resource"; Components: gs; Flags: recursesubdirs restartreplace
+
+;32-on-64bit
+#include "32on64.isi"
+;prefer 32bit twain plugin over 64bit because 64bit twain drivers are rare
+Source: "{#GIMP_DIR32}\lib\gimp\2.0\plug-ins\twain.exe"; DestDir: "{app}\lib\gimp\2.0\plug-ins"; Components: gimp32on64; Flags: recursesubdirs restartreplace
+Source: "{#GIMP_DIR64}\lib\gimp\2.0\plug-ins\twain.exe"; DestDir: "{app}\lib\gimp\2.0\plug-ins"; Components: (not gimp32on64) and gimp64; Flags: recursesubdirs restartreplace
+;special case due to MS-Windows engine
+Source: "{#DEPS_DIR32}\etc\gtk-2.0\*"; DestDir: "{app}\32\etc\gtk-2.0"; Excludes: gtkrc; Components: gimp32on64; Flags: recursesubdirs restartreplace
+Source: "{#DEPS_DIR32}\etc\gtk-2.0\gtkrc"; DestDir: "{app}\32\etc\gtk-2.0"; Components: gimp32on64 and deps64\wimp; Flags: recursesubdirs restartreplace
+;python scripts
+Source: "{#GIMP_DIR32}\lib\gimp\2.0\plug-ins\*.py"; DestDir: "{app}\lib\gimp\2.0\plug-ins"; Components: gimp32on64\py; Flags: recursesubdirs restartreplace
+Source: "{#GIMP_DIR32}\lib\gimp\2.0\python\*.p*"; DestDir: "{app}\32\lib\gimp\2.0\python"; Components: gimp32on64\py; Flags: recursesubdirs restartreplace
+;compat libraries
+Source: "{#DEPS_DIR}-compat\*.dll"; DestDir: "{app}\32\"; Components: gimp32on64\compat; Flags: recursesubdirs restartreplace
+
+;32bit
+#define PLATFORM 32
+#include "files.isi"
+;special case, since 64bit version doesn't work, and is excluded in files.isi
+Source: "{#GIMP_DIR32}\lib\gimp\2.0\plug-ins\twain.exe"; DestDir: "{app}\lib\gimp\2.0\plug-ins"; Components: gimp32; Flags: recursesubdirs restartreplace
+;python scripts
+Source: "{#GIMP_DIR32}\lib\gimp\2.0\plug-ins\*.py"; DestDir: "{app}\lib\gimp\2.0\plug-ins"; Components: py; Flags: recursesubdirs restartreplace
+Source: "{#GIMP_DIR32}\lib\gimp\2.0\python\*.p*"; DestDir: "{app}\lib\gimp\2.0\python"; Components: py; Flags: recursesubdirs restartreplace
+;compat libraries
+Source: "{#DEPS_DIR}-compat\*.dll"; DestDir: "{app}"; Components: deps32\compat; Flags: recursesubdirs restartreplace
+
+;64bit
+#define PLATFORM 64
+#include "files.isi"
+
+;python
+Source: "{#PY_DIR}\pythonw.exe"; DestDir: "{app}\Python"; Components: py or gimp32on64\py; Flags: restartreplace
+Source: "{#PY_DIR}\python.exe"; DestDir: "{app}\Python"; Components: py or gimp32on64\py; Flags: restartreplace
+Source: "{#PY_DIR}\python27.dll"; DestDir: "{app}\Python"; Components: py or gimp32on64\py; Flags: restartreplace
+Source: "{#PY_DIR}\DLLs\*"; DestDir: "{app}\Python\DLLs"; Components: py or gimp32on64\py; Flags: recursesubdirs restartreplace
+Source: "{#PY_DIR}\Lib\*"; DestDir: "{app}\Python\Lib"; Components: py or gimp32on64\py; Flags: recursesubdirs restartreplace
+#endif //NOFILES
+
+[InstallDelete]
+Type: files; Name: "{app}\bin\gimp-?.?.exe"
+Type: files; Name: "{app}\bin\gimp-console-?.?.exe"
+Type: files; Name: "{app}\lib\gegl-0.1\*.dll"
+;obsolete plugins from gimp 2.6
+Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\file-pdf.exe"
+Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gee.exe"
+Type: files; Name: "{app}\lib\gimp\2.0\plug-ins\gee-zoom.exe"
+
+[UninstallDelete]
+Type: files; Name: "{app}\uninst\uninst.inf"
+;need to clean out all the generated .pyc files
+Type: filesandordirs; Name: "{app}\Python\*"
+
+[Code]
+
+function SHAutoComplete(hWnd: Integer; dwFlags: DWORD): Integer; external 'SHAutoComplete shlwapi dll stdcall delayload';
+
+function WideCharToMultiByte(CodePage: Cardinal; dwFlags: DWORD; lpWideCharStr: String; cchWideCharStr: Integer;
+                             lpMultiByteStr: PAnsiChar; cbMultiByte: Integer; lpDefaultChar: Integer;
+                             lpUsedDefaultChar: Integer): Integer; external 'WideCharToMultiByte Kernel32 stdcall';
+
+function MultiByteToWideChar(CodePage: Cardinal; dwFlags: DWORD; lpMultiByteStr: PAnsiChar; cbMultiByte: Integer;
+                             lpWideCharStr: String; cchWideChar: Integer): Integer;
+                             external 'MultiByteToWideChar Kernel32 stdcall';
+
+function GetLastError(): DWORD; external 'GetLastError Kernel32 stdcall';
+
+function GetSysColor(nIndex: Integer): DWORD; external 'GetSysColor user32 dll stdcall';
+
+function IsProcessorFeaturePresent(ProcessorFeature: DWORD): LongBool; external 'IsProcessorFeaturePresent kernel32 stdcall';
+
+procedure ComponentsListOnClick(pSender: TObject); forward;
+procedure SaveToUninstInf(const pText: AnsiString); forward;
+procedure CreateRunOnceEntry; forward;
+function RestartSetupAfterReboot(): Boolean; forward;
+
+const
+	CP_ACP = 0;
+	CP_UTF8 = 65001;
+
+	SHACF_FILESYSTEM = $1;
+	SHACF_FILESYS_ONLY = $10;
+	SHACF_FILESYS_DIRS = $20;
+
+	COLOR_HOTLIGHT = 26;
+
+	PF_XMMI_INSTRUCTIONS_AVAILABLE = 6;
+
+	GIMP_URL = 'http://www.gimp.org/';
+
+	RTFHeader = '{\rtf1\deff0{\fonttbl{\f0\fswiss\fprq2\fcharset0 Tahoma;}{\f1\fnil\fcharset2 Symbol;}}\viewkind4\uc1\fs16';
+	//RTFBullet = '{\pntext\f1\''B7\tab}';
+	RTFPara	  = '\par ';
+
+	RunOnceName = 'Resume GIMP {#VERSION} install';
+
+	UNINSTALL_MAX_WAIT_TIME = 10000;
+	UNINSTALL_CHECK_TIME    =   250;
+
+type
+	TRemoveOldGIMPResult = (rogContinue, rogRestartRequired, rogUninstallFailed, rogCantUninstall);
+
+var
+	lblComponentDescription: TNewStaticText;
+
+	SetupINI: String;
+
+	ReadyMemoRichText: String;
+
+	WelcomeBitmapBottom: TBitmapImage;
+
+	Associations: record
+		AssociationsPage: record
+			Page: TWizardPage;
+			clbAssociations: TNewCheckListBox;
+			lblAssocInfo2: TNewStaticText;
+		end;
+		Association: array of record
+			Description: String;
+			Extensions: TArrayOfString;
+			Selected: Boolean;
+			Associated: Boolean;
+			AssociatedElsewhere: String;
+		end;
+	end;
+
+	//pgSimple: TWizardPage;
+	btnInstall, btnCustomize: TButton;
+
+	InstallMode: (imNone, imSimple, imCustom, imRebootContinue);
+
+	asUninstInf: TArrayOfString; //uninst.inf contents (loaded at start of uninstall, exectued at the end)
+
+
+#include "MessageWithURL.isi"
+
+function Check3264(const pWhich: String): Boolean;
+begin
+	if pWhich = '64' then
+		Result := Is64BitInstallMode()
+	else if pWhich = '32' then
+		Result := not Is64BitInstallMode()
+	else
+		RaiseException('Unknown check');
+end;
+
+
+#include "utils.isi"
+
+#include "associations.isi"
+
+
+procedure PreparePyGimp();
+var PyGimpInterp,Interp: String;
+begin
+	if IsComponentSelected('py') or IsComponentSelected('gimp32on64\py') then
+	begin
+		StatusLabel(CustomMessage('SettingUpPyGimp'),'');
+
+		PyGimpInterp := ExpandConstant('{app}\lib\gimp\2.0\interpreters\pygimp.interp');
+        DebugMsg('PreparePyGimp','Writing interpreter file for gimp-python: ' + PyGimpInterp);
+		
+		Interp := 'python=' + ExpandConstant('{app}\Python\pythonw.exe') + #10 + 
+		           '/usr/bin/python=' + ExpandConstant('{app}\Python\pythonw.exe') + #10':Python:E::py::python:'#10
+
+		if not SaveStringToUTF8File(PyGimpInterp,Interp,False) then
+		begin
+			DebugMsg('PreparePyGimp','Problem writing the file. [' + Interp + ']');
+			SuppressibleMsgBox(CustomMessage('ErrorUpdatingPython') + ' (2)',mbInformation,mb_ok,IDOK);
+		end;
+
+	end;
+end;
+
+
+procedure PrepareGimpPath();
+var DefaultEnv,Env: String;
+begin
+	
+	StatusLabel(CustomMessage('SettingUpEnvironment'),'');
+
+	//set PATH to be used by plug-ins
+	DefaultEnv := ExpandConstant('{app}\lib\gimp\2.0\environ\default.env');
+	DebugMsg('PrepareGimpPath','Setting environment in ' + DefaultEnv);
+
+	Env := #10'PATH=' + ExpandConstant('{app}\bin');
+	
+	if IsComponentSelected('gimp32on64') then
+	begin
+
+		Env := Env + ';' + ExpandConstant('{app}\32\bin') + #10;
+
+		if IsComponentSelected('gimp32on64\py') then
+			Env := Env + 'PYTHONPATH=' + ExpandConstant('{app}\32\lib\gimp\2.0\python') + #10; //only needed on 64bit GIMP
+
+	end else
+	begin
+
+		Env := Env + #10;
+
+	end;
+	
+	DebugMsg('PrepareGimpPath','Appending ' + Env);
+
+	if not SaveStringToUTF8File(DefaultEnv,Env,True) then
+	begin
+		DebugMsg('PrepareGimpPath','Problem appending');
+		SuppressibleMsgBox(FmtMessage(CustomMessage('ErrorChangingEnviron'),[DefaultEnv]),mbInformation,mb_ok,IDOK);
+	end;
+end;
+
+
+#if 0
+procedure PrepareGimpRC();
+var GimpRC,GimpRCText: String;
+	GimpRCTextA: AnsiString;
+begin
+	if IsComponentSelected('gimp32on64') then
+	begin
+		StatusLabel(CustomMessage('SettingUpGimpRC'),'');
+
+		GimpRC := ExpandConstant('{app}\etc\gimp\2.0\gimprc');
+        DebugMsg('PrepareGimpRC','Updating gimprc: ' + GimpRC);
+
+        if not LoadStringFromFile(GimpRC,GimpRCTextA) then
+        begin
+			DebugMsg('PrepareGimpRC','Problem loading');
+			SuppressibleMsgBox(FmtMessage(CustomMessage('ErrorReadingGimpRC'),[GimpRC]),mbInformation,mb_ok,IDOK);
+        end;
+
+        GimpRCText := GimpRCTextA;
+        
+        StringChangeEx(GimpRCText,'# (plug-in-path', //add (relative) path to 32-bit plugin dir
+                       '(plug-in-path "${gimp_dir}\\plug-ins;${gimp_plug_in_dir}\\plug-ins;${gimp_plug_in_dir}\\..\\..\\..\\32\\lib\\gimp\\2.0\\plug-ins")'#10'# (plug-in-path',
+                       False);
+
+        if not SaveStringToUTF8File(GimpRC,GimpRCText,False) then
+        begin
+			DebugMsg('PrepareGimpRC','Problem saving');
+			SuppressibleMsgBox(FmtMessage(CustomMessage('ErrorUpdatingGimpRC'),[GimpRC]),mbInformation,mb_ok,IDOK);
+        end;
+	end;
+end;
+#endif
+
+
+procedure CleanUpCustomWelcome();
+begin
+	WizardForm.NextButton.Visible := True;
+	btnInstall.Visible := False;
+	btnCustomize.Visible := False;
+
+	WizardForm.Bevel.Visible := True;
+	WelcomeBitmapBottom.Visible := False;
+end;
+
+
+procedure InstallOnClick(Sender: TObject);
+begin
+	DebugMsg('Install mode','Simple');
+	InstallMode := imSimple;
+
+	CleanUpCustomWelcome();
+
+	WizardForm.NextButton.OnClick(TButton(Sender).Parent);
+end;
+
+
+procedure CustomizeOnClick(Sender: TObject);
+begin
+	DebugMsg('Install mode','Custom');
+	InstallMode := imCustom;
+	
+	CleanUpCustomWelcome();
+
+	WizardForm.NextButton.OnClick(TButton(Sender).Parent);
+end;
+
+
+procedure InitCustomPages();
+var lblAssocInfo: TNewStaticText;
+	btnSelectAll,btnSelectUnused: TButton;
+	i: Integer;
+	//lblInfo: TNewStaticText;
+begin
+	DebugMsg('InitCustomPages','pgAssociations');
+	Associations.AssociationsPage.Page := CreateCustomPage(wpSelectComponents,CustomMessage('SelectAssociationsCaption'),CustomMessage('SelectAssociationsCaption'));
+
+	lblAssocInfo := TNewStaticText.Create(Associations.AssociationsPage.Page);
+	with lblAssocInfo do
+	begin
+		Parent := Associations.AssociationsPage.Page.Surface;
+		Left := 0;
+		Top := 0;
+		Width := Associations.AssociationsPage.Page.SurfaceWidth;
+		Height := ScaleY(13);
+		Caption := CustomMessage('SelectAssociationsInfo1')+#13+CustomMessage('SelectAssociationsInfo2')+#13;
+	end;	
+	Associations.AssociationsPage.lblAssocInfo2 := TNewStaticText.Create(Associations.AssociationsPage.Page);
+	with Associations.AssociationsPage.lblAssocInfo2 do
+	begin
+		Parent := Associations.AssociationsPage.Page.Surface;
+		Left := 0;
+		Width := Associations.AssociationsPage.Page.SurfaceWidth;
+		Height := 13;
+		AutoSize := True;
+		Caption := #13+CustomMessage('SelectAssociationsExtensions');
+	end;
+	
+	Associations.AssociationsPage.clbAssociations := TNewCheckListBox.Create(Associations.AssociationsPage.Page);
+	with Associations.AssociationsPage.clbAssociations do
+	begin
+		Parent := Associations.AssociationsPage.Page.Surface;
+		Left := 0;
+		Top := lblAssocInfo.Top + lblAssocInfo.Height;
+		Width := Associations.AssociationsPage.Page.SurfaceWidth;
+		Height := Associations.AssociationsPage.Page.SurfaceHeight - lblAssocInfo.Height - Associations.AssociationsPage.lblAssocInfo2.Height - ScaleX(8);
+		TabOrder := 1;
+		Flat := True;
+
+		Associations.AssociationsPage.lblAssocInfo2.Top := Height + Top;
+
+		OnClick := @Associations_OnClick;
+
+		for i := 0 to GetArrayLength(Associations.Association) - 1 do
+			AddCheckBox(Associations.Association[i].Description,
+			            '',
+			            0,
+			            Associations.Association[i].Selected,
+			            not Associations.Association[i].Associated, //don't allow unchecking associations that are already present
+			            False,
+			            False,
+			            nil
+			           );			
+
+	end;
+
+	btnSelectUnused := TButton.Create(Associations.AssociationsPage.Page);
+	with btnSelectUnused do
+	begin
+		Parent := Associations.AssociationsPage.Page.Surface;
+		Width := Round(WizardForm.NextButton.Width * 1.2);
+		Left := Associations.AssociationsPage.Page.SurfaceWidth - Width * 2;
+		Height := WizardForm.NextButton.Height;
+		Top := Associations.AssociationsPage.clbAssociations.Top + Associations.AssociationsPage.clbAssociations.Height + ScaleX(8);
+		Caption := CustomMessage('SelectAssociationsSelectUnused');
+		OnClick := @Associations_SelectUnused;
+	end;
+
+	btnSelectAll := TButton.Create(Associations.AssociationsPage.Page);
+	with btnSelectAll do
+	begin
+		Parent := Associations.AssociationsPage.Page.Surface;
+		Width := Round(WizardForm.NextButton.Width * 1.2);
+		Left := Associations.AssociationsPage.Page.SurfaceWidth - Width;
+		Height := WizardForm.NextButton.Height;
+		Top := Associations.AssociationsPage.clbAssociations.Top + Associations.AssociationsPage.clbAssociations.Height + ScaleX(8);
+		Caption := CustomMessage('SelectAssociationsSelectAll');
+		OnClick := @Associations_SelectAll;
+	end;
+
+	DebugMsg('InitCustomPages','wpLicense');
+
+	(*pgSimple := CreateCustomPage(wpInfoBefore,SetupMessage(msgWizardReady),
+	             Replace('[name]','{#SetupSetting("AppName")}',SetupMessage(msgReadyLabel1)));
+
+	lblInfo := TNewStaticText.Create(pgSimple);
+	with lblInfo do
+	begin
+		Parent := pgSimple.Surface;
+		Left := 0;
+		Top := 0;
+
+		WordWrap := True;
+		AutoSize := True;
+		Width := pgSimple.SurfaceWidth;
+
+		Caption := CustomMessage('InstallOrCustomize');
+	end;*)
+
+	btnInstall := TButton.Create(WizardForm);
+	with btnInstall do
+	begin
+		Parent := WizardForm;
+		Width := WizardForm.NextButton.Width;
+		Height := WizardForm.NextButton.Height;
+		Left := WizardForm.NextButton.Left;
+		Top := WizardForm.NextButton.Top;
+		Caption := CustomMessage('Install');
+		Default := True;
+		Visible := False;
+
+		OnClick := @InstallOnClick;
+	end;
+
+	btnCustomize := TButton.Create(WizardForm);
+	with btnCustomize do
+	begin
+		Parent := WizardForm;
+		Width := WizardForm.NextButton.Width;
+		Height := WizardForm.NextButton.Height;
+		Left := WizardForm.ClientWidth - (WizardForm.CancelButton.Left + WizardForm.CancelButton.Width);
+		//Left := WizardForm.BackButton.Left;
+		Top := WizardForm.NextButton.Top;
+		Visible := False;
+
+		Caption := CustomMessage('Customize');
+
+		OnClick := @CustomizeOnClick;
+	end;
+
+end;
+
+
+procedure SelectComponentsFaceLift();
+var pnlDescription: TPanel;
+	lblDescription: TNewStaticText;
+begin
+	DebugMsg('SelectComponentsFaceLift','');
+
+	if WizardForm.ComponentsList.Width = WizardForm.SelectComponentsPage.Width then
+		WizardForm.ComponentsList.Width := Round(WizardForm.ComponentsList.Width * 0.6)
+	else
+		exit;
+	DebugMsg('SelectComponentsFaceLift','2');
+			
+	WizardForm.ComponentsList.OnClick := @ComponentsListOnClick;
+			
+	lblDescription := TNewStaticText.Create(WizardForm.ComponentsList.Parent)
+	with lblDescription do
+	begin
+		Left := WizardForm.ComponentsList.Left + WizardForm.ComponentsList.Width + ScaleX(16);
+		Top := WizardForm.ComponentsList.Top;
+		AutoSize := True;
+		Caption := CustomMessage('ComponentsDescription');
+	end;
+			
+	pnlDescription := TPanel.Create(WizardForm.ComponentsList.Parent);
+	with pnlDescription do
+	begin
+		Parent := WizardForm.ComponentsList.Parent;
+		Left := WizardForm.ComponentsList.Left + WizardForm.ComponentsList.Width + ScaleX(8);
+		Width := WizardForm.TypesCombo.Width - WizardForm.ComponentsList.Width - ScaleX(8);
+		BevelOuter := bvLowered;
+		BevelInner := bvRaised;
+		Top := WizardForm.ComponentsList.Top + Round(lblDescription.Height * 0.4);
+		Height := WizardForm.ComponentsList.Height - Round(lblDescription.Height * 0.4);
+	end;
+
+	lblDescription.Parent := WizardForm.ComponentsList.Parent; //place lblDescription above pnlDescription
+			
+	lblComponentDescription := TNewStaticText.Create(pnlDescription);
+	with lblComponentDescription do
+	begin
+		Parent := pnlDescription;
+		Left := ScaleX(8);
+		WordWrap := True;
+		AutoSize := False;
+		Width := Parent.Width - ScaleX(16);
+		Height := Parent.Height - ScaleY(20);
+		Top := ScaleY(12);
+	end;
+			
+end;
+
+
+procedure ReadyFaceLift();
+var rtfNewReadyMemo: TRichEditViewer;
+begin
+	DebugMsg('ReadyFaceLift','');
+	WizardForm.ReadyMemo.Visible := False;
+		
+	rtfNewReadyMemo := TRichEditViewer.Create(WizardForm.ReadyMemo.Parent);
+	with rtfNewReadyMemo do
+	begin
+		Parent := WizardForm.ReadyMemo.Parent;
+		Scrollbars := ssVertical;
+		Color := WizardForm.Color;
+		UseRichEdit := True;
+		RTFText := ReadyMemoRichText;
+		ReadOnly := True;
+		Left := WizardForm.ReadyMemo.Left;
+		Top := WizardForm.ReadyMemo.Top;
+		Width := WizardForm.ReadyMemo.Width;
+		Height := WizardForm.ReadyMemo.Height;
+		Visible := True;
+	end;
+end;
+
+
+procedure lblURL_OnClick(Sender: TObject);
+var ErrorCode: Integer;
+begin
+	ShellExecAsOriginalUser('',GIMP_URL,'','',SW_SHOW,ewNoWait,ErrorCode);
+end;
+
+
+function MeasureLabel(const pText: String): Integer; //WordWrap + AutoSize works better with TNewStaticText than with TLabel,
+var lblMeasure: TNewStaticText;                      //abuse this
+begin
+	lblMeasure := TNewStaticText.Create(WizardForm.InstallingPage);
+	with lblMeasure do
+	begin
+		Parent := WizardForm.InstallingPage;
+
+		AutoSize := True;
+		WordWrap := True;
+		Width := Parent.ClientWidth;
+
+		Caption := pText;
+
+		Result := Height;
+	end;
+	lblMeasure.Free;
+end;
+
+
+procedure InstallingFaceLift();
+var lblMessage1,lblURL,lblMessage2: TLabel; //TNewStaticText doesn't support alignment
+begin
+	with WizardForm.ProgressGauge do
+	begin
+		Height := ScaleY(16);
+		Top := WizardForm.InstallingPage.ClientHeight - Top - Height;
+
+		WizardForm.StatusLabel.Top := Top - WizardForm.FilenameLabel.Height - ScaleY(4);
+		WizardForm.FilenameLabel.Top := Top + Height + ScaleY(4);
+	end;
+
+	lblMessage1 := TLabel.Create(WizardForm.InstallingPage);
+	with lblMessage1 do
+	begin
+		Parent := WizardForm.InstallingPage;
+
+		Alignment := taCenter;
+		WordWrap := True;
+		AutoSize := False;
+		Width := WizardForm.InstallingPage.ClientWidth;
+		Height := MeasureLabel(CustomMessage('Billboard1'));
+
+		Caption := CustomMessage('Billboard1');
+	end;
+
+	lblURL := TLabel.Create(WizardForm.InstallingPage);
+	with lblURL do
+	begin
+		Parent := WizardForm.InstallingPage;
+
+		AutoSize := True;
+		WordWrap := False;
+
+		Font.Color := GetSysColor(COLOR_HOTLIGHT);
+		Font.Style := [fsUnderline];
+		Font.Size := 12;
+
+		Cursor := crHand;
+
+		OnClick := @lblURL_OnClick;
+
+		Caption := 'http://www.gimp.org/';
+
+		Left := Integer(WizardForm.InstallingPage.ClientWidth / 2 - Width / 2);
+	end;
+
+	lblMessage2 := TLabel.Create(WizardForm.InstallingPage);
+	with lblMessage2 do
+	begin
+		Parent := WizardForm.InstallingPage;
+
+		Alignment := taCenter;
+		WordWrap := True;
+		AutoSize := False;
+		Width := WizardForm.InstallingPage.ClientWidth;
+		Height := MeasureLabel(CustomMessage('Billboard2'));
+
+		Caption := CustomMessage('Billboard2');
+	end;
+
+	lblMessage1.Top := Integer(WizardForm.StatusLabel.Top / 2 -
+	                           (lblMessage1.Height + ScaleY(4) + lblURL.Height + ScaleY(4) + lblMessage2.Height) / 2);
+	lblURL.Top := lblMessage1.Top + lblMessage1.Height + ScaleY(4);
+	lblMessage2.Top := lblURL.Top + lblURL.Height + ScaleY(4);
+
+end;
+
+
+procedure ComponentsListOnClick(pSender: TObject);
+var i,j: Integer;
+	Components: TArrayOfString;
+	ComponentDesc: String;
+begin
+	DebugMsg('ComponentsListOnClick','');
+
+	Components := ['Gimp','Deps','GtkWimp','Translations','Python','Ghostscript','Gimp32','Compat'];
+	ComponentDesc := '';
+	
+	for i := 0 to TNewCheckListBox(pSender).Items.Count - 1 do
+		if TNewCheckListBox(pSender).Selected[i] then
+		begin
+			for j := 0 to Length(Components) - 1 do
+			begin
+				if TNewCheckListBox(pSender).Items.Strings[i] = CustomMessage('Components' + Components[j]) then
+					ComponentDesc := CustomMessage('Components' + Components[j] + 'Description');
+			end;
+
+			if ComponentDesc <> '' then
+				break;
+		end;
+
+	lblComponentDescription.Caption := ComponentDesc;
+
+end;
+
+
+function CopyW(const S: String; const Start, Len: Integer): String; //work-around for unicode-related bug in Copy
+begin
+	Result := Copy(S, Start, Len);
+end;
+
+function ParseReadyMemoText(pSpaces,pText: String): String;
+var sTemp: String;
+	i: Integer;
+	c: SmallInt;
+begin
+
+	sTemp := CopyW(pText,Pos(#10,pText)+1,Length(pText));
+	sTemp := Replace('{','\{',sTemp);
+	sTemp := Replace('\','\\',sTemp);
+	sTemp := Replace(#13#10,RTFpara,sTemp);
+	sTemp := Replace(pSpaces,'',sTemp);
+	sTemp := '\b ' + CopyW(pText,1,Pos(#13,pText)-1) + '\par\sb0' +
+						'\li284\b0 ' + sTemp + '\par \pard';
+
+	Result := '';
+	for i := 1 to Length(sTemp) do //convert to RTF-compatible unicode
+		if Ord(sTemp[i]) <= 127 then
+		begin
+			Result := Result + sTemp[i];
+		end else
+		begin
+			c := Ord(sTemp[i]); //code points above 7FFF must be expressed as negative numbers
+			Result := Result + '\u' + IntToStr(c) + '?';
+		end;
+end;
+
+
+function UpdateReadyMemo(pSpace, pNewLine, pMemoUserInfo, pMemoDirInfo, pMemoTypeInfo, pMemoComponentsInfo, pMemoGroupInfo, pMemoTasksInfo: String): String;
+var sText: String;
+	bShowAssoc: Boolean;
+	i,j: Integer;
+begin
+	DebugMsg('UpdateReadyMemo','');
+	(* Prepare the text for new Ready Memo *)
+	
+	sText := RTFHeader;
+	sText := sText + ParseReadyMemoText(pSpace,pMemoDirInfo);
+	sText := sText + '\sb100' + ParseReadyMemoText(pSpace,pMemoTypeInfo);
+	sText := sText + '\sb100' + ParseReadyMemoText(pSpace,pMemoComponentsInfo);
+
+	for i := 0 to GetArrayLength(Associations.Association) - 1 do
+		if Associations.Association[i].Selected then
+			bShowAssoc := True;
+
+	if bShowAssoc then
+	begin
+		sText := sText + '\sb100\b '+CustomMessage('ReadyMemoAssociations')+'\par \sb0\li284\b0 '; //which file types to associate
+
+		for i := 0 to GetArrayLength(Associations.Association) - 1 do							
+			if Associations.Association[i].Selected then
+				for j := 0 to GetArrayLength(Associations.Association[i].Extensions) - 1 do
+					sText := sText + LowerCase(Associations.Association[i].Extensions[j]) + ', ';
+					
+		sText := Copy(sText, 1, Length(sText) - 2) + '\par \pard';
+
+	end;
+	
+	//sText := sText + '\sb100' + ParseReadyMemoText(pSpace,pMemoGroupInfo);
+
+	If pMemoTasksInfo<>'' then
+		sText := sText + '\sb100' + ParseReadyMemoText(pSpace,pMemoTasksInfo);
+		
+	ReadyMemoRichText := Copy(sText,1,Length(sText)-6) + '}';
+
+	Result := 'If you see this, something went wrong';
+end;
+
+
+#if 0 && (Defined(DEVEL) && DEVEL != "")
+procedure chkTesting_onClick(Sender: TObject);
+begin
+	if TCheckBox(Sender).Checked then
+		WizardForm.NextButton.Enabled := True
+	else
+		WizardForm.NextButton.Enabled := False;
+end;
+
+
+procedure WarnTestingVersion();
+var lblTesting: TNewStaticText;
+	chkTesting: TCheckBox;
+begin
+	if not (WizardSilent or (InstallMode = imRebootContinue)) then
+		WizardForm.NextButton.Enabled := False;
+
+	chkTesting := TCheckBox.Create(WizardForm.WelcomePage);
+	with chkTesting do
+	begin
+		Parent := WizardForm.WelcomePage;
+		Caption := CustomMessage('TestingCheckBox');
+
+		Left := WizardForm.WelcomeLabel2.Left;
+		Width := WizardForm.WelcomeLabel2.Width;
+		Height := ScaleY(32);
+		Top := WizardForm.WelcomePage.ClientHeight - Height - ScaleY(8);
+
+		OnClick := @chkTesting_onClick;
+	end;
+
+	lblTesting := TNewStaticText.Create(WizardForm.WelcomePage);
+	with lblTesting do
+	begin
+		Parent := WizardForm.WelcomePage;
+		Left := WizardForm.WelcomeLabel2.Left;
+		Font.Color := $ff; //red
+		AutoSize := True;
+		WordWrap := True;
+		Width := WizardForm.WelcomeLabel2.Width;
+
+		Caption := CustomMessage('TestingWarning');
+		
+		Top := chkTesting.Top - Height - ScaleY(8);
+	end;
+end;
+#endif //(Defined(DEVEL) && DEVEL != "")
+
+
+procedure UpdateWizardImages();
+var NewBitmap1,NewBitmap2: TFileStream;
+begin
+	WelcomeBitmapBottom := TBitmapImage.Create(WizardForm);
+	with WelcomeBitmapBottom do
+	begin 
+		Left := 0;
+		Top := 0;
+		Parent := WizardForm;
+		Width := WizardForm.ClientWidth;
+		Height := WizardForm.ClientHeight;
+		Stretch := True;
+	end;
+
+	DebugMsg('UpdateWizardImages','Height: ' + IntToStr(WizardForm.WizardBitmapImage.Height));
+	
+	if WizardForm.WizardBitmapImage.Height < 386 then //use smaller image when not using Large Fonts
+	begin
+		try
+			NewBitmap1 := TFileStream.Create(ExpandConstant('{tmp}\installsplash_small.bmp'),fmOpenRead);
+			WizardForm.WizardBitmapImage.Bitmap.LoadFromStream(NewBitmap1);
+			WelcomeBitmapBottom.Bitmap := WizardForm.WizardBitmapImage.Bitmap;
+			try
+				NewBitmap2 := TFileStream.Create(ExpandConstant('{tmp}\windows-installer-intro-small.bmp'),fmOpenRead);
+				WizardForm.WizardBitmapImage2.Bitmap.LoadFromStream(NewBitmap2);
+			except
+				DebugMsg('UpdateWizardImages','Error loading image: ' + GetExceptionMessage);
+			finally
+				if NewBitmap2 <> nil then
+					NewBitmap2.Free;
+			end;
+		except
+			DebugMsg('UpdateWizardImages','Error loading image: ' + GetExceptionMessage);
+		finally
+			if NewBitmap1 <> nil then
+				NewBitmap1.Free;
+		end;
+	end
+	else
+	begin
+		try
+			NewBitmap1 := TFileStream.Create(ExpandConstant('{tmp}\installsplash.bmp'),fmOpenRead);
+			WizardForm.WizardBitmapImage.Bitmap.LoadFromStream(NewBitmap1);
+			WelcomeBitmapBottom.Bitmap := WizardForm.WizardBitmapImage.Bitmap;
+		except
+			DebugMsg('UpdateWizardImages','Error loading image: ' + GetExceptionMessage);
+		finally
+			if NewBitmap1 <> nil then
+				NewBitmap1.Free;
+		end;
+	end;
+	WizardForm.WizardBitmapImage.Width := WizardForm.ClientWidth;
+	WizardForm.WizardBitmapImage.Height := WizardForm.ClientHeight;
+end;
+
+
+procedure DoUninstall(const UninstStr, InstallDir: String; const pInfoLabel: TNewStaticText; var oResult: TRemoveOldGIMPResult);
+var InResult: TRemoveOldGIMPResult;
+	ResultCode, i: Integer;
+begin
+	InResult := oResult;
+	InstallDir := '';
+
+	DebugMsg('DoUninstall','Uninstall string: ' + UninstStr);
+
+	//when installing to same directory, assume that restart is required by default ...
+	if LowerCase(RemoveBackslashUnlessRoot(InstallDir)) = LowerCase(RemoveBackslashUnlessRoot(ExpandConstant('{app}'))) then
+		oResult := rogRestartRequired
+	else
+		oResult := rogContinue;
+
+	pInfoLabel.Caption := InstallDir;
+
+	if not Exec('>',UninstStr,'',SW_SHOW,ewWaitUntilTerminated,ResultCode) then
+	begin
+		DebugMsg('DoUninstall','Exec failed: ' + IntToStr(ResultCode));
+		oResult := rogUninstallFailed;
+		exit;
+	end;
+
+	DebugMsg('DoUninstall','Exec succeeded, uninstaller result: ' + IntToStr(ResultCode));
+
+	//... unless the complete installation directory was removed on uninstall
+	i := 0;
+	while i < (UNINSTALL_MAX_WAIT_TIME / UNINSTALL_CHECK_TIME) do
+	begin
+		DebugMsg('DoUninstall','Waiting for ' + ExpandConstant('{app}') + ' to disappear [' + IntToStr(i) + ']');
+		if not DirExists(ExpandConstant('{app}')) then
+		begin
+			DebugMsg('DoUninstall','Existing GIMP directory removed, restoring previous restart requirement');
+			oResult := InResult; //restore previous result
+			break;
+		end;
+		Sleep(UNINSTALL_CHECK_TIME); //it may take a few seconds for the uninstaller to remove the directory after it's exited
+		Inc(i);
+	end;
+end;
+
+
+function RemoveOldGIMPVersions(): TRemoveOldGIMPResult;
+var lblInfo1,lblInfo2: TNewStaticText;
+	RootKey: Integer;
+	OldPath, UninstallString, WhichStr: String;
+begin
+	Result := rogContinue;
+
+	lblInfo1 := TNewStaticText.Create(WizardForm.PreparingPage);
+	with lblInfo1 do
+	begin
+		Parent := WizardForm.PreparingPage;
+		Left := 0;
+		Top := 0;
+		AutoSize := True;
+		WordWrap := True;
+		Width := WizardForm.PreparingPage.ClientWidth;
+
+		Caption := CustomMessage('RemovingOldVersion');
+	end;
+	lblInfo2 := TNewStaticText.Create(WizardForm.PreparingPage);
+	with lblInfo2 do
+	begin
+		Parent := WizardForm.PreparingPage;
+		Left := 0;
+		AutoSize := True;
+		WordWrap := True;
+		Width := WizardForm.PreparingPage.ClientWidth;
+		Top := lblInfo1.Height + ScaleY(8);
+	end;
+
+	if ExpandConstant('{param:debugresume|0}') = '1' then
+		Result := rogRestartRequired; //for testing
+
+	(*if DirExists(ExpandConstant('{app}')) then
+	begin
+		DebugMsg('RemoveOldGIMPVersions',ExpandConstant('{app}') + ' exists, checking if old GIMP version is in it');*)
+
+		if Is64BitInstallMode() then
+			RootKey := HKLM32
+		else
+			RootKey := HKLM;
+
+		if RegValueExists(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1',
+		                  'Inno Setup: App Path') then
+		begin
+			if RegQueryStringValue(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1',
+			                       'Inno Setup: App Path',OldPath) then
+			begin
+				(*if LowerCase(RemoveBackslashUnlessRoot(OldPath)) = LowerCase(RemoveBackslashUnlessRoot(ExpandConstant('{app}'))) then
+				begin //directory contains previous version of GIMP, run it's uninstaller*)
+					DebugMsg('RemoveOldGIMPVersions','Found legacy GIMP install, removing');
+
+					if RegValueExists(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1',
+					                  'QuietUninstallString') then
+						WhichStr := 'QuietUninstallString'
+					else if RegValueExists(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1',
+					                       'UninstallString') then
+						WhichStr := 'UninstallString'
+					else
+					begin
+						Result := rogCantUninstall;
+						exit;
+					end;
+
+					if not RegQueryStringValue(RootKey,'Software\Microsoft\Windows\CurrentVersion\Uninstall\WinGimp-2.0_is1',
+					                           WhichStr,UninstallString) then
+					begin
+						Result := rogCantUninstall;
+						exit;
+					end;
+
+					if WhichStr = 'UninstallString' then
+						UninstallString := UninstallString + ' /SILENT';
+
+					UninstallString := UninstallString + ' /NORESTART';
+
+					DoUninstall(UninstallString, OldPath, lblInfo2, Result);
+					
+				//end;
+			end;
+			
+			
+		end;
+
+	//end;
+
+	lblInfo1.Free;
+	lblInfo2.Free;
+end;
+
+
+procedure InfoBeforeLikeLicense();
+begin
+	WizardForm.InfoBeforeClickLabel.Visible := False;
+	WizardForm.InfoBeforeMemo.Height := WizardForm.InfoBeforeMemo.Height + WizardForm.InfoBeforeMemo.Top - WizardForm.InfoBeforeClickLabel.Top;
+	WizardForm.InfoBeforeMemo.Top := WizardForm.InfoBeforeClickLabel.Top;
+end;
+
+
+procedure PrepareWelcomePage();
+begin
+	if not WizardSilent then
+	begin
+		WizardForm.NextButton.Visible := False;
+
+		btnInstall.Visible := True;
+		btnInstall.TabOrder := 1;
+		btnCustomize.Visible := True;
+
+		WizardForm.Bevel.Visible := False;
+		WizardForm.WelcomeLabel1.Visible := False;
+		WizardForm.WelcomeLabel2.Visible := False;
+
+		WelcomeBitmapBottom.Visible := True;
+	end;
+end;
+
+
+procedure CurPageChanged(pCurPageID: Integer); 
+begin
+	DebugMsg('CurPageChanged','ID: '+IntToStr(pCurPageID));
+	case pCurPageID of
+#if 0 && (Defined(DEVEL) && DEVEL != "")
+		wpWelcome:
+			WarnTestingVersion();
+#endif
+		wpWelcome:
+			PrepareWelcomePage();
+		wpInfoBefore:
+			InfoBeforeLikeLicense();
+		wpSelectComponents:
+			SelectComponentsFaceLift();
+		wpReady:
+			ReadyFaceLift();
+		wpInstalling:
+			InstallingFaceLift();
+	end;
+end;
+
+
+function ShouldSkipPage(pPageID: Integer): Boolean;
+begin
+	DebugMsg('ShouldSkipPage','ID: '+IntToStr(pPageID));
+
+	Result := ((InstallMode = imSimple) or (InstallMode = imRebootContinue)) and (pPageID <> wpFinished);
+	                                                               //skip all pages except for the finished one if using simple
+	                                                               //install mode
+	(*case pPageID of
+	pgSimple.ID:
+		Result := InstallMode <> imNone; //only display the Install/Customize page once
+	end;*)
+
+	if Result then
+		DebugMsg('ShouldSkipPage','Yes')
+	else
+		DebugMsg('ShouldSkipPage','No');
+
+end;
+
+
+procedure CurStepChanged(pCurStep: TSetupStep);
+begin
+	case pCurStep of
+		ssPostInstall:
+		begin
+			Associations_Create();
+			PreparePyGimp();
+			PrepareGimpPath();
+			//PrepareGimpRC();
+		end;
+	end;
+end;
+
+
+function PrepareToInstall(var pNeedsRestart: Boolean): String;
+var	ChecksumBefore, ChecksumAfter: String;
+	RemoveResult: TRemoveOldGIMPResult;
+begin
+
+	ChecksumBefore := MakePendingFileRenameOperationsChecksum;
+
+	RemoveResult := RemoveOldGIMPVersions;
+
+	if RemoveResult = rogRestartRequired then //old version was uninstalled, but something was left behind, so to be safe a reboot
+	begin                                     //is enforced - this can only happen when reusing install directory
+
+		DebugMsg('PrepareToInstall','RemoveOldGIMPVersions requires restart');
+
+		ChecksumAfter := MakePendingFileRenameOperationsChecksum;
+		if (ChecksumBefore <> ChecksumAfter) or (ExpandConstant('{param:debugresume|0}') = '1') then
+		begin //this check is most likely redundant, since the uninstaller will be added to pending rename operations
+			CreateRunOnceEntry;
+			pNeedsRestart := True;
+			Result := CustomMessage('RebootRequiredFirst');
+		end;
+	end else
+	if RemoveResult = rogContinue then
+	begin
+		DebugMsg('PrepareToInstall','RemoveOldGIMPVersions finished successfully');
+		Result := ''; //old version was uninstalled successfully, nothing was left behind, so install can continue immediately
+	end else
+	if RemoveResult = rogUninstallFailed then
+	begin
+		DebugMsg('PrepareToInstall','RemoveOldGIMPVersions failed to uninstall old GIMP version');
+		Result := FmtMessage(CustomMessage('RemovingOldVersionFailed'),['{#VERSION}',ExpandConstant('{app}')]);
+	end else
+	if RemoveResult = rogCantUninstall then
+	begin
+		DebugMsg('PrepareToInstall','RemoveOldGIMPVersions failed to uninstall old GIMP version [1]');
+		Result := FmtMessage(CustomMessage('RemovingOldVersionCantUninstall'),['{#VERSION}',ExpandConstant('{app}')]);
+	end else
+	begin
+		DebugMsg('PrepareToInstall','Internal error 11');
+		Result := FmtMessage(CustomMessage('InternalError'),['11']); //should never happen
+	end;
+
+end;
+
+
+procedure InitializeWizard();
+var r: Integer;
+begin
+	UpdateWizardImages();
+	InitCustomPages();
+
+	r := SHAutoComplete(WizardForm.DirEdit.Handle,SHACF_FILESYSTEM);
+
+	{if InstallMode = imRebootContinue then  //ReadyMemo form isn't skipped if the wizard isn't shown
+	begin
+		DebugMsg('InitializeWizard','Continuing after reboot - showing wizard form');
+		WizardForm.Show;
+	end;}
+end;
+
+
+function InitializeSetup(): Boolean;
+#if (Defined(DEVEL) && DEVEL != "") || Defined(DEVEL_WARNING)
+var Message,Buttons: TArrayOfString;
+#endif
+begin
+	if not IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE) then
+	begin
+		SuppressibleMsgBox(CustomMessage('SSERequired'), mbCriticalError, MB_OK, 0);
+		Result := false;
+		exit;
+	end;
+
+	Result := RestartSetupAfterReboot(); //resume install after reboot - skip all setting pages, and install directly
+
+	if not Result then //no need to do anything else
+		exit;
+
+#if (Defined(DEVEL) && DEVEL != "") || Defined(DEVEL_WARNING)
+	Explode(Message, CustomMessage('DevelopmentWarning'), #13#10);
+	SetArrayLength(Buttons,2);
+	Buttons[0] := CustomMessage('DevelopmentButtonContinue');
+	Buttons[1] := CustomMessage('DevelopmentButtonExit');
+	if (not WizardSilent) and 
+	   (MessageWithURL(Message, CustomMessage('DevelopmentWarningTitle'), Buttons, mbError, 2, 2) = 2) then
+	begin
+		Result := False;
+		Exit;
+	end;
+#endif
+
+	try
+		ExtractTemporaryFile('setup.ini');
+		SetupINI := ExpandConstant('{tmp}\setup.ini');
+		ExtractTemporaryFile('windows-installer-intro-small.bmp');
+		ExtractTemporaryFile('installsplash.bmp');
+		ExtractTemporaryFile('installsplash_small.bmp');
+	except
+		DebugMsg('InitializeSetup','Error extracting temporary file');
+		MsgBox(CustomMessage('ErrorExtractingTemp'),mbError,MB_OK);
+		Result := False;
+		exit;
+	end;
+
+	Associations_Init();
+
+	//if InstallMode <> imRebootContinue then
+	//	SuppressibleMsgBox(CustomMessage('UninstallWarning'),mbError,MB_OK,IDOK);
+
+end;
+
+
+procedure SaveToUninstInf(const pText: AnsiString);
+var sUnInf: String;
+	sOldContent: String;
+begin
+	sUnInf := ExpandConstant('{app}\uninst\uninst.inf');
+
+	if not FileExists(sUnInf) then //save small header
+		SaveStringToUTF8File(sUnInf,#$feff+'#Additional uninstall tasks'#13#10+ //#$feff BOM is required for LoadStringsFromFile
+		                            '#This file uses UTF-8 encoding'#13#10+
+		                            '#'#13#10+
+		                            '#Empty lines and lines beginning with # are ignored'#13#10+
+		                            '#'#13#10+
+		                            '#Add uninstallers for GIMP add-ons that should be removed together with GIMP like this:'#13#10+
+		                            '#Run:<description>/<full path to uninstaller>/<parameters for automatic uninstall>'#13#10+
+		                            '#'#13#10+
+		                            '#The file is parsed in reverse order' + #13#10 +
+		                            '' + #13#10 //needs '' in front, otherwise preprocessor complains
+		                            ,False)
+	else
+	begin
+		LoadStringFromUTF8File(sUnInf,sOldContent);
+		if Pos(#13#10+pText+#13#10,sOldContent) > 0 then //don't write duplicate lines
+			exit;
+	end;
+
+	SaveStringToUTF8File(sUnInf,pText+#13#10,True);
+end;
+
+#include "rebootcontinue.isi"
+
+#include "uninst.isi"
+
+#expr SaveToFile(AddBackslash(SourcePath) + "Preprocessed.iss")
+
diff --git a/build/windows/installer/gpl+python.rtf b/build/windows/installer/gpl+python.rtf
new file mode 100755
index 0000000..8bb5ee7
--- /dev/null
+++ b/build/windows/installer/gpl+python.rtf
@@ -0,0 +1,123 @@
+{\rtf1\ansi\ansicpg1250\deff0\deflang1060\deflangfe1060{\fonttbl{\f0\fswiss\fprq2\fcharset0 Verdana;}{\f1\fmodern\fprq1\fcharset0 Lucida Console;}}
+\viewkind4\uc1\pard\nowidctlpar\sb100\sa100\qc\kerning36\b\f0\fs28 GNU General Public License\par
+\kerning0\b0\fs16 Version 2, June 1991\par
+\pard\nowidctlpar\sb140\f1\fs14 Copyright (C) 1989, 1991 Free Software Foundation, Inc.\par
+\pard\nowidctlpar\sa140 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA\par
+\pard\nowidctlpar Everyone is permitted to copy and distribute verbatim copies\par
+\pard\nowidctlpar\sa140 of this license document, but changing it is not allowed.\par
+\pard\keepn\nowidctlpar\sb100\sa100\qc\b\f0\fs20 Preamble\fs24\par
+\pard\nowidctlpar\fi142\sb100\sa100\qj\b0\fs16 The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.\par
+When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.\par
+To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.\par
+For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.\par
+We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.\par
+Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.\par
+Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.\par
+The precise terms and conditions for copying, distribution and modification follow.\par
+\pard\keepn\nowidctlpar\sb100\sa100\qc\b\fs20 TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\par
+\pard\nowidctlpar\fi142\sb100\sa100\qj\fs16 0.\b0  This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".\par
+\pard\nowidctlpar\sb100\sa100\qj Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.\par
+\pard\nowidctlpar\fi142\sb100\sa100\qj\b 1.\b0  You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.\par
+\pard\nowidctlpar\sb100\sa100\qj You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.\par
+\pard\nowidctlpar\fi142\sb100\sa100\qj\b 2.\b0  You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:\par
+\pard\nowidctlpar\li284\sb100\sa100\qj\b a)\b0  You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.\par
+\b b)\b0  You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.\par
+\b c)\b0  If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)\par
+\pard\nowidctlpar\sb100\sa100\qj These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.\par
+Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.\par
+In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.\par
+\pard\nowidctlpar\fi142\sb100\sa100\qj\b 3.\b0  You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: \v <!-- we use this doubled UL to get the sub-sections indented, --><!-- while making the bullets as unobvious as possible. --\v0\par
+\pard\nowidctlpar\li284\sb100\sa100\qj\b a)\b0  Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,\par
+\b b)\b0  Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,\par
+\b c)\b0  Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)\par
+\pard\nowidctlpar\sb100\sa100\qj The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.\par
+If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.\par
+\pard\nowidctlpar\fi142\sb100\sa100\qj\b 4.\b0  You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.\par
+\b 5.\b0  You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.\par
+\b 6.\b0  Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.\par
+\b 7.\b0  If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.\par
+\pard\nowidctlpar\sb100\sa100\qj If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.\par
+It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.\par
+This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.\par
+\pard\nowidctlpar\fi142\sb100\sa100\qj\b 8.\b0  If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.\par
+\b 9.\b0  The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.\par
+\pard\nowidctlpar\sb100\sa100\qj Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.\par
+\pard\nowidctlpar\fi142\sb100\sa100\qj\b 10.\b0  If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.\par
+\pard\nowidctlpar\sb100\sa100\qc\fs20 NO WARRANTY\par
+\pard\nowidctlpar\fi142\sb100\sa100\qj\b\fs16 11.\b0  BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.\par
+\b 12.\b0  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.\par
+\pard\keepn\nowidctlpar\sb100\sa100\qc\b END OF TERMS AND CONDITIONS\par
+\fs20 How to Apply These Terms to Your New Programs\par
+\pard\nowidctlpar\fi142\sb100\sa100\qj\b0\fs16 If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.\par
+\pard\nowidctlpar\fi142\sb100\sa240\qj To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.\f1\fs14\par
+\pard\nowidctlpar\li284\i one line to give the program's name and an idea of what it does.\i0\par
+\pard\nowidctlpar\li284\sa140 Copyright (C) \i yyyy\i0   \i name of author\i0\par
+\pard\nowidctlpar\li284 This program is free software; you can redistribute it and/or\par
+modify it under the terms of the GNU General Public License\par
+as published by the Free Software Foundation; either version 2\par
+\pard\nowidctlpar\li284\sa140 of the License, or (at your option) any later version.\par
+\pard\nowidctlpar\li284 This program is distributed in the hope that it will be useful,\par
+but WITHOUT ANY WARRANTY; without even the implied warranty of\par
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\par
+\pard\nowidctlpar\li284\sa140 GNU General Public License for more details.\par
+\pard\nowidctlpar\li284 You should have received a copy of the GNU General Public License\par
+along with this program; if not, write to the Free Software\par
+\pard\nowidctlpar\li284\sa140 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\par
+\pard\nowidctlpar\sb100\sa100\qj\f0\fs16 Also add information on how to contact you by electronic and paper mail.\par
+If the program is interactive, make it output a short notice like this when it starts in an interactive mode:\par
+\pard\nowidctlpar\li284\sb140\f1\fs14 Gnomovision version 69, Copyright (C) \i year\i0  \i name of author\i0\par
+\pard\nowidctlpar\li284 Gnomovision comes with ABSOLUTELY NO WARRANTY; for details\par
+type `show w'.  This is free software, and you are welcome\par
+to redistribute it under certain conditions; type `show c'\par
+\pard\nowidctlpar\li284\sa140 for details.\par
+\pard\nowidctlpar\sb100\sa100\qj\f0\fs16 The hypothetical commands \f1\fs14 `show w'\f0\fs16  and \f1\fs14 `show c'\f0\fs16  should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than \f1\fs14 `show w'\f0\fs16  and \f1\fs14 `show c'\f0\fs16 ; they could even be mouse-clicks or menu items--whatever suits your program.\par
+You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:\par
+\pard\nowidctlpar\li284\sb140\f1\fs14 Yoyodyne, Inc., hereby disclaims all copyright\par
+\pard\nowidctlpar\li284 interest in the program `Gnomovision'\par
+(which makes passes at compilers) written\par
+\pard\nowidctlpar\li284\sa140 by James Hacker.\par
+\pard\nowidctlpar\li284\i signature of Ty Coon\i0 , 1 April 1989\par
+\pard\nowidctlpar\li284\sa140 Ty Coon, President of Vice\par
+\pard\nowidctlpar\sb100\sa240\qj\f0\fs16 This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.\par
+\pard\nowidctlpar\qj\f1\fs12 PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2\par
+\pard\nowidctlpar\sa120\qj --------------------------------------------\par
+\pard\nowidctlpar\qj 1. This LICENSE AGREEMENT is between the Python Software Foundation\par
+("PSF"), and the Individual or Organization ("Licensee") accessing and\par
+otherwise using this software ("Python") in source or binary form and\par
+\pard\nowidctlpar\sa120\qj its associated documentation.\par
+\pard\nowidctlpar\qj 2. Subject to the terms and conditions of this License Agreement, PSF\par
+hereby grants Licensee a nonexclusive, royalty-free, world-wide\par
+license to reproduce, analyze, test, perform and/or display publicly,\par
+prepare derivative works, distribute, and otherwise use Python\par
+alone or in any derivative version, provided, however, that PSF's\par
+License Agreement and PSF's notice of copyright, i.e., "Copyright (c)\par
+2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation; All Rights\par
+Reserved" are retained in Python alone or in any derivative version \par
+\pard\nowidctlpar\sa120\qj prepared by Licensee.\par
+\pard\nowidctlpar\qj 3. In the event Licensee prepares a derivative work that is based on\par
+or incorporates Python or any part thereof, and wants to make\par
+the derivative work available to others as provided herein, then\par
+Licensee hereby agrees to include in any such work a brief summary of\par
+\pard\nowidctlpar\sa120\qj the changes made to Python.\par
+\pard\nowidctlpar\qj 4. PSF is making Python available to Licensee on an "AS IS"\par
+basis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR\par
+IMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND\par
+DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS\par
+FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT\par
+\pard\nowidctlpar\sa120\qj INFRINGE ANY THIRD PARTY RIGHTS.\par
+\pard\nowidctlpar\qj 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON\par
+FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS\par
+A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,\par
+\pard\nowidctlpar\sa120\qj OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\par
+\pard\nowidctlpar\qj 6. This License Agreement will automatically terminate upon a material\par
+\pard\nowidctlpar\sa120\qj breach of its terms and conditions.\par
+\pard\nowidctlpar\qj 7. Nothing in this License Agreement shall be deemed to create any\par
+relationship of agency, partnership, or joint venture between PSF and\par
+Licensee.  This License Agreement does not grant permission to use PSF\par
+trademarks or trade name in a trademark sense to endorse or promote\par
+\pard\nowidctlpar\sa120\qj products or services of Licensee, or any third party.\par
+\pard\nowidctlpar\qj 8. By copying, installing or otherwise using Python, Licensee\par
+agrees to be bound by the terms and conditions of this License\par
+Agreement.\fs15\par
+}
+
\ No newline at end of file
diff --git a/build/windows/installer/installsplash.bmp b/build/windows/installer/installsplash.bmp
new file mode 100755
index 0000000..0c061e6
Binary files /dev/null and b/build/windows/installer/installsplash.bmp differ
diff --git a/build/windows/installer/installsplash_small.bmp b/build/windows/installer/installsplash_small.bmp
new file mode 100755
index 0000000..c327951
Binary files /dev/null and b/build/windows/installer/installsplash_small.bmp differ
diff --git a/build/windows/installer/rebootcontinue.isi b/build/windows/installer/rebootcontinue.isi
new file mode 100755
index 0000000..bafb581
--- /dev/null
+++ b/build/windows/installer/rebootcontinue.isi
@@ -0,0 +1,128 @@
+#if 0
+[Code]
+#endif
+
+function Quote(const S: String): String;
+begin
+	Result := '"' + S + '"';
+end;
+
+
+function AddParam(const S, P, V: String): String;
+begin
+	if V <> '""' then
+		Result := S + ' /' + P + '=' + V;
+end;
+
+
+function AddSimpleParam(const S, P: String): String;
+begin
+	Result := S + ' /' + P;
+end;
+
+
+procedure CreateRunOnceEntry;
+var	RunOnceData, SetupRestartData: String;
+	i: Integer;
+begin
+	DebugMsg('CreateRunOnceEntry','Preparing for restart');
+
+	//RunOnce command-line is limited to 256 characters, so keep it to the bare minimum required to start setup
+	RunOnceData := Quote(ExpandConstant('{srcexe}')) + ' /resumeinstall=1';
+	RunOnceData := AddParam(RunOnceData, 'LANG', ExpandConstant('{language}'));
+
+	SetupRestartData := Quote(ExpandConstant('{srcexe}')) + ' /resumeinstall=2';
+	SetupRestartData := AddParam(SetupRestartData, 'LANG', ExpandConstant('{language}'));
+	SetupRestartData := AddParam(SetupRestartData, 'DIR', Quote(WizardDirValue));
+	//SetupRestartData := AddParam(SetupRestartData, 'GROUP', Quote(WizardGroupValue));
+	//if WizardNoIcons then
+	//	SetupRestartData := AddSimpleParam(SetupRestartData, 'NOICONS');
+	SetupRestartData := AddParam(SetupRestartData, 'TYPE', Quote(WizardSetupType(False)));
+	SetupRestartData := AddParam(SetupRestartData, 'COMPONENTS', Quote(WizardSelectedComponents(False)));
+	SetupRestartData := AddParam(SetupRestartData, 'TASKS', Quote(WizardSelectedTasks(False)));
+	SetupRestartData := AddParam(SetupRestartData, 'ASSOC', Quote(Associations_GetSelected()));
+
+	if ExpandConstant('{param:log|*}') <> '*' then
+	begin
+		SetupRestartData := AddParam(SetupRestartData, 'LOG', Quote(ExpandConstant('{param:log|*}')));
+	end else
+	begin
+		for i := 0 to ParamCount() do
+			if LowerCase(ParamStr(i)) = '/log' then
+			begin
+				RunOnceData := AddSimpleParam(RunOnceData,'LOG'); //multiple logs are created in %TEMP% when no filename is given
+				SetupRestartData := AddSimpleParam(SetupRestartData,'LOG');
+				break;
+			end;
+	end;
+
+	DebugMsg('CreateRunOnceEntry','RunOnce: ' + RunOnceData);
+	RegWriteStringValue(HKLM, 'Software\Microsoft\Windows\CurrentVersion\RunOnce', RunOnceName, RunOnceData);
+
+	DebugMsg('CreateRunOnceEntry','RunOnce: ' + SetupRestartData);
+	RegWriteStringValue(HKLM, 'Software\' + RunOnceName, '', SetupRestartData);
+end;
+
+
+procedure RestartMyself();
+var CmdLine: String;
+	ResultCode: Integer;
+begin
+	DebugMsg('RestartMyself','Continuing install after reboot (reexecuting setup)');
+
+	if RegValueExists(HKLM, 'Software\' + RunOnceName, '') then
+	begin
+		if RegQueryStringValue(HKLM, 'Software\' + RunOnceName, '', CmdLine) then
+		begin
+			RegDeleteKeyIncludingSubkeys(HKLM, 'Software\' + RunOnceName); //clean up
+			if not Exec('>',CmdLine,'',SW_SHOW,ewNoWait,ResultCode) then //bonus: don't block shell from loading, since RunOnce installer exits immediately
+				MsgBox(FmtMessage(CustomMessage('ErrorRestartingSetup'),[IntToStr(ResultCode)]), mbError, mb_Ok);
+		
+			DebugMsg('RestartMyself','Result of running ' + CmdLine + ': ' + IntToStr(ResultCode));
+
+		end else
+		begin
+			MsgBox(FmtMessage(CustomMessage('ErrorRestartingSetup'),['-2']), mbError, mb_Ok);
+			DebugMsg('RestartMyself','Error reading HKLM\'+RunOnceName);
+		end;
+	end else
+	begin
+		MsgBox(FmtMessage(CustomMessage('ErrorRestartingSetup'),['-1']), mbError, mb_Ok);
+		DebugMsg('RestartMyself','HKLM\'+RunOnceName + ' not found in Registy');
+	end;
+end;
+
+
+function RestartSetupAfterReboot(): Boolean;
+begin
+
+	if ExpandConstant('{param:resumeinstall|0}') = '1' then //called from RunOnce
+	begin
+		Result := False; //setup will just re-execute itself in this run
+
+		RestartMyself();
+
+		DebugMsg('RestartSetupAfterReboot','Phase 1 complete, exiting');
+		exit;
+
+	end else
+	if ExpandConstant('{param:resumeinstall|0}') = '2' then //setup re-executed itself
+	begin
+
+		Result := True;
+		InstallMode := imRebootContinue;
+		DebugMsg('RestartSetupAfterReboot','Continuing install after reboot');
+
+	end else
+	begin
+		Result := True; //normal install
+	end;
+
+	if InstallMode <> imRebootContinue then
+		if RegValueExists(HKLM, 'Software\Microsoft\Windows\CurrentVersion\RunOnce', RunOnceName) then
+		begin
+			DebugMsg('RestartSetupAfterReboot','System must be restarted first');
+			MsgBox(CustomMessage('RebootRequiredFirst'), mbError, mb_Ok);
+			Result := False;
+		end;
+end;
diff --git a/build/windows/installer/setup.ini b/build/windows/installer/setup.ini
new file mode 100755
index 0000000..389bd4b
--- /dev/null
+++ b/build/windows/installer/setup.ini
@@ -0,0 +1,29 @@
+[File Associations]
+1=GIMP image:XCF
+2=Adobe Photoshop(tm) image:PSD
+3=Alias|Wavefront PowerAnimator:matte:mask:alpha:als:PIX
+4=Compuserve GIF:GIF
+5=Corel PaintShopPro image:PSP:PSPIMAGE:TUB
+6=Digital Imaging and Communications in Medicine:DICOM:DCM
+7=Fax G3 Image file:g3
+8=Flexible Image Transport System:fit:fits
+9=GIMP brush pipe:gih
+10=GIMP brush:gbr:gpb
+11=GIMP pattern:pat
+12=JPEG image:JPEG:JPG
+13=KISS CEL:CEL
+14=Netpbm format:pnm:ppm:pgm:pbm
+15=Portable Network Graphics:PNG
+16=PostScript, Encapsulated PostScript:PS:EPS
+17=Scalable Vector Graphics:svg
+18=SGI image format:SGI:RGB:BW:ICON
+19=SUN Raster Image:ras:im1:im8:im24:im32:rs
+20=Tagged Image File:tif:tiff
+21=TrueVision Targa:tga
+22=Windows and OS/2 Bitmaps:BMP
+23=Windows Icon:ICO
+24=Windows Metafile:wmf
+25=X10 and X11 Bitmap:xbm:icon:bitmap
+26=X Pixmap:xpm
+27=X Window Dump:xwd
+28=ZSoft Paintbrush image:PCX
diff --git a/build/windows/installer/sl.setup.isl b/build/windows/installer/sl.setup.isl
new file mode 100755
index 0000000..92eec74
--- /dev/null
+++ b/build/windows/installer/sl.setup.isl
@@ -0,0 +1,100 @@
+[Messages]
+WizardInfoBefore=Licenè pogodba
+AboutSetupNote=Namestitveni program je pripravil Jernej Simonè, jernej-gimp ena si%n%nSlika na prvi strani namestitvenega programa: Alexia_Death%nSlika na zadnji strani namestitvenega programa: Jakub Steiner
+WinVersionTooLowError=Ta razlièa programa GIMP potrebuje Windows XP s servisnim paketom 2, ali novejšo razlièo programa Windows.
+
+[CustomMessages]
+DevelopmentWarningTitle=Razvojna razlièa
+;DevelopmentWarning=To je razvojna razlièa programa GIMP, zaradi èar nekateri deli programa morda niso dokonèi, poleg tega pa je program lahko tudi nestabilen. V primeru težav preverite, da le-te niso bile že odpravljene v GIT-u, preden stopite v stik z razvijalci.%nZaradi nestabilnosti ta razlièa ni namenjena za vsakodnevno delo, saj lahko kadarkoli izgubite svoje delo. Ali želite vseeno nadaljevati z namestitvijo?
+DevelopmentWarning=To je razvojna razlièa namestitvenega programa za GIMP, ki še ni tako preizkušena kot obièna razlièa. È naletite na kakršne koli težave pri namestitvi, jih prosim sporoèe v Bugzilli (komponenta Installer):%n_https://bugzilla.gnome.org/enter_bug.cgi?product=GIMP%n%nV tem namestitvenem programu je nekaj znanih napak:%n- odpiranje TIFF datotek ne deluje%n- prikazane velikosti datotek so napaè%nProsimo, da teh napak ne sporoèe.%n%nAli želite vseeno nadaljevati z namestitvijo?
+DevelopmentButtonContinue=&Nadaljuj
+DevelopmentButtonExit=Prekini
+
+;XPSP3Recommended=Opozorilo: uporabljate nepodprto razlièo sistema Windows. Prosimo, namestite servisni paket 3 za Windows XP ali novejšo razlièo sistema Windows preden nas obvešèe o kakršnih koli težavah.
+SSERequired=Ta razliŸica programa GIMP potrebuje procesor, ki ima podporo za SSE ukaze.
+
+InstallOrCustomize=GIMP je pripravljen na namestitev. Kliknite gumb Namesti za namestitev s privzetimi nastavitvami, ali pa kliknite gumb Po meri, èbi radi imeli veèadzora nad možnostmi namestitve.
+Install=Namest&i
+Customize=&Po meri
+
+TypeCompact=Minimalna namestitev
+TypeCustom=Namestitev po meri
+TypeFull=Polna namestitev
+
+;components
+ComponentsDescription=Opis
+ComponentsGimp=GIMP
+ComponentsGimpDescription=GIMP z vsemi privzetimi vtièki
+ComponentsDeps=Podporne knjižnice
+ComponentsDepsDescription=Podporne knjižnice za GIMP, vkljuè z okoljem GTK+
+ComponentsGtkWimp=Tema MS-Windows za GTK+
+ComponentsGtkWimpDescription=Windows izgled za GIMP
+ComponentsCompat=Podpora za stare vtièke
+ComponentsCompatDescription=Podporne knjižnice za stare zunanje vtièke za GIMP
+ComponentsTranslations=Prevodi
+ComponentsTranslationsDescription=Prevodi
+ComponentsPython=Podpora za Python
+ComponentsPythonDescription=Omogoèizvajanje vtièkov za GIMP, napisanih v programskem jeziku Python
+ComponentsGhostscript=Podpora za PostScript
+ComponentsGhostscriptDescription=Omogoènalaganje PostScript datotek
+ComponentsGimp32=Podpora za 32-bitne vtièke
+ComponentsGimp32Description=Omogoèuporabo 32-bitnih vtièkov.%nPotrebno za uporabo podpore za Python
+
+AdditionalIcons=Dodatne ikone:
+AdditionalIconsDesktop=Ustvari ikono na n&amizju
+AdditionalIconsQuickLaunch=Ustvari ikono v vrstici &hitri zagon
+
+RemoveOldGIMP=Odstrani prejço razliŸico programa GIMP
+
+;%1 is replaced by file name; these messages should never appear (unless user runs out of disk space at the exact right moment)
+ErrorChangingEnviron=Prišlo je do težav pri posodabljanju okolja za GIMP v datoteki %1. È se pri nalaganju vtièkov pojavijo sporoèa o napakah, poizkusite odstraniti in ponovno namestiti GIMP.
+ErrorExtractingTemp=Prišlo je do napake pri razširjanju zaènih datotek.
+ErrorUpdatingPython=Prišlo je do napake pri nastavljanju podpore za Python.
+ErrorReadingGimpRC=Prišlo je do napake pri branju datoteke %1.
+ErrorUpdatingGimpRC=Prišlo je do napake pri pisanju nastavitev v datoteko %1.
+
+;displayed in Explorer's right-click menu
+OpenWithGimp=Uredi z GIMP-om
+
+SelectAssociationsCaption=Povezovanje vrst datotek
+SelectAssociationsExtensions=Pripone:
+SelectAssociationsInfo1=Izberite vste datotek, ki bi jih radi odpirali z GIMP-om
+SelectAssociationsInfo2=Tu lahko izberete vrste datotek, ki se bodo odprle v GIMP-u, ko jih dvokliknete v Raziskovalcu
+SelectAssociationsSelectAll=Izber&i vse
+SelectAssociationsUnselectAll=Poèt&i izbor
+SelectAssociationsSelectUnused=Ne&uporabljene
+
+ReadyMemoAssociations=Vrste datotek, ki jih bo odpiral GIMP:
+
+RemovingOldVersion=Odstranjevanje starejših razliè programa GIMP:
+;%1 = version, %2 = installation directory
+;ran uninstaller, but it returned an error, or didn't remove everything
+RemovingOldVersionFailed=Te razlièe programa GIMP ne morete namestiti preko prejšnje razlièe, namestitvenemu programu pa prejšnje razlièe ni uspelo samodejno odstraniti.%n%nPred ponovnim namešèjem te razlièe programa GIMP v mapo %2, odstranite prejšnjo razlièo, ali pa izberite namestitev po meri, in GIMP %1 namestite v drugo mapo.%n%nNamestitveni program se bo zdaj konè.
+;couldn't find an uninstaller, or found several uninstallers
+RemovingOldVersionCantUninstall=Te razlièe programa GIMP ne morete namestiti preko prejšnje razlièe, namestitvenemu programu pa ni uspelo ugotoviti, kako prejšnjo razlièo odstraniti samodejno.%n%nPred ponovnim namešèjem te razlièe programa GIMP v mapo %2, odstranite prejšnjo razlièo, ali pa izberite namestitev po meri, in GIMP %1 namestite v drugo mapo.%n%nNamestitveni program se bo zdaj konè.
+
+RebootRequiredFirst=Prejšnja razlièa programa GIMP je bila uspešno odstranjena, vendar je pred nadaljevanjem namestitve potrebno znova zagnati Windows.%n%nNamestitveni program bo dokonè namestitev po ponovnem zagonu, ko se prvièrijavi administrator.
+
+;displayed while the files are being extracted
+Billboard1=GIMP spada med prosto programje.%n%nObišèe
+;www.gimp.org (displayed between Billboard1 and Billboard2)
+Billboard2=za brezplaè posodobitve.
+
+;displayed if restart settings couldn't be read, or if the setup couldn't re-run itself
+ErrorRestartingSetup=Prišlo je do napake pri ponovnem zagonu namestitvenega programa. (%1)
+
+SettingUpAssociations=Nastavljam povezane vrste datotek...
+SettingUpPyGimp=Pripravljam okolje za GIMP Python...
+SettingUpEnvironment=Pripravljam okolje za GIMP...
+SettingUpGimpRC=Pripravljam nastavitve za 32-bitne vtièke...
+
+;displayed on last page
+LaunchGimp=Zaženi GIMP
+
+;shown during uninstall when removing add-ons
+UninstallingAddOnCaption=Odstranjujem dodatek
+
+InternalError=Notranja napaka (%1).
+
+;used by installer for add-ons (currently only help)
+DirNotGimp=GIMP oèno ni namešè v izbrani mapi. Želite kljub temu nadaljevati?
diff --git a/build/windows/installer/uninst.isi b/build/windows/installer/uninst.isi
new file mode 100755
index 0000000..4b2fc88
--- /dev/null
+++ b/build/windows/installer/uninst.isi
@@ -0,0 +1,269 @@
+#if 0
+[Code]
+#endif
+
+function SplitRegParams(const pInf: String; var oRootKey: Integer; var oKey,oValue: String): Boolean;
+var	sRootKey: String;
+	d: Integer;
+begin
+	Result := False;
+
+	d := Pos('/',pInf);
+	if d = 0 then
+	begin
+		DebugMsg('SplitRegParams','Error: malformed line (no /)');
+		exit;
+	end;
+
+	sRootKey := Copy(pInf,1,d - 1);
+	oKey := Copy(pInf,d + 1,Length(pInf));
+
+	if oValue <> 'nil' then
+	begin
+		d := RevPos('\',oKey);
+		if d = 0 then
+		begin
+			DebugMsg('SplitRegParams','Error: malformed line (no \)');
+			exit;
+		end;
+
+		oValue := Decode(Copy(oKey,d+1,Length(oKey)));
+		oKey := Copy(oKey,1,d-1);
+	end;
+
+	DebugMsg('SplitRegParams','Root: '+sRootKey+', Key:'+oKey + ', Value:'+oValue);
+
+	case sRootKey of
+	'HKCR': oRootKey := HKCR;
+	'HKLM': oRootKey := HKLM;
+	'HKU': oRootKey := HKU;
+	'HKCU': oRootKey := HKCU;
+	else
+		begin
+			DebugMsg('SplitRegParams','Unrecognised root key: ' + sRootKey);
+			exit;
+		end;
+	end;
+
+	Result := True;
+end;
+
+
+procedure UninstInfRegKey(const pInf: String; const pIfEmpty: Boolean);
+var	sKey,sVal: String;
+	iRootKey: Integer;
+begin
+	sVal := 'nil';
+	if not SplitRegParams(pInf,iRootKey,sKey,sVal) then
+		exit;
+
+	if pIfEmpty then
+	begin
+		if not RegDeleteKeyIfEmpty(iRootKey,sKey) then
+			DebugMsg('UninstInfRegKey','RegDeleteKeyIfEmpty failed');
+	end
+	else
+	begin
+		if not RegDeleteKeyIncludingSubkeys(iRootKey,sKey) then
+			DebugMsg('UninstInfRegKey','RegDeleteKeyIncludingSubkeys failed');
+	end;
+end;
+
+
+procedure UninstInfRegVal(const pInf: String);
+var	sKey,sVal: String;
+	iRootKey: Integer;
+begin
+	if not SplitRegParams(pInf,iRootKey,sKey,sVal) then
+		exit;
+
+	if not RegDeleteValue(iRootKey,sKey,sVal) then
+		DebugMsg('UninstInfREG','RegDeleteKeyIncludingSubkeys failed');
+end;
+
+
+procedure UninstInfFile(const pFile: String);
+begin
+	DebugMsg('UninstInfFile','File: '+pFile);
+
+	if not DeleteFile(pFile) then
+		DebugMsg('UninstInfFile','DeleteFile failed');
+end;
+
+
+procedure UninstInfDir(const pDir: String);
+begin
+	DebugMsg('UninstInfDir','Dir: '+pDir);
+
+	if not RemoveDir(pDir) then
+		DebugMsg('UninstInfDir','RemoveDir failed');
+end;
+
+
+procedure CreateMessageForm(var frmMessage: TForm; const pMessage: String);
+var lblMessage: TNewStaticText;
+begin
+	frmMessage := CreateCustomForm();
+	with frmMessage do
+	begin
+		BorderStyle := bsDialog;
+
+		ClientWidth := ScaleX(300);
+		ClientHeight := ScaleY(48);
+
+		Caption := CustomMessage('UninstallingAddOnCaption');
+
+		Position := poScreenCenter;
+
+		BorderIcons := [];
+	end;
+
+	lblMessage := TNewStaticText.Create(frmMessage);
+	with lblMessage do
+	begin
+		Parent := frmMessage;
+		AutoSize := True;
+		Caption := pMessage;
+		Top := (frmMessage.ClientHeight - Height) div 2;
+		Left := (frmMessage.ClientWidth - Width) div 2;
+		Visible := True;
+	end;
+	
+	frmMessage.Show();
+
+    frmMessage.Refresh();
+end;
+
+
+procedure UninstInfRun(const pInf: String);
+var Description,Prog,Params: String;
+	Split, ResultCode, Ctr: Integer;
+	frmMessage: TForm;	
+begin
+	DebugMsg('UninstInfRun',pInf);
+
+	Split := Pos('/',pInf);
+	if Split <> 0 then
+	begin
+		Description := Copy(pInf, 1, Split - 1);
+		Prog := Copy(pInf, Split + 1, Length(pInf));
+	end else
+	begin
+		Prog := pInf;
+		Description := '';
+	end;
+
+	Split := Pos('/',Prog);
+	if Split <> 0 then
+	begin
+		Params := Copy(Prog, Split + 1, Length(Prog));
+		Prog := Copy(Prog, 1, Split - 1);
+	end else
+	begin
+		Params := '';
+	end;
+
+	if not UninstallSilent then //can't manipulate uninstaller messages, so create a form instead
+		CreateMessageForm(frmMessage,Description);
+
+	DebugMsg('UninstInfRun','Running: ' + Prog + '; Params: ' + Params);
+
+	if Exec(Prog,Params,'',SW_SHOW,ewWaitUntilTerminated,ResultCode) then
+	begin
+		DebugMsg('UninstInfRun','Exec result: ' + IntToStr(ResultCode));
+		
+		Ctr := 0;
+		while FileExists(Prog) do //wait a few seconds for the uninstaller to be deleted - since this is done by a program
+		begin                     //running from a temporary directory, the uninstaller we ran above will exit some time before
+			Sleep(UNINSTALL_CHECK_TIME);           //it's removed from disk
+			Inc(Ctr);
+			if Ctr = (UNINSTALL_MAX_WAIT_TIME/UNINSTALL_CHECK_TIME) then //don't wait more than 5 seconds
+				break;
+		end;
+
+	end else
+		DebugMsg('UninstInfRun','Exec failed: ' + IntToStr(ResultCode) + ' (' + SysErrorMessage(ResultCode) + ')');
+
+	if not UninstallSilent then
+		frmMessage.Free();
+end;
+
+(*
+uninst.inf documentation:
+
+- Delete Registry keys (with all subkeys):
+  RegKey:<RootKey>/<SubKey>
+    RootKey = HKCR, HKLM, HKCU, HKU
+    SubKey = subkey to delete (warning: this will delete all keys under subkey, so be very careful with it)
+
+- Delete empty registry keys:
+  RegKeyEmpty:<RootKey>/<SubKey>
+    RootKey = HKCR, HKLM, HKCU, HKU
+    SubKey = subkey to delete if empty
+
+- Delete values from registry:
+  RegVal:<RootKey>/<SubKey>/Value
+    RootKey = HKCR, HKLM, HKCU, HKU
+    SubKey = subkey to delete Value from
+    Value = value to delete; \ and % must be escaped as %5c and %25
+
+- Delete files:
+  File:<Path>
+    Path = full path to file
+
+- Delete empty directories:
+  Dir:<Path>
+
+- Run program with parameters:
+  Run:<description>/<path>/<params>
+
+Directives are parsed from the end of the file backwards as the first step of uninstall.
+
+*)
+procedure ParseUninstInf();
+var i,d: Integer;
+	sWhat: String;
+begin
+	for i := GetArrayLength(asUninstInf) - 1 downto 0 do
+	begin
+
+		DebugMsg('ParseUninstInf',asUninstInf[i]);
+
+		if (Length(asUninstInf[i]) = 0) or (asUninstInf[i][1] = '#') then //skip comments and empty lines
+			continue;
+
+		d := Pos(':',asUninstInf[i]);
+		if d = 0 then
+		begin
+			DebugMsg('ParseUninstInf','Malformed line: ' + asUninstInf[i]);
+			continue;
+		end;
+
+		sWhat := Copy(asUninstInf[i],d+1,Length(asUninstInf[i]));
+
+		case Copy(asUninstInf[i],1,d) of
+		'RegKey:': UninstInfRegKey(sWhat,False);
+		'RegKeyEmpty:': UninstInfRegKey(sWhat,True);
+		'RegVal:': UninstInfRegVal(sWhat);
+		'File:': UninstInfFile(sWhat);
+		'Dir:': UninstInfDir(sWhat);
+		'Run:': UninstInfRun(sWhat);
+		end;
+
+	end;
+
+end;
+
+procedure CurUninstallStepChanged(CurStep: TUninstallStep);
+begin
+	DebugMsg('CurUninstallStepChanged','');
+	case CurStep of
+	usUninstall:
+	begin
+		LoadStringsFromFile(ExpandConstant('{app}\uninst\uninst.inf'),asUninstInf);
+		ParseUninstInf();
+	end;
+	//usPostUninstall:
+	end;
+end;
+
diff --git a/build/windows/installer/utils.isi b/build/windows/installer/utils.isi
new file mode 100755
index 0000000..f820200
--- /dev/null
+++ b/build/windows/installer/utils.isi
@@ -0,0 +1,139 @@
+#if 0
+[Code]
+#endif
+
+procedure DebugMsg(Const pProc,pMsg: String);
+begin
+	Log('[Code] ' + pProc + #9 + pMsg);
+end;
+
+
+function RevPos(const SearchStr, Str: string): Integer;
+var i: Integer;
+begin
+
+	if Length(SearchStr) < Length(Str) then
+		for i := (Length(Str) - Length(SearchStr) + 1) downto 1 do
+		begin
+
+			if Copy(Str, i, Length(SearchStr)) = SearchStr then
+			begin
+				Result := i;
+				exit;
+			end;
+
+		end;
+
+	Result := 0;
+end;
+
+
+function Replace(pSearchFor, pReplaceWith, pText: String): String;
+begin
+    StringChangeEx(pText,pSearchFor,pReplaceWith,True);
+
+	Result := pText;
+end;
+
+
+function Count(What, Where: String): Integer;
+begin
+	Result := 0;
+	if Length(What) = 0 then
+		exit;
+
+	while Pos(What,Where)>0 do
+	begin
+		Where := Copy(Where,Pos(What,Where)+Length(What),Length(Where));
+		Result := Result + 1;
+	end;
+end;
+
+
+//split text to array
+procedure Explode(var ADest: TArrayOfString; aText, aSeparator: String);
+var tmp: Integer;
+begin
+	if aSeparator='' then
+		exit;
+
+	SetArrayLength(ADest,Count(aSeparator,aText)+1)
+
+	tmp := 0;
+	repeat
+		if Pos(aSeparator,aText)>0 then
+		begin
+
+			ADest[tmp] := Copy(aText,1,Pos(aSeparator,aText)-1);
+			aText := Copy(aText,Pos(aSeparator,aText)+Length(aSeparator),Length(aText));
+			tmp := tmp + 1;
+
+		end else
+		begin
+
+			 ADest[tmp] := aText;
+			 aText := '';
+
+		end;
+	until Length(aText)=0;
+end;
+
+
+function String2Utf8(const pInput: String): AnsiString;
+var Output: AnsiString;
+	ret, outLen, nulPos: Integer;
+begin
+	outLen := WideCharToMultiByte(CP_UTF8, 0, pInput, -1, Output, 0, 0, 0);
+	Output := StringOfChar(#0,outLen);
+	ret := WideCharToMultiByte(CP_UTF8, 0, pInput, -1, Output, outLen, 0, 0);
+
+	if ret = 0 then
+		RaiseException('WideCharToMultiByte failed: ' + IntToStr(GetLastError));
+
+	nulPos := Pos(#0,Output) - 1;
+	if nulPos = -1 then
+		nulPos := Length(Output);
+
+    Result := Copy(Output,1,nulPos);
+end;
+
+
+function Utf82String(const pInput: AnsiString): String;
+var Output: AnsiString;
+	ret, outLen, nulPos: Integer;
+begin
+	outLen := MultiByteToWideChar(CP_UTF8, 0, pInput, -1, Output, 0);
+	Output := StringOfChar(#0,outLen);
+	ret := MultiByteToWideChar(CP_UTF8, 0, pInput, -1, Output, outLen);
+
+	if ret = 0 then
+		RaiseException('MultiByteToWideChar failed: ' + IntToStr(GetLastError));
+
+	nulPos := Pos(#0,Output) - 1;
+	if nulPos = -1 then
+		nulPos := Length(Output);
+
+    Result := Copy(Output,1,nulPos);
+end;
+
+
+function SaveStringToUTF8File(const pFileName, pS: String; const pAppend: Boolean): Boolean;
+begin
+	Result := SaveStringToFile(pFileName, String2Utf8(pS), pAppend);
+end;
+
+
+function LoadStringFromUTF8File(const pFileName: String; var oS: String): Boolean;
+var Utf8String: AnsiString;
+begin
+	Result := LoadStringFromFile(pFileName, Utf8String);
+	oS := Utf82String(Utf8String);
+end;
+
+
+procedure StatusLabel(const Status1,Status2: string);
+begin
+	WizardForm.StatusLabel.Caption := Status1;
+	WizardForm.FilenameLabel.Caption := Status2;
+	WizardForm.Refresh();
+end;
diff --git a/build/windows/installer/version.isi b/build/windows/installer/version.isi
new file mode 100755
index 0000000..5333b6a
--- /dev/null
+++ b/build/windows/installer/version.isi
@@ -0,0 +1,28 @@
+//set the version string
+
+#define public
+
+#if !Defined(VERSION)
+  #error "VERSION must be defined"
+#endif
+
+#define GTK_VER=GetFileVersion(AddBackslash(DEPS_DIR64) + "bin\libgtk-win32-2.0-0.dll")
+
+#define public
+//used in the component list
+#define GTK_VERSION=Copy(GTK_VER,1,RPos(".",GTK_VER)-1)
+
+#define MAJOR=Copy(VERSION,1,Pos(".",VERSION)-1)
+#define MINOR=Copy(VERSION,Pos(".",VERSION)+1)
+#define MICRO=Copy(MINOR,Pos(".",MINOR)+1)
+#expr MINOR=Copy(MINOR,1,Pos(".",MINOR)-1)
+
+#if Int(MINOR) % 2 == 1
+ #define DEVEL="-dev"
+ //used for setting up file associations
+ #define ASSOC_VERSION=MAJOR + "." + MINOR
+#else
+ #define DEVEL=""
+ //new setup is incompatible with GIMP 2.6 and older installers
+ #define ASSOC_VERSION=MAJOR + ".8"
+#endif
diff --git a/build/windows/installer/wilber.bmp b/build/windows/installer/wilber.bmp
new file mode 100755
index 0000000..2d15f3b
Binary files /dev/null and b/build/windows/installer/wilber.bmp differ
diff --git a/build/windows/installer/windows-installer-intro-big.bmp b/build/windows/installer/windows-installer-intro-big.bmp
new file mode 100755
index 0000000..73fda81
Binary files /dev/null and b/build/windows/installer/windows-installer-intro-big.bmp differ
diff --git a/build/windows/installer/windows-installer-intro-small.bmp b/build/windows/installer/windows-installer-intro-small.bmp
new file mode 100755
index 0000000..a531ed3
Binary files /dev/null and b/build/windows/installer/windows-installer-intro-small.bmp differ



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]