/* PowerComPress v1.0 Copyright (C) 2005 Jonas Gehring PowerComPress is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. PowerComPress is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with PowerComPress; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // C Source File // Created 29.08.2005; 18:30:08 #include #include #include #include "pcpress.h" #include "brieflz.h" #include "boolsoft.h" #include "advdialogs.h" #define MAX_READ_SIZE (32u*32u) typedef struct GroupHeader { unsigned long hcode; BOOL compressed; char varname[18]; long varsize; } GROUPHEADER; // Only for testing!!! void ShowHeader(GROUPHEADER header) { char msg[40]; // Initialize dialog AdvDlgInit(100, 58, "PowerComPress", B_ESC, B_OK, TRUE, save_int_1); // Add dialog elements sprintf(msg, "%lX", header.hcode); AdvDlgAdd(AD_TEXT, msg, NULL, 0, 0, 0, TXT_CENTERED); sprintf(msg, "%d", header.compressed); AdvDlgAdd(AD_TEXT, msg, NULL, 0, 0, 0, TXT_CENTERED); sprintf(msg, "%s", header.varname); AdvDlgAdd(AD_TEXT, msg, NULL, 0, 0, 0, TXT_CENTERED); sprintf(msg, "%ld", header.varsize); AdvDlgAdd(AD_TEXT, msg, NULL, 0, 0, 0, TXT_CENTERED); AdvDlgDo(); } // Restores a group file if somethin wrong was written in it BOOL RestoreGroup(char *groupname, fpos_t position) { FILE *group, *tempgroup; short data; unsigned long i = 0; SYM_ENTRY *sym; const char *tgrpname = "pcptgrp"; if (position <= 0) return TRUE; // Open files if ((group = fopen(groupname, "rb")) == NULL) return FALSE; if ((tempgroup = fopen(tgrpname, "wb")) == NULL) return FALSE; // Set up ProgressBar sym = SymFindPtr(SYMSTR(groupname), 0); AdvDlgProgressBar("PowerComPress", "Restoring GroupFile...", ((position+1) / MAX_READ_SIZE) + 1); // Restore to temporary variable do { i++; if (!(i%MAX_READ_SIZE)) AdvDlgProgressUp(); data = fgetc(group); fputc(data, tempgroup); } while (i < (position-4)); // Close files fclose(group); // Add the file ID tag fputc(0, tempgroup); fputs("PCP", tempgroup); fputc(0, tempgroup); fputc(OTH_TAG, tempgroup); fclose(tempgroup); // Delete original file SymDel(SYMSTR(groupname)); // Move temp file to group file SymMove(SYMSTR(tgrpname), SYMSTR(groupname)); return TRUE; } /* // Adds a compressed variable it to a .PCP-file short AddVarToGroup(char *varname, char *groupname) { FILE *var, *group; long groupsize; short act; BYTE *data = NULL, header[HEADER_SIZE];; unsigned char msg[40], type[4], tbuffer[20], ttbuffer[20]; BOOL compressed = TRUE; fpos_t pos; size_t readsize; GROUPHEADER gheader; ttbuffer[0] = 0; start: do { if (!isfolder) { // Initialize dialog AdvDlgInit(120, 70, "PowerComPress", B_ESC, B_OK, TRUE, save_int_1); sprintf(msg, "Add %s to", varname); // Add dialog elements AdvDlgAdd(AD_TEXT, msg, NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_INPUT, NULL, ttbuffer, 17, INPUT_STR, 0, 0); AdvDlgAdd(AD_NONE, NULL, NULL, 0, 0, 0, 0); AdvDlgAdd(AD_TEXT, "Options:", NULL, 0, 0, 0, TXT_STANDARD); sprintf(msg, "Delete %s", varname); AdvDlgAdd(AD_CHECKBOX, msg, NULL, 0, 0, options.AlwaysDelVar, 0); AdvDlgAdd(AD_CHECKBOX, "Archive GroupFile", NULL, 0, 0, options.AlwaysArcVar, 0); // Execute Dialog if (!AdvDlgDo()) { return REDRAW; } } else { strcpy(ttbuffer, groupname); break; } } while (!ttbuffer[0]); // The variable should be compressed to the folder if (strcspn(ttbuffer, append) == strlen(ttbuffer)) sprintf(tbuffer, "%s%c%s", folder, append[0], ttbuffer); else strcpy(tbuffer, ttbuffer); AdvDlgMessage("PowerComPress - Error", tbuffer, B_OK); if (!TestFolder(tbuffer)) { AdvDlgMessage("PowerComPress - Error", "Unable to open GroupFile", B_OK); SymDel(SYMSTR("pcptemp")); return REDRAW; } // Try to open group file if ((group = fopen(tbuffer, "wb")) == NULL) { AdvDlgMessage("PowerComPress - Error", "Invalid file name", B_OK); tbuffer[0] = 0; goto start; } fclose(group); // Determine the type VarTypeToStr(DerefSym(SymFind(SYMSTR(varname))), type); // Try to compress the file if (strncmp(type, ".pcp", 4)) { if ((act = compress_file(varname, "pcptemp")) == 1) { return REDRAW; } if (act == GRP_ADDUNCOMP) compressed = FALSE; else if (act == GRP_SKIP) return 1; } else { compressed = FALSE; } strcpy(gheader.varname, varname); if (compressed) strcpy(varname, "pcptemp"); // Unarchive goup file EM_moveSymFromExtMem(SYMSTR(tbuffer), HS_NULL); // Allocate space for reading if ((data = (BYTE *) malloc(MAX_READ_SIZE)) == NULL) { AdvDlgMessage("PowerComPress - Error", "Not enough memory", B_OK); return REDRAW; } // Does the variable exist? if ((var = fopen(varname, "rb")) == NULL) { AdvDlgMessage("PowerComPress - Error", "Unable to open input file", B_OK); free(data); return REDRAW; } // Set header values gheader.varsize = GetVarSize(SymFindPtr(SYMSTR(varname), 0)); gheader.hcode = 0x636C8F1A; gheader.compressed = compressed; // Determine size of the group file groupsize = GetVarSize(SymFindPtr(SYMSTR(tbuffer), 0)); // If the output file is too large for the file if ((gheader.varsize + groupsize) > UINT_MAX) { AdvDlgMessage("PowerComPress - Error", "Max. file size reached", B_OK); free(data); SymDel(SYMSTR("pcptemp")); return REDRAW; } Open GroupFiles if (SymFind(SYMSTR( { } else { return FALSE; } // Open group file if ((group = fopen(tbuffer, "a+b")) != NULL) { // Save file position fgetpos(group, &pos); Wait(1); // Write header to group file fwrite(&gheader, 1, sizeof(GROUPHEADER), group); // Initialize ProgressBar sprintf(msg, "Adding %s...", gheader.varname); AdvDlgProgressBar("PowerComPress", msg, gheader.varsize / MAX_READ_SIZE + 1); // Add data from variable to group while ((readsize = fread(data, 1, MAX_READ_SIZE, var)) > 0) { AdvDlgProgressUp(); if (fwrite(data, 1, readsize, group) != readsize) { AdvDlgMessage("PowerComPress - Error", "Unable to write data", B_OK); fclose(var); fclose(group); free(data); SymDel(SYMSTR("pcptemp")); //RestoreGroup(tbuffer, pos); return REDRAW; } } } else { AdvDlgMessage("PowerComPress - Error", "Unable to open GroupFile", B_OK); fclose(var); fclose(group); free(data); SymDel(SYMSTR("pcptemp")); return REDRAW; } if (!isfolder) { // Add the file ID tag fputc(0, group); fputs("PCP", group); fputc(0, group); fputc(OTH_TAG, group); } // Close files fclose(group); fclose(var); // Delete temporary file SymDel(SYMSTR("pcptemp")); // Free pointer free(data); // Archive group file if needed if (!isfolder && AD_CHECKED[1]) EM_moveSymToExtMem(SYMSTR(tbuffer), HS_NULL); if (AD_CHECKED[0]) { EM_moveSymFromExtMem(SYMSTR(gheader.varname), HS_NULL); SymDel(SYMSTR(gheader.varname)); } return REDRAW; }*/ // Extracts a variable from a .PCP-file short ExtractGroup(const char *groupname) { FILE *var, *group; BYTE data; unsigned char msg[40], outfile[20]; GROUPHEADER gheader; long i; BOOL archived = FALSE; // Initialize dialog AdvDlgInit(100, 60, "PowerComPress", B_ESC, B_OK, TRUE, save_int_1); sprintf(msg, "Extract %s", groupname); // Add dialog elements AdvDlgAdd(AD_TEXT, msg, NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_NONE, NULL, NULL, 0, 0, 0, 0); AdvDlgAdd(AD_TEXT, "Options:", NULL, 0, 0, 0, TXT_STANDARD); sprintf(msg, "Delete %s", groupname); AdvDlgAdd(AD_CHECKBOX, msg, NULL, 0, 0, FALSE, 0); AdvDlgAdd(AD_CHECKBOX, "Archive output files", NULL, 0, 0, TRUE, 0); // Execute Dialog if (!AdvDlgDo()) { return REDRAW; } // Ceck if group file is archived if (DerefSym(SymFind(SYMSTR(groupname)))->flags.bits.archived) { // Unarchive group file EM_moveSymFromExtMem(SYMSTR(groupname), HS_NULL); archived = TRUE; } // Open group file if ((group = fopen(groupname, "rb")) == NULL) { AdvDlgMessage("PowerComPress - Error", "Unable to open GroupFile", B_OK); return REDRAW; } // Start extracting while (fread(&gheader, 1, sizeof(GROUPHEADER), group) == sizeof(GROUPHEADER)) { #ifdef DEBUG ShowHeader(gheader); #endif if (gheader.compressed) strcpy(outfile, "pcptemp"); else strcpy(outfile, gheader.varname); // Check header code if (gheader.hcode != 0x636C8F1A) { fclose(group); AdvDlgMessage("PowerComPress - Error", "File is not valid", B_OK); return REDRAW; } if (!TestFolder(gheader.varname)) { fclose(group); AdvDlgMessage("PowerComPress - Error", "Unable to open output file", B_OK); return REDRAW; } // Memory check if (HeapAvail() < gheader.varsize) { fclose(group); AdvDlgMessage("PowerComPress - Error", "Not enough memory", B_OK); return REDRAW; } sprintf(msg, "Extr. %s...", gheader.varname); AdvDlgProgressBar("PowerCompress", msg, (gheader.varsize / (MAX_READ_SIZE)) +1); // Test output file if ((var = fopen(gheader.varname, "wb")) == NULL) { // Ask to skip file AdvDlgInit(110, 45, "PowerComPress", B_NONE, B_NONE, TRUE, save_int_1); AdvDlgAdd(AD_TEXT, "Unable to extract", NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_TEXT, gheader.varname, NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_TEXT, "[ENTER] = Skip file", NULL, 0, 0, 0, TXT_STANDARD); AdvDlgAdd(AD_TEXT, "[ESC] = Cancel action", NULL, 0, 0, 0, TXT_STANDARD); if (AdvDlgDo()) { fseek(group, gheader.varsize, SEEK_CUR); continue; } fclose(group); SymDel(SYMSTR("pcptemp")); return REDRAW; } fclose(var); // Open file for writing if ((var = fopen(outfile, "wb")) == NULL) { AdvDlgMessage("PowerComPress - Error", "Unable to extract file", B_OK); fclose(group); SymDel(SYMSTR("pcptemp")); return REDRAW; } // Write data from group to variable for (i = 0; i < gheader.varsize; i++) { // Get data data = fgetc(group); if (!(i%MAX_READ_SIZE)) AdvDlgProgressUp(); // Write data if ((fputc(data, var)) != data) { AdvDlgMessage("PowerComPress - Error", "Unable to write data", B_OK); fclose(var); fclose(group); SymDel(SYMSTR("pcptemp")); return REDRAW; } } fclose(var); /*if (gheader.compressed) { if (decompress_file("pcptemp", gheader.varname)) { fclose(group); SymDel(SYMSTR("pcptemp")); return REDRAW; } }*/ // Archive file if needed if (AD_CHECKED[1]) EM_moveSymToExtMem(SYMSTR(gheader.varname), HS_NULL); } fclose(group); // Delete temporary file SymDel(SYMSTR("pcptemp")); // Delete group file if needed if (AD_CHECKED[0]) SymDel(SYMSTR(groupname)); else if (!AD_CHECKED[0] && archived) EM_moveSymToExtMem(SYMSTR(groupname), HS_NULL); return REDRAW; } // View the contents of a GroupFile short ViewGroupFile(SYM_ENTRY *group) { return TRUE; }