2 static define buildString = $"Ecere SDK v0.44.08 (Without MinGW) -- built on August 8, 2013 ";
4 static define buildString = $"Ecere SDK v0.44.08 -- built on August 8, 2013 ";
7 #define WIN32_LEAN_AND_MEAN
8 #define GetFreeSpace _GetFreeSpace
26 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
31 void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)
33 if(!displayFlags.active) { displayFlags.current = false; displayFlags.selected = false; }
34 class::OnDisplay(surface, x + 22, y, width - 22, fieldData, alignment, displayFlags);
38 //#define BUFFERSIZE 0x10000
39 #define BUFFERSIZE 0x1000
40 bool abortInstall = false;
42 void ExtractFileFromArchive(ProgressBar progressBar, char * path, char * outputFile)
44 char fileName[MAX_LOCATION];
45 FileAttribs exists = FileExists(path);
49 if(exists.isDirectory)
51 FileListing listing { path };
55 if(MakeDir(outputFile))
58 FileGetStats(path, &stats);
62 while(listing.Find() && !abortInstall)
64 strcpy(fileName, outputFile);
66 // Tweak file name if out
69 if(!strcmp(fileName, ".")) fileName[0] = '\0';
70 if(listing.name[0] == '/' || listing.name[0] == '\\')
72 char * afterSlash, rest[MAX_LOCATION];
73 for(afterSlash = fileName; *afterSlash == '/' || *afterSlash == '\\'; afterSlash++);
74 strcpy(rest, afterSlash);
75 PathCat(fileName, "_root");
76 PathCat(fileName, rest);
78 else if(listing.name[1] == ':')
81 sprintf(letter, "_%cdrive", toupper(listing.name[0]));
82 PathCat(fileName, letter);
83 PathCat(fileName, listing.name[2] ? (listing.name + 3) : (listing.name + 2));
86 PathCat(fileName, listing.name);
89 PathCat(fileName, listing.name);
90 if(!strcmp(fileName, "/") || !strcmp(fileName, "\\"))
91 strcpy(fileName, DIR_SEPS);
92 ExtractFileFromArchive(progressBar, listing.path, fileName);
98 File input = FileOpen(path, read);
101 File output = FileOpen(outputFile, write);
104 char fileName[MAX_FILENAME];
105 uint position = progressBar.progress;
108 byte buffer[BUFFERSIZE];
110 FileGetSize(path, &dataSize);
111 GetLastDirectory(outputFile, fileName);
113 ((GuiApplication)__thisModule).SignalEvent();
114 //((GuiApplication)__thisModule).ProcessInput();
115 //((GuiApplication)__thisModule).UpdateDisplay();
117 for(c = 0; c<dataSize && !abortInstall; c += BUFFERSIZE)
119 uint size = (dataSize > c + BUFFERSIZE) ? BUFFERSIZE : (dataSize - c);
121 ((GuiApplication)__thisModule).Unlock();
123 input.Read(buffer, 1, size);
124 output.Write(buffer, 1, size);
126 ((GuiApplication)__thisModule).Lock();
128 progressBar.progress = position + c + size;
129 ((GuiApplication)__thisModule).SignalEvent();
131 //((GuiApplication)__thisModule).ProcessInput();
132 //((GuiApplication)__thisModule).UpdateDisplay();
137 FileGetStats(path, &stats);
143 FileSetTime(outputFile, stats.created, 0, stats.modified);
150 char * defInstallPath;
151 Component * subComponents;
160 char installPath[MAX_LOCATION];
163 void GetFullPath(char * path)
165 if(this != null && parent)
166 parent->GetFullPath(path);
168 strcpy(path, installDir);
171 PathCat(path, installPath);
174 void Install(char * parentPath)
179 char path[MAX_LOCATION];
180 strcpy(path, parentPath);
181 PathCat(path, installPath);
183 installProgress.installing.SetText($"Installing %s...", name);
184 ((GuiApplication)__thisModule).UpdateDisplay();
188 char source[MAX_LOCATION];
190 strcat(source, dataPath);
194 if(FileExists(source).isFile)
196 char name[MAX_FILENAME];
197 GetLastDirectory(source, name);
202 uint p = installProgress.progressBar.progress;
203 ExtractFileFromArchive(installProgress.progressBar, source, path);
208 for(c = 0; subComponents[c].name; c++)
209 subComponents[c].Install(path);
216 define minGWIncluded = true;
218 define minGWIncluded = false;
221 Component samples[] =
223 { "Ecere Chess", "samples/chess", "chess", null, false, true, true },
224 { "Ecere Fractals", "samples/fractals", "fractals", null, false, true, true },
225 { "3D", "samples/3D", "3D", null, false, true, true },
226 { "Audio", "samples/audio", "audio", null, false, true, true },
227 { "Database", "samples/db", "db", null, false, true, true },
228 { "eC", "samples/eC", "eC", null, false, true, true },
229 { "Games", "samples/games", "games", null, false, true, true },
230 { "GUI & Graphics", "samples/guiAndGfx", "guiAndGfx", null, false, true, true },
231 { "Miscellaneous", "samples/misc", "misc", null, false, true, true },
232 { "Networking", "samples/net", "net", null, false, true, true },
233 { "WIA Scanning", "samples/scanning", "scanning", null, false, true, true },
234 { "Threading", "samples/threads", "threads", null, false, true, true }
238 public enum CoreSDKID
241 gcc, gdb, mingw, binutils, make,
245 Component coreSDK[CoreSDKID] =
247 { "Ecere IDE", "ecere-sdk/ide", "bin", null, true, true, true },
248 { "Runtime Library", "ecere-sdk/ecere.dll", "bin", null, true, true, true },
249 { "eC Compiler", "ecere-sdk/compiler", "bin", null, true, true, true },
250 { "GNU C Compiler", "mingw/gcc/core", "mingw", null, true, true, minGWIncluded },
251 { "GNU Debugger", "mingw/gdb", "mingw", null, true, true, minGWIncluded },
252 { "MinGW Runtime", "mingw/mingwrt", "mingw", null, true, true, minGWIncluded },
253 { "Binary Utils", "mingw/binutils", "mingw", null, true, true, minGWIncluded },
254 { "GNU Make", "mingw/make", "mingw", null, true, true, minGWIncluded },
258 public enum AdditionalID
260 eda, vanilla, extras, upx, gnurx, pthreads, cpp, w32api, gcci18n, gdbi18n, makei18n, binutilsi18n
263 Component additional[AdditionalID] =
265 { "Data Access", "ecere-sdk/eda", "bin", null, false, true, true },
266 { "Ecere Vanilla", "ecere-sdk/libecereVanilla.a", "lib", null, false, true, true },
267 { "Ecere Extras", "extras", "extras", null, false, true, true },
268 { "UPX", "upx/bin", "bin", null, false, true, true },
269 { "GNU Regexp", "mingw/gnurx", "mingw", null, false, true, true },
270 { "pthreads", "mingw/pthreads", "mingw", null, false, true, minGWIncluded },
271 { "C++ Compiler", "mingw/gcc/c++", "mingw", null, false, true, minGWIncluded },
272 { "Win32 APIs", "mingw/w32api", "mingw", null, false, true, minGWIncluded },
273 { "GCC I18n", "mingw/locale/gcc", "mingw", null, false, false, minGWIncluded },
274 { "GDB I18n", "mingw/locale/gdb", "mingw", null, false, false, minGWIncluded },
275 { "Make I18n", "mingw/locale/make", "mingw", null, false, false, minGWIncluded },
276 { "Binutils I18n", "mingw/locale/binutils", "mingw", null, false, false, minGWIncluded },
280 public enum DocumentationID
282 ecereBook, apiRef, tutorials, coursework,
283 gccDoc, gppDocs, gdbDocs, makeDocs, binDocs, mingwDocs, gnurxDocs, upxDocs,
287 Component documentation[DocumentationID] =
289 { "Ecere Book", "ecere-sdk/book", "doc", null, false, true, true },
290 { "API Reference", "ecere-sdk/doc", "doc", null, false, true, true },
291 { "Ecere Tutorials", "ecere-sdk/tutorials", "doc", null, false, true, true },
292 { "Ecere Coursework", "ecere-sdk/coursework", "doc", null, false, true, true },
293 { "GCC Docs", "mingw/doc/gcc", "mingw", null, false, false, minGWIncluded },
294 { "G++ Docs", "mingw/doc/g++", "mingw", null, false, false, minGWIncluded },
295 { "GDB Docs", "mingw/doc/gdb", "mingw", null, false, false, minGWIncluded },
296 { "Make Docs", "mingw/doc/make", "mingw", null, false, false, minGWIncluded },
297 { "Binutils Docs", "mingw/doc/binutils", "mingw", null, false, false, minGWIncluded },
298 { "MinGW Docs", "mingw/doc/mingwrt", "mingw", null, false, false, minGWIncluded },
299 { "gnurx Docs", "mingw/doc/gnurx", "mingw", null, false, false, minGWIncluded },
300 { "UPX Docs", "upx/doc", "mingw/doc/upx", null, false, false, minGWIncluded },
304 public enum ComponentID
313 Component components[ComponentID] =
315 { "Core SDK Files", null, null, coreSDK, true, true, true },
316 { "Additional Support", null, null, additional, false, true, true },
317 { "Documentation", null /*"doc"*/, null /*"doc"*/, documentation, false, true, true },
318 { "Samples", null, "samples", samples, false, true, true },
322 FileSize totalInstalled;
327 InstallOption * subOptions;
333 enum AssociateOptions
344 InstallOption associateOptions[] =
346 { "Associate with Ecere Project Files (*.epj)", null, true },
347 { "Associate with eC Files (*.ec, *.eh)", null, true },
348 { "Associate with C files (*.c, *.h)", null, false },
349 { "Associate with C++ Files (*.cpp, *.hpp, *.cc, *.hh, *.cxx, *.hxx)", null, false },
350 { "Associate with text files (*.txt)", null, false },
351 { "Associate with 3D Studio Model Files (*.3ds)", null, true },
352 { "Associate with Image Files (*.png, *.jpg, *.pcx, *.bmp, *.gif)", null, false },
358 AddECEREPaths, AddMinGWPaths
361 InstallOption pathOptions[] =
363 { "Add Ecere binaries location to the system path", null, true, true },
364 { "Add MinGW to the system path", null, true, minGWIncluded }
375 InstallOption options[] =
377 { "Start Menu Group", null, true, true },
378 { "Desktop Icon", null, true, true },
379 { "Quicklaunch Icon", null, true, true },
380 { "Associate the ECERE IDE with Supported File Types", associateOptions, true, true },
381 { "Add binaries location to the system paths", pathOptions, true, minGWIncluded },
385 char sourceDir[MAX_LOCATION] = ":";
386 char installDir[MAX_LOCATION];
388 class Installer : Window
390 text = $"Ecere Software Development Kit Setup - v0.44.08 \"Ryōan-ji\"";
391 background = activeBorder;
396 clientSize = { 636, 456 };
397 // clientSize = { 796, 576 };
398 icon = { ":icon.png" };
400 Picture back { image = BitmapResource { ":ryoanji.png" }, parent = this, position = { 0, 0 } };
401 FileDialog fileDialog
403 master = this, type = selectDir,
404 text = $"Select a new location"
408 master = this, autoCreate = false, inactive = true, text = "...";
410 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
412 DataRow row = componentsBox.currentRow;
413 Component * component = ((CheckItem *)row.GetData(componentField))->data;
414 component->GetFullPath(fileDialog.filePath);
415 StripLastDirectory(fileDialog.filePath, fileDialog.currentDirectory);
417 if(fileDialog.Modal() == ok)
419 componentsBox.StopEditing(false);
420 row.SetData(locationField, fileDialog.filePath);
421 componentsBox.NotifyChanged(this, componentsBox, row);
422 componentsBox.currentField = componentsBox.currentField;
427 CheckListBox componentsBox
429 this, size = { 460, 112 }, position = { 160, 160 }, hasHeader = true;
430 fullRowSelect = false, collapseControl = true, treeBranches = true, rootCollapseButton = true,
433 selectionColor = { 145, 150, 140 };
438 bool NotifyKeyDown(ListBox listBox, DataRow row, Key key, unichar ch)
440 if(key == f2 && browse.visible)
441 browse.NotifyClicked(this, browse, 0, 0, 0);
445 bool NotifyChanged(ListBox listBox, DataRow row)
447 Component * component = ((CheckItem *)listBox.GetData(componentField))->data;
448 char path[MAX_LOCATION], relative[MAX_LOCATION] = "", * newPath;
449 char fullPath[MAX_LOCATION];
451 component->parent->GetFullPath(path);
452 strcpy(fullPath, path);
454 newPath = row.GetData(locationField);
457 PathCat(fullPath, newPath);
458 MakePathRelative(fullPath, path, relative);
460 listBox.SetData(locationField, relative);
461 strcpy(component->installPath, relative);
463 //SetAvailableSpace(component, path);
466 install.disabled = false;
467 for(c = 0; components[c].name; c++)
469 SetAvailableSpace(components[c], installDir);
475 bool NotifyEditDone(ListBox listBox, DataRow row)
481 bool NotifyEdited(ListBox listBox, DataRow row)
484 browse.parent = listBox;
485 browse.position = { componentField.width + locationField.width + 18, (listBox.currentIndex+1) * listBox.rowHeight - 2 };
486 browse.size = { 30, listBox.rowHeight + 3 };
487 for(e = listBox.firstChild; e; e = e.next)
489 if(e._class == class(DataBox))
498 void NotifyChecked(CheckListBox listBox, DataRow row)
500 Component * component = ((CheckItem *)row.GetData(componentField))->data;
502 component->selected = listBox.IsChecked(row);
504 if(!component->parent) totalSize -= component->requiredSize;
505 component->requiredSize = 0;
506 if(component->selected)
508 component->requiredSize += component->size;
509 if(component->subComponents)
510 for(c = 0; component->subComponents[c].name; c++)
511 component->requiredSize += component->subComponents[c].requiredSize;
513 if(component->requiredSize)
515 uint requiredSize = component->requiredSize;
516 row.SetData(reqField, requiredSize);
519 row.UnsetData(reqField);
520 if(!component->parent)
522 totalSize += component->requiredSize;
524 char sizeString[100];
525 PrintSize(sizeString, totalSize, 2);
526 totalSpaceValue.text = sizeString;
531 Label agreementLbl { parent = this, text = $"By installing the Ecere SDK, you agree to the .", font = { "Tahoma", 8.25f }, anchor = Anchor { left = 24, top = 424 } };
534 this, inactive = true, offset = false, bevel = false, foreground = blue, font = { "Tahoma", 8.25f, underline = true, bold = true },
535 // text = $"terms and conditions", anchor = Anchor { left = 241, top = 421 };
536 text = $"terms and conditions", anchor = Anchor { left = 237, top = 421 };
537 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
539 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
541 // LicenseBox { master = this, sourceFile = ":ecere-sdk/doc/LICENSE" }.Modal();
542 LicensesForm { master = this }.Modal();
546 CheckListBox optionsBox
548 this, size = { 460, 94 }, position = { 160, 284 };
549 fullRowSelect = false, collapseControl = true, treeBranches = true, rootCollapseButton = true,
554 void NotifyChecked(CheckListBox listBox, DataRow row)
556 CheckItem * item = row.GetData(optionField);
557 InstallOption * option = item->data;
558 option->selected = listBox.IsChecked(row);
563 parent = this, text = $"Install", isDefault = true, size = { 75, 23 }, position = { 432, 416 };
565 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
567 installProgress.Create();
569 // installProgress.thread.Main();
570 installProgress.thread.Create();
574 Button button3 { parent = this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 }, NotifyClicked = ButtonCloseDialog };
575 Label label1 { labeledWindow = destBox, tabCycle = true, isGroupBox = true, parent = this, inactive = false, size = Size { 458, 50 }, anchor = Anchor { left = 160, top = 96 } };
578 parent = label1, master = this, text = $" Destination Folder", size = Size { 336, 22 }, anchor = Anchor { left = 12, top = 20, right = 12 };
579 typeExpected = directory;
580 browseDialog = fileDialog;
583 bool NotifyModified(PathBox pathBox)
586 strcpy(installDir, destBox.path);
587 install.disabled = false;
588 for(c = 0; components[c].name; c++)
590 SetAvailableSpace(components[c], installDir);
597 label1, this, $"Browse", altB, size = { 83, 24 }, position = { 360, 16 };
599 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
601 strcpy(fileDialog.filePath, installDir);
602 StripLastDirectory(installDir, fileDialog.currentDirectory);
603 if(fileDialog.Modal())
605 strcpy(installDir, fileDialog.filePath);
606 destBox.contents = installDir;
607 // TOCHECK: Should setting contents call NotifyModified?
608 destBox.NotifyModified(destBox.master, destBox);
615 this, multiLine = true,
616 opacity = 0, borderStyle = none, inactive = true, size = { 136, 53 }, position = { 14, 96 }, noSelect = true,
617 contents = $"Select the default root\n"
618 "folder where to install\n"
623 this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 132 }, position = { 14, 152 }, noSelect = true,
625 contents = $"Select the optional\n"
626 "components you wish\n"
628 "You may customize the\n"
629 "install location for each\n"
630 "of them, or use the default\n"
631 "based on the main\n"
632 "destination folder."
636 this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 53 }, position = { 14, 280 }, noSelect = true,
638 contents = $"Select icons to install, file\n"
639 "associations, and system\n"
640 "environment modifications:"
642 Label totalSpaceLabel
644 this, position = { 18, 352 }, text = $"Space Required: "
646 Label totalSpaceValue
648 this, position = { 100, 352 }, text = "0 mb"
652 inactive = true, noSelect = true,
653 multiLine = true, parent = label3, text = "editBox1", opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 },
654 contents = $"Choose in which folder to install the Ecere SDK, which features\n"
655 "of the SDK to install, as well as where to install program icons."
657 Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder };
660 image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, text = "picture1", anchor = Anchor { left = 16, top = 4 };
661 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
663 bool OnLeftButtonDown(int x, int y, Modifiers mods)
665 ShellOpen("http://www.ecere.com/");
669 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 } };
670 DataField componentField { "CheckItem", width = 140, header = $"Component" };
671 DataField locationField { "char *", width = 108, header = $"Destination Folder", editable = true };
672 DataField reqField { "FileSize", width = 80, header = $"Req. Space", alignment = right };
673 DataField avField { "FileSize64", width = 80, header = $"Avail. Space", alignment = right };
674 DataField optionField { "CheckItem" };
676 void SetAvailableSpace(Component component, char * parentPath)
678 char path[MAX_LOCATION];
682 strcpy(path, parentPath);
683 PathCat(path, component.installPath);
685 if(component.subComponents)
686 for(c = 0; component.subComponents[c].name; c++)
687 SetAvailableSpace(component.subComponents[c], path);
689 while(!FileExists(path) && path[0])
690 StripLastDirectory(path, path);
693 GetFreeSpace(path, &size);
694 component.row.SetData(avField, size);
695 if(!size) install.disabled = true;
698 FileSize ComputeSize(char * path)
701 FileAttribs attribs = FileExists(path);
702 if(attribs.isDirectory)
704 FileListing listing { path };
705 while(listing.Find())
707 if(listing.stats.attribs.isDirectory)
708 size += ComputeSize(listing.path);
710 size += listing.stats.size;
714 FileGetSize(path, &size);
718 void AddComponent(Component component, Component parent, char * parentPath)
720 DataRow row = (parent != null) ? parent.row.AddRow() : componentsBox.AddRow();
722 FileSize64 avSize = 0;
723 char path[MAX_LOCATION];
726 strcpy(path, parentPath);
727 if(component.defInstallPath)
728 PathCat(path, component.defInstallPath);
729 component.parent = parent;
731 row.SetData(null, CheckItem { component.name, component } );
733 if(component.defInstallPath)
735 strcpy(component.installPath, component.defInstallPath);
736 ChangeCh(component.installPath, '/', DIR_SEP);
737 row.SetData(locationField, component.installPath);
740 if(component.mandatory)
741 componentsBox.SetDisabled(row, true);
742 componentsBox.SetCheck(row, component.selected);
744 if(component.dataPath)
746 char path[MAX_LOCATION];
748 PathCat(path, component.dataPath);
749 component.size = ComputeSize(path);
751 if(component.subComponents)
754 for(c = 0; component.subComponents[c].name; c++)
756 if(component.subComponents[c].available)
758 AddComponent(component.subComponents[c], component, path);
759 size += component.subComponents[c].requiredSize;
762 component.subComponents[c].selected = false;
766 component.requiredSize = component.selected ? (size + component.size) : 0;
767 if(component.requiredSize)
768 row.SetData(reqField, component.requiredSize);
770 while(!FileExists(path) && path[0])
771 StripLastDirectory(path, path);
774 GetFreeSpace(path, &avSize);
777 row.SetData(avField, avSize);
778 row.collapsed = true;
781 void AddOption(InstallOption option, InstallOption parent)
783 DataRow row = option.row = (parent != null) ? parent.row.AddRow() : optionsBox.AddRow();
784 row.SetData(null, CheckItem { option.name, option } );
785 optionsBox.SetCheck(row, option.selected);
786 if(option.subOptions)
789 for(c = 0; option.subOptions[c].name; c++)
791 AddOption(option.subOptions[c], option);
794 row.collapsed = true;
800 char programFilesDir[MAX_LOCATION];
801 char appData[MAX_LOCATION];
802 char homeDrive[MAX_LOCATION];
803 char winDir[MAX_LOCATION];
805 GetEnvironment("APPDATA", appData, sizeof(appData));
806 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
807 GetEnvironment("windir", winDir, sizeof(winDir));
809 componentsBox.AddField(componentField);
810 componentsBox.AddField(locationField);
811 componentsBox.AddField(reqField);
812 componentsBox.AddField(avField);
814 optionsBox.AddField(optionField);
816 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
818 strcpy(installDir, programFilesDir);
819 PathCat(installDir, "Ecere SDK");
821 else if(homeDrive && homeDrive[0])
823 strcpy(installDir, homeDrive);
824 PathCat(installDir, "Ecere SDK");
826 else if(winDir && winDir[0])
828 strcpy(installDir, winDir);
829 PathCat(installDir, "..\\Ecere SDK");
832 strcpy(installDir, "C:\\Ecere SDK");
834 if(appData && appData[0])
836 static char defSamplesPath[MAX_LOCATION];
837 static char defExtrasPath[MAX_LOCATION];
838 strcpy(defSamplesPath, appData);
839 PathCat(defSamplesPath, "Ecere SDK\\Samples");
840 components[samples].defInstallPath = defSamplesPath;
842 strcpy(defExtrasPath, appData);
843 PathCat(defExtrasPath, "Ecere SDK\\extras");
844 additional[extras].defInstallPath = defExtrasPath;
847 destBox.path = installDir;
851 for(c = 0; components[c].name; c++)
852 AddComponent(components[c], null, installDir);
855 // Compute size apart because ToggleCheck will change it
859 for(c = 0; components[c].name; c++)
860 totalSize += components[c].requiredSize;
863 char sizeString[100];
864 PrintSize(sizeString, totalSize, 2);
865 totalSpaceValue.text = sizeString;
867 for(c = 0; options[c].name; c++)
868 AddOption(options[c], null);
877 void OnDrawOverChildren(Surface surface)
879 int tw = label2.size.w;
880 surface.SetForeground(Color { 128, 128, 128 });
881 surface.HLine(label2.position.x + tw + 6, 620, 400);
882 surface.SetForeground(white);
883 surface.HLine(label2.position.x + tw + 6, 621, 401);
884 surface.PutPixel(621, 400);
889 parent = this, opacity = 0, borderStyle = deep, size = Size { 644, 93 }, anchor = Anchor { left = -8, top = -8 };
893 class InstallProgress : Window
895 text = $"Ecere Software Development Kit Setup - v0.44 \"Ryōan-ji\"";
896 background = activeBorder;
901 // size = Size { 640, 480 };
902 clientSize = { 636, 456 };
903 //clientSize = { 796, 576 };
904 icon = { ":icon.png" };
906 Picture back { image = BitmapResource { ":ryoanji-progress.png" }, parent = this, position = { 0, 0 } };
907 Label installing { this, position = { 32, 160 } };
908 ProgressBar progressBar { parent = this, size = Size { 588, 24 }, anchor = Anchor { left = 24, top = 184 } };
911 parent = this, text = $"Install", disabled = true, isDefault = true, size = Size { 75, 23 }, anchor = Anchor { left = 432, top = 416 };
913 NotifyClicked = ButtonCloseDialog
917 this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 };
919 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
927 inactive = true, noSelect = true,
928 multiLine = true, parent = label3, opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 },
929 contents = $"Please wait while the Ecere Software Development Kit is being installed."
931 Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder };
934 image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, anchor = Anchor { left = 16, top = 4 };
935 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
937 bool OnLeftButtonDown(int x, int y, Modifiers mods)
939 ShellOpen("http://www.ecere.com/");
943 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 } };
945 void OnDrawOverChildren(Surface surface)
947 int tw = label2.size.w;
948 surface.SetForeground(Color { 128, 128, 128 });
949 surface.HLine(label2.position.x + tw + 6, 620, 400);
950 surface.SetForeground(white);
951 surface.HLine(label2.position.x + tw + 6, 621, 401);
952 surface.PutPixel(621, 400);
957 parent = this, opacity = 0, borderStyle = deep, size = Size { 644, 93 }, anchor = Anchor { left = -8, top = -8 };
964 Installer installer {};
965 InstallProgress installProgress { autoCreate = false };
967 static void AddPath(char * sysPaths[200], int sysCount, char * paths[200], int * count, char * oldPath, char * userPath, char * path)
971 for(p = 0; p<sysCount; p++)
972 if(!fstrcmp(sysPaths[p], path))
977 for(p = 0; !found && p<*count; p++)
978 if(!fstrcmp(paths[p], path))
988 strcat(userPath, ";");
989 start = paths[(*count)-1] + strlen(paths[(*count)-1])+1;
995 *(start + strlen(path)) = '\0';
996 paths[(*count)++] = start;
998 strcat(userPath, path);
1003 void ModifyPath(char * systemPath, char * userPath)
1005 char oldPath[8192], * paths[200], * sysPaths[200];
1006 int count, sysCount;
1008 strcpy(oldPath, userPath);
1009 count = TokenizeWith(oldPath, sizeof(paths) / sizeof(char *), paths, ";", false);
1010 sysCount = TokenizeWith(systemPath, sizeof(sysPaths) / sizeof(char *), sysPaths, ";", false);
1014 for(c = 0; coreSDK[c].name; c++)
1017 char path[MAX_LOCATION];
1018 if(!coreSDK[c].selected) continue;
1019 coreSDK[c].GetFullPath(path);
1020 if(c != ide && c != runtime && c != ec)
1022 if(!pathOptions[PathOptions::AddMinGWPaths].available || !pathOptions[PathOptions::AddMinGWPaths].selected)
1024 PathCat(path, "bin");
1026 else if(!pathOptions[PathOptions::AddECEREPaths].selected) continue;
1028 AddPath(sysPaths, sysCount, paths, &count, oldPath, userPath, path);
1033 // Up to before Win32 APIs
1034 for(c = 0; c < w32api; c++)
1037 char path[MAX_LOCATION];
1038 if(!additional[c].selected || c == vanilla || c == extras) continue;
1039 if((c != eda && c != upx) && (!pathOptions[PathOptions::AddMinGWPaths].available || !pathOptions[PathOptions::AddMinGWPaths].selected))
1041 additional[c].GetFullPath(path);
1042 if(c != eda && c != upx)
1043 PathCat(path, "bin");
1044 AddPath(sysPaths, sysCount, paths, &count, oldPath, userPath, path);
1049 void AssociateExtension(char * extension, char * description, char *name, char * action, char * path)
1055 RegCreateKeyEx(HKEY_CLASSES_ROOT, extension, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1056 RegSetValueEx(key, null, 0, REG_SZ, name, (uint)strlen(name)+1);
1059 RegCreateKeyEx(HKEY_CLASSES_ROOT, name, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1060 RegSetValueEx(key, null, 0, REG_SZ, description, (uint)strlen(description)+1);
1063 sprintf(keyName, "%s\\shell", extension);
1064 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1065 RegSetValueEx(key, null, 0, REG_SZ, action, (uint)strlen(action)+1);
1068 sprintf(keyName, "%s\\shell\\%s", name, action);
1069 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1072 sprintf(keyName, "%s\\shell\\%s\\command", name, action);
1073 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1075 sprintf(keyName, path);
1076 strcat(keyName, " \"%L\"");
1078 uint16 wKeyName[2048];
1079 UTF8toUTF16Buffer(keyName, wKeyName, sizeof(wKeyName) / sizeof(uint16));
1080 RegSetValueExW(key, null, 0, REG_SZ, (byte *)wKeyName, (uint)(wcslen(wKeyName) + 1)*sizeof(uint16));
1085 class InstallThread : Thread
1090 ((GuiApplication)__thisModule).Lock();
1091 installProgress.progressBar.range = totalSize;
1092 for(c = 0; components[c].name && !abortInstall; c++)
1093 components[c].Install(installDir);
1096 installProgress.progressBar.range = 0;
1097 installProgress.finish.Destroy(0);
1098 installProgress.cancel.text = $"Close";
1099 installProgress.cancel.isDefault = true;
1100 installProgress.cancel.disabled = false;
1101 installProgress.cancel.NotifyClicked = Window::ButtonCloseDialog;
1102 installProgress.installing.text = $"Installation Cancelled.";
1103 installProgress.title.text = $"Installation Cancelled";
1104 installProgress.titleInfo.contents = $"The installation was not completed.";
1108 char idePath[MAX_LOCATION];
1109 char userProfile[MAX_LOCATION];
1112 IDESettings settings = null; // Don't instantiate yet so we can pick up old settings
1114 IDESettingsContainer settingsContainer
1117 dataOwner = &settings;
1118 dataClass = class(IDESettings);
1120 CompilerConfig compiler;
1121 installProgress.installing.text = $"Configuring ECERE IDE...";
1122 ((GuiApplication)__thisModule).Unlock();
1123 ((GuiApplication)__thisModule).SignalEvent();
1125 settingsContainer.Load();
1126 compiler = settings.GetCompilerConfig(defaultCompilerName);
1131 for(c = 0; coreSDK[c].name; c++)
1133 char path[MAX_LOCATION];
1134 if(!coreSDK[c].selected || !coreSDK[c].available) continue;
1136 coreSDK[c].GetFullPath(path);
1137 if(c != ide && c != runtime && c != ec)
1138 PathCat(path, "bin");
1139 MakeSlashPath(path);
1142 coreSDK[c].GetFullPath(idePath);
1143 PathCat(idePath, "IDE.exe");
1148 if(!compiler.libraryDirs.Find(path))
1149 compiler.libraryDirs.Add(CopyString(path));
1155 // Up to before Win32 APIs
1156 for(c = 0; c < w32api; c++)
1158 char path[MAX_LOCATION];
1159 if(c == extras || !additional[c].selected || !additional[c].available) continue;
1160 additional[c].GetFullPath(path);
1161 if(c != upx && c != eda && c != vanilla)
1162 PathCat(path, "bin");
1163 MakeSlashPath(path);
1166 if(!compiler.libraryDirs.Find(path))
1167 compiler.libraryDirs.Add(CopyString(path));
1171 if(!compiler.executableDirs.Find(path))
1172 compiler.executableDirs.Add(CopyString(path));
1179 char path[MAX_LOCATION] = "";
1181 if(components[samples].selected)
1182 components[samples].GetFullPath(path);
1184 components[coreSDK].GetFullPath(path);
1186 if(!settings.ideProjectFileDialogLocation[0])
1187 settings.ideProjectFileDialogLocation = path;
1188 if(!settings.ideFileDialogLocation[0])
1189 settings.ideFileDialogLocation = path;
1191 if(documentation[apiRef].selected)
1193 documentation[apiRef].GetFullPath(path);
1194 if(!settings.docDir[0])
1195 settings.docDir = path;
1199 settingsContainer.Save();
1200 delete settingsContainer;
1203 // Set up Uninstaller
1204 ((GuiApplication)__thisModule).Lock();
1205 installProgress.installing.text = $"Registering uninstaller...";
1206 ((GuiApplication)__thisModule).Unlock();
1207 ((GuiApplication)__thisModule).SignalEvent();
1212 char * displayName = "Ecere SDK 0.44";
1213 char uninstaller[MAX_LOCATION];
1214 bool nomodify = true;
1216 strcpy(uninstaller, installDir);
1217 PathCat(uninstaller, "uninstall_ecere.exe");
1219 RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\Ecere SDK", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1221 RegSetValueEx(key, "DisplayName", 0, REG_SZ, displayName, (uint)strlen(displayName)+1);
1222 RegSetValueEx(key, "UninstallString", 0, REG_SZ, uninstaller, (uint)strlen(uninstaller)+1);
1223 RegSetValueEx(key, "DisplayIcon", 0, REG_SZ, idePath, (uint)strlen(idePath)+1);
1224 //RegSetValueEx(key, "NoModify", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1225 //RegSetValueEx(key, "NoRepair", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1230 if(pathOptions[PathOptions::AddECEREPaths].selected
1232 || pathOptions[PathOptions::AddMinGWPaths].selected
1236 HKEY userKey = null, systemKey = null;
1238 char userPath[8192] = "";
1239 char systemPath[8192] = "";
1240 uint16 wUserPath[8192];
1241 uint16 wSystemPath[8192];
1246 ((GuiApplication)__thisModule).Lock();
1247 installProgress.installing.text = "Registering paths...";
1248 ((GuiApplication)__thisModule).Unlock();
1249 ((GuiApplication)__thisModule).SignalEvent();
1251 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, KEY_QUERY_VALUE, &systemKey) == ERROR_SUCCESS)
1253 size = sizeof(wSystemPath);
1254 RegQueryValueExW(systemKey, L"path", null, null, (byte *)wSystemPath, &size);
1255 UTF16toUTF8Buffer(wSystemPath, systemPath, sizeof(systemPath));
1258 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &userKey, &status);
1259 if(status == REG_OPENED_EXISTING_KEY)
1261 size = sizeof(wUserPath);
1262 RegQueryValueExW(userKey, L"path", null, null, (byte *)wUserPath, &size);
1263 UTF16toUTF8Buffer(wUserPath, userPath, sizeof(userPath));
1265 ModifyPath(systemPath, userPath);
1266 UTF8toUTF16Buffer(userPath, wUserPath, sizeof(wUserPath) / sizeof(uint16));
1267 RegSetValueExW(userKey, L"path", 0, REG_EXPAND_SZ, (byte *)wUserPath, (uint)(wcslen(wUserPath)+1) * 2);
1268 RegCloseKey(userKey);
1269 RegCloseKey(systemKey);
1271 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (int)"Environment", SMTO_NORMAL, 1000, NULL);
1274 // Install Program Group Icons
1275 GetEnvironment("USERPROFILE", userProfile, sizeof(userProfile));
1277 if(options[IconOptions::StartMenuIcon].selected)
1279 char destPath[MAX_LOCATION];
1280 char startMenuPath[MAX_LOCATION] = "";
1283 ((GuiApplication)__thisModule).Lock();
1284 installProgress.installing.text = $"Installing Start Menu Icons...";
1285 ((GuiApplication)__thisModule).Unlock();
1286 ((GuiApplication)__thisModule).SignalEvent();
1288 strcpy(destPath, userProfile);
1290 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1292 uint16 wStartMenuPath[2048];
1293 uint size = sizeof(wStartMenuPath);
1294 // RegQueryValueEx(key, "Start Menu", null, null, startMenuPath, &size);
1295 RegQueryValueExW(key, L"Programs", null, null, (byte *)wStartMenuPath, &size);
1296 UTF16toUTF8Buffer(wStartMenuPath, startMenuPath, sizeof(startMenuPath));
1299 if(!startMenuPath[0] && userProfile[0])
1301 strcpy(startMenuPath, userProfile);
1302 PathCat(startMenuPath, "Start Menu\\Programs");
1305 if(startMenuPath[0])
1307 strcpy(destPath, startMenuPath);
1308 PathCat(destPath, "Ecere SDK");
1311 strcpy(destPath, startMenuPath);
1312 PathCat(destPath, "Ecere SDK\\Ecere IDE.lnk");
1313 CreateLink(idePath, destPath, null); //"ECERE IDE");
1314 if(components[samples].selected)
1316 char samplesPath[MAX_LOCATION] = "";
1317 components[samples].GetFullPath(samplesPath);
1319 strcpy(destPath, startMenuPath);
1320 PathCat(destPath, "Ecere SDK\\Sample Projects.lnk");
1321 CreateLink(samplesPath, destPath, null);//"Sample Projects");
1323 if(components[documentation].selected && documentation[ecereBook].selected)
1325 char docPath[MAX_LOCATION] = "";
1326 documentation[ecereBook].GetFullPath(docPath);
1327 PathCat(docPath, "Ecere Tao of Programming [work in progress].pdf");
1330 char tao[MAX_LOCATION] ;
1331 documentation[ecereBook].GetFullPath(tao);
1332 PathCat(tao, "tao.pdf");
1333 RenameFile(tao, docPath);
1336 strcpy(destPath, startMenuPath);
1337 PathCat(destPath, "Ecere SDK\\The Ecere Tao of Programming.lnk");
1338 CreateLink(docPath, destPath, null);
1343 // Install Desktop Icon
1344 if(options[IconOptions::DesktopIcon].selected)
1347 char desktopPath[MAX_LOCATION];
1349 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1351 uint16 wDesktopPath[MAX_LOCATION];
1352 uint size = sizeof(wDesktopPath);
1353 RegQueryValueExW(key, L"Desktop", null, null, (byte *)wDesktopPath, &size);
1354 UTF16toUTF8Buffer(wDesktopPath, desktopPath, sizeof(desktopPath));
1357 if(!desktopPath[0] && userProfile[0])
1359 strcpy(desktopPath, userProfile);
1360 PathCat(desktopPath, "Desktop");
1365 PathCat(desktopPath, "ECERE IDE.lnk");
1367 ((GuiApplication)__thisModule).Lock();
1368 installProgress.installing.text = $"Installing Desktop Icon...";
1369 ((GuiApplication)__thisModule).Unlock();
1370 ((GuiApplication)__thisModule).SignalEvent();
1372 CreateLink(idePath, desktopPath, null);//"ECERE IDE");
1376 // Install QuickLaunch Icon
1377 if(options[IconOptions::QuickLaunchIcon].selected)
1379 char appData[MAX_LOCATION];
1380 GetEnvironment("APPDATA", appData, sizeof(appData));
1384 char destPath[MAX_LOCATION];
1386 ((GuiApplication)__thisModule).Lock();
1387 installProgress.installing.text = $"Installing Quicklaunch Icon...";
1388 ((GuiApplication)__thisModule).Unlock();
1389 ((GuiApplication)__thisModule).SignalEvent();
1391 strcpy(destPath, appData);
1392 PathCat(destPath, "Microsoft\\Internet Explorer\\Quick Launch\\ECERE IDE.lnk");
1394 CreateLink(idePath, destPath, null);//"ECERE IDE");
1398 // Register File Types
1399 if(associateOptions[AssociateOptions::AssociateEPJ].selected ||
1400 associateOptions[AssociateOptions::AssociateEC].selected ||
1401 associateOptions[AssociateOptions::AssociateC].selected ||
1402 associateOptions[AssociateOptions::AssociateCPP].selected ||
1403 associateOptions[AssociateOptions::AssociateTXT].selected ||
1404 associateOptions[AssociateOptions::Associate3DS].selected ||
1405 associateOptions[AssociateOptions::AssociateIMG].selected)
1407 ((GuiApplication)__thisModule).Lock();
1408 installProgress.installing.text = $"Resgistering File Types...";
1409 ((GuiApplication)__thisModule).Unlock();
1410 ((GuiApplication)__thisModule).SignalEvent();
1412 if(associateOptions[AssociateOptions::AssociateEPJ].selected)
1414 AssociateExtension(".epj", "ECERE IDE Project", "epj_file", "Open", idePath);
1416 if(associateOptions[AssociateOptions::AssociateEC].selected)
1418 AssociateExtension(".ec", "eC Source File", "ec_file", "Open", idePath);
1419 AssociateExtension(".eh", "eC Header File", "eh_file", "Open", idePath);
1421 if(associateOptions[AssociateOptions::AssociateC].selected)
1423 AssociateExtension(".c", "C Source File", "c_file", "Open", idePath);
1424 AssociateExtension(".h", "C Header File", "h_file", "Open", idePath);
1426 if(associateOptions[AssociateOptions::AssociateCPP].selected)
1428 AssociateExtension(".cpp", "C++ Source File", "cpp_file", "Open", idePath);
1429 AssociateExtension(".cc", "C++ Source File", "cpp_file", "Open", idePath);
1430 AssociateExtension(".cxx", "C++ Source File", "cpp_file", "Open", idePath);
1431 AssociateExtension(".chh", "C++ Header File", "chh_file", "Open", idePath);
1432 AssociateExtension(".hh", "C++ Header File", "chh_file", "Open", idePath);
1433 AssociateExtension(".hxx", "C++ Header File", "chh_file", "Open", idePath);
1435 if(associateOptions[AssociateOptions::AssociateTXT].selected)
1437 AssociateExtension(".txt", "Text File", "txt_file", "Open", idePath);
1439 if(associateOptions[AssociateOptions::Associate3DS].selected)
1441 AssociateExtension(".3ds", "3D Studio Model", "3ds_file", "View", idePath);
1443 if(associateOptions[AssociateOptions::AssociateIMG].selected)
1445 AssociateExtension(".bmp", "BMP Image", "bmp_file", "View", idePath);
1446 AssociateExtension(".pcx", "PCX Image", "pcx_file", "View", idePath);
1447 AssociateExtension(".png", "PNG Image", "png_file", "View", idePath);
1448 AssociateExtension(".jpg", "JPEG Image", "jpg_file", "View", idePath);
1449 AssociateExtension(".jpeg", "JPEG Image", "jpg_file", "View", idePath);
1450 AssociateExtension(".gif", "GIF Image", "gif_file", "View", idePath);
1453 ((GuiApplication)__thisModule).Lock();
1455 installProgress.cancel.Destroy(0);
1456 installProgress.finish.text = $"Finish";
1457 installProgress.finish.disabled = false;
1458 installProgress.finish.Activate();
1459 installProgress.installing.text = $"Installation Complete.";
1460 installProgress.title.text = $"Installation Complete";
1461 installProgress.titleInfo.contents = $"Thank you for using the Ecere SDK.";
1463 ((GuiApplication)__thisModule).Unlock();