2 static define buildString = $"Ecere SDK v0.44.10 (Without MinGW) -- built on March 2nd, 2014 ";
4 static define buildString = $"Ecere SDK v0.44.10 -- built on March 2nd, 2014 ";
7 #define WIN32_LEAN_AND_MEAN
8 #define GetFreeSpace _GetFreeSpace
27 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
31 strcpy(tempString, name);
32 strcat(tempString, " (32)");
38 void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)
40 if(!displayFlags.active) { displayFlags.current = false; displayFlags.selected = false; }
41 class::OnDisplay(surface, x + 22, y, width - 22, fieldData, alignment, displayFlags);
45 //#define BUFFERSIZE 0x10000
46 #define BUFFERSIZE 0x1000
47 bool abortInstall = false;
49 void ExtractFileFromArchive(ProgressBar progressBar, char * path, char * outputFile)
51 char fileName[MAX_LOCATION];
52 FileAttribs exists = FileExists(path);
56 if(exists.isDirectory)
58 FileListing listing { path };
62 if(MakeDir(outputFile))
65 FileGetStats(path, &stats);
69 while(listing.Find() && !abortInstall)
71 strcpy(fileName, outputFile);
73 // Tweak file name if out
76 if(!strcmp(fileName, ".")) fileName[0] = '\0';
77 if(listing.name[0] == '/' || listing.name[0] == '\\')
79 char * afterSlash, rest[MAX_LOCATION];
80 for(afterSlash = fileName; *afterSlash == '/' || *afterSlash == '\\'; afterSlash++);
81 strcpy(rest, afterSlash);
82 PathCat(fileName, "_root");
83 PathCat(fileName, rest);
85 else if(listing.name[1] == ':')
88 sprintf(letter, "_%cdrive", toupper(listing.name[0]));
89 PathCat(fileName, letter);
90 PathCat(fileName, listing.name[2] ? (listing.name + 3) : (listing.name + 2));
93 PathCat(fileName, listing.name);
96 PathCat(fileName, listing.name);
97 if(!strcmp(fileName, "/") || !strcmp(fileName, "\\"))
98 strcpy(fileName, DIR_SEPS);
99 ExtractFileFromArchive(progressBar, listing.path, fileName);
105 File input = FileOpen(path, read);
108 File output = FileOpen(outputFile, write);
111 char fileName[MAX_FILENAME];
112 uint position = progressBar.progress;
115 byte buffer[BUFFERSIZE];
117 FileGetSize(path, &dataSize);
118 GetLastDirectory(outputFile, fileName);
120 ((GuiApplication)__thisModule).SignalEvent();
121 //((GuiApplication)__thisModule).ProcessInput();
122 //((GuiApplication)__thisModule).UpdateDisplay();
124 for(c = 0; c<dataSize && !abortInstall; c += BUFFERSIZE)
126 uint size = (dataSize > c + BUFFERSIZE) ? BUFFERSIZE : (dataSize - c);
128 ((GuiApplication)__thisModule).Unlock();
130 input.Read(buffer, 1, size);
131 output.Write(buffer, 1, size);
133 ((GuiApplication)__thisModule).Lock();
135 progressBar.progress = position + c + size;
136 ((GuiApplication)__thisModule).SignalEvent();
138 //((GuiApplication)__thisModule).ProcessInput();
139 //((GuiApplication)__thisModule).UpdateDisplay();
144 FileGetStats(path, &stats);
150 FileSetTime(outputFile, stats.created, 0, stats.modified);
153 public enum BitArch { none, bits32, bits64 };
159 char * defInstallPath;
160 Component * subComponents;
170 char installPath[MAX_LOCATION];
173 void GetFullPath(char * path, bool is32bit)
175 if(this != null && parent)
176 parent->GetFullPath(path, is32bit || (arch == bits32 && osIS64bit));
178 strcpy(path, (is32bit || (arch == bits32 && osIS64bit)) ? installDir32 : installDir);
181 PathCat(path, installPath);
184 void Install(char * parentPath, char * parentPath32)
187 if(selected && (arch == none || arch == bits32 || osIS64bit))
189 char path64[MAX_LOCATION];
190 char path32[MAX_LOCATION];
191 strcpy(path64, parentPath);
192 PathCat(path64, installPath);
194 strcpy(path32, parentPath32);
195 PathCat(path32, installPath);
197 installProgress.installing.SetText($"Installing %s...", name);
198 ((GuiApplication)__thisModule).UpdateDisplay();
202 char * path = path64;
203 char source[MAX_LOCATION];
205 strcat(source, dataPath);
212 if(FileExists(source).isFile)
214 char name[MAX_FILENAME];
215 GetLastDirectory(source, name);
220 uint p = installProgress.progressBar.progress;
221 ExtractFileFromArchive(installProgress.progressBar, source, path);
226 for(c = 0; subComponents[c].name; c++)
227 subComponents[c].Install(path64, path32);
234 define minGWIncluded = true;
236 define minGWIncluded = false;
239 Component samples[] =
241 { "Ecere Chess", "samples/chess", "chess", null, false, true, true, none },
242 { "Ecere Fractals", "samples/fractals", "fractals", null, false, true, true, none },
243 { "3D", "samples/3D", "3D", null, false, true, true, none },
244 { "Android", "samples/android", "android", null, false, true, true, none },
245 { "Audio", "samples/audio", "audio", null, false, true, true, none },
246 { "Database", "samples/db", "db", null, false, true, true, none },
247 { "eC", "samples/eC", "eC", null, false, true, true, none },
248 { "Games", "samples/games", "games", null, false, true, true, none },
249 { "GUI & Graphics", "samples/guiAndGfx", "guiAndGfx", null, false, true, true, none },
250 { "Miscellaneous", "samples/misc", "misc", null, false, true, true, none },
251 { "Networking", "samples/net", "net", null, false, true, true, none },
252 { "WIA Scanning", "samples/scanning", "scanning", null, false, true, true, none },
253 { "Threading", "samples/threads", "threads", null, false, true, true, none }
257 public enum CoreSDKID
259 ide, ide32, runtime, runtime32, ec, ec32,
260 gcc, gdb, gdb32, mingw, binutils, make,
264 Component coreSDK[CoreSDKID] =
266 { "Ecere IDE", "ecere-sdk/ide", "bin", null, true, true, true, bits64 },
267 { "Ecere IDE", "ecere-sdk32/ide", "bin", null, true, true, true, bits32 },
268 { "Runtime Library", "ecere-sdk/ecere.dll", "bin", null, true, true, true, bits64 },
269 { "Runtime Library", "ecere-sdk32/ecere.dll", "bin", null, true, true, true, bits32 },
270 { "eC Compiler", "ecere-sdk/compiler", "bin", null, true, true, true, bits64 },
271 { "eC Compiler", "ecere-sdk32/compiler", "bin", null, true, true, true, bits32 },
272 { "GNU C Compiler", "tdm/gcc/core", "tdm", null, true, true, minGWIncluded, none },
273 { "GNU Debugger", "tdm/gdb", "tdm", null, true, true, minGWIncluded, bits64 },
274 { "GNU Debugger", "tdm/gdb32", "tdm", null, true, true, minGWIncluded, bits32 },
275 { "MinGW-w64 Runtime", "tdm/mingwrt", "tdm", null, true, true, minGWIncluded, none },
276 { "Binary Utils", "tdm/binutils", "tdm", null, true, true, minGWIncluded, none },
277 { "GNU Make", "tdm/make", "tdm", null, true, true, minGWIncluded, none },
281 public enum AdditionalID
283 eda, eda32, vanilla, vanilla32, extras, upx, gnurx, gnurx32, /*pthreads, */cpp, /*w32api, gcci18n, gdbi18n, makei18n, binutilsi18n, */none
286 Component additional[AdditionalID] =
288 { "Data Access", "ecere-sdk/eda", "bin", null, false, true, true, bits64 },
289 { "Data Access", "ecere-sdk32/eda", "bin", null, false, true, true, bits32 },
290 { "Ecere Vanilla", "ecere-sdk/libecereVanilla.a", "lib", null, false, true, true, bits64 },
291 { "Ecere Vanilla", "ecere-sdk32/libecereVanilla.a", "lib", null, false, true, true, bits32 },
292 { "Ecere Extras", "extras", "extras", null, false, true, true, none },
293 { "UPX", "upx/bin", "upx/bin", null, false, true, true, none },
294 { "GNU Regexp", "tdm/gnurx", "tdm", null, false, true, true, bits64 },
295 { "GNU Regexp", "tdm/gnurx32", "tdm", null, false, true, true, bits32 },
296 // { "pthreads", "tdm/pthreads", "mingw", null, false, true, minGWIncluded, none },
297 { "C++ Compiler", "tdm/gcc/c++", "tdm", null, false, true, minGWIncluded, none },
298 // { "Win32 APIs", "mingw/w32api", "mingw", null, false, true, minGWIncluded, none },
299 /* { "GCC I18n", "mingw/locale/gcc", "tdm", null, false, false, minGWIncluded, none },
300 { "GDB I18n", "mingw/locale/gdb", "tdm", null, false, false, minGWIncluded, none },
301 { "Make I18n", "mingw/locale/make", "tdm", null, false, false, minGWIncluded, none },
302 { "Binutils I18n", "mingw/locale/binutils", "tdm", null, false, false, minGWIncluded, none },
307 public enum DocumentationID
309 ecereBook, apiRef, tutorials, coursework,
310 gccDoc, gppDocs, gdbDocs, makeDocs, binDocs, mingwDocs, gnurxDocs, upxDocs,
314 Component documentation[DocumentationID] =
316 { "Ecere Book", "ecere-sdk/book", "doc", null, false, true, true, none },
317 { "API Reference", "ecere-sdk/doc", "doc", null, false, true, true, none },
318 { "Ecere Tutorials", "ecere-sdk/tutorials", "doc", null, false, true, true, none },
319 { "Ecere Coursework", "ecere-sdk/coursework", "doc", null, false, true, true, none },
320 { "GCC Docs", "tdm/doc/gcc", "tdm", null, false, false, minGWIncluded, none },
321 { "G++ Docs", "tdm/doc/g++", "tdm", null, false, false, minGWIncluded, none },
322 { "GDB Docs", "tdm/doc/gdb", "tdm", null, false, false, minGWIncluded, none },
323 { "Make Docs", "tdm/doc/make", "tdm", null, false, false, minGWIncluded, none },
324 { "Binutils Docs", "tdm/doc/binutils", "tdm", null, false, false, minGWIncluded, none },
325 { "gnurx Docs", "tdm/doc/gnurx", "tdm", null, false, false, minGWIncluded, none },
326 { "UPX Docs", "upx/doc", "upx/doc", null, false, false, minGWIncluded, none },
330 public enum ComponentID
339 Component components[ComponentID] =
341 { "Core SDK Files", null, null, coreSDK, true, true, true, none },
342 { "Additional Support", null, null, additional, false, true, true, none },
343 { "Documentation", null /*"doc"*/, null /*"doc"*/, documentation, false, true, true, none },
344 { "Samples", null, "samples", samples, false, true, true, none },
348 FileSize totalInstalled;
353 InstallOption * subOptions;
359 enum AssociateOptions
370 InstallOption associateOptions[] =
372 { "Associate with Ecere Project Files (*.epj)", null, true },
373 { "Associate with eC Files (*.ec, *.eh)", null, true },
374 { "Associate with C files (*.c, *.h)", null, false },
375 { "Associate with C++ Files (*.cpp, *.hpp, *.cc, *.hh, *.cxx, *.hxx)", null, false },
376 { "Associate with text files (*.txt)", null, false },
377 { "Associate with 3D Studio Model Files (*.3ds)", null, true },
378 { "Associate with Image Files (*.png, *.jpg, *.pcx, *.bmp, *.gif)", null, false },
384 AddECEREPaths, AddMinGWPaths
387 InstallOption pathOptions[] =
389 { "Add Ecere binaries location to the user environment path", null, true, true },
390 { "Add MinGW to the user environment path", null, true, minGWIncluded }
401 InstallOption options[] =
403 { "Start Menu Group", null, true, true },
404 { "Desktop Icon", null, true, true },
405 { "Quicklaunch Icon", null, true, true },
406 { "Associate the Ecere IDE with Supported File Types", associateOptions, true, true },
407 { "Add binaries location to the user environment paths", pathOptions, true, minGWIncluded },
411 char sourceDir[MAX_LOCATION] = ":";
412 char installDir[MAX_LOCATION];
413 char installDir32[MAX_LOCATION];
416 class Installer : Window
418 text = $"Ecere Software Development Kit Setup - v0.44.10 \"Ryōan-ji\" 64 Bit Edition";
419 background = activeBorder;
424 clientSize = { 636, 456 };
425 // clientSize = { 796, 576 };
426 icon = { ":icon.png" };
428 Picture back { image = BitmapResource { ":ryoanji.png" }, parent = this, position = { 0, 0 } };
429 FileDialog fileDialog
431 master = this, type = selectDir,
432 text = $"Select a new location"
436 master = this, autoCreate = false, inactive = true, text = "...";
438 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
440 DataRow row = componentsBox.currentRow;
441 Component * component = ((CheckItem *)row.GetData(componentField))->data;
442 component->GetFullPath(fileDialog.filePath, false);
443 StripLastDirectory(fileDialog.filePath, fileDialog.currentDirectory);
445 if(fileDialog.Modal() == ok)
447 componentsBox.StopEditing(false);
448 row.SetData(locationField, fileDialog.filePath);
449 componentsBox.NotifyChanged(this, componentsBox, row);
450 componentsBox.currentField = componentsBox.currentField;
455 CheckListBox componentsBox
457 this, size = { 460, 112 }, position = { 160, 160 }, hasHeader = true;
458 fullRowSelect = false, collapseControl = true, treeBranches = true, rootCollapseButton = true,
461 selectionColor = { 145, 150, 140 };
466 bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch)
468 if(key == f2 && browse.visible)
469 browse.NotifyClicked(this, browse, 0, 0, 0);
473 bool NotifyChanged(ListBox listBox, DataRow row)
475 Component * component = ((CheckItem *)listBox.GetData(componentField))->data;
476 char path[MAX_LOCATION], relative[MAX_LOCATION] = "", * newPath;
477 char fullPath[MAX_LOCATION];
479 component->parent->GetFullPath(path, false);
480 strcpy(fullPath, path);
482 newPath = row.GetData(locationField);
485 PathCat(fullPath, newPath);
486 MakePathRelative(fullPath, path, relative);
488 listBox.SetData(locationField, relative);
489 strcpy(component->installPath, relative);
491 //SetAvailableSpace(component, path);
494 install.disabled = false;
495 for(c = 0; components[c].name; c++)
497 SetAvailableSpace(components[c], installDir);
503 bool NotifyEditDone(ListBox listBox, DataRow row)
509 bool NotifyEdited(ListBox listBox, DataRow row)
512 browse.parent = listBox;
513 browse.position = { componentField.width + locationField.width + 18, (listBox.currentIndex+1) * listBox.rowHeight - 2 };
514 browse.size = { 30, listBox.rowHeight + 3 };
515 for(e = listBox.firstChild; e; e = e.next)
517 if(e._class == class(DataBox))
526 void NotifyChecked(CheckListBox listBox, DataRow row)
528 Component * component = ((CheckItem *)row.GetData(componentField))->data;
530 component->selected = listBox.IsChecked(row);
532 if(!component->parent) totalSize -= component->requiredSize;
533 component->requiredSize = 0;
534 if(component->selected)
536 component->requiredSize += component->size;
537 if(component->subComponents)
538 for(c = 0; component->subComponents[c].name; c++)
539 component->requiredSize += component->subComponents[c].requiredSize;
541 if(component->requiredSize)
543 uint requiredSize = component->requiredSize;
544 row.SetData(reqField, requiredSize);
547 row.UnsetData(reqField);
548 if(!component->parent)
550 totalSize += component->requiredSize;
552 char sizeString[100];
553 PrintSize(sizeString, totalSize, 2);
554 totalSpaceValue.text = sizeString;
559 Label agreementLbl { parent = this, text = $"By installing the Ecere SDK, you agree to the .", font = { "Tahoma", 8.25f }, anchor = Anchor { left = 24, top = 424 } };
562 this, inactive = true, offset = false, bevel = false, foreground = blue, font = { "Tahoma", 8.25f, underline = true, bold = true },
563 // text = $"terms and conditions", anchor = Anchor { left = 241, top = 421 };
564 text = $"terms and conditions", anchor = Anchor { left = 237, top = 421 };
565 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
567 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
569 // LicenseBox { master = this, sourceFile = ":ecere-sdk/doc/LICENSE" }.Modal();
570 LicensesForm { master = this }.Modal();
574 CheckListBox optionsBox
576 this, size = { 460, 94 }, position = { 160, 284 };
577 fullRowSelect = false, collapseControl = true, treeBranches = true, rootCollapseButton = true,
582 void NotifyChecked(CheckListBox listBox, DataRow row)
584 CheckItem * item = row.GetData(optionField);
585 InstallOption * option = item->data;
586 option->selected = listBox.IsChecked(row);
591 parent = this, text = $"Install", isDefault = true, size = { 75, 23 }, position = { 432, 416 };
593 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
595 installProgress.Create();
597 // installProgress.thread.Main();
598 installProgress.thread.Create();
602 Button button3 { parent = this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 }, NotifyClicked = ButtonCloseDialog };
603 Label label1 { labeledWindow = destBox, tabCycle = true, isGroupBox = true, parent = this, inactive = false, size = Size { 458, 50 }, anchor = Anchor { left = 160, top = 96 } };
606 parent = label1, master = this, text = $" Destination Folder", size = Size { 336, 22 }, anchor = Anchor { left = 12, top = 20, right = 12 };
607 typeExpected = directory;
608 browseDialog = fileDialog;
611 bool NotifyModified(PathBox pathBox)
614 strcpy(installDir, destBox.path);
615 install.disabled = false;
616 for(c = 0; components[c].name; c++)
618 SetAvailableSpace(components[c], installDir);
625 label1, this, $"Browse", altB, size = { 83, 24 }, position = { 360, 16 };
627 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
629 strcpy(fileDialog.filePath, installDir);
630 StripLastDirectory(installDir, fileDialog.currentDirectory);
631 if(fileDialog.Modal())
633 strcpy(installDir, fileDialog.filePath);
634 destBox.contents = installDir;
635 // TOCHECK: Should setting contents call NotifyModified?
636 destBox.NotifyModified(destBox.master, destBox);
643 this, multiLine = true,
644 opacity = 0, borderStyle = none, inactive = true, size = { 136, 53 }, position = { 14, 96 }, noSelect = true,
645 contents = $"Select the default root\n"
646 "folder where to install\n"
651 this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 132 }, position = { 14, 152 }, noSelect = true,
653 contents = $"Select the optional\n"
654 "components you wish\n"
656 "You may customize the\n"
657 "install location for each\n"
658 "of them, or use the default\n"
659 "based on the main\n"
660 "destination folder."
664 this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 53 }, position = { 14, 280 }, noSelect = true,
666 contents = $"Select icons to install, file\n"
667 "associations, and system\n"
668 "environment modifications:"
670 Label totalSpaceLabel
672 this, position = { 18, 352 }, text = $"Space Required: "
674 Label totalSpaceValue
676 this, position = { 100, 352 }, text = "0 mb"
680 inactive = true, noSelect = true,
681 multiLine = true, parent = label3, text = "editBox1", opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 },
682 contents = $"Choose in which folder to install the Ecere SDK, which features\n"
683 "of the SDK to install, as well as where to install program icons."
685 Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder };
688 image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, text = "picture1", anchor = Anchor { left = 16, top = 4 };
689 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
691 bool OnLeftButtonDown(int x, int y, Modifiers mods)
693 ShellOpen("http://www.ecere.com/");
697 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 } };
698 DataField componentField { "CheckItem", width = 160, header = $"Component" };
699 DataField locationField { "char *", width = 108, header = $"Destination Folder", editable = true };
700 DataField reqField { "FileSize", width = 70, header = $"Req. Space", alignment = right };
701 DataField avField { "FileSize64", width = 70, header = $"Avail. Space", alignment = right };
702 DataField optionField { "CheckItem" };
704 void SetAvailableSpace(Component component, char * parentPath)
706 char path[MAX_LOCATION];
710 strcpy(path, parentPath);
711 PathCat(path, component.installPath);
713 if(component.subComponents)
714 for(c = 0; component.subComponents[c].name; c++)
715 SetAvailableSpace(component.subComponents[c], path);
717 while(!FileExists(path) && path[0])
718 StripLastDirectory(path, path);
721 GetFreeSpace(path, &size);
722 component.row.SetData(avField, size);
723 if(!size) install.disabled = true;
726 FileSize ComputeSize(char * path)
729 FileAttribs attribs = FileExists(path);
730 if(attribs.isDirectory)
732 FileListing listing { path };
733 while(listing.Find())
735 if(listing.stats.attribs.isDirectory)
736 size += ComputeSize(listing.path);
738 size += listing.stats.size;
742 FileGetSize(path, &size);
746 void AddComponent(Component component, Component parent, char * parentPath)
748 DataRow row = (parent != null) ? parent.row.AddRow() : componentsBox.AddRow();
750 FileSize64 avSize = 0;
751 char path[MAX_LOCATION];
754 strcpy(path, parentPath);
755 if(component.defInstallPath)
756 PathCat(path, component.defInstallPath);
757 component.parent = parent;
759 row.SetData(null, CheckItem { component.name, component, (component.arch == bits32 && osIS64bit) } );
761 if(component.defInstallPath)
763 strcpy(component.installPath, component.defInstallPath);
764 ChangeCh(component.installPath, '/', DIR_SEP);
765 row.SetData(locationField, component.installPath);
768 if(component.mandatory)
770 if(component.arch != bits32 || !osIS64bit) // || component == &coreSDK[gdb32])
771 componentsBox.SetDisabled(row, true);
773 component.selected = false;*/
775 else if(component.arch == bits32 && osIS64bit)
776 ; //component.selected = false;
778 componentsBox.SetCheck(row, component.selected);
780 if(component.dataPath)
782 char path[MAX_LOCATION];
784 PathCat(path, component.dataPath);
785 component.size = ComputeSize(path);
787 if(component.subComponents)
790 for(c = 0; component.subComponents[c].name; c++)
792 Component * sub = &component.subComponents[c];
793 if(sub->available && (osIS64bit || sub->arch == bits32 || sub->arch == none))
795 AddComponent(sub, component, path);
796 size += sub->requiredSize;
799 sub->selected = false;
803 component.requiredSize = component.selected ? (size + component.size) : 0;
804 if(component.requiredSize)
805 row.SetData(reqField, component.requiredSize);
807 while(!FileExists(path) && path[0])
808 StripLastDirectory(path, path);
811 GetFreeSpace(path, &avSize);
814 row.SetData(avField, avSize);
815 row.collapsed = true;
818 void AddOption(InstallOption option, InstallOption parent)
820 DataRow row = option.row = (parent != null) ? parent.row.AddRow() : optionsBox.AddRow();
821 row.SetData(null, CheckItem { option.name, option } );
822 optionsBox.SetCheck(row, option.selected);
823 if(option.subOptions)
826 for(c = 0; option.subOptions[c].name; c++)
828 AddOption(option.subOptions[c], option);
831 row.collapsed = true;
837 char programFilesDir[MAX_LOCATION];
838 char appData[MAX_LOCATION];
839 char homeDrive[MAX_LOCATION];
840 char winDir[MAX_LOCATION];
842 GetEnvironment("APPDATA", appData, sizeof(appData));
843 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
844 GetEnvironment("windir", winDir, sizeof(winDir));
846 componentsBox.AddField(componentField);
847 componentsBox.AddField(locationField);
848 componentsBox.AddField(reqField);
849 componentsBox.AddField(avField);
851 optionsBox.AddField(optionField);
853 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
855 char * x86 = strstr(programFilesDir, " (x86)");
858 strcpy(installDir32, programFilesDir);
859 PathCat(installDir32, "Ecere SDK");
863 strcpy(installDir, programFilesDir);
864 PathCat(installDir, "Ecere SDK");
868 strcpy(installDir, programFilesDir);
869 PathCat(installDir, "Ecere SDK");
870 strcpy(installDir32, installDir);
873 else if(homeDrive && homeDrive[0])
875 strcpy(installDir, homeDrive);
876 PathCat(installDir, "Ecere SDK");
878 else if(winDir && winDir[0])
880 strcpy(installDir, winDir);
881 PathCat(installDir, "..\\Ecere SDK");
884 strcpy(installDir, "C:\\Ecere SDK");
886 if(appData && appData[0])
888 static char defSamplesPath[MAX_LOCATION];
889 static char defExtrasPath[MAX_LOCATION];
890 strcpy(defSamplesPath, appData);
891 PathCat(defSamplesPath, "Ecere SDK\\Samples");
892 components[samples].defInstallPath = defSamplesPath;
894 strcpy(defExtrasPath, appData);
895 PathCat(defExtrasPath, "Ecere SDK\\extras");
896 additional[extras].defInstallPath = defExtrasPath;
899 destBox.path = installDir;
903 for(c = 0; components[c].name; c++)
904 AddComponent(components[c], null, installDir);
907 // Compute size apart because ToggleCheck will change it
911 for(c = 0; components[c].name; c++)
912 totalSize += components[c].requiredSize;
915 char sizeString[100];
916 PrintSize(sizeString, totalSize, 2);
917 totalSpaceValue.text = sizeString;
919 for(c = 0; options[c].name; c++)
920 AddOption(options[c], null);
929 void OnDrawOverChildren(Surface surface)
931 int tw = label2.size.w;
932 surface.SetForeground(Color { 128, 128, 128 });
933 surface.HLine(label2.position.x + tw + 6, 620, 400);
934 surface.SetForeground(white);
935 surface.HLine(label2.position.x + tw + 6, 621, 401);
936 surface.PutPixel(621, 400);
941 parent = this, opacity = 0, borderStyle = deep, size = Size { 644, 93 }, anchor = Anchor { left = -8, top = -8 };
945 class InstallProgress : Window
947 text = $"Ecere Software Development Kit Setup - v0.44.10 \"Ryōan-ji\" 64 Bit Edition";
948 background = activeBorder;
953 // size = Size { 640, 480 };
954 clientSize = { 636, 456 };
955 //clientSize = { 796, 576 };
956 icon = { ":icon.png" };
958 Picture back { image = BitmapResource { ":ryoanji-progress.png" }, parent = this, position = { 0, 0 } };
959 Label installing { this, position = { 32, 160 } };
960 ProgressBar progressBar { parent = this, size = Size { 588, 24 }, anchor = Anchor { left = 24, top = 184 } };
963 parent = this, text = $"Install", disabled = true, isDefault = true, size = Size { 75, 23 }, anchor = Anchor { left = 432, top = 416 };
965 NotifyClicked = ButtonCloseDialog
969 this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 };
971 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
979 inactive = true, noSelect = true,
980 multiLine = true, parent = label3, opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 },
981 contents = $"Please wait while the Ecere Software Development Kit is being installed."
983 Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder };
986 image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, anchor = Anchor { left = 16, top = 4 };
987 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
989 bool OnLeftButtonDown(int x, int y, Modifiers mods)
991 ShellOpen("http://www.ecere.com/");
995 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 } };
997 void OnDrawOverChildren(Surface surface)
999 int tw = label2.size.w;
1000 surface.SetForeground(Color { 128, 128, 128 });
1001 surface.HLine(label2.position.x + tw + 6, 620, 400);
1002 surface.SetForeground(white);
1003 surface.HLine(label2.position.x + tw + 6, 621, 401);
1004 surface.PutPixel(621, 400);
1009 parent = this, opacity = 0, borderStyle = deep, size = Size { 644, 93 }, anchor = Anchor { left = -8, top = -8 };
1011 InstallThread thread
1016 Installer installer {};
1017 InstallProgress installProgress { autoCreate = false };
1019 static void AddPath(char * sysPaths[200], int sysCount, char * paths[200], int * count, char * oldPath, char * userPath, char * path)
1023 for(p = 0; p<sysCount; p++)
1024 if(!fstrcmp(sysPaths[p], path))
1029 for(p = 0; !found && p<*count; p++)
1030 if(!fstrcmp(paths[p], path))
1040 strcat(userPath, ";");
1041 start = paths[(*count)-1] + strlen(paths[(*count)-1])+1;
1046 strcpy(start, path);
1047 *(start + strlen(path)) = '\0';
1048 paths[(*count)++] = start;
1050 strcat(userPath, path);
1055 void ModifyPath(char * systemPath, char * userPath)
1057 char oldPath[8192], * paths[200], * sysPaths[200];
1058 int count, sysCount;
1060 strcpy(oldPath, userPath);
1061 count = TokenizeWith(oldPath, sizeof(paths) / sizeof(char *), paths, ";", false);
1062 sysCount = TokenizeWith(systemPath, sizeof(sysPaths) / sizeof(char *), sysPaths, ";", false);
1066 for(c = 0; coreSDK[c].name; c++)
1069 char path[MAX_LOCATION];
1070 if(!coreSDK[c].selected) continue;
1071 coreSDK[c].GetFullPath(path, false);
1072 if(c != ide && c != runtime && c != ec &&
1073 c != ide32 && c != runtime32 && c != ec32)
1075 if(!pathOptions[PathOptions::AddMinGWPaths].available || !pathOptions[PathOptions::AddMinGWPaths].selected)
1077 PathCat(path, "bin");
1079 else if(!pathOptions[PathOptions::AddECEREPaths].selected) continue;
1081 AddPath(sysPaths, sysCount, paths, &count, oldPath, userPath, path);
1087 for(c = 0; c <= cpp; c++)
1090 char path[MAX_LOCATION];
1091 if(!additional[c].selected || c == vanilla || c == vanilla32 || c == extras) continue;
1092 if((c != eda && c != eda32 && c != upx) && (!pathOptions[PathOptions::AddMinGWPaths].available || !pathOptions[PathOptions::AddMinGWPaths].selected))
1094 additional[c].GetFullPath(path, false);
1095 if(c != eda && c != eda32 && c != upx)
1096 PathCat(path, "bin");
1097 AddPath(sysPaths, sysCount, paths, &count, oldPath, userPath, path);
1102 void AssociateExtension(char * extension, char * description, char *name, char * action, char * path)
1108 RegCreateKeyEx(HKEY_CLASSES_ROOT, extension, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1109 RegSetValueEx(key, null, 0, REG_SZ, name, (uint)strlen(name)+1);
1112 RegCreateKeyEx(HKEY_CLASSES_ROOT, name, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1113 RegSetValueEx(key, null, 0, REG_SZ, description, (uint)strlen(description)+1);
1116 sprintf(keyName, "%s\\shell", extension);
1117 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1118 RegSetValueEx(key, null, 0, REG_SZ, action, (uint)strlen(action)+1);
1121 sprintf(keyName, "%s\\shell\\%s", name, action);
1122 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1125 sprintf(keyName, "%s\\shell\\%s\\command", name, action);
1126 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1128 sprintf(keyName, path);
1129 strcat(keyName, " \"%L\"");
1131 uint16 wKeyName[2048];
1132 UTF8toUTF16Buffer(keyName, wKeyName, sizeof(wKeyName) / sizeof(uint16));
1133 RegSetValueExW(key, null, 0, REG_SZ, (byte *)wKeyName, (uint)(wcslen(wKeyName) + 1)*sizeof(uint16));
1138 class InstallThread : Thread
1143 ((GuiApplication)__thisModule).Lock();
1144 installProgress.progressBar.range = totalSize;
1145 for(c = 0; components[c].name && !abortInstall; c++)
1146 components[c].Install(installDir, installDir32);
1149 installProgress.progressBar.range = 0;
1150 installProgress.finish.Destroy(0);
1151 installProgress.cancel.text = $"Close";
1152 installProgress.cancel.isDefault = true;
1153 installProgress.cancel.disabled = false;
1154 installProgress.cancel.NotifyClicked = Window::ButtonCloseDialog;
1155 installProgress.installing.text = $"Installation Cancelled.";
1156 installProgress.title.text = $"Installation Cancelled";
1157 installProgress.titleInfo.contents = $"The installation was not completed.";
1161 char idePath[MAX_LOCATION];
1162 char userProfile[MAX_LOCATION];
1165 IDESettings settings = null; // Don't instantiate yet so we can pick up old settings
1167 IDESettingsContainer settingsContainer
1170 dataOwner = &settings;
1171 dataClass = class(IDESettings);
1173 CompilerConfig compiler;
1174 installProgress.installing.text = $"Configuring Ecere IDE...";
1175 ((GuiApplication)__thisModule).Unlock();
1176 ((GuiApplication)__thisModule).SignalEvent();
1178 settingsContainer.Load();
1179 compiler = settings.GetCompilerConfig(defaultCompilerName);
1184 for(c = 0; coreSDK[c].name; c++)
1186 char path[MAX_LOCATION];
1187 if(!coreSDK[c].selected || !coreSDK[c].available) continue;
1189 coreSDK[c].GetFullPath(path, false);
1190 if(c != ide && c != runtime && c != ec &&
1191 c != ide32 && c != runtime32 && c != ec32)
1192 PathCat(path, "bin");
1193 MakeSlashPath(path);
1194 if((c == ide && osIS64bit) || (c == ide32 && !osIS64bit))
1196 coreSDK[c].GetFullPath(idePath, false);
1197 PathCat(idePath, "ide.exe");
1200 if(c == runtime || c == runtime32)
1202 if(!compiler.libraryDirs.Find(path))
1203 compiler.libraryDirs.Add(CopyString(path));
1210 for(c = 0; c <= cpp; c++)
1212 char path[MAX_LOCATION];
1213 if(c == extras || !additional[c].selected || !additional[c].available) continue;
1214 additional[c].GetFullPath(path, false);
1215 if(c != upx && c != eda && c != vanilla && c != eda32 && c != vanilla32)
1216 PathCat(path, "bin");
1217 MakeSlashPath(path);
1218 if(c == vanilla || c == vanilla32)
1220 if(!compiler.libraryDirs.Find(path))
1221 compiler.libraryDirs.Add(CopyString(path));
1225 if(!compiler.executableDirs.Find(path))
1226 compiler.executableDirs.Add(CopyString(path));
1233 char path[MAX_LOCATION] = "";
1235 if(components[samples].selected)
1236 components[samples].GetFullPath(path, false);
1237 // IDE will now default to HOME for the default project/files locations
1239 if(!settings.ideProjectFileDialogLocation[0])
1240 settings.ideProjectFileDialogLocation = path;
1241 if(!settings.ideFileDialogLocation[0])
1242 settings.ideFileDialogLocation = path;
1244 if(documentation[apiRef].selected)
1246 documentation[apiRef].GetFullPath(path, false);
1247 if(!settings.docDir[0])
1248 settings.docDir = path;
1252 settingsContainer.Save();
1253 delete settingsContainer;
1256 // Set up Uninstaller
1257 ((GuiApplication)__thisModule).Lock();
1258 installProgress.installing.text = $"Registering uninstaller...";
1259 ((GuiApplication)__thisModule).Unlock();
1260 ((GuiApplication)__thisModule).SignalEvent();
1265 char * displayName = "Ecere SDK 0.44";
1266 char uninstaller[MAX_LOCATION];
1267 bool nomodify = true;
1269 strcpy(uninstaller, installDir);
1270 PathCat(uninstaller, "uninstall_ecere.exe");
1272 RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Ecere SDK", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1274 RegSetValueEx(key, "DisplayName", 0, REG_SZ, displayName, (uint)strlen(displayName)+1);
1275 RegSetValueEx(key, "UninstallString", 0, REG_SZ, uninstaller, (uint)strlen(uninstaller)+1);
1276 RegSetValueEx(key, "DisplayIcon", 0, REG_SZ, idePath, (uint)strlen(idePath)+1);
1277 //RegSetValueEx(key, "NoModify", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1278 //RegSetValueEx(key, "NoRepair", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1283 if(pathOptions[PathOptions::AddECEREPaths].selected
1285 || pathOptions[PathOptions::AddMinGWPaths].selected
1289 HKEY userKey = null, systemKey = null;
1291 char userPath[8192] = "";
1292 char systemPath[8192] = "";
1293 uint16 wUserPath[8192];
1294 uint16 wSystemPath[8192];
1299 ((GuiApplication)__thisModule).Lock();
1300 installProgress.installing.text = "Registering paths...";
1301 ((GuiApplication)__thisModule).Unlock();
1302 ((GuiApplication)__thisModule).SignalEvent();
1304 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, KEY_QUERY_VALUE, &systemKey) == ERROR_SUCCESS)
1306 size = sizeof(wSystemPath);
1307 RegQueryValueExW(systemKey, L"path", null, null, (byte *)wSystemPath, &size);
1308 UTF16toUTF8Buffer(wSystemPath, systemPath, sizeof(systemPath));
1311 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &userKey, &status);
1312 if(status == REG_OPENED_EXISTING_KEY)
1314 size = sizeof(wUserPath);
1315 RegQueryValueExW(userKey, L"path", null, null, (byte *)wUserPath, &size);
1316 UTF16toUTF8Buffer(wUserPath, userPath, sizeof(userPath));
1318 ModifyPath(systemPath, userPath);
1319 UTF8toUTF16Buffer(userPath, wUserPath, sizeof(wUserPath) / sizeof(uint16));
1320 RegSetValueExW(userKey, L"path", 0, REG_EXPAND_SZ, (byte *)wUserPath, (uint)(wcslen(wUserPath)+1) * 2);
1321 RegCloseKey(userKey);
1322 RegCloseKey(systemKey);
1324 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (int)"Environment", SMTO_NORMAL, 1000, NULL);
1327 // Install Program Group Icons
1328 GetEnvironment("USERPROFILE", userProfile, sizeof(userProfile));
1330 if(options[IconOptions::StartMenuIcon].selected)
1332 char destPath[MAX_LOCATION];
1333 char startMenuPath[MAX_LOCATION] = "";
1336 ((GuiApplication)__thisModule).Lock();
1337 installProgress.installing.text = $"Installing Start Menu Icons...";
1338 ((GuiApplication)__thisModule).Unlock();
1339 ((GuiApplication)__thisModule).SignalEvent();
1341 strcpy(destPath, userProfile);
1343 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1345 uint16 wStartMenuPath[2048];
1346 uint size = sizeof(wStartMenuPath);
1347 // RegQueryValueEx(key, "Start Menu", null, null, startMenuPath, &size);
1348 RegQueryValueExW(key, L"Programs", null, null, (byte *)wStartMenuPath, &size);
1349 UTF16toUTF8Buffer(wStartMenuPath, startMenuPath, sizeof(startMenuPath));
1352 if(!startMenuPath[0] && userProfile[0])
1354 strcpy(startMenuPath, userProfile);
1355 PathCat(startMenuPath, "Start Menu\\Programs");
1358 if(startMenuPath[0])
1360 strcpy(destPath, startMenuPath);
1361 PathCat(destPath, "Ecere SDK");
1364 strcpy(destPath, startMenuPath);
1365 PathCat(destPath, "Ecere SDK\\Ecere IDE.lnk");
1366 CreateLink(idePath, destPath, null); //"Ecere IDE");
1367 if(components[samples].selected)
1369 char samplesPath[MAX_LOCATION] = "";
1370 components[samples].GetFullPath(samplesPath, false);
1372 strcpy(destPath, startMenuPath);
1373 PathCat(destPath, "Ecere SDK\\Sample Projects.lnk");
1374 CreateLink(samplesPath, destPath, null);//"Sample Projects");
1376 if(components[documentation].selected && documentation[ecereBook].selected)
1378 char docPath[MAX_LOCATION] = "";
1379 documentation[ecereBook].GetFullPath(docPath, false);
1380 PathCat(docPath, "Ecere Tao of Programming [work in progress].pdf");
1383 char tao[MAX_LOCATION] ;
1384 documentation[ecereBook].GetFullPath(tao, false);
1385 PathCat(tao, "tao.pdf");
1386 RenameFile(tao, docPath);
1389 strcpy(destPath, startMenuPath);
1390 PathCat(destPath, "Ecere SDK\\The Ecere Tao of Programming.lnk");
1391 CreateLink(docPath, destPath, null);
1396 // Install Desktop Icon
1397 if(options[IconOptions::DesktopIcon].selected)
1400 char desktopPath[MAX_LOCATION];
1402 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1404 uint16 wDesktopPath[MAX_LOCATION];
1405 uint size = sizeof(wDesktopPath);
1406 RegQueryValueExW(key, L"Desktop", null, null, (byte *)wDesktopPath, &size);
1407 UTF16toUTF8Buffer(wDesktopPath, desktopPath, sizeof(desktopPath));
1410 if(!desktopPath[0] && userProfile[0])
1412 strcpy(desktopPath, userProfile);
1413 PathCat(desktopPath, "Desktop");
1418 PathCat(desktopPath, "Ecere IDE.lnk");
1420 ((GuiApplication)__thisModule).Lock();
1421 installProgress.installing.text = $"Installing Desktop Icon...";
1422 ((GuiApplication)__thisModule).Unlock();
1423 ((GuiApplication)__thisModule).SignalEvent();
1425 CreateLink(idePath, desktopPath, null);//"Ecere IDE");
1429 // Install QuickLaunch Icon
1430 if(options[IconOptions::QuickLaunchIcon].selected)
1432 char appData[MAX_LOCATION];
1433 GetEnvironment("APPDATA", appData, sizeof(appData));
1437 char destPath[MAX_LOCATION];
1439 ((GuiApplication)__thisModule).Lock();
1440 installProgress.installing.text = $"Installing Quicklaunch Icon...";
1441 ((GuiApplication)__thisModule).Unlock();
1442 ((GuiApplication)__thisModule).SignalEvent();
1444 strcpy(destPath, appData);
1445 PathCat(destPath, "Microsoft\\Internet Explorer\\Quick Launch\\Ecere IDE.lnk");
1447 CreateLink(idePath, destPath, null);//"Ecere IDE");
1451 // Register File Types
1452 if(associateOptions[AssociateOptions::AssociateEPJ].selected ||
1453 associateOptions[AssociateOptions::AssociateEC].selected ||
1454 associateOptions[AssociateOptions::AssociateC].selected ||
1455 associateOptions[AssociateOptions::AssociateCPP].selected ||
1456 associateOptions[AssociateOptions::AssociateTXT].selected ||
1457 associateOptions[AssociateOptions::Associate3DS].selected ||
1458 associateOptions[AssociateOptions::AssociateIMG].selected)
1460 ((GuiApplication)__thisModule).Lock();
1461 installProgress.installing.text = $"Resgistering File Types...";
1462 ((GuiApplication)__thisModule).Unlock();
1463 ((GuiApplication)__thisModule).SignalEvent();
1465 if(associateOptions[AssociateOptions::AssociateEPJ].selected)
1467 AssociateExtension(".epj", "Ecere IDE Project", "epj_file", "Open", idePath);
1469 if(associateOptions[AssociateOptions::AssociateEC].selected)
1471 AssociateExtension(".ec", "eC Source File", "ec_file", "Open", idePath);
1472 AssociateExtension(".eh", "eC Header File", "eh_file", "Open", idePath);
1474 if(associateOptions[AssociateOptions::AssociateC].selected)
1476 AssociateExtension(".c", "C Source File", "c_file", "Open", idePath);
1477 AssociateExtension(".h", "C Header File", "h_file", "Open", idePath);
1479 if(associateOptions[AssociateOptions::AssociateCPP].selected)
1481 AssociateExtension(".cpp", "C++ Source File", "cpp_file", "Open", idePath);
1482 AssociateExtension(".cc", "C++ Source File", "cpp_file", "Open", idePath);
1483 AssociateExtension(".cxx", "C++ Source File", "cpp_file", "Open", idePath);
1484 AssociateExtension(".chh", "C++ Header File", "chh_file", "Open", idePath);
1485 AssociateExtension(".hh", "C++ Header File", "chh_file", "Open", idePath);
1486 AssociateExtension(".hxx", "C++ Header File", "chh_file", "Open", idePath);
1488 if(associateOptions[AssociateOptions::AssociateTXT].selected)
1490 AssociateExtension(".txt", "Text File", "txt_file", "Open", idePath);
1492 if(associateOptions[AssociateOptions::Associate3DS].selected)
1494 AssociateExtension(".3ds", "3D Studio Model", "3ds_file", "View", idePath);
1496 if(associateOptions[AssociateOptions::AssociateIMG].selected)
1498 AssociateExtension(".bmp", "BMP Image", "bmp_file", "View", idePath);
1499 AssociateExtension(".pcx", "PCX Image", "pcx_file", "View", idePath);
1500 AssociateExtension(".png", "PNG Image", "png_file", "View", idePath);
1501 AssociateExtension(".jpg", "JPEG Image", "jpg_file", "View", idePath);
1502 AssociateExtension(".jpeg", "JPEG Image", "jpg_file", "View", idePath);
1503 AssociateExtension(".gif", "GIF Image", "gif_file", "View", idePath);
1506 ((GuiApplication)__thisModule).Lock();
1508 installProgress.cancel.Destroy(0);
1509 installProgress.finish.text = $"Finish";
1510 installProgress.finish.disabled = false;
1511 installProgress.finish.Activate();
1512 installProgress.installing.text = $"Installation Complete.";
1513 installProgress.title.text = $"Installation Complete";
1514 installProgress.titleInfo.contents = $"Thank you for using the Ecere SDK.";
1516 ((GuiApplication)__thisModule).Unlock();