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
19 // import "licenseBox"
22 class CheckListBox : ListBox
24 fullRowSelect = false, collapseControl = true, treeBranches = true, rootCollapseButton = true,
28 void ToggleCheck(DataRow row)
30 Button checkBox = (Button)row.tag;
32 bool checked = !(checkBox.checked) || checkBox.buttonState == down;
33 if(!checkBox.disabled)
35 SetCheck(row, checked);
36 checkBox.buttonState = up;
38 for(parent = row; parent; parent = parent.parent)
40 for(row = parent.firstRow; row; row = row.next)
42 checkBox = (Button)row.tag;
43 if(checkBox.checked != checked)
46 checkBox = (Button)parent.tag;
49 checkBox.checked = true;
50 NotifyChecked(master, this, parent);
51 checkBox.buttonState = down;
56 checkBox.checked = checked;
57 NotifyChecked(master, this, parent);
58 checkBox.buttonState = up;
64 void SetCheck(DataRow row, bool checked)
66 Button checkBox = (Button)row.tag;
68 if(!checkBox.disabled && (checkBox.checked != checked || checkBox.buttonState == down))
70 checkBox.checked = checked;
71 for(subRow = row.firstRow; subRow; subRow = subRow.next)
72 SetCheck(subRow, checked);
73 NotifyChecked(master, this, row);
77 DataRow AddRow(DataRow parentRow)
79 DataRow row = parentRow ? parentRow.AddRow() : ListBox::AddRow();
83 for(parent = row.parent; parent; parent = parent.parent)
87 this, isCheckbox = true, inactive = true, checked = true,
88 position = { 2 + indent, 1+(row.index + hasHeader) * rowHeight }, size = { 12, 12 };
91 bool NotifyPushed(Button button, int x, int y, Modifiers mods)
93 currentRow = (DataRow)button.id;
94 ToggleCheck(currentRow);
98 bool NotifyReleased(Button button, int x, int y, Modifiers mods)
103 bool OnMouseOver(int x, int y, Modifiers mods)
109 bool OnMouseLeave(Modifiers mods)
118 bool NotifyKeyDown(CheckListBox listBox, DataRow row, Key key, unichar ch)
122 listBox.ToggleCheck(row);
128 bool OnKeyHit(Key key, unichar ch)
132 return ListBox::OnKeyHit(key, ch);
135 bool NotifyDoubleClick(CheckListBox listBox, int x, int y, Modifiers mods)
137 listBox.OnLeftButtonDown(x, y, mods);
141 bool NotifyReclick(CheckListBox listBox, DataRow row, Modifiers mods)
143 listBox.ToggleCheck(row);
147 bool NotifyCollapse(ListBox listBox, DataRow row, bool collapsed)
150 for(r = row.firstRow; r && r != row; )
152 Button checkBox = (Button)r.tag;
153 checkBox.visible = !collapsed;
154 if(r.firstRow && !r.collapsed)
157 for(; r != row; r = r.parent)
158 if(r.next) { r = r.next; break; }
160 for(r = row.GetNextRow(); r; r = r.GetNextRow())
162 Button checkBox = (Button)r.tag;
163 checkBox.position.y = 1 + (r.index + listBox.hasHeader) * listBox.rowHeight;
168 virtual void Window::NotifyChecked(CheckListBox listBox, DataRow row);
175 char * OnGetString(char * tempString, void * fieldData, bool * needClass)
180 void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)
182 if(!displayFlags.active) displayFlags.current = false;
183 class::OnDisplay(surface, x + 22, y, width - 22, fieldData, alignment, displayFlags);
187 //#define BUFFERSIZE 0x10000
188 #define BUFFERSIZE 0x1000
189 bool abortInstall = false;
191 void ExtractFileFromArchive(ProgressBar progressBar, char * path, char * outputFile)
193 char fileName[MAX_LOCATION];
194 FileAttribs exists = FileExists(path);
195 bool setTime = false;
198 if(exists.isDirectory)
200 FileListing listing { path };
204 if(MakeDir(outputFile))
207 FileGetStats(path, &stats);
211 while(listing.Find() && !abortInstall)
213 strcpy(fileName, outputFile);
215 // Tweak file name if out
218 if(!strcmp(fileName, ".")) fileName[0] = '\0';
219 if(listing.name[0] == '/' || listing.name[0] == '\\')
221 char * afterSlash, rest[MAX_LOCATION];
222 for(afterSlash = fileName; *afterSlash == '/' || *afterSlash == '\\'; afterSlash++);
223 strcpy(rest, afterSlash);
224 PathCat(fileName, "_root");
225 PathCat(fileName, rest);
227 else if(listing.name[1] == ':')
230 sprintf(letter, "_%cdrive", toupper(listing.name[0]));
231 PathCat(fileName, letter);
232 PathCat(fileName, listing.name[2] ? (listing.name + 3) : (listing.name + 2));
235 PathCat(fileName, listing.name);
238 PathCat(fileName, listing.name);
239 if(!strcmp(fileName, "/") || !strcmp(fileName, "\\"))
240 strcpy(fileName, DIR_SEPS);
241 ExtractFileFromArchive(progressBar, listing.path, fileName);
247 File input = FileOpen(path, read);
250 File output = FileOpen(outputFile, write);
253 char fileName[MAX_FILENAME];
254 uint position = progressBar.progress;
257 byte buffer[BUFFERSIZE];
259 FileGetSize(path, &dataSize);
260 GetLastDirectory(outputFile, fileName);
262 ((GuiApplication)__thisModule).SignalEvent();
263 //((GuiApplication)__thisModule).ProcessInput();
264 //((GuiApplication)__thisModule).UpdateDisplay();
266 for(c = 0; c<dataSize && !abortInstall; c += BUFFERSIZE)
268 uint size = (dataSize > c + BUFFERSIZE) ? BUFFERSIZE : (dataSize - c);
270 ((GuiApplication)__thisModule).Unlock();
272 input.Read(buffer, 1, size);
273 output.Write(buffer, 1, size);
275 ((GuiApplication)__thisModule).Lock();
277 progressBar.progress = position + c + size;
278 ((GuiApplication)__thisModule).SignalEvent();
280 //((GuiApplication)__thisModule).ProcessInput();
281 //((GuiApplication)__thisModule).UpdateDisplay();
286 FileGetStats(path, &stats);
292 FileSetTime(outputFile, stats.created, 0, stats.modified);
299 char * defInstallPath;
300 Component * subComponents;
307 char installPath[MAX_LOCATION];
310 void GetFullPath(char * path)
312 if(this != null && parent)
313 parent->GetFullPath(path);
315 strcpy(path, installDir);
318 PathCat(path, installPath);
321 void Install(char * parentPath)
326 char path[MAX_LOCATION];
327 strcpy(path, parentPath);
328 PathCat(path, installPath);
330 installProgress.installing.SetText($"Installing %s...", name);
331 ((GuiApplication)__thisModule).UpdateDisplay();
335 char source[MAX_LOCATION];
337 strcat(source, dataPath);
341 if(FileExists(source).isFile)
343 char name[MAX_FILENAME];
344 GetLastDirectory(source, name);
349 uint p = installProgress.progressBar.progress;
350 ExtractFileFromArchive(installProgress.progressBar, source, path);
355 for(c = 0; subComponents[c].name; c++)
356 subComponents[c].Install(path);
361 Component samples[] =
363 { "Ecere Chess", "samples/chess", "chess", null, false, true },
364 { "Ecere Fractals", "samples/fractals", "fractals", null, false, true },
365 { "3D", "samples/3D", "3D", null, false, true },
366 { "Audio", "samples/audio", "audio", null, false, true },
367 { "Database", "samples/db", "db", null, false, true },
368 { "eC", "samples/eC", "eC", null, false, true },
369 { "Games", "samples/games", "games", null, false, true },
370 { "GUI & Graphics", "samples/guiAndGfx", "guiAndGfx", null, false, true },
371 { "Miscellaneous", "samples/misc", "misc", null, false, true },
372 { "Networking", "samples/net", "net", null, false, true },
373 { "WIA Scanning", "samples/scanning", "scanning", null, false, true },
374 { "Threading", "samples/threads", "threads", null, false, true }
378 public enum CoreSDKID
380 ide, runtime, ec, eda, vanilla, extras,
382 gcc, gdb, mingw, binutils, make,
387 Component coreSDK[CoreSDKID] =
389 { "Ecere IDE", "ecere-sdk/ide", "bin", null, true, true },
390 { "Runtime Library", "ecere-sdk/ecere.dll", "bin", null, true, true },
391 { "eC Compiler", "ecere-sdk/compiler", "bin", null, true, true },
392 { "Data Access", "ecere-sdk/eda", "bin", null, false, true },
393 { "Ecere Vanilla", "ecere-sdk/libecereVanilla.a", "lib", null, false, true },
394 { "Ecere Extras", "extras", "extras", null, false, true },
396 { "GNU C Compiler", "mingw/gcc/core", "mingw", null, true, true },
397 { "GNU Debugger", "mingw/gdb", "mingw", null, true, true },
398 { "MinGW Runtime", "mingw/mingwrt", "mingw", null, true, true },
399 { "Binary Utils", "mingw/binutils", "mingw", null, true, true },
400 { "GNU Make", "mingw/make", "mingw", null, true, true },
406 Component additional[] =
408 { "UPX", "upx/bin", "mingw", null, false, true },
409 { "GNU Regexp", "mingw/gnurx", "mingw", null, false, true },
410 { "Win32 APIs", "mingw/w32api", "mingw", null, false, true },
411 { "pthreads", "mingw/pthreads", "mingw", null, false, true },
412 { "C++ Compiler", "mingw/gcc/c++", "mingw", null, false, true },
413 { "GCC I18n", "mingw/locale/gcc", "mingw", null, false, false },
414 { "GDB I18n", "mingw/locale/gdb", "mingw", null, false, false },
415 { "Make I18n", "mingw/locale/make", "mingw", null, false, false },
416 { "Binutils I18n", "mingw/locale/binutils", "mingw", null, false, false },
421 public enum DocumentationID
423 ecereBook, apiRef, tutorials, coursework,
425 gccDoc, gppDocs, gdbDocs, makeDocs, binDocs, mingwDocs, gnurxDocs, upxDocs,
430 Component documentation[DocumentationID] =
432 { "Ecere Book", "ecere-sdk/book", "doc", null, false, true },
433 { "API Reference", "ecere-sdk/doc", "doc", null, false, true },
434 { "Ecere Tutorials", "ecere-sdk/tutorials", "doc", null, false, true },
435 { "Ecere Coursework", "ecere-sdk/coursework", "doc", null, false, true },
437 { "GCC Docs", "mingw/doc/gcc", "mingw", null, false, false },
438 { "G++ Docs", "mingw/doc/g++", "mingw", null, false, false },
439 { "GDB Docs", "mingw/doc/gdb", "mingw", null, false, false },
440 { "Make Docs", "mingw/doc/make", "mingw", null, false, false },
441 { "Binutils Docs", "mingw/doc/binutils", "mingw", null, false, false },
442 { "MinGW Docs", "mingw/doc/mingw", "mingw", null, false, false },
443 { "gnurx Docs", "mingw/doc/gnurx", "mingw", null, false, false },
444 { "UPX Docs", "upx/doc", "mingw/doc/upx", null, false, false },
449 public enum ComponentID
460 Component components[ComponentID] =
462 { "Core SDK Files", null, null, coreSDK, true, true },
464 { "Additional Support", null, null, additional, false, true },
466 { "Documentation", null /*"doc"*/, null /*"doc"*/, documentation, false, true },
467 { "Samples", null, "samples", samples, false, true },
471 FileSize totalInstalled;
476 InstallOption * subOptions;
481 enum AssociateOptions
492 InstallOption associateOptions[] =
494 { "Associate with Ecere Project Files (*.epj)", null, true },
495 { "Associate with eC Files (*.ec, *.eh)", null, true },
496 { "Associate with C files (*.c, *.h)", null, false },
497 { "Associate with C++ Files (*.cpp, *.hpp, *.cc, *.hh, *.cxx, *.hxx)", null, false },
498 { "Associate with text files (*.txt)", null, false },
499 { "Associate with 3D Studio Model Files (*.3ds)", null, true },
500 { "Associate with Image Files (*.png, *.jpg, *.pcx, *.bmp, *.gif)", null, false },
512 InstallOption pathOptions[] =
514 { "Add Ecere binaries location to the system path", null, true },
515 { "Add MinGW to the system path", null, true }
526 InstallOption options[] =
528 { "Start Menu Group", null, true },
529 { "Desktop Icon", null, true },
530 { "Quicklaunch Icon", null, true },
531 { "Associate the ECERE IDE with Supported File Types", associateOptions, true },
533 { "Add binaries location to the system paths", pathOptions, true },
538 char sourceDir[MAX_LOCATION] = ":";
539 char installDir[MAX_LOCATION];
541 class Installer : Window
543 text = $"Ecere Software Development Kit Setup - v0.44 \"Ryōan-ji\"";
544 background = activeBorder;
549 clientSize = { 636, 456 };
550 icon = { ":icon.png" };
552 Picture back { image = BitmapResource { ":ryoanji.png" }, parent = this, position = { 0, 0 } };
553 FileDialog fileDialog
555 master = this, type = selectDir,
556 text = $"Select a new location"
560 master = this, autoCreate = false, inactive = true, /*hotKey = F2,*/ text = "...";
562 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
564 DataRow row = componentsBox.currentRow;
565 Component * component = ((CheckItem *)row.GetData(componentField))->data;
566 component->GetFullPath(fileDialog.filePath);
567 StripLastDirectory(fileDialog.filePath, fileDialog.currentDirectory);
569 if(fileDialog.Modal() == ok)
571 componentsBox.StopEditing(false);
572 row.SetData(locationField, fileDialog.filePath);
573 componentsBox.NotifyChanged(this, componentsBox, row);
574 componentsBox.currentField = componentsBox.currentField;
579 CheckListBox componentsBox
581 this, size = { 460, 112 }, position = { 160, 160 }, hasHeader = true;
586 bool NotifyChanged(ListBox listBox, DataRow row)
588 Component * component = ((CheckItem *)listBox.GetData(componentField))->data;
589 char path[MAX_LOCATION], relative[MAX_LOCATION] = "", ** newPath;
590 char fullPath[MAX_LOCATION];
592 component->parent->GetFullPath(path);
593 strcpy(fullPath, path);
595 newPath = (char **)row.GetData(locationField);
596 if(newPath && *newPath)
598 PathCat(fullPath, *newPath);
599 MakePathRelative(fullPath, path, relative);
601 listBox.SetData(locationField, relative);
602 strcpy(component->installPath, relative);
604 //SetAvailableSpace(component, path);
607 install.disabled = false;
608 for(c = 0; components[c].name; c++)
610 SetAvailableSpace(components[c], installDir);
616 bool NotifyEditDone(ListBox listBox, DataRow row)
622 bool NotifyEdited(ListBox listBox, DataRow row)
624 browse.parent = listBox;
625 browse.position = { componentField.width + locationField.width + 18, (listBox.currentIndex+1) * listBox.rowHeight - 2 };
626 browse.size = { 30, listBox.rowHeight + 3 };
632 void NotifyChecked(CheckListBox listBox, DataRow row)
634 Component * component = ((CheckItem *)row.GetData(componentField))->data;
636 Button checkBox = (Button)row.tag;
637 component->selected = checkBox.checked;
639 if(!component->parent) totalSize -= component->requiredSize;
640 component->requiredSize = 0;
641 if(component->selected)
643 component->requiredSize += component->size;
644 if(component->subComponents)
645 for(c = 0; component->subComponents[c].name; c++)
646 component->requiredSize += component->subComponents[c].requiredSize;
648 if(component->requiredSize)
650 uint requiredSize = component->requiredSize;
651 row.SetData(reqField, requiredSize);
654 row.UnsetData(reqField);
655 if(!component->parent)
657 totalSize += component->requiredSize;
659 char sizeString[100];
660 PrintSize(sizeString, totalSize, 2);
661 totalSpaceValue.text = sizeString;
666 Label agreementLbl { parent = this, text = $"By installing the Ecere SDK, you agree to the .", font = { "Tahoma", 8.25f }, anchor = Anchor { left = 24, top = 424 } };
669 this, inactive = true, offset = false, bevel = false, foreground = blue, font = { "Tahoma", 8.25f, underline = true, bold = true },
670 // text = $"terms and conditions", anchor = Anchor { left = 241, top = 421 };
671 text = $"terms and conditions", anchor = Anchor { left = 237, top = 421 };
672 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
674 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
676 // LicenseBox { master = this, sourceFile = ":ecere-sdk/doc/LICENSE" }.Modal();
677 LicensesForm { master = this }.Modal();
681 CheckListBox optionsBox
683 this, size = { 460, 94 }, position = { 160, 284 };
686 void NotifyChecked(CheckListBox listBox, DataRow row)
688 CheckItem * item = row.GetData(optionField);
689 InstallOption * option = item->data;
691 Button checkBox = (Button)row.tag;
692 option->selected = checkBox.checked;
697 parent = this, text = $"Install", isDefault = true, size = { 75, 23 }, position = { 432, 416 };
699 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
701 installProgress.Create();
703 // installProgress.thread.Main();
704 installProgress.thread.Create();
708 Button button3 { parent = this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 }, NotifyClicked = ButtonCloseDialog };
709 Label label1 { labeledWindow = destBox, tabCycle = true, isGroupBox = true, parent = this, inactive = false, size = Size { 458, 50 }, anchor = Anchor { left = 160, top = 96 } };
712 parent = label1, master = this, text = $" Destination Folder", size = Size { 336, 19 }, anchor = Anchor { left = 12, top = 20 };
714 bool NotifyModified(EditBox editBox)
717 strcpy(installDir, destBox.contents);
718 install.disabled = false;
719 for(c = 0; components[c].name; c++)
721 SetAvailableSpace(components[c], installDir);
728 label1, this, $"Browse", altB, size = { 83, 24 }, position = { 360, 16 };
730 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
732 strcpy(fileDialog.filePath, installDir);
733 StripLastDirectory(installDir, fileDialog.currentDirectory);
734 if(fileDialog.Modal())
736 strcpy(installDir, fileDialog.filePath);
737 destBox.contents = installDir;
738 // TOCHECK: Should setting contents call NotifyModified?
739 destBox.NotifyModified(destBox.master, destBox);
746 this, multiLine = true,
747 opacity = 0, borderStyle = none, inactive = true, size = { 136, 53 }, position = { 14, 96 }, noSelect = true,
748 contents = $"Select the default root\n"
749 "folder where to install\n"
754 this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 132 }, position = { 14, 152 }, noSelect = true,
756 contents = $"Select the optional\n"
757 "components you wish\n"
759 "You may customize the\n"
760 "install location for each\n"
761 "of them, or use the default\n"
762 "based on the main\n"
763 "destination folder."
767 this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 53 }, position = { 14, 280 }, noSelect = true,
769 contents = $"Select icons to install, file\n"
770 "associations, and system\n"
771 "environment modifications:"
773 Label totalSpaceLabel
775 this, position = { 18, 352 }, text = $"Space Required: "
777 Label totalSpaceValue
779 this, position = { 100, 352 }, text = "0 mb"
783 inactive = true, noSelect = true,
784 multiLine = true, parent = label3, text = "editBox1", opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 },
785 contents = $"Choose in which folder to install the ECERE SDK, which features\n"
786 "of the SDK to install, as well as where to install program icons."
788 Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder };
789 Picture picture1 { image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, text = "picture1", anchor = Anchor { left = 16, top = 4 } };
790 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 } };
791 DataField componentField { "CheckItem", width = 140, header = $"Component" };
792 DataField locationField { "char *", width = 108, header = $"Destination Folder", editable = true };
793 DataField reqField { "FileSize", width = 80, header = $"Req. Space", alignment = right };
794 DataField avField { "FileSize64", width = 80, header = $"Avail. Space", alignment = right };
795 DataField optionField { "CheckItem" };
797 void SetAvailableSpace(Component component, char * parentPath)
799 char path[MAX_LOCATION];
803 strcpy(path, parentPath);
804 PathCat(path, component.installPath);
806 if(component.subComponents)
807 for(c = 0; component.subComponents[c].name; c++)
808 SetAvailableSpace(component.subComponents[c], path);
810 while(!FileExists(path) && path[0])
811 StripLastDirectory(path, path);
814 GetFreeSpace(path, &size);
815 component.row.SetData(avField, size);
816 if(!size) install.disabled = true;
819 FileSize ComputeSize(char * path)
822 FileAttribs attribs = FileExists(path);
823 if(attribs.isDirectory)
825 FileListing listing { path };
826 while(listing.Find())
828 if(listing.stats.attribs.isDirectory)
829 size += ComputeSize(listing.path);
831 size += listing.stats.size;
835 FileGetSize(path, &size);
839 void AddComponent(Component component, Component parent, char * parentPath)
841 DataRow row = component.row = componentsBox.AddRow((parent != null) ? parent.row : null);
842 Button checkBox = (Button) row.tag;
844 FileSize64 avSize = 0;
845 char path[MAX_LOCATION];
846 strcpy(path, parentPath);
847 if(component.defInstallPath)
848 PathCat(path, component.defInstallPath);
849 component.parent = parent;
851 row.SetData(null, CheckItem { component.name, component } );
853 if(component.defInstallPath)
855 strcpy(component.installPath, component.defInstallPath);
856 ChangeCh(component.installPath, '/', DIR_SEP);
857 row.SetData(locationField, component.installPath);
860 if(component.mandatory) checkBox.disabled = true;
861 if(!component.selected) componentsBox.ToggleCheck(row);
862 if(component.dataPath)
864 char path[MAX_LOCATION];
866 PathCat(path, component.dataPath);
867 component.size = ComputeSize(path);
869 if(component.subComponents)
872 for(c = 0; component.subComponents[c].name; c++)
874 AddComponent(component.subComponents[c], component, path);
875 size += component.subComponents[c].requiredSize;
879 component.requiredSize = component.selected ? (size + component.size) : 0;
880 if(component.requiredSize)
881 row.SetData(reqField, component.requiredSize);
883 while(!FileExists(path) && path[0])
884 StripLastDirectory(path, path);
887 GetFreeSpace(path, &avSize);
890 row.SetData(avField, avSize);
891 row.collapsed = true;
894 void AddOption(InstallOption option, InstallOption parent)
896 DataRow row = option.row = optionsBox.AddRow((parent != null) ? parent.row : null);
897 row.SetData(null, CheckItem { option.name, option } );
899 optionsBox.ToggleCheck(row);
900 if(option.subOptions)
903 for(c = 0; option.subOptions[c].name; c++)
905 AddOption(option.subOptions[c], option);
908 row.collapsed = true;
914 char programFilesDir[MAX_LOCATION];
915 char appData[MAX_LOCATION]; // = getenv("APPDATA");
916 char homeDrive[MAX_LOCATION]; //= getenv("HOMEDRIVE");
917 char winDir[MAX_LOCATION]; //= getenv("windir");
919 GetEnvironment("APPDATA", appData, sizeof(appData));
920 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
921 GetEnvironment("windir", winDir, sizeof(winDir));
923 componentsBox.AddField(componentField);
924 componentsBox.AddField(locationField);
925 componentsBox.AddField(reqField);
926 componentsBox.AddField(avField);
928 optionsBox.AddField(optionField);
930 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
932 strcpy(installDir, programFilesDir);
933 PathCat(installDir, "ECERE SDK");
935 else if(homeDrive && homeDrive[0])
937 strcpy(installDir, homeDrive);
938 PathCat(installDir, "ECERE SDK");
940 else if(winDir && winDir[0])
942 strcpy(installDir, winDir);
943 PathCat(installDir, "..\\ECERE SDK");
946 strcpy(installDir, "C:\\ECERE SDK");
948 if(appData && appData[0])
950 static char defSamplesPath[MAX_LOCATION];
951 static char defExtrasPath[MAX_LOCATION];
952 strcpy(defSamplesPath, appData);
953 PathCat(defSamplesPath, "ECERE SDK\\Samples");
954 components[samples].defInstallPath = defSamplesPath;
956 strcpy(defExtrasPath, appData);
957 PathCat(defExtrasPath, "ECERE SDK\\extras");
958 coreSDK[extras].defInstallPath = defExtrasPath;
961 destBox.contents = installDir;
965 for(c = 0; components[c].name; c++)
966 AddComponent(components[c], null, installDir);
969 // Compute size apart because ToggleCheck will change it
973 for(c = 0; components[c].name; c++)
974 totalSize += components[c].requiredSize;
977 char sizeString[100];
978 PrintSize(sizeString, totalSize, 2);
979 totalSpaceValue.text = sizeString;
981 for(c = 0; options[c].name; c++)
982 AddOption(options[c], null);
991 void OnDrawOverChildren(Surface surface)
993 int tw = label2.size.w;
994 surface.SetForeground(Color { 128, 128, 128 });
995 surface.HLine(label2.position.x + tw + 6, 620, 400);
996 surface.SetForeground(white);
997 surface.HLine(label2.position.x + tw + 6, 621, 401);
998 surface.PutPixel(621, 400);
1003 parent = this, opacity = 0, borderStyle = deep, size = Size { 644, 93 }, anchor = Anchor { left = -8, top = -8 };
1007 class InstallProgress : Window
1009 text = $"Ecere Software Development Kit Setup - v0.44 \"Ryōan-ji\"";
1010 background = activeBorder;
1011 borderStyle = fixed;
1015 size = Size { 640, 480 };
1016 icon = { ":icon.png" };
1018 Picture back { image = BitmapResource { ":ryoanji-progress.png" }, parent = this, position = { 0, 0 } };
1019 Label installing { this, position = { 32, 160 } };
1020 ProgressBar progressBar { parent = this, size = Size { 588, 24 }, anchor = Anchor { left = 24, top = 184 } };
1023 parent = this, text = $"Install", disabled = true, isDefault = true, size = Size { 75, 23 }, anchor = Anchor { left = 432, top = 416 };
1025 NotifyClicked = ButtonCloseDialog
1029 this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 };
1031 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1033 abortInstall = true;
1039 inactive = true, noSelect = true,
1040 multiLine = true, parent = label3, opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 },
1041 contents = $"Please wait while the Ecere Software Development Kit is being installed."
1043 Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder };
1044 Picture picture1 { image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, anchor = Anchor { left = 16, top = 4 } };
1045 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 } };
1047 void OnDrawOverChildren(Surface surface)
1049 int tw = label2.size.w;
1050 surface.SetForeground(Color { 128, 128, 128 });
1051 surface.HLine(label2.position.x + tw + 6, 620, 400);
1052 surface.SetForeground(white);
1053 surface.HLine(label2.position.x + tw + 6, 621, 401);
1054 surface.PutPixel(621, 400);
1059 parent = this, opacity = 0, borderStyle = deep, size = Size { 644, 93 }, anchor = Anchor { left = -8, top = -8 };
1061 InstallThread thread
1066 Installer installer {};
1067 InstallProgress installProgress { autoCreate = false };
1069 void ModifyPath(char * newPath)
1076 strcpy(oldPath, newPath);
1077 count = TokenizeWith(oldPath, sizeof(paths) / sizeof(char *), paths, ";", false);
1079 for(c = 0; coreSDK[c].name; c++)
1081 char path[MAX_LOCATION];
1082 coreSDK[c].GetFullPath(path);
1083 if(c != ide && c != runtime && c != eda && c != ec && c !=extras && c != vanilla)
1086 if(!pathOptions[PathOptions::AddMinGWPaths].selected)
1089 PathCat(path, "bin");
1091 else if(!pathOptions[PathOptions::AddECEREPaths].selected) continue;
1093 for(p = 0; p<count; p++)
1094 if(!fstrcmp(paths[p], path))
1101 strcat(newPath, ";");
1102 start = oldPath + strlen(paths[count-1])+1;
1107 strcpy(start, path);
1108 *(start + strlen(path)) = '\0';
1109 paths[count++] = start;
1111 strcat(newPath, path);
1115 if(pathOptions[PathOptions::AddMinGWPaths].selected)
1118 for(c = 0; additional[c].name; c++)
1120 char path[MAX_LOCATION];
1122 additional[c].GetFullPath(path);
1123 PathCat(path, "bin");
1124 for(p = 0; p<count; p++)
1125 if(!fstrcmp(paths[p], path))
1133 strcat(newPath, ";");
1134 start = oldPath + strlen(paths[count-1])+1;
1139 strcpy(start, path);
1140 *(start + strlen(path)) = '\0';
1141 paths[count++] = start;
1143 strcat(newPath, path);
1150 void AssociateExtension(char * extension, char * description, char *name, char * action, char * path)
1156 RegCreateKeyEx(HKEY_CLASSES_ROOT, extension, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1157 RegSetValueEx(key, null, 0, REG_SZ, name, strlen(name)+1);
1160 RegCreateKeyEx(HKEY_CLASSES_ROOT, name, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1161 RegSetValueEx(key, null, 0, REG_SZ, description, strlen(description)+1);
1164 sprintf(keyName, "%s\\shell", extension);
1165 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1166 RegSetValueEx(key, null, 0, REG_SZ, action, strlen(action)+1);
1169 sprintf(keyName, "%s\\shell\\%s", name, action);
1170 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1173 sprintf(keyName, "%s\\shell\\%s\\command", name, action);
1174 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1176 sprintf(keyName, path);
1177 strcat(keyName, " \"%L\"");
1179 uint16 wKeyName[2048];
1180 UTF8toUTF16Buffer(keyName, wKeyName, sizeof(wKeyName) / sizeof(uint16));
1181 RegSetValueExW(key, null, 0, REG_SZ, (byte *)wKeyName, (wcslen(wKeyName) + 1)*sizeof(uint16));
1186 class InstallThread : Thread
1191 ((GuiApplication)__thisModule).Lock();
1192 installProgress.progressBar.range = totalSize;
1193 for(c = 0; components[c].name && !abortInstall; c++)
1194 components[c].Install(installDir);
1197 installProgress.progressBar.range = 0;
1198 installProgress.finish.Destroy(0);
1199 installProgress.cancel.text = $"Close";
1200 installProgress.cancel.isDefault = true;
1201 installProgress.cancel.disabled = false;
1202 installProgress.cancel.NotifyClicked = Window::ButtonCloseDialog;
1203 installProgress.installing.text = $"Installation Cancelled.";
1204 installProgress.title.text = $"Installation Cancelled";
1205 installProgress.titleInfo.contents = $"The installation was not completed.";
1210 char idePath[MAX_LOCATION];
1211 char userProfile[MAX_LOCATION];
1214 GlobalSettings settings
1218 installProgress.installing.text = $"Configuring ECERE IDE...";
1219 ((GuiApplication)__thisModule).Unlock();
1220 ((GuiApplication)__thisModule).SignalEvent();
1223 for(c = 0; coreSDK[c].name; c++)
1225 char path[MAX_LOCATION];
1227 coreSDK[c].GetFullPath(path);
1228 if(c != ide && c != runtime && c != eda && c != ec)
1229 PathCat(path, "bin");
1232 coreSDK[c].GetFullPath(idePath);
1233 PathCat(idePath, "IDE.exe");
1236 // TODO: Update This!
1238 for(item = settings.systemDirs[executables].first; item; item = item.next)
1239 if(!fstrcmp(item.name, path))
1243 settings.systemDirs[executables].Add(NamedItem { name = CopyString(path); });
1248 for(item = settings.systemDirs[libraries].first; item; item = item.next)
1249 if(!fstrcmp(item.name, path))
1253 settings.systemDirs[libraries].Add(NamedItem { name = CopyString(path); });
1260 for(c = 0; additional[c].name; c++)
1262 char path[MAX_LOCATION];
1264 additional[c].GetFullPath(path);
1265 PathCat(path, "bin");
1266 for(item = settings.systemDirs[executables].first; item; item = item.next)
1267 if(!fstrcmp(item.name, path))
1271 settings.systemDirs[executables].Add(NamedItem { name = CopyString(path); });
1278 char path[MAX_LOCATION] = "";
1279 if(components[samples].selected)
1280 components[samples].GetFullPath(path);
1282 components[coreSDK].GetFullPath(path);
1283 /* TODO: Update This!
1284 if(!settings.ideProjectFileDialogLocation)
1285 settings.ideProjectFileDialogLocation = path;
1286 if(!settings.ideFileDialogLocation)
1287 settings.ideFileDialogLocation = path;
1294 // Set up Uninstaller
1295 ((GuiApplication)__thisModule).Lock();
1296 installProgress.installing.text = $"Registering uninstaller...";
1297 ((GuiApplication)__thisModule).Unlock();
1298 ((GuiApplication)__thisModule).SignalEvent();
1303 char * displayName = "ECERE SDK 0.44";
1304 char uninstaller[MAX_LOCATION];
1305 bool nomodify = true;
1307 strcpy(uninstaller, installDir);
1308 PathCat(uninstaller, "uninstall_ecere.exe");
1310 RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ECERE SDK", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1312 RegSetValueEx(key, "DisplayName", 0, REG_SZ, displayName, strlen(displayName)+1);
1313 RegSetValueEx(key, "UninstallString", 0, REG_SZ, uninstaller, strlen(uninstaller)+1);
1314 RegSetValueEx(key, "DisplayIcon", 0, REG_SZ, idePath, strlen(idePath)+1);
1315 //RegSetValueEx(key, "NoModify", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1316 //RegSetValueEx(key, "NoRepair", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1321 if(pathOptions[PathOptions::AddECEREPaths].selected
1323 || pathOptions[PathOptions::AddMinGWPaths].selected
1329 char path[2048] = "";
1332 ((GuiApplication)__thisModule).Lock();
1333 installProgress.installing.text = "Registering paths...";
1334 ((GuiApplication)__thisModule).Unlock();
1335 ((GuiApplication)__thisModule).SignalEvent();
1337 // if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Environment", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1339 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1340 // RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1341 if(status == REG_OPENED_EXISTING_KEY)
1343 size = sizeof(wPath);
1344 RegQueryValueExW(key, L"path", null, null, (byte *)wPath, &size);
1345 UTF16toUTF8Buffer(wPath, path, sizeof(path));
1348 UTF8toUTF16Buffer(path, wPath, sizeof(wPath) / sizeof(uint16));
1349 RegSetValueExW(key, L"path", 0, REG_EXPAND_SZ, (byte *)wPath, (wcslen(wPath)+1) * 2);
1352 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (int)"Environment", SMTO_NORMAL, 1000, NULL);
1355 // Install Program Group Icons
1356 // userProfile = getenv("USERPROFILE");
1357 GetEnvironment("USERPROFILE", userProfile, sizeof(userProfile));
1359 if(options[IconOptions::StartMenuIcon].selected)
1361 char destPath[MAX_LOCATION];
1362 char startMenuPath[MAX_LOCATION] = "";
1365 ((GuiApplication)__thisModule).Lock();
1366 installProgress.installing.text = $"Installing Start Menu Icons...";
1367 ((GuiApplication)__thisModule).Unlock();
1368 ((GuiApplication)__thisModule).SignalEvent();
1370 strcpy(destPath, userProfile);
1372 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1374 uint16 wStartMenuPath[2048];
1375 uint size = sizeof(wStartMenuPath);
1376 // RegQueryValueEx(key, "Start Menu", null, null, startMenuPath, &size);
1377 RegQueryValueExW(key, L"Programs", null, null, (byte *)wStartMenuPath, &size);
1378 UTF16toUTF8Buffer(wStartMenuPath, startMenuPath, sizeof(startMenuPath));
1381 if(!startMenuPath[0] && userProfile && userProfile[0])
1383 strcpy(startMenuPath, userProfile);
1384 PathCat(startMenuPath, "Start Menu\\Programs");
1387 if(startMenuPath[0])
1389 strcpy(destPath, startMenuPath);
1390 PathCat(destPath, "ECERE SDK");
1393 strcpy(destPath, startMenuPath);
1394 PathCat(destPath, "ECERE SDK\\ECERE IDE.lnk");
1395 CreateLink(idePath, destPath, null); //"ECERE IDE");
1396 if(components[samples].selected)
1398 char samplesPath[MAX_LOCATION] = "";
1399 components[samples].GetFullPath(samplesPath);
1401 strcpy(destPath, startMenuPath);
1402 PathCat(destPath, "ECERE SDK\\Sample Projects.lnk");
1403 CreateLink(samplesPath, destPath, null);//"Sample Projects");
1405 if(components[documentation].selected && documentation[ecereBook].selected)
1407 char docPath[MAX_LOCATION] = "";
1408 documentation[ecereBook].GetFullPath(docPath);
1409 PathCat(docPath, "Ecere Tao of Programming [work in progress].pdf");
1411 strcpy(destPath, startMenuPath);
1412 PathCat(destPath, "ECERE SDK\\The Ecere Tao of Programming.lnk");
1413 CreateLink(docPath, destPath, null);
1418 // Install Desktop Icon
1419 if(options[IconOptions::DesktopIcon].selected)
1422 char desktopPath[MAX_LOCATION];
1424 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1426 uint16 wDesktopPath[MAX_LOCATION];
1427 uint size = sizeof(wDesktopPath);
1428 RegQueryValueExW(key, L"Desktop", null, null, (byte *)wDesktopPath, &size);
1429 UTF16toUTF8Buffer(wDesktopPath, desktopPath, sizeof(desktopPath));
1432 if(!desktopPath[0] && userProfile && userProfile[0])
1434 strcpy(desktopPath, userProfile);
1435 PathCat(desktopPath, "Desktop");
1440 PathCat(desktopPath, "ECERE IDE.lnk");
1442 ((GuiApplication)__thisModule).Lock();
1443 installProgress.installing.text = $"Installing Desktop Icon...";
1444 ((GuiApplication)__thisModule).Unlock();
1445 ((GuiApplication)__thisModule).SignalEvent();
1447 CreateLink(idePath, desktopPath, null);//"ECERE IDE");
1451 // Install QuickLaunch Icon
1452 if(options[IconOptions::QuickLaunchIcon].selected)
1454 char appData[MAX_LOCATION]; // = getenv("APPDATA");
1455 GetEnvironment("APPDATA", appData, sizeof(appData));
1457 if(appData && appData[0])
1459 char destPath[MAX_LOCATION];
1461 ((GuiApplication)__thisModule).Lock();
1462 installProgress.installing.text = $"Installing Quicklaunch Icon...";
1463 ((GuiApplication)__thisModule).Unlock();
1464 ((GuiApplication)__thisModule).SignalEvent();
1466 strcpy(destPath, appData);
1467 PathCat(destPath, "Microsoft\\Internet Explorer\\Quick Launch\\ECERE IDE.lnk");
1469 CreateLink(idePath, destPath, null);//"ECERE IDE");
1473 // Register File Types
1474 if(associateOptions[AssociateOptions::AssociateEPJ].selected ||
1475 associateOptions[AssociateOptions::AssociateEC].selected ||
1476 associateOptions[AssociateOptions::AssociateC].selected ||
1477 associateOptions[AssociateOptions::AssociateCPP].selected ||
1478 associateOptions[AssociateOptions::AssociateTXT].selected ||
1479 associateOptions[AssociateOptions::Associate3DS].selected ||
1480 associateOptions[AssociateOptions::AssociateIMG].selected)
1482 ((GuiApplication)__thisModule).Lock();
1483 installProgress.installing.text = $"Resgistering File Types...";
1484 ((GuiApplication)__thisModule).Unlock();
1485 ((GuiApplication)__thisModule).SignalEvent();
1487 if(associateOptions[AssociateOptions::AssociateEPJ].selected)
1489 AssociateExtension(".epj", "ECERE IDE Project", "epj_file", "Open", idePath);
1491 if(associateOptions[AssociateOptions::AssociateEC].selected)
1493 AssociateExtension(".ec", "eC Source File", "ec_file", "Open", idePath);
1494 AssociateExtension(".eh", "eC Header File", "eh_file", "Open", idePath);
1496 if(associateOptions[AssociateOptions::AssociateC].selected)
1498 AssociateExtension(".c", "C Source File", "c_file", "Open", idePath);
1499 AssociateExtension(".h", "C Header File", "h_file", "Open", idePath);
1501 if(associateOptions[AssociateOptions::AssociateCPP].selected)
1503 AssociateExtension(".cpp", "C++ Source File", "cpp_file", "Open", idePath);
1504 AssociateExtension(".cc", "C++ Source File", "cpp_file", "Open", idePath);
1505 AssociateExtension(".cxx", "C++ Source File", "cpp_file", "Open", idePath);
1506 AssociateExtension(".chh", "C++ Header File", "chh_file", "Open", idePath);
1507 AssociateExtension(".hh", "C++ Header File", "chh_file", "Open", idePath);
1508 AssociateExtension(".hxx", "C++ Header File", "chh_file", "Open", idePath);
1510 if(associateOptions[AssociateOptions::AssociateTXT].selected)
1512 AssociateExtension(".txt", "Text File", "txt_file", "Open", idePath);
1514 if(associateOptions[AssociateOptions::Associate3DS].selected)
1516 AssociateExtension(".3ds", "3D Studio Model", "3ds_file", "View", idePath);
1518 if(associateOptions[AssociateOptions::AssociateIMG].selected)
1520 AssociateExtension(".bmp", "BMP Image", "bmp_file", "View", idePath);
1521 AssociateExtension(".pcx", "PCX Image", "pcx_file", "View", idePath);
1522 AssociateExtension(".png", "PNG Image", "png_file", "View", idePath);
1523 AssociateExtension(".jpg", "JPEG Image", "jpg_file", "View", idePath);
1524 AssociateExtension(".jpeg", "JPEG Image", "jpg_file", "View", idePath);
1525 AssociateExtension(".gif", "GIF Image", "gif_file", "View", idePath);
1528 ((GuiApplication)__thisModule).Lock();
1530 installProgress.cancel.Destroy(0);
1531 installProgress.finish.text = $"Finish";
1532 installProgress.finish.disabled = false;
1533 installProgress.finish.Activate();
1534 installProgress.installing.text = $"Installation Complete.";
1535 installProgress.title.text = $"Installation Complete";
1536 installProgress.titleInfo.contents = $"Thank you for using the Ecere SDK.";
1538 ((GuiApplication)__thisModule).Unlock();