X-Git-Url: https://ecere.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=installer%2Fsrc%2Finstaller.ec;h=fb05b35ecb111f78d5d16ce6350f8a547a41ed98;hb=cf37e3addcf039065340e429f0c3e1cf30849bb2;hp=02d8ad8e04aed2e22ef7e2e9dd6f891cb4fe52b2;hpb=8ee80ec2b5c2317d48ff1ac4b3a886a5d1bed7aa;p=sdk diff --git a/installer/src/installer.ec b/installer/src/installer.ec index 02d8ad8..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.08 (Without MinGW) -- built on August 9, 2013 "; -#else -static define buildString = $"Ecere SDK v0.44.08 -- built on August 9, 2013 "; -#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 @@ -19,12 +18,41 @@ import "createLink" import "licensing" import "CheckListBox" +static void SetBuildString(Label label) +{ + static const String addMinGW = ""; + String s; + +#ifdef NOMINGW + addMinGW = withoutMinGW; +#endif + + s = PrintString(versionString, addMinGW, " -- ", builtOnString, dateString); + label.caption = s; + delete s; +} + +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) + { + if(!CheckTokenMembership(NULL, AdministratorsGroup, &b)) + b = FALSE; + FreeSid(AdministratorsGroup); + } + return b == TRUE; +} + struct CheckItem { - char * name; + const char * name; void * data; bool add32Bit; - char * OnGetString(char * tempString, void * fieldData, bool * needClass) + const char * OnGetString(char * tempString, void * fieldData, bool * needClass) { if(add32Bit) { @@ -46,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); @@ -154,9 +182,9 @@ 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; @@ -175,7 +203,7 @@ struct Component if(this != null && parent) parent->GetFullPath(path, is32bit || (arch == bits32 && osIS64bit)); else - strcpy(path, (is32bit || (arch == bits32 && osIS64bit)) ? installDir32 : installDir); + strcpy(path, (this && (is32bit || (arch == bits32 && osIS64bit))) ? installDir32 : installDir); if(this != null) PathCat(path, installPath); @@ -216,10 +244,7 @@ struct Component PathCat(path, name); } if(requiredSize) - { - uint p = installProgress.progressBar.progress; ExtractFileFromArchive(installProgress.progressBar, source, path); - } } if(subComponents) { @@ -236,65 +261,64 @@ define minGWIncluded = true; define minGWIncluded = false; #endif -Component samples[] = -{ - { "Ecere Chess", "samples/chess", "chess", null, false, true, true, none }, - { "Ecere Fractals", "samples/fractals", "fractals", null, false, true, true, none }, +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 }, + { $"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 } + { $"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, ide32, runtime, runtime32, ec, ec32, - gcc, gdb, gdb32, mingw, binutils, make, + gcc, gdb, mingw, binutils, make, none }; -Component coreSDK[CoreSDKID] = -{ - { "Ecere IDE", "ecere-sdk/ide", "bin", null, true, true, true, bits64 }, - { "Ecere IDE", "ecere-sdk32/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, bits64 }, - { "GNU Debugger", "tdm/gdb32", "tdm", null, true, true, minGWIncluded, bits32 }, - { "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 }, +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 } -}; +] }; public enum AdditionalID { - eda, eda32, vanilla, vanilla32, extras, upx, gnurx, gnurx32, /*pthreads, */cpp, /*w32api, gcci18n, gdbi18n, makei18n, binutilsi18n, */none + eda, eda32, audio, audio32, vanilla, vanilla32, extras, upx, gnurx, gnurx32, /*pthreads, */cpp, /*w32api, gcci18n, gdbi18n, makei18n, binutilsi18n, */none }; -Component additional[AdditionalID] = -{ - { "Data Access", "ecere-sdk/eda", "bin", null, false, true, true, bits64 }, - { "Data Access", "ecere-sdk32/eda", "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 }, +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 }, + { $"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 }, + { $"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 }, @@ -302,31 +326,29 @@ Component additional[AdditionalID] = { "Binutils I18n", "mingw/locale/binutils", "tdm", null, false, false, minGWIncluded, none }, */ { null } -}; +] }; public enum DocumentationID { - ecereBook, apiRef, tutorials, coursework, + ecereBook, apiRef, coursework, gccDoc, gppDocs, gdbDocs, makeDocs, binDocs, mingwDocs, gnurxDocs, upxDocs, none }; -Component documentation[DocumentationID] = -{ - { "Ecere Book", "ecere-sdk/book", "doc", null, false, true, true, none }, - { "API Reference", "ecere-sdk/doc", "doc", null, false, true, true, none }, - { "Ecere Tutorials", "ecere-sdk/tutorials", "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 }, - { "MinGW Docs", "tdm/doc/mingwrt", "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 }, +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 { @@ -337,20 +359,20 @@ public enum ComponentID none }; -Component components[ComponentID] = -{ - { "Core SDK Files", null, null, coreSDK, true, true, true, none }, - { "Additional Support", null, null, additional, false, true, true, none }, - { "Documentation", null /*"doc"*/, null /*"doc"*/, documentation, false, true, true, none }, - { "Samples", null, "samples", samples, false, true, true, none }, +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; @@ -368,46 +390,47 @@ 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, AddMinGWPaths }; -InstallOption pathOptions[] = -{ - { "Add Ecere binaries location to the user environment path", null, true, true }, - { "Add MinGW to the user environment path", null, true, minGWIncluded } +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, true }, - { "Desktop Icon", null, true, true }, - { "Quicklaunch Icon", null, true, true }, - { "Associate the Ecere IDE with Supported File Types", associateOptions, true, true }, - { "Add binaries location to the user environment paths", pathOptions, true, minGWIncluded }, +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]; @@ -416,32 +439,37 @@ bool osIS64bit; class Installer : Window { - text = $"Ecere Software Development Kit Setup - v0.44.08 \"Ryōan-ji\" 64 Bit Edition"; - background = activeBorder; + background = formColor; borderStyle = fixed; hasMinimize = true; hasClose = true; tabCycle = true; - clientSize = { 636, 456 }; - // clientSize = { 796, 576 }; + 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, 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, false); - 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) { @@ -457,6 +485,8 @@ class Installer : Window { 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 }; @@ -484,7 +514,10 @@ class Installer : Window if(newPath) { PathCat(fullPath, newPath); - MakePathRelative(fullPath, path, relative); + if(IsPathInsideOf(fullPath, path)) + MakePathRelative(fullPath, path, relative); + else + strcpy(relative, fullPath); } listBox.SetData(locationField, relative); strcpy(component->installPath, relative); @@ -552,17 +585,17 @@ class Installer : Window { 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) @@ -572,9 +605,10 @@ 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; @@ -585,11 +619,65 @@ class Installer : Window CheckItem * item = row.GetData(optionField); InstallOption * option = item->data; 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) { @@ -600,11 +688,43 @@ 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; @@ -662,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" @@ -670,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) @@ -695,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 } }; + 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 = 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; @@ -724,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); @@ -744,7 +864,7 @@ class Installer : Window return size; } - void AddComponent(Component component, Component parent, char * parentPath) + void AddComponent(Component component, Component parent, const char * parentPath) { DataRow row = (parent != null) ? parent.row.AddRow() : componentsBox.AddRow(); FileSize size = 0; @@ -839,11 +959,50 @@ class Installer : Window 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); @@ -851,15 +1010,22 @@ class Installer : Window optionsBox.AddField(optionField); + languageBox.AddField(languageField); + + programFilesDir[0] = 0; if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION)) { - char * x86 = strstr(programFilesDir, " (x86)"); + x86 = strstr(programFilesDir, " (x86)"); + if(x86) + osIS64bit = true; + } + + if(isAdministrator && programFilesDir[0]) + { if(x86) { strcpy(installDir32, programFilesDir); PathCat(installDir32, "Ecere SDK"); - osIS64bit = true; - *x86 = 0; strcpy(installDir, programFilesDir); PathCat(installDir, "Ecere SDK"); @@ -871,30 +1037,38 @@ class Installer : Window strcpy(installDir32, installDir); } } - else if(homeDrive && homeDrive[0]) + else if(homeDrive[0]) { strcpy(installDir, homeDrive); 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"); + strcpy(installDir32, installDir); + strcat(installDir32, " (32)"); } else + { strcpy(installDir, "C:\\Ecere SDK"); + strcpy(installDir32, installDir); + strcat(installDir32, " (32)"); + } - if(appData && appData[0]) + 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; + components[ComponentID::samples].defInstallPath = defSamplesPath; strcpy(defExtrasPath, appData); PathCat(defExtrasPath, "Ecere SDK\\extras"); - additional[extras].defInstallPath = defExtrasPath; + additional[AdditionalID::extras].defInstallPath = defExtrasPath; } destBox.path = installDir; @@ -915,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; } @@ -931,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 }; @@ -945,29 +1194,34 @@ class Installer : Window class InstallProgress : Window { - text = $"Ecere Software Development Kit Setup - v0.44.08 \"Ryōan-ji\" 64 Bit Edition"; + 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 }; - clientSize = { 636, 456 }; + 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) { @@ -981,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 }; @@ -993,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); } @@ -1056,17 +1310,24 @@ static void AddPath(char * sysPaths[200], int sysCount, char * paths[200], int * void ModifyPath(char * systemPath, char * userPath) { char oldPath[8192], * paths[200], * sysPaths[200]; - int count, sysCount; + int count, sysCount = 0; - strcpy(oldPath, userPath); - count = TokenizeWith(oldPath, sizeof(paths) / sizeof(char *), paths, ";", false); - sysCount = TokenizeWith(systemPath, sizeof(sysPaths) / sizeof(char *), sysPaths, ";", false); + if(userPath) + { + strcpy(oldPath, userPath); + count = TokenizeWith(oldPath, sizeof(paths) / sizeof(char *), paths, ";", false); + sysCount = TokenizeWith(systemPath, sizeof(sysPaths) / sizeof(char *), sysPaths, ";", false); + } + else + { + strcpy(oldPath, systemPath); + count = TokenizeWith(oldPath, sizeof(paths) / sizeof(char *), paths, ";", false); + } { CoreSDKID c; for(c = 0; coreSDK[c].name; c++) { - bool found = false; char path[MAX_LOCATION]; if(!coreSDK[c].selected) continue; coreSDK[c].GetFullPath(path, false); @@ -1079,7 +1340,7 @@ void ModifyPath(char * systemPath, char * userPath) } else if(!pathOptions[PathOptions::AddECEREPaths].selected) continue; - AddPath(sysPaths, sysCount, paths, &count, oldPath, userPath, path); + AddPath(sysPaths, sysCount, paths, &count, oldPath, userPath ? userPath : systemPath, path); } } { @@ -1087,44 +1348,43 @@ void ModifyPath(char * systemPath, char * userPath) // Up to C++ for(c = 0; c <= cpp; c++) { - bool found = false; char path[MAX_LOCATION]; if(!additional[c].selected || c == vanilla || c == vanilla32 || c == extras) continue; if((c != eda && c != eda32 && c != upx) && (!pathOptions[PathOptions::AddMinGWPaths].available || !pathOptions[PathOptions::AddMinGWPaths].selected)) continue; additional[c].GetFullPath(path, false); - if(c != eda && c != eda32 && c != upx) + if(c != eda && c != eda32 && c != upx && c != audio && c != audio32) PathCat(path, "bin"); - AddPath(sysPaths, sysCount, paths, &count, oldPath, userPath, path); + AddPath(sysPaths, sysCount, paths, &count, oldPath, userPath ? userPath : systemPath, path); } } } -void AssociateExtension(char * extension, char * description, char *name, char * action, char * path) +void AssociateExtension(const char * extension, const char * description, const char *name, const char * action, const char * path) { HKEY key; - uint status, size; + DWORD status; char keyName[1024]; - RegCreateKeyEx(HKEY_CLASSES_ROOT, extension, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); - RegSetValueEx(key, null, 0, REG_SZ, name, (uint)strlen(name)+1); + RegCreateKeyEx(HKEY_CLASSES_ROOT, extension, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); + RegSetValueEx(key, null, 0, REG_SZ, (byte *)name, (uint)strlen(name)+1); RegCloseKey(key); - RegCreateKeyEx(HKEY_CLASSES_ROOT, name, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); - RegSetValueEx(key, null, 0, REG_SZ, description, (uint)strlen(description)+1); + RegCreateKeyEx(HKEY_CLASSES_ROOT, name, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); + RegSetValueEx(key, null, 0, REG_SZ, (byte *)description, (uint)strlen(description)+1); RegCloseKey(key); sprintf(keyName, "%s\\shell", extension); - RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); - RegSetValueEx(key, null, 0, REG_SZ, action, (uint)strlen(action)+1); + RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); + RegSetValueEx(key, null, 0, REG_SZ, (byte *)action, (uint)strlen(action)+1); RegCloseKey(key); sprintf(keyName, "%s\\shell\\%s", name, action); - RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); + RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); RegCloseKey(key); sprintf(keyName, "%s\\shell\\%s\\command", name, action); - RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); + RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); sprintf(keyName, path); strcat(keyName, " \"%L\""); @@ -1143,18 +1403,22 @@ class InstallThread : Thread ComponentID c; ((GuiApplication)__thisModule).Lock(); installProgress.progressBar.range = totalSize; + + if(!osIS64bit) + strcpy(installDir32, installDir); + for(c = 0; components[c].name && !abortInstall; c++) components[c].Install(installDir, installDir32); if(abortInstall) { installProgress.progressBar.range = 0; installProgress.finish.Destroy(0); - installProgress.cancel.text = $"Close"; + installProgress.cancel.caption = $"Close"; installProgress.cancel.isDefault = true; installProgress.cancel.disabled = false; installProgress.cancel.NotifyClicked = Window::ButtonCloseDialog; - installProgress.installing.text = $"Installation Cancelled."; - installProgress.title.text = $"Installation Cancelled"; + installProgress.installing.caption = $"Installation Cancelled."; + installProgress.title.caption = $"Installation Cancelled"; installProgress.titleInfo.contents = $"The installation was not completed."; } else @@ -1164,20 +1428,24 @@ class InstallThread : Thread // Configure IDE IDESettings settings = null; // Don't instantiate yet so we can pick up old settings + CompilerConfigs configs { }; IDESettingsContainer settingsContainer { driver = "JSON"; dataOwner = &settings; dataClass = class(IDESettings); + allUsers = options[0].selected; }; CompilerConfig compiler; - installProgress.installing.text = $"Configuring Ecere IDE..."; + installProgress.installing.caption = $"Configuring Ecere IDE..."; ((GuiApplication)__thisModule).Unlock(); ((GuiApplication)__thisModule).SignalEvent(); settingsContainer.Load(); - compiler = settings.GetCompilerConfig(defaultCompilerName); + configs.read(settingsContainer); + + compiler = configs.GetCompilerConfig(defaultCompilerName); if(compiler) { { @@ -1195,7 +1463,7 @@ class InstallThread : Thread if((c == ide && osIS64bit) || (c == ide32 && !osIS64bit)) { coreSDK[c].GetFullPath(idePath, false); - PathCat(idePath, "ide.exe"); + PathCat(idePath, "ecere-ide.exe"); } if(c == runtime || c == runtime32) @@ -1233,49 +1501,75 @@ class InstallThread : Thread { char path[MAX_LOCATION] = ""; - if(components[samples].selected) - components[samples].GetFullPath(path, false); - else - components[coreSDK].GetFullPath(path, false); + if(components[ComponentID::samples].selected) + components[ComponentID::samples].GetFullPath(path, false); + // IDE will now default to HOME for the default project/files locations if(!settings.ideProjectFileDialogLocation[0]) settings.ideProjectFileDialogLocation = path; if(!settings.ideFileDialogLocation[0]) settings.ideFileDialogLocation = path; - if(documentation[apiRef].selected) + if(documentation[DocumentationID::apiRef].selected) { - documentation[apiRef].GetFullPath(path, false); + documentation[DocumentationID::apiRef].GetFullPath(path, false); if(!settings.docDir[0]) settings.docDir = path; } } + settings.language = GetLanguageString(); + + // Set LANGUAGE environment variable + { + HKEY key = null; + uint16 wLanguage[256]; + DWORD status; + wLanguage[0] = 0; + + if(options[0].selected) + RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, KEY_ALL_ACCESS, &key); + else + RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status); + if(key) + { + UTF8toUTF16Buffer(settings.language, wLanguage, sizeof(wLanguage) / sizeof(uint16)); + RegSetValueExW(key, L"ECERE_LANGUAGE", 0, REG_EXPAND_SZ, (byte *)wLanguage, (uint)(wcslen(wLanguage)+1) * 2); + RegCloseKey(key); + } + } + settingsContainer.Save(); + { + AVLTree 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, (uint)strlen(displayName)+1); - RegSetValueEx(key, "UninstallString", 0, REG_SZ, uninstaller, (uint)strlen(uninstaller)+1); - RegSetValueEx(key, "DisplayIcon", 0, REG_SZ, idePath, (uint)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); @@ -1289,7 +1583,7 @@ class InstallThread : Thread ) { HKEY userKey = null, systemKey = null; - uint status, size; + DWORD status, size; char userPath[8192] = ""; char systemPath[8192] = ""; uint16 wUserPath[8192]; @@ -1299,35 +1593,51 @@ class InstallThread : Thread 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, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, KEY_QUERY_VALUE, &systemKey) == ERROR_SUCCESS) + if(options[0].selected) { - size = sizeof(wSystemPath); - RegQueryValueExW(systemKey, L"path", null, null, (byte *)wSystemPath, &size); - UTF16toUTF8Buffer(wSystemPath, systemPath, sizeof(systemPath)); + 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); + } } - - RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &userKey, &status); - if(status == REG_OPENED_EXISTING_KEY) + else { - 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); - RegCloseKey(systemKey); + 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 - GetEnvironment("USERPROFILE", userProfile, sizeof(userProfile)); + GetEnvironment(options[0].selected ? "ALLUSERSPROFILE" : "USERPROFILE", userProfile, sizeof(userProfile)); if(options[IconOptions::StartMenuIcon].selected) { @@ -1336,18 +1646,19 @@ 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); } @@ -1366,24 +1677,24 @@ class InstallThread : Thread strcpy(destPath, startMenuPath); PathCat(destPath, "Ecere SDK\\Ecere IDE.lnk"); CreateLink(idePath, destPath, null); //"Ecere IDE"); - if(components[samples].selected) + if(components[ComponentID::samples].selected) { char samplesPath[MAX_LOCATION] = ""; - components[samples].GetFullPath(samplesPath, false); + components[ComponentID::samples].GetFullPath(samplesPath, false); strcpy(destPath, startMenuPath); 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, false); + documentation[DocumentationID::ecereBook].GetFullPath(docPath, false); PathCat(docPath, "Ecere Tao of Programming [work in progress].pdf"); { char tao[MAX_LOCATION] ; - documentation[ecereBook].GetFullPath(tao, false); + documentation[DocumentationID::ecereBook].GetFullPath(tao, false); PathCat(tao, "tao.pdf"); RenameFile(tao, docPath); } @@ -1401,11 +1712,12 @@ 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); } @@ -1420,7 +1732,7 @@ class InstallThread : Thread 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(); @@ -1428,25 +1740,44 @@ class InstallThread : Thread } } + SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment", SMTO_NORMAL, 1000, NULL); + // Install QuickLaunch Icon if(options[IconOptions::QuickLaunchIcon].selected) { char appData[MAX_LOCATION]; GetEnvironment("APPDATA", appData, sizeof(appData)); - 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"); + 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); + */ } } @@ -1460,7 +1791,7 @@ 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(); @@ -1508,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();