X-Git-Url: https://ecere.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=installer%2Fsrc%2Finstaller.ec;h=fb05b35ecb111f78d5d16ce6350f8a547a41ed98;hb=cf37e3addcf039065340e429f0c3e1cf30849bb2;hp=4200e039a5673125fad6d7782378345fd84a7df4;hpb=988b810f4720785bbb407af82199559bd99b8ddd;p=sdk diff --git a/installer/src/installer.ec b/installer/src/installer.ec index 4200e03..fb05b35 100644 --- a/installer/src/installer.ec +++ b/installer/src/installer.ec @@ -1,8 +1,7 @@ -#ifdef NOMINGW -static define buildString = $"Ecere SDK v0.44 (Without MinGW) -- built on March 7, 2012 "; -#else -static define buildString = $"Ecere SDK v0.44 -- built on March 7, 2012 "; -#endif +static define versionString = "Ecere SDK v0.44.15"; +static define dateString = $"August 3, 2016"; +static define builtOnString = $"built on "; +static define withoutMinGW = $" (Without MinGW)"; #define WIN32_LEAN_AND_MEAN #define GetFreeSpace _GetFreeSpace @@ -16,170 +15,57 @@ import "ecere" #endif import "IDESettings" import "createLink" -// import "licenseBox" import "licensing" +import "CheckListBox" -class CheckListBox : ListBox +static void SetBuildString(Label label) { - fullRowSelect = false, collapseControl = true, treeBranches = true, rootCollapseButton = true, - noDragging = true; - rowHeight = 18; - - void ToggleCheck(DataRow row) - { - Button checkBox = (Button)row.tag; - DataRow parent; - bool checked = !(checkBox.checked) || checkBox.buttonState == down; - if(!checkBox.disabled) - { - SetCheck(row, checked); - checkBox.buttonState = up; - - for(parent = row; parent; parent = parent.parent) - { - for(row = parent.firstRow; row; row = row.next) - { - checkBox = (Button)row.tag; - if(checkBox.checked != checked) - break; - } - checkBox = (Button)parent.tag; - if(row) - { - checkBox.checked = true; - NotifyChecked(master, this, parent); - checkBox.buttonState = down; - checked = true; - } - else - { - checkBox.checked = checked; - NotifyChecked(master, this, parent); - checkBox.buttonState = up; - } - } - } - } - - void SetCheck(DataRow row, bool checked) - { - Button checkBox = (Button)row.tag; - DataRow subRow; - if(!checkBox.disabled && (checkBox.checked != checked || checkBox.buttonState == down)) - { - checkBox.checked = checked; - for(subRow = row.firstRow; subRow; subRow = subRow.next) - SetCheck(subRow, checked); - NotifyChecked(master, this, row); - } - } - - DataRow AddRow(DataRow parentRow) - { - DataRow row = parentRow ? parentRow.AddRow() : ListBox::AddRow(); - int c; - DataRow parent; - int indent = 20; - for(parent = row.parent; parent; parent = parent.parent) - indent += 20; - row.tag = (int)Button - { - this, isCheckbox = true, inactive = true, checked = true, - position = { 2 + indent, 1+(row.index + hasHeader) * rowHeight }, size = { 12, 12 }; - id = (int)row; - - bool NotifyPushed(Button button, int x, int y, Modifiers mods) - { - currentRow = (DataRow)button.id; - ToggleCheck(currentRow); - return false; - } - - bool NotifyReleased(Button button, int x, int y, Modifiers mods) - { - return false; - } - - bool OnMouseOver(int x, int y, Modifiers mods) - { - - return true; - } - - bool OnMouseLeave(Modifiers mods) - { - - return true; - } - }; - return row; - } - - bool NotifyKeyDown(CheckListBox listBox, DataRow row, Key key, unichar ch) - { - if(key == space) - { - listBox.ToggleCheck(row); - return false; - } - return true; - } + static const String addMinGW = ""; + String s; - bool OnKeyHit(Key key, unichar ch) - { - if(key == space) - return false; - return ListBox::OnKeyHit(key, ch); - } - - bool NotifyDoubleClick(CheckListBox listBox, int x, int y, Modifiers mods) - { - listBox.OnLeftButtonDown(x, y, mods); - return false; - } +#ifdef NOMINGW + addMinGW = withoutMinGW; +#endif - bool NotifyReclick(CheckListBox listBox, DataRow row, Modifiers mods) - { - listBox.ToggleCheck(row); - return true; - } + s = PrintString(versionString, addMinGW, " -- ", builtOnString, dateString); + label.caption = s; + delete s; +} - bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed) +static bool IsAdministrator() +{ + BOOL b; + SID_IDENTIFIER_AUTHORITY NtAuthority = { SECURITY_NT_AUTHORITY }; + PSID AdministratorsGroup; + b = AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorsGroup); + if(b) { - DataRow r; - for(r = row.firstRow; r && r != row; ) - { - Button checkBox = (Button)r.tag; - checkBox.visible = !collapsed; - if(r.firstRow && !r.collapsed) - row = r.firstRow; - else - for(; r != row; r = r.parent) - if(r.next) { r = r.next; break; } - } - for(r = row.GetNextRow(); r; r = r.GetNextRow()) - { - Button checkBox = (Button)r.tag; - checkBox.position.y = 1 + (r.index + listBox.hasHeader) * listBox.rowHeight; - } - return true; + if(!CheckTokenMembership(NULL, AdministratorsGroup, &b)) + b = FALSE; + FreeSid(AdministratorsGroup); } - - virtual void Window::NotifyChecked(CheckListBox listBox, DataRow row); -}; + return b == TRUE; +} struct CheckItem { - char * name; + const char * name; void * data; - char * OnGetString(char * tempString, void * fieldData, bool * needClass) + bool add32Bit; + const char * OnGetString(char * tempString, void * fieldData, bool * needClass) { + if(add32Bit) + { + strcpy(tempString, name); + strcat(tempString, " (32)"); + return tempString; + } return name; } void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags) { - if(!displayFlags.active) displayFlags.current = false; + if(!displayFlags.active) { displayFlags.current = false; displayFlags.selected = false; } class::OnDisplay(surface, x + 22, y, width - 22, fieldData, alignment, displayFlags); } }; @@ -188,7 +74,7 @@ struct CheckItem #define BUFFERSIZE 0x1000 bool abortInstall = false; -void ExtractFileFromArchive(ProgressBar progressBar, char * path, char * outputFile) +void ExtractFileFromArchive(ProgressBar progressBar, const char * path, const char * outputFile) { char fileName[MAX_LOCATION]; FileAttribs exists = FileExists(path); @@ -258,11 +144,11 @@ void ExtractFileFromArchive(ProgressBar progressBar, char * path, char * outputF FileGetSize(path, &dataSize); GetLastDirectory(outputFile, fileName); - + ((GuiApplication)__thisModule).SignalEvent(); //((GuiApplication)__thisModule).ProcessInput(); //((GuiApplication)__thisModule).UpdateDisplay(); - + for(c = 0; c c + BUFFERSIZE) ? BUFFERSIZE : (dataSize - c); @@ -292,14 +178,19 @@ void ExtractFileFromArchive(ProgressBar progressBar, char * path, char * outputF FileSetTime(outputFile, stats.created, 0, stats.modified); } +public enum BitArch { none, bits32, bits64 }; + struct Component { - char * name; - char * dataPath; - char * defInstallPath; + const char * name; + const char * dataPath; + const char * defInstallPath; Component * subComponents; bool mandatory; bool selected; + bool available; + BitArch arch; + Component * parent; uint requiredSize; @@ -307,35 +198,43 @@ struct Component char installPath[MAX_LOCATION]; DataRow row; - void GetFullPath(char * path) + void GetFullPath(char * path, bool is32bit) { if(this != null && parent) - parent->GetFullPath(path); + parent->GetFullPath(path, is32bit || (arch == bits32 && osIS64bit)); else - strcpy(path, installDir); + strcpy(path, (this && (is32bit || (arch == bits32 && osIS64bit))) ? installDir32 : installDir); if(this != null) PathCat(path, installPath); } - void Install(char * parentPath) + void Install(char * parentPath, char * parentPath32) { int c; - if(selected) + if(selected && (arch == none || arch == bits32 || osIS64bit)) { - char path[MAX_LOCATION]; - strcpy(path, parentPath); - PathCat(path, installPath); + char path64[MAX_LOCATION]; + char path32[MAX_LOCATION]; + strcpy(path64, parentPath); + PathCat(path64, installPath); + + strcpy(path32, parentPath32); + PathCat(path32, installPath); installProgress.installing.SetText($"Installing %s...", name); ((GuiApplication)__thisModule).UpdateDisplay(); if(dataPath) { + char * path = path64; char source[MAX_LOCATION]; strcpy(source, ":"); strcat(source, dataPath); + if(arch == bits32) + path = path32; + MakeDir(path); if(FileExists(source).isFile) @@ -345,136 +244,138 @@ struct Component PathCat(path, name); } if(requiredSize) - { - uint p = installProgress.progressBar.progress; - ExtractFileFromArchive(installProgress.progressBar, source, path); - } + ExtractFileFromArchive(installProgress.progressBar, source, path); } if(subComponents) { for(c = 0; subComponents[c].name; c++) - subComponents[c].Install(path); + subComponents[c].Install(path64, path32); } } } }; -Component samples[] = -{ - { "Ecere Chess", "samples/chess", "chess", null, false, true }, - { "Ecere Fractals", "samples/fractals", "fractals", null, false, true }, - { "3D", "samples/3D", "3D", null, false, true }, - { "Audio", "samples/audio", "audio", null, false, true }, - { "Database", "samples/db", "db", null, false, true }, - { "eC", "samples/eC", "eC", null, false, true }, - { "Games", "samples/games", "games", null, false, true }, - { "GUI & Graphics", "samples/guiAndGfx", "guiAndGfx", null, false, true }, - { "Miscellaneous", "samples/misc", "misc", null, false, true }, - { "Networking", "samples/net", "net", null, false, true }, - { "WIA Scanning", "samples/scanning", "scanning", null, false, true }, - { "Threading", "samples/threads", "threads", null, false, true } + +#ifndef NOMINGW +define minGWIncluded = true; +#else +define minGWIncluded = false; +#endif + +Array samples +{ [ + { "3D", "samples/3D", "3D", null, false, true, true, none }, + { "Android", "samples/android", "android", null, false, true, true, none }, + { $"Audio", "samples/audio", "audio", null, false, true, true, none }, + { $"Database", "samples/db", "db", null, false, true, true, none }, + { "eC", "samples/eC", "eC", null, false, true, true, none }, + { $"Games", "samples/games", "games", null, false, true, true, none }, + { $"GUI & Graphics", "samples/guiAndGfx", "guiAndGfx", null, false, true, true, none }, + { $"Miscellaneous", "samples/misc", "misc", null, false, true, true, none }, + { $"Networking", "samples/net", "net", null, false, true, true, none }, + { $"WIA Scanning", "samples/scanning", "scanning", null, false, true, true, none }, + { $"Threading", "samples/threads", "threads", null, false, true, true, none }, { null } -}; +] }; public enum CoreSDKID { - ide, runtime, ec, eda, vanilla, extras, -#ifndef NOMINGW + ide, ide32, runtime, runtime32, ec, ec32, gcc, gdb, mingw, binutils, make, -#endif none }; -Component coreSDK[CoreSDKID] = -{ - { "Ecere IDE", "ecere-sdk/ide", "bin", null, true, true }, - { "Runtime Library", "ecere-sdk/ecere.dll", "bin", null, true, true }, - { "eC Compiler", "ecere-sdk/compiler", "bin", null, true, true }, - { "Data Access", "ecere-sdk/eda", "bin", null, false, true }, - { "Ecere Vanilla", "ecere-sdk/libecereVanilla.a", "lib", null, false, true }, - { "Ecere Extras", "extras", "extras", null, false, true }, -#ifndef NOMINGW - { "GNU C Compiler", "mingw/gcc/core", "mingw", null, true, true }, - { "GNU Debugger", "mingw/gdb", "mingw", null, true, true }, - { "MinGW Runtime", "mingw/mingwrt", "mingw", null, true, true }, - { "Binary Utils", "mingw/binutils", "mingw", null, true, true }, - { "GNU Make", "mingw/make", "mingw", null, true, true }, -#endif +Array coreSDK +{ [ + { "Ecere IDE", "ecere-sdk/ecere-ide", "bin", null, true, true, true, bits64 }, + { "Ecere IDE", "ecere-sdk32/ecere-ide", "bin", null, true, true, true, bits32 }, + { $"Runtime Library", "ecere-sdk/ecere.dll", "bin", null, true, true, true, bits64 }, + { $"Runtime Library", "ecere-sdk32/ecere.dll", "bin", null, true, true, true, bits32 }, + { $"eC Compiler", "ecere-sdk/compiler", "bin", null, true, true, true, bits64 }, + { $"eC Compiler", "ecere-sdk32/compiler", "bin", null, true, true, true, bits32 }, + { $"GNU C Compiler", "tdm/gcc/core", "tdm", null, true, true, minGWIncluded, none }, + { $"GNU Debugger", "tdm/gdb", "tdm", null, true, true, minGWIncluded, none }, + { $"MinGW-w64 Runtime", "tdm/mingwrt", "tdm", null, true, true, minGWIncluded, none }, + { $"Binary Utils", "tdm/binutils", "tdm", null, true, true, minGWIncluded, none }, + { $"GNU Make", "tdm/make", "tdm", null, true, true, minGWIncluded, none }, { null } -}; +] }; -#ifndef NOMINGW -Component additional[] = +public enum AdditionalID { - { "UPX", "upx/bin", "mingw", null, false, true }, - { "GNU Regexp", "mingw/gnurx", "mingw", null, false, true }, - { "Win32 APIs", "mingw/w32api", "mingw", null, false, true }, - { "pthreads", "mingw/pthreads", "mingw", null, false, true }, - { "C++ Compiler", "mingw/gcc/c++", "mingw", null, false, true }, - { "GCC I18n", "mingw/locale/gcc", "mingw", null, false, false }, - { "GDB I18n", "mingw/locale/gdb", "mingw", null, false, false }, - { "Make I18n", "mingw/locale/make", "mingw", null, false, false }, - { "Binutils I18n", "mingw/locale/binutils", "mingw", null, false, false }, - { null } + eda, eda32, audio, audio32, vanilla, vanilla32, extras, upx, gnurx, gnurx32, /*pthreads, */cpp, /*w32api, gcci18n, gdbi18n, makei18n, binutilsi18n, */none }; -#endif + +Array additional +{ [ + { $"Data Access", "ecere-sdk/eda", "bin", null, false, true, true, bits64 }, + { $"Data Access", "ecere-sdk32/eda", "bin", null, false, true, true, bits32 }, + { $"Ecere Audio", "ecere-sdk/EcereAudio.dll", "bin", null, false, true, true, bits64 }, + { $"Ecere Audio", "ecere-sdk32/EcereAudio.dll", "bin", null, false, true, true, bits32 }, + { $"Ecere Vanilla", "ecere-sdk/libecereVanilla.a", "lib", null, false, true, true, bits64 }, + { $"Ecere Vanilla", "ecere-sdk32/libecereVanilla.a", "lib", null, false, true, true, bits32 }, + { $"Ecere Extras", "extras", "extras", null, false, true, true, none }, + { "UPX", "upx/bin", "upx/bin", null, false, true, true, none }, + { $"GNU Regexp", "tdm/gnurx", "tdm", null, false, true, true, bits64 }, + { $"GNU Regexp", "tdm/gnurx32", "tdm", null, false, true, true, bits32 }, +// { "pthreads", "tdm/pthreads", "mingw", null, false, true, minGWIncluded, none }, + { $"C++ Compiler", "tdm/gcc/c++", "tdm", null, false, true, minGWIncluded, none }, +// { "Win32 APIs", "mingw/w32api", "mingw", null, false, true, minGWIncluded, none }, +/* { "GCC I18n", "mingw/locale/gcc", "tdm", null, false, false, minGWIncluded, none }, + { "GDB I18n", "mingw/locale/gdb", "tdm", null, false, false, minGWIncluded, none }, + { "Make I18n", "mingw/locale/make", "tdm", null, false, false, minGWIncluded, none }, + { "Binutils I18n", "mingw/locale/binutils", "tdm", null, false, false, minGWIncluded, none }, +*/ + { null } +] }; public enum DocumentationID { - ecereBook, apiRef, tutorials, coursework, -#ifndef NOMINGW + ecereBook, apiRef, coursework, gccDoc, gppDocs, gdbDocs, makeDocs, binDocs, mingwDocs, gnurxDocs, upxDocs, -#endif none }; -Component documentation[DocumentationID] = -{ - { "Ecere Book", "ecere-sdk/book", "doc", null, false, true }, - { "API Reference", "ecere-sdk/doc", "doc", null, false, true }, - { "Ecere Tutorials", "ecere-sdk/tutorials", "doc", null, false, true }, - { "Ecere Coursework", "ecere-sdk/coursework", "doc", null, false, true }, -#ifndef NOMINGW - { "GCC Docs", "mingw/doc/gcc", "mingw", null, false, false }, - { "G++ Docs", "mingw/doc/g++", "mingw", null, false, false }, - { "GDB Docs", "mingw/doc/gdb", "mingw", null, false, false }, - { "Make Docs", "mingw/doc/make", "mingw", null, false, false }, - { "Binutils Docs", "mingw/doc/binutils", "mingw", null, false, false }, - { "MinGW Docs", "mingw/doc/mingw", "mingw", null, false, false }, - { "gnurx Docs", "mingw/doc/gnurx", "mingw", null, false, false }, - { "UPX Docs", "upx/doc", "mingw/doc/upx", null, false, false }, -#endif +Array documentation +{ [ + { $"Ecere Book", "ecere-sdk/book", "doc", null, false, true, true, none }, + { $"API Reference", "ecere-sdk/doc", "doc", null, false, true, true, none }, + { $"Ecere Coursework", "ecere-sdk/coursework", "doc", null, false, true, true, none }, + { $"GCC Docs", "tdm/doc/gcc", "tdm", null, false, false, minGWIncluded, none }, + { $"G++ Docs", "tdm/doc/g++", "tdm", null, false, false, minGWIncluded, none }, + { $"GDB Docs", "tdm/doc/gdb", "tdm", null, false, false, minGWIncluded, none }, + { $"Make Docs", "tdm/doc/make", "tdm", null, false, false, minGWIncluded, none }, + { $"Binutils Docs", "tdm/doc/binutils", "tdm", null, false, false, minGWIncluded, none }, + { $"gnurx Docs", "tdm/doc/gnurx", "tdm", null, false, false, minGWIncluded, none }, + { $"UPX Docs", "upx/doc", "upx/doc", null, false, false, minGWIncluded, none }, { null } -}; +] }; public enum ComponentID { coreSDK, -#ifndef NOMINGW additional, -#endif documentation, samples, none }; -Component components[ComponentID] = -{ - { "Core SDK Files", null, null, coreSDK, true, true }, -#ifndef NOMINGW - { "Additional Support", null, null, additional, false, true }, -#endif - { "Documentation", null /*"doc"*/, null /*"doc"*/, documentation, false, true }, - { "Samples", null, "samples", samples, false, true }, +Array components +{ [ + { $"Core SDK Files", null, null, coreSDK.array, true, true, true, none }, + { $"Additional Support", null, null, additional.array, false, true, true, none }, + { $"Documentation", null /*"doc"*/, null /*"doc"*/, documentation.array, false, true, true, none }, + { $"Samples", null, "samples", samples.array, false, true, true, none }, { null } -}; +] }; FileSize totalSize; FileSize totalInstalled; struct InstallOption { - char * name; + const char * name; InstallOption * subOptions; bool selected; + bool available; DataRow row; }; @@ -489,82 +390,86 @@ enum AssociateOptions AssociateIMG }; -InstallOption associateOptions[] = -{ - { "Associate with Ecere Project Files (*.epj)", null, true }, - { "Associate with eC Files (*.ec, *.eh)", null, true }, - { "Associate with C files (*.c, *.h)", null, false }, - { "Associate with C++ Files (*.cpp, *.hpp, *.cc, *.hh, *.cxx, *.hxx)", null, false }, - { "Associate with text files (*.txt)", null, false }, - { "Associate with 3D Studio Model Files (*.3ds)", null, true }, - { "Associate with Image Files (*.png, *.jpg, *.pcx, *.bmp, *.gif)", null, false }, +Array associateOptions +{ [ + { $"Associate with Ecere Project Files (*.epj)", null, true }, + { $"Associate with eC Files (*.ec, *.eh)", null, true }, + { $"Associate with C files (*.c, *.h)", null, false }, + { $"Associate with C++ Files (*.cpp, *.hpp, *.cc, *.hh, *.cxx, *.hxx)", null, false }, + { $"Associate with text files (*.txt)", null, false }, + { $"Associate with 3D Studio Model Files (*.3ds)", null, true }, + { $"Associate with Image Files (*.png, *.jpg, *.pcx, *.bmp, *.gif)", null, false }, { null } -}; +] }; enum PathOptions { - AddECEREPaths -#ifndef NOMINGW - , AddMinGWPaths -#endif + AddECEREPaths, AddMinGWPaths }; -InstallOption pathOptions[] = -{ - { "Add Ecere binaries location to the system path", null, true }, - { "Add MinGW to the system path", null, true } +Array pathOptions +{ [ + { $"Add Ecere binaries location to the user environment path", null, true, true }, + { $"Add MinGW to the user environment path", null, true, minGWIncluded }, { null } -}; +] }; enum IconOptions { - StartMenuIcon, - DesktopIcon, - QuickLaunchIcon + StartMenuIcon = 1, + DesktopIcon = 2, + QuickLaunchIcon = 3 }; -InstallOption options[] = -{ - { "Start Menu Group", null, true }, - { "Desktop Icon", null, true }, - { "Quicklaunch Icon", null, true }, - { "Associate the ECERE IDE with Supported File Types", associateOptions, true }, -#ifndef NOMINGW - { "Add binaries location to the system paths", pathOptions, true }, -#endif +Array options +{ [ + { $"Install for All Users", null, true, true }, + { $"Start Menu Group", null, true, true }, + { $"Desktop Icon", null, true, true }, + { $"Quicklaunch Icon", null, true, true }, + { $"Associate the Ecere IDE with Supported File Types", associateOptions.array, true, true }, + { $"Add binaries location to the user environment paths", pathOptions.array, true, minGWIncluded }, { null } -}; +] }; char sourceDir[MAX_LOCATION] = ":"; char installDir[MAX_LOCATION]; +char installDir32[MAX_LOCATION]; +bool osIS64bit; class Installer : Window { - text = $"Ecere Software Development Kit Setup - v0.44 \"Ryōan-ji\""; - background = activeBorder; + background = formColor; borderStyle = fixed; hasMinimize = true; hasClose = true; tabCycle = true; - clientSize = { 636, 456 }; + clientSize = { 636, 476 }; icon = { ":icon.png" }; + caption = $"Ecere Software Development Kit Setup - v0.44.15 \"Ryōan-ji\" Web Edition"; + + // clientSize = { 796, 576 }; + bool loaded; Picture back { image = BitmapResource { ":ryoanji.png" }, parent = this, position = { 0, 0 } }; FileDialog fileDialog { master = this, type = selectDir, - text = $"Select a new location" + caption = $"Select a new location" }; Button browse { - master = this, autoCreate = false, inactive = true, /*hotKey = F2,*/ text = "..."; - + master = this, autoCreate = false, inactive = true, caption = "..."; + bool NotifyClicked(Button button, int x, int y, Modifiers mods) { DataRow row = componentsBox.currentRow; Component * component = ((CheckItem *)row.GetData(componentField))->data; - component->GetFullPath(fileDialog.filePath); - StripLastDirectory(fileDialog.filePath, fileDialog.currentDirectory); + char filePath[MAX_LOCATION]; + component->GetFullPath(filePath, false); + fileDialog.filePath = filePath; + StripLastDirectory(filePath, filePath); + fileDialog.currentDirectory = filePath; if(fileDialog.Modal() == ok) { @@ -579,23 +484,40 @@ class Installer : Window CheckListBox componentsBox { this, size = { 460, 112 }, position = { 160, 160 }, hasHeader = true; + fullRowSelect = false, collapseControl = true, treeBranches = true, rootCollapseButton = true, + hasHorzScroll = true; + resizable = true, + noDragging = true; + rowHeight = 18; + selectionColor = { 145, 150, 140 }; + alwaysEdit = true; opacity = 0; + bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch) + { + if(key == f2 && browse.visible) + browse.NotifyClicked(this, browse, 0, 0, 0); + return true; + } + bool NotifyChanged(ListBox listBox, DataRow row) { Component * component = ((CheckItem *)listBox.GetData(componentField))->data; - char path[MAX_LOCATION], relative[MAX_LOCATION] = "", ** newPath; + char path[MAX_LOCATION], relative[MAX_LOCATION] = "", * newPath; char fullPath[MAX_LOCATION]; - component->parent->GetFullPath(path); + component->parent->GetFullPath(path, false); strcpy(fullPath, path); - newPath = (char **)row.GetData(locationField); - if(newPath && *newPath) + newPath = row.GetData(locationField); + if(newPath) { - PathCat(fullPath, *newPath); - MakePathRelative(fullPath, path, relative); + PathCat(fullPath, newPath); + if(IsPathInsideOf(fullPath, path)) + MakePathRelative(fullPath, path, relative); + else + strcpy(relative, fullPath); } listBox.SetData(locationField, relative); strcpy(component->installPath, relative); @@ -620,10 +542,17 @@ class Installer : Window bool NotifyEdited(ListBox listBox, DataRow row) { + Window e; browse.parent = listBox; browse.position = { componentField.width + locationField.width + 18, (listBox.currentIndex+1) * listBox.rowHeight - 2 }; browse.size = { 30, listBox.rowHeight + 3 }; - + for(e = listBox.firstChild; e; e = e.next) + { + if(e._class == class(DataBox)) + break; + } + if(e) + e.Activate(); browse.Create(); return true; } @@ -632,14 +561,13 @@ class Installer : Window { Component * component = ((CheckItem *)row.GetData(componentField))->data; int c; - Button checkBox = (Button)row.tag; - component->selected = checkBox.checked; + component->selected = listBox.IsChecked(row); if(!component->parent) totalSize -= component->requiredSize; component->requiredSize = 0; if(component->selected) { - component->requiredSize += component->size; + component->requiredSize += component->size; if(component->subComponents) for(c = 0; component->subComponents[c].name; c++) component->requiredSize += component->subComponents[c].requiredSize; @@ -651,23 +579,23 @@ class Installer : Window } else row.UnsetData(reqField); - if(!component->parent) + if(!component->parent) { totalSize += component->requiredSize; { char sizeString[100]; PrintSize(sizeString, totalSize, 2); - totalSpaceValue.text = sizeString; + totalSpaceValue.caption = sizeString; } } } }; - Label agreementLbl { parent = this, text = $"By installing the Ecere SDK, you agree to the .", font = { "Tahoma", 8.25f }, anchor = Anchor { left = 24, top = 424 } }; + Label agreementLbl { parent = this, caption = $"By installing the Ecere SDK, you agree to the", font = { "Tahoma", 8.25f }, anchor = Anchor { right = 399, top = 448 } }; Button licenseButton { this, inactive = true, offset = false, bevel = false, foreground = blue, font = { "Tahoma", 8.25f, underline = true, bold = true }, - // text = $"terms and conditions", anchor = Anchor { left = 241, top = 421 }; - text = $"terms and conditions", anchor = Anchor { left = 237, top = 421 }; + // caption = $"terms and conditions", anchor = Anchor { left = 241, top = 421 }; + caption = $"terms and conditions", anchor = Anchor { left = 235, top = 445 }; cursor = ((GuiApplication)__thisModule).GetCursor(hand); bool NotifyClicked(Button button, int x, int y, Modifiers mods) @@ -677,23 +605,79 @@ class Installer : Window return true; } }; + Label dotLbl { parent = this, caption = ".", font = { "Tahoma", 8.25f }, anchor = Anchor { left = 372, top = 448 } }; CheckListBox optionsBox { - this, size = { 460, 94 }, position = { 160, 284 }; + this, size = { 460, 114 }, position = { 160, 284 }; + fullRowSelect = false, collapseControl = true, treeBranches = true, rootCollapseButton = true, + noDragging = true; + rowHeight = 18; opacity = 0; void NotifyChecked(CheckListBox listBox, DataRow row) { CheckItem * item = row.GetData(optionField); InstallOption * option = item->data; - int c; - Button checkBox = (Button)row.tag; - option->selected = checkBox.checked; + option->selected = listBox.IsChecked(row); + // Update default samples/extras path whether we're installing for All Users or not + if(option == &options[0]) + { + char appData[MAX_LOCATION]; + + options[5].name = options[0].selected ? $"Add binaries location to the system environment paths" : $"Add binaries location to the user environment paths"; + if(options[5].row) + ((CheckItem *)options[5].row.GetData(optionField))->name = options[5].name; + + pathOptions[PathOptions::AddECEREPaths].name = options[0].selected ? $"Add Ecere binaries location to the system environment path" : $"Add Ecere binaries location to the user environment path"; + if(pathOptions[PathOptions::AddECEREPaths].row) + ((CheckItem *)pathOptions[PathOptions::AddECEREPaths].row.GetData(optionField))->name = pathOptions[PathOptions::AddECEREPaths].name; + + pathOptions[PathOptions::AddMinGWPaths].name = options[0].selected ? $"Add TDM-GCC/MinGW-w64 to the system environment path" : $"Add TDM-GCC/MinGW-w64 to the user environment path"; + if(pathOptions[PathOptions::AddMinGWPaths].row) + ((CheckItem *)pathOptions[PathOptions::AddMinGWPaths].row.GetData(optionField))->name = pathOptions[PathOptions::AddMinGWPaths].name; + + GetEnvironment(options[0].selected ? "ALLUSERSPROFILE" : "APPDATA", appData, sizeof(appData)); + if(appData[0]) + { + char defPath[MAX_LOCATION]; + + strcpy(defPath, installDir); + PathCat(defPath, components[ComponentID::samples].defInstallPath); + ChangeCh(defPath, '/', DIR_SEP); + if(!strcmp(defPath, components[ComponentID::samples].installPath)) + { + static char defSamplesPath[MAX_LOCATION]; + strcpy(defSamplesPath, appData); + PathCat(defSamplesPath, "Ecere SDK\\Samples"); + components[ComponentID::samples].defInstallPath = defSamplesPath; + + strcpy(components[ComponentID::samples].installPath, components[ComponentID::samples].defInstallPath); + ChangeCh(components[ComponentID::samples].installPath, '/', DIR_SEP); + components[ComponentID::samples].row.SetData(locationField, components[ComponentID::samples].installPath); + } + + strcpy(defPath, installDir); + PathCat(defPath, additional[AdditionalID::extras].defInstallPath); + ChangeCh(defPath, '/', DIR_SEP); + if(!strcmp(additional[AdditionalID::extras].installPath, additional[AdditionalID::extras].installPath)) + { + static char defExtrasPath[MAX_LOCATION]; + strcpy(defExtrasPath, appData); + PathCat(defExtrasPath, "Ecere SDK\\extras"); + additional[AdditionalID::extras].defInstallPath = defExtrasPath; + + strcpy(additional[AdditionalID::extras].installPath, additional[AdditionalID::extras].defInstallPath); + ChangeCh(additional[AdditionalID::extras].installPath, '/', DIR_SEP); + additional[AdditionalID::extras].row.SetData(locationField, additional[AdditionalID::extras].installPath); + } + } + listBox.Update(null); + } } }; Button install { - parent = this, text = $"Install", isDefault = true, size = { 75, 23 }, position = { 432, 416 }; + parent = this, caption = $"Install", isDefault = true, size = { 75, 23 }, position = { 432, 440 }; bool NotifyClicked(Button button, int x, int y, Modifiers mods) { @@ -704,13 +688,46 @@ class Installer : Window return true; } }; - Button button3 { parent = this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 }, NotifyClicked = ButtonCloseDialog }; + Button button3 { parent = this, caption = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 440 }, NotifyClicked = ButtonCloseDialog }; + DropBox languageBox + { + this, position = { 14, 374 }, size = { 142, 0 }, caption = "Language:"; + + bool NotifySelect(DropBox dropBox, DataRow row, Modifiers mods) + { + LanguageOption * option = row.GetData(null); + // If the language is already set, we need to override it + { + IDESettings settings = null; + IDESettingsContainer settingsContainer + { + driver = "JSON"; + dataOwner = &settings; + dataClass = class(IDESettings); + allUsers = options[0].selected; + }; + settingsContainer.Load(); + if(settings.language) + { + settings.language = option->code; + settingsContainer.Save(); + } + delete settingsContainer; + delete settings; + } + ((GuiApplication)__thisModule.application).desktop.Destroy(0); + LanguageRestart(option->code, __thisModule.application, null, null, null, null, false); + return true; + } + }; + Label lblLanguageBox { this, position = { 14, 354 }, labeledWindow = languageBox }; Label label1 { labeledWindow = destBox, tabCycle = true, isGroupBox = true, parent = this, inactive = false, size = Size { 458, 50 }, anchor = Anchor { left = 160, top = 96 } }; PathBox destBox { - parent = label1, master = this, text = $" Destination Folder", size = Size { 336, 22 }, anchor = Anchor { left = 12, top = 20, right = 12 }; + parent = label1, master = this, caption = $" Destination Folder", size = Size { 336, 22 }, anchor = Anchor { left = 12, top = 20, right = 12 }; typeExpected = directory; browseDialog = fileDialog; + opacity = 0; bool NotifyModified(PathBox pathBox) { @@ -765,7 +782,7 @@ class Installer : Window }; EditBox label7 { - this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 53 }, position = { 14, 280 }, noSelect = true, + this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 83 }, position = { 14, 280 }, noSelect = true, multiLine = true, contents = $"Select icons to install, file\n" "associations, and system\n" @@ -773,23 +790,21 @@ class Installer : Window }; Label totalSpaceLabel { - this, position = { 18, 352 }, text = $"Space Required: " + this, anchor = { right = 72, top = 404 }, caption = $"Space Required: " }; Label totalSpaceValue { - this, position = { 100, 352 }, text = "0 mb" + this, anchor = { right = 14, top = 404 }, caption = "0 mb" }; EditBox editBox1 { - inactive = true, noSelect = true, - multiLine = true, parent = label3, text = "editBox1", opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 }, - contents = $"Choose in which folder to install the ECERE SDK, which features\n" + label3, caption = "editBox1", opacity = 0, borderStyle = none, inactive = true, size = { 350, 35 }, position = { 256, 40 }, multiLine = true, noSelect = true, contents = $"Choose in which folder to install the Ecere SDK, which features\n" "of the SDK to install, as well as where to install program icons." }; - Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder }; + Label label2 { parent = this, position = { 16, 422 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder }; Picture picture1 { - image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, text = "picture1", anchor = Anchor { left = 16, top = 4 }; + image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, caption = "picture1", anchor = Anchor { left = 16, top = 4 }; cursor = ((GuiApplication)__thisModule).GetCursor(hand); bool OnLeftButtonDown(int x, int y, Modifiers mods) @@ -798,14 +813,16 @@ class Installer : Window return true; } }; - Label label4 { parent = label3, text = $"Choose Components, Locations and Install Options", font = FontResource { "Tahoma", 8.25f, bold = true }, size = Size { 326, 16 }, anchor = Anchor { horz = 91, vert = -12 } }; - DataField componentField { "CheckItem", width = 140, header = $"Component" }; + Label label4 { label3, font = { "Tahoma", 8.25f, bold = true }, /*size = { 326, 16 }, */position = { 248, 24 }, caption = $"Choose Components, Locations and Install Options" }; + DataField componentField { "CheckItem", width = 160, header = $"Component" }; DataField locationField { "char *", width = 108, header = $"Destination Folder", editable = true }; - DataField reqField { "FileSize", width = 80, header = $"Req. Space", alignment = right }; - DataField avField { "FileSize64", width = 80, header = $"Avail. Space", alignment = right }; + DataField reqField { "FileSize", width = 70, header = $"Req. Space", alignment = right }; + DataField avField { "FileSize64", width = 70, header = $"Avail. Space", alignment = right }; DataField optionField { "CheckItem" }; - void SetAvailableSpace(Component component, char * parentPath) + DataField languageField { class(LanguageOption) }; + + void SetAvailableSpace(Component component, const char * parentPath) { char path[MAX_LOCATION]; int c; @@ -827,7 +844,7 @@ class Installer : Window if(!size) install.disabled = true; } - FileSize ComputeSize(char * path) + FileSize ComputeSize(const char * path) { FileSize size = 0; FileAttribs attribs = FileExists(path); @@ -847,19 +864,20 @@ class Installer : Window return size; } - void AddComponent(Component component, Component parent, char * parentPath) + void AddComponent(Component component, Component parent, const char * parentPath) { - DataRow row = component.row = componentsBox.AddRow((parent != null) ? parent.row : null); - Button checkBox = (Button) row.tag; + DataRow row = (parent != null) ? parent.row.AddRow() : componentsBox.AddRow(); FileSize size = 0; FileSize64 avSize = 0; char path[MAX_LOCATION]; + + component.row = row; strcpy(path, parentPath); if(component.defInstallPath) PathCat(path, component.defInstallPath); component.parent = parent; - - row.SetData(null, CheckItem { component.name, component } ); + + row.SetData(null, CheckItem { component.name, component, (component.arch == bits32 && osIS64bit) } ); if(component.defInstallPath) { @@ -868,8 +886,18 @@ class Installer : Window row.SetData(locationField, component.installPath); } - if(component.mandatory) checkBox.disabled = true; - if(!component.selected) componentsBox.ToggleCheck(row); + if(component.mandatory) + { + if(component.arch != bits32 || !osIS64bit) // || component == &coreSDK[gdb32]) + componentsBox.SetDisabled(row, true); + /*else + component.selected = false;*/ + } + else if(component.arch == bits32 && osIS64bit) + ; //component.selected = false; + + componentsBox.SetCheck(row, component.selected); + if(component.dataPath) { char path[MAX_LOCATION]; @@ -882,8 +910,14 @@ class Installer : Window int c; for(c = 0; component.subComponents[c].name; c++) { - AddComponent(component.subComponents[c], component, path); - size += component.subComponents[c].requiredSize; + Component * sub = &component.subComponents[c]; + if(sub->available && (osIS64bit || sub->arch == bits32 || sub->arch == none)) + { + AddComponent(sub, component, path); + size += sub->requiredSize; + } + else + sub->selected = false; } } @@ -893,7 +927,7 @@ class Installer : Window while(!FileExists(path) && path[0]) StripLastDirectory(path, path); - + if(path[0]) GetFreeSpace(path, &avSize); else @@ -904,10 +938,9 @@ class Installer : Window void AddOption(InstallOption option, InstallOption parent) { - DataRow row = option.row = optionsBox.AddRow((parent != null) ? parent.row : null); + DataRow row = option.row = (parent != null) ? parent.row.AddRow() : optionsBox.AddRow(); row.SetData(null, CheckItem { option.name, option } ); - if(!option.selected) - optionsBox.ToggleCheck(row); + optionsBox.SetCheck(row, option.selected); if(option.subOptions) { int c; @@ -923,14 +956,53 @@ class Installer : Window { int c; char programFilesDir[MAX_LOCATION]; - char appData[MAX_LOCATION]; // = getenv("APPDATA"); - char homeDrive[MAX_LOCATION]; //= getenv("HOMEDRIVE"); - char winDir[MAX_LOCATION]; //= getenv("windir"); + char appData[MAX_LOCATION]; + char homeDrive[MAX_LOCATION]; + char winDir[MAX_LOCATION]; + char * x86 = null; + + bool isAdministrator = IsAdministrator(); + + SetBuildString(label2); + + if(!isAdministrator) + { + options[0].available = false; + options[0].selected = false; + } + + // If the SDK is already installed, use currently selected language + { + IDESettings settings = null; + IDESettingsContainer settingsContainer + { + driver = "JSON"; + dataOwner = &settings; + dataClass = class(IDESettings); + allUsers = options[0].selected; + }; + + settingsContainer.Load(); + + if(settings.language) + { + const String language = GetLanguageString(); + if(settings.language.OnCompare(language)) + { + // Relaunch the installer with previously selected language + LanguageRestart(settings.language, __thisModule.application, null, null, null, null, false); + return false; + } + } + delete settingsContainer; + delete settings; + } - GetEnvironment("APPDATA", appData, sizeof(appData)); GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive)); GetEnvironment("windir", winDir, sizeof(winDir)); - + + GetEnvironment(options[0].selected ? "ALLUSERSPROFILE" : "APPDATA", appData, sizeof(appData)); + componentsBox.AddField(componentField); componentsBox.AddField(locationField); componentsBox.AddField(reqField); @@ -938,37 +1010,67 @@ class Installer : Window optionsBox.AddField(optionField); + languageBox.AddField(languageField); + + programFilesDir[0] = 0; if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION)) { - strcpy(installDir, programFilesDir); - PathCat(installDir, "ECERE SDK"); + x86 = strstr(programFilesDir, " (x86)"); + if(x86) + osIS64bit = true; + } + + if(isAdministrator && programFilesDir[0]) + { + if(x86) + { + strcpy(installDir32, programFilesDir); + PathCat(installDir32, "Ecere SDK"); + *x86 = 0; + strcpy(installDir, programFilesDir); + PathCat(installDir, "Ecere SDK"); + } + else + { + strcpy(installDir, programFilesDir); + PathCat(installDir, "Ecere SDK"); + strcpy(installDir32, installDir); + } } - else if(homeDrive && homeDrive[0]) + else if(homeDrive[0]) { strcpy(installDir, homeDrive); - PathCat(installDir, "ECERE SDK"); + PathCat(installDir, "Ecere SDK"); + strcpy(installDir32, installDir); + strcat(installDir32, " (32)"); } - else if(winDir && winDir[0]) + else if(winDir[0]) { strcpy(installDir, winDir); - PathCat(installDir, "..\\ECERE SDK"); + PathCat(installDir, "..\\Ecere SDK"); + strcpy(installDir32, installDir); + strcat(installDir32, " (32)"); } else - strcpy(installDir, "C:\\ECERE SDK"); - - if(appData && appData[0]) + { + strcpy(installDir, "C:\\Ecere SDK"); + strcpy(installDir32, installDir); + strcat(installDir32, " (32)"); + } + + if(appData[0]) { static char defSamplesPath[MAX_LOCATION]; static char defExtrasPath[MAX_LOCATION]; strcpy(defSamplesPath, appData); - PathCat(defSamplesPath, "ECERE SDK\\Samples"); - components[samples].defInstallPath = defSamplesPath; + PathCat(defSamplesPath, "Ecere SDK\\Samples"); + components[ComponentID::samples].defInstallPath = defSamplesPath; strcpy(defExtrasPath, appData); - PathCat(defExtrasPath, "ECERE SDK\\extras"); - coreSDK[extras].defInstallPath = defExtrasPath; + PathCat(defExtrasPath, "Ecere SDK\\extras"); + additional[AdditionalID::extras].defInstallPath = defExtrasPath; } - + destBox.path = installDir; { @@ -987,14 +1089,90 @@ class Installer : Window { char sizeString[100]; PrintSize(sizeString, totalSize, 2); - totalSpaceValue.text = sizeString; + totalSpaceValue.caption = sizeString; } for(c = 0; options[c].name; c++) - AddOption(options[c], null); + { + if(options[c].available) + AddOption(options[c], null); + } + } + + void OnDestroy() + { + for(l : languages) + delete l.res; + } + + bool OnPostCreate() + { + dotLbl.position.x = licenseButton.position.x + licenseButton.size.w - 4; + return true; } bool OnCreate() { + // Constructor happens before Languages is instantiated... + for(l : languages) + { + l.res = { l.bitmap, window = this }; + incref l.res; + } + + if(!loaded) + { + const String language = GetLanguageString(); + bool found = false; + DataRow row; + + // Try to find country-specific language first + for(l : languages) + { + LanguageOption option = l; + row = languageBox.AddRow(); + row.SetData(null, option); // TOFIX: l used directly here + + if(!found && (!strcmpi(l.code, language) || (!row.GetPrevRow() && !strcmpi("en", language)))) + { + languageBox.currentRow = row; + found = true; + } + } + + // Try generalizing locale + if(!found) + { + char * under; + char genericLocale[256]; + strncpy(genericLocale, language, sizeof(genericLocale)); + genericLocale[sizeof(genericLocale)-1] = 0; + + under = strchr(genericLocale, '_'); + if(under) + *under = 0; + if(!strcmpi(genericLocale, "zh")) + strcpy(genericLocale, "zh_CN"); + if(strcmp(genericLocale, language)) + { + row = languageBox.firstRow; + for(l : languages) + { + if(!strcmpi(l.code, genericLocale) || (!row.GetPrevRow() && !strcmpi("en", genericLocale))) + { + languageBox.currentRow = row; + found = true; + break; + } + row = row.GetNextRow(); + } + } + } + + if(!found) + languageBox.currentRow = languageBox.firstRow; + loaded = true; + } + destBox.Activate(); return true; } @@ -1003,12 +1181,11 @@ class Installer : Window { int tw = label2.size.w; surface.SetForeground(Color { 128, 128, 128 }); - surface.HLine(label2.position.x + tw + 6, 620, 400); + surface.HLine(label2.position.x + tw + 6, 620, 430); surface.SetForeground(white); - surface.HLine(label2.position.x + tw + 6, 621, 401); + surface.HLine(label2.position.x + tw + 6, 621, 431); surface.PutPixel(621, 400); } - Label label3 { parent = this, opacity = 0, borderStyle = deep, size = Size { 644, 93 }, anchor = Anchor { left = -8, top = -8 }; @@ -1017,27 +1194,34 @@ class Installer : Window class InstallProgress : Window { - text = $"Ecere Software Development Kit Setup - v0.44 \"Ryōan-ji\""; + caption = $"Ecere Software Development Kit Setup - v0.44.15 \"Ryōan-ji\" Web Edition"; background = activeBorder; borderStyle = fixed; hasMinimize = true; hasClose = true; tabCycle = true; - size = Size { 640, 480 }; + // size = Size { 640, 480 }; + clientSize = { 636, 476 }; + //clientSize = { 796, 576 }; icon = { ":icon.png" }; + InstallProgress() + { + SetBuildString(label2); + } + Picture back { image = BitmapResource { ":ryoanji-progress.png" }, parent = this, position = { 0, 0 } }; Label installing { this, position = { 32, 160 } }; ProgressBar progressBar { parent = this, size = Size { 588, 24 }, anchor = Anchor { left = 24, top = 184 } }; Button finish { - parent = this, text = $"Install", disabled = true, isDefault = true, size = Size { 75, 23 }, anchor = Anchor { left = 432, top = 416 }; + parent = this, caption = $"Install", disabled = true, isDefault = true, size = Size { 75, 23 }, anchor = Anchor { left = 432, top = 440 }; NotifyClicked = ButtonCloseDialog }; Button cancel { - this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 }; + this, caption = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 440 }; bool NotifyClicked(Button button, int x, int y, Modifiers mods) { @@ -1051,7 +1235,7 @@ class InstallProgress : Window multiLine = true, parent = label3, opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 }, contents = $"Please wait while the Ecere Software Development Kit is being installed." }; - Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder }; + Label label2 { parent = this, position = { 16, 422 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder }; Picture picture1 { image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, anchor = Anchor { left = 16, top = 4 }; @@ -1063,15 +1247,15 @@ class InstallProgress : Window return true; } }; - Label title { parent = label3, text = $"Installing the ECERE SDK", font = FontResource { "Tahoma", 8.25f, bold = true }, size = Size { 326, 16 }, anchor = Anchor { horz = 91, vert = -12 } }; + Label title { parent = label3, caption = $"Installing the Ecere SDK", font = FontResource { "Tahoma", 8.25f, bold = true }, size = Size { 326, 16 }, anchor = Anchor { horz = 91, vert = -12 } }; void OnDrawOverChildren(Surface surface) { int tw = label2.size.w; surface.SetForeground(Color { 128, 128, 128 }); - surface.HLine(label2.position.x + tw + 6, 620, 400); + surface.HLine(label2.position.x + tw + 6, 620, 430); surface.SetForeground(white); - surface.HLine(label2.position.x + tw + 6, 621, 401); + surface.HLine(label2.position.x + tw + 6, 621, 431); surface.PutPixel(621, 400); } @@ -1087,121 +1271,127 @@ class InstallProgress : Window Installer installer {}; InstallProgress installProgress { autoCreate = false }; -void ModifyPath(char * newPath) +static void AddPath(char * sysPaths[200], int sysCount, char * paths[200], int * count, char * oldPath, char * userPath, char * path) { - char * paths[100]; - int p, count; - char oldPath[4096]; - CoreSDKID c; - - strcpy(oldPath, newPath); - count = TokenizeWith(oldPath, sizeof(paths) / sizeof(char *), paths, ";", false); - - for(c = 0; coreSDK[c].name; c++) + int p; + bool found = false; + for(p = 0; p cfgsToWrite { [ compiler.name ] }; + configs.write(settingsContainer, cfgsToWrite); + delete cfgsToWrite; + } + delete settingsContainer; delete settings; + delete configs; // Set up Uninstaller ((GuiApplication)__thisModule).Lock(); - installProgress.installing.text = $"Registering uninstaller..."; + installProgress.installing.caption = $"Registering uninstaller..."; ((GuiApplication)__thisModule).Unlock(); ((GuiApplication)__thisModule).SignalEvent(); { HKEY key; - uint status, size; - char * displayName = "ECERE SDK 0.44"; + DWORD status; + const char * displayName = "Ecere SDK 0.44"; char uninstaller[MAX_LOCATION]; - bool nomodify = true; + //bool nomodify = true; strcpy(uninstaller, installDir); PathCat(uninstaller, "uninstall_ecere.exe"); - RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ECERE SDK", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); + RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Ecere SDK", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); - RegSetValueEx(key, "DisplayName", 0, REG_SZ, displayName, strlen(displayName)+1); - RegSetValueEx(key, "UninstallString", 0, REG_SZ, uninstaller, strlen(uninstaller)+1); - RegSetValueEx(key, "DisplayIcon", 0, REG_SZ, idePath, strlen(idePath)+1); + RegSetValueEx(key, "DisplayName", 0, REG_SZ, (byte *)displayName, (uint)strlen(displayName)+1); + RegSetValueEx(key, "UninstallString", 0, REG_SZ, (byte *)uninstaller, (uint)strlen(uninstaller)+1); + RegSetValueEx(key, "DisplayIcon", 0, REG_SZ, (byte *)idePath, (uint)strlen(idePath)+1); //RegSetValueEx(key, "NoModify", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify)); //RegSetValueEx(key, "NoRepair", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify)); RegCloseKey(key); } // Add paths - if(pathOptions[PathOptions::AddECEREPaths].selected + if(pathOptions[PathOptions::AddECEREPaths].selected #ifndef NOMINGW || pathOptions[PathOptions::AddMinGWPaths].selected #endif ) { - HKEY key; - uint status, size; - char path[2048] = ""; - uint16 wPath[2048]; + HKEY userKey = null, systemKey = null; + DWORD status, size; + char userPath[8192] = ""; + char systemPath[8192] = ""; + uint16 wUserPath[8192]; + uint16 wSystemPath[8192]; + + wUserPath[0] = 0; + wSystemPath[0] = 0; ((GuiApplication)__thisModule).Lock(); - installProgress.installing.text = "Registering paths..."; + installProgress.installing.caption = "Registering paths..."; ((GuiApplication)__thisModule).Unlock(); ((GuiApplication)__thisModule).SignalEvent(); - - // if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Environment", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS) - - RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); - // RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); - if(status == REG_OPENED_EXISTING_KEY) + + if(options[0].selected) { - size = sizeof(wPath); - RegQueryValueExW(key, L"path", null, null, (byte *)wPath, &size); - UTF16toUTF8Buffer(wPath, path, sizeof(path)); + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, KEY_ALL_ACCESS, &systemKey) == ERROR_SUCCESS) + { + size = sizeof(wSystemPath); + RegQueryValueExW(systemKey, L"path", null, null, (byte *)wSystemPath, &size); + UTF16toUTF8Buffer(wSystemPath, systemPath, sizeof(systemPath)); + ModifyPath(systemPath, null); + + UTF8toUTF16Buffer(systemPath, wSystemPath, sizeof(wSystemPath) / sizeof(uint16)); + RegSetValueExW(systemKey, L"path", 0, REG_EXPAND_SZ, (byte *)wSystemPath, (uint)(wcslen(wSystemPath)+1) * 2); + RegCloseKey(systemKey); + } } - ModifyPath(path); - UTF8toUTF16Buffer(path, wPath, sizeof(wPath) / sizeof(uint16)); - RegSetValueExW(key, L"path", 0, REG_EXPAND_SZ, (byte *)wPath, (wcslen(wPath)+1) * 2); - RegCloseKey(key); + else + { + if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, KEY_QUERY_VALUE, &systemKey) == ERROR_SUCCESS) + { + size = sizeof(wSystemPath); + RegQueryValueExW(systemKey, L"path", null, null, (byte *)wSystemPath, &size); + UTF16toUTF8Buffer(wSystemPath, systemPath, sizeof(systemPath)); + RegCloseKey(systemKey); + } - SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (int)"Environment", SMTO_NORMAL, 1000, NULL); + RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &userKey, &status); + if(status == REG_OPENED_EXISTING_KEY) + { + size = sizeof(wUserPath); + RegQueryValueExW(userKey, L"path", null, null, (byte *)wUserPath, &size); + UTF16toUTF8Buffer(wUserPath, userPath, sizeof(userPath)); + } + ModifyPath(systemPath, userPath); + UTF8toUTF16Buffer(userPath, wUserPath, sizeof(wUserPath) / sizeof(uint16)); + RegSetValueExW(userKey, L"path", 0, REG_EXPAND_SZ, (byte *)wUserPath, (uint)(wcslen(wUserPath)+1) * 2); + RegCloseKey(userKey); + } + // SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment", SMTO_NORMAL, 1000, NULL); } // Install Program Group Icons - // userProfile = getenv("USERPROFILE"); - GetEnvironment("USERPROFILE", userProfile, sizeof(userProfile)); + GetEnvironment(options[0].selected ? "ALLUSERSPROFILE" : "USERPROFILE", userProfile, sizeof(userProfile)); if(options[IconOptions::StartMenuIcon].selected) { @@ -1386,22 +1646,23 @@ class InstallThread : Thread HKEY key; ((GuiApplication)__thisModule).Lock(); - installProgress.installing.text = $"Installing Start Menu Icons..."; + installProgress.installing.caption = $"Installing Start Menu Icons..."; ((GuiApplication)__thisModule).Unlock(); ((GuiApplication)__thisModule).SignalEvent(); strcpy(destPath, userProfile); - if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS) + if(RegOpenKeyEx(options[0].selected ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { uint16 wStartMenuPath[2048]; - uint size = sizeof(wStartMenuPath); + DWORD size = sizeof(wStartMenuPath); // RegQueryValueEx(key, "Start Menu", null, null, startMenuPath, &size); - RegQueryValueExW(key, L"Programs", null, null, (byte *)wStartMenuPath, &size); + RegQueryValueExW(key, options[0].selected ? L"Common Programs" : L"Programs", null, null, (byte *)wStartMenuPath, &size); UTF16toUTF8Buffer(wStartMenuPath, startMenuPath, sizeof(startMenuPath)); RegCloseKey(key); } - if(!startMenuPath[0] && userProfile && userProfile[0]) + if(!startMenuPath[0] && userProfile[0]) { strcpy(startMenuPath, userProfile); PathCat(startMenuPath, "Start Menu\\Programs"); @@ -1410,29 +1671,36 @@ class InstallThread : Thread if(startMenuPath[0]) { strcpy(destPath, startMenuPath); - PathCat(destPath, "ECERE SDK"); + PathCat(destPath, "Ecere SDK"); MakeDir(destPath); strcpy(destPath, startMenuPath); - PathCat(destPath, "ECERE SDK\\ECERE IDE.lnk"); - CreateLink(idePath, destPath, null); //"ECERE IDE"); - if(components[samples].selected) + PathCat(destPath, "Ecere SDK\\Ecere IDE.lnk"); + CreateLink(idePath, destPath, null); //"Ecere IDE"); + if(components[ComponentID::samples].selected) { char samplesPath[MAX_LOCATION] = ""; - components[samples].GetFullPath(samplesPath); + components[ComponentID::samples].GetFullPath(samplesPath, false); strcpy(destPath, startMenuPath); - PathCat(destPath, "ECERE SDK\\Sample Projects.lnk"); + PathCat(destPath, "Ecere SDK\\Sample Projects.lnk"); CreateLink(samplesPath, destPath, null);//"Sample Projects"); } - if(components[documentation].selected && documentation[ecereBook].selected) + if(components[ComponentID::documentation].selected && documentation[DocumentationID::ecereBook].selected) { char docPath[MAX_LOCATION] = ""; - documentation[ecereBook].GetFullPath(docPath); + documentation[DocumentationID::ecereBook].GetFullPath(docPath, false); PathCat(docPath, "Ecere Tao of Programming [work in progress].pdf"); + { + char tao[MAX_LOCATION] ; + documentation[DocumentationID::ecereBook].GetFullPath(tao, false); + PathCat(tao, "tao.pdf"); + RenameFile(tao, docPath); + } + strcpy(destPath, startMenuPath); - PathCat(destPath, "ECERE SDK\\The Ecere Tao of Programming.lnk"); + PathCat(destPath, "Ecere SDK\\The Ecere Tao of Programming.lnk"); CreateLink(docPath, destPath, null); } } @@ -1444,15 +1712,16 @@ class InstallThread : Thread HKEY key; char desktopPath[MAX_LOCATION]; - if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS) + if(RegOpenKeyEx(options[0].selected ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { uint16 wDesktopPath[MAX_LOCATION]; - uint size = sizeof(wDesktopPath); - RegQueryValueExW(key, L"Desktop", null, null, (byte *)wDesktopPath, &size); + DWORD size = sizeof(wDesktopPath); + RegQueryValueExW(key, options[0].selected ? L"Common Desktop" : L"Desktop", null, null, (byte *)wDesktopPath, &size); UTF16toUTF8Buffer(wDesktopPath, desktopPath, sizeof(desktopPath)); RegCloseKey(key); } - if(!desktopPath[0] && userProfile && userProfile[0]) + if(!desktopPath[0] && userProfile[0]) { strcpy(desktopPath, userProfile); PathCat(desktopPath, "Desktop"); @@ -1460,36 +1729,55 @@ class InstallThread : Thread if(desktopPath[0]) { - PathCat(desktopPath, "ECERE IDE.lnk"); + PathCat(desktopPath, "Ecere IDE.lnk"); ((GuiApplication)__thisModule).Lock(); - installProgress.installing.text = $"Installing Desktop Icon..."; + installProgress.installing.caption = $"Installing Desktop Icon..."; ((GuiApplication)__thisModule).Unlock(); ((GuiApplication)__thisModule).SignalEvent(); - CreateLink(idePath, desktopPath, null);//"ECERE IDE"); + CreateLink(idePath, desktopPath, null);//"Ecere IDE"); } } + SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment", SMTO_NORMAL, 1000, NULL); + // Install QuickLaunch Icon if(options[IconOptions::QuickLaunchIcon].selected) { - char appData[MAX_LOCATION]; // = getenv("APPDATA"); + char appData[MAX_LOCATION]; GetEnvironment("APPDATA", appData, sizeof(appData)); - - if(appData && appData[0]) + if(appData[0]) { char destPath[MAX_LOCATION]; + if(appData[0] && options[0].selected) + { + char dir[MAX_FILENAME]; + GetLastDirectory(appData, dir); + if(!strcmpi(dir, "Roaming")) + PathCat(appData, "../../../Default/AppData/Roaming"); + else + PathCat(appData, "../Default"); + } + ((GuiApplication)__thisModule).Lock(); - installProgress.installing.text = $"Installing Quicklaunch Icon..."; + installProgress.installing.caption = $"Installing Quicklaunch Icon..."; ((GuiApplication)__thisModule).Unlock(); ((GuiApplication)__thisModule).SignalEvent(); strcpy(destPath, appData); - PathCat(destPath, "Microsoft\\Internet Explorer\\Quick Launch\\ECERE IDE.lnk"); + PathCat(destPath, "Microsoft\\Internet Explorer\\Quick Launch\\Ecere IDE.lnk"); + CreateLink(idePath, destPath, null); - CreateLink(idePath, destPath, null);//"ECERE IDE"); + // Set it up on the dock for Windows 7 -- not working + /* + StripLastDirectory(destPath, destPath); + PathCat(destPath, "User Pinned\\TaskBar"); + MakeDir(destPath); + PathCat(destPath, "Ecere IDE.lnk"); + CreateLink(idePath, destPath, null); + */ } } @@ -1503,13 +1791,13 @@ class InstallThread : Thread associateOptions[AssociateOptions::AssociateIMG].selected) { ((GuiApplication)__thisModule).Lock(); - installProgress.installing.text = $"Resgistering File Types..."; + installProgress.installing.caption = $"Registering File Types..."; ((GuiApplication)__thisModule).Unlock(); ((GuiApplication)__thisModule).SignalEvent(); - + if(associateOptions[AssociateOptions::AssociateEPJ].selected) { - AssociateExtension(".epj", "ECERE IDE Project", "epj_file", "Open", idePath); + AssociateExtension(".epj", "Ecere IDE Project", "epj_file", "Open", idePath); } if(associateOptions[AssociateOptions::AssociateEC].selected) { @@ -1551,11 +1839,11 @@ class InstallThread : Thread ((GuiApplication)__thisModule).Lock(); installProgress.cancel.Destroy(0); - installProgress.finish.text = $"Finish"; + installProgress.finish.caption = $"Finish"; installProgress.finish.disabled = false; installProgress.finish.Activate(); - installProgress.installing.text = $"Installation Complete."; - installProgress.title.text = $"Installation Complete"; + installProgress.installing.caption = $"Installation Complete."; + installProgress.title.caption = $"Installation Complete"; installProgress.titleInfo.contents = $"Thank you for using the Ecere SDK."; } ((GuiApplication)__thisModule).Unlock();