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];
217 const char * directory;
220 SplitArchivePath(path, string, &directory);
226 strcpy(string, directory);
227 if(!strcmp(directory, "/") || !strcmp(directory, "\\"))
228 strcpy(string, DIR_SEPS);
230 strcat(string, DIR_SEPS);
232 FileGetStats(path, &stats);
234 row = viewList.AddRow();
235 row.SetData(nameField, string);
236 row.SetData(sizeField, 0);
238 TimeStamp m = stats.modified.local, c = stats.created.local;
239 row.SetData(mField, m);//(void *)stats.modified.local); // .local was missing here
240 row.SetData(cField, c);//(void *)stats.created.local);
244 while(listing.Find())
246 if(strcmp(listing.path, "<:>ecere"))
248 strcpy(string, directory);
251 if(!strcmp(directory, "/") || !strcmp(directory, "\\"))
252 strcpy(string, DIR_SEPS);
254 strcat(string, DIR_SEPS);
256 PathCat(string, listing.name);
257 if(listing.stats.attribs.isDirectory)
258 ViewArchive(listing.path);
261 row = viewList.AddRow();
262 row.SetData(nameField, string);
263 row.SetData(sizeField, listing.stats.size);
265 TimeStamp m = listing.stats.modified.local, c = listing.stats.created.local;
266 row.SetData(mField, m);//(void *)listing.stats.modified.local);
267 row.SetData(cField, c);//(void *)listing.stats.created.local);
276 viewList.AddField(nameField);
277 viewList.AddField(sizeField);
278 viewList.AddField(mField);
279 viewList.AddField(cField);
281 ViewArchive(archivePath);
286 class SelfExtractApp : GuiApplication
296 strcpy(archive, argv[1]);
297 sprintf(archivePath, "<%s>", archive);
298 sprintf(title, $"ECERE Archive - %s", argv[1]);
302 strcpy(archive, ":");
303 strcpy(archivePath, ":");
304 strcpy(title, $"ECERE Self-Extractable Archive");
307 SetLoggingMode(stdOut, null);
308 SelfExtract { text = title };
310 GuiApplication::Main();