7 static char archivePath[MAX_LOCATION], archive[MAX_LOCATION];
9 #define BUFFERSIZE 0x10000
11 void ExtractFileFromArchive(ProgressBar progressBar, const char * path, const char * outputFile)
13 char fileName[MAX_LOCATION];
14 FileAttribs exists = FileExists(path);
18 if(exists.isDirectory)
20 FileListing listing { path };
24 if(MakeDir(outputFile))
27 FileGetStats(path, &stats);
33 if(strcmp(listing.path, "<:>ecere"))
35 strcpy(fileName, outputFile);
37 // Tweak file name if out
40 if(!strcmp(fileName, ".")) fileName[0] = '\0';
41 if(listing.name[0] == '/' || listing.name[0] == '\\')
43 char * afterSlash, rest[MAX_LOCATION];
44 for(afterSlash = fileName; *afterSlash == '/' || *afterSlash == '\\'; afterSlash++);
45 strcpy(rest, afterSlash);
46 PathCat(fileName, "_root");
47 PathCat(fileName, rest);
49 else if(listing.name[1] == ':')
52 sprintf(letter, "_%cdrive", toupper(listing.name[0]));
53 PathCat(fileName, letter);
54 PathCat(fileName, listing.name[2] ? (listing.name + 3) : (listing.name + 2));
57 PathCat(fileName, listing.name);
60 PathCat(fileName, listing.name);
61 if(!strcmp(fileName, "/") || !strcmp(fileName, "\\"))
62 strcpy(fileName, DIR_SEPS);
63 ExtractFileFromArchive(progressBar, listing.path, fileName);
69 File input = FileOpen(path, read);
72 File output = FileOpen(outputFile, write);
75 char fileName[MAX_FILENAME];
76 uint position = progressBar.progress;
79 byte buffer[BUFFERSIZE];
81 FileGetSize(path, &dataSize);
82 GetLastDirectory(outputFile, fileName);
83 progressBar.statusBar.SetText($"Extracting %s...", fileName);
87 for(c = 0; c<dataSize; c += BUFFERSIZE)
89 uint size = (dataSize > c + BUFFERSIZE) ? BUFFERSIZE : (dataSize - c);
90 input.Read(buffer, 1, size);
91 output.Write(buffer, 1, size);
93 progressBar.progress = position + c + size;
98 FileGetStats(path, &stats);
104 FileSetTime(outputFile, stats.created, 0, stats.modified);
107 class SelfExtract : Window
109 background = activeBorder;
111 minClientSize = Size { 500, 112 };
114 size = Size { 506, 138 };
115 anchor = Anchor { vert = -0.15 };
117 Button view { this, text = $"View Files", anchor = Anchor { right = 100, top = 70 }, size = Size { 100 }, hotKey = altV, NotifyClicked = ViewClicked };
120 this, isCheckbox = true, text = $"Use paths from archive...", position = Point { 10,70 }, hotKey = altU, checked = true;
122 bool NotifyClicked(Button control, int x, int y, Modifiers mods)
126 browse.disabled = true;
127 where.disabled = true;
131 browse.disabled = false;
132 where.disabled = false;
134 whereLabel.Update(null); // Is this still needed?
138 EditBox where { this, text = $"Extract to", anchor = Anchor { left = 10, top = 40, right = 100 }, size = Size { h = 22 }, hotKey = altT, disabled = true };
139 Label whereLabel { this, position = Point { 10,20 }, labeledWindow = where };
142 this, text = $"Browse...", anchor = Anchor { right = 10, top = 40 }, size = Size { 80 }, hotKey = altB, disabled = true;
144 bool NotifyClicked(Button control, int x, int y, Modifiers mods)
146 fileDialog.currentDirectory = where.contents;
147 if(fileDialog.Modal() == ok)
148 where.contents = fileDialog.filePath;
152 Button close { this, text = $"Exit", anchor = Anchor { right = 10, top = 70 }, size = Size { 80 }, hotKey = altX, NotifyClicked = ButtonCloseDialog };
155 this, isDefault = true, text = $"Extract", anchor = Anchor { right = 10, top = 10 }, size = Size { 80 }, hotKey = altE;
157 bool NotifyClicked(Button control, int x, int y, Modifiers mods)
160 ProgressBar progressBar { master = this, isModal = true, borderStyle = fixed, hasStatusBar = true, text = $"Extracting Files...", clientSize = Size { 400, 40 } };
162 ArchiveQuerySize(archive, &totalSize);
163 progressBar.range = totalSize;
168 ExtractFileFromArchive(progressBar, archivePath, "");
171 char output[MAX_LOCATION];
172 TrimLSpaces(where.contents, output);
173 TrimRSpaces(output, output);
174 if(!output[0]) strcpy(output, ".");
175 ExtractFileFromArchive(progressBar, archivePath, output);
177 MessageBox { master = progressBar, text = $"Done.", contents = $"Extraction Completed" }.Modal();
178 progressBar.Destroy(0);
182 ListBox viewList { this, hasHeader = true, borderStyle = deep, hasHorzScroll = true, hasVertScroll = true, anchor = Anchor { left = 10, top = 112, right = 10,bottom = 10 } };
183 DataField nameField { header = $"File", width = 360 };
184 DataField sizeField { dataType = "FileSize", header = $"Size", width = 96 };
185 DataField mField { dataType = "TimeStamp", header = $"Modified", width = 216 };
186 DataField cField {dataType = "TimeStamp", header = $"Created", width = 216 };
187 FileDialog fileDialog { master = this, type = selectDir, text = $"Select extraction directory" };
189 bool HideClicked(Button control, int x, int y, Modifiers mods)
192 viewList.visible = false;
195 view.text = $"View Files";
197 view.NotifyClicked = ViewClicked;
201 bool ViewClicked(Button control, int x, int y, Modifiers mods)
203 borderStyle = sizable;
206 viewList.visible = true;
207 view.text = $"Hide Files";
209 view.NotifyClicked = HideClicked;
213 void ViewArchive(const char * path)
215 FileListing listing { path };
216 char string[MAX_LOCATION], * directory;
219 SplitArchivePath(path, string, &directory);
225 strcpy(string, directory);
226 if(!strcmp(directory, "/") || !strcmp(directory, "\\"))
227 strcpy(string, DIR_SEPS);
229 strcat(string, DIR_SEPS);
231 FileGetStats(path, &stats);
233 row = viewList.AddRow();
234 row.SetData(nameField, string);
235 row.SetData(sizeField, 0);
237 TimeStamp m = stats.modified.local, c = stats.created.local;
238 row.SetData(mField, m);//(void *)stats.modified.local); // .local was missing here
239 row.SetData(cField, c);//(void *)stats.created.local);
243 while(listing.Find())
245 if(strcmp(listing.path, "<:>ecere"))
247 strcpy(string, directory);
250 if(!strcmp(directory, "/") || !strcmp(directory, "\\"))
251 strcpy(string, DIR_SEPS);
253 strcat(string, DIR_SEPS);
255 PathCat(string, listing.name);
256 if(listing.stats.attribs.isDirectory)
257 ViewArchive(listing.path);
260 row = viewList.AddRow();
261 row.SetData(nameField, string);
262 row.SetData(sizeField, listing.stats.size);
264 TimeStamp m = listing.stats.modified.local, c = listing.stats.created.local;
265 row.SetData(mField, m);//(void *)listing.stats.modified.local);
266 row.SetData(cField, c);//(void *)listing.stats.created.local);
275 viewList.AddField(nameField);
276 viewList.AddField(sizeField);
277 viewList.AddField(mField);
278 viewList.AddField(cField);
280 ViewArchive(archivePath);
285 class SelfExtractApp : GuiApplication
295 strcpy(archive, argv[1]);
296 sprintf(archivePath, "<%s>", archive);
297 sprintf(title, $"ECERE Archive - %s", argv[1]);
301 strcpy(archive, ":");
302 strcpy(archivePath, ":");
303 strcpy(title, $"ECERE Self-Extractable Archive");
306 SetLoggingMode(stdOut, null);
307 SelfExtract { text = title };
309 GuiApplication::Main();