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)
175 if(this != null && parent)
176 parent->GetFullPath(path);
178 strcpy(path, 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 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);
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);
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 PathCat(installDir, "Ecere SDK");
870 strcpy(installDir, programFilesDir);
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.08 \"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);
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);
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);
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);
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);
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);
1238 components[coreSDK].GetFullPath(path);
1240 if(!settings.ideProjectFileDialogLocation[0])
1241 settings.ideProjectFileDialogLocation = path;
1242 if(!settings.ideFileDialogLocation[0])
1243 settings.ideFileDialogLocation = path;
1245 if(documentation[apiRef].selected)
1247 documentation[apiRef].GetFullPath(path);
1248 if(!settings.docDir[0])
1249 settings.docDir = path;
1253 settingsContainer.Save();
1254 delete settingsContainer;
1257 // Set up Uninstaller
1258 ((GuiApplication)__thisModule).Lock();
1259 installProgress.installing.text = $"Registering uninstaller...";
1260 ((GuiApplication)__thisModule).Unlock();
1261 ((GuiApplication)__thisModule).SignalEvent();
1266 char * displayName = "Ecere SDK 0.44";
1267 char uninstaller[MAX_LOCATION];
1268 bool nomodify = true;
1270 strcpy(uninstaller, installDir);
1271 PathCat(uninstaller, "uninstall_ecere.exe");
1273 RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Ecere SDK", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1275 RegSetValueEx(key, "DisplayName", 0, REG_SZ, displayName, (uint)strlen(displayName)+1);
1276 RegSetValueEx(key, "UninstallString", 0, REG_SZ, uninstaller, (uint)strlen(uninstaller)+1);
1277 RegSetValueEx(key, "DisplayIcon", 0, REG_SZ, idePath, (uint)strlen(idePath)+1);
1278 //RegSetValueEx(key, "NoModify", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1279 //RegSetValueEx(key, "NoRepair", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1284 if(pathOptions[PathOptions::AddECEREPaths].selected
1286 || pathOptions[PathOptions::AddMinGWPaths].selected
1290 HKEY userKey = null, systemKey = null;
1292 char userPath[8192] = "";
1293 char systemPath[8192] = "";
1294 uint16 wUserPath[8192];
1295 uint16 wSystemPath[8192];
1300 ((GuiApplication)__thisModule).Lock();
1301 installProgress.installing.text = "Registering paths...";
1302 ((GuiApplication)__thisModule).Unlock();
1303 ((GuiApplication)__thisModule).SignalEvent();
1305 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, KEY_QUERY_VALUE, &systemKey) == ERROR_SUCCESS)
1307 size = sizeof(wSystemPath);
1308 RegQueryValueExW(systemKey, L"path", null, null, (byte *)wSystemPath, &size);
1309 UTF16toUTF8Buffer(wSystemPath, systemPath, sizeof(systemPath));
1312 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &userKey, &status);
1313 if(status == REG_OPENED_EXISTING_KEY)
1315 size = sizeof(wUserPath);
1316 RegQueryValueExW(userKey, L"path", null, null, (byte *)wUserPath, &size);
1317 UTF16toUTF8Buffer(wUserPath, userPath, sizeof(userPath));
1319 ModifyPath(systemPath, userPath);
1320 UTF8toUTF16Buffer(userPath, wUserPath, sizeof(wUserPath) / sizeof(uint16));
1321 RegSetValueExW(userKey, L"path", 0, REG_EXPAND_SZ, (byte *)wUserPath, (uint)(wcslen(wUserPath)+1) * 2);
1322 RegCloseKey(userKey);
1323 RegCloseKey(systemKey);
1325 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (int)"Environment", SMTO_NORMAL, 1000, NULL);
1328 // Install Program Group Icons
1329 GetEnvironment("USERPROFILE", userProfile, sizeof(userProfile));
1331 if(options[IconOptions::StartMenuIcon].selected)
1333 char destPath[MAX_LOCATION];
1334 char startMenuPath[MAX_LOCATION] = "";
1337 ((GuiApplication)__thisModule).Lock();
1338 installProgress.installing.text = $"Installing Start Menu Icons...";
1339 ((GuiApplication)__thisModule).Unlock();
1340 ((GuiApplication)__thisModule).SignalEvent();
1342 strcpy(destPath, userProfile);
1344 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1346 uint16 wStartMenuPath[2048];
1347 uint size = sizeof(wStartMenuPath);
1348 // RegQueryValueEx(key, "Start Menu", null, null, startMenuPath, &size);
1349 RegQueryValueExW(key, L"Programs", null, null, (byte *)wStartMenuPath, &size);
1350 UTF16toUTF8Buffer(wStartMenuPath, startMenuPath, sizeof(startMenuPath));
1353 if(!startMenuPath[0] && userProfile[0])
1355 strcpy(startMenuPath, userProfile);
1356 PathCat(startMenuPath, "Start Menu\\Programs");
1359 if(startMenuPath[0])
1361 strcpy(destPath, startMenuPath);
1362 PathCat(destPath, "Ecere SDK");
1365 strcpy(destPath, startMenuPath);
1366 PathCat(destPath, "Ecere SDK\\Ecere IDE.lnk");
1367 CreateLink(idePath, destPath, null); //"Ecere IDE");
1368 if(components[samples].selected)
1370 char samplesPath[MAX_LOCATION] = "";
1371 components[samples].GetFullPath(samplesPath);
1373 strcpy(destPath, startMenuPath);
1374 PathCat(destPath, "Ecere SDK\\Sample Projects.lnk");
1375 CreateLink(samplesPath, destPath, null);//"Sample Projects");
1377 if(components[documentation].selected && documentation[ecereBook].selected)
1379 char docPath[MAX_LOCATION] = "";
1380 documentation[ecereBook].GetFullPath(docPath);
1381 PathCat(docPath, "Ecere Tao of Programming [work in progress].pdf");
1384 char tao[MAX_LOCATION] ;
1385 documentation[ecereBook].GetFullPath(tao);
1386 PathCat(tao, "tao.pdf");
1387 RenameFile(tao, docPath);
1390 strcpy(destPath, startMenuPath);
1391 PathCat(destPath, "Ecere SDK\\The Ecere Tao of Programming.lnk");
1392 CreateLink(docPath, destPath, null);
1397 // Install Desktop Icon
1398 if(options[IconOptions::DesktopIcon].selected)
1401 char desktopPath[MAX_LOCATION];
1403 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1405 uint16 wDesktopPath[MAX_LOCATION];
1406 uint size = sizeof(wDesktopPath);
1407 RegQueryValueExW(key, L"Desktop", null, null, (byte *)wDesktopPath, &size);
1408 UTF16toUTF8Buffer(wDesktopPath, desktopPath, sizeof(desktopPath));
1411 if(!desktopPath[0] && userProfile[0])
1413 strcpy(desktopPath, userProfile);
1414 PathCat(desktopPath, "Desktop");
1419 PathCat(desktopPath, "Ecere IDE.lnk");
1421 ((GuiApplication)__thisModule).Lock();
1422 installProgress.installing.text = $"Installing Desktop Icon...";
1423 ((GuiApplication)__thisModule).Unlock();
1424 ((GuiApplication)__thisModule).SignalEvent();
1426 CreateLink(idePath, desktopPath, null);//"Ecere IDE");
1430 // Install QuickLaunch Icon
1431 if(options[IconOptions::QuickLaunchIcon].selected)
1433 char appData[MAX_LOCATION];
1434 GetEnvironment("APPDATA", appData, sizeof(appData));
1438 char destPath[MAX_LOCATION];
1440 ((GuiApplication)__thisModule).Lock();
1441 installProgress.installing.text = $"Installing Quicklaunch Icon...";
1442 ((GuiApplication)__thisModule).Unlock();
1443 ((GuiApplication)__thisModule).SignalEvent();
1445 strcpy(destPath, appData);
1446 PathCat(destPath, "Microsoft\\Internet Explorer\\Quick Launch\\Ecere IDE.lnk");
1448 CreateLink(idePath, destPath, null);//"Ecere IDE");
1452 // Register File Types
1453 if(associateOptions[AssociateOptions::AssociateEPJ].selected ||
1454 associateOptions[AssociateOptions::AssociateEC].selected ||
1455 associateOptions[AssociateOptions::AssociateC].selected ||
1456 associateOptions[AssociateOptions::AssociateCPP].selected ||
1457 associateOptions[AssociateOptions::AssociateTXT].selected ||
1458 associateOptions[AssociateOptions::Associate3DS].selected ||
1459 associateOptions[AssociateOptions::AssociateIMG].selected)
1461 ((GuiApplication)__thisModule).Lock();
1462 installProgress.installing.text = $"Resgistering File Types...";
1463 ((GuiApplication)__thisModule).Unlock();
1464 ((GuiApplication)__thisModule).SignalEvent();
1466 if(associateOptions[AssociateOptions::AssociateEPJ].selected)
1468 AssociateExtension(".epj", "Ecere IDE Project", "epj_file", "Open", idePath);
1470 if(associateOptions[AssociateOptions::AssociateEC].selected)
1472 AssociateExtension(".ec", "eC Source File", "ec_file", "Open", idePath);
1473 AssociateExtension(".eh", "eC Header File", "eh_file", "Open", idePath);
1475 if(associateOptions[AssociateOptions::AssociateC].selected)
1477 AssociateExtension(".c", "C Source File", "c_file", "Open", idePath);
1478 AssociateExtension(".h", "C Header File", "h_file", "Open", idePath);
1480 if(associateOptions[AssociateOptions::AssociateCPP].selected)
1482 AssociateExtension(".cpp", "C++ Source File", "cpp_file", "Open", idePath);
1483 AssociateExtension(".cc", "C++ Source File", "cpp_file", "Open", idePath);
1484 AssociateExtension(".cxx", "C++ Source File", "cpp_file", "Open", idePath);
1485 AssociateExtension(".chh", "C++ Header File", "chh_file", "Open", idePath);
1486 AssociateExtension(".hh", "C++ Header File", "chh_file", "Open", idePath);
1487 AssociateExtension(".hxx", "C++ Header File", "chh_file", "Open", idePath);
1489 if(associateOptions[AssociateOptions::AssociateTXT].selected)
1491 AssociateExtension(".txt", "Text File", "txt_file", "Open", idePath);
1493 if(associateOptions[AssociateOptions::Associate3DS].selected)
1495 AssociateExtension(".3ds", "3D Studio Model", "3ds_file", "View", idePath);
1497 if(associateOptions[AssociateOptions::AssociateIMG].selected)
1499 AssociateExtension(".bmp", "BMP Image", "bmp_file", "View", idePath);
1500 AssociateExtension(".pcx", "PCX Image", "pcx_file", "View", idePath);
1501 AssociateExtension(".png", "PNG Image", "png_file", "View", idePath);
1502 AssociateExtension(".jpg", "JPEG Image", "jpg_file", "View", idePath);
1503 AssociateExtension(".jpeg", "JPEG Image", "jpg_file", "View", idePath);
1504 AssociateExtension(".gif", "GIF Image", "gif_file", "View", idePath);
1507 ((GuiApplication)__thisModule).Lock();
1509 installProgress.cancel.Destroy(0);
1510 installProgress.finish.text = $"Finish";
1511 installProgress.finish.disabled = false;
1512 installProgress.finish.Activate();
1513 installProgress.installing.text = $"Installation Complete.";
1514 installProgress.title.text = $"Installation Complete";
1515 installProgress.titleInfo.contents = $"Thank you for using the Ecere SDK.";
1517 ((GuiApplication)__thisModule).Unlock();