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; 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", 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/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 for(c = 0; additional[c].name; c++)
1144 char path[MAX_LOCATION];
1146 additional[c].GetFullPath(path);
1147 PathCat(path, "bin");
1148 for(p = 0; p<count; p++)
1149 if(!fstrcmp(paths[p], path))
1157 strcat(newPath, ";");
1158 start = oldPath + strlen(paths[count-1])+1;
1163 strcpy(start, path);
1164 *(start + strlen(path)) = '\0';
1165 paths[count++] = start;
1167 strcat(newPath, path);
1174 void AssociateExtension(char * extension, char * description, char *name, char * action, char * path)
1180 RegCreateKeyEx(HKEY_CLASSES_ROOT, extension, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1181 RegSetValueEx(key, null, 0, REG_SZ, name, strlen(name)+1);
1184 RegCreateKeyEx(HKEY_CLASSES_ROOT, name, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1185 RegSetValueEx(key, null, 0, REG_SZ, description, strlen(description)+1);
1188 sprintf(keyName, "%s\\shell", extension);
1189 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1190 RegSetValueEx(key, null, 0, REG_SZ, action, strlen(action)+1);
1193 sprintf(keyName, "%s\\shell\\%s", name, action);
1194 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1197 sprintf(keyName, "%s\\shell\\%s\\command", name, action);
1198 RegCreateKeyEx(HKEY_CLASSES_ROOT, keyName, 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1200 sprintf(keyName, path);
1201 strcat(keyName, " \"%L\"");
1203 uint16 wKeyName[2048];
1204 UTF8toUTF16Buffer(keyName, wKeyName, sizeof(wKeyName) / sizeof(uint16));
1205 RegSetValueExW(key, null, 0, REG_SZ, (byte *)wKeyName, (wcslen(wKeyName) + 1)*sizeof(uint16));
1210 class InstallThread : Thread
1215 ((GuiApplication)__thisModule).Lock();
1216 installProgress.progressBar.range = totalSize;
1217 for(c = 0; components[c].name && !abortInstall; c++)
1218 components[c].Install(installDir);
1221 installProgress.progressBar.range = 0;
1222 installProgress.finish.Destroy(0);
1223 installProgress.cancel.text = $"Close";
1224 installProgress.cancel.isDefault = true;
1225 installProgress.cancel.disabled = false;
1226 installProgress.cancel.NotifyClicked = Window::ButtonCloseDialog;
1227 installProgress.installing.text = $"Installation Cancelled.";
1228 installProgress.title.text = $"Installation Cancelled";
1229 installProgress.titleInfo.contents = $"The installation was not completed.";
1234 char idePath[MAX_LOCATION];
1235 char userProfile[MAX_LOCATION];
1238 GlobalSettings settings
1242 installProgress.installing.text = $"Configuring ECERE IDE...";
1243 ((GuiApplication)__thisModule).Unlock();
1244 ((GuiApplication)__thisModule).SignalEvent();
1247 for(c = 0; coreSDK[c].name; c++)
1249 char path[MAX_LOCATION];
1251 coreSDK[c].GetFullPath(path);
1252 if(c != ide && c != runtime && c != eda && c != ec)
1253 PathCat(path, "bin");
1256 coreSDK[c].GetFullPath(idePath);
1257 PathCat(idePath, "IDE.exe");
1260 // TODO: Update This!
1262 for(item = settings.systemDirs[executables].first; item; item = item.next)
1263 if(!fstrcmp(item.name, path))
1267 settings.systemDirs[executables].Add(NamedItem { name = CopyString(path); });
1272 for(item = settings.systemDirs[libraries].first; item; item = item.next)
1273 if(!fstrcmp(item.name, path))
1277 settings.systemDirs[libraries].Add(NamedItem { name = CopyString(path); });
1284 for(c = 0; additional[c].name; c++)
1286 char path[MAX_LOCATION];
1288 additional[c].GetFullPath(path);
1289 PathCat(path, "bin");
1290 for(item = settings.systemDirs[executables].first; item; item = item.next)
1291 if(!fstrcmp(item.name, path))
1295 settings.systemDirs[executables].Add(NamedItem { name = CopyString(path); });
1302 char path[MAX_LOCATION] = "";
1303 if(components[samples].selected)
1304 components[samples].GetFullPath(path);
1306 components[coreSDK].GetFullPath(path);
1307 /* TODO: Update This!
1308 if(!settings.ideProjectFileDialogLocation)
1309 settings.ideProjectFileDialogLocation = path;
1310 if(!settings.ideFileDialogLocation)
1311 settings.ideFileDialogLocation = path;
1318 // Set up Uninstaller
1319 ((GuiApplication)__thisModule).Lock();
1320 installProgress.installing.text = $"Registering uninstaller...";
1321 ((GuiApplication)__thisModule).Unlock();
1322 ((GuiApplication)__thisModule).SignalEvent();
1327 char * displayName = "ECERE SDK 0.44";
1328 char uninstaller[MAX_LOCATION];
1329 bool nomodify = true;
1331 strcpy(uninstaller, installDir);
1332 PathCat(uninstaller, "uninstall_ecere.exe");
1334 RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\ECERE SDK", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1336 RegSetValueEx(key, "DisplayName", 0, REG_SZ, displayName, strlen(displayName)+1);
1337 RegSetValueEx(key, "UninstallString", 0, REG_SZ, uninstaller, strlen(uninstaller)+1);
1338 RegSetValueEx(key, "DisplayIcon", 0, REG_SZ, idePath, strlen(idePath)+1);
1339 //RegSetValueEx(key, "NoModify", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1340 //RegSetValueEx(key, "NoRepair", 0, REG_DWORD, (byte *)&nomodify, sizeof(nomodify));
1345 if(pathOptions[PathOptions::AddECEREPaths].selected
1347 || pathOptions[PathOptions::AddMinGWPaths].selected
1353 char path[2048] = "";
1356 ((GuiApplication)__thisModule).Lock();
1357 installProgress.installing.text = "Registering paths...";
1358 ((GuiApplication)__thisModule).Unlock();
1359 ((GuiApplication)__thisModule).SignalEvent();
1361 // if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Environment", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1363 RegCreateKeyEx(HKEY_CURRENT_USER, "Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1364 // RegCreateKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", 0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, null, &key, &status);
1365 if(status == REG_OPENED_EXISTING_KEY)
1367 size = sizeof(wPath);
1368 RegQueryValueExW(key, L"path", null, null, (byte *)wPath, &size);
1369 UTF16toUTF8Buffer(wPath, path, sizeof(path));
1372 UTF8toUTF16Buffer(path, wPath, sizeof(wPath) / sizeof(uint16));
1373 RegSetValueExW(key, L"path", 0, REG_EXPAND_SZ, (byte *)wPath, (wcslen(wPath)+1) * 2);
1376 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (int)"Environment", SMTO_NORMAL, 1000, NULL);
1379 // Install Program Group Icons
1380 // userProfile = getenv("USERPROFILE");
1381 GetEnvironment("USERPROFILE", userProfile, sizeof(userProfile));
1383 if(options[IconOptions::StartMenuIcon].selected)
1385 char destPath[MAX_LOCATION];
1386 char startMenuPath[MAX_LOCATION] = "";
1389 ((GuiApplication)__thisModule).Lock();
1390 installProgress.installing.text = $"Installing Start Menu Icons...";
1391 ((GuiApplication)__thisModule).Unlock();
1392 ((GuiApplication)__thisModule).SignalEvent();
1394 strcpy(destPath, userProfile);
1396 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1398 uint16 wStartMenuPath[2048];
1399 uint size = sizeof(wStartMenuPath);
1400 // RegQueryValueEx(key, "Start Menu", null, null, startMenuPath, &size);
1401 RegQueryValueExW(key, L"Programs", null, null, (byte *)wStartMenuPath, &size);
1402 UTF16toUTF8Buffer(wStartMenuPath, startMenuPath, sizeof(startMenuPath));
1405 if(!startMenuPath[0] && userProfile && userProfile[0])
1407 strcpy(startMenuPath, userProfile);
1408 PathCat(startMenuPath, "Start Menu\\Programs");
1411 if(startMenuPath[0])
1413 strcpy(destPath, startMenuPath);
1414 PathCat(destPath, "ECERE SDK");
1417 strcpy(destPath, startMenuPath);
1418 PathCat(destPath, "ECERE SDK\\ECERE IDE.lnk");
1419 CreateLink(idePath, destPath, null); //"ECERE IDE");
1420 if(components[samples].selected)
1422 char samplesPath[MAX_LOCATION] = "";
1423 components[samples].GetFullPath(samplesPath);
1425 strcpy(destPath, startMenuPath);
1426 PathCat(destPath, "ECERE SDK\\Sample Projects.lnk");
1427 CreateLink(samplesPath, destPath, null);//"Sample Projects");
1429 if(components[documentation].selected && documentation[ecereBook].selected)
1431 char docPath[MAX_LOCATION] = "";
1432 documentation[ecereBook].GetFullPath(docPath);
1433 PathCat(docPath, "Ecere Tao of Programming [work in progress].pdf");
1435 strcpy(destPath, startMenuPath);
1436 PathCat(destPath, "ECERE SDK\\The Ecere Tao of Programming.lnk");
1437 CreateLink(docPath, destPath, null);
1442 // Install Desktop Icon
1443 if(options[IconOptions::DesktopIcon].selected)
1446 char desktopPath[MAX_LOCATION];
1448 if(RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS)
1450 uint16 wDesktopPath[MAX_LOCATION];
1451 uint size = sizeof(wDesktopPath);
1452 RegQueryValueExW(key, L"Desktop", null, null, (byte *)wDesktopPath, &size);
1453 UTF16toUTF8Buffer(wDesktopPath, desktopPath, sizeof(desktopPath));
1456 if(!desktopPath[0] && userProfile && userProfile[0])
1458 strcpy(desktopPath, userProfile);
1459 PathCat(desktopPath, "Desktop");
1464 PathCat(desktopPath, "ECERE IDE.lnk");
1466 ((GuiApplication)__thisModule).Lock();
1467 installProgress.installing.text = $"Installing Desktop Icon...";
1468 ((GuiApplication)__thisModule).Unlock();
1469 ((GuiApplication)__thisModule).SignalEvent();
1471 CreateLink(idePath, desktopPath, null);//"ECERE IDE");
1475 // Install QuickLaunch Icon
1476 if(options[IconOptions::QuickLaunchIcon].selected)
1478 char appData[MAX_LOCATION]; // = getenv("APPDATA");
1479 GetEnvironment("APPDATA", appData, sizeof(appData));
1481 if(appData && appData[0])
1483 char destPath[MAX_LOCATION];
1485 ((GuiApplication)__thisModule).Lock();
1486 installProgress.installing.text = $"Installing Quicklaunch Icon...";
1487 ((GuiApplication)__thisModule).Unlock();
1488 ((GuiApplication)__thisModule).SignalEvent();
1490 strcpy(destPath, appData);
1491 PathCat(destPath, "Microsoft\\Internet Explorer\\Quick Launch\\ECERE IDE.lnk");
1493 CreateLink(idePath, destPath, null);//"ECERE IDE");
1497 // Register File Types
1498 if(associateOptions[AssociateOptions::AssociateEPJ].selected ||
1499 associateOptions[AssociateOptions::AssociateEC].selected ||
1500 associateOptions[AssociateOptions::AssociateC].selected ||
1501 associateOptions[AssociateOptions::AssociateCPP].selected ||
1502 associateOptions[AssociateOptions::AssociateTXT].selected ||
1503 associateOptions[AssociateOptions::Associate3DS].selected ||
1504 associateOptions[AssociateOptions::AssociateIMG].selected)
1506 ((GuiApplication)__thisModule).Lock();
1507 installProgress.installing.text = $"Resgistering File Types...";
1508 ((GuiApplication)__thisModule).Unlock();
1509 ((GuiApplication)__thisModule).SignalEvent();
1511 if(associateOptions[AssociateOptions::AssociateEPJ].selected)
1513 AssociateExtension(".epj", "ECERE IDE Project", "epj_file", "Open", idePath);
1515 if(associateOptions[AssociateOptions::AssociateEC].selected)
1517 AssociateExtension(".ec", "eC Source File", "ec_file", "Open", idePath);
1518 AssociateExtension(".eh", "eC Header File", "eh_file", "Open", idePath);
1520 if(associateOptions[AssociateOptions::AssociateC].selected)
1522 AssociateExtension(".c", "C Source File", "c_file", "Open", idePath);
1523 AssociateExtension(".h", "C Header File", "h_file", "Open", idePath);
1525 if(associateOptions[AssociateOptions::AssociateCPP].selected)
1527 AssociateExtension(".cpp", "C++ Source File", "cpp_file", "Open", idePath);
1528 AssociateExtension(".cc", "C++ Source File", "cpp_file", "Open", idePath);
1529 AssociateExtension(".cxx", "C++ Source File", "cpp_file", "Open", idePath);
1530 AssociateExtension(".chh", "C++ Header File", "chh_file", "Open", idePath);
1531 AssociateExtension(".hh", "C++ Header File", "chh_file", "Open", idePath);
1532 AssociateExtension(".hxx", "C++ Header File", "chh_file", "Open", idePath);
1534 if(associateOptions[AssociateOptions::AssociateTXT].selected)
1536 AssociateExtension(".txt", "Text File", "txt_file", "Open", idePath);
1538 if(associateOptions[AssociateOptions::Associate3DS].selected)
1540 AssociateExtension(".3ds", "3D Studio Model", "3ds_file", "View", idePath);
1542 if(associateOptions[AssociateOptions::AssociateIMG].selected)
1544 AssociateExtension(".bmp", "BMP Image", "bmp_file", "View", idePath);
1545 AssociateExtension(".pcx", "PCX Image", "pcx_file", "View", idePath);
1546 AssociateExtension(".png", "PNG Image", "png_file", "View", idePath);
1547 AssociateExtension(".jpg", "JPEG Image", "jpg_file", "View", idePath);
1548 AssociateExtension(".jpeg", "JPEG Image", "jpg_file", "View", idePath);
1549 AssociateExtension(".gif", "GIF Image", "gif_file", "View", idePath);
1552 ((GuiApplication)__thisModule).Lock();
1554 installProgress.cancel.Destroy(0);
1555 installProgress.finish.text = $"Finish";
1556 installProgress.finish.disabled = false;
1557 installProgress.finish.Activate();
1558 installProgress.installing.text = $"Installation Complete.";
1559 installProgress.title.text = $"Installation Complete";
1560 installProgress.titleInfo.contents = $"Thank you for using the Ecere SDK.";
1562 ((GuiApplication)__thisModule).Unlock();