2 static define buildString = $"Ecere SDK v0.44 (Without MinGW) -- built on March 7, 2012 ";
4 static define buildString = $"Ecere SDK v0.44 -- built on March 7, 2012 ";
7 #define WIN32_LEAN_AND_MEAN
8 #define GetFreeSpace _GetFreeSpace
21 class CheckListBox : ListBox
23 fullRowSelect = false, collapseControl = true, treeBranches = true, rootCollapseButton = true,
27 void ToggleCheck(DataRow row)
29 Button checkBox = (Button)row.tag;
31 bool checked = !(checkBox.checked) || checkBox.buttonState == down;
32 if(!checkBox.disabled)
34 SetCheck(row, checked);
35 checkBox.buttonState = up;
37 for(parent = row; parent; parent = parent.parent)
39 for(row = parent.firstRow; row; row = row.next)
41 checkBox = (Button)row.tag;
42 if(checkBox.checked != checked)
45 checkBox = (Button)parent.tag;
48 checkBox.checked = true;
49 NotifyChecked(master, this, parent);
50 checkBox.buttonState = down;
55 checkBox.checked = checked;
56 NotifyChecked(master, this, parent);
57 checkBox.buttonState = up;
63 void SetCheck(DataRow row, bool checked)
65 Button checkBox = (Button)row.tag;
67 if(!checkBox.disabled && (checkBox.checked != checked || checkBox.buttonState == down))
69 checkBox.checked = checked;
70 for(subRow = row.firstRow; subRow; subRow = subRow.next)
71 SetCheck(subRow, checked);
72 NotifyChecked(master, this, row);
76 DataRow AddRow(DataRow parentRow)
78 DataRow row = parentRow ? parentRow.AddRow() : ListBox::AddRow();
82 for(parent = row.parent; parent; parent = parent.parent)
86 this, isCheckbox = true, inactive = true, checked = true,
87 position = { 2 + indent, 1+(row.index + hasHeader) * rowHeight }, size = { 12, 12 };
90 bool NotifyPushed(Button button, int x, int y, Modifiers mods)
92 currentRow = (DataRow)button.id;
93 ToggleCheck(currentRow);
97 bool NotifyReleased(Button button, int x, int y, Modifiers mods)
102 bool OnMouseOver(int x, int y, Modifiers mods)
108 bool OnMouseLeave(Modifiers mods)
117 bool NotifyKeyDown(CheckListBox listBox, DataRow row, Key key, unichar ch)
121 listBox.ToggleCheck(row);
127 bool OnKeyHit(Key key, unichar ch)
131 return ListBox::OnKeyHit(key, ch);
134 bool NotifyDoubleClick(CheckListBox listBox, int x, int y, Modifiers mods)
136 listBox.OnLeftButtonDown(x, y, mods);
140 bool NotifyReclick(CheckListBox listBox, DataRow row, Modifiers mods)
142 listBox.ToggleCheck(row);
146 bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed)
149 for(r = row.firstRow; r && r != row; )
151 Button checkBox = (Button)r.tag;
152 checkBox.visible = !collapsed;
153 if(r.firstRow && !r.collapsed)
156 for(; r != row; r = r.parent)
157 if(r.next) { r = r.next; break; }
159 for(r = row.GetNextRow(); r; r = r.GetNextRow())
161 Button checkBox = (Button)r.tag;
162 checkBox.position.y = 1 + (r.index + listBox.hasHeader) * listBox.rowHeight;
167 virtual void Window::NotifyChecked(CheckListBox listBox, DataRow row);
174 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
179 void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)
181 if(!displayFlags.active) displayFlags.current = false;
182 class::OnDisplay(surface, x + 22, y, width - 22, fieldData, alignment, displayFlags);
186 //#define BUFFERSIZE 0x10000
187 #define BUFFERSIZE 0x1000
188 bool abortInstall = false;
190 void ExtractFileFromArchive(ProgressBar progressBar, char * path, char * outputFile)
192 char fileName[MAX_LOCATION];
193 FileAttribs exists = FileExists(path);
194 bool setTime = false;
197 if(exists.isDirectory)
199 FileListing listing { path };
203 if(MakeDir(outputFile))
206 FileGetStats(path, &stats);
210 while(listing.Find() && !abortInstall)
212 strcpy(fileName, outputFile);
214 // Tweak file name if out
217 if(!strcmp(fileName, ".")) fileName[0] = '\0';
218 if(listing.name[0] == '/' || listing.name[0] == '\\')
220 char * afterSlash, rest[MAX_LOCATION];
221 for(afterSlash = fileName; *afterSlash == '/' || *afterSlash == '\\'; afterSlash++);
222 strcpy(rest, afterSlash);
223 PathCat(fileName, "_root");
224 PathCat(fileName, rest);
226 else if(listing.name[1] == ':')
229 sprintf(letter, "_%cdrive", toupper(listing.name[0]));
230 PathCat(fileName, letter);
231 PathCat(fileName, listing.name[2] ? (listing.name + 3) : (listing.name + 2));
234 PathCat(fileName, listing.name);
237 PathCat(fileName, listing.name);
238 if(!strcmp(fileName, "/") || !strcmp(fileName, "\\"))
239 strcpy(fileName, DIR_SEPS);
240 ExtractFileFromArchive(progressBar, listing.path, fileName);
246 File input = FileOpen(path, read);
249 File output = FileOpen(outputFile, write);
252 char fileName[MAX_FILENAME];
253 uint position = progressBar.progress;
256 byte buffer[BUFFERSIZE];
258 FileGetSize(path, &dataSize);
259 GetLastDirectory(outputFile, fileName);
261 ((GuiApplication)__thisModule).SignalEvent();
262 //((GuiApplication)__thisModule).ProcessInput();
263 //((GuiApplication)__thisModule).UpdateDisplay();
265 for(c = 0; c<dataSize && !abortInstall; c += BUFFERSIZE)
267 uint size = (dataSize > c + BUFFERSIZE) ? BUFFERSIZE : (dataSize - c);
269 ((GuiApplication)__thisModule).Unlock();
271 input.Read(buffer, 1, size);
272 output.Write(buffer, 1, size);
274 ((GuiApplication)__thisModule).Lock();
276 progressBar.progress = position + c + size;
277 ((GuiApplication)__thisModule).SignalEvent();
279 //((GuiApplication)__thisModule).ProcessInput();
280 //((GuiApplication)__thisModule).UpdateDisplay();
285 FileGetStats(path, &stats);
291 FileSetTime(outputFile, stats.created, 0, stats.modified);
298 char * defInstallPath;
299 Component * subComponents;
306 char installPath[MAX_LOCATION];
309 void GetFullPath(char * path)
311 if(this != null && parent)
312 parent->GetFullPath(path);
314 strcpy(path, installDir);
317 PathCat(path, installPath);
320 void Install(char * parentPath)
325 char path[MAX_LOCATION];
326 strcpy(path, parentPath);
327 PathCat(path, installPath);
329 installProgress.installing.SetText($"Installing %s...", name);
330 ((GuiApplication)__thisModule).UpdateDisplay();
334 char source[MAX_LOCATION];
336 strcat(source, dataPath);
340 if(FileExists(source).isFile)
342 char name[MAX_FILENAME];
343 GetLastDirectory(source, name);
348 uint p = installProgress.progressBar.progress;
349 ExtractFileFromArchive(installProgress.progressBar, source, path);
354 for(c = 0; subComponents[c].name; c++)
355 subComponents[c].Install(path);
360 Component samples[] =
362 { "Ecere Chess", "samples/chess", "chess", null, false, true },
363 { "Ecere Fractals", "samples/fractals", "fractals", null, false, true },
364 { "3D", "samples/3D", "3D", null, false, true },
365 { "Audio", "samples/audio", "audio", null, false, true },
366 { "Database", "samples/db", "db", null, false, true },
367 { "eC", "samples/eC", "eC", null, false, true },
368 { "Games", "samples/games", "games", null, false, true },
369 { "GUI & Graphics", "samples/guiAndGfx", "guiAndGfx", null, false, true },
370 { "Miscellaneous", "samples/misc", "misc", null, false, true },
371 { "Networking", "samples/net", "net", null, false, true },
372 { "WIA Scanning", "samples/scanning", "scanning", null, false, true },
373 { "Threading", "samples/threads", "threads", null, false, true }
377 public enum CoreSDKID
379 ide, runtime, ec, eda, vanilla, extras,
381 gcc, gdb, mingw, binutils, make,
386 Component coreSDK[CoreSDKID] =
388 { "Ecere IDE", "ecere-sdk/ide", "bin", null, true, true },
389 { "Runtime Library", "ecere-sdk/ecere.dll", "bin", null, true, true },
390 { "eC Compiler", "ecere-sdk/compiler", "bin", null, true, true },
391 { "Data Access", "ecere-sdk/eda", "bin", null, false, true },
392 { "Ecere Vanilla", "ecere-sdk/libecereVanilla.a", "lib", null, false, true },
393 { "Ecere Extras", "extras", "extras", null, false, true },
395 { "GNU C Compiler", "mingw/gcc/core", "mingw", null, true, true },
396 { "GNU Debugger", "mingw/gdb", "mingw", null, true, true },
397 { "MinGW Runtime", "mingw/mingwrt", "mingw", null, true, true },
398 { "Binary Utils", "mingw/binutils", "mingw", null, true, true },
399 { "GNU Make", "mingw/make", "mingw", null, true, true },
405 Component additional[] =
407 { "UPX", "upx/bin", "mingw", null, false, true },
408 { "GNU Regexp", "mingw/gnurx", "mingw", null, false, true },
409 { "Win32 APIs", "mingw/w32api", "mingw", null, false, true },
410 { "pthreads", "mingw/pthreads", "mingw", null, false, true },
411 { "C++ Compiler", "mingw/gcc/c++", "mingw", null, false, true },
412 { "GCC I18n", "mingw/locale/gcc", "mingw", null, false, false },
413 { "GDB I18n", "mingw/locale/gdb", "mingw", null, false, false },
414 { "Make I18n", "mingw/locale/make", "mingw", null, false, false },
415 { "Binutils I18n", "mingw/locale/binutils", "mingw", null, false, false },
420 public enum DocumentationID
422 ecereBook, apiRef, tutorials, coursework,
424 gccDoc, gppDocs, gdbDocs, makeDocs, binDocs, mingwDocs, gnurxDocs, upxDocs,
429 Component documentation[DocumentationID] =
431 { "Ecere Book", "ecere-sdk/book", "doc", null, false, true },
432 { "API Reference", "ecere-sdk/doc", "doc", null, false, true },
433 { "Ecere Tutorials", "ecere-sdk/tutorials", "doc", null, false, true },
434 { "Ecere Coursework", "ecere-sdk/coursework", "doc", null, false, true },
436 { "GCC Docs", "mingw/doc/gcc", "mingw", null, false, false },
437 { "G++ Docs", "mingw/doc/g++", "mingw", null, false, false },
438 { "GDB Docs", "mingw/doc/gdb", "mingw", null, false, false },
439 { "Make Docs", "mingw/doc/make", "mingw", null, false, false },
440 { "Binutils Docs", "mingw/doc/binutils", "mingw", null, false, false },
441 { "MinGW Docs", "mingw/doc/mingw", "mingw", null, false, false },
442 { "gnurx Docs", "mingw/doc/gnurx", "mingw", null, false, false },
443 { "UPX Docs", "upx/doc", "mingw/doc/upx", null, false, false },
448 public enum ComponentID
459 Component components[ComponentID] =
461 { "Core SDK Files", null, null, coreSDK, true, true },
463 { "Additional Support", null, null, additional, false, true },
465 { "Documentation", null /*"doc"*/, null /*"doc"*/, documentation, false, true },
466 { "Samples", null, "samples", samples, false, true },
470 FileSize totalInstalled;
475 InstallOption * subOptions;
480 enum AssociateOptions
491 InstallOption associateOptions[] =
493 { "Associate with Ecere Project Files (*.epj)", null, true },
494 { "Associate with eC Files (*.ec, *.eh)", null, true },
495 { "Associate with C files (*.c, *.h)", null, false },
496 { "Associate with C++ Files (*.cpp, *.hpp, *.cc, *.hh, *.cxx, *.hxx)", null, false },
497 { "Associate with text files (*.txt)", null, false },
498 { "Associate with 3D Studio Model Files (*.3ds)", null, true },
499 { "Associate with Image Files (*.png, *.jpg, *.pcx, *.bmp, *.gif)", null, false },
511 InstallOption pathOptions[] =
513 { "Add Ecere binaries location to the system path", null, true },
514 { "Add MinGW to the system path", null, true }
525 InstallOption options[] =
527 { "Start Menu Group", null, true },
528 { "Desktop Icon", null, true },
529 { "Quicklaunch Icon", null, true },
530 { "Associate the ECERE IDE with Supported File Types", associateOptions, true },
532 { "Add binaries location to the system paths", pathOptions, true },
537 char sourceDir[MAX_LOCATION] = ":";
538 char installDir[MAX_LOCATION];
540 class Installer : Window
542 text = $"Ecere Software Development Kit Setup - v0.44 \"Ryōan-ji\"";
543 background = activeBorder;
548 clientSize = { 636, 456 };
549 icon = { ":icon.png" };
551 Picture back { image = BitmapResource { ":ryoanji.png" }, parent = this, position = { 0, 0 } };
552 FileDialog fileDialog
554 master = this, type = selectDir,
555 text = $"Select a new location"
559 master = this, autoCreate = false, inactive = true, /*hotKey = F2,*/ text = "...";
561 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
563 DataRow row = componentsBox.currentRow;
564 Component * component = ((CheckItem *)row.GetData(componentField))->data;
565 component->GetFullPath(fileDialog.filePath);
566 StripLastDirectory(fileDialog.filePath, fileDialog.currentDirectory);
568 if(fileDialog.Modal() == ok)
570 componentsBox.StopEditing(false);
571 row.SetData(locationField, fileDialog.filePath);
572 componentsBox.NotifyChanged(this, componentsBox, row);
573 componentsBox.currentField = componentsBox.currentField;
578 CheckListBox componentsBox
580 this, size = { 460, 112 }, position = { 160, 160 }, hasHeader = true;
585 bool NotifyChanged(ListBox listBox, DataRow row)
587 Component * component = ((CheckItem *)listBox.GetData(componentField))->data;
588 char path[MAX_LOCATION], relative[MAX_LOCATION] = "", ** newPath;
589 char fullPath[MAX_LOCATION];
591 component->parent->GetFullPath(path);
592 strcpy(fullPath, path);
594 newPath = (char **)row.GetData(locationField);
595 if(newPath && *newPath)
597 PathCat(fullPath, *newPath);
598 MakePathRelative(fullPath, path, relative);
600 listBox.SetData(locationField, relative);
601 strcpy(component->installPath, relative);
603 //SetAvailableSpace(component, path);
606 install.disabled = false;
607 for(c = 0; components[c].name; c++)
609 SetAvailableSpace(components[c], installDir);
615 bool NotifyEditDone(ListBox listBox, DataRow row)
621 bool NotifyEdited(ListBox listBox, DataRow row)
623 browse.parent = listBox;
624 browse.position = { componentField.width + locationField.width + 18, (listBox.currentIndex+1) * listBox.rowHeight - 2 };
625 browse.size = { 30, listBox.rowHeight + 3 };
631 void NotifyChecked(CheckListBox listBox, DataRow row)
633 Component * component = ((CheckItem *)row.GetData(componentField))->data;
635 Button checkBox = (Button)row.tag;
636 component->selected = checkBox.checked;
638 if(!component->parent) totalSize -= component->requiredSize;
639 component->requiredSize = 0;
640 if(component->selected)
642 component->requiredSize += component->size;
643 if(component->subComponents)
644 for(c = 0; component->subComponents[c].name; c++)
645 component->requiredSize += component->subComponents[c].requiredSize;
647 if(component->requiredSize)
649 uint requiredSize = component->requiredSize;
650 row.SetData(reqField, requiredSize);
653 row.UnsetData(reqField);
654 if(!component->parent)
656 totalSize += component->requiredSize;
658 char sizeString[100];
659 PrintSize(sizeString, totalSize, 2);
660 totalSpaceValue.text = sizeString;
665 Label agreementLbl { parent = this, text = $"By installing the Ecere SDK, you agree to the .", font = { "Tahoma", 8.25f }, anchor = Anchor { left = 24, top = 424 } };
668 this, inactive = true, offset = false, bevel = false, foreground = blue, font = { "Tahoma", 8.25f, underline = true, bold = true },
669 // text = $"terms and conditions", anchor = Anchor { left = 241, top = 421 };
670 text = $"terms and conditions", anchor = Anchor { left = 237, top = 421 };
671 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
673 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
675 LicenseBox { master = this, sourceFile = ":ecere-sdk/doc/LICENSE" }.Modal();
679 CheckListBox optionsBox
681 this, size = { 460, 94 }, position = { 160, 284 };
684 void NotifyChecked(CheckListBox listBox, DataRow row)
686 CheckItem * item = row.GetData(optionField);
687 InstallOption * option = item->data;
689 Button checkBox = (Button)row.tag;
690 option->selected = checkBox.checked;
695 parent = this, text = $"Install", isDefault = true, size = { 75, 23 }, position = { 432, 416 };
697 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
699 installProgress.Create();
701 // installProgress.thread.Main();
702 installProgress.thread.Create();
706 Button button3 { parent = this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 }, NotifyClicked = ButtonCloseDialog };
707 Label label1 { labeledWindow = destBox, tabCycle = true, isGroupBox = true, parent = this, inactive = false, size = Size { 458, 50 }, anchor = Anchor { left = 160, top = 96 } };
710 parent = label1, master = this, text = $" Destination Folder", size = Size { 336, 19 }, anchor = Anchor { left = 12, top = 20 };
712 bool NotifyModified(EditBox editBox)
715 strcpy(installDir, destBox.contents);
716 install.disabled = false;
717 for(c = 0; components[c].name; c++)
719 SetAvailableSpace(components[c], installDir);
726 label1, this, $"Browse", altB, size = { 83, 24 }, position = { 360, 16 };
728 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
730 strcpy(fileDialog.filePath, installDir);
731 StripLastDirectory(installDir, fileDialog.currentDirectory);
732 if(fileDialog.Modal())
734 strcpy(installDir, fileDialog.filePath);
735 destBox.contents = installDir;
736 // TOCHECK: Should setting contents call NotifyModified?
737 destBox.NotifyModified(destBox.master, destBox);
744 this, multiLine = true,
745 opacity = 0, borderStyle = none, inactive = true, size = { 136, 53 }, position = { 14, 96 }, noSelect = true,
746 contents = $"Select the default root\n"
747 "folder where to install\n"
752 this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 132 }, position = { 14, 152 }, noSelect = true,
754 contents = $"Select the optional\n"
755 "components you wish\n"
757 "You may customize the\n"
758 "install location for each\n"
759 "of them, or use the default\n"
760 "based on the main\n"
761 "destination folder."
765 this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 53 }, position = { 14, 280 }, noSelect = true,
767 contents = $"Select icons to install, file\n"
768 "associations, and system\n"
769 "environment modifications:"
771 Label totalSpaceLabel
773 this, position = { 18, 352 }, text = $"Space Required: "
775 Label totalSpaceValue
777 this, position = { 100, 352 }, text = "0 mb"
781 inactive = true, noSelect = true,
782 multiLine = true, parent = label3, text = "editBox1", opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 },
783 contents = $"Choose in which folder to install the ECERE SDK, which features\n"
784 "of the SDK to install, as well as where to install program icons."
786 Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder };
787 Picture picture1 { image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, text = "picture1", anchor = Anchor { left = 16, top = 4 } };
788 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 } };
789 DataField componentField { "CheckItem", width = 140, header = $"Component" };
790 DataField locationField { "char *", width = 108, header = $"Destination Folder", editable = true };
791 DataField reqField { "FileSize", width = 80, header = $"Req. Space", alignment = right };
792 DataField avField { "FileSize64", width = 80, header = $"Avail. Space", alignment = right };
793 DataField optionField { "CheckItem" };
795 void SetAvailableSpace(Component component, char * parentPath)
797 char path[MAX_LOCATION];
801 strcpy(path, parentPath);
802 PathCat(path, component.installPath);
804 if(component.subComponents)
805 for(c = 0; component.subComponents[c].name; c++)
806 SetAvailableSpace(component.subComponents[c], path);
808 while(!FileExists(path) && path[0])
809 StripLastDirectory(path, path);
812 GetFreeSpace(path, &size);
813 component.row.SetData(avField, size);
814 if(!size) install.disabled = true;
817 FileSize ComputeSize(char * path)
820 FileAttribs attribs = FileExists(path);
821 if(attribs.isDirectory)
823 FileListing listing { path };
824 while(listing.Find())
826 if(listing.stats.attribs.isDirectory)
827 size += ComputeSize(listing.path);
829 size += listing.stats.size;
833 FileGetSize(path, &size);
837 void AddComponent(Component component, Component parent, char * parentPath)
839 DataRow row = component.row = componentsBox.AddRow((parent != null) ? parent.row : null);
840 Button checkBox = (Button) row.tag;
842 FileSize64 avSize = 0;
843 char path[MAX_LOCATION];
844 strcpy(path, parentPath);
845 if(component.defInstallPath)
846 PathCat(path, component.defInstallPath);
847 component.parent = parent;
849 row.SetData(null, CheckItem { component.name, component } );
851 if(component.defInstallPath)
853 strcpy(component.installPath, component.defInstallPath);
854 ChangeCh(component.installPath, '/', DIR_SEP);
855 row.SetData(locationField, component.installPath);
858 if(component.mandatory) checkBox.disabled = true;
859 if(!component.selected) componentsBox.ToggleCheck(row);
860 if(component.dataPath)
862 char path[MAX_LOCATION];
864 PathCat(path, component.dataPath);
865 component.size = ComputeSize(path);
867 if(component.subComponents)
870 for(c = 0; component.subComponents[c].name; c++)
872 AddComponent(component.subComponents[c], component, path);
873 size += component.subComponents[c].requiredSize;
877 component.requiredSize = component.selected ? (size + component.size) : 0;
878 if(component.requiredSize)
879 row.SetData(reqField, component.requiredSize);
881 while(!FileExists(path) && path[0])
882 StripLastDirectory(path, path);
885 GetFreeSpace(path, &avSize);
888 row.SetData(avField, avSize);
889 row.collapsed = true;
892 void AddOption(InstallOption option, InstallOption parent)
894 DataRow row = option.row = optionsBox.AddRow((parent != null) ? parent.row : null);
895 row.SetData(null, CheckItem { option.name, option } );
897 optionsBox.ToggleCheck(row);
898 if(option.subOptions)
901 for(c = 0; option.subOptions[c].name; c++)
903 AddOption(option.subOptions[c], option);
906 row.collapsed = true;
912 char programFilesDir[MAX_LOCATION];
913 char appData[MAX_LOCATION]; // = getenv("APPDATA");
914 char homeDrive[MAX_LOCATION]; //= getenv("HOMEDRIVE");
915 char winDir[MAX_LOCATION]; //= getenv("windir");
917 GetEnvironment("APPDATA", appData, sizeof(appData));
918 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
919 GetEnvironment("windir", winDir, sizeof(winDir));
921 componentsBox.AddField(componentField);
922 componentsBox.AddField(locationField);
923 componentsBox.AddField(reqField);
924 componentsBox.AddField(avField);
926 optionsBox.AddField(optionField);
928 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
930 strcpy(installDir, programFilesDir);
931 PathCat(installDir, "ECERE SDK");
933 else if(homeDrive && homeDrive[0])
935 strcpy(installDir, homeDrive);
936 PathCat(installDir, "ECERE SDK");
938 else if(winDir && winDir[0])
940 strcpy(installDir, winDir);
941 PathCat(installDir, "..\\ECERE SDK");
944 strcpy(installDir, "C:\\ECERE SDK");
946 if(appData && appData[0])
948 static char defSamplesPath[MAX_LOCATION];
949 static char defExtrasPath[MAX_LOCATION];
950 strcpy(defSamplesPath, appData);
951 PathCat(defSamplesPath, "ECERE SDK\\Samples");
952 components[samples].defInstallPath = defSamplesPath;
954 strcpy(defExtrasPath, appData);
955 PathCat(defExtrasPath, "ECERE SDK\\extras");
956 coreSDK[extras].defInstallPath = defExtrasPath;
959 destBox.contents = installDir;
963 for(c = 0; components[c].name; c++)
964 AddComponent(components[c], null, installDir);
967 // Compute size apart because ToggleCheck will change it
971 for(c = 0; components[c].name; c++)
972 totalSize += components[c].requiredSize;
975 char sizeString[100];
976 PrintSize(sizeString, totalSize, 2);
977 totalSpaceValue.text = sizeString;
979 for(c = 0; options[c].name; c++)
980 AddOption(options[c], null);
989 void OnDrawOverChildren(Surface surface)
991 int tw = label2.size.w;
992 surface.SetForeground(Color { 128, 128, 128 });
993 surface.HLine(label2.position.x + tw + 6, 620, 400);
994 surface.SetForeground(white);
995 surface.HLine(label2.position.x + tw + 6, 621, 401);
996 surface.PutPixel(621, 400);
1001 parent = this, opacity = 0, borderStyle = deep, size = Size { 644, 93 }, anchor = Anchor { left = -8, top = -8 };
1005 class InstallProgress : Window
1007 text = $"Ecere Software Development Kit Setup - v0.44 \"Ryōan-ji\"";
1008 background = activeBorder;
1009 borderStyle = fixed;
1013 size = Size { 640, 480 };
1014 icon = { ":icon.png" };
1016 Picture back { image = BitmapResource { ":ryoanji-progress.png" }, parent = this, position = { 0, 0 } };
1017 Label installing { this, position = { 32, 160 } };
1018 ProgressBar progressBar { parent = this, size = Size { 588, 24 }, anchor = Anchor { left = 24, top = 184 } };
1021 parent = this, text = $"Install", disabled = true, isDefault = true, size = Size { 75, 23 }, anchor = Anchor { left = 432, top = 416 };
1023 NotifyClicked = ButtonCloseDialog
1027 this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 };
1029 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1031 abortInstall = true;
1037 inactive = true, noSelect = true,
1038 multiLine = true, parent = label3, opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 },
1039 contents = $"Please wait while the Ecere Software Development Kit is being installed."
1041 Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder };
1042 Picture picture1 { image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, anchor = Anchor { left = 16, top = 4 } };
1043 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 } };
1045 void OnDrawOverChildren(Surface surface)
1047 int tw = label2.size.w;
1048 surface.SetForeground(Color { 128, 128, 128 });
1049 surface.HLine(label2.position.x + tw + 6, 620, 400);
1050 surface.SetForeground(white);
1051 surface.HLine(label2.position.x + tw + 6, 621, 401);
1052 surface.PutPixel(621, 400);
1057 parent = this, opacity = 0, borderStyle = deep, size = Size { 644, 93 }, anchor = Anchor { left = -8, top = -8 };
1059 InstallThread thread
1064 Installer installer {};
1065 InstallProgress installProgress { autoCreate = false };
1067 void ModifyPath(char * newPath)
1074 strcpy(oldPath, newPath);
1075 count = TokenizeWith(oldPath, sizeof(paths) / sizeof(char *), paths, ";", false);
1077 for(c = 0; coreSDK[c].name; c++)
1079 char path[MAX_LOCATION];
1080 coreSDK[c].GetFullPath(path);
1081 if(c != ide && c != runtime && c != eda && c != ec && c !=extras && c != vanilla)
1084 if(!pathOptions[PathOptions::AddMinGWPaths].selected)
1087 PathCat(path, "bin");
1089 else if(!pathOptions[PathOptions::AddECEREPaths].selected) continue;
1091 for(p = 0; p<count; p++)
1092 if(!fstrcmp(paths[p], path))
1099 strcat(newPath, ";");
1100 start = oldPath + strlen(paths[count-1])+1;
1105 strcpy(start, path);
1106 *(start + strlen(path)) = '\0';
1107 paths[count++] = start;
1109 strcat(newPath, path);
1113 if(pathOptions[PathOptions::AddMinGWPaths].selected)
1116 for(c = 0; additional[c].name; c++)
1118 char path[MAX_LOCATION];
1120 additional[c].GetFullPath(path);
1121 PathCat(path, "bin");
1122 for(p = 0; p<count; p++)
1123 if(!fstrcmp(paths[p], path))
1131 strcat(newPath, ";");
1132 start = oldPath + strlen(paths[count-1])+1;
1137 strcpy(start, path);
1138 *(start + strlen(path)) = '\0';
1139 paths[count++] = start;
1141 strcat(newPath, path);
1148 void AssociateExtension(char * extension, char * description, char *name, char * action, char * path)
1154 RegCreateKeyEx(HKEY_CLASSES_ROOT, extension, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1155 RegSetValueEx(key, null, 0, REG_SZ, name, strlen(name)+1);
1158 RegCreateKeyEx(HKEY_CLASSES_ROOT, name, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1159 RegSetValueEx(key, null, 0, REG_SZ, description, strlen(description)+1);
1162 sprintf(keyName, "%s\\shell", extension);
1163 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1164 RegSetValueEx(key, null, 0, REG_SZ, action, strlen(action)+1);
1167 sprintf(keyName, "%s\\shell\\%s", name, action);
1168 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1171 sprintf(keyName, "%s\\shell\\%s\\command", name, action);
1172 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1174 sprintf(keyName, path);
1175 strcat(keyName, " \"%L\"");
1177 uint16 wKeyName[2048];
1178 UTF8toUTF16Buffer(keyName, wKeyName, sizeof(wKeyName) / sizeof(uint16));
1179 RegSetValueExW(key, null, 0, REG_SZ, (byte *)wKeyName, (wcslen(wKeyName) + 1)*sizeof(uint16));
1184 class InstallThread : Thread
1189 ((GuiApplication)__thisModule).Lock();
1190 installProgress.progressBar.range = totalSize;
1191 for(c = 0; components[c].name && !abortInstall; c++)
1192 components[c].Install(installDir);
1195 installProgress.progressBar.range = 0;
1196 installProgress.finish.Destroy(0);
1197 installProgress.cancel.text = $"Close";
1198 installProgress.cancel.isDefault = true;
1199 installProgress.cancel.disabled = false;
1200 installProgress.cancel.NotifyClicked = Window::ButtonCloseDialog;
1201 installProgress.installing.text = $"Installation Cancelled.";
1202 installProgress.title.text = $"Installation Cancelled";
1203 installProgress.titleInfo.contents = $"The installation was not completed.";
1208 char idePath[MAX_LOCATION];
1209 char userProfile[MAX_LOCATION];
1212 GlobalSettings settings
1216 installProgress.installing.text = $"Configuring ECERE IDE...";
1217 ((GuiApplication)__thisModule).Unlock();
1218 ((GuiApplication)__thisModule).SignalEvent();
1221 for(c = 0; coreSDK[c].name; c++)
1223 char path[MAX_LOCATION];
1225 coreSDK[c].GetFullPath(path);
1226 if(c != ide && c != runtime && c != eda && c != ec)
1227 PathCat(path, "bin");
1230 coreSDK[c].GetFullPath(idePath);
1231 PathCat(idePath, "IDE.exe");
1234 // TODO: Update This!
1236 for(item = settings.systemDirs[executables].first; item; item = item.next)
1237 if(!fstrcmp(item.name, path))
1241 settings.systemDirs[executables].Add(NamedItem { name = CopyString(path); });
1246 for(item = settings.systemDirs[libraries].first; item; item = item.next)
1247 if(!fstrcmp(item.name, path))
1251 settings.systemDirs[libraries].Add(NamedItem { name = CopyString(path); });
1258 for(c = 0; additional[c].name; c++)
1260 char path[MAX_LOCATION];
1262 additional[c].GetFullPath(path);
1263 PathCat(path, "bin");
1264 for(item = settings.systemDirs[executables].first; item; item = item.next)
1265 if(!fstrcmp(item.name, path))
1269 settings.systemDirs[executables].Add(NamedItem { name = CopyString(path); });
1276 char path[MAX_LOCATION] = "";
1277 if(components[samples].selected)
1278 components[samples].GetFullPath(path);
1280 components[coreSDK].GetFullPath(path);
1281 /* TODO: Update This!
1282 if(!settings.ideProjectFileDialogLocation)
1283 settings.ideProjectFileDialogLocation = path;
1284 if(!settings.ideFileDialogLocation)
1285 settings.ideFileDialogLocation = path;
1292 // Set up Uninstaller
1293 ((GuiApplication)__thisModule).Lock();
1294 installProgress.installing.text = $"Registering uninstaller...";
1295 ((GuiApplication)__thisModule).Unlock();
1296 ((GuiApplication)__thisModule).SignalEvent();
1301 char * displayName = "ECERE SDK 0.44";
1302 char uninstaller[MAX_LOCATION];
1303 bool nomodify = true;
1305 strcpy(uninstaller, installDir);
1306 PathCat(uninstaller, "uninstall_ecere.exe");
1308 RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ECERE SDK", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1310 RegSetValueEx(key, "DisplayName", 0, REG_SZ, displayName, strlen(displayName)+1);
1311 RegSetValueEx(key, "UninstallString", 0, REG_SZ, uninstaller, strlen(uninstaller)+1);
1312 RegSetValueEx(key, "DisplayIcon", 0, REG_SZ, idePath, strlen(idePath)+1);
1313 //RegSetValueEx(key, "NoModify", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1314 //RegSetValueEx(key, "NoRepair", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1319 if(pathOptions[PathOptions::AddECEREPaths].selected
1321 || pathOptions[PathOptions::AddMinGWPaths].selected
1327 char path[2048] = "";
1330 ((GuiApplication)__thisModule).Lock();
1331 installProgress.installing.text = "Registering paths...";
1332 ((GuiApplication)__thisModule).Unlock();
1333 ((GuiApplication)__thisModule).SignalEvent();
1335 // if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Environment", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1337 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1338 // RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1339 if(status == REG_OPENED_EXISTING_KEY)
1341 size = sizeof(wPath);
1342 RegQueryValueExW(key, L"path", null, null, (byte *)wPath, &size);
1343 UTF16toUTF8Buffer(wPath, path, sizeof(path));
1346 UTF8toUTF16Buffer(path, wPath, sizeof(wPath) / sizeof(uint16));
1347 RegSetValueExW(key, L"path", 0, REG_EXPAND_SZ, (byte *)wPath, (wcslen(wPath)+1) * 2);
1350 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (int)"Environment", SMTO_NORMAL, 1000, NULL);
1353 // Install Program Group Icons
1354 // userProfile = getenv("USERPROFILE");
1355 GetEnvironment("USERPROFILE", userProfile, sizeof(userProfile));
1357 if(options[IconOptions::StartMenuIcon].selected)
1359 char destPath[MAX_LOCATION];
1360 char startMenuPath[MAX_LOCATION] = "";
1363 ((GuiApplication)__thisModule).Lock();
1364 installProgress.installing.text = $"Installing Start Menu Icons...";
1365 ((GuiApplication)__thisModule).Unlock();
1366 ((GuiApplication)__thisModule).SignalEvent();
1368 strcpy(destPath, userProfile);
1370 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1372 uint16 wStartMenuPath[2048];
1373 uint size = sizeof(wStartMenuPath);
1374 // RegQueryValueEx(key, "Start Menu", null, null, startMenuPath, &size);
1375 RegQueryValueExW(key, L"Programs", null, null, (byte *)wStartMenuPath, &size);
1376 UTF16toUTF8Buffer(wStartMenuPath, startMenuPath, sizeof(startMenuPath));
1379 if(!startMenuPath[0] && userProfile && userProfile[0])
1381 strcpy(startMenuPath, userProfile);
1382 PathCat(startMenuPath, "Start Menu\\Programs");
1385 if(startMenuPath[0])
1387 strcpy(destPath, startMenuPath);
1388 PathCat(destPath, "ECERE SDK");
1391 strcpy(destPath, startMenuPath);
1392 PathCat(destPath, "ECERE SDK\\ECERE IDE.lnk");
1393 CreateLink(idePath, destPath, null); //"ECERE IDE");
1394 if(components[samples].selected)
1396 char samplesPath[MAX_LOCATION] = "";
1397 components[samples].GetFullPath(samplesPath);
1399 strcpy(destPath, startMenuPath);
1400 PathCat(destPath, "ECERE SDK\\Sample Projects.lnk");
1401 CreateLink(samplesPath, destPath, null);//"Sample Projects");
1403 if(components[documentation].selected && documentation[ecereBook].selected)
1405 char docPath[MAX_LOCATION] = "";
1406 documentation[ecereBook].GetFullPath(docPath);
1407 PathCat(docPath, "Ecere Tao of Programming [work in progress].pdf");
1409 strcpy(destPath, startMenuPath);
1410 PathCat(destPath, "ECERE SDK\\The Ecere Tao of Programming.lnk");
1411 CreateLink(docPath, destPath, null);
1416 // Install Desktop Icon
1417 if(options[IconOptions::DesktopIcon].selected)
1420 char desktopPath[MAX_LOCATION];
1422 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1424 uint16 wDesktopPath[MAX_LOCATION];
1425 uint size = sizeof(wDesktopPath);
1426 RegQueryValueExW(key, L"Desktop", null, null, (byte *)wDesktopPath, &size);
1427 UTF16toUTF8Buffer(wDesktopPath, desktopPath, sizeof(desktopPath));
1430 if(!desktopPath[0] && userProfile && userProfile[0])
1432 strcpy(desktopPath, userProfile);
1433 PathCat(desktopPath, "Desktop");
1438 PathCat(desktopPath, "ECERE IDE.lnk");
1440 ((GuiApplication)__thisModule).Lock();
1441 installProgress.installing.text = $"Installing Desktop Icon...";
1442 ((GuiApplication)__thisModule).Unlock();
1443 ((GuiApplication)__thisModule).SignalEvent();
1445 CreateLink(idePath, desktopPath, null);//"ECERE IDE");
1449 // Install QuickLaunch Icon
1450 if(options[IconOptions::QuickLaunchIcon].selected)
1452 char appData[MAX_LOCATION]; // = getenv("APPDATA");
1453 GetEnvironment("APPDATA", appData, sizeof(appData));
1455 if(appData && appData[0])
1457 char destPath[MAX_LOCATION];
1459 ((GuiApplication)__thisModule).Lock();
1460 installProgress.installing.text = $"Installing Quicklaunch Icon...";
1461 ((GuiApplication)__thisModule).Unlock();
1462 ((GuiApplication)__thisModule).SignalEvent();
1464 strcpy(destPath, appData);
1465 PathCat(destPath, "Microsoft\\Internet Explorer\\Quick Launch\\ECERE IDE.lnk");
1467 CreateLink(idePath, destPath, null);//"ECERE IDE");
1471 // Register File Types
1472 if(associateOptions[AssociateOptions::AssociateEPJ].selected ||
1473 associateOptions[AssociateOptions::AssociateEC].selected ||
1474 associateOptions[AssociateOptions::AssociateC].selected ||
1475 associateOptions[AssociateOptions::AssociateCPP].selected ||
1476 associateOptions[AssociateOptions::AssociateTXT].selected ||
1477 associateOptions[AssociateOptions::Associate3DS].selected ||
1478 associateOptions[AssociateOptions::AssociateIMG].selected)
1480 ((GuiApplication)__thisModule).Lock();
1481 installProgress.installing.text = $"Resgistering File Types...";
1482 ((GuiApplication)__thisModule).Unlock();
1483 ((GuiApplication)__thisModule).SignalEvent();
1485 if(associateOptions[AssociateOptions::AssociateEPJ].selected)
1487 AssociateExtension(".epj", "ECERE IDE Project", "epj_file", "Open", idePath);
1489 if(associateOptions[AssociateOptions::AssociateEC].selected)
1491 AssociateExtension(".ec", "eC Source File", "ec_file", "Open", idePath);
1492 AssociateExtension(".eh", "eC Header File", "eh_file", "Open", idePath);
1494 if(associateOptions[AssociateOptions::AssociateC].selected)
1496 AssociateExtension(".c", "C Source File", "c_file", "Open", idePath);
1497 AssociateExtension(".h", "C Header File", "h_file", "Open", idePath);
1499 if(associateOptions[AssociateOptions::AssociateCPP].selected)
1501 AssociateExtension(".cpp", "C++ Source File", "cpp_file", "Open", idePath);
1502 AssociateExtension(".cc", "C++ Source File", "cpp_file", "Open", idePath);
1503 AssociateExtension(".cxx", "C++ Source File", "cpp_file", "Open", idePath);
1504 AssociateExtension(".chh", "C++ Header File", "chh_file", "Open", idePath);
1505 AssociateExtension(".hh", "C++ Header File", "chh_file", "Open", idePath);
1506 AssociateExtension(".hxx", "C++ Header File", "chh_file", "Open", idePath);
1508 if(associateOptions[AssociateOptions::AssociateTXT].selected)
1510 AssociateExtension(".txt", "Text File", "txt_file", "Open", idePath);
1512 if(associateOptions[AssociateOptions::Associate3DS].selected)
1514 AssociateExtension(".3ds", "3D Studio Model", "3ds_file", "View", idePath);
1516 if(associateOptions[AssociateOptions::AssociateIMG].selected)
1518 AssociateExtension(".bmp", "BMP Image", "bmp_file", "View", idePath);
1519 AssociateExtension(".pcx", "PCX Image", "pcx_file", "View", idePath);
1520 AssociateExtension(".png", "PNG Image", "png_file", "View", idePath);
1521 AssociateExtension(".jpg", "JPEG Image", "jpg_file", "View", idePath);
1522 AssociateExtension(".jpeg", "JPEG Image", "jpg_file", "View", idePath);
1523 AssociateExtension(".gif", "GIF Image", "gif_file", "View", idePath);
1526 ((GuiApplication)__thisModule).Lock();
1528 installProgress.cancel.Destroy(0);
1529 installProgress.finish.text = $"Finish";
1530 installProgress.finish.disabled = false;
1531 installProgress.finish.Activate();
1532 installProgress.installing.text = $"Installation Complete.";
1533 installProgress.title.text = $"Installation Complete";
1534 installProgress.titleInfo.contents = $"Thank you for using the Ecere SDK.";
1536 ((GuiApplication)__thisModule).Unlock();