2 static define buildString = $"Ecere SDK v0.44 (Without MinGW) -- built on March 9, 2012 ";
4 static define buildString = $"Ecere SDK v0.44 -- built on March 9, 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; displayFlags.selected = 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/bin",null, false, true },
409 { "GNU Regexp", "mingw/gnurx", "mingw", null, false, true },
410 { "pthreads", "mingw/pthreads", "mingw", null, false, true },
411 { "C++ Compiler", "mingw/gcc/c++", "mingw", null, false, true },
412 { "Win32 APIs", "mingw/w32api", "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/mingwrt", "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;
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();
676 LicensesForm { master = this }.Modal();
680 CheckListBox optionsBox
682 this, size = { 460, 94 }, position = { 160, 284 };
685 void NotifyChecked(CheckListBox listBox, DataRow row)
687 CheckItem * item = row.GetData(optionField);
688 InstallOption * option = item->data;
690 Button checkBox = (Button)row.tag;
691 option->selected = checkBox.checked;
696 parent = this, text = $"Install", isDefault = true, size = { 75, 23 }, position = { 432, 416 };
698 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
700 installProgress.Create();
702 // installProgress.thread.Main();
703 installProgress.thread.Create();
707 Button button3 { parent = this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 }, NotifyClicked = ButtonCloseDialog };
708 Label label1 { labeledWindow = destBox, tabCycle = true, isGroupBox = true, parent = this, inactive = false, size = Size { 458, 50 }, anchor = Anchor { left = 160, top = 96 } };
711 parent = label1, master = this, text = $" Destination Folder", size = Size { 336, 22 }, anchor = Anchor { left = 12, top = 20, right = 12 };
712 typeExpected = directory;
713 browseDialog = fileDialog;
716 bool NotifyModified(PathBox pathBox)
719 strcpy(installDir, destBox.path);
720 install.disabled = false;
721 for(c = 0; components[c].name; c++)
723 SetAvailableSpace(components[c], installDir);
730 label1, this, $"Browse", altB, size = { 83, 24 }, position = { 360, 16 };
732 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
734 strcpy(fileDialog.filePath, installDir);
735 StripLastDirectory(installDir, fileDialog.currentDirectory);
736 if(fileDialog.Modal())
738 strcpy(installDir, fileDialog.filePath);
739 destBox.contents = installDir;
740 // TOCHECK: Should setting contents call NotifyModified?
741 destBox.NotifyModified(destBox.master, destBox);
748 this, multiLine = true,
749 opacity = 0, borderStyle = none, inactive = true, size = { 136, 53 }, position = { 14, 96 }, noSelect = true,
750 contents = $"Select the default root\n"
751 "folder where to install\n"
756 this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 132 }, position = { 14, 152 }, noSelect = true,
758 contents = $"Select the optional\n"
759 "components you wish\n"
761 "You may customize the\n"
762 "install location for each\n"
763 "of them, or use the default\n"
764 "based on the main\n"
765 "destination folder."
769 this, opacity = 0, borderStyle = none, inactive = true, size = { 136, 53 }, position = { 14, 280 }, noSelect = true,
771 contents = $"Select icons to install, file\n"
772 "associations, and system\n"
773 "environment modifications:"
775 Label totalSpaceLabel
777 this, position = { 18, 352 }, text = $"Space Required: "
779 Label totalSpaceValue
781 this, position = { 100, 352 }, text = "0 mb"
785 inactive = true, noSelect = true,
786 multiLine = true, parent = label3, text = "editBox1", opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 },
787 contents = $"Choose in which folder to install the ECERE SDK, which features\n"
788 "of the SDK to install, as well as where to install program icons."
790 Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder };
793 image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, text = "picture1", anchor = Anchor { left = 16, top = 4 };
794 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
796 bool OnLeftButtonDown(int x, int y, Modifiers mods)
798 ShellOpen("http://www.ecere.com/");
802 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 } };
803 DataField componentField { "CheckItem", width = 140, header = $"Component" };
804 DataField locationField { "char *", width = 108, header = $"Destination Folder", editable = true };
805 DataField reqField { "FileSize", width = 80, header = $"Req. Space", alignment = right };
806 DataField avField { "FileSize64", width = 80, header = $"Avail. Space", alignment = right };
807 DataField optionField { "CheckItem" };
809 void SetAvailableSpace(Component component, char * parentPath)
811 char path[MAX_LOCATION];
815 strcpy(path, parentPath);
816 PathCat(path, component.installPath);
818 if(component.subComponents)
819 for(c = 0; component.subComponents[c].name; c++)
820 SetAvailableSpace(component.subComponents[c], path);
822 while(!FileExists(path) && path[0])
823 StripLastDirectory(path, path);
826 GetFreeSpace(path, &size);
827 component.row.SetData(avField, size);
828 if(!size) install.disabled = true;
831 FileSize ComputeSize(char * path)
834 FileAttribs attribs = FileExists(path);
835 if(attribs.isDirectory)
837 FileListing listing { path };
838 while(listing.Find())
840 if(listing.stats.attribs.isDirectory)
841 size += ComputeSize(listing.path);
843 size += listing.stats.size;
847 FileGetSize(path, &size);
851 void AddComponent(Component component, Component parent, char * parentPath)
853 DataRow row = component.row = componentsBox.AddRow((parent != null) ? parent.row : null);
854 Button checkBox = (Button) row.tag;
856 FileSize64 avSize = 0;
857 char path[MAX_LOCATION];
858 strcpy(path, parentPath);
859 if(component.defInstallPath)
860 PathCat(path, component.defInstallPath);
861 component.parent = parent;
863 row.SetData(null, CheckItem { component.name, component } );
865 if(component.defInstallPath)
867 strcpy(component.installPath, component.defInstallPath);
868 ChangeCh(component.installPath, '/', DIR_SEP);
869 row.SetData(locationField, component.installPath);
872 if(component.mandatory) checkBox.disabled = true;
873 if(!component.selected) componentsBox.ToggleCheck(row);
874 if(component.dataPath)
876 char path[MAX_LOCATION];
878 PathCat(path, component.dataPath);
879 component.size = ComputeSize(path);
881 if(component.subComponents)
884 for(c = 0; component.subComponents[c].name; c++)
886 AddComponent(component.subComponents[c], component, path);
887 size += component.subComponents[c].requiredSize;
891 component.requiredSize = component.selected ? (size + component.size) : 0;
892 if(component.requiredSize)
893 row.SetData(reqField, component.requiredSize);
895 while(!FileExists(path) && path[0])
896 StripLastDirectory(path, path);
899 GetFreeSpace(path, &avSize);
902 row.SetData(avField, avSize);
903 row.collapsed = true;
906 void AddOption(InstallOption option, InstallOption parent)
908 DataRow row = option.row = optionsBox.AddRow((parent != null) ? parent.row : null);
909 row.SetData(null, CheckItem { option.name, option } );
911 optionsBox.ToggleCheck(row);
912 if(option.subOptions)
915 for(c = 0; option.subOptions[c].name; c++)
917 AddOption(option.subOptions[c], option);
920 row.collapsed = true;
926 char programFilesDir[MAX_LOCATION];
927 char appData[MAX_LOCATION]; // = getenv("APPDATA");
928 char homeDrive[MAX_LOCATION]; //= getenv("HOMEDRIVE");
929 char winDir[MAX_LOCATION]; //= getenv("windir");
931 GetEnvironment("APPDATA", appData, sizeof(appData));
932 GetEnvironment("HOMEDRIVE", homeDrive, sizeof(homeDrive));
933 GetEnvironment("windir", winDir, sizeof(winDir));
935 componentsBox.AddField(componentField);
936 componentsBox.AddField(locationField);
937 componentsBox.AddField(reqField);
938 componentsBox.AddField(avField);
940 optionsBox.AddField(optionField);
942 if(GetEnvironment("ProgramFiles", programFilesDir, MAX_LOCATION))
944 strcpy(installDir, programFilesDir);
945 PathCat(installDir, "ECERE SDK");
947 else if(homeDrive && homeDrive[0])
949 strcpy(installDir, homeDrive);
950 PathCat(installDir, "ECERE SDK");
952 else if(winDir && winDir[0])
954 strcpy(installDir, winDir);
955 PathCat(installDir, "..\\ECERE SDK");
958 strcpy(installDir, "C:\\ECERE SDK");
960 if(appData && appData[0])
962 static char defSamplesPath[MAX_LOCATION];
963 static char defExtrasPath[MAX_LOCATION];
964 strcpy(defSamplesPath, appData);
965 PathCat(defSamplesPath, "ECERE SDK\\Samples");
966 components[samples].defInstallPath = defSamplesPath;
968 strcpy(defExtrasPath, appData);
969 PathCat(defExtrasPath, "ECERE SDK\\extras");
970 coreSDK[extras].defInstallPath = defExtrasPath;
973 destBox.path = installDir;
977 for(c = 0; components[c].name; c++)
978 AddComponent(components[c], null, installDir);
981 // Compute size apart because ToggleCheck will change it
985 for(c = 0; components[c].name; c++)
986 totalSize += components[c].requiredSize;
989 char sizeString[100];
990 PrintSize(sizeString, totalSize, 2);
991 totalSpaceValue.text = sizeString;
993 for(c = 0; options[c].name; c++)
994 AddOption(options[c], null);
1003 void OnDrawOverChildren(Surface surface)
1005 int tw = label2.size.w;
1006 surface.SetForeground(Color { 128, 128, 128 });
1007 surface.HLine(label2.position.x + tw + 6, 620, 400);
1008 surface.SetForeground(white);
1009 surface.HLine(label2.position.x + tw + 6, 621, 401);
1010 surface.PutPixel(621, 400);
1015 parent = this, opacity = 0, borderStyle = deep, size = Size { 644, 93 }, anchor = Anchor { left = -8, top = -8 };
1019 class InstallProgress : Window
1021 text = $"Ecere Software Development Kit Setup - v0.44 \"Ryōan-ji\"";
1022 background = activeBorder;
1023 borderStyle = fixed;
1027 size = Size { 640, 480 };
1028 icon = { ":icon.png" };
1030 Picture back { image = BitmapResource { ":ryoanji-progress.png" }, parent = this, position = { 0, 0 } };
1031 Label installing { this, position = { 32, 160 } };
1032 ProgressBar progressBar { parent = this, size = Size { 588, 24 }, anchor = Anchor { left = 24, top = 184 } };
1035 parent = this, text = $"Install", disabled = true, isDefault = true, size = Size { 75, 23 }, anchor = Anchor { left = 432, top = 416 };
1037 NotifyClicked = ButtonCloseDialog
1041 this, text = $"Cancel", hotKey = altX, size = Size { 75, 23 }, anchor = Anchor { left = 544, top = 416 };
1043 bool NotifyClicked(Button button, int x, int y, Modifiers mods)
1045 abortInstall = true;
1051 inactive = true, noSelect = true,
1052 multiLine = true, parent = label3, opacity = 0, borderStyle = none, size = Size { 350, 35 }, anchor = Anchor { horz = 111, vert = 13 },
1053 contents = $"Please wait while the Ecere Software Development Kit is being installed."
1055 Label label2 { parent = this, text = buildString, position = { 16, 392 }, font = { "Tahoma", 10, true }, disabled = true, opacity = 0, background = activeBorder };
1058 image = BitmapResource { ":ecere.png", alphaBlend = true }, filter = true, parent = label3, anchor = Anchor { left = 16, top = 4 };
1059 cursor = ((GuiApplication)__thisModule).GetCursor(hand);
1061 bool OnLeftButtonDown(int x, int y, Modifiers mods)
1063 ShellOpen("http://www.ecere.com/");
1067 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 } };
1069 void OnDrawOverChildren(Surface surface)
1071 int tw = label2.size.w;
1072 surface.SetForeground(Color { 128, 128, 128 });
1073 surface.HLine(label2.position.x + tw + 6, 620, 400);
1074 surface.SetForeground(white);
1075 surface.HLine(label2.position.x + tw + 6, 621, 401);
1076 surface.PutPixel(621, 400);
1081 parent = this, opacity = 0, borderStyle = deep, size = Size { 644, 93 }, anchor = Anchor { left = -8, top = -8 };
1083 InstallThread thread
1088 Installer installer {};
1089 InstallProgress installProgress { autoCreate = false };
1091 void ModifyPath(char * newPath)
1098 strcpy(oldPath, newPath);
1099 count = TokenizeWith(oldPath, sizeof(paths) / sizeof(char *), paths, ";", false);
1101 for(c = 0; coreSDK[c].name; c++)
1103 char path[MAX_LOCATION];
1104 if(c == extras || c == vanilla) continue;
1106 coreSDK[c].GetFullPath(path);
1107 if(c != ide && c != runtime && c != eda && c != ec)
1110 if(!pathOptions[PathOptions::AddMinGWPaths].selected)
1113 PathCat(path, "bin");
1115 else if(!pathOptions[PathOptions::AddECEREPaths].selected) continue;
1117 for(p = 0; p<count; p++)
1118 if(!fstrcmp(paths[p], path))
1125 strcat(newPath, ";");
1126 start = oldPath + strlen(paths[count-1])+1;
1131 strcpy(start, path);
1132 *(start + strlen(path)) = '\0';
1133 paths[count++] = start;
1135 strcat(newPath, path);
1139 if(pathOptions[PathOptions::AddMinGWPaths].selected)
1142 // Up to before Win32 APIs
1143 for(c = 0; c < 4 /*additional[c].name*/; c++)
1145 char path[MAX_LOCATION];
1147 additional[c].GetFullPath(path);
1148 PathCat(path, "bin");
1149 for(p = 0; p<count; p++)
1150 if(!fstrcmp(paths[p], path))
1158 strcat(newPath, ";");
1159 start = oldPath + strlen(paths[count-1])+1;
1164 strcpy(start, path);
1165 *(start + strlen(path)) = '\0';
1166 paths[count++] = start;
1168 strcat(newPath, path);
1175 void AssociateExtension(char * extension, char * description, char *name, char * action, char * path)
1181 RegCreateKeyEx(HKEY_CLASSES_ROOT, extension, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1182 RegSetValueEx(key, null, 0, REG_SZ, name, strlen(name)+1);
1185 RegCreateKeyEx(HKEY_CLASSES_ROOT, name, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1186 RegSetValueEx(key, null, 0, REG_SZ, description, strlen(description)+1);
1189 sprintf(keyName, "%s\\shell", extension);
1190 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1191 RegSetValueEx(key, null, 0, REG_SZ, action, strlen(action)+1);
1194 sprintf(keyName, "%s\\shell\\%s", name, action);
1195 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1198 sprintf(keyName, "%s\\shell\\%s\\command", name, action);
1199 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1201 sprintf(keyName, path);
1202 strcat(keyName, " \"%L\"");
1204 uint16 wKeyName[2048];
1205 UTF8toUTF16Buffer(keyName, wKeyName, sizeof(wKeyName) / sizeof(uint16));
1206 RegSetValueExW(key, null, 0, REG_SZ, (byte *)wKeyName, (wcslen(wKeyName) + 1)*sizeof(uint16));
1211 class InstallThread : Thread
1216 ((GuiApplication)__thisModule).Lock();
1217 installProgress.progressBar.range = totalSize;
1218 for(c = 0; components[c].name && !abortInstall; c++)
1219 components[c].Install(installDir);
1222 installProgress.progressBar.range = 0;
1223 installProgress.finish.Destroy(0);
1224 installProgress.cancel.text = $"Close";
1225 installProgress.cancel.isDefault = true;
1226 installProgress.cancel.disabled = false;
1227 installProgress.cancel.NotifyClicked = Window::ButtonCloseDialog;
1228 installProgress.installing.text = $"Installation Cancelled.";
1229 installProgress.title.text = $"Installation Cancelled";
1230 installProgress.titleInfo.contents = $"The installation was not completed.";
1235 char idePath[MAX_LOCATION];
1236 char userProfile[MAX_LOCATION];
1239 IDESettings settings = null; // Don't instantiate yet so we can pick up old settings
1241 IDESettingsContainer settingsContainer
1244 dataOwner = &settings;
1245 dataClass = class(IDESettings);
1247 CompilerConfig compiler;
1248 installProgress.installing.text = $"Configuring ECERE IDE...";
1249 ((GuiApplication)__thisModule).Unlock();
1250 ((GuiApplication)__thisModule).SignalEvent();
1252 settingsContainer.Load();
1253 compiler = settings.GetCompilerConfig(defaultCompilerName);
1256 for(c = 0; coreSDK[c].name; c++)
1258 char path[MAX_LOCATION];
1260 if(c == extras) continue;
1261 coreSDK[c].GetFullPath(path);
1262 if(c != ide && c != runtime && c != eda && c != ec && c != vanilla)
1263 PathCat(path, "bin");
1266 coreSDK[c].GetFullPath(idePath);
1267 PathCat(idePath, "IDE.exe");
1272 if(!compiler.executableDirs.Find(path))
1273 compiler.executableDirs.Add(CopyString(path));
1276 if(c == runtime || c == vanilla)
1278 if(!compiler.libraryDirs.Find(path))
1279 compiler.libraryDirs.Add(CopyString(path));
1283 // Up to before Win32 APIs
1284 for(c = 0; c < 4 /*additional[c].name*/; c++)
1286 char path[MAX_LOCATION];
1287 additional[c].GetFullPath(path);
1289 PathCat(path, "bin");
1290 if(!compiler.executableDirs.Find(path))
1291 compiler.executableDirs.Add(CopyString(path));
1296 char path[MAX_LOCATION] = "";
1297 if(components[samples].selected)
1298 components[samples].GetFullPath(path);
1300 components[coreSDK].GetFullPath(path);
1302 if(!settings.ideProjectFileDialogLocation)
1303 settings.ideProjectFileDialogLocation = path;
1304 if(!settings.ideFileDialogLocation)
1305 settings.ideFileDialogLocation = path;
1309 settingsContainer.Save();
1310 delete settingsContainer;
1313 // Set up Uninstaller
1314 ((GuiApplication)__thisModule).Lock();
1315 installProgress.installing.text = $"Registering uninstaller...";
1316 ((GuiApplication)__thisModule).Unlock();
1317 ((GuiApplication)__thisModule).SignalEvent();
1322 char * displayName = "ECERE SDK 0.44";
1323 char uninstaller[MAX_LOCATION];
1324 bool nomodify = true;
1326 strcpy(uninstaller, installDir);
1327 PathCat(uninstaller, "uninstall_ecere.exe");
1329 RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ECERE SDK", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1331 RegSetValueEx(key, "DisplayName", 0, REG_SZ, displayName, strlen(displayName)+1);
1332 RegSetValueEx(key, "UninstallString", 0, REG_SZ, uninstaller, strlen(uninstaller)+1);
1333 RegSetValueEx(key, "DisplayIcon", 0, REG_SZ, idePath, strlen(idePath)+1);
1334 //RegSetValueEx(key, "NoModify", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1335 //RegSetValueEx(key, "NoRepair", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1340 if(pathOptions[PathOptions::AddECEREPaths].selected
1342 || pathOptions[PathOptions::AddMinGWPaths].selected
1348 char path[2048] = "";
1351 ((GuiApplication)__thisModule).Lock();
1352 installProgress.installing.text = "Registering paths...";
1353 ((GuiApplication)__thisModule).Unlock();
1354 ((GuiApplication)__thisModule).SignalEvent();
1356 // if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Environment", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1358 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1359 // RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1360 if(status == REG_OPENED_EXISTING_KEY)
1362 size = sizeof(wPath);
1363 RegQueryValueExW(key, L"path", null, null, (byte *)wPath, &size);
1364 UTF16toUTF8Buffer(wPath, path, sizeof(path));
1367 UTF8toUTF16Buffer(path, wPath, sizeof(wPath) / sizeof(uint16));
1368 RegSetValueExW(key, L"path", 0, REG_EXPAND_SZ, (byte *)wPath, (wcslen(wPath)+1) * 2);
1371 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (int)"Environment", SMTO_NORMAL, 1000, NULL);
1374 // Install Program Group Icons
1375 // userProfile = getenv("USERPROFILE");
1376 GetEnvironment("USERPROFILE", userProfile, sizeof(userProfile));
1378 if(options[IconOptions::StartMenuIcon].selected)
1380 char destPath[MAX_LOCATION];
1381 char startMenuPath[MAX_LOCATION] = "";
1384 ((GuiApplication)__thisModule).Lock();
1385 installProgress.installing.text = $"Installing Start Menu Icons...";
1386 ((GuiApplication)__thisModule).Unlock();
1387 ((GuiApplication)__thisModule).SignalEvent();
1389 strcpy(destPath, userProfile);
1391 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1393 uint16 wStartMenuPath[2048];
1394 uint size = sizeof(wStartMenuPath);
1395 // RegQueryValueEx(key, "Start Menu", null, null, startMenuPath, &size);
1396 RegQueryValueExW(key, L"Programs", null, null, (byte *)wStartMenuPath, &size);
1397 UTF16toUTF8Buffer(wStartMenuPath, startMenuPath, sizeof(startMenuPath));
1400 if(!startMenuPath[0] && userProfile && userProfile[0])
1402 strcpy(startMenuPath, userProfile);
1403 PathCat(startMenuPath, "Start Menu\\Programs");
1406 if(startMenuPath[0])
1408 strcpy(destPath, startMenuPath);
1409 PathCat(destPath, "ECERE SDK");
1412 strcpy(destPath, startMenuPath);
1413 PathCat(destPath, "ECERE SDK\\ECERE IDE.lnk");
1414 CreateLink(idePath, destPath, null); //"ECERE IDE");
1415 if(components[samples].selected)
1417 char samplesPath[MAX_LOCATION] = "";
1418 components[samples].GetFullPath(samplesPath);
1420 strcpy(destPath, startMenuPath);
1421 PathCat(destPath, "ECERE SDK\\Sample Projects.lnk");
1422 CreateLink(samplesPath, destPath, null);//"Sample Projects");
1424 if(components[documentation].selected && documentation[ecereBook].selected)
1426 char docPath[MAX_LOCATION] = "";
1427 documentation[ecereBook].GetFullPath(docPath);
1428 PathCat(docPath, "Ecere Tao of Programming [work in progress].pdf");
1431 char tao[MAX_LOCATION] ;
1432 documentation[ecereBook].GetFullPath(tao);
1433 PathCat(tao, "tao.pdf");
1434 RenameFile(tao, docPath);
1437 strcpy(destPath, startMenuPath);
1438 PathCat(destPath, "ECERE SDK\\The Ecere Tao of Programming.lnk");
1439 CreateLink(docPath, destPath, null);
1444 // Install Desktop Icon
1445 if(options[IconOptions::DesktopIcon].selected)
1448 char desktopPath[MAX_LOCATION];
1450 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1452 uint16 wDesktopPath[MAX_LOCATION];
1453 uint size = sizeof(wDesktopPath);
1454 RegQueryValueExW(key, L"Desktop", null, null, (byte *)wDesktopPath, &size);
1455 UTF16toUTF8Buffer(wDesktopPath, desktopPath, sizeof(desktopPath));
1458 if(!desktopPath[0] && userProfile && userProfile[0])
1460 strcpy(desktopPath, userProfile);
1461 PathCat(desktopPath, "Desktop");
1466 PathCat(desktopPath, "ECERE IDE.lnk");
1468 ((GuiApplication)__thisModule).Lock();
1469 installProgress.installing.text = $"Installing Desktop Icon...";
1470 ((GuiApplication)__thisModule).Unlock();
1471 ((GuiApplication)__thisModule).SignalEvent();
1473 CreateLink(idePath, desktopPath, null);//"ECERE IDE");
1477 // Install QuickLaunch Icon
1478 if(options[IconOptions::QuickLaunchIcon].selected)
1480 char appData[MAX_LOCATION]; // = getenv("APPDATA");
1481 GetEnvironment("APPDATA", appData, sizeof(appData));
1483 if(appData && appData[0])
1485 char destPath[MAX_LOCATION];
1487 ((GuiApplication)__thisModule).Lock();
1488 installProgress.installing.text = $"Installing Quicklaunch Icon...";
1489 ((GuiApplication)__thisModule).Unlock();
1490 ((GuiApplication)__thisModule).SignalEvent();
1492 strcpy(destPath, appData);
1493 PathCat(destPath, "Microsoft\\Internet Explorer\\Quick Launch\\ECERE IDE.lnk");
1495 CreateLink(idePath, destPath, null);//"ECERE IDE");
1499 // Register File Types
1500 if(associateOptions[AssociateOptions::AssociateEPJ].selected ||
1501 associateOptions[AssociateOptions::AssociateEC].selected ||
1502 associateOptions[AssociateOptions::AssociateC].selected ||
1503 associateOptions[AssociateOptions::AssociateCPP].selected ||
1504 associateOptions[AssociateOptions::AssociateTXT].selected ||
1505 associateOptions[AssociateOptions::Associate3DS].selected ||
1506 associateOptions[AssociateOptions::AssociateIMG].selected)
1508 ((GuiApplication)__thisModule).Lock();
1509 installProgress.installing.text = $"Resgistering File Types...";
1510 ((GuiApplication)__thisModule).Unlock();
1511 ((GuiApplication)__thisModule).SignalEvent();
1513 if(associateOptions[AssociateOptions::AssociateEPJ].selected)
1515 AssociateExtension(".epj", "ECERE IDE Project", "epj_file", "Open", idePath);
1517 if(associateOptions[AssociateOptions::AssociateEC].selected)
1519 AssociateExtension(".ec", "eC Source File", "ec_file", "Open", idePath);
1520 AssociateExtension(".eh", "eC Header File", "eh_file", "Open", idePath);
1522 if(associateOptions[AssociateOptions::AssociateC].selected)
1524 AssociateExtension(".c", "C Source File", "c_file", "Open", idePath);
1525 AssociateExtension(".h", "C Header File", "h_file", "Open", idePath);
1527 if(associateOptions[AssociateOptions::AssociateCPP].selected)
1529 AssociateExtension(".cpp", "C++ Source File", "cpp_file", "Open", idePath);
1530 AssociateExtension(".cc", "C++ Source File", "cpp_file", "Open", idePath);
1531 AssociateExtension(".cxx", "C++ Source File", "cpp_file", "Open", idePath);
1532 AssociateExtension(".chh", "C++ Header File", "chh_file", "Open", idePath);
1533 AssociateExtension(".hh", "C++ Header File", "chh_file", "Open", idePath);
1534 AssociateExtension(".hxx", "C++ Header File", "chh_file", "Open", idePath);
1536 if(associateOptions[AssociateOptions::AssociateTXT].selected)
1538 AssociateExtension(".txt", "Text File", "txt_file", "Open", idePath);
1540 if(associateOptions[AssociateOptions::Associate3DS].selected)
1542 AssociateExtension(".3ds", "3D Studio Model", "3ds_file", "View", idePath);
1544 if(associateOptions[AssociateOptions::AssociateIMG].selected)
1546 AssociateExtension(".bmp", "BMP Image", "bmp_file", "View", idePath);
1547 AssociateExtension(".pcx", "PCX Image", "pcx_file", "View", idePath);
1548 AssociateExtension(".png", "PNG Image", "png_file", "View", idePath);
1549 AssociateExtension(".jpg", "JPEG Image", "jpg_file", "View", idePath);
1550 AssociateExtension(".jpeg", "JPEG Image", "jpg_file", "View", idePath);
1551 AssociateExtension(".gif", "GIF Image", "gif_file", "View", idePath);
1554 ((GuiApplication)__thisModule).Lock();
1556 installProgress.cancel.Destroy(0);
1557 installProgress.finish.text = $"Finish";
1558 installProgress.finish.disabled = false;
1559 installProgress.finish.Activate();
1560 installProgress.installing.text = $"Installation Complete.";
1561 installProgress.title.text = $"Installation Complete";
1562 installProgress.titleInfo.contents = $"Thank you for using the Ecere SDK.";
1564 ((GuiApplication)__thisModule).Unlock();