2 static define buildString = $"Ecere SDK v0.44.08 (Without MinGW) -- built on August 9, 2013 ";
4 static define buildString = $"Ecere SDK v0.44.08 -- built on August 9, 2013 ";
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 { "MinGW Docs", "tdm/doc/mingwrt", "tdm", null, false, false, minGWIncluded, none },
326 { "gnurx Docs", "tdm/doc/gnurx", "tdm", null, false, false, minGWIncluded, none },
327 { "UPX Docs", "upx/doc", "upx/doc", null, false, false, minGWIncluded, none },
331 public enum ComponentID
340 Component components[ComponentID] =
342 { "Core SDK Files", null, null, coreSDK, true, true, true, none },
343 { "Additional Support", null, null, additional, false, true, true, none },
344 { "Documentation", null /*"doc"*/, null /*"doc"*/, documentation, false, true, true, none },
345 { "Samples", null, "samples", samples, false, true, true, none },
349 FileSize totalInstalled;
354 InstallOption * subOptions;
360 enum AssociateOptions
371 InstallOption associateOptions[] =
373 { "Associate with Ecere Project Files (*.epj)", null, true },
374 { "Associate with eC Files (*.ec, *.eh)", null, true },
375 { "Associate with C files (*.c, *.h)", null, false },
376 { "Associate with C++ Files (*.cpp, *.hpp, *.cc, *.hh, *.cxx, *.hxx)", null, false },
377 { "Associate with text files (*.txt)", null, false },
378 { "Associate with 3D Studio Model Files (*.3ds)", null, true },
379 { "Associate with Image Files (*.png, *.jpg, *.pcx, *.bmp, *.gif)", null, false },
385 AddECEREPaths, AddMinGWPaths
388 InstallOption pathOptions[] =
390 { "Add Ecere binaries location to the user environment path", null, true, true },
391 { "Add MinGW to the user environment path", null, true, minGWIncluded }
402 InstallOption options[] =
404 { "Start Menu Group", null, true, true },
405 { "Desktop Icon", null, true, true },
406 { "Quicklaunch Icon", null, true, true },
407 { "Associate the Ecere IDE with Supported File Types", associateOptions, true, true },
408 { "Add binaries location to the user environment paths", pathOptions, true, minGWIncluded },
412 char sourceDir[MAX_LOCATION] = ":";
413 char installDir[MAX_LOCATION];
414 char installDir32[MAX_LOCATION];
417 class Installer : Window
419 text = $"Ecere Software Development Kit Setup - v0.44.08 \"Ryōan-ji\" 64 Bit Edition";
420 background = activeBorder;
425 clientSize = { 636, 456 };
426 // clientSize = { 796, 576 };
427 icon = { ":icon.png" };
429 Picture back { image = BitmapResource { ":ryoanji.png" }, parent = this, position = { 0, 0 } };
430 FileDialog fileDialog
432 master = this, type = selectDir,
433 text = $"Select a new location"
437 master = this, autoCreate = false, inactive = true, text = "...";
439 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
441 DataRow row = componentsBox.currentRow;
442 Component * component = ((CheckItem *)row.GetData(componentField))->data;
443 component->GetFullPath(fileDialog.filePath, false);
444 StripLastDirectory(fileDialog.filePath, fileDialog.currentDirectory);
446 if(fileDialog.Modal() == ok)
448 componentsBox.StopEditing(false);
449 row.SetData(locationField, fileDialog.filePath);
450 componentsBox.NotifyChanged(this, componentsBox, row);
451 componentsBox.currentField = componentsBox.currentField;
456 CheckListBox componentsBox
458 this, size = { 460, 112 }, position = { 160, 160 }, hasHeader = true;
459 fullRowSelect = false, collapseControl = true, treeBranches = true, rootCollapseButton = true,
462 selectionColor = { 145, 150, 140 };
467 bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch)
469 if(key == f2 && browse.visible)
470 browse.NotifyClicked(this, browse, 0, 0, 0);
474 bool NotifyChanged(ListBox listBox, DataRow row)
476 Component * component = ((CheckItem *)listBox.GetData(componentField))->data;
477 char path[MAX_LOCATION], relative[MAX_LOCATION] = "", * newPath;
478 char fullPath[MAX_LOCATION];
480 component->parent->GetFullPath(path, false);
481 strcpy(fullPath, path);
483 newPath = row.GetData(locationField);
486 PathCat(fullPath, newPath);
487 MakePathRelative(fullPath, path, relative);
489 listBox.SetData(locationField, relative);
490 strcpy(component->installPath, relative);
492 //SetAvailableSpace(component, path);
495 install.disabled = false;
496 for(c = 0; components[c].name; c++)
498 SetAvailableSpace(components[c], installDir);
504 bool NotifyEditDone(ListBox listBox, DataRow row)
510 bool NotifyEdited(ListBox listBox, DataRow row)
513 browse.parent = listBox;
514 browse.position = { componentField.width + locationField.width + 18, (listBox.currentIndex+1) * listBox.rowHeight - 2 };
515 browse.size = { 30, listBox.rowHeight + 3 };
516 for(e = listBox.firstChild; e; e = e.next)
518 if(e._class == class(DataBox))
527 void NotifyChecked(CheckListBox listBox, DataRow row)
529 Component * component = ((CheckItem *)row.GetData(componentField))->data;
531 component->selected = listBox.IsChecked(row);
533 if(!component->parent) totalSize -= component->requiredSize;
534 component->requiredSize = 0;
535 if(component->selected)
537 component->requiredSize += component->size;
538 if(component->subComponents)
539 for(c = 0; component->subComponents[c].name; c++)
540 component->requiredSize += component->subComponents[c].requiredSize;
542 if(component->requiredSize)
544 uint requiredSize = component->requiredSize;
545 row.SetData(reqField, requiredSize);
548 row.UnsetData(reqField);
549 if(!component->parent)
551 totalSize += component->requiredSize;
553 char sizeString[100];
554 PrintSize(sizeString, totalSize, 2);
555 totalSpaceValue.text = sizeString;
560 Label agreementLbl { parent = this, text = $"By installing the Ecere SDK, you agree to the .", font = { "Tahoma", 8.25f }, anchor = Anchor { left = 24, top = 424 } };
563 this, inactive = true, offset = false, bevel = false, foreground = blue, font = { "Tahoma", 8.25f, underline = true, bold = true },
564 // text = $"terms and conditions", anchor = Anchor { left = 241, top = 421 };
565 text = $"terms and conditions", anchor = Anchor { left = 237, top = 421 };
566 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
568 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
570 // LicenseBox { master = this, sourceFile = ":ecere-sdk/doc/LICENSE" }.Modal();
571 LicensesForm { master = this }.Modal();
575 CheckListBox optionsBox
577 this, size = { 460, 94 }, position = { 160, 284 };
578 fullRowSelect = false, collapseControl = true, treeBranches = true, rootCollapseButton = true,
583 void NotifyChecked(CheckListBox listBox, DataRow row)
585 CheckItem * item = row.GetData(optionField);
586 InstallOption * option = item->data;
587 option->selected = listBox.IsChecked(row);
592 parent = this, text = $"Install", isDefault = true, size = { 75, 23 }, position = { 432, 416 };
594 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
596 installProgress.Create();
598 // installProgress.thread.Main();
599 installProgress.thread.Create();
603 Button button3 { parent = this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 }, NotifyClicked = ButtonCloseDialog };
604 Label label1 { labeledWindow = destBox, tabCycle = true, isGroupBox = true, parent = this, inactive = false, size = Size { 458, 50 }, anchor = Anchor { left = 160, top = 96 } };
607 parent = label1, master = this, text = $" Destination Folder", size = Size { 336, 22 }, anchor = Anchor { left = 12, top = 20, right = 12 };
608 typeExpected = directory;
609 browseDialog = fileDialog;
612 bool NotifyModified(PathBox pathBox)
615 strcpy(installDir, destBox.path);
616 install.disabled = false;
617 for(c = 0; components[c].name; c++)
619 SetAvailableSpace(components[c], installDir);
626 label1, this, $"Browse", altB, size = { 83, 24 }, position = { 360, 16 };
628 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
630 strcpy(fileDialog.filePath, installDir);
631 StripLastDirectory(installDir, fileDialog.currentDirectory);
632 if(fileDialog.Modal())
634 strcpy(installDir, fileDialog.filePath);
635 destBox.contents = installDir;
636 // TOCHECK: Should setting contents call NotifyModified?
637 destBox.NotifyModified(destBox.master, destBox);
644 this, multiLine = true,
645 opacity = 0, borderStyle = none, inactive = true, size = { 136, 53 }, position = { 14, 96 }, noSelect = true,
646 contents = $"Select the default root\n"
647 "folder where to install\n"
652 this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 132 }, position = { 14, 152 }, noSelect = true,
654 contents = $"Select the optional\n"
655 "components you wish\n"
657 "You may customize the\n"
658 "install location for each\n"
659 "of them, or use the default\n"
660 "based on the main\n"
661 "destination folder."
665 this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 53 }, position = { 14, 280 }, noSelect = true,
667 contents = $"Select icons to install, file\n"
668 "associations, and system\n"
669 "environment modifications:"
671 Label totalSpaceLabel
673 this, position = { 18, 352 }, text = $"Space Required: "
675 Label totalSpaceValue
677 this, position = { 100, 352 }, text = "0 mb"
681 inactive = true, noSelect = true,
682 multiLine = true, parent = label3, text = "editBox1", opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 },
683 contents = $"Choose in which folder to install the Ecere SDK, which features\n"
684 "of the SDK to install, as well as where to install program icons."
686 Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder };
689 image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, text = "picture1", anchor = Anchor { left = 16, top = 4 };
690 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
692 bool OnLeftButtonDown(int x, int y, Modifiers mods)
694 ShellOpen("http://www.ecere.com/");
698 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 } };
699 DataField componentField { "CheckItem", width = 160, header = $"Component" };
700 DataField locationField { "char *", width = 108, header = $"Destination Folder", editable = true };
701 DataField reqField { "FileSize", width = 70, header = $"Req. Space", alignment = right };
702 DataField avField { "FileSize64", width = 70, header = $"Avail. Space", alignment = right };
703 DataField optionField { "CheckItem" };
705 void SetAvailableSpace(Component component, char * parentPath)
707 char path[MAX_LOCATION];
711 strcpy(path, parentPath);
712 PathCat(path, component.installPath);
714 if(component.subComponents)
715 for(c = 0; component.subComponents[c].name; c++)
716 SetAvailableSpace(component.subComponents[c], path);
718 while(!FileExists(path) && path[0])
719 StripLastDirectory(path, path);
722 GetFreeSpace(path, &size);
723 component.row.SetData(avField, size);
724 if(!size) install.disabled = true;
727 FileSize ComputeSize(char * path)
730 FileAttribs attribs = FileExists(path);
731 if(attribs.isDirectory)
733 FileListing listing { path };
734 while(listing.Find())
736 if(listing.stats.attribs.isDirectory)
737 size += ComputeSize(listing.path);
739 size += listing.stats.size;
743 FileGetSize(path, &size);
747 void AddComponent(Component component, Component parent, char * parentPath)
749 DataRow row = (parent != null) ? parent.row.AddRow() : componentsBox.AddRow();
751 FileSize64 avSize = 0;
752 char path[MAX_LOCATION];
755 strcpy(path, parentPath);
756 if(component.defInstallPath)
757 PathCat(path, component.defInstallPath);
758 component.parent = parent;
760 row.SetData(null, CheckItem { component.name, component, (component.arch == bits32 && osIS64bit) } );
762 if(component.defInstallPath)
764 strcpy(component.installPath, component.defInstallPath);
765 ChangeCh(component.installPath, '/', DIR_SEP);
766 row.SetData(locationField, component.installPath);
769 if(component.mandatory)
771 if(component.arch != bits32 || !osIS64bit) // || component == &coreSDK[gdb32])
772 componentsBox.SetDisabled(row, true);
774 component.selected = false;*/
776 else if(component.arch == bits32 && osIS64bit)
777 ; //component.selected = false;
779 componentsBox.SetCheck(row, component.selected);
781 if(component.dataPath)
783 char path[MAX_LOCATION];
785 PathCat(path, component.dataPath);
786 component.size = ComputeSize(path);
788 if(component.subComponents)
791 for(c = 0; component.subComponents[c].name; c++)
793 Component * sub = &component.subComponents[c];
794 if(sub->available && (osIS64bit || sub->arch == bits32 || sub->arch == none))
796 AddComponent(sub, component, path);
797 size += sub->requiredSize;
800 sub->selected = false;
804 component.requiredSize = component.selected ? (size + component.size) : 0;
805 if(component.requiredSize)
806 row.SetData(reqField, component.requiredSize);
808 while(!FileExists(path) && path[0])
809 StripLastDirectory(path, path);
812 GetFreeSpace(path, &avSize);
815 row.SetData(avField, avSize);
816 row.collapsed = true;
819 void AddOption(InstallOption option, InstallOption parent)
821 DataRow row = option.row = (parent != null) ? parent.row.AddRow() : optionsBox.AddRow();
822 row.SetData(null, CheckItem { option.name, option } );
823 optionsBox.SetCheck(row, option.selected);
824 if(option.subOptions)
827 for(c = 0; option.subOptions[c].name; c++)
829 AddOption(option.subOptions[c], option);
832 row.collapsed = true;
838 char programFilesDir[MAX_LOCATION];
839 char appData[MAX_LOCATION];
840 char homeDrive[MAX_LOCATION];
841 char winDir[MAX_LOCATION];
843 GetEnvironment("APPDATA", appData, sizeof(appData));
844 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
845 GetEnvironment("windir", winDir, sizeof(winDir));
847 componentsBox.AddField(componentField);
848 componentsBox.AddField(locationField);
849 componentsBox.AddField(reqField);
850 componentsBox.AddField(avField);
852 optionsBox.AddField(optionField);
854 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
856 char * x86 = strstr(programFilesDir, " (x86)");
859 strcpy(installDir32, programFilesDir);
860 PathCat(installDir32, "Ecere SDK");
864 strcpy(installDir, programFilesDir);
865 PathCat(installDir, "Ecere SDK");
869 strcpy(installDir, programFilesDir);
870 PathCat(installDir, "Ecere SDK");
871 strcpy(installDir32, installDir);
874 else if(homeDrive && homeDrive[0])
876 strcpy(installDir, homeDrive);
877 PathCat(installDir, "Ecere SDK");
879 else if(winDir && winDir[0])
881 strcpy(installDir, winDir);
882 PathCat(installDir, "..\\Ecere SDK");
885 strcpy(installDir, "C:\\Ecere SDK");
887 if(appData && appData[0])
889 static char defSamplesPath[MAX_LOCATION];
890 static char defExtrasPath[MAX_LOCATION];
891 strcpy(defSamplesPath, appData);
892 PathCat(defSamplesPath, "Ecere SDK\\Samples");
893 components[samples].defInstallPath = defSamplesPath;
895 strcpy(defExtrasPath, appData);
896 PathCat(defExtrasPath, "Ecere SDK\\extras");
897 additional[extras].defInstallPath = defExtrasPath;
900 destBox.path = installDir;
904 for(c = 0; components[c].name; c++)
905 AddComponent(components[c], null, installDir);
908 // Compute size apart because ToggleCheck will change it
912 for(c = 0; components[c].name; c++)
913 totalSize += components[c].requiredSize;
916 char sizeString[100];
917 PrintSize(sizeString, totalSize, 2);
918 totalSpaceValue.text = sizeString;
920 for(c = 0; options[c].name; c++)
921 AddOption(options[c], null);
930 void OnDrawOverChildren(Surface surface)
932 int tw = label2.size.w;
933 surface.SetForeground(Color { 128, 128, 128 });
934 surface.HLine(label2.position.x + tw + 6, 620, 400);
935 surface.SetForeground(white);
936 surface.HLine(label2.position.x + tw + 6, 621, 401);
937 surface.PutPixel(621, 400);
942 parent = this, opacity = 0, borderStyle = deep, size = Size { 644, 93 }, anchor = Anchor { left = -8, top = -8 };
946 class InstallProgress : Window
948 text = $"Ecere Software Development Kit Setup - v0.44.08 \"Ryōan-ji\" 64 Bit Edition";
949 background = activeBorder;
954 // size = Size { 640, 480 };
955 clientSize = { 636, 456 };
956 //clientSize = { 796, 576 };
957 icon = { ":icon.png" };
959 Picture back { image = BitmapResource { ":ryoanji-progress.png" }, parent = this, position = { 0, 0 } };
960 Label installing { this, position = { 32, 160 } };
961 ProgressBar progressBar { parent = this, size = Size { 588, 24 }, anchor = Anchor { left = 24, top = 184 } };
964 parent = this, text = $"Install", disabled = true, isDefault = true, size = Size { 75, 23 }, anchor = Anchor { left = 432, top = 416 };
966 NotifyClicked = ButtonCloseDialog
970 this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 };
972 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
980 inactive = true, noSelect = true,
981 multiLine = true, parent = label3, opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 },
982 contents = $"Please wait while the Ecere Software Development Kit is being installed."
984 Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder };
987 image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, anchor = Anchor { left = 16, top = 4 };
988 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
990 bool OnLeftButtonDown(int x, int y, Modifiers mods)
992 ShellOpen("http://www.ecere.com/");
996 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 } };
998 void OnDrawOverChildren(Surface surface)
1000 int tw = label2.size.w;
1001 surface.SetForeground(Color { 128, 128, 128 });
1002 surface.HLine(label2.position.x + tw + 6, 620, 400);
1003 surface.SetForeground(white);
1004 surface.HLine(label2.position.x + tw + 6, 621, 401);
1005 surface.PutPixel(621, 400);
1010 parent = this, opacity = 0, borderStyle = deep, size = Size { 644, 93 }, anchor = Anchor { left = -8, top = -8 };
1012 InstallThread thread
1017 Installer installer {};
1018 InstallProgress installProgress { autoCreate = false };
1020 static void AddPath(char * sysPaths[200], int sysCount, char * paths[200], int * count, char * oldPath, char * userPath, char * path)
1024 for(p = 0; p<sysCount; p++)
1025 if(!fstrcmp(sysPaths[p], path))
1030 for(p = 0; !found && p<*count; p++)
1031 if(!fstrcmp(paths[p], path))
1041 strcat(userPath, ";");
1042 start = paths[(*count)-1] + strlen(paths[(*count)-1])+1;
1047 strcpy(start, path);
1048 *(start + strlen(path)) = '\0';
1049 paths[(*count)++] = start;
1051 strcat(userPath, path);
1056 void ModifyPath(char * systemPath, char * userPath)
1058 char oldPath[8192], * paths[200], * sysPaths[200];
1059 int count, sysCount;
1061 strcpy(oldPath, userPath);
1062 count = TokenizeWith(oldPath, sizeof(paths) / sizeof(char *), paths, ";", false);
1063 sysCount = TokenizeWith(systemPath, sizeof(sysPaths) / sizeof(char *), sysPaths, ";", false);
1067 for(c = 0; coreSDK[c].name; c++)
1070 char path[MAX_LOCATION];
1071 if(!coreSDK[c].selected) continue;
1072 coreSDK[c].GetFullPath(path, false);
1073 if(c != ide && c != runtime && c != ec &&
1074 c != ide32 && c != runtime32 && c != ec32)
1076 if(!pathOptions[PathOptions::AddMinGWPaths].available || !pathOptions[PathOptions::AddMinGWPaths].selected)
1078 PathCat(path, "bin");
1080 else if(!pathOptions[PathOptions::AddECEREPaths].selected) continue;
1082 AddPath(sysPaths, sysCount, paths, &count, oldPath, userPath, path);
1088 for(c = 0; c <= cpp; c++)
1091 char path[MAX_LOCATION];
1092 if(!additional[c].selected || c == vanilla || c == vanilla32 || c == extras) continue;
1093 if((c != eda && c != eda32 && c != upx) && (!pathOptions[PathOptions::AddMinGWPaths].available || !pathOptions[PathOptions::AddMinGWPaths].selected))
1095 additional[c].GetFullPath(path, false);
1096 if(c != eda && c != eda32 && c != upx)
1097 PathCat(path, "bin");
1098 AddPath(sysPaths, sysCount, paths, &count, oldPath, userPath, path);
1103 void AssociateExtension(char * extension, char * description, char *name, char * action, char * path)
1109 RegCreateKeyEx(HKEY_CLASSES_ROOT, extension, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1110 RegSetValueEx(key, null, 0, REG_SZ, name, (uint)strlen(name)+1);
1113 RegCreateKeyEx(HKEY_CLASSES_ROOT, name, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1114 RegSetValueEx(key, null, 0, REG_SZ, description, (uint)strlen(description)+1);
1117 sprintf(keyName, "%s\\shell", extension);
1118 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1119 RegSetValueEx(key, null, 0, REG_SZ, action, (uint)strlen(action)+1);
1122 sprintf(keyName, "%s\\shell\\%s", name, action);
1123 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1126 sprintf(keyName, "%s\\shell\\%s\\command", name, action);
1127 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1129 sprintf(keyName, path);
1130 strcat(keyName, " \"%L\"");
1132 uint16 wKeyName[2048];
1133 UTF8toUTF16Buffer(keyName, wKeyName, sizeof(wKeyName) / sizeof(uint16));
1134 RegSetValueExW(key, null, 0, REG_SZ, (byte *)wKeyName, (uint)(wcslen(wKeyName) + 1)*sizeof(uint16));
1139 class InstallThread : Thread
1144 ((GuiApplication)__thisModule).Lock();
1145 installProgress.progressBar.range = totalSize;
1146 for(c = 0; components[c].name && !abortInstall; c++)
1147 components[c].Install(installDir, installDir32);
1150 installProgress.progressBar.range = 0;
1151 installProgress.finish.Destroy(0);
1152 installProgress.cancel.text = $"Close";
1153 installProgress.cancel.isDefault = true;
1154 installProgress.cancel.disabled = false;
1155 installProgress.cancel.NotifyClicked = Window::ButtonCloseDialog;
1156 installProgress.installing.text = $"Installation Cancelled.";
1157 installProgress.title.text = $"Installation Cancelled";
1158 installProgress.titleInfo.contents = $"The installation was not completed.";
1162 char idePath[MAX_LOCATION];
1163 char userProfile[MAX_LOCATION];
1166 IDESettings settings = null; // Don't instantiate yet so we can pick up old settings
1168 IDESettingsContainer settingsContainer
1171 dataOwner = &settings;
1172 dataClass = class(IDESettings);
1174 CompilerConfig compiler;
1175 installProgress.installing.text = $"Configuring Ecere IDE...";
1176 ((GuiApplication)__thisModule).Unlock();
1177 ((GuiApplication)__thisModule).SignalEvent();
1179 settingsContainer.Load();
1180 compiler = settings.GetCompilerConfig(defaultCompilerName);
1185 for(c = 0; coreSDK[c].name; c++)
1187 char path[MAX_LOCATION];
1188 if(!coreSDK[c].selected || !coreSDK[c].available) continue;
1190 coreSDK[c].GetFullPath(path, false);
1191 if(c != ide && c != runtime && c != ec &&
1192 c != ide32 && c != runtime32 && c != ec32)
1193 PathCat(path, "bin");
1194 MakeSlashPath(path);
1195 if((c == ide && osIS64bit) || (c == ide32 && !osIS64bit))
1197 coreSDK[c].GetFullPath(idePath, false);
1198 PathCat(idePath, "ide.exe");
1201 if(c == runtime || c == runtime32)
1203 if(!compiler.libraryDirs.Find(path))
1204 compiler.libraryDirs.Add(CopyString(path));
1211 for(c = 0; c <= cpp; c++)
1213 char path[MAX_LOCATION];
1214 if(c == extras || !additional[c].selected || !additional[c].available) continue;
1215 additional[c].GetFullPath(path, false);
1216 if(c != upx && c != eda && c != vanilla && c != eda32 && c != vanilla32)
1217 PathCat(path, "bin");
1218 MakeSlashPath(path);
1219 if(c == vanilla || c == vanilla32)
1221 if(!compiler.libraryDirs.Find(path))
1222 compiler.libraryDirs.Add(CopyString(path));
1226 if(!compiler.executableDirs.Find(path))
1227 compiler.executableDirs.Add(CopyString(path));
1234 char path[MAX_LOCATION] = "";
1236 if(components[samples].selected)
1237 components[samples].GetFullPath(path, false);
1239 components[coreSDK].GetFullPath(path, false);
1241 if(!settings.ideProjectFileDialogLocation[0])
1242 settings.ideProjectFileDialogLocation = path;
1243 if(!settings.ideFileDialogLocation[0])
1244 settings.ideFileDialogLocation = path;
1246 if(documentation[apiRef].selected)
1248 documentation[apiRef].GetFullPath(path, false);
1249 if(!settings.docDir[0])
1250 settings.docDir = path;
1254 settingsContainer.Save();
1255 delete settingsContainer;
1258 // Set up Uninstaller
1259 ((GuiApplication)__thisModule).Lock();
1260 installProgress.installing.text = $"Registering uninstaller...";
1261 ((GuiApplication)__thisModule).Unlock();
1262 ((GuiApplication)__thisModule).SignalEvent();
1267 char * displayName = "Ecere SDK 0.44";
1268 char uninstaller[MAX_LOCATION];
1269 bool nomodify = true;
1271 strcpy(uninstaller, installDir);
1272 PathCat(uninstaller, "uninstall_ecere.exe");
1274 RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Ecere SDK", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1276 RegSetValueEx(key, "DisplayName", 0, REG_SZ, displayName, (uint)strlen(displayName)+1);
1277 RegSetValueEx(key, "UninstallString", 0, REG_SZ, uninstaller, (uint)strlen(uninstaller)+1);
1278 RegSetValueEx(key, "DisplayIcon", 0, REG_SZ, idePath, (uint)strlen(idePath)+1);
1279 //RegSetValueEx(key, "NoModify", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1280 //RegSetValueEx(key, "NoRepair", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1285 if(pathOptions[PathOptions::AddECEREPaths].selected
1287 || pathOptions[PathOptions::AddMinGWPaths].selected
1291 HKEY userKey = null, systemKey = null;
1293 char userPath[8192] = "";
1294 char systemPath[8192] = "";
1295 uint16 wUserPath[8192];
1296 uint16 wSystemPath[8192];
1301 ((GuiApplication)__thisModule).Lock();
1302 installProgress.installing.text = "Registering paths...";
1303 ((GuiApplication)__thisModule).Unlock();
1304 ((GuiApplication)__thisModule).SignalEvent();
1306 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, KEY_QUERY_VALUE, &systemKey) == ERROR_SUCCESS)
1308 size = sizeof(wSystemPath);
1309 RegQueryValueExW(systemKey, L"path", null, null, (byte *)wSystemPath, &size);
1310 UTF16toUTF8Buffer(wSystemPath, systemPath, sizeof(systemPath));
1313 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &userKey, &status);
1314 if(status == REG_OPENED_EXISTING_KEY)
1316 size = sizeof(wUserPath);
1317 RegQueryValueExW(userKey, L"path", null, null, (byte *)wUserPath, &size);
1318 UTF16toUTF8Buffer(wUserPath, userPath, sizeof(userPath));
1320 ModifyPath(systemPath, userPath);
1321 UTF8toUTF16Buffer(userPath, wUserPath, sizeof(wUserPath) / sizeof(uint16));
1322 RegSetValueExW(userKey, L"path", 0, REG_EXPAND_SZ, (byte *)wUserPath, (uint)(wcslen(wUserPath)+1) * 2);
1323 RegCloseKey(userKey);
1324 RegCloseKey(systemKey);
1326 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (int)"Environment", SMTO_NORMAL, 1000, NULL);
1329 // Install Program Group Icons
1330 GetEnvironment("USERPROFILE", userProfile, sizeof(userProfile));
1332 if(options[IconOptions::StartMenuIcon].selected)
1334 char destPath[MAX_LOCATION];
1335 char startMenuPath[MAX_LOCATION] = "";
1338 ((GuiApplication)__thisModule).Lock();
1339 installProgress.installing.text = $"Installing Start Menu Icons...";
1340 ((GuiApplication)__thisModule).Unlock();
1341 ((GuiApplication)__thisModule).SignalEvent();
1343 strcpy(destPath, userProfile);
1345 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1347 uint16 wStartMenuPath[2048];
1348 uint size = sizeof(wStartMenuPath);
1349 // RegQueryValueEx(key, "Start Menu", null, null, startMenuPath, &size);
1350 RegQueryValueExW(key, L"Programs", null, null, (byte *)wStartMenuPath, &size);
1351 UTF16toUTF8Buffer(wStartMenuPath, startMenuPath, sizeof(startMenuPath));
1354 if(!startMenuPath[0] && userProfile[0])
1356 strcpy(startMenuPath, userProfile);
1357 PathCat(startMenuPath, "Start Menu\\Programs");
1360 if(startMenuPath[0])
1362 strcpy(destPath, startMenuPath);
1363 PathCat(destPath, "Ecere SDK");
1366 strcpy(destPath, startMenuPath);
1367 PathCat(destPath, "Ecere SDK\\Ecere IDE.lnk");
1368 CreateLink(idePath, destPath, null); //"Ecere IDE");
1369 if(components[samples].selected)
1371 char samplesPath[MAX_LOCATION] = "";
1372 components[samples].GetFullPath(samplesPath, false);
1374 strcpy(destPath, startMenuPath);
1375 PathCat(destPath, "Ecere SDK\\Sample Projects.lnk");
1376 CreateLink(samplesPath, destPath, null);//"Sample Projects");
1378 if(components[documentation].selected && documentation[ecereBook].selected)
1380 char docPath[MAX_LOCATION] = "";
1381 documentation[ecereBook].GetFullPath(docPath, false);
1382 PathCat(docPath, "Ecere Tao of Programming [work in progress].pdf");
1385 char tao[MAX_LOCATION] ;
1386 documentation[ecereBook].GetFullPath(tao, false);
1387 PathCat(tao, "tao.pdf");
1388 RenameFile(tao, docPath);
1391 strcpy(destPath, startMenuPath);
1392 PathCat(destPath, "Ecere SDK\\The Ecere Tao of Programming.lnk");
1393 CreateLink(docPath, destPath, null);
1398 // Install Desktop Icon
1399 if(options[IconOptions::DesktopIcon].selected)
1402 char desktopPath[MAX_LOCATION];
1404 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1406 uint16 wDesktopPath[MAX_LOCATION];
1407 uint size = sizeof(wDesktopPath);
1408 RegQueryValueExW(key, L"Desktop", null, null, (byte *)wDesktopPath, &size);
1409 UTF16toUTF8Buffer(wDesktopPath, desktopPath, sizeof(desktopPath));
1412 if(!desktopPath[0] && userProfile[0])
1414 strcpy(desktopPath, userProfile);
1415 PathCat(desktopPath, "Desktop");
1420 PathCat(desktopPath, "Ecere IDE.lnk");
1422 ((GuiApplication)__thisModule).Lock();
1423 installProgress.installing.text = $"Installing Desktop Icon...";
1424 ((GuiApplication)__thisModule).Unlock();
1425 ((GuiApplication)__thisModule).SignalEvent();
1427 CreateLink(idePath, desktopPath, null);//"Ecere IDE");
1431 // Install QuickLaunch Icon
1432 if(options[IconOptions::QuickLaunchIcon].selected)
1434 char appData[MAX_LOCATION];
1435 GetEnvironment("APPDATA", appData, sizeof(appData));
1439 char destPath[MAX_LOCATION];
1441 ((GuiApplication)__thisModule).Lock();
1442 installProgress.installing.text = $"Installing Quicklaunch Icon...";
1443 ((GuiApplication)__thisModule).Unlock();
1444 ((GuiApplication)__thisModule).SignalEvent();
1446 strcpy(destPath, appData);
1447 PathCat(destPath, "Microsoft\\Internet Explorer\\Quick Launch\\Ecere IDE.lnk");
1449 CreateLink(idePath, destPath, null);//"Ecere IDE");
1453 // Register File Types
1454 if(associateOptions[AssociateOptions::AssociateEPJ].selected ||
1455 associateOptions[AssociateOptions::AssociateEC].selected ||
1456 associateOptions[AssociateOptions::AssociateC].selected ||
1457 associateOptions[AssociateOptions::AssociateCPP].selected ||
1458 associateOptions[AssociateOptions::AssociateTXT].selected ||
1459 associateOptions[AssociateOptions::Associate3DS].selected ||
1460 associateOptions[AssociateOptions::AssociateIMG].selected)
1462 ((GuiApplication)__thisModule).Lock();
1463 installProgress.installing.text = $"Resgistering File Types...";
1464 ((GuiApplication)__thisModule).Unlock();
1465 ((GuiApplication)__thisModule).SignalEvent();
1467 if(associateOptions[AssociateOptions::AssociateEPJ].selected)
1469 AssociateExtension(".epj", "Ecere IDE Project", "epj_file", "Open", idePath);
1471 if(associateOptions[AssociateOptions::AssociateEC].selected)
1473 AssociateExtension(".ec", "eC Source File", "ec_file", "Open", idePath);
1474 AssociateExtension(".eh", "eC Header File", "eh_file", "Open", idePath);
1476 if(associateOptions[AssociateOptions::AssociateC].selected)
1478 AssociateExtension(".c", "C Source File", "c_file", "Open", idePath);
1479 AssociateExtension(".h", "C Header File", "h_file", "Open", idePath);
1481 if(associateOptions[AssociateOptions::AssociateCPP].selected)
1483 AssociateExtension(".cpp", "C++ Source File", "cpp_file", "Open", idePath);
1484 AssociateExtension(".cc", "C++ Source File", "cpp_file", "Open", idePath);
1485 AssociateExtension(".cxx", "C++ Source File", "cpp_file", "Open", idePath);
1486 AssociateExtension(".chh", "C++ Header File", "chh_file", "Open", idePath);
1487 AssociateExtension(".hh", "C++ Header File", "chh_file", "Open", idePath);
1488 AssociateExtension(".hxx", "C++ Header File", "chh_file", "Open", idePath);
1490 if(associateOptions[AssociateOptions::AssociateTXT].selected)
1492 AssociateExtension(".txt", "Text File", "txt_file", "Open", idePath);
1494 if(associateOptions[AssociateOptions::Associate3DS].selected)
1496 AssociateExtension(".3ds", "3D Studio Model", "3ds_file", "View", idePath);
1498 if(associateOptions[AssociateOptions::AssociateIMG].selected)
1500 AssociateExtension(".bmp", "BMP Image", "bmp_file", "View", idePath);
1501 AssociateExtension(".pcx", "PCX Image", "pcx_file", "View", idePath);
1502 AssociateExtension(".png", "PNG Image", "png_file", "View", idePath);
1503 AssociateExtension(".jpg", "JPEG Image", "jpg_file", "View", idePath);
1504 AssociateExtension(".jpeg", "JPEG Image", "jpg_file", "View", idePath);
1505 AssociateExtension(".gif", "GIF Image", "gif_file", "View", idePath);
1508 ((GuiApplication)__thisModule).Lock();
1510 installProgress.cancel.Destroy(0);
1511 installProgress.finish.text = $"Finish";
1512 installProgress.finish.disabled = false;
1513 installProgress.finish.Activate();
1514 installProgress.installing.text = $"Installation Complete.";
1515 installProgress.title.text = $"Installation Complete";
1516 installProgress.titleInfo.contents = $"Thank you for using the Ecere SDK.";
1518 ((GuiApplication)__thisModule).Unlock();