diff --git a/app/ACUArchive.cpp b/app/ACUArchive.cpp index a956266..530b3ad 100644 --- a/app/ACUArchive.cpp +++ b/app/ACUArchive.cpp @@ -11,17 +11,17 @@ */ #include "stdafx.h" #include "ACUArchive.h" -#include "NufxArchive.h" // uses NuError +#include "NufxArchive.h" // uses NuError #include "Preferences.h" #include "Main.h" #include "Squeeze.h" #include /* -+00 2b Number of items in archive -+02 2b 0100 -+04 5b "fZink" -+09 11b 0136 0000 0000 0000 0000 dd ++00 2b Number of items in archive ++02 2b 0100 ++04 5b "fZink" ++09 11b 0136 0000 0000 0000 0000 dd +14 @@ -54,7 +54,7 @@ /* * =========================================================================== - * AcuEntry + * AcuEntry * =========================================================================== */ @@ -76,127 +76,127 @@ */ int AcuEntry::ExtractThreadToBuffer(int which, char** ppText, long* pLength, - CString* pErrMsg) const + CString* pErrMsg) const { - NuError nerr; - ExpandBuffer expBuf; - char* dataBuf = nil; - long len; - bool needAlloc = true; - int result = -1; + NuError nerr; + ExpandBuffer expBuf; + char* dataBuf = nil; + long len; + bool needAlloc = true; + int result = -1; - ASSERT(fpArchive != nil); - ASSERT(fpArchive->fFp != nil); + ASSERT(fpArchive != nil); + ASSERT(fpArchive->fFp != nil); - if (*ppText != nil) - needAlloc = false; + if (*ppText != nil) + needAlloc = false; - if (which != kDataThread) { - *pErrMsg = "No such fork"; - goto bail; - } + if (which != kDataThread) { + *pErrMsg = "No such fork"; + goto bail; + } - len = (long) GetUncompressedLen(); - if (len == 0) { - if (needAlloc) { - *ppText = new char[1]; - **ppText = '\0'; - } - *pLength = 0; - result = IDOK; - goto bail; - } + len = (long) GetUncompressedLen(); + if (len == 0) { + if (needAlloc) { + *ppText = new char[1]; + **ppText = '\0'; + } + *pLength = 0; + result = IDOK; + goto bail; + } - SET_PROGRESS_BEGIN(); + SET_PROGRESS_BEGIN(); - errno = 0; - if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) { - pErrMsg->Format("Unable to seek to offset %ld: %s", - fOffset, strerror(errno)); - goto bail; - } + errno = 0; + if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) { + pErrMsg->Format("Unable to seek to offset %ld: %s", + fOffset, strerror(errno)); + goto bail; + } - if (GetSqueezed()) { - nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetCompressedLen(), - &expBuf, false, 0); - if (nerr != kNuErrNone) { - pErrMsg->Format("File read failed: %s", NuStrError(nerr)); - goto bail; - } + if (GetSqueezed()) { + nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetCompressedLen(), + &expBuf, false, 0); + if (nerr != kNuErrNone) { + pErrMsg->Format("File read failed: %s", NuStrError(nerr)); + goto bail; + } - char* unsqBuf = nil; - long unsqLen = 0; - expBuf.SeizeBuffer(&unsqBuf, &unsqLen); - WMSG2("Unsqueezed %ld bytes to %d\n", - (unsigned long) GetCompressedLen(), unsqLen); - if (unsqLen == 0) { - // some bonehead squeezed a zero-length file - delete[] unsqBuf; - ASSERT(*ppText == nil); - WMSG0("Handling zero-length squeezed file!\n"); - if (needAlloc) { - *ppText = new char[1]; - **ppText = '\0'; - } - *pLength = 0; - } else { - if (needAlloc) { - /* just use the seized buffer */ - *ppText = unsqBuf; - *pLength = unsqLen; - } else { - if (*pLength < unsqLen) { - pErrMsg->Format("buf size %ld too short (%ld)", - *pLength, unsqLen); - delete[] unsqBuf; - goto bail; - } + char* unsqBuf = nil; + long unsqLen = 0; + expBuf.SeizeBuffer(&unsqBuf, &unsqLen); + WMSG2("Unsqueezed %ld bytes to %d\n", + (unsigned long) GetCompressedLen(), unsqLen); + if (unsqLen == 0) { + // some bonehead squeezed a zero-length file + delete[] unsqBuf; + ASSERT(*ppText == nil); + WMSG0("Handling zero-length squeezed file!\n"); + if (needAlloc) { + *ppText = new char[1]; + **ppText = '\0'; + } + *pLength = 0; + } else { + if (needAlloc) { + /* just use the seized buffer */ + *ppText = unsqBuf; + *pLength = unsqLen; + } else { + if (*pLength < unsqLen) { + pErrMsg->Format("buf size %ld too short (%ld)", + *pLength, unsqLen); + delete[] unsqBuf; + goto bail; + } - memcpy(*ppText, unsqBuf, unsqLen); - delete[] unsqBuf; - *pLength = unsqLen; - } - } + memcpy(*ppText, unsqBuf, unsqLen); + delete[] unsqBuf; + *pLength = unsqLen; + } + } - } else { - if (needAlloc) { - dataBuf = new char[len]; - if (dataBuf == nil) { - pErrMsg->Format("allocation of %ld bytes failed", len); - goto bail; - } - } else { - if (*pLength < (long) len) { - pErrMsg->Format("buf size %ld too short (%ld)", - *pLength, len); - goto bail; - } - dataBuf = *ppText; - } - if (fread(dataBuf, len, 1, fpArchive->fFp) != 1) { - pErrMsg->Format("File read failed: %s", strerror(errno)); - goto bail; - } + } else { + if (needAlloc) { + dataBuf = new char[len]; + if (dataBuf == nil) { + pErrMsg->Format("allocation of %ld bytes failed", len); + goto bail; + } + } else { + if (*pLength < (long) len) { + pErrMsg->Format("buf size %ld too short (%ld)", + *pLength, len); + goto bail; + } + dataBuf = *ppText; + } + if (fread(dataBuf, len, 1, fpArchive->fFp) != 1) { + pErrMsg->Format("File read failed: %s", strerror(errno)); + goto bail; + } - if (needAlloc) - *ppText = dataBuf; - *pLength = len; - } + if (needAlloc) + *ppText = dataBuf; + *pLength = len; + } - result = IDOK; + result = IDOK; bail: - if (result == IDOK) { - SET_PROGRESS_END(); - ASSERT(pErrMsg->IsEmpty()); - } else { - ASSERT(result == IDCANCEL || !pErrMsg->IsEmpty()); - if (needAlloc) { - delete[] dataBuf; - ASSERT(*ppText == nil); - } - } - return result; + if (result == IDOK) { + SET_PROGRESS_END(); + ASSERT(pErrMsg->IsEmpty()); + } else { + ASSERT(result == IDCANCEL || !pErrMsg->IsEmpty()); + if (needAlloc) { + delete[] dataBuf; + ASSERT(*ppText == nil); + } + } + return result; } /* @@ -209,92 +209,92 @@ bail: */ int AcuEntry::ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, - ConvertHighASCII convHA, CString* pErrMsg) const + ConvertHighASCII convHA, CString* pErrMsg) const { - NuError nerr; - long len; - int result = -1; + NuError nerr; + long len; + int result = -1; - ASSERT(IDOK != -1 && IDCANCEL != -1); - if (which != kDataThread) { - *pErrMsg = "No such fork"; - goto bail; - } + ASSERT(IDOK != -1 && IDCANCEL != -1); + if (which != kDataThread) { + *pErrMsg = "No such fork"; + goto bail; + } - len = (long) GetUncompressedLen(); - if (len == 0) { - WMSG0("Empty fork\n"); - result = IDOK; - goto bail; - } + len = (long) GetUncompressedLen(); + if (len == 0) { + WMSG0("Empty fork\n"); + result = IDOK; + goto bail; + } - errno = 0; - if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) { - pErrMsg->Format("Unable to seek to offset %ld: %s", - fOffset, strerror(errno)); - goto bail; - } + errno = 0; + if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) { + pErrMsg->Format("Unable to seek to offset %ld: %s", + fOffset, strerror(errno)); + goto bail; + } - SET_PROGRESS_BEGIN(); + SET_PROGRESS_BEGIN(); - /* - * Generally speaking, anything in a BNY file is going to be small. The - * major exception is a BXY file, which could be huge. However, the - * SHK embedded in a BXY is never squeezed. - * - * To make life easy, we either unsqueeze the entire thing into a buffer - * and then write that, or we do a file-to-file copy of the specified - * number of bytes. - */ - if (GetSqueezed()) { - ExpandBuffer expBuf; - bool lastCR = false; - char* buf; - long uncLen; + /* + * Generally speaking, anything in a BNY file is going to be small. The + * major exception is a BXY file, which could be huge. However, the + * SHK embedded in a BXY is never squeezed. + * + * To make life easy, we either unsqueeze the entire thing into a buffer + * and then write that, or we do a file-to-file copy of the specified + * number of bytes. + */ + if (GetSqueezed()) { + ExpandBuffer expBuf; + bool lastCR = false; + char* buf; + long uncLen; - nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetCompressedLen(), - &expBuf, false, 0); - if (nerr != kNuErrNone) { - pErrMsg->Format("File read failed: %s", NuStrError(nerr)); - goto bail; - } + nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetCompressedLen(), + &expBuf, false, 0); + if (nerr != kNuErrNone) { + pErrMsg->Format("File read failed: %s", NuStrError(nerr)); + goto bail; + } - expBuf.SeizeBuffer(&buf, &uncLen); - WMSG2("Unsqueezed %ld bytes to %d\n", len, uncLen); + expBuf.SeizeBuffer(&buf, &uncLen); + WMSG2("Unsqueezed %ld bytes to %d\n", len, uncLen); - // some bonehead squeezed a zero-length file - if (uncLen == 0) { - ASSERT(buf == nil); - WMSG0("Handling zero-length squeezed file!\n"); - result = IDOK; - goto bail; - } + // some bonehead squeezed a zero-length file + if (uncLen == 0) { + ASSERT(buf == nil); + WMSG0("Handling zero-length squeezed file!\n"); + result = IDOK; + goto bail; + } - int err = GenericEntry::WriteConvert(outfp, buf, uncLen, &conv, - &convHA, &lastCR); - if (err != 0) { - pErrMsg->Format("File write failed: %s", strerror(err)); - delete[] buf; - goto bail; - } + int err = GenericEntry::WriteConvert(outfp, buf, uncLen, &conv, + &convHA, &lastCR); + if (err != 0) { + pErrMsg->Format("File write failed: %s", strerror(err)); + delete[] buf; + goto bail; + } - delete[] buf; - } else { - nerr = CopyData(outfp, conv, convHA, pErrMsg); - if (nerr != kNuErrNone) { - if (pErrMsg->IsEmpty()) { - pErrMsg->Format("Failed while copying data: %s\n", - NuStrError(nerr)); - } - goto bail; - } - } + delete[] buf; + } else { + nerr = CopyData(outfp, conv, convHA, pErrMsg); + if (nerr != kNuErrNone) { + if (pErrMsg->IsEmpty()) { + pErrMsg->Format("Failed while copying data: %s\n", + NuStrError(nerr)); + } + goto bail; + } + } - result = IDOK; + result = IDOK; bail: - SET_PROGRESS_END(); - return result; + SET_PROGRESS_END(); + return result; } /* @@ -303,51 +303,51 @@ bail: */ NuError AcuEntry::CopyData(FILE* outfp, ConvertEOL conv, ConvertHighASCII convHA, - CString* pMsg) const + CString* pMsg) const { - NuError nerr = kNuErrNone; - const int kChunkSize = 8192; - char buf[kChunkSize]; - bool lastCR = false; - long srcLen, dataRem; + NuError nerr = kNuErrNone; + const int kChunkSize = 8192; + char buf[kChunkSize]; + bool lastCR = false; + long srcLen, dataRem; - srcLen = (long) GetUncompressedLen(); - ASSERT(srcLen > 0); // empty files should've been caught earlier + srcLen = (long) GetUncompressedLen(); + ASSERT(srcLen > 0); // empty files should've been caught earlier - /* - * Loop until all data copied. - */ - dataRem = srcLen; - while (dataRem) { - int chunkLen; + /* + * Loop until all data copied. + */ + dataRem = srcLen; + while (dataRem) { + int chunkLen; - if (dataRem > kChunkSize) - chunkLen = kChunkSize; - else - chunkLen = dataRem; + if (dataRem > kChunkSize) + chunkLen = kChunkSize; + else + chunkLen = dataRem; - /* read a chunk from the source file */ - nerr = fpArchive->AcuRead(buf, chunkLen); - if (nerr != kNuErrNone) { - pMsg->Format("File read failed: %s.", NuStrError(nerr)); - goto bail; - } + /* read a chunk from the source file */ + nerr = fpArchive->AcuRead(buf, chunkLen); + if (nerr != kNuErrNone) { + pMsg->Format("File read failed: %s.", NuStrError(nerr)); + goto bail; + } - /* write chunk to destination file */ - int err = GenericEntry::WriteConvert(outfp, buf, chunkLen, &conv, - &convHA, &lastCR); - if (err != 0) { - pMsg->Format("File write failed: %s.", strerror(err)); - nerr = kNuErrGeneric; - goto bail; - } + /* write chunk to destination file */ + int err = GenericEntry::WriteConvert(outfp, buf, chunkLen, &conv, + &convHA, &lastCR); + if (err != 0) { + pMsg->Format("File write failed: %s.", strerror(err)); + nerr = kNuErrGeneric; + goto bail; + } - dataRem -= chunkLen; - SET_PROGRESS_UPDATE(ComputePercent(srcLen - dataRem, srcLen)); - } + dataRem -= chunkLen; + SET_PROGRESS_UPDATE(ComputePercent(srcLen - dataRem, srcLen)); + } bail: - return nerr; + return nerr; } @@ -360,54 +360,54 @@ bail: NuError AcuEntry::TestEntry(CWnd* pMsgWnd) { - NuError nerr = kNuErrNone; - CString errMsg; - long len; - int result = -1; + NuError nerr = kNuErrNone; + CString errMsg; + long len; + int result = -1; - len = (long) GetUncompressedLen(); - if (len == 0) - goto bail; + len = (long) GetUncompressedLen(); + if (len == 0) + goto bail; - errno = 0; - if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) { - nerr = kNuErrGeneric; - errMsg.Format("Unable to seek to offset %ld: %s\n", - fOffset, strerror(errno)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } + errno = 0; + if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) { + nerr = kNuErrGeneric; + errMsg.Format("Unable to seek to offset %ld: %s\n", + fOffset, strerror(errno)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } - if (GetSqueezed()) { - nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetCompressedLen(), - nil, false, 0); - if (nerr != kNuErrNone) { - errMsg.Format("Unsqueeze failed: %s.", NuStrError(nerr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - } else { - errno = 0; - if (fseek(fpArchive->fFp, fOffset + len, SEEK_SET) < 0) { - nerr = kNuErrGeneric; - errMsg.Format("Unable to seek to offset %ld (file truncated?): %s\n", - fOffset, strerror(errno)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - } + if (GetSqueezed()) { + nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetCompressedLen(), + nil, false, 0); + if (nerr != kNuErrNone) { + errMsg.Format("Unsqueeze failed: %s.", NuStrError(nerr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + } else { + errno = 0; + if (fseek(fpArchive->fFp, fOffset + len, SEEK_SET) < 0) { + nerr = kNuErrGeneric; + errMsg.Format("Unable to seek to offset %ld (file truncated?): %s\n", + fOffset, strerror(errno)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + } - if (SET_PROGRESS_UPDATE(100) == IDCANCEL) - nerr = kNuErrAborted; + if (SET_PROGRESS_UPDATE(100) == IDCANCEL) + nerr = kNuErrAborted; bail: - return nerr; + return nerr; } /* * =========================================================================== - * AcuArchive + * AcuArchive * =========================================================================== */ @@ -419,7 +419,7 @@ bail: /*static*/ CString AcuArchive::AppInit(void) { - return ""; + return ""; } /* @@ -430,39 +430,39 @@ AcuArchive::AppInit(void) GenericArchive::OpenResult AcuArchive::Open(const char* filename, bool readOnly, CString* pErrMsg) { - CString errMsg; + CString errMsg; - fIsReadOnly = true; // ignore "readOnly" + fIsReadOnly = true; // ignore "readOnly" - errno = 0; - fFp = fopen(filename, "rb"); - if (fFp == nil) { - errMsg.Format("Unable to open %s: %s.", filename, strerror(errno)); - goto bail; - } + errno = 0; + fFp = fopen(filename, "rb"); + if (fFp == nil) { + errMsg.Format("Unable to open %s: %s.", filename, strerror(errno)); + goto bail; + } - { - CWaitCursor waitc; - int result; + { + CWaitCursor waitc; + int result; - result = LoadContents(); - if (result < 0) { - errMsg.Format("The file is not an ACU archive."); - goto bail; - } else if (result > 0) { - errMsg.Format("Failed while reading data from ACU archive."); - goto bail; - } - } + result = LoadContents(); + if (result < 0) { + errMsg.Format("The file is not an ACU archive."); + goto bail; + } else if (result > 0) { + errMsg.Format("Failed while reading data from ACU archive."); + goto bail; + } + } - SetPathName(filename); + SetPathName(filename); bail: - *pErrMsg = errMsg; - if (!errMsg.IsEmpty()) - return kResultFailure; - else - return kResultSuccess; + *pErrMsg = errMsg; + if (!errMsg.IsEmpty()) + return kResultFailure; + else + return kResultSuccess; } /* @@ -473,8 +473,8 @@ bail: CString AcuArchive::New(const char* /*filename*/, const void* /*options*/) { - CString retmsg("Sorry, AppleLink Compression Utility files can't be created."); - return retmsg; + CString retmsg("Sorry, AppleLink Compression Utility files can't be created."); + return retmsg; } @@ -484,36 +484,36 @@ AcuArchive::New(const char* /*filename*/, const void* /*options*/) long AcuArchive::GetCapability(Capability cap) { - switch (cap) { - case kCapCanTest: - return true; - break; - case kCapCanRenameFullPath: - return true; - break; - case kCapCanRecompress: - return true; - break; - case kCapCanEditComment: - return false; - break; - case kCapCanAddDisk: - return false; - break; - case kCapCanConvEOLOnAdd: - return false; - break; - case kCapCanCreateSubdir: - return false; - break; - case kCapCanRenameVolume: - return false; - break; - default: - ASSERT(false); - return -1; - break; - } + switch (cap) { + case kCapCanTest: + return true; + break; + case kCapCanRenameFullPath: + return true; + break; + case kCapCanRecompress: + return true; + break; + case kCapCanEditComment: + return false; + break; + case kCapCanAddDisk: + return false; + break; + case kCapCanConvEOLOnAdd: + return false; + break; + case kCapCanCreateSubdir: + return false; + break; + case kCapCanRenameVolume: + return false; + break; + default: + ASSERT(false); + return -1; + break; + } } @@ -526,40 +526,40 @@ AcuArchive::GetCapability(Capability cap) int AcuArchive::LoadContents(void) { - NuError nerr; - int numEntries; + NuError nerr; + int numEntries; - ASSERT(fFp != nil); - rewind(fFp); + ASSERT(fFp != nil); + rewind(fFp); - /* - * Read the master header. In an ACU file this holds the number of - * files and a bunch of stuff that doesn't seem to change. - */ - if (ReadMasterHeader(&numEntries) != 0) - return -1; + /* + * Read the master header. In an ACU file this holds the number of + * files and a bunch of stuff that doesn't seem to change. + */ + if (ReadMasterHeader(&numEntries) != 0) + return -1; - while (numEntries) { - AcuFileEntry fileEntry; + while (numEntries) { + AcuFileEntry fileEntry; - nerr = ReadFileHeader(&fileEntry); - if (nerr != kNuErrNone) - return 1; + nerr = ReadFileHeader(&fileEntry); + if (nerr != kNuErrNone) + return 1; - if (CreateEntry(&fileEntry) != 0) - return 1; + if (CreateEntry(&fileEntry) != 0) + return 1; - /* if file isn't empty, seek past it */ - if (fileEntry.dataStorageLen) { - nerr = AcuSeek(fileEntry.dataStorageLen); - if (nerr != kNuErrNone) - return 1; - } + /* if file isn't empty, seek past it */ + if (fileEntry.dataStorageLen) { + nerr = AcuSeek(fileEntry.dataStorageLen); + if (nerr != kNuErrNone) + return 1; + } - numEntries--; - } + numEntries--; + } - return 0; + return 0; } /* @@ -568,14 +568,14 @@ AcuArchive::LoadContents(void) CString AcuArchive::Reload(void) { - fReloadFlag = true; // tell everybody that cached data is invalid + fReloadFlag = true; // tell everybody that cached data is invalid - DeleteEntries(); - if (LoadContents() != 0) { - return "Reload failed."; - } - - return ""; + DeleteEntries(); + if (LoadContents() != 0) { + return "Reload failed."; + } + + return ""; } /* @@ -588,32 +588,32 @@ AcuArchive::Reload(void) int AcuArchive::ReadMasterHeader(int* pNumEntries) { - AcuMasterHeader header; - unsigned char buf[kAcuMasterHeaderLen]; - NuError nerr; + AcuMasterHeader header; + unsigned char buf[kAcuMasterHeaderLen]; + NuError nerr; - nerr = AcuRead(buf, kAcuMasterHeaderLen); - if (nerr != kNuErrNone) - return -1; + nerr = AcuRead(buf, kAcuMasterHeaderLen); + if (nerr != kNuErrNone) + return -1; - header.fileCount = buf[0x00] | buf[0x01] << 8; - header.unknown1 = buf[0x02] | buf[0x03] << 8; - memcpy(header.fZink, &buf[0x04], 5); - header.fZink[5] = '\0'; - memcpy(header.unknown2, &buf[0x09], 11); + header.fileCount = buf[0x00] | buf[0x01] << 8; + header.unknown1 = buf[0x02] | buf[0x03] << 8; + memcpy(header.fZink, &buf[0x04], 5); + header.fZink[5] = '\0'; + memcpy(header.unknown2, &buf[0x09], 11); - if (header.fileCount == 0 || - header.unknown1 != 1 || - strcmp((char*) header.fZink, "fZink") != 0) - { - WMSG0("Not an ACU archive\n"); - return -1; - } + if (header.fileCount == 0 || + header.unknown1 != 1 || + strcmp((char*) header.fZink, "fZink") != 0) + { + WMSG0("Not an ACU archive\n"); + return -1; + } - WMSG1("Looks like an ACU archive with %d entries\n", header.fileCount); + WMSG1("Looks like an ACU archive with %d entries\n", header.fileCount); - *pNumEntries = header.fileCount; - return 0; + *pNumEntries = header.fileCount; + return 0; } /* @@ -623,70 +623,70 @@ AcuArchive::ReadMasterHeader(int* pNumEntries) NuError AcuArchive::ReadFileHeader(AcuFileEntry* pEntry) { - NuError err = kNuErrNone; - unsigned char buf[kAcuEntryHeaderLen]; + NuError err = kNuErrNone; + unsigned char buf[kAcuEntryHeaderLen]; - ASSERT(pEntry != nil); + ASSERT(pEntry != nil); - err = AcuRead(buf, kAcuEntryHeaderLen); - if (err != kNuErrNone) - goto bail; + err = AcuRead(buf, kAcuEntryHeaderLen); + if (err != kNuErrNone) + goto bail; - // unknown at 00 - pEntry->compressionType = buf[0x01]; - // unknown at 02-03 - pEntry->dataChecksum = buf[0x04] | buf[0x05] << 8; // not sure - // unknown at 06-09 - pEntry->blockCount = buf[0x0a] | buf[0x0b] << 8; - // unknown at 0c-11 - pEntry->dataStorageLen = buf[0x12] | buf [0x13] << 8 | buf[0x14] << 16 | - buf[0x15] << 24; - pEntry->access = buf[0x16] | buf[0x17] << 8; - pEntry->fileType = buf[0x18] | buf[0x19] << 8; - pEntry->auxType = buf[0x1a] | buf[0x1b] << 8; - // unknown at 1e-1f - pEntry->storageType = buf[0x20]; - // unknown at 21-25 - pEntry->dataEof = buf[0x26] | buf[0x27] << 8 | buf[0x28] << 16 | - buf[0x29] << 24; - pEntry->prodosModDate = buf[0x2a] | buf[0x2b] << 8; - pEntry->prodosModTime = buf[0x2c] | buf[0x2d] << 8; - AcuConvertDateTime(pEntry->prodosModDate, pEntry->prodosModTime, - &pEntry->modWhen); - pEntry->prodosCreateDate = buf[0x2e] | buf[0x2f] << 8; - pEntry->prodosCreateTime = buf[0x30] | buf[0x31] << 8; - AcuConvertDateTime(pEntry->prodosCreateDate, pEntry->prodosCreateTime, - &pEntry->createWhen); - pEntry->fileNameLen = buf[0x32] | buf[0x33] << 8; - pEntry->headerChecksum = buf[0x34] | buf[0x35] << 8; // not sure + // unknown at 00 + pEntry->compressionType = buf[0x01]; + // unknown at 02-03 + pEntry->dataChecksum = buf[0x04] | buf[0x05] << 8; // not sure + // unknown at 06-09 + pEntry->blockCount = buf[0x0a] | buf[0x0b] << 8; + // unknown at 0c-11 + pEntry->dataStorageLen = buf[0x12] | buf [0x13] << 8 | buf[0x14] << 16 | + buf[0x15] << 24; + pEntry->access = buf[0x16] | buf[0x17] << 8; + pEntry->fileType = buf[0x18] | buf[0x19] << 8; + pEntry->auxType = buf[0x1a] | buf[0x1b] << 8; + // unknown at 1e-1f + pEntry->storageType = buf[0x20]; + // unknown at 21-25 + pEntry->dataEof = buf[0x26] | buf[0x27] << 8 | buf[0x28] << 16 | + buf[0x29] << 24; + pEntry->prodosModDate = buf[0x2a] | buf[0x2b] << 8; + pEntry->prodosModTime = buf[0x2c] | buf[0x2d] << 8; + AcuConvertDateTime(pEntry->prodosModDate, pEntry->prodosModTime, + &pEntry->modWhen); + pEntry->prodosCreateDate = buf[0x2e] | buf[0x2f] << 8; + pEntry->prodosCreateTime = buf[0x30] | buf[0x31] << 8; + AcuConvertDateTime(pEntry->prodosCreateDate, pEntry->prodosCreateTime, + &pEntry->createWhen); + pEntry->fileNameLen = buf[0x32] | buf[0x33] << 8; + pEntry->headerChecksum = buf[0x34] | buf[0x35] << 8; // not sure - /* read the filename */ - if (pEntry->fileNameLen > kAcuMaxFileName) { - WMSG1("GLITCH: filename is too long (%d bytes)\n", - pEntry->fileNameLen); - err = kNuErrGeneric; - goto bail; - } - if (!pEntry->fileNameLen) { - WMSG0("GLITCH: filename missing\n"); - err = kNuErrGeneric; - goto bail; - } + /* read the filename */ + if (pEntry->fileNameLen > kAcuMaxFileName) { + WMSG1("GLITCH: filename is too long (%d bytes)\n", + pEntry->fileNameLen); + err = kNuErrGeneric; + goto bail; + } + if (!pEntry->fileNameLen) { + WMSG0("GLITCH: filename missing\n"); + err = kNuErrGeneric; + goto bail; + } - /* don't know if this is possible or not */ - if (pEntry->storageType == 5) { - WMSG0("HEY: EXTENDED FILE\n"); - } + /* don't know if this is possible or not */ + if (pEntry->storageType == 5) { + WMSG0("HEY: EXTENDED FILE\n"); + } - err = AcuRead(pEntry->fileName, pEntry->fileNameLen); - if (err != kNuErrNone) - goto bail; - pEntry->fileName[pEntry->fileNameLen] = '\0'; + err = AcuRead(pEntry->fileName, pEntry->fileNameLen); + if (err != kNuErrNone) + goto bail; + pEntry->fileName[pEntry->fileNameLen] = '\0'; - //DumpFileHeader(pEntry); + //DumpFileHeader(pEntry); bail: - return err; + return err; } /* @@ -695,24 +695,24 @@ bail: void AcuArchive::DumpFileHeader(const AcuFileEntry* pEntry) { - time_t createWhen, modWhen; - CString createStr, modStr; + time_t createWhen, modWhen; + CString createStr, modStr; - createWhen = NufxArchive::DateTimeToSeconds(&pEntry->createWhen); - modWhen = NufxArchive::DateTimeToSeconds(&pEntry->modWhen); - FormatDate(createWhen, &createStr); - FormatDate(modWhen, &modStr); + createWhen = NufxArchive::DateTimeToSeconds(&pEntry->createWhen); + modWhen = NufxArchive::DateTimeToSeconds(&pEntry->modWhen); + FormatDate(createWhen, &createStr); + FormatDate(modWhen, &modStr); - WMSG1(" Header for file '%s':\n", pEntry->fileName); - WMSG4(" dataStorageLen=%d eof=%d blockCount=%d checksum=0x%04x\n", - pEntry->dataStorageLen, pEntry->dataEof, pEntry->blockCount, - pEntry->dataChecksum); - WMSG4(" fileType=0x%02x auxType=0x%04x storageType=0x%02x access=0x%04x\n", - pEntry->fileType, pEntry->auxType, pEntry->storageType, pEntry->access); - WMSG2(" created %s, modified %s\n", (const char*) createStr, - (const char*) modStr); - WMSG2(" fileNameLen=%d headerChecksum=0x%04x\n", - pEntry->fileNameLen, pEntry->headerChecksum); + WMSG1(" Header for file '%s':\n", pEntry->fileName); + WMSG4(" dataStorageLen=%d eof=%d blockCount=%d checksum=0x%04x\n", + pEntry->dataStorageLen, pEntry->dataEof, pEntry->blockCount, + pEntry->dataChecksum); + WMSG4(" fileType=0x%02x auxType=0x%04x storageType=0x%02x access=0x%04x\n", + pEntry->fileType, pEntry->auxType, pEntry->storageType, pEntry->access); + WMSG2(" created %s, modified %s\n", (const char*) createStr, + (const char*) modStr); + WMSG2(" fileNameLen=%d headerChecksum=0x%04x\n", + pEntry->fileNameLen, pEntry->headerChecksum); } @@ -722,57 +722,57 @@ AcuArchive::DumpFileHeader(const AcuFileEntry* pEntry) int AcuArchive::CreateEntry(const AcuFileEntry* pEntry) { - const int kAcuFssep = '/'; - NuError err = kNuErrNone; - AcuEntry* pNewEntry; + const int kAcuFssep = '/'; + NuError err = kNuErrNone; + AcuEntry* pNewEntry; - /* - * Create the new entry. - */ - pNewEntry = new AcuEntry(this); - pNewEntry->SetPathName(pEntry->fileName); - pNewEntry->SetFssep(kAcuFssep); - pNewEntry->SetFileType(pEntry->fileType); - pNewEntry->SetAuxType(pEntry->auxType); - pNewEntry->SetAccess(pEntry->access); - pNewEntry->SetCreateWhen(NufxArchive::DateTimeToSeconds(&pEntry->createWhen)); - pNewEntry->SetModWhen(NufxArchive::DateTimeToSeconds(&pEntry->modWhen)); + /* + * Create the new entry. + */ + pNewEntry = new AcuEntry(this); + pNewEntry->SetPathName(pEntry->fileName); + pNewEntry->SetFssep(kAcuFssep); + pNewEntry->SetFileType(pEntry->fileType); + pNewEntry->SetAuxType(pEntry->auxType); + pNewEntry->SetAccess(pEntry->access); + pNewEntry->SetCreateWhen(NufxArchive::DateTimeToSeconds(&pEntry->createWhen)); + pNewEntry->SetModWhen(NufxArchive::DateTimeToSeconds(&pEntry->modWhen)); - /* always ProDOS? */ - pNewEntry->SetSourceFS(DiskImg::kFormatProDOS); + /* always ProDOS? */ + pNewEntry->SetSourceFS(DiskImg::kFormatProDOS); - pNewEntry->SetHasDataFork(true); - pNewEntry->SetHasRsrcFork(false); // ? - if (IsDir(pEntry)) { - pNewEntry->SetRecordKind(GenericEntry::kRecordKindDirectory); - } else { - pNewEntry->SetRecordKind(GenericEntry::kRecordKindFile); - } + pNewEntry->SetHasDataFork(true); + pNewEntry->SetHasRsrcFork(false); // ? + if (IsDir(pEntry)) { + pNewEntry->SetRecordKind(GenericEntry::kRecordKindDirectory); + } else { + pNewEntry->SetRecordKind(GenericEntry::kRecordKindFile); + } - pNewEntry->SetCompressedLen(pEntry->dataStorageLen); - pNewEntry->SetDataForkLen(pEntry->dataEof); + pNewEntry->SetCompressedLen(pEntry->dataStorageLen); + pNewEntry->SetDataForkLen(pEntry->dataEof); - if (pEntry->compressionType == kAcuCompNone) { - pNewEntry->SetFormatStr("Uncompr"); - } else if (pEntry->compressionType == kAcuCompSqueeze) { - pNewEntry->SetFormatStr("Squeeze"); - pNewEntry->SetSqueezed(true); - } else { - pNewEntry->SetFormatStr("(unknown)"); - pNewEntry->SetSqueezed(false); - } + if (pEntry->compressionType == kAcuCompNone) { + pNewEntry->SetFormatStr("Uncompr"); + } else if (pEntry->compressionType == kAcuCompSqueeze) { + pNewEntry->SetFormatStr("Squeeze"); + pNewEntry->SetSqueezed(true); + } else { + pNewEntry->SetFormatStr("(unknown)"); + pNewEntry->SetSqueezed(false); + } - pNewEntry->SetOffset(ftell(fFp)); + pNewEntry->SetOffset(ftell(fFp)); - AddEntry(pNewEntry); + AddEntry(pNewEntry); - return err; + return err; } /* * =========================================================================== - * ACU functions + * ACU functions * =========================================================================== */ @@ -782,7 +782,7 @@ AcuArchive::CreateEntry(const AcuFileEntry* pEntry) bool AcuArchive::IsDir(const AcuFileEntry* pEntry) { - return (pEntry->storageType == 0x0d); + return (pEntry->storageType == 0x0d); } /* @@ -792,36 +792,36 @@ AcuArchive::IsDir(const AcuFileEntry* pEntry) NuError AcuArchive::AcuRead(void* buf, size_t nbyte) { - size_t result; + size_t result; - ASSERT(buf != nil); - ASSERT(nbyte > 0); - ASSERT(fFp != nil); + ASSERT(buf != nil); + ASSERT(nbyte > 0); + ASSERT(fFp != nil); - errno = 0; - result = fread(buf, 1, nbyte, fFp); - if (result != nbyte) - return errno ? (NuError)errno : kNuErrFileRead; - return kNuErrNone; + errno = 0; + result = fread(buf, 1, nbyte, fFp); + if (result != nbyte) + return errno ? (NuError)errno : kNuErrFileRead; + return kNuErrNone; } /* - * Seek within an archive. Because we need to handle streaming archives, + * Seek within an archive. Because we need to handle streaming archives, * and don't need to special-case anything, we only allow relative * forward seeks. */ NuError AcuArchive::AcuSeek(long offset) { - ASSERT(fFp != nil); - ASSERT(offset > 0); + ASSERT(fFp != nil); + ASSERT(offset > 0); - /*DBUG(("--- seeking forward %ld bytes\n", offset));*/ + /*DBUG(("--- seeking forward %ld bytes\n", offset));*/ - if (fseek(fFp, offset, SEEK_CUR) < 0) - return kNuErrFileSeek; - - return kNuErrNone; + if (fseek(fFp, offset, SEEK_CUR) < 0) + return kNuErrFileSeek; + + return kNuErrNone; } @@ -830,24 +830,24 @@ AcuArchive::AcuSeek(long offset) */ void AcuArchive::AcuConvertDateTime(unsigned short prodosDate, - unsigned short prodosTime, NuDateTime* pWhen) + unsigned short prodosTime, NuDateTime* pWhen) { - pWhen->second = 0; - pWhen->minute = prodosTime & 0x3f; - pWhen->hour = (prodosTime >> 8) & 0x1f; - pWhen->day = (prodosDate & 0x1f) -1; - pWhen->month = ((prodosDate >> 5) & 0x0f) -1; - pWhen->year = (prodosDate >> 9) & 0x7f; - if (pWhen->year < 40) - pWhen->year += 100; /* P8 uses 0-39 for 2000-2039 */ - pWhen->extra = 0; - pWhen->weekDay = 0; + pWhen->second = 0; + pWhen->minute = prodosTime & 0x3f; + pWhen->hour = (prodosTime >> 8) & 0x1f; + pWhen->day = (prodosDate & 0x1f) -1; + pWhen->month = ((prodosDate >> 5) & 0x0f) -1; + pWhen->year = (prodosDate >> 9) & 0x7f; + if (pWhen->year < 40) + pWhen->year += 100; /* P8 uses 0-39 for 2000-2039 */ + pWhen->extra = 0; + pWhen->weekDay = 0; } /* * =========================================================================== - * AcuArchive -- test files + * AcuArchive -- test files * =========================================================================== */ @@ -857,50 +857,50 @@ AcuArchive::AcuConvertDateTime(unsigned short prodosDate, bool AcuArchive::TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) { - NuError nerr; - AcuEntry* pEntry; - CString errMsg; - bool retVal = false; + NuError nerr; + AcuEntry* pEntry; + CString errMsg; + bool retVal = false; - ASSERT(fFp != nil); + ASSERT(fFp != nil); - WMSG1("Testing %d entries\n", pSelSet->GetNumEntries()); + WMSG1("Testing %d entries\n", pSelSet->GetNumEntries()); - SelectionEntry* pSelEntry = pSelSet->IterNext(); - while (pSelEntry != nil) { - pEntry = (AcuEntry*) pSelEntry->GetEntry(); + SelectionEntry* pSelEntry = pSelSet->IterNext(); + while (pSelEntry != nil) { + pEntry = (AcuEntry*) pSelEntry->GetEntry(); - WMSG2(" Testing '%s' (offset=%ld)\n", pEntry->GetDisplayName(), - pEntry->GetOffset()); + WMSG2(" Testing '%s' (offset=%ld)\n", pEntry->GetDisplayName(), + pEntry->GetOffset()); - SET_PROGRESS_UPDATE2(0, pEntry->GetDisplayName(), nil); + SET_PROGRESS_UPDATE2(0, pEntry->GetDisplayName(), nil); - nerr = pEntry->TestEntry(pMsgWnd); - if (nerr != kNuErrNone) { - if (nerr == kNuErrAborted) { - CString title; - title.LoadString(IDS_MB_APP_NAME); - errMsg = "Cancelled."; - pMsgWnd->MessageBox(errMsg, title, MB_OK); - } else { - errMsg.Format("Failed while testing '%s': %s.", - pEntry->GetPathName(), NuStrError(nerr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - } - goto bail; - } + nerr = pEntry->TestEntry(pMsgWnd); + if (nerr != kNuErrNone) { + if (nerr == kNuErrAborted) { + CString title; + title.LoadString(IDS_MB_APP_NAME); + errMsg = "Cancelled."; + pMsgWnd->MessageBox(errMsg, title, MB_OK); + } else { + errMsg.Format("Failed while testing '%s': %s.", + pEntry->GetPathName(), NuStrError(nerr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + } + goto bail; + } - pSelEntry = pSelSet->IterNext(); - } + pSelEntry = pSelSet->IterNext(); + } - /* show success message */ - errMsg.Format("Tested %d file%s, no errors found.", - pSelSet->GetNumEntries(), - pSelSet->GetNumEntries() == 1 ? "" : "s"); - pMsgWnd->MessageBox(errMsg); - retVal = true; + /* show success message */ + errMsg.Format("Tested %d file%s, no errors found.", + pSelSet->GetNumEntries(), + pSelSet->GetNumEntries() == 1 ? "" : "s"); + pMsgWnd->MessageBox(errMsg); + retVal = true; bail: - SET_PROGRESS_END(); - return retVal; + SET_PROGRESS_END(); + return retVal; } diff --git a/app/ACUArchive.h b/app/ACUArchive.h index 8724711..1fe0ba6 100644 --- a/app/ACUArchive.h +++ b/app/ACUArchive.h @@ -19,41 +19,41 @@ class AcuArchive; */ class AcuEntry : public GenericEntry { public: - AcuEntry(AcuArchive* pArchive) : - fpArchive(pArchive), fIsSqueezed(false), fOffset(-1) - {} - virtual ~AcuEntry(void) {} + AcuEntry(AcuArchive* pArchive) : + fpArchive(pArchive), fIsSqueezed(false), fOffset(-1) + {} + virtual ~AcuEntry(void) {} - // retrieve thread data - virtual int ExtractThreadToBuffer(int which, char** ppText, long* pLength, - CString* pErrMsg) const; - virtual int ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, - ConvertHighASCII convHA, CString* pErrMsg) const; - virtual long GetSelectionSerial(void) const { return -1; } // doesn't matter + // retrieve thread data + virtual int ExtractThreadToBuffer(int which, char** ppText, long* pLength, + CString* pErrMsg) const; + virtual int ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, + ConvertHighASCII convHA, CString* pErrMsg) const; + virtual long GetSelectionSerial(void) const { return -1; } // doesn't matter - virtual bool GetFeatureFlag(Feature feature) const { - if (feature == kFeaturePascalTypes || feature == kFeatureDOSTypes || - feature == kFeatureHasSimpleAccess) - return false; - else - return true; - } + virtual bool GetFeatureFlag(Feature feature) const { + if (feature == kFeaturePascalTypes || feature == kFeatureDOSTypes || + feature == kFeatureHasSimpleAccess) + return false; + else + return true; + } - NuError TestEntry(CWnd* pMsgWnd); + NuError TestEntry(CWnd* pMsgWnd); - bool GetSqueezed(void) const { return fIsSqueezed; } - void SetSqueezed(bool val) { fIsSqueezed = val; } - long GetOffset(void) const { return fOffset; } - void SetOffset(long offset) { fOffset = offset; } + bool GetSqueezed(void) const { return fIsSqueezed; } + void SetSqueezed(bool val) { fIsSqueezed = val; } + long GetOffset(void) const { return fOffset; } + void SetOffset(long offset) { fOffset = offset; } private: - NuError CopyData(FILE* outfp, ConvertEOL conv, ConvertHighASCII convHA, - CString* pMsg) const; - //NuError BNYUnSqueeze(ExpandBuffer* outExp) const; + NuError CopyData(FILE* outfp, ConvertEOL conv, ConvertHighASCII convHA, + CString* pMsg) const; + //NuError BNYUnSqueeze(ExpandBuffer* outExp) const; - AcuArchive* fpArchive; // holds FILE* for archive - bool fIsSqueezed; - long fOffset; + AcuArchive* fpArchive; // holds FILE* for archive + bool fIsSqueezed; + long fOffset; }; @@ -62,161 +62,161 @@ private: */ class AcuArchive : public GenericArchive { public: - AcuArchive(void) : fIsReadOnly(false), fFp(nil) - {} - virtual ~AcuArchive(void) { (void) Close(); } + AcuArchive(void) : fIsReadOnly(false), fFp(nil) + {} + virtual ~AcuArchive(void) { (void) Close(); } - // One-time initialization; returns an error string. - static CString AppInit(void); + // One-time initialization; returns an error string. + static CString AppInit(void); - virtual OpenResult Open(const char* filename, bool readOnly, - CString* pErrMsg); - virtual CString New(const char* filename, const void* options); - virtual CString Flush(void) { return ""; } - virtual CString Reload(void); - virtual bool IsReadOnly(void) const { return fIsReadOnly; }; - virtual bool IsModified(void) const { return false; } - virtual void GetDescription(CString* pStr) const { *pStr = "AppleLink ACU"; } - virtual bool BulkAdd(ActionProgressDialog* pActionProgress, - const AddFilesDialog* pAddOpts) - { ASSERT(false); return false; } - virtual bool AddDisk(ActionProgressDialog* pActionProgress, - const AddFilesDialog* pAddOpts) - { ASSERT(false); return false; } - virtual bool CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry, - const char* newName) - { ASSERT(false); return false; } - virtual bool TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); - virtual bool DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) - { ASSERT(false); return false; } - virtual bool RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) - { ASSERT(false); return false; } - virtual bool RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS, - const char* newName) - { ASSERT(false); return false; } - virtual CString TestVolumeName(const DiskFS* pDiskFS, - const char* newName) const - { ASSERT(false); return "!"; } - virtual CString TestPathName(const GenericEntry* pGenericEntry, - const CString& basePath, const CString& newName, char newFssep) const - { ASSERT(false); return "!"; } - virtual bool RecompressSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, - const RecompressOptionsDialog* pRecompOpts) - { ASSERT(false); return false; } - virtual XferStatus XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, - ActionProgressDialog* pActionProgress, const XferFileOptions* pXferOpts) - { ASSERT(false); return kXferFailed; } - virtual bool GetComment(CWnd* pMsgWnd, const GenericEntry* pEntry, - CString* pStr) - { ASSERT(false); return false; } - virtual bool SetComment(CWnd* pMsgWnd, GenericEntry* pEntry, - const CString& str) - { ASSERT(false); return false; } - virtual bool DeleteComment(CWnd* pMsgWnd, GenericEntry* pEntry) - { ASSERT(false); return false; } - virtual bool SetProps(CWnd* pMsgWnd, GenericEntry* pEntry, - const FileProps* pProps) - { ASSERT(false); return false; } - virtual void PreferencesChanged(void) {} - virtual long GetCapability(Capability cap); + virtual OpenResult Open(const char* filename, bool readOnly, + CString* pErrMsg); + virtual CString New(const char* filename, const void* options); + virtual CString Flush(void) { return ""; } + virtual CString Reload(void); + virtual bool IsReadOnly(void) const { return fIsReadOnly; }; + virtual bool IsModified(void) const { return false; } + virtual void GetDescription(CString* pStr) const { *pStr = "AppleLink ACU"; } + virtual bool BulkAdd(ActionProgressDialog* pActionProgress, + const AddFilesDialog* pAddOpts) + { ASSERT(false); return false; } + virtual bool AddDisk(ActionProgressDialog* pActionProgress, + const AddFilesDialog* pAddOpts) + { ASSERT(false); return false; } + virtual bool CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry, + const char* newName) + { ASSERT(false); return false; } + virtual bool TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); + virtual bool DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) + { ASSERT(false); return false; } + virtual bool RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) + { ASSERT(false); return false; } + virtual bool RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS, + const char* newName) + { ASSERT(false); return false; } + virtual CString TestVolumeName(const DiskFS* pDiskFS, + const char* newName) const + { ASSERT(false); return "!"; } + virtual CString TestPathName(const GenericEntry* pGenericEntry, + const CString& basePath, const CString& newName, char newFssep) const + { ASSERT(false); return "!"; } + virtual bool RecompressSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, + const RecompressOptionsDialog* pRecompOpts) + { ASSERT(false); return false; } + virtual XferStatus XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, + ActionProgressDialog* pActionProgress, const XferFileOptions* pXferOpts) + { ASSERT(false); return kXferFailed; } + virtual bool GetComment(CWnd* pMsgWnd, const GenericEntry* pEntry, + CString* pStr) + { ASSERT(false); return false; } + virtual bool SetComment(CWnd* pMsgWnd, GenericEntry* pEntry, + const CString& str) + { ASSERT(false); return false; } + virtual bool DeleteComment(CWnd* pMsgWnd, GenericEntry* pEntry) + { ASSERT(false); return false; } + virtual bool SetProps(CWnd* pMsgWnd, GenericEntry* pEntry, + const FileProps* pProps) + { ASSERT(false); return false; } + virtual void PreferencesChanged(void) {} + virtual long GetCapability(Capability cap); - friend class AcuEntry; + friend class AcuEntry; private: - virtual CString Close(void) { - if (fFp != nil) { - fclose(fFp); - fFp = nil; - } - return ""; - } - virtual void XferPrepare(const XferFileOptions* pXferOpts) - { ASSERT(false); } - virtual CString XferFile(FileDetails* pDetails, unsigned char** pDataBuf, - long dataLen, unsigned char** pRsrcBuf, long rsrcLen) - { ASSERT(false); return "!"; } - virtual void XferAbort(CWnd* pMsgWnd) - { ASSERT(false); } - virtual void XferFinish(CWnd* pMsgWnd) - { ASSERT(false); } + virtual CString Close(void) { + if (fFp != nil) { + fclose(fFp); + fFp = nil; + } + return ""; + } + virtual void XferPrepare(const XferFileOptions* pXferOpts) + { ASSERT(false); } + virtual CString XferFile(FileDetails* pDetails, unsigned char** pDataBuf, + long dataLen, unsigned char** pRsrcBuf, long rsrcLen) + { ASSERT(false); return "!"; } + virtual void XferAbort(CWnd* pMsgWnd) + { ASSERT(false); } + virtual void XferFinish(CWnd* pMsgWnd) + { ASSERT(false); } - virtual ArchiveKind GetArchiveKind(void) { return kArchiveACU; } - virtual NuError DoAddFile(const AddFilesDialog* pAddOpts, - FileDetails* pDetails) - { ASSERT(false); return kNuErrGeneric; } + virtual ArchiveKind GetArchiveKind(void) { return kArchiveACU; } + virtual NuError DoAddFile(const AddFilesDialog* pAddOpts, + FileDetails* pDetails) + { ASSERT(false); return kNuErrGeneric; } - enum { - kAcuMaxFileName = 256, // nice big number + enum { + kAcuMaxFileName = 256, // nice big number - kAcuMasterHeaderLen = 20, - kAcuEntryHeaderLen = 54, - }; + kAcuMasterHeaderLen = 20, + kAcuEntryHeaderLen = 54, + }; - /* - * The header at the front of an ACU archive. - */ - typedef struct AcuMasterHeader { - unsigned short fileCount; - unsigned short unknown1; // 0x01 00 -- might be "version 1?" - unsigned char fZink[6]; // "fZink", low ASCII - unsigned char unknown2[11]; // 0x01 36 00 00 00 00 00 00 00 00 dd - } AcuMasterHeader; + /* + * The header at the front of an ACU archive. + */ + typedef struct AcuMasterHeader { + unsigned short fileCount; + unsigned short unknown1; // 0x01 00 -- might be "version 1?" + unsigned char fZink[6]; // "fZink", low ASCII + unsigned char unknown2[11]; // 0x01 36 00 00 00 00 00 00 00 00 dd + } AcuMasterHeader; - /* - * An entry in an ACU archive. Each archive is essentially a stream - * of files; only the "filesToFollow" value gives any indication that - * something else follows this entry. - * - * We read this from the archive and then unpack the interesting parts - * into GenericEntry fields in an AcuEntry. - */ - struct AcuFileEntry; - friend struct AcuFileEntry; - typedef struct AcuFileEntry { - unsigned char compressionType; - unsigned short dataChecksum; // ?? - unsigned short blockCount; // total blocks req'd to hold file - unsigned long dataStorageLen; // length of data within archive - unsigned short access; - unsigned short fileType; - unsigned long auxType; - unsigned char storageType; - unsigned long dataEof; - unsigned short prodosModDate; - unsigned short prodosModTime; - NuDateTime modWhen; // computed from previous two fields - unsigned short prodosCreateDate; - unsigned short prodosCreateTime; - NuDateTime createWhen; // computed from previous two fields - unsigned short fileNameLen; - unsigned short headerChecksum; // ?? - char fileName[kAcuMaxFileName+1]; + /* + * An entry in an ACU archive. Each archive is essentially a stream + * of files; only the "filesToFollow" value gives any indication that + * something else follows this entry. + * + * We read this from the archive and then unpack the interesting parts + * into GenericEntry fields in an AcuEntry. + */ + struct AcuFileEntry; + friend struct AcuFileEntry; + typedef struct AcuFileEntry { + unsigned char compressionType; + unsigned short dataChecksum; // ?? + unsigned short blockCount; // total blocks req'd to hold file + unsigned long dataStorageLen; // length of data within archive + unsigned short access; + unsigned short fileType; + unsigned long auxType; + unsigned char storageType; + unsigned long dataEof; + unsigned short prodosModDate; + unsigned short prodosModTime; + NuDateTime modWhen; // computed from previous two fields + unsigned short prodosCreateDate; + unsigned short prodosCreateTime; + NuDateTime createWhen; // computed from previous two fields + unsigned short fileNameLen; + unsigned short headerChecksum; // ?? + char fileName[kAcuMaxFileName+1]; - // possibilities for mystery fields: - // - OS type (note ProDOS is $00) - // - forked file support - } AcuFileEntry; + // possibilities for mystery fields: + // - OS type (note ProDOS is $00) + // - forked file support + } AcuFileEntry; - /* known compression types */ - enum CompressionType { - kAcuCompNone = 0, - kAcuCompSqueeze = 3, - }; + /* known compression types */ + enum CompressionType { + kAcuCompNone = 0, + kAcuCompSqueeze = 3, + }; - int LoadContents(void); - int ReadMasterHeader(int* pNumEntries); - NuError ReadFileHeader(AcuFileEntry* pEntry); - void DumpFileHeader(const AcuFileEntry* pEntry); - int CreateEntry(const AcuFileEntry* pEntry); + int LoadContents(void); + int ReadMasterHeader(int* pNumEntries); + NuError ReadFileHeader(AcuFileEntry* pEntry); + void DumpFileHeader(const AcuFileEntry* pEntry); + int CreateEntry(const AcuFileEntry* pEntry); - bool IsDir(const AcuFileEntry* pEntry); - NuError AcuRead(void* buf, size_t nbyte); - NuError AcuSeek(long offset); - void AcuConvertDateTime(unsigned short prodosDate, - unsigned short prodosTime, NuDateTime* pWhen); + bool IsDir(const AcuFileEntry* pEntry); + NuError AcuRead(void* buf, size_t nbyte); + NuError AcuSeek(long offset); + void AcuConvertDateTime(unsigned short prodosDate, + unsigned short prodosTime, NuDateTime* pWhen); - FILE* fFp; - bool fIsReadOnly; + FILE* fFp; + bool fIsReadOnly; }; #endif /*__ACU_ARCHIVE__*/ \ No newline at end of file diff --git a/app/AboutDialog.cpp b/app/AboutDialog.cpp index ea3afa8..f7407a1 100644 --- a/app/AboutDialog.cpp +++ b/app/AboutDialog.cpp @@ -19,22 +19,22 @@ BEGIN_MESSAGE_MAP(AboutDialog, CDialog) - ON_BN_CLICKED(IDC_ABOUT_CREDITS, OnAboutCredits) - //ON_BN_CLICKED(IDC_ABOUT_ENTER_REG, OnEnterReg) + ON_BN_CLICKED(IDC_ABOUT_CREDITS, OnAboutCredits) + //ON_BN_CLICKED(IDC_ABOUT_ENTER_REG, OnEnterReg) END_MESSAGE_MAP() static const char* kVersionExtra = #ifdef _DEBUG - " _DEBUG" + " _DEBUG" #else - "" + "" #endif #ifdef _DEBUG_LOG - " _LOG" + " _LOG" #else - "" + "" #endif - ; + ; /* * Update the static strings with DLL version numbers. @@ -42,75 +42,75 @@ static const char* kVersionExtra = BOOL AboutDialog::OnInitDialog(void) { - NuError nerr; - long major, minor, bug; - CString newVersion, tmpStr; - CStatic* pStatic; - //CString versionFmt; + NuError nerr; + long major, minor, bug; + CString newVersion, tmpStr; + CStatic* pStatic; + //CString versionFmt; - /* CiderPress version string */ - pStatic = (CStatic*) GetDlgItem(IDC_CIDERPRESS_VERS_TEXT); - ASSERT(pStatic != nil); - pStatic->GetWindowText(tmpStr); - newVersion.Format(tmpStr, - kAppMajorVersion, kAppMinorVersion, kAppBugVersion, - kAppDevString, kVersionExtra); - pStatic->SetWindowText(newVersion); + /* CiderPress version string */ + pStatic = (CStatic*) GetDlgItem(IDC_CIDERPRESS_VERS_TEXT); + ASSERT(pStatic != nil); + pStatic->GetWindowText(tmpStr); + newVersion.Format(tmpStr, + kAppMajorVersion, kAppMinorVersion, kAppBugVersion, + kAppDevString, kVersionExtra); + pStatic->SetWindowText(newVersion); - /* grab the static text control with the NufxLib version info */ - pStatic = (CStatic*) GetDlgItem(IDC_NUFXLIB_VERS_TEXT); - ASSERT(pStatic != nil); - nerr = NuGetVersion(&major, &minor, &bug, NULL, NULL); - ASSERT(nerr == kNuErrNone); + /* grab the static text control with the NufxLib version info */ + pStatic = (CStatic*) GetDlgItem(IDC_NUFXLIB_VERS_TEXT); + ASSERT(pStatic != nil); + nerr = NuGetVersion(&major, &minor, &bug, NULL, NULL); + ASSERT(nerr == kNuErrNone); - pStatic->GetWindowText(tmpStr); - newVersion.Format(tmpStr, major, minor, bug); - pStatic->SetWindowText(newVersion); + pStatic->GetWindowText(tmpStr); + newVersion.Format(tmpStr, major, minor, bug); + pStatic->SetWindowText(newVersion); - /* grab the static text control with the DiskImg version info */ - pStatic = (CStatic*) GetDlgItem(IDC_DISKIMG_VERS_TEXT); - ASSERT(pStatic != nil); - DiskImgLib::Global::GetVersion(&major, &minor, &bug); + /* grab the static text control with the DiskImg version info */ + pStatic = (CStatic*) GetDlgItem(IDC_DISKIMG_VERS_TEXT); + ASSERT(pStatic != nil); + DiskImgLib::Global::GetVersion(&major, &minor, &bug); - pStatic->GetWindowText(tmpStr); - newVersion.Format(tmpStr, major, minor, bug); - pStatic->SetWindowText(newVersion); + pStatic->GetWindowText(tmpStr); + newVersion.Format(tmpStr, major, minor, bug); + pStatic->SetWindowText(newVersion); - /* set the zlib version */ - pStatic = (CStatic*) GetDlgItem(IDC_ZLIB_VERS_TEXT); - ASSERT(pStatic != nil); - pStatic->GetWindowText(tmpStr); - newVersion.Format(tmpStr, zlibVersion()); - pStatic->SetWindowText(newVersion); + /* set the zlib version */ + pStatic = (CStatic*) GetDlgItem(IDC_ZLIB_VERS_TEXT); + ASSERT(pStatic != nil); + pStatic->GetWindowText(tmpStr); + newVersion.Format(tmpStr, zlibVersion()); + pStatic->SetWindowText(newVersion); - /* and, finally, the ASPI version */ - pStatic = (CStatic*) GetDlgItem(IDC_ASPI_VERS_TEXT); - ASSERT(pStatic != nil); - if (DiskImgLib::Global::GetHasASPI()) { - CString versionStr; - DWORD version = DiskImgLib::Global::GetASPIVersion(); - versionStr.Format("%d.%d.%d.%d", - version & 0x0ff, - (version >> 8) & 0xff, - (version >> 16) & 0xff, - (version >> 24) & 0xff); - pStatic->GetWindowText(tmpStr); - newVersion.Format(tmpStr, versionStr); - } else { - newVersion.LoadString(IDS_ASPI_NOT_LOADED); - } - pStatic->SetWindowText(newVersion); + /* and, finally, the ASPI version */ + pStatic = (CStatic*) GetDlgItem(IDC_ASPI_VERS_TEXT); + ASSERT(pStatic != nil); + if (DiskImgLib::Global::GetHasASPI()) { + CString versionStr; + DWORD version = DiskImgLib::Global::GetASPIVersion(); + versionStr.Format("%d.%d.%d.%d", + version & 0x0ff, + (version >> 8) & 0xff, + (version >> 16) & 0xff, + (version >> 24) & 0xff); + pStatic->GetWindowText(tmpStr); + newVersion.Format(tmpStr, versionStr); + } else { + newVersion.LoadString(IDS_ASPI_NOT_LOADED); + } + pStatic->SetWindowText(newVersion); - //ShowRegistrationInfo(); - { - CWnd* pWnd = GetDlgItem(IDC_ABOUT_ENTER_REG); - if (pWnd != nil) { - pWnd->EnableWindow(FALSE); - pWnd->ShowWindow(FALSE); - } - } + //ShowRegistrationInfo(); + { + CWnd* pWnd = GetDlgItem(IDC_ABOUT_ENTER_REG); + if (pWnd != nil) { + pWnd->EnableWindow(FALSE); + pWnd->ShowWindow(FALSE); + } + } - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } #if 0 @@ -123,64 +123,64 @@ AboutDialog::OnInitDialog(void) void AboutDialog::ShowRegistrationInfo(void) { - /* - * Pull out the registration info. We shouldn't need to do much in the - * way of validation, since it should have been validated either before - * the program finished initializing or before we wrote the values into - * the registry. It's always possible that somebody went and messed with - * the registry while we were running -- perhaps a different instance of - * CiderPress -- but that should be rare enough that we don't have to - * worry about the occasional ugliness. - */ - const int kDay = 24 * 60 * 60; - CString user, company, reg, versions, expire; - CWnd* pUserWnd; - CWnd* pCompanyWnd; - //CWnd* pExpireWnd; + /* + * Pull out the registration info. We shouldn't need to do much in the + * way of validation, since it should have been validated either before + * the program finished initializing or before we wrote the values into + * the registry. It's always possible that somebody went and messed with + * the registry while we were running -- perhaps a different instance of + * CiderPress -- but that should be rare enough that we don't have to + * worry about the occasional ugliness. + */ + const int kDay = 24 * 60 * 60; + CString user, company, reg, versions, expire; + CWnd* pUserWnd; + CWnd* pCompanyWnd; + //CWnd* pExpireWnd; - pUserWnd = GetDlgItem(IDC_REG_USER_NAME); - ASSERT(pUserWnd != nil); - pCompanyWnd = GetDlgItem(IDC_REG_COMPANY_NAME); - ASSERT(pCompanyWnd != nil); - //pExpireWnd = GetDlgItem(IDC_REG_EXPIRES); - //ASSERT(pExpireWnd != nil); + pUserWnd = GetDlgItem(IDC_REG_USER_NAME); + ASSERT(pUserWnd != nil); + pCompanyWnd = GetDlgItem(IDC_REG_COMPANY_NAME); + ASSERT(pCompanyWnd != nil); + //pExpireWnd = GetDlgItem(IDC_REG_EXPIRES); + //ASSERT(pExpireWnd != nil); - if (gMyApp.fRegistry.GetRegistration(&user, &company, ®, &versions, - &expire) == 0) - { - if (reg.IsEmpty()) { - /* not registered, show blank stuff */ - CString unreg; - unreg.LoadString(IDS_ABOUT_UNREGISTERED); - pUserWnd->SetWindowText(unreg); - pCompanyWnd->SetWindowText(""); + if (gMyApp.fRegistry.GetRegistration(&user, &company, ®, &versions, + &expire) == 0) + { + if (reg.IsEmpty()) { + /* not registered, show blank stuff */ + CString unreg; + unreg.LoadString(IDS_ABOUT_UNREGISTERED); + pUserWnd->SetWindowText(unreg); + pCompanyWnd->SetWindowText(""); - /* show expire date */ - time_t expireWhen; - expireWhen = atol(expire); - if (expireWhen > 0) { - CString expireStr; - time_t now = time(nil); - expireStr.Format(IDS_REG_EVAL_REM, - ((expireWhen - now) + kDay-1) / kDay); - /* leave pUserWnd and pCompanyWnd set to defaults */ - pCompanyWnd->SetWindowText(expireStr); - } else { - pCompanyWnd->SetWindowText(_T("Has already expired!")); - } - } else { - /* show registration info */ - pUserWnd->SetWindowText(user); - pCompanyWnd->SetWindowText(company); - //pExpireWnd->SetWindowText(""); + /* show expire date */ + time_t expireWhen; + expireWhen = atol(expire); + if (expireWhen > 0) { + CString expireStr; + time_t now = time(nil); + expireStr.Format(IDS_REG_EVAL_REM, + ((expireWhen - now) + kDay-1) / kDay); + /* leave pUserWnd and pCompanyWnd set to defaults */ + pCompanyWnd->SetWindowText(expireStr); + } else { + pCompanyWnd->SetWindowText(_T("Has already expired!")); + } + } else { + /* show registration info */ + pUserWnd->SetWindowText(user); + pCompanyWnd->SetWindowText(company); + //pExpireWnd->SetWindowText(""); - /* remove "Enter Registration" button */ - CWnd* pWnd = GetDlgItem(IDC_ABOUT_ENTER_REG); - if (pWnd != nil) { - pWnd->EnableWindow(FALSE); - } - } - } + /* remove "Enter Registration" button */ + CWnd* pWnd = GetDlgItem(IDC_ABOUT_ENTER_REG); + if (pWnd != nil) { + pWnd->EnableWindow(FALSE); + } + } + } } #endif @@ -191,7 +191,7 @@ AboutDialog::ShowRegistrationInfo(void) void AboutDialog::OnAboutCredits(void) { - WinHelp(HELP_TOPIC_CREDITS, HELP_CONTEXT /*HELP_CONTEXTPOPUP*/); + WinHelp(HELP_TOPIC_CREDITS, HELP_CONTEXT /*HELP_CONTEXTPOPUP*/); } #if 0 @@ -201,8 +201,8 @@ AboutDialog::OnAboutCredits(void) void AboutDialog::OnEnterReg(void) { - if (EnterRegDialog::GetRegInfo(this) == 0) { - ShowRegistrationInfo(); - } + if (EnterRegDialog::GetRegInfo(this) == 0) { + ShowRegistrationInfo(); + } } #endif diff --git a/app/AboutDialog.h b/app/AboutDialog.h index 0785399..148c738 100644 --- a/app/AboutDialog.h +++ b/app/AboutDialog.h @@ -18,20 +18,20 @@ */ class AboutDialog : public CDialog { public: - AboutDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_ABOUTDLG, pParentWnd) - {} + AboutDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_ABOUTDLG, pParentWnd) + {} protected: - // overrides - virtual BOOL OnInitDialog(void); + // overrides + virtual BOOL OnInitDialog(void); - afx_msg void OnAboutCredits(void); - afx_msg void OnEnterReg(void); + afx_msg void OnAboutCredits(void); + afx_msg void OnEnterReg(void); - //void ShowRegistrationInfo(void); + //void ShowRegistrationInfo(void); - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__ABOUT_DIALOG__*/ \ No newline at end of file diff --git a/app/ActionProgressDialog.cpp b/app/ActionProgressDialog.cpp index 48e50d8..1ea8f6d 100644 --- a/app/ActionProgressDialog.cpp +++ b/app/ActionProgressDialog.cpp @@ -12,7 +12,7 @@ #include "Main.h" BEGIN_MESSAGE_MAP(ActionProgressDialog, ProgressCancelDialog) - //ON_MESSAGE(WMU_START, OnStart) + //ON_MESSAGE(WMU_START, OnStart) END_MESSAGE_MAP() /* @@ -21,79 +21,79 @@ END_MESSAGE_MAP() BOOL ActionProgressDialog::OnInitDialog(void) { - CDialog::OnInitDialog(); + CDialog::OnInitDialog(); - WMSG1("Action is %d\n", fAction); + WMSG1("Action is %d\n", fAction); - CenterWindow(AfxGetMainWnd()); + CenterWindow(AfxGetMainWnd()); - CWnd* pWnd; + CWnd* pWnd; - // clear the filename fields - pWnd = GetDlgItem(IDC_PROG_ARC_NAME); - ASSERT(pWnd != nil); - pWnd->SetWindowText(_T("-")); - pWnd = GetDlgItem(IDC_PROG_FILE_NAME); - ASSERT(pWnd != nil); - pWnd->SetWindowText(_T("-")); + // clear the filename fields + pWnd = GetDlgItem(IDC_PROG_ARC_NAME); + ASSERT(pWnd != nil); + pWnd->SetWindowText(_T("-")); + pWnd = GetDlgItem(IDC_PROG_FILE_NAME); + ASSERT(pWnd != nil); + pWnd->SetWindowText(_T("-")); - pWnd->SetFocus(); // get the focus off the Cancel button + pWnd->SetFocus(); // get the focus off the Cancel button - if (fAction == kActionExtract) { - /* defaults are correct */ - } else if (fAction == kActionRecompress) { - CString tmpStr; - pWnd = GetDlgItem(IDC_PROG_VERB); - ASSERT(pWnd != nil); - tmpStr.LoadString(IDS_NOW_EXPANDING); - pWnd->SetWindowText(tmpStr); + if (fAction == kActionExtract) { + /* defaults are correct */ + } else if (fAction == kActionRecompress) { + CString tmpStr; + pWnd = GetDlgItem(IDC_PROG_VERB); + ASSERT(pWnd != nil); + tmpStr.LoadString(IDS_NOW_EXPANDING); + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_PROG_TOFROM); - ASSERT(pWnd != nil); - tmpStr.LoadString(IDS_NOW_COMPRESSING); - pWnd->SetWindowText(tmpStr); - } else if (fAction == kActionAdd || fAction == kActionAddDisk || - fAction == kActionConvFile || fAction == kActionConvDisk) - { - CString tmpStr; - pWnd = GetDlgItem(IDC_PROG_VERB); - ASSERT(pWnd != nil); - tmpStr.LoadString(IDS_NOW_ADDING); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_PROG_TOFROM); + ASSERT(pWnd != nil); + tmpStr.LoadString(IDS_NOW_COMPRESSING); + pWnd->SetWindowText(tmpStr); + } else if (fAction == kActionAdd || fAction == kActionAddDisk || + fAction == kActionConvFile || fAction == kActionConvDisk) + { + CString tmpStr; + pWnd = GetDlgItem(IDC_PROG_VERB); + ASSERT(pWnd != nil); + tmpStr.LoadString(IDS_NOW_ADDING); + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_PROG_TOFROM); - ASSERT(pWnd != nil); - tmpStr.LoadString(IDS_ADDING_AS); - pWnd->SetWindowText(tmpStr); - } else if (fAction == kActionDelete) { - CString tmpStr; - pWnd = GetDlgItem(IDC_PROG_VERB); - ASSERT(pWnd != nil); - tmpStr.LoadString(IDS_NOW_DELETING); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_PROG_TOFROM); + ASSERT(pWnd != nil); + tmpStr.LoadString(IDS_ADDING_AS); + pWnd->SetWindowText(tmpStr); + } else if (fAction == kActionDelete) { + CString tmpStr; + pWnd = GetDlgItem(IDC_PROG_VERB); + ASSERT(pWnd != nil); + tmpStr.LoadString(IDS_NOW_DELETING); + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_PROG_TOFROM); - pWnd->DestroyWindow(); - pWnd = GetDlgItem(IDC_PROG_FILE_NAME); - ASSERT(pWnd != nil); - pWnd->SetWindowText(_T("")); - } else if (fAction == kActionTest) { - CString tmpStr; - pWnd = GetDlgItem(IDC_PROG_VERB); - ASSERT(pWnd != nil); - tmpStr.LoadString(IDS_NOW_TESTING); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_PROG_TOFROM); + pWnd->DestroyWindow(); + pWnd = GetDlgItem(IDC_PROG_FILE_NAME); + ASSERT(pWnd != nil); + pWnd->SetWindowText(_T("")); + } else if (fAction == kActionTest) { + CString tmpStr; + pWnd = GetDlgItem(IDC_PROG_VERB); + ASSERT(pWnd != nil); + tmpStr.LoadString(IDS_NOW_TESTING); + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_PROG_TOFROM); - pWnd->DestroyWindow(); - pWnd = GetDlgItem(IDC_PROG_FILE_NAME); - ASSERT(pWnd != nil); - pWnd->SetWindowText(_T("")); - } else { - ASSERT(false); - } + pWnd = GetDlgItem(IDC_PROG_TOFROM); + pWnd->DestroyWindow(); + pWnd = GetDlgItem(IDC_PROG_FILE_NAME); + ASSERT(pWnd != nil); + pWnd->SetWindowText(_T("")); + } else { + ASSERT(false); + } - return FALSE; + return FALSE; } /* @@ -102,25 +102,25 @@ ActionProgressDialog::OnInitDialog(void) void ActionProgressDialog::SetArcName(const char* str) { - CString oldStr; + CString oldStr; - CWnd* pWnd = GetDlgItem(IDC_PROG_ARC_NAME); - ASSERT(pWnd != nil); - pWnd->GetWindowText(oldStr); - if (oldStr != str) - pWnd->SetWindowText(str); + CWnd* pWnd = GetDlgItem(IDC_PROG_ARC_NAME); + ASSERT(pWnd != nil); + pWnd->GetWindowText(oldStr); + if (oldStr != str) + pWnd->SetWindowText(str); } const CString ActionProgressDialog::GetFileName(void) { - CString str; + CString str; - CWnd* pWnd = GetDlgItem(IDC_PROG_FILE_NAME); - ASSERT(pWnd != nil); - pWnd->GetWindowText(str); + CWnd* pWnd = GetDlgItem(IDC_PROG_FILE_NAME); + ASSERT(pWnd != nil); + pWnd->GetWindowText(str); - return str; + return str; } /* @@ -129,13 +129,13 @@ ActionProgressDialog::GetFileName(void) void ActionProgressDialog::SetFileName(const char* str) { - CString oldStr; + CString oldStr; - CWnd* pWnd = GetDlgItem(IDC_PROG_FILE_NAME); - ASSERT(pWnd != nil); - pWnd->GetWindowText(oldStr); - if (oldStr != str) - pWnd->SetWindowText(str); + CWnd* pWnd = GetDlgItem(IDC_PROG_FILE_NAME); + ASSERT(pWnd != nil); + pWnd->GetWindowText(oldStr); + if (oldStr != str) + pWnd->SetWindowText(str); } /* @@ -146,12 +146,12 @@ ActionProgressDialog::SetFileName(const char* str) int ActionProgressDialog::SetProgress(int perc) { - ASSERT(perc >= 0 && perc <= 100); - MainWindow* pMainWin = (MainWindow*)::AfxGetMainWnd(); + ASSERT(perc >= 0 && perc <= 100); + MainWindow* pMainWin = (MainWindow*)::AfxGetMainWnd(); - /* solicit input */ - pMainWin->PeekAndPump(); + /* solicit input */ + pMainWin->PeekAndPump(); - return ProgressCancelDialog::SetProgress(perc * - (kProgressResolution/100)); + return ProgressCancelDialog::SetProgress(perc * + (kProgressResolution/100)); } diff --git a/app/ActionProgressDialog.h b/app/ActionProgressDialog.h index 1fce87c..1c3d28e 100644 --- a/app/ActionProgressDialog.h +++ b/app/ActionProgressDialog.h @@ -16,50 +16,50 @@ */ class ActionProgressDialog : public ProgressCancelDialog { public: - typedef enum { - kActionUnknown = 0, - kActionAdd, - kActionAddDisk, - kActionExtract, - kActionDelete, - kActionTest, - kActionRecompress, - kActionConvDisk, - kActionConvFile, - } Action; + typedef enum { + kActionUnknown = 0, + kActionAdd, + kActionAddDisk, + kActionExtract, + kActionDelete, + kActionTest, + kActionRecompress, + kActionConvDisk, + kActionConvFile, + } Action; - ActionProgressDialog(void) { - fAction = kActionUnknown; - //fpSelSet = nil; - //fpOptionsDlg = nil; - fCancel = false; - //fResult = 0; - } - virtual ~ActionProgressDialog(void) {} + ActionProgressDialog(void) { + fAction = kActionUnknown; + //fpSelSet = nil; + //fpOptionsDlg = nil; + fCancel = false; + //fResult = 0; + } + virtual ~ActionProgressDialog(void) {} - BOOL Create(Action action, CWnd* pParentWnd = NULL) { - fAction = action; - pParentWnd->EnableWindow(FALSE); - return ProgressCancelDialog::Create(&fCancel, IDD_ACTION_PROGRESS, - IDC_PROG_PROGRESS, pParentWnd); - } - void Cleanup(CWnd* pParentWnd) { - pParentWnd->EnableWindow(TRUE); - DestroyWindow(); - } + BOOL Create(Action action, CWnd* pParentWnd = NULL) { + fAction = action; + pParentWnd->EnableWindow(FALSE); + return ProgressCancelDialog::Create(&fCancel, IDD_ACTION_PROGRESS, + IDC_PROG_PROGRESS, pParentWnd); + } + void Cleanup(CWnd* pParentWnd) { + pParentWnd->EnableWindow(TRUE); + DestroyWindow(); + } - void SetArcName(const char* str); - void SetFileName(const char* str); - const CString GetFileName(void); - int SetProgress(int perc); + void SetArcName(const char* str); + void SetFileName(const char* str); + const CString GetFileName(void); + int SetProgress(int perc); private: - virtual BOOL OnInitDialog(void); + virtual BOOL OnInitDialog(void); - Action fAction; - bool fCancel; + Action fAction; + bool fCancel; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__ACTIONPROGRESSDIALOG__*/ diff --git a/app/Actions.cpp b/app/Actions.cpp index 335a720..de08b49 100644 --- a/app/Actions.cpp +++ b/app/Actions.cpp @@ -38,7 +38,7 @@ /* * ========================================================================== - * View + * View * ========================================================================== */ @@ -51,13 +51,13 @@ void MainWindow::OnActionsView(void) { - HandleView(); + HandleView(); } void MainWindow::OnUpdateActionsView(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil && - fpContentList->GetSelectedCount() > 0); + pCmdUI->Enable(fpContentList != nil && + fpContentList->GetSelectedCount() > 0); } @@ -73,43 +73,43 @@ MainWindow::OnUpdateActionsView(CCmdUI* pCmdUI) void MainWindow::HandleView(void) { - ASSERT(fpContentList != nil); + ASSERT(fpContentList != nil); - SelectionSet selSet; - int threadMask = GenericEntry::kAnyThread | GenericEntry::kAllowDamaged | - GenericEntry::kAllowDirectory | GenericEntry::kAllowVolumeDir; - selSet.CreateFromSelection(fpContentList, threadMask); - selSet.Dump(); + SelectionSet selSet; + int threadMask = GenericEntry::kAnyThread | GenericEntry::kAllowDamaged | + GenericEntry::kAllowDirectory | GenericEntry::kAllowVolumeDir; + selSet.CreateFromSelection(fpContentList, threadMask); + selSet.Dump(); - if (selSet.GetNumEntries() == 0) { - MessageBox("Nothing viewable found.", - "No match", MB_OK | MB_ICONEXCLAMATION); - return; - } + if (selSet.GetNumEntries() == 0) { + MessageBox("Nothing viewable found.", + "No match", MB_OK | MB_ICONEXCLAMATION); + return; + } - //fpSelSet = &selSet; + //fpSelSet = &selSet; - ViewFilesDialog vfd(this); - vfd.SetSelectionSet(&selSet); - vfd.SetTextTypeFace(fPreferences.GetPrefString(kPrViewTextTypeFace)); - vfd.SetTextPointSize(fPreferences.GetPrefLong(kPrViewTextPointSize)); - vfd.SetNoWrapText(fPreferences.GetPrefBool(kPrNoWrapText)); - vfd.DoModal(); + ViewFilesDialog vfd(this); + vfd.SetSelectionSet(&selSet); + vfd.SetTextTypeFace(fPreferences.GetPrefString(kPrViewTextTypeFace)); + vfd.SetTextPointSize(fPreferences.GetPrefLong(kPrViewTextPointSize)); + vfd.SetNoWrapText(fPreferences.GetPrefBool(kPrNoWrapText)); + vfd.DoModal(); - //fpSelSet = nil; + //fpSelSet = nil; - // remember which font they used (sticky pref, not in registry) - fPreferences.SetPrefString(kPrViewTextTypeFace, vfd.GetTextTypeFace()); - fPreferences.SetPrefLong(kPrViewTextPointSize, vfd.GetTextPointSize()); - WMSG2("Preferences: saving view font %d-point '%s'\n", - fPreferences.GetPrefLong(kPrViewTextPointSize), - fPreferences.GetPrefString(kPrViewTextTypeFace)); + // remember which font they used (sticky pref, not in registry) + fPreferences.SetPrefString(kPrViewTextTypeFace, vfd.GetTextTypeFace()); + fPreferences.SetPrefLong(kPrViewTextPointSize, vfd.GetTextPointSize()); + WMSG2("Preferences: saving view font %d-point '%s'\n", + fPreferences.GetPrefLong(kPrViewTextPointSize), + fPreferences.GetPrefString(kPrViewTextTypeFace)); } /* * ========================================================================== - * Open as disk image + * Open as disk image * ========================================================================== */ @@ -122,38 +122,38 @@ MainWindow::HandleView(void) void MainWindow::OnActionsOpenAsDisk(void) { - ASSERT(fpContentList != nil); - ASSERT(fpContentList->GetSelectedCount() == 1); + ASSERT(fpContentList != nil); + ASSERT(fpContentList->GetSelectedCount() == 1); - GenericEntry* pEntry = GetSelectedItem(fpContentList); - if (pEntry->GetHasDiskImage()) - TmpExtractAndOpen(pEntry, GenericEntry::kDiskImageThread, kModeDiskImage); - else - TmpExtractAndOpen(pEntry, GenericEntry::kDataThread, kModeDiskImage); + GenericEntry* pEntry = GetSelectedItem(fpContentList); + if (pEntry->GetHasDiskImage()) + TmpExtractAndOpen(pEntry, GenericEntry::kDiskImageThread, kModeDiskImage); + else + TmpExtractAndOpen(pEntry, GenericEntry::kDataThread, kModeDiskImage); } void MainWindow::OnUpdateActionsOpenAsDisk(CCmdUI* pCmdUI) { - const int kMinLen = 512 * 7; - bool allow = false; + const int kMinLen = 512 * 7; + bool allow = false; - if (fpContentList != nil && fpContentList->GetSelectedCount() == 1) { - GenericEntry* pEntry = GetSelectedItem(fpContentList); - if (pEntry != nil) { - if ((pEntry->GetHasDataFork() || pEntry->GetHasDiskImage()) && - pEntry->GetUncompressedLen() > kMinLen) - { - allow = true; - } - } - } - pCmdUI->Enable(allow); + if (fpContentList != nil && fpContentList->GetSelectedCount() == 1) { + GenericEntry* pEntry = GetSelectedItem(fpContentList); + if (pEntry != nil) { + if ((pEntry->GetHasDataFork() || pEntry->GetHasDiskImage()) && + pEntry->GetUncompressedLen() > kMinLen) + { + allow = true; + } + } + } + pCmdUI->Enable(allow); } /* * ========================================================================== - * Add Files + * Add Files * ========================================================================== */ @@ -163,113 +163,113 @@ MainWindow::OnUpdateActionsOpenAsDisk(CCmdUI* pCmdUI) void MainWindow::OnActionsAddFiles(void) { - WMSG0("Add files!\n"); - AddFilesDialog addFiles(this); - DiskImgLib::A2File* pTargetSubdir = nil; + WMSG0("Add files!\n"); + AddFilesDialog addFiles(this); + DiskImgLib::A2File* pTargetSubdir = nil; - /* - * Special handling for adding files to disk images. - */ - if (fpOpenArchive->GetArchiveKind() == GenericArchive::kArchiveDiskImage) - { - if (!ChooseAddTarget(&pTargetSubdir, &addFiles.fpTargetDiskFS)) - return; - } + /* + * Special handling for adding files to disk images. + */ + if (fpOpenArchive->GetArchiveKind() == GenericArchive::kArchiveDiskImage) + { + if (!ChooseAddTarget(&pTargetSubdir, &addFiles.fpTargetDiskFS)) + return; + } - addFiles.fStoragePrefix = ""; - addFiles.fIncludeSubfolders = - fPreferences.GetPrefBool(kPrAddIncludeSubFolders); - addFiles.fStripFolderNames = - fPreferences.GetPrefBool(kPrAddStripFolderNames); - addFiles.fOverwriteExisting = - fPreferences.GetPrefBool(kPrAddOverwriteExisting); - addFiles.fTypePreservation = - fPreferences.GetPrefLong(kPrAddTypePreservation); - addFiles.fConvEOL = - fPreferences.GetPrefLong(kPrAddConvEOL); + addFiles.fStoragePrefix = ""; + addFiles.fIncludeSubfolders = + fPreferences.GetPrefBool(kPrAddIncludeSubFolders); + addFiles.fStripFolderNames = + fPreferences.GetPrefBool(kPrAddStripFolderNames); + addFiles.fOverwriteExisting = + fPreferences.GetPrefBool(kPrAddOverwriteExisting); + addFiles.fTypePreservation = + fPreferences.GetPrefLong(kPrAddTypePreservation); + addFiles.fConvEOL = + fPreferences.GetPrefLong(kPrAddConvEOL); - /* if they can't convert EOL when adding files, disable the option */ - if (!fpOpenArchive->GetCapability(GenericArchive::kCapCanConvEOLOnAdd)) { - addFiles.fConvEOL = AddFilesDialog::kConvEOLNone; - addFiles.fConvEOLEnable = false; - } + /* if they can't convert EOL when adding files, disable the option */ + if (!fpOpenArchive->GetCapability(GenericArchive::kCapCanConvEOLOnAdd)) { + addFiles.fConvEOL = AddFilesDialog::kConvEOLNone; + addFiles.fConvEOLEnable = false; + } - /* - * Disable editing of the storage prefix field. Force pathname - * stripping to be on for non-hierarchical filesystems (i.e. everything - * but ProDOS and HFS). - */ - if (addFiles.fpTargetDiskFS != nil) { - DiskImg::FSFormat format; - format = addFiles.fpTargetDiskFS->GetDiskImg()->GetFSFormat(); + /* + * Disable editing of the storage prefix field. Force pathname + * stripping to be on for non-hierarchical filesystems (i.e. everything + * but ProDOS and HFS). + */ + if (addFiles.fpTargetDiskFS != nil) { + DiskImg::FSFormat format; + format = addFiles.fpTargetDiskFS->GetDiskImg()->GetFSFormat(); - if (pTargetSubdir != nil) { - ASSERT(!pTargetSubdir->IsVolumeDirectory()); - addFiles.fStoragePrefix = pTargetSubdir->GetPathName(); - } + if (pTargetSubdir != nil) { + ASSERT(!pTargetSubdir->IsVolumeDirectory()); + addFiles.fStoragePrefix = pTargetSubdir->GetPathName(); + } - addFiles.fStripFolderNamesEnable = false; - addFiles.fStoragePrefixEnable = false; - switch (format) { - case DiskImg::kFormatProDOS: - case DiskImg::kFormatMacHFS: - addFiles.fStripFolderNamesEnable = true; - break; - default: - break; - } - } - if (!addFiles.fStripFolderNamesEnable) { - /* if we disabled it, we did so because it's mandatory */ - addFiles.fStripFolderNames = true; - } + addFiles.fStripFolderNamesEnable = false; + addFiles.fStoragePrefixEnable = false; + switch (format) { + case DiskImg::kFormatProDOS: + case DiskImg::kFormatMacHFS: + addFiles.fStripFolderNamesEnable = true; + break; + default: + break; + } + } + if (!addFiles.fStripFolderNamesEnable) { + /* if we disabled it, we did so because it's mandatory */ + addFiles.fStripFolderNames = true; + } - addFiles.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrAddFileFolder); + addFiles.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrAddFileFolder); - addFiles.DoModal(); - if (addFiles.GetExitStatus() == IDOK) { - fPreferences.SetPrefBool(kPrAddIncludeSubFolders, - addFiles.fIncludeSubfolders != 0); - if (addFiles.fStripFolderNamesEnable) { - // only update the pref if they had the ability to change it - fPreferences.SetPrefBool(kPrAddStripFolderNames, - addFiles.fStripFolderNames != 0); - } - fPreferences.SetPrefBool(kPrAddOverwriteExisting, - addFiles.fOverwriteExisting != 0); - fPreferences.SetPrefLong(kPrAddTypePreservation, - addFiles.fTypePreservation); - if (addFiles.fConvEOLEnable) - fPreferences.SetPrefLong(kPrAddConvEOL, - addFiles.fConvEOL); + addFiles.DoModal(); + if (addFiles.GetExitStatus() == IDOK) { + fPreferences.SetPrefBool(kPrAddIncludeSubFolders, + addFiles.fIncludeSubfolders != 0); + if (addFiles.fStripFolderNamesEnable) { + // only update the pref if they had the ability to change it + fPreferences.SetPrefBool(kPrAddStripFolderNames, + addFiles.fStripFolderNames != 0); + } + fPreferences.SetPrefBool(kPrAddOverwriteExisting, + addFiles.fOverwriteExisting != 0); + fPreferences.SetPrefLong(kPrAddTypePreservation, + addFiles.fTypePreservation); + if (addFiles.fConvEOLEnable) + fPreferences.SetPrefLong(kPrAddConvEOL, + addFiles.fConvEOL); - CString saveFolder = addFiles.GetFileNames(); - saveFolder = saveFolder.Left(addFiles.GetFileNameOffset()); - fPreferences.SetPrefString(kPrAddFileFolder, saveFolder); + CString saveFolder = addFiles.GetFileNames(); + saveFolder = saveFolder.Left(addFiles.GetFileNameOffset()); + fPreferences.SetPrefString(kPrAddFileFolder, saveFolder); - /* - * Set up a progress dialog and kick things off. - */ - bool result; - fpActionProgress = new ActionProgressDialog; - fpActionProgress->Create(ActionProgressDialog::kActionAdd, this); + /* + * Set up a progress dialog and kick things off. + */ + bool result; + fpActionProgress = new ActionProgressDialog; + fpActionProgress->Create(ActionProgressDialog::kActionAdd, this); - //fpContentList->Invalidate(); // don't allow redraws until done - result = fpOpenArchive->BulkAdd(fpActionProgress, &addFiles); - fpContentList->Reload(); + //fpContentList->Invalidate(); // don't allow redraws until done + result = fpOpenArchive->BulkAdd(fpActionProgress, &addFiles); + fpContentList->Reload(); - fpActionProgress->Cleanup(this); - fpActionProgress = nil; - if (result) - SuccessBeep(); - } else { - WMSG0("SFD bailed with Cancel\n"); - } + fpActionProgress->Cleanup(this); + fpActionProgress = nil; + if (result) + SuccessBeep(); + } else { + WMSG0("SFD bailed with Cancel\n"); + } } void MainWindow::OnUpdateActionsAddFiles(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly()); + pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly()); } @@ -281,63 +281,63 @@ MainWindow::OnUpdateActionsAddFiles(CCmdUI* pCmdUI) */ bool MainWindow::ChooseAddTarget(DiskImgLib::A2File** ppTargetSubdir, - DiskImgLib::DiskFS** ppTargetDiskFS) + DiskImgLib::DiskFS** ppTargetDiskFS) { - ASSERT(ppTargetSubdir != nil); - ASSERT(ppTargetDiskFS != nil); + ASSERT(ppTargetSubdir != nil); + ASSERT(ppTargetDiskFS != nil); - *ppTargetSubdir = nil; - *ppTargetDiskFS = nil; + *ppTargetSubdir = nil; + *ppTargetDiskFS = nil; - GenericEntry* pEntry = GetSelectedItem(fpContentList); - if (pEntry != nil && - (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory || - pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir)) - { - /* - * They've selected a single subdirectory. Add the files there. - */ - DiskEntry* pDiskEntry = (DiskEntry*) pEntry; - *ppTargetSubdir = pDiskEntry->GetA2File(); - *ppTargetDiskFS = (*ppTargetSubdir)->GetDiskFS(); - } else { - /* - * Nothing selected, non-subdir selected, or multiple files - * selected. Whatever the case, pop up the choose target dialog. - * - * This works on DOS 3.3 and Pascal disks, because the absence - * of subdirectories means there's only one possible place to - * put the files. We could short-circuit this code for anything - * but ProDOS and HFS, but we have to be careful about embedded - * sub-volumes. - */ - DiskArchive* pDiskArchive = (DiskArchive*) fpOpenArchive; + GenericEntry* pEntry = GetSelectedItem(fpContentList); + if (pEntry != nil && + (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory || + pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir)) + { + /* + * They've selected a single subdirectory. Add the files there. + */ + DiskEntry* pDiskEntry = (DiskEntry*) pEntry; + *ppTargetSubdir = pDiskEntry->GetA2File(); + *ppTargetDiskFS = (*ppTargetSubdir)->GetDiskFS(); + } else { + /* + * Nothing selected, non-subdir selected, or multiple files + * selected. Whatever the case, pop up the choose target dialog. + * + * This works on DOS 3.3 and Pascal disks, because the absence + * of subdirectories means there's only one possible place to + * put the files. We could short-circuit this code for anything + * but ProDOS and HFS, but we have to be careful about embedded + * sub-volumes. + */ + DiskArchive* pDiskArchive = (DiskArchive*) fpOpenArchive; - WMSG0("Trying ChooseAddTarget\n"); + WMSG0("Trying ChooseAddTarget\n"); - ChooseAddTargetDialog targetDialog(this); - targetDialog.fpDiskFS = pDiskArchive->GetDiskFS(); - if (targetDialog.DoModal() != IDOK) - return false; + ChooseAddTargetDialog targetDialog(this); + targetDialog.fpDiskFS = pDiskArchive->GetDiskFS(); + if (targetDialog.DoModal() != IDOK) + return false; - *ppTargetSubdir = targetDialog.fpChosenSubdir; - *ppTargetDiskFS = targetDialog.fpChosenDiskFS; + *ppTargetSubdir = targetDialog.fpChosenSubdir; + *ppTargetDiskFS = targetDialog.fpChosenDiskFS; - /* make sure the subdir is part of the diskfs */ - ASSERT(*ppTargetSubdir == nil || - (*ppTargetSubdir)->GetDiskFS() == *ppTargetDiskFS); - } + /* make sure the subdir is part of the diskfs */ + ASSERT(*ppTargetSubdir == nil || + (*ppTargetSubdir)->GetDiskFS() == *ppTargetDiskFS); + } - if (*ppTargetSubdir != nil && (*ppTargetSubdir)->IsVolumeDirectory()) - *ppTargetSubdir = nil; + if (*ppTargetSubdir != nil && (*ppTargetSubdir)->IsVolumeDirectory()) + *ppTargetSubdir = nil; - return true; + return true; } /* * ========================================================================== - * Add Disks + * Add Disks * ========================================================================== */ @@ -351,155 +351,155 @@ MainWindow::ChooseAddTarget(DiskImgLib::A2File** ppTargetSubdir, void MainWindow::OnActionsAddDisks(void) { - DIError dierr; - DiskImg img; - CString failed, errMsg; - CString openFilters, saveFolder; - AddFilesDialog addOpts; + DIError dierr; + DiskImg img; + CString failed, errMsg; + CString openFilters, saveFolder; + AddFilesDialog addOpts; - WMSG0("Add disks!\n"); + WMSG0("Add disks!\n"); - failed.LoadString(IDS_FAILED); + failed.LoadString(IDS_FAILED); - openFilters = kOpenDiskImage; - openFilters += kOpenAll; - openFilters += kOpenEnd; - CFileDialog dlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); - dlg.m_ofn.lpstrTitle = "Add Disk Image"; + openFilters = kOpenDiskImage; + openFilters += kOpenAll; + openFilters += kOpenEnd; + CFileDialog dlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); + dlg.m_ofn.lpstrTitle = "Add Disk Image"; - /* file is always opened read-only */ - dlg.m_ofn.Flags |= OFN_HIDEREADONLY; - dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrAddFileFolder); + /* file is always opened read-only */ + dlg.m_ofn.Flags |= OFN_HIDEREADONLY; + dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrAddFileFolder); - if (dlg.DoModal() != IDOK) - goto bail; + if (dlg.DoModal() != IDOK) + goto bail; - saveFolder = dlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrAddFileFolder, saveFolder); + saveFolder = dlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrAddFileFolder, saveFolder); - /* open the image file and analyze it */ - dierr = img.OpenImage(dlg.GetPathName(), PathProposal::kLocalFssep, true); - if (dierr != kDIErrNone) { - errMsg.Format("Unable to open disk image: %s.", - DiskImgLib::DIStrError(dierr)); - MessageBox(errMsg, failed, MB_OK|MB_ICONSTOP); - goto bail; - } + /* open the image file and analyze it */ + dierr = img.OpenImage(dlg.GetPathName(), PathProposal::kLocalFssep, true); + if (dierr != kDIErrNone) { + errMsg.Format("Unable to open disk image: %s.", + DiskImgLib::DIStrError(dierr)); + MessageBox(errMsg, failed, MB_OK|MB_ICONSTOP); + goto bail; + } - if (img.AnalyzeImage() != kDIErrNone) { - errMsg.Format("The file '%s' doesn't seem to hold a valid disk image.", - dlg.GetPathName()); - MessageBox(errMsg, failed, MB_OK|MB_ICONSTOP); - goto bail; - } + if (img.AnalyzeImage() != kDIErrNone) { + errMsg.Format("The file '%s' doesn't seem to hold a valid disk image.", + dlg.GetPathName()); + MessageBox(errMsg, failed, MB_OK|MB_ICONSTOP); + goto bail; + } - /* if requested (or necessary), verify the format */ - if (/*img.GetFSFormat() == DiskImg::kFormatUnknown ||*/ - img.GetSectorOrder() == DiskImg::kSectorOrderUnknown || - fPreferences.GetPrefBool(kPrQueryImageFormat)) - { - ImageFormatDialog imf; + /* if requested (or necessary), verify the format */ + if (/*img.GetFSFormat() == DiskImg::kFormatUnknown ||*/ + img.GetSectorOrder() == DiskImg::kSectorOrderUnknown || + fPreferences.GetPrefBool(kPrQueryImageFormat)) + { + ImageFormatDialog imf; - imf.InitializeValues(&img); - imf.fFileSource = dlg.GetPathName(); - imf.SetQueryDisplayFormat(false); + imf.InitializeValues(&img); + imf.fFileSource = dlg.GetPathName(); + imf.SetQueryDisplayFormat(false); - WMSG2(" On entry, sectord=%d format=%d\n", - imf.fSectorOrder, imf.fFSFormat); - if (imf.fFSFormat == DiskImg::kFormatUnknown) - imf.fFSFormat = DiskImg::kFormatGenericProDOSOrd; + WMSG2(" On entry, sectord=%d format=%d\n", + imf.fSectorOrder, imf.fFSFormat); + if (imf.fFSFormat == DiskImg::kFormatUnknown) + imf.fFSFormat = DiskImg::kFormatGenericProDOSOrd; - if (imf.DoModal() != IDOK) { - WMSG0("User bailed on IMF dialog\n"); - goto bail; - } + if (imf.DoModal() != IDOK) { + WMSG0("User bailed on IMF dialog\n"); + goto bail; + } - WMSG2(" On exit, sectord=%d format=%d\n", - imf.fSectorOrder, imf.fFSFormat); + WMSG2(" On exit, sectord=%d format=%d\n", + imf.fSectorOrder, imf.fFSFormat); - if (imf.fSectorOrder != img.GetSectorOrder() || - imf.fFSFormat != img.GetFSFormat()) - { - WMSG0("Initial values overridden, forcing img format\n"); - dierr = img.OverrideFormat(img.GetPhysicalFormat(), imf.fFSFormat, - imf.fSectorOrder); - if (dierr != kDIErrNone) { - errMsg.Format("Unable to access disk image using selected" - " parameters. Error: %s.", - DiskImgLib::DIStrError(dierr)); - MessageBox(errMsg, failed, MB_OK | MB_ICONSTOP); - goto bail; - } - } - } + if (imf.fSectorOrder != img.GetSectorOrder() || + imf.fFSFormat != img.GetFSFormat()) + { + WMSG0("Initial values overridden, forcing img format\n"); + dierr = img.OverrideFormat(img.GetPhysicalFormat(), imf.fFSFormat, + imf.fSectorOrder); + if (dierr != kDIErrNone) { + errMsg.Format("Unable to access disk image using selected" + " parameters. Error: %s.", + DiskImgLib::DIStrError(dierr)); + MessageBox(errMsg, failed, MB_OK | MB_ICONSTOP); + goto bail; + } + } + } - /* - * We want to read from the image the way that a ProDOS application - * would, which means forcing the FSFormat to generic ProDOS ordering. - * This way, ProDOS disks load serially, and DOS 3.3 disks load with - * their sectors swapped around. - */ - dierr = img.OverrideFormat(img.GetPhysicalFormat(), - DiskImg::kFormatGenericProDOSOrd, img.GetSectorOrder()); - if (dierr != kDIErrNone) { - errMsg.Format("Internal error: couldn't switch to generic ProDOS: %s.", - DiskImgLib::DIStrError(dierr)); - MessageBox(errMsg, failed, MB_OK | MB_ICONSTOP); - goto bail; - } + /* + * We want to read from the image the way that a ProDOS application + * would, which means forcing the FSFormat to generic ProDOS ordering. + * This way, ProDOS disks load serially, and DOS 3.3 disks load with + * their sectors swapped around. + */ + dierr = img.OverrideFormat(img.GetPhysicalFormat(), + DiskImg::kFormatGenericProDOSOrd, img.GetSectorOrder()); + if (dierr != kDIErrNone) { + errMsg.Format("Internal error: couldn't switch to generic ProDOS: %s.", + DiskImgLib::DIStrError(dierr)); + MessageBox(errMsg, failed, MB_OK | MB_ICONSTOP); + goto bail; + } - /* - * Set up an AddFilesDialog, but don't actually use it as a dialog. - * Instead, we just configure the various options appropriately. - * - * To conform to multi-file-selection semantics, we need to drop a - * null byte in right after the pathname. - */ - ASSERT(dlg.m_ofn.nFileOffset > 0); - int len; - len = strlen(dlg.m_ofn.lpstrFile) + 2; - dlg.m_ofn.lpstrFile[dlg.m_ofn.nFileOffset-1] = '\0'; - addOpts.SetFileNames(dlg.m_ofn.lpstrFile, len, dlg.m_ofn.nFileOffset); - addOpts.fStoragePrefix = ""; - addOpts.fIncludeSubfolders = false; - addOpts.fStripFolderNames = false; - addOpts.fOverwriteExisting = false; - addOpts.fTypePreservation = AddFilesDialog::kPreserveTypes; - addOpts.fConvEOL = AddFilesDialog::kConvEOLNone; - addOpts.fConvEOLEnable = false; // no EOL conversion on disk images! - addOpts.fpDiskImg = &img; + /* + * Set up an AddFilesDialog, but don't actually use it as a dialog. + * Instead, we just configure the various options appropriately. + * + * To conform to multi-file-selection semantics, we need to drop a + * null byte in right after the pathname. + */ + ASSERT(dlg.m_ofn.nFileOffset > 0); + int len; + len = strlen(dlg.m_ofn.lpstrFile) + 2; + dlg.m_ofn.lpstrFile[dlg.m_ofn.nFileOffset-1] = '\0'; + addOpts.SetFileNames(dlg.m_ofn.lpstrFile, len, dlg.m_ofn.nFileOffset); + addOpts.fStoragePrefix = ""; + addOpts.fIncludeSubfolders = false; + addOpts.fStripFolderNames = false; + addOpts.fOverwriteExisting = false; + addOpts.fTypePreservation = AddFilesDialog::kPreserveTypes; + addOpts.fConvEOL = AddFilesDialog::kConvEOLNone; + addOpts.fConvEOLEnable = false; // no EOL conversion on disk images! + addOpts.fpDiskImg = &img; - bool result; + bool result; - fpActionProgress = new ActionProgressDialog; - fpActionProgress->Create(ActionProgressDialog::kActionAddDisk, this); + fpActionProgress = new ActionProgressDialog; + fpActionProgress->Create(ActionProgressDialog::kActionAddDisk, this); - //fpContentList->Invalidate(); // don't allow updates until done - result = fpOpenArchive->AddDisk(fpActionProgress, &addOpts); - fpContentList->Reload(); + //fpContentList->Invalidate(); // don't allow updates until done + result = fpOpenArchive->AddDisk(fpActionProgress, &addOpts); + fpContentList->Reload(); - fpActionProgress->Cleanup(this); - fpActionProgress = nil; + fpActionProgress->Cleanup(this); + fpActionProgress = nil; - if (result) - SuccessBeep(); + if (result) + SuccessBeep(); bail: - return; + return; } void MainWindow::OnUpdateActionsAddDisks(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() && - fpOpenArchive->GetCapability(GenericArchive::kCapCanAddDisk)); + pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() && + fpOpenArchive->GetCapability(GenericArchive::kCapCanAddDisk)); } /* * ========================================================================== - * Create Subdirectory + * Create Subdirectory * ========================================================================== */ @@ -514,69 +514,69 @@ MainWindow::OnUpdateActionsAddDisks(CCmdUI* pCmdUI) void MainWindow::OnActionsCreateSubdir(void) { - CreateSubdirDialog csDialog; + CreateSubdirDialog csDialog; - ASSERT(fpContentList != nil); - ASSERT(fpOpenArchive != nil); - ASSERT(!fpOpenArchive->IsReadOnly()); + ASSERT(fpContentList != nil); + ASSERT(fpOpenArchive != nil); + ASSERT(!fpOpenArchive->IsReadOnly()); - GenericEntry* pEntry = GetSelectedItem(fpContentList); - if (pEntry == nil) { - // can happen for no selection or multi-selection; should not be here - ASSERT(false); - return; - } - if (pEntry->GetRecordKind() != GenericEntry::kRecordKindDirectory && - pEntry->GetRecordKind() != GenericEntry::kRecordKindVolumeDir) - { - CString errMsg; - errMsg = "Please select a subdirectory."; - ShowFailureMsg(this, errMsg, IDS_MB_APP_NAME); - return; - } + GenericEntry* pEntry = GetSelectedItem(fpContentList); + if (pEntry == nil) { + // can happen for no selection or multi-selection; should not be here + ASSERT(false); + return; + } + if (pEntry->GetRecordKind() != GenericEntry::kRecordKindDirectory && + pEntry->GetRecordKind() != GenericEntry::kRecordKindVolumeDir) + { + CString errMsg; + errMsg = "Please select a subdirectory."; + ShowFailureMsg(this, errMsg, IDS_MB_APP_NAME); + return; + } - WMSG1("Creating subdir in '%s'\n", pEntry->GetPathName()); + WMSG1("Creating subdir in '%s'\n", pEntry->GetPathName()); - csDialog.fBasePath = pEntry->GetPathName(); - csDialog.fpArchive = fpOpenArchive; - csDialog.fpParentEntry = pEntry; - csDialog.fNewName = "New.Subdir"; - if (csDialog.DoModal() != IDOK) - return; + csDialog.fBasePath = pEntry->GetPathName(); + csDialog.fpArchive = fpOpenArchive; + csDialog.fpParentEntry = pEntry; + csDialog.fNewName = "New.Subdir"; + if (csDialog.DoModal() != IDOK) + return; - WMSG1("Creating '%s'\n", csDialog.fNewName); + WMSG1("Creating '%s'\n", csDialog.fNewName); - fpOpenArchive->CreateSubdir(this, pEntry, csDialog.fNewName); - fpContentList->Reload(); + fpOpenArchive->CreateSubdir(this, pEntry, csDialog.fNewName); + fpContentList->Reload(); } void MainWindow::OnUpdateActionsCreateSubdir(CCmdUI* pCmdUI) { - bool enable = fpContentList != nil && !fpOpenArchive->IsReadOnly() && - fpContentList->GetSelectedCount() == 1 && - fpOpenArchive->GetCapability(GenericArchive::kCapCanCreateSubdir); + bool enable = fpContentList != nil && !fpOpenArchive->IsReadOnly() && + fpContentList->GetSelectedCount() == 1 && + fpOpenArchive->GetCapability(GenericArchive::kCapCanCreateSubdir); - if (enable) { - /* second-level check: make sure it's a subdir */ - GenericEntry* pEntry = GetSelectedItem(fpContentList); - if (pEntry == nil) { - ASSERT(false); - return; - } - if (pEntry->GetRecordKind() != GenericEntry::kRecordKindDirectory && - pEntry->GetRecordKind() != GenericEntry::kRecordKindVolumeDir) - { - enable = false; - } - } + if (enable) { + /* second-level check: make sure it's a subdir */ + GenericEntry* pEntry = GetSelectedItem(fpContentList); + if (pEntry == nil) { + ASSERT(false); + return; + } + if (pEntry->GetRecordKind() != GenericEntry::kRecordKindDirectory && + pEntry->GetRecordKind() != GenericEntry::kRecordKindVolumeDir) + { + enable = false; + } + } - pCmdUI->Enable(enable); + pCmdUI->Enable(enable); } /* * ========================================================================== - * Extract + * Extract * ========================================================================== */ @@ -586,90 +586,90 @@ MainWindow::OnUpdateActionsCreateSubdir(CCmdUI* pCmdUI) void MainWindow::OnActionsExtract(void) { - ASSERT(fpContentList != nil); + ASSERT(fpContentList != nil); - /* - * Ask the user about various options. - */ - ExtractOptionsDialog extOpts(fpContentList->GetSelectedCount(), this); - extOpts.fExtractPath = fPreferences.GetPrefString(kPrExtractFileFolder); - extOpts.fConvEOL = fPreferences.GetPrefLong(kPrExtractConvEOL); - extOpts.fConvHighASCII = fPreferences.GetPrefBool(kPrExtractConvHighASCII); - extOpts.fIncludeDataForks = fPreferences.GetPrefBool(kPrExtractIncludeData); - extOpts.fIncludeRsrcForks = fPreferences.GetPrefBool(kPrExtractIncludeRsrc); - extOpts.fIncludeDiskImages = fPreferences.GetPrefBool(kPrExtractIncludeDisk); - extOpts.fEnableReformat = fPreferences.GetPrefBool(kPrExtractEnableReformat); - extOpts.fDiskTo2MG = fPreferences.GetPrefBool(kPrExtractDiskTo2MG); - extOpts.fAddTypePreservation = fPreferences.GetPrefBool(kPrExtractAddTypePreservation); - extOpts.fAddExtension = fPreferences.GetPrefBool(kPrExtractAddExtension); - extOpts.fStripFolderNames = fPreferences.GetPrefBool(kPrExtractStripFolderNames); - extOpts.fOverwriteExisting = fPreferences.GetPrefBool(kPrExtractOverwriteExisting); + /* + * Ask the user about various options. + */ + ExtractOptionsDialog extOpts(fpContentList->GetSelectedCount(), this); + extOpts.fExtractPath = fPreferences.GetPrefString(kPrExtractFileFolder); + extOpts.fConvEOL = fPreferences.GetPrefLong(kPrExtractConvEOL); + extOpts.fConvHighASCII = fPreferences.GetPrefBool(kPrExtractConvHighASCII); + extOpts.fIncludeDataForks = fPreferences.GetPrefBool(kPrExtractIncludeData); + extOpts.fIncludeRsrcForks = fPreferences.GetPrefBool(kPrExtractIncludeRsrc); + extOpts.fIncludeDiskImages = fPreferences.GetPrefBool(kPrExtractIncludeDisk); + extOpts.fEnableReformat = fPreferences.GetPrefBool(kPrExtractEnableReformat); + extOpts.fDiskTo2MG = fPreferences.GetPrefBool(kPrExtractDiskTo2MG); + extOpts.fAddTypePreservation = fPreferences.GetPrefBool(kPrExtractAddTypePreservation); + extOpts.fAddExtension = fPreferences.GetPrefBool(kPrExtractAddExtension); + extOpts.fStripFolderNames = fPreferences.GetPrefBool(kPrExtractStripFolderNames); + extOpts.fOverwriteExisting = fPreferences.GetPrefBool(kPrExtractOverwriteExisting); - if (fpContentList->GetSelectedCount() > 0) - extOpts.fFilesToExtract = ExtractOptionsDialog::kExtractSelection; - else - extOpts.fFilesToExtract = ExtractOptionsDialog::kExtractAll; + if (fpContentList->GetSelectedCount() > 0) + extOpts.fFilesToExtract = ExtractOptionsDialog::kExtractSelection; + else + extOpts.fFilesToExtract = ExtractOptionsDialog::kExtractAll; - if (extOpts.DoModal() != IDOK) - return; + if (extOpts.DoModal() != IDOK) + return; - if (extOpts.fExtractPath.Right(1) != "\\") - extOpts.fExtractPath += "\\"; + if (extOpts.fExtractPath.Right(1) != "\\") + extOpts.fExtractPath += "\\"; - /* push preferences back out */ - fPreferences.SetPrefString(kPrExtractFileFolder, extOpts.fExtractPath); - fPreferences.SetPrefLong(kPrExtractConvEOL, extOpts.fConvEOL); - fPreferences.SetPrefBool(kPrExtractConvHighASCII, extOpts.fConvHighASCII != 0); - fPreferences.SetPrefBool(kPrExtractIncludeData, extOpts.fIncludeDataForks != 0); - fPreferences.SetPrefBool(kPrExtractIncludeRsrc, extOpts.fIncludeRsrcForks != 0); - fPreferences.SetPrefBool(kPrExtractIncludeDisk, extOpts.fIncludeDiskImages != 0); - fPreferences.SetPrefBool(kPrExtractEnableReformat, extOpts.fEnableReformat != 0); - fPreferences.SetPrefBool(kPrExtractDiskTo2MG, extOpts.fDiskTo2MG != 0); - fPreferences.SetPrefBool(kPrExtractAddTypePreservation, extOpts.fAddTypePreservation != 0); - fPreferences.SetPrefBool(kPrExtractAddExtension, extOpts.fAddExtension != 0); - fPreferences.SetPrefBool(kPrExtractStripFolderNames, extOpts.fStripFolderNames != 0); - fPreferences.SetPrefBool(kPrExtractOverwriteExisting, extOpts.fOverwriteExisting != 0); + /* push preferences back out */ + fPreferences.SetPrefString(kPrExtractFileFolder, extOpts.fExtractPath); + fPreferences.SetPrefLong(kPrExtractConvEOL, extOpts.fConvEOL); + fPreferences.SetPrefBool(kPrExtractConvHighASCII, extOpts.fConvHighASCII != 0); + fPreferences.SetPrefBool(kPrExtractIncludeData, extOpts.fIncludeDataForks != 0); + fPreferences.SetPrefBool(kPrExtractIncludeRsrc, extOpts.fIncludeRsrcForks != 0); + fPreferences.SetPrefBool(kPrExtractIncludeDisk, extOpts.fIncludeDiskImages != 0); + fPreferences.SetPrefBool(kPrExtractEnableReformat, extOpts.fEnableReformat != 0); + fPreferences.SetPrefBool(kPrExtractDiskTo2MG, extOpts.fDiskTo2MG != 0); + fPreferences.SetPrefBool(kPrExtractAddTypePreservation, extOpts.fAddTypePreservation != 0); + fPreferences.SetPrefBool(kPrExtractAddExtension, extOpts.fAddExtension != 0); + fPreferences.SetPrefBool(kPrExtractStripFolderNames, extOpts.fStripFolderNames != 0); + fPreferences.SetPrefBool(kPrExtractOverwriteExisting, extOpts.fOverwriteExisting != 0); - WMSG1("Requested extract path is '%s'\n", extOpts.fExtractPath); + WMSG1("Requested extract path is '%s'\n", extOpts.fExtractPath); - /* - * Create a "selection set" of things to display. - */ - SelectionSet selSet; - int threadMask = 0; - if (extOpts.fIncludeDataForks) - threadMask |= GenericEntry::kDataThread; - if (extOpts.fIncludeRsrcForks) - threadMask |= GenericEntry::kRsrcThread; - if (extOpts.fIncludeDiskImages) - threadMask |= GenericEntry::kDiskImageThread; + /* + * Create a "selection set" of things to display. + */ + SelectionSet selSet; + int threadMask = 0; + if (extOpts.fIncludeDataForks) + threadMask |= GenericEntry::kDataThread; + if (extOpts.fIncludeRsrcForks) + threadMask |= GenericEntry::kRsrcThread; + if (extOpts.fIncludeDiskImages) + threadMask |= GenericEntry::kDiskImageThread; - if (extOpts.fFilesToExtract == ExtractOptionsDialog::kExtractSelection) { - selSet.CreateFromSelection(fpContentList, threadMask); - } else { - selSet.CreateFromAll(fpContentList, threadMask); - } - //selSet.Dump(); + if (extOpts.fFilesToExtract == ExtractOptionsDialog::kExtractSelection) { + selSet.CreateFromSelection(fpContentList, threadMask); + } else { + selSet.CreateFromAll(fpContentList, threadMask); + } + //selSet.Dump(); - if (selSet.GetNumEntries() == 0) { - MessageBox("No files matched the selection criteria.", - "No match", MB_OK | MB_ICONEXCLAMATION); - return; - } + if (selSet.GetNumEntries() == 0) { + MessageBox("No files matched the selection criteria.", + "No match", MB_OK | MB_ICONEXCLAMATION); + return; + } - /* - * Set up the progress dialog then do the extraction. - */ - fpActionProgress = new ActionProgressDialog; - fpActionProgress->Create(ActionProgressDialog::kActionExtract, this); - DoBulkExtract(&selSet, &extOpts); - fpActionProgress->Cleanup(this); - fpActionProgress = nil; + /* + * Set up the progress dialog then do the extraction. + */ + fpActionProgress = new ActionProgressDialog; + fpActionProgress->Create(ActionProgressDialog::kActionExtract, this); + DoBulkExtract(&selSet, &extOpts); + fpActionProgress->Cleanup(this); + fpActionProgress = nil; } void MainWindow::OnUpdateActionsExtract(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil); + pCmdUI->Enable(fpContentList != nil); } /* @@ -683,111 +683,111 @@ MainWindow::OnUpdateActionsExtract(CCmdUI* pCmdUI) */ void MainWindow::DoBulkExtract(SelectionSet* pSelSet, - const ExtractOptionsDialog* pExtOpts) + const ExtractOptionsDialog* pExtOpts) { - ReformatHolder* pHolder = nil; - bool overwriteExisting, ovwrForAll; + ReformatHolder* pHolder = nil; + bool overwriteExisting, ovwrForAll; - ASSERT(pSelSet != nil); - ASSERT(fpActionProgress != nil); + ASSERT(pSelSet != nil); + ASSERT(fpActionProgress != nil); - pSelSet->IterReset(); + pSelSet->IterReset(); - /* set up our "overwrite existing files" logic */ - overwriteExisting = ovwrForAll = (pExtOpts->fOverwriteExisting != FALSE); + /* set up our "overwrite existing files" logic */ + overwriteExisting = ovwrForAll = (pExtOpts->fOverwriteExisting != FALSE); - while (true) { - SelectionEntry* pSelEntry; - bool result; + while (true) { + SelectionEntry* pSelEntry; + bool result; - /* make sure we service events */ - PeekAndPump(); + /* make sure we service events */ + PeekAndPump(); - pSelEntry = pSelSet->IterNext(); - if (pSelEntry == nil) { - SuccessBeep(); - break; // out of while (all done!) - } + pSelEntry = pSelSet->IterNext(); + if (pSelEntry == nil) { + SuccessBeep(); + break; // out of while (all done!) + } - GenericEntry* pEntry = pSelEntry->GetEntry(); - if (pEntry->GetDamaged()) { - WMSG1("Skipping '%s' due to damage\n", pEntry->GetPathName()); - continue; - } + GenericEntry* pEntry = pSelEntry->GetEntry(); + if (pEntry->GetDamaged()) { + WMSG1("Skipping '%s' due to damage\n", pEntry->GetPathName()); + continue; + } - /* - * Extract all parts of the file -- including those we don't actually - * intend to extract to disk -- and hold them in the ReformatHolder. - * Some formats, e.g. GWP, need the resource fork to do formatting, - * so it's important to have the resource fork available even if - * we're just going to throw it away. - * - * The selection set should have screened out anything totally - * inappropriate, e.g. files with nothing but a resource fork don't - * make it into the set if we're not extracting resource forks. - * - * We only want to reformat files, not disk images, directories, - * volume dirs, etc. We have a reformatter for ProDOS directories, - * but (a) we don't explicitly extract subdirs, and (b) we'd really - * like directories to be directories so we can extract files into - * them. - */ - if (pExtOpts->ShouldTryReformat() && - (pEntry->GetRecordKind() == GenericEntry::kRecordKindFile || - pEntry->GetRecordKind() == GenericEntry::kRecordKindForkedFile)) - { - fpActionProgress->SetArcName(pEntry->GetDisplayName()); - fpActionProgress->SetFileName(_T("-")); - SET_PROGRESS_BEGIN(); + /* + * Extract all parts of the file -- including those we don't actually + * intend to extract to disk -- and hold them in the ReformatHolder. + * Some formats, e.g. GWP, need the resource fork to do formatting, + * so it's important to have the resource fork available even if + * we're just going to throw it away. + * + * The selection set should have screened out anything totally + * inappropriate, e.g. files with nothing but a resource fork don't + * make it into the set if we're not extracting resource forks. + * + * We only want to reformat files, not disk images, directories, + * volume dirs, etc. We have a reformatter for ProDOS directories, + * but (a) we don't explicitly extract subdirs, and (b) we'd really + * like directories to be directories so we can extract files into + * them. + */ + if (pExtOpts->ShouldTryReformat() && + (pEntry->GetRecordKind() == GenericEntry::kRecordKindFile || + pEntry->GetRecordKind() == GenericEntry::kRecordKindForkedFile)) + { + fpActionProgress->SetArcName(pEntry->GetDisplayName()); + fpActionProgress->SetFileName(_T("-")); + SET_PROGRESS_BEGIN(); - if (GetFileParts(pEntry, &pHolder) == 0) { - /* - * Use the prefs, but disable generic text conversion, so - * that we default to "raw". That way we will use the text - * conversion that the user has specified in the "extract" - * dialog. - * - * We might want to just disable any "always"-level - * reformatter, but that would require tweaking the reformat - * code to return "raw" when nothing applies. - */ - ConfigureReformatFromPreferences(pHolder); - pHolder->SetReformatAllowed(ReformatHolder::kReformatTextEOL_HA, - false); + if (GetFileParts(pEntry, &pHolder) == 0) { + /* + * Use the prefs, but disable generic text conversion, so + * that we default to "raw". That way we will use the text + * conversion that the user has specified in the "extract" + * dialog. + * + * We might want to just disable any "always"-level + * reformatter, but that would require tweaking the reformat + * code to return "raw" when nothing applies. + */ + ConfigureReformatFromPreferences(pHolder); + pHolder->SetReformatAllowed(ReformatHolder::kReformatTextEOL_HA, + false); - pHolder->SetSourceAttributes( - pEntry->GetFileType(), - pEntry->GetAuxType(), - ReformatterSourceFormat(pEntry->GetSourceFS()), - pEntry->GetFileNameExtension()); - pHolder->TestApplicability(); - } - } + pHolder->SetSourceAttributes( + pEntry->GetFileType(), + pEntry->GetAuxType(), + ReformatterSourceFormat(pEntry->GetSourceFS()), + pEntry->GetFileNameExtension()); + pHolder->TestApplicability(); + } + } - if (pExtOpts->fIncludeDataForks && pEntry->GetHasDataFork()) { - result = ExtractEntry(pEntry, GenericEntry::kDataThread, - pHolder, pExtOpts, &overwriteExisting, &ovwrForAll); - if (!result) - break; - } - if (pExtOpts->fIncludeRsrcForks && pEntry->GetHasRsrcFork()) { - result = ExtractEntry(pEntry, GenericEntry::kRsrcThread, - pHolder, pExtOpts, &overwriteExisting, &ovwrForAll); - if (!result) - break; - } - if (pExtOpts->fIncludeDiskImages && pEntry->GetHasDiskImage()) { - result = ExtractEntry(pEntry, GenericEntry::kDiskImageThread, - pHolder, pExtOpts, &overwriteExisting, &ovwrForAll); - if (!result) - break; - } - delete pHolder; - pHolder = nil; - } + if (pExtOpts->fIncludeDataForks && pEntry->GetHasDataFork()) { + result = ExtractEntry(pEntry, GenericEntry::kDataThread, + pHolder, pExtOpts, &overwriteExisting, &ovwrForAll); + if (!result) + break; + } + if (pExtOpts->fIncludeRsrcForks && pEntry->GetHasRsrcFork()) { + result = ExtractEntry(pEntry, GenericEntry::kRsrcThread, + pHolder, pExtOpts, &overwriteExisting, &ovwrForAll); + if (!result) + break; + } + if (pExtOpts->fIncludeDiskImages && pEntry->GetHasDiskImage()) { + result = ExtractEntry(pEntry, GenericEntry::kDiskImageThread, + pHolder, pExtOpts, &overwriteExisting, &ovwrForAll); + if (!result) + break; + } + delete pHolder; + pHolder = nil; + } - // if they cancelled, delete the "stray" - delete pHolder; + // if they cancelled, delete the "stray" + delete pHolder; } /* @@ -801,474 +801,474 @@ MainWindow::DoBulkExtract(SelectionSet* pSelSet, */ bool MainWindow::ExtractEntry(GenericEntry* pEntry, int thread, - ReformatHolder* pHolder, const ExtractOptionsDialog* pExtOpts, - bool* pOverwriteExisting, bool* pOvwrForAll) + ReformatHolder* pHolder, const ExtractOptionsDialog* pExtOpts, + bool* pOverwriteExisting, bool* pOvwrForAll) { - /* - * This first bit of setup is the same for every file. However, it's - * pretty quick, and it's easier to pass "pExtOpts" in than all of - * this stuff, so we just do it every time. - */ - GenericEntry::ConvertEOL convEOL; - GenericEntry::ConvertHighASCII convHA; - bool convTextByType = false; + /* + * This first bit of setup is the same for every file. However, it's + * pretty quick, and it's easier to pass "pExtOpts" in than all of + * this stuff, so we just do it every time. + */ + GenericEntry::ConvertEOL convEOL; + GenericEntry::ConvertHighASCII convHA; + bool convTextByType = false; - /* translate the EOL conversion mode into GenericEntry terms */ - switch (pExtOpts->fConvEOL) { - case ExtractOptionsDialog::kConvEOLNone: - convEOL = GenericEntry::kConvertEOLOff; - break; - case ExtractOptionsDialog::kConvEOLType: - convEOL = GenericEntry::kConvertEOLOff; - convTextByType = true; - break; - case ExtractOptionsDialog::kConvEOLAuto: - convEOL = GenericEntry::kConvertEOLAuto; - break; - case ExtractOptionsDialog::kConvEOLAll: - convEOL = GenericEntry::kConvertEOLOn; - break; - default: - ASSERT(false); - convEOL = GenericEntry::kConvertEOLOff; - break; - } - if (pExtOpts->fConvHighASCII) - convHA = GenericEntry::kConvertHAAuto; - else - convHA = GenericEntry::kConvertHAOff; + /* translate the EOL conversion mode into GenericEntry terms */ + switch (pExtOpts->fConvEOL) { + case ExtractOptionsDialog::kConvEOLNone: + convEOL = GenericEntry::kConvertEOLOff; + break; + case ExtractOptionsDialog::kConvEOLType: + convEOL = GenericEntry::kConvertEOLOff; + convTextByType = true; + break; + case ExtractOptionsDialog::kConvEOLAuto: + convEOL = GenericEntry::kConvertEOLAuto; + break; + case ExtractOptionsDialog::kConvEOLAll: + convEOL = GenericEntry::kConvertEOLOn; + break; + default: + ASSERT(false); + convEOL = GenericEntry::kConvertEOLOff; + break; + } + if (pExtOpts->fConvHighASCII) + convHA = GenericEntry::kConvertHAAuto; + else + convHA = GenericEntry::kConvertHAOff; - //WMSG2(" DBE initial text conversion: eol=%d ha=%d\n", - // convEOL, convHA); + //WMSG2(" DBE initial text conversion: eol=%d ha=%d\n", + // convEOL, convHA); - ReformatHolder holder; - CString outputPath; - CString failed, errMsg; - failed.LoadString(IDS_FAILED); - bool writeFailed = false; - bool extractAs2MG = false; - char* reformatText = nil; - MyDIBitmap* reformatDib = nil; + ReformatHolder holder; + CString outputPath; + CString failed, errMsg; + failed.LoadString(IDS_FAILED); + bool writeFailed = false; + bool extractAs2MG = false; + char* reformatText = nil; + MyDIBitmap* reformatDib = nil; - ASSERT(pEntry != nil); + ASSERT(pEntry != nil); - /* - * If we're interested in extracting disk images as 2MG files, - * see if we want to handle this one that way. - * - * If they said "don't extract disk images", the images should - * have been culled from the selection set earlier. - */ - if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDisk) { - ASSERT(pExtOpts->fIncludeDiskImages); - if (pExtOpts->fDiskTo2MG) { - if (pEntry->GetUncompressedLen() > 0 && - (pEntry->GetUncompressedLen() % TwoImgHeader::kBlockSize) == 0) - { - extractAs2MG = true; - } else { - WMSG2("Not extracting funky image '%s' as 2MG (len=%ld)\n", - pEntry->GetPathName(), pEntry->GetUncompressedLen()); - } - } - } + /* + * If we're interested in extracting disk images as 2MG files, + * see if we want to handle this one that way. + * + * If they said "don't extract disk images", the images should + * have been culled from the selection set earlier. + */ + if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDisk) { + ASSERT(pExtOpts->fIncludeDiskImages); + if (pExtOpts->fDiskTo2MG) { + if (pEntry->GetUncompressedLen() > 0 && + (pEntry->GetUncompressedLen() % TwoImgHeader::kBlockSize) == 0) + { + extractAs2MG = true; + } else { + WMSG2("Not extracting funky image '%s' as 2MG (len=%ld)\n", + pEntry->GetPathName(), pEntry->GetUncompressedLen()); + } + } + } - /* - * Convert the archived pathname to something suitable for the - * local machine (i.e. Win32). - */ - PathProposal pathProp; - CString convName, convNameExtd, convNameExtdPlus; - pathProp.Init(pEntry); - pathProp.fThreadKind = thread; - if (pExtOpts->fStripFolderNames) - pathProp.fJunkPaths = true; + /* + * Convert the archived pathname to something suitable for the + * local machine (i.e. Win32). + */ + PathProposal pathProp; + CString convName, convNameExtd, convNameExtdPlus; + pathProp.Init(pEntry); + pathProp.fThreadKind = thread; + if (pExtOpts->fStripFolderNames) + pathProp.fJunkPaths = true; - pathProp.ArchiveToLocal(); - convName = pathProp.fLocalPathName; + pathProp.ArchiveToLocal(); + convName = pathProp.fLocalPathName; - /* run it through again, this time with optional type preservation */ - if (pExtOpts->fAddTypePreservation) - pathProp.fPreservation = true; - pathProp.ArchiveToLocal(); - convNameExtd = pathProp.fLocalPathName; + /* run it through again, this time with optional type preservation */ + if (pExtOpts->fAddTypePreservation) + pathProp.fPreservation = true; + pathProp.ArchiveToLocal(); + convNameExtd = pathProp.fLocalPathName; - /* and a 3rd time, also taking additional extensions into account */ - if (pExtOpts->fAddExtension) - pathProp.fAddExtension = true; - pathProp.ArchiveToLocal(); - convNameExtdPlus = pathProp.fLocalPathName; + /* and a 3rd time, also taking additional extensions into account */ + if (pExtOpts->fAddExtension) + pathProp.fAddExtension = true; + pathProp.ArchiveToLocal(); + convNameExtdPlus = pathProp.fLocalPathName; - /* - * Prepend the extraction dir to the local pathname. We also add - * the sub-volume name (if any), which should already be a valid - * Win32 directory name. We can't add it earlier because the fssep - * char might be '\0'. - */ - ASSERT(pExtOpts->fExtractPath.Right(1) == "\\"); - CString adjustedExtractPath(pExtOpts->fExtractPath); - if (!pExtOpts->fStripFolderNames && pEntry->GetSubVolName() != nil) { - adjustedExtractPath += pEntry->GetSubVolName(); - adjustedExtractPath += "\\"; - } - outputPath = adjustedExtractPath; - outputPath += convNameExtdPlus; + /* + * Prepend the extraction dir to the local pathname. We also add + * the sub-volume name (if any), which should already be a valid + * Win32 directory name. We can't add it earlier because the fssep + * char might be '\0'. + */ + ASSERT(pExtOpts->fExtractPath.Right(1) == "\\"); + CString adjustedExtractPath(pExtOpts->fExtractPath); + if (!pExtOpts->fStripFolderNames && pEntry->GetSubVolName() != nil) { + adjustedExtractPath += pEntry->GetSubVolName(); + adjustedExtractPath += "\\"; + } + outputPath = adjustedExtractPath; + outputPath += convNameExtdPlus; - ReformatOutput* pOutput = nil; + ReformatOutput* pOutput = nil; - /* - * If requested, try to reformat this file. - */ - if (pHolder != nil) { - ReformatHolder::ReformatPart part = ReformatHolder::kPartUnknown; - ReformatHolder::ReformatID id; - CString title; - //int result; + /* + * If requested, try to reformat this file. + */ + if (pHolder != nil) { + ReformatHolder::ReformatPart part = ReformatHolder::kPartUnknown; + ReformatHolder::ReformatID id; + CString title; + //int result; - switch (thread) { - case GenericEntry::kDataThread: - part = ReformatHolder::kPartData; - break; - case GenericEntry::kRsrcThread: - part = ReformatHolder::kPartRsrc; - break; - case GenericEntry::kDiskImageThread: - part = ReformatHolder::kPartData; - break; - case GenericEntry::kCommentThread: - default: - assert(false); - return false; - } + switch (thread) { + case GenericEntry::kDataThread: + part = ReformatHolder::kPartData; + break; + case GenericEntry::kRsrcThread: + part = ReformatHolder::kPartRsrc; + break; + case GenericEntry::kDiskImageThread: + part = ReformatHolder::kPartData; + break; + case GenericEntry::kCommentThread: + default: + assert(false); + return false; + } - fpActionProgress->SetFileName(_T("(reformatting)")); - id = pHolder->FindBest(part); + fpActionProgress->SetFileName(_T("(reformatting)")); + id = pHolder->FindBest(part); - { - CWaitCursor waitc; - pOutput = pHolder->Apply(part, id); - } + { + CWaitCursor waitc; + pOutput = pHolder->Apply(part, id); + } - if (pOutput != nil) { - /* use output pathname without preservation */ - CString tmpPath; - bool goodReformat = true; - bool noChangePath = false; + if (pOutput != nil) { + /* use output pathname without preservation */ + CString tmpPath; + bool goodReformat = true; + bool noChangePath = false; - tmpPath = adjustedExtractPath; - tmpPath += convName; + tmpPath = adjustedExtractPath; + tmpPath += convName; - CString lastFour = tmpPath.Right(4); + CString lastFour = tmpPath.Right(4); - /* - * Tack on a file extension identifying the reformatted - * contents. If the filename already has the correct - * extension, don't tack it on again. - */ - switch (pOutput->GetOutputKind()) { - case ReformatOutput::kOutputText: - if (lastFour.CompareNoCase(".txt") != 0) - tmpPath += ".txt"; - break; - case ReformatOutput::kOutputRTF: - if (lastFour.CompareNoCase(".rtf") != 0) - tmpPath += ".rtf"; - break; - case ReformatOutput::kOutputCSV: - if (lastFour.CompareNoCase(".csv") != 0) - tmpPath += ".csv"; - break; - case ReformatOutput::kOutputBitmap: - if (lastFour.CompareNoCase(".bmp") != 0) - tmpPath += ".bmp"; - break; - case ReformatOutput::kOutputRaw: - noChangePath = true; - break; - default: - // kOutputErrorMsg, kOutputUnknown - goodReformat = false; - break; - } + /* + * Tack on a file extension identifying the reformatted + * contents. If the filename already has the correct + * extension, don't tack it on again. + */ + switch (pOutput->GetOutputKind()) { + case ReformatOutput::kOutputText: + if (lastFour.CompareNoCase(".txt") != 0) + tmpPath += ".txt"; + break; + case ReformatOutput::kOutputRTF: + if (lastFour.CompareNoCase(".rtf") != 0) + tmpPath += ".rtf"; + break; + case ReformatOutput::kOutputCSV: + if (lastFour.CompareNoCase(".csv") != 0) + tmpPath += ".csv"; + break; + case ReformatOutput::kOutputBitmap: + if (lastFour.CompareNoCase(".bmp") != 0) + tmpPath += ".bmp"; + break; + case ReformatOutput::kOutputRaw: + noChangePath = true; + break; + default: + // kOutputErrorMsg, kOutputUnknown + goodReformat = false; + break; + } - if (goodReformat) { - if (!noChangePath) - outputPath = tmpPath; - } else { - delete pOutput; - pOutput = nil; - } - } - } - if (extractAs2MG) { - /* - * Reduce to base name and add 2IMG suffix. Would be nice to keep - * the non-extended file type preservation stuff, but right now we - * only expect unadorned sectors for that (and so does NuLib2). - */ - outputPath = adjustedExtractPath; - outputPath += convName; - outputPath += ".2mg"; - } + if (goodReformat) { + if (!noChangePath) + outputPath = tmpPath; + } else { + delete pOutput; + pOutput = nil; + } + } + } + if (extractAs2MG) { + /* + * Reduce to base name and add 2IMG suffix. Would be nice to keep + * the non-extended file type preservation stuff, but right now we + * only expect unadorned sectors for that (and so does NuLib2). + */ + outputPath = adjustedExtractPath; + outputPath += convName; + outputPath += ".2mg"; + } - /* update the display in case we renamed it */ - if (outputPath != fpActionProgress->GetFileName()) { - WMSG2(" Renamed our output, from '%s' to '%s'\n", - (LPCTSTR) fpActionProgress->GetFileName(), outputPath); - fpActionProgress->SetFileName(outputPath); - } + /* update the display in case we renamed it */ + if (outputPath != fpActionProgress->GetFileName()) { + WMSG2(" Renamed our output, from '%s' to '%s'\n", + (LPCTSTR) fpActionProgress->GetFileName(), outputPath); + fpActionProgress->SetFileName(outputPath); + } - /* - * Update the progress meter output filename, and reset the thermometer. - */ - fpActionProgress->SetArcName(pathProp.fStoredPathName); - fpActionProgress->SetFileName(outputPath); - WMSG2("Extracting from '%s' to '%s'\n", - pathProp.fStoredPathName, outputPath); - SET_PROGRESS_BEGIN(); + /* + * Update the progress meter output filename, and reset the thermometer. + */ + fpActionProgress->SetArcName(pathProp.fStoredPathName); + fpActionProgress->SetFileName(outputPath); + WMSG2("Extracting from '%s' to '%s'\n", + pathProp.fStoredPathName, outputPath); + SET_PROGRESS_BEGIN(); - /* - * Open the output file. - * - * Returns IDCANCEL on failures as well as user cancellation. - */ - FILE* fp = nil; - int result; - result = OpenOutputFile(&outputPath, pathProp, pEntry->GetModWhen(), - pOverwriteExisting, pOvwrForAll, &fp); - if (result == IDCANCEL) { - // no messagebox for this one - delete pOutput; - return false; - } + /* + * Open the output file. + * + * Returns IDCANCEL on failures as well as user cancellation. + */ + FILE* fp = nil; + int result; + result = OpenOutputFile(&outputPath, pathProp, pEntry->GetModWhen(), + pOverwriteExisting, pOvwrForAll, &fp); + if (result == IDCANCEL) { + // no messagebox for this one + delete pOutput; + return false; + } - /* update the display in case they renamed the file */ - if (outputPath != fpActionProgress->GetFileName()) { - WMSG2(" Detected rename, from '%s' to '%s'\n", - (LPCTSTR) fpActionProgress->GetFileName(), outputPath); - fpActionProgress->SetFileName(outputPath); - } + /* update the display in case they renamed the file */ + if (outputPath != fpActionProgress->GetFileName()) { + WMSG2(" Detected rename, from '%s' to '%s'\n", + (LPCTSTR) fpActionProgress->GetFileName(), outputPath); + fpActionProgress->SetFileName(outputPath); + } - if (fp == nil) { - /* looks like they elected to skip extraction of this file */ - delete pOutput; - return true; - } + if (fp == nil) { + /* looks like they elected to skip extraction of this file */ + delete pOutput; + return true; + } - //EventPause(500); // DEBUG DEBUG + //EventPause(500); // DEBUG DEBUG - /* - * Handle "extract as 2MG" by writing a 2MG header to the start - * of the file before we hand off to the extraction function. - * - * NOTE: we're currently assuming that we're extracting an image - * in ProDOS sector order. This is a valid assumption so long as - * we're only pulling disk images out of ShrinkIt archives. - * - * We don't currently use the WriteFooter call here, because we're - * not adding comments. - */ - if (extractAs2MG) { - TwoImgHeader header; - header.InitHeader(TwoImgHeader::kImageFormatProDOS, - (long) pEntry->GetUncompressedLen(), - (long) (pEntry->GetUncompressedLen() / TwoImgHeader::kBlockSize)); - int err; - ASSERT(ftell(fp) == 0); - err = header.WriteHeader(fp); - if (err != 0) { - errMsg.Format("Unable to save 2MG file '%s': %s\n", - outputPath, strerror(err)); - fpActionProgress->MessageBox(errMsg, failed, - MB_OK | MB_ICONERROR); - goto open_file_fail; - } - ASSERT(ftell(fp) == 64); // size of 2MG header - } + /* + * Handle "extract as 2MG" by writing a 2MG header to the start + * of the file before we hand off to the extraction function. + * + * NOTE: we're currently assuming that we're extracting an image + * in ProDOS sector order. This is a valid assumption so long as + * we're only pulling disk images out of ShrinkIt archives. + * + * We don't currently use the WriteFooter call here, because we're + * not adding comments. + */ + if (extractAs2MG) { + TwoImgHeader header; + header.InitHeader(TwoImgHeader::kImageFormatProDOS, + (long) pEntry->GetUncompressedLen(), + (long) (pEntry->GetUncompressedLen() / TwoImgHeader::kBlockSize)); + int err; + ASSERT(ftell(fp) == 0); + err = header.WriteHeader(fp); + if (err != 0) { + errMsg.Format("Unable to save 2MG file '%s': %s\n", + outputPath, strerror(err)); + fpActionProgress->MessageBox(errMsg, failed, + MB_OK | MB_ICONERROR); + goto open_file_fail; + } + ASSERT(ftell(fp) == 64); // size of 2MG header + } - /* - * In some cases we want to override the automatic text detection. - * - * If we're in "auto" mode, force conversion on for DOS/RDOS text files. - * This is important when "convHA" is off, because in high-ASCII mode - * we might not recognize text files for what they are. We also - * consider 0x00 to be binary, which screws up random-access text. - * - * We don't want to do text conversion on disk images or resource - * forks, ever. Turn them off here. - */ - GenericEntry::ConvertEOL thisConv; - thisConv = convEOL; - if (thisConv == GenericEntry::kConvertEOLAuto) { - if (DiskImg::UsesDOSFileStructure(pEntry->GetSourceFS()) && - pEntry->GetFileType() == kFileTypeTXT) - { - WMSG0("Switching EOLAuto to EOLOn for DOS text file\n"); - thisConv = GenericEntry::kConvertEOLOn; - } - } else if (convTextByType) { - /* force it on or off when in conv-by-type mode */ - if (pEntry->GetFileType() == kFileTypeTXT || - pEntry->GetFileType() == kFileTypeSRC) - { - WMSG0("Enabling EOL conv for text file\n"); - thisConv = GenericEntry::kConvertEOLOn; - } else { - ASSERT(thisConv == GenericEntry::kConvertEOLOff); - } - } - if (thisConv != GenericEntry::kConvertEOLOff && - (thread == GenericEntry::kRsrcThread || - thread == GenericEntry::kDiskImageThread)) - { - WMSG0("Disabling EOL conv for resource fork or disk image\n"); - thisConv = GenericEntry::kConvertEOLOff; - } + /* + * In some cases we want to override the automatic text detection. + * + * If we're in "auto" mode, force conversion on for DOS/RDOS text files. + * This is important when "convHA" is off, because in high-ASCII mode + * we might not recognize text files for what they are. We also + * consider 0x00 to be binary, which screws up random-access text. + * + * We don't want to do text conversion on disk images or resource + * forks, ever. Turn them off here. + */ + GenericEntry::ConvertEOL thisConv; + thisConv = convEOL; + if (thisConv == GenericEntry::kConvertEOLAuto) { + if (DiskImg::UsesDOSFileStructure(pEntry->GetSourceFS()) && + pEntry->GetFileType() == kFileTypeTXT) + { + WMSG0("Switching EOLAuto to EOLOn for DOS text file\n"); + thisConv = GenericEntry::kConvertEOLOn; + } + } else if (convTextByType) { + /* force it on or off when in conv-by-type mode */ + if (pEntry->GetFileType() == kFileTypeTXT || + pEntry->GetFileType() == kFileTypeSRC) + { + WMSG0("Enabling EOL conv for text file\n"); + thisConv = GenericEntry::kConvertEOLOn; + } else { + ASSERT(thisConv == GenericEntry::kConvertEOLOff); + } + } + if (thisConv != GenericEntry::kConvertEOLOff && + (thread == GenericEntry::kRsrcThread || + thread == GenericEntry::kDiskImageThread)) + { + WMSG0("Disabling EOL conv for resource fork or disk image\n"); + thisConv = GenericEntry::kConvertEOLOff; + } - /* - * Extract the contents to the file. - * - * In some cases, notably when the file size exceeds the limit of - * the reformatter, we will be trying to reformat but won't have - * loaded the original data. In such cases we fall through to the - * normal extraction mode, because we threw out pOutput above when - * the result was kOutputErrorMsg. - * - * (Could also be due to extraction failure, e.g. bad CRC.) - */ - if (pOutput != nil) { - /* - * We have the data in our buffer. Write it out. No need - * to tweak the progress updater, which already shows 100%. - * - * There are four possibilities: - * - Valid text/rtf/csv converted text. Write reformatted. - * - Valid bitmap converted. Write bitmap. - * - No reformatter found, type is "raw". Write raw. (Note - * this may be zero bytes long for an empty file.) - * - Error message encoded in result. Should not be here! - */ - if (pOutput->GetOutputKind() == ReformatOutput::kOutputText || - pOutput->GetOutputKind() == ReformatOutput::kOutputRTF || - pOutput->GetOutputKind() == ReformatOutput::kOutputCSV) - { - WMSG0(" Writing text, RTF, CSV, or raw\n"); - ASSERT(pOutput->GetTextBuf() != nil); - int err = 0; - if (fwrite(pOutput->GetTextBuf(), - pOutput->GetTextLen(), 1, fp) != 1) - err = errno; - if (err != 0) { - errMsg.Format("Unable to save reformatted file '%s': %s\n", - outputPath, strerror(err)); - fpActionProgress->MessageBox(errMsg, failed, - MB_OK | MB_ICONERROR); - writeFailed = true; - } else { - SET_PROGRESS_UPDATE(100); - } - } else if (pOutput->GetOutputKind() == ReformatOutput::kOutputBitmap) { - WMSG0(" Writing bitmap\n"); - ASSERT(pOutput->GetDIB() != nil); - int err = pOutput->GetDIB()->WriteToFile(fp); - if (err != 0) { - errMsg.Format("Unable to save bitmap '%s': %s\n", - outputPath, strerror(err)); - fpActionProgress->MessageBox(errMsg, failed, - MB_OK | MB_ICONERROR); - writeFailed = true; - } else { - SET_PROGRESS_UPDATE(100); - } - } else if (pOutput->GetOutputKind() == ReformatOutput::kOutputRaw) { - /* - * Send raw data through the text conversion configured in the - * extract files dialog. Any file for which no dedicated - * reformatter could be found ends up here. - * - * We could just send it through to the generic non-reformatter - * case, but that would require reading the file twice. - */ - WMSG1(" Writing un-reformatted data (%ld bytes)\n", - pOutput->GetTextLen()); - ASSERT(pOutput->GetTextBuf() != nil); - bool lastCR = false; - GenericEntry::ConvertHighASCII thisConvHA = convHA; - int err; - err = GenericEntry::WriteConvert(fp, pOutput->GetTextBuf(), - pOutput->GetTextLen(), &thisConv, &thisConvHA, &lastCR); - if (err != 0) { - errMsg.Format("Unable to write file '%s': %s\n", - outputPath, strerror(err)); - fpActionProgress->MessageBox(errMsg, failed, - MB_OK | MB_ICONERROR); - writeFailed = true; - } else { - SET_PROGRESS_UPDATE(100); - } + /* + * Extract the contents to the file. + * + * In some cases, notably when the file size exceeds the limit of + * the reformatter, we will be trying to reformat but won't have + * loaded the original data. In such cases we fall through to the + * normal extraction mode, because we threw out pOutput above when + * the result was kOutputErrorMsg. + * + * (Could also be due to extraction failure, e.g. bad CRC.) + */ + if (pOutput != nil) { + /* + * We have the data in our buffer. Write it out. No need + * to tweak the progress updater, which already shows 100%. + * + * There are four possibilities: + * - Valid text/rtf/csv converted text. Write reformatted. + * - Valid bitmap converted. Write bitmap. + * - No reformatter found, type is "raw". Write raw. (Note + * this may be zero bytes long for an empty file.) + * - Error message encoded in result. Should not be here! + */ + if (pOutput->GetOutputKind() == ReformatOutput::kOutputText || + pOutput->GetOutputKind() == ReformatOutput::kOutputRTF || + pOutput->GetOutputKind() == ReformatOutput::kOutputCSV) + { + WMSG0(" Writing text, RTF, CSV, or raw\n"); + ASSERT(pOutput->GetTextBuf() != nil); + int err = 0; + if (fwrite(pOutput->GetTextBuf(), + pOutput->GetTextLen(), 1, fp) != 1) + err = errno; + if (err != 0) { + errMsg.Format("Unable to save reformatted file '%s': %s\n", + outputPath, strerror(err)); + fpActionProgress->MessageBox(errMsg, failed, + MB_OK | MB_ICONERROR); + writeFailed = true; + } else { + SET_PROGRESS_UPDATE(100); + } + } else if (pOutput->GetOutputKind() == ReformatOutput::kOutputBitmap) { + WMSG0(" Writing bitmap\n"); + ASSERT(pOutput->GetDIB() != nil); + int err = pOutput->GetDIB()->WriteToFile(fp); + if (err != 0) { + errMsg.Format("Unable to save bitmap '%s': %s\n", + outputPath, strerror(err)); + fpActionProgress->MessageBox(errMsg, failed, + MB_OK | MB_ICONERROR); + writeFailed = true; + } else { + SET_PROGRESS_UPDATE(100); + } + } else if (pOutput->GetOutputKind() == ReformatOutput::kOutputRaw) { + /* + * Send raw data through the text conversion configured in the + * extract files dialog. Any file for which no dedicated + * reformatter could be found ends up here. + * + * We could just send it through to the generic non-reformatter + * case, but that would require reading the file twice. + */ + WMSG1(" Writing un-reformatted data (%ld bytes)\n", + pOutput->GetTextLen()); + ASSERT(pOutput->GetTextBuf() != nil); + bool lastCR = false; + GenericEntry::ConvertHighASCII thisConvHA = convHA; + int err; + err = GenericEntry::WriteConvert(fp, pOutput->GetTextBuf(), + pOutput->GetTextLen(), &thisConv, &thisConvHA, &lastCR); + if (err != 0) { + errMsg.Format("Unable to write file '%s': %s\n", + outputPath, strerror(err)); + fpActionProgress->MessageBox(errMsg, failed, + MB_OK | MB_ICONERROR); + writeFailed = true; + } else { + SET_PROGRESS_UPDATE(100); + } - } else { - /* something failed, and we don't have the file */ - WMSG0("How'd we get here?\n"); - ASSERT(false); - } - } else { - /* - * We don't have the data, probably because we aren't using file - * reformatters. Use the GenericEntry extraction routine to copy - * the data directly into the file. - * - * We also get here if the file has a length of zero. - */ - CString msg; - int result; - ASSERT(fpActionProgress != nil); - WMSG3("Extracting '%s', requesting thisConv=%d, convHA=%d\n", - outputPath, thisConv, convHA); - result = pEntry->ExtractThreadToFile(thread, fp, - thisConv, convHA, &msg); - if (result != IDOK) { - if (result == IDCANCEL) { - CString msg; - msg.LoadString(IDS_OPERATION_CANCELLED); - fpActionProgress->MessageBox(msg, - "CiderPress", MB_OK | MB_ICONEXCLAMATION); - } else { - WMSG2(" FAILED on '%s': %s\n", outputPath, msg); - errMsg.Format("Unable to extract file '%s': %s\n", - outputPath, (LPCTSTR) msg); - fpActionProgress->MessageBox(errMsg, failed, - MB_OK | MB_ICONERROR); - } - writeFailed = true; - } - } + } else { + /* something failed, and we don't have the file */ + WMSG0("How'd we get here?\n"); + ASSERT(false); + } + } else { + /* + * We don't have the data, probably because we aren't using file + * reformatters. Use the GenericEntry extraction routine to copy + * the data directly into the file. + * + * We also get here if the file has a length of zero. + */ + CString msg; + int result; + ASSERT(fpActionProgress != nil); + WMSG3("Extracting '%s', requesting thisConv=%d, convHA=%d\n", + outputPath, thisConv, convHA); + result = pEntry->ExtractThreadToFile(thread, fp, + thisConv, convHA, &msg); + if (result != IDOK) { + if (result == IDCANCEL) { + CString msg; + msg.LoadString(IDS_OPERATION_CANCELLED); + fpActionProgress->MessageBox(msg, + "CiderPress", MB_OK | MB_ICONEXCLAMATION); + } else { + WMSG2(" FAILED on '%s': %s\n", outputPath, msg); + errMsg.Format("Unable to extract file '%s': %s\n", + outputPath, (LPCTSTR) msg); + fpActionProgress->MessageBox(errMsg, failed, + MB_OK | MB_ICONERROR); + } + writeFailed = true; + } + } open_file_fail: - delete pOutput; + delete pOutput; - fclose(fp); - if (writeFailed) { - // clean up - ::DeleteFile(outputPath); - return false; - } + fclose(fp); + if (writeFailed) { + // clean up + ::DeleteFile(outputPath); + return false; + } - /* - * Fix the modification date. - */ - PathName datePath(outputPath); - datePath.SetModWhen(pEntry->GetModWhen()); -// datePath.SetAccess(pEntry->GetAccess()); + /* + * Fix the modification date. + */ + PathName datePath(outputPath); + datePath.SetModWhen(pEntry->GetModWhen()); +// datePath.SetAccess(pEntry->GetAccess()); - return true; + return true; } @@ -1291,113 +1291,113 @@ open_file_fail: */ int MainWindow::OpenOutputFile(CString* pOutputPath, const PathProposal& pathProp, - time_t arcFileModWhen, bool* pOverwriteExisting, bool* pOvwrForAll, - FILE** pFp) + time_t arcFileModWhen, bool* pOverwriteExisting, bool* pOvwrForAll, + FILE** pFp) { - const int kUserCancel = -2; // must not conflict with errno values - CString failed; - CString msg; - int err = 0; + const int kUserCancel = -2; // must not conflict with errno values + CString failed; + CString msg; + int err = 0; - failed.LoadString(IDS_FAILED); + failed.LoadString(IDS_FAILED); - *pFp = nil; + *pFp = nil; did_rename: - PathName path(*pOutputPath); - if (path.Exists()) { - if (*pOverwriteExisting) { + PathName path(*pOutputPath); + if (path.Exists()) { + if (*pOverwriteExisting) { do_overwrite: - /* delete existing */ - WMSG1(" Deleting existing '%s'\n", (LPCTSTR) *pOutputPath); - if (::unlink(*pOutputPath) != 0) { - err = errno; - WMSG2(" Failed deleting '%s', err=%d\n", - (LPCTSTR)*pOutputPath, err); - if (err == ENOENT) { - /* user might have removed it while dialog was up */ - err = 0; - } else { - /* unable to delete, we'd better bail out */ - goto bail; - } - } - } else if (*pOvwrForAll) { - /* never overwrite */ - WMSG1(" Skipping '%s'\n", (LPCTSTR) *pOutputPath); - goto bail; - } else { - /* no firm policy, ask the user */ - ConfirmOverwriteDialog confOvwr; - PathName path(*pOutputPath); - - confOvwr.fExistingFile = *pOutputPath; - confOvwr.fExistingFileModWhen = path.GetModWhen(); - confOvwr.fNewFileSource = pathProp.fStoredPathName; - confOvwr.fNewFileModWhen = arcFileModWhen; - if (confOvwr.DoModal() == IDCANCEL) { - err = kUserCancel; - goto bail; - } - if (confOvwr.fResultRename) { - *pOutputPath = confOvwr.fExistingFile; - goto did_rename; - } - if (confOvwr.fResultApplyToAll) { - *pOvwrForAll = confOvwr.fResultApplyToAll; - *pOverwriteExisting = confOvwr.fResultOverwrite; - } - if (confOvwr.fResultOverwrite) - goto do_overwrite; - else - goto bail; - } + /* delete existing */ + WMSG1(" Deleting existing '%s'\n", (LPCTSTR) *pOutputPath); + if (::unlink(*pOutputPath) != 0) { + err = errno; + WMSG2(" Failed deleting '%s', err=%d\n", + (LPCTSTR)*pOutputPath, err); + if (err == ENOENT) { + /* user might have removed it while dialog was up */ + err = 0; + } else { + /* unable to delete, we'd better bail out */ + goto bail; + } + } + } else if (*pOvwrForAll) { + /* never overwrite */ + WMSG1(" Skipping '%s'\n", (LPCTSTR) *pOutputPath); + goto bail; + } else { + /* no firm policy, ask the user */ + ConfirmOverwriteDialog confOvwr; + PathName path(*pOutputPath); + + confOvwr.fExistingFile = *pOutputPath; + confOvwr.fExistingFileModWhen = path.GetModWhen(); + confOvwr.fNewFileSource = pathProp.fStoredPathName; + confOvwr.fNewFileModWhen = arcFileModWhen; + if (confOvwr.DoModal() == IDCANCEL) { + err = kUserCancel; + goto bail; + } + if (confOvwr.fResultRename) { + *pOutputPath = confOvwr.fExistingFile; + goto did_rename; + } + if (confOvwr.fResultApplyToAll) { + *pOvwrForAll = confOvwr.fResultApplyToAll; + *pOverwriteExisting = confOvwr.fResultOverwrite; + } + if (confOvwr.fResultOverwrite) + goto do_overwrite; + else + goto bail; + } - } + } - /* create the subdirectories, if necessary */ - err = path.CreatePathIFN(); - if (err != 0) - goto bail; + /* create the subdirectories, if necessary */ + err = path.CreatePathIFN(); + if (err != 0) + goto bail; - *pFp = fopen(*pOutputPath, "wb"); - if (*pFp == nil) - err = errno ? errno : -1; - /* fall through with error */ + *pFp = fopen(*pOutputPath, "wb"); + if (*pFp == nil) + err = errno ? errno : -1; + /* fall through with error */ bail: - /* if we failed, tell the user why */ - if (err == ENOTDIR) { - /* part of the output path exists, but isn't a directory */ - msg.Format("Unable to create folders for '%s': part of the path " - "already exists but is not a folder.\n", - *pOutputPath); - fpActionProgress->MessageBox(msg, failed, MB_OK | MB_ICONERROR); - return IDCANCEL; - } else if (err == EINVAL) { - /* invalid argument; assume it's an invalid filename */ - msg.Format("Unable to create file '%s': invalid filename.\n", - *pOutputPath); - fpActionProgress->MessageBox(msg, failed, MB_OK | MB_ICONERROR); - return IDCANCEL; - } else if (err == kUserCancel) { - /* user elected to cancel */ - WMSG0("Cancelling due to user request\n"); - return IDCANCEL; - } else if (err != 0) { - msg.Format("Unable to create file '%s': %s\n", - *pOutputPath, strerror(err)); - fpActionProgress->MessageBox(msg, failed, MB_OK | MB_ICONERROR); - return IDCANCEL; - } + /* if we failed, tell the user why */ + if (err == ENOTDIR) { + /* part of the output path exists, but isn't a directory */ + msg.Format("Unable to create folders for '%s': part of the path " + "already exists but is not a folder.\n", + *pOutputPath); + fpActionProgress->MessageBox(msg, failed, MB_OK | MB_ICONERROR); + return IDCANCEL; + } else if (err == EINVAL) { + /* invalid argument; assume it's an invalid filename */ + msg.Format("Unable to create file '%s': invalid filename.\n", + *pOutputPath); + fpActionProgress->MessageBox(msg, failed, MB_OK | MB_ICONERROR); + return IDCANCEL; + } else if (err == kUserCancel) { + /* user elected to cancel */ + WMSG0("Cancelling due to user request\n"); + return IDCANCEL; + } else if (err != 0) { + msg.Format("Unable to create file '%s': %s\n", + *pOutputPath, strerror(err)); + fpActionProgress->MessageBox(msg, failed, MB_OK | MB_ICONERROR); + return IDCANCEL; + } - return IDOK; + return IDOK; } /* * ========================================================================== - * Test + * Test * ========================================================================== */ @@ -1407,75 +1407,75 @@ bail: void MainWindow::OnActionsTest(void) { - ASSERT(fpContentList != nil); - ASSERT(fpOpenArchive != nil); + ASSERT(fpContentList != nil); + ASSERT(fpOpenArchive != nil); - /* - * Ask the user about various options. - */ - UseSelectionDialog selOpts(fpContentList->GetSelectedCount(), this); - selOpts.Setup(IDS_TEST_TITLE, IDS_TEST_OK, IDS_TEST_SELECTED_COUNT, - IDS_TEST_SELECTED_COUNTS_FMT, IDS_TEST_ALL_FILES); - if (fpContentList->GetSelectedCount() > 0) - selOpts.fFilesToAction = UseSelectionDialog::kActionSelection; - else - selOpts.fFilesToAction = UseSelectionDialog::kActionAll; + /* + * Ask the user about various options. + */ + UseSelectionDialog selOpts(fpContentList->GetSelectedCount(), this); + selOpts.Setup(IDS_TEST_TITLE, IDS_TEST_OK, IDS_TEST_SELECTED_COUNT, + IDS_TEST_SELECTED_COUNTS_FMT, IDS_TEST_ALL_FILES); + if (fpContentList->GetSelectedCount() > 0) + selOpts.fFilesToAction = UseSelectionDialog::kActionSelection; + else + selOpts.fFilesToAction = UseSelectionDialog::kActionAll; - if (selOpts.DoModal() != IDOK) { - WMSG0("Test cancelled\n"); - return; - } + if (selOpts.DoModal() != IDOK) { + WMSG0("Test cancelled\n"); + return; + } - /* - * Create a "selection set" of things to test. - * - * We don't currently test directories, because we don't currently - * allow testing anything that has a directory (NuFX doesn't store - * them explicitly). We could probably add them to the threadMask. - */ - SelectionSet selSet; - int threadMask = GenericEntry::kAnyThread; + /* + * Create a "selection set" of things to test. + * + * We don't currently test directories, because we don't currently + * allow testing anything that has a directory (NuFX doesn't store + * them explicitly). We could probably add them to the threadMask. + */ + SelectionSet selSet; + int threadMask = GenericEntry::kAnyThread; - if (selOpts.fFilesToAction == UseSelectionDialog::kActionSelection) { - selSet.CreateFromSelection(fpContentList, threadMask); - } else { - selSet.CreateFromAll(fpContentList, threadMask); - } - //selSet.Dump(); + if (selOpts.fFilesToAction == UseSelectionDialog::kActionSelection) { + selSet.CreateFromSelection(fpContentList, threadMask); + } else { + selSet.CreateFromAll(fpContentList, threadMask); + } + //selSet.Dump(); - if (selSet.GetNumEntries() == 0) { - /* should be impossible */ - MessageBox("No files matched the selection criteria.", - "No match", MB_OK|MB_ICONEXCLAMATION); - return; - } + if (selSet.GetNumEntries() == 0) { + /* should be impossible */ + MessageBox("No files matched the selection criteria.", + "No match", MB_OK|MB_ICONEXCLAMATION); + return; + } - /* - * Set up the progress window. - */ - bool result; + /* + * Set up the progress window. + */ + bool result; - fpActionProgress = new ActionProgressDialog; - fpActionProgress->Create(ActionProgressDialog::kActionTest, this); + fpActionProgress = new ActionProgressDialog; + fpActionProgress->Create(ActionProgressDialog::kActionTest, this); - result = fpOpenArchive->TestSelection(fpActionProgress, &selSet); + result = fpOpenArchive->TestSelection(fpActionProgress, &selSet); - fpActionProgress->Cleanup(this); - fpActionProgress = nil; - //if (result) - // SuccessBeep(); + fpActionProgress->Cleanup(this); + fpActionProgress = nil; + //if (result) + // SuccessBeep(); } void MainWindow::OnUpdateActionsTest(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil && fpContentList->GetItemCount() > 0 - && fpOpenArchive->GetCapability(GenericArchive::kCapCanTest)); + pCmdUI->Enable(fpContentList != nil && fpContentList->GetItemCount() > 0 + && fpOpenArchive->GetCapability(GenericArchive::kCapCanTest)); } /* * ========================================================================== - * Delete + * Delete * ========================================================================== */ @@ -1485,102 +1485,102 @@ MainWindow::OnUpdateActionsTest(CCmdUI* pCmdUI) void MainWindow::OnActionsDelete(void) { - ASSERT(fpContentList != nil); - ASSERT(fpOpenArchive != nil); - ASSERT(!fpOpenArchive->IsReadOnly()); + ASSERT(fpContentList != nil); + ASSERT(fpOpenArchive != nil); + ASSERT(!fpOpenArchive->IsReadOnly()); - /* - * We handle deletions specially. If they have selected any - * subdirectories, we recursively select the files in those subdirs - * as well. We want to do it early so that the "#of files to delete" - * display accurately reflects what we're about to do. - */ - fpContentList->SelectSubdirContents(); + /* + * We handle deletions specially. If they have selected any + * subdirectories, we recursively select the files in those subdirs + * as well. We want to do it early so that the "#of files to delete" + * display accurately reflects what we're about to do. + */ + fpContentList->SelectSubdirContents(); #if 0 - /* - * Ask the user about various options. - */ - UseSelectionDialog delOpts(fpContentList->GetSelectedCount(), this); - delOpts.Setup(IDS_DEL_TITLE, IDS_DEL_OK, IDS_DEL_SELECTED_COUNT, - IDS_DEL_SELECTED_COUNTS_FMT, IDS_DEL_ALL_FILES); - if (fpContentList->GetSelectedCount() > 0) - delOpts.fFilesToAction = UseSelectionDialog::kActionSelection; - else - delOpts.fFilesToAction = UseSelectionDialog::kActionAll; + /* + * Ask the user about various options. + */ + UseSelectionDialog delOpts(fpContentList->GetSelectedCount(), this); + delOpts.Setup(IDS_DEL_TITLE, IDS_DEL_OK, IDS_DEL_SELECTED_COUNT, + IDS_DEL_SELECTED_COUNTS_FMT, IDS_DEL_ALL_FILES); + if (fpContentList->GetSelectedCount() > 0) + delOpts.fFilesToAction = UseSelectionDialog::kActionSelection; + else + delOpts.fFilesToAction = UseSelectionDialog::kActionAll; - if (delOpts.DoModal() != IDOK) { - WMSG0("Delete cancelled\n"); - return; - } + if (delOpts.DoModal() != IDOK) { + WMSG0("Delete cancelled\n"); + return; + } #endif - /* - * Create a "selection set" of things to delete. - * - * We can't delete volume directories, so they're not included. - */ - SelectionSet selSet; - int threadMask = GenericEntry::kAnyThread | - GenericEntry::kAllowDirectory /*| GenericEntry::kAllowVolumeDir*/; + /* + * Create a "selection set" of things to delete. + * + * We can't delete volume directories, so they're not included. + */ + SelectionSet selSet; + int threadMask = GenericEntry::kAnyThread | + GenericEntry::kAllowDirectory /*| GenericEntry::kAllowVolumeDir*/; #if 0 - if (delOpts.fFilesToAction == UseSelectionDialog::kActionSelection) { - selSet.CreateFromSelection(fpContentList, threadMask); - } else { - CString appName; - UINT response; - appName.LoadString(IDS_MB_APP_NAME); - response = MessageBox("Are you sure you want to delete everything?", - appName, MB_OKCANCEL | MB_ICONEXCLAMATION); - if (response == IDCANCEL) - return; - selSet.CreateFromAll(fpContentList, threadMask); - } - //selSet.Dump(); + if (delOpts.fFilesToAction == UseSelectionDialog::kActionSelection) { + selSet.CreateFromSelection(fpContentList, threadMask); + } else { + CString appName; + UINT response; + appName.LoadString(IDS_MB_APP_NAME); + response = MessageBox("Are you sure you want to delete everything?", + appName, MB_OKCANCEL | MB_ICONEXCLAMATION); + if (response == IDCANCEL) + return; + selSet.CreateFromAll(fpContentList, threadMask); + } + //selSet.Dump(); #endif - selSet.CreateFromSelection(fpContentList, threadMask); - if (selSet.GetNumEntries() == 0) { - /* can happen if they selected volume dir only */ - MessageBox("Nothing to delete.", - "No match", MB_OK | MB_ICONEXCLAMATION); - return; - } + selSet.CreateFromSelection(fpContentList, threadMask); + if (selSet.GetNumEntries() == 0) { + /* can happen if they selected volume dir only */ + MessageBox("Nothing to delete.", + "No match", MB_OK | MB_ICONEXCLAMATION); + return; + } - CString appName, msg; + CString appName, msg; - appName.LoadString(IDS_MB_APP_NAME); - msg.Format("Delete %d file%s?", selSet.GetNumEntries(), - selSet.GetNumEntries() == 1 ? "" : "s"); - if (MessageBox(msg, appName, MB_OKCANCEL | MB_ICONQUESTION) != IDOK) - return; + appName.LoadString(IDS_MB_APP_NAME); + msg.Format("Delete %d file%s?", selSet.GetNumEntries(), + selSet.GetNumEntries() == 1 ? "" : "s"); + if (MessageBox(msg, appName, MB_OKCANCEL | MB_ICONQUESTION) != IDOK) + return; - bool result; - fpActionProgress = new ActionProgressDialog; - fpActionProgress->Create(ActionProgressDialog::kActionDelete, this); + bool result; + fpActionProgress = new ActionProgressDialog; + fpActionProgress->Create(ActionProgressDialog::kActionDelete, this); - //fpContentList->Invalidate(); // don't allow updates until done - result = fpOpenArchive->DeleteSelection(fpActionProgress, &selSet); - fpContentList->Reload(); + //fpContentList->Invalidate(); // don't allow updates until done + result = fpOpenArchive->DeleteSelection(fpActionProgress, &selSet); + fpContentList->Reload(); - fpActionProgress->Cleanup(this); - fpActionProgress = nil; + fpActionProgress->Cleanup(this); + fpActionProgress = nil; - if (result) - SuccessBeep(); + if (result) + SuccessBeep(); } void MainWindow::OnUpdateActionsDelete(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() - && fpContentList->GetSelectedCount() > 0); + pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() + && fpContentList->GetSelectedCount() > 0); } /* * ========================================================================== - * Rename + * Rename * ========================================================================== */ @@ -1592,50 +1592,50 @@ MainWindow::OnUpdateActionsDelete(CCmdUI* pCmdUI) void MainWindow::OnActionsRename(void) { - ASSERT(fpContentList != nil); - ASSERT(fpOpenArchive != nil); - ASSERT(!fpOpenArchive->IsReadOnly()); + ASSERT(fpContentList != nil); + ASSERT(fpOpenArchive != nil); + ASSERT(!fpOpenArchive->IsReadOnly()); - /* - * Create a "selection set" of entries to rename. We always go by - * the selection, so there's no need to present a "all or some?" dialog. - * - * Renaming the volume dir is not done from here, so we don't include - * it in the set. We could theoretically allow renaming of "damaged" - * files, since most of the time the damage is in the file structure - * not the directory, but the disk will be read-only anyway so there's - * no point. - */ - SelectionSet selSet; - int threadMask = GenericEntry::kAnyThread | GenericEntry::kAllowDirectory; + /* + * Create a "selection set" of entries to rename. We always go by + * the selection, so there's no need to present a "all or some?" dialog. + * + * Renaming the volume dir is not done from here, so we don't include + * it in the set. We could theoretically allow renaming of "damaged" + * files, since most of the time the damage is in the file structure + * not the directory, but the disk will be read-only anyway so there's + * no point. + */ + SelectionSet selSet; + int threadMask = GenericEntry::kAnyThread | GenericEntry::kAllowDirectory; - selSet.CreateFromSelection(fpContentList, threadMask); - //selSet.Dump(); + selSet.CreateFromSelection(fpContentList, threadMask); + //selSet.Dump(); - if (selSet.GetNumEntries() == 0) { - /* should be impossible */ - MessageBox("No files matched the selection criteria.", - "No match", MB_OK | MB_ICONEXCLAMATION); - return; - } + if (selSet.GetNumEntries() == 0) { + /* should be impossible */ + MessageBox("No files matched the selection criteria.", + "No match", MB_OK | MB_ICONEXCLAMATION); + return; + } - //fpContentList->Invalidate(); // this might be unnecessary - fpOpenArchive->RenameSelection(this, &selSet); - fpContentList->Reload(); + //fpContentList->Invalidate(); // this might be unnecessary + fpOpenArchive->RenameSelection(this, &selSet); + fpContentList->Reload(); - // user interaction on each step, so skip the SuccessBeep + // user interaction on each step, so skip the SuccessBeep } void MainWindow::OnUpdateActionsRename(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() - && fpContentList->GetSelectedCount() > 0); + pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() + && fpContentList->GetSelectedCount() > 0); } /* * ========================================================================== - * Edit Comment + * Edit Comment * ========================================================================== */ @@ -1645,60 +1645,60 @@ MainWindow::OnUpdateActionsRename(CCmdUI* pCmdUI) void MainWindow::OnActionsEditComment(void) { - ASSERT(fpContentList != nil); - ASSERT(fpOpenArchive != nil); - ASSERT(!fpOpenArchive->IsReadOnly()); + ASSERT(fpContentList != nil); + ASSERT(fpOpenArchive != nil); + ASSERT(!fpOpenArchive->IsReadOnly()); - EditCommentDialog editDlg(this); - CString oldComment; + EditCommentDialog editDlg(this); + CString oldComment; - GenericEntry* pEntry = GetSelectedItem(fpContentList); - if (pEntry == nil) { - ASSERT(false); - return; - } + GenericEntry* pEntry = GetSelectedItem(fpContentList); + if (pEntry == nil) { + ASSERT(false); + return; + } - if (!pEntry->GetHasComment()) { - CString question, title; - int result; + if (!pEntry->GetHasComment()) { + CString question, title; + int result; - question.LoadString(IDS_NO_COMMENT_ADD); - title.LoadString(IDS_EDIT_COMMENT); - result = MessageBox(question, title, MB_OKCANCEL | MB_ICONQUESTION); - if (result == IDCANCEL) - return; + question.LoadString(IDS_NO_COMMENT_ADD); + title.LoadString(IDS_EDIT_COMMENT); + result = MessageBox(question, title, MB_OKCANCEL | MB_ICONQUESTION); + if (result == IDCANCEL) + return; - editDlg.fComment = ""; - editDlg.fNewComment = true; - } else { - fpOpenArchive->GetComment(this, pEntry, &editDlg.fComment); - } + editDlg.fComment = ""; + editDlg.fNewComment = true; + } else { + fpOpenArchive->GetComment(this, pEntry, &editDlg.fComment); + } - int result; - result = editDlg.DoModal(); - if (result == IDOK) { - //fpContentList->Invalidate(); // probably unnecessary - fpOpenArchive->SetComment(this, pEntry, editDlg.fComment); - fpContentList->Reload(); - } else if (result == EditCommentDialog::kDeleteCommentID) { - //fpContentList->Invalidate(); // possibly unnecessary - fpOpenArchive->DeleteComment(this, pEntry); - fpContentList->Reload(); - } + int result; + result = editDlg.DoModal(); + if (result == IDOK) { + //fpContentList->Invalidate(); // probably unnecessary + fpOpenArchive->SetComment(this, pEntry, editDlg.fComment); + fpContentList->Reload(); + } else if (result == EditCommentDialog::kDeleteCommentID) { + //fpContentList->Invalidate(); // possibly unnecessary + fpOpenArchive->DeleteComment(this, pEntry); + fpContentList->Reload(); + } } void MainWindow::OnUpdateActionsEditComment(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() && - fpContentList->GetSelectedCount() == 1 && - fpOpenArchive->GetCapability(GenericArchive::kCapCanEditComment)); + pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() && + fpContentList->GetSelectedCount() == 1 && + fpOpenArchive->GetCapability(GenericArchive::kCapCanEditComment)); } /* * ========================================================================== - * Edit Properties + * Edit Properties * ========================================================================== */ @@ -1714,45 +1714,45 @@ MainWindow::OnUpdateActionsEditComment(CCmdUI* pCmdUI) void MainWindow::OnActionsEditProps(void) { - ASSERT(fpContentList != nil); - ASSERT(fpOpenArchive != nil); + ASSERT(fpContentList != nil); + ASSERT(fpOpenArchive != nil); - EditPropsDialog propsDlg(this); - CString oldComment; + EditPropsDialog propsDlg(this); + CString oldComment; - GenericEntry* pEntry = GetSelectedItem(fpContentList); - if (pEntry == nil) { - ASSERT(false); - return; - } + GenericEntry* pEntry = GetSelectedItem(fpContentList); + if (pEntry == nil) { + ASSERT(false); + return; + } - propsDlg.InitProps(pEntry); - if (fpOpenArchive->IsReadOnly()) - propsDlg.fReadOnly = true; - else if (pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir) - propsDlg.fReadOnly = true; + propsDlg.InitProps(pEntry); + if (fpOpenArchive->IsReadOnly()) + propsDlg.fReadOnly = true; + else if (pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir) + propsDlg.fReadOnly = true; - int result; - result = propsDlg.DoModal(); - if (result == IDOK && !propsDlg.fReadOnly) { - (void) fpOpenArchive->SetProps(this, pEntry, &propsDlg.fProps); + int result; + result = propsDlg.DoModal(); + if (result == IDOK && !propsDlg.fReadOnly) { + (void) fpOpenArchive->SetProps(this, pEntry, &propsDlg.fProps); - // only needed if underlying archive reloads - fpContentList->Reload(true); - } + // only needed if underlying archive reloads + fpContentList->Reload(true); + } } void MainWindow::OnUpdateActionsEditProps(CCmdUI* pCmdUI) { - // allow it in read-only mode, so we can view the props - pCmdUI->Enable(fpContentList != nil && - fpContentList->GetSelectedCount() == 1); + // allow it in read-only mode, so we can view the props + pCmdUI->Enable(fpContentList != nil && + fpContentList->GetSelectedCount() == 1); } /* * ========================================================================== - * Rename Volume + * Rename Volume * ========================================================================== */ @@ -1762,60 +1762,60 @@ MainWindow::OnUpdateActionsEditProps(CCmdUI* pCmdUI) void MainWindow::OnActionsRenameVolume(void) { - RenameVolumeDialog rvDialog; + RenameVolumeDialog rvDialog; - ASSERT(fpContentList != nil); - ASSERT(fpOpenArchive != nil); - ASSERT(!fpOpenArchive->IsReadOnly()); + ASSERT(fpContentList != nil); + ASSERT(fpOpenArchive != nil); + ASSERT(!fpOpenArchive->IsReadOnly()); - /* only know how to deal with disk images */ - if (fpOpenArchive->GetArchiveKind() != GenericArchive::kArchiveDiskImage) { - ASSERT(false); - return; - } + /* only know how to deal with disk images */ + if (fpOpenArchive->GetArchiveKind() != GenericArchive::kArchiveDiskImage) { + ASSERT(false); + return; + } - DiskImgLib::DiskFS* pDiskFS; + DiskImgLib::DiskFS* pDiskFS; - pDiskFS = ((DiskArchive*) fpOpenArchive)->GetDiskFS(); - ASSERT(pDiskFS != nil); + pDiskFS = ((DiskArchive*) fpOpenArchive)->GetDiskFS(); + ASSERT(pDiskFS != nil); - rvDialog.fpArchive = (DiskArchive*) fpOpenArchive; - if (rvDialog.DoModal() != IDOK) - return; + rvDialog.fpArchive = (DiskArchive*) fpOpenArchive; + if (rvDialog.DoModal() != IDOK) + return; - //WMSG1("Creating '%s'\n", rvDialog.fNewName); + //WMSG1("Creating '%s'\n", rvDialog.fNewName); - /* rename the chosen disk to the specified name */ - bool result; - result = fpOpenArchive->RenameVolume(this, rvDialog.fpChosenDiskFS, - rvDialog.fNewName); - if (!result) { - WMSG0("RenameVolume FAILED\n"); - /* keep going -- reload just in case something partially happened */ - } + /* rename the chosen disk to the specified name */ + bool result; + result = fpOpenArchive->RenameVolume(this, rvDialog.fpChosenDiskFS, + rvDialog.fNewName); + if (!result) { + WMSG0("RenameVolume FAILED\n"); + /* keep going -- reload just in case something partially happened */ + } - /* - * We need to do two things: reload the content list, because the - * underlying DiskArchive got reloaded, and update the title bar. We - * put the "volume ID" in the title, and we most likely just changed it. - * - * SetCPTitle invokes fpOpenArchive->GetDescription(), which pulls the - * volume ID out of the primary DiskFS. - */ - fpContentList->Reload(); - SetCPTitle(fOpenArchivePathName, fpOpenArchive); + /* + * We need to do two things: reload the content list, because the + * underlying DiskArchive got reloaded, and update the title bar. We + * put the "volume ID" in the title, and we most likely just changed it. + * + * SetCPTitle invokes fpOpenArchive->GetDescription(), which pulls the + * volume ID out of the primary DiskFS. + */ + fpContentList->Reload(); + SetCPTitle(fOpenArchivePathName, fpOpenArchive); } void MainWindow::OnUpdateActionsRenameVolume(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() && - fpOpenArchive->GetCapability(GenericArchive::kCapCanRenameVolume)); + pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() && + fpOpenArchive->GetCapability(GenericArchive::kCapCanRenameVolume)); } /* * ========================================================================== - * Recompress + * Recompress * ========================================================================== */ @@ -1825,92 +1825,92 @@ MainWindow::OnUpdateActionsRenameVolume(CCmdUI* pCmdUI) void MainWindow::OnActionsRecompress(void) { - ASSERT(fpContentList != nil); - ASSERT(fpOpenArchive != nil); + ASSERT(fpContentList != nil); + ASSERT(fpOpenArchive != nil); - /* - * Ask the user about various options. - */ - RecompressOptionsDialog selOpts(fpContentList->GetSelectedCount(), this); - selOpts.Setup(IDS_RECOMP_TITLE, IDS_RECOMP_OK, IDS_RECOMP_SELECTED_COUNT, - IDS_RECOMP_SELECTED_COUNTS_FMT, IDS_RECOMP_ALL_FILES); - if (fpContentList->GetSelectedCount() > 0) - selOpts.fFilesToAction = UseSelectionDialog::kActionSelection; - else - selOpts.fFilesToAction = UseSelectionDialog::kActionAll; + /* + * Ask the user about various options. + */ + RecompressOptionsDialog selOpts(fpContentList->GetSelectedCount(), this); + selOpts.Setup(IDS_RECOMP_TITLE, IDS_RECOMP_OK, IDS_RECOMP_SELECTED_COUNT, + IDS_RECOMP_SELECTED_COUNTS_FMT, IDS_RECOMP_ALL_FILES); + if (fpContentList->GetSelectedCount() > 0) + selOpts.fFilesToAction = UseSelectionDialog::kActionSelection; + else + selOpts.fFilesToAction = UseSelectionDialog::kActionAll; - selOpts.fCompressionType = fPreferences.GetPrefLong(kPrCompressionType); + selOpts.fCompressionType = fPreferences.GetPrefLong(kPrCompressionType); - if (selOpts.DoModal() != IDOK) { - WMSG0("Recompress cancelled\n"); - return; - } + if (selOpts.DoModal() != IDOK) { + WMSG0("Recompress cancelled\n"); + return; + } - /* - * Create a "selection set" of data forks, resource forks, and disk - * images. If an entry has nothing but a comment, ignore it. - */ - SelectionSet selSet; - int threadMask = GenericEntry::kDataThread | GenericEntry::kRsrcThread | - GenericEntry::kDiskImageThread; + /* + * Create a "selection set" of data forks, resource forks, and disk + * images. If an entry has nothing but a comment, ignore it. + */ + SelectionSet selSet; + int threadMask = GenericEntry::kDataThread | GenericEntry::kRsrcThread | + GenericEntry::kDiskImageThread; - if (selOpts.fFilesToAction == UseSelectionDialog::kActionSelection) { - selSet.CreateFromSelection(fpContentList, threadMask); - } else { - selSet.CreateFromAll(fpContentList, threadMask); - } - //selSet.Dump(); + if (selOpts.fFilesToAction == UseSelectionDialog::kActionSelection) { + selSet.CreateFromSelection(fpContentList, threadMask); + } else { + selSet.CreateFromAll(fpContentList, threadMask); + } + //selSet.Dump(); - if (selSet.GetNumEntries() == 0) { - /* should be impossible */ - MessageBox("No files matched the selection criteria.", - "No match", MB_OK|MB_ICONEXCLAMATION); - return; - } + if (selSet.GetNumEntries() == 0) { + /* should be impossible */ + MessageBox("No files matched the selection criteria.", + "No match", MB_OK|MB_ICONEXCLAMATION); + return; + } - LONGLONG beforeUncomp, beforeComp; - LONGLONG afterUncomp, afterComp; - CalcTotalSize(&beforeUncomp, &beforeComp); + LONGLONG beforeUncomp, beforeComp; + LONGLONG afterUncomp, afterComp; + CalcTotalSize(&beforeUncomp, &beforeComp); - /* - * Set up the progress window. - */ - int result; + /* + * Set up the progress window. + */ + int result; - fpActionProgress = new ActionProgressDialog; - fpActionProgress->Create(ActionProgressDialog::kActionRecompress, this); + fpActionProgress = new ActionProgressDialog; + fpActionProgress->Create(ActionProgressDialog::kActionRecompress, this); - //fpContentList->Invalidate(); // possibly unnecessary - result = fpOpenArchive->RecompressSelection(fpActionProgress, &selSet, - &selOpts); - fpContentList->Reload(); + //fpContentList->Invalidate(); // possibly unnecessary + result = fpOpenArchive->RecompressSelection(fpActionProgress, &selSet, + &selOpts); + fpContentList->Reload(); - fpActionProgress->Cleanup(this); - fpActionProgress = nil; + fpActionProgress->Cleanup(this); + fpActionProgress = nil; - - if (result) { - CString msg, appName; + + if (result) { + CString msg, appName; - CalcTotalSize(&afterUncomp, &afterComp); - ASSERT(beforeUncomp == afterUncomp); + CalcTotalSize(&afterUncomp, &afterComp); + ASSERT(beforeUncomp == afterUncomp); - appName.LoadString(IDS_MB_APP_NAME); - msg.Format("Total uncompressed size of all files:\t%.1fK\r\n" - "Total size before recompress:\t\t%.1fK\r\n" - "Total size after recompress:\t\t%.1fK\r\n" - "Overall reduction:\t\t\t%.1fK", - beforeUncomp / 1024.0, beforeComp / 1024.0, afterComp / 1024.0, - (beforeComp - afterComp) / 1024.0); - MessageBox(msg, appName, MB_OK|MB_ICONINFORMATION); - } + appName.LoadString(IDS_MB_APP_NAME); + msg.Format("Total uncompressed size of all files:\t%.1fK\r\n" + "Total size before recompress:\t\t%.1fK\r\n" + "Total size after recompress:\t\t%.1fK\r\n" + "Overall reduction:\t\t\t%.1fK", + beforeUncomp / 1024.0, beforeComp / 1024.0, afterComp / 1024.0, + (beforeComp - afterComp) / 1024.0); + MessageBox(msg, appName, MB_OK|MB_ICONINFORMATION); + } } void MainWindow::OnUpdateActionsRecompress(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() && - fpContentList->GetItemCount() > 0 && - fpOpenArchive->GetCapability(GenericArchive::kCapCanRecompress)); + pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() && + fpContentList->GetItemCount() > 0 && + fpOpenArchive->GetCapability(GenericArchive::kCapCanRecompress)); } /* @@ -1919,23 +1919,23 @@ MainWindow::OnUpdateActionsRecompress(CCmdUI* pCmdUI) void MainWindow::CalcTotalSize(LONGLONG* pUncomp, LONGLONG* pComp) const { - GenericEntry* pEntry = fpOpenArchive->GetEntries(); - LONGLONG uncomp = 0, comp = 0; + GenericEntry* pEntry = fpOpenArchive->GetEntries(); + LONGLONG uncomp = 0, comp = 0; - while (pEntry != nil) { - uncomp += pEntry->GetUncompressedLen(); - comp += pEntry->GetCompressedLen(); - pEntry = pEntry->GetNext(); - } + while (pEntry != nil) { + uncomp += pEntry->GetUncompressedLen(); + comp += pEntry->GetCompressedLen(); + pEntry = pEntry->GetNext(); + } - *pUncomp = uncomp; - *pComp = comp; + *pUncomp = uncomp; + *pComp = comp; } /* * ========================================================================== - * Convert to disk archive + * Convert to disk archive * ========================================================================== */ @@ -1945,147 +1945,147 @@ MainWindow::CalcTotalSize(LONGLONG* pUncomp, LONGLONG* pComp) const void MainWindow::OnActionsConvDisk(void) { - ASSERT(fpContentList != nil); - ASSERT(fpOpenArchive != nil); + ASSERT(fpContentList != nil); + ASSERT(fpOpenArchive != nil); - /* - * Ask the user about various options. - */ - ConvDiskOptionsDialog selOpts(fpContentList->GetSelectedCount(), this); - selOpts.Setup(IDS_CONVDISK_TITLE, IDS_CONVDISK_OK, IDS_CONVDISK_SELECTED_COUNT, - IDS_CONVDISK_SELECTED_COUNTS_FMT, IDS_CONVDISK_ALL_FILES); - if (fpContentList->GetSelectedCount() > 0) - selOpts.fFilesToAction = UseSelectionDialog::kActionSelection; - else - selOpts.fFilesToAction = UseSelectionDialog::kActionAll; + /* + * Ask the user about various options. + */ + ConvDiskOptionsDialog selOpts(fpContentList->GetSelectedCount(), this); + selOpts.Setup(IDS_CONVDISK_TITLE, IDS_CONVDISK_OK, IDS_CONVDISK_SELECTED_COUNT, + IDS_CONVDISK_SELECTED_COUNTS_FMT, IDS_CONVDISK_ALL_FILES); + if (fpContentList->GetSelectedCount() > 0) + selOpts.fFilesToAction = UseSelectionDialog::kActionSelection; + else + selOpts.fFilesToAction = UseSelectionDialog::kActionAll; - //selOpts.fAllowLower = - // fPreferences.GetPrefBool(kPrConvDiskAllowLower); - //selOpts.fSparseAlloc = - // fPreferences.GetPrefBool(kPrConvDiskAllocSparse); + //selOpts.fAllowLower = + // fPreferences.GetPrefBool(kPrConvDiskAllowLower); + //selOpts.fSparseAlloc = + // fPreferences.GetPrefBool(kPrConvDiskAllocSparse); - if (selOpts.DoModal() != IDOK) { - WMSG0("ConvDisk cancelled\n"); - return; - } + if (selOpts.DoModal() != IDOK) { + WMSG0("ConvDisk cancelled\n"); + return; + } - ASSERT(selOpts.fNumBlocks > 0); + ASSERT(selOpts.fNumBlocks > 0); - //fPreferences.SetPrefBool(kPrConvDiskAllowLower, - // selOpts.fAllowLower != 0); - //fPreferences.SetPrefBool(kPrConvDiskAllocSparse, - // selOpts.fSparseAlloc != 0); + //fPreferences.SetPrefBool(kPrConvDiskAllowLower, + // selOpts.fAllowLower != 0); + //fPreferences.SetPrefBool(kPrConvDiskAllocSparse, + // selOpts.fSparseAlloc != 0); - /* - * Create a "selection set" of data forks, resource forks, and - * disk images. We don't want comment threads, but we can ignore - * them later. - */ - SelectionSet selSet; - int threadMask = GenericEntry::kAnyThread; + /* + * Create a "selection set" of data forks, resource forks, and + * disk images. We don't want comment threads, but we can ignore + * them later. + */ + SelectionSet selSet; + int threadMask = GenericEntry::kAnyThread; - if (selOpts.fFilesToAction == UseSelectionDialog::kActionSelection) { - selSet.CreateFromSelection(fpContentList, threadMask); - } else { - selSet.CreateFromAll(fpContentList, threadMask); - } - //selSet.Dump(); + if (selOpts.fFilesToAction == UseSelectionDialog::kActionSelection) { + selSet.CreateFromSelection(fpContentList, threadMask); + } else { + selSet.CreateFromAll(fpContentList, threadMask); + } + //selSet.Dump(); - if (selSet.GetNumEntries() == 0) { - /* should be impossible */ - MessageBox("No files matched the selection criteria.", - "No match", MB_OK|MB_ICONEXCLAMATION); - return; - } + if (selSet.GetNumEntries() == 0) { + /* should be impossible */ + MessageBox("No files matched the selection criteria.", + "No match", MB_OK|MB_ICONEXCLAMATION); + return; + } - XferFileOptions xferOpts; - //xferOpts.fAllowLowerCase = - // fPreferences.GetPrefBool(kPrProDOSAllowLower) != 0; - //xferOpts.fUseSparseBlocks = - // fPreferences.GetPrefBool(kPrProDOSUseSparse) != 0; + XferFileOptions xferOpts; + //xferOpts.fAllowLowerCase = + // fPreferences.GetPrefBool(kPrProDOSAllowLower) != 0; + //xferOpts.fUseSparseBlocks = + // fPreferences.GetPrefBool(kPrProDOSUseSparse) != 0; - WMSG1("New volume name will be '%s'\n", selOpts.fVolName); + WMSG1("New volume name will be '%s'\n", selOpts.fVolName); - /* - * Create a new disk image. - */ - CString filename, saveFolder, errStr; + /* + * Create a new disk image. + */ + CString filename, saveFolder, errStr; - CFileDialog dlg(FALSE, _T("po"), NULL, - OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, - "Disk Images (*.po)|*.po||", this); + CFileDialog dlg(FALSE, _T("po"), NULL, + OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, + "Disk Images (*.po)|*.po||", this); - dlg.m_ofn.lpstrTitle = "New Disk Image (.PO)"; - dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); + dlg.m_ofn.lpstrTitle = "New Disk Image (.PO)"; + dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); - if (dlg.DoModal() != IDOK) { - WMSG0(" User cancelled xfer from image create dialog\n"); - return; - } + if (dlg.DoModal() != IDOK) { + WMSG0(" User cancelled xfer from image create dialog\n"); + return; + } - saveFolder = dlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); + saveFolder = dlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); - filename = dlg.GetPathName(); - WMSG1(" Will xfer to file '%s'\n", filename); + filename = dlg.GetPathName(); + WMSG1(" Will xfer to file '%s'\n", filename); - /* remove file if it already exists */ - CString errMsg; - errMsg = RemoveFile(filename); - if (!errMsg.IsEmpty()) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - return; - } + /* remove file if it already exists */ + CString errMsg; + errMsg = RemoveFile(filename); + if (!errMsg.IsEmpty()) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + return; + } - DiskArchive::NewOptions options; - memset(&options, 0, sizeof(options)); - options.base.format = DiskImg::kFormatProDOS; - options.base.sectorOrder = DiskImg::kSectorOrderProDOS; - options.prodos.volName = selOpts.fVolName; - options.prodos.numBlocks = selOpts.fNumBlocks; + DiskArchive::NewOptions options; + memset(&options, 0, sizeof(options)); + options.base.format = DiskImg::kFormatProDOS; + options.base.sectorOrder = DiskImg::kSectorOrderProDOS; + options.prodos.volName = selOpts.fVolName; + options.prodos.numBlocks = selOpts.fNumBlocks; - xferOpts.fTarget = new DiskArchive; - errStr = xferOpts.fTarget->New(filename, &options); - if (!errStr.IsEmpty()) { - ShowFailureMsg(this, errStr, IDS_FAILED); - delete xferOpts.fTarget; - return; - } + xferOpts.fTarget = new DiskArchive; + errStr = xferOpts.fTarget->New(filename, &options); + if (!errStr.IsEmpty()) { + ShowFailureMsg(this, errStr, IDS_FAILED); + delete xferOpts.fTarget; + return; + } - /* - * Set up the progress window. - */ - GenericArchive::XferStatus result; + /* + * Set up the progress window. + */ + GenericArchive::XferStatus result; - fpActionProgress = new ActionProgressDialog; - fpActionProgress->Create(ActionProgressDialog::kActionConvDisk, this); + fpActionProgress = new ActionProgressDialog; + fpActionProgress->Create(ActionProgressDialog::kActionConvDisk, this); - result = fpOpenArchive->XferSelection(fpActionProgress, &selSet, - fpActionProgress, &xferOpts); + result = fpOpenArchive->XferSelection(fpActionProgress, &selSet, + fpActionProgress, &xferOpts); - fpActionProgress->Cleanup(this); - fpActionProgress = nil; + fpActionProgress->Cleanup(this); + fpActionProgress = nil; - if (result == GenericArchive::kXferOK) - SuccessBeep(); + if (result == GenericArchive::kXferOK) + SuccessBeep(); - /* clean up */ - delete xferOpts.fTarget; + /* clean up */ + delete xferOpts.fTarget; } void MainWindow::OnUpdateActionsConvDisk(CCmdUI* pCmdUI) { - /* right now, only NufxArchive has the Xfer stuff implemented */ - pCmdUI->Enable(fpContentList != nil && - fpContentList->GetItemCount() > 0 && - fpOpenArchive->GetArchiveKind() == GenericArchive::kArchiveNuFX); + /* right now, only NufxArchive has the Xfer stuff implemented */ + pCmdUI->Enable(fpContentList != nil && + fpContentList->GetItemCount() > 0 && + fpOpenArchive->GetArchiveKind() == GenericArchive::kArchiveNuFX); } /* * ========================================================================== - * Convert to file archive + * Convert to file archive * ========================================================================== */ @@ -2095,141 +2095,141 @@ MainWindow::OnUpdateActionsConvDisk(CCmdUI* pCmdUI) void MainWindow::OnActionsConvFile(void) { - ASSERT(fpContentList != nil); - ASSERT(fpOpenArchive != nil); + ASSERT(fpContentList != nil); + ASSERT(fpOpenArchive != nil); - /* - * Ask the user about various options. - */ - ConvFileOptionsDialog selOpts(fpContentList->GetSelectedCount(), this); - selOpts.Setup(IDS_CONVFILE_TITLE, IDS_CONVFILE_OK, IDS_CONVFILE_SELECTED_COUNT, - IDS_CONVFILE_SELECTED_COUNTS_FMT, IDS_CONVFILE_ALL_FILES); - if (fpContentList->GetSelectedCount() > 0) - selOpts.fFilesToAction = UseSelectionDialog::kActionSelection; - else - selOpts.fFilesToAction = UseSelectionDialog::kActionAll; + /* + * Ask the user about various options. + */ + ConvFileOptionsDialog selOpts(fpContentList->GetSelectedCount(), this); + selOpts.Setup(IDS_CONVFILE_TITLE, IDS_CONVFILE_OK, IDS_CONVFILE_SELECTED_COUNT, + IDS_CONVFILE_SELECTED_COUNTS_FMT, IDS_CONVFILE_ALL_FILES); + if (fpContentList->GetSelectedCount() > 0) + selOpts.fFilesToAction = UseSelectionDialog::kActionSelection; + else + selOpts.fFilesToAction = UseSelectionDialog::kActionAll; - //selOpts.fConvDOSText = - // fPreferences.GetPrefBool(kPrConvFileConvDOSText); - //selOpts.fConvPascalText = - // fPreferences.GetPrefBool(kPrConvFileConvPascalText); - selOpts.fPreserveEmptyFolders = - fPreferences.GetPrefBool(kPrConvFileEmptyFolders); + //selOpts.fConvDOSText = + // fPreferences.GetPrefBool(kPrConvFileConvDOSText); + //selOpts.fConvPascalText = + // fPreferences.GetPrefBool(kPrConvFileConvPascalText); + selOpts.fPreserveEmptyFolders = + fPreferences.GetPrefBool(kPrConvFileEmptyFolders); - if (selOpts.DoModal() != IDOK) { - WMSG0("ConvFile cancelled\n"); - return; - } + if (selOpts.DoModal() != IDOK) { + WMSG0("ConvFile cancelled\n"); + return; + } - //fPreferences.SetPrefBool(kPrConvFileConvDOSText, - // selOpts.fConvDOSText != 0); - //fPreferences.SetPrefBool(kPrConvFileConvPascalText, - // selOpts.fConvPascalText != 0); - fPreferences.SetPrefBool(kPrConvFileEmptyFolders, - selOpts.fPreserveEmptyFolders != 0); + //fPreferences.SetPrefBool(kPrConvFileConvDOSText, + // selOpts.fConvDOSText != 0); + //fPreferences.SetPrefBool(kPrConvFileConvPascalText, + // selOpts.fConvPascalText != 0); + fPreferences.SetPrefBool(kPrConvFileEmptyFolders, + selOpts.fPreserveEmptyFolders != 0); - /* - * Create a "selection set" of data forks, resource forks, and - * directories. There are no comments or disk images on a disk image, - * so we just request "any" thread. - * - * We only need to explicitly include directories if "preserve - * empty folders" is set. - */ - SelectionSet selSet; - int threadMask = GenericEntry::kAnyThread; - if (selOpts.fPreserveEmptyFolders) - threadMask |= GenericEntry::kAllowDirectory; + /* + * Create a "selection set" of data forks, resource forks, and + * directories. There are no comments or disk images on a disk image, + * so we just request "any" thread. + * + * We only need to explicitly include directories if "preserve + * empty folders" is set. + */ + SelectionSet selSet; + int threadMask = GenericEntry::kAnyThread; + if (selOpts.fPreserveEmptyFolders) + threadMask |= GenericEntry::kAllowDirectory; - if (selOpts.fFilesToAction == UseSelectionDialog::kActionSelection) { - selSet.CreateFromSelection(fpContentList, threadMask); - } else { - selSet.CreateFromAll(fpContentList, threadMask); - } - //selSet.Dump(); + if (selOpts.fFilesToAction == UseSelectionDialog::kActionSelection) { + selSet.CreateFromSelection(fpContentList, threadMask); + } else { + selSet.CreateFromAll(fpContentList, threadMask); + } + //selSet.Dump(); - if (selSet.GetNumEntries() == 0) { - MessageBox("No files matched the selection criteria.", - "No match", MB_OK|MB_ICONEXCLAMATION); - return; - } + if (selSet.GetNumEntries() == 0) { + MessageBox("No files matched the selection criteria.", + "No match", MB_OK|MB_ICONEXCLAMATION); + return; + } - XferFileOptions xferOpts; - //xferOpts.fConvDOSText = (selOpts.fConvDOSText != 0); - //xferOpts.fConvPascalText = (selOpts.fConvPascalText != 0); - xferOpts.fPreserveEmptyFolders = (selOpts.fPreserveEmptyFolders != 0); + XferFileOptions xferOpts; + //xferOpts.fConvDOSText = (selOpts.fConvDOSText != 0); + //xferOpts.fConvPascalText = (selOpts.fConvPascalText != 0); + xferOpts.fPreserveEmptyFolders = (selOpts.fPreserveEmptyFolders != 0); - /* - * Create a new NuFX archive. - */ - CString filename, saveFolder, errStr; + /* + * Create a new NuFX archive. + */ + CString filename, saveFolder, errStr; - CFileDialog dlg(FALSE, _T("shk"), NULL, - OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, - "ShrinkIt Archives (*.shk)|*.shk||", this); + CFileDialog dlg(FALSE, _T("shk"), NULL, + OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, + "ShrinkIt Archives (*.shk)|*.shk||", this); - dlg.m_ofn.lpstrTitle = "New Archive"; - dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); + dlg.m_ofn.lpstrTitle = "New Archive"; + dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); - if (dlg.DoModal() != IDOK) { - WMSG0(" User cancelled xfer from archive create dialog\n"); - return; - } + if (dlg.DoModal() != IDOK) { + WMSG0(" User cancelled xfer from archive create dialog\n"); + return; + } - saveFolder = dlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); + saveFolder = dlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); - filename = dlg.GetPathName(); - WMSG1(" Will xfer to file '%s'\n", filename); + filename = dlg.GetPathName(); + WMSG1(" Will xfer to file '%s'\n", filename); - /* remove file if it already exists */ - CString errMsg; - errMsg = RemoveFile(filename); - if (!errMsg.IsEmpty()) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - return; - } + /* remove file if it already exists */ + CString errMsg; + errMsg = RemoveFile(filename); + if (!errMsg.IsEmpty()) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + return; + } - xferOpts.fTarget = new NufxArchive; - errStr = xferOpts.fTarget->New(filename, nil); - if (!errStr.IsEmpty()) { - ShowFailureMsg(this, errStr, IDS_FAILED); - delete xferOpts.fTarget; - return; - } + xferOpts.fTarget = new NufxArchive; + errStr = xferOpts.fTarget->New(filename, nil); + if (!errStr.IsEmpty()) { + ShowFailureMsg(this, errStr, IDS_FAILED); + delete xferOpts.fTarget; + return; + } - /* - * Set up the progress window. - */ - GenericArchive::XferStatus result; + /* + * Set up the progress window. + */ + GenericArchive::XferStatus result; - fpActionProgress = new ActionProgressDialog; - fpActionProgress->Create(ActionProgressDialog::kActionConvFile, this); + fpActionProgress = new ActionProgressDialog; + fpActionProgress->Create(ActionProgressDialog::kActionConvFile, this); - result = fpOpenArchive->XferSelection(fpActionProgress, &selSet, - fpActionProgress, &xferOpts); + result = fpOpenArchive->XferSelection(fpActionProgress, &selSet, + fpActionProgress, &xferOpts); - fpActionProgress->Cleanup(this); - fpActionProgress = nil; - if (result == GenericArchive::kXferOK) - SuccessBeep(); + fpActionProgress->Cleanup(this); + fpActionProgress = nil; + if (result == GenericArchive::kXferOK) + SuccessBeep(); - /* clean up */ - delete xferOpts.fTarget; + /* clean up */ + delete xferOpts.fTarget; } void MainWindow::OnUpdateActionsConvFile(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil && - fpContentList->GetItemCount() > 0 && - fpOpenArchive->GetArchiveKind() == GenericArchive::kArchiveDiskImage); + pCmdUI->Enable(fpContentList != nil && + fpContentList->GetItemCount() > 0 && + fpOpenArchive->GetArchiveKind() == GenericArchive::kArchiveDiskImage); } /* * ========================================================================== - * Cassette WAV conversions + * Cassette WAV conversions * ========================================================================== */ @@ -2239,28 +2239,28 @@ MainWindow::OnUpdateActionsConvFile(CCmdUI* pCmdUI) void MainWindow::OnActionsConvToWav(void) { - // do this someday - WMSG0("Convert TO wav\n"); + // do this someday + WMSG0("Convert TO wav\n"); } void MainWindow::OnUpdateActionsConvToWav(CCmdUI* pCmdUI) { - BOOL enable = false; + BOOL enable = false; - if (fpContentList != nil && fpContentList->GetSelectedCount() == 1) { - /* only BAS, INT, and BIN shorter than 64K */ - GenericEntry* pEntry = GetSelectedItem(fpContentList); + if (fpContentList != nil && fpContentList->GetSelectedCount() == 1) { + /* only BAS, INT, and BIN shorter than 64K */ + GenericEntry* pEntry = GetSelectedItem(fpContentList); - if ((pEntry->GetFileType() == kFileTypeBAS || - pEntry->GetFileType() == kFileTypeINT || - pEntry->GetFileType() == kFileTypeBIN) && - pEntry->GetDataForkLen() < 65536 && - pEntry->GetRecordKind() == GenericEntry::kRecordKindFile) - { - enable = true; - } - } - pCmdUI->Enable(enable); + if ((pEntry->GetFileType() == kFileTypeBAS || + pEntry->GetFileType() == kFileTypeINT || + pEntry->GetFileType() == kFileTypeBIN) && + pEntry->GetDataForkLen() < 65536 && + pEntry->GetRecordKind() == GenericEntry::kRecordKindFile) + { + enable = true; + } + } + pCmdUI->Enable(enable); } /* @@ -2270,40 +2270,40 @@ MainWindow::OnUpdateActionsConvToWav(CCmdUI* pCmdUI) void MainWindow::OnActionsConvFromWav(void) { - CassetteDialog dlg; - CString fileName, saveFolder; + CassetteDialog dlg; + CString fileName, saveFolder; - CFileDialog fileDlg(TRUE, "wav", NULL, OFN_FILEMUSTEXIST|OFN_HIDEREADONLY, - "Sound Files (*.wav)|*.wav||", this); - fileDlg.m_ofn.lpstrTitle = "Open Sound File"; - fileDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenWAVFolder); + CFileDialog fileDlg(TRUE, "wav", NULL, OFN_FILEMUSTEXIST|OFN_HIDEREADONLY, + "Sound Files (*.wav)|*.wav||", this); + fileDlg.m_ofn.lpstrTitle = "Open Sound File"; + fileDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenWAVFolder); - if (fileDlg.DoModal() != IDOK) - goto bail; + if (fileDlg.DoModal() != IDOK) + goto bail; - saveFolder = fileDlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(fileDlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrOpenWAVFolder, saveFolder); + saveFolder = fileDlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(fileDlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrOpenWAVFolder, saveFolder); - fileName = fileDlg.GetPathName(); - WMSG1("Opening WAV file '%s'\n", fileName); + fileName = fileDlg.GetPathName(); + WMSG1("Opening WAV file '%s'\n", fileName); - dlg.fFileName = fileName; - // pass in fpOpenArchive? + dlg.fFileName = fileName; + // pass in fpOpenArchive? - dlg.DoModal(); - if (dlg.IsDirty()) { - assert(fpContentList != nil); - fpContentList->Reload(); - } + dlg.DoModal(); + if (dlg.IsDirty()) { + assert(fpContentList != nil); + fpContentList->Reload(); + } bail: - return; + return; } void MainWindow::OnUpdateActionsConvFromWav(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly()); + pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly()); } @@ -2316,96 +2316,96 @@ MainWindow::OnUpdateActionsConvFromWav(CCmdUI* pCmdUI) */ /*static*/ bool MainWindow::SaveToArchive(GenericArchive::FileDetails* pDetails, - const unsigned char* dataBufIn, long dataLen, - const unsigned char* rsrcBufIn, long rsrcLen, - CString& errMsg, CWnd* pDialog) + const unsigned char* dataBufIn, long dataLen, + const unsigned char* rsrcBufIn, long rsrcLen, + CString& errMsg, CWnd* pDialog) { - MainWindow* pMain = GET_MAIN_WINDOW(); - GenericArchive* pArchive = pMain->GetOpenArchive(); - DiskImgLib::A2File* pTargetSubdir = nil; - XferFileOptions xferOpts; - CString storagePrefix; - unsigned char* dataBuf = nil; - unsigned char* rsrcBuf = nil; + MainWindow* pMain = GET_MAIN_WINDOW(); + GenericArchive* pArchive = pMain->GetOpenArchive(); + DiskImgLib::A2File* pTargetSubdir = nil; + XferFileOptions xferOpts; + CString storagePrefix; + unsigned char* dataBuf = nil; + unsigned char* rsrcBuf = nil; - ASSERT(pArchive != nil); - ASSERT(errMsg.IsEmpty()); + ASSERT(pArchive != nil); + ASSERT(errMsg.IsEmpty()); - /* - * Make a copy of the data for XferFile. - */ - if (dataLen >= 0) { - if (dataLen == 0) - dataBuf = new unsigned char[1]; - else - dataBuf = new unsigned char[dataLen]; - if (dataBuf == nil) { - errMsg.Format("Unable to allocate %ld bytes", dataLen); - goto bail; - } - memcpy(dataBuf, dataBufIn, dataLen); - } - if (rsrcLen >= 0) { - assert(false); - } + /* + * Make a copy of the data for XferFile. + */ + if (dataLen >= 0) { + if (dataLen == 0) + dataBuf = new unsigned char[1]; + else + dataBuf = new unsigned char[dataLen]; + if (dataBuf == nil) { + errMsg.Format("Unable to allocate %ld bytes", dataLen); + goto bail; + } + memcpy(dataBuf, dataBufIn, dataLen); + } + if (rsrcLen >= 0) { + assert(false); + } - /* - * Figure out where we want to put the files. For a disk archive - * this can be complicated. - * - * The target DiskFS (which could be a sub-volume) gets tucked into - * the xferOpts. - */ - if (pArchive->GetArchiveKind() == GenericArchive::kArchiveDiskImage) { - if (!pMain->ChooseAddTarget(&pTargetSubdir, &xferOpts.fpTargetFS)) - goto bail; - } else if (pArchive->GetArchiveKind() == GenericArchive::kArchiveNuFX) { - // Always use ':' separator for SHK; this is a matter of - // convenience, so they can specify a full path. - //details.storageName.Replace(':', '_'); - pDetails->fileSysInfo = ':'; - } - if (pTargetSubdir != nil) { - storagePrefix = pTargetSubdir->GetPathName(); - WMSG1("--- using storagePrefix '%s'\n", (const char*) storagePrefix); - } - if (!storagePrefix.IsEmpty()) { - CString tmpStr, tmpFileName; - tmpFileName = pDetails->storageName; - tmpFileName.Replace(':', '_'); // strip any ':'s in the name - pDetails->fileSysInfo = ':'; - tmpStr = storagePrefix; - tmpStr += ':'; - tmpStr += tmpFileName; - pDetails->storageName = tmpStr; - } + /* + * Figure out where we want to put the files. For a disk archive + * this can be complicated. + * + * The target DiskFS (which could be a sub-volume) gets tucked into + * the xferOpts. + */ + if (pArchive->GetArchiveKind() == GenericArchive::kArchiveDiskImage) { + if (!pMain->ChooseAddTarget(&pTargetSubdir, &xferOpts.fpTargetFS)) + goto bail; + } else if (pArchive->GetArchiveKind() == GenericArchive::kArchiveNuFX) { + // Always use ':' separator for SHK; this is a matter of + // convenience, so they can specify a full path. + //details.storageName.Replace(':', '_'); + pDetails->fileSysInfo = ':'; + } + if (pTargetSubdir != nil) { + storagePrefix = pTargetSubdir->GetPathName(); + WMSG1("--- using storagePrefix '%s'\n", (const char*) storagePrefix); + } + if (!storagePrefix.IsEmpty()) { + CString tmpStr, tmpFileName; + tmpFileName = pDetails->storageName; + tmpFileName.Replace(':', '_'); // strip any ':'s in the name + pDetails->fileSysInfo = ':'; + tmpStr = storagePrefix; + tmpStr += ':'; + tmpStr += tmpFileName; + pDetails->storageName = tmpStr; + } - /* - * Handle the transfer. - * - * On success, XferFile will null out our dataBuf and rsrcBuf pointers. - */ - pArchive->XferPrepare(&xferOpts); + /* + * Handle the transfer. + * + * On success, XferFile will null out our dataBuf and rsrcBuf pointers. + */ + pArchive->XferPrepare(&xferOpts); - errMsg = pArchive->XferFile(pDetails, &dataBuf, dataLen, - &rsrcBuf, rsrcLen); - delete[] dataBuf; - delete[] rsrcBuf; + errMsg = pArchive->XferFile(pDetails, &dataBuf, dataLen, + &rsrcBuf, rsrcLen); + delete[] dataBuf; + delete[] rsrcBuf; - if (errMsg.IsEmpty()) - pArchive->XferFinish(pDialog); - else - pArchive->XferAbort(pDialog); + if (errMsg.IsEmpty()) + pArchive->XferFinish(pDialog); + else + pArchive->XferAbort(pDialog); bail: - return (errMsg.IsEmpty() != 0); + return (errMsg.IsEmpty() != 0); } /* * ========================================================================== - * Import BASIC programs from a text file + * Import BASIC programs from a text file * ========================================================================== */ @@ -2418,46 +2418,46 @@ bail: void MainWindow::OnActionsImportBAS(void) { - ImportBASDialog dlg; - CString fileName, saveFolder; + ImportBASDialog dlg; + CString fileName, saveFolder; - CFileDialog fileDlg(TRUE, "txt", NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, - "Text files (*.txt)|*.txt||", this); - fileDlg.m_ofn.lpstrTitle = "Open Text File"; - fileDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrAddFileFolder); + CFileDialog fileDlg(TRUE, "txt", NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, + "Text files (*.txt)|*.txt||", this); + fileDlg.m_ofn.lpstrTitle = "Open Text File"; + fileDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrAddFileFolder); - if (fileDlg.DoModal() != IDOK) - goto bail; + if (fileDlg.DoModal() != IDOK) + goto bail; - saveFolder = fileDlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(fileDlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrAddFileFolder, saveFolder); + saveFolder = fileDlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(fileDlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrAddFileFolder, saveFolder); - fileName = fileDlg.GetPathName(); - WMSG1("Opening TXT file '%s'\n", fileName); + fileName = fileDlg.GetPathName(); + WMSG1("Opening TXT file '%s'\n", fileName); - dlg.fFileName = fileName; - // pass in fpOpenArchive? + dlg.fFileName = fileName; + // pass in fpOpenArchive? - dlg.DoModal(); - if (dlg.IsDirty()) { - assert(fpContentList != nil); - fpContentList->Reload(); - } + dlg.DoModal(); + if (dlg.IsDirty()) { + assert(fpContentList != nil); + fpContentList->Reload(); + } bail: - return; + return; } void MainWindow::OnUpdateActionsImportBAS(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly()); + pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly()); } /* * ========================================================================== - * Multiple file handling + * Multiple file handling * ========================================================================== */ @@ -2470,26 +2470,26 @@ MainWindow::OnUpdateActionsImportBAS(CCmdUI* pCmdUI) */ int MainWindow::GetFileParts(const GenericEntry* pEntry, - ReformatHolder** ppHolder) const + ReformatHolder** ppHolder) const { - ReformatHolder* pHolder = new ReformatHolder; - CString errMsg; + ReformatHolder* pHolder = new ReformatHolder; + CString errMsg; - if (pHolder == nil) - return -1; + if (pHolder == nil) + return -1; - if (pEntry->GetHasDataFork()) - GetFilePart(pEntry, GenericEntry::kDataThread, pHolder); - if (pEntry->GetHasRsrcFork()) - GetFilePart(pEntry, GenericEntry::kRsrcThread, pHolder); - if (pEntry->GetHasComment()) - GetFilePart(pEntry, GenericEntry::kCommentThread, pHolder); - if (pEntry->GetHasDiskImage()) - GetFilePart(pEntry, GenericEntry::kDiskImageThread, pHolder); + if (pEntry->GetHasDataFork()) + GetFilePart(pEntry, GenericEntry::kDataThread, pHolder); + if (pEntry->GetHasRsrcFork()) + GetFilePart(pEntry, GenericEntry::kRsrcThread, pHolder); + if (pEntry->GetHasComment()) + GetFilePart(pEntry, GenericEntry::kCommentThread, pHolder); + if (pEntry->GetHasDiskImage()) + GetFilePart(pEntry, GenericEntry::kDiskImageThread, pHolder); - *ppHolder = pHolder; + *ppHolder = pHolder; - return 0; + return 0; } /* @@ -2497,65 +2497,65 @@ MainWindow::GetFileParts(const GenericEntry* pEntry, */ void MainWindow::GetFilePart(const GenericEntry* pEntry, int whichThread, - ReformatHolder* pHolder) const + ReformatHolder* pHolder) const { - CString errMsg; - ReformatHolder::ReformatPart part; - char* buf = nil; - long len = 0; - di_off_t threadLen; - int result; + CString errMsg; + ReformatHolder::ReformatPart part; + char* buf = nil; + long len = 0; + di_off_t threadLen; + int result; - switch (whichThread) { - case GenericEntry::kDataThread: - part = ReformatHolder::kPartData; - threadLen = pEntry->GetDataForkLen(); - break; - case GenericEntry::kRsrcThread: - part = ReformatHolder::kPartRsrc; - threadLen = pEntry->GetRsrcForkLen(); - break; - case GenericEntry::kCommentThread: - part = ReformatHolder::kPartCmmt; - threadLen = -1; // no comment len getter; assume it's small - break; - case GenericEntry::kDiskImageThread: - part = ReformatHolder::kPartData; // put disks into data thread - threadLen = pEntry->GetDataForkLen(); - break; - default: - ASSERT(false); - return; - } + switch (whichThread) { + case GenericEntry::kDataThread: + part = ReformatHolder::kPartData; + threadLen = pEntry->GetDataForkLen(); + break; + case GenericEntry::kRsrcThread: + part = ReformatHolder::kPartRsrc; + threadLen = pEntry->GetRsrcForkLen(); + break; + case GenericEntry::kCommentThread: + part = ReformatHolder::kPartCmmt; + threadLen = -1; // no comment len getter; assume it's small + break; + case GenericEntry::kDiskImageThread: + part = ReformatHolder::kPartData; // put disks into data thread + threadLen = pEntry->GetDataForkLen(); + break; + default: + ASSERT(false); + return; + } - if (threadLen > fPreferences.GetPrefLong(kPrMaxViewFileSize)) { - errMsg.Format( - "[File size (%I64d KBytes) exceeds file viewer maximum (%ld KBytes).]\n", - ((LONGLONG) threadLen + 1023) / 1024, - (fPreferences.GetPrefLong(kPrMaxViewFileSize) + 1023) / 1024); - pHolder->SetErrorMsg(part, errMsg); - goto bail; - } - + if (threadLen > fPreferences.GetPrefLong(kPrMaxViewFileSize)) { + errMsg.Format( + "[File size (%I64d KBytes) exceeds file viewer maximum (%ld KBytes).]\n", + ((LONGLONG) threadLen + 1023) / 1024, + (fPreferences.GetPrefLong(kPrMaxViewFileSize) + 1023) / 1024); + pHolder->SetErrorMsg(part, errMsg); + goto bail; + } + - result = pEntry->ExtractThreadToBuffer(whichThread, &buf, &len, &errMsg); + result = pEntry->ExtractThreadToBuffer(whichThread, &buf, &len, &errMsg); - if (result == IDOK) { - /* on success, ETTB guarantees a buffer, even for zero-len file */ - ASSERT(buf != nil); - pHolder->SetSourceBuf(part, (unsigned char*) buf, len); - } else if (result == IDCANCEL) { - /* not expected */ - errMsg = "Cancelled!"; - pHolder->SetErrorMsg(part, errMsg); - ASSERT(buf == nil); - } else { - /* transfer error message to ReformatHolder buffer */ - WMSG1("Got error message from ExtractThread: '%s'\n", errMsg); - pHolder->SetErrorMsg(part, errMsg); - ASSERT(buf == nil); - } + if (result == IDOK) { + /* on success, ETTB guarantees a buffer, even for zero-len file */ + ASSERT(buf != nil); + pHolder->SetSourceBuf(part, (unsigned char*) buf, len); + } else if (result == IDCANCEL) { + /* not expected */ + errMsg = "Cancelled!"; + pHolder->SetErrorMsg(part, errMsg); + ASSERT(buf == nil); + } else { + /* transfer error message to ReformatHolder buffer */ + WMSG1("Got error message from ExtractThread: '%s'\n", errMsg); + pHolder->SetErrorMsg(part, errMsg); + ASSERT(buf == nil); + } bail: - return; + return; } diff --git a/app/AddClashDialog.cpp b/app/AddClashDialog.cpp index db2adc4..d26524d 100644 --- a/app/AddClashDialog.cpp +++ b/app/AddClashDialog.cpp @@ -11,9 +11,9 @@ #include "AddClashDialog.h" BEGIN_MESSAGE_MAP(AddClashDialog, CDialog) - ON_BN_CLICKED(IDC_CLASH_RENAME, OnRename) - ON_BN_CLICKED(IDC_CLASH_SKIP, OnSkip) - //ON_WM_HELPINFO() + ON_BN_CLICKED(IDC_CLASH_RENAME, OnRename) + ON_BN_CLICKED(IDC_CLASH_SKIP, OnSkip) + //ON_WM_HELPINFO() END_MESSAGE_MAP() /* @@ -22,17 +22,17 @@ END_MESSAGE_MAP() BOOL AddClashDialog::OnInitDialog(void) { - CWnd* pWnd; + CWnd* pWnd; - pWnd = GetDlgItem(IDC_CLASH_WINNAME); - ASSERT(pWnd != nil); - pWnd->SetWindowText(fWindowsName); + pWnd = GetDlgItem(IDC_CLASH_WINNAME); + ASSERT(pWnd != nil); + pWnd->SetWindowText(fWindowsName); - pWnd = GetDlgItem(IDC_CLASH_STORAGENAME); - ASSERT(pWnd != nil); - pWnd->SetWindowText(fStorageName); + pWnd = GetDlgItem(IDC_CLASH_STORAGENAME); + ASSERT(pWnd != nil); + pWnd->SetWindowText(fStorageName); - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } /* @@ -41,20 +41,20 @@ AddClashDialog::OnInitDialog(void) void AddClashDialog::OnSkip(void) { - fDoRename = false; - CDialog::OnOK(); + fDoRename = false; + CDialog::OnOK(); } void AddClashDialog::OnRename(void) { - RenameOverwriteDialog dlg; + RenameOverwriteDialog dlg; - dlg.fNewFileSource = fWindowsName; - dlg.fExistingFile = fStorageName; - dlg.fNewName = fStorageName; - if (dlg.DoModal() == IDOK) { - fNewName = dlg.fNewName; - fDoRename = true; - CDialog::OnOK(); - } + dlg.fNewFileSource = fWindowsName; + dlg.fExistingFile = fStorageName; + dlg.fNewName = fStorageName; + if (dlg.DoModal() == IDOK) { + fNewName = dlg.fNewName; + fDoRename = true; + CDialog::OnOK(); + } } diff --git a/app/AddClashDialog.h b/app/AddClashDialog.h index fdbe97f..47c1a28 100644 --- a/app/AddClashDialog.h +++ b/app/AddClashDialog.h @@ -14,26 +14,26 @@ */ class AddClashDialog : public CDialog { public: - AddClashDialog(CWnd* pParentWnd = nil) : - CDialog(IDD_ADD_CLASH, pParentWnd) - { - fDoRename = false; - } - ~AddClashDialog(void) {} + AddClashDialog(CWnd* pParentWnd = nil) : + CDialog(IDD_ADD_CLASH, pParentWnd) + { + fDoRename = false; + } + ~AddClashDialog(void) {} - CString fWindowsName; - CString fStorageName; + CString fWindowsName; + CString fStorageName; - bool fDoRename; // if "false", skip this file - CString fNewName; + bool fDoRename; // if "false", skip this file + CString fNewName; private: - afx_msg void OnRename(void); - afx_msg void OnSkip(void); + afx_msg void OnRename(void); + afx_msg void OnSkip(void); - virtual BOOL OnInitDialog(void); + virtual BOOL OnInitDialog(void); - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__ADDCLASHDIALOG__*/ diff --git a/app/AddFilesDialog.cpp b/app/AddFilesDialog.cpp index ec27a96..7a469a5 100644 --- a/app/AddFilesDialog.cpp +++ b/app/AddFilesDialog.cpp @@ -26,91 +26,91 @@ bool AddFilesDialog::MyDataExchange(bool saveAndValidate) { - CWnd* pWnd; + CWnd* pWnd; - if (saveAndValidate) { - if (GetDlgButtonCheck(this, IDC_ADDFILES_NOPRESERVE) == BST_CHECKED) - fTypePreservation = kPreserveNone; - else if (GetDlgButtonCheck(this, IDC_ADDFILES_PRESERVE) == BST_CHECKED) - fTypePreservation = kPreserveTypes; - else if (GetDlgButtonCheck(this, IDC_ADDFILES_PRESERVEPLUS) == BST_CHECKED) - fTypePreservation = kPreserveAndExtend; - else { - ASSERT(false); - fTypePreservation = kPreserveNone; - } + if (saveAndValidate) { + if (GetDlgButtonCheck(this, IDC_ADDFILES_NOPRESERVE) == BST_CHECKED) + fTypePreservation = kPreserveNone; + else if (GetDlgButtonCheck(this, IDC_ADDFILES_PRESERVE) == BST_CHECKED) + fTypePreservation = kPreserveTypes; + else if (GetDlgButtonCheck(this, IDC_ADDFILES_PRESERVEPLUS) == BST_CHECKED) + fTypePreservation = kPreserveAndExtend; + else { + ASSERT(false); + fTypePreservation = kPreserveNone; + } - if (GetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLNONE) == BST_CHECKED) - fConvEOL = kConvEOLNone; - else if (GetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLTYPE) == BST_CHECKED) - fConvEOL = kConvEOLType; - else if (GetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLTEXT) == BST_CHECKED) - fConvEOL = kConvEOLAuto; - else if (GetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLALL) == BST_CHECKED) - fConvEOL = kConvEOLAll; - else { - ASSERT(false); - fConvEOL = kConvEOLNone; - } + if (GetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLNONE) == BST_CHECKED) + fConvEOL = kConvEOLNone; + else if (GetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLTYPE) == BST_CHECKED) + fConvEOL = kConvEOLType; + else if (GetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLTEXT) == BST_CHECKED) + fConvEOL = kConvEOLAuto; + else if (GetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLALL) == BST_CHECKED) + fConvEOL = kConvEOLAll; + else { + ASSERT(false); + fConvEOL = kConvEOLNone; + } - fIncludeSubfolders = - (GetDlgButtonCheck(this, IDC_ADDFILES_INCLUDE_SUBFOLDERS) == BST_CHECKED); - fStripFolderNames = - (GetDlgButtonCheck(this, IDC_ADDFILES_STRIP_FOLDER) == BST_CHECKED); - fOverwriteExisting = - (GetDlgButtonCheck(this, IDC_ADDFILES_OVERWRITE) == BST_CHECKED); + fIncludeSubfolders = + (GetDlgButtonCheck(this, IDC_ADDFILES_INCLUDE_SUBFOLDERS) == BST_CHECKED); + fStripFolderNames = + (GetDlgButtonCheck(this, IDC_ADDFILES_STRIP_FOLDER) == BST_CHECKED); + fOverwriteExisting = + (GetDlgButtonCheck(this, IDC_ADDFILES_OVERWRITE) == BST_CHECKED); - pWnd = GetDlgItem(IDC_ADDFILES_PREFIX); - ASSERT(pWnd != nil); - pWnd->GetWindowText(fStoragePrefix); + pWnd = GetDlgItem(IDC_ADDFILES_PREFIX); + ASSERT(pWnd != nil); + pWnd->GetWindowText(fStoragePrefix); - if (!ValidateStoragePrefix()) - return false; + if (!ValidateStoragePrefix()) + return false; - return true; - } else { - SetDlgButtonCheck(this, IDC_ADDFILES_NOPRESERVE, - fTypePreservation == kPreserveNone); - SetDlgButtonCheck(this, IDC_ADDFILES_PRESERVE, - fTypePreservation == kPreserveTypes); - SetDlgButtonCheck(this, IDC_ADDFILES_PRESERVEPLUS, - fTypePreservation == kPreserveAndExtend); + return true; + } else { + SetDlgButtonCheck(this, IDC_ADDFILES_NOPRESERVE, + fTypePreservation == kPreserveNone); + SetDlgButtonCheck(this, IDC_ADDFILES_PRESERVE, + fTypePreservation == kPreserveTypes); + SetDlgButtonCheck(this, IDC_ADDFILES_PRESERVEPLUS, + fTypePreservation == kPreserveAndExtend); - SetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLNONE, - fConvEOL == kConvEOLNone); - SetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLTYPE, - fConvEOL == kConvEOLType); - SetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLTEXT, - fConvEOL == kConvEOLAuto); - SetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLALL, - fConvEOL == kConvEOLAll); + SetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLNONE, + fConvEOL == kConvEOLNone); + SetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLTYPE, + fConvEOL == kConvEOLType); + SetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLTEXT, + fConvEOL == kConvEOLAuto); + SetDlgButtonCheck(this, IDC_ADDFILES_CONVEOLALL, + fConvEOL == kConvEOLAll); - SetDlgButtonCheck(this, IDC_ADDFILES_INCLUDE_SUBFOLDERS, - fIncludeSubfolders != FALSE); - SetDlgButtonCheck(this, IDC_ADDFILES_STRIP_FOLDER, - fStripFolderNames != FALSE); - SetDlgButtonCheck(this, IDC_ADDFILES_OVERWRITE, - fOverwriteExisting != FALSE); + SetDlgButtonCheck(this, IDC_ADDFILES_INCLUDE_SUBFOLDERS, + fIncludeSubfolders != FALSE); + SetDlgButtonCheck(this, IDC_ADDFILES_STRIP_FOLDER, + fStripFolderNames != FALSE); + SetDlgButtonCheck(this, IDC_ADDFILES_OVERWRITE, + fOverwriteExisting != FALSE); - pWnd = GetDlgItem(IDC_ADDFILES_PREFIX); - ASSERT(pWnd != nil); - pWnd->SetWindowText(fStoragePrefix); - if (!fStoragePrefixEnable) - pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_ADDFILES_PREFIX); + ASSERT(pWnd != nil); + pWnd->SetWindowText(fStoragePrefix); + if (!fStoragePrefixEnable) + pWnd->EnableWindow(FALSE); - if (!fStripFolderNamesEnable) { - ::EnableControl(this, IDC_ADDFILES_STRIP_FOLDER, false); - } + if (!fStripFolderNamesEnable) { + ::EnableControl(this, IDC_ADDFILES_STRIP_FOLDER, false); + } - if (!fConvEOLEnable) { - ::EnableControl(this, IDC_ADDFILES_CONVEOLNONE, false); - ::EnableControl(this, IDC_ADDFILES_CONVEOLTYPE, false); - ::EnableControl(this, IDC_ADDFILES_CONVEOLTEXT, false); - ::EnableControl(this, IDC_ADDFILES_CONVEOLALL, false); - } + if (!fConvEOLEnable) { + ::EnableControl(this, IDC_ADDFILES_CONVEOLNONE, false); + ::EnableControl(this, IDC_ADDFILES_CONVEOLTYPE, false); + ::EnableControl(this, IDC_ADDFILES_CONVEOLTEXT, false); + ::EnableControl(this, IDC_ADDFILES_CONVEOLALL, false); + } - return true; - } + return true; + } } /* @@ -119,19 +119,19 @@ AddFilesDialog::MyDataExchange(bool saveAndValidate) bool AddFilesDialog::ValidateStoragePrefix(void) { - if (fStoragePrefix.IsEmpty()) - return true; + if (fStoragePrefix.IsEmpty()) + return true; - const char kFssep = PathProposal::kDefaultStoredFssep; - if (fStoragePrefix[0] == kFssep || fStoragePrefix.Right(1) == kFssep) { - CString errMsg; - errMsg.Format("The storage prefix may not start or end with '%c'.", - kFssep); - MessageBox(errMsg, m_ofn.lpstrTitle, MB_OK | MB_ICONWARNING); - return false; - } + const char kFssep = PathProposal::kDefaultStoredFssep; + if (fStoragePrefix[0] == kFssep || fStoragePrefix.Right(1) == kFssep) { + CString errMsg; + errMsg.Format("The storage prefix may not start or end with '%c'.", + kFssep); + MessageBox(errMsg, m_ofn.lpstrTitle, MB_OK | MB_ICONWARNING); + return false; + } - return true; + return true; } @@ -141,13 +141,13 @@ AddFilesDialog::ValidateStoragePrefix(void) UINT AddFilesDialog::MyOnCommand(WPARAM wParam, LPARAM lParam) { - switch (wParam) { - case IDHELP: - OnIDHelp(); - return 1; - default: - return SelectFilesDialog::MyOnCommand(wParam, lParam); - } + switch (wParam) { + case IDHELP: + OnIDHelp(); + return 1; + default: + return SelectFilesDialog::MyOnCommand(wParam, lParam); + } } /* @@ -159,33 +159,33 @@ AddFilesDialog::MyOnCommand(WPARAM wParam, LPARAM lParam) void AddFilesDialog::ShiftControls(int deltaX, int deltaY) { - /* - * These only need to be here so that the initial move puts them - * where they belong. Once the dialog has been created, the - * CFileDialog will move things where they need to go. - */ - MoveControl(this, IDC_ADDFILES_STATIC1, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_NOPRESERVE, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_PRESERVE, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_PRESERVEPLUS, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_STATIC2, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_STRIP_FOLDER, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_INCLUDE_SUBFOLDERS, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_OVERWRITE, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_STATIC3, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_PREFIX, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_STATIC4, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_CONVEOLNONE, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_CONVEOLTYPE, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_CONVEOLTEXT, 0, deltaY, false); - MoveControl(this, IDC_ADDFILES_CONVEOLALL, 0, deltaY, false); + /* + * These only need to be here so that the initial move puts them + * where they belong. Once the dialog has been created, the + * CFileDialog will move things where they need to go. + */ + MoveControl(this, IDC_ADDFILES_STATIC1, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_NOPRESERVE, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_PRESERVE, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_PRESERVEPLUS, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_STATIC2, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_STRIP_FOLDER, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_INCLUDE_SUBFOLDERS, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_OVERWRITE, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_STATIC3, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_PREFIX, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_STATIC4, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_CONVEOLNONE, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_CONVEOLTYPE, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_CONVEOLTEXT, 0, deltaY, false); + MoveControl(this, IDC_ADDFILES_CONVEOLALL, 0, deltaY, false); - /* - * These actively move. - */ - MoveControl(this, IDHELP, deltaX, deltaY, false); - StretchControl(this, IDC_ADDFILES_PREFIX, deltaX, 0, false); - SelectFilesDialog::ShiftControls(deltaX, deltaY); + /* + * These actively move. + */ + MoveControl(this, IDHELP, deltaX, deltaY, false); + StretchControl(this, IDC_ADDFILES_PREFIX, deltaX, 0, false); + SelectFilesDialog::ShiftControls(deltaX, deltaY); } /* @@ -194,9 +194,9 @@ AddFilesDialog::ShiftControls(int deltaX, int deltaY) void AddFilesDialog::OnIDHelp(void) { - CWnd* pWndMain = ::AfxGetMainWnd(); - CWinApp* pAppMain = ::AfxGetApp(); + CWnd* pWndMain = ::AfxGetMainWnd(); + CWinApp* pAppMain = ::AfxGetApp(); - ::WinHelp(pWndMain->m_hWnd, pAppMain->m_pszHelpFilePath, - HELP_CONTEXT, HELP_TOPIC_ADD_FILES_DLG); + ::WinHelp(pWndMain->m_hWnd, pAppMain->m_pszHelpFilePath, + HELP_CONTEXT, HELP_TOPIC_ADD_FILES_DLG); } diff --git a/app/AddFilesDialog.h b/app/AddFilesDialog.h index e5a39db..ff13e5e 100644 --- a/app/AddFilesDialog.h +++ b/app/AddFilesDialog.h @@ -22,59 +22,59 @@ */ class AddFilesDialog : public SelectFilesDialog { public: - AddFilesDialog(CWnd* pParentWnd = NULL) : - SelectFilesDialog("IDD_ADD_FILES", pParentWnd) - { - SetWindowTitle(_T("Add Files...")); - fStoragePrefix = ""; - fStoragePrefixEnable = true; - fIncludeSubfolders = FALSE; - fStripFolderNames = FALSE; - fStripFolderNamesEnable = true; - fOverwriteExisting = FALSE; - fTypePreservation = 0; - fConvEOL = 0; - fConvEOLEnable = true; + AddFilesDialog(CWnd* pParentWnd = NULL) : + SelectFilesDialog("IDD_ADD_FILES", pParentWnd) + { + SetWindowTitle(_T("Add Files...")); + fStoragePrefix = ""; + fStoragePrefixEnable = true; + fIncludeSubfolders = FALSE; + fStripFolderNames = FALSE; + fStripFolderNamesEnable = true; + fOverwriteExisting = FALSE; + fTypePreservation = 0; + fConvEOL = 0; + fConvEOLEnable = true; - fAcceptButtonID = IDC_SELECT_ACCEPT; + fAcceptButtonID = IDC_SELECT_ACCEPT; - fpTargetDiskFS = nil; - //fpTargetSubdir = nil; - fpDiskImg = nil; - } - virtual ~AddFilesDialog(void) {} + fpTargetDiskFS = nil; + //fpTargetSubdir = nil; + fpDiskImg = nil; + } + virtual ~AddFilesDialog(void) {} - /* values from dialog */ - CString fStoragePrefix; - bool fStoragePrefixEnable; - BOOL fIncludeSubfolders; - BOOL fStripFolderNames; - bool fStripFolderNamesEnable; - BOOL fOverwriteExisting; + /* values from dialog */ + CString fStoragePrefix; + bool fStoragePrefixEnable; + BOOL fIncludeSubfolders; + BOOL fStripFolderNames; + bool fStripFolderNamesEnable; + BOOL fOverwriteExisting; - enum { kPreserveNone = 0, kPreserveTypes, kPreserveAndExtend }; - int fTypePreservation; + enum { kPreserveNone = 0, kPreserveTypes, kPreserveAndExtend }; + int fTypePreservation; - enum { kConvEOLNone = 0, kConvEOLType, kConvEOLAuto, kConvEOLAll }; - int fConvEOL; - bool fConvEOLEnable; + enum { kConvEOLNone = 0, kConvEOLType, kConvEOLAuto, kConvEOLAll }; + int fConvEOL; + bool fConvEOLEnable; - /* carryover from ChooseAddTargetDialog */ - DiskImgLib::DiskFS* fpTargetDiskFS; - //DiskImgLib::A2File* fpTargetSubdir; + /* carryover from ChooseAddTargetDialog */ + DiskImgLib::DiskFS* fpTargetDiskFS; + //DiskImgLib::A2File* fpTargetSubdir; - /* kluge; we carry this around for the benefit of AddDisk */ - DiskImgLib::DiskImg* fpDiskImg; + /* kluge; we carry this around for the benefit of AddDisk */ + DiskImgLib::DiskImg* fpDiskImg; private: - virtual bool MyDataExchange(bool saveAndValidate); - virtual void ShiftControls(int deltaX, int deltaY); - virtual UINT MyOnCommand(WPARAM wParam, LPARAM lParam); + virtual bool MyDataExchange(bool saveAndValidate); + virtual void ShiftControls(int deltaX, int deltaY); + virtual UINT MyOnCommand(WPARAM wParam, LPARAM lParam); - void OnIDHelp(void); - bool ValidateStoragePrefix(void); + void OnIDHelp(void); + bool ValidateStoragePrefix(void); - //DECLARE_MESSAGE_MAP() + //DECLARE_MESSAGE_MAP() }; #endif /*__ADDFILESDIALOG__*/ \ No newline at end of file diff --git a/app/ArchiveInfoDialog.cpp b/app/ArchiveInfoDialog.cpp index 3edc3f5..f73cfcb 100644 --- a/app/ArchiveInfoDialog.cpp +++ b/app/ArchiveInfoDialog.cpp @@ -13,12 +13,12 @@ /* * =========================================================================== - * ArchiveInfoDialog + * ArchiveInfoDialog * =========================================================================== */ BEGIN_MESSAGE_MAP(ArchiveInfoDialog, CDialog) - ON_COMMAND(IDHELP, OnHelp) + ON_COMMAND(IDHELP, OnHelp) END_MESSAGE_MAP() /* @@ -27,13 +27,13 @@ END_MESSAGE_MAP() void ArchiveInfoDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_ARCHIVE_INFO, HELP_CONTEXT); + WinHelp(HELP_TOPIC_ARCHIVE_INFO, HELP_CONTEXT); } /* * =========================================================================== - * NufxArchiveInfoDialog + * NufxArchiveInfoDialog * =========================================================================== */ @@ -43,82 +43,82 @@ ArchiveInfoDialog::OnHelp(void) BOOL NufxArchiveInfoDialog::OnInitDialog(void) { - CString notAvailable = "(not available)"; - NuArchive* pNuArchive; - const NuMasterHeader* pMasterHeader; - CWnd* pWnd; - CString tmpStr; - NuAttr attr; - NuError nerr; - time_t when; + CString notAvailable = "(not available)"; + NuArchive* pNuArchive; + const NuMasterHeader* pMasterHeader; + CWnd* pWnd; + CString tmpStr; + NuAttr attr; + NuError nerr; + time_t when; - ASSERT(fpArchive != nil); + ASSERT(fpArchive != nil); - pNuArchive = fpArchive->GetNuArchivePointer(); - ASSERT(pNuArchive != nil); - (void) NuGetMasterHeader(pNuArchive, &pMasterHeader); - ASSERT(pMasterHeader != nil); + pNuArchive = fpArchive->GetNuArchivePointer(); + ASSERT(pNuArchive != nil); + (void) NuGetMasterHeader(pNuArchive, &pMasterHeader); + ASSERT(pMasterHeader != nil); - pWnd = GetDlgItem(IDC_AI_FILENAME); - pWnd->SetWindowText(fpArchive->GetPathName()); + pWnd = GetDlgItem(IDC_AI_FILENAME); + pWnd->SetWindowText(fpArchive->GetPathName()); - pWnd = GetDlgItem(IDC_AINUFX_RECORDS); - nerr = NuGetAttr(pNuArchive, kNuAttrNumRecords, &attr); - if (nerr == kNuErrNone) - tmpStr.Format("%ld", attr); - else - tmpStr = notAvailable; - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AINUFX_RECORDS); + nerr = NuGetAttr(pNuArchive, kNuAttrNumRecords, &attr); + if (nerr == kNuErrNone) + tmpStr.Format("%ld", attr); + else + tmpStr = notAvailable; + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_AINUFX_FORMAT); - nerr = NuGetAttr(pNuArchive, kNuAttrArchiveType, &attr); - switch (attr) { - case kNuArchiveNuFX: tmpStr = "NuFX"; break; - case kNuArchiveNuFXInBNY: tmpStr = "NuFX in Binary II"; break; - case kNuArchiveNuFXSelfEx: tmpStr = "Self-extracting NuFX"; break; - case kNuArchiveNuFXSelfExInBNY: tmpStr = "Self-extracting NuFX in Binary II"; - break; - case kNuArchiveBNY: tmpStr = "Binary II"; break; - default: - tmpStr = "(unknown)"; - break; - }; - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AINUFX_FORMAT); + nerr = NuGetAttr(pNuArchive, kNuAttrArchiveType, &attr); + switch (attr) { + case kNuArchiveNuFX: tmpStr = "NuFX"; break; + case kNuArchiveNuFXInBNY: tmpStr = "NuFX in Binary II"; break; + case kNuArchiveNuFXSelfEx: tmpStr = "Self-extracting NuFX"; break; + case kNuArchiveNuFXSelfExInBNY: tmpStr = "Self-extracting NuFX in Binary II"; + break; + case kNuArchiveBNY: tmpStr = "Binary II"; break; + default: + tmpStr = "(unknown)"; + break; + }; + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_AINUFX_MASTERVERSION); - tmpStr.Format("%ld", pMasterHeader->mhMasterVersion); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AINUFX_MASTERVERSION); + tmpStr.Format("%ld", pMasterHeader->mhMasterVersion); + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_AINUFX_CREATEWHEN); - when = NufxArchive::DateTimeToSeconds(&pMasterHeader->mhArchiveCreateWhen); - tmpStr.Format("%.24s", ctime(&when)); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AINUFX_CREATEWHEN); + when = NufxArchive::DateTimeToSeconds(&pMasterHeader->mhArchiveCreateWhen); + tmpStr.Format("%.24s", ctime(&when)); + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_AINUFX_MODIFYWHEN); - when = NufxArchive::DateTimeToSeconds(&pMasterHeader->mhArchiveModWhen); - tmpStr.Format("%.24s", ctime(&when)); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AINUFX_MODIFYWHEN); + when = NufxArchive::DateTimeToSeconds(&pMasterHeader->mhArchiveModWhen); + tmpStr.Format("%.24s", ctime(&when)); + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_AINUFX_JUNKSKIPPED); - nerr = NuGetAttr(pNuArchive, kNuAttrJunkOffset, &attr); - if (nerr == kNuErrNone) - tmpStr.Format("%ld bytes", attr); - else - tmpStr = notAvailable; - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AINUFX_JUNKSKIPPED); + nerr = NuGetAttr(pNuArchive, kNuAttrJunkOffset, &attr); + if (nerr == kNuErrNone) + tmpStr.Format("%ld bytes", attr); + else + tmpStr = notAvailable; + pWnd->SetWindowText(tmpStr); - return ArchiveInfoDialog::OnInitDialog(); + return ArchiveInfoDialog::OnInitDialog(); } /* * =========================================================================== - * DiskArchiveInfoDialog + * DiskArchiveInfoDialog * =========================================================================== */ BEGIN_MESSAGE_MAP(DiskArchiveInfoDialog, ArchiveInfoDialog) - ON_CBN_SELCHANGE(IDC_AIDISK_SUBVOLSEL, OnSubVolSelChange) + ON_CBN_SELCHANGE(IDC_AIDISK_SUBVOLSEL, OnSubVolSelChange) END_MESSAGE_MAP() /* @@ -127,65 +127,65 @@ END_MESSAGE_MAP() BOOL DiskArchiveInfoDialog::OnInitDialog(void) { - CWnd* pWnd; - CString tmpStr; - const DiskImg* pDiskImg; - const DiskFS* pDiskFS; + CWnd* pWnd; + CString tmpStr; + const DiskImg* pDiskImg; + const DiskFS* pDiskFS; - ASSERT(fpArchive != nil); + ASSERT(fpArchive != nil); - pDiskImg = fpArchive->GetDiskImg(); - ASSERT(pDiskImg != nil); - pDiskFS = fpArchive->GetDiskFS(); - ASSERT(pDiskFS != nil); + pDiskImg = fpArchive->GetDiskImg(); + ASSERT(pDiskImg != nil); + pDiskFS = fpArchive->GetDiskFS(); + ASSERT(pDiskFS != nil); - /* - * Volume characteristics. - */ - pWnd = GetDlgItem(IDC_AI_FILENAME); - pWnd->SetWindowText(fpArchive->GetPathName()); + /* + * Volume characteristics. + */ + pWnd = GetDlgItem(IDC_AI_FILENAME); + pWnd->SetWindowText(fpArchive->GetPathName()); - pWnd = GetDlgItem(IDC_AIDISK_OUTERFORMAT); - pWnd->SetWindowText(DiskImg::ToString(pDiskImg->GetOuterFormat())); + pWnd = GetDlgItem(IDC_AIDISK_OUTERFORMAT); + pWnd->SetWindowText(DiskImg::ToString(pDiskImg->GetOuterFormat())); - pWnd = GetDlgItem(IDC_AIDISK_FILEFORMAT); - pWnd->SetWindowText(DiskImg::ToString(pDiskImg->GetFileFormat())); + pWnd = GetDlgItem(IDC_AIDISK_FILEFORMAT); + pWnd->SetWindowText(DiskImg::ToString(pDiskImg->GetFileFormat())); - pWnd = GetDlgItem(IDC_AIDISK_PHYSICALFORMAT); - DiskImg::PhysicalFormat physicalFormat = pDiskImg->GetPhysicalFormat(); - if (physicalFormat == DiskImg::kPhysicalFormatNib525_6656 || - physicalFormat == DiskImg::kPhysicalFormatNib525_6384 || - physicalFormat == DiskImg::kPhysicalFormatNib525_Var) - { - CString tmpStr; - const DiskImg::NibbleDescr* pNibbleDescr = pDiskImg->GetNibbleDescr(); - if (pNibbleDescr != nil) - tmpStr.Format("%s, layout is \"%s\"", - DiskImg::ToString(physicalFormat), pNibbleDescr->description); - else - tmpStr = DiskImg::ToString(physicalFormat); // unexpected - pWnd->SetWindowText(tmpStr); - } else { - pWnd->SetWindowText(DiskImg::ToString(physicalFormat)); - } + pWnd = GetDlgItem(IDC_AIDISK_PHYSICALFORMAT); + DiskImg::PhysicalFormat physicalFormat = pDiskImg->GetPhysicalFormat(); + if (physicalFormat == DiskImg::kPhysicalFormatNib525_6656 || + physicalFormat == DiskImg::kPhysicalFormatNib525_6384 || + physicalFormat == DiskImg::kPhysicalFormatNib525_Var) + { + CString tmpStr; + const DiskImg::NibbleDescr* pNibbleDescr = pDiskImg->GetNibbleDescr(); + if (pNibbleDescr != nil) + tmpStr.Format("%s, layout is \"%s\"", + DiskImg::ToString(physicalFormat), pNibbleDescr->description); + else + tmpStr = DiskImg::ToString(physicalFormat); // unexpected + pWnd->SetWindowText(tmpStr); + } else { + pWnd->SetWindowText(DiskImg::ToString(physicalFormat)); + } - FillInVolumeInfo(pDiskFS); + FillInVolumeInfo(pDiskFS); - /* - * Configure the sub-volume drop down menu. If there's only one item, - * we disable it. - */ - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_AIDISK_SUBVOLSEL); - int idx = 0; + /* + * Configure the sub-volume drop down menu. If there's only one item, + * we disable it. + */ + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_AIDISK_SUBVOLSEL); + int idx = 0; - AddSubVolumes(pDiskFS, "", &idx); - ASSERT(idx > 0); // must have at least the top-level DiskFS + AddSubVolumes(pDiskFS, "", &idx); + ASSERT(idx > 0); // must have at least the top-level DiskFS - pCombo->SetCurSel(0); - if (idx == 1) - pCombo->EnableWindow(FALSE); + pCombo->SetCurSel(0); + if (idx == 1) + pCombo->EnableWindow(FALSE); - return ArchiveInfoDialog::OnInitDialog(); + return ArchiveInfoDialog::OnInitDialog(); } /* @@ -193,32 +193,32 @@ DiskArchiveInfoDialog::OnInitDialog(void) */ void DiskArchiveInfoDialog::AddSubVolumes(const DiskFS* pDiskFS, const char* prefix, - int* pIdx) + int* pIdx) { - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_AIDISK_SUBVOLSEL); - CString tmpStr; + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_AIDISK_SUBVOLSEL); + CString tmpStr; - /* - * Add the current DiskFS. - */ - tmpStr = prefix; - tmpStr += pDiskFS->GetVolumeID(); - pCombo->AddString(tmpStr); - pCombo->SetItemData(*pIdx, (unsigned long) pDiskFS); - (*pIdx)++; + /* + * Add the current DiskFS. + */ + tmpStr = prefix; + tmpStr += pDiskFS->GetVolumeID(); + pCombo->AddString(tmpStr); + pCombo->SetItemData(*pIdx, (unsigned long) pDiskFS); + (*pIdx)++; - /* - * Add everything beneath the current level. - */ - DiskFS::SubVolume* pSubVol; - pSubVol = pDiskFS->GetNextSubVolume(nil); - tmpStr = prefix; - tmpStr += " "; - while (pSubVol != nil) { - AddSubVolumes(pSubVol->GetDiskFS(), tmpStr, pIdx); + /* + * Add everything beneath the current level. + */ + DiskFS::SubVolume* pSubVol; + pSubVol = pDiskFS->GetNextSubVolume(nil); + tmpStr = prefix; + tmpStr += " "; + while (pSubVol != nil) { + AddSubVolumes(pSubVol->GetDiskFS(), tmpStr, pIdx); - pSubVol = pDiskFS->GetNextSubVolume(pSubVol); - } + pSubVol = pDiskFS->GetNextSubVolume(pSubVol); + } } /* @@ -227,14 +227,14 @@ DiskArchiveInfoDialog::AddSubVolumes(const DiskFS* pDiskFS, const char* prefix, void DiskArchiveInfoDialog::OnSubVolSelChange(void) { - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_AIDISK_SUBVOLSEL); - ASSERT(pCombo != nil); - //WMSG1("+++ SELECTION IS NOW %d\n", pCombo->GetCurSel()); + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_AIDISK_SUBVOLSEL); + ASSERT(pCombo != nil); + //WMSG1("+++ SELECTION IS NOW %d\n", pCombo->GetCurSel()); - const DiskFS* pDiskFS; - pDiskFS = (DiskFS*) pCombo->GetItemData(pCombo->GetCurSel()); - ASSERT(pDiskFS != nil); - FillInVolumeInfo(pDiskFS); + const DiskFS* pDiskFS; + pDiskFS = (DiskFS*) pCombo->GetItemData(pCombo->GetCurSel()); + ASSERT(pDiskFS != nil); + FillInVolumeInfo(pDiskFS); } /* @@ -243,109 +243,109 @@ DiskArchiveInfoDialog::OnSubVolSelChange(void) void DiskArchiveInfoDialog::FillInVolumeInfo(const DiskFS* pDiskFS) { - const DiskImg* pDiskImg = pDiskFS->GetDiskImg(); - CString unknown = "(unknown)"; - CString tmpStr; - DIError dierr; - CWnd* pWnd; + const DiskImg* pDiskImg = pDiskFS->GetDiskImg(); + CString unknown = "(unknown)"; + CString tmpStr; + DIError dierr; + CWnd* pWnd; - pWnd = GetDlgItem(IDC_AIDISK_SECTORORDER); - pWnd->SetWindowText(DiskImg::ToString(pDiskImg->GetSectorOrder())); + pWnd = GetDlgItem(IDC_AIDISK_SECTORORDER); + pWnd->SetWindowText(DiskImg::ToString(pDiskImg->GetSectorOrder())); - pWnd = GetDlgItem(IDC_AIDISK_FSFORMAT); - pWnd->SetWindowText(DiskImg::ToString(pDiskImg->GetFSFormat())); + pWnd = GetDlgItem(IDC_AIDISK_FSFORMAT); + pWnd->SetWindowText(DiskImg::ToString(pDiskImg->GetFSFormat())); - pWnd = GetDlgItem(IDC_AIDISK_FILECOUNT); - tmpStr.Format("%ld", pDiskFS->GetFileCount()); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AIDISK_FILECOUNT); + tmpStr.Format("%ld", pDiskFS->GetFileCount()); + pWnd->SetWindowText(tmpStr); - long totalUnits, freeUnits; - int unitSize; - CString reducedSize; + long totalUnits, freeUnits; + int unitSize; + CString reducedSize; - dierr = pDiskFS->GetFreeSpaceCount(&totalUnits, &freeUnits, &unitSize); - if (dierr == kDIErrNone) { + dierr = pDiskFS->GetFreeSpaceCount(&totalUnits, &freeUnits, &unitSize); + if (dierr == kDIErrNone) { - /* got the space; break it down by disk type */ - if (unitSize == DiskImgLib::kBlockSize) { - pWnd = GetDlgItem(IDC_AIDISK_CAPACITY); - GetReducedSize(totalUnits, unitSize, &reducedSize); - tmpStr.Format("%ld blocks (%s)", - totalUnits, reducedSize); - if (totalUnits != pDiskImg->GetNumBlocks()) { - CString tmpStr2; - tmpStr2.Format(", image has room for %ld blocks", - pDiskImg->GetNumBlocks()); - tmpStr += tmpStr2; - } - pWnd->SetWindowText(tmpStr); + /* got the space; break it down by disk type */ + if (unitSize == DiskImgLib::kBlockSize) { + pWnd = GetDlgItem(IDC_AIDISK_CAPACITY); + GetReducedSize(totalUnits, unitSize, &reducedSize); + tmpStr.Format("%ld blocks (%s)", + totalUnits, reducedSize); + if (totalUnits != pDiskImg->GetNumBlocks()) { + CString tmpStr2; + tmpStr2.Format(", image has room for %ld blocks", + pDiskImg->GetNumBlocks()); + tmpStr += tmpStr2; + } + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_AIDISK_FREESPACE); - GetReducedSize(freeUnits, unitSize, &reducedSize); - tmpStr.Format("%ld blocks (%s)", - freeUnits, reducedSize); - pWnd->SetWindowText(tmpStr); - } else { - ASSERT(unitSize == DiskImgLib::kSectorSize); + pWnd = GetDlgItem(IDC_AIDISK_FREESPACE); + GetReducedSize(freeUnits, unitSize, &reducedSize); + tmpStr.Format("%ld blocks (%s)", + freeUnits, reducedSize); + pWnd->SetWindowText(tmpStr); + } else { + ASSERT(unitSize == DiskImgLib::kSectorSize); - pWnd = GetDlgItem(IDC_AIDISK_CAPACITY); - GetReducedSize(totalUnits, unitSize, &reducedSize); - tmpStr.Format("%ld sectors (%s)", - totalUnits, reducedSize); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AIDISK_CAPACITY); + GetReducedSize(totalUnits, unitSize, &reducedSize); + tmpStr.Format("%ld sectors (%s)", + totalUnits, reducedSize); + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_AIDISK_FREESPACE); - GetReducedSize(freeUnits, unitSize, &reducedSize); - tmpStr.Format("%ld sectors (%s)", - freeUnits, reducedSize); - pWnd->SetWindowText(tmpStr); - } - } else { - /* "free space" not supported; fill in what we do know */ - pWnd = GetDlgItem(IDC_AIDISK_CAPACITY); - if (pDiskImg->GetHasBlocks()) { - totalUnits = pDiskImg->GetNumBlocks(); - GetReducedSize(totalUnits, DiskImgLib::kBlockSize, &reducedSize); - tmpStr.Format("%ld blocks (%s)", - totalUnits, reducedSize); - } else if (pDiskImg->GetHasSectors()) { - tmpStr.Format("%ld tracks, %d sectors per track", - pDiskImg->GetNumTracks(), pDiskImg->GetNumSectPerTrack()); - } else { - tmpStr = unknown; - } - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AIDISK_FREESPACE); + GetReducedSize(freeUnits, unitSize, &reducedSize); + tmpStr.Format("%ld sectors (%s)", + freeUnits, reducedSize); + pWnd->SetWindowText(tmpStr); + } + } else { + /* "free space" not supported; fill in what we do know */ + pWnd = GetDlgItem(IDC_AIDISK_CAPACITY); + if (pDiskImg->GetHasBlocks()) { + totalUnits = pDiskImg->GetNumBlocks(); + GetReducedSize(totalUnits, DiskImgLib::kBlockSize, &reducedSize); + tmpStr.Format("%ld blocks (%s)", + totalUnits, reducedSize); + } else if (pDiskImg->GetHasSectors()) { + tmpStr.Format("%ld tracks, %d sectors per track", + pDiskImg->GetNumTracks(), pDiskImg->GetNumSectPerTrack()); + } else { + tmpStr = unknown; + } + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_AIDISK_FREESPACE); - pWnd->SetWindowText(unknown); - } + pWnd = GetDlgItem(IDC_AIDISK_FREESPACE); + pWnd->SetWindowText(unknown); + } - pWnd = GetDlgItem(IDC_AIDISK_WRITEABLE); - tmpStr = pDiskFS->GetReadWriteSupported() ? "Yes" : "No"; - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AIDISK_WRITEABLE); + tmpStr = pDiskFS->GetReadWriteSupported() ? "Yes" : "No"; + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_AIDISK_DAMAGED); - tmpStr = pDiskFS->GetFSDamaged() ? "Yes" : "No"; - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AIDISK_DAMAGED); + tmpStr = pDiskFS->GetFSDamaged() ? "Yes" : "No"; + pWnd->SetWindowText(tmpStr); - const char* cp; - char* outp; + const char* cp; + char* outp; - pWnd = GetDlgItem(IDC_AIDISK_NOTES); - cp = pDiskImg->GetNotes(); - outp = tmpStr.GetBuffer(strlen(cp) * 2 +1); - /* convert '\n' to '\r\n' */ - while (*cp != '\0') { - if (*cp == '\n') - *outp++ = '\r'; - *outp++ = *cp++; - } - *outp = '\0'; - tmpStr.ReleaseBuffer(); - /* drop the trailing linefeed */ - if (!tmpStr.IsEmpty() && tmpStr.GetAt(tmpStr.GetLength()-1) == '\n') - tmpStr.TrimRight(); // trim the whitespace chars off - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AIDISK_NOTES); + cp = pDiskImg->GetNotes(); + outp = tmpStr.GetBuffer(strlen(cp) * 2 +1); + /* convert '\n' to '\r\n' */ + while (*cp != '\0') { + if (*cp == '\n') + *outp++ = '\r'; + *outp++ = *cp++; + } + *outp = '\0'; + tmpStr.ReleaseBuffer(); + /* drop the trailing linefeed */ + if (!tmpStr.IsEmpty() && tmpStr.GetAt(tmpStr.GetLength()-1) == '\n') + tmpStr.TrimRight(); // trim the whitespace chars off + pWnd->SetWindowText(tmpStr); } /* @@ -353,33 +353,33 @@ DiskArchiveInfoDialog::FillInVolumeInfo(const DiskFS* pDiskFS) */ void DiskArchiveInfoDialog::GetReducedSize(long numUnits, int unitSize, - CString* pOut) const + CString* pOut) const { - LONGLONG sizeInBytes = numUnits; - sizeInBytes *= unitSize; - long reducedSize; + LONGLONG sizeInBytes = numUnits; + sizeInBytes *= unitSize; + long reducedSize; - if (sizeInBytes < 0) { - ASSERT(false); - pOut->Format(""); - return; - } + if (sizeInBytes < 0) { + ASSERT(false); + pOut->Format(""); + return; + } - if (sizeInBytes >= 1024*1024*1024) { - reducedSize = (long) (sizeInBytes / (1024*1024)); - pOut->Format("%.2fGB", reducedSize / 1024.0); - } else if (sizeInBytes >= 1024*1024) { - reducedSize = (long) (sizeInBytes / 1024); - pOut->Format("%.2fMB", reducedSize / 1024.0); - } else { - pOut->Format("%.2fKB", ((long) sizeInBytes) / 1024.0); - } + if (sizeInBytes >= 1024*1024*1024) { + reducedSize = (long) (sizeInBytes / (1024*1024)); + pOut->Format("%.2fGB", reducedSize / 1024.0); + } else if (sizeInBytes >= 1024*1024) { + reducedSize = (long) (sizeInBytes / 1024); + pOut->Format("%.2fMB", reducedSize / 1024.0); + } else { + pOut->Format("%.2fKB", ((long) sizeInBytes) / 1024.0); + } } /* * =========================================================================== - * BnyArchiveInfoDialog + * BnyArchiveInfoDialog * =========================================================================== */ @@ -391,24 +391,24 @@ DiskArchiveInfoDialog::GetReducedSize(long numUnits, int unitSize, BOOL BnyArchiveInfoDialog::OnInitDialog(void) { - CWnd* pWnd; - CString tmpStr; + CWnd* pWnd; + CString tmpStr; - ASSERT(fpArchive != nil); + ASSERT(fpArchive != nil); - pWnd = GetDlgItem(IDC_AI_FILENAME); - pWnd->SetWindowText(fpArchive->GetPathName()); - tmpStr.Format("%ld", fpArchive->GetNumEntries()); - pWnd = GetDlgItem(IDC_AIBNY_RECORDS); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AI_FILENAME); + pWnd->SetWindowText(fpArchive->GetPathName()); + tmpStr.Format("%ld", fpArchive->GetNumEntries()); + pWnd = GetDlgItem(IDC_AIBNY_RECORDS); + pWnd->SetWindowText(tmpStr); - return ArchiveInfoDialog::OnInitDialog(); + return ArchiveInfoDialog::OnInitDialog(); } /* * =========================================================================== - * AcuArchiveInfoDialog + * AcuArchiveInfoDialog * =========================================================================== */ @@ -418,16 +418,16 @@ BnyArchiveInfoDialog::OnInitDialog(void) BOOL AcuArchiveInfoDialog::OnInitDialog(void) { - CWnd* pWnd; - CString tmpStr; + CWnd* pWnd; + CString tmpStr; - ASSERT(fpArchive != nil); + ASSERT(fpArchive != nil); - pWnd = GetDlgItem(IDC_AI_FILENAME); - pWnd->SetWindowText(fpArchive->GetPathName()); - tmpStr.Format("%ld", fpArchive->GetNumEntries()); - pWnd = GetDlgItem(IDC_AIBNY_RECORDS); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_AI_FILENAME); + pWnd->SetWindowText(fpArchive->GetPathName()); + tmpStr.Format("%ld", fpArchive->GetNumEntries()); + pWnd = GetDlgItem(IDC_AIBNY_RECORDS); + pWnd->SetWindowText(tmpStr); - return ArchiveInfoDialog::OnInitDialog(); + return ArchiveInfoDialog::OnInitDialog(); } diff --git a/app/ArchiveInfoDialog.h b/app/ArchiveInfoDialog.h index 53ced39..4eedd03 100644 --- a/app/ArchiveInfoDialog.h +++ b/app/ArchiveInfoDialog.h @@ -22,15 +22,15 @@ */ class ArchiveInfoDialog : public CDialog { public: - ArchiveInfoDialog(UINT dialogID, CWnd* pParentWnd = NULL) : - CDialog(dialogID, pParentWnd) - {} - virtual ~ArchiveInfoDialog(void) {} + ArchiveInfoDialog(UINT dialogID, CWnd* pParentWnd = NULL) : + CDialog(dialogID, pParentWnd) + {} + virtual ~ArchiveInfoDialog(void) {} private: - afx_msg void OnHelp(void); + afx_msg void OnHelp(void); - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; /* @@ -38,17 +38,17 @@ private: */ class NufxArchiveInfoDialog : public ArchiveInfoDialog { public: - NufxArchiveInfoDialog(NufxArchive* pArchive, CWnd* pParentWnd = NULL) : - fpArchive(pArchive), - ArchiveInfoDialog(IDD_ARCHIVEINFO_NUFX, pParentWnd) - {} - virtual ~NufxArchiveInfoDialog(void) {} + NufxArchiveInfoDialog(NufxArchive* pArchive, CWnd* pParentWnd = NULL) : + fpArchive(pArchive), + ArchiveInfoDialog(IDD_ARCHIVEINFO_NUFX, pParentWnd) + {} + virtual ~NufxArchiveInfoDialog(void) {} private: - // overrides - virtual BOOL OnInitDialog(void); + // overrides + virtual BOOL OnInitDialog(void); - NufxArchive* fpArchive; + NufxArchive* fpArchive; }; /* @@ -56,27 +56,27 @@ private: */ class DiskArchiveInfoDialog : public ArchiveInfoDialog { public: - DiskArchiveInfoDialog(DiskArchive* pArchive, CWnd* pParentWnd = NULL) : - fpArchive(pArchive), - ArchiveInfoDialog(IDD_ARCHIVEINFO_DISK, pParentWnd) - {} - virtual ~DiskArchiveInfoDialog(void) {} + DiskArchiveInfoDialog(DiskArchive* pArchive, CWnd* pParentWnd = NULL) : + fpArchive(pArchive), + ArchiveInfoDialog(IDD_ARCHIVEINFO_DISK, pParentWnd) + {} + virtual ~DiskArchiveInfoDialog(void) {} private: - // overrides - virtual BOOL OnInitDialog(void); + // overrides + virtual BOOL OnInitDialog(void); - afx_msg void OnSubVolSelChange(void); + afx_msg void OnSubVolSelChange(void); - void FillInVolumeInfo(const DiskFS* pDiskFS); - void AddSubVolumes(const DiskFS* pDiskFS, const char* prefix, - int* pIdx); - void GetReducedSize(long numUnits, int unitSize, - CString* pOut) const; + void FillInVolumeInfo(const DiskFS* pDiskFS); + void AddSubVolumes(const DiskFS* pDiskFS, const char* prefix, + int* pIdx); + void GetReducedSize(long numUnits, int unitSize, + CString* pOut) const; - DiskArchive* fpArchive; + DiskArchive* fpArchive; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; /* @@ -84,17 +84,17 @@ private: */ class BnyArchiveInfoDialog : public ArchiveInfoDialog { public: - BnyArchiveInfoDialog(BnyArchive* pArchive, CWnd* pParentWnd = NULL) : - fpArchive(pArchive), - ArchiveInfoDialog(IDD_ARCHIVEINFO_BNY, pParentWnd) - {} - virtual ~BnyArchiveInfoDialog(void) {} + BnyArchiveInfoDialog(BnyArchive* pArchive, CWnd* pParentWnd = NULL) : + fpArchive(pArchive), + ArchiveInfoDialog(IDD_ARCHIVEINFO_BNY, pParentWnd) + {} + virtual ~BnyArchiveInfoDialog(void) {} private: - // overrides - virtual BOOL OnInitDialog(void); + // overrides + virtual BOOL OnInitDialog(void); - BnyArchive* fpArchive; + BnyArchive* fpArchive; }; /* @@ -102,17 +102,17 @@ private: */ class AcuArchiveInfoDialog : public ArchiveInfoDialog { public: - AcuArchiveInfoDialog(AcuArchive* pArchive, CWnd* pParentWnd = NULL) : - fpArchive(pArchive), - ArchiveInfoDialog(IDD_ARCHIVEINFO_ACU, pParentWnd) - {} - virtual ~AcuArchiveInfoDialog(void) {} + AcuArchiveInfoDialog(AcuArchive* pArchive, CWnd* pParentWnd = NULL) : + fpArchive(pArchive), + ArchiveInfoDialog(IDD_ARCHIVEINFO_ACU, pParentWnd) + {} + virtual ~AcuArchiveInfoDialog(void) {} private: - // overrides - virtual BOOL OnInitDialog(void); + // overrides + virtual BOOL OnInitDialog(void); - AcuArchive* fpArchive; + AcuArchive* fpArchive; }; #endif /*__ARCHIVEINFODIALOG__*/ diff --git a/app/BNYArchive.cpp b/app/BNYArchive.cpp index 57f80c1..4414584 100644 --- a/app/BNYArchive.cpp +++ b/app/BNYArchive.cpp @@ -17,7 +17,7 @@ /* * =========================================================================== - * BnyEntry + * BnyEntry * =========================================================================== */ @@ -39,126 +39,126 @@ */ int BnyEntry::ExtractThreadToBuffer(int which, char** ppText, long* pLength, - CString* pErrMsg) const + CString* pErrMsg) const { - NuError nerr; - ExpandBuffer expBuf; - char* dataBuf = nil; - long len; - bool needAlloc = true; - int result = -1; + NuError nerr; + ExpandBuffer expBuf; + char* dataBuf = nil; + long len; + bool needAlloc = true; + int result = -1; - ASSERT(fpArchive != nil); - ASSERT(fpArchive->fFp != nil); + ASSERT(fpArchive != nil); + ASSERT(fpArchive->fFp != nil); - if (*ppText != nil) - needAlloc = false; + if (*ppText != nil) + needAlloc = false; - if (which != kDataThread) { - *pErrMsg = "No such fork"; - goto bail; - } + if (which != kDataThread) { + *pErrMsg = "No such fork"; + goto bail; + } - len = (long) GetUncompressedLen(); - if (len == 0) { - if (needAlloc) { - *ppText = new char[1]; - **ppText = '\0'; - } - *pLength = 0; - result = IDOK; - goto bail; - } + len = (long) GetUncompressedLen(); + if (len == 0) { + if (needAlloc) { + *ppText = new char[1]; + **ppText = '\0'; + } + *pLength = 0; + result = IDOK; + goto bail; + } - SET_PROGRESS_BEGIN(); + SET_PROGRESS_BEGIN(); - errno = 0; - if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) { - pErrMsg->Format("Unable to seek to offset %ld: %s", - fOffset, strerror(errno)); - goto bail; - } + errno = 0; + if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) { + pErrMsg->Format("Unable to seek to offset %ld: %s", + fOffset, strerror(errno)); + goto bail; + } - if (GetSqueezed()) { - nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetUncompressedLen(), - &expBuf, true, kBNYBlockSize); - if (nerr != kNuErrNone) { - pErrMsg->Format("File read failed: %s", NuStrError(nerr)); - goto bail; - } + if (GetSqueezed()) { + nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetUncompressedLen(), + &expBuf, true, kBNYBlockSize); + if (nerr != kNuErrNone) { + pErrMsg->Format("File read failed: %s", NuStrError(nerr)); + goto bail; + } - char* unsqBuf = nil; - long unsqLen = 0; - expBuf.SeizeBuffer(&unsqBuf, &unsqLen); - WMSG2("Unsqueezed %ld bytes to %d\n", len, unsqLen); - if (unsqLen == 0) { - // some bonehead squeezed a zero-length file - delete[] unsqBuf; - ASSERT(*ppText == nil); - WMSG0("Handling zero-length squeezed file!\n"); - if (needAlloc) { - *ppText = new char[1]; - **ppText = '\0'; - } - *pLength = 0; - } else { - if (needAlloc) { - /* just use the seized buffer */ - *ppText = unsqBuf; - *pLength = unsqLen; - } else { - if (*pLength < unsqLen) { - pErrMsg->Format("buf size %ld too short (%ld)", - *pLength, unsqLen); - delete[] unsqBuf; - goto bail; - } + char* unsqBuf = nil; + long unsqLen = 0; + expBuf.SeizeBuffer(&unsqBuf, &unsqLen); + WMSG2("Unsqueezed %ld bytes to %d\n", len, unsqLen); + if (unsqLen == 0) { + // some bonehead squeezed a zero-length file + delete[] unsqBuf; + ASSERT(*ppText == nil); + WMSG0("Handling zero-length squeezed file!\n"); + if (needAlloc) { + *ppText = new char[1]; + **ppText = '\0'; + } + *pLength = 0; + } else { + if (needAlloc) { + /* just use the seized buffer */ + *ppText = unsqBuf; + *pLength = unsqLen; + } else { + if (*pLength < unsqLen) { + pErrMsg->Format("buf size %ld too short (%ld)", + *pLength, unsqLen); + delete[] unsqBuf; + goto bail; + } - memcpy(*ppText, unsqBuf, unsqLen); - delete[] unsqBuf; - *pLength = unsqLen; - } - } + memcpy(*ppText, unsqBuf, unsqLen); + delete[] unsqBuf; + *pLength = unsqLen; + } + } - } else { - if (needAlloc) { - dataBuf = new char[len]; - if (dataBuf == nil) { - pErrMsg->Format("allocation of %ld bytes failed", len); - goto bail; - } - } else { - if (*pLength < (long) len) { - pErrMsg->Format("buf size %ld too short (%ld)", - *pLength, len); - goto bail; - } - dataBuf = *ppText; - } - if (fread(dataBuf, len, 1, fpArchive->fFp) != 1) { - pErrMsg->Format("File read failed: %s", strerror(errno)); - goto bail; - } + } else { + if (needAlloc) { + dataBuf = new char[len]; + if (dataBuf == nil) { + pErrMsg->Format("allocation of %ld bytes failed", len); + goto bail; + } + } else { + if (*pLength < (long) len) { + pErrMsg->Format("buf size %ld too short (%ld)", + *pLength, len); + goto bail; + } + dataBuf = *ppText; + } + if (fread(dataBuf, len, 1, fpArchive->fFp) != 1) { + pErrMsg->Format("File read failed: %s", strerror(errno)); + goto bail; + } - if (needAlloc) - *ppText = dataBuf; - *pLength = len; - } + if (needAlloc) + *ppText = dataBuf; + *pLength = len; + } - result = IDOK; + result = IDOK; bail: - if (result == IDOK) { - SET_PROGRESS_END(); - ASSERT(pErrMsg->IsEmpty()); - } else { - ASSERT(result == IDCANCEL || !pErrMsg->IsEmpty()); - if (needAlloc) { - delete[] dataBuf; - ASSERT(*ppText == nil); - } - } - return result; + if (result == IDOK) { + SET_PROGRESS_END(); + ASSERT(pErrMsg->IsEmpty()); + } else { + ASSERT(result == IDCANCEL || !pErrMsg->IsEmpty()); + if (needAlloc) { + delete[] dataBuf; + ASSERT(*ppText == nil); + } + } + return result; } /* @@ -171,92 +171,92 @@ bail: */ int BnyEntry::ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, - ConvertHighASCII convHA, CString* pErrMsg) const + ConvertHighASCII convHA, CString* pErrMsg) const { - NuError nerr; - long len; - int result = -1; + NuError nerr; + long len; + int result = -1; - ASSERT(IDOK != -1 && IDCANCEL != -1); - if (which != kDataThread) { - *pErrMsg = "No such fork"; - goto bail; - } + ASSERT(IDOK != -1 && IDCANCEL != -1); + if (which != kDataThread) { + *pErrMsg = "No such fork"; + goto bail; + } - len = (long) GetUncompressedLen(); - if (len == 0) { - WMSG0("Empty fork\n"); - result = IDOK; - goto bail; - } + len = (long) GetUncompressedLen(); + if (len == 0) { + WMSG0("Empty fork\n"); + result = IDOK; + goto bail; + } - errno = 0; - if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) { - pErrMsg->Format("Unable to seek to offset %ld: %s", - fOffset, strerror(errno)); - goto bail; - } + errno = 0; + if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) { + pErrMsg->Format("Unable to seek to offset %ld: %s", + fOffset, strerror(errno)); + goto bail; + } - SET_PROGRESS_BEGIN(); + SET_PROGRESS_BEGIN(); - /* - * Generally speaking, anything in a BNY file is going to be small. The - * major exception is a BXY file, which could be huge. However, the - * SHK embedded in a BXY is never squeezed. - * - * To make life easy, we either unsqueeze the entire thing into a buffer - * and then write that, or we do a file-to-file copy of the specified - * number of bytes. - */ - if (GetSqueezed()) { - ExpandBuffer expBuf; - bool lastCR = false; - char* buf; - long uncLen; + /* + * Generally speaking, anything in a BNY file is going to be small. The + * major exception is a BXY file, which could be huge. However, the + * SHK embedded in a BXY is never squeezed. + * + * To make life easy, we either unsqueeze the entire thing into a buffer + * and then write that, or we do a file-to-file copy of the specified + * number of bytes. + */ + if (GetSqueezed()) { + ExpandBuffer expBuf; + bool lastCR = false; + char* buf; + long uncLen; - nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetUncompressedLen(), - &expBuf, true, kBNYBlockSize); - if (nerr != kNuErrNone) { - pErrMsg->Format("File read failed: %s", NuStrError(nerr)); - goto bail; - } + nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetUncompressedLen(), + &expBuf, true, kBNYBlockSize); + if (nerr != kNuErrNone) { + pErrMsg->Format("File read failed: %s", NuStrError(nerr)); + goto bail; + } - expBuf.SeizeBuffer(&buf, &uncLen); - WMSG2("Unsqueezed %ld bytes to %d\n", len, uncLen); + expBuf.SeizeBuffer(&buf, &uncLen); + WMSG2("Unsqueezed %ld bytes to %d\n", len, uncLen); - // some bonehead squeezed a zero-length file - if (uncLen == 0) { - ASSERT(buf == nil); - WMSG0("Handling zero-length squeezed file!\n"); - result = IDOK; - goto bail; - } + // some bonehead squeezed a zero-length file + if (uncLen == 0) { + ASSERT(buf == nil); + WMSG0("Handling zero-length squeezed file!\n"); + result = IDOK; + goto bail; + } - int err = GenericEntry::WriteConvert(outfp, buf, uncLen, &conv, - &convHA, &lastCR); - if (err != 0) { - pErrMsg->Format("File write failed: %s", strerror(err)); - delete[] buf; - goto bail; - } + int err = GenericEntry::WriteConvert(outfp, buf, uncLen, &conv, + &convHA, &lastCR); + if (err != 0) { + pErrMsg->Format("File write failed: %s", strerror(err)); + delete[] buf; + goto bail; + } - delete[] buf; - } else { - nerr = CopyData(outfp, conv, convHA, pErrMsg); - if (nerr != kNuErrNone) { - if (pErrMsg->IsEmpty()) { - pErrMsg->Format("Failed while copying data: %s\n", - NuStrError(nerr)); - } - goto bail; - } - } + delete[] buf; + } else { + nerr = CopyData(outfp, conv, convHA, pErrMsg); + if (nerr != kNuErrNone) { + if (pErrMsg->IsEmpty()) { + pErrMsg->Format("Failed while copying data: %s\n", + NuStrError(nerr)); + } + goto bail; + } + } - result = IDOK; + result = IDOK; bail: - SET_PROGRESS_END(); - return result; + SET_PROGRESS_END(); + return result; } /* @@ -265,51 +265,51 @@ bail: */ NuError BnyEntry::CopyData(FILE* outfp, ConvertEOL conv, ConvertHighASCII convHA, - CString* pMsg) const + CString* pMsg) const { - NuError nerr = kNuErrNone; - const int kChunkSize = 8192; - char buf[kChunkSize]; - bool lastCR = false; - long srcLen, dataRem; + NuError nerr = kNuErrNone; + const int kChunkSize = 8192; + char buf[kChunkSize]; + bool lastCR = false; + long srcLen, dataRem; - srcLen = (long) GetUncompressedLen(); - ASSERT(srcLen > 0); // empty files should've been caught earlier + srcLen = (long) GetUncompressedLen(); + ASSERT(srcLen > 0); // empty files should've been caught earlier - /* - * Loop until all data copied. - */ - dataRem = srcLen; - while (dataRem) { - int chunkLen; + /* + * Loop until all data copied. + */ + dataRem = srcLen; + while (dataRem) { + int chunkLen; - if (dataRem > kChunkSize) - chunkLen = kChunkSize; - else - chunkLen = dataRem; + if (dataRem > kChunkSize) + chunkLen = kChunkSize; + else + chunkLen = dataRem; - /* read a chunk from the source file */ - nerr = fpArchive->BNYRead(buf, chunkLen); - if (nerr != kNuErrNone) { - pMsg->Format("File read failed: %s.", NuStrError(nerr)); - goto bail; - } + /* read a chunk from the source file */ + nerr = fpArchive->BNYRead(buf, chunkLen); + if (nerr != kNuErrNone) { + pMsg->Format("File read failed: %s.", NuStrError(nerr)); + goto bail; + } - /* write chunk to destination file */ - int err = GenericEntry::WriteConvert(outfp, buf, chunkLen, &conv, - &convHA, &lastCR); - if (err != 0) { - pMsg->Format("File write failed: %s.", strerror(err)); - nerr = kNuErrGeneric; - goto bail; - } + /* write chunk to destination file */ + int err = GenericEntry::WriteConvert(outfp, buf, chunkLen, &conv, + &convHA, &lastCR); + if (err != 0) { + pMsg->Format("File write failed: %s.", strerror(err)); + nerr = kNuErrGeneric; + goto bail; + } - dataRem -= chunkLen; - SET_PROGRESS_UPDATE(ComputePercent(srcLen - dataRem, srcLen)); - } + dataRem -= chunkLen; + SET_PROGRESS_UPDATE(ComputePercent(srcLen - dataRem, srcLen)); + } bail: - return nerr; + return nerr; } @@ -322,54 +322,54 @@ bail: NuError BnyEntry::TestEntry(CWnd* pMsgWnd) { - NuError nerr = kNuErrNone; - CString errMsg; - long len; - int result = -1; + NuError nerr = kNuErrNone; + CString errMsg; + long len; + int result = -1; - len = (long) GetUncompressedLen(); - if (len == 0) - goto bail; + len = (long) GetUncompressedLen(); + if (len == 0) + goto bail; - errno = 0; - if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) { - nerr = kNuErrGeneric; - errMsg.Format("Unable to seek to offset %ld: %s\n", - fOffset, strerror(errno)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } + errno = 0; + if (fseek(fpArchive->fFp, fOffset, SEEK_SET) < 0) { + nerr = kNuErrGeneric; + errMsg.Format("Unable to seek to offset %ld: %s\n", + fOffset, strerror(errno)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } - if (GetSqueezed()) { - nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetUncompressedLen(), - nil, true, kBNYBlockSize); - if (nerr != kNuErrNone) { - errMsg.Format("Unsqueeze failed: %s.", NuStrError(nerr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - } else { - errno = 0; - if (fseek(fpArchive->fFp, fOffset + len, SEEK_SET) < 0) { - nerr = kNuErrGeneric; - errMsg.Format("Unable to seek to offset %ld (file truncated?): %s\n", - fOffset, strerror(errno)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - } + if (GetSqueezed()) { + nerr = UnSqueeze(fpArchive->fFp, (unsigned long) GetUncompressedLen(), + nil, true, kBNYBlockSize); + if (nerr != kNuErrNone) { + errMsg.Format("Unsqueeze failed: %s.", NuStrError(nerr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + } else { + errno = 0; + if (fseek(fpArchive->fFp, fOffset + len, SEEK_SET) < 0) { + nerr = kNuErrGeneric; + errMsg.Format("Unable to seek to offset %ld (file truncated?): %s\n", + fOffset, strerror(errno)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + } - if (SET_PROGRESS_UPDATE(100) == IDCANCEL) - nerr = kNuErrAborted; + if (SET_PROGRESS_UPDATE(100) == IDCANCEL) + nerr = kNuErrAborted; bail: - return nerr; + return nerr; } /* * =========================================================================== - * BnyArchive + * BnyArchive * =========================================================================== */ @@ -382,7 +382,7 @@ bail: /*static*/ CString BnyArchive::AppInit(void) { - return ""; + return ""; } /* @@ -393,34 +393,34 @@ BnyArchive::AppInit(void) GenericArchive::OpenResult BnyArchive::Open(const char* filename, bool readOnly, CString* pErrMsg) { - CString errMsg; + CString errMsg; - fIsReadOnly = true; // ignore "readOnly" + fIsReadOnly = true; // ignore "readOnly" - errno = 0; - fFp = fopen(filename, "rb"); - if (fFp == nil) { - errMsg.Format("Unable to open %s: %s.", filename, strerror(errno)); - goto bail; - } + errno = 0; + fFp = fopen(filename, "rb"); + if (fFp == nil) { + errMsg.Format("Unable to open %s: %s.", filename, strerror(errno)); + goto bail; + } - { - CWaitCursor waitc; + { + CWaitCursor waitc; - if (LoadContents() != 0) { - errMsg.Format("Failed while loading contents of Binary II file."); - goto bail; - } - } + if (LoadContents() != 0) { + errMsg.Format("Failed while loading contents of Binary II file."); + goto bail; + } + } - SetPathName(filename); + SetPathName(filename); bail: - *pErrMsg = errMsg; - if (!errMsg.IsEmpty()) - return kResultFailure; - else - return kResultSuccess; + *pErrMsg = errMsg; + if (!errMsg.IsEmpty()) + return kResultFailure; + else + return kResultSuccess; } /* @@ -431,8 +431,8 @@ bail: CString BnyArchive::New(const char* /*filename*/, const void* /*options*/) { - CString retmsg("Sorry, Binary II files can't be created."); - return retmsg; + CString retmsg("Sorry, Binary II files can't be created."); + return retmsg; } @@ -442,36 +442,36 @@ BnyArchive::New(const char* /*filename*/, const void* /*options*/) long BnyArchive::GetCapability(Capability cap) { - switch (cap) { - case kCapCanTest: - return true; - break; - case kCapCanRenameFullPath: - return true; - break; - case kCapCanRecompress: - return true; - break; - case kCapCanEditComment: - return false; - break; - case kCapCanAddDisk: - return false; - break; - case kCapCanConvEOLOnAdd: - return false; - break; - case kCapCanCreateSubdir: - return false; - break; - case kCapCanRenameVolume: - return false; - break; - default: - ASSERT(false); - return -1; - break; - } + switch (cap) { + case kCapCanTest: + return true; + break; + case kCapCanRenameFullPath: + return true; + break; + case kCapCanRecompress: + return true; + break; + case kCapCanEditComment: + return false; + break; + case kCapCanAddDisk: + return false; + break; + case kCapCanConvEOLOnAdd: + return false; + break; + case kCapCanCreateSubdir: + return false; + break; + case kCapCanRenameVolume: + return false; + break; + default: + ASSERT(false); + return -1; + break; + } } @@ -483,14 +483,14 @@ BnyArchive::GetCapability(Capability cap) int BnyArchive::LoadContents(void) { - NuError nerr; + NuError nerr; - ASSERT(fFp != nil); - rewind(fFp); + ASSERT(fFp != nil); + rewind(fFp); - nerr = BNYIterate(); - WMSG1("BNYIterate returned %d\n", nerr); - return (nerr != kNuErrNone); + nerr = BNYIterate(); + WMSG1("BNYIterate returned %d\n", nerr); + return (nerr != kNuErrNone); } /* @@ -499,14 +499,14 @@ BnyArchive::LoadContents(void) CString BnyArchive::Reload(void) { - fReloadFlag = true; // tell everybody that cached data is invalid + fReloadFlag = true; // tell everybody that cached data is invalid - DeleteEntries(); - if (LoadContents() != 0) { - return "Reload failed."; - } - - return ""; + DeleteEntries(); + if (LoadContents() != 0) { + return "Reload failed."; + } + + return ""; } /* @@ -517,83 +517,83 @@ BnyArchive::Reload(void) NuError BnyArchive::LoadContentsCallback(BnyFileEntry* pEntry) { - const int kBNYFssep = '/'; - NuError err = kNuErrNone; - BnyEntry* pNewEntry; - char* fileName; + const int kBNYFssep = '/'; + NuError err = kNuErrNone; + BnyEntry* pNewEntry; + char* fileName; - /* make sure filename doesn't start with '/' (not allowed by BNY spec) */ - fileName = pEntry->fileName; - while (*fileName == kBNYFssep) - fileName++; - if (*fileName == '\0') - return kNuErrBadData; + /* make sure filename doesn't start with '/' (not allowed by BNY spec) */ + fileName = pEntry->fileName; + while (*fileName == kBNYFssep) + fileName++; + if (*fileName == '\0') + return kNuErrBadData; - /* remove '.QQ' from end of squeezed files */ - bool isSqueezed = false; - if (pEntry->realEOF && IsSqueezed(pEntry->blockBuf[0], pEntry->blockBuf[1])) - isSqueezed = true; + /* remove '.QQ' from end of squeezed files */ + bool isSqueezed = false; + if (pEntry->realEOF && IsSqueezed(pEntry->blockBuf[0], pEntry->blockBuf[1])) + isSqueezed = true; - if (isSqueezed && strlen(fileName) > 3) { - char* ext; - ext = fileName + strlen(fileName) -3; - if (strcasecmp(ext, ".qq") == 0) - *ext = '\0'; - } + if (isSqueezed && strlen(fileName) > 3) { + char* ext; + ext = fileName + strlen(fileName) -3; + if (strcasecmp(ext, ".qq") == 0) + *ext = '\0'; + } - /* - * Create the new entry. - */ - pNewEntry = new BnyEntry(this); - pNewEntry->SetPathName(fileName); - pNewEntry->SetFssep(kBNYFssep); - pNewEntry->SetFileType(pEntry->fileType); - pNewEntry->SetAuxType(pEntry->auxType); - pNewEntry->SetAccess(pEntry->access); - pNewEntry->SetCreateWhen(NufxArchive::DateTimeToSeconds(&pEntry->createWhen)); - pNewEntry->SetModWhen(NufxArchive::DateTimeToSeconds(&pEntry->modWhen)); + /* + * Create the new entry. + */ + pNewEntry = new BnyEntry(this); + pNewEntry->SetPathName(fileName); + pNewEntry->SetFssep(kBNYFssep); + pNewEntry->SetFileType(pEntry->fileType); + pNewEntry->SetAuxType(pEntry->auxType); + pNewEntry->SetAccess(pEntry->access); + pNewEntry->SetCreateWhen(NufxArchive::DateTimeToSeconds(&pEntry->createWhen)); + pNewEntry->SetModWhen(NufxArchive::DateTimeToSeconds(&pEntry->modWhen)); - /* always ProDOS */ - pNewEntry->SetSourceFS(DiskImg::kFormatProDOS); + /* always ProDOS */ + pNewEntry->SetSourceFS(DiskImg::kFormatProDOS); - pNewEntry->SetHasDataFork(true); - pNewEntry->SetHasRsrcFork(false); - if (IsDir(pEntry)) { - pNewEntry->SetRecordKind(GenericEntry::kRecordKindDirectory); - } else { - pNewEntry->SetRecordKind(GenericEntry::kRecordKindFile); - } + pNewEntry->SetHasDataFork(true); + pNewEntry->SetHasRsrcFork(false); + if (IsDir(pEntry)) { + pNewEntry->SetRecordKind(GenericEntry::kRecordKindDirectory); + } else { + pNewEntry->SetRecordKind(GenericEntry::kRecordKindFile); + } - /* there's no way to get the uncompressed EOF from a squeezed file */ - pNewEntry->SetCompressedLen(pEntry->realEOF); - pNewEntry->SetDataForkLen(pEntry->realEOF); + /* there's no way to get the uncompressed EOF from a squeezed file */ + pNewEntry->SetCompressedLen(pEntry->realEOF); + pNewEntry->SetDataForkLen(pEntry->realEOF); - if (isSqueezed) - pNewEntry->SetFormatStr("Squeeze"); - else - pNewEntry->SetFormatStr("Uncompr"); + if (isSqueezed) + pNewEntry->SetFormatStr("Squeeze"); + else + pNewEntry->SetFormatStr("Uncompr"); - pNewEntry->SetSqueezed(isSqueezed); - if (pEntry->realEOF != 0) - pNewEntry->SetOffset(ftell(fFp) - kBNYBlockSize); - else - pNewEntry->SetOffset(ftell(fFp)); + pNewEntry->SetSqueezed(isSqueezed); + if (pEntry->realEOF != 0) + pNewEntry->SetOffset(ftell(fFp) - kBNYBlockSize); + else + pNewEntry->SetOffset(ftell(fFp)); - AddEntry(pNewEntry); + AddEntry(pNewEntry); - return err; + return err; } /* * =========================================================================== - * Binary II functions + * Binary II functions * =========================================================================== */ /* - * Most of what follows was adapted directly from NuLib2 v2.0. There's no + * Most of what follows was adapted directly from NuLib2 v2.0. There's no * such thing as BnyLib, so all of the code for manipulating the file is * included here. */ @@ -613,12 +613,12 @@ BnyArchive::IsSqueezed(uchar one, uchar two) bool BnyArchive::IsDir(BnyFileEntry* pEntry) { - /* - * NuLib and "unblu.c" compared against file type 15 (DIR), so I'm - * going to do that too, but it would probably be better to compare - * against storageType 0x0d. - */ - return (pEntry->fileType == 15); + /* + * NuLib and "unblu.c" compared against file type 15 (DIR), so I'm + * going to do that too, but it would probably be better to compare + * against storageType 0x0d. + */ + return (pEntry->fileType == 15); } /* @@ -628,36 +628,36 @@ BnyArchive::IsDir(BnyFileEntry* pEntry) NuError BnyArchive::BNYRead(void* buf, size_t nbyte) { - size_t result; + size_t result; - ASSERT(buf != nil); - ASSERT(nbyte > 0); - ASSERT(fFp != nil); + ASSERT(buf != nil); + ASSERT(nbyte > 0); + ASSERT(fFp != nil); - errno = 0; - result = fread(buf, 1, nbyte, fFp); - if (result != nbyte) - return errno ? (NuError)errno : kNuErrFileRead; - return kNuErrNone; + errno = 0; + result = fread(buf, 1, nbyte, fFp); + if (result != nbyte) + return errno ? (NuError)errno : kNuErrFileRead; + return kNuErrNone; } /* - * Seek within an archive. Because we need to handle streaming archives, + * Seek within an archive. Because we need to handle streaming archives, * and don't need to special-case anything, we only allow relative * forward seeks. */ NuError BnyArchive::BNYSeek(long offset) { - ASSERT(fFp != nil); - ASSERT(offset > 0); + ASSERT(fFp != nil); + ASSERT(offset > 0); - /*DBUG(("--- seeking forward %ld bytes\n", offset));*/ + /*DBUG(("--- seeking forward %ld bytes\n", offset));*/ - if (fseek(fFp, offset, SEEK_CUR) < 0) - return kNuErrFileSeek; - - return kNuErrNone; + if (fseek(fFp, offset, SEEK_CUR) < 0) + return kNuErrFileSeek; + + return kNuErrNone; } @@ -666,18 +666,18 @@ BnyArchive::BNYSeek(long offset) */ void BnyArchive::BNYConvertDateTime(unsigned short prodosDate, - unsigned short prodosTime, NuDateTime* pWhen) + unsigned short prodosTime, NuDateTime* pWhen) { - pWhen->second = 0; - pWhen->minute = prodosTime & 0x3f; - pWhen->hour = (prodosTime >> 8) & 0x1f; - pWhen->day = (prodosDate & 0x1f) -1; - pWhen->month = ((prodosDate >> 5) & 0x0f) -1; - pWhen->year = (prodosDate >> 9) & 0x7f; - if (pWhen->year < 40) - pWhen->year += 100; /* P8 uses 0-39 for 2000-2039 */ - pWhen->extra = 0; - pWhen->weekDay = 0; + pWhen->second = 0; + pWhen->minute = prodosTime & 0x3f; + pWhen->hour = (prodosTime >> 8) & 0x1f; + pWhen->day = (prodosDate & 0x1f) -1; + pWhen->month = ((prodosDate >> 5) & 0x0f) -1; + pWhen->year = (prodosDate >> 9) & 0x7f; + if (pWhen->year < 40) + pWhen->year += 100; /* P8 uses 0-39 for 2000-2039 */ + pWhen->extra = 0; + pWhen->weekDay = 0; } /* @@ -689,73 +689,73 @@ BnyArchive::BNYConvertDateTime(unsigned short prodosDate, NuError BnyArchive::BNYDecodeHeader(BnyFileEntry* pEntry) { - NuError err = kNuErrNone; - uchar* raw; - int len; + NuError err = kNuErrNone; + uchar* raw; + int len; - ASSERT(pEntry != nil); + ASSERT(pEntry != nil); - raw = pEntry->blockBuf; + raw = pEntry->blockBuf; - if (raw[0] != 0x0a || raw[1] != 0x47 || raw[2] != 0x4c || raw[18] != 0x02) { - err = kNuErrBadData; - WMSG0("this doesn't look like a Binary II header\n"); - goto bail; - } + if (raw[0] != 0x0a || raw[1] != 0x47 || raw[2] != 0x4c || raw[18] != 0x02) { + err = kNuErrBadData; + WMSG0("this doesn't look like a Binary II header\n"); + goto bail; + } - pEntry->access = raw[3] | raw[111] << 8; - pEntry->fileType = raw[4] | raw[112] << 8; - pEntry->auxType = raw[5] | raw[6] << 8 | raw[109] << 16 | raw[110] << 24; - pEntry->storageType = raw[7]; - pEntry->fileSize = raw[8] | raw[9] << 8; - pEntry->prodosModDate = raw[10] | raw[11] << 8; - pEntry->prodosModTime = raw[12] | raw[13] << 8; - BNYConvertDateTime(pEntry->prodosModDate, pEntry->prodosModTime, - &pEntry->modWhen); - pEntry->prodosCreateDate = raw[14] | raw[15] << 8; - pEntry->prodosCreateTime = raw[16] | raw[17] << 8; - BNYConvertDateTime(pEntry->prodosCreateDate, pEntry->prodosCreateTime, - &pEntry->createWhen); - pEntry->eof = raw[20] | raw[21] << 8 | raw[22] << 16 | raw[116] << 24; - len = raw[23]; - if (len > kBNYMaxFileName) { - err = kNuErrBadData; - WMSG1("invalid filename length %d\n", len); - goto bail; - } - memcpy(pEntry->fileName, &raw[24], len); - pEntry->fileName[len] = '\0'; + pEntry->access = raw[3] | raw[111] << 8; + pEntry->fileType = raw[4] | raw[112] << 8; + pEntry->auxType = raw[5] | raw[6] << 8 | raw[109] << 16 | raw[110] << 24; + pEntry->storageType = raw[7]; + pEntry->fileSize = raw[8] | raw[9] << 8; + pEntry->prodosModDate = raw[10] | raw[11] << 8; + pEntry->prodosModTime = raw[12] | raw[13] << 8; + BNYConvertDateTime(pEntry->prodosModDate, pEntry->prodosModTime, + &pEntry->modWhen); + pEntry->prodosCreateDate = raw[14] | raw[15] << 8; + pEntry->prodosCreateTime = raw[16] | raw[17] << 8; + BNYConvertDateTime(pEntry->prodosCreateDate, pEntry->prodosCreateTime, + &pEntry->createWhen); + pEntry->eof = raw[20] | raw[21] << 8 | raw[22] << 16 | raw[116] << 24; + len = raw[23]; + if (len > kBNYMaxFileName) { + err = kNuErrBadData; + WMSG1("invalid filename length %d\n", len); + goto bail; + } + memcpy(pEntry->fileName, &raw[24], len); + pEntry->fileName[len] = '\0'; - pEntry->nativeName[0] = '\0'; - if (len <= 15 && raw[39] != 0) { - len = raw[39]; - if (len > kBNYMaxNativeName) { - err = kNuErrBadData; - WMSG1("invalid filename length %d\n", len); - goto bail; - } - memcpy(pEntry->nativeName, &raw[40], len); - pEntry->nativeName[len] = '\0'; - } + pEntry->nativeName[0] = '\0'; + if (len <= 15 && raw[39] != 0) { + len = raw[39]; + if (len > kBNYMaxNativeName) { + err = kNuErrBadData; + WMSG1("invalid filename length %d\n", len); + goto bail; + } + memcpy(pEntry->nativeName, &raw[40], len); + pEntry->nativeName[len] = '\0'; + } - pEntry->diskSpace = raw[117] | raw[118] << 8 | raw[119] << 16 | - raw[120] << 24; + pEntry->diskSpace = raw[117] | raw[118] << 8 | raw[119] << 16 | + raw[120] << 24; - pEntry->osType = raw[121]; - pEntry->nativeFileType = raw[122] | raw[123] << 8; - pEntry->phantomFlag = raw[124]; - pEntry->dataFlags = raw[125]; - pEntry->version = raw[126]; - pEntry->filesToFollow = raw[127]; + pEntry->osType = raw[121]; + pEntry->nativeFileType = raw[122] | raw[123] << 8; + pEntry->phantomFlag = raw[124]; + pEntry->dataFlags = raw[125]; + pEntry->version = raw[126]; + pEntry->filesToFollow = raw[127]; - /* directories are given an EOF but don't actually have any content */ - if (IsDir(pEntry)) - pEntry->realEOF = 0; - else - pEntry->realEOF = pEntry->eof; + /* directories are given an EOF but don't actually have any content */ + if (IsDir(pEntry)) + pEntry->realEOF = 0; + else + pEntry->realEOF = pEntry->eof; bail: - return err; + return err; } #if 0 @@ -774,32 +774,32 @@ bail: const char* BNYNormalizePath(BnyFileEntry* pEntry) { - NuPathnameProposal pathProposal; - NuRecord fakeRecord; - NuThread fakeThread; + NuPathnameProposal pathProposal; + NuRecord fakeRecord; + NuThread fakeThread; - /* make uninitialized data obvious */ - memset(&fakeRecord, 0xa1, sizeof(fakeRecord)); - memset(&fakeThread, 0xa5, sizeof(fakeThread)); + /* make uninitialized data obvious */ + memset(&fakeRecord, 0xa1, sizeof(fakeRecord)); + memset(&fakeThread, 0xa5, sizeof(fakeThread)); - pathProposal.pathname = pEntry->fileName; - pathProposal.filenameSeparator = '/'; /* BNY always uses ProDOS conv */ - pathProposal.pRecord = &fakeRecord; - pathProposal.pThread = &fakeThread; + pathProposal.pathname = pEntry->fileName; + pathProposal.filenameSeparator = '/'; /* BNY always uses ProDOS conv */ + pathProposal.pRecord = &fakeRecord; + pathProposal.pThread = &fakeThread; - pathProposal.newPathname = nil; - pathProposal.newFilenameSeparator = '\0'; - pathProposal.newDataSink = nil; + pathProposal.newPathname = nil; + pathProposal.newFilenameSeparator = '\0'; + pathProposal.newDataSink = nil; - /* need the filetype and auxtype for -e/-ee */ - fakeRecord.recFileType = pEntry->fileType; - fakeRecord.recExtraType = pEntry->auxType; + /* need the filetype and auxtype for -e/-ee */ + fakeRecord.recFileType = pEntry->fileType; + fakeRecord.recExtraType = pEntry->auxType; - /* need the components of a ThreadID */ - fakeThread.thThreadClass = kNuThreadClassData; - fakeThread.thThreadKind = 0x0000; /* data fork */ + /* need the components of a ThreadID */ + fakeThread.thThreadClass = kNuThreadClassData; + fakeThread.thThreadKind = 0x0000; /* data fork */ - return NormalizePath(pBny->pState, &pathProposal); + return NormalizePath(pBny->pState, &pathProposal); } #endif @@ -813,40 +813,40 @@ BNYNormalizePath(BnyFileEntry* pEntry) NuError BnyArchive::BNYCopyBlocks(BnyFileEntry* pEntry, FILE* outfp) { - NuError err = kNuErrNone; - long bytesLeft; + NuError err = kNuErrNone; + long bytesLeft; - ASSERT(pEntry->realEOF > 0); + ASSERT(pEntry->realEOF > 0); - bytesLeft = pEntry->realEOF; - while (bytesLeft > 0) { - long toWrite; + bytesLeft = pEntry->realEOF; + while (bytesLeft > 0) { + long toWrite; - toWrite = bytesLeft; - if (toWrite > kBNYBlockSize) - toWrite = kBNYBlockSize; + toWrite = bytesLeft; + if (toWrite > kBNYBlockSize) + toWrite = kBNYBlockSize; - if (outfp != nil) { - if (fwrite(pEntry->blockBuf, toWrite, 1, outfp) != 1) { - err = errno ? (NuError) errno : kNuErrFileWrite; - WMSG0("BNY write failed\n"); - goto bail; - } - } + if (outfp != nil) { + if (fwrite(pEntry->blockBuf, toWrite, 1, outfp) != 1) { + err = errno ? (NuError) errno : kNuErrFileWrite; + WMSG0("BNY write failed\n"); + goto bail; + } + } - bytesLeft -= toWrite; + bytesLeft -= toWrite; - if (bytesLeft) { - err = BNYRead(pEntry->blockBuf, kBNYBlockSize); - if (err != kNuErrNone) { - WMSG0("BNY read failed\n"); - goto bail; - } - } - } + if (bytesLeft) { + err = BNYRead(pEntry->blockBuf, kBNYBlockSize); + if (err != kNuErrNone) { + WMSG0("BNY read failed\n"); + goto bail; + } + } + } bail: - return err; + return err; } #endif @@ -857,89 +857,89 @@ bail: NuError BnyArchive::BNYIterate(void) { - NuError err = kNuErrNone; - BnyFileEntry entry; - //bool consumed; - int first = true; - int toFollow; + NuError err = kNuErrNone; + BnyFileEntry entry; + //bool consumed; + int first = true; + int toFollow; - toFollow = 1; /* assume 1 file in archive */ - while (toFollow) { - err = BNYRead(entry.blockBuf, sizeof(entry.blockBuf)); - if (err != kNuErrNone) { - WMSG0("failed while reading header\n"); - goto bail; - } + toFollow = 1; /* assume 1 file in archive */ + while (toFollow) { + err = BNYRead(entry.blockBuf, sizeof(entry.blockBuf)); + if (err != kNuErrNone) { + WMSG0("failed while reading header\n"); + goto bail; + } - err = BNYDecodeHeader(&entry); - if (err != kNuErrNone) { - if (first) { - WMSG0("not a Binary II archive?\n"); - } - goto bail; - } + err = BNYDecodeHeader(&entry); + if (err != kNuErrNone) { + if (first) { + WMSG0("not a Binary II archive?\n"); + } + goto bail; + } - /* - * If the file has one or more blocks, read the first block now. - * This will allow the various functions to evaluate the file - * contents for SQueeze compression. - */ - if (entry.realEOF != 0) { - err = BNYRead(entry.blockBuf, sizeof(entry.blockBuf)); - if (err != kNuErrNone) { - WMSG0("failed while reading\n"); - goto bail; - } - } + /* + * If the file has one or more blocks, read the first block now. + * This will allow the various functions to evaluate the file + * contents for SQueeze compression. + */ + if (entry.realEOF != 0) { + err = BNYRead(entry.blockBuf, sizeof(entry.blockBuf)); + if (err != kNuErrNone) { + WMSG0("failed while reading\n"); + goto bail; + } + } - /* - * Invoke the load function. - */ - //consumed = false; + /* + * Invoke the load function. + */ + //consumed = false; - err = LoadContentsCallback(&entry); - if (err != kNuErrNone) - goto bail; + err = LoadContentsCallback(&entry); + if (err != kNuErrNone) + goto bail; - /* - * If they didn't "consume" the entire BNY entry, we need to - * do it for them. We've already read the first block (if it - * existed), so we don't need to eat that one again. - */ - if (true /*!consumed*/) { - int nblocks = (entry.realEOF + kBNYBlockSize-1) / kBNYBlockSize; + /* + * If they didn't "consume" the entire BNY entry, we need to + * do it for them. We've already read the first block (if it + * existed), so we don't need to eat that one again. + */ + if (true /*!consumed*/) { + int nblocks = (entry.realEOF + kBNYBlockSize-1) / kBNYBlockSize; - if (nblocks > 1) { - err = BNYSeek((nblocks-1) * kBNYBlockSize); - if (err != kNuErrNone) { - WMSG0("failed while seeking forward\n"); - goto bail; - } - } - } + if (nblocks > 1) { + err = BNYSeek((nblocks-1) * kBNYBlockSize); + if (err != kNuErrNone) { + WMSG0("failed while seeking forward\n"); + goto bail; + } + } + } - if (!first) { - if (entry.filesToFollow != toFollow -1) { - WMSG2("WARNING: filesToFollow %d, expected %d\n", - entry.filesToFollow, toFollow -1); - } - } - toFollow = entry.filesToFollow; + if (!first) { + if (entry.filesToFollow != toFollow -1) { + WMSG2("WARNING: filesToFollow %d, expected %d\n", + entry.filesToFollow, toFollow -1); + } + } + toFollow = entry.filesToFollow; - first = false; - } + first = false; + } bail: - if (err != kNuErrNone) { - WMSG1("--- Iterator returning failure %d\n", err); - } - return err; + if (err != kNuErrNone) { + WMSG1("--- Iterator returning failure %d\n", err); + } + return err; } /* * =========================================================================== - * BnyArchive -- test files + * BnyArchive -- test files * =========================================================================== */ @@ -949,50 +949,50 @@ bail: bool BnyArchive::TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) { - NuError nerr; - BnyEntry* pEntry; - CString errMsg; - bool retVal = false; + NuError nerr; + BnyEntry* pEntry; + CString errMsg; + bool retVal = false; - ASSERT(fFp != nil); + ASSERT(fFp != nil); - WMSG1("Testing %d entries\n", pSelSet->GetNumEntries()); + WMSG1("Testing %d entries\n", pSelSet->GetNumEntries()); - SelectionEntry* pSelEntry = pSelSet->IterNext(); - while (pSelEntry != nil) { - pEntry = (BnyEntry*) pSelEntry->GetEntry(); + SelectionEntry* pSelEntry = pSelSet->IterNext(); + while (pSelEntry != nil) { + pEntry = (BnyEntry*) pSelEntry->GetEntry(); - WMSG2(" Testing '%s' (offset=%ld)\n", pEntry->GetDisplayName(), - pEntry->GetOffset()); + WMSG2(" Testing '%s' (offset=%ld)\n", pEntry->GetDisplayName(), + pEntry->GetOffset()); - SET_PROGRESS_UPDATE2(0, pEntry->GetDisplayName(), nil); + SET_PROGRESS_UPDATE2(0, pEntry->GetDisplayName(), nil); - nerr = pEntry->TestEntry(pMsgWnd); - if (nerr != kNuErrNone) { - if (nerr == kNuErrAborted) { - CString title; - title.LoadString(IDS_MB_APP_NAME); - errMsg = "Cancelled."; - pMsgWnd->MessageBox(errMsg, title, MB_OK); - } else { - errMsg.Format("Failed while testing '%s': %s.", - pEntry->GetPathName(), NuStrError(nerr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - } - goto bail; - } + nerr = pEntry->TestEntry(pMsgWnd); + if (nerr != kNuErrNone) { + if (nerr == kNuErrAborted) { + CString title; + title.LoadString(IDS_MB_APP_NAME); + errMsg = "Cancelled."; + pMsgWnd->MessageBox(errMsg, title, MB_OK); + } else { + errMsg.Format("Failed while testing '%s': %s.", + pEntry->GetPathName(), NuStrError(nerr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + } + goto bail; + } - pSelEntry = pSelSet->IterNext(); - } + pSelEntry = pSelSet->IterNext(); + } - /* show success message */ - errMsg.Format("Tested %d file%s, no errors found.", - pSelSet->GetNumEntries(), - pSelSet->GetNumEntries() == 1 ? "" : "s"); - pMsgWnd->MessageBox(errMsg); - retVal = true; + /* show success message */ + errMsg.Format("Tested %d file%s, no errors found.", + pSelSet->GetNumEntries(), + pSelSet->GetNumEntries() == 1 ? "" : "s"); + pMsgWnd->MessageBox(errMsg); + retVal = true; bail: - SET_PROGRESS_END(); - return retVal; + SET_PROGRESS_END(); + return retVal; } diff --git a/app/BNYArchive.h b/app/BNYArchive.h index e4b07ac..34b89a9 100644 --- a/app/BNYArchive.h +++ b/app/BNYArchive.h @@ -19,45 +19,45 @@ class BnyArchive; */ class BnyEntry : public GenericEntry { public: - BnyEntry(BnyArchive* pArchive) : - fpArchive(pArchive), fIsSqueezed(false), fOffset(-1) - {} - virtual ~BnyEntry(void) {} + BnyEntry(BnyArchive* pArchive) : + fpArchive(pArchive), fIsSqueezed(false), fOffset(-1) + {} + virtual ~BnyEntry(void) {} - // retrieve thread data - virtual int ExtractThreadToBuffer(int which, char** ppText, long* pLength, - CString* pErrMsg) const; - virtual int ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, - ConvertHighASCII convHA, CString* pErrMsg) const; - virtual long GetSelectionSerial(void) const { return -1; } // doesn't matter + // retrieve thread data + virtual int ExtractThreadToBuffer(int which, char** ppText, long* pLength, + CString* pErrMsg) const; + virtual int ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, + ConvertHighASCII convHA, CString* pErrMsg) const; + virtual long GetSelectionSerial(void) const { return -1; } // doesn't matter - virtual bool GetFeatureFlag(Feature feature) const { - if (feature == kFeaturePascalTypes || feature == kFeatureDOSTypes || - feature == kFeatureHasSimpleAccess) - return false; - else - return true; - } + virtual bool GetFeatureFlag(Feature feature) const { + if (feature == kFeaturePascalTypes || feature == kFeatureDOSTypes || + feature == kFeatureHasSimpleAccess) + return false; + else + return true; + } - NuError TestEntry(CWnd* pMsgWnd); + NuError TestEntry(CWnd* pMsgWnd); - bool GetSqueezed(void) const { return fIsSqueezed; } - void SetSqueezed(bool val) { fIsSqueezed = val; } - long GetOffset(void) const { return fOffset; } - void SetOffset(long offset) { fOffset = offset; } + bool GetSqueezed(void) const { return fIsSqueezed; } + void SetSqueezed(bool val) { fIsSqueezed = val; } + long GetOffset(void) const { return fOffset; } + void SetOffset(long offset) { fOffset = offset; } - enum { - kBNYBlockSize = 128, - }; + enum { + kBNYBlockSize = 128, + }; private: - NuError CopyData(FILE* outfp, ConvertEOL conv, ConvertHighASCII convHA, - CString* pMsg) const; - //NuError BNYUnSqueeze(ExpandBuffer* outExp) const; + NuError CopyData(FILE* outfp, ConvertEOL conv, ConvertHighASCII convHA, + CString* pMsg) const; + //NuError BNYUnSqueeze(ExpandBuffer* outExp) const; - BnyArchive* fpArchive; // holds FILE* for archive - bool fIsSqueezed; - long fOffset; + BnyArchive* fpArchive; // holds FILE* for archive + bool fIsSqueezed; + long fOffset; }; @@ -66,153 +66,153 @@ private: */ class BnyArchive : public GenericArchive { public: - BnyArchive(void) : fIsReadOnly(false), fFp(nil) - {} - virtual ~BnyArchive(void) { (void) Close(); } + BnyArchive(void) : fIsReadOnly(false), fFp(nil) + {} + virtual ~BnyArchive(void) { (void) Close(); } - // One-time initialization; returns an error string. - static CString AppInit(void); + // One-time initialization; returns an error string. + static CString AppInit(void); - virtual OpenResult Open(const char* filename, bool readOnly, - CString* pErrMsg); - virtual CString New(const char* filename, const void* options); - virtual CString Flush(void) { return ""; } - virtual CString Reload(void); - virtual bool IsReadOnly(void) const { return fIsReadOnly; }; - virtual bool IsModified(void) const { return false; } - virtual void GetDescription(CString* pStr) const { *pStr = "Binary II"; } - virtual bool BulkAdd(ActionProgressDialog* pActionProgress, - const AddFilesDialog* pAddOpts) - { ASSERT(false); return false; } - virtual bool AddDisk(ActionProgressDialog* pActionProgress, - const AddFilesDialog* pAddOpts) - { ASSERT(false); return false; } - virtual bool CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry, - const char* newName) - { ASSERT(false); return false; } - virtual bool TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); - virtual bool DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) - { ASSERT(false); return false; } - virtual bool RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) - { ASSERT(false); return false; } - virtual bool RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS, - const char* newName) - { ASSERT(false); return false; } - virtual CString TestVolumeName(const DiskFS* pDiskFS, - const char* newName) const - { ASSERT(false); return "!"; } - virtual CString TestPathName(const GenericEntry* pGenericEntry, - const CString& basePath, const CString& newName, char newFssep) const - { ASSERT(false); return "!"; } - virtual bool RecompressSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, - const RecompressOptionsDialog* pRecompOpts) - { ASSERT(false); return false; } - virtual XferStatus XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, - ActionProgressDialog* pActionProgress, const XferFileOptions* pXferOpts) - { ASSERT(false); return kXferFailed; } - virtual bool GetComment(CWnd* pMsgWnd, const GenericEntry* pEntry, - CString* pStr) - { ASSERT(false); return false; } - virtual bool SetComment(CWnd* pMsgWnd, GenericEntry* pEntry, - const CString& str) - { ASSERT(false); return false; } - virtual bool DeleteComment(CWnd* pMsgWnd, GenericEntry* pEntry) - { ASSERT(false); return false; } - virtual bool SetProps(CWnd* pMsgWnd, GenericEntry* pEntry, - const FileProps* pProps) - { ASSERT(false); return false; } - virtual void PreferencesChanged(void) {} - virtual long GetCapability(Capability cap); + virtual OpenResult Open(const char* filename, bool readOnly, + CString* pErrMsg); + virtual CString New(const char* filename, const void* options); + virtual CString Flush(void) { return ""; } + virtual CString Reload(void); + virtual bool IsReadOnly(void) const { return fIsReadOnly; }; + virtual bool IsModified(void) const { return false; } + virtual void GetDescription(CString* pStr) const { *pStr = "Binary II"; } + virtual bool BulkAdd(ActionProgressDialog* pActionProgress, + const AddFilesDialog* pAddOpts) + { ASSERT(false); return false; } + virtual bool AddDisk(ActionProgressDialog* pActionProgress, + const AddFilesDialog* pAddOpts) + { ASSERT(false); return false; } + virtual bool CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry, + const char* newName) + { ASSERT(false); return false; } + virtual bool TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); + virtual bool DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) + { ASSERT(false); return false; } + virtual bool RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) + { ASSERT(false); return false; } + virtual bool RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS, + const char* newName) + { ASSERT(false); return false; } + virtual CString TestVolumeName(const DiskFS* pDiskFS, + const char* newName) const + { ASSERT(false); return "!"; } + virtual CString TestPathName(const GenericEntry* pGenericEntry, + const CString& basePath, const CString& newName, char newFssep) const + { ASSERT(false); return "!"; } + virtual bool RecompressSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, + const RecompressOptionsDialog* pRecompOpts) + { ASSERT(false); return false; } + virtual XferStatus XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, + ActionProgressDialog* pActionProgress, const XferFileOptions* pXferOpts) + { ASSERT(false); return kXferFailed; } + virtual bool GetComment(CWnd* pMsgWnd, const GenericEntry* pEntry, + CString* pStr) + { ASSERT(false); return false; } + virtual bool SetComment(CWnd* pMsgWnd, GenericEntry* pEntry, + const CString& str) + { ASSERT(false); return false; } + virtual bool DeleteComment(CWnd* pMsgWnd, GenericEntry* pEntry) + { ASSERT(false); return false; } + virtual bool SetProps(CWnd* pMsgWnd, GenericEntry* pEntry, + const FileProps* pProps) + { ASSERT(false); return false; } + virtual void PreferencesChanged(void) {} + virtual long GetCapability(Capability cap); - friend class BnyEntry; + friend class BnyEntry; private: - virtual CString Close(void) { - if (fFp != nil) { - fclose(fFp); - fFp = nil; - } - return ""; - } - virtual void XferPrepare(const XferFileOptions* pXferOpts) - { ASSERT(false); } - virtual CString XferFile(FileDetails* pDetails, unsigned char** pDataBuf, - long dataLen, unsigned char** pRsrcBuf, long rsrcLen) - { ASSERT(false); return "!"; } - virtual void XferAbort(CWnd* pMsgWnd) - { ASSERT(false); } - virtual void XferFinish(CWnd* pMsgWnd) - { ASSERT(false); } + virtual CString Close(void) { + if (fFp != nil) { + fclose(fFp); + fFp = nil; + } + return ""; + } + virtual void XferPrepare(const XferFileOptions* pXferOpts) + { ASSERT(false); } + virtual CString XferFile(FileDetails* pDetails, unsigned char** pDataBuf, + long dataLen, unsigned char** pRsrcBuf, long rsrcLen) + { ASSERT(false); return "!"; } + virtual void XferAbort(CWnd* pMsgWnd) + { ASSERT(false); } + virtual void XferFinish(CWnd* pMsgWnd) + { ASSERT(false); } - virtual ArchiveKind GetArchiveKind(void) { return kArchiveBNY; } - virtual NuError DoAddFile(const AddFilesDialog* pAddOpts, - FileDetails* pDetails) - { ASSERT(false); return kNuErrGeneric; } + virtual ArchiveKind GetArchiveKind(void) { return kArchiveBNY; } + virtual NuError DoAddFile(const AddFilesDialog* pAddOpts, + FileDetails* pDetails) + { ASSERT(false); return kNuErrGeneric; } - enum { - kBNYBlockSize = BnyEntry::kBNYBlockSize, - kBNYMaxFileName = 64, - kBNYMaxNativeName = 48, - kBNYFlagCompressed = (1<<7), - kBNYFlagEncrypted = (1<<6), - kBNYFlagSparse = (1), - }; + enum { + kBNYBlockSize = BnyEntry::kBNYBlockSize, + kBNYMaxFileName = 64, + kBNYMaxNativeName = 48, + kBNYFlagCompressed = (1<<7), + kBNYFlagEncrypted = (1<<6), + kBNYFlagSparse = (1), + }; - typedef unsigned char uchar; - typedef unsigned short ushort; - typedef unsigned long ulong; + typedef unsigned char uchar; + typedef unsigned short ushort; + typedef unsigned long ulong; - /* - * An entry in a Binary II archive. Each archive is essentially a stream - * of files; only the "filesToFollow" value gives any indication that - * something else follows this entry. - * - * We read this from the archive and then unpack it into GenericEntry - * fields in a BnyEntry. - */ - struct BnyFileEntry; // VC++6 needs these to access private enums - friend struct BnyFileEntry; // in this class - typedef struct BnyFileEntry { - ushort access; - ushort fileType; - ulong auxType; - uchar storageType; - ulong fileSize; /* in 512-byte blocks */ - ushort prodosModDate; - ushort prodosModTime; - NuDateTime modWhen; /* computed from previous two fields */ - ushort prodosCreateDate; - ushort prodosCreateTime; - NuDateTime createWhen; /* computed from previous two fields */ - ulong eof; - ulong realEOF; /* eof is bogus for directories */ - char fileName[kBNYMaxFileName+1]; - char nativeName[kBNYMaxNativeName+1]; - ulong diskSpace; /* in 512-byte blocks */ - uchar osType; /* not exactly same as NuFileSysID */ - ushort nativeFileType; - uchar phantomFlag; - uchar dataFlags; /* advisory flags */ - uchar version; - uchar filesToFollow; /* #of files after this one */ + /* + * An entry in a Binary II archive. Each archive is essentially a stream + * of files; only the "filesToFollow" value gives any indication that + * something else follows this entry. + * + * We read this from the archive and then unpack it into GenericEntry + * fields in a BnyEntry. + */ + struct BnyFileEntry; // VC++6 needs these to access private enums + friend struct BnyFileEntry; // in this class + typedef struct BnyFileEntry { + ushort access; + ushort fileType; + ulong auxType; + uchar storageType; + ulong fileSize; /* in 512-byte blocks */ + ushort prodosModDate; + ushort prodosModTime; + NuDateTime modWhen; /* computed from previous two fields */ + ushort prodosCreateDate; + ushort prodosCreateTime; + NuDateTime createWhen; /* computed from previous two fields */ + ulong eof; + ulong realEOF; /* eof is bogus for directories */ + char fileName[kBNYMaxFileName+1]; + char nativeName[kBNYMaxNativeName+1]; + ulong diskSpace; /* in 512-byte blocks */ + uchar osType; /* not exactly same as NuFileSysID */ + ushort nativeFileType; + uchar phantomFlag; + uchar dataFlags; /* advisory flags */ + uchar version; + uchar filesToFollow; /* #of files after this one */ - uchar blockBuf[kBNYBlockSize]; - } BnyFileEntry; + uchar blockBuf[kBNYBlockSize]; + } BnyFileEntry; - int LoadContents(void); - NuError LoadContentsCallback(BnyFileEntry* pEntry); + int LoadContents(void); + NuError LoadContentsCallback(BnyFileEntry* pEntry); - bool IsSqueezed(uchar one, uchar two); - bool IsDir(BnyFileEntry* pEntry); - NuError BNYRead(void* buf, size_t nbyte); - NuError BNYSeek(long offset); - void BNYConvertDateTime(unsigned short prodosDate, - unsigned short prodosTime, NuDateTime* pWhen); - NuError BNYDecodeHeader(BnyFileEntry* pEntry); - NuError BNYIterate(void); + bool IsSqueezed(uchar one, uchar two); + bool IsDir(BnyFileEntry* pEntry); + NuError BNYRead(void* buf, size_t nbyte); + NuError BNYSeek(long offset); + void BNYConvertDateTime(unsigned short prodosDate, + unsigned short prodosTime, NuDateTime* pWhen); + NuError BNYDecodeHeader(BnyFileEntry* pEntry); + NuError BNYIterate(void); - FILE* fFp; - bool fIsReadOnly; + FILE* fFp; + bool fIsReadOnly; }; #endif /*__BNY_ARCHIVE__*/ \ No newline at end of file diff --git a/app/BasicImport.cpp b/app/BasicImport.cpp index 7751edc..f834aa1 100644 --- a/app/BasicImport.cpp +++ b/app/BasicImport.cpp @@ -17,7 +17,7 @@ /* * ========================================================================== - * BASTokenLookup + * BASTokenLookup * ========================================================================== */ @@ -26,27 +26,27 @@ */ void BASTokenLookup::Init(const char* tokenList, int numTokens, - int tokenLen) + int tokenLen) { - int i; + int i; - ASSERT(tokenList != nil); - ASSERT(numTokens > 0); - ASSERT(tokenLen > 0); + ASSERT(tokenList != nil); + ASSERT(numTokens > 0); + ASSERT(tokenLen > 0); - delete[] fTokenPtr; // in case we're being re-initialized - delete[] fTokenLen; + delete[] fTokenPtr; // in case we're being re-initialized + delete[] fTokenLen; - fTokenPtr = new const char*[numTokens]; - fTokenLen = new int[numTokens]; - fNumTokens = numTokens; + fTokenPtr = new const char*[numTokens]; + fTokenLen = new int[numTokens]; + fNumTokens = numTokens; - for (i = 0; i < numTokens; i++) { - fTokenPtr[i] = tokenList; - fTokenLen[i] = strlen(tokenList); + for (i = 0; i < numTokens; i++) { + fTokenPtr[i] = tokenList; + fTokenLen[i] = strlen(tokenList); - tokenList += tokenLen; - } + tokenList += tokenLen; + } } /* @@ -57,32 +57,32 @@ BASTokenLookup::Init(const char* tokenList, int numTokens, int BASTokenLookup::Lookup(const char* str, int len, int* pFoundLen) { - int longestIndex, longestLen; - int i; + int longestIndex, longestLen; + int i; - longestIndex = longestLen = -1; - for (i = 0; i < fNumTokens; i++) { - if (fTokenLen[i] <= len && fTokenLen[i] > longestLen && - strncasecmp(str, fTokenPtr[i], fTokenLen[i]) == 0) - { - longestIndex = i; - longestLen = fTokenLen[i]; - } - } + longestIndex = longestLen = -1; + for (i = 0; i < fNumTokens; i++) { + if (fTokenLen[i] <= len && fTokenLen[i] > longestLen && + strncasecmp(str, fTokenPtr[i], fTokenLen[i]) == 0) + { + longestIndex = i; + longestLen = fTokenLen[i]; + } + } - *pFoundLen = longestLen; - return longestIndex; + *pFoundLen = longestLen; + return longestIndex; } /* * ========================================================================== - * ImportBASDialog + * ImportBASDialog * ========================================================================== */ BEGIN_MESSAGE_MAP(ImportBASDialog, CDialog) - ON_COMMAND(IDHELP, OnHelp) + ON_COMMAND(IDHELP, OnHelp) END_MESSAGE_MAP() @@ -92,31 +92,31 @@ END_MESSAGE_MAP() BOOL ImportBASDialog::OnInitDialog(void) { - CDialog::OnInitDialog(); // base class init + CDialog::OnInitDialog(); // base class init - PathName path(fFileName); - CString fileNameOnly(path.GetFileName()); - CString ext(fileNameOnly.Right(4)); - if (ext.CompareNoCase(".txt") == 0) { - WMSG1("removing extension from '%s'\n", (const char*) fileNameOnly); - fileNameOnly = fileNameOnly.Left(fileNameOnly.GetLength() - 4); - } + PathName path(fFileName); + CString fileNameOnly(path.GetFileName()); + CString ext(fileNameOnly.Right(4)); + if (ext.CompareNoCase(".txt") == 0) { + WMSG1("removing extension from '%s'\n", (const char*) fileNameOnly); + fileNameOnly = fileNameOnly.Left(fileNameOnly.GetLength() - 4); + } - CEdit* pEdit = (CEdit*) GetDlgItem(IDC_IMPORT_BAS_SAVEAS); - pEdit->SetWindowText(fileNameOnly); - pEdit->SetSel(0, -1); - pEdit->SetFocus(); + CEdit* pEdit = (CEdit*) GetDlgItem(IDC_IMPORT_BAS_SAVEAS); + pEdit->SetWindowText(fileNameOnly); + pEdit->SetSel(0, -1); + pEdit->SetFocus(); - /* - * Do the actual import. If it fails, disable the "save" button. - */ - if (!ImportBAS(fFileName)) { - CButton* pButton = (CButton*) GetDlgItem(IDOK); - pButton->EnableWindow(FALSE); - pEdit->EnableWindow(FALSE); - } + /* + * Do the actual import. If it fails, disable the "save" button. + */ + if (!ImportBAS(fFileName)) { + CButton* pButton = (CButton*) GetDlgItem(IDOK); + pButton->EnableWindow(FALSE); + pEdit->EnableWindow(FALSE); + } - return FALSE; // keep our focus + return FALSE; // keep our focus } static const char* kFailed = "failed.\r\n\r\n"; @@ -128,72 +128,72 @@ static const char* kSuccess = "success!\r\n\r\n"; bool ImportBASDialog::ImportBAS(const char* fileName) { - FILE* fp = NULL; - ExpandBuffer msgs(1024); - long fileLen, outLen, count; - char* buf = nil; - char* outBuf = nil; - bool result = false; + FILE* fp = NULL; + ExpandBuffer msgs(1024); + long fileLen, outLen, count; + char* buf = nil; + char* outBuf = nil; + bool result = false; - msgs.Printf("Importing from '%s'...", fileName); - fp = fopen(fileName, "rb"); // EOL unknown, open as binary and deal - if (fp == NULL) { - msgs.Printf("%sUnable to open file.", kFailed); - goto bail; - } + msgs.Printf("Importing from '%s'...", fileName); + fp = fopen(fileName, "rb"); // EOL unknown, open as binary and deal + if (fp == NULL) { + msgs.Printf("%sUnable to open file.", kFailed); + goto bail; + } - /* determine file length, and verify that it looks okay */ - fseek(fp, 0, SEEK_END); - fileLen = ftell(fp); - rewind(fp); - if (ferror(fp) || fileLen < 0) { - msgs.Printf("%sUnable to determine file length.", kFailed); - goto bail; - } - if (fileLen == 0) { - msgs.Printf("%sFile is empty.", kFailed); - goto bail; - } - if (fileLen >= 128*1024) { - msgs.Printf("%sFile is too large to be Applesoft.", kFailed); - goto bail; - } + /* determine file length, and verify that it looks okay */ + fseek(fp, 0, SEEK_END); + fileLen = ftell(fp); + rewind(fp); + if (ferror(fp) || fileLen < 0) { + msgs.Printf("%sUnable to determine file length.", kFailed); + goto bail; + } + if (fileLen == 0) { + msgs.Printf("%sFile is empty.", kFailed); + goto bail; + } + if (fileLen >= 128*1024) { + msgs.Printf("%sFile is too large to be Applesoft.", kFailed); + goto bail; + } - buf = new char[fileLen]; - if (buf == NULL) { - msgs.Printf("%sUnable to allocate memory.", kFailed); - goto bail; - } + buf = new char[fileLen]; + if (buf == NULL) { + msgs.Printf("%sUnable to allocate memory.", kFailed); + goto bail; + } - /* read the entire thing into memory */ - count = fread(buf, 1, fileLen, fp); - if (count != fileLen) { - msgs.Printf("%sCould only read %ld of %ld bytes.", kFailed, - count, fileLen); - goto bail; - } + /* read the entire thing into memory */ + count = fread(buf, 1, fileLen, fp); + if (count != fileLen) { + msgs.Printf("%sCould only read %ld of %ld bytes.", kFailed, + count, fileLen); + goto bail; + } - /* process it */ - if (!ConvertTextToBAS(buf, fileLen, &outBuf, &outLen, &msgs)) - goto bail; + /* process it */ + if (!ConvertTextToBAS(buf, fileLen, &outBuf, &outLen, &msgs)) + goto bail; - result = true; - SetOutput(outBuf, outLen); + result = true; + SetOutput(outBuf, outLen); bail: - if (fp != NULL) - fclose(fp); - delete[] buf; + if (fp != NULL) + fclose(fp); + delete[] buf; - /* copy our error messages out */ - CEdit* pEdit = (CEdit*) GetDlgItem(IDC_IMPORT_BAS_RESULTS); - char* msgBuf = nil; - long msgLen; - msgs.SeizeBuffer(&msgBuf, &msgLen); - pEdit->SetWindowText(msgBuf); - delete[] msgBuf; + /* copy our error messages out */ + CEdit* pEdit = (CEdit*) GetDlgItem(IDC_IMPORT_BAS_RESULTS); + char* msgBuf = nil; + long msgLen; + msgs.SeizeBuffer(&msgBuf, &msgLen); + pEdit->SetWindowText(msgBuf); + delete[] msgBuf; - return result; + return result; } /* @@ -201,65 +201,65 @@ bail: */ bool ImportBASDialog::ConvertTextToBAS(const char* buf, long fileLen, - char** pOutBuf, long* pOutLen, ExpandBuffer* pMsgs) + char** pOutBuf, long* pOutLen, ExpandBuffer* pMsgs) { - ExpandBuffer output(32768); - CString msg; - const char* lineStart; - const char* lineEnd; - long textRemaining; - int lineNum; + ExpandBuffer output(32768); + CString msg; + const char* lineStart; + const char* lineEnd; + long textRemaining; + int lineNum; - fBASLookup.Init(ReformatApplesoft::GetApplesoftTokens(), - ReformatApplesoft::kTokenCount, ReformatApplesoft::kTokenLen); + fBASLookup.Init(ReformatApplesoft::GetApplesoftTokens(), + ReformatApplesoft::kTokenCount, ReformatApplesoft::kTokenLen); - lineEnd = buf; - textRemaining = fileLen; - lineNum = 0; + lineEnd = buf; + textRemaining = fileLen; + lineNum = 0; - while (textRemaining > 0) { - lineNum++; - lineStart = lineEnd; - lineEnd = FindEOL(lineStart, textRemaining); + while (textRemaining > 0) { + lineNum++; + lineStart = lineEnd; + lineEnd = FindEOL(lineStart, textRemaining); - if (!ProcessBASLine(lineStart, lineEnd - lineStart, &output, - /*ref*/ msg)) - { - pMsgs->Printf("%sLine %d: %s", kFailed, lineNum, (const char*) msg); - return false; - } + if (!ProcessBASLine(lineStart, lineEnd - lineStart, &output, + /*ref*/ msg)) + { + pMsgs->Printf("%sLine %d: %s", kFailed, lineNum, (const char*) msg); + return false; + } - textRemaining -= lineEnd - lineStart; - } + textRemaining -= lineEnd - lineStart; + } - /* output EOF marker */ - output.Putc(0x00); - output.Putc(0x00); + /* output EOF marker */ + output.Putc(0x00); + output.Putc(0x00); - /* grab the buffer */ - char* outBuf; - long outLen; - output.SeizeBuffer(&outBuf, &outLen); + /* grab the buffer */ + char* outBuf; + long outLen; + output.SeizeBuffer(&outBuf, &outLen); - if (outLen >= 0xc000) { - pMsgs->Printf("%sOutput is too large to be valid", kFailed); - delete[] outBuf; - return false; - } + if (outLen >= 0xc000) { + pMsgs->Printf("%sOutput is too large to be valid", kFailed); + delete[] outBuf; + return false; + } - /* go back and fix up the "next line" pointers, assuming a $0801 start */ - if (!FixBASLinePointers(outBuf, outLen, 0x0801)) { - pMsgs->Printf("%sFailed while fixing line pointers", kFailed); - delete[] outBuf; - return false; - } + /* go back and fix up the "next line" pointers, assuming a $0801 start */ + if (!FixBASLinePointers(outBuf, outLen, 0x0801)) { + pMsgs->Printf("%sFailed while fixing line pointers", kFailed); + delete[] outBuf; + return false; + } - *pOutBuf = outBuf; - *pOutLen = outLen; - pMsgs->Printf("%sProcessed %d lines", kSuccess, lineNum); - pMsgs->Printf("\r\nTokenized file is %d bytes long", *pOutLen); + *pOutBuf = outBuf; + *pOutLen = outLen; + pMsgs->Printf("%sProcessed %d lines", kSuccess, lineNum); + pMsgs->Printf("\r\nTokenized file is %d bytes long", *pOutLen); - return true; + return true; } /* @@ -335,205 +335,205 @@ differentiating between "at n"/"atn" and "at o"/"ato". */ bool ImportBASDialog::ProcessBASLine(const char* buf, int len, - ExpandBuffer* pOutput, CString& msg) + ExpandBuffer* pOutput, CString& msg) { - const int kMaxTokenLen = 7; // longest token; must also hold linenum - const int kTokenAT = 0xc5 - 128; - const int kTokenATN = 0xe1 - 128; - char tokenBuf[kMaxTokenLen+1]; - bool gotOne = false; - bool haveLineNum = false; - char ch; - int tokenLen; - int lineNum; - int foundToken; + const int kMaxTokenLen = 7; // longest token; must also hold linenum + const int kTokenAT = 0xc5 - 128; + const int kTokenATN = 0xe1 - 128; + char tokenBuf[kMaxTokenLen+1]; + bool gotOne = false; + bool haveLineNum = false; + char ch; + int tokenLen; + int lineNum; + int foundToken; - if (!len) - return false; + if (!len) + return false; - /* - * Remove the CR, LF, or CRLF from the end of the line. - */ - if (len > 1 && buf[len-2] == '\r' && buf[len-1] == '\n') { - //WMSG0("removed CRLF\n"); - len -= 2; - } else if (buf[len-1] == '\r') { - //WMSG0("removed CR\n"); - len--; - } else if (buf[len-1] == '\n') { - //WMSG0("removed LF\n"); - len--; - } else { - //WMSG0("no EOL marker found\n"); - } + /* + * Remove the CR, LF, or CRLF from the end of the line. + */ + if (len > 1 && buf[len-2] == '\r' && buf[len-1] == '\n') { + //WMSG0("removed CRLF\n"); + len -= 2; + } else if (buf[len-1] == '\r') { + //WMSG0("removed CR\n"); + len--; + } else if (buf[len-1] == '\n') { + //WMSG0("removed LF\n"); + len--; + } else { + //WMSG0("no EOL marker found\n"); + } - if (!len) - return true; // blank lines are okay + if (!len) + return true; // blank lines are okay - /* - * Extract the line number. - */ - tokenLen = 0; - while (len > 0) { - if (!GetNextNWC(&buf, &len, &ch)) { - if (!gotOne) - return true; // blank lines with whitespace are okay - else { - // end of line reached while scanning line number is bad - msg = "found nothing except line number"; - return false; - } - } - gotOne = true; + /* + * Extract the line number. + */ + tokenLen = 0; + while (len > 0) { + if (!GetNextNWC(&buf, &len, &ch)) { + if (!gotOne) + return true; // blank lines with whitespace are okay + else { + // end of line reached while scanning line number is bad + msg = "found nothing except line number"; + return false; + } + } + gotOne = true; - if (!isdigit(ch)) - break; - if (tokenLen == 5) { // theoretical max is "65535" - msg = "line number has too many digits"; - return false; - } - tokenBuf[tokenLen++] = ch; - } + if (!isdigit(ch)) + break; + if (tokenLen == 5) { // theoretical max is "65535" + msg = "line number has too many digits"; + return false; + } + tokenBuf[tokenLen++] = ch; + } - if (!tokenLen) { - msg = "line did not start with a line number"; - return false; - } - tokenBuf[tokenLen] = '\0'; - lineNum = atoi(tokenBuf); - WMSG1("FOUND line %d\n", lineNum); + if (!tokenLen) { + msg = "line did not start with a line number"; + return false; + } + tokenBuf[tokenLen] = '\0'; + lineNum = atoi(tokenBuf); + WMSG1("FOUND line %d\n", lineNum); - pOutput->Putc((char) 0xcc); // placeholder - pOutput->Putc((char) 0xcc); - pOutput->Putc(lineNum & 0xff); - pOutput->Putc((lineNum >> 8) & 0xff); + pOutput->Putc((char) 0xcc); // placeholder + pOutput->Putc((char) 0xcc); + pOutput->Putc(lineNum & 0xff); + pOutput->Putc((lineNum >> 8) & 0xff); - /* - * Start scanning tokens. - * - * We need to find the longest matching token (i.e. prefer "ONERR" over - * "ON"). Grab a bunch of characters, ignoring whitespace, and scan - * for a match. - */ - buf--; // back up - len++; - foundToken = -1; + /* + * Start scanning tokens. + * + * We need to find the longest matching token (i.e. prefer "ONERR" over + * "ON"). Grab a bunch of characters, ignoring whitespace, and scan + * for a match. + */ + buf--; // back up + len++; + foundToken = -1; - while (len > 0) { - const char* dummy = buf; - int remaining = len; + while (len > 0) { + const char* dummy = buf; + int remaining = len; - /* load up the buffer */ - for (tokenLen = 0; tokenLen < kMaxTokenLen; tokenLen++) { - if (!GetNextNWC(&dummy, &remaining, &ch)) - break; - if (ch == '"') - break; - tokenBuf[tokenLen] = ch; - } + /* load up the buffer */ + for (tokenLen = 0; tokenLen < kMaxTokenLen; tokenLen++) { + if (!GetNextNWC(&dummy, &remaining, &ch)) + break; + if (ch == '"') + break; + tokenBuf[tokenLen] = ch; + } - if (tokenLen == 0) { - if (ch == '"') { - /* - * Note it's possible for strings to be unterminated. This - * will go unnoticed by Applesoft if it's at the end of a - * line. - */ - GetNextNWC(&buf, &len, &ch); - pOutput->Putc(ch); - while (len--) { - ch = *buf++; - pOutput->Putc(ch); - if (ch == '"') - break; - } - } else { - /* end of line reached */ - break; - } - } else { - int token, foundLen; + if (tokenLen == 0) { + if (ch == '"') { + /* + * Note it's possible for strings to be unterminated. This + * will go unnoticed by Applesoft if it's at the end of a + * line. + */ + GetNextNWC(&buf, &len, &ch); + pOutput->Putc(ch); + while (len--) { + ch = *buf++; + pOutput->Putc(ch); + if (ch == '"') + break; + } + } else { + /* end of line reached */ + break; + } + } else { + int token, foundLen; - token = fBASLookup.Lookup(tokenBuf, tokenLen, &foundLen); - if (token >= 0) { - /* match! */ - if (token == kTokenAT || token == kTokenATN) { - /* have to go back and re-scan original */ - const char* tp = buf +1; - while (toupper(*tp++) != 'T') - ; - if (toupper(*tp) == 'N') { - /* keep this token */ - assert(token == kTokenATN); - } else if (toupper(*tp) == 'O') { - /* eat and emit the 'A' so we get the "TO" instead */ - goto output_single; - } else { - if (token == kTokenATN) { - /* reduce to "AT" */ - token = kTokenAT; - foundLen--; - } - } - } - pOutput->Putc(token + 128); + token = fBASLookup.Lookup(tokenBuf, tokenLen, &foundLen); + if (token >= 0) { + /* match! */ + if (token == kTokenAT || token == kTokenATN) { + /* have to go back and re-scan original */ + const char* tp = buf +1; + while (toupper(*tp++) != 'T') + ; + if (toupper(*tp) == 'N') { + /* keep this token */ + assert(token == kTokenATN); + } else if (toupper(*tp) == 'O') { + /* eat and emit the 'A' so we get the "TO" instead */ + goto output_single; + } else { + if (token == kTokenATN) { + /* reduce to "AT" */ + token = kTokenAT; + foundLen--; + } + } + } + pOutput->Putc(token + 128); - /* consume token chars, including whitespace */ - for (int j = 0; j < foundLen; j++) - GetNextNWC(&buf, &len, &ch); + /* consume token chars, including whitespace */ + for (int j = 0; j < foundLen; j++) + GetNextNWC(&buf, &len, &ch); - //WMSG2("TOKEN '%s' (%d)\n", - // fBASLookup.GetToken(token), tokenLen); + //WMSG2("TOKEN '%s' (%d)\n", + // fBASLookup.GetToken(token), tokenLen); - /* special handling for REM or DATA */ - if (token == 0xb2 - 128) { - /* for a REM statement, copy verbatim to end of line */ - if (*buf == ' ') { - /* eat one leading space, if present */ - buf++; - len--; - } - while (len--) { - ch = *buf++; - pOutput->Putc(ch); - } - } else if (token == 0x83 - 128) { - bool inQuote = false; + /* special handling for REM or DATA */ + if (token == 0xb2 - 128) { + /* for a REM statement, copy verbatim to end of line */ + if (*buf == ' ') { + /* eat one leading space, if present */ + buf++; + len--; + } + while (len--) { + ch = *buf++; + pOutput->Putc(ch); + } + } else if (token == 0x83 - 128) { + bool inQuote = false; - /* for a DATA statement, copy until ':' */ - if (*buf == ' ') { - /* eat one leading space */ - buf++; - len--; - } - while (len--) { - ch = *buf++; - if (ch == '"') // ignore ':' in quoted strings - inQuote = !inQuote; + /* for a DATA statement, copy until ':' */ + if (*buf == ' ') { + /* eat one leading space */ + buf++; + len--; + } + while (len--) { + ch = *buf++; + if (ch == '"') // ignore ':' in quoted strings + inQuote = !inQuote; - if (!inQuote && ch == ':') { - len++; - buf--; - break; - } - pOutput->Putc(ch); - } - } - } else { - /* - * Not a quote, and no token begins with this character. - * Output it and advance. - */ + if (!inQuote && ch == ':') { + len++; + buf--; + break; + } + pOutput->Putc(ch); + } + } + } else { + /* + * Not a quote, and no token begins with this character. + * Output it and advance. + */ output_single: - GetNextNWC(&buf, &len, &ch); - pOutput->Putc(toupper(ch)); - } - } - } + GetNextNWC(&buf, &len, &ch); + pOutput->Putc(toupper(ch)); + } + } + } - pOutput->Putc('\0'); + pOutput->Putc('\0'); - return true; + return true; } /* @@ -542,49 +542,49 @@ output_single: bool ImportBASDialog::FixBASLinePointers(char* buf, long len, unsigned short addr) { - unsigned short val; - char* start; + unsigned short val; + char* start; - while (len >= 4) { - start = buf; - val = (*buf) & 0xff | (*(buf+1)) << 8; + while (len >= 4) { + start = buf; + val = (*buf) & 0xff | (*(buf+1)) << 8; - if (val == 0) - break; - if (val != 0xcccc) { - WMSG1("unexpected value 0x%04x found\n", val); - return false; - } + if (val == 0) + break; + if (val != 0xcccc) { + WMSG1("unexpected value 0x%04x found\n", val); + return false; + } - buf += 4; - len -= 4; + buf += 4; + len -= 4; - /* - * Find the next end-of-line marker. - */ - while (*buf != '\0' && len > 0) { - buf++; - len--; - } - if (!len) { - WMSG0("ran off the end?\n"); - return false; - } - buf++; - len--; + /* + * Find the next end-of-line marker. + */ + while (*buf != '\0' && len > 0) { + buf++; + len--; + } + if (!len) { + WMSG0("ran off the end?\n"); + return false; + } + buf++; + len--; - /* - * Set the value. - */ - val = (unsigned short) (buf - start); - ASSERT((int) val == buf - start); - addr += val; + /* + * Set the value. + */ + val = (unsigned short) (buf - start); + ASSERT((int) val == buf - start); + addr += val; - *start = addr & 0xff; - *(start+1) = (addr >> 8) & 0xff; - } + *start = addr & 0xff; + *(start+1) = (addr >> 8) & 0xff; + } - return true; + return true; } /* @@ -596,25 +596,25 @@ ImportBASDialog::FixBASLinePointers(char* buf, long len, unsigned short addr) const char* ImportBASDialog::FindEOL(const char* buf, long max) { - ASSERT(max >= 0); - if (max == 0) - return nil; + ASSERT(max >= 0); + if (max == 0) + return nil; - while (max) { - if (*buf == '\r' || *buf == '\n') { - if (*buf == '\r' && max > 0 && *(buf+1) == '\n') - return buf+2; - return buf+1; - } + while (max) { + if (*buf == '\r' || *buf == '\n') { + if (*buf == '\r' && max > 0 && *(buf+1) == '\n') + return buf+2; + return buf+1; + } - buf++; - max--; - } + buf++; + max--; + } - /* - * Looks like the last line didn't have an EOL. That's okay. - */ - return buf; + /* + * Looks like the last line didn't have an EOL. That's okay. + */ + return buf; } /* @@ -627,24 +627,24 @@ ImportBASDialog::FindEOL(const char* buf, long max) bool ImportBASDialog::GetNextNWC(const char** pBuf, int* pLen, char* pCh) { - static const char* kWhitespace = " \t\r\n"; + static const char* kWhitespace = " \t\r\n"; - while (*pLen > 0) { - const char* ptr; - char ch; + while (*pLen > 0) { + const char* ptr; + char ch; - ch = **pBuf; - ptr = strchr(kWhitespace, ch); - (*pBuf)++; - (*pLen)--; + ch = **pBuf; + ptr = strchr(kWhitespace, ch); + (*pBuf)++; + (*pLen)--; - if (ptr == nil) { - *pCh = ch; - return true; - } - } + if (ptr == nil) { + *pCh = ch; + return true; + } + } - return false; + return false; } @@ -653,55 +653,55 @@ ImportBASDialog::GetNextNWC(const char** pBuf, int* pLen, char* pCh) */ void ImportBASDialog::OnOK(void) { - CEdit* pEdit = (CEdit*) GetDlgItem(IDC_IMPORT_BAS_SAVEAS); - CString fileName; + CEdit* pEdit = (CEdit*) GetDlgItem(IDC_IMPORT_BAS_SAVEAS); + CString fileName; - pEdit->GetWindowText(fileName); - if (fileName.IsEmpty()) { - CString appName; - appName.LoadString(IDS_MB_APP_NAME); + pEdit->GetWindowText(fileName); + if (fileName.IsEmpty()) { + CString appName; + appName.LoadString(IDS_MB_APP_NAME); - MessageBox("You must specify a filename.", - appName, MB_OK); - } + MessageBox("You must specify a filename.", + appName, MB_OK); + } - /* - * Write the file to the currently-open archive. - */ - GenericArchive::FileDetails details; + /* + * Write the file to the currently-open archive. + */ + GenericArchive::FileDetails details; - details.entryKind = GenericArchive::FileDetails::kFileKindDataFork; - details.origName = "Imported BASIC"; - details.storageName = fileName; - details.access = 0xe3; // unlocked, backup bit set - details.fileType = kFileTypeBAS; - details.extraType = 0x0801; - details.storageType = DiskFS::kStorageSeedling; - time_t now = time(nil); - GenericArchive::UNIXTimeToDateTime(&now, &details.createWhen); - GenericArchive::UNIXTimeToDateTime(&now, &details.archiveWhen); - GenericArchive::UNIXTimeToDateTime(&now, &details.modWhen); + details.entryKind = GenericArchive::FileDetails::kFileKindDataFork; + details.origName = "Imported BASIC"; + details.storageName = fileName; + details.access = 0xe3; // unlocked, backup bit set + details.fileType = kFileTypeBAS; + details.extraType = 0x0801; + details.storageType = DiskFS::kStorageSeedling; + time_t now = time(nil); + GenericArchive::UNIXTimeToDateTime(&now, &details.createWhen); + GenericArchive::UNIXTimeToDateTime(&now, &details.archiveWhen); + GenericArchive::UNIXTimeToDateTime(&now, &details.modWhen); - CString errMsg; + CString errMsg; - fDirty = true; - if (!MainWindow::SaveToArchive(&details, (const unsigned char*) fOutput, - fOutputLen, nil, -1, /*ref*/errMsg, this)) - { - goto bail; - } + fDirty = true; + if (!MainWindow::SaveToArchive(&details, (const unsigned char*) fOutput, + fOutputLen, nil, -1, /*ref*/errMsg, this)) + { + goto bail; + } - /* success! close the dialog */ - CDialog::OnOK(); + /* success! close the dialog */ + CDialog::OnOK(); bail: - if (!errMsg.IsEmpty()) { - CString msg; - msg.Format("Unable to import file: %s.", (const char *) errMsg); - ShowFailureMsg(this, msg, IDS_FAILED); - return; - } - return; + if (!errMsg.IsEmpty()) { + CString msg; + msg.Format("Unable to import file: %s.", (const char *) errMsg); + ShowFailureMsg(this, msg, IDS_FAILED); + return; + } + return; } /* @@ -710,5 +710,5 @@ bail: void ImportBASDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_IMPORT_BASIC, HELP_CONTEXT); + WinHelp(HELP_TOPIC_IMPORT_BASIC, HELP_CONTEXT); } diff --git a/app/BasicImport.h b/app/BasicImport.h index 5c5b639..ae5b3ec 100644 --- a/app/BasicImport.h +++ b/app/BasicImport.h @@ -23,29 +23,29 @@ */ class BASTokenLookup { public: - BASTokenLookup(void) - : fTokenPtr(nil), fTokenLen(nil) - {} - ~BASTokenLookup(void) { - delete[] fTokenPtr; - delete[] fTokenLen; - } + BASTokenLookup(void) + : fTokenPtr(nil), fTokenLen(nil) + {} + ~BASTokenLookup(void) { + delete[] fTokenPtr; + delete[] fTokenLen; + } - // Initialize the array. - void Init(const char* tokenList, int numTokens, int tokenLen); + // Initialize the array. + void Init(const char* tokenList, int numTokens, int tokenLen); - // Return the index of the matching token, or -1 if none found. - int Lookup(const char* str, int len, int* pFoundLen); + // Return the index of the matching token, or -1 if none found. + int Lookup(const char* str, int len, int* pFoundLen); - // Return a printable string. - const char* GetToken(int idx) { - return fTokenPtr[idx]; - } + // Return a printable string. + const char* GetToken(int idx) { + return fTokenPtr[idx]; + } private: - int fNumTokens; - const char** fTokenPtr; - int* fTokenLen; + int fNumTokens; + const char** fTokenPtr; + int* fTokenLen; }; @@ -56,49 +56,49 @@ private: */ class ImportBASDialog : public CDialog { public: - ImportBASDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_IMPORT_BAS, pParentWnd), fDirty(false), - fOutput(nil), fOutputLen(-1) - {} - virtual ~ImportBASDialog(void) { - delete[] fOutput; - } + ImportBASDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_IMPORT_BAS, pParentWnd), fDirty(false), + fOutput(nil), fOutputLen(-1) + {} + virtual ~ImportBASDialog(void) { + delete[] fOutput; + } - CString fFileName; // file to open + CString fFileName; // file to open - // did we add something to the archive? - bool IsDirty(void) const { return fDirty; } + // did we add something to the archive? + bool IsDirty(void) const { return fDirty; } private: - virtual BOOL OnInitDialog(void); - //virtual void DoDataExchange(CDataExchange* pDX); - virtual void OnOK(void); + virtual BOOL OnInitDialog(void); + //virtual void DoDataExchange(CDataExchange* pDX); + virtual void OnOK(void); - afx_msg void OnHelp(void); + afx_msg void OnHelp(void); - bool ImportBAS(const char* fileName); - bool ConvertTextToBAS(const char* buf, long fileLen, - char** pOutBuf, long* pOutLen, ExpandBuffer* pMsgs); - bool ProcessBASLine(const char* buf, int len, - ExpandBuffer* pOutput, CString& msg); - bool FixBASLinePointers(char* buf, long len, unsigned short addr); + bool ImportBAS(const char* fileName); + bool ConvertTextToBAS(const char* buf, long fileLen, + char** pOutBuf, long* pOutLen, ExpandBuffer* pMsgs); + bool ProcessBASLine(const char* buf, int len, + ExpandBuffer* pOutput, CString& msg); + bool FixBASLinePointers(char* buf, long len, unsigned short addr); - const char* FindEOL(const char* buf, long max); - bool GetNextNWC(const char** pBuf, int* pLen, char* pCh); + const char* FindEOL(const char* buf, long max); + bool GetNextNWC(const char** pBuf, int* pLen, char* pCh); - void SetOutput(char* outBuf, long outLen) { - delete[] fOutput; - fOutput = outBuf; - fOutputLen = outLen; - } + void SetOutput(char* outBuf, long outLen) { + delete[] fOutput; + fOutput = outBuf; + fOutputLen = outLen; + } - BASTokenLookup fBASLookup; - bool fDirty; + BASTokenLookup fBASLookup; + bool fDirty; - char* fOutput; - long fOutputLen; + char* fOutput; + long fOutputLen; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__BASICIMPORT__*/ \ No newline at end of file diff --git a/app/CassImpTargetDialog.cpp b/app/CassImpTargetDialog.cpp index 45e57d7..bdfc4ab 100644 --- a/app/CassImpTargetDialog.cpp +++ b/app/CassImpTargetDialog.cpp @@ -9,13 +9,13 @@ */ #include "StdAfx.h" #include "CassImpTargetDialog.h" -#include "GenericArchive.h" // just want kFileTypeXXX +#include "GenericArchive.h" // just want kFileTypeXXX BEGIN_MESSAGE_MAP(CassImpTargetDialog, CDialog) - ON_BN_CLICKED(IDC_CASSIMPTARG_BAS, OnTypeChange) - ON_BN_CLICKED(IDC_CASSIMPTARG_INT, OnTypeChange) - ON_BN_CLICKED(IDC_CASSIMPTARG_BIN, OnTypeChange) - ON_EN_CHANGE(IDC_CASSIMPTARG_BINADDR, OnAddrChange) + ON_BN_CLICKED(IDC_CASSIMPTARG_BAS, OnTypeChange) + ON_BN_CLICKED(IDC_CASSIMPTARG_INT, OnTypeChange) + ON_BN_CLICKED(IDC_CASSIMPTARG_BIN, OnTypeChange) + ON_EN_CHANGE(IDC_CASSIMPTARG_BINADDR, OnAddrChange) END_MESSAGE_MAP() /* @@ -24,25 +24,25 @@ END_MESSAGE_MAP() BOOL CassImpTargetDialog::OnInitDialog(void) { - /* substitute our replacement edit control */ - fAddrEdit.ReplaceDlgCtrl(this, IDC_CASSIMPTARG_BINADDR); - fAddrEdit.SetProperties(MyEdit::kCapsOnly | MyEdit::kHexOnly); + /* substitute our replacement edit control */ + fAddrEdit.ReplaceDlgCtrl(this, IDC_CASSIMPTARG_BINADDR); + fAddrEdit.SetProperties(MyEdit::kCapsOnly | MyEdit::kHexOnly); - //CWnd* pWnd; - CEdit* pEdit; + //CWnd* pWnd; + CEdit* pEdit; - pEdit = (CEdit*) GetDlgItem(IDC_CASSIMPTARG_BINADDR); - pEdit->SetLimitText(4); // 4-digit hex value + pEdit = (CEdit*) GetDlgItem(IDC_CASSIMPTARG_BINADDR); + pEdit->SetLimitText(4); // 4-digit hex value - /* do the DDX thing, then update computed fields */ - CDialog::OnInitDialog(); - OnTypeChange(); - OnAddrChange(); + /* do the DDX thing, then update computed fields */ + CDialog::OnInitDialog(); + OnTypeChange(); + OnAddrChange(); - pEdit = (CEdit*) GetDlgItem(IDC_CASSIMPTARG_FILENAME); - pEdit->SetSel(0, -1); - pEdit->SetFocus(); - return FALSE; // don't change the focus + pEdit = (CEdit*) GetDlgItem(IDC_CASSIMPTARG_FILENAME); + pEdit->SetSel(0, -1); + pEdit->SetFocus(); + return FALSE; // don't change the focus } /* @@ -51,36 +51,36 @@ CassImpTargetDialog::OnInitDialog(void) void CassImpTargetDialog::DoDataExchange(CDataExchange* pDX) { - DDX_Radio(pDX, IDC_CASSIMPTARG_BAS, fFileTypeIndex); - DDX_Text(pDX, IDC_CASSIMPTARG_FILENAME, fFileName); + DDX_Radio(pDX, IDC_CASSIMPTARG_BAS, fFileTypeIndex); + DDX_Text(pDX, IDC_CASSIMPTARG_FILENAME, fFileName); - if (pDX->m_bSaveAndValidate) { - CString appName; - appName.LoadString(IDS_MB_APP_NAME); + if (pDX->m_bSaveAndValidate) { + CString appName; + appName.LoadString(IDS_MB_APP_NAME); - if (fFileTypeIndex == kTypeBIN) { - if (GetStartAddr() < 0) { - MessageBox("The address field must be a valid 4-digit " - " hexadecimal number.", - appName, MB_OK); - pDX->Fail(); - return; - } - fStartAddr = (unsigned short) GetStartAddr(); - } - if (fFileName.IsEmpty()) { - MessageBox("You must enter a filename.", appName, MB_OK); - pDX->Fail(); - return; - } - } else { - CWnd* pWnd; - CString tmpStr; + if (fFileTypeIndex == kTypeBIN) { + if (GetStartAddr() < 0) { + MessageBox("The address field must be a valid 4-digit " + " hexadecimal number.", + appName, MB_OK); + pDX->Fail(); + return; + } + fStartAddr = (unsigned short) GetStartAddr(); + } + if (fFileName.IsEmpty()) { + MessageBox("You must enter a filename.", appName, MB_OK); + pDX->Fail(); + return; + } + } else { + CWnd* pWnd; + CString tmpStr; - pWnd = GetDlgItem(IDC_CASSIMPTARG_BINADDR); - tmpStr.Format("%04X", fStartAddr); - pWnd->SetWindowText(tmpStr); - } + pWnd = GetDlgItem(IDC_CASSIMPTARG_BINADDR); + tmpStr.Format("%04X", fStartAddr); + pWnd->SetWindowText(tmpStr); + } } /* @@ -90,13 +90,13 @@ CassImpTargetDialog::DoDataExchange(CDataExchange* pDX) void CassImpTargetDialog::OnTypeChange(void) { - CButton* pButton; - CWnd* pWnd; + CButton* pButton; + CWnd* pWnd; - pButton = (CButton*) GetDlgItem(IDC_CASSIMPTARG_BIN); - pWnd = GetDlgItem(IDC_CASSIMPTARG_BINADDR); + pButton = (CButton*) GetDlgItem(IDC_CASSIMPTARG_BIN); + pWnd = GetDlgItem(IDC_CASSIMPTARG_BINADDR); - pWnd->EnableWindow(pButton->GetCheck() == BST_CHECKED); + pWnd->EnableWindow(pButton->GetCheck() == BST_CHECKED); } /* @@ -105,18 +105,18 @@ CassImpTargetDialog::OnTypeChange(void) void CassImpTargetDialog::OnAddrChange(void) { - CWnd* pWnd; - CString tmpStr; - long val; + CWnd* pWnd; + CString tmpStr; + long val; - val = GetStartAddr(); - if (val < 0) - val = 0; + val = GetStartAddr(); + if (val < 0) + val = 0; - tmpStr.Format(".%04X", val + fFileLength-1); + tmpStr.Format(".%04X", val + fFileLength-1); - pWnd = GetDlgItem(IDC_CASSIMPTARG_RANGE); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_CASSIMPTARG_RANGE); + pWnd->SetWindowText(tmpStr); } /* @@ -128,27 +128,27 @@ CassImpTargetDialog::OnAddrChange(void) long CassImpTargetDialog::GetStartAddr(void) const { - CWnd* pWnd = GetDlgItem(IDC_CASSIMPTARG_BINADDR); - ASSERT(pWnd != nil); + CWnd* pWnd = GetDlgItem(IDC_CASSIMPTARG_BINADDR); + ASSERT(pWnd != nil); - CString aux; - pWnd->GetWindowText(aux); + CString aux; + pWnd->GetWindowText(aux); - const char* str = aux; - char* end; - long val; + const char* str = aux; + char* end; + long val; - if (str[0] == '\0') { - WMSG0(" HEY: blank addr, returning -1\n"); - return -1; - } - val = strtoul(aux, &end, 16); - if (end != str + strlen(str)) { - WMSG1(" HEY: found some garbage in addr '%s', returning -1\n", - (LPCTSTR) aux); - return -1; - } - return val; + if (str[0] == '\0') { + WMSG0(" HEY: blank addr, returning -1\n"); + return -1; + } + val = strtoul(aux, &end, 16); + if (end != str + strlen(str)) { + WMSG1(" HEY: found some garbage in addr '%s', returning -1\n", + (LPCTSTR) aux); + return -1; + } + return val; } /* @@ -157,14 +157,14 @@ CassImpTargetDialog::GetStartAddr(void) const long CassImpTargetDialog::GetFileType(void) const { - switch (fFileTypeIndex) { - case kTypeBIN: return kFileTypeBIN; - case kTypeINT: return kFileTypeINT; - case kTypeBAS: return kFileTypeBAS; - default: - assert(false); - return -1; - } + switch (fFileTypeIndex) { + case kTypeBIN: return kFileTypeBIN; + case kTypeINT: return kFileTypeINT; + case kTypeBAS: return kFileTypeBAS; + default: + assert(false); + return -1; + } } /* @@ -173,12 +173,12 @@ CassImpTargetDialog::GetFileType(void) const void CassImpTargetDialog::SetFileType(long type) { - switch (type) { - case kFileTypeBIN: fFileTypeIndex = kTypeBIN; break; - case kFileTypeINT: fFileTypeIndex = kTypeINT; break; - case kFileTypeBAS: fFileTypeIndex = kTypeBAS; break; - default: - assert(false); - break; - } + switch (type) { + case kFileTypeBIN: fFileTypeIndex = kTypeBIN; break; + case kFileTypeINT: fFileTypeIndex = kTypeINT; break; + case kFileTypeBAS: fFileTypeIndex = kTypeBAS; break; + default: + assert(false); + break; + } } diff --git a/app/CassImpTargetDialog.h b/app/CassImpTargetDialog.h index 262a873..5c31d7a 100644 --- a/app/CassImpTargetDialog.h +++ b/app/CassImpTargetDialog.h @@ -18,35 +18,35 @@ */ class CassImpTargetDialog : public CDialog { public: - CassImpTargetDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_CASSIMPTARGET, pParentWnd), - fStartAddr(0x0800), - fFileTypeIndex(0) - {} - virtual ~CassImpTargetDialog(void) {} + CassImpTargetDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_CASSIMPTARGET, pParentWnd), + fStartAddr(0x0800), + fFileTypeIndex(0) + {} + virtual ~CassImpTargetDialog(void) {} - long GetFileType(void) const; - void SetFileType(long type); + long GetFileType(void) const; + void SetFileType(long type); - CString fFileName; - unsigned short fStartAddr; // start addr for BIN files - long fFileLength; // used for BIN display + CString fFileName; + unsigned short fStartAddr; // start addr for BIN files + long fFileLength; // used for BIN display private: - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); - afx_msg void OnTypeChange(void); - afx_msg void OnAddrChange(void); + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); + afx_msg void OnTypeChange(void); + afx_msg void OnAddrChange(void); - MyEdit fAddrEdit; // replacement edit ctrl for addr field + MyEdit fAddrEdit; // replacement edit ctrl for addr field - long GetStartAddr(void) const; + long GetStartAddr(void) const; - /* for radio button; enum must match order of controls in dialog */ - enum { kTypeBAS = 0, kTypeINT, kTypeBIN }; - int fFileTypeIndex; + /* for radio button; enum must match order of controls in dialog */ + enum { kTypeBAS = 0, kTypeINT, kTypeBIN }; + int fFileTypeIndex; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__CASSIMPTARGETDIALOG__*/ diff --git a/app/CassetteDialog.cpp b/app/CassetteDialog.cpp index 6ce5f3c..457c7d4 100644 --- a/app/CassetteDialog.cpp +++ b/app/CassetteDialog.cpp @@ -12,15 +12,15 @@ #include "HelpTopics.h" #include "GenericArchive.h" #include "Main.h" -#include "../diskimg/DiskImg.h" // need kStorageSeedling +#include "../diskimg/DiskImg.h" // need kStorageSeedling #include /* * Tape layout: - * 10.6 seconds of 770Hz (8192 cycles * 1300 usec/cycle) - * 1/2 cycle at 400 usec/cycle, followed by 1/2 cycle at 500 usec/cycle - * Data, using 500 usec/cycle for '0' and 1000 usec/cycle for '1' - * There is no "end" marker, except perhaps for the absence of data + * 10.6 seconds of 770Hz (8192 cycles * 1300 usec/cycle) + * 1/2 cycle at 400 usec/cycle, followed by 1/2 cycle at 500 usec/cycle + * Data, using 500 usec/cycle for '0' and 1000 usec/cycle for '1' + * There is no "end" marker, except perhaps for the absence of data * * The last byte of data is an XOR checksum (seeded with 0xff). * @@ -44,12 +44,12 @@ * I'm not sure, and in the end it doesn't really matter. * * Typical instructions for loading data from tape look like this: - * - Type "LOAD" or "xxxx.xxxxR", but don't hit . - * - Play tape until you here the tone. - * - Immediately hit stop. - * - Plug the cable from the Apple II into the tape player. - * - Hit "play" on the recorder, then immediately hit . - * - When the Apple II beeps, it's done. Stop the tape. + * - Type "LOAD" or "xxxx.xxxxR", but don't hit . + * - Play tape until you here the tone. + * - Immediately hit stop. + * - Plug the cable from the Apple II into the tape player. + * - Hit "play" on the recorder, then immediately hit . + * - When the Apple II beeps, it's done. Stop the tape. * * How quickly do we need to sample? The highest frequency we expect to * find is 2KHz, so anything over 4KHz should be sufficient. However, we @@ -254,17 +254,17 @@ FD0B: 60 753 RTS /* * ========================================================================== - * CassetteDialog + * CassetteDialog * ========================================================================== */ BEGIN_MESSAGE_MAP(CassetteDialog, CDialog) - ON_NOTIFY(LVN_ITEMCHANGED, IDC_CASSETTE_LIST, OnListChange) - ON_NOTIFY(NM_DBLCLK, IDC_CASSETTE_LIST, OnListDblClick) - //ON_MESSAGE(WMU_DIALOG_READY, OnDialogReady) - ON_COMMAND(IDC_IMPORT_CHUNK, OnImport) - ON_COMMAND(IDHELP, OnHelp) - ON_CBN_SELCHANGE(IDC_CASSETTE_ALG, OnAlgorithmChange) + ON_NOTIFY(LVN_ITEMCHANGED, IDC_CASSETTE_LIST, OnListChange) + ON_NOTIFY(NM_DBLCLK, IDC_CASSETTE_LIST, OnListDblClick) + //ON_MESSAGE(WMU_DIALOG_READY, OnDialogReady) + ON_COMMAND(IDC_IMPORT_CHUNK, OnImport) + ON_COMMAND(IDHELP, OnHelp) + ON_CBN_SELCHANGE(IDC_CASSETTE_ALG, OnAlgorithmChange) END_MESSAGE_MAP() @@ -274,77 +274,77 @@ END_MESSAGE_MAP() BOOL CassetteDialog::OnInitDialog(void) { - CRect rect; - const Preferences* pPreferences = GET_PREFERENCES(); + CRect rect; + const Preferences* pPreferences = GET_PREFERENCES(); - CDialog::OnInitDialog(); // does DDX init + CDialog::OnInitDialog(); // does DDX init - CWnd* pWnd; - pWnd = GetDlgItem(IDC_IMPORT_CHUNK); - pWnd->EnableWindow(FALSE); + CWnd* pWnd; + pWnd = GetDlgItem(IDC_IMPORT_CHUNK); + pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_CASSETTE_INPUT); - pWnd->SetWindowText(fFileName); + pWnd = GetDlgItem(IDC_CASSETTE_INPUT); + pWnd->SetWindowText(fFileName); - /* prep the combo box */ - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_CASSETTE_ALG); - ASSERT(pCombo != nil); - int defaultAlg = pPreferences->GetPrefLong(kPrCassetteAlgorithm); - if (defaultAlg > CassetteData::kAlgorithmMIN && - defaultAlg < CassetteData::kAlgorithmMAX) - { - pCombo->SetCurSel(defaultAlg); - } else { - WMSG1("GLITCH: invalid defaultAlg in prefs (%d)\n", defaultAlg); - pCombo->SetCurSel(CassetteData::kAlgorithmZero); - } - fAlgorithm = (CassetteData::Algorithm) defaultAlg; + /* prep the combo box */ + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_CASSETTE_ALG); + ASSERT(pCombo != nil); + int defaultAlg = pPreferences->GetPrefLong(kPrCassetteAlgorithm); + if (defaultAlg > CassetteData::kAlgorithmMIN && + defaultAlg < CassetteData::kAlgorithmMAX) + { + pCombo->SetCurSel(defaultAlg); + } else { + WMSG1("GLITCH: invalid defaultAlg in prefs (%d)\n", defaultAlg); + pCombo->SetCurSel(CassetteData::kAlgorithmZero); + } + fAlgorithm = (CassetteData::Algorithm) defaultAlg; - /* - * Prep the listview control. - * - * Columns: - * [icon] Index | Format | Length | Checksum OK - */ - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_CASSETTE_LIST); - ASSERT(pListView != nil); - ListView_SetExtendedListViewStyleEx(pListView->m_hWnd, - LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); + /* + * Prep the listview control. + * + * Columns: + * [icon] Index | Format | Length | Checksum OK + */ + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_CASSETTE_LIST); + ASSERT(pListView != nil); + ListView_SetExtendedListViewStyleEx(pListView->m_hWnd, + LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); - int width0, width1, width2, width3, width4; + int width0, width1, width2, width3, width4; - pListView->GetClientRect(&rect); - width0 = pListView->GetStringWidth("XXIndexX"); - width1 = pListView->GetStringWidth("XXFormatXmmmmmmmmmmmmmm"); - width2 = pListView->GetStringWidth("XXLengthXm"); - width3 = pListView->GetStringWidth("XXChecksumXm"); - width4 = pListView->GetStringWidth("XXStart sampleX"); - //width5 = pListView->GetStringWidth("XXEnd sampleX"); + pListView->GetClientRect(&rect); + width0 = pListView->GetStringWidth("XXIndexX"); + width1 = pListView->GetStringWidth("XXFormatXmmmmmmmmmmmmmm"); + width2 = pListView->GetStringWidth("XXLengthXm"); + width3 = pListView->GetStringWidth("XXChecksumXm"); + width4 = pListView->GetStringWidth("XXStart sampleX"); + //width5 = pListView->GetStringWidth("XXEnd sampleX"); - pListView->InsertColumn(0, "Index", LVCFMT_LEFT, width0); - pListView->InsertColumn(1, "Format", LVCFMT_LEFT, width1); - pListView->InsertColumn(2, "Length", LVCFMT_LEFT, width2); - pListView->InsertColumn(3, "Checksum", LVCFMT_LEFT, width3); - pListView->InsertColumn(4, "Start sample", LVCFMT_LEFT, width4); - pListView->InsertColumn(5, "End sample", LVCFMT_LEFT, - rect.Width() - (width0+width1+width2+width3+width4) - /*- ::GetSystemMetrics(SM_CXVSCROLL)*/ ); + pListView->InsertColumn(0, "Index", LVCFMT_LEFT, width0); + pListView->InsertColumn(1, "Format", LVCFMT_LEFT, width1); + pListView->InsertColumn(2, "Length", LVCFMT_LEFT, width2); + pListView->InsertColumn(3, "Checksum", LVCFMT_LEFT, width3); + pListView->InsertColumn(4, "Start sample", LVCFMT_LEFT, width4); + pListView->InsertColumn(5, "End sample", LVCFMT_LEFT, + rect.Width() - (width0+width1+width2+width3+width4) + /*- ::GetSystemMetrics(SM_CXVSCROLL)*/ ); - /* add images for list; this MUST be loaded before header images */ -// LoadListImages(); -// pListView->SetImageList(&fListImageList, LVSIL_SMALL); + /* add images for list; this MUST be loaded before header images */ +// LoadListImages(); +// pListView->SetImageList(&fListImageList, LVSIL_SMALL); -// LoadList(); +// LoadList(); - CenterWindow(); + CenterWindow(); - //int cc = PostMessage(WMU_DIALOG_READY, 0, 0); - //ASSERT(cc != 0); + //int cc = PostMessage(WMU_DIALOG_READY, 0, 0); + //ASSERT(cc != 0); - if (!AnalyzeWAV()) - OnCancel(); + if (!AnalyzeWAV()) + OnCancel(); - return TRUE; + return TRUE; } #if 0 @@ -354,8 +354,8 @@ CassetteDialog::OnInitDialog(void) LONG CassetteDialog::OnDialogReady(UINT, LONG) { - //AnalyzeWAV(); - return 0; + //AnalyzeWAV(); + return 0; } #endif @@ -366,12 +366,12 @@ CassetteDialog::OnDialogReady(UINT, LONG) void CassetteDialog::OnListChange(NMHDR*, LRESULT* pResult) { - WMSG0("List change\n"); - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_CASSETTE_LIST); - CButton* pButton = (CButton*) GetDlgItem(IDC_IMPORT_CHUNK); - pButton->EnableWindow(pListView->GetSelectedCount() != 0); + WMSG0("List change\n"); + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_CASSETTE_LIST); + CButton* pButton = (CButton*) GetDlgItem(IDC_IMPORT_CHUNK); + pButton->EnableWindow(pListView->GetSelectedCount() != 0); - *pResult = 0; + *pResult = 0; } @@ -381,13 +381,13 @@ CassetteDialog::OnListChange(NMHDR*, LRESULT* pResult) void CassetteDialog::OnListDblClick(NMHDR* pNotifyStruct, LRESULT* pResult) { - WMSG0("Double click!\n"); - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_CASSETTE_LIST); + WMSG0("Double click!\n"); + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_CASSETTE_LIST); - if (pListView->GetSelectedCount() == 1) - OnImport(); + if (pListView->GetSelectedCount() == 1) + OnImport(); - *pResult = 0; + *pResult = 0; } /* @@ -396,11 +396,11 @@ CassetteDialog::OnListDblClick(NMHDR* pNotifyStruct, LRESULT* pResult) void CassetteDialog::OnAlgorithmChange(void) { - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_CASSETTE_ALG); - ASSERT(pCombo != nil); - WMSG1("+++ SELECTION IS NOW %d\n", pCombo->GetCurSel()); - fAlgorithm = (CassetteData::Algorithm) pCombo->GetCurSel(); - AnalyzeWAV(); + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_CASSETTE_ALG); + ASSERT(pCombo != nil); + WMSG1("+++ SELECTION IS NOW %d\n", pCombo->GetCurSel()); + fAlgorithm = (CassetteData::Algorithm) pCombo->GetCurSel(); + AnalyzeWAV(); } /* @@ -409,7 +409,7 @@ CassetteDialog::OnAlgorithmChange(void) void CassetteDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_IMPORT_CASSETTE, HELP_CONTEXT); + WinHelp(HELP_TOPIC_IMPORT_CASSETTE, HELP_CONTEXT); } /* @@ -419,71 +419,71 @@ CassetteDialog::OnHelp(void) void CassetteDialog::OnImport(void) { - /* - * Figure out which item they have selected. - */ - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_CASSETTE_LIST); - ASSERT(pListView != nil); - assert(pListView->GetSelectedCount() == 1); + /* + * Figure out which item they have selected. + */ + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_CASSETTE_LIST); + ASSERT(pListView != nil); + assert(pListView->GetSelectedCount() == 1); - POSITION posn; - posn = pListView->GetFirstSelectedItemPosition(); - if (posn == nil) { - ASSERT(false); - return; - } - int idx = pListView->GetNextSelectedItem(posn); + POSITION posn; + posn = pListView->GetFirstSelectedItemPosition(); + if (posn == nil) { + ASSERT(false); + return; + } + int idx = pListView->GetNextSelectedItem(posn); - /* - * Set up the import dialog. - */ - CassImpTargetDialog impDialog(this); + /* + * Set up the import dialog. + */ + CassImpTargetDialog impDialog(this); - impDialog.fFileName = "From.Tape"; - impDialog.fFileLength = fDataArray[idx].GetDataLen(); - impDialog.SetFileType(fDataArray[idx].GetFileType()); + impDialog.fFileName = "From.Tape"; + impDialog.fFileLength = fDataArray[idx].GetDataLen(); + impDialog.SetFileType(fDataArray[idx].GetFileType()); - if (impDialog.DoModal() != IDOK) - return; + if (impDialog.DoModal() != IDOK) + return; - /* - * Write the file to the currently-open archive. - */ - GenericArchive::FileDetails details; + /* + * Write the file to the currently-open archive. + */ + GenericArchive::FileDetails details; - details.entryKind = GenericArchive::FileDetails::kFileKindDataFork; - details.origName = "Cassette WAV"; - details.storageName = impDialog.fFileName; - details.access = 0xe3; // unlocked, backup bit set - details.fileType = impDialog.GetFileType(); - if (details.fileType == kFileTypeBIN) - details.extraType = impDialog.fStartAddr; - else if (details.fileType == kFileTypeBAS) - details.extraType = 0x0801; - else - details.extraType = 0x0000; - details.storageType = DiskFS::kStorageSeedling; - time_t now = time(nil); - GenericArchive::UNIXTimeToDateTime(&now, &details.createWhen); - GenericArchive::UNIXTimeToDateTime(&now, &details.archiveWhen); + details.entryKind = GenericArchive::FileDetails::kFileKindDataFork; + details.origName = "Cassette WAV"; + details.storageName = impDialog.fFileName; + details.access = 0xe3; // unlocked, backup bit set + details.fileType = impDialog.GetFileType(); + if (details.fileType == kFileTypeBIN) + details.extraType = impDialog.fStartAddr; + else if (details.fileType == kFileTypeBAS) + details.extraType = 0x0801; + else + details.extraType = 0x0000; + details.storageType = DiskFS::kStorageSeedling; + time_t now = time(nil); + GenericArchive::UNIXTimeToDateTime(&now, &details.createWhen); + GenericArchive::UNIXTimeToDateTime(&now, &details.archiveWhen); - CString errMsg; + CString errMsg; - fDirty = true; - if (!MainWindow::SaveToArchive(&details, fDataArray[idx].GetDataBuf(), - fDataArray[idx].GetDataLen(), nil, -1, /*ref*/errMsg, this)) - { - goto bail; - } + fDirty = true; + if (!MainWindow::SaveToArchive(&details, fDataArray[idx].GetDataBuf(), + fDataArray[idx].GetDataLen(), nil, -1, /*ref*/errMsg, this)) + { + goto bail; + } bail: - if (!errMsg.IsEmpty()) { - CString msg; - msg.Format("Unable to import file: %s.", (const char *) errMsg); - ShowFailureMsg(this, msg, IDS_FAILED); - return; - } + if (!errMsg.IsEmpty()) { + CString msg; + msg.Format("Unable to import file: %s.", (const char *) errMsg); + ShowFailureMsg(this, msg, IDS_FAILED); + return; + } } @@ -495,55 +495,55 @@ bail: bool CassetteDialog::AnalyzeWAV(void) { - SoundFile soundFile; - CWaitCursor waitc; - CListCtrl* pListCtrl = (CListCtrl*) GetDlgItem(IDC_CASSETTE_LIST); - CString errMsg; - long sampleOffset; - int idx; + SoundFile soundFile; + CWaitCursor waitc; + CListCtrl* pListCtrl = (CListCtrl*) GetDlgItem(IDC_CASSETTE_LIST); + CString errMsg; + long sampleOffset; + int idx; - if (soundFile.Create(fFileName, &errMsg) != 0) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - return false; - } + if (soundFile.Create(fFileName, &errMsg) != 0) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + return false; + } - const WAVEFORMATEX* pFormat = soundFile.GetWaveFormat(); - if (pFormat->nChannels < 1 || pFormat->nChannels > 2 || - (pFormat->wBitsPerSample != 8 && pFormat->wBitsPerSample != 16)) - { - errMsg.Format("Unexpected PCM format (%d channels, %d bits/sample)", - pFormat->nChannels, pFormat->wBitsPerSample); - ShowFailureMsg(this, errMsg, IDS_FAILED); - return false; - } - if (soundFile.GetDataLen() % soundFile.GetBPS() != 0) { - errMsg.Format("Unexpected sound data length (%ld, samples are %d bytes)", - soundFile.GetDataLen(), soundFile.GetBPS()); - ShowFailureMsg(this, errMsg, IDS_FAILED); - return false; - } + const WAVEFORMATEX* pFormat = soundFile.GetWaveFormat(); + if (pFormat->nChannels < 1 || pFormat->nChannels > 2 || + (pFormat->wBitsPerSample != 8 && pFormat->wBitsPerSample != 16)) + { + errMsg.Format("Unexpected PCM format (%d channels, %d bits/sample)", + pFormat->nChannels, pFormat->wBitsPerSample); + ShowFailureMsg(this, errMsg, IDS_FAILED); + return false; + } + if (soundFile.GetDataLen() % soundFile.GetBPS() != 0) { + errMsg.Format("Unexpected sound data length (%ld, samples are %d bytes)", + soundFile.GetDataLen(), soundFile.GetBPS()); + ShowFailureMsg(this, errMsg, IDS_FAILED); + return false; + } - pListCtrl->DeleteAllItems(); + pListCtrl->DeleteAllItems(); - sampleOffset = 0; - for (idx = 0; idx < kMaxRecordings; idx++) { - long fileType; - bool result; + sampleOffset = 0; + for (idx = 0; idx < kMaxRecordings; idx++) { + long fileType; + bool result; - result = fDataArray[idx].Scan(&soundFile, fAlgorithm, &sampleOffset); - if (!result) - break; + result = fDataArray[idx].Scan(&soundFile, fAlgorithm, &sampleOffset); + if (!result) + break; - AddEntry(idx, pListCtrl, &fileType); - fDataArray[idx].SetFileType(fileType); - } + AddEntry(idx, pListCtrl, &fileType); + fDataArray[idx].SetFileType(fileType); + } - if (idx == 0) { - WMSG0("No Apple II files found\n"); - /* that's okay, just show the empty list */ - } + if (idx == 0) { + WMSG0("No Apple II files found\n"); + /* that's okay, just show the empty list */ + } - return true; + return true; } /* @@ -554,54 +554,54 @@ CassetteDialog::AnalyzeWAV(void) void CassetteDialog::AddEntry(int idx, CListCtrl* pListCtrl, long* pFileType) { - CString tmpStr; - const CassetteData* pData = &fDataArray[idx]; - const unsigned char* pDataBuf = pData->GetDataBuf(); + CString tmpStr; + const CassetteData* pData = &fDataArray[idx]; + const unsigned char* pDataBuf = pData->GetDataBuf(); - ASSERT(pDataBuf != nil); + ASSERT(pDataBuf != nil); - tmpStr.Format("%d", idx); - pListCtrl->InsertItem(idx, tmpStr); + tmpStr.Format("%d", idx); + pListCtrl->InsertItem(idx, tmpStr); - *pFileType = kFileTypeBIN; - if (pData->GetDataLen() == 2) { - tmpStr.Format("Integer header ($%04X)", - pDataBuf[0] | pDataBuf[1] << 8); - } else if (pData->GetDataLen() == 3) { - tmpStr.Format("Applesoft header ($%04X $%02x)", - pDataBuf[0] | pDataBuf[1] << 8, pDataBuf[2]); - } else if (pData->GetDataLen() > 3 && idx > 0 && - fDataArray[idx-1].GetDataLen() == 2) - { - tmpStr = "Integer BASIC"; - *pFileType = kFileTypeINT; - } else if (pData->GetDataLen() > 3 && idx > 0 && - fDataArray[idx-1].GetDataLen() == 3) - { - tmpStr = "Applesoft BASIC"; - *pFileType = kFileTypeBAS; - } else { - tmpStr = "Binary"; - } - pListCtrl->SetItemText(idx, 1, tmpStr); - - tmpStr.Format("%d", pData->GetDataLen()); - pListCtrl->SetItemText(idx, 2, tmpStr); - if (pData->GetDataChkGood()) - tmpStr.Format("Good (0x%02x)", pData->GetDataChecksum()); - else - tmpStr.Format("BAD (0x%02x)", pData->GetDataChecksum()); - pListCtrl->SetItemText(idx, 3, tmpStr); - tmpStr.Format("%ld", pData->GetDataOffset()); - pListCtrl->SetItemText(idx, 4, tmpStr); - tmpStr.Format("%ld", pData->GetDataEndOffset()); - pListCtrl->SetItemText(idx, 5, tmpStr); + *pFileType = kFileTypeBIN; + if (pData->GetDataLen() == 2) { + tmpStr.Format("Integer header ($%04X)", + pDataBuf[0] | pDataBuf[1] << 8); + } else if (pData->GetDataLen() == 3) { + tmpStr.Format("Applesoft header ($%04X $%02x)", + pDataBuf[0] | pDataBuf[1] << 8, pDataBuf[2]); + } else if (pData->GetDataLen() > 3 && idx > 0 && + fDataArray[idx-1].GetDataLen() == 2) + { + tmpStr = "Integer BASIC"; + *pFileType = kFileTypeINT; + } else if (pData->GetDataLen() > 3 && idx > 0 && + fDataArray[idx-1].GetDataLen() == 3) + { + tmpStr = "Applesoft BASIC"; + *pFileType = kFileTypeBAS; + } else { + tmpStr = "Binary"; + } + pListCtrl->SetItemText(idx, 1, tmpStr); + + tmpStr.Format("%d", pData->GetDataLen()); + pListCtrl->SetItemText(idx, 2, tmpStr); + if (pData->GetDataChkGood()) + tmpStr.Format("Good (0x%02x)", pData->GetDataChecksum()); + else + tmpStr.Format("BAD (0x%02x)", pData->GetDataChecksum()); + pListCtrl->SetItemText(idx, 3, tmpStr); + tmpStr.Format("%ld", pData->GetDataOffset()); + pListCtrl->SetItemText(idx, 4, tmpStr); + tmpStr.Format("%ld", pData->GetDataEndOffset()); + pListCtrl->SetItemText(idx, 5, tmpStr); } /* * ========================================================================== - * CassetteData + * CassetteData * ========================================================================== */ @@ -614,150 +614,150 @@ CassetteDialog::AddEntry(int idx, CListCtrl* pListCtrl, long* pFileType) */ bool CassetteDialog::CassetteData::Scan(SoundFile* pSoundFile, Algorithm alg, - long* pStartOffset) + long* pStartOffset) { - const int kSampleChunkSize = 65536; // should be multiple of 4 - const WAVEFORMATEX* pFormat; - ScanState scanState; - long initialLen, dataLen, chunkLen, byteOffset; - long sampleStartIndex; - unsigned char* buf = nil; - float* sampleBuf = nil; - int bytesPerSample; - bool result = false; - unsigned char checkSum; - int outByteIndex, bitAcc; + const int kSampleChunkSize = 65536; // should be multiple of 4 + const WAVEFORMATEX* pFormat; + ScanState scanState; + long initialLen, dataLen, chunkLen, byteOffset; + long sampleStartIndex; + unsigned char* buf = nil; + float* sampleBuf = nil; + int bytesPerSample; + bool result = false; + unsigned char checkSum; + int outByteIndex, bitAcc; - bytesPerSample = pSoundFile->GetBPS(); - assert(bytesPerSample >= 1 && bytesPerSample <= 4); - assert(kSampleChunkSize % bytesPerSample == 0); - byteOffset = *pStartOffset; - initialLen = dataLen = pSoundFile->GetDataLen() - byteOffset; - sampleStartIndex = byteOffset/bytesPerSample; - WMSG4("CassetteData::Scan(off=%ld / %ld) len=%ld alg=%d\n", - byteOffset, sampleStartIndex, dataLen, alg); + bytesPerSample = pSoundFile->GetBPS(); + assert(bytesPerSample >= 1 && bytesPerSample <= 4); + assert(kSampleChunkSize % bytesPerSample == 0); + byteOffset = *pStartOffset; + initialLen = dataLen = pSoundFile->GetDataLen() - byteOffset; + sampleStartIndex = byteOffset/bytesPerSample; + WMSG4("CassetteData::Scan(off=%ld / %ld) len=%ld alg=%d\n", + byteOffset, sampleStartIndex, dataLen, alg); - pFormat = pSoundFile->GetWaveFormat(); + pFormat = pSoundFile->GetWaveFormat(); - buf = new unsigned char[kSampleChunkSize]; - sampleBuf = new float[kSampleChunkSize/bytesPerSample]; - if (fOutputBuf == nil) // alloc on first use - fOutputBuf = new unsigned char[kMaxFileLen]; - if (buf == nil || sampleBuf == nil || fOutputBuf == nil) { - WMSG0("Buffer alloc failed\n"); - goto bail; - } + buf = new unsigned char[kSampleChunkSize]; + sampleBuf = new float[kSampleChunkSize/bytesPerSample]; + if (fOutputBuf == nil) // alloc on first use + fOutputBuf = new unsigned char[kMaxFileLen]; + if (buf == nil || sampleBuf == nil || fOutputBuf == nil) { + WMSG0("Buffer alloc failed\n"); + goto bail; + } - memset(&scanState, 0, sizeof(scanState)); - scanState.algorithm = alg; - scanState.phase = kPhaseScanFor770Start; - scanState.mode = kModeInitial0; - scanState.positive = false; - scanState.usecPerSample = 1000000.0f / (float) pFormat->nSamplesPerSec; + memset(&scanState, 0, sizeof(scanState)); + scanState.algorithm = alg; + scanState.phase = kPhaseScanFor770Start; + scanState.mode = kModeInitial0; + scanState.positive = false; + scanState.usecPerSample = 1000000.0f / (float) pFormat->nSamplesPerSec; - checkSum = 0xff; - outByteIndex = 0; - bitAcc = 1; + checkSum = 0xff; + outByteIndex = 0; + bitAcc = 1; - /* - * Loop until done or out of data. - */ - while (dataLen > 0) { - int cc; + /* + * Loop until done or out of data. + */ + while (dataLen > 0) { + int cc; - chunkLen = dataLen; - if (chunkLen > kSampleChunkSize) - chunkLen = kSampleChunkSize; + chunkLen = dataLen; + if (chunkLen > kSampleChunkSize) + chunkLen = kSampleChunkSize; - cc = pSoundFile->ReadData(buf, byteOffset, chunkLen); - if (cc < 0) { - WMSG1("ReadData(%d) failed\n", chunkLen); - goto bail; - } + cc = pSoundFile->ReadData(buf, byteOffset, chunkLen); + if (cc < 0) { + WMSG1("ReadData(%d) failed\n", chunkLen); + goto bail; + } - ConvertSamplesToReal(pFormat, buf, chunkLen, sampleBuf); + ConvertSamplesToReal(pFormat, buf, chunkLen, sampleBuf); - for (int i = 0; i < chunkLen / bytesPerSample; i++) { - int bitVal; - if (ProcessSample(sampleBuf[i], sampleStartIndex + i, - &scanState, &bitVal)) - { - if (outByteIndex >= kMaxFileLen) { - WMSG0("Cassette data overflow\n"); - scanState.phase = kPhaseEndReached; - } else { - /* output a bit, shifting until bit 8 lights up */ - assert(bitVal == 0 || bitVal == 1); - bitAcc = (bitAcc << 1) | bitVal; - if (bitAcc > 0xff) { - fOutputBuf[outByteIndex++] = (unsigned char) bitAcc; - checkSum ^= (unsigned char) bitAcc; - bitAcc = 1; - } - } - } - if (scanState.phase == kPhaseEndReached) { - dataLen -= i * bytesPerSample; - break; - } - } - if (scanState.phase == kPhaseEndReached) - break; + for (int i = 0; i < chunkLen / bytesPerSample; i++) { + int bitVal; + if (ProcessSample(sampleBuf[i], sampleStartIndex + i, + &scanState, &bitVal)) + { + if (outByteIndex >= kMaxFileLen) { + WMSG0("Cassette data overflow\n"); + scanState.phase = kPhaseEndReached; + } else { + /* output a bit, shifting until bit 8 lights up */ + assert(bitVal == 0 || bitVal == 1); + bitAcc = (bitAcc << 1) | bitVal; + if (bitAcc > 0xff) { + fOutputBuf[outByteIndex++] = (unsigned char) bitAcc; + checkSum ^= (unsigned char) bitAcc; + bitAcc = 1; + } + } + } + if (scanState.phase == kPhaseEndReached) { + dataLen -= i * bytesPerSample; + break; + } + } + if (scanState.phase == kPhaseEndReached) + break; - dataLen -= chunkLen; - byteOffset += chunkLen; - sampleStartIndex += chunkLen / bytesPerSample; - } + dataLen -= chunkLen; + byteOffset += chunkLen; + sampleStartIndex += chunkLen / bytesPerSample; + } - switch (scanState.phase) { - case kPhaseScanFor770Start: - case kPhaseScanning770: - // expected case for trailing part of file - WMSG0("Scan ended while searching for 770\n"); - goto bail; - case kPhaseScanForShort0: - case kPhaseShort0B: - WMSG0("Scan ended while searching for short 0/0B\n"); - //DebugBreak(); // unusual - goto bail; - case kPhaseReadData: - WMSG0("Scan ended while reading data\n"); - //DebugBreak(); // truncated WAV file? - goto bail; - case kPhaseEndReached: - WMSG0("Scan found end\n"); - // winner! - break; - default: - WMSG1("Unknown phase %d\n", scanState.phase); - assert(false); - goto bail; - } + switch (scanState.phase) { + case kPhaseScanFor770Start: + case kPhaseScanning770: + // expected case for trailing part of file + WMSG0("Scan ended while searching for 770\n"); + goto bail; + case kPhaseScanForShort0: + case kPhaseShort0B: + WMSG0("Scan ended while searching for short 0/0B\n"); + //DebugBreak(); // unusual + goto bail; + case kPhaseReadData: + WMSG0("Scan ended while reading data\n"); + //DebugBreak(); // truncated WAV file? + goto bail; + case kPhaseEndReached: + WMSG0("Scan found end\n"); + // winner! + break; + default: + WMSG1("Unknown phase %d\n", scanState.phase); + assert(false); + goto bail; + } - WMSG3("*** Output %d bytes (bitAcc=0x%02x, checkSum=0x%02x)\n", - outByteIndex, bitAcc, checkSum); + WMSG3("*** Output %d bytes (bitAcc=0x%02x, checkSum=0x%02x)\n", + outByteIndex, bitAcc, checkSum); - if (outByteIndex == 0) { - fOutputLen = 0; - fChecksum = 0x00; - fChecksumGood = false; - } else { - fOutputLen = outByteIndex-1; - fChecksum = fOutputBuf[outByteIndex-1]; - fChecksumGood = (checkSum == 0x00); - } - fStartSample = scanState.dataStart; - fEndSample = scanState.dataEnd; + if (outByteIndex == 0) { + fOutputLen = 0; + fChecksum = 0x00; + fChecksumGood = false; + } else { + fOutputLen = outByteIndex-1; + fChecksum = fOutputBuf[outByteIndex-1]; + fChecksumGood = (checkSum == 0x00); + } + fStartSample = scanState.dataStart; + fEndSample = scanState.dataEnd; - /* we're done with this file; advance the start offset */ - *pStartOffset = *pStartOffset + (initialLen - dataLen); + /* we're done with this file; advance the start offset */ + *pStartOffset = *pStartOffset + (initialLen - dataLen); - result = true; + result = true; bail: - delete[] buf; - delete[] sampleBuf; - return result; + delete[] buf; + delete[] sampleBuf; + return result; } /* @@ -767,63 +767,63 @@ bail: */ void CassetteDialog::CassetteData::ConvertSamplesToReal(const WAVEFORMATEX* pFormat, - const unsigned char* buf, long chunkLen, float* sampleBuf) + const unsigned char* buf, long chunkLen, float* sampleBuf) { - int bps = ((pFormat->wBitsPerSample+7)/8) * pFormat->nChannels; - int bitsPerSample = pFormat->wBitsPerSample; - int offset = 0; + int bps = ((pFormat->wBitsPerSample+7)/8) * pFormat->nChannels; + int bitsPerSample = pFormat->wBitsPerSample; + int offset = 0; - assert(chunkLen % bps == 0); + assert(chunkLen % bps == 0); - if (bitsPerSample == 8) { - while (chunkLen > 0) { - *sampleBuf++ = (*buf - 128) / 128.0f; - //WMSG3("Sample8(%5d)=%d float=%.3f\n", offset, *buf, *(sampleBuf-1)); - //offset++; - buf += bps; - chunkLen -= bps; - } - } else if (bitsPerSample == 16) { - while (chunkLen > 0) { - short sample = *buf | *(buf+1) << 8; - *sampleBuf++ = sample / 32768.0f; - //WMSG3("Sample16(%5d)=%d float=%.3f\n", offset, sample, *(sampleBuf-1)); - //offset++; - buf += bps; - chunkLen -= bps; - } - } else { - assert(false); - } + if (bitsPerSample == 8) { + while (chunkLen > 0) { + *sampleBuf++ = (*buf - 128) / 128.0f; + //WMSG3("Sample8(%5d)=%d float=%.3f\n", offset, *buf, *(sampleBuf-1)); + //offset++; + buf += bps; + chunkLen -= bps; + } + } else if (bitsPerSample == 16) { + while (chunkLen > 0) { + short sample = *buf | *(buf+1) << 8; + *sampleBuf++ = sample / 32768.0f; + //WMSG3("Sample16(%5d)=%d float=%.3f\n", offset, sample, *(sampleBuf-1)); + //offset++; + buf += bps; + chunkLen -= bps; + } + } else { + assert(false); + } - //WMSG1("Conv %d\n", bitsPerSample); + //WMSG1("Conv %d\n", bitsPerSample); } /* width of 1/2 cycle in 770Hz lead-in */ -const float kLeadInHalfWidth = 650.0f; // usec +const float kLeadInHalfWidth = 650.0f; // usec /* max error when detecting 770Hz lead-in, in usec */ -const float kLeadInMaxError = 108.0f; // usec (542 - 758) +const float kLeadInMaxError = 108.0f; // usec (542 - 758) /* width of 1/2 cycle of "short 0" */ -const float kShortZeroHalfWidth = 200.0f; // usec +const float kShortZeroHalfWidth = 200.0f; // usec /* max error when detection short 0 */ -const float kShortZeroMaxError = 150.0f; // usec (50 - 350) +const float kShortZeroMaxError = 150.0f; // usec (50 - 350) /* width of 1/2 cycle of '0' */ -const float kZeroHalfWidth = 250.0f; // usec +const float kZeroHalfWidth = 250.0f; // usec /* max error when detecting '0' */ -const float kZeroMaxError = 94.0f; // usec +const float kZeroMaxError = 94.0f; // usec /* width of 1/2 cycle of '1' */ -const float kOneHalfWidth = 500.0f; // usec +const float kOneHalfWidth = 500.0f; // usec /* max error when detecting '1' */ -const float kOneMaxError = 94.0f; // usec +const float kOneMaxError = 94.0f; // usec /* after this many 770Hz half-cycles, start looking for short 0 */ -const long kLeadInHalfCycThreshold = 1540; // 1 full second +const long kLeadInHalfCycThreshold = 1540; // 1 full second /* amplitude must change by this much before we switch out of "peak" mode */ -const float kPeakThreshold = 0.2f; // 10% +const float kPeakThreshold = 0.2f; // 10% /* amplitude must change by at least this much to stay in "transition" mode */ -const float kTransMinDelta = 0.02f; // 1% +const float kTransMinDelta = 0.02f; // 1% /* kTransMinDelta happens over this range */ -const float kTransDeltaBase = 45.35f; // usec (1 sample at 22.05KHz) +const float kTransDeltaBase = 45.35f; // usec (1 sample at 22.05KHz) /* @@ -833,18 +833,18 @@ const float kTransDeltaBase = 45.35f; // usec (1 sample at 22.05KHz) */ bool CassetteDialog::CassetteData::ProcessSample(float sample, long sampleIndex, - ScanState* pScanState, int* pBitVal) + ScanState* pScanState, int* pBitVal) { - if (pScanState->algorithm == kAlgorithmZero) - return ProcessSampleZero(sample, sampleIndex, pScanState, pBitVal); - else if (pScanState->algorithm == kAlgorithmRoundPeak || - pScanState->algorithm == kAlgorithmSharpPeak || - pScanState->algorithm == kAlgorithmShallowPeak) - return ProcessSamplePeak(sample, sampleIndex, pScanState, pBitVal); - else { - assert(false); - return false; - } + if (pScanState->algorithm == kAlgorithmZero) + return ProcessSampleZero(sample, sampleIndex, pScanState, pBitVal); + else if (pScanState->algorithm == kAlgorithmRoundPeak || + pScanState->algorithm == kAlgorithmSharpPeak || + pScanState->algorithm == kAlgorithmShallowPeak) + return ProcessSamplePeak(sample, sampleIndex, pScanState, pBitVal); + else { + assert(false); + return false; + } } /* @@ -859,65 +859,65 @@ CassetteDialog::CassetteData::ProcessSample(float sample, long sampleIndex, */ bool CassetteDialog::CassetteData::ProcessSampleZero(float sample, long sampleIndex, - ScanState* pScanState, int* pBitVal) + ScanState* pScanState, int* pBitVal) { - long timeDelta; - bool crossedZero = false; - bool emitBit = false; + long timeDelta; + bool crossedZero = false; + bool emitBit = false; - /* - * Analyze the mode, changing to a new one when appropriate. - */ - switch (pScanState->mode) { - case kModeInitial0: - assert(pScanState->phase == kPhaseScanFor770Start); - pScanState->mode = kModeRunning; - break; - case kModeRunning: - if (pScanState->prevSample < 0.0f && sample >= 0.0f || - pScanState->prevSample >= 0.0f && sample < 0.0f) - { - crossedZero = true; - } - break; - default: - assert(false); - break; - } + /* + * Analyze the mode, changing to a new one when appropriate. + */ + switch (pScanState->mode) { + case kModeInitial0: + assert(pScanState->phase == kPhaseScanFor770Start); + pScanState->mode = kModeRunning; + break; + case kModeRunning: + if (pScanState->prevSample < 0.0f && sample >= 0.0f || + pScanState->prevSample >= 0.0f && sample < 0.0f) + { + crossedZero = true; + } + break; + default: + assert(false); + break; + } - /* - * Deal with a zero crossing. - * - * We currently just grab the first point after we cross. We should - * be grabbing the closest point or interpolating across. - */ - if (crossedZero) { - float halfCycleUsec; - int bias; + /* + * Deal with a zero crossing. + * + * We currently just grab the first point after we cross. We should + * be grabbing the closest point or interpolating across. + */ + if (crossedZero) { + float halfCycleUsec; + int bias; - if (fabs(pScanState->prevSample) < fabs(sample)) - bias = -1; // previous sample was closer to zero point - else - bias = 0; // current sample is closer + if (fabs(pScanState->prevSample) < fabs(sample)) + bias = -1; // previous sample was closer to zero point + else + bias = 0; // current sample is closer - /* delta time for zero-to-zero (half cycle) */ - timeDelta = (sampleIndex+bias) - pScanState->lastZeroIndex; + /* delta time for zero-to-zero (half cycle) */ + timeDelta = (sampleIndex+bias) - pScanState->lastZeroIndex; - halfCycleUsec = timeDelta * pScanState->usecPerSample; - //WMSG3("Zero %6ld: half=%.1fusec full=%.1fusec\n", - // sampleIndex, halfCycleUsec, - // halfCycleUsec + pScanState->halfCycleWidth); + halfCycleUsec = timeDelta * pScanState->usecPerSample; + //WMSG3("Zero %6ld: half=%.1fusec full=%.1fusec\n", + // sampleIndex, halfCycleUsec, + // halfCycleUsec + pScanState->halfCycleWidth); - emitBit = UpdatePhase(pScanState, sampleIndex+bias, halfCycleUsec, - pBitVal); + emitBit = UpdatePhase(pScanState, sampleIndex+bias, halfCycleUsec, + pBitVal); - pScanState->lastZeroIndex = sampleIndex + bias; - } + pScanState->lastZeroIndex = sampleIndex + bias; + } - /* record this sample for the next go-round */ - pScanState->prevSample = sample; + /* record this sample for the next go-round */ + pScanState->prevSample = sample; - return emitBit; + return emitBit; } /* @@ -925,133 +925,133 @@ CassetteDialog::CassetteData::ProcessSampleZero(float sample, long sampleIndex, */ bool CassetteDialog::CassetteData::ProcessSamplePeak(float sample, long sampleIndex, - ScanState* pScanState, int* pBitVal) + ScanState* pScanState, int* pBitVal) { - /* values range from [-1.0,1.0), so range is 2.0 total */ - long timeDelta; - float ampDelta; - float transitionLimit; - bool hitPeak = false; - bool emitBit = false; + /* values range from [-1.0,1.0), so range is 2.0 total */ + long timeDelta; + float ampDelta; + float transitionLimit; + bool hitPeak = false; + bool emitBit = false; - /* - * Analyze the mode, changing to a new one when appropriate. - */ - switch (pScanState->mode) { - case kModeInitial0: - assert(pScanState->phase == kPhaseScanFor770Start); - pScanState->mode = kModeInitial1; - break; - case kModeInitial1: - assert(pScanState->phase == kPhaseScanFor770Start); - if (sample >= pScanState->prevSample) - pScanState->positive = true; - else - pScanState->positive = false; - pScanState->mode = kModeInTransition; - /* set these up with something reasonable */ - pScanState->lastPeakStartIndex = sampleIndex; - pScanState->lastPeakStartValue = sample; - break; + /* + * Analyze the mode, changing to a new one when appropriate. + */ + switch (pScanState->mode) { + case kModeInitial0: + assert(pScanState->phase == kPhaseScanFor770Start); + pScanState->mode = kModeInitial1; + break; + case kModeInitial1: + assert(pScanState->phase == kPhaseScanFor770Start); + if (sample >= pScanState->prevSample) + pScanState->positive = true; + else + pScanState->positive = false; + pScanState->mode = kModeInTransition; + /* set these up with something reasonable */ + pScanState->lastPeakStartIndex = sampleIndex; + pScanState->lastPeakStartValue = sample; + break; - case kModeInTransition: - /* - * Stay here until two adjacent samples are very close in amplitude - * (or we change direction). We need to adjust our amplitude - * threshold based on sampling frequency, or at higher sample - * rates we're going to think everything is a transition. - * - * The approach here is overly simplistic, and is prone to failure - * when the sampling rate is high, especially with 8-bit samples - * or sound cards that don't really have 16-bit resolution. The - * proper way to do this is to keep a short history, and evaluate - * the delta amplitude over longer periods. [At this point I'd - * rather just tell people to record at 22.05KHz.] - * - * Set the "hitPeak" flag and handle the consequences below. - */ - if (pScanState->algorithm == kAlgorithmRoundPeak) - transitionLimit = kTransMinDelta * - (pScanState->usecPerSample / kTransDeltaBase); - else - transitionLimit = 0.0f; + case kModeInTransition: + /* + * Stay here until two adjacent samples are very close in amplitude + * (or we change direction). We need to adjust our amplitude + * threshold based on sampling frequency, or at higher sample + * rates we're going to think everything is a transition. + * + * The approach here is overly simplistic, and is prone to failure + * when the sampling rate is high, especially with 8-bit samples + * or sound cards that don't really have 16-bit resolution. The + * proper way to do this is to keep a short history, and evaluate + * the delta amplitude over longer periods. [At this point I'd + * rather just tell people to record at 22.05KHz.] + * + * Set the "hitPeak" flag and handle the consequences below. + */ + if (pScanState->algorithm == kAlgorithmRoundPeak) + transitionLimit = kTransMinDelta * + (pScanState->usecPerSample / kTransDeltaBase); + else + transitionLimit = 0.0f; - if (pScanState->positive) { - if (sample < pScanState->prevSample + transitionLimit) { - pScanState->mode = kModeAtPeak; - hitPeak = true; - } - } else { - if (sample > pScanState->prevSample - transitionLimit) { - pScanState->mode = kModeAtPeak; - hitPeak = true; - } - } - break; - case kModeAtPeak: - /* - * Stay here until we're a certain distance above or below the - * previous peak. This also keeps us in a holding pattern for - * large flat areas. - */ - transitionLimit = kPeakThreshold; - if (pScanState->algorithm == kAlgorithmShallowPeak) - transitionLimit /= 4.0f; + if (pScanState->positive) { + if (sample < pScanState->prevSample + transitionLimit) { + pScanState->mode = kModeAtPeak; + hitPeak = true; + } + } else { + if (sample > pScanState->prevSample - transitionLimit) { + pScanState->mode = kModeAtPeak; + hitPeak = true; + } + } + break; + case kModeAtPeak: + /* + * Stay here until we're a certain distance above or below the + * previous peak. This also keeps us in a holding pattern for + * large flat areas. + */ + transitionLimit = kPeakThreshold; + if (pScanState->algorithm == kAlgorithmShallowPeak) + transitionLimit /= 4.0f; - ampDelta = pScanState->lastPeakStartValue - sample; - if (ampDelta < 0) - ampDelta = -ampDelta; - if (ampDelta > transitionLimit) { - if (sample >= pScanState->lastPeakStartValue) - pScanState->positive = true; // going up - else - pScanState->positive = false; // going down + ampDelta = pScanState->lastPeakStartValue - sample; + if (ampDelta < 0) + ampDelta = -ampDelta; + if (ampDelta > transitionLimit) { + if (sample >= pScanState->lastPeakStartValue) + pScanState->positive = true; // going up + else + pScanState->positive = false; // going down - /* mark the end of the peak; could be same as start of peak */ - pScanState->mode = kModeInTransition; - } - break; - default: - assert(false); - break; - } + /* mark the end of the peak; could be same as start of peak */ + pScanState->mode = kModeInTransition; + } + break; + default: + assert(false); + break; + } - /* - * If we hit "peak" criteria, we regard the *previous* sample as the - * peak. This is very important for lower sampling rates (e.g. 8KHz). - */ - if (hitPeak) { - /* compute half-cycle amplitude and time */ - float halfCycleUsec; //, fullCycleUsec; + /* + * If we hit "peak" criteria, we regard the *previous* sample as the + * peak. This is very important for lower sampling rates (e.g. 8KHz). + */ + if (hitPeak) { + /* compute half-cycle amplitude and time */ + float halfCycleUsec; //, fullCycleUsec; - /* delta time for peak-to-peak (half cycle) */ - timeDelta = (sampleIndex-1) - pScanState->lastPeakStartIndex; - /* amplitude peak-to-peak */ - ampDelta = pScanState->lastPeakStartValue - pScanState->prevSample; - if (ampDelta < 0) - ampDelta = -ampDelta; + /* delta time for peak-to-peak (half cycle) */ + timeDelta = (sampleIndex-1) - pScanState->lastPeakStartIndex; + /* amplitude peak-to-peak */ + ampDelta = pScanState->lastPeakStartValue - pScanState->prevSample; + if (ampDelta < 0) + ampDelta = -ampDelta; - halfCycleUsec = timeDelta * pScanState->usecPerSample; - //if (sampleIndex > 584327 && sampleIndex < 590000) { - // WMSG4("Peak %6ld: amp=%.3f height=%.3f peakWidth=%.1fusec\n", - // sampleIndex-1, pScanState->prevSample, ampDelta, - // halfCycleUsec); - // ::Sleep(10); - //} - if (sampleIndex == 32739) - WMSG0("whee\n"); + halfCycleUsec = timeDelta * pScanState->usecPerSample; + //if (sampleIndex > 584327 && sampleIndex < 590000) { + // WMSG4("Peak %6ld: amp=%.3f height=%.3f peakWidth=%.1fusec\n", + // sampleIndex-1, pScanState->prevSample, ampDelta, + // halfCycleUsec); + // ::Sleep(10); + //} + if (sampleIndex == 32739) + WMSG0("whee\n"); - emitBit = UpdatePhase(pScanState, sampleIndex-1, halfCycleUsec, pBitVal); + emitBit = UpdatePhase(pScanState, sampleIndex-1, halfCycleUsec, pBitVal); - /* set the "peak start" values */ - pScanState->lastPeakStartIndex = sampleIndex-1; - pScanState->lastPeakStartValue = pScanState->prevSample; - } + /* set the "peak start" values */ + pScanState->lastPeakStartIndex = sampleIndex-1; + pScanState->lastPeakStartValue = pScanState->prevSample; + } - /* record this sample for the next go-round */ - pScanState->prevSample = sample; + /* record this sample for the next go-round */ + pScanState->prevSample = sample; - return emitBit; + return emitBit; } @@ -1067,126 +1067,126 @@ CassetteDialog::CassetteData::ProcessSamplePeak(float sample, long sampleIndex, */ bool CassetteDialog::CassetteData::UpdatePhase(ScanState* pScanState, long sampleIndex, - float halfCycleUsec, int* pBitVal) + float halfCycleUsec, int* pBitVal) { - float fullCycleUsec; - bool emitBit = false; + float fullCycleUsec; + bool emitBit = false; - if (pScanState->halfCycleWidth != 0.0f) - fullCycleUsec = halfCycleUsec + pScanState->halfCycleWidth; - else - fullCycleUsec = 0.0f; // only have first half + if (pScanState->halfCycleWidth != 0.0f) + fullCycleUsec = halfCycleUsec + pScanState->halfCycleWidth; + else + fullCycleUsec = 0.0f; // only have first half - switch (pScanState->phase) { - case kPhaseScanFor770Start: - /* watch for a cycle of the appropriate length */ - if (fullCycleUsec != 0.0f && - fullCycleUsec > kLeadInHalfWidth*2.0f - kLeadInMaxError*2.0f && - fullCycleUsec < kLeadInHalfWidth*2.0f + kLeadInMaxError*2.0f) - { - //WMSG1(" scanning 770 at %ld\n", sampleIndex); - pScanState->phase = kPhaseScanning770; - pScanState->num770 = 1; - } - break; - case kPhaseScanning770: - /* count up the 770Hz cycles */ - if (fullCycleUsec != 0.0f && - fullCycleUsec > kLeadInHalfWidth*2.0f - kLeadInMaxError*2.0f && - fullCycleUsec < kLeadInHalfWidth*2.0f + kLeadInMaxError*2.0f) - { - pScanState->num770++; - if (pScanState->num770 > kLeadInHalfCycThreshold/2) { - /* looks like a solid tone, advance to next phase */ - pScanState->phase = kPhaseScanForShort0; - WMSG0(" looking for short 0\n"); - } - } else if (fullCycleUsec != 0.0f) { - /* pattern lost, reset */ - if (pScanState->num770 > 5) { - WMSG3(" lost 770 at %ld width=%.1f (count=%ld)\n", - sampleIndex, fullCycleUsec, pScanState->num770); - } - pScanState->phase = kPhaseScanFor770Start; - } - /* else we only have a half cycle, so do nothing */ - break; - case kPhaseScanForShort0: - /* found what looks like a 770Hz field, find the short 0 */ - if (halfCycleUsec > kShortZeroHalfWidth - kShortZeroMaxError && - halfCycleUsec < kShortZeroHalfWidth + kShortZeroMaxError) - { - WMSG3(" found short zero (half=%.1f) at %ld after %ld 770s\n", - halfCycleUsec, sampleIndex, pScanState->num770); - pScanState->phase = kPhaseShort0B; - /* make sure we treat current sample as first half */ - pScanState->halfCycleWidth = 0.0f; - } else - if (fullCycleUsec != 0.0f && - fullCycleUsec > kLeadInHalfWidth*2.0f - kLeadInMaxError*2.0f && - fullCycleUsec < kLeadInHalfWidth*2.0f + kLeadInMaxError*2.0f) - { - /* found another 770Hz cycle */ - pScanState->num770++; - } else if (fullCycleUsec != 0.0f) { - /* full cycle of the wrong size, we've lost it */ - WMSG3(" Lost 770 at %ld width=%.1f (count=%ld)\n", - sampleIndex, fullCycleUsec, pScanState->num770); - pScanState->phase = kPhaseScanFor770Start; - } - break; - case kPhaseShort0B: - /* pick up the second half of the start cycle */ - assert(fullCycleUsec != 0.0f); - if (fullCycleUsec > (kShortZeroHalfWidth + kZeroHalfWidth) - kZeroMaxError*2.0f && - fullCycleUsec < (kShortZeroHalfWidth + kZeroHalfWidth) + kZeroMaxError*2.0f) - { - /* as expected */ - WMSG2(" Found 0B %.1f (total %.1f), advancing to 'read data' phase\n", - halfCycleUsec, fullCycleUsec); - pScanState->dataStart = sampleIndex; - pScanState->phase = kPhaseReadData; - } else { - /* must be a false-positive at end of tone */ - WMSG2(" Didn't find post-short-0 value (half=%.1f + %.1f)\n", - pScanState->halfCycleWidth, halfCycleUsec); - pScanState->phase = kPhaseScanFor770Start; - } - break; + switch (pScanState->phase) { + case kPhaseScanFor770Start: + /* watch for a cycle of the appropriate length */ + if (fullCycleUsec != 0.0f && + fullCycleUsec > kLeadInHalfWidth*2.0f - kLeadInMaxError*2.0f && + fullCycleUsec < kLeadInHalfWidth*2.0f + kLeadInMaxError*2.0f) + { + //WMSG1(" scanning 770 at %ld\n", sampleIndex); + pScanState->phase = kPhaseScanning770; + pScanState->num770 = 1; + } + break; + case kPhaseScanning770: + /* count up the 770Hz cycles */ + if (fullCycleUsec != 0.0f && + fullCycleUsec > kLeadInHalfWidth*2.0f - kLeadInMaxError*2.0f && + fullCycleUsec < kLeadInHalfWidth*2.0f + kLeadInMaxError*2.0f) + { + pScanState->num770++; + if (pScanState->num770 > kLeadInHalfCycThreshold/2) { + /* looks like a solid tone, advance to next phase */ + pScanState->phase = kPhaseScanForShort0; + WMSG0(" looking for short 0\n"); + } + } else if (fullCycleUsec != 0.0f) { + /* pattern lost, reset */ + if (pScanState->num770 > 5) { + WMSG3(" lost 770 at %ld width=%.1f (count=%ld)\n", + sampleIndex, fullCycleUsec, pScanState->num770); + } + pScanState->phase = kPhaseScanFor770Start; + } + /* else we only have a half cycle, so do nothing */ + break; + case kPhaseScanForShort0: + /* found what looks like a 770Hz field, find the short 0 */ + if (halfCycleUsec > kShortZeroHalfWidth - kShortZeroMaxError && + halfCycleUsec < kShortZeroHalfWidth + kShortZeroMaxError) + { + WMSG3(" found short zero (half=%.1f) at %ld after %ld 770s\n", + halfCycleUsec, sampleIndex, pScanState->num770); + pScanState->phase = kPhaseShort0B; + /* make sure we treat current sample as first half */ + pScanState->halfCycleWidth = 0.0f; + } else + if (fullCycleUsec != 0.0f && + fullCycleUsec > kLeadInHalfWidth*2.0f - kLeadInMaxError*2.0f && + fullCycleUsec < kLeadInHalfWidth*2.0f + kLeadInMaxError*2.0f) + { + /* found another 770Hz cycle */ + pScanState->num770++; + } else if (fullCycleUsec != 0.0f) { + /* full cycle of the wrong size, we've lost it */ + WMSG3(" Lost 770 at %ld width=%.1f (count=%ld)\n", + sampleIndex, fullCycleUsec, pScanState->num770); + pScanState->phase = kPhaseScanFor770Start; + } + break; + case kPhaseShort0B: + /* pick up the second half of the start cycle */ + assert(fullCycleUsec != 0.0f); + if (fullCycleUsec > (kShortZeroHalfWidth + kZeroHalfWidth) - kZeroMaxError*2.0f && + fullCycleUsec < (kShortZeroHalfWidth + kZeroHalfWidth) + kZeroMaxError*2.0f) + { + /* as expected */ + WMSG2(" Found 0B %.1f (total %.1f), advancing to 'read data' phase\n", + halfCycleUsec, fullCycleUsec); + pScanState->dataStart = sampleIndex; + pScanState->phase = kPhaseReadData; + } else { + /* must be a false-positive at end of tone */ + WMSG2(" Didn't find post-short-0 value (half=%.1f + %.1f)\n", + pScanState->halfCycleWidth, halfCycleUsec); + pScanState->phase = kPhaseScanFor770Start; + } + break; - case kPhaseReadData: - /* check width of full cycle; don't double error allowance */ - if (fullCycleUsec != 0.0f) { - if (fullCycleUsec > kZeroHalfWidth*2 - kZeroMaxError*2 && - fullCycleUsec < kZeroHalfWidth*2 + kZeroMaxError*2) - { - *pBitVal = 0; - emitBit = true; - } else - if (fullCycleUsec > kOneHalfWidth*2 - kOneMaxError*2 && - fullCycleUsec < kOneHalfWidth*2 + kOneMaxError*2) - { - *pBitVal = 1; - emitBit = true; - } else { - /* bad cycle, assume end reached */ - WMSG2(" Bad full cycle time %.1f in data at %ld, bailing\n", - fullCycleUsec, sampleIndex); - pScanState->dataEnd = sampleIndex; - pScanState->phase = kPhaseEndReached; - } - } - break; - default: - assert(false); - break; - } + case kPhaseReadData: + /* check width of full cycle; don't double error allowance */ + if (fullCycleUsec != 0.0f) { + if (fullCycleUsec > kZeroHalfWidth*2 - kZeroMaxError*2 && + fullCycleUsec < kZeroHalfWidth*2 + kZeroMaxError*2) + { + *pBitVal = 0; + emitBit = true; + } else + if (fullCycleUsec > kOneHalfWidth*2 - kOneMaxError*2 && + fullCycleUsec < kOneHalfWidth*2 + kOneMaxError*2) + { + *pBitVal = 1; + emitBit = true; + } else { + /* bad cycle, assume end reached */ + WMSG2(" Bad full cycle time %.1f in data at %ld, bailing\n", + fullCycleUsec, sampleIndex); + pScanState->dataEnd = sampleIndex; + pScanState->phase = kPhaseEndReached; + } + } + break; + default: + assert(false); + break; + } - /* save the half-cycle stats */ - if (pScanState->halfCycleWidth == 0.0f) - pScanState->halfCycleWidth = halfCycleUsec; - else - pScanState->halfCycleWidth = 0.0f; + /* save the half-cycle stats */ + if (pScanState->halfCycleWidth == 0.0f) + pScanState->halfCycleWidth = halfCycleUsec; + else + pScanState->halfCycleWidth = 0.0f; - return emitBit; + return emitBit; } diff --git a/app/CassetteDialog.h b/app/CassetteDialog.h index bebb688..98139a5 100644 --- a/app/CassetteDialog.h +++ b/app/CassetteDialog.h @@ -15,146 +15,146 @@ */ class CassetteDialog : public CDialog { public: - CassetteDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_IMPORTCASSETTE, pParentWnd), fDirty(false) - {} - virtual ~CassetteDialog(void) {} + CassetteDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_IMPORTCASSETTE, pParentWnd), fDirty(false) + {} + virtual ~CassetteDialog(void) {} - CString fFileName; // file to open + CString fFileName; // file to open - bool IsDirty(void) const { return fDirty; } + bool IsDirty(void) const { return fDirty; } private: - virtual BOOL OnInitDialog(void); - //virtual void DoDataExchange(CDataExchange* pDX); - //virtual void OnOK(void); - - //enum { WMU_DIALOG_READY = WM_USER+2 }; + virtual BOOL OnInitDialog(void); + //virtual void DoDataExchange(CDataExchange* pDX); + //virtual void OnOK(void); + + //enum { WMU_DIALOG_READY = WM_USER+2 }; - afx_msg void OnListChange(NMHDR* pNotifyStruct, LRESULT* pResult); - afx_msg void OnListDblClick(NMHDR* pNotifyStruct, LRESULT* pResult); - afx_msg void OnAlgorithmChange(void); - afx_msg void OnHelp(void); - afx_msg void OnImport(void); + afx_msg void OnListChange(NMHDR* pNotifyStruct, LRESULT* pResult); + afx_msg void OnListDblClick(NMHDR* pNotifyStruct, LRESULT* pResult); + afx_msg void OnAlgorithmChange(void); + afx_msg void OnHelp(void); + afx_msg void OnImport(void); - /* - * This holds converted data from the WAV file, plus some meta-data - * like what type of file we think this is. - */ - class CassetteData { - public: - CassetteData(void) : fFileType(0x00), fOutputBuf(nil), fOutputLen(-1), - fStartSample(-1), fEndSample(-1), fChecksum(0x00), - fChecksumGood(false) - {} - virtual ~CassetteData(void) { delete[] fOutputBuf; } + /* + * This holds converted data from the WAV file, plus some meta-data + * like what type of file we think this is. + */ + class CassetteData { + public: + CassetteData(void) : fFileType(0x00), fOutputBuf(nil), fOutputLen(-1), + fStartSample(-1), fEndSample(-1), fChecksum(0x00), + fChecksumGood(false) + {} + virtual ~CassetteData(void) { delete[] fOutputBuf; } - /* - * Algorithm to use. This must match up with the order of the items - * in the dialog IDC_CASSETTE_ALG combo box. - */ - typedef enum Algorithm { - kAlgorithmMIN = -1, + /* + * Algorithm to use. This must match up with the order of the items + * in the dialog IDC_CASSETTE_ALG combo box. + */ + typedef enum Algorithm { + kAlgorithmMIN = -1, - kAlgorithmZero = 0, - kAlgorithmSharpPeak, - kAlgorithmRoundPeak, - kAlgorithmShallowPeak, + kAlgorithmZero = 0, + kAlgorithmSharpPeak, + kAlgorithmRoundPeak, + kAlgorithmShallowPeak, - kAlgorithmMAX - } Algorithm; + kAlgorithmMAX + } Algorithm; - bool Scan(SoundFile* pSoundFile, Algorithm alg, long* pSampleOffset); - unsigned char* GetDataBuf(void) const { return fOutputBuf; } - int GetDataLen(void) const { return fOutputLen; } - int GetDataOffset(void) const { return fStartSample; } - int GetDataEndOffset(void) const { return fEndSample; } - unsigned char GetDataChecksum(void) const { return fChecksum; } - bool GetDataChkGood(void) const { return fChecksumGood; } + bool Scan(SoundFile* pSoundFile, Algorithm alg, long* pSampleOffset); + unsigned char* GetDataBuf(void) const { return fOutputBuf; } + int GetDataLen(void) const { return fOutputLen; } + int GetDataOffset(void) const { return fStartSample; } + int GetDataEndOffset(void) const { return fEndSample; } + unsigned char GetDataChecksum(void) const { return fChecksum; } + bool GetDataChkGood(void) const { return fChecksumGood; } - long GetFileType(void) const { return fFileType; } - void SetFileType(long fileType) { fFileType = fileType; } + long GetFileType(void) const { return fFileType; } + void SetFileType(long fileType) { fFileType = fileType; } - private: - typedef enum Phase { - kPhaseUnknown = 0, - kPhaseScanFor770Start, - kPhaseScanning770, - kPhaseScanForShort0, - kPhaseShort0B, - kPhaseReadData, - kPhaseEndReached, - // kPhaseError, - } Phase; - typedef enum Mode { - kModeUnknown = 0, - kModeInitial0, - kModeInitial1, + private: + typedef enum Phase { + kPhaseUnknown = 0, + kPhaseScanFor770Start, + kPhaseScanning770, + kPhaseScanForShort0, + kPhaseShort0B, + kPhaseReadData, + kPhaseEndReached, + // kPhaseError, + } Phase; + typedef enum Mode { + kModeUnknown = 0, + kModeInitial0, + kModeInitial1, - kModeInTransition, - kModeAtPeak, + kModeInTransition, + kModeAtPeak, - kModeRunning, - } Mode; + kModeRunning, + } Mode; - typedef struct ScanState { - Algorithm algorithm; - Phase phase; - Mode mode; - bool positive; // rising or at +peak if true + typedef struct ScanState { + Algorithm algorithm; + Phase phase; + Mode mode; + bool positive; // rising or at +peak if true - long lastZeroIndex; // in samples - long lastPeakStartIndex; // in samples - float lastPeakStartValue; + long lastZeroIndex; // in samples + long lastPeakStartIndex; // in samples + float lastPeakStartValue; - float prevSample; + float prevSample; - float halfCycleWidth; // in usec - long num770; // #of consecutive 770Hz cycles - long dataStart; - long dataEnd; + float halfCycleWidth; // in usec + long num770; // #of consecutive 770Hz cycles + long dataStart; + long dataEnd; - /* constants */ - float usecPerSample; - } ScanState; - void ConvertSamplesToReal(const WAVEFORMATEX* pFormat, - const unsigned char* buf, long chunkLen, float* sampleBuf); - bool ProcessSample(float sample, long sampleIndex, - ScanState* pScanState, int* pBitVal); - bool ProcessSampleZero(float sample, long sampleIndex, - ScanState* pScanState, int* pBitVal); - bool ProcessSamplePeak(float sample, long sampleIndex, - ScanState* pScanState, int* pBitVal); - bool UpdatePhase(ScanState* pScanState, long sampleIndex, - float halfCycleUsec, int* pBitVal); + /* constants */ + float usecPerSample; + } ScanState; + void ConvertSamplesToReal(const WAVEFORMATEX* pFormat, + const unsigned char* buf, long chunkLen, float* sampleBuf); + bool ProcessSample(float sample, long sampleIndex, + ScanState* pScanState, int* pBitVal); + bool ProcessSampleZero(float sample, long sampleIndex, + ScanState* pScanState, int* pBitVal); + bool ProcessSamplePeak(float sample, long sampleIndex, + ScanState* pScanState, int* pBitVal); + bool UpdatePhase(ScanState* pScanState, long sampleIndex, + float halfCycleUsec, int* pBitVal); - enum { - kMaxFileLen = 65535+2+1+1, // 64K + length + checksum + 1 slop - }; + enum { + kMaxFileLen = 65535+2+1+1, // 64K + length + checksum + 1 slop + }; - long fFileType; // 0x06, 0xfa, or 0xfc - unsigned char* fOutputBuf; - int fOutputLen; - long fStartSample; - long fEndSample; - unsigned char fChecksum; - bool fChecksumGood; - }; + long fFileType; // 0x06, 0xfa, or 0xfc + unsigned char* fOutputBuf; + int fOutputLen; + long fStartSample; + long fEndSample; + unsigned char fChecksum; + bool fChecksumGood; + }; - bool AnalyzeWAV(void); - void AddEntry(int idx, CListCtrl* pListCtrl, long* pFileType); + bool AnalyzeWAV(void); + void AddEntry(int idx, CListCtrl* pListCtrl, long* pFileType); - enum { - kMaxRecordings = 100, // max A2 files per WAV file - }; + enum { + kMaxRecordings = 100, // max A2 files per WAV file + }; - /* array with one entry per file */ - CassetteData fDataArray[kMaxRecordings]; + /* array with one entry per file */ + CassetteData fDataArray[kMaxRecordings]; - CassetteData::Algorithm fAlgorithm; - bool fDirty; + CassetteData::Algorithm fAlgorithm; + bool fDirty; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__CASSETTEDIALOG__*/ diff --git a/app/ChooseAddTargetDialog.cpp b/app/ChooseAddTargetDialog.cpp index 81a7423..30aff02 100644 --- a/app/ChooseAddTargetDialog.cpp +++ b/app/ChooseAddTargetDialog.cpp @@ -14,7 +14,7 @@ using namespace DiskImgLib; BEGIN_MESSAGE_MAP(ChooseAddTargetDialog, CDialog) - ON_COMMAND(IDHELP, OnHelp) + ON_COMMAND(IDHELP, OnHelp) END_MESSAGE_MAP() /* @@ -24,31 +24,31 @@ END_MESSAGE_MAP() BOOL ChooseAddTargetDialog::OnInitDialog(void) { - CDialog::OnInitDialog(); + CDialog::OnInitDialog(); - CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_ADD_TARGET_TREE); + CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_ADD_TARGET_TREE); - ASSERT(fpDiskFS != nil); - ASSERT(pTree != nil); + ASSERT(fpDiskFS != nil); + ASSERT(pTree != nil); - fDiskFSTree.fIncludeSubdirs = true; - fDiskFSTree.fExpandDepth = -1; - if (!fDiskFSTree.BuildTree(fpDiskFS, pTree)) { - WMSG0("Tree load failed!\n"); - OnCancel(); - } + fDiskFSTree.fIncludeSubdirs = true; + fDiskFSTree.fExpandDepth = -1; + if (!fDiskFSTree.BuildTree(fpDiskFS, pTree)) { + WMSG0("Tree load failed!\n"); + OnCancel(); + } - int count = pTree->GetCount(); - WMSG1("ChooseAddTargetDialog tree has %d items\n", count); - if (count <= 1) { - WMSG0(" Skipping out of target selection\n"); - // adding to root volume of the sole DiskFS - fpChosenDiskFS = fpDiskFS; - ASSERT(fpChosenSubdir == nil); - OnOK(); - } + int count = pTree->GetCount(); + WMSG1("ChooseAddTargetDialog tree has %d items\n", count); + if (count <= 1) { + WMSG0(" Skipping out of target selection\n"); + // adding to root volume of the sole DiskFS + fpChosenDiskFS = fpDiskFS; + ASSERT(fpChosenSubdir == nil); + OnOK(); + } - return TRUE; + return TRUE; } /* @@ -59,36 +59,36 @@ ChooseAddTargetDialog::OnInitDialog(void) void ChooseAddTargetDialog::DoDataExchange(CDataExchange* pDX) { - if (pDX->m_bSaveAndValidate) { - CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_ADD_TARGET_TREE); - CString errMsg, appName; - appName.LoadString(IDS_MB_APP_NAME); + if (pDX->m_bSaveAndValidate) { + CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_ADD_TARGET_TREE); + CString errMsg, appName; + appName.LoadString(IDS_MB_APP_NAME); - /* shortcut for simple disk images */ - if (pTree->GetCount() == 1 && fpChosenDiskFS != nil) - return; + /* shortcut for simple disk images */ + if (pTree->GetCount() == 1 && fpChosenDiskFS != nil) + return; - HTREEITEM selected; - selected = pTree->GetSelectedItem(); - if (selected == nil) { - errMsg = "Please select a disk or subdirectory to add files to."; - MessageBox(errMsg, appName, MB_OK); - pDX->Fail(); - return; - } + HTREEITEM selected; + selected = pTree->GetSelectedItem(); + if (selected == nil) { + errMsg = "Please select a disk or subdirectory to add files to."; + MessageBox(errMsg, appName, MB_OK); + pDX->Fail(); + return; + } - DiskFSTree::TargetData* pTargetData; - pTargetData = (DiskFSTree::TargetData*) pTree->GetItemData(selected); - if (!pTargetData->selectable) { - errMsg = "You can't add files there."; - MessageBox(errMsg, appName, MB_OK); - pDX->Fail(); - return; - } + DiskFSTree::TargetData* pTargetData; + pTargetData = (DiskFSTree::TargetData*) pTree->GetItemData(selected); + if (!pTargetData->selectable) { + errMsg = "You can't add files there."; + MessageBox(errMsg, appName, MB_OK); + pDX->Fail(); + return; + } - fpChosenDiskFS = pTargetData->pDiskFS; - fpChosenSubdir = pTargetData->pFile; - } + fpChosenDiskFS = pTargetData->pDiskFS; + fpChosenSubdir = pTargetData->pFile; + } } @@ -98,5 +98,5 @@ ChooseAddTargetDialog::DoDataExchange(CDataExchange* pDX) void ChooseAddTargetDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_CHOOSE_TARGET, HELP_CONTEXT); + WinHelp(HELP_TOPIC_CHOOSE_TARGET, HELP_CONTEXT); } diff --git a/app/ChooseAddTargetDialog.h b/app/ChooseAddTargetDialog.h index eb87af7..d0cbbe7 100644 --- a/app/ChooseAddTargetDialog.h +++ b/app/ChooseAddTargetDialog.h @@ -19,29 +19,29 @@ */ class ChooseAddTargetDialog : public CDialog { public: - ChooseAddTargetDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_CHOOSE_ADD_TARGET, pParentWnd) - { - fpDiskFS = fpChosenDiskFS = nil; - fpChosenSubdir = nil; - } - virtual ~ChooseAddTargetDialog(void) {} + ChooseAddTargetDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_CHOOSE_ADD_TARGET, pParentWnd) + { + fpDiskFS = fpChosenDiskFS = nil; + fpChosenSubdir = nil; + } + virtual ~ChooseAddTargetDialog(void) {} - /* set this before calling DoModal */ - DiskImgLib::DiskFS* fpDiskFS; + /* set this before calling DoModal */ + DiskImgLib::DiskFS* fpDiskFS; - /* results; fpChosenSubdir will be nil if root vol selected */ - DiskImgLib::DiskFS* fpChosenDiskFS; - DiskImgLib::A2File* fpChosenSubdir; + /* results; fpChosenSubdir will be nil if root vol selected */ + DiskImgLib::DiskFS* fpChosenDiskFS; + DiskImgLib::A2File* fpChosenSubdir; private: - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); - afx_msg void OnHelp(void); + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); + afx_msg void OnHelp(void); - DiskFSTree fDiskFSTree; + DiskFSTree fDiskFSTree; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__CHOOSE_ADD_TARGET_DIALOG__*/ diff --git a/app/ChooseDirDialog.cpp b/app/ChooseDirDialog.cpp index efa6a1e..4055e74 100644 --- a/app/ChooseDirDialog.cpp +++ b/app/ChooseDirDialog.cpp @@ -13,12 +13,12 @@ #include "HelpTopics.h" BEGIN_MESSAGE_MAP(ChooseDirDialog, CDialog) - ON_NOTIFY(TVN_SELCHANGED, IDC_CHOOSEDIR_TREE, OnSelChanged) - ON_BN_CLICKED(IDC_CHOOSEDIR_EXPAND_TREE, OnExpandTree) - ON_BN_CLICKED(IDC_CHOOSEDIR_NEW_FOLDER, OnNewFolder) - ON_WM_HELPINFO() - //ON_COMMAND(ID_HELP, OnIDHelp) - ON_BN_CLICKED(IDHELP, OnHelp) + ON_NOTIFY(TVN_SELCHANGED, IDC_CHOOSEDIR_TREE, OnSelChanged) + ON_BN_CLICKED(IDC_CHOOSEDIR_EXPAND_TREE, OnExpandTree) + ON_BN_CLICKED(IDC_CHOOSEDIR_NEW_FOLDER, OnNewFolder) + ON_WM_HELPINFO() + //ON_COMMAND(ID_HELP, OnIDHelp) + ON_BN_CLICKED(IDHELP, OnHelp) END_MESSAGE_MAP() @@ -28,39 +28,39 @@ END_MESSAGE_MAP() BOOL ChooseDirDialog::OnInitDialog(void) { - CDialog::OnInitDialog(); + CDialog::OnInitDialog(); - /* set up the "new folder" button */ - fNewFolderButton.ReplaceDlgCtrl(this, IDC_CHOOSEDIR_NEW_FOLDER); - fNewFolderButton.SetBitmapID(IDB_NEW_FOLDER); + /* set up the "new folder" button */ + fNewFolderButton.ReplaceDlgCtrl(this, IDC_CHOOSEDIR_NEW_FOLDER); + fNewFolderButton.SetBitmapID(IDB_NEW_FOLDER); - /* replace the tree control with a ShellTree */ - if (fShellTree.ReplaceDlgCtrl(this, IDC_CHOOSEDIR_TREE) != TRUE) { - WMSG0("WARNING: ShellTree replacement failed\n"); - ASSERT(false); - } + /* replace the tree control with a ShellTree */ + if (fShellTree.ReplaceDlgCtrl(this, IDC_CHOOSEDIR_TREE) != TRUE) { + WMSG0("WARNING: ShellTree replacement failed\n"); + ASSERT(false); + } - //enable images - fShellTree.EnableImages(); - //populate for the with Shell Folders for the first time - fShellTree.PopulateTree(/*CSIDL_DRIVES*/); + //enable images + fShellTree.EnableImages(); + //populate for the with Shell Folders for the first time + fShellTree.PopulateTree(/*CSIDL_DRIVES*/); - if (fPathName.IsEmpty()) { - // start somewhere reasonable - fShellTree.ExpandMyComputer(); - } else { - CString msg(""); - fShellTree.TunnelTree(fPathName, &msg); - if (!msg.IsEmpty()) { - /* failed */ - WMSG2("TunnelTree failed on '%s' (%s), using MyComputer instead\n", - fPathName, msg); - fShellTree.ExpandMyComputer(); - } - } + if (fPathName.IsEmpty()) { + // start somewhere reasonable + fShellTree.ExpandMyComputer(); + } else { + CString msg(""); + fShellTree.TunnelTree(fPathName, &msg); + if (!msg.IsEmpty()) { + /* failed */ + WMSG2("TunnelTree failed on '%s' (%s), using MyComputer instead\n", + fPathName, msg); + fShellTree.ExpandMyComputer(); + } + } - fShellTree.SetFocus(); - return FALSE; // leave focus on shell tree + fShellTree.SetFocus(); + return FALSE; // leave focus on shell tree } /* @@ -69,17 +69,17 @@ ChooseDirDialog::OnInitDialog(void) BOOL ChooseDirDialog::PreTranslateMessage(MSG* pMsg) { - if (pMsg->message == WM_KEYDOWN && + if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) - { - //WMSG0("RETURN!\n"); - if (GetFocus() == GetDlgItem(IDC_CHOOSEDIR_PATHEDIT)) { - OnExpandTree(); - return TRUE; - } - } + { + //WMSG0("RETURN!\n"); + if (GetFocus() == GetDlgItem(IDC_CHOOSEDIR_PATHEDIT)) { + OnExpandTree(); + return TRUE; + } + } - return CDialog::PreTranslateMessage(pMsg); + return CDialog::PreTranslateMessage(pMsg); } /* @@ -89,9 +89,9 @@ ChooseDirDialog::PreTranslateMessage(MSG* pMsg) BOOL ChooseDirDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - DWORD context = lpHelpInfo->iCtrlId; - WinHelp(context, HELP_CONTEXTPOPUP); - return TRUE; // indicate success?? + DWORD context = lpHelpInfo->iCtrlId; + WinHelp(context, HELP_CONTEXTPOPUP); + return TRUE; // indicate success?? } /* @@ -100,7 +100,7 @@ ChooseDirDialog::OnHelpInfo(HELPINFO* lpHelpInfo) void ChooseDirDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_CHOOSE_FOLDER, HELP_CONTEXT); + WinHelp(HELP_TOPIC_CHOOSE_FOLDER, HELP_CONTEXT); } /* @@ -110,27 +110,27 @@ ChooseDirDialog::OnHelp(void) void ChooseDirDialog::OnSelChanged(NMHDR* pnmh, LRESULT* pResult) { - CString path; - CWnd* pWnd = GetDlgItem(IDC_CHOOSEDIR_PATH); - ASSERT(pWnd != nil); + CString path; + CWnd* pWnd = GetDlgItem(IDC_CHOOSEDIR_PATH); + ASSERT(pWnd != nil); - if (fShellTree.GetFolderPath(&path)) - fPathName = path; - else - fPathName = ""; - pWnd->SetWindowText(fPathName); + if (fShellTree.GetFolderPath(&path)) + fPathName = path; + else + fPathName = ""; + pWnd->SetWindowText(fPathName); - // disable the "Select" button when there's no path ready - pWnd = GetDlgItem(IDOK); - ASSERT(pWnd != nil); - pWnd->EnableWindow(!fPathName.IsEmpty()); + // disable the "Select" button when there's no path ready + pWnd = GetDlgItem(IDOK); + ASSERT(pWnd != nil); + pWnd->EnableWindow(!fPathName.IsEmpty()); - // It's confusing to have two different paths showing, so wipe out the - // free entry field when the selection changes. - pWnd = GetDlgItem(IDC_CHOOSEDIR_PATHEDIT); - pWnd->SetWindowText(""); + // It's confusing to have two different paths showing, so wipe out the + // free entry field when the selection changes. + pWnd = GetDlgItem(IDC_CHOOSEDIR_PATHEDIT); + pWnd->SetWindowText(""); - *pResult = 0; + *pResult = 0; } /* @@ -139,22 +139,22 @@ ChooseDirDialog::OnSelChanged(NMHDR* pnmh, LRESULT* pResult) void ChooseDirDialog::OnExpandTree(void) { - CWnd* pWnd; - CString str; - CString msg; + CWnd* pWnd; + CString str; + CString msg; - pWnd = GetDlgItem(IDC_CHOOSEDIR_PATHEDIT); - ASSERT(pWnd != nil); - pWnd->GetWindowText(str); + pWnd = GetDlgItem(IDC_CHOOSEDIR_PATHEDIT); + ASSERT(pWnd != nil); + pWnd->GetWindowText(str); - if (!str.IsEmpty()) { - fShellTree.TunnelTree(str, &msg); - if (!msg.IsEmpty()) { - CString failed; - failed.LoadString(IDS_FAILED); - MessageBox(msg, failed, MB_OK | MB_ICONERROR); - } - } + if (!str.IsEmpty()) { + fShellTree.TunnelTree(str, &msg); + if (!msg.IsEmpty()) { + CString failed; + failed.LoadString(IDS_FAILED); + MessageBox(msg, failed, MB_OK | MB_ICONERROR); + } + } } /* @@ -163,37 +163,37 @@ ChooseDirDialog::OnExpandTree(void) void ChooseDirDialog::OnNewFolder(void) { - if (fPathName.IsEmpty()) { - MessageBox("You can't create a folder in this part of the tree.", - "Bad Location", MB_OK | MB_ICONERROR); - return; - } + if (fPathName.IsEmpty()) { + MessageBox("You can't create a folder in this part of the tree.", + "Bad Location", MB_OK | MB_ICONERROR); + return; + } - NewFolderDialog newFolderDlg; + NewFolderDialog newFolderDlg; - newFolderDlg.fCurrentFolder = fPathName; - if (newFolderDlg.DoModal() == IDOK) { - if (newFolderDlg.GetFolderCreated()) { - /* - * They created a new folder. We want to add it to the tree - * and then select it. This is not too hard because we know - * that the folder was created under the currently-selected - * tree node. - */ - if (fShellTree.AddFolderAtSelection(newFolderDlg.fNewFolder)) { - CString msg; - WMSG1("Success, tunneling to '%s'\n", - newFolderDlg.fNewFullPath); - fShellTree.TunnelTree(newFolderDlg.fNewFullPath, &msg); - if (!msg.IsEmpty()) { - WMSG1("TunnelTree failed: %s\n", (LPCTSTR) msg); - } - } else { - WMSG0("AddFolderAtSelection FAILED\n"); - ASSERT(false); - } - } else { - WMSG0("NewFolderDialog returned IDOK but no create\n"); - } - } + newFolderDlg.fCurrentFolder = fPathName; + if (newFolderDlg.DoModal() == IDOK) { + if (newFolderDlg.GetFolderCreated()) { + /* + * They created a new folder. We want to add it to the tree + * and then select it. This is not too hard because we know + * that the folder was created under the currently-selected + * tree node. + */ + if (fShellTree.AddFolderAtSelection(newFolderDlg.fNewFolder)) { + CString msg; + WMSG1("Success, tunneling to '%s'\n", + newFolderDlg.fNewFullPath); + fShellTree.TunnelTree(newFolderDlg.fNewFullPath, &msg); + if (!msg.IsEmpty()) { + WMSG1("TunnelTree failed: %s\n", (LPCTSTR) msg); + } + } else { + WMSG0("AddFolderAtSelection FAILED\n"); + ASSERT(false); + } + } else { + WMSG0("NewFolderDialog returned IDOK but no create\n"); + } + } } diff --git a/app/ChooseDirDialog.h b/app/ChooseDirDialog.h index 014376e..cd4a140 100644 --- a/app/ChooseDirDialog.h +++ b/app/ChooseDirDialog.h @@ -19,35 +19,35 @@ */ class ChooseDirDialog : public CDialog { public: - ChooseDirDialog(CWnd* pParent = NULL, int dialogID = IDD_CHOOSEDIR) : - CDialog(dialogID, pParent) - { - fPathName = ""; - } - virtual ~ChooseDirDialog(void) {} + ChooseDirDialog(CWnd* pParent = NULL, int dialogID = IDD_CHOOSEDIR) : + CDialog(dialogID, pParent) + { + fPathName = ""; + } + virtual ~ChooseDirDialog(void) {} - const char* GetPathName(void) const { return fPathName; } + const char* GetPathName(void) const { return fPathName; } - // set the pathname; when DoModal is called this will tunnel in - void SetPathName(const char* str) { fPathName = str; } + // set the pathname; when DoModal is called this will tunnel in + void SetPathName(const char* str) { fPathName = str; } protected: - virtual BOOL OnInitDialog(void); - virtual BOOL PreTranslateMessage(MSG* pMsg); + virtual BOOL OnInitDialog(void); + virtual BOOL PreTranslateMessage(MSG* pMsg); - afx_msg void OnSelChanged(NMHDR* pnmh, LRESULT* pResult); - afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - afx_msg void OnExpandTree(void); - afx_msg void OnNewFolder(void); - afx_msg void OnHelp(void); + afx_msg void OnSelChanged(NMHDR* pnmh, LRESULT* pResult); + afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg void OnExpandTree(void); + afx_msg void OnNewFolder(void); + afx_msg void OnHelp(void); private: - CString fPathName; + CString fPathName; - ShellTree fShellTree; - MyBitmapButton fNewFolderButton; + ShellTree fShellTree; + MyBitmapButton fNewFolderButton; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__CHOOSEDIRDIALOG__*/ \ No newline at end of file diff --git a/app/Clipboard.cpp b/app/Clipboard.cpp index 57235fe..d4ae7ac 100644 --- a/app/Clipboard.cpp +++ b/app/Clipboard.cpp @@ -12,7 +12,7 @@ static const char* kClipboardFmtName = "faddenSoft:CiderPress:v1"; -const int kClipVersion = 1; // should match "vN" in fmt name +const int kClipVersion = 1; // should match "vN" in fmt name const unsigned short kEntrySignature = 0x4350; /* @@ -40,27 +40,27 @@ const unsigned short kEntrySignature = 0x4350; * successful and too-reliably failing for me to believe that. */ const long kWin98ClipboardMax = 16 * 1024 * 1024; -const long kWin98NeutralZone = 512; // extra padding -const int kClipTextMult = 4; // CF_OEMTEXT, CF_LOCALE, CF_UNICODETEXT*2 +const long kWin98NeutralZone = 512; // extra padding +const int kClipTextMult = 4; // CF_OEMTEXT, CF_LOCALE, CF_UNICODETEXT*2 /* * File collection header. */ typedef struct FileCollection { - unsigned short version; // currently 1 - unsigned short dataOffset; // offset to start of data - unsigned long length; // total length; - unsigned long count; // #of entries + unsigned short version; // currently 1 + unsigned short dataOffset; // offset to start of data + unsigned long length; // total length; + unsigned long count; // #of entries } FileCollection; /* what kind of entry is this */ typedef enum EntryKind { - kEntryKindUnknown = 0, - kEntryKindFileDataFork, - kEntryKindFileRsrcFork, - kEntryKindFileBothForks, - kEntryKindDirectory, - kEntryKindDiskImage, + kEntryKindUnknown = 0, + kEntryKindFileDataFork, + kEntryKindFileRsrcFork, + kEntryKindFileBothForks, + kEntryKindDirectory, + kEntryKindDiskImage, } EntryKind; /* @@ -69,28 +69,28 @@ typedef enum EntryKind { * The next file starts at (start + dataOffset + dataLen + rsrcLen + cmmtLen). */ typedef struct FileCollectionEntry { - unsigned short signature; // let's be paranoid - unsigned short dataOffset; // offset to start of data - unsigned short fileNameLen; // len of filename - unsigned long dataLen; // len of data fork - unsigned long rsrcLen; // len of rsrc fork - unsigned long cmmtLen; // len of comments - unsigned long fileType; - unsigned long auxType; - time_t createWhen; - time_t modWhen; - unsigned char access; // ProDOS access flags - unsigned char entryKind; // GenericArchive::FileDetails::FileKind - unsigned char sourceFS; // DiskImgLib::DiskImg::FSFormat - unsigned char fssep; // filesystem separator char, e.g. ':' + unsigned short signature; // let's be paranoid + unsigned short dataOffset; // offset to start of data + unsigned short fileNameLen; // len of filename + unsigned long dataLen; // len of data fork + unsigned long rsrcLen; // len of rsrc fork + unsigned long cmmtLen; // len of comments + unsigned long fileType; + unsigned long auxType; + time_t createWhen; + time_t modWhen; + unsigned char access; // ProDOS access flags + unsigned char entryKind; // GenericArchive::FileDetails::FileKind + unsigned char sourceFS; // DiskImgLib::DiskImg::FSFormat + unsigned char fssep; // filesystem separator char, e.g. ':' - /* data comes next: filename, then data, then resource, then comment */ + /* data comes next: filename, then data, then resource, then comment */ } FileCollectionEntry; /* * ========================================================================== - * Copy + * Copy * ========================================================================== */ @@ -100,92 +100,92 @@ typedef struct FileCollectionEntry { void MainWindow::OnEditCopy(void) { - CString errStr, fileList; - SelectionSet selSet; - UINT myFormat; - bool isOpen = false; - HGLOBAL hGlobal; - LPVOID pGlobal; - unsigned char* buf = nil; - long bufLen = -1; + CString errStr, fileList; + SelectionSet selSet; + UINT myFormat; + bool isOpen = false; + HGLOBAL hGlobal; + LPVOID pGlobal; + unsigned char* buf = nil; + long bufLen = -1; - /* associate a number with the format name */ - myFormat = RegisterClipboardFormat(kClipboardFmtName); - if (myFormat == 0) { - errStr.LoadString(IDS_CLIPBOARD_REGFAILED); - ShowFailureMsg(this, errStr, IDS_FAILED); - goto bail; - } - WMSG1("myFormat = %u\n", myFormat); + /* associate a number with the format name */ + myFormat = RegisterClipboardFormat(kClipboardFmtName); + if (myFormat == 0) { + errStr.LoadString(IDS_CLIPBOARD_REGFAILED); + ShowFailureMsg(this, errStr, IDS_FAILED); + goto bail; + } + WMSG1("myFormat = %u\n", myFormat); - /* open & empty the clipboard, even if we fail later */ - if (OpenClipboard() == false) { - errStr.LoadString(IDS_CLIPBOARD_OPENFAILED); - ShowFailureMsg(this, errStr, IDS_FAILED); - goto bail; - } - isOpen = true; - EmptyClipboard(); + /* open & empty the clipboard, even if we fail later */ + if (OpenClipboard() == false) { + errStr.LoadString(IDS_CLIPBOARD_OPENFAILED); + ShowFailureMsg(this, errStr, IDS_FAILED); + goto bail; + } + isOpen = true; + EmptyClipboard(); - /* - * Create a selection set with the entries. - * - * Strictly speaking we don't need the directories, since we recreate - * them as needed. However, storing them explicitly will allow us - * to preserve empty subdirs. - */ - selSet.CreateFromSelection(fpContentList, - GenericEntry::kAnyThread | GenericEntry::kAllowDirectory); - if (selSet.GetNumEntries() == 0) { - errStr.LoadString(IDS_CLIPBOARD_NOITEMS); - MessageBox(errStr, "No match", MB_OK | MB_ICONEXCLAMATION); - goto bail; - } + /* + * Create a selection set with the entries. + * + * Strictly speaking we don't need the directories, since we recreate + * them as needed. However, storing them explicitly will allow us + * to preserve empty subdirs. + */ + selSet.CreateFromSelection(fpContentList, + GenericEntry::kAnyThread | GenericEntry::kAllowDirectory); + if (selSet.GetNumEntries() == 0) { + errStr.LoadString(IDS_CLIPBOARD_NOITEMS); + MessageBox(errStr, "No match", MB_OK | MB_ICONEXCLAMATION); + goto bail; + } - /* - * Make a big string with a file listing. - */ - fileList = CreateFileList(&selSet); + /* + * Make a big string with a file listing. + */ + fileList = CreateFileList(&selSet); - /* - * Add the string to the clipboard. The clipboard will own the memory we - * allocate. - */ - hGlobal = ::GlobalAlloc(GHND | GMEM_SHARE, fileList.GetLength() +1); - if (hGlobal == nil) { - WMSG1("Failed allocating %ld bytes\n", fileList.GetLength() +1); - errStr.LoadString(IDS_CLIPBOARD_ALLOCFAILED); - ShowFailureMsg(this, errStr, IDS_FAILED); - goto bail; - } - WMSG1(" Allocated %ld bytes for file list on clipboard\n", - fileList.GetLength() +1); - pGlobal = ::GlobalLock(hGlobal); - ASSERT(pGlobal != nil); - strcpy((char*) pGlobal, fileList); - ::GlobalUnlock(hGlobal); + /* + * Add the string to the clipboard. The clipboard will own the memory we + * allocate. + */ + hGlobal = ::GlobalAlloc(GHND | GMEM_SHARE, fileList.GetLength() +1); + if (hGlobal == nil) { + WMSG1("Failed allocating %ld bytes\n", fileList.GetLength() +1); + errStr.LoadString(IDS_CLIPBOARD_ALLOCFAILED); + ShowFailureMsg(this, errStr, IDS_FAILED); + goto bail; + } + WMSG1(" Allocated %ld bytes for file list on clipboard\n", + fileList.GetLength() +1); + pGlobal = ::GlobalLock(hGlobal); + ASSERT(pGlobal != nil); + strcpy((char*) pGlobal, fileList); + ::GlobalUnlock(hGlobal); - SetClipboardData(CF_TEXT, hGlobal); + SetClipboardData(CF_TEXT, hGlobal); - /* - * Create a (potentially very large) buffer with the contents of the - * files in it. This may fail for any number of reasons. - */ - hGlobal = CreateFileCollection(&selSet); - if (hGlobal != nil) { - SetClipboardData(myFormat, hGlobal); - // beep annoys me on copy - //SuccessBeep(); - } + /* + * Create a (potentially very large) buffer with the contents of the + * files in it. This may fail for any number of reasons. + */ + hGlobal = CreateFileCollection(&selSet); + if (hGlobal != nil) { + SetClipboardData(myFormat, hGlobal); + // beep annoys me on copy + //SuccessBeep(); + } bail: - CloseClipboard(); + CloseClipboard(); } void MainWindow::OnUpdateEditCopy(CCmdUI* pCmdUI) { - pCmdUI->Enable(fpContentList != nil && - fpContentList->GetSelectedCount() > 0); + pCmdUI->Enable(fpContentList != nil && + fpContentList->GetSelectedCount() > 0); } /* @@ -198,36 +198,36 @@ MainWindow::OnUpdateEditCopy(CCmdUI* pCmdUI) CString MainWindow::CreateFileList(SelectionSet* pSelSet) { - SelectionEntry* pSelEntry; - GenericEntry* pEntry; - CString tmpStr, fullStr; - char fileTypeBuf[ContentList::kFileTypeBufLen]; - char auxTypeBuf[ContentList::kAuxTypeBufLen]; - CString fileName, subVol, fileType, auxType, modDate, format, length; + SelectionEntry* pSelEntry; + GenericEntry* pEntry; + CString tmpStr, fullStr; + char fileTypeBuf[ContentList::kFileTypeBufLen]; + char auxTypeBuf[ContentList::kAuxTypeBufLen]; + CString fileName, subVol, fileType, auxType, modDate, format, length; - pSelEntry = pSelSet->IterNext(); - while (pSelEntry != nil) { - pEntry = pSelEntry->GetEntry(); - ASSERT(pEntry != nil); + pSelEntry = pSelSet->IterNext(); + while (pSelEntry != nil) { + pEntry = pSelEntry->GetEntry(); + ASSERT(pEntry != nil); - fileName = DblDblQuote(pEntry->GetPathName()); - subVol = pEntry->GetSubVolName(); - ContentList::MakeFileTypeDisplayString(pEntry, fileTypeBuf); - fileType = DblDblQuote(fileTypeBuf); // Mac HFS types might have '"'? - ContentList::MakeAuxTypeDisplayString(pEntry, auxTypeBuf); - auxType = DblDblQuote(auxTypeBuf); - FormatDate(pEntry->GetModWhen(), &modDate); - format = pEntry->GetFormatStr(); - length.Format("%I64d", (LONGLONG) pEntry->GetUncompressedLen()); + fileName = DblDblQuote(pEntry->GetPathName()); + subVol = pEntry->GetSubVolName(); + ContentList::MakeFileTypeDisplayString(pEntry, fileTypeBuf); + fileType = DblDblQuote(fileTypeBuf); // Mac HFS types might have '"'? + ContentList::MakeAuxTypeDisplayString(pEntry, auxTypeBuf); + auxType = DblDblQuote(auxTypeBuf); + FormatDate(pEntry->GetModWhen(), &modDate); + format = pEntry->GetFormatStr(); + length.Format("%I64d", (LONGLONG) pEntry->GetUncompressedLen()); - tmpStr.Format("\"%s\"\t%s\t\"%s\"\t\"%s\"\t%s\t%s\t%s\r\n", - fileName, subVol, fileType, auxType, modDate, format, length); - fullStr += tmpStr; + tmpStr.Format("\"%s\"\t%s\t\"%s\"\t\"%s\"\t%s\t%s\t%s\r\n", + fileName, subVol, fileType, auxType, modDate, format, length); + fullStr += tmpStr; - pSelEntry = pSelSet->IterNext(); - } + pSelEntry = pSelSet->IterNext(); + } - return fullStr; + return fullStr; } /* @@ -236,24 +236,24 @@ MainWindow::CreateFileList(SelectionSet* pSelSet) /*static*/ CString MainWindow::DblDblQuote(const char* str) { - CString result; - char* buf; + CString result; + char* buf; - buf = result.GetBuffer(strlen(str) * 2 +1); - while (*str != '\0') { - if (*str == '"') { - *buf++ = *str; - *buf++ = *str; - } else { - *buf++ = *str; - } - str++; - } - *buf = *str; + buf = result.GetBuffer(strlen(str) * 2 +1); + while (*str != '\0') { + if (*str == '"') { + *buf++ = *str; + *buf++ = *str; + } else { + *buf++ = *str; + } + str++; + } + *buf = *str; - result.ReleaseBuffer(); + result.ReleaseBuffer(); - return result; + return result; } @@ -263,17 +263,17 @@ MainWindow::DblDblQuote(const char* str) long MainWindow::GetClipboardContentLen(void) { - long len = 0; - UINT format = 0; - HGLOBAL hGlobal; + long len = 0; + UINT format = 0; + HGLOBAL hGlobal; - while ((format = EnumClipboardFormats(format)) != 0) { - hGlobal = GetClipboardData(format); - ASSERT(hGlobal != nil); - len += GlobalSize(hGlobal); - } + while ((format = EnumClipboardFormats(format)) != 0) { + hGlobal = GetClipboardData(format); + ASSERT(hGlobal != nil); + len += GlobalSize(hGlobal); + } - return len; + return len; } /* @@ -282,160 +282,160 @@ MainWindow::GetClipboardContentLen(void) HGLOBAL MainWindow::CreateFileCollection(SelectionSet* pSelSet) { - SelectionEntry* pSelEntry; - GenericEntry* pEntry; - HGLOBAL hGlobal = nil; - HGLOBAL hResult = nil; - LPVOID pGlobal; - long totalLength, numFiles; - long priorLength; + SelectionEntry* pSelEntry; + GenericEntry* pEntry; + HGLOBAL hGlobal = nil; + HGLOBAL hResult = nil; + LPVOID pGlobal; + long totalLength, numFiles; + long priorLength; - /* get len of text version(s), with kluge to avoid close & reopen */ - priorLength = GetClipboardContentLen() * kClipTextMult; - /* add some padding -- textmult doesn't work for fixed-size CF_LOCALE */ - priorLength += kWin98NeutralZone; + /* get len of text version(s), with kluge to avoid close & reopen */ + priorLength = GetClipboardContentLen() * kClipTextMult; + /* add some padding -- textmult doesn't work for fixed-size CF_LOCALE */ + priorLength += kWin98NeutralZone; - totalLength = sizeof(FileCollection); - numFiles = 0; + totalLength = sizeof(FileCollection); + numFiles = 0; - /* - * Compute the amount of space required to hold it all. - */ - pSelSet->IterReset(); - pSelEntry = pSelSet->IterNext(); - while (pSelEntry != nil) { - pEntry = pSelEntry->GetEntry(); - ASSERT(pEntry != nil); + /* + * Compute the amount of space required to hold it all. + */ + pSelSet->IterReset(); + pSelEntry = pSelSet->IterNext(); + while (pSelEntry != nil) { + pEntry = pSelEntry->GetEntry(); + ASSERT(pEntry != nil); - //WMSG1("+++ Examining '%s'\n", pEntry->GetDisplayName()); + //WMSG1("+++ Examining '%s'\n", pEntry->GetDisplayName()); - if (pEntry->GetRecordKind() != GenericEntry::kRecordKindVolumeDir) { - totalLength += sizeof(FileCollectionEntry); - totalLength += strlen(pEntry->GetPathName()) +1; - numFiles++; - if (pEntry->GetRecordKind() != GenericEntry::kRecordKindDirectory) { - totalLength += (long) pEntry->GetDataForkLen(); - totalLength += (long) pEntry->GetRsrcForkLen(); - } - } + if (pEntry->GetRecordKind() != GenericEntry::kRecordKindVolumeDir) { + totalLength += sizeof(FileCollectionEntry); + totalLength += strlen(pEntry->GetPathName()) +1; + numFiles++; + if (pEntry->GetRecordKind() != GenericEntry::kRecordKindDirectory) { + totalLength += (long) pEntry->GetDataForkLen(); + totalLength += (long) pEntry->GetRsrcForkLen(); + } + } - if (totalLength < 0) { - DebugBreak(); - WMSG0("Overflow\n"); // pretty hard to do right now! - return nil; - } + if (totalLength < 0) { + DebugBreak(); + WMSG0("Overflow\n"); // pretty hard to do right now! + return nil; + } - pSelEntry = pSelSet->IterNext(); - } + pSelEntry = pSelSet->IterNext(); + } #if 0 - { - CString msg; - msg.Format("totalLength is %ld+%ld = %ld", - totalLength, priorLength, totalLength+priorLength); - if (MessageBox(msg, nil, MB_OKCANCEL) == IDCANCEL) - goto bail; - } + { + CString msg; + msg.Format("totalLength is %ld+%ld = %ld", + totalLength, priorLength, totalLength+priorLength); + if (MessageBox(msg, nil, MB_OKCANCEL) == IDCANCEL) + goto bail; + } #endif - WMSG3("Total length required is %ld + %ld = %ld\n", - totalLength, priorLength, totalLength+priorLength); - if (IsWin9x() && totalLength+priorLength >= kWin98ClipboardMax) { - CString errMsg; - errMsg.Format(IDS_CLIPBOARD_WIN9XMAX, - kWin98ClipboardMax / (1024*1024), - ((float) (totalLength+priorLength)) / (1024.0*1024.0)); - ShowFailureMsg(this, errMsg, IDS_MB_APP_NAME); - goto bail; - } + WMSG3("Total length required is %ld + %ld = %ld\n", + totalLength, priorLength, totalLength+priorLength); + if (IsWin9x() && totalLength+priorLength >= kWin98ClipboardMax) { + CString errMsg; + errMsg.Format(IDS_CLIPBOARD_WIN9XMAX, + kWin98ClipboardMax / (1024*1024), + ((float) (totalLength+priorLength)) / (1024.0*1024.0)); + ShowFailureMsg(this, errMsg, IDS_MB_APP_NAME); + goto bail; + } - /* - * Create a big buffer to hold it all. - */ - hGlobal = ::GlobalAlloc(GHND | GMEM_SHARE, totalLength); - if (hGlobal == nil) { - CString errMsg; - errMsg.Format("ERROR: unable to allocate %ld bytes for copy", - totalLength); - WMSG1("%s\n", (const char*) errMsg); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } - pGlobal = ::GlobalLock(hGlobal); + /* + * Create a big buffer to hold it all. + */ + hGlobal = ::GlobalAlloc(GHND | GMEM_SHARE, totalLength); + if (hGlobal == nil) { + CString errMsg; + errMsg.Format("ERROR: unable to allocate %ld bytes for copy", + totalLength); + WMSG1("%s\n", (const char*) errMsg); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } + pGlobal = ::GlobalLock(hGlobal); - ASSERT(pGlobal != nil); - ASSERT(GlobalSize(hGlobal) >= (DWORD) totalLength); - WMSG3("hGlobal=0x%08lx pGlobal=0x%08lx size=%ld\n", - (long) hGlobal, (long) pGlobal, GlobalSize(hGlobal)); + ASSERT(pGlobal != nil); + ASSERT(GlobalSize(hGlobal) >= (DWORD) totalLength); + WMSG3("hGlobal=0x%08lx pGlobal=0x%08lx size=%ld\n", + (long) hGlobal, (long) pGlobal, GlobalSize(hGlobal)); - /* - * Set up a progress dialog to track it. - */ - ASSERT(fpActionProgress == nil); - fpActionProgress = new ActionProgressDialog; - fpActionProgress->Create(ActionProgressDialog::kActionExtract, this); - fpActionProgress->SetFileName("Clipboard"); + /* + * Set up a progress dialog to track it. + */ + ASSERT(fpActionProgress == nil); + fpActionProgress = new ActionProgressDialog; + fpActionProgress->Create(ActionProgressDialog::kActionExtract, this); + fpActionProgress->SetFileName("Clipboard"); - /* - * Extract the data into the buffer. - */ - long remainingLen; - void* buf; + /* + * Extract the data into the buffer. + */ + long remainingLen; + void* buf; - remainingLen = totalLength - sizeof(FileCollection); - buf = (unsigned char*) pGlobal + sizeof(FileCollection); - pSelSet->IterReset(); - pSelEntry = pSelSet->IterNext(); - while (pSelEntry != nil) { - CString errStr; + remainingLen = totalLength - sizeof(FileCollection); + buf = (unsigned char*) pGlobal + sizeof(FileCollection); + pSelSet->IterReset(); + pSelEntry = pSelSet->IterNext(); + while (pSelEntry != nil) { + CString errStr; - pEntry = pSelEntry->GetEntry(); - ASSERT(pEntry != nil); + pEntry = pSelEntry->GetEntry(); + ASSERT(pEntry != nil); - fpActionProgress->SetArcName(pEntry->GetDisplayName()); + fpActionProgress->SetArcName(pEntry->GetDisplayName()); - errStr = CopyToCollection(pEntry, &buf, &remainingLen); - if (!errStr.IsEmpty()) { - ShowFailureMsg(fpActionProgress, errStr, IDS_MB_APP_NAME); - goto bail; - } - //WMSG1("remainingLen now %ld\n", remainingLen); + errStr = CopyToCollection(pEntry, &buf, &remainingLen); + if (!errStr.IsEmpty()) { + ShowFailureMsg(fpActionProgress, errStr, IDS_MB_APP_NAME); + goto bail; + } + //WMSG1("remainingLen now %ld\n", remainingLen); - pSelEntry = pSelSet->IterNext(); - } + pSelEntry = pSelSet->IterNext(); + } - ASSERT(remainingLen == 0); - ASSERT(buf == (unsigned char*) pGlobal + totalLength); + ASSERT(remainingLen == 0); + ASSERT(buf == (unsigned char*) pGlobal + totalLength); - /* - * Write the header. - */ - FileCollection fileColl; - fileColl.version = kClipVersion; - fileColl.dataOffset = sizeof(FileCollection); - fileColl.length = totalLength; - fileColl.count = numFiles; - memcpy(pGlobal, &fileColl, sizeof(fileColl)); + /* + * Write the header. + */ + FileCollection fileColl; + fileColl.version = kClipVersion; + fileColl.dataOffset = sizeof(FileCollection); + fileColl.length = totalLength; + fileColl.count = numFiles; + memcpy(pGlobal, &fileColl, sizeof(fileColl)); - /* - * Success! - */ - ::GlobalUnlock(hGlobal); + /* + * Success! + */ + ::GlobalUnlock(hGlobal); - hResult = hGlobal; - hGlobal = nil; + hResult = hGlobal; + hGlobal = nil; bail: - if (hGlobal != nil) { - ASSERT(hResult == nil); - ::GlobalUnlock(hGlobal); - ::GlobalFree(hGlobal); - } - if (fpActionProgress != nil) { - fpActionProgress->Cleanup(this); - fpActionProgress = nil; - } - return hResult; + if (hGlobal != nil) { + ASSERT(hResult == nil); + ::GlobalUnlock(hGlobal); + ::GlobalFree(hGlobal); + } + if (fpActionProgress != nil) { + fpActionProgress->Cleanup(this); + fpActionProgress = nil; + } + return hResult; } /* @@ -451,164 +451,164 @@ bail: CString MainWindow::CopyToCollection(GenericEntry* pEntry, void** pBuf, long* pBufLen) { - FileCollectionEntry collEnt; - CString errStr, dummyStr; - unsigned char* buf = (unsigned char*) *pBuf; - long remLen = *pBufLen; + FileCollectionEntry collEnt; + CString errStr, dummyStr; + unsigned char* buf = (unsigned char*) *pBuf; + long remLen = *pBufLen; - errStr.LoadString(IDS_CLIPBOARD_WRITEFAILURE); + errStr.LoadString(IDS_CLIPBOARD_WRITEFAILURE); - if (pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir) { - WMSG0("Not copying volume dir to collection\n"); - return ""; - } + if (pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir) { + WMSG0("Not copying volume dir to collection\n"); + return ""; + } - if (remLen < sizeof(collEnt)) { - ASSERT(false); - return errStr; - } + if (remLen < sizeof(collEnt)) { + ASSERT(false); + return errStr; + } - GenericArchive::FileDetails::FileKind entryKind; - if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory) - entryKind = GenericArchive::FileDetails::kFileKindDirectory; - else if (pEntry->GetHasDataFork() && pEntry->GetHasRsrcFork()) - entryKind = GenericArchive::FileDetails::kFileKindBothForks; - else if (pEntry->GetHasDataFork()) - entryKind = GenericArchive::FileDetails::kFileKindDataFork; - else if (pEntry->GetHasRsrcFork()) - entryKind = GenericArchive::FileDetails::kFileKindRsrcFork; - else if (pEntry->GetHasDiskImage()) - entryKind = GenericArchive::FileDetails::kFileKindDiskImage; - else { - ASSERT(false); - return errStr; - } - ASSERT((int) entryKind >= 0 && (int) entryKind <= 255); + GenericArchive::FileDetails::FileKind entryKind; + if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory) + entryKind = GenericArchive::FileDetails::kFileKindDirectory; + else if (pEntry->GetHasDataFork() && pEntry->GetHasRsrcFork()) + entryKind = GenericArchive::FileDetails::kFileKindBothForks; + else if (pEntry->GetHasDataFork()) + entryKind = GenericArchive::FileDetails::kFileKindDataFork; + else if (pEntry->GetHasRsrcFork()) + entryKind = GenericArchive::FileDetails::kFileKindRsrcFork; + else if (pEntry->GetHasDiskImage()) + entryKind = GenericArchive::FileDetails::kFileKindDiskImage; + else { + ASSERT(false); + return errStr; + } + ASSERT((int) entryKind >= 0 && (int) entryKind <= 255); - memset(&collEnt, 0x99, sizeof(collEnt)); - collEnt.signature = kEntrySignature; - collEnt.dataOffset = sizeof(collEnt); - collEnt.fileNameLen = strlen(pEntry->GetPathName()) +1; - if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory) { - collEnt.dataLen = collEnt.rsrcLen = collEnt.cmmtLen = 0; - } else { - collEnt.dataLen = (unsigned long) pEntry->GetDataForkLen(); - collEnt.rsrcLen = (unsigned long) pEntry->GetRsrcForkLen(); - collEnt.cmmtLen = 0; // CMMT FIX -- length unknown?? - } - collEnt.fileType = pEntry->GetFileType(); - collEnt.auxType = pEntry->GetAuxType(); - collEnt.createWhen = pEntry->GetCreateWhen(); - collEnt.modWhen = pEntry->GetModWhen(); - collEnt.access = (unsigned char) pEntry->GetAccess(); - collEnt.entryKind = (unsigned char) entryKind; - collEnt.sourceFS = pEntry->GetSourceFS(); - collEnt.fssep = pEntry->GetFssep(); + memset(&collEnt, 0x99, sizeof(collEnt)); + collEnt.signature = kEntrySignature; + collEnt.dataOffset = sizeof(collEnt); + collEnt.fileNameLen = strlen(pEntry->GetPathName()) +1; + if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory) { + collEnt.dataLen = collEnt.rsrcLen = collEnt.cmmtLen = 0; + } else { + collEnt.dataLen = (unsigned long) pEntry->GetDataForkLen(); + collEnt.rsrcLen = (unsigned long) pEntry->GetRsrcForkLen(); + collEnt.cmmtLen = 0; // CMMT FIX -- length unknown?? + } + collEnt.fileType = pEntry->GetFileType(); + collEnt.auxType = pEntry->GetAuxType(); + collEnt.createWhen = pEntry->GetCreateWhen(); + collEnt.modWhen = pEntry->GetModWhen(); + collEnt.access = (unsigned char) pEntry->GetAccess(); + collEnt.entryKind = (unsigned char) entryKind; + collEnt.sourceFS = pEntry->GetSourceFS(); + collEnt.fssep = pEntry->GetFssep(); - /* verify there's enough space to hold everything */ - if ((unsigned long) remLen < collEnt.fileNameLen + - collEnt.dataLen + collEnt.rsrcLen + collEnt.cmmtLen) - { - ASSERT(false); - return errStr; - } + /* verify there's enough space to hold everything */ + if ((unsigned long) remLen < collEnt.fileNameLen + + collEnt.dataLen + collEnt.rsrcLen + collEnt.cmmtLen) + { + ASSERT(false); + return errStr; + } - memcpy(buf, &collEnt, sizeof(collEnt)); - buf += sizeof(collEnt); - remLen -= sizeof(collEnt); + memcpy(buf, &collEnt, sizeof(collEnt)); + buf += sizeof(collEnt); + remLen -= sizeof(collEnt); - /* copy string with terminating null */ - memcpy(buf, pEntry->GetPathName(), collEnt.fileNameLen); - buf += collEnt.fileNameLen; - remLen -= collEnt.fileNameLen; + /* copy string with terminating null */ + memcpy(buf, pEntry->GetPathName(), collEnt.fileNameLen); + buf += collEnt.fileNameLen; + remLen -= collEnt.fileNameLen; - /* - * Extract data forks, resource forks, and disk images as appropriate. - */ - char* bufCopy; - long lenCopy; - int result, which; + /* + * Extract data forks, resource forks, and disk images as appropriate. + */ + char* bufCopy; + long lenCopy; + int result, which; - if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory) { - ASSERT(collEnt.dataLen == 0); - ASSERT(collEnt.rsrcLen == 0); - ASSERT(collEnt.cmmtLen == 0); - ASSERT(!pEntry->GetHasRsrcFork()); - } else if (pEntry->GetHasDataFork() || pEntry->GetHasDiskImage()) { - bufCopy = (char*) buf; - lenCopy = remLen; - if (pEntry->GetHasDiskImage()) - which = GenericEntry::kDiskImageThread; - else - which = GenericEntry::kDataThread; + if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory) { + ASSERT(collEnt.dataLen == 0); + ASSERT(collEnt.rsrcLen == 0); + ASSERT(collEnt.cmmtLen == 0); + ASSERT(!pEntry->GetHasRsrcFork()); + } else if (pEntry->GetHasDataFork() || pEntry->GetHasDiskImage()) { + bufCopy = (char*) buf; + lenCopy = remLen; + if (pEntry->GetHasDiskImage()) + which = GenericEntry::kDiskImageThread; + else + which = GenericEntry::kDataThread; - result = pEntry->ExtractThreadToBuffer(which, &bufCopy, &lenCopy, - &dummyStr); - if (result == IDCANCEL) { - errStr.LoadString(IDS_CANCELLED); - return errStr; - } else if (result != IDOK) { - WMSG0("ExtractThreadToBuffer (data) failed\n"); - return errStr; - } + result = pEntry->ExtractThreadToBuffer(which, &bufCopy, &lenCopy, + &dummyStr); + if (result == IDCANCEL) { + errStr.LoadString(IDS_CANCELLED); + return errStr; + } else if (result != IDOK) { + WMSG0("ExtractThreadToBuffer (data) failed\n"); + return errStr; + } - ASSERT(lenCopy == (long) collEnt.dataLen); - buf += collEnt.dataLen; - remLen -= collEnt.dataLen; - } else { - ASSERT(collEnt.dataLen == 0); - } + ASSERT(lenCopy == (long) collEnt.dataLen); + buf += collEnt.dataLen; + remLen -= collEnt.dataLen; + } else { + ASSERT(collEnt.dataLen == 0); + } - if (pEntry->GetHasRsrcFork()) { - bufCopy = (char*) buf; - lenCopy = remLen; - which = GenericEntry::kRsrcThread; + if (pEntry->GetHasRsrcFork()) { + bufCopy = (char*) buf; + lenCopy = remLen; + which = GenericEntry::kRsrcThread; - result = pEntry->ExtractThreadToBuffer(which, &bufCopy, &lenCopy, - &dummyStr); - if (result == IDCANCEL) { - errStr.LoadString(IDS_CANCELLED); - return errStr; - } else if (result != IDOK) { - WMSG0("ExtractThreadToBuffer (rsrc) failed\n"); - return errStr; - } + result = pEntry->ExtractThreadToBuffer(which, &bufCopy, &lenCopy, + &dummyStr); + if (result == IDCANCEL) { + errStr.LoadString(IDS_CANCELLED); + return errStr; + } else if (result != IDOK) { + WMSG0("ExtractThreadToBuffer (rsrc) failed\n"); + return errStr; + } - ASSERT(lenCopy == (long) collEnt.rsrcLen); - buf += collEnt.rsrcLen; - remLen -= collEnt.rsrcLen; - } + ASSERT(lenCopy == (long) collEnt.rsrcLen); + buf += collEnt.rsrcLen; + remLen -= collEnt.rsrcLen; + } - if (pEntry->GetHasComment()) { -#if 0 // CMMT FIX - bufCopy = (char*) buf; - lenCopy = remLen; - which = GenericEntry::kCommentThread; + if (pEntry->GetHasComment()) { +#if 0 // CMMT FIX + bufCopy = (char*) buf; + lenCopy = remLen; + which = GenericEntry::kCommentThread; - result = pEntry->ExtractThreadToBuffer(which, &bufCopy, &lenCopy); - if (result == IDCANCEL) { - errStr.LoadString(IDS_CANCELLED); - return errStr; - } else if (result != IDOK) - return errStr; + result = pEntry->ExtractThreadToBuffer(which, &bufCopy, &lenCopy); + if (result == IDCANCEL) { + errStr.LoadString(IDS_CANCELLED); + return errStr; + } else if (result != IDOK) + return errStr; - ASSERT(lenCopy == (long) collEnt.cmmtLen); - buf += collEnt.cmmtLen; - remLen -= collEnt.cmmtLen; + ASSERT(lenCopy == (long) collEnt.cmmtLen); + buf += collEnt.cmmtLen; + remLen -= collEnt.cmmtLen; #else - ASSERT(collEnt.cmmtLen == 0); + ASSERT(collEnt.cmmtLen == 0); #endif - } + } - *pBuf = buf; - *pBufLen = remLen; - return ""; + *pBuf = buf; + *pBufLen = remLen; + return ""; } /* * ========================================================================== - * Paste + * Paste * ========================================================================== */ @@ -618,22 +618,22 @@ MainWindow::CopyToCollection(GenericEntry* pEntry, void** pBuf, long* pBufLen) void MainWindow::OnEditPaste(void) { - bool pasteJunkPaths = fPreferences.GetPrefBool(kPrPasteJunkPaths); + bool pasteJunkPaths = fPreferences.GetPrefBool(kPrPasteJunkPaths); - DoPaste(pasteJunkPaths); + DoPaste(pasteJunkPaths); } void MainWindow::OnUpdateEditPaste(CCmdUI* pCmdUI) { - bool dataAvailable = false; - UINT myFormat; + bool dataAvailable = false; + UINT myFormat; - myFormat = RegisterClipboardFormat(kClipboardFmtName); - if (myFormat != 0 && IsClipboardFormatAvailable(myFormat)) - dataAvailable = true; + myFormat = RegisterClipboardFormat(kClipboardFmtName); + if (myFormat != 0 && IsClipboardFormatAvailable(myFormat)) + dataAvailable = true; - pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() && - dataAvailable); + pCmdUI->Enable(fpContentList != nil && !fpOpenArchive->IsReadOnly() && + dataAvailable); } /* @@ -643,35 +643,35 @@ MainWindow::OnUpdateEditPaste(CCmdUI* pCmdUI) void MainWindow::OnEditPasteSpecial(void) { - PasteSpecialDialog dlg; - bool pasteJunkPaths = fPreferences.GetPrefBool(kPrPasteJunkPaths); + PasteSpecialDialog dlg; + bool pasteJunkPaths = fPreferences.GetPrefBool(kPrPasteJunkPaths); - // invert the meaning, so non-default mode is default in dialog - if (pasteJunkPaths) - dlg.fPasteHow = PasteSpecialDialog::kPastePaths; - else - dlg.fPasteHow = PasteSpecialDialog::kPasteNoPaths; - if (dlg.DoModal() != IDOK) - return; + // invert the meaning, so non-default mode is default in dialog + if (pasteJunkPaths) + dlg.fPasteHow = PasteSpecialDialog::kPastePaths; + else + dlg.fPasteHow = PasteSpecialDialog::kPasteNoPaths; + if (dlg.DoModal() != IDOK) + return; - switch (dlg.fPasteHow) { - case PasteSpecialDialog::kPastePaths: - pasteJunkPaths = false; - break; - case PasteSpecialDialog::kPasteNoPaths: - pasteJunkPaths = true; - break; - default: - assert(false); - break; - } + switch (dlg.fPasteHow) { + case PasteSpecialDialog::kPastePaths: + pasteJunkPaths = false; + break; + case PasteSpecialDialog::kPasteNoPaths: + pasteJunkPaths = true; + break; + default: + assert(false); + break; + } - DoPaste(pasteJunkPaths); + DoPaste(pasteJunkPaths); } void MainWindow::OnUpdateEditPasteSpecial(CCmdUI* pCmdUI) { - OnUpdateEditPaste(pCmdUI); + OnUpdateEditPaste(pCmdUI); } /* @@ -680,80 +680,80 @@ MainWindow::OnUpdateEditPasteSpecial(CCmdUI* pCmdUI) void MainWindow::DoPaste(bool pasteJunkPaths) { - CString errStr, buildStr; - UINT format = 0; - UINT myFormat; - bool isOpen = false; + CString errStr, buildStr; + UINT format = 0; + UINT myFormat; + bool isOpen = false; - if (fpContentList == nil || fpOpenArchive->IsReadOnly()) { - ASSERT(false); - return; - } + if (fpContentList == nil || fpOpenArchive->IsReadOnly()) { + ASSERT(false); + return; + } - myFormat = RegisterClipboardFormat(kClipboardFmtName); - if (myFormat == 0) { - errStr.LoadString(IDS_CLIPBOARD_REGFAILED); - ShowFailureMsg(this, errStr, IDS_FAILED); - goto bail; - } - WMSG1("myFormat = %u\n", myFormat); + myFormat = RegisterClipboardFormat(kClipboardFmtName); + if (myFormat == 0) { + errStr.LoadString(IDS_CLIPBOARD_REGFAILED); + ShowFailureMsg(this, errStr, IDS_FAILED); + goto bail; + } + WMSG1("myFormat = %u\n", myFormat); - if (OpenClipboard() == false) { - errStr.LoadString(IDS_CLIPBOARD_OPENFAILED); - ShowFailureMsg(this, errStr, IDS_FAILED); - goto bail;; - } - isOpen = true; + if (OpenClipboard() == false) { + errStr.LoadString(IDS_CLIPBOARD_OPENFAILED); + ShowFailureMsg(this, errStr, IDS_FAILED); + goto bail;; + } + isOpen = true; - WMSG1("Found %d clipboard formats\n", CountClipboardFormats()); - while ((format = EnumClipboardFormats(format)) != 0) { - CString tmpStr; - tmpStr.Format(" %u", format); - buildStr += tmpStr; - } - WMSG1(" %s\n", buildStr); + WMSG1("Found %d clipboard formats\n", CountClipboardFormats()); + while ((format = EnumClipboardFormats(format)) != 0) { + CString tmpStr; + tmpStr.Format(" %u", format); + buildStr += tmpStr; + } + WMSG1(" %s\n", buildStr); #if 0 - if (IsClipboardFormatAvailable(CF_HDROP)) { - errStr.LoadString(IDS_CLIPBOARD_NO_HDROP); - ShowFailureMsg(this, errStr, IDS_FAILED); - goto bail; - } + if (IsClipboardFormatAvailable(CF_HDROP)) { + errStr.LoadString(IDS_CLIPBOARD_NO_HDROP); + ShowFailureMsg(this, errStr, IDS_FAILED); + goto bail; + } #endif - /* impossible unless OnUpdateEditPaste was bypassed */ - if (!IsClipboardFormatAvailable(myFormat)) { - errStr.LoadString(IDS_CLIPBOARD_NOTFOUND); - ShowFailureMsg(this, errStr, IDS_FAILED); - goto bail; - } + /* impossible unless OnUpdateEditPaste was bypassed */ + if (!IsClipboardFormatAvailable(myFormat)) { + errStr.LoadString(IDS_CLIPBOARD_NOTFOUND); + ShowFailureMsg(this, errStr, IDS_FAILED); + goto bail; + } - WMSG1("+++ total data on clipboard: %ld bytes\n", - GetClipboardContentLen()); + WMSG1("+++ total data on clipboard: %ld bytes\n", + GetClipboardContentLen()); - HGLOBAL hGlobal; - LPVOID pGlobal; + HGLOBAL hGlobal; + LPVOID pGlobal; - hGlobal = GetClipboardData(myFormat); - if (hGlobal == nil) { - ASSERT(false); - goto bail; - } - pGlobal = GlobalLock(hGlobal); - ASSERT(pGlobal != nil); - errStr = ProcessClipboard(pGlobal, GlobalSize(hGlobal), pasteJunkPaths); - fpContentList->Reload(); + hGlobal = GetClipboardData(myFormat); + if (hGlobal == nil) { + ASSERT(false); + goto bail; + } + pGlobal = GlobalLock(hGlobal); + ASSERT(pGlobal != nil); + errStr = ProcessClipboard(pGlobal, GlobalSize(hGlobal), pasteJunkPaths); + fpContentList->Reload(); - if (!errStr.IsEmpty()) - ShowFailureMsg(this, errStr, IDS_FAILED); - else - SuccessBeep(); + if (!errStr.IsEmpty()) + ShowFailureMsg(this, errStr, IDS_FAILED); + else + SuccessBeep(); - GlobalUnlock(hGlobal); + GlobalUnlock(hGlobal); bail: - if (isOpen) - CloseClipboard(); + if (isOpen) + CloseClipboard(); } /* @@ -764,189 +764,189 @@ bail: CString MainWindow::ProcessClipboard(const void* vbuf, long bufLen, bool pasteJunkPaths) { - FileCollection fileColl; - CString errMsg, storagePrefix; - const unsigned char* buf = (const unsigned char*) vbuf; - DiskImgLib::A2File* pTargetSubdir = nil; - XferFileOptions xferOpts; - bool xferPrepped = false; + FileCollection fileColl; + CString errMsg, storagePrefix; + const unsigned char* buf = (const unsigned char*) vbuf; + DiskImgLib::A2File* pTargetSubdir = nil; + XferFileOptions xferOpts; + bool xferPrepped = false; - /* set a standard error message */ - errMsg.LoadString(IDS_CLIPBOARD_READFAILURE); + /* set a standard error message */ + errMsg.LoadString(IDS_CLIPBOARD_READFAILURE); - /* - * Pull the header out. - */ - if (bufLen < sizeof(fileColl)) { - WMSG0("Clipboard contents too small!\n"); - goto bail; - } - memcpy(&fileColl, buf, sizeof(fileColl)); + /* + * Pull the header out. + */ + if (bufLen < sizeof(fileColl)) { + WMSG0("Clipboard contents too small!\n"); + goto bail; + } + memcpy(&fileColl, buf, sizeof(fileColl)); - /* - * Verify the length. Win98 seems to like to round things up to 16-byte - * boundaries, which screws up our "bufLen > 0" while condition below. - */ - if ((long) fileColl.length > bufLen) { - WMSG2("GLITCH: stored len=%ld, clip len=%ld\n", - fileColl.length, bufLen); - goto bail; - } - if (bufLen > (long) fileColl.length) { - /* trim off extra */ - WMSG2("NOTE: Windows reports excess length (%ld vs %ld)\n", - fileColl.length, bufLen); - bufLen = fileColl.length; - } + /* + * Verify the length. Win98 seems to like to round things up to 16-byte + * boundaries, which screws up our "bufLen > 0" while condition below. + */ + if ((long) fileColl.length > bufLen) { + WMSG2("GLITCH: stored len=%ld, clip len=%ld\n", + fileColl.length, bufLen); + goto bail; + } + if (bufLen > (long) fileColl.length) { + /* trim off extra */ + WMSG2("NOTE: Windows reports excess length (%ld vs %ld)\n", + fileColl.length, bufLen); + bufLen = fileColl.length; + } - buf += sizeof(fileColl); - bufLen -= sizeof(fileColl); + buf += sizeof(fileColl); + bufLen -= sizeof(fileColl); - WMSG4("FileCollection found: vers=%d off=%d len=%ld count=%ld\n", - fileColl.version, fileColl.dataOffset, fileColl.length, - fileColl.count); - if (fileColl.count == 0) { - /* nothing to do? */ - ASSERT(false); - return errMsg; - } + WMSG4("FileCollection found: vers=%d off=%d len=%ld count=%ld\n", + fileColl.version, fileColl.dataOffset, fileColl.length, + fileColl.count); + if (fileColl.count == 0) { + /* nothing to do? */ + ASSERT(false); + return errMsg; + } - /* - * Figure out where we want to put the files. For a disk archive - * this can be complicated. - * - * The target DiskFS (which could be a sub-volume) gets tucked into - * the xferOpts. - */ - if (fpOpenArchive->GetArchiveKind() == GenericArchive::kArchiveDiskImage) { - if (!ChooseAddTarget(&pTargetSubdir, &xferOpts.fpTargetFS)) - return ""; - } - fpOpenArchive->XferPrepare(&xferOpts); - xferPrepped = true; + /* + * Figure out where we want to put the files. For a disk archive + * this can be complicated. + * + * The target DiskFS (which could be a sub-volume) gets tucked into + * the xferOpts. + */ + if (fpOpenArchive->GetArchiveKind() == GenericArchive::kArchiveDiskImage) { + if (!ChooseAddTarget(&pTargetSubdir, &xferOpts.fpTargetFS)) + return ""; + } + fpOpenArchive->XferPrepare(&xferOpts); + xferPrepped = true; - if (pTargetSubdir != nil) { - storagePrefix = pTargetSubdir->GetPathName(); - WMSG1("--- using storagePrefix '%s'\n", (const char*) storagePrefix); - } + if (pTargetSubdir != nil) { + storagePrefix = pTargetSubdir->GetPathName(); + WMSG1("--- using storagePrefix '%s'\n", (const char*) storagePrefix); + } - /* - * Set up a progress dialog to track it. - */ - ASSERT(fpActionProgress == nil); - fpActionProgress = new ActionProgressDialog; - fpActionProgress->Create(ActionProgressDialog::kActionAdd, this); - fpActionProgress->SetArcName("Clipboard data"); + /* + * Set up a progress dialog to track it. + */ + ASSERT(fpActionProgress == nil); + fpActionProgress = new ActionProgressDialog; + fpActionProgress->Create(ActionProgressDialog::kActionAdd, this); + fpActionProgress->SetArcName("Clipboard data"); - /* - * Loop over all files. - */ - WMSG1("+++ Starting paste, bufLen=%ld\n", bufLen); - while (bufLen > 0) { - FileCollectionEntry collEnt; - CString fileName, processErrStr; + /* + * Loop over all files. + */ + WMSG1("+++ Starting paste, bufLen=%ld\n", bufLen); + while (bufLen > 0) { + FileCollectionEntry collEnt; + CString fileName, processErrStr; - /* read the entry info */ - if (bufLen < sizeof(collEnt)) { - WMSG2("GLITCH: bufLen=%ld, sizeof(collEnt)=%d\n", - bufLen, sizeof(collEnt)); - ASSERT(false); - goto bail; - } - memcpy(&collEnt, buf, sizeof(collEnt)); - if (collEnt.signature != kEntrySignature) { - ASSERT(false); - goto bail; - } + /* read the entry info */ + if (bufLen < sizeof(collEnt)) { + WMSG2("GLITCH: bufLen=%ld, sizeof(collEnt)=%d\n", + bufLen, sizeof(collEnt)); + ASSERT(false); + goto bail; + } + memcpy(&collEnt, buf, sizeof(collEnt)); + if (collEnt.signature != kEntrySignature) { + ASSERT(false); + goto bail; + } - /* advance to the start of data */ - if (bufLen < collEnt.dataOffset) { - ASSERT(false); - goto bail; - } - buf += collEnt.dataOffset; - bufLen -= collEnt.dataOffset; + /* advance to the start of data */ + if (bufLen < collEnt.dataOffset) { + ASSERT(false); + goto bail; + } + buf += collEnt.dataOffset; + bufLen -= collEnt.dataOffset; - /* extract the filename */ - if (bufLen < collEnt.fileNameLen) { - ASSERT(false); - goto bail; - } - fileName = buf; - buf += collEnt.fileNameLen; - bufLen -= collEnt.fileNameLen; + /* extract the filename */ + if (bufLen < collEnt.fileNameLen) { + ASSERT(false); + goto bail; + } + fileName = buf; + buf += collEnt.fileNameLen; + bufLen -= collEnt.fileNameLen; - //WMSG1("+++ pasting '%s'\n", fileName); + //WMSG1("+++ pasting '%s'\n", fileName); - /* strip the path (if requested) and prepend the storage prefix */ - ASSERT(fileName.GetLength() == collEnt.fileNameLen -1); - if (pasteJunkPaths && collEnt.fssep != '\0') { - int idx; - idx = fileName.ReverseFind(collEnt.fssep); - if (idx >= 0) - fileName = fileName.Right(fileName.GetLength() - idx -1); - } - if (!storagePrefix.IsEmpty()) { - CString tmpStr, tmpFileName; - tmpFileName = fileName; - if (collEnt.fssep == '\0') { - tmpFileName.Replace(':', '_'); // strip any ':'s in the name - collEnt.fssep = ':'; // define an fssep - } + /* strip the path (if requested) and prepend the storage prefix */ + ASSERT(fileName.GetLength() == collEnt.fileNameLen -1); + if (pasteJunkPaths && collEnt.fssep != '\0') { + int idx; + idx = fileName.ReverseFind(collEnt.fssep); + if (idx >= 0) + fileName = fileName.Right(fileName.GetLength() - idx -1); + } + if (!storagePrefix.IsEmpty()) { + CString tmpStr, tmpFileName; + tmpFileName = fileName; + if (collEnt.fssep == '\0') { + tmpFileName.Replace(':', '_'); // strip any ':'s in the name + collEnt.fssep = ':'; // define an fssep + } - tmpStr = storagePrefix; + tmpStr = storagePrefix; - /* storagePrefix fssep is always ':'; change it to match */ - if (collEnt.fssep != ':') - tmpStr.Replace(':', collEnt.fssep); + /* storagePrefix fssep is always ':'; change it to match */ + if (collEnt.fssep != ':') + tmpStr.Replace(':', collEnt.fssep); - tmpStr += collEnt.fssep; - tmpStr += tmpFileName; - fileName = tmpStr; + tmpStr += collEnt.fssep; + tmpStr += tmpFileName; + fileName = tmpStr; - } - fpActionProgress->SetFileName(fileName); + } + fpActionProgress->SetFileName(fileName); - /* make sure the data is there */ - if (bufLen < (long) (collEnt.dataLen + collEnt.rsrcLen + collEnt.cmmtLen)) - { - ASSERT(false); - goto bail; - } + /* make sure the data is there */ + if (bufLen < (long) (collEnt.dataLen + collEnt.rsrcLen + collEnt.cmmtLen)) + { + ASSERT(false); + goto bail; + } - /* - * Process the entry. - * - * If the user hits "cancel" in the progress dialog we'll get thrown - * back out. For the time being I'm just treating it like any other - * failure. - */ - processErrStr = ProcessClipboardEntry(&collEnt, fileName, buf, bufLen); - if (!processErrStr.IsEmpty()) { - errMsg.Format("Unable to paste '%s': %s.", - (const char*) fileName, (const char*) processErrStr); - goto bail; - } - - buf += collEnt.dataLen + collEnt.rsrcLen + collEnt.cmmtLen; - bufLen -= collEnt.dataLen + collEnt.rsrcLen + collEnt.cmmtLen; - } + /* + * Process the entry. + * + * If the user hits "cancel" in the progress dialog we'll get thrown + * back out. For the time being I'm just treating it like any other + * failure. + */ + processErrStr = ProcessClipboardEntry(&collEnt, fileName, buf, bufLen); + if (!processErrStr.IsEmpty()) { + errMsg.Format("Unable to paste '%s': %s.", + (const char*) fileName, (const char*) processErrStr); + goto bail; + } + + buf += collEnt.dataLen + collEnt.rsrcLen + collEnt.cmmtLen; + bufLen -= collEnt.dataLen + collEnt.rsrcLen + collEnt.cmmtLen; + } - ASSERT(bufLen == 0); - errMsg = ""; + ASSERT(bufLen == 0); + errMsg = ""; bail: - if (xferPrepped) { - if (errMsg.IsEmpty()) - fpOpenArchive->XferFinish(this); - else - fpOpenArchive->XferAbort(this); - } - if (fpActionProgress != nil) { - fpActionProgress->Cleanup(this); - fpActionProgress = nil; - } - return errMsg; + if (xferPrepped) { + if (errMsg.IsEmpty()) + fpOpenArchive->XferFinish(this); + else + fpOpenArchive->XferAbort(this); + } + if (fpActionProgress != nil) { + fpActionProgress->Cleanup(this); + fpActionProgress = nil; + } + return errMsg; } /* @@ -959,121 +959,121 @@ bail: */ CString MainWindow::ProcessClipboardEntry(const FileCollectionEntry* pCollEnt, - const char* pathName, const unsigned char* buf, long remLen) + const char* pathName, const unsigned char* buf, long remLen) { - GenericArchive::FileDetails::FileKind entryKind; - GenericArchive::FileDetails details; - unsigned char* dataBuf = nil; - unsigned char* rsrcBuf = nil; - long dataLen, rsrcLen, cmmtLen; - CString errMsg; + GenericArchive::FileDetails::FileKind entryKind; + GenericArchive::FileDetails details; + unsigned char* dataBuf = nil; + unsigned char* rsrcBuf = nil; + long dataLen, rsrcLen, cmmtLen; + CString errMsg; - entryKind = (GenericArchive::FileDetails::FileKind) pCollEnt->entryKind; - WMSG2(" Processing '%s' (%d)\n", pathName, entryKind); + entryKind = (GenericArchive::FileDetails::FileKind) pCollEnt->entryKind; + WMSG2(" Processing '%s' (%d)\n", pathName, entryKind); - details.entryKind = entryKind; - details.origName = "Clipboard"; - details.storageName = pathName; - details.fileSysFmt = (DiskImg::FSFormat) pCollEnt->sourceFS; - details.fileSysInfo = pCollEnt->fssep; - details.access = pCollEnt->access; - details.fileType = pCollEnt->fileType; - details.extraType = pCollEnt->auxType; - GenericArchive::UNIXTimeToDateTime(&pCollEnt->createWhen, - &details.createWhen); - GenericArchive::UNIXTimeToDateTime(&pCollEnt->modWhen, - &details.modWhen); - time_t now = time(nil); - GenericArchive::UNIXTimeToDateTime(&now, &details.archiveWhen); + details.entryKind = entryKind; + details.origName = "Clipboard"; + details.storageName = pathName; + details.fileSysFmt = (DiskImg::FSFormat) pCollEnt->sourceFS; + details.fileSysInfo = pCollEnt->fssep; + details.access = pCollEnt->access; + details.fileType = pCollEnt->fileType; + details.extraType = pCollEnt->auxType; + GenericArchive::UNIXTimeToDateTime(&pCollEnt->createWhen, + &details.createWhen); + GenericArchive::UNIXTimeToDateTime(&pCollEnt->modWhen, + &details.modWhen); + time_t now = time(nil); + GenericArchive::UNIXTimeToDateTime(&now, &details.archiveWhen); - /* - * Because of the way XferFile works, we need to make a copy of - * the data. (For NufxLib, it's going to gather up all of the - * data and flush it all at once, so it needs to own the memory.) - * - * Ideally we'd use a different interface that didn't require a - * data copy -- NufxLib can do it that way as well -- but it's - * not worth maintaining two separate interfaces. - * - * This approach does allow the xfer code to handle DOS high-ASCII - * text conversions in place, though. If we didn't do it this way - * we'd have to make a copy in the xfer code to avoid contaminating - * the clipboard data. That would be more efficient, but probably - * a bit messier. - * - * The stuff below figures out which forks we're expected to have based - * on the file type info. This helps us distinguish between a file - * with a zero-length fork and a file without that kind of fork. - */ - bool hasData = false; - bool hasRsrc = false; - if (details.entryKind == GenericArchive::FileDetails::kFileKindDataFork) { - hasData = true; - details.storageType = kNuStorageSeedling; - } else if (details.entryKind == GenericArchive::FileDetails::kFileKindRsrcFork) { - hasRsrc = true; - details.storageType = kNuStorageExtended; - } else if (details.entryKind == GenericArchive::FileDetails::kFileKindBothForks) { - hasData = hasRsrc = true; - details.storageType = kNuStorageExtended; - } else if (details.entryKind == GenericArchive::FileDetails::kFileKindDiskImage) { - hasData = true; - details.storageType = kNuStorageSeedling; - } else if (details.entryKind == GenericArchive::FileDetails::kFileKindDirectory) { - details.storageType = kNuStorageDirectory; - } else { - ASSERT(false); - return "Internal error."; - } + /* + * Because of the way XferFile works, we need to make a copy of + * the data. (For NufxLib, it's going to gather up all of the + * data and flush it all at once, so it needs to own the memory.) + * + * Ideally we'd use a different interface that didn't require a + * data copy -- NufxLib can do it that way as well -- but it's + * not worth maintaining two separate interfaces. + * + * This approach does allow the xfer code to handle DOS high-ASCII + * text conversions in place, though. If we didn't do it this way + * we'd have to make a copy in the xfer code to avoid contaminating + * the clipboard data. That would be more efficient, but probably + * a bit messier. + * + * The stuff below figures out which forks we're expected to have based + * on the file type info. This helps us distinguish between a file + * with a zero-length fork and a file without that kind of fork. + */ + bool hasData = false; + bool hasRsrc = false; + if (details.entryKind == GenericArchive::FileDetails::kFileKindDataFork) { + hasData = true; + details.storageType = kNuStorageSeedling; + } else if (details.entryKind == GenericArchive::FileDetails::kFileKindRsrcFork) { + hasRsrc = true; + details.storageType = kNuStorageExtended; + } else if (details.entryKind == GenericArchive::FileDetails::kFileKindBothForks) { + hasData = hasRsrc = true; + details.storageType = kNuStorageExtended; + } else if (details.entryKind == GenericArchive::FileDetails::kFileKindDiskImage) { + hasData = true; + details.storageType = kNuStorageSeedling; + } else if (details.entryKind == GenericArchive::FileDetails::kFileKindDirectory) { + details.storageType = kNuStorageDirectory; + } else { + ASSERT(false); + return "Internal error."; + } - if (hasData) { - if (pCollEnt->dataLen == 0) { - dataBuf = new unsigned char[1]; - dataLen = 0; - } else { - dataLen = pCollEnt->dataLen; - dataBuf = new unsigned char[dataLen]; - if (dataBuf == nil) - return "memory allocation failed."; - memcpy(dataBuf, buf, dataLen); - buf += dataLen; - remLen -= dataLen; - } - } else { - ASSERT(dataBuf == nil); - dataLen = -1; - } + if (hasData) { + if (pCollEnt->dataLen == 0) { + dataBuf = new unsigned char[1]; + dataLen = 0; + } else { + dataLen = pCollEnt->dataLen; + dataBuf = new unsigned char[dataLen]; + if (dataBuf == nil) + return "memory allocation failed."; + memcpy(dataBuf, buf, dataLen); + buf += dataLen; + remLen -= dataLen; + } + } else { + ASSERT(dataBuf == nil); + dataLen = -1; + } - if (hasRsrc) { - if (pCollEnt->rsrcLen == 0) { - rsrcBuf = new unsigned char[1]; - rsrcLen = 0; - } else { - rsrcLen = pCollEnt->rsrcLen; - rsrcBuf = new unsigned char[rsrcLen]; - if (rsrcBuf == nil) - return "Memory allocation failed."; - memcpy(rsrcBuf, buf, rsrcLen); - buf += rsrcLen; - remLen -= rsrcLen; - } - } else { - ASSERT(rsrcBuf == nil); - rsrcLen = -1; - } + if (hasRsrc) { + if (pCollEnt->rsrcLen == 0) { + rsrcBuf = new unsigned char[1]; + rsrcLen = 0; + } else { + rsrcLen = pCollEnt->rsrcLen; + rsrcBuf = new unsigned char[rsrcLen]; + if (rsrcBuf == nil) + return "Memory allocation failed."; + memcpy(rsrcBuf, buf, rsrcLen); + buf += rsrcLen; + remLen -= rsrcLen; + } + } else { + ASSERT(rsrcBuf == nil); + rsrcLen = -1; + } - if (pCollEnt->cmmtLen > 0) { - cmmtLen = pCollEnt->cmmtLen; - /* CMMT FIX -- not supported by XferFile */ - } + if (pCollEnt->cmmtLen > 0) { + cmmtLen = pCollEnt->cmmtLen; + /* CMMT FIX -- not supported by XferFile */ + } - ASSERT(remLen >= 0); + ASSERT(remLen >= 0); - errMsg = fpOpenArchive->XferFile(&details, &dataBuf, dataLen, - &rsrcBuf, rsrcLen); - delete[] dataBuf; - delete[] rsrcBuf; - dataBuf = rsrcBuf = nil; + errMsg = fpOpenArchive->XferFile(&details, &dataBuf, dataLen, + &rsrcBuf, rsrcLen); + delete[] dataBuf; + delete[] rsrcBuf; + dataBuf = rsrcBuf = nil; - return errMsg; + return errMsg; } diff --git a/app/ConfirmOverwriteDialog.cpp b/app/ConfirmOverwriteDialog.cpp index e5d910a..673a75b 100644 --- a/app/ConfirmOverwriteDialog.cpp +++ b/app/ConfirmOverwriteDialog.cpp @@ -14,12 +14,12 @@ /* * ========================================================================== - * RenameOverwriteDialog + * RenameOverwriteDialog * ========================================================================== */ BEGIN_MESSAGE_MAP(RenameOverwriteDialog, CDialog) - ON_WM_HELPINFO() + ON_WM_HELPINFO() END_MESSAGE_MAP() /* @@ -28,13 +28,13 @@ END_MESSAGE_MAP() BOOL RenameOverwriteDialog::OnInitDialog(void) { - CWnd* pWnd; + CWnd* pWnd; - pWnd = GetDlgItem(IDC_RENOVWR_SOURCE_NAME); - ASSERT(pWnd != nil); - pWnd->SetWindowText(fNewFileSource); + pWnd = GetDlgItem(IDC_RENOVWR_SOURCE_NAME); + ASSERT(pWnd != nil); + pWnd->SetWindowText(fNewFileSource); - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } /* @@ -43,42 +43,42 @@ RenameOverwriteDialog::OnInitDialog(void) void RenameOverwriteDialog::DoDataExchange(CDataExchange* pDX) { - DDX_Text(pDX, IDC_RENOVWR_ORIG_NAME, fExistingFile); - DDX_Text(pDX, IDC_RENOVWR_NEW_NAME, fNewName); + DDX_Text(pDX, IDC_RENOVWR_ORIG_NAME, fExistingFile); + DDX_Text(pDX, IDC_RENOVWR_NEW_NAME, fNewName); - /* validate the path field */ - if (pDX->m_bSaveAndValidate) { - if (fNewName.IsEmpty()) { - MessageBox("You must specify a new name.", - "CiderPress", MB_OK); - pDX->Fail(); - } + /* validate the path field */ + if (pDX->m_bSaveAndValidate) { + if (fNewName.IsEmpty()) { + MessageBox("You must specify a new name.", + "CiderPress", MB_OK); + pDX->Fail(); + } - // we *could* try to validate the path here... - } + // we *could* try to validate the path here... + } } BOOL RenameOverwriteDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* * ========================================================================== - * ConfirmOverwriteDialog + * ConfirmOverwriteDialog * ========================================================================== */ BEGIN_MESSAGE_MAP(ConfirmOverwriteDialog, CDialog) - ON_BN_CLICKED(IDC_OVWR_YES, OnYes) - ON_BN_CLICKED(IDC_OVWR_YESALL, OnYesToAll) - ON_BN_CLICKED(IDC_OVWR_NO, OnNo) - ON_BN_CLICKED(IDC_OVWR_NOALL, OnNoToAll) - ON_BN_CLICKED(IDC_OVWR_RENAME, OnRename) - ON_WM_HELPINFO() + ON_BN_CLICKED(IDC_OVWR_YES, OnYes) + ON_BN_CLICKED(IDC_OVWR_YESALL, OnYesToAll) + ON_BN_CLICKED(IDC_OVWR_NO, OnNo) + ON_BN_CLICKED(IDC_OVWR_NOALL, OnNoToAll) + ON_BN_CLICKED(IDC_OVWR_RENAME, OnRename) + ON_WM_HELPINFO() END_MESSAGE_MAP() @@ -88,34 +88,34 @@ END_MESSAGE_MAP() BOOL ConfirmOverwriteDialog::OnInitDialog(void) { - CWnd* pWnd; - CString tmpStr, dateStr; + CWnd* pWnd; + CString tmpStr, dateStr; - pWnd = GetDlgItem(IDC_OVWR_EXIST_NAME); - ASSERT(pWnd != nil); - pWnd->SetWindowText(fExistingFile); + pWnd = GetDlgItem(IDC_OVWR_EXIST_NAME); + ASSERT(pWnd != nil); + pWnd->SetWindowText(fExistingFile); - pWnd = GetDlgItem(IDC_OVWR_EXIST_INFO); - ASSERT(pWnd != nil); - FormatDate(fExistingFileModWhen, &dateStr); - tmpStr.Format("Modified %s", dateStr); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_OVWR_EXIST_INFO); + ASSERT(pWnd != nil); + FormatDate(fExistingFileModWhen, &dateStr); + tmpStr.Format("Modified %s", dateStr); + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_OVWR_NEW_NAME); - ASSERT(pWnd != nil); - pWnd->SetWindowText(fNewFileSource); + pWnd = GetDlgItem(IDC_OVWR_NEW_NAME); + ASSERT(pWnd != nil); + pWnd->SetWindowText(fNewFileSource); - pWnd = GetDlgItem(IDC_OVWR_NEW_INFO); - ASSERT(pWnd != nil); - FormatDate(fNewFileModWhen, &dateStr); - tmpStr.Format("Modified %s", dateStr); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_OVWR_NEW_INFO); + ASSERT(pWnd != nil); + FormatDate(fNewFileModWhen, &dateStr); + tmpStr.Format("Modified %s", dateStr); + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_OVWR_RENAME); - ASSERT(pWnd != nil); - pWnd->EnableWindow(fAllowRename); + pWnd = GetDlgItem(IDC_OVWR_RENAME); + ASSERT(pWnd != nil); + pWnd->EnableWindow(fAllowRename); - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } /* @@ -124,8 +124,8 @@ ConfirmOverwriteDialog::OnInitDialog(void) BOOL ConfirmOverwriteDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* @@ -134,40 +134,40 @@ ConfirmOverwriteDialog::OnHelpInfo(HELPINFO* lpHelpInfo) void ConfirmOverwriteDialog::OnYes(void) { - fResultOverwrite = true; - CDialog::OnOK(); + fResultOverwrite = true; + CDialog::OnOK(); } void ConfirmOverwriteDialog::OnYesToAll(void) { - fResultOverwrite = true; - fResultApplyToAll = true; - CDialog::OnOK(); + fResultOverwrite = true; + fResultApplyToAll = true; + CDialog::OnOK(); } void ConfirmOverwriteDialog::OnNo(void) { - //fResultOverwrite = false; - CDialog::OnOK(); + //fResultOverwrite = false; + CDialog::OnOK(); } void ConfirmOverwriteDialog::OnNoToAll(void) { - //fResultOverwrite = true; - fResultApplyToAll = true; - CDialog::OnOK(); + //fResultOverwrite = true; + fResultApplyToAll = true; + CDialog::OnOK(); } void ConfirmOverwriteDialog::OnRename(void) { - RenameOverwriteDialog dlg; + RenameOverwriteDialog dlg; - dlg.fNewFileSource = fNewFileSource; - dlg.fExistingFile = fExistingFile; - dlg.fNewName = fExistingFile; - if (dlg.DoModal() == IDOK) { - fExistingFile = dlg.fNewName; - fResultRename = true; - CDialog::OnOK(); - } + dlg.fNewFileSource = fNewFileSource; + dlg.fExistingFile = fExistingFile; + dlg.fNewName = fExistingFile; + if (dlg.DoModal() == IDOK) { + fExistingFile = dlg.fNewName; + fResultRename = true; + CDialog::OnOK(); + } } diff --git a/app/ConfirmOverwriteDialog.h b/app/ConfirmOverwriteDialog.h index 8de5e96..c7ec23d 100644 --- a/app/ConfirmOverwriteDialog.h +++ b/app/ConfirmOverwriteDialog.h @@ -16,45 +16,45 @@ */ class ConfirmOverwriteDialog : public CDialog { public: - ConfirmOverwriteDialog(CWnd* pParentWnd = nil) : - CDialog(IDD_CONFIRM_OVERWRITE, pParentWnd) - { - fResultOverwrite = false; - fResultApplyToAll = false; - fResultRename = false; - fAllowRename = true; - fNewFileModWhen = -1; - fExistingFileModWhen = -1; - } - ~ConfirmOverwriteDialog(void) {} + ConfirmOverwriteDialog(CWnd* pParentWnd = nil) : + CDialog(IDD_CONFIRM_OVERWRITE, pParentWnd) + { + fResultOverwrite = false; + fResultApplyToAll = false; + fResultRename = false; + fAllowRename = true; + fNewFileModWhen = -1; + fExistingFileModWhen = -1; + } + ~ConfirmOverwriteDialog(void) {} - // name of file in archive (during extraction) or disk (for add) - CString fNewFileSource; - time_t fNewFileModWhen; + // name of file in archive (during extraction) or disk (for add) + CString fNewFileSource; + time_t fNewFileModWhen; - // full path of file being extracted onto (or record name for add) - CString fExistingFile; - time_t fExistingFileModWhen; + // full path of file being extracted onto (or record name for add) + CString fExistingFile; + time_t fExistingFileModWhen; - // result flags: yes/no/yes-all/no-all - bool fResultOverwrite; - bool fResultApplyToAll; - // if this flag is set, try again with updated "fExistingFile" value - bool fResultRename; - // set this to enable the "Rename" button - bool fAllowRename; + // result flags: yes/no/yes-all/no-all + bool fResultOverwrite; + bool fResultApplyToAll; + // if this flag is set, try again with updated "fExistingFile" value + bool fResultRename; + // set this to enable the "Rename" button + bool fAllowRename; private: - afx_msg void OnYes(void); - afx_msg void OnYesToAll(void); - afx_msg void OnNo(void); - afx_msg void OnNoToAll(void); - afx_msg void OnRename(void); - afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg void OnYes(void); + afx_msg void OnYesToAll(void); + afx_msg void OnNo(void); + afx_msg void OnNoToAll(void); + afx_msg void OnRename(void); + afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - virtual BOOL OnInitDialog(void); + virtual BOOL OnInitDialog(void); - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; /* @@ -67,27 +67,27 @@ private: */ class RenameOverwriteDialog : public CDialog { public: - RenameOverwriteDialog(CWnd* pParentWnd = nil) : - CDialog(IDD_RENAME_OVERWRITE, pParentWnd) - {} - ~RenameOverwriteDialog(void) {} + RenameOverwriteDialog(CWnd* pParentWnd = nil) : + CDialog(IDD_RENAME_OVERWRITE, pParentWnd) + {} + ~RenameOverwriteDialog(void) {} - // name of file on source medium - CString fNewFileSource; + // name of file on source medium + CString fNewFileSource; - // converted name, which already exists in destination medium - CString fExistingFile; + // converted name, which already exists in destination medium + CString fExistingFile; - // result: what the user has renamed it to - CString fNewName; + // result: what the user has renamed it to + CString fNewName; private: - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__CONFIRMOVERWRITEDIALOG__*/ \ No newline at end of file diff --git a/app/ContentList.cpp b/app/ContentList.cpp index 903bea1..1a74d78 100644 --- a/app/ContentList.cpp +++ b/app/ContentList.cpp @@ -14,23 +14,23 @@ const LPARAM kDescendingFlag = 0x0100; BEGIN_MESSAGE_MAP(ContentList, CListCtrl) - ON_WM_CREATE() - ON_WM_DESTROY() - ON_WM_SYSCOLORCHANGE() - //ON_WM_MOUSEWHEEL() - ON_NOTIFY_REFLECT(NM_DBLCLK, OnDoubleClick) - ON_NOTIFY_REFLECT(NM_RCLICK, OnRightClick) - ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick) - ON_NOTIFY_REFLECT(LVN_GETDISPINFO, OnGetDispInfo) + ON_WM_CREATE() + ON_WM_DESTROY() + ON_WM_SYSCOLORCHANGE() + //ON_WM_MOUSEWHEEL() + ON_NOTIFY_REFLECT(NM_DBLCLK, OnDoubleClick) + ON_NOTIFY_REFLECT(NM_RCLICK, OnRightClick) + ON_NOTIFY_REFLECT(LVN_COLUMNCLICK, OnColumnClick) + ON_NOTIFY_REFLECT(LVN_GETDISPINFO, OnGetDispInfo) END_MESSAGE_MAP() #if 0 afx_msg BOOL ContentList::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) { - WMSG0("MOUSE WHEEL\n"); - return CWnd::OnMouseWheel(nFlags, zDelta, pt); -// return TRUE; + WMSG0("MOUSE WHEEL\n"); + return CWnd::OnMouseWheel(nFlags, zDelta, pt); +// return TRUE; } #endif @@ -42,15 +42,15 @@ ContentList::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) BOOL ContentList::PreCreateWindow(CREATESTRUCT& cs) { - if (!CListCtrl::PreCreateWindow(cs)) - return FALSE; + if (!CListCtrl::PreCreateWindow(cs)) + return FALSE; - cs.style &= ~LVS_TYPEMASK; - cs.style |= LVS_REPORT; - cs.style |= LVS_SHOWSELALWAYS; - cs.dwExStyle |= WS_EX_CLIENTEDGE; + cs.style &= ~LVS_TYPEMASK; + cs.style |= LVS_REPORT; + cs.style |= LVS_SHOWSELALWAYS; + cs.dwExStyle |= WS_EX_CLIENTEDGE; - return TRUE; + return TRUE; } /* @@ -59,14 +59,14 @@ ContentList::PreCreateWindow(CREATESTRUCT& cs) void ContentList::PostNcDestroy(void) { - WMSG0("ContentList PostNcDestroy\n"); - delete this; + WMSG0("ContentList PostNcDestroy\n"); + delete this; } static inline int MaxVal(int a, int b) { - return a > b ? a : b; + return a > b ? a : b; } /* @@ -75,55 +75,55 @@ MaxVal(int a, int b) int ContentList::OnCreate(LPCREATESTRUCT lpcs) { - CString colHdrs[kNumVisibleColumns] = { - "Pathname", "Type", "Aux", "Mod Date", - "Format", "Size", "Ratio", "Packed", "Access" - }; // these should come from string table, not hard-coded - static int colFmt[kNumVisibleColumns] = { - LVCFMT_LEFT, LVCFMT_LEFT, LVCFMT_LEFT, LVCFMT_LEFT, - LVCFMT_LEFT, LVCFMT_RIGHT, LVCFMT_RIGHT, LVCFMT_RIGHT, LVCFMT_LEFT - }; + CString colHdrs[kNumVisibleColumns] = { + "Pathname", "Type", "Aux", "Mod Date", + "Format", "Size", "Ratio", "Packed", "Access" + }; // these should come from string table, not hard-coded + static int colFmt[kNumVisibleColumns] = { + LVCFMT_LEFT, LVCFMT_LEFT, LVCFMT_LEFT, LVCFMT_LEFT, + LVCFMT_LEFT, LVCFMT_RIGHT, LVCFMT_RIGHT, LVCFMT_RIGHT, LVCFMT_LEFT + }; - if (CListCtrl::OnCreate(lpcs) == -1) - return -1; + if (CListCtrl::OnCreate(lpcs) == -1) + return -1; - /* - * Create all of the columns with an initial width of 1, then set - * them to the correct values with NewColumnWidths() (which handles - * defaulted values). - */ - for (int i = 0; i < kNumVisibleColumns; i++) - InsertColumn(i, colHdrs[i], colFmt[i], 1); - NewColumnWidths(); + /* + * Create all of the columns with an initial width of 1, then set + * them to the correct values with NewColumnWidths() (which handles + * defaulted values). + */ + for (int i = 0; i < kNumVisibleColumns; i++) + InsertColumn(i, colHdrs[i], colFmt[i], 1); + NewColumnWidths(); - /* add images for list; this MUST be loaded before header images */ - LoadListImages(); - SetImageList(&fListImageList, LVSIL_SMALL); + /* add images for list; this MUST be loaded before header images */ + LoadListImages(); + SetImageList(&fListImageList, LVSIL_SMALL); - /* add our up/down arrow bitmaps */ - LoadHeaderImages(); - CHeaderCtrl* pHeader = GetHeaderCtrl(); - if (pHeader == nil) - WMSG0("GLITCH: couldn't get header ctrl\n"); - ASSERT(pHeader != NULL); - pHeader->SetImageList(&fHdrImageList); + /* add our up/down arrow bitmaps */ + LoadHeaderImages(); + CHeaderCtrl* pHeader = GetHeaderCtrl(); + if (pHeader == nil) + WMSG0("GLITCH: couldn't get header ctrl\n"); + ASSERT(pHeader != NULL); + pHeader->SetImageList(&fHdrImageList); - /* load the data and sort it */ - if (LoadData() != 0) { - MessageBox("Not all entries were loaded.", "Error", - MB_OK | MB_ICONSTOP); - /* keep going with what we've got; the error only affects display */ - } - NewSortOrder(); + /* load the data and sort it */ + if (LoadData() != 0) { + MessageBox("Not all entries were loaded.", "Error", + MB_OK | MB_ICONSTOP); + /* keep going with what we've got; the error only affects display */ + } + NewSortOrder(); - /* grab the focus so we get keyboard and mouse wheel messages */ - SetFocus(); + /* grab the focus so we get keyboard and mouse wheel messages */ + SetFocus(); - /* highlight/select entire line, not just filename */ - ListView_SetExtendedListViewStyleEx(m_hWnd, - LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); + /* highlight/select entire line, not just filename */ + ListView_SetExtendedListViewStyleEx(m_hWnd, + LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); - return 0; + return 0; } /* @@ -133,10 +133,10 @@ ContentList::OnCreate(LPCREATESTRUCT lpcs) void ContentList::OnDestroy(void) { - WMSG0("ContentList OnDestroy\n"); + WMSG0("ContentList OnDestroy\n"); - ExportColumnWidths(); - CListCtrl::OnDestroy(); + ExportColumnWidths(); + CListCtrl::OnDestroy(); } /* @@ -145,8 +145,8 @@ ContentList::OnDestroy(void) void ContentList::OnSysColorChange(void) { - fHdrImageList.DeleteImageList(); - LoadHeaderImages(); + fHdrImageList.DeleteImageList(); + LoadHeaderImages(); } /* @@ -156,19 +156,19 @@ ContentList::OnSysColorChange(void) void ContentList::OnColumnClick(NMHDR* pnmh, LRESULT* pResult) { - NM_LISTVIEW* pnmlv = (NM_LISTVIEW*) pnmh; + NM_LISTVIEW* pnmlv = (NM_LISTVIEW*) pnmh; - WMSG0("OnColumnClick!!\n"); + WMSG0("OnColumnClick!!\n"); - if (fpLayout->GetSortColumn() == pnmlv->iSubItem) - fpLayout->SetAscending(!fpLayout->GetAscending()); - else { - fpLayout->SetSortColumn(pnmlv->iSubItem); - fpLayout->SetAscending(true); - } + if (fpLayout->GetSortColumn() == pnmlv->iSubItem) + fpLayout->SetAscending(!fpLayout->GetAscending()); + else { + fpLayout->SetSortColumn(pnmlv->iSubItem); + fpLayout->SetAscending(true); + } - NewSortOrder(); - *pResult = 0; + NewSortOrder(); + *pResult = 0; } /* @@ -177,9 +177,9 @@ ContentList::OnColumnClick(NMHDR* pnmh, LRESULT* pResult) void ContentList::ExportColumnWidths(void) { - //WMSG0("ExportColumnWidths\n"); - for (int i = 0; i < kNumVisibleColumns; i++) - fpLayout->SetColumnWidth(i, GetColumnWidth(i)); + //WMSG0("ExportColumnWidths\n"); + for (int i = 0; i < kNumVisibleColumns; i++) + fpLayout->SetColumnWidth(i, GetColumnWidth(i)); } /* @@ -194,18 +194,18 @@ ContentList::ExportColumnWidths(void) void ContentList::NewColumnWidths(void) { - for (int i = 0; i < kNumVisibleColumns; i++) { - int width = fpLayout->GetColumnWidth(i); - if (width == ColumnLayout::kWidthDefaulted) { - width = GetDefaultWidth(i); - WMSG2("Defaulting width %d to %d\n", i, width); - fpLayout->SetColumnWidth(i, width); - } - SetColumnWidth(i, width); - } + for (int i = 0; i < kNumVisibleColumns; i++) { + int width = fpLayout->GetColumnWidth(i); + if (width == ColumnLayout::kWidthDefaulted) { + width = GetDefaultWidth(i); + WMSG2("Defaulting width %d to %d\n", i, width); + fpLayout->SetColumnWidth(i, width); + } + SetColumnWidth(i, width); + } } -#if 0 // replaced by GenericArchive reload flag +#if 0 // replaced by GenericArchive reload flag /* * If we're in the middle of an update, invalidate the contents of the list * so that we don't try to redraw from underlying storage that is no longer @@ -220,7 +220,7 @@ ContentList::NewColumnWidths(void) void ContentList::Invalidate(void) { - fInvalid = true; + fInvalid = true; } #endif @@ -238,37 +238,37 @@ ContentList::Invalidate(void) void ContentList::Reload(bool saveSelection) { - WMSG0("Reloading ContentList\n"); - CWaitCursor waitc; + WMSG0("Reloading ContentList\n"); + CWaitCursor waitc; -// fInvalid = false; - fpArchive->ClearReloadFlag(); +// fInvalid = false; + fpArchive->ClearReloadFlag(); - long* savedSel = nil; - long selCount = 0; + long* savedSel = nil; + long selCount = 0; - if (saveSelection) { - /* get the serials for the current selection (if any) */ - savedSel = GetSelectionSerials(&selCount); - } + if (saveSelection) { + /* get the serials for the current selection (if any) */ + savedSel = GetSelectionSerials(&selCount); + } - /* get the item that's currently at the top of the page */ - int top = GetTopIndex(); - int bottom = top + GetCountPerPage() -1; + /* get the item that's currently at the top of the page */ + int top = GetTopIndex(); + int bottom = top + GetCountPerPage() -1; - /* reload the list */ - LoadData(); - NewSortOrder(); + /* reload the list */ + LoadData(); + NewSortOrder(); - if (savedSel != nil) { - /* restore the selection */ - RestoreSelection(savedSel, selCount); - delete[] savedSel; - } + if (savedSel != nil) { + /* restore the selection */ + RestoreSelection(savedSel, selCount); + delete[] savedSel; + } - /* try to put us back in the same place */ - EnsureVisible(bottom, false); - EnsureVisible(top, false); + /* try to put us back in the same place */ + EnsureVisible(bottom, false); + EnsureVisible(top, false); } #if 1 @@ -280,37 +280,37 @@ ContentList::Reload(bool saveSelection) long* ContentList::GetSelectionSerials(long* pSelCount) { - long* savedSel = nil; - long maxCount; + long* savedSel = nil; + long maxCount; - maxCount = GetSelectedCount(); - WMSG1("GetSelectionSerials (maxCount=%d)\n", maxCount); + maxCount = GetSelectedCount(); + WMSG1("GetSelectionSerials (maxCount=%d)\n", maxCount); - if (maxCount > 0) { - savedSel = new long[maxCount]; - int idx = 0; + if (maxCount > 0) { + savedSel = new long[maxCount]; + int idx = 0; - POSITION posn; - posn = GetFirstSelectedItemPosition(); - ASSERT(posn != nil); - if (posn == nil) - return nil; - while (posn != nil) { - int num = GetNextSelectedItem(posn); - GenericEntry* pEntry = (GenericEntry*) GetItemData(num); + POSITION posn; + posn = GetFirstSelectedItemPosition(); + ASSERT(posn != nil); + if (posn == nil) + return nil; + while (posn != nil) { + int num = GetNextSelectedItem(posn); + GenericEntry* pEntry = (GenericEntry*) GetItemData(num); - if (idx == maxCount) { - ASSERT(false); - break; - } - savedSel[idx++] = pEntry->GetSelectionSerial(); - } + if (idx == maxCount) { + ASSERT(false); + break; + } + savedSel[idx++] = pEntry->GetSelectionSerial(); + } - ASSERT(idx == maxCount); - } + ASSERT(idx == maxCount); + } - *pSelCount = maxCount; - return savedSel; + *pSelCount = maxCount; + return savedSel; } /* @@ -319,27 +319,27 @@ ContentList::GetSelectionSerials(long* pSelCount) void ContentList::RestoreSelection(const long* savedSel, long selCount) { - WMSG1("RestoreSelection (selCount=%d)\n", selCount); - if (savedSel == nil) - return; + WMSG1("RestoreSelection (selCount=%d)\n", selCount); + if (savedSel == nil) + return; - int i, j; + int i, j; - for (i = GetItemCount()-1; i >= 0; i--) { - GenericEntry* pEntry = (GenericEntry*) GetItemData(i); + for (i = GetItemCount()-1; i >= 0; i--) { + GenericEntry* pEntry = (GenericEntry*) GetItemData(i); - for (j = 0; j < selCount; j++) { - if (pEntry->GetSelectionSerial() == savedSel[j] && - pEntry->GetSelectionSerial() != -1) - { - /* match! */ - if (SetItemState(i, LVIS_SELECTED, LVIS_SELECTED) == FALSE) { - WMSG1("WHOA: unable to set selected on item=%d\n", i); - } - break; - } - } - } + for (j = 0; j < selCount; j++) { + if (pEntry->GetSelectionSerial() == savedSel[j] && + pEntry->GetSelectionSerial() != -1) + { + /* match! */ + if (SetItemState(i, LVIS_SELECTED, LVIS_SELECTED) == FALSE) { + WMSG1("WHOA: unable to set selected on item=%d\n", i); + } + break; + } + } + } } #endif @@ -350,15 +350,15 @@ ContentList::RestoreSelection(const long* savedSel, long selCount) void ContentList::NewSortOrder(void) { - CWaitCursor wait; // automatically changes mouse to hourglass - int column; + CWaitCursor wait; // automatically changes mouse to hourglass + int column; - column = fpLayout->GetSortColumn(); - if (!fpLayout->GetAscending()) - column |= kDescendingFlag; + column = fpLayout->GetSortColumn(); + if (!fpLayout->GetAscending()) + column |= kDescendingFlag; - SetSortIcon(); - SortItems(CompareFunc, column); + SetSortIcon(); + SortItems(CompareFunc, column); } /* @@ -370,64 +370,64 @@ ContentList::NewSortOrder(void) /*static*/ void ContentList::MakeFileTypeDisplayString(const GenericEntry* pEntry, char* buf) { - bool isDir = - pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir || - pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory; + bool isDir = + pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir || + pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory; - if (pEntry->GetSourceFS() == DiskImg::kFormatMacHFS && isDir) { - /* HFS directories don't have types; fake it */ - ::lstrcpy(buf, "DIR/"); - } else if (!(pEntry->GetFileType() >= 0 && pEntry->GetFileType() <= 0xff)) - { - /* oversized type; assume it's HFS */ - char typeBuf[kFileTypeBufLen]; - MakeMacTypeString(pEntry->GetFileType(), typeBuf); + if (pEntry->GetSourceFS() == DiskImg::kFormatMacHFS && isDir) { + /* HFS directories don't have types; fake it */ + ::lstrcpy(buf, "DIR/"); + } else if (!(pEntry->GetFileType() >= 0 && pEntry->GetFileType() <= 0xff)) + { + /* oversized type; assume it's HFS */ + char typeBuf[kFileTypeBufLen]; + MakeMacTypeString(pEntry->GetFileType(), typeBuf); - switch (pEntry->GetRecordKind()) { - case GenericEntry::kRecordKindFile: - ::lstrcpy(buf, typeBuf); - break; - case GenericEntry::kRecordKindForkedFile: - ::sprintf(buf, "%s+", typeBuf); - break; - case GenericEntry::kRecordKindUnknown: - // shouldn't happen - ::sprintf(buf, "%s-", typeBuf); - break; - case GenericEntry::kRecordKindVolumeDir: - case GenericEntry::kRecordKindDirectory: - case GenericEntry::kRecordKindDisk: - default: - ASSERT(FALSE); - ::lstrcpy(buf, "!!!"); - break; - } - } else { - /* typical ProDOS-style stuff */ - switch (pEntry->GetRecordKind()) { - case GenericEntry::kRecordKindVolumeDir: - case GenericEntry::kRecordKindDirectory: - ::sprintf(buf, "%s/", pEntry->GetFileTypeString()); - break; - case GenericEntry::kRecordKindFile: - ::sprintf(buf, "%s", pEntry->GetFileTypeString()); - break; - case GenericEntry::kRecordKindForkedFile: - ::sprintf(buf, "%s+", pEntry->GetFileTypeString()); - break; - case GenericEntry::kRecordKindDisk: - ::lstrcpy(buf, "Disk"); - break; - case GenericEntry::kRecordKindUnknown: - // usually a GSHK-archived empty data file does this - ::sprintf(buf, "%s-", pEntry->GetFileTypeString()); - break; - default: - ASSERT(FALSE); - ::lstrcpy(buf, "!!!"); - break; - } - } + switch (pEntry->GetRecordKind()) { + case GenericEntry::kRecordKindFile: + ::lstrcpy(buf, typeBuf); + break; + case GenericEntry::kRecordKindForkedFile: + ::sprintf(buf, "%s+", typeBuf); + break; + case GenericEntry::kRecordKindUnknown: + // shouldn't happen + ::sprintf(buf, "%s-", typeBuf); + break; + case GenericEntry::kRecordKindVolumeDir: + case GenericEntry::kRecordKindDirectory: + case GenericEntry::kRecordKindDisk: + default: + ASSERT(FALSE); + ::lstrcpy(buf, "!!!"); + break; + } + } else { + /* typical ProDOS-style stuff */ + switch (pEntry->GetRecordKind()) { + case GenericEntry::kRecordKindVolumeDir: + case GenericEntry::kRecordKindDirectory: + ::sprintf(buf, "%s/", pEntry->GetFileTypeString()); + break; + case GenericEntry::kRecordKindFile: + ::sprintf(buf, "%s", pEntry->GetFileTypeString()); + break; + case GenericEntry::kRecordKindForkedFile: + ::sprintf(buf, "%s+", pEntry->GetFileTypeString()); + break; + case GenericEntry::kRecordKindDisk: + ::lstrcpy(buf, "Disk"); + break; + case GenericEntry::kRecordKindUnknown: + // usually a GSHK-archived empty data file does this + ::sprintf(buf, "%s-", pEntry->GetFileTypeString()); + break; + default: + ASSERT(FALSE); + ::lstrcpy(buf, "!!!"); + break; + } + } } /* @@ -439,16 +439,16 @@ ContentList::MakeFileTypeDisplayString(const GenericEntry* pEntry, char* buf) /*static*/ void ContentList::MakeMacTypeString(unsigned long val, char* buf) { - /* expand longword with ASCII type bytes */ - buf[0] = (unsigned char) (val >> 24); - buf[1] = (unsigned char) (val >> 16); - buf[2] = (unsigned char) (val >> 8); - buf[3] = (unsigned char) val; - buf[4] = '\0'; + /* expand longword with ASCII type bytes */ + buf[0] = (unsigned char) (val >> 24); + buf[1] = (unsigned char) (val >> 16); + buf[2] = (unsigned char) (val >> 8); + buf[3] = (unsigned char) val; + buf[4] = '\0'; - /* sanitize */ + /* sanitize */ while (*buf != '\0') { - *buf = DiskImg::MacToASCII(*buf); + *buf = DiskImg::MacToASCII(*buf); buf++; } } @@ -462,23 +462,23 @@ ContentList::MakeMacTypeString(unsigned long val, char* buf) /*static*/ void ContentList::MakeAuxTypeDisplayString(const GenericEntry* pEntry, char* buf) { - bool isDir = - pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir || - pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory; + bool isDir = + pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir || + pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory; - if (pEntry->GetSourceFS() == DiskImg::kFormatMacHFS && isDir) { - /* HFS directories don't have types; fake it */ - ::lstrcpy(buf, " "); - } else if (!(pEntry->GetFileType() >= 0 && pEntry->GetFileType() <= 0xff)) - { - /* oversized type; assume it's HFS */ - MakeMacTypeString(pEntry->GetAuxType(), buf); - } else { - if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDisk) - ::sprintf(buf, "%dk", pEntry->GetUncompressedLen() / 1024); - else - ::sprintf(buf, "$%04lX", pEntry->GetAuxType()); - } + if (pEntry->GetSourceFS() == DiskImg::kFormatMacHFS && isDir) { + /* HFS directories don't have types; fake it */ + ::lstrcpy(buf, " "); + } else if (!(pEntry->GetFileType() >= 0 && pEntry->GetFileType() <= 0xff)) + { + /* oversized type; assume it's HFS */ + MakeMacTypeString(pEntry->GetAuxType(), buf); + } else { + if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDisk) + ::sprintf(buf, "%dk", pEntry->GetUncompressedLen() / 1024); + else + ::sprintf(buf, "$%04lX", pEntry->GetAuxType()); + } } @@ -490,22 +490,22 @@ ContentList::MakeAuxTypeDisplayString(const GenericEntry* pEntry, char* buf) */ void ContentList::MakeRatioDisplayString(const GenericEntry* pEntry, char* buf, - int* pPerc) + int* pPerc) { - LONGLONG totalLen, totalCompLen; - totalLen = pEntry->GetUncompressedLen(); - totalCompLen = pEntry->GetCompressedLen(); + LONGLONG totalLen, totalCompLen; + totalLen = pEntry->GetUncompressedLen(); + totalCompLen = pEntry->GetCompressedLen(); - if ((!totalLen && totalCompLen) || (totalLen && !totalCompLen)) { - ::lstrcpy(buf, "---"); /* weird */ - *pPerc = -1; - } else if (totalLen < totalCompLen) { - ::lstrcpy(buf, ">100%"); /* compression failed? */ - *pPerc = 101; - } else { - *pPerc = ComputePercent(totalCompLen, totalLen); - ::sprintf(buf, "%d%%", *pPerc); - } + if ((!totalLen && totalCompLen) || (totalLen && !totalCompLen)) { + ::lstrcpy(buf, "---"); /* weird */ + *pPerc = -1; + } else if (totalLen < totalCompLen) { + ::lstrcpy(buf, ">100%"); /* compression failed? */ + *pPerc = 101; + } else { + *pPerc = ComputePercent(totalCompLen, totalLen); + ::sprintf(buf, "%d%%", *pPerc); + } } @@ -518,103 +518,103 @@ ContentList::MakeRatioDisplayString(const GenericEntry* pEntry, char* buf, void ContentList::OnGetDispInfo(NMHDR* pnmh, LRESULT* pResult) { - //static const char kAccessBits[] = "DNB IWR"; - static const char kAccessBits[] = "dnb iwr"; - LV_DISPINFO* plvdi = (LV_DISPINFO*) pnmh; - CString str; + //static const char kAccessBits[] = "DNB IWR"; + static const char kAccessBits[] = "dnb iwr"; + LV_DISPINFO* plvdi = (LV_DISPINFO*) pnmh; + CString str; - if (fpArchive->GetReloadFlag()) { - ::lstrcpy(plvdi->item.pszText, ""); - *pResult = 0; - return; - } + if (fpArchive->GetReloadFlag()) { + ::lstrcpy(plvdi->item.pszText, ""); + *pResult = 0; + return; + } - //WMSG0("OnGetDispInfo\n"); + //WMSG0("OnGetDispInfo\n"); - if (plvdi->item.mask & LVIF_TEXT) { - GenericEntry* pEntry = (GenericEntry*) plvdi->item.lParam; - //GenericEntry* pEntry = fpArchive->GetEntry(plvdi->item.iItem); + if (plvdi->item.mask & LVIF_TEXT) { + GenericEntry* pEntry = (GenericEntry*) plvdi->item.lParam; + //GenericEntry* pEntry = fpArchive->GetEntry(plvdi->item.iItem); - switch (plvdi->item.iSubItem) { - case 0: // pathname - if ((int)strlen(pEntry->GetDisplayName()) > plvdi->item.cchTextMax) { - // looks like current limit is 264 chars, which we could hit - ::strncpy(plvdi->item.pszText, pEntry->GetDisplayName(), - plvdi->item.cchTextMax); - plvdi->item.pszText[plvdi->item.cchTextMax-1] = '\0'; - } else { - ::lstrcpy(plvdi->item.pszText, pEntry->GetDisplayName()); - } + switch (plvdi->item.iSubItem) { + case 0: // pathname + if ((int)strlen(pEntry->GetDisplayName()) > plvdi->item.cchTextMax) { + // looks like current limit is 264 chars, which we could hit + ::strncpy(plvdi->item.pszText, pEntry->GetDisplayName(), + plvdi->item.cchTextMax); + plvdi->item.pszText[plvdi->item.cchTextMax-1] = '\0'; + } else { + ::lstrcpy(plvdi->item.pszText, pEntry->GetDisplayName()); + } - /* - * Sanitize the string. This is really only necessary for - * HFS, which has 8-bit "Macintosh Roman" filenames. The Win32 - * controls can deal with it, but it looks better if we massage - * it a little. - */ - { - unsigned char* str = (unsigned char*) plvdi->item.pszText; + /* + * Sanitize the string. This is really only necessary for + * HFS, which has 8-bit "Macintosh Roman" filenames. The Win32 + * controls can deal with it, but it looks better if we massage + * it a little. + */ + { + unsigned char* str = (unsigned char*) plvdi->item.pszText; - while (*str != '\0') { - *str = DiskImg::MacToASCII(*str); - str++; - } - } - break; - case 1: // type - MakeFileTypeDisplayString(pEntry, plvdi->item.pszText); - break; - case 2: // auxtype - MakeAuxTypeDisplayString(pEntry, plvdi->item.pszText); - break; - case 3: // mod date - { - CString modDate; - FormatDate(pEntry->GetModWhen(), &modDate); - ::lstrcpy(plvdi->item.pszText, (LPCTSTR) modDate); - } - break; - case 4: // format - ASSERT(pEntry->GetFormatStr() != nil); - ::lstrcpy(plvdi->item.pszText, pEntry->GetFormatStr()); - break; - case 5: // size - ::sprintf(plvdi->item.pszText, "%ld", pEntry->GetUncompressedLen()); - break; - case 6: // ratio - int crud; - MakeRatioDisplayString(pEntry, plvdi->item.pszText, &crud); - break; - case 7: // packed - ::sprintf(plvdi->item.pszText, "%ld", pEntry->GetCompressedLen()); - break; - case 8: // access - char bitLabels[sizeof(kAccessBits)]; - int i, j, mask; + while (*str != '\0') { + *str = DiskImg::MacToASCII(*str); + str++; + } + } + break; + case 1: // type + MakeFileTypeDisplayString(pEntry, plvdi->item.pszText); + break; + case 2: // auxtype + MakeAuxTypeDisplayString(pEntry, plvdi->item.pszText); + break; + case 3: // mod date + { + CString modDate; + FormatDate(pEntry->GetModWhen(), &modDate); + ::lstrcpy(plvdi->item.pszText, (LPCTSTR) modDate); + } + break; + case 4: // format + ASSERT(pEntry->GetFormatStr() != nil); + ::lstrcpy(plvdi->item.pszText, pEntry->GetFormatStr()); + break; + case 5: // size + ::sprintf(plvdi->item.pszText, "%ld", pEntry->GetUncompressedLen()); + break; + case 6: // ratio + int crud; + MakeRatioDisplayString(pEntry, plvdi->item.pszText, &crud); + break; + case 7: // packed + ::sprintf(plvdi->item.pszText, "%ld", pEntry->GetCompressedLen()); + break; + case 8: // access + char bitLabels[sizeof(kAccessBits)]; + int i, j, mask; - for (i = 0, j = 0, mask = 0x80; i < 8; i++, mask >>= 1) { - if (pEntry->GetAccess() & mask) - bitLabels[j++] = kAccessBits[i]; - } - bitLabels[j] = '\0'; - ASSERT(j < sizeof(bitLabels)); - //::sprintf(plvdi->item.pszText, "0x%02x", pEntry->GetAccess()); - ::lstrcpy(plvdi->item.pszText, bitLabels); - break; - case 9: // NuRecordIdx [hidden] - break; - default: - ASSERT(false); - break; - } - } + for (i = 0, j = 0, mask = 0x80; i < 8; i++, mask >>= 1) { + if (pEntry->GetAccess() & mask) + bitLabels[j++] = kAccessBits[i]; + } + bitLabels[j] = '\0'; + ASSERT(j < sizeof(bitLabels)); + //::sprintf(plvdi->item.pszText, "0x%02x", pEntry->GetAccess()); + ::lstrcpy(plvdi->item.pszText, bitLabels); + break; + case 9: // NuRecordIdx [hidden] + break; + default: + ASSERT(false); + break; + } + } - //if (plvdi->item.mask & LVIF_IMAGE) { - // WMSG2("IMAGE req item=%d subitem=%d\n", - // plvdi->item.iItem, plvdi->item.iSubItem); - //} + //if (plvdi->item.mask & LVIF_IMAGE) { + // WMSG2("IMAGE req item=%d subitem=%d\n", + // plvdi->item.iItem, plvdi->item.iSubItem); + //} - *pResult = 0; + *pResult = 0; } @@ -624,22 +624,22 @@ ContentList::OnGetDispInfo(NMHDR* pnmh, LRESULT* pResult) static inline CompareUnsignedLong(unsigned long u1, unsigned long u2) { - if (u1 < u2) - return -1; - else if (u1 > u2) - return 1; - else - return 0; + if (u1 < u2) + return -1; + else if (u1 > u2) + return 1; + else + return 0; } static inline CompareLONGLONG(LONGLONG u1, LONGLONG u2) { - if (u1 < u2) - return -1; - else if (u1 > u2) - return 1; - else - return 0; + if (u1 < u2) + return -1; + else if (u1 > u2) + return 1; + else + return 0; } /* @@ -648,77 +648,77 @@ CompareLONGLONG(LONGLONG u1, LONGLONG u2) int CALLBACK ContentList::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { - const GenericEntry* pEntry1 = (const GenericEntry*) lParam1; - const GenericEntry* pEntry2 = (const GenericEntry*) lParam2; - char tmpBuf1[16]; // needs >= 5 for file type compare, and - char tmpBuf2[16]; // >= 7 for ratio string - int result; + const GenericEntry* pEntry1 = (const GenericEntry*) lParam1; + const GenericEntry* pEntry2 = (const GenericEntry*) lParam2; + char tmpBuf1[16]; // needs >= 5 for file type compare, and + char tmpBuf2[16]; // >= 7 for ratio string + int result; - /* for descending order, flip the parameters */ - if (lParamSort & kDescendingFlag) { - const GenericEntry* tmp; - lParamSort &= ~(kDescendingFlag); - tmp = pEntry1; - pEntry1 = pEntry2; - pEntry2 = tmp; - } + /* for descending order, flip the parameters */ + if (lParamSort & kDescendingFlag) { + const GenericEntry* tmp; + lParamSort &= ~(kDescendingFlag); + tmp = pEntry1; + pEntry1 = pEntry2; + pEntry2 = tmp; + } - switch (lParamSort) { - case 0: // pathname - result = ::stricmp(pEntry1->GetDisplayName(), pEntry2->GetDisplayName()); - break; - case 1: // file type - MakeFileTypeDisplayString(pEntry1, tmpBuf1); - MakeFileTypeDisplayString(pEntry2, tmpBuf2); - result = ::stricmp(tmpBuf1, tmpBuf2); - if (result != 0) - break; - /* else fall through to case 2 */ - case 2: // aux type - if (pEntry1->GetRecordKind() == GenericEntry::kRecordKindDisk) { - if (pEntry2->GetRecordKind() == GenericEntry::kRecordKindDisk) { - result = pEntry1->GetAuxType() - pEntry2->GetAuxType(); - } else { - result = -1; - } - } else if (pEntry2->GetRecordKind() == GenericEntry::kRecordKindDisk) { - result = 1; - } else { - result = pEntry1->GetAuxType() - pEntry2->GetAuxType(); - } - break; - case 3: // mod date - result = CompareUnsignedLong(pEntry1->GetModWhen(), - pEntry2->GetModWhen()); - break; - case 4: // format - result = ::lstrcmp(pEntry1->GetFormatStr(), pEntry2->GetFormatStr()); - break; - case 5: // size - result = CompareLONGLONG(pEntry1->GetUncompressedLen(), - pEntry2->GetUncompressedLen()); - break; - case 6: // ratio - int perc1, perc2; - MakeRatioDisplayString(pEntry1, tmpBuf1, &perc1); - MakeRatioDisplayString(pEntry2, tmpBuf2, &perc2); - result = perc1 - perc2; - break; - case 7: // packed - result = CompareLONGLONG(pEntry1->GetCompressedLen(), - pEntry2->GetCompressedLen()); - break; - case 8: // access - result = CompareUnsignedLong(pEntry1->GetAccess(), - pEntry2->GetAccess()); - break; - case kNumVisibleColumns: // file-order sort - default: - result = pEntry1->GetIndex() - pEntry2->GetIndex(); - break; - } + switch (lParamSort) { + case 0: // pathname + result = ::stricmp(pEntry1->GetDisplayName(), pEntry2->GetDisplayName()); + break; + case 1: // file type + MakeFileTypeDisplayString(pEntry1, tmpBuf1); + MakeFileTypeDisplayString(pEntry2, tmpBuf2); + result = ::stricmp(tmpBuf1, tmpBuf2); + if (result != 0) + break; + /* else fall through to case 2 */ + case 2: // aux type + if (pEntry1->GetRecordKind() == GenericEntry::kRecordKindDisk) { + if (pEntry2->GetRecordKind() == GenericEntry::kRecordKindDisk) { + result = pEntry1->GetAuxType() - pEntry2->GetAuxType(); + } else { + result = -1; + } + } else if (pEntry2->GetRecordKind() == GenericEntry::kRecordKindDisk) { + result = 1; + } else { + result = pEntry1->GetAuxType() - pEntry2->GetAuxType(); + } + break; + case 3: // mod date + result = CompareUnsignedLong(pEntry1->GetModWhen(), + pEntry2->GetModWhen()); + break; + case 4: // format + result = ::lstrcmp(pEntry1->GetFormatStr(), pEntry2->GetFormatStr()); + break; + case 5: // size + result = CompareLONGLONG(pEntry1->GetUncompressedLen(), + pEntry2->GetUncompressedLen()); + break; + case 6: // ratio + int perc1, perc2; + MakeRatioDisplayString(pEntry1, tmpBuf1, &perc1); + MakeRatioDisplayString(pEntry2, tmpBuf2, &perc2); + result = perc1 - perc2; + break; + case 7: // packed + result = CompareLONGLONG(pEntry1->GetCompressedLen(), + pEntry2->GetCompressedLen()); + break; + case 8: // access + result = CompareUnsignedLong(pEntry1->GetAccess(), + pEntry2->GetAccess()); + break; + case kNumVisibleColumns: // file-order sort + default: + result = pEntry1->GetIndex() - pEntry2->GetIndex(); + break; + } - return result; + return result; } /* @@ -732,44 +732,44 @@ ContentList::CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) int ContentList::LoadData(void) { - GenericEntry* pEntry; - LV_ITEM lvi; - int dirCount = 0; - int idx = 0; + GenericEntry* pEntry; + LV_ITEM lvi; + int dirCount = 0; + int idx = 0; - DeleteAllItems(); // for Reload case + DeleteAllItems(); // for Reload case - pEntry = fpArchive->GetEntries(); - while (pEntry != nil) { - pEntry->SetIndex(idx); + pEntry = fpArchive->GetEntries(); + while (pEntry != nil) { + pEntry->SetIndex(idx); - lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; - lvi.iItem = idx++; - lvi.iSubItem = 0; - if (pEntry->GetDamaged()) - lvi.iImage = kListIconDamaged; - else if (pEntry->GetSuspicious()) - lvi.iImage = kListIconSuspicious; - else if (pEntry->GetHasNonEmptyComment()) - lvi.iImage = kListIconNonEmptyComment; - else if (pEntry->GetHasComment()) - lvi.iImage = kListIconComment; - else - lvi.iImage = kListIconNone; - lvi.pszText = LPSTR_TEXTCALLBACK; - lvi.lParam = (LPARAM) pEntry; + lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; + lvi.iItem = idx++; + lvi.iSubItem = 0; + if (pEntry->GetDamaged()) + lvi.iImage = kListIconDamaged; + else if (pEntry->GetSuspicious()) + lvi.iImage = kListIconSuspicious; + else if (pEntry->GetHasNonEmptyComment()) + lvi.iImage = kListIconNonEmptyComment; + else if (pEntry->GetHasComment()) + lvi.iImage = kListIconComment; + else + lvi.iImage = kListIconNone; + lvi.pszText = LPSTR_TEXTCALLBACK; + lvi.lParam = (LPARAM) pEntry; - if (InsertItem(&lvi) == -1) { - ASSERT(false); - return -1; - } + if (InsertItem(&lvi) == -1) { + ASSERT(false); + return -1; + } - pEntry = pEntry->GetNext(); - } + pEntry = pEntry->GetNext(); + } - WMSG3("ContentList got %d entries (%d files + %d unseen directories)\n", - idx, idx - dirCount, dirCount); - return 0; + WMSG3("ContentList got %d entries (%d files + %d unseen directories)\n", + idx, idx - dirCount, dirCount); + return 0; } @@ -779,44 +779,44 @@ ContentList::LoadData(void) int ContentList::GetDefaultWidth(int col) { - int retval; + int retval; - switch (col) { - case 0: // pathname - retval = 200; - break; - case 1: // type (need "$XY" and long HFS types) - //retval = MaxVal(GetStringWidth("XXMMM+"), GetStringWidth("XXType")); - retval = MaxVal(GetStringWidth("XXMMMM+"), GetStringWidth("XXType")); - break; - case 2: // auxtype (hex or long HFS type) - //retval = MaxVal(GetStringWidth("XX$8888"), GetStringWidth("XXAux")); - retval = MaxVal(GetStringWidth("XX$CCCC"), GetStringWidth("XXAux")); - break; - case 3: // mod date - retval = GetStringWidth("XX88-MMM-88 88:88"); - break; - case 4: // format - retval = GetStringWidth("XXUncompr"); - break; - case 5: // uncompressed size - retval = GetStringWidth("XX88888888"); - break; - case 6: // ratio - retval = MaxVal(GetStringWidth("XXRatio"), GetStringWidth("XX100%")); - break; - case 7: // packed - retval = GetStringWidth("XX88888888"); - break; - case 8: // access - retval = MaxVal(GetStringWidth("XXAccess"), GetStringWidth("XXdnbiwr")); - break; - default: - ASSERT(false); - retval = 0; - } + switch (col) { + case 0: // pathname + retval = 200; + break; + case 1: // type (need "$XY" and long HFS types) + //retval = MaxVal(GetStringWidth("XXMMM+"), GetStringWidth("XXType")); + retval = MaxVal(GetStringWidth("XXMMMM+"), GetStringWidth("XXType")); + break; + case 2: // auxtype (hex or long HFS type) + //retval = MaxVal(GetStringWidth("XX$8888"), GetStringWidth("XXAux")); + retval = MaxVal(GetStringWidth("XX$CCCC"), GetStringWidth("XXAux")); + break; + case 3: // mod date + retval = GetStringWidth("XX88-MMM-88 88:88"); + break; + case 4: // format + retval = GetStringWidth("XXUncompr"); + break; + case 5: // uncompressed size + retval = GetStringWidth("XX88888888"); + break; + case 6: // ratio + retval = MaxVal(GetStringWidth("XXRatio"), GetStringWidth("XX100%")); + break; + case 7: // packed + retval = GetStringWidth("XX88888888"); + break; + case 8: // access + retval = MaxVal(GetStringWidth("XXAccess"), GetStringWidth("XXdnbiwr")); + break; + default: + ASSERT(false); + retval = 0; + } - return retval; + return retval; } @@ -826,28 +826,28 @@ ContentList::GetDefaultWidth(int col) void ContentList::SetSortIcon(void) { - CHeaderCtrl* pHeader = GetHeaderCtrl(); - ASSERT(pHeader != NULL); - HDITEM curItem; + CHeaderCtrl* pHeader = GetHeaderCtrl(); + ASSERT(pHeader != NULL); + HDITEM curItem; - /* update all column headers */ - for (int i = 0; i < kNumVisibleColumns; i++) { - curItem.mask = HDI_IMAGE | HDI_FORMAT; - pHeader->GetItem(i, &curItem); + /* update all column headers */ + for (int i = 0; i < kNumVisibleColumns; i++) { + curItem.mask = HDI_IMAGE | HDI_FORMAT; + pHeader->GetItem(i, &curItem); - if (fpLayout->GetSortColumn() != i) { - curItem.fmt &= ~(HDF_IMAGE | HDF_BITMAP_ON_RIGHT); - } else { - //WMSG1(" Sorting on %d\n", i); - curItem.fmt |= HDF_IMAGE | HDF_BITMAP_ON_RIGHT; - if (fpLayout->GetAscending()) - curItem.iImage = 0; - else - curItem.iImage = 1; - } + if (fpLayout->GetSortColumn() != i) { + curItem.fmt &= ~(HDF_IMAGE | HDF_BITMAP_ON_RIGHT); + } else { + //WMSG1(" Sorting on %d\n", i); + curItem.fmt |= HDF_IMAGE | HDF_BITMAP_ON_RIGHT; + if (fpLayout->GetAscending()) + curItem.iImage = 0; + else + curItem.iImage = 1; + } - pHeader->SetItem(i, &curItem); - } + pHeader->SetItem(i, &curItem); + } } @@ -861,19 +861,19 @@ ContentList::SetSortIcon(void) void ContentList::OnDoubleClick(NMHDR*, LRESULT* pResult) { - /* test */ - DWORD dwPos = ::GetMessagePos(); - CPoint point ((int) LOWORD(dwPos), (int) HIWORD(dwPos)); - ScreenToClient(&point); + /* test */ + DWORD dwPos = ::GetMessagePos(); + CPoint point ((int) LOWORD(dwPos), (int) HIWORD(dwPos)); + ScreenToClient(&point); - int idx = HitTest(point); - if (idx != -1) { - CString str = GetItemText(idx, 0); - WMSG1("%s was double-clicked\n", str); - } + int idx = HitTest(point); + if (idx != -1) { + CString str = GetItemText(idx, 0); + WMSG1("%s was double-clicked\n", str); + } - ((MainWindow*) ::AfxGetMainWnd())->HandleDoubleClick(); - *pResult = 0; + ((MainWindow*) ::AfxGetMainWnd())->HandleDoubleClick(); + *pResult = 0; } /* @@ -890,30 +890,30 @@ ContentList::OnDoubleClick(NMHDR*, LRESULT* pResult) void ContentList::OnRightClick(NMHDR*, LRESULT* pResult) { - DWORD dwPos = ::GetMessagePos(); - CPoint point ((int) LOWORD(dwPos), (int) HIWORD(dwPos)); - ScreenToClient(&point); + DWORD dwPos = ::GetMessagePos(); + CPoint point ((int) LOWORD(dwPos), (int) HIWORD(dwPos)); + ScreenToClient(&point); #if 0 - int idx = HitTest(point); - if (idx != -1) { - CString str = GetItemText(idx, 0); - //TRACE1("%s was right-clicked\n", str); - WMSG1("%s was right-clicked\n", str); + int idx = HitTest(point); + if (idx != -1) { + CString str = GetItemText(idx, 0); + //TRACE1("%s was right-clicked\n", str); + WMSG1("%s was right-clicked\n", str); - //fRightClickItem = idx; + //fRightClickItem = idx; #else - { + { #endif - CMenu menu; - menu.LoadMenu(IDR_RIGHTCLICKMENU); - CMenu* pContextMenu = menu.GetSubMenu(0); - ClientToScreen(&point); - pContextMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, - point.x, point.y, ::AfxGetMainWnd()); - } - *pResult = 0; + CMenu menu; + menu.LoadMenu(IDR_RIGHTCLICKMENU); + CMenu* pContextMenu = menu.GetSubMenu(0); + ClientToScreen(&point); + pContextMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, + point.x, point.y, ::AfxGetMainWnd()); + } + *pResult = 0; } /* @@ -922,13 +922,13 @@ ContentList::OnRightClick(NMHDR*, LRESULT* pResult) void ContentList::SelectAll(void) { - int i; + int i; - for (i = GetItemCount()-1; i >= 0; i--) { - if (!SetItemState(i, LVIS_SELECTED, LVIS_SELECTED)) { - WMSG1("Glitch: SetItemState failed on %d\n", i); - } - } + for (i = GetItemCount()-1; i >= 0; i--) { + if (!SetItemState(i, LVIS_SELECTED, LVIS_SELECTED)) { + WMSG1("Glitch: SetItemState failed on %d\n", i); + } + } } /* @@ -937,14 +937,14 @@ ContentList::SelectAll(void) void ContentList::InvertSelection(void) { - int i, oldState; + int i, oldState; - for (i = GetItemCount()-1; i >= 0; i--) { - oldState = GetItemState(i, LVIS_SELECTED); - if (!SetItemState(i, oldState ? 0 : LVIS_SELECTED, LVIS_SELECTED)) { - WMSG1("Glitch: SetItemState failed on %d\n", i); - } - } + for (i = GetItemCount()-1; i >= 0; i--) { + oldState = GetItemState(i, LVIS_SELECTED); + if (!SetItemState(i, oldState ? 0 : LVIS_SELECTED, LVIS_SELECTED)) { + WMSG1("Glitch: SetItemState failed on %d\n", i); + } + } } /* @@ -970,46 +970,46 @@ ContentList::InvertSelection(void) void ContentList::SelectSubdirContents(void) { - POSITION posn; - posn = GetFirstSelectedItemPosition(); - if (posn == nil) { - WMSG0("SelectSubdirContents: nothing is selected\n"); - return; - } - /* mark all selected items with LVIS_CUT */ - while (posn != nil) { - int num = GetNextSelectedItem(/*ref*/ posn); - SetItemState(num, LVIS_CUT, LVIS_CUT); - } + POSITION posn; + posn = GetFirstSelectedItemPosition(); + if (posn == nil) { + WMSG0("SelectSubdirContents: nothing is selected\n"); + return; + } + /* mark all selected items with LVIS_CUT */ + while (posn != nil) { + int num = GetNextSelectedItem(/*ref*/ posn); + SetItemState(num, LVIS_CUT, LVIS_CUT); + } - /* for each LVIS_CUT entry, select all prefix matches */ - CString prefix; - for (int i = GetItemCount()-1; i >= 0; i--) { - GenericEntry* pEntry = (GenericEntry*) GetItemData(i); - bool origSel; + /* for each LVIS_CUT entry, select all prefix matches */ + CString prefix; + for (int i = GetItemCount()-1; i >= 0; i--) { + GenericEntry* pEntry = (GenericEntry*) GetItemData(i); + bool origSel; - origSel = GetItemState(i, LVIS_CUT) != 0; + origSel = GetItemState(i, LVIS_CUT) != 0; - if (origSel && - (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory || - pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir)) - { - prefix = pEntry->GetDisplayName(); - prefix += pEntry->GetFssep(); - SelectSubdir(prefix); - } + if (origSel && + (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory || + pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir)) + { + prefix = pEntry->GetDisplayName(); + prefix += pEntry->GetFssep(); + SelectSubdir(prefix); + } -// if (!SetItemState(i, oldState ? 0 : LVIS_SELECTED, LVIS_SELECTED)) { -// WMSG1("GLITCH: SetItemState failed on %d\n", i); -// } - } +// if (!SetItemState(i, oldState ? 0 : LVIS_SELECTED, LVIS_SELECTED)) { +// WMSG1("GLITCH: SetItemState failed on %d\n", i); +// } + } - /* clear the LVIS_CUT flags */ - posn = GetFirstSelectedItemPosition(); - while (posn != nil) { - int num = GetNextSelectedItem(/*ref*/ posn); - SetItemState(num, 0, LVIS_CUT); - } + /* clear the LVIS_CUT flags */ + posn = GetFirstSelectedItemPosition(); + while (posn != nil) { + int num = GetNextSelectedItem(/*ref*/ posn); + SetItemState(num, 0, LVIS_CUT); + } } /* @@ -1018,15 +1018,15 @@ ContentList::SelectSubdirContents(void) void ContentList::SelectSubdir(const char* displayPrefix) { - WMSG1(" ContentList selecting all in '%s'\n", displayPrefix); - int len = strlen(displayPrefix); + WMSG1(" ContentList selecting all in '%s'\n", displayPrefix); + int len = strlen(displayPrefix); - for (int i = GetItemCount()-1; i >= 0; i--) { - GenericEntry* pEntry = (GenericEntry*) GetItemData(i); + for (int i = GetItemCount()-1; i >= 0; i--) { + GenericEntry* pEntry = (GenericEntry*) GetItemData(i); - if (strncasecmp(displayPrefix, pEntry->GetDisplayName(), len) == 0) - SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); - } + if (strncasecmp(displayPrefix, pEntry->GetDisplayName(), len) == 0) + SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); + } } /* @@ -1035,8 +1035,8 @@ ContentList::SelectSubdir(const char* displayPrefix) void ContentList::ClearSelection(void) { - for (int i = GetItemCount()-1; i >= 0; i--) - SetItemState(i, 0, LVIS_SELECTED); + for (int i = GetItemCount()-1; i >= 0; i--) + SetItemState(i, 0, LVIS_SELECTED); } /* @@ -1045,63 +1045,63 @@ ContentList::ClearSelection(void) */ void ContentList::FindNext(const char* str, bool down, bool matchCase, - bool wholeWord) + bool wholeWord) { - POSITION posn; - int i, num; - bool found = false; + POSITION posn; + int i, num; + bool found = false; - WMSG4("FindNext '%s' d=%d c=%d w=%d\n", str, down, matchCase, wholeWord); + WMSG4("FindNext '%s' d=%d c=%d w=%d\n", str, down, matchCase, wholeWord); - posn = GetFirstSelectedItemPosition(); - num = GetNextSelectedItem(/*ref*/ posn); - if (num < 0) { // num will be -1 if nothing is selected - if (down) - num = -1; - else - num = GetItemCount(); - } + posn = GetFirstSelectedItemPosition(); + num = GetNextSelectedItem(/*ref*/ posn); + if (num < 0) { // num will be -1 if nothing is selected + if (down) + num = -1; + else + num = GetItemCount(); + } - WMSG1(" starting search from entry %d\n", num); + WMSG1(" starting search from entry %d\n", num); - if (down) { - for (i = num+1; i < GetItemCount(); i++) { - found = CompareFindString(i, str, matchCase, wholeWord); - if (found) - break; - } - if (!found) { // wrap - for (i = 0; i <= num; i++) { - found = CompareFindString(i, str, matchCase, wholeWord); - if (found) - break; - } - } - } else { - for (i = num-1; i >= 0; i--) { - found = CompareFindString(i, str, matchCase, wholeWord); - if (found) - break; - } - if (!found) { // wrap - for (i = GetItemCount()-1; i >= num; i--) { - found = CompareFindString(i, str, matchCase, wholeWord); - if (found) - break; - } - } - } + if (down) { + for (i = num+1; i < GetItemCount(); i++) { + found = CompareFindString(i, str, matchCase, wholeWord); + if (found) + break; + } + if (!found) { // wrap + for (i = 0; i <= num; i++) { + found = CompareFindString(i, str, matchCase, wholeWord); + if (found) + break; + } + } + } else { + for (i = num-1; i >= 0; i--) { + found = CompareFindString(i, str, matchCase, wholeWord); + if (found) + break; + } + if (!found) { // wrap + for (i = GetItemCount()-1; i >= num; i--) { + found = CompareFindString(i, str, matchCase, wholeWord); + if (found) + break; + } + } + } - if (found) { - WMSG1("Found, i=%d\n", i); - ClearSelection(); - SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); - EnsureVisible(i, false); - } else { - WMSG0("Not found\n"); - MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); - pMain->FailureBeep(); - } + if (found) { + WMSG1("Found, i=%d\n", i); + ClearSelection(); + SetItemState(i, LVIS_SELECTED, LVIS_SELECTED); + EnsureVisible(i, false); + } else { + WMSG0("Not found\n"); + MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); + pMain->FailureBeep(); + } } /* @@ -1109,42 +1109,42 @@ ContentList::FindNext(const char* str, bool down, bool matchCase, */ bool ContentList::CompareFindString(int num, const char* str, bool matchCase, - bool wholeWord) + bool wholeWord) { - GenericEntry* pEntry = (GenericEntry*) GetItemData(num); - char fssep = pEntry->GetFssep(); - char* (*pSubCompare)(const char* str, const char* subStr) = nil; + GenericEntry* pEntry = (GenericEntry*) GetItemData(num); + char fssep = pEntry->GetFssep(); + char* (*pSubCompare)(const char* str, const char* subStr) = nil; - if (matchCase) - pSubCompare = strstr; - else - pSubCompare = stristr; + if (matchCase) + pSubCompare = strstr; + else + pSubCompare = stristr; - if (wholeWord) { - const char* src = pEntry->GetDisplayName(); - const char* start = src; - int strLen = strlen(str); + if (wholeWord) { + const char* src = pEntry->GetDisplayName(); + const char* start = src; + int strLen = strlen(str); - /* scan forward, looking for a match that starts & ends on fssep */ - while (*start != '\0') { - const char* match; + /* scan forward, looking for a match that starts & ends on fssep */ + while (*start != '\0') { + const char* match; - match = (*pSubCompare)(start, str); + match = (*pSubCompare)(start, str); - if (match == nil) - break; - if ((match == src || *(match-1) == fssep) && - (match[strLen] == '\0' || match[strLen] == fssep)) - { - return true; - } + if (match == nil) + break; + if ((match == src || *(match-1) == fssep) && + (match[strLen] == '\0' || match[strLen] == fssep)) + { + return true; + } - start++; - } - } else { - if ((*pSubCompare)(pEntry->GetDisplayName(), str) != nil) - return true; - } + start++; + } + } else { + if ((*pSubCompare)(pEntry->GetDisplayName(), str) != nil) + return true; + } - return false; + return false; } diff --git a/app/ContentList.h b/app/ContentList.h index 63098b8..3b25947 100644 --- a/app/ContentList.h +++ b/app/ContentList.h @@ -34,103 +34,103 @@ class ContentList: public CListCtrl { public: - ContentList(GenericArchive* pArchive, ColumnLayout* pLayout) { - ASSERT(pArchive != nil); - ASSERT(pLayout != nil); - fpArchive = pArchive; - fpLayout = pLayout; -// fInvalid = false; - //fRightClickItem = -1; + ContentList(GenericArchive* pArchive, ColumnLayout* pLayout) { + ASSERT(pArchive != nil); + ASSERT(pLayout != nil); + fpArchive = pArchive; + fpLayout = pLayout; +// fInvalid = false; + //fRightClickItem = -1; - fpArchive->ClearReloadFlag(); - } + fpArchive->ClearReloadFlag(); + } - // call this before updating underlying storage; call Reload to un-inval -// void Invalidate(void); - // reload from underlying storage - void Reload(bool saveSelection = false); + // call this before updating underlying storage; call Reload to un-inval +// void Invalidate(void); + // reload from underlying storage + void Reload(bool saveSelection = false); - void NewSortOrder(void); - void NewColumnWidths(void); - void ExportColumnWidths(void); - void SelectAll(void); - void InvertSelection(void); - void ClearSelection(void); + void NewSortOrder(void); + void NewColumnWidths(void); + void ExportColumnWidths(void); + void SelectAll(void); + void InvertSelection(void); + void ClearSelection(void); - void SelectSubdirContents(void); + void SelectSubdirContents(void); - void FindNext(const char* str, bool down, bool matchCase, bool wholeWord); - bool CompareFindString(int num, const char* str, bool matchCase, - bool wholeWord); + void FindNext(const char* str, bool down, bool matchCase, bool wholeWord); + bool CompareFindString(int num, const char* str, bool matchCase, + bool wholeWord); - //int GetRightClickItem(void) const { return fRightClickItem; } - //void ClearRightClickItem(void) { fRightClickItem = -1; } + //int GetRightClickItem(void) const { return fRightClickItem; } + //void ClearRightClickItem(void) { fRightClickItem = -1; } - enum { kFileTypeBufLen = 5, kAuxTypeBufLen = 6 }; - static void MakeFileTypeDisplayString(const GenericEntry* pEntry, - char* buf); - static void MakeAuxTypeDisplayString(const GenericEntry* pEntry, - char* buf); + enum { kFileTypeBufLen = 5, kAuxTypeBufLen = 6 }; + static void MakeFileTypeDisplayString(const GenericEntry* pEntry, + char* buf); + static void MakeAuxTypeDisplayString(const GenericEntry* pEntry, + char* buf); protected: - // overridden functions - virtual BOOL PreCreateWindow(CREATESTRUCT& cs); - virtual void PostNcDestroy(void); + // overridden functions + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual void PostNcDestroy(void); - afx_msg int OnCreate(LPCREATESTRUCT); - afx_msg void OnDestroy(void); - afx_msg void OnSysColorChange(void); - //afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); - afx_msg void OnColumnClick(NMHDR*, LRESULT*); - afx_msg void OnGetDispInfo(NMHDR* pnmh, LRESULT* pResult); + afx_msg int OnCreate(LPCREATESTRUCT); + afx_msg void OnDestroy(void); + afx_msg void OnSysColorChange(void); + //afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); + afx_msg void OnColumnClick(NMHDR*, LRESULT*); + afx_msg void OnGetDispInfo(NMHDR* pnmh, LRESULT* pResult); private: - // Load the header images. Must do this every time the syscolors change. - // (Ideally this would re-map all 3dface colors. Note the current - // implementation relies on the top left pixel color.) - void LoadHeaderImages(void) { - if (!fHdrImageList.Create(IDB_HDRBAR, 16, 1, CLR_DEFAULT)) - WMSG0("GLITCH: header list create failed\n"); - fHdrImageList.SetBkColor(::GetSysColor(COLOR_BTNFACE)); - } - void LoadListImages(void) { - if (!fListImageList.Create(IDB_LIST_PICS, 16, 1, CLR_DEFAULT)) - WMSG0("GLITCH: list image create failed\n"); - fListImageList.SetBkColor(::GetSysColor(COLOR_WINDOW)); - } - enum { // defs for IDB_LIST_PICS - kListIconNone = 0, - kListIconComment = 1, - kListIconNonEmptyComment = 2, - kListIconDamaged = 3, - kListIconSuspicious = 4, - }; - int LoadData(void); - long* GetSelectionSerials(long* pSelCount); - void RestoreSelection(const long* savedSel, long selCount); + // Load the header images. Must do this every time the syscolors change. + // (Ideally this would re-map all 3dface colors. Note the current + // implementation relies on the top left pixel color.) + void LoadHeaderImages(void) { + if (!fHdrImageList.Create(IDB_HDRBAR, 16, 1, CLR_DEFAULT)) + WMSG0("GLITCH: header list create failed\n"); + fHdrImageList.SetBkColor(::GetSysColor(COLOR_BTNFACE)); + } + void LoadListImages(void) { + if (!fListImageList.Create(IDB_LIST_PICS, 16, 1, CLR_DEFAULT)) + WMSG0("GLITCH: list image create failed\n"); + fListImageList.SetBkColor(::GetSysColor(COLOR_WINDOW)); + } + enum { // defs for IDB_LIST_PICS + kListIconNone = 0, + kListIconComment = 1, + kListIconNonEmptyComment = 2, + kListIconDamaged = 3, + kListIconSuspicious = 4, + }; + int LoadData(void); + long* GetSelectionSerials(long* pSelCount); + void RestoreSelection(const long* savedSel, long selCount); - int GetDefaultWidth(int col); + int GetDefaultWidth(int col); - static void MakeMacTypeString(unsigned long val, char* buf); - static void MakeRatioDisplayString(const GenericEntry* pEntry, char* buf, - int* pPerc); + static void MakeMacTypeString(unsigned long val, char* buf); + static void MakeRatioDisplayString(const GenericEntry* pEntry, char* buf, + int* pPerc); - void SetSortIcon(void); - static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, - LPARAM lParamSort); + void SetSortIcon(void); + static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, + LPARAM lParamSort); - void OnDoubleClick(NMHDR* pnmh, LRESULT* pResult); - void OnRightClick(NMHDR* pnmh, LRESULT* pResult); - void SelectSubdir(const char* displayPrefix); + void OnDoubleClick(NMHDR* pnmh, LRESULT* pResult); + void OnRightClick(NMHDR* pnmh, LRESULT* pResult); + void SelectSubdir(const char* displayPrefix); - CImageList fHdrImageList; - CImageList fListImageList; - GenericArchive* fpArchive; // data we're expected to display - ColumnLayout* fpLayout; -// int fRightClickItem; -// bool fInvalid; + CImageList fHdrImageList; + CImageList fListImageList; + GenericArchive* fpArchive; // data we're expected to display + ColumnLayout* fpLayout; +// int fRightClickItem; +// bool fInvalid; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__CONTENT_LIST__*/ \ No newline at end of file diff --git a/app/ConvDiskOptionsDialog.cpp b/app/ConvDiskOptionsDialog.cpp index 1b594be..f5a0001 100644 --- a/app/ConvDiskOptionsDialog.cpp +++ b/app/ConvDiskOptionsDialog.cpp @@ -13,22 +13,22 @@ #include "ActionProgressDialog.h" #include "DiskArchive.h" #include "NewDiskSize.h" -#include "../diskimg/DiskImgDetail.h" // need ProDOS filename validator +#include "../diskimg/DiskImgDetail.h" // need ProDOS filename validator BEGIN_MESSAGE_MAP(ConvDiskOptionsDialog, CDialog) - ON_WM_HELPINFO() - //ON_COMMAND(IDHELP, OnHelp) - ON_BN_CLICKED(IDC_CONVDISK_COMPUTE, OnCompute) - ON_BN_CLICKED(IDC_USE_SELECTED, ResetSizeControls) - ON_BN_CLICKED(IDC_USE_ALL, ResetSizeControls) - //ON_BN_CLICKED(IDC_CONVDISK_SPARSE, ResetSizeControls) - ON_CONTROL_RANGE(BN_CLICKED, IDC_CONVDISK_140K, IDC_CONVDISK_SPECIFY, - OnRadioChangeRange) + ON_WM_HELPINFO() + //ON_COMMAND(IDHELP, OnHelp) + ON_BN_CLICKED(IDC_CONVDISK_COMPUTE, OnCompute) + ON_BN_CLICKED(IDC_USE_SELECTED, ResetSizeControls) + ON_BN_CLICKED(IDC_USE_ALL, ResetSizeControls) + //ON_BN_CLICKED(IDC_CONVDISK_SPARSE, ResetSizeControls) + ON_CONTROL_RANGE(BN_CLICKED, IDC_CONVDISK_140K, IDC_CONVDISK_SPECIFY, + OnRadioChangeRange) END_MESSAGE_MAP() -const int kProDOSVolNameMax = 15; // longest possible ProDOS volume name +const int kProDOSVolNameMax = 15; // longest possible ProDOS volume name /* * Set up our modified version of the "use selection" dialog. @@ -36,18 +36,18 @@ const int kProDOSVolNameMax = 15; // longest possible ProDOS volume name BOOL ConvDiskOptionsDialog::OnInitDialog(void) { - CEdit* pEdit = (CEdit*) GetDlgItem(IDC_CONVDISK_VOLNAME); - ASSERT(pEdit != nil); - pEdit->SetLimitText(kProDOSVolNameMax); + CEdit* pEdit = (CEdit*) GetDlgItem(IDC_CONVDISK_VOLNAME); + ASSERT(pEdit != nil); + pEdit->SetLimitText(kProDOSVolNameMax); - ResetSizeControls(); + ResetSizeControls(); - pEdit = (CEdit*) GetDlgItem(IDC_CONVDISK_SPECIFY_EDIT); - ASSERT(pEdit != nil); - pEdit->SetLimitText(5); // enough for "65535" - pEdit->EnableWindow(FALSE); + pEdit = (CEdit*) GetDlgItem(IDC_CONVDISK_SPECIFY_EDIT); + ASSERT(pEdit != nil); + pEdit->SetLimitText(5); // enough for "65535" + pEdit->EnableWindow(FALSE); - return UseSelectionDialog::OnInitDialog(); + return UseSelectionDialog::OnInitDialog(); } /* @@ -56,47 +56,47 @@ ConvDiskOptionsDialog::OnInitDialog(void) void ConvDiskOptionsDialog::DoDataExchange(CDataExchange* pDX) { - UINT specifyBlocks = 280; - CString errMsg; + UINT specifyBlocks = 280; + CString errMsg; - DDX_Radio(pDX, IDC_CONVDISK_140K, fDiskSizeIdx); - //DDX_Check(pDX, IDC_CONVDISK_ALLOWLOWER, fAllowLower); - //DDX_Check(pDX, IDC_CONVDISK_SPARSE, fSparseAlloc); - DDX_Text(pDX, IDC_CONVDISK_VOLNAME, fVolName); - DDX_Text(pDX, IDC_CONVDISK_SPECIFY_EDIT, specifyBlocks); + DDX_Radio(pDX, IDC_CONVDISK_140K, fDiskSizeIdx); + //DDX_Check(pDX, IDC_CONVDISK_ALLOWLOWER, fAllowLower); + //DDX_Check(pDX, IDC_CONVDISK_SPARSE, fSparseAlloc); + DDX_Text(pDX, IDC_CONVDISK_VOLNAME, fVolName); + DDX_Text(pDX, IDC_CONVDISK_SPECIFY_EDIT, specifyBlocks); - ASSERT(fDiskSizeIdx >= 0 && fDiskSizeIdx < (int)NewDiskSize::GetNumSizeEntries()); + ASSERT(fDiskSizeIdx >= 0 && fDiskSizeIdx < (int)NewDiskSize::GetNumSizeEntries()); - if (pDX->m_bSaveAndValidate) { + if (pDX->m_bSaveAndValidate) { - fNumBlocks = NewDiskSize::GetDiskSizeByIndex(fDiskSizeIdx); - if (fNumBlocks == NewDiskSize::kSpecified) { - fNumBlocks = specifyBlocks; + fNumBlocks = NewDiskSize::GetDiskSizeByIndex(fDiskSizeIdx); + if (fNumBlocks == NewDiskSize::kSpecified) { + fNumBlocks = specifyBlocks; - // Max is really 65535, but we allow 65536 for creation of volumes - // that can be copied to CFFA cards. - if (specifyBlocks < 16 || specifyBlocks > 65536) - errMsg = "Specify a size of at least 16 blocks and no more" - " than 65536 blocks."; - } + // Max is really 65535, but we allow 65536 for creation of volumes + // that can be copied to CFFA cards. + if (specifyBlocks < 16 || specifyBlocks > 65536) + errMsg = "Specify a size of at least 16 blocks and no more" + " than 65536 blocks."; + } - if (fVolName.IsEmpty() || fVolName.GetLength() > kProDOSVolNameMax) { - errMsg = "You must specify a volume name 1-15 characters long."; - } else { - if (!IsValidVolumeName_ProDOS(fVolName)) - errMsg.LoadString(IDS_VALID_VOLNAME_PRODOS); - } - } + if (fVolName.IsEmpty() || fVolName.GetLength() > kProDOSVolNameMax) { + errMsg = "You must specify a volume name 1-15 characters long."; + } else { + if (!IsValidVolumeName_ProDOS(fVolName)) + errMsg.LoadString(IDS_VALID_VOLNAME_PRODOS); + } + } - if (!errMsg.IsEmpty()) { - CString appName; - appName.LoadString(IDS_MB_APP_NAME); - MessageBox(errMsg, appName, MB_OK); - pDX->Fail(); - } + if (!errMsg.IsEmpty()) { + CString appName; + appName.LoadString(IDS_MB_APP_NAME); + MessageBox(errMsg, appName, MB_OK); + pDX->Fail(); + } - UseSelectionDialog::DoDataExchange(pDX); + UseSelectionDialog::DoDataExchange(pDX); } /* @@ -106,13 +106,13 @@ ConvDiskOptionsDialog::DoDataExchange(CDataExchange* pDX) void ConvDiskOptionsDialog::OnRadioChangeRange(UINT nID) { - WMSG1("OnChangeRange id=%d\n", nID); + WMSG1("OnChangeRange id=%d\n", nID); - CButton* pButton = (CButton*) GetDlgItem(IDC_CONVDISK_SPECIFY); - CEdit* pEdit = (CEdit*) GetDlgItem(IDC_CONVDISK_SPECIFY_EDIT); - pEdit->EnableWindow(pButton->GetCheck() == BST_CHECKED); + CButton* pButton = (CButton*) GetDlgItem(IDC_CONVDISK_SPECIFY); + CEdit* pEdit = (CEdit*) GetDlgItem(IDC_CONVDISK_SPECIFY_EDIT); + pEdit->EnableWindow(pButton->GetCheck() == BST_CHECKED); - NewDiskSize::UpdateSpecifyEdit(this); + NewDiskSize::UpdateSpecifyEdit(this); } /* @@ -121,7 +121,7 @@ ConvDiskOptionsDialog::OnRadioChangeRange(UINT nID) bool ConvDiskOptionsDialog::IsValidVolumeName_ProDOS(const char* name) { - return DiskImgLib::DiskFSProDOS::IsValidVolumeName(name); + return DiskImgLib::DiskFSProDOS::IsValidVolumeName(name); } @@ -134,24 +134,24 @@ ConvDiskOptionsDialog::IsValidVolumeName_ProDOS(const char* name) void ConvDiskOptionsDialog::ResetSizeControls(void) { - CWnd* pWnd; - CString spaceReq; + CWnd* pWnd; + CString spaceReq; - WMSG0("Resetting size controls\n"); - spaceReq.Format(IDS_CONVDISK_SPACEREQ, "(unknown)"); - pWnd = GetDlgItem(IDC_CONVDISK_SPACEREQ); - ASSERT(pWnd != nil); - pWnd->SetWindowText(spaceReq); + WMSG0("Resetting size controls\n"); + spaceReq.Format(IDS_CONVDISK_SPACEREQ, "(unknown)"); + pWnd = GetDlgItem(IDC_CONVDISK_SPACEREQ); + ASSERT(pWnd != nil); + pWnd->SetWindowText(spaceReq); #if 0 - int i; - for (i = 0; i < NELEM(gDiskSizes); i++) { - pWnd = GetDlgItem(gDiskSizes[i].ctrlID); - ASSERT(pWnd != nil); - pWnd->EnableWindow(TRUE); - } + int i; + for (i = 0; i < NELEM(gDiskSizes); i++) { + pWnd = GetDlgItem(gDiskSizes[i].ctrlID); + ASSERT(pWnd != nil); + pWnd->EnableWindow(TRUE); + } #endif - NewDiskSize::EnableButtons(this); + NewDiskSize::EnableButtons(this); } /* @@ -163,48 +163,48 @@ ConvDiskOptionsDialog::ResetSizeControls(void) void ConvDiskOptionsDialog::LimitSizeControls(long totalBlocks, long blocksUsed) { - WMSG2("LimitSizeControls %ld %ld\n", totalBlocks, blocksUsed); - WMSG1("Full volume requires %ld bitmap blocks\n", - NewDiskSize::GetNumBitmapBlocks_ProDOS(totalBlocks)); + WMSG2("LimitSizeControls %ld %ld\n", totalBlocks, blocksUsed); + WMSG1("Full volume requires %ld bitmap blocks\n", + NewDiskSize::GetNumBitmapBlocks_ProDOS(totalBlocks)); - CWnd* pWnd; - long usedWithoutBitmap = - blocksUsed - NewDiskSize::GetNumBitmapBlocks_ProDOS(totalBlocks); - long sizeInK = usedWithoutBitmap / 2; - CString sizeStr, spaceReq; - sizeStr.Format("%dK", sizeInK); - spaceReq.Format(IDS_CONVDISK_SPACEREQ, sizeStr); + CWnd* pWnd; + long usedWithoutBitmap = + blocksUsed - NewDiskSize::GetNumBitmapBlocks_ProDOS(totalBlocks); + long sizeInK = usedWithoutBitmap / 2; + CString sizeStr, spaceReq; + sizeStr.Format("%dK", sizeInK); + spaceReq.Format(IDS_CONVDISK_SPACEREQ, sizeStr); - pWnd = GetDlgItem(IDC_CONVDISK_SPACEREQ); - ASSERT(pWnd != nil); - pWnd->SetWindowText(spaceReq); + pWnd = GetDlgItem(IDC_CONVDISK_SPACEREQ); + ASSERT(pWnd != nil); + pWnd->SetWindowText(spaceReq); - NewDiskSize::EnableButtons_ProDOS(this, totalBlocks, blocksUsed); + NewDiskSize::EnableButtons_ProDOS(this, totalBlocks, blocksUsed); #if 0 - bool first = true; - for (int i = 0; i < NELEM(gDiskSizes); i++) { - if (gDiskSizes[i].blocks == -1) - continue; + bool first = true; + for (int i = 0; i < NELEM(gDiskSizes); i++) { + if (gDiskSizes[i].blocks == -1) + continue; - CButton* pButton; - pButton = (CButton*) GetDlgItem(gDiskSizes[i].ctrlID); - ASSERT(pButton != nil); - if (usedWithoutBitmap + GetNumBitmapBlocks(gDiskSizes[i].blocks) <= - gDiskSizes[i].blocks) - { - pButton->EnableWindow(TRUE); - if (first) { - pButton->SetCheck(BST_CHECKED); - first = false; - } else { - pButton->SetCheck(BST_UNCHECKED); - } - } else { - pButton->EnableWindow(FALSE); - pButton->SetCheck(BST_UNCHECKED); - } - } + CButton* pButton; + pButton = (CButton*) GetDlgItem(gDiskSizes[i].ctrlID); + ASSERT(pButton != nil); + if (usedWithoutBitmap + GetNumBitmapBlocks(gDiskSizes[i].blocks) <= + gDiskSizes[i].blocks) + { + pButton->EnableWindow(TRUE); + if (first) { + pButton->SetCheck(BST_CHECKED); + first = false; + } else { + pButton->SetCheck(BST_UNCHECKED); + } + } else { + pButton->EnableWindow(FALSE); + pButton->SetCheck(BST_UNCHECKED); + } + } #endif } @@ -220,125 +220,125 @@ ConvDiskOptionsDialog::LimitSizeControls(long totalBlocks, long blocksUsed) void ConvDiskOptionsDialog::OnCompute(void) { - MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); - const Preferences* pPreferences = GET_PREFERENCES(); + MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); + const Preferences* pPreferences = GET_PREFERENCES(); - if (UpdateData() == FALSE) - return; + if (UpdateData() == FALSE) + return; - /* - * Create a "selection set" of data forks, resource forks, and - * disk images. We don't want comment threads. We can filter all that - * out later, though, so we just specify "any". - */ - SelectionSet selSet; - int threadMask = GenericEntry::kAnyThread; + /* + * Create a "selection set" of data forks, resource forks, and + * disk images. We don't want comment threads. We can filter all that + * out later, though, so we just specify "any". + */ + SelectionSet selSet; + int threadMask = GenericEntry::kAnyThread; - if (fFilesToAction == UseSelectionDialog::kActionSelection) { - selSet.CreateFromSelection(pMain->GetContentList(), threadMask); - } else { - selSet.CreateFromAll(pMain->GetContentList(), threadMask); - } + if (fFilesToAction == UseSelectionDialog::kActionSelection) { + selSet.CreateFromSelection(pMain->GetContentList(), threadMask); + } else { + selSet.CreateFromAll(pMain->GetContentList(), threadMask); + } - if (selSet.GetNumEntries() == 0) { - /* should be impossible */ - MessageBox("No files matched the selection criteria.", - "No match", MB_OK|MB_ICONEXCLAMATION); - return; - } + if (selSet.GetNumEntries() == 0) { + /* should be impossible */ + MessageBox("No files matched the selection criteria.", + "No match", MB_OK|MB_ICONEXCLAMATION); + return; + } - XferFileOptions xferOpts; - //xferOpts.fAllowLowerCase = - // pPreferences->GetPrefBool(kPrProDOSAllowLower) != 0; - //xferOpts.fUseSparseBlocks = - // pPreferences->GetPrefBool(kPrProDOSUseSparse) != 0; + XferFileOptions xferOpts; + //xferOpts.fAllowLowerCase = + // pPreferences->GetPrefBool(kPrProDOSAllowLower) != 0; + //xferOpts.fUseSparseBlocks = + // pPreferences->GetPrefBool(kPrProDOSUseSparse) != 0; - WMSG1("New volume name will be '%s'\n", fVolName); + WMSG1("New volume name will be '%s'\n", fVolName); - /* - * Create a new disk image file. - */ - CString errStr; - char nameBuf[MAX_PATH]; - UINT unique; - unique = GetTempFileName(pMain->GetPreferences()->GetPrefString(kPrTempPath), - "CPdisk", 0, nameBuf); - if (unique == 0) { - DWORD dwerr = ::GetLastError(); - errStr.Format("GetTempFileName failed on '%s' (err=0x%08lx)\n", - pMain->GetPreferences()->GetPrefString(kPrTempPath), dwerr); - ShowFailureMsg(this, errStr, IDS_FAILED); - return; - } - WMSG1(" Will xfer to file '%s'\n", nameBuf); - // annoying -- DiskArchive insists on creating it - (void) unlink(nameBuf); + /* + * Create a new disk image file. + */ + CString errStr; + char nameBuf[MAX_PATH]; + UINT unique; + unique = GetTempFileName(pMain->GetPreferences()->GetPrefString(kPrTempPath), + "CPdisk", 0, nameBuf); + if (unique == 0) { + DWORD dwerr = ::GetLastError(); + errStr.Format("GetTempFileName failed on '%s' (err=0x%08lx)\n", + pMain->GetPreferences()->GetPrefString(kPrTempPath), dwerr); + ShowFailureMsg(this, errStr, IDS_FAILED); + return; + } + WMSG1(" Will xfer to file '%s'\n", nameBuf); + // annoying -- DiskArchive insists on creating it + (void) unlink(nameBuf); - DiskArchive::NewOptions options; - memset(&options, 0, sizeof(options)); - options.base.format = DiskImg::kFormatProDOS; - options.base.sectorOrder = DiskImg::kSectorOrderProDOS; - options.prodos.volName = fVolName; - options.prodos.numBlocks = 65535; + DiskArchive::NewOptions options; + memset(&options, 0, sizeof(options)); + options.base.format = DiskImg::kFormatProDOS; + options.base.sectorOrder = DiskImg::kSectorOrderProDOS; + options.prodos.volName = fVolName; + options.prodos.numBlocks = 65535; - xferOpts.fTarget = new DiskArchive; + xferOpts.fTarget = new DiskArchive; - { - CWaitCursor waitc; - errStr = xferOpts.fTarget->New(nameBuf, &options); - } - if (!errStr.IsEmpty()) { - ShowFailureMsg(this, errStr, IDS_FAILED); - } else { - /* - * Set up the progress window as a modal dialog. - */ - GenericArchive::XferStatus result; + { + CWaitCursor waitc; + errStr = xferOpts.fTarget->New(nameBuf, &options); + } + if (!errStr.IsEmpty()) { + ShowFailureMsg(this, errStr, IDS_FAILED); + } else { + /* + * Set up the progress window as a modal dialog. + */ + GenericArchive::XferStatus result; - ActionProgressDialog* pActionProgress = new ActionProgressDialog; - pMain->SetActionProgressDialog(pActionProgress); - pActionProgress->Create(ActionProgressDialog::kActionConvFile, this); - pMain->PeekAndPump(); - result = pMain->GetOpenArchive()->XferSelection(pActionProgress, &selSet, - pActionProgress, &xferOpts); - pActionProgress->Cleanup(this); - pMain->SetActionProgressDialog(nil); + ActionProgressDialog* pActionProgress = new ActionProgressDialog; + pMain->SetActionProgressDialog(pActionProgress); + pActionProgress->Create(ActionProgressDialog::kActionConvFile, this); + pMain->PeekAndPump(); + result = pMain->GetOpenArchive()->XferSelection(pActionProgress, &selSet, + pActionProgress, &xferOpts); + pActionProgress->Cleanup(this); + pMain->SetActionProgressDialog(nil); - if (result == GenericArchive::kXferOK) { - DiskFS* pDiskFS; - long totalBlocks, freeBlocks; - int unitSize; - DIError dierr; + if (result == GenericArchive::kXferOK) { + DiskFS* pDiskFS; + long totalBlocks, freeBlocks; + int unitSize; + DIError dierr; - WMSG0("SUCCESS\n"); + WMSG0("SUCCESS\n"); - pDiskFS = ((DiskArchive*) xferOpts.fTarget)->GetDiskFS(); - ASSERT(pDiskFS != nil); + pDiskFS = ((DiskArchive*) xferOpts.fTarget)->GetDiskFS(); + ASSERT(pDiskFS != nil); - dierr = pDiskFS->GetFreeSpaceCount(&totalBlocks, &freeBlocks, - &unitSize); - if (dierr != kDIErrNone) { - errStr.Format("Unable to get free space count: %s.\n", - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(this, errStr, IDS_FAILED); - } else { - ASSERT(totalBlocks >= freeBlocks); - ASSERT(unitSize == DiskImgLib::kBlockSize); - LimitSizeControls(totalBlocks, totalBlocks - freeBlocks); - } - } else if (result == GenericArchive::kXferCancelled) { - WMSG0("CANCEL - cancel button hit\n"); - ResetSizeControls(); - } else { - WMSG1("FAILURE (result=%d)\n", result); - ResetSizeControls(); - } - } + dierr = pDiskFS->GetFreeSpaceCount(&totalBlocks, &freeBlocks, + &unitSize); + if (dierr != kDIErrNone) { + errStr.Format("Unable to get free space count: %s.\n", + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(this, errStr, IDS_FAILED); + } else { + ASSERT(totalBlocks >= freeBlocks); + ASSERT(unitSize == DiskImgLib::kBlockSize); + LimitSizeControls(totalBlocks, totalBlocks - freeBlocks); + } + } else if (result == GenericArchive::kXferCancelled) { + WMSG0("CANCEL - cancel button hit\n"); + ResetSizeControls(); + } else { + WMSG1("FAILURE (result=%d)\n", result); + ResetSizeControls(); + } + } - // debug - ((DiskArchive*) (xferOpts.fTarget))->GetDiskFS()->DumpFileList(); + // debug + ((DiskArchive*) (xferOpts.fTarget))->GetDiskFS()->DumpFileList(); - /* clean up */ - delete xferOpts.fTarget; - (void) unlink(nameBuf); + /* clean up */ + delete xferOpts.fTarget; + (void) unlink(nameBuf); } diff --git a/app/ConvDiskOptionsDialog.h b/app/ConvDiskOptionsDialog.h index 8a257c5..687dbd9 100644 --- a/app/ConvDiskOptionsDialog.h +++ b/app/ConvDiskOptionsDialog.h @@ -17,37 +17,37 @@ */ class ConvDiskOptionsDialog : public UseSelectionDialog { public: - ConvDiskOptionsDialog(int selCount, CWnd* pParentWnd = NULL) : - UseSelectionDialog(selCount, pParentWnd, IDD_CONVDISK_OPTS) - { - fDiskSizeIdx = 0; - //fAllowLower = fSparseAlloc = FALSE; - fVolName = "NEW.DISK"; - fNumBlocks = -1; - } - virtual ~ConvDiskOptionsDialog(void) {} + ConvDiskOptionsDialog(int selCount, CWnd* pParentWnd = NULL) : + UseSelectionDialog(selCount, pParentWnd, IDD_CONVDISK_OPTS) + { + fDiskSizeIdx = 0; + //fAllowLower = fSparseAlloc = FALSE; + fVolName = "NEW.DISK"; + fNumBlocks = -1; + } + virtual ~ConvDiskOptionsDialog(void) {} - int fDiskSizeIdx; - //BOOL fAllowLower; - //BOOL fSparseAlloc; - CString fVolName; + int fDiskSizeIdx; + //BOOL fAllowLower; + //BOOL fSparseAlloc; + CString fVolName; - long fNumBlocks; // computed when DoModal finishes + long fNumBlocks; // computed when DoModal finishes private: - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); -// BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - afx_msg void ResetSizeControls(void); - afx_msg void OnCompute(void); +// BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg void ResetSizeControls(void); + afx_msg void OnCompute(void); - afx_msg void OnRadioChangeRange(UINT nID); + afx_msg void OnRadioChangeRange(UINT nID); - void LimitSizeControls(long totalBlocks, long blocksUsed); - bool IsValidVolumeName_ProDOS(const char* name); + void LimitSizeControls(long totalBlocks, long blocksUsed); + bool IsValidVolumeName_ProDOS(const char* name); - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__CONVDISK_OPTIONS_DIALOG__*/ \ No newline at end of file diff --git a/app/ConvFileOptionsDialog.cpp b/app/ConvFileOptionsDialog.cpp index 2cf5a25..fc183c1 100644 --- a/app/ConvFileOptionsDialog.cpp +++ b/app/ConvFileOptionsDialog.cpp @@ -17,7 +17,7 @@ BOOL ConvFileOptionsDialog::OnInitDialog(void) { - return UseSelectionDialog::OnInitDialog(); + return UseSelectionDialog::OnInitDialog(); } #endif @@ -27,9 +27,9 @@ ConvFileOptionsDialog::OnInitDialog(void) void ConvFileOptionsDialog::DoDataExchange(CDataExchange* pDX) { - //DDX_Check(pDX, IDC_CONVFILE_CONVDOS, fConvDOSText); - //DDX_Check(pDX, IDC_CONVFILE_CONVPASCAL, fConvPascalText); - DDX_Check(pDX, IDC_CONVFILE_PRESERVEDIR, fPreserveEmptyFolders); + //DDX_Check(pDX, IDC_CONVFILE_CONVDOS, fConvDOSText); + //DDX_Check(pDX, IDC_CONVFILE_CONVPASCAL, fConvPascalText); + DDX_Check(pDX, IDC_CONVFILE_PRESERVEDIR, fPreserveEmptyFolders); - UseSelectionDialog::DoDataExchange(pDX); + UseSelectionDialog::DoDataExchange(pDX); } diff --git a/app/ConvFileOptionsDialog.h b/app/ConvFileOptionsDialog.h index 4e560c1..dceef38 100644 --- a/app/ConvFileOptionsDialog.h +++ b/app/ConvFileOptionsDialog.h @@ -17,22 +17,22 @@ */ class ConvFileOptionsDialog : public UseSelectionDialog { public: - ConvFileOptionsDialog(int selCount, CWnd* pParentWnd = NULL) : - UseSelectionDialog(selCount, pParentWnd, IDD_CONVFILE_OPTS) - { - fPreserveEmptyFolders = FALSE; - } - virtual ~ConvFileOptionsDialog(void) {} + ConvFileOptionsDialog(int selCount, CWnd* pParentWnd = NULL) : + UseSelectionDialog(selCount, pParentWnd, IDD_CONVFILE_OPTS) + { + fPreserveEmptyFolders = FALSE; + } + virtual ~ConvFileOptionsDialog(void) {} - //BOOL fConvDOSText; - //BOOL fConvPascalText; - BOOL fPreserveEmptyFolders; + //BOOL fConvDOSText; + //BOOL fConvPascalText; + BOOL fPreserveEmptyFolders; private: - //virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + //virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - //DECLARE_MESSAGE_MAP() + //DECLARE_MESSAGE_MAP() }; #endif /*__CONVFILE_OPTIONS_DIALOG__*/ \ No newline at end of file diff --git a/app/CreateImageDialog.cpp b/app/CreateImageDialog.cpp index 6e53c6d..8e3ab91 100644 --- a/app/CreateImageDialog.cpp +++ b/app/CreateImageDialog.cpp @@ -10,23 +10,23 @@ #include "CreateImageDialog.h" #include "NewDiskSize.h" #include "HelpTopics.h" -#include "../diskimg/DiskImgDetail.h" // need ProDOS filename validator +#include "../diskimg/DiskImgDetail.h" // need ProDOS filename validator BEGIN_MESSAGE_MAP(CreateImageDialog, CDialog) - ON_WM_HELPINFO() - ON_COMMAND(IDHELP, OnHelp) - ON_CONTROL_RANGE(BN_CLICKED, IDC_CREATEFS_DOS32, IDC_CREATEFS_BLANK, - OnFormatChangeRange) - ON_CONTROL_RANGE(BN_CLICKED, IDC_CONVDISK_140K, IDC_CONVDISK_SPECIFY, - OnSizeChangeRange) + ON_WM_HELPINFO() + ON_COMMAND(IDHELP, OnHelp) + ON_CONTROL_RANGE(BN_CLICKED, IDC_CREATEFS_DOS32, IDC_CREATEFS_BLANK, + OnFormatChangeRange) + ON_CONTROL_RANGE(BN_CLICKED, IDC_CONVDISK_140K, IDC_CONVDISK_SPECIFY, + OnSizeChangeRange) END_MESSAGE_MAP() -const int kProDOSVolNameMax = 15; // longest possible ProDOS volume name -const int kPascalVolNameMax = 7; // longest possible Pascal volume name -const int kHFSVolNameMax = 27; // longest possible HFS volume name -const long kMaxBlankBlocks = 16777216; // 8GB in 512-byte blocks +const int kProDOSVolNameMax = 15; // longest possible ProDOS volume name +const int kPascalVolNameMax = 7; // longest possible Pascal volume name +const int kHFSVolNameMax = 27; // longest possible HFS volume name +const long kMaxBlankBlocks = 16777216; // 8GB in 512-byte blocks /* * Set up our modified version of the "use selection" dialog. @@ -34,33 +34,33 @@ const long kMaxBlankBlocks = 16777216; // 8GB in 512-byte blocks BOOL CreateImageDialog::OnInitDialog(void) { - // high bit set in signed short means key is down - if (::GetKeyState(VK_SHIFT) < 0) { - WMSG0("Shift key is down, enabling extended options\n"); - fExtendedOpts = true; - } + // high bit set in signed short means key is down + if (::GetKeyState(VK_SHIFT) < 0) { + WMSG0("Shift key is down, enabling extended options\n"); + fExtendedOpts = true; + } - CEdit* pEdit = (CEdit*) GetDlgItem(IDC_CREATEFSPRODOS_VOLNAME); - ASSERT(pEdit != nil); - pEdit->SetLimitText(kProDOSVolNameMax); + CEdit* pEdit = (CEdit*) GetDlgItem(IDC_CREATEFSPRODOS_VOLNAME); + ASSERT(pEdit != nil); + pEdit->SetLimitText(kProDOSVolNameMax); - pEdit = (CEdit*) GetDlgItem(IDC_CREATEFSPASCAL_VOLNAME); - ASSERT(pEdit != nil); - pEdit->SetLimitText(kPascalVolNameMax); + pEdit = (CEdit*) GetDlgItem(IDC_CREATEFSPASCAL_VOLNAME); + ASSERT(pEdit != nil); + pEdit->SetLimitText(kPascalVolNameMax); - pEdit = (CEdit*) GetDlgItem(IDC_CREATEFSHFS_VOLNAME); - ASSERT(pEdit != nil); - pEdit->SetLimitText(kHFSVolNameMax); + pEdit = (CEdit*) GetDlgItem(IDC_CREATEFSHFS_VOLNAME); + ASSERT(pEdit != nil); + pEdit->SetLimitText(kHFSVolNameMax); - pEdit = (CEdit*) GetDlgItem(IDC_CREATEFSDOS_VOLNUM); - ASSERT(pEdit != nil); - pEdit->SetLimitText(3); // 3 digit volume number + pEdit = (CEdit*) GetDlgItem(IDC_CREATEFSDOS_VOLNUM); + ASSERT(pEdit != nil); + pEdit->SetLimitText(3); // 3 digit volume number - pEdit = (CEdit*) GetDlgItem(IDC_CONVDISK_SPECIFY_EDIT); - ASSERT(pEdit != nil); - pEdit->EnableWindow(FALSE); + pEdit = (CEdit*) GetDlgItem(IDC_CONVDISK_SPECIFY_EDIT); + ASSERT(pEdit != nil); + pEdit->EnableWindow(FALSE); - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } /* @@ -69,104 +69,104 @@ CreateImageDialog::OnInitDialog(void) void CreateImageDialog::DoDataExchange(CDataExchange* pDX) { - UINT specifyBlocks = 280; - CString errMsg; + UINT specifyBlocks = 280; + CString errMsg; - DDX_Radio(pDX, IDC_CONVDISK_140K, fDiskSizeIdx); - DDX_Radio(pDX, IDC_CREATEFS_DOS32, fDiskFormatIdx); - DDX_Check(pDX, IDC_CREATEFSDOS_ALLOCDOS, fAllocTracks_DOS); - DDX_Text(pDX, IDC_CREATEFSDOS_VOLNUM, fDOSVolumeNum); - DDX_Text(pDX, IDC_CREATEFSPRODOS_VOLNAME, fVolName_ProDOS); - DDX_Text(pDX, IDC_CREATEFSPASCAL_VOLNAME, fVolName_Pascal); - DDX_Text(pDX, IDC_CREATEFSHFS_VOLNAME, fVolName_HFS); - DDX_Text(pDX, IDC_CONVDISK_SPECIFY_EDIT, specifyBlocks); + DDX_Radio(pDX, IDC_CONVDISK_140K, fDiskSizeIdx); + DDX_Radio(pDX, IDC_CREATEFS_DOS32, fDiskFormatIdx); + DDX_Check(pDX, IDC_CREATEFSDOS_ALLOCDOS, fAllocTracks_DOS); + DDX_Text(pDX, IDC_CREATEFSDOS_VOLNUM, fDOSVolumeNum); + DDX_Text(pDX, IDC_CREATEFSPRODOS_VOLNAME, fVolName_ProDOS); + DDX_Text(pDX, IDC_CREATEFSPASCAL_VOLNAME, fVolName_Pascal); + DDX_Text(pDX, IDC_CREATEFSHFS_VOLNAME, fVolName_HFS); + DDX_Text(pDX, IDC_CONVDISK_SPECIFY_EDIT, specifyBlocks); - ASSERT(fDiskSizeIdx >= 0 && fDiskSizeIdx < (int)NewDiskSize::GetNumSizeEntries()); + ASSERT(fDiskSizeIdx >= 0 && fDiskSizeIdx < (int)NewDiskSize::GetNumSizeEntries()); - if (pDX->m_bSaveAndValidate) { - fNumBlocks = NewDiskSize::GetDiskSizeByIndex(fDiskSizeIdx); - if (fNumBlocks == NewDiskSize::kSpecified) - fNumBlocks = specifyBlocks; + if (pDX->m_bSaveAndValidate) { + fNumBlocks = NewDiskSize::GetDiskSizeByIndex(fDiskSizeIdx); + if (fNumBlocks == NewDiskSize::kSpecified) + fNumBlocks = specifyBlocks; - if (fDiskFormatIdx == kFmtDOS32) { - CString tmpStr; - tmpStr.Format("%d", fDOSVolumeNum); - if (!IsValidVolumeName_DOS(tmpStr)) - errMsg.LoadString(IDS_VALID_VOLNAME_DOS); - } else if (fDiskFormatIdx == kFmtDOS33) { - CString tmpStr; - tmpStr.Format("%d", fDOSVolumeNum); - if (!IsValidVolumeName_DOS(tmpStr)) - errMsg.LoadString(IDS_VALID_VOLNAME_DOS); + if (fDiskFormatIdx == kFmtDOS32) { + CString tmpStr; + tmpStr.Format("%d", fDOSVolumeNum); + if (!IsValidVolumeName_DOS(tmpStr)) + errMsg.LoadString(IDS_VALID_VOLNAME_DOS); + } else if (fDiskFormatIdx == kFmtDOS33) { + CString tmpStr; + tmpStr.Format("%d", fDOSVolumeNum); + if (!IsValidVolumeName_DOS(tmpStr)) + errMsg.LoadString(IDS_VALID_VOLNAME_DOS); - // only needed in "extended" mode -- this stuff is too painful to - // inflict on the average user - if (fNumBlocks < 18*8 || fNumBlocks > 800 || - (fNumBlocks <= 400 && (fNumBlocks % 8) != 0) || - (fNumBlocks > 400 && (fNumBlocks % 16) != 0)) - { - errMsg = "Specify a size between 144 blocks (18 tracks) and" - " 800 blocks (50 tracks/32 sectors). The block count" - " must be a multiple of 8 for 16-sector disks, or a" - " multiple of 16 for 32-sector disks. 32 sector" - " formatting starts at 400 blocks. Disks larger than" - " 400 blocks but less than 800 aren't recognized by" - " CiderPress."; - } - } else if (fDiskFormatIdx == kFmtProDOS) { - // Max is really 65535, but we allow 65536 for creation of volumes - // that can be copied to CFFA cards. - if (fNumBlocks < 16 || fNumBlocks > 65536) { - errMsg = "Specify a size of at least 16 blocks and no more" - " than 65536 blocks."; - } else if (fVolName_ProDOS.IsEmpty() || - fVolName_ProDOS.GetLength() > kProDOSVolNameMax) - { - errMsg = "You must specify a volume name 1-15 characters long."; - } else { - if (!IsValidVolumeName_ProDOS(fVolName_ProDOS)) - errMsg.LoadString(IDS_VALID_VOLNAME_PRODOS); - } - } else if (fDiskFormatIdx == kFmtPascal) { - if (fVolName_Pascal.IsEmpty() || - fVolName_Pascal.GetLength() > kPascalVolNameMax) - { - errMsg = "You must specify a volume name 1-7 characters long."; - } else { - if (!IsValidVolumeName_Pascal(fVolName_Pascal)) - errMsg.LoadString(IDS_VALID_VOLNAME_PASCAL); - } - } else if (fDiskFormatIdx == kFmtHFS) { - if (fNumBlocks < 1600 || fNumBlocks > 4194303) { - errMsg = "Specify a size of at least 1600 blocks and no more" - " than 4194303 blocks."; - } else if (fVolName_HFS.IsEmpty() || - fVolName_HFS.GetLength() > kHFSVolNameMax) - { - errMsg = "You must specify a volume name 1-27 characters long."; - } else { - if (!IsValidVolumeName_HFS(fVolName_HFS)) - errMsg.LoadString(IDS_VALID_VOLNAME_HFS); - } - } else if (fDiskFormatIdx == kFmtBlank) { - if (fNumBlocks < 1 || fNumBlocks > kMaxBlankBlocks) - errMsg = "Specify a size of at least 1 block and no more" - " than 16777216 blocks."; - } else { - ASSERT(false); - } - } else { - OnFormatChangeRange(IDC_CREATEFS_DOS32 + fDiskFormatIdx); - } + // only needed in "extended" mode -- this stuff is too painful to + // inflict on the average user + if (fNumBlocks < 18*8 || fNumBlocks > 800 || + (fNumBlocks <= 400 && (fNumBlocks % 8) != 0) || + (fNumBlocks > 400 && (fNumBlocks % 16) != 0)) + { + errMsg = "Specify a size between 144 blocks (18 tracks) and" + " 800 blocks (50 tracks/32 sectors). The block count" + " must be a multiple of 8 for 16-sector disks, or a" + " multiple of 16 for 32-sector disks. 32 sector" + " formatting starts at 400 blocks. Disks larger than" + " 400 blocks but less than 800 aren't recognized by" + " CiderPress."; + } + } else if (fDiskFormatIdx == kFmtProDOS) { + // Max is really 65535, but we allow 65536 for creation of volumes + // that can be copied to CFFA cards. + if (fNumBlocks < 16 || fNumBlocks > 65536) { + errMsg = "Specify a size of at least 16 blocks and no more" + " than 65536 blocks."; + } else if (fVolName_ProDOS.IsEmpty() || + fVolName_ProDOS.GetLength() > kProDOSVolNameMax) + { + errMsg = "You must specify a volume name 1-15 characters long."; + } else { + if (!IsValidVolumeName_ProDOS(fVolName_ProDOS)) + errMsg.LoadString(IDS_VALID_VOLNAME_PRODOS); + } + } else if (fDiskFormatIdx == kFmtPascal) { + if (fVolName_Pascal.IsEmpty() || + fVolName_Pascal.GetLength() > kPascalVolNameMax) + { + errMsg = "You must specify a volume name 1-7 characters long."; + } else { + if (!IsValidVolumeName_Pascal(fVolName_Pascal)) + errMsg.LoadString(IDS_VALID_VOLNAME_PASCAL); + } + } else if (fDiskFormatIdx == kFmtHFS) { + if (fNumBlocks < 1600 || fNumBlocks > 4194303) { + errMsg = "Specify a size of at least 1600 blocks and no more" + " than 4194303 blocks."; + } else if (fVolName_HFS.IsEmpty() || + fVolName_HFS.GetLength() > kHFSVolNameMax) + { + errMsg = "You must specify a volume name 1-27 characters long."; + } else { + if (!IsValidVolumeName_HFS(fVolName_HFS)) + errMsg.LoadString(IDS_VALID_VOLNAME_HFS); + } + } else if (fDiskFormatIdx == kFmtBlank) { + if (fNumBlocks < 1 || fNumBlocks > kMaxBlankBlocks) + errMsg = "Specify a size of at least 1 block and no more" + " than 16777216 blocks."; + } else { + ASSERT(false); + } + } else { + OnFormatChangeRange(IDC_CREATEFS_DOS32 + fDiskFormatIdx); + } - if (!errMsg.IsEmpty()) { - CString appName; - appName.LoadString(IDS_MB_APP_NAME); - MessageBox(errMsg, appName, MB_OK); - pDX->Fail(); - } + if (!errMsg.IsEmpty()) { + CString appName; + appName.LoadString(IDS_MB_APP_NAME); + MessageBox(errMsg, appName, MB_OK); + pDX->Fail(); + } - CDialog::DoDataExchange(pDX); + CDialog::DoDataExchange(pDX); } /* @@ -176,90 +176,90 @@ CreateImageDialog::DoDataExchange(CDataExchange* pDX) void CreateImageDialog::OnFormatChangeRange(UINT nID) { - static const struct { - UINT buttonID; - UINT ctrlID; - } kFormatTab[] = { - { IDC_CREATEFS_DOS32, IDC_CREATEFSDOS_ALLOCDOS }, - { IDC_CREATEFS_DOS32, IDC_CREATEFSDOS_VOLNUM }, - { IDC_CREATEFS_DOS32, IDC_CONVDISK_140K }, - { IDC_CREATEFS_DOS33, IDC_CREATEFSDOS_ALLOCDOS }, - { IDC_CREATEFS_DOS33, IDC_CREATEFSDOS_VOLNUM }, - { IDC_CREATEFS_DOS33, IDC_CONVDISK_140K }, - { IDC_CREATEFS_PRODOS, IDC_CREATEFSPRODOS_VOLNAME }, - { IDC_CREATEFS_PRODOS, IDC_CONVDISK_140K }, - { IDC_CREATEFS_PRODOS, IDC_CONVDISK_800K }, - { IDC_CREATEFS_PRODOS, IDC_CONVDISK_1440K }, - { IDC_CREATEFS_PRODOS, IDC_CONVDISK_5MB }, - { IDC_CREATEFS_PRODOS, IDC_CONVDISK_16MB }, - { IDC_CREATEFS_PRODOS, IDC_CONVDISK_20MB }, - { IDC_CREATEFS_PRODOS, IDC_CONVDISK_32MB }, - { IDC_CREATEFS_PRODOS, IDC_CONVDISK_SPECIFY }, - { IDC_CREATEFS_PASCAL, IDC_CREATEFSPASCAL_VOLNAME }, - { IDC_CREATEFS_PASCAL, IDC_CONVDISK_140K }, - { IDC_CREATEFS_PASCAL, IDC_CONVDISK_800K }, - { IDC_CREATEFS_HFS, IDC_CREATEFSHFS_VOLNAME }, - { IDC_CREATEFS_HFS, IDC_CONVDISK_800K }, - { IDC_CREATEFS_HFS, IDC_CONVDISK_1440K }, - { IDC_CREATEFS_HFS, IDC_CONVDISK_5MB }, - { IDC_CREATEFS_HFS, IDC_CONVDISK_16MB }, - { IDC_CREATEFS_HFS, IDC_CONVDISK_20MB }, - { IDC_CREATEFS_HFS, IDC_CONVDISK_32MB }, - { IDC_CREATEFS_HFS, IDC_CONVDISK_SPECIFY }, - { IDC_CREATEFS_BLANK, IDC_CONVDISK_140K }, - { IDC_CREATEFS_BLANK, IDC_CONVDISK_800K }, - { IDC_CREATEFS_BLANK, IDC_CONVDISK_1440K }, - { IDC_CREATEFS_BLANK, IDC_CONVDISK_5MB }, - { IDC_CREATEFS_BLANK, IDC_CONVDISK_16MB }, - { IDC_CREATEFS_BLANK, IDC_CONVDISK_20MB }, - { IDC_CREATEFS_BLANK, IDC_CONVDISK_32MB }, - { IDC_CREATEFS_BLANK, IDC_CONVDISK_SPECIFY }, - }; - static const UINT kDetailControls[] = { - IDC_CREATEFSDOS_ALLOCDOS, - IDC_CREATEFSDOS_VOLNUM, - IDC_CREATEFSPRODOS_VOLNAME, - IDC_CREATEFSPASCAL_VOLNAME, - IDC_CREATEFSHFS_VOLNAME - }; - int i; - - WMSG1("OnFormatChangeRange id=%d\n", nID); + static const struct { + UINT buttonID; + UINT ctrlID; + } kFormatTab[] = { + { IDC_CREATEFS_DOS32, IDC_CREATEFSDOS_ALLOCDOS }, + { IDC_CREATEFS_DOS32, IDC_CREATEFSDOS_VOLNUM }, + { IDC_CREATEFS_DOS32, IDC_CONVDISK_140K }, + { IDC_CREATEFS_DOS33, IDC_CREATEFSDOS_ALLOCDOS }, + { IDC_CREATEFS_DOS33, IDC_CREATEFSDOS_VOLNUM }, + { IDC_CREATEFS_DOS33, IDC_CONVDISK_140K }, + { IDC_CREATEFS_PRODOS, IDC_CREATEFSPRODOS_VOLNAME }, + { IDC_CREATEFS_PRODOS, IDC_CONVDISK_140K }, + { IDC_CREATEFS_PRODOS, IDC_CONVDISK_800K }, + { IDC_CREATEFS_PRODOS, IDC_CONVDISK_1440K }, + { IDC_CREATEFS_PRODOS, IDC_CONVDISK_5MB }, + { IDC_CREATEFS_PRODOS, IDC_CONVDISK_16MB }, + { IDC_CREATEFS_PRODOS, IDC_CONVDISK_20MB }, + { IDC_CREATEFS_PRODOS, IDC_CONVDISK_32MB }, + { IDC_CREATEFS_PRODOS, IDC_CONVDISK_SPECIFY }, + { IDC_CREATEFS_PASCAL, IDC_CREATEFSPASCAL_VOLNAME }, + { IDC_CREATEFS_PASCAL, IDC_CONVDISK_140K }, + { IDC_CREATEFS_PASCAL, IDC_CONVDISK_800K }, + { IDC_CREATEFS_HFS, IDC_CREATEFSHFS_VOLNAME }, + { IDC_CREATEFS_HFS, IDC_CONVDISK_800K }, + { IDC_CREATEFS_HFS, IDC_CONVDISK_1440K }, + { IDC_CREATEFS_HFS, IDC_CONVDISK_5MB }, + { IDC_CREATEFS_HFS, IDC_CONVDISK_16MB }, + { IDC_CREATEFS_HFS, IDC_CONVDISK_20MB }, + { IDC_CREATEFS_HFS, IDC_CONVDISK_32MB }, + { IDC_CREATEFS_HFS, IDC_CONVDISK_SPECIFY }, + { IDC_CREATEFS_BLANK, IDC_CONVDISK_140K }, + { IDC_CREATEFS_BLANK, IDC_CONVDISK_800K }, + { IDC_CREATEFS_BLANK, IDC_CONVDISK_1440K }, + { IDC_CREATEFS_BLANK, IDC_CONVDISK_5MB }, + { IDC_CREATEFS_BLANK, IDC_CONVDISK_16MB }, + { IDC_CREATEFS_BLANK, IDC_CONVDISK_20MB }, + { IDC_CREATEFS_BLANK, IDC_CONVDISK_32MB }, + { IDC_CREATEFS_BLANK, IDC_CONVDISK_SPECIFY }, + }; + static const UINT kDetailControls[] = { + IDC_CREATEFSDOS_ALLOCDOS, + IDC_CREATEFSDOS_VOLNUM, + IDC_CREATEFSPRODOS_VOLNAME, + IDC_CREATEFSPASCAL_VOLNAME, + IDC_CREATEFSHFS_VOLNAME + }; + int i; + + WMSG1("OnFormatChangeRange id=%d\n", nID); - /* reset so 140K is highlighted */ - NewDiskSize::EnableButtons_ProDOS(this, 32, 16); + /* reset so 140K is highlighted */ + NewDiskSize::EnableButtons_ProDOS(this, 32, 16); - /* disable all buttons */ - NewDiskSize::EnableButtons(this, FALSE); + /* disable all buttons */ + NewDiskSize::EnableButtons(this, FALSE); - for (i = 0; i < NELEM(kDetailControls); i++) { - CWnd* pWnd = GetDlgItem(kDetailControls[i]); - if (pWnd != nil) - pWnd->EnableWindow(FALSE); - } + for (i = 0; i < NELEM(kDetailControls); i++) { + CWnd* pWnd = GetDlgItem(kDetailControls[i]); + if (pWnd != nil) + pWnd->EnableWindow(FALSE); + } - /* re-enable just the ones we like */ - for (i = 0; i < NELEM(kFormatTab); i++) { - if (kFormatTab[i].buttonID == nID) { - CWnd* pWnd = GetDlgItem(kFormatTab[i].ctrlID); - ASSERT(pWnd != nil); - if (pWnd != nil) - pWnd->EnableWindow(TRUE); - } - } - if (fExtendedOpts && nID != IDC_CREATEFS_DOS32) { - CWnd* pWnd = GetDlgItem(IDC_CONVDISK_SPECIFY); - pWnd->EnableWindow(TRUE); - } + /* re-enable just the ones we like */ + for (i = 0; i < NELEM(kFormatTab); i++) { + if (kFormatTab[i].buttonID == nID) { + CWnd* pWnd = GetDlgItem(kFormatTab[i].ctrlID); + ASSERT(pWnd != nil); + if (pWnd != nil) + pWnd->EnableWindow(TRUE); + } + } + if (fExtendedOpts && nID != IDC_CREATEFS_DOS32) { + CWnd* pWnd = GetDlgItem(IDC_CONVDISK_SPECIFY); + pWnd->EnableWindow(TRUE); + } - /* make sure 140K is viable; doesn't work for HFS */ - CButton* pButton; - pButton = (CButton*) GetDlgItem(IDC_CONVDISK_140K); - if (!pButton->IsWindowEnabled()) { - pButton->SetCheck(BST_UNCHECKED); - pButton = (CButton*) GetDlgItem(IDC_CONVDISK_800K); - pButton->SetCheck(BST_CHECKED); - } + /* make sure 140K is viable; doesn't work for HFS */ + CButton* pButton; + pButton = (CButton*) GetDlgItem(IDC_CONVDISK_140K); + if (!pButton->IsWindowEnabled()) { + pButton->SetCheck(BST_UNCHECKED); + pButton = (CButton*) GetDlgItem(IDC_CONVDISK_800K); + pButton->SetCheck(BST_CHECKED); + } } /* @@ -269,24 +269,24 @@ CreateImageDialog::OnFormatChangeRange(UINT nID) void CreateImageDialog::OnSizeChangeRange(UINT nID) { - WMSG1("OnSizeChangeRange id=%d\n", nID); + WMSG1("OnSizeChangeRange id=%d\n", nID); - CButton* pButton = (CButton*) GetDlgItem(IDC_CONVDISK_SPECIFY); - CEdit* pEdit = (CEdit*) GetDlgItem(IDC_CONVDISK_SPECIFY_EDIT); - pEdit->EnableWindow(pButton->GetCheck() == BST_CHECKED); + CButton* pButton = (CButton*) GetDlgItem(IDC_CONVDISK_SPECIFY); + CEdit* pEdit = (CEdit*) GetDlgItem(IDC_CONVDISK_SPECIFY_EDIT); + pEdit->EnableWindow(pButton->GetCheck() == BST_CHECKED); - CButton* pBlank; - CButton* pHFS; - pBlank = (CButton*) GetDlgItem(IDC_CREATEFS_BLANK); - pHFS = (CButton*) GetDlgItem(IDC_CREATEFS_HFS); - if (pHFS->GetCheck() == BST_CHECKED) - pEdit->SetLimitText(10); // enough for "2147483647" - else if (pBlank->GetCheck() == BST_CHECKED) - pEdit->SetLimitText(8); // enough for "16777216" - else - pEdit->SetLimitText(5); // enough for "65535" + CButton* pBlank; + CButton* pHFS; + pBlank = (CButton*) GetDlgItem(IDC_CREATEFS_BLANK); + pHFS = (CButton*) GetDlgItem(IDC_CREATEFS_HFS); + if (pHFS->GetCheck() == BST_CHECKED) + pEdit->SetLimitText(10); // enough for "2147483647" + else if (pBlank->GetCheck() == BST_CHECKED) + pEdit->SetLimitText(8); // enough for "16777216" + else + pEdit->SetLimitText(5); // enough for "65535" - NewDiskSize::UpdateSpecifyEdit(this); + NewDiskSize::UpdateSpecifyEdit(this); } @@ -296,7 +296,7 @@ CreateImageDialog::OnSizeChangeRange(UINT nID) bool CreateImageDialog::IsValidVolumeName_DOS(const char* name) { - return DiskImgLib::DiskFSDOS33::IsValidVolumeName(name); + return DiskImgLib::DiskFSDOS33::IsValidVolumeName(name); } /* @@ -305,7 +305,7 @@ CreateImageDialog::IsValidVolumeName_DOS(const char* name) bool CreateImageDialog::IsValidVolumeName_ProDOS(const char* name) { - return DiskImgLib::DiskFSProDOS::IsValidVolumeName(name); + return DiskImgLib::DiskFSProDOS::IsValidVolumeName(name); } /* @@ -314,7 +314,7 @@ CreateImageDialog::IsValidVolumeName_ProDOS(const char* name) bool CreateImageDialog::IsValidVolumeName_Pascal(const char* name) { - return DiskImgLib::DiskFSPascal::IsValidVolumeName(name); + return DiskImgLib::DiskFSPascal::IsValidVolumeName(name); } /* @@ -323,7 +323,7 @@ CreateImageDialog::IsValidVolumeName_Pascal(const char* name) bool CreateImageDialog::IsValidVolumeName_HFS(const char* name) { - return DiskImgLib::DiskFSHFS::IsValidVolumeName(name); + return DiskImgLib::DiskFSHFS::IsValidVolumeName(name); } @@ -333,8 +333,8 @@ CreateImageDialog::IsValidVolumeName_HFS(const char* name) BOOL CreateImageDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* @@ -343,5 +343,5 @@ CreateImageDialog::OnHelpInfo(HELPINFO* lpHelpInfo) void CreateImageDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_IMAGE_CREATOR, HELP_CONTEXT); + WinHelp(HELP_TOPIC_IMAGE_CREATOR, HELP_CONTEXT); } diff --git a/app/CreateImageDialog.h b/app/CreateImageDialog.h index 5390823..3e6bb56 100644 --- a/app/CreateImageDialog.h +++ b/app/CreateImageDialog.h @@ -16,60 +16,60 @@ */ class CreateImageDialog : public CDialog { public: - /* this must match up with control IDs in dialog */ - enum { - kFmtDOS32 = 0, - kFmtDOS33, - kFmtProDOS, - kFmtPascal, - kFmtHFS, - kFmtBlank - }; + /* this must match up with control IDs in dialog */ + enum { + kFmtDOS32 = 0, + kFmtDOS33, + kFmtProDOS, + kFmtPascal, + kFmtHFS, + kFmtBlank + }; - CreateImageDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_CREATEIMAGE, pParentWnd) - { - fDiskSizeIdx = 0; - fDiskFormatIdx = kFmtProDOS; - fAllocTracks_DOS = TRUE; - fDOSVolumeNum = 254; - fVolName_ProDOS = "NEW.DISK"; - fVolName_Pascal = "BLANK"; - fVolName_HFS = "New Disk"; - fNumBlocks = -2; // -1 has special meaning - fExtendedOpts = false; - } - virtual ~CreateImageDialog(void) {} + CreateImageDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_CREATEIMAGE, pParentWnd) + { + fDiskSizeIdx = 0; + fDiskFormatIdx = kFmtProDOS; + fAllocTracks_DOS = TRUE; + fDOSVolumeNum = 254; + fVolName_ProDOS = "NEW.DISK"; + fVolName_Pascal = "BLANK"; + fVolName_HFS = "New Disk"; + fNumBlocks = -2; // -1 has special meaning + fExtendedOpts = false; + } + virtual ~CreateImageDialog(void) {} - int fDiskSizeIdx; - int fDiskFormatIdx; - BOOL fAllocTracks_DOS; - int fDOSVolumeNum; - CString fVolName_ProDOS; - CString fVolName_Pascal; - CString fVolName_HFS; + int fDiskSizeIdx; + int fDiskFormatIdx; + BOOL fAllocTracks_DOS; + int fDOSVolumeNum; + CString fVolName_ProDOS; + CString fVolName_Pascal; + CString fVolName_HFS; - long fNumBlocks; // computed when DoModal finishes + long fNumBlocks; // computed when DoModal finishes private: - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); -// BOOL OnHelpInfo(HELPINFO* lpHelpInfo); +// BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - afx_msg void OnFormatChangeRange(UINT nID); - afx_msg void OnSizeChangeRange(UINT nID); - afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - afx_msg void OnHelp(void); + afx_msg void OnFormatChangeRange(UINT nID); + afx_msg void OnSizeChangeRange(UINT nID); + afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg void OnHelp(void); - bool IsValidVolumeName_DOS(const char* name); - bool IsValidVolumeName_ProDOS(const char* name); - bool IsValidVolumeName_Pascal(const char* name); - bool IsValidVolumeName_HFS(const char* name); + bool IsValidVolumeName_DOS(const char* name); + bool IsValidVolumeName_ProDOS(const char* name); + bool IsValidVolumeName_Pascal(const char* name); + bool IsValidVolumeName_HFS(const char* name); - bool fExtendedOpts; + bool fExtendedOpts; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__CREATE_IMAGE_DIALOG__*/ \ No newline at end of file diff --git a/app/CreateSubdirDialog.cpp b/app/CreateSubdirDialog.cpp index 1d5327a..0a51d71 100644 --- a/app/CreateSubdirDialog.cpp +++ b/app/CreateSubdirDialog.cpp @@ -13,7 +13,7 @@ #include "CreateSubdirDialog.h" BEGIN_MESSAGE_MAP(CreateSubdirDialog, CDialog) - ON_WM_HELPINFO() + ON_WM_HELPINFO() END_MESSAGE_MAP() /* @@ -22,16 +22,16 @@ END_MESSAGE_MAP() BOOL CreateSubdirDialog::OnInitDialog(void) { - /* do the DoDataExchange stuff */ - CDialog::OnInitDialog(); + /* do the DoDataExchange stuff */ + CDialog::OnInitDialog(); - /* select the default text and set the focus */ - CEdit* pEdit = (CEdit*) GetDlgItem(IDC_CREATESUBDIR_NEW); - ASSERT(pEdit != nil); - pEdit->SetSel(0, -1); - pEdit->SetFocus(); + /* select the default text and set the focus */ + CEdit* pEdit = (CEdit*) GetDlgItem(IDC_CREATESUBDIR_NEW); + ASSERT(pEdit != nil); + pEdit->SetSel(0, -1); + pEdit->SetFocus(); - return FALSE; // we set the focus + return FALSE; // we set the focus } /* @@ -40,35 +40,35 @@ CreateSubdirDialog::OnInitDialog(void) void CreateSubdirDialog::DoDataExchange(CDataExchange* pDX) { - CString msg, failed; + CString msg, failed; - msg = ""; - failed.LoadString(IDS_MB_APP_NAME); + msg = ""; + failed.LoadString(IDS_MB_APP_NAME); - /* put fNewName last so it gets the focus after failure */ - DDX_Text(pDX, IDC_CREATESUBDIR_BASE, fBasePath); - DDX_Text(pDX, IDC_CREATESUBDIR_NEW, fNewName); + /* put fNewName last so it gets the focus after failure */ + DDX_Text(pDX, IDC_CREATESUBDIR_BASE, fBasePath); + DDX_Text(pDX, IDC_CREATESUBDIR_NEW, fNewName); - /* validate the path field */ - if (pDX->m_bSaveAndValidate) { - if (fNewName.IsEmpty()) { - msg = "You must specify a new name."; - goto fail; - } + /* validate the path field */ + if (pDX->m_bSaveAndValidate) { + if (fNewName.IsEmpty()) { + msg = "You must specify a new name."; + goto fail; + } - msg = fpArchive->TestPathName(fpParentEntry, fBasePath, fNewName, - '\0'); - if (!msg.IsEmpty()) - goto fail; - } + msg = fpArchive->TestPathName(fpParentEntry, fBasePath, fNewName, + '\0'); + if (!msg.IsEmpty()) + goto fail; + } - return; + return; fail: - ASSERT(!msg.IsEmpty()); - MessageBox(msg, failed, MB_OK); - pDX->Fail(); - return; + ASSERT(!msg.IsEmpty()); + MessageBox(msg, failed, MB_OK); + pDX->Fail(); + return; } /* @@ -77,6 +77,6 @@ fail: BOOL CreateSubdirDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } diff --git a/app/CreateSubdirDialog.h b/app/CreateSubdirDialog.h index c8ee049..ab12ecc 100644 --- a/app/CreateSubdirDialog.h +++ b/app/CreateSubdirDialog.h @@ -17,29 +17,29 @@ */ class CreateSubdirDialog : public CDialog { public: - CreateSubdirDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_CREATE_SUBDIR, pParentWnd) - { - fpArchive = nil; - fpParentEntry = nil; - } - virtual ~CreateSubdirDialog(void) {} + CreateSubdirDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_CREATE_SUBDIR, pParentWnd) + { + fpArchive = nil; + fpParentEntry = nil; + } + virtual ~CreateSubdirDialog(void) {} - CString fBasePath; // where subdir will be created - CString fNewName; - const GenericArchive* fpArchive; - const GenericEntry* fpParentEntry; + CString fBasePath; // where subdir will be created + CString fNewName; + const GenericArchive* fpArchive; + const GenericEntry* fpParentEntry; protected: - // overrides - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + // overrides + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); private: - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__CREATESUBDIRDIALOG__*/ diff --git a/app/DEFileDialog.cpp b/app/DEFileDialog.cpp index 20853f0..554bfd6 100644 --- a/app/DEFileDialog.cpp +++ b/app/DEFileDialog.cpp @@ -11,8 +11,8 @@ BEGIN_MESSAGE_MAP(DEFileDialog, CDialog) - ON_EN_CHANGE(IDC_DEFILE_FILENAME, OnChange) - ON_WM_HELPINFO() + ON_EN_CHANGE(IDC_DEFILE_FILENAME, OnChange) + ON_WM_HELPINFO() END_MESSAGE_MAP() /* @@ -22,11 +22,11 @@ END_MESSAGE_MAP() BOOL DEFileDialog::OnInitDialog(void) { - CWnd* pWnd = GetDlgItem(IDOK); - ASSERT(pWnd != nil); - pWnd->EnableWindow(FALSE); + CWnd* pWnd = GetDlgItem(IDOK); + ASSERT(pWnd != nil); + pWnd->EnableWindow(FALSE); - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } /* @@ -35,8 +35,8 @@ DEFileDialog::OnInitDialog(void) void DEFileDialog::DoDataExchange(CDataExchange* pDX) { - DDX_Text(pDX, IDC_DEFILE_FILENAME, fName); - DDX_Check(pDX, IDC_DEFILE_RSRC, fOpenRsrcFork); + DDX_Text(pDX, IDC_DEFILE_FILENAME, fName); + DDX_Check(pDX, IDC_DEFILE_RSRC, fOpenRsrcFork); } /* @@ -46,16 +46,16 @@ DEFileDialog::DoDataExchange(CDataExchange* pDX) void DEFileDialog::OnChange(void) { - CEdit* pEdit = (CEdit*) GetDlgItem(IDC_DEFILE_FILENAME); - ASSERT(pEdit != nil); + CEdit* pEdit = (CEdit*) GetDlgItem(IDC_DEFILE_FILENAME); + ASSERT(pEdit != nil); - CString str; - pEdit->GetWindowText(str); - //WMSG2("STR is '%s' (%d)\n", str, str.GetLength()); + CString str; + pEdit->GetWindowText(str); + //WMSG2("STR is '%s' (%d)\n", str, str.GetLength()); - CWnd* pWnd = GetDlgItem(IDOK); - ASSERT(pWnd != nil); - pWnd->EnableWindow(!str.IsEmpty()); + CWnd* pWnd = GetDlgItem(IDOK); + ASSERT(pWnd != nil); + pWnd->EnableWindow(!str.IsEmpty()); } /* @@ -64,6 +64,6 @@ DEFileDialog::OnChange(void) BOOL DEFileDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } diff --git a/app/DEFileDialog.h b/app/DEFileDialog.h index b958978..ae43bb9 100644 --- a/app/DEFileDialog.h +++ b/app/DEFileDialog.h @@ -29,32 +29,32 @@ using namespace DiskImgLib; */ class DEFileDialog : public CDialog { public: - DEFileDialog(CWnd* pParentWnd = NULL) : CDialog(IDD_DEFILE, pParentWnd) - { - fOpenRsrcFork = false; - fName = ""; - } - virtual ~DEFileDialog(void) {} + DEFileDialog(CWnd* pParentWnd = NULL) : CDialog(IDD_DEFILE, pParentWnd) + { + fOpenRsrcFork = false; + fName = ""; + } + virtual ~DEFileDialog(void) {} - void Setup(DiskFS* pDiskFS) { - fpDiskFS = pDiskFS; - } + void Setup(DiskFS* pDiskFS) { + fpDiskFS = pDiskFS; + } - CString fName; - int fOpenRsrcFork; + CString fName; + int fOpenRsrcFork; protected: - // overrides - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + // overrides + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - afx_msg virtual void OnChange(void); - afx_msg virtual BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg virtual void OnChange(void); + afx_msg virtual BOOL OnHelpInfo(HELPINFO* lpHelpInfo); private: - DiskFS* fpDiskFS; + DiskFS* fpDiskFS; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__DEFILEDIALOG__*/ \ No newline at end of file diff --git a/app/DiskArchive.cpp b/app/DiskArchive.cpp index 017b290..6879116 100644 --- a/app/DiskArchive.cpp +++ b/app/DiskArchive.cpp @@ -1,3157 +1,3157 @@ -/* - * CiderPress - * Copyright (C) 2009 by CiderPress authors. All Rights Reserved. - * Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved. - * See the file LICENSE for distribution terms. - */ -/* - * Bridge between DiskImg and GenericArchive. - */ -#include "stdafx.h" -#include "DiskArchive.h" -#include "NufxArchive.h" -#include "Preferences.h" -#include "Main.h" -#include "ImageFormatDialog.h" -#include "RenameEntryDialog.h" -#include "ConfirmOverwriteDialog.h" -#include "../diskimg/DiskImgDetail.h" - -static const char* kEmptyFolderMarker = ".$$EmptyFolder"; - - -/* - * =========================================================================== - * DiskEntry - * =========================================================================== - */ - -/* - * Extract data from a disk image. - * - * If "*ppText" is non-nil, the data will be read into the pointed-to buffer - * so long as it's shorter than *pLength bytes. The value in "*pLength" - * will be set to the actual length used. - * - * If "*ppText" is nil, the uncompressed data will be placed into a buffer - * allocated with "new[]". - * - * Returns IDOK on success, IDCANCEL if the operation was cancelled by the - * user, and -1 value on failure. On failure, "*pErrMsg" holds an error - * message. - * - * "which" is an anonymous GenericArchive enum (e.g. "kDataThread"). - */ -int -DiskEntry::ExtractThreadToBuffer(int which, char** ppText, long* pLength, - CString* pErrMsg) const -{ - DIError dierr; - A2FileDescr* pOpenFile = nil; - char* dataBuf = nil; - bool rsrcFork; - bool needAlloc = true; - int result = -1; - - ASSERT(fpFile != nil); - ASSERT(pErrMsg != nil); - *pErrMsg = ""; - - if (*ppText != nil) - needAlloc = false; - - if (GetDamaged()) { - *pErrMsg = "File is damaged"; - goto bail; - } - - if (which == kDataThread) - rsrcFork = false; - else if (which == kRsrcThread) - rsrcFork = true; - else { - *pErrMsg = "No such fork"; - goto bail; - } - - LONGLONG len; - if (rsrcFork) - len = fpFile->GetRsrcLength(); - else - len = fpFile->GetDataLength(); - - if (len == 0) { - if (needAlloc) { - *ppText = new char[1]; - **ppText = '\0'; - } - *pLength = 0; - result = IDOK; - goto bail; - } else if (len < 0) { - assert(rsrcFork); // forked files always have a data fork - *pErrMsg = "That fork doesn't exist"; - goto bail; - } - - dierr = fpFile->Open(&pOpenFile, true, rsrcFork); - if (dierr != kDIErrNone) { - *pErrMsg = "File open failed"; - goto bail; - } - - SET_PROGRESS_BEGIN(); - pOpenFile->SetProgressUpdater(DiskArchive::ProgressCallback, len, nil); - - if (needAlloc) { - dataBuf = new char[(int) len]; - if (dataBuf == nil) { - pErrMsg->Format("ERROR: allocation of %ld bytes failed", len); - goto bail; - } - } else { - if (*pLength < (long) len) { - pErrMsg->Format("ERROR: buf size %ld too short (%ld)", - *pLength, (long) len); - goto bail; - } - dataBuf = *ppText; - } - - dierr = pOpenFile->Read(dataBuf, (size_t) len); - if (dierr != kDIErrNone) { - if (dierr == kDIErrCancelled) { - result = IDCANCEL; - } else { - pErrMsg->Format("File read failed: %s", - DiskImgLib::DIStrError(dierr)); - } - goto bail; - } - - if (needAlloc) - *ppText = dataBuf; - *pLength = (long) len; - result = IDOK; - -bail: - if (pOpenFile != nil) - pOpenFile->Close(); - if (result == IDOK) { - SET_PROGRESS_END(); - ASSERT(pErrMsg->IsEmpty()); - } else { - ASSERT(result == IDCANCEL || !pErrMsg->IsEmpty()); - if (needAlloc) { - delete[] dataBuf; - ASSERT(*ppText == nil); - } - } - return result; -} - -/* - * Extract data from a thread to a file. Since we're not copying to memory, - * we can't assume that we're able to hold the entire file all at once. - * - * Returns IDOK on success, IDCANCEL if the operation was cancelled by the - * user, and -1 value on failure. On failure, "*pMsg" holds an - * error message. - */ -int -DiskEntry::ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, - ConvertHighASCII convHA, CString* pErrMsg) const -{ - A2FileDescr* pOpenFile = nil; - bool rsrcFork; - int result = -1; - - ASSERT(IDOK != -1 && IDCANCEL != -1); - ASSERT(fpFile != nil); - - if (which == kDataThread) - rsrcFork = false; - else if (which == kRsrcThread) - rsrcFork = true; - else { - /* if we handle disk images, make sure we disable "conv" */ - *pErrMsg = "No such fork"; - goto bail; - } - - LONGLONG len; - if (rsrcFork) - len = fpFile->GetRsrcLength(); - else - len = fpFile->GetDataLength(); - - if (len == 0) { - WMSG0("Empty fork\n"); - result = IDOK; - goto bail; - } else if (len < 0) { - assert(rsrcFork); // forked files always have a data fork - *pErrMsg = "That fork doesn't exist"; - goto bail; - } - - DIError dierr; - dierr = fpFile->Open(&pOpenFile, true, rsrcFork); - if (dierr != kDIErrNone) { - *pErrMsg = "Unable to open file on disk image"; - goto bail; - } - - dierr = CopyData(pOpenFile, outfp, conv, convHA, pErrMsg); - if (dierr != kDIErrNone) { - if (pErrMsg->IsEmpty()) { - pErrMsg->Format("Failed while copying data: %s\n", - DiskImgLib::DIStrError(dierr)); - } - goto bail; - } - - result = IDOK; - -bail: - if (pOpenFile != nil) - pOpenFile->Close(); - return result; -} - -/* - * Copy data from the open A2File to outfp, possibly converting EOL along - * the way. - */ -DIError -DiskEntry::CopyData(A2FileDescr* pOpenFile, FILE* outfp, ConvertEOL conv, - ConvertHighASCII convHA, CString* pMsg) const -{ - DIError dierr = kDIErrNone; - const int kChunkSize = 16384; - char buf[kChunkSize]; - //bool firstChunk = true; - //EOLType sourceType; - bool lastCR = false; - LONGLONG srcLen, dataRem; - - /* get the length of the open file */ - dierr = pOpenFile->Seek(0, DiskImgLib::kSeekEnd); - if (dierr != kDIErrNone) - goto bail; - srcLen = pOpenFile->Tell(); - dierr = pOpenFile->Rewind(); - if (dierr != kDIErrNone) - goto bail; - ASSERT(srcLen > 0); // empty files should've been caught earlier - - SET_PROGRESS_BEGIN(); - pOpenFile->SetProgressUpdater(DiskArchive::ProgressCallback, srcLen, nil); - - /* - * Loop until all data copied. - */ - dataRem = srcLen; - while (dataRem) { - int chunkLen; - - if (dataRem > kChunkSize) - chunkLen = kChunkSize; - else - chunkLen = (int) dataRem; - - /* read a chunk from the source file */ - dierr = pOpenFile->Read(buf, chunkLen); - if (dierr != kDIErrNone) { - pMsg->Format("File read failed: %s", - DiskImgLib::DIStrError(dierr)); - goto bail; - } - - /* write chunk to destination file */ - int err = GenericEntry::WriteConvert(outfp, buf, chunkLen, &conv, - &convHA, &lastCR); - if (err != 0) { - pMsg->Format("File write failed: %s", strerror(err)); - dierr = kDIErrGeneric; - goto bail; - } - - dataRem -= chunkLen; - //SET_PROGRESS_UPDATE(ComputePercent(srcLen - dataRem, srcLen)); - } - -bail: - pOpenFile->ClearProgressUpdater(); - SET_PROGRESS_END(); - return dierr; -} - - -/* - * Figure out whether or not we're allowed to change a file's type and - * aux type. - */ -bool -DiskEntry::GetFeatureFlag(Feature feature) const -{ - DiskImg::FSFormat format; - - format = fpFile->GetDiskFS()->GetDiskImg()->GetFSFormat(); - - switch (feature) { - case kFeatureCanChangeType: - { - //if (GetRecordKind() == kRecordKindVolumeDir) - // return false; - - switch (format) { - case DiskImg::kFormatProDOS: - case DiskImg::kFormatPascal: - case DiskImg::kFormatMacHFS: - case DiskImg::kFormatDOS32: - case DiskImg::kFormatDOS33: - return true; - default: - return false; - } - } - case kFeaturePascalTypes: - { - switch (format) { - case DiskImg::kFormatPascal: - return true; - default: - return false; - } - } - case kFeatureDOSTypes: - { - switch (format) { - case DiskImg::kFormatDOS32: - case DiskImg::kFormatDOS33: - return true; - default: - return false; - } - } - case kFeatureHFSTypes: - { - switch (format) { - case DiskImg::kFormatMacHFS: - return true; - default: - return false; - } - } - case kFeatureHasFullAccess: - { - switch (format) { - case DiskImg::kFormatProDOS: - return true; - default: - return false; - } - } - case kFeatureHasSimpleAccess: - { - switch (format) { - case DiskImg::kFormatDOS33: - case DiskImg::kFormatDOS32: - case DiskImg::kFormatCPM: - case DiskImg::kFormatMacHFS: - return true; - default: - return false; - } - } - case kFeatureHasInvisibleFlag: - { - switch(format) { - case DiskImg::kFormatProDOS: - case DiskImg::kFormatMacHFS: - return true; - default: - return false; - } - } - default: - WMSG1("Unexpected feature flag %d\n", feature); - assert(false); - return false; - } - - assert(false); - return false; -} - - -/* - * =========================================================================== - * DiskArchive - * =========================================================================== - */ - -/* - * Perform one-time initialization of the DiskLib library. - */ -/*static*/ CString -DiskArchive::AppInit(void) -{ - CString result(""); - DIError dierr; - long major, minor, bug; - - WMSG0("Initializing DiskImg library\n"); - - // set this before initializing, so we can see init debug msgs - DiskImgLib::Global::SetDebugMsgHandler(DebugMsgHandler); - - dierr = DiskImgLib::Global::AppInit(); - if (dierr != kDIErrNone) { - result.Format("DiskImg DLL failed to initialize: %s\n", - DiskImgLib::DIStrError(dierr)); - goto bail; - } - - DiskImgLib::Global::GetVersion(&major, &minor, &bug); - if (major != kDiskImgVersionMajor || minor < kDiskImgVersionMinor) { - result.Format("Older or incompatible version of DiskImg DLL found.\r\r" - "Wanted v%d.%d.x, found %ld.%ld.%ld.", - kDiskImgVersionMajor, kDiskImgVersionMinor, - major, minor, bug); - goto bail; - } - -bail: - return result; -} - -/* - * Perform one-time cleanup of DiskImgLib at shutdown time. - */ -/*static*/ void -DiskArchive::AppCleanup(void) -{ - DiskImgLib::Global::AppCleanup(); -} - - -/* - * Handle a debug message from the DiskImg library. - */ -/*static*/ void -DiskArchive::DebugMsgHandler(const char* file, int line, const char* msg) -{ - ASSERT(file != nil); - ASSERT(msg != nil); - -#if defined(_DEBUG_LOG) - //fprintf(gLog, "%s(%d) : %s", file, line, msg); - fprintf(gLog, "%05u %s", gPid, msg); -#elif defined(_DEBUG) - _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s", msg); -#else - /* do nothing */ -#endif -} - -/* - * Progress update callback, called from DiskImgLib during read/write - * operations. - * - * Returns "true" if we should continue; - */ -/*static*/ bool -DiskArchive::ProgressCallback(DiskImgLib::A2FileDescr* pFile, - DiskImgLib::di_off_t max, DiskImgLib::di_off_t current, void* state) -{ - int status; - - //::Sleep(10); - status = SET_PROGRESS_UPDATE(ComputePercent(current, max)); - if (status == IDCANCEL) { - WMSG0("IDCANCEL returned from Main progress updater\n"); - return false; - } - - return true; // tell DiskImgLib to continue what it's doing -} - -/* - * Progress update callback, called from DiskImgLib while scanning a volume - * during Open(). - * - * Returns "true" if we should continue; - */ -/*static*/ bool -DiskArchive::ScanProgressCallback(void* cookie, const char* str, int count) -{ - CString fmt; - bool cont; - - if (count == 0) - fmt = str; - else - fmt.Format("%s (%%d)", str); - cont = SET_PROGRESS_COUNTER_2(fmt, count); - - if (!cont) { - WMSG0("cancelled\n"); - } - - return cont; -} - - -/* - * Finish instantiating a DiskArchive object by opening an existing file. - */ -GenericArchive::OpenResult -DiskArchive::Open(const char* filename, bool readOnly, CString* pErrMsg) -{ - DIError dierr; - CString errMsg; - OpenResult result = kResultUnknown; - const Preferences* pPreferences = GET_PREFERENCES(); - - ASSERT(fpPrimaryDiskFS == nil); - ASSERT(filename != nil); - //ASSERT(ext != nil); - - ASSERT(pPreferences != nil); - - fIsReadOnly = readOnly; - - // special case for volume open - bool isVolume = false; - if (filename[0] >= 'A' && filename[0] <= 'Z' && - filename[1] == ':' && filename[2] == '\\' && - filename[3] == '\0') - { - isVolume = true; - } - - /* - * Open the image. This can be very slow for compressed images, - * especially 3.5" FDI images. - */ - { - CWaitCursor waitc; - - dierr = fDiskImg.OpenImage(filename, PathProposal::kLocalFssep, readOnly); - if (dierr == kDIErrAccessDenied && !readOnly && !isVolume) { - // retry file open with read-only set - // don't do that for volumes -- assume they know what they want - WMSG0(" Retrying open with read-only set\n"); - fIsReadOnly = readOnly = true; - dierr = fDiskImg.OpenImage(filename, PathProposal::kLocalFssep, readOnly); - } - if (dierr != kDIErrNone) { - if (dierr == kDIErrFileArchive) - result = kResultFileArchive; - else { - result = kResultFailure; - errMsg.Format("Unable to open '%s': %s.", filename, - DiskImgLib::DIStrError(dierr)); - } - goto bail; - } - } - - dierr = fDiskImg.AnalyzeImage(); - if (dierr != kDIErrNone) { - result = kResultFailure; - errMsg.Format("Analysis of '%s' failed: %s", filename, - DiskImgLib::DIStrError(dierr)); - goto bail; - } - - /* allow them to override sector order and filesystem, if requested */ - if (pPreferences->GetPrefBool(kPrQueryImageFormat)) { - ImageFormatDialog imf; - - imf.InitializeValues(&fDiskImg); - imf.fFileSource = filename; - imf.SetQueryDisplayFormat(false); - imf.SetAllowGenericFormats(false); - - if (imf.DoModal() != IDOK) { - WMSG0("User bailed on IMF dialog\n"); - result = kResultCancel; - goto bail; - } - - if (imf.fSectorOrder != fDiskImg.GetSectorOrder() || - imf.fFSFormat != fDiskImg.GetFSFormat()) - { - WMSG0("Initial values overridden, forcing img format\n"); - dierr = fDiskImg.OverrideFormat(fDiskImg.GetPhysicalFormat(), - imf.fFSFormat, imf.fSectorOrder); - if (dierr != kDIErrNone) { - result = kResultFailure; - errMsg.Format("Unable to access disk image using selected" - " parameters. Error: %s.", - DiskImgLib::DIStrError(dierr)); - goto bail; - } - } - } - - if (fDiskImg.GetFSFormat() == DiskImg::kFormatUnknown || - fDiskImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown) - { - result = kResultFailure; - errMsg.Format("Unable to identify filesystem on '%s'", filename); - goto bail; - } - - /* create an appropriate DiskFS object */ - fpPrimaryDiskFS = fDiskImg.OpenAppropriateDiskFS(); - if (fpPrimaryDiskFS == nil) { - /* unknown FS should've been caught above! */ - ASSERT(false); - result = kResultFailure; - errMsg.Format("Format of '%s' not recognized.", filename); - goto bail; - } - - fpPrimaryDiskFS->SetScanForSubVolumes(DiskFS::kScanSubEnabled); - - /* - * Scan all files and on the disk image, and recursively descend into - * sub-volumes. Can be slow on physical volumes. - * - * This is really only useful for ProDOS and HFS disks. Nothing else - * can be large enough to really get slow, and nothing else is likely - * to show up in a large multi-partition image. - * - * THOUGHT: only show the dialog if the volume is over a certain size. - */ - { - MainWindow* pMain = GET_MAIN_WINDOW(); - ProgressCounterDialog* pProgress; - - pProgress = new ProgressCounterDialog; - pProgress->Create(_T("Examining contents, please wait..."), pMain); - pProgress->SetCounterFormat("Scanning..."); - pProgress->CenterWindow(); - //pMain->PeekAndPump(); // redraw - CWaitCursor waitc; - - /* set up progress dialog and scan all files */ - pMain->SetProgressCounterDialog(pProgress); - fDiskImg.SetScanProgressCallback(ScanProgressCallback, this); - - dierr = fpPrimaryDiskFS->Initialize(&fDiskImg, DiskFS::kInitFull); - - fDiskImg.SetScanProgressCallback(nil, nil); - pMain->SetProgressCounterDialog(nil); - pProgress->DestroyWindow(); - - if (dierr != kDIErrNone) { - if (dierr == kDIErrCancelled) { - result = kResultCancel; - } else { - result = kResultFailure; - errMsg.Format("Error reading list of files from disk: %s", - DiskImgLib::DIStrError(dierr)); - } - goto bail; - } - } - - if (LoadContents() != 0) { - result = kResultFailure; - errMsg.Format("Failed while loading contents of disk image."); - goto bail; - } - - /* - * Force read-only flag if underlying FS doesn't allow RW. We need to - * consider embedded filesystems, so we only set RO if none of the - * filesystems are writable. - * - * BUG: this only checks the first level. Should be fully recursive. - */ - if (!fpPrimaryDiskFS->GetReadWriteSupported()) { - const DiskFS::SubVolume* pSubVol; - - fIsReadOnly = true; - pSubVol = fpPrimaryDiskFS->GetNextSubVolume(nil); - while (pSubVol != nil) { - if (pSubVol->GetDiskFS()->GetReadWriteSupported()) { - fIsReadOnly = false; - break; - } - - pSubVol = fpPrimaryDiskFS->GetNextSubVolume(pSubVol); - } - } - - /* force read-only if the primary is damaged */ - if (fpPrimaryDiskFS->GetFSDamaged()) - fIsReadOnly = true; - /* force read-only if the DiskImg thinks a wrapper is damaged */ - if (fpPrimaryDiskFS->GetDiskImg()->GetReadOnly()) - fIsReadOnly = true; - -// /* force read-only on .gz/.zip unless pref allows */ -// if (fDiskImg.GetOuterFormat() != DiskImg::kOuterFormatNone) { -// if (pPreferences->GetPrefBool(kPrWriteZips) == 0) -// fIsReadOnly = true; -// } - - SetPathName(filename); - result = kResultSuccess; - - /* set any preferences-based settings */ - PreferencesChanged(); - -bail: - *pErrMsg = errMsg; - if (!errMsg.IsEmpty()) { - assert(result == kResultFailure); - delete fpPrimaryDiskFS; - fpPrimaryDiskFS = nil; - } else { - assert(result != kResultFailure); - } - return result; -} - - -/* - * Finish instantiating a DiskArchive object by creating a new archive. - * - * Returns an error string on failure, or "" on success. - */ -CString -DiskArchive::New(const char* fileName, const void* vOptions) -{ - const Preferences* pPreferences = GET_PREFERENCES(); - NewOptions* pOptions = (NewOptions*) vOptions; - CString volName; - long numBlocks = -1; - long numTracks = -1; - int numSectors; - CString retmsg; - DIError dierr; - bool allowLowerCase; - - ASSERT(fileName != nil); - ASSERT(pOptions != nil); - - allowLowerCase = pPreferences->GetPrefBool(kPrProDOSAllowLower) != 0; - - switch (pOptions->base.format) { - case DiskImg::kFormatUnknown: - numBlocks = pOptions->blank.numBlocks; - break; - case DiskImg::kFormatProDOS: - volName = pOptions->prodos.volName; - numBlocks = pOptions->prodos.numBlocks; - break; - case DiskImg::kFormatPascal: - volName = pOptions->pascalfs.volName; - numBlocks = pOptions->pascalfs.numBlocks; - break; - case DiskImg::kFormatMacHFS: - volName = pOptions->hfs.volName; - numBlocks = pOptions->hfs.numBlocks; - break; - case DiskImg::kFormatDOS32: - numTracks = pOptions->dos.numTracks; - numSectors = pOptions->dos.numSectors; - - if (numTracks < DiskFSDOS33::kMinTracks || - numTracks > DiskFSDOS33::kMaxTracks) - { - retmsg.Format("Invalid DOS32 track count"); - goto bail; - } - if (numSectors != 13) { - retmsg.Format("Invalid DOS32 sector count"); - goto bail; - } - if (pOptions->dos.allocDOSTracks) - volName = "DOS"; - break; - case DiskImg::kFormatDOS33: - numTracks = pOptions->dos.numTracks; - numSectors = pOptions->dos.numSectors; - - if (numTracks < DiskFSDOS33::kMinTracks || - numTracks > DiskFSDOS33::kMaxTracks) - { - retmsg.Format("Invalid DOS33 track count"); - goto bail; - } - if (numSectors != 16 && numSectors != 32) { // no 13-sector (yet) - retmsg.Format("Invalid DOS33 sector count"); - goto bail; - } - if (pOptions->dos.allocDOSTracks) - volName = "DOS"; - break; - default: - retmsg.Format("Unsupported disk format"); - goto bail; - } - - WMSG4("DiskArchive: new '%s' %ld %s in '%s'\n", - (const char*)volName, numBlocks, - DiskImg::ToString(pOptions->base.format), fileName); - - bool canSkipFormat; - if (IsWin9x()) - canSkipFormat = false; - else - canSkipFormat = true; - - /* - * Create an image with the appropriate characteristics. We set - * "skipFormat" because we know this will be a brand-new file, and - * we're not currently creating nibble images. - * - * GLITCH: under Win98/ME, brand-new files contain the previous contents - * of the hard drive. We need to explicitly zero them out. We don't - * want to do it under Win2K/XP because it can be slow for larger - * volumes. - */ - if (numBlocks > 0) { - dierr = fDiskImg.CreateImage(fileName, nil, - DiskImg::kOuterFormatNone, - DiskImg::kFileFormatUnadorned, - DiskImg::kPhysicalFormatSectors, - nil, - pOptions->base.sectorOrder, - DiskImg::kFormatGenericProDOSOrd, // arg must be generic - numBlocks, - canSkipFormat); - } else { - ASSERT(numTracks > 0); - dierr = fDiskImg.CreateImage(fileName, nil, - DiskImg::kOuterFormatNone, - DiskImg::kFileFormatUnadorned, - DiskImg::kPhysicalFormatSectors, - nil, - pOptions->base.sectorOrder, - DiskImg::kFormatGenericProDOSOrd, // arg must be generic - numTracks, numSectors, - canSkipFormat); - } - if (dierr != kDIErrNone) { - retmsg.Format("Unable to create disk image: %s.", - DiskImgLib::DIStrError(dierr)); - goto bail; - } - - if (pOptions->base.format == DiskImg::kFormatUnknown) - goto skip_format; - - if (pOptions->base.format == DiskImg::kFormatDOS33 || - pOptions->base.format == DiskImg::kFormatDOS32) - fDiskImg.SetDOSVolumeNum(pOptions->dos.volumeNum); - - /* - * If we don't allow lower case in ProDOS filenames, don't allow them - * in volume names either. This works because we don't allow ' ' in - * volume names; otherwise we'd need to invoke a ProDOS-specific call - * to convert the ' ' to '.'. (Or we could just do it ourselves.) - * - * We can't ask the ProDOS DiskFS to force upper case for us because - * the ProDOS DiskFS object doesn't yet exist. - */ - if (pOptions->base.format == DiskImg::kFormatProDOS && !allowLowerCase) - volName.MakeUpper(); - - /* format it */ - dierr = fDiskImg.FormatImage(pOptions->base.format, volName); - if (dierr != kDIErrNone) { - retmsg.Format("Unable to format disk image: %s.", - DiskImgLib::DIStrError(dierr)); - goto bail; - } - fpPrimaryDiskFS = fDiskImg.OpenAppropriateDiskFS(false); - if (fpPrimaryDiskFS == nil) { - retmsg.Format("Unable to create DiskFS."); - goto bail; - } - - /* prep it */ - dierr = fpPrimaryDiskFS->Initialize(&fDiskImg, DiskFS::kInitFull); - if (dierr != kDIErrNone) { - retmsg.Format("Error reading list of files from disk: %s", - DiskImgLib::DIStrError(dierr)); - goto bail; - } - - /* this is pretty meaningless, but do it to ensure we're initialized */ - if (LoadContents() != 0) { - retmsg.Format("Failed while loading contents of disk image."); - goto bail; - } - -skip_format: - SetPathName(fileName); - - /* set any preferences-based settings */ - PreferencesChanged(); - -bail: - return retmsg; -} - -/* - * Close the DiskArchive ojbect. - */ -CString -DiskArchive::Close(void) -{ - if (fpPrimaryDiskFS != nil) { - WMSG0("DiskArchive shutdown closing disk image\n"); - delete fpPrimaryDiskFS; - fpPrimaryDiskFS = nil; - } - - DIError dierr; - dierr = fDiskImg.CloseImage(); - if (dierr != kDIErrNone) { - MainWindow* pMainWin = (MainWindow*)::AfxGetMainWnd(); - CString msg, failed; - - msg.Format("Failed while closing disk image: %s.", - DiskImgLib::DIStrError(dierr)); - failed.LoadString(IDS_FAILED); - WMSG1("During close: %s\n", (const char*) msg); - - pMainWin->MessageBox(msg, failed, MB_OK); - } - - return ""; -} - -/* - * Flush the DiskArchive object. - * - * Most of the stuff we do with disk images goes straight through, but in - * the case of compressed disks we don't normally re-compress them until - * it's time to close them. This forces us to update the copy on disk. - * - * Returns an empty string on success, or an error message on failure. - */ -CString -DiskArchive::Flush(void) -{ - DIError dierr; - CWaitCursor waitc; - - assert(fpPrimaryDiskFS != nil); - - dierr = fpPrimaryDiskFS->Flush(DiskImg::kFlushAll); - if (dierr != kDIErrNone) { - CString errMsg; - - errMsg.Format("Attempt to flush the current archive failed: %s.", - DiskImgLib::DIStrError(dierr)); - return errMsg; - } - - return ""; -} - -/* - * Returns "true" if the archive has un-flushed modifications pending. - */ -bool -DiskArchive::IsModified(void) const -{ - assert(fpPrimaryDiskFS != nil); - - return fpPrimaryDiskFS->GetDiskImg()->GetDirtyFlag(); -} - -/* - * Return an description of the disk archive, suitable for display in the - * main title bar. - */ -void -DiskArchive::GetDescription(CString* pStr) const -{ - if (fpPrimaryDiskFS == nil) - return; - - if (fpPrimaryDiskFS->GetVolumeID() != nil) - pStr->Format("Disk Image - %s", fpPrimaryDiskFS->GetVolumeID()); -} - - -/* - * Load the contents of a "disk archive". - * - * Returns 0 on success. - */ -int -DiskArchive::LoadContents(void) -{ - int result; - - WMSG0("DiskArchive LoadContents\n"); - ASSERT(fpPrimaryDiskFS != nil); - - { - MainWindow* pMain = GET_MAIN_WINDOW(); - ExclusiveModelessDialog* pWaitDlg = new ExclusiveModelessDialog; - pWaitDlg->Create(IDD_LOADING, pMain); - pWaitDlg->CenterWindow(); - pMain->PeekAndPump(); // redraw - CWaitCursor waitc; - - result = LoadDiskFSContents(fpPrimaryDiskFS, ""); - - SET_PROGRESS_COUNTER(-1); - - pWaitDlg->DestroyWindow(); - //pMain->PeekAndPump(); // redraw - } - - return result; -} - -/* - * Reload the stuff from the underlying DiskFS. - * - * This also does a "lite" flush of the disk data. For files that are - * essentially being written as we go, this does little more than clear - * the "dirty" flag. Files that need to be recompressed or have some - * other slow operation remain dirty. - * - * We don't need to do the flush as part of the reload -- we can load the - * contents with everything in a perfectly dirty state. We don't need to - * do it at all. We do it to keep the "dirty" flag clear when nothing is - * really dirty, and we do it here because almost all of our functions call - * "reload" after making changes, which makes it convenient to call from here. - */ -CString -DiskArchive::Reload() -{ - fReloadFlag = true; // tell everybody that cached data is invalid - - (void) fpPrimaryDiskFS->Flush(DiskImg::kFlushFastOnly); - - DeleteEntries(); // a GenericArchive operation - - if (LoadContents() != 0) - return "Disk image reload failed."; - - return ""; -} - -/* - * Reload the contents of the archive, showing an error message if the - * reload fails. - * - * Returns 0 on success, -1 on failure. - */ -int -DiskArchive::InternalReload(CWnd* pMsgWnd) -{ - CString errMsg; - - errMsg = Reload(); - - if (!errMsg.IsEmpty()) { - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - return -1; - } - - return 0; -} - -/* - * Load the contents of a DiskFS. - * - * Recursively handle sub-volumes. "volName" holds the name of the - * sub-volume as it should appear in the list. - */ -int -DiskArchive::LoadDiskFSContents(DiskFS* pDiskFS, const char* volName) -{ - static const char* kBlankFileName = ""; - A2File* pFile; - DiskEntry* pNewEntry; - DiskFS::SubVolume* pSubVol; - const Preferences* pPreferences = GET_PREFERENCES(); - bool wantCoerceDOSFilenames = false; - CString ourSubVolName; - - wantCoerceDOSFilenames = pPreferences->GetPrefBool(kPrCoerceDOSFilenames); - - WMSG2("Notes for disk image '%s':\n%s", - volName, pDiskFS->GetDiskImg()->GetNotes()); - - ASSERT(pDiskFS != nil); - pFile = pDiskFS->GetNextFile(nil); - while (pFile != nil) { - pNewEntry = new DiskEntry(pFile); - if (pNewEntry == nil) - return -1; - - CString path(pFile->GetPathName()); - if (path.IsEmpty()) - path = kBlankFileName; - if (DiskImg::UsesDOSFileStructure(pFile->GetFSFormat()) && - wantCoerceDOSFilenames) - { - InjectLowercase(&path); - } - pNewEntry->SetPathName(path); - if (volName[0] != '\0') - pNewEntry->SetSubVolName(volName); - pNewEntry->SetFssep(pFile->GetFssep()); - pNewEntry->SetFileType(pFile->GetFileType()); - pNewEntry->SetAuxType(pFile->GetAuxType()); - pNewEntry->SetAccess(pFile->GetAccess()); - if (pFile->GetCreateWhen() == 0) - pNewEntry->SetCreateWhen(kDateNone); - else - pNewEntry->SetCreateWhen(pFile->GetCreateWhen()); - if (pFile->GetModWhen() == 0) - pNewEntry->SetModWhen(kDateNone); - else - pNewEntry->SetModWhen(pFile->GetModWhen()); - pNewEntry->SetSourceFS(pFile->GetFSFormat()); - pNewEntry->SetHasDataFork(true); - if (pFile->IsVolumeDirectory()) { - /* volume directory entry; only on ProDOS/HFS */ - ASSERT(pFile->GetRsrcLength() < 0); - pNewEntry->SetRecordKind(GenericEntry::kRecordKindVolumeDir); - //pNewEntry->SetUncompressedLen(pFile->GetDataLength()); - pNewEntry->SetDataForkLen(pFile->GetDataLength()); - pNewEntry->SetCompressedLen(pFile->GetDataLength()); - } else if (pFile->IsDirectory()) { - /* directory entry */ - ASSERT(pFile->GetRsrcLength() < 0); - pNewEntry->SetRecordKind(GenericEntry::kRecordKindDirectory); - //pNewEntry->SetUncompressedLen(pFile->GetDataLength()); - pNewEntry->SetDataForkLen(pFile->GetDataLength()); - pNewEntry->SetCompressedLen(pFile->GetDataLength()); - } else if (pFile->GetRsrcLength() >= 0) { - /* has resource fork */ - pNewEntry->SetRecordKind(GenericEntry::kRecordKindForkedFile); - pNewEntry->SetDataForkLen(pFile->GetDataLength()); - pNewEntry->SetRsrcForkLen(pFile->GetRsrcLength()); - //pNewEntry->SetUncompressedLen( - // pFile->GetDataLength() + pFile->GetRsrcLength() ); - pNewEntry->SetCompressedLen( - pFile->GetDataSparseLength() + pFile->GetRsrcSparseLength() ); - pNewEntry->SetHasRsrcFork(true); - } else { - /* just data fork */ - pNewEntry->SetRecordKind(GenericEntry::kRecordKindFile); - //pNewEntry->SetUncompressedLen(pFile->GetDataLength()); - pNewEntry->SetDataForkLen(pFile->GetDataLength()); - pNewEntry->SetCompressedLen(pFile->GetDataSparseLength()); - } - - switch (pNewEntry->GetSourceFS()) { - case DiskImg::kFormatDOS33: - case DiskImg::kFormatDOS32: - case DiskImg::kFormatUNIDOS: - case DiskImg::kFormatGutenberg: - pNewEntry->SetFormatStr("DOS"); - break; - case DiskImg::kFormatProDOS: - pNewEntry->SetFormatStr("ProDOS"); - break; - case DiskImg::kFormatPascal: - pNewEntry->SetFormatStr("Pascal"); - break; - case DiskImg::kFormatCPM: - pNewEntry->SetFormatStr("CP/M"); - break; - case DiskImg::kFormatMSDOS: - pNewEntry->SetFormatStr("MS-DOS"); - break; - case DiskImg::kFormatRDOS33: - case DiskImg::kFormatRDOS32: - case DiskImg::kFormatRDOS3: - pNewEntry->SetFormatStr("RDOS"); - break; - case DiskImg::kFormatMacHFS: - pNewEntry->SetFormatStr("HFS"); - break; - default: - pNewEntry->SetFormatStr("???"); - break; - } - - pNewEntry->SetDamaged(pFile->GetQuality() == A2File::kQualityDamaged); - pNewEntry->SetSuspicious(pFile->GetQuality() == A2File::kQualitySuspicious); - - AddEntry(pNewEntry); - - /* this is not very useful -- all the heavy lifting was done earlier */ - if ((GetNumEntries() % 100) == 0) - SET_PROGRESS_COUNTER(GetNumEntries()); - - pFile = pDiskFS->GetNextFile(pFile); - } - - /* - * Load all sub-volumes. - * - * We define the sub-volume name to use for the next layer down. We - * prepend an underscore to the unmodified name. So long as the volume - * name is a valid Windows path -- which should hold true for most disks, - * though possibly not for Pascal -- it can be extracted directly with - * its full path with no risk of conflict. (The extraction code relies - * on this, so don't put a ':' in the subvol name or Windows will choke.) - */ - pSubVol = pDiskFS->GetNextSubVolume(nil); - while (pSubVol != nil) { - CString concatSubVolName; - const char* subVolName; - int ret; - - subVolName = pSubVol->GetDiskFS()->GetVolumeName(); - if (subVolName == nil) - subVolName = "+++"; // call it *something* - - if (volName[0] == '\0') - concatSubVolName.Format("_%s", subVolName); - else - concatSubVolName.Format("%s_%s", volName, subVolName); - ret = LoadDiskFSContents(pSubVol->GetDiskFS(), concatSubVolName); - if (ret != 0) - return ret; - pSubVol = pDiskFS->GetNextSubVolume(pSubVol); - } - - return 0; -} - - -/* - * User has updated their preferences. Take note. - * - * Setting preferences in a DiskFS causes those prefs to be pushed down - * to all sub-volumes. - */ -void -DiskArchive::PreferencesChanged(void) -{ - const Preferences* pPreferences = GET_PREFERENCES(); - - if (fpPrimaryDiskFS != nil) { - fpPrimaryDiskFS->SetParameter(DiskFS::kParmProDOS_AllowLowerCase, - pPreferences->GetPrefBool(kPrProDOSAllowLower) != 0); - fpPrimaryDiskFS->SetParameter(DiskFS::kParmProDOS_AllocSparse, - pPreferences->GetPrefBool(kPrProDOSUseSparse) != 0); - } -} - - -/* - * Report on what this disk image is capable of. - */ -long -DiskArchive::GetCapability(Capability cap) -{ - switch (cap) { - case kCapCanTest: - return false; - break; - case kCapCanRenameFullPath: - return false; - break; - case kCapCanRecompress: - return false; - break; - case kCapCanEditComment: - return false; - break; - case kCapCanAddDisk: - return false; - break; - case kCapCanConvEOLOnAdd: - return true; - break; - case kCapCanCreateSubdir: - return true; - break; - case kCapCanRenameVolume: - return true; - break; - default: - ASSERT(false); - return -1; - break; - } -} - - -/* - * =========================================================================== - * DiskArchive -- add files - * =========================================================================== - */ - -/* - * Process a bulk "add" request. - * - * Returns "true" on success, "false" on failure. - */ -bool -DiskArchive::BulkAdd(ActionProgressDialog* pActionProgress, - const AddFilesDialog* pAddOpts) -{ - NuError nerr; - CString errMsg; - char curDir[MAX_PATH] = ""; - bool retVal = false; - - WMSG2("Opts: '%s' typePres=%d\n", - pAddOpts->fStoragePrefix, pAddOpts->fTypePreservation); - WMSG3(" sub=%d strip=%d ovwr=%d\n", - pAddOpts->fIncludeSubfolders, pAddOpts->fStripFolderNames, - pAddOpts->fOverwriteExisting); - - ASSERT(fpAddDataHead == nil); - - /* these reset on every new add */ - fOverwriteExisting = false; - fOverwriteNoAsk = false; - - /* we screen for clashes with existing files later; this just ensures - "batch uniqueness" */ - fpPrimaryDiskFS->SetParameter(DiskFS::kParm_CreateUnique, true); - - /* - * Save the current directory and change to the one from the file dialog. - */ - const char* buf = pAddOpts->GetFileNames(); - WMSG2("Selected path = '%s' (offset=%d)\n", buf, - pAddOpts->GetFileNameOffset()); - - if (GetCurrentDirectory(sizeof(curDir), curDir) == 0) { - errMsg = "Unable to get current directory.\n"; - ShowFailureMsg(pActionProgress, errMsg, IDS_FAILED); - goto bail; - } - if (SetCurrentDirectory(buf) == false) { - errMsg.Format("Unable to set current directory to '%s'.\n", buf); - ShowFailureMsg(pActionProgress, errMsg, IDS_FAILED); - goto bail; - } - - buf += pAddOpts->GetFileNameOffset(); - while (*buf != '\0') { - WMSG1(" file '%s'\n", buf); - - /* add the file, calling DoAddFile via the generic AddFile */ - nerr = AddFile(pAddOpts, buf, &errMsg); - if (nerr != kNuErrNone) { - if (errMsg.IsEmpty()) - errMsg.Format("Failed while adding file '%s': %s.", - (LPCTSTR) buf, NuStrError(nerr)); - if (nerr != kNuErrAborted) { - ShowFailureMsg(pActionProgress, errMsg, IDS_FAILED); - } - goto bail; - } - - buf += strlen(buf)+1; - } - - if (fpAddDataHead == nil) { - CString title; - title.LoadString(IDS_MB_APP_NAME); - errMsg = "No files added.\n"; - pActionProgress->MessageBox(errMsg, title, MB_OK | MB_ICONWARNING); - } else { - /* add all pending files */ - retVal = true; - errMsg = ProcessFileAddData(pAddOpts->fpTargetDiskFS, - pAddOpts->fConvEOL); - if (!errMsg.IsEmpty()) { - CString title; - ShowFailureMsg(pActionProgress, errMsg, IDS_FAILED); - retVal = false; - } - - /* success or failure, reload the contents */ - errMsg = Reload(); - if (!errMsg.IsEmpty()) - retVal = false; - } - -bail: - FreeAddDataList(); - if (SetCurrentDirectory(curDir) == false) { - errMsg.Format("Unable to reset current directory to '%s'.\n", buf); - ShowFailureMsg(pActionProgress, errMsg, IDS_FAILED); - // bummer, but don't signal failure - } - return retVal; -} - -/* - * Add a file to a disk image. - * - * Unfortunately we can't just add the files here. We need to figure out - * which pairs of files should be combined into a single "extended" file. - * (Yes, the cursed forked files strike again.) - * - * The way you tell if two files should be one is by comparing their - * filenames and type info. If they match, and one is a data fork and - * one is a resource fork, we have a single split file. - * - * We have to be careful here because we don't know which will be seen - * first and whether they'll be adjacent. We have to dig through the - * list of previously-added files for a match (O(n^2) behavior currently). - * - * We also have to compare the right filename. Comparing the Windows - * filename is a bad idea, because by definition one of them has a resource - * fork tag on it. We need to compare the normalized filename before - * the ProDOS normalizer/uniqifier gets a chance to mangle it. As luck - * would have it, that's exactly what we have in "storageName". - * - * For a NuFX archive, NufxLib does all this nonsense for us, but we have - * to manage it ourselves here. The good news is that, since we have to - * wade through all the filenames, we have an opportunity to make the names - * unique. So long as we ensure that the names we have don't clash with - * anything currently on the disk, we know that anything we add that does - * clash is running into something we just added, which means we can turn - * on CreateFile's "make unique" feature and let the filesystem-specific - * code handle uniqueness. - * - * Any fields we want to keep from the NuFileDetails struct need to be - * copied out. It's a "hairy" struct, so we need to duplicate the strings. - */ -NuError -DiskArchive::DoAddFile(const AddFilesDialog* pAddOpts, - FileDetails* pDetails) -{ - NuError nuerr = kNuErrNone; - DiskFS* pDiskFS = pAddOpts->fpTargetDiskFS; - - DIError dierr; - int neededLen = 64; // reasonable guess - char* fsNormalBuf = nil; - - WMSG2(" +++ ADD file: orig='%s' stor='%s'\n", - pDetails->origName, pDetails->storageName); - -retry: - /* - * Convert "storageName" to a filesystem-normalized path. - */ - delete[] fsNormalBuf; - fsNormalBuf = new char[neededLen]; - dierr = pDiskFS->NormalizePath(pDetails->storageName, - PathProposal::kDefaultStoredFssep, fsNormalBuf, &neededLen); - if (dierr == kDIErrDataOverrun) { - /* not long enough, try again *once* */ - delete[] fsNormalBuf; - fsNormalBuf = new char[neededLen]; - dierr = pDiskFS->NormalizePath(pDetails->storageName, - PathProposal::kDefaultStoredFssep, fsNormalBuf, &neededLen); - } - if (dierr != kDIErrNone) { - nuerr = kNuErrInternal; - goto bail; - } - - /* - * Test to see if the file already exists. If it does, give the user - * the opportunity to rename it, overwrite the original, or skip - * adding it. - * - * The FS-normalized path may not reflect the actual storage name, - * because some features (like ProDOS "allow lower case") aren't - * factored in until later. However, it should be close enough -- it - * has to be, or we'd be in trouble for saying it's going to overwrite - * the file in the archive. - */ - A2File* pExisting; - pExisting = pDiskFS->GetFileByName(fsNormalBuf); - if (pExisting != nil) { - NuResult result; - - result = HandleReplaceExisting(pExisting, pDetails); - if (result == kNuAbort) { - nuerr = kNuErrAborted; - goto bail; - } else if (result == kNuSkip) { - nuerr = kNuErrSkipped; - goto bail; - } else if (result == kNuRename) { - goto retry; - } else if (result == kNuOverwrite) { - /* delete the existing file immediately */ - WMSG1(" Deleting existing file '%s'\n", fsNormalBuf); - dierr = pDiskFS->DeleteFile(pExisting); - if (dierr != kDIErrNone) { - // Would be nice to show a dialog and explain *why*, but - // I'm not sure we have a window here. - WMSG1(" Deletion failed (err=%d)\n", dierr); - goto bail; - } - } else { - WMSG1("GLITCH: bad return %d from HandleReplaceExisting\n",result); - assert(false); - nuerr = kNuErrInternal; - goto bail; - } - } - - /* - * Put all the goodies into a new FileAddData object, and add it to - * the end of the list. - */ - FileAddData* pAddData; - pAddData = new FileAddData(pDetails, fsNormalBuf); - if (pAddData == nil) { - nuerr = kNuErrMalloc; - goto bail; - } - - WMSG1("FSNormalized is '%s'\n", pAddData->GetFSNormalPath()); - - AddToAddDataList(pAddData); - -bail: - delete[] fsNormalBuf; - return nuerr; -} - -/* - * A file we're adding clashes with an existing file. Decide what to do - * about it. - * - * Returns one of the following: - * kNuOverwrite - overwrite the existing file - * kNuSkip - skip adding the existing file - * kNuRename - user wants to rename the file - * kNuAbort - cancel out of the entire add process - * - * Side effects: - * Sets fOverwriteExisting and fOverwriteNoAsk if a "to all" button is hit - * Replaces pDetails->storageName if the user elects to rename - */ -NuResult -DiskArchive::HandleReplaceExisting(const A2File* pExisting, - FileDetails* pDetails) -{ - NuResult result; - - if (fOverwriteNoAsk) { - if (fOverwriteExisting) - return kNuOverwrite; - else - return kNuSkip; - } - - ConfirmOverwriteDialog confOvwr; - - confOvwr.fExistingFile = pExisting->GetPathName(); - confOvwr.fExistingFileModWhen = pExisting->GetModWhen(); - - PathName srcPath(pDetails->origName); - confOvwr.fNewFileSource = pDetails->origName; // or storageName? - confOvwr.fNewFileModWhen = srcPath.GetModWhen(); - - if (confOvwr.DoModal() == IDCANCEL) { - WMSG0("User cancelled out of add-to-diskimg replace-existing\n"); - return kNuAbort; - } - - if (confOvwr.fResultRename) { - /* - * Replace the name in FileDetails. They were asked to modify - * the already-normalized version of the filename. We will run - * it back through the FS-specific normalizer, which will handle - * any oddities they type in. - * - * We don't want to run it through PathProposal.LocalToArchive - * because that'll strip out ':' in the pathnames. - * - * Ideally the rename dialog would have a way to validate the - * full path and reject "OK" if it's not valid. Instead, we just - * allow the FS normalizer to force the filename to be valid. - */ - pDetails->storageName = confOvwr.fExistingFile; - WMSG1("Trying rename to '%s'\n", pDetails->storageName); - return kNuRename; - } - - if (confOvwr.fResultApplyToAll) { - fOverwriteNoAsk = true; - if (confOvwr.fResultOverwrite) - fOverwriteExisting = true; - else - fOverwriteExisting = false; - } - if (confOvwr.fResultOverwrite) - result = kNuOverwrite; - else - result = kNuSkip; - - return result; -} - - -/* - * Process the list of pending file adds. - * - * This is where the rubber (finally!) meets the road. - */ -CString -DiskArchive::ProcessFileAddData(DiskFS* pDiskFS, int addOptsConvEOL) -{ - CString errMsg; - FileAddData* pData; - unsigned char* dataBuf = nil; - unsigned char* rsrcBuf = nil; - long dataLen, rsrcLen; - MainWindow* pMainWin = (MainWindow*)::AfxGetMainWnd(); - - WMSG0("--- ProcessFileAddData\n"); - - /* map the EOL conversion to something we can use */ - GenericEntry::ConvertEOL convEOL; - - switch (addOptsConvEOL) { - case AddFilesDialog::kConvEOLNone: - convEOL = GenericEntry::kConvertEOLOff; - break; - case AddFilesDialog::kConvEOLType: - // will be adjusted each time through the loop - convEOL = GenericEntry::kConvertEOLOff; - break; - case AddFilesDialog::kConvEOLAuto: - convEOL = GenericEntry::kConvertEOLAuto; - break; - case AddFilesDialog::kConvEOLAll: - convEOL = GenericEntry::kConvertEOLOn; - break; - default: - assert(false); - convEOL = GenericEntry::kConvertEOLOff; - break; - } - - - pData = fpAddDataHead; - while (pData != nil) { - const FileDetails* pDataDetails = nil; - const FileDetails* pRsrcDetails = nil; - const FileDetails* pDetails = pData->GetDetails(); - const char* typeStr = "????"; - - switch (pDetails->entryKind) { - case FileDetails::kFileKindDataFork: - pDataDetails = pDetails; - typeStr = "data"; - break; - case FileDetails::kFileKindRsrcFork: - pRsrcDetails = pDetails; - typeStr = "rsrc"; - break; - case FileDetails::kFileKindDiskImage: - pDataDetails = pDetails; - typeStr = "disk"; - break; - case FileDetails::kFileKindBothForks: - case FileDetails::kFileKindDirectory: - default: - assert(false); - return "internal error"; - } - - if (pData->GetOtherFork() != nil) { - pDetails = pData->GetOtherFork()->GetDetails(); - typeStr = "both"; - - switch (pDetails->entryKind) { - case FileDetails::kFileKindDataFork: - assert(pDataDetails == nil); - pDataDetails = pDetails; - break; - case FileDetails::kFileKindRsrcFork: - assert(pRsrcDetails == nil); - pRsrcDetails = pDetails; - break; - case FileDetails::kFileKindDiskImage: - assert(false); - return "(internal) add other disk error"; - case FileDetails::kFileKindBothForks: - case FileDetails::kFileKindDirectory: - default: - assert(false); - return "internal error"; - } - } - - WMSG2("Adding file '%s' (%s)\n", - pDetails->storageName, typeStr); - ASSERT(pDataDetails != nil || pRsrcDetails != nil); - - /* - * The current implementation of DiskImg/DiskFS requires writing each - * fork in one shot. This means loading the entire thing into - * memory. Not so bad for ProDOS, with its 16MB maximum file size, - * but it could be awkward for HFS (not to mention HFS Plus!). - */ - DiskFS::CreateParms parms; - ConvertFDToCP(pData->GetDetails(), &parms); - if (pRsrcDetails != nil) - parms.storageType = kNuStorageExtended; - else - parms.storageType = kNuStorageSeedling; - /* use the FS-normalized path here */ - parms.pathName = pData->GetFSNormalPath(); - - dataLen = rsrcLen = -1; - if (pDataDetails != nil) { - /* figure out text conversion, including high ASCII for DOS */ - /* (HA conversion only happens if text conversion happens) */ - GenericEntry::ConvertHighASCII convHA; - if (addOptsConvEOL == AddFilesDialog::kConvEOLType) { - if (pDataDetails->fileType == kFileTypeTXT || - pDataDetails->fileType == kFileTypeSRC) - { - WMSG0("Enabling text conversion by type\n"); - convEOL = GenericEntry::kConvertEOLOn; - } else { - convEOL = GenericEntry::kConvertEOLOff; - } - } - if (DiskImg::UsesDOSFileStructure(pDiskFS->GetDiskImg()->GetFSFormat())) - convHA = GenericEntry::kConvertHAOn; - else - convHA = GenericEntry::kConvertHAOff; - - errMsg = LoadFile(pDataDetails->origName, &dataBuf, &dataLen, - convEOL, convHA); - if (!errMsg.IsEmpty()) - goto bail; - } - if (pRsrcDetails != nil) { - /* no text conversion on resource forks */ - errMsg = LoadFile(pRsrcDetails->origName, &rsrcBuf, &rsrcLen, - GenericEntry::kConvertEOLOff, GenericEntry::kConvertHAOff); - if (!errMsg.IsEmpty()) - goto bail; - } - - /* really ought to do this separately for each thread */ - SET_PROGRESS_BEGIN(); - SET_PROGRESS_UPDATE2(0, pDetails->origName, - parms.pathName); - - DIError dierr; - dierr = AddForksToDisk(pDiskFS, &parms, dataBuf, dataLen, - rsrcBuf, rsrcLen); - SET_PROGRESS_END(); - if (dierr != kDIErrNone) { - errMsg.Format("Unable to add '%s' to image: %s.", - parms.pathName, DiskImgLib::DIStrError(dierr)); - goto bail; - } - delete[] dataBuf; - delete[] rsrcBuf; - dataBuf = rsrcBuf = nil; - - pData = pData->GetNext(); - } - -bail: - delete[] dataBuf; - delete[] rsrcBuf; - return errMsg; -} - -#define kCharLF '\n' -#define kCharCR '\r' - -/* - * Load a file into a buffer, possibly converting EOL markers and setting - * "high ASCII" along the way. - * - * Returns a pointer to a newly-allocated buffer (new[]) and the data length. - * If the file is empty, no buffer will be allocated. - * - * Returns an empty string on success, or an error message on failure. - * - * HEY: really ought to update the progress counter, especially when reading - * really large files. - */ -CString -DiskArchive::LoadFile(const char* pathName, unsigned char** pBuf, long* pLen, - GenericEntry::ConvertEOL conv, GenericEntry::ConvertHighASCII convHA) const -{ - CString errMsg; - FILE* fp; - long fileLen; - - ASSERT(convHA == GenericEntry::kConvertHAOn || - convHA == GenericEntry::kConvertHAOff); - ASSERT(conv == GenericEntry::kConvertEOLOn || - conv == GenericEntry::kConvertEOLOff || - conv == GenericEntry::kConvertEOLAuto); - ASSERT(pathName != nil); - ASSERT(pBuf != nil); - ASSERT(pLen != nil); - - fp = fopen(pathName, "rb"); - if (fp == nil) { - errMsg.Format("Unable to open '%s': %s.", pathName, - strerror(errno)); - goto bail; - } - - if (fseek(fp, 0, SEEK_END) != 0) { - errMsg.Format("Unable to seek to end of '%s': %s", pathName, - strerror(errno)); - goto bail; - } - fileLen = ftell(fp); - if (fileLen < 0) { - errMsg.Format("Unable to determine length of '%s': %s", pathName, - strerror(errno)); - goto bail; - } - rewind(fp); - - if (fileLen == 0) { // handle zero-length files - *pBuf = nil; - *pLen = 0; - goto bail; - } else if (fileLen > 0x00ffffff) { - errMsg = "Cannot add files larger than 16MB to a disk image."; - goto bail; - } - - *pBuf = new unsigned char[fileLen]; - if (*pBuf == nil) { - errMsg.Format("Unable to allocate %ld bytes for '%s'.", - fileLen, pathName); - goto bail; - } - - /* - * We're ready to load the file. We need to sort out EOL conversion. - * Since we always convert to CR, we know the file will stay the same - * size or get smaller, which means the buffer we've allocated is - * guaranteed to hold the file even if we convert it. - * - * If the text mode is "auto", we need to load a piece of the file and - * analyze it. - */ - if (conv == GenericEntry::kConvertEOLAuto) { - GenericEntry::EOLType eolType; - GenericEntry::ConvertHighASCII dummy; - - int chunkLen = 16384; // nice big chunk - if (chunkLen > fileLen) - chunkLen = fileLen; - - if (fread(*pBuf, chunkLen, 1, fp) != 1) { - errMsg.Format("Unable to read initial chunk of '%s': %s.", - pathName, strerror(errno)); - delete[] *pBuf; - *pBuf = nil; - goto bail; - } - rewind(fp); - - conv = GenericEntry::DetermineConversion(*pBuf, chunkLen, - &eolType, &dummy); - WMSG2("LoadFile DetermineConv returned conv=%d eolType=%d\n", - conv, eolType); - if (conv == GenericEntry::kConvertEOLOn && - eolType == GenericEntry::kEOLCR) - { - WMSG0(" (skipping conversion due to matching eolType)\n"); - conv = GenericEntry::kConvertEOLOff; - } - } - ASSERT(conv != GenericEntry::kConvertEOLAuto); - - /* - * The "high ASCII" conversion is either on or off. In this context, - * "on" means "convert all text files", and "off" means "don't convert - * text files". We never convert non-text files. Conversion should - * always be "on" for DOS 3.2/3.3, and "off" for everything else (except - * RDOS, should we choose to make that writeable). - */ - if (conv == GenericEntry::kConvertEOLOff) { - /* fast path */ - WMSG1(" +++ NOT converting text '%s'\n", pathName); - if (fread(*pBuf, fileLen, 1, fp) != 1) { - errMsg.Format("Unable to read '%s': %s.", pathName, strerror(errno)); - delete[] *pBuf; - *pBuf = nil; - goto bail; - } - } else { - /* - * Convert as we go. - * - * Observation: if we copy a binary file to a DOS disk, and force - * the text conversion, we will convert 0x0a to 0x0d, and thence - * to 0x8d. However, we may still have some 0x8a bytes lying around, - * because we don't convert 0x8a in the original file to anything. - * This means that a CR->CRLF or LF->CRLF conversion can't be - * "undone" on a DOS disk. (Not that anyone cares.) - */ - long count = fileLen; - int mask, ic; - bool lastCR = false; - unsigned char* buf = *pBuf; - - if (convHA == GenericEntry::kConvertHAOn) - mask = 0x80; - else - mask = 0x00; - - WMSG2(" +++ Converting text '%s', mask=0x%02x\n", pathName, mask); - - while (count--) { - ic = getc(fp); - - if (ic == kCharCR) { - *buf++ = (unsigned char) (kCharCR | mask); - lastCR = true; - } else if (ic == kCharLF) { - if (!lastCR) - *buf++ = (unsigned char) (kCharCR | mask); - lastCR = false; - } else { - if (ic == '\0') - *buf++ = (unsigned char) ic; // don't conv 0x00 - else - *buf++ = (unsigned char) (ic | mask); - lastCR = false; - } - } - fileLen = buf - *pBuf; - } - - (void) fclose(fp); - - *pLen = fileLen; - -bail: - return errMsg; -} - -/* - * Add a file with the supplied data to the disk image. - * - * Forks that exist but are empty have a length of zero. Forks that don't - * exist have a length of -1. - * - * Called by XferFile and ProcessFileAddData. - */ -DIError -DiskArchive::AddForksToDisk(DiskFS* pDiskFS, const DiskFS::CreateParms* pParms, - const unsigned char* dataBuf, long dataLen, - const unsigned char* rsrcBuf, long rsrcLen) const -{ - DIError dierr = kDIErrNone; - CString replacementFileName; - const int kFileTypeBIN = 0x06; - const int kFileTypeINT = 0xfa; - const int kFileTypeBAS = 0xfc; - A2File* pNewFile = nil; - A2FileDescr* pOpenFile = nil; - DiskFS::CreateParms parmCopy; - - /* - * Make a temporary copy, pointers and all, so we can rewrite some of - * the fields. This is sort of bad, because we're making copies of a - * const char* filename pointer whose underlying storage we're not - * really familiar with. However, so long as we don't try to retain - * it after this function returns we should be fine. - * - * Might be better to make CreateParms a class instead of a struct, - * make the pathName field new[] storage, and write a copy constructor - * for the operation below. This will be fine for now. - */ - memcpy(&parmCopy, pParms, sizeof(parmCopy)); - - if (rsrcLen >= 0) { - ASSERT(parmCopy.storageType == kNuStorageExtended); - } - - /* - * Look for "empty directory holders" that we put into NuFX archives - * when doing disk-to-archive conversions. These make no sense if - * there's no fssep (because it's coming from DOS), or if there's no - * base path, so we can ignore those cases. We can also ignore it if - * the file is forked or is already a directory. - */ - if (parmCopy.fssep != '\0' && parmCopy.storageType == kNuStorageSeedling) { - const char* cp; - cp = strrchr(parmCopy.pathName, parmCopy.fssep); - if (cp != nil) { - if (strcmp(cp+1, kEmptyFolderMarker) == 0 && dataLen == 0) { - /* drop the junk on the end */ - parmCopy.storageType = kNuStorageDirectory; - replacementFileName = parmCopy.pathName; - replacementFileName = - replacementFileName.Left(cp - parmCopy.pathName -1); - parmCopy.pathName = replacementFileName; - parmCopy.fileType = 0x0f; // DIR - parmCopy.access &= ~(A2FileProDOS::kAccessInvisible); - dataLen = -1; - } - } - } - - /* - * If this is a subdir create request (from the clipboard or an "empty - * directory placeholder" in a NuFX archive), handle it here. If we're - * on a filesystem that doesn't have subdirectories, just skip it. - */ - if (parmCopy.storageType == kNuStorageDirectory) { - A2File* pDummyFile; - ASSERT(dataLen < 0 && rsrcLen < 0); - - if (DiskImg::IsHierarchical(pDiskFS->GetDiskImg()->GetFSFormat())) { - dierr = pDiskFS->CreateFile(&parmCopy, &pDummyFile); - if (dierr == kDIErrDirectoryExists) - dierr = kDIErrNone; // dirs are not made unique - goto bail; - } else { - WMSG0(" Ignoring subdir create req on non-hierarchic FS\n"); - goto bail; - } - } - - /* don't try to put resource forks onto a DOS disk */ - if (!DiskImg::HasResourceForks(pDiskFS->GetDiskImg()->GetFSFormat())) { - if (rsrcLen >= 0) { - rsrcLen = -1; - parmCopy.storageType = kNuStorageSeedling; - - if (dataLen < 0) { - /* this was a resource-fork-only file */ - WMSG1("--- nothing left to write for '%s'\n", - parmCopy.pathName); - goto bail; - } - } else { - ASSERT(parmCopy.storageType == kNuStorageSeedling); - } - } - - /* quick kluge to get the right file type on large DOS files */ - if (DiskImg::UsesDOSFileStructure(pDiskFS->GetDiskImg()->GetFSFormat()) && - dataLen >= 65536) - { - if (parmCopy.fileType == kFileTypeBIN || - parmCopy.fileType == kFileTypeINT || - parmCopy.fileType == kFileTypeBAS) - { - WMSG0("+++ switching DOS file type to $f2\n"); - parmCopy.fileType = 0xf2; // DOS 'S' file - } - } - - /* - * Create the file on the disk. The storage type determines whether - * it has data+rsrc forks or just data (there's no such thing in - * ProDOS as "just a resource fork"). There's no need to open the - * fork if we're not going to write to it. - * - * This holds for resource forks as well, because the storage type - * determines whether or not the file is forked, and we've asserted - * that a file with a non-(-1) rsrcLen is forked. - */ - dierr = pDiskFS->CreateFile(&parmCopy, &pNewFile); - if (dierr != kDIErrNone) { - WMSG1(" CreateFile failed: %s\n", DiskImgLib::DIStrError(dierr)); - goto bail; - } - - /* - * Note: if this was an empty directory holder, pNewFile will be set - * to nil. We used to avoid handling this by just not opening the file - * if it had a length of zero. However, DOS 3.3 needs to write some - * kinds of zero-length files, because e.g. a zero-length 'B' file - * actually has 4 bytes of data in it. - * - * Of course, if dataLen is zero then dataBuf is nil, so we need to - * supply a dummy write buffer. None of this is an issue for resource - * forks, because DOS 3.3 doesn't have those. - */ - - if (dataLen > 0 || - (dataLen == 0 && pNewFile != nil)) - { - ASSERT(pNewFile != nil); - unsigned char dummyBuf[1] = { '\0' }; - - dierr = pNewFile->Open(&pOpenFile, false, false); - if (dierr != kDIErrNone) - goto bail; - - pOpenFile->SetProgressUpdater(DiskArchive::ProgressCallback, - dataLen, nil); - - dierr = pOpenFile->Write(dataBuf != nil ? dataBuf : dummyBuf, dataLen); - if (dierr != kDIErrNone) - goto bail; - - dierr = pOpenFile->Close(); - if (dierr != kDIErrNone) - goto bail; - pOpenFile = nil; - } - - if (rsrcLen > 0) { - ASSERT(pNewFile != nil); - - dierr = pNewFile->Open(&pOpenFile, false, true); - if (dierr != kDIErrNone) - goto bail; - - pOpenFile->SetProgressUpdater(DiskArchive::ProgressCallback, - rsrcLen, nil); - - dierr = pOpenFile->Write(rsrcBuf, rsrcLen); - if (dierr != kDIErrNone) - goto bail; - - dierr = pOpenFile->Close(); - if (dierr != kDIErrNone) - goto bail; - pOpenFile = nil; - } - -bail: - if (pOpenFile != nil) - pOpenFile->Close(); - if (dierr != kDIErrNone && pNewFile != nil) { - /* - * Clean up the partially-written file. This does not, of course, - * erase any subdirectories that were created to contain this file. - * Not worth worrying about. - */ - WMSG1(" Deleting newly-created file '%s'\n", parmCopy.pathName); - (void) pDiskFS->DeleteFile(pNewFile); - } - return dierr; -} - -/* - * Fill out a CreateParms structure from a FileDetails structure. - * - * The NuStorageType values correspond exactly to ProDOS storage types, so - * there's no need to convert them. - */ -void -DiskArchive::ConvertFDToCP(const FileDetails* pDetails, - DiskFS::CreateParms* pCreateParms) -{ - pCreateParms->pathName = pDetails->storageName; - pCreateParms->fssep = (char) pDetails->fileSysInfo; - pCreateParms->storageType = pDetails->storageType; - pCreateParms->fileType = pDetails->fileType; - pCreateParms->auxType = pDetails->extraType; - pCreateParms->access = pDetails->access; - pCreateParms->createWhen = NufxArchive::DateTimeToSeconds(&pDetails->createWhen); - pCreateParms->modWhen = NufxArchive::DateTimeToSeconds(&pDetails->modWhen); -} - - -/* - * Add an entry to the end of the FileAddData list. - * - * If "storeName" (the Windows filename with type goodies stripped, but - * without filesystem normalization) matches an entry already in the list, - * we check to see if these are forks of the same file. If they are - * different forks and we don't already have both forks, we put the - * pointer into the "fork pointer" of the existing file rather than adding - * it to the end of the list. - */ -void -DiskArchive::AddToAddDataList(FileAddData* pData) -{ - ASSERT(pData != nil); - ASSERT(pData->GetNext() == nil); - - /* - * Run through the entire existing list, looking for a match. This is - * O(n^2) behavior, but I'm expecting N to be relatively small (under - * 1000 in almost all cases). - */ - //if (strcasecmp(pData->GetDetails()->storageName, "system\\finder") == 0) - // WMSG0("whee\n"); - FileAddData* pSearch = fpAddDataHead; - FileDetails::FileKind dataKind, listKind; - - dataKind = pData->GetDetails()->entryKind; - while (pSearch != nil) { - if (pSearch->GetOtherFork() == nil && - strcmp(pSearch->GetDetails()->storageName, - pData->GetDetails()->storageName) == 0) - { - //NuThreadID dataID = pData->GetDetails()->threadID; - //NuThreadID listID = pSearch->GetDetails()->threadID; - - listKind = pSearch->GetDetails()->entryKind; - - /* got a name match */ - if (dataKind != listKind && - (dataKind == FileDetails::kFileKindDataFork || dataKind == FileDetails::kFileKindRsrcFork) && - (listKind == FileDetails::kFileKindDataFork || listKind == FileDetails::kFileKindRsrcFork)) - { - /* looks good, hook it in here instead of the list */ - WMSG2("--- connecting forks of '%s' and '%s'\n", - pData->GetDetails()->origName, - pSearch->GetDetails()->origName); - pSearch->SetOtherFork(pData); - return; - } - } - - pSearch = pSearch->GetNext(); - } - - if (fpAddDataHead == nil) { - assert(fpAddDataTail == nil); - fpAddDataHead = fpAddDataTail = pData; - } else { - fpAddDataTail->SetNext(pData); - fpAddDataTail = pData; - } -} - -/* - * Free all entries in the FileAddData list. - */ -void -DiskArchive::FreeAddDataList(void) -{ - FileAddData* pData; - FileAddData* pNext; - - pData = fpAddDataHead; - while (pData != nil) { - pNext = pData->GetNext(); - delete pData->GetOtherFork(); - delete pData; - pData = pNext; - } - - fpAddDataHead = fpAddDataTail = nil; -} - - -/* - * =========================================================================== - * DiskArchive -- create subdir - * =========================================================================== - */ - -/* - * Create a subdirectory named "newName" in "pParentEntry". - */ -bool -DiskArchive::CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry, - const char* newName) -{ - ASSERT(newName != nil && strlen(newName) > 0); - DiskEntry* pEntry = (DiskEntry*) pParentEntry; - ASSERT(pEntry != nil); - A2File* pFile = pEntry->GetA2File(); - ASSERT(pFile != nil); - DiskFS* pDiskFS = pFile->GetDiskFS(); - ASSERT(pDiskFS != nil); - - if (!pFile->IsDirectory()) { - ASSERT(false); - return false; - } - - DIError dierr; - A2File* pNewFile = nil; - DiskFS::CreateParms parms; - CString pathName; - time_t now = time(nil); - - /* - * Create the full path. - */ - if (pFile->IsVolumeDirectory()) { - pathName = newName; - } else { - pathName = pParentEntry->GetPathName(); - pathName += pParentEntry->GetFssep(); - pathName += newName; - } - ASSERT(strchr(newName, pParentEntry->GetFssep()) == nil); - - /* using NufxLib constants; they match with ProDOS */ - memset(&parms, 0, sizeof(parms)); - parms.pathName = pathName; - parms.fssep = pParentEntry->GetFssep(); - parms.storageType = kNuStorageDirectory; - parms.fileType = 0x0f; // ProDOS DIR - parms.auxType = 0; - parms.access = kNuAccessUnlocked; - parms.createWhen = now; - parms.modWhen = now; - - dierr = pDiskFS->CreateFile(&parms, &pNewFile); - if (dierr != kDIErrNone) { - CString errMsg; - errMsg.Format("Unable to create subdirectory: %s.\n", - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - return false; - } - - if (InternalReload(pMsgWnd) != 0) - return false; - - return true; -} - - -/* - * =========================================================================== - * DiskArchive -- delete selection - * =========================================================================== - */ - -/* - * Compare DiskEntry display names in descending order (Z-A). - */ -/*static*/ int -DiskArchive::CompareDisplayNamesDesc(const void* ventry1, const void* ventry2) -{ - const DiskEntry* pEntry1 = *((const DiskEntry**) ventry1); - const DiskEntry* pEntry2 = *((const DiskEntry**) ventry2); - - return strcasecmp(pEntry2->GetDisplayName(), pEntry1->GetDisplayName()); -} - -/* - * Delete the records listed in the selection set. - * - * The DiskFS DeleteFile() function will not delete a subdirectory unless - * it is empty. This complicates matters somewhat for us, because the - * selection set isn't in any particular order. We need to sort on the - * pathname and then delete bottom-up. - * - * CiderPress does work to ensure that, if a subdir is selected, everything - * in that subdir is also selected. So if we just delete everything in the - * right order, we should be okay. - */ -bool -DiskArchive::DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) -{ - CString errMsg; - SelectionEntry* pSelEntry; - DiskEntry* pEntry; - DIError dierr; - bool retVal = false; - - SET_PROGRESS_BEGIN(); - - /* - * Start by copying the DiskEntry pointers out of the selection set and - * into an array. The selection set was created such that there is one - * entry in the set for each file. (The file viewer likes to have one - * entry for each thread.) - */ - int numEntries = pSelSet->GetNumEntries(); - ASSERT(numEntries > 0); - DiskEntry** entryArray = new DiskEntry*[numEntries]; - int idx = 0; - - pSelEntry = pSelSet->IterNext(); - while (pSelEntry != nil) { - pEntry = (DiskEntry*) pSelEntry->GetEntry(); - ASSERT(pEntry != nil); - - entryArray[idx++] = pEntry; - WMSG2("Added 0x%08lx '%s'\n", (long) entryArray[idx-1], - entryArray[idx-1]->GetDisplayName()); - - pSelEntry = pSelSet->IterNext(); - } - ASSERT(idx == numEntries); - - /* - * Sort the file array by descending filename. - */ - ::qsort(entryArray, numEntries, sizeof(DiskEntry*), CompareDisplayNamesDesc); - - /* - * Run through the sorted list, deleting each entry. - */ - for (idx = 0; idx < numEntries; idx++) { - A2File* pFile; - - pEntry = entryArray[idx]; - pFile = pEntry->GetA2File(); - - /* - * We shouldn't be here at all if the main volume were opened - * read-only. However, it's possible that the main is read-write - * and our sub-volumes are read-only (probably because we don't - * support write access to the filesystem). - */ - if (!pFile->GetDiskFS()->GetReadWriteSupported()) { - errMsg.Format("Unable to delete '%s' on '%s': operation not supported.", - pEntry->GetDisplayName(), pFile->GetDiskFS()->GetVolumeName()); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - - WMSG2(" Deleting '%s' from '%s'\n", pEntry->GetPathName(), - pFile->GetDiskFS()->GetVolumeName()); - SET_PROGRESS_UPDATE2(0, pEntry->GetPathName(), nil); - - /* - * Ask the DiskFS to delete the file. As soon as this completes, - * "pFile" is invalid and must not be dereferenced. - */ - dierr = pFile->GetDiskFS()->DeleteFile(pFile); - if (dierr != kDIErrNone) { - errMsg.Format("Unable to delete '%s' on '%s': %s.", - pEntry->GetDisplayName(), pFile->GetDiskFS()->GetVolumeName(), - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - SET_PROGRESS_UPDATE(100); - - /* - * Be paranoid and zap the pointer, on the off chance somebody - * tries to redraw the content list from the deleted data. - * - * In practice we don't work this way -- the stuff that gets drawn - * on the screen comes out of GenericEntry, not A2File. If this - * changes we'll need to raise the "reload" flag here, before the - * reload, to prevent the ContentList from chasing a bad pointer. - */ - pEntry->SetA2File(nil); - } - - retVal = true; - -bail: - SET_PROGRESS_END(); - delete[] entryArray; - if (InternalReload(pMsgWnd) != 0) - retVal = false; - - return retVal; -} - -/* - * =========================================================================== - * DiskArchive -- rename files - * =========================================================================== - */ - - /* - * Rename a set of files, one at a time. - * - * If we rename a subdirectory, it could affect the next thing we try to - * rename (because we show the full path). We have to reload our file - * list from the DiskFS after each renamed subdir. The trouble is that - * this invalidates the data displayed in the ContentList, and we won't - * redraw the screen correctly. We can work around the problem by getting - * the pathname directly from the DiskFS instead of from DiskEntry, though - * it's not immediately obvious which is less confusing. - */ -bool -DiskArchive::RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) -{ - CString errMsg; - bool retVal = false; - - WMSG1("Renaming %d entries\n", pSelSet->GetNumEntries()); - - /* - * For each item in the selection set, bring up the "rename" dialog, - * and ask the GenericEntry to process it. - * - * If they hit "cancel" or there's an error, we still flush the - * previous changes. This is so that we don't have to create the - * same sort of deferred-write feature when renaming things in other - * sorts of archives (e.g. disk archives). - */ - SelectionEntry* pSelEntry = pSelSet->IterNext(); - while (pSelEntry != nil) { - RenameEntryDialog renameDlg(pMsgWnd); - DiskEntry* pEntry = (DiskEntry*) pSelEntry->GetEntry(); - - WMSG1(" Renaming '%s'\n", pEntry->GetPathName()); - if (!SetRenameFields(pMsgWnd, pEntry, &renameDlg)) - break; - - int result; - if (pEntry->GetA2File()->IsVolumeDirectory()) - result = IDIGNORE; // don't allow rename of volume dir - else - result = renameDlg.DoModal(); - if (result == IDOK) { - DIError dierr; - DiskFS* pDiskFS; - A2File* pFile; - - pFile = pEntry->GetA2File(); - pDiskFS = pFile->GetDiskFS(); - dierr = pDiskFS->RenameFile(pFile, renameDlg.fNewName); - if (dierr != kDIErrNone) { - errMsg.Format("Unable to rename '%s' to '%s': %s.", - pEntry->GetPathName(), renameDlg.fNewName, - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - WMSG2("Rename of '%s' to '%s' succeeded\n", - pEntry->GetDisplayName(), renameDlg.fNewName); - } else if (result == IDCANCEL) { - WMSG0("Canceling out of remaining renames\n"); - break; - } else { - /* 3rd possibility is IDIGNORE, i.e. skip this entry */ - WMSG1("Skipping rename of '%s'\n", pEntry->GetDisplayName()); - } - - pSelEntry = pSelSet->IterNext(); - } - - /* reload GenericArchive from disk image */ - if (InternalReload(pMsgWnd) == kNuErrNone) - retVal = true; - -bail: - return retVal; -} - -/* - * Set up a RenameEntryDialog for the entry in "*pEntry". - * - * Returns "true" on success, "false" on failure. - */ -bool -DiskArchive::SetRenameFields(CWnd* pMsgWnd, DiskEntry* pEntry, - RenameEntryDialog* pDialog) -{ - DiskFS* pDiskFS; - - ASSERT(pEntry != nil); - - /* - * Figure out if we're allowed to change the entire path. (This is - * doing it the hard way, but what the hell.) - */ - long cap = GetCapability(GenericArchive::kCapCanRenameFullPath); - bool renameFullPath = (cap != 0); - - // a bit round-about, but it works - pDiskFS = pEntry->GetA2File()->GetDiskFS(); - - /* - * Make sure rename is allowed. It's nice to do these *before* putting - * up the rename dialog, so that the user doesn't do a bunch of typing - * before being told that it's pointless. - */ - if (!pDiskFS->GetReadWriteSupported()) { - CString errMsg; - errMsg.Format("Unable to rename '%s': operation not supported.", - pEntry->GetPathName()); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - return false; - } - if (pDiskFS->GetFSDamaged()) { - CString errMsg; - errMsg.Format("Unable to rename '%s': the disk it's on appears to be damaged.", - pEntry->GetPathName()); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - return false; - } - - pDialog->SetCanRenameFullPath(renameFullPath); - pDialog->fOldName = pEntry->GetPathName(); - pDialog->fFssep = pEntry->GetFssep(); - pDialog->fpArchive = this; - pDialog->fpEntry = pEntry; - - return true; -} - -/* - * Verify that the a name is suitable. Called by RenameEntryDialog and - * CreateSubdirDialog. - * - * Tests for context-specific syntax and checks for duplicates. - * - * Returns an empty string on success, or an error message on failure. - */ -CString -DiskArchive::TestPathName(const GenericEntry* pGenericEntry, - const CString& basePath, const CString& newName, char newFssep) const -{ - const DiskEntry* pEntry = (DiskEntry*) pGenericEntry; - DiskImg::FSFormat format; - CString pathName, errMsg; - DiskFS* pDiskFS; - - if (basePath.IsEmpty()) { - pathName = newName; - } else { - pathName = basePath; - pathName += newFssep; - pathName += newName; - } - - pDiskFS = pEntry->GetA2File()->GetDiskFS(); - format = pDiskFS->GetDiskImg()->GetFSFormat(); - - /* look for an existing file, but don't compare against self */ - A2File* existingFile; - existingFile = pDiskFS->GetFileByName(pathName); - if (existingFile != nil && existingFile != pEntry->GetA2File()) { - errMsg = "A file with that name already exists."; - goto bail; - } - - switch (format) { - case DiskImg::kFormatProDOS: - if (!DiskFSProDOS::IsValidFileName(newName)) - errMsg.LoadString(IDS_VALID_FILENAME_PRODOS); - break; - case DiskImg::kFormatDOS33: - case DiskImg::kFormatDOS32: - if (!DiskFSDOS33::IsValidFileName(newName)) - errMsg.LoadString(IDS_VALID_FILENAME_DOS); - break; - case DiskImg::kFormatPascal: - if (!DiskFSPascal::IsValidFileName(newName)) - errMsg.LoadString(IDS_VALID_FILENAME_PASCAL); - break; - case DiskImg::kFormatMacHFS: - if (!DiskFSHFS::IsValidFileName(newName)) - errMsg.LoadString(IDS_VALID_FILENAME_HFS); - break; - default: - errMsg = "Not supported by TestPathName!"; - } - -bail: - return errMsg; -} - - -/* - * =========================================================================== - * DiskArchive -- rename a volume - * =========================================================================== - */ - -/* - * Ask a DiskFS to change its volume name. - * - * Returns "true" on success, "false" on failure. - */ -bool -DiskArchive::RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS, - const char* newName) -{ - DIError dierr; - CString errMsg; - bool retVal = true; - - dierr = pDiskFS->RenameVolume(newName); - if (dierr != kDIErrNone) { - errMsg.Format("Unable to rename volume: %s.\n", - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - retVal = false; - /* fall through to reload anyway */ - } - - /* reload GenericArchive from disk image */ - if (InternalReload(pMsgWnd) != 0) - retVal = false; - - return retVal; -} - -/* - * Test a volume name for validity. - */ -CString -DiskArchive::TestVolumeName(const DiskFS* pDiskFS, - const char* newName) const -{ - DiskImg::FSFormat format; - CString errMsg; - - ASSERT(pDiskFS != nil); - ASSERT(newName != nil); - - format = pDiskFS->GetDiskImg()->GetFSFormat(); - - switch (format) { - case DiskImg::kFormatProDOS: - if (!DiskFSProDOS::IsValidVolumeName(newName)) - errMsg.LoadString(IDS_VALID_VOLNAME_PRODOS); - break; - case DiskImg::kFormatDOS33: - case DiskImg::kFormatDOS32: - if (!DiskFSDOS33::IsValidVolumeName(newName)) - errMsg.LoadString(IDS_VALID_VOLNAME_DOS); - break; - case DiskImg::kFormatPascal: - if (!DiskFSPascal::IsValidVolumeName(newName)) - errMsg.LoadString(IDS_VALID_VOLNAME_PASCAL); - break; - case DiskImg::kFormatMacHFS: - if (!DiskFSHFS::IsValidVolumeName(newName)) - errMsg.LoadString(IDS_VALID_VOLNAME_HFS); - break; - default: - errMsg = "Not supported by TestVolumeName!"; - } - - return errMsg; -} - - -/* - * =========================================================================== - * DiskArchive -- set file properties - * =========================================================================== - */ - -/* - * Set the properties of "pEntry" to what's in "pProps". - * - * [currently only supports file type, aux type, and access flags] - * - * Technically we should reload the GenericArchive from the NufxArchive, - * but the set of changes is pretty small, so we just make them here. - */ -bool -DiskArchive::SetProps(CWnd* pMsgWnd, GenericEntry* pGenericEntry, - const FileProps* pProps) -{ - DIError dierr; - DiskEntry* pEntry = (DiskEntry*) pGenericEntry; - A2File* pFile = pEntry->GetA2File(); - - dierr = pFile->GetDiskFS()->SetFileInfo(pFile, pProps->fileType, - pProps->auxType, pProps->access); - if (dierr != kDIErrNone) { - CString errMsg; - errMsg.Format("Unable to set file info: %s.\n", - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - return false; - } - - /* do this in lieu of reloading GenericArchive */ - pEntry->SetFileType(pFile->GetFileType()); - pEntry->SetAuxType(pFile->GetAuxType()); - pEntry->SetAccess(pFile->GetAccess()); - - /* DOS 3.2/3.3 may change these as well */ - DiskImg::FSFormat fsFormat; - fsFormat = pFile->GetDiskFS()->GetDiskImg()->GetFSFormat(); - if (fsFormat == DiskImg::kFormatDOS32 || fsFormat == DiskImg::kFormatDOS33) { - WMSG0(" (reloading additional fields after DOS SFI)\n"); - pEntry->SetDataForkLen(pFile->GetDataLength()); - pEntry->SetCompressedLen(pFile->GetDataSparseLength()); - pEntry->SetSuspicious(pFile->GetQuality() == A2File::kQualitySuspicious); - } - - /* clear the dirty flag in trivial cases */ - (void) fpPrimaryDiskFS->Flush(DiskImg::kFlushFastOnly); - - return true; -} - - -/* - * =========================================================================== - * DiskArchive -- transfer files to another archive - * =========================================================================== - */ - -/* - * Transfer the selected files out of this archive and into another. - * - * In this case, it's files on a disk (with unspecified filesystem) to a NuFX - * archive. We get the open archive pointer and some options from "pXferOpts". - * - * The selection set was created with the "any" selection criteria, which - * means there's only one entry for each file regardless of whether it's - * forked or not. - */ -GenericArchive::XferStatus -DiskArchive::XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, - ActionProgressDialog* pActionProgress, const XferFileOptions* pXferOpts) -{ - WMSG0("DiskArchive XferSelection!\n"); - unsigned char* dataBuf = nil; - unsigned char* rsrcBuf = nil; - FileDetails fileDetails; - CString errMsg, extractErrMsg, cmpStr; - CString fixedPathName; - XferStatus retval = kXferFailed; - - pXferOpts->fTarget->XferPrepare(pXferOpts); - - SelectionEntry* pSelEntry = pSelSet->IterNext(); - for ( ; pSelEntry != nil; pSelEntry = pSelSet->IterNext()) { - long dataLen=-1, rsrcLen=-1; - DiskEntry* pEntry = (DiskEntry*) pSelEntry->GetEntry(); - int typeOverride = -1; - int result; - - ASSERT(dataBuf == nil); - ASSERT(rsrcBuf == nil); - - if (pEntry->GetDamaged()) { - WMSG1(" XFER skipping damaged entry '%s'\n", - pEntry->GetDisplayName()); - continue; - } - - /* - * Do a quick de-colonizing pass for non-ProDOS volumes, then prepend - * the subvolume name (if any). - */ - fixedPathName = pEntry->GetPathName(); - if (fixedPathName.IsEmpty()) - fixedPathName = _T("(no filename)"); - if (pEntry->GetFSFormat() != DiskImg::kFormatProDOS) - fixedPathName.Replace(PathProposal::kDefaultStoredFssep, '.'); - if (pEntry->GetSubVolName() != nil) { - CString tmpStr; - tmpStr = pEntry->GetSubVolName(); - tmpStr += (char)PathProposal::kDefaultStoredFssep; - tmpStr += fixedPathName; - fixedPathName = tmpStr; - } - - if (pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir) { - /* this is the volume dir */ - WMSG1(" XFER not transferring volume dir '%s'\n", - fixedPathName); - continue; - } else if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory) { - if (pXferOpts->fPreserveEmptyFolders) { - /* if this is an empty directory, create a fake entry */ - cmpStr = fixedPathName; - cmpStr += (char)PathProposal::kDefaultStoredFssep; - - if (pSelSet->CountMatchingPrefix(cmpStr) == 0) { - WMSG1("FOUND empty dir '%s'\n", fixedPathName); - cmpStr += kEmptyFolderMarker; - dataBuf = new unsigned char[1]; - dataLen = 0; - fileDetails.entryKind = FileDetails::kFileKindDataFork; - fileDetails.storageName = cmpStr; - fileDetails.fileType = 0; // NON - fileDetails.access = - pEntry->GetAccess() | GenericEntry::kAccessInvisible; - goto have_stuff2; - } else { - WMSG1("NOT empty dir '%s'\n", fixedPathName); - } - } - - WMSG1(" XFER not transferring directory '%s'\n", - fixedPathName); - continue; - } - - WMSG3(" Xfer '%s' (data=%d rsrc=%d)\n", - fixedPathName, pEntry->GetHasDataFork(), - pEntry->GetHasRsrcFork()); - - dataBuf = nil; - dataLen = 0; - result = pEntry->ExtractThreadToBuffer(GenericEntry::kDataThread, - (char**) &dataBuf, &dataLen, &extractErrMsg); - if (result == IDCANCEL) { - WMSG0("Cancelled during data extract!\n"); - goto bail; /* abort anything that was pending */ - } else if (result != IDOK) { - errMsg.Format("Failed while extracting '%s': %s.", - fixedPathName, extractErrMsg); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - ASSERT(dataBuf != nil); - ASSERT(dataLen >= 0); - -#if 0 - if (pXferOpts->fConvDOSText && - DiskImg::UsesDOSFileStructure(pEntry->GetFSFormat()) && - pEntry->GetFileType() == kFileTypeTXT) - { - /* don't need to convert EOL, so just strip in place */ - long len; - unsigned char* ucp; - - WMSG1(" Converting DOS text in '%s'\n", fixedPathName); - for (ucp = dataBuf, len = dataLen; len > 0; len--, ucp++) - *ucp = *ucp & 0x7f; - } -#endif - -#if 0 // annoying to invoke PTX reformatter from here... ReformatHolder, etc. - if (pXferOpts->fConvPascalText && - pEntry->GetFSFormat() == DiskImg::kFormatPascal && - pEntry->GetFileType() == kFileTypePTX) - { - WMSG1("WOULD CONVERT ptx '%s'\n", fixedPathName); - } -#endif - - if (pEntry->GetHasRsrcFork()) { - rsrcBuf = nil; - rsrcLen = 0; - result = pEntry->ExtractThreadToBuffer(GenericEntry::kRsrcThread, - (char**) &rsrcBuf, &rsrcLen, &extractErrMsg); - if (result == IDCANCEL) { - WMSG0("Cancelled during rsrc extract!\n"); - goto bail; /* abort anything that was pending */ - } else if (result != IDOK) { - errMsg.Format("Failed while extracting '%s': %s.", - fixedPathName, extractErrMsg); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - } else { - ASSERT(rsrcBuf == nil); - } - - if (pEntry->GetHasDataFork() && pEntry->GetHasRsrcFork()) - fileDetails.entryKind = FileDetails::kFileKindBothForks; - else if (pEntry->GetHasDataFork()) - fileDetails.entryKind = FileDetails::kFileKindDataFork; - else if (pEntry->GetHasRsrcFork()) - fileDetails.entryKind = FileDetails::kFileKindRsrcFork; - else { - ASSERT(false); - fileDetails.entryKind = FileDetails::kFileKindUnknown; - } - - /* - * Set up the FileDetails. - */ - fileDetails.storageName = fixedPathName; - fileDetails.fileType = pEntry->GetFileType(); - fileDetails.access = pEntry->GetAccess(); -have_stuff2: - fileDetails.fileSysFmt = pEntry->GetSourceFS(); - fileDetails.fileSysInfo = PathProposal::kDefaultStoredFssep; - fileDetails.extraType = pEntry->GetAuxType(); - fileDetails.storageType = kNuStorageUnknown; /* let NufxLib deal */ - - time_t when; - when = time(nil); - UNIXTimeToDateTime(&when, &fileDetails.archiveWhen); - when = pEntry->GetModWhen(); - UNIXTimeToDateTime(&when, &fileDetails.modWhen); - when = pEntry->GetCreateWhen(); - UNIXTimeToDateTime(&when, &fileDetails.createWhen); - - pActionProgress->SetArcName(fileDetails.storageName); - if (pActionProgress->SetProgress(0) == IDCANCEL) { - retval = kXferCancelled; - goto bail; - } - - errMsg = pXferOpts->fTarget->XferFile(&fileDetails, &dataBuf, dataLen, - &rsrcBuf, rsrcLen); - if (!errMsg.IsEmpty()) { - WMSG0("XferFile failed!\n"); - errMsg.Format("Failed while transferring '%s': %s.", - pEntry->GetDisplayName(), (const char*) errMsg); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - ASSERT(dataBuf == nil); - ASSERT(rsrcBuf == nil); - - if (pActionProgress->SetProgress(100) == IDCANCEL) { - retval = kXferCancelled; - goto bail; - } - } - - //MainWindow* pMainWin; - //pMainWin = (MainWindow*)::AfxGetMainWnd(); - //pMainWin->EventPause(1000); - - retval = kXferOK; - -bail: - if (retval != kXferOK) - pXferOpts->fTarget->XferAbort(pMsgWnd); - else - pXferOpts->fTarget->XferFinish(pMsgWnd); - delete[] dataBuf; - delete[] rsrcBuf; - return retval; -} - -/* - * Prepare for file transfers. - */ -void -DiskArchive::XferPrepare(const XferFileOptions* pXferOpts) -{ - WMSG0("DiskArchive::XferPrepare\n"); - - //fpPrimaryDiskFS->SetParameter(DiskFS::kParmProDOS_AllowLowerCase, - // pXferOpts->fAllowLowerCase); - //fpPrimaryDiskFS->SetParameter(DiskFS::kParmProDOS_AllocSparse, - // pXferOpts->fUseSparseBlocks); - fpPrimaryDiskFS->SetParameter(DiskFS::kParm_CreateUnique, true); - - //fXferStoragePrefix = pXferOpts->fStoragePrefix; - fpXferTargetFS = pXferOpts->fpTargetFS; -} - -/* - * Transfer a file to the disk image. Called from NufxArchive's XferSelection - * and clipboard "paste". - * - * "dataLen" and "rsrcLen" will be -1 if the corresponding fork doesn't - * exist. - * - * Returns 0 on success, nonzero on failure. - * - * On success, *pDataBuf and *pRsrcBuf are freed and set to nil. (It's - * necessary for the interface to work this way because the NufxArchive - * version just tucks the pointers into NufxLib structures.) - */ -CString -DiskArchive::XferFile(FileDetails* pDetails, unsigned char** pDataBuf, - long dataLen, unsigned char** pRsrcBuf, long rsrcLen) -{ - //const int kFileTypeTXT = 0x04; - DiskFS::CreateParms createParms; - DiskFS* pDiskFS; - CString errMsg; - DIError dierr = kDIErrNone; - - WMSG3(" XFER: transfer '%s' (dataLen=%ld rsrcLen=%ld)\n", - pDetails->storageName, dataLen, rsrcLen); - - ASSERT(pDataBuf != nil); - ASSERT(pRsrcBuf != nil); - - /* fill out CreateParms from FileDetails */ - ConvertFDToCP(pDetails, &createParms); - - if (fpXferTargetFS == nil) - pDiskFS = fpPrimaryDiskFS; - else - pDiskFS = fpXferTargetFS; - - /* - * Strip the high ASCII from DOS and RDOS text files, unless we're adding - * them to a DOS disk. Likewise, if we're adding non-DOS text files to - * a DOS disk, we need to add the high bit. - * - * DOS converts both TXT and SRC to 'T', so we have to handle both here. - * Ideally we'd just ask DOS, "do you think this is a text file?", but it's - * not worth adding a new interface just for that. - */ - bool srcIsDOS, dstIsDOS; - srcIsDOS = DiskImg::UsesDOSFileStructure(pDetails->fileSysFmt); - dstIsDOS = DiskImg::UsesDOSFileStructure(pDiskFS->GetDiskImg()->GetFSFormat()); - if (dataLen > 0 && - (pDetails->fileType == kFileTypeTXT || pDetails->fileType == kFileTypeSRC)) - { - unsigned char* ucp = *pDataBuf; - long len = dataLen; - - if (srcIsDOS && !dstIsDOS) { - WMSG1(" Stripping high ASCII from '%s'\n", pDetails->storageName); - - while (len--) - *ucp++ &= 0x7f; - } else if (!srcIsDOS && dstIsDOS) { - WMSG1(" Adding high ASCII to '%s'\n", pDetails->storageName); - - while (len--) { - if (*ucp != '\0') - *ucp |= 0x80; - ucp++; - } - } else if (srcIsDOS && dstIsDOS) { - WMSG1(" --- not altering DOS-to-DOS text '%s'\n", - pDetails->storageName); - } else { - WMSG1(" --- non-DOS transfer '%s'\n", pDetails->storageName); - } - } - - /* add a file with one or two forks */ - if (createParms.storageType == kNuStorageDirectory) { - ASSERT(dataLen < 0 && rsrcLen < 0); - } else { - ASSERT(dataLen >= 0 || rsrcLen >= 0); // at least one fork - } - - /* if we still have something to write, write it */ - dierr = AddForksToDisk(pDiskFS, &createParms, *pDataBuf, dataLen, - *pRsrcBuf, rsrcLen); - if (dierr != kDIErrNone) { - errMsg.Format("%s", DiskImgLib::DIStrError(dierr)); - goto bail; - } - - /* clean up */ - delete[] *pDataBuf; - *pDataBuf = nil; - delete[] *pRsrcBuf; - *pRsrcBuf = nil; - -bail: - return errMsg; -} - - -/* - * Abort our progress. Not really possible, except by throwing the disk - * image away. - */ -void -DiskArchive::XferAbort(CWnd* pMsgWnd) -{ - WMSG0("DiskArchive::XferAbort\n"); - InternalReload(pMsgWnd); -} - -/* - * Transfer is finished. - */ -void -DiskArchive::XferFinish(CWnd* pMsgWnd) -{ - WMSG0("DiskArchive::XferFinish\n"); - InternalReload(pMsgWnd); -} +/* + * CiderPress + * Copyright (C) 2009 by CiderPress authors. All Rights Reserved. + * Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved. + * See the file LICENSE for distribution terms. + */ +/* + * Bridge between DiskImg and GenericArchive. + */ +#include "stdafx.h" +#include "DiskArchive.h" +#include "NufxArchive.h" +#include "Preferences.h" +#include "Main.h" +#include "ImageFormatDialog.h" +#include "RenameEntryDialog.h" +#include "ConfirmOverwriteDialog.h" +#include "../diskimg/DiskImgDetail.h" + +static const char* kEmptyFolderMarker = ".$$EmptyFolder"; + + +/* + * =========================================================================== + * DiskEntry + * =========================================================================== + */ + +/* + * Extract data from a disk image. + * + * If "*ppText" is non-nil, the data will be read into the pointed-to buffer + * so long as it's shorter than *pLength bytes. The value in "*pLength" + * will be set to the actual length used. + * + * If "*ppText" is nil, the uncompressed data will be placed into a buffer + * allocated with "new[]". + * + * Returns IDOK on success, IDCANCEL if the operation was cancelled by the + * user, and -1 value on failure. On failure, "*pErrMsg" holds an error + * message. + * + * "which" is an anonymous GenericArchive enum (e.g. "kDataThread"). + */ +int +DiskEntry::ExtractThreadToBuffer(int which, char** ppText, long* pLength, + CString* pErrMsg) const +{ + DIError dierr; + A2FileDescr* pOpenFile = nil; + char* dataBuf = nil; + bool rsrcFork; + bool needAlloc = true; + int result = -1; + + ASSERT(fpFile != nil); + ASSERT(pErrMsg != nil); + *pErrMsg = ""; + + if (*ppText != nil) + needAlloc = false; + + if (GetDamaged()) { + *pErrMsg = "File is damaged"; + goto bail; + } + + if (which == kDataThread) + rsrcFork = false; + else if (which == kRsrcThread) + rsrcFork = true; + else { + *pErrMsg = "No such fork"; + goto bail; + } + + LONGLONG len; + if (rsrcFork) + len = fpFile->GetRsrcLength(); + else + len = fpFile->GetDataLength(); + + if (len == 0) { + if (needAlloc) { + *ppText = new char[1]; + **ppText = '\0'; + } + *pLength = 0; + result = IDOK; + goto bail; + } else if (len < 0) { + assert(rsrcFork); // forked files always have a data fork + *pErrMsg = "That fork doesn't exist"; + goto bail; + } + + dierr = fpFile->Open(&pOpenFile, true, rsrcFork); + if (dierr != kDIErrNone) { + *pErrMsg = "File open failed"; + goto bail; + } + + SET_PROGRESS_BEGIN(); + pOpenFile->SetProgressUpdater(DiskArchive::ProgressCallback, len, nil); + + if (needAlloc) { + dataBuf = new char[(int) len]; + if (dataBuf == nil) { + pErrMsg->Format("ERROR: allocation of %ld bytes failed", len); + goto bail; + } + } else { + if (*pLength < (long) len) { + pErrMsg->Format("ERROR: buf size %ld too short (%ld)", + *pLength, (long) len); + goto bail; + } + dataBuf = *ppText; + } + + dierr = pOpenFile->Read(dataBuf, (size_t) len); + if (dierr != kDIErrNone) { + if (dierr == kDIErrCancelled) { + result = IDCANCEL; + } else { + pErrMsg->Format("File read failed: %s", + DiskImgLib::DIStrError(dierr)); + } + goto bail; + } + + if (needAlloc) + *ppText = dataBuf; + *pLength = (long) len; + result = IDOK; + +bail: + if (pOpenFile != nil) + pOpenFile->Close(); + if (result == IDOK) { + SET_PROGRESS_END(); + ASSERT(pErrMsg->IsEmpty()); + } else { + ASSERT(result == IDCANCEL || !pErrMsg->IsEmpty()); + if (needAlloc) { + delete[] dataBuf; + ASSERT(*ppText == nil); + } + } + return result; +} + +/* + * Extract data from a thread to a file. Since we're not copying to memory, + * we can't assume that we're able to hold the entire file all at once. + * + * Returns IDOK on success, IDCANCEL if the operation was cancelled by the + * user, and -1 value on failure. On failure, "*pMsg" holds an + * error message. + */ +int +DiskEntry::ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, + ConvertHighASCII convHA, CString* pErrMsg) const +{ + A2FileDescr* pOpenFile = nil; + bool rsrcFork; + int result = -1; + + ASSERT(IDOK != -1 && IDCANCEL != -1); + ASSERT(fpFile != nil); + + if (which == kDataThread) + rsrcFork = false; + else if (which == kRsrcThread) + rsrcFork = true; + else { + /* if we handle disk images, make sure we disable "conv" */ + *pErrMsg = "No such fork"; + goto bail; + } + + LONGLONG len; + if (rsrcFork) + len = fpFile->GetRsrcLength(); + else + len = fpFile->GetDataLength(); + + if (len == 0) { + WMSG0("Empty fork\n"); + result = IDOK; + goto bail; + } else if (len < 0) { + assert(rsrcFork); // forked files always have a data fork + *pErrMsg = "That fork doesn't exist"; + goto bail; + } + + DIError dierr; + dierr = fpFile->Open(&pOpenFile, true, rsrcFork); + if (dierr != kDIErrNone) { + *pErrMsg = "Unable to open file on disk image"; + goto bail; + } + + dierr = CopyData(pOpenFile, outfp, conv, convHA, pErrMsg); + if (dierr != kDIErrNone) { + if (pErrMsg->IsEmpty()) { + pErrMsg->Format("Failed while copying data: %s\n", + DiskImgLib::DIStrError(dierr)); + } + goto bail; + } + + result = IDOK; + +bail: + if (pOpenFile != nil) + pOpenFile->Close(); + return result; +} + +/* + * Copy data from the open A2File to outfp, possibly converting EOL along + * the way. + */ +DIError +DiskEntry::CopyData(A2FileDescr* pOpenFile, FILE* outfp, ConvertEOL conv, + ConvertHighASCII convHA, CString* pMsg) const +{ + DIError dierr = kDIErrNone; + const int kChunkSize = 16384; + char buf[kChunkSize]; + //bool firstChunk = true; + //EOLType sourceType; + bool lastCR = false; + LONGLONG srcLen, dataRem; + + /* get the length of the open file */ + dierr = pOpenFile->Seek(0, DiskImgLib::kSeekEnd); + if (dierr != kDIErrNone) + goto bail; + srcLen = pOpenFile->Tell(); + dierr = pOpenFile->Rewind(); + if (dierr != kDIErrNone) + goto bail; + ASSERT(srcLen > 0); // empty files should've been caught earlier + + SET_PROGRESS_BEGIN(); + pOpenFile->SetProgressUpdater(DiskArchive::ProgressCallback, srcLen, nil); + + /* + * Loop until all data copied. + */ + dataRem = srcLen; + while (dataRem) { + int chunkLen; + + if (dataRem > kChunkSize) + chunkLen = kChunkSize; + else + chunkLen = (int) dataRem; + + /* read a chunk from the source file */ + dierr = pOpenFile->Read(buf, chunkLen); + if (dierr != kDIErrNone) { + pMsg->Format("File read failed: %s", + DiskImgLib::DIStrError(dierr)); + goto bail; + } + + /* write chunk to destination file */ + int err = GenericEntry::WriteConvert(outfp, buf, chunkLen, &conv, + &convHA, &lastCR); + if (err != 0) { + pMsg->Format("File write failed: %s", strerror(err)); + dierr = kDIErrGeneric; + goto bail; + } + + dataRem -= chunkLen; + //SET_PROGRESS_UPDATE(ComputePercent(srcLen - dataRem, srcLen)); + } + +bail: + pOpenFile->ClearProgressUpdater(); + SET_PROGRESS_END(); + return dierr; +} + + +/* + * Figure out whether or not we're allowed to change a file's type and + * aux type. + */ +bool +DiskEntry::GetFeatureFlag(Feature feature) const +{ + DiskImg::FSFormat format; + + format = fpFile->GetDiskFS()->GetDiskImg()->GetFSFormat(); + + switch (feature) { + case kFeatureCanChangeType: + { + //if (GetRecordKind() == kRecordKindVolumeDir) + // return false; + + switch (format) { + case DiskImg::kFormatProDOS: + case DiskImg::kFormatPascal: + case DiskImg::kFormatMacHFS: + case DiskImg::kFormatDOS32: + case DiskImg::kFormatDOS33: + return true; + default: + return false; + } + } + case kFeaturePascalTypes: + { + switch (format) { + case DiskImg::kFormatPascal: + return true; + default: + return false; + } + } + case kFeatureDOSTypes: + { + switch (format) { + case DiskImg::kFormatDOS32: + case DiskImg::kFormatDOS33: + return true; + default: + return false; + } + } + case kFeatureHFSTypes: + { + switch (format) { + case DiskImg::kFormatMacHFS: + return true; + default: + return false; + } + } + case kFeatureHasFullAccess: + { + switch (format) { + case DiskImg::kFormatProDOS: + return true; + default: + return false; + } + } + case kFeatureHasSimpleAccess: + { + switch (format) { + case DiskImg::kFormatDOS33: + case DiskImg::kFormatDOS32: + case DiskImg::kFormatCPM: + case DiskImg::kFormatMacHFS: + return true; + default: + return false; + } + } + case kFeatureHasInvisibleFlag: + { + switch(format) { + case DiskImg::kFormatProDOS: + case DiskImg::kFormatMacHFS: + return true; + default: + return false; + } + } + default: + WMSG1("Unexpected feature flag %d\n", feature); + assert(false); + return false; + } + + assert(false); + return false; +} + + +/* + * =========================================================================== + * DiskArchive + * =========================================================================== + */ + +/* + * Perform one-time initialization of the DiskLib library. + */ +/*static*/ CString +DiskArchive::AppInit(void) +{ + CString result(""); + DIError dierr; + long major, minor, bug; + + WMSG0("Initializing DiskImg library\n"); + + // set this before initializing, so we can see init debug msgs + DiskImgLib::Global::SetDebugMsgHandler(DebugMsgHandler); + + dierr = DiskImgLib::Global::AppInit(); + if (dierr != kDIErrNone) { + result.Format("DiskImg DLL failed to initialize: %s\n", + DiskImgLib::DIStrError(dierr)); + goto bail; + } + + DiskImgLib::Global::GetVersion(&major, &minor, &bug); + if (major != kDiskImgVersionMajor || minor < kDiskImgVersionMinor) { + result.Format("Older or incompatible version of DiskImg DLL found.\r\r" + "Wanted v%d.%d.x, found %ld.%ld.%ld.", + kDiskImgVersionMajor, kDiskImgVersionMinor, + major, minor, bug); + goto bail; + } + +bail: + return result; +} + +/* + * Perform one-time cleanup of DiskImgLib at shutdown time. + */ +/*static*/ void +DiskArchive::AppCleanup(void) +{ + DiskImgLib::Global::AppCleanup(); +} + + +/* + * Handle a debug message from the DiskImg library. + */ +/*static*/ void +DiskArchive::DebugMsgHandler(const char* file, int line, const char* msg) +{ + ASSERT(file != nil); + ASSERT(msg != nil); + +#if defined(_DEBUG_LOG) + //fprintf(gLog, "%s(%d) : %s", file, line, msg); + fprintf(gLog, "%05u %s", gPid, msg); +#elif defined(_DEBUG) + _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s", msg); +#else + /* do nothing */ +#endif +} + +/* + * Progress update callback, called from DiskImgLib during read/write + * operations. + * + * Returns "true" if we should continue; + */ +/*static*/ bool +DiskArchive::ProgressCallback(DiskImgLib::A2FileDescr* pFile, + DiskImgLib::di_off_t max, DiskImgLib::di_off_t current, void* state) +{ + int status; + + //::Sleep(10); + status = SET_PROGRESS_UPDATE(ComputePercent(current, max)); + if (status == IDCANCEL) { + WMSG0("IDCANCEL returned from Main progress updater\n"); + return false; + } + + return true; // tell DiskImgLib to continue what it's doing +} + +/* + * Progress update callback, called from DiskImgLib while scanning a volume + * during Open(). + * + * Returns "true" if we should continue; + */ +/*static*/ bool +DiskArchive::ScanProgressCallback(void* cookie, const char* str, int count) +{ + CString fmt; + bool cont; + + if (count == 0) + fmt = str; + else + fmt.Format("%s (%%d)", str); + cont = SET_PROGRESS_COUNTER_2(fmt, count); + + if (!cont) { + WMSG0("cancelled\n"); + } + + return cont; +} + + +/* + * Finish instantiating a DiskArchive object by opening an existing file. + */ +GenericArchive::OpenResult +DiskArchive::Open(const char* filename, bool readOnly, CString* pErrMsg) +{ + DIError dierr; + CString errMsg; + OpenResult result = kResultUnknown; + const Preferences* pPreferences = GET_PREFERENCES(); + + ASSERT(fpPrimaryDiskFS == nil); + ASSERT(filename != nil); + //ASSERT(ext != nil); + + ASSERT(pPreferences != nil); + + fIsReadOnly = readOnly; + + // special case for volume open + bool isVolume = false; + if (filename[0] >= 'A' && filename[0] <= 'Z' && + filename[1] == ':' && filename[2] == '\\' && + filename[3] == '\0') + { + isVolume = true; + } + + /* + * Open the image. This can be very slow for compressed images, + * especially 3.5" FDI images. + */ + { + CWaitCursor waitc; + + dierr = fDiskImg.OpenImage(filename, PathProposal::kLocalFssep, readOnly); + if (dierr == kDIErrAccessDenied && !readOnly && !isVolume) { + // retry file open with read-only set + // don't do that for volumes -- assume they know what they want + WMSG0(" Retrying open with read-only set\n"); + fIsReadOnly = readOnly = true; + dierr = fDiskImg.OpenImage(filename, PathProposal::kLocalFssep, readOnly); + } + if (dierr != kDIErrNone) { + if (dierr == kDIErrFileArchive) + result = kResultFileArchive; + else { + result = kResultFailure; + errMsg.Format("Unable to open '%s': %s.", filename, + DiskImgLib::DIStrError(dierr)); + } + goto bail; + } + } + + dierr = fDiskImg.AnalyzeImage(); + if (dierr != kDIErrNone) { + result = kResultFailure; + errMsg.Format("Analysis of '%s' failed: %s", filename, + DiskImgLib::DIStrError(dierr)); + goto bail; + } + + /* allow them to override sector order and filesystem, if requested */ + if (pPreferences->GetPrefBool(kPrQueryImageFormat)) { + ImageFormatDialog imf; + + imf.InitializeValues(&fDiskImg); + imf.fFileSource = filename; + imf.SetQueryDisplayFormat(false); + imf.SetAllowGenericFormats(false); + + if (imf.DoModal() != IDOK) { + WMSG0("User bailed on IMF dialog\n"); + result = kResultCancel; + goto bail; + } + + if (imf.fSectorOrder != fDiskImg.GetSectorOrder() || + imf.fFSFormat != fDiskImg.GetFSFormat()) + { + WMSG0("Initial values overridden, forcing img format\n"); + dierr = fDiskImg.OverrideFormat(fDiskImg.GetPhysicalFormat(), + imf.fFSFormat, imf.fSectorOrder); + if (dierr != kDIErrNone) { + result = kResultFailure; + errMsg.Format("Unable to access disk image using selected" + " parameters. Error: %s.", + DiskImgLib::DIStrError(dierr)); + goto bail; + } + } + } + + if (fDiskImg.GetFSFormat() == DiskImg::kFormatUnknown || + fDiskImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown) + { + result = kResultFailure; + errMsg.Format("Unable to identify filesystem on '%s'", filename); + goto bail; + } + + /* create an appropriate DiskFS object */ + fpPrimaryDiskFS = fDiskImg.OpenAppropriateDiskFS(); + if (fpPrimaryDiskFS == nil) { + /* unknown FS should've been caught above! */ + ASSERT(false); + result = kResultFailure; + errMsg.Format("Format of '%s' not recognized.", filename); + goto bail; + } + + fpPrimaryDiskFS->SetScanForSubVolumes(DiskFS::kScanSubEnabled); + + /* + * Scan all files and on the disk image, and recursively descend into + * sub-volumes. Can be slow on physical volumes. + * + * This is really only useful for ProDOS and HFS disks. Nothing else + * can be large enough to really get slow, and nothing else is likely + * to show up in a large multi-partition image. + * + * THOUGHT: only show the dialog if the volume is over a certain size. + */ + { + MainWindow* pMain = GET_MAIN_WINDOW(); + ProgressCounterDialog* pProgress; + + pProgress = new ProgressCounterDialog; + pProgress->Create(_T("Examining contents, please wait..."), pMain); + pProgress->SetCounterFormat("Scanning..."); + pProgress->CenterWindow(); + //pMain->PeekAndPump(); // redraw + CWaitCursor waitc; + + /* set up progress dialog and scan all files */ + pMain->SetProgressCounterDialog(pProgress); + fDiskImg.SetScanProgressCallback(ScanProgressCallback, this); + + dierr = fpPrimaryDiskFS->Initialize(&fDiskImg, DiskFS::kInitFull); + + fDiskImg.SetScanProgressCallback(nil, nil); + pMain->SetProgressCounterDialog(nil); + pProgress->DestroyWindow(); + + if (dierr != kDIErrNone) { + if (dierr == kDIErrCancelled) { + result = kResultCancel; + } else { + result = kResultFailure; + errMsg.Format("Error reading list of files from disk: %s", + DiskImgLib::DIStrError(dierr)); + } + goto bail; + } + } + + if (LoadContents() != 0) { + result = kResultFailure; + errMsg.Format("Failed while loading contents of disk image."); + goto bail; + } + + /* + * Force read-only flag if underlying FS doesn't allow RW. We need to + * consider embedded filesystems, so we only set RO if none of the + * filesystems are writable. + * + * BUG: this only checks the first level. Should be fully recursive. + */ + if (!fpPrimaryDiskFS->GetReadWriteSupported()) { + const DiskFS::SubVolume* pSubVol; + + fIsReadOnly = true; + pSubVol = fpPrimaryDiskFS->GetNextSubVolume(nil); + while (pSubVol != nil) { + if (pSubVol->GetDiskFS()->GetReadWriteSupported()) { + fIsReadOnly = false; + break; + } + + pSubVol = fpPrimaryDiskFS->GetNextSubVolume(pSubVol); + } + } + + /* force read-only if the primary is damaged */ + if (fpPrimaryDiskFS->GetFSDamaged()) + fIsReadOnly = true; + /* force read-only if the DiskImg thinks a wrapper is damaged */ + if (fpPrimaryDiskFS->GetDiskImg()->GetReadOnly()) + fIsReadOnly = true; + +// /* force read-only on .gz/.zip unless pref allows */ +// if (fDiskImg.GetOuterFormat() != DiskImg::kOuterFormatNone) { +// if (pPreferences->GetPrefBool(kPrWriteZips) == 0) +// fIsReadOnly = true; +// } + + SetPathName(filename); + result = kResultSuccess; + + /* set any preferences-based settings */ + PreferencesChanged(); + +bail: + *pErrMsg = errMsg; + if (!errMsg.IsEmpty()) { + assert(result == kResultFailure); + delete fpPrimaryDiskFS; + fpPrimaryDiskFS = nil; + } else { + assert(result != kResultFailure); + } + return result; +} + + +/* + * Finish instantiating a DiskArchive object by creating a new archive. + * + * Returns an error string on failure, or "" on success. + */ +CString +DiskArchive::New(const char* fileName, const void* vOptions) +{ + const Preferences* pPreferences = GET_PREFERENCES(); + NewOptions* pOptions = (NewOptions*) vOptions; + CString volName; + long numBlocks = -1; + long numTracks = -1; + int numSectors; + CString retmsg; + DIError dierr; + bool allowLowerCase; + + ASSERT(fileName != nil); + ASSERT(pOptions != nil); + + allowLowerCase = pPreferences->GetPrefBool(kPrProDOSAllowLower) != 0; + + switch (pOptions->base.format) { + case DiskImg::kFormatUnknown: + numBlocks = pOptions->blank.numBlocks; + break; + case DiskImg::kFormatProDOS: + volName = pOptions->prodos.volName; + numBlocks = pOptions->prodos.numBlocks; + break; + case DiskImg::kFormatPascal: + volName = pOptions->pascalfs.volName; + numBlocks = pOptions->pascalfs.numBlocks; + break; + case DiskImg::kFormatMacHFS: + volName = pOptions->hfs.volName; + numBlocks = pOptions->hfs.numBlocks; + break; + case DiskImg::kFormatDOS32: + numTracks = pOptions->dos.numTracks; + numSectors = pOptions->dos.numSectors; + + if (numTracks < DiskFSDOS33::kMinTracks || + numTracks > DiskFSDOS33::kMaxTracks) + { + retmsg.Format("Invalid DOS32 track count"); + goto bail; + } + if (numSectors != 13) { + retmsg.Format("Invalid DOS32 sector count"); + goto bail; + } + if (pOptions->dos.allocDOSTracks) + volName = "DOS"; + break; + case DiskImg::kFormatDOS33: + numTracks = pOptions->dos.numTracks; + numSectors = pOptions->dos.numSectors; + + if (numTracks < DiskFSDOS33::kMinTracks || + numTracks > DiskFSDOS33::kMaxTracks) + { + retmsg.Format("Invalid DOS33 track count"); + goto bail; + } + if (numSectors != 16 && numSectors != 32) { // no 13-sector (yet) + retmsg.Format("Invalid DOS33 sector count"); + goto bail; + } + if (pOptions->dos.allocDOSTracks) + volName = "DOS"; + break; + default: + retmsg.Format("Unsupported disk format"); + goto bail; + } + + WMSG4("DiskArchive: new '%s' %ld %s in '%s'\n", + (const char*)volName, numBlocks, + DiskImg::ToString(pOptions->base.format), fileName); + + bool canSkipFormat; + if (IsWin9x()) + canSkipFormat = false; + else + canSkipFormat = true; + + /* + * Create an image with the appropriate characteristics. We set + * "skipFormat" because we know this will be a brand-new file, and + * we're not currently creating nibble images. + * + * GLITCH: under Win98/ME, brand-new files contain the previous contents + * of the hard drive. We need to explicitly zero them out. We don't + * want to do it under Win2K/XP because it can be slow for larger + * volumes. + */ + if (numBlocks > 0) { + dierr = fDiskImg.CreateImage(fileName, nil, + DiskImg::kOuterFormatNone, + DiskImg::kFileFormatUnadorned, + DiskImg::kPhysicalFormatSectors, + nil, + pOptions->base.sectorOrder, + DiskImg::kFormatGenericProDOSOrd, // arg must be generic + numBlocks, + canSkipFormat); + } else { + ASSERT(numTracks > 0); + dierr = fDiskImg.CreateImage(fileName, nil, + DiskImg::kOuterFormatNone, + DiskImg::kFileFormatUnadorned, + DiskImg::kPhysicalFormatSectors, + nil, + pOptions->base.sectorOrder, + DiskImg::kFormatGenericProDOSOrd, // arg must be generic + numTracks, numSectors, + canSkipFormat); + } + if (dierr != kDIErrNone) { + retmsg.Format("Unable to create disk image: %s.", + DiskImgLib::DIStrError(dierr)); + goto bail; + } + + if (pOptions->base.format == DiskImg::kFormatUnknown) + goto skip_format; + + if (pOptions->base.format == DiskImg::kFormatDOS33 || + pOptions->base.format == DiskImg::kFormatDOS32) + fDiskImg.SetDOSVolumeNum(pOptions->dos.volumeNum); + + /* + * If we don't allow lower case in ProDOS filenames, don't allow them + * in volume names either. This works because we don't allow ' ' in + * volume names; otherwise we'd need to invoke a ProDOS-specific call + * to convert the ' ' to '.'. (Or we could just do it ourselves.) + * + * We can't ask the ProDOS DiskFS to force upper case for us because + * the ProDOS DiskFS object doesn't yet exist. + */ + if (pOptions->base.format == DiskImg::kFormatProDOS && !allowLowerCase) + volName.MakeUpper(); + + /* format it */ + dierr = fDiskImg.FormatImage(pOptions->base.format, volName); + if (dierr != kDIErrNone) { + retmsg.Format("Unable to format disk image: %s.", + DiskImgLib::DIStrError(dierr)); + goto bail; + } + fpPrimaryDiskFS = fDiskImg.OpenAppropriateDiskFS(false); + if (fpPrimaryDiskFS == nil) { + retmsg.Format("Unable to create DiskFS."); + goto bail; + } + + /* prep it */ + dierr = fpPrimaryDiskFS->Initialize(&fDiskImg, DiskFS::kInitFull); + if (dierr != kDIErrNone) { + retmsg.Format("Error reading list of files from disk: %s", + DiskImgLib::DIStrError(dierr)); + goto bail; + } + + /* this is pretty meaningless, but do it to ensure we're initialized */ + if (LoadContents() != 0) { + retmsg.Format("Failed while loading contents of disk image."); + goto bail; + } + +skip_format: + SetPathName(fileName); + + /* set any preferences-based settings */ + PreferencesChanged(); + +bail: + return retmsg; +} + +/* + * Close the DiskArchive ojbect. + */ +CString +DiskArchive::Close(void) +{ + if (fpPrimaryDiskFS != nil) { + WMSG0("DiskArchive shutdown closing disk image\n"); + delete fpPrimaryDiskFS; + fpPrimaryDiskFS = nil; + } + + DIError dierr; + dierr = fDiskImg.CloseImage(); + if (dierr != kDIErrNone) { + MainWindow* pMainWin = (MainWindow*)::AfxGetMainWnd(); + CString msg, failed; + + msg.Format("Failed while closing disk image: %s.", + DiskImgLib::DIStrError(dierr)); + failed.LoadString(IDS_FAILED); + WMSG1("During close: %s\n", (const char*) msg); + + pMainWin->MessageBox(msg, failed, MB_OK); + } + + return ""; +} + +/* + * Flush the DiskArchive object. + * + * Most of the stuff we do with disk images goes straight through, but in + * the case of compressed disks we don't normally re-compress them until + * it's time to close them. This forces us to update the copy on disk. + * + * Returns an empty string on success, or an error message on failure. + */ +CString +DiskArchive::Flush(void) +{ + DIError dierr; + CWaitCursor waitc; + + assert(fpPrimaryDiskFS != nil); + + dierr = fpPrimaryDiskFS->Flush(DiskImg::kFlushAll); + if (dierr != kDIErrNone) { + CString errMsg; + + errMsg.Format("Attempt to flush the current archive failed: %s.", + DiskImgLib::DIStrError(dierr)); + return errMsg; + } + + return ""; +} + +/* + * Returns "true" if the archive has un-flushed modifications pending. + */ +bool +DiskArchive::IsModified(void) const +{ + assert(fpPrimaryDiskFS != nil); + + return fpPrimaryDiskFS->GetDiskImg()->GetDirtyFlag(); +} + +/* + * Return an description of the disk archive, suitable for display in the + * main title bar. + */ +void +DiskArchive::GetDescription(CString* pStr) const +{ + if (fpPrimaryDiskFS == nil) + return; + + if (fpPrimaryDiskFS->GetVolumeID() != nil) + pStr->Format("Disk Image - %s", fpPrimaryDiskFS->GetVolumeID()); +} + + +/* + * Load the contents of a "disk archive". + * + * Returns 0 on success. + */ +int +DiskArchive::LoadContents(void) +{ + int result; + + WMSG0("DiskArchive LoadContents\n"); + ASSERT(fpPrimaryDiskFS != nil); + + { + MainWindow* pMain = GET_MAIN_WINDOW(); + ExclusiveModelessDialog* pWaitDlg = new ExclusiveModelessDialog; + pWaitDlg->Create(IDD_LOADING, pMain); + pWaitDlg->CenterWindow(); + pMain->PeekAndPump(); // redraw + CWaitCursor waitc; + + result = LoadDiskFSContents(fpPrimaryDiskFS, ""); + + SET_PROGRESS_COUNTER(-1); + + pWaitDlg->DestroyWindow(); + //pMain->PeekAndPump(); // redraw + } + + return result; +} + +/* + * Reload the stuff from the underlying DiskFS. + * + * This also does a "lite" flush of the disk data. For files that are + * essentially being written as we go, this does little more than clear + * the "dirty" flag. Files that need to be recompressed or have some + * other slow operation remain dirty. + * + * We don't need to do the flush as part of the reload -- we can load the + * contents with everything in a perfectly dirty state. We don't need to + * do it at all. We do it to keep the "dirty" flag clear when nothing is + * really dirty, and we do it here because almost all of our functions call + * "reload" after making changes, which makes it convenient to call from here. + */ +CString +DiskArchive::Reload() +{ + fReloadFlag = true; // tell everybody that cached data is invalid + + (void) fpPrimaryDiskFS->Flush(DiskImg::kFlushFastOnly); + + DeleteEntries(); // a GenericArchive operation + + if (LoadContents() != 0) + return "Disk image reload failed."; + + return ""; +} + +/* + * Reload the contents of the archive, showing an error message if the + * reload fails. + * + * Returns 0 on success, -1 on failure. + */ +int +DiskArchive::InternalReload(CWnd* pMsgWnd) +{ + CString errMsg; + + errMsg = Reload(); + + if (!errMsg.IsEmpty()) { + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + return -1; + } + + return 0; +} + +/* + * Load the contents of a DiskFS. + * + * Recursively handle sub-volumes. "volName" holds the name of the + * sub-volume as it should appear in the list. + */ +int +DiskArchive::LoadDiskFSContents(DiskFS* pDiskFS, const char* volName) +{ + static const char* kBlankFileName = ""; + A2File* pFile; + DiskEntry* pNewEntry; + DiskFS::SubVolume* pSubVol; + const Preferences* pPreferences = GET_PREFERENCES(); + bool wantCoerceDOSFilenames = false; + CString ourSubVolName; + + wantCoerceDOSFilenames = pPreferences->GetPrefBool(kPrCoerceDOSFilenames); + + WMSG2("Notes for disk image '%s':\n%s", + volName, pDiskFS->GetDiskImg()->GetNotes()); + + ASSERT(pDiskFS != nil); + pFile = pDiskFS->GetNextFile(nil); + while (pFile != nil) { + pNewEntry = new DiskEntry(pFile); + if (pNewEntry == nil) + return -1; + + CString path(pFile->GetPathName()); + if (path.IsEmpty()) + path = kBlankFileName; + if (DiskImg::UsesDOSFileStructure(pFile->GetFSFormat()) && + wantCoerceDOSFilenames) + { + InjectLowercase(&path); + } + pNewEntry->SetPathName(path); + if (volName[0] != '\0') + pNewEntry->SetSubVolName(volName); + pNewEntry->SetFssep(pFile->GetFssep()); + pNewEntry->SetFileType(pFile->GetFileType()); + pNewEntry->SetAuxType(pFile->GetAuxType()); + pNewEntry->SetAccess(pFile->GetAccess()); + if (pFile->GetCreateWhen() == 0) + pNewEntry->SetCreateWhen(kDateNone); + else + pNewEntry->SetCreateWhen(pFile->GetCreateWhen()); + if (pFile->GetModWhen() == 0) + pNewEntry->SetModWhen(kDateNone); + else + pNewEntry->SetModWhen(pFile->GetModWhen()); + pNewEntry->SetSourceFS(pFile->GetFSFormat()); + pNewEntry->SetHasDataFork(true); + if (pFile->IsVolumeDirectory()) { + /* volume directory entry; only on ProDOS/HFS */ + ASSERT(pFile->GetRsrcLength() < 0); + pNewEntry->SetRecordKind(GenericEntry::kRecordKindVolumeDir); + //pNewEntry->SetUncompressedLen(pFile->GetDataLength()); + pNewEntry->SetDataForkLen(pFile->GetDataLength()); + pNewEntry->SetCompressedLen(pFile->GetDataLength()); + } else if (pFile->IsDirectory()) { + /* directory entry */ + ASSERT(pFile->GetRsrcLength() < 0); + pNewEntry->SetRecordKind(GenericEntry::kRecordKindDirectory); + //pNewEntry->SetUncompressedLen(pFile->GetDataLength()); + pNewEntry->SetDataForkLen(pFile->GetDataLength()); + pNewEntry->SetCompressedLen(pFile->GetDataLength()); + } else if (pFile->GetRsrcLength() >= 0) { + /* has resource fork */ + pNewEntry->SetRecordKind(GenericEntry::kRecordKindForkedFile); + pNewEntry->SetDataForkLen(pFile->GetDataLength()); + pNewEntry->SetRsrcForkLen(pFile->GetRsrcLength()); + //pNewEntry->SetUncompressedLen( + // pFile->GetDataLength() + pFile->GetRsrcLength() ); + pNewEntry->SetCompressedLen( + pFile->GetDataSparseLength() + pFile->GetRsrcSparseLength() ); + pNewEntry->SetHasRsrcFork(true); + } else { + /* just data fork */ + pNewEntry->SetRecordKind(GenericEntry::kRecordKindFile); + //pNewEntry->SetUncompressedLen(pFile->GetDataLength()); + pNewEntry->SetDataForkLen(pFile->GetDataLength()); + pNewEntry->SetCompressedLen(pFile->GetDataSparseLength()); + } + + switch (pNewEntry->GetSourceFS()) { + case DiskImg::kFormatDOS33: + case DiskImg::kFormatDOS32: + case DiskImg::kFormatUNIDOS: + case DiskImg::kFormatGutenberg: + pNewEntry->SetFormatStr("DOS"); + break; + case DiskImg::kFormatProDOS: + pNewEntry->SetFormatStr("ProDOS"); + break; + case DiskImg::kFormatPascal: + pNewEntry->SetFormatStr("Pascal"); + break; + case DiskImg::kFormatCPM: + pNewEntry->SetFormatStr("CP/M"); + break; + case DiskImg::kFormatMSDOS: + pNewEntry->SetFormatStr("MS-DOS"); + break; + case DiskImg::kFormatRDOS33: + case DiskImg::kFormatRDOS32: + case DiskImg::kFormatRDOS3: + pNewEntry->SetFormatStr("RDOS"); + break; + case DiskImg::kFormatMacHFS: + pNewEntry->SetFormatStr("HFS"); + break; + default: + pNewEntry->SetFormatStr("???"); + break; + } + + pNewEntry->SetDamaged(pFile->GetQuality() == A2File::kQualityDamaged); + pNewEntry->SetSuspicious(pFile->GetQuality() == A2File::kQualitySuspicious); + + AddEntry(pNewEntry); + + /* this is not very useful -- all the heavy lifting was done earlier */ + if ((GetNumEntries() % 100) == 0) + SET_PROGRESS_COUNTER(GetNumEntries()); + + pFile = pDiskFS->GetNextFile(pFile); + } + + /* + * Load all sub-volumes. + * + * We define the sub-volume name to use for the next layer down. We + * prepend an underscore to the unmodified name. So long as the volume + * name is a valid Windows path -- which should hold true for most disks, + * though possibly not for Pascal -- it can be extracted directly with + * its full path with no risk of conflict. (The extraction code relies + * on this, so don't put a ':' in the subvol name or Windows will choke.) + */ + pSubVol = pDiskFS->GetNextSubVolume(nil); + while (pSubVol != nil) { + CString concatSubVolName; + const char* subVolName; + int ret; + + subVolName = pSubVol->GetDiskFS()->GetVolumeName(); + if (subVolName == nil) + subVolName = "+++"; // call it *something* + + if (volName[0] == '\0') + concatSubVolName.Format("_%s", subVolName); + else + concatSubVolName.Format("%s_%s", volName, subVolName); + ret = LoadDiskFSContents(pSubVol->GetDiskFS(), concatSubVolName); + if (ret != 0) + return ret; + pSubVol = pDiskFS->GetNextSubVolume(pSubVol); + } + + return 0; +} + + +/* + * User has updated their preferences. Take note. + * + * Setting preferences in a DiskFS causes those prefs to be pushed down + * to all sub-volumes. + */ +void +DiskArchive::PreferencesChanged(void) +{ + const Preferences* pPreferences = GET_PREFERENCES(); + + if (fpPrimaryDiskFS != nil) { + fpPrimaryDiskFS->SetParameter(DiskFS::kParmProDOS_AllowLowerCase, + pPreferences->GetPrefBool(kPrProDOSAllowLower) != 0); + fpPrimaryDiskFS->SetParameter(DiskFS::kParmProDOS_AllocSparse, + pPreferences->GetPrefBool(kPrProDOSUseSparse) != 0); + } +} + + +/* + * Report on what this disk image is capable of. + */ +long +DiskArchive::GetCapability(Capability cap) +{ + switch (cap) { + case kCapCanTest: + return false; + break; + case kCapCanRenameFullPath: + return false; + break; + case kCapCanRecompress: + return false; + break; + case kCapCanEditComment: + return false; + break; + case kCapCanAddDisk: + return false; + break; + case kCapCanConvEOLOnAdd: + return true; + break; + case kCapCanCreateSubdir: + return true; + break; + case kCapCanRenameVolume: + return true; + break; + default: + ASSERT(false); + return -1; + break; + } +} + + +/* + * =========================================================================== + * DiskArchive -- add files + * =========================================================================== + */ + +/* + * Process a bulk "add" request. + * + * Returns "true" on success, "false" on failure. + */ +bool +DiskArchive::BulkAdd(ActionProgressDialog* pActionProgress, + const AddFilesDialog* pAddOpts) +{ + NuError nerr; + CString errMsg; + char curDir[MAX_PATH] = ""; + bool retVal = false; + + WMSG2("Opts: '%s' typePres=%d\n", + pAddOpts->fStoragePrefix, pAddOpts->fTypePreservation); + WMSG3(" sub=%d strip=%d ovwr=%d\n", + pAddOpts->fIncludeSubfolders, pAddOpts->fStripFolderNames, + pAddOpts->fOverwriteExisting); + + ASSERT(fpAddDataHead == nil); + + /* these reset on every new add */ + fOverwriteExisting = false; + fOverwriteNoAsk = false; + + /* we screen for clashes with existing files later; this just ensures + "batch uniqueness" */ + fpPrimaryDiskFS->SetParameter(DiskFS::kParm_CreateUnique, true); + + /* + * Save the current directory and change to the one from the file dialog. + */ + const char* buf = pAddOpts->GetFileNames(); + WMSG2("Selected path = '%s' (offset=%d)\n", buf, + pAddOpts->GetFileNameOffset()); + + if (GetCurrentDirectory(sizeof(curDir), curDir) == 0) { + errMsg = "Unable to get current directory.\n"; + ShowFailureMsg(pActionProgress, errMsg, IDS_FAILED); + goto bail; + } + if (SetCurrentDirectory(buf) == false) { + errMsg.Format("Unable to set current directory to '%s'.\n", buf); + ShowFailureMsg(pActionProgress, errMsg, IDS_FAILED); + goto bail; + } + + buf += pAddOpts->GetFileNameOffset(); + while (*buf != '\0') { + WMSG1(" file '%s'\n", buf); + + /* add the file, calling DoAddFile via the generic AddFile */ + nerr = AddFile(pAddOpts, buf, &errMsg); + if (nerr != kNuErrNone) { + if (errMsg.IsEmpty()) + errMsg.Format("Failed while adding file '%s': %s.", + (LPCTSTR) buf, NuStrError(nerr)); + if (nerr != kNuErrAborted) { + ShowFailureMsg(pActionProgress, errMsg, IDS_FAILED); + } + goto bail; + } + + buf += strlen(buf)+1; + } + + if (fpAddDataHead == nil) { + CString title; + title.LoadString(IDS_MB_APP_NAME); + errMsg = "No files added.\n"; + pActionProgress->MessageBox(errMsg, title, MB_OK | MB_ICONWARNING); + } else { + /* add all pending files */ + retVal = true; + errMsg = ProcessFileAddData(pAddOpts->fpTargetDiskFS, + pAddOpts->fConvEOL); + if (!errMsg.IsEmpty()) { + CString title; + ShowFailureMsg(pActionProgress, errMsg, IDS_FAILED); + retVal = false; + } + + /* success or failure, reload the contents */ + errMsg = Reload(); + if (!errMsg.IsEmpty()) + retVal = false; + } + +bail: + FreeAddDataList(); + if (SetCurrentDirectory(curDir) == false) { + errMsg.Format("Unable to reset current directory to '%s'.\n", buf); + ShowFailureMsg(pActionProgress, errMsg, IDS_FAILED); + // bummer, but don't signal failure + } + return retVal; +} + +/* + * Add a file to a disk image. + * + * Unfortunately we can't just add the files here. We need to figure out + * which pairs of files should be combined into a single "extended" file. + * (Yes, the cursed forked files strike again.) + * + * The way you tell if two files should be one is by comparing their + * filenames and type info. If they match, and one is a data fork and + * one is a resource fork, we have a single split file. + * + * We have to be careful here because we don't know which will be seen + * first and whether they'll be adjacent. We have to dig through the + * list of previously-added files for a match (O(n^2) behavior currently). + * + * We also have to compare the right filename. Comparing the Windows + * filename is a bad idea, because by definition one of them has a resource + * fork tag on it. We need to compare the normalized filename before + * the ProDOS normalizer/uniqifier gets a chance to mangle it. As luck + * would have it, that's exactly what we have in "storageName". + * + * For a NuFX archive, NufxLib does all this nonsense for us, but we have + * to manage it ourselves here. The good news is that, since we have to + * wade through all the filenames, we have an opportunity to make the names + * unique. So long as we ensure that the names we have don't clash with + * anything currently on the disk, we know that anything we add that does + * clash is running into something we just added, which means we can turn + * on CreateFile's "make unique" feature and let the filesystem-specific + * code handle uniqueness. + * + * Any fields we want to keep from the NuFileDetails struct need to be + * copied out. It's a "hairy" struct, so we need to duplicate the strings. + */ +NuError +DiskArchive::DoAddFile(const AddFilesDialog* pAddOpts, + FileDetails* pDetails) +{ + NuError nuerr = kNuErrNone; + DiskFS* pDiskFS = pAddOpts->fpTargetDiskFS; + + DIError dierr; + int neededLen = 64; // reasonable guess + char* fsNormalBuf = nil; + + WMSG2(" +++ ADD file: orig='%s' stor='%s'\n", + pDetails->origName, pDetails->storageName); + +retry: + /* + * Convert "storageName" to a filesystem-normalized path. + */ + delete[] fsNormalBuf; + fsNormalBuf = new char[neededLen]; + dierr = pDiskFS->NormalizePath(pDetails->storageName, + PathProposal::kDefaultStoredFssep, fsNormalBuf, &neededLen); + if (dierr == kDIErrDataOverrun) { + /* not long enough, try again *once* */ + delete[] fsNormalBuf; + fsNormalBuf = new char[neededLen]; + dierr = pDiskFS->NormalizePath(pDetails->storageName, + PathProposal::kDefaultStoredFssep, fsNormalBuf, &neededLen); + } + if (dierr != kDIErrNone) { + nuerr = kNuErrInternal; + goto bail; + } + + /* + * Test to see if the file already exists. If it does, give the user + * the opportunity to rename it, overwrite the original, or skip + * adding it. + * + * The FS-normalized path may not reflect the actual storage name, + * because some features (like ProDOS "allow lower case") aren't + * factored in until later. However, it should be close enough -- it + * has to be, or we'd be in trouble for saying it's going to overwrite + * the file in the archive. + */ + A2File* pExisting; + pExisting = pDiskFS->GetFileByName(fsNormalBuf); + if (pExisting != nil) { + NuResult result; + + result = HandleReplaceExisting(pExisting, pDetails); + if (result == kNuAbort) { + nuerr = kNuErrAborted; + goto bail; + } else if (result == kNuSkip) { + nuerr = kNuErrSkipped; + goto bail; + } else if (result == kNuRename) { + goto retry; + } else if (result == kNuOverwrite) { + /* delete the existing file immediately */ + WMSG1(" Deleting existing file '%s'\n", fsNormalBuf); + dierr = pDiskFS->DeleteFile(pExisting); + if (dierr != kDIErrNone) { + // Would be nice to show a dialog and explain *why*, but + // I'm not sure we have a window here. + WMSG1(" Deletion failed (err=%d)\n", dierr); + goto bail; + } + } else { + WMSG1("GLITCH: bad return %d from HandleReplaceExisting\n",result); + assert(false); + nuerr = kNuErrInternal; + goto bail; + } + } + + /* + * Put all the goodies into a new FileAddData object, and add it to + * the end of the list. + */ + FileAddData* pAddData; + pAddData = new FileAddData(pDetails, fsNormalBuf); + if (pAddData == nil) { + nuerr = kNuErrMalloc; + goto bail; + } + + WMSG1("FSNormalized is '%s'\n", pAddData->GetFSNormalPath()); + + AddToAddDataList(pAddData); + +bail: + delete[] fsNormalBuf; + return nuerr; +} + +/* + * A file we're adding clashes with an existing file. Decide what to do + * about it. + * + * Returns one of the following: + * kNuOverwrite - overwrite the existing file + * kNuSkip - skip adding the existing file + * kNuRename - user wants to rename the file + * kNuAbort - cancel out of the entire add process + * + * Side effects: + * Sets fOverwriteExisting and fOverwriteNoAsk if a "to all" button is hit + * Replaces pDetails->storageName if the user elects to rename + */ +NuResult +DiskArchive::HandleReplaceExisting(const A2File* pExisting, + FileDetails* pDetails) +{ + NuResult result; + + if (fOverwriteNoAsk) { + if (fOverwriteExisting) + return kNuOverwrite; + else + return kNuSkip; + } + + ConfirmOverwriteDialog confOvwr; + + confOvwr.fExistingFile = pExisting->GetPathName(); + confOvwr.fExistingFileModWhen = pExisting->GetModWhen(); + + PathName srcPath(pDetails->origName); + confOvwr.fNewFileSource = pDetails->origName; // or storageName? + confOvwr.fNewFileModWhen = srcPath.GetModWhen(); + + if (confOvwr.DoModal() == IDCANCEL) { + WMSG0("User cancelled out of add-to-diskimg replace-existing\n"); + return kNuAbort; + } + + if (confOvwr.fResultRename) { + /* + * Replace the name in FileDetails. They were asked to modify + * the already-normalized version of the filename. We will run + * it back through the FS-specific normalizer, which will handle + * any oddities they type in. + * + * We don't want to run it through PathProposal.LocalToArchive + * because that'll strip out ':' in the pathnames. + * + * Ideally the rename dialog would have a way to validate the + * full path and reject "OK" if it's not valid. Instead, we just + * allow the FS normalizer to force the filename to be valid. + */ + pDetails->storageName = confOvwr.fExistingFile; + WMSG1("Trying rename to '%s'\n", pDetails->storageName); + return kNuRename; + } + + if (confOvwr.fResultApplyToAll) { + fOverwriteNoAsk = true; + if (confOvwr.fResultOverwrite) + fOverwriteExisting = true; + else + fOverwriteExisting = false; + } + if (confOvwr.fResultOverwrite) + result = kNuOverwrite; + else + result = kNuSkip; + + return result; +} + + +/* + * Process the list of pending file adds. + * + * This is where the rubber (finally!) meets the road. + */ +CString +DiskArchive::ProcessFileAddData(DiskFS* pDiskFS, int addOptsConvEOL) +{ + CString errMsg; + FileAddData* pData; + unsigned char* dataBuf = nil; + unsigned char* rsrcBuf = nil; + long dataLen, rsrcLen; + MainWindow* pMainWin = (MainWindow*)::AfxGetMainWnd(); + + WMSG0("--- ProcessFileAddData\n"); + + /* map the EOL conversion to something we can use */ + GenericEntry::ConvertEOL convEOL; + + switch (addOptsConvEOL) { + case AddFilesDialog::kConvEOLNone: + convEOL = GenericEntry::kConvertEOLOff; + break; + case AddFilesDialog::kConvEOLType: + // will be adjusted each time through the loop + convEOL = GenericEntry::kConvertEOLOff; + break; + case AddFilesDialog::kConvEOLAuto: + convEOL = GenericEntry::kConvertEOLAuto; + break; + case AddFilesDialog::kConvEOLAll: + convEOL = GenericEntry::kConvertEOLOn; + break; + default: + assert(false); + convEOL = GenericEntry::kConvertEOLOff; + break; + } + + + pData = fpAddDataHead; + while (pData != nil) { + const FileDetails* pDataDetails = nil; + const FileDetails* pRsrcDetails = nil; + const FileDetails* pDetails = pData->GetDetails(); + const char* typeStr = "????"; + + switch (pDetails->entryKind) { + case FileDetails::kFileKindDataFork: + pDataDetails = pDetails; + typeStr = "data"; + break; + case FileDetails::kFileKindRsrcFork: + pRsrcDetails = pDetails; + typeStr = "rsrc"; + break; + case FileDetails::kFileKindDiskImage: + pDataDetails = pDetails; + typeStr = "disk"; + break; + case FileDetails::kFileKindBothForks: + case FileDetails::kFileKindDirectory: + default: + assert(false); + return "internal error"; + } + + if (pData->GetOtherFork() != nil) { + pDetails = pData->GetOtherFork()->GetDetails(); + typeStr = "both"; + + switch (pDetails->entryKind) { + case FileDetails::kFileKindDataFork: + assert(pDataDetails == nil); + pDataDetails = pDetails; + break; + case FileDetails::kFileKindRsrcFork: + assert(pRsrcDetails == nil); + pRsrcDetails = pDetails; + break; + case FileDetails::kFileKindDiskImage: + assert(false); + return "(internal) add other disk error"; + case FileDetails::kFileKindBothForks: + case FileDetails::kFileKindDirectory: + default: + assert(false); + return "internal error"; + } + } + + WMSG2("Adding file '%s' (%s)\n", + pDetails->storageName, typeStr); + ASSERT(pDataDetails != nil || pRsrcDetails != nil); + + /* + * The current implementation of DiskImg/DiskFS requires writing each + * fork in one shot. This means loading the entire thing into + * memory. Not so bad for ProDOS, with its 16MB maximum file size, + * but it could be awkward for HFS (not to mention HFS Plus!). + */ + DiskFS::CreateParms parms; + ConvertFDToCP(pData->GetDetails(), &parms); + if (pRsrcDetails != nil) + parms.storageType = kNuStorageExtended; + else + parms.storageType = kNuStorageSeedling; + /* use the FS-normalized path here */ + parms.pathName = pData->GetFSNormalPath(); + + dataLen = rsrcLen = -1; + if (pDataDetails != nil) { + /* figure out text conversion, including high ASCII for DOS */ + /* (HA conversion only happens if text conversion happens) */ + GenericEntry::ConvertHighASCII convHA; + if (addOptsConvEOL == AddFilesDialog::kConvEOLType) { + if (pDataDetails->fileType == kFileTypeTXT || + pDataDetails->fileType == kFileTypeSRC) + { + WMSG0("Enabling text conversion by type\n"); + convEOL = GenericEntry::kConvertEOLOn; + } else { + convEOL = GenericEntry::kConvertEOLOff; + } + } + if (DiskImg::UsesDOSFileStructure(pDiskFS->GetDiskImg()->GetFSFormat())) + convHA = GenericEntry::kConvertHAOn; + else + convHA = GenericEntry::kConvertHAOff; + + errMsg = LoadFile(pDataDetails->origName, &dataBuf, &dataLen, + convEOL, convHA); + if (!errMsg.IsEmpty()) + goto bail; + } + if (pRsrcDetails != nil) { + /* no text conversion on resource forks */ + errMsg = LoadFile(pRsrcDetails->origName, &rsrcBuf, &rsrcLen, + GenericEntry::kConvertEOLOff, GenericEntry::kConvertHAOff); + if (!errMsg.IsEmpty()) + goto bail; + } + + /* really ought to do this separately for each thread */ + SET_PROGRESS_BEGIN(); + SET_PROGRESS_UPDATE2(0, pDetails->origName, + parms.pathName); + + DIError dierr; + dierr = AddForksToDisk(pDiskFS, &parms, dataBuf, dataLen, + rsrcBuf, rsrcLen); + SET_PROGRESS_END(); + if (dierr != kDIErrNone) { + errMsg.Format("Unable to add '%s' to image: %s.", + parms.pathName, DiskImgLib::DIStrError(dierr)); + goto bail; + } + delete[] dataBuf; + delete[] rsrcBuf; + dataBuf = rsrcBuf = nil; + + pData = pData->GetNext(); + } + +bail: + delete[] dataBuf; + delete[] rsrcBuf; + return errMsg; +} + +#define kCharLF '\n' +#define kCharCR '\r' + +/* + * Load a file into a buffer, possibly converting EOL markers and setting + * "high ASCII" along the way. + * + * Returns a pointer to a newly-allocated buffer (new[]) and the data length. + * If the file is empty, no buffer will be allocated. + * + * Returns an empty string on success, or an error message on failure. + * + * HEY: really ought to update the progress counter, especially when reading + * really large files. + */ +CString +DiskArchive::LoadFile(const char* pathName, unsigned char** pBuf, long* pLen, + GenericEntry::ConvertEOL conv, GenericEntry::ConvertHighASCII convHA) const +{ + CString errMsg; + FILE* fp; + long fileLen; + + ASSERT(convHA == GenericEntry::kConvertHAOn || + convHA == GenericEntry::kConvertHAOff); + ASSERT(conv == GenericEntry::kConvertEOLOn || + conv == GenericEntry::kConvertEOLOff || + conv == GenericEntry::kConvertEOLAuto); + ASSERT(pathName != nil); + ASSERT(pBuf != nil); + ASSERT(pLen != nil); + + fp = fopen(pathName, "rb"); + if (fp == nil) { + errMsg.Format("Unable to open '%s': %s.", pathName, + strerror(errno)); + goto bail; + } + + if (fseek(fp, 0, SEEK_END) != 0) { + errMsg.Format("Unable to seek to end of '%s': %s", pathName, + strerror(errno)); + goto bail; + } + fileLen = ftell(fp); + if (fileLen < 0) { + errMsg.Format("Unable to determine length of '%s': %s", pathName, + strerror(errno)); + goto bail; + } + rewind(fp); + + if (fileLen == 0) { // handle zero-length files + *pBuf = nil; + *pLen = 0; + goto bail; + } else if (fileLen > 0x00ffffff) { + errMsg = "Cannot add files larger than 16MB to a disk image."; + goto bail; + } + + *pBuf = new unsigned char[fileLen]; + if (*pBuf == nil) { + errMsg.Format("Unable to allocate %ld bytes for '%s'.", + fileLen, pathName); + goto bail; + } + + /* + * We're ready to load the file. We need to sort out EOL conversion. + * Since we always convert to CR, we know the file will stay the same + * size or get smaller, which means the buffer we've allocated is + * guaranteed to hold the file even if we convert it. + * + * If the text mode is "auto", we need to load a piece of the file and + * analyze it. + */ + if (conv == GenericEntry::kConvertEOLAuto) { + GenericEntry::EOLType eolType; + GenericEntry::ConvertHighASCII dummy; + + int chunkLen = 16384; // nice big chunk + if (chunkLen > fileLen) + chunkLen = fileLen; + + if (fread(*pBuf, chunkLen, 1, fp) != 1) { + errMsg.Format("Unable to read initial chunk of '%s': %s.", + pathName, strerror(errno)); + delete[] *pBuf; + *pBuf = nil; + goto bail; + } + rewind(fp); + + conv = GenericEntry::DetermineConversion(*pBuf, chunkLen, + &eolType, &dummy); + WMSG2("LoadFile DetermineConv returned conv=%d eolType=%d\n", + conv, eolType); + if (conv == GenericEntry::kConvertEOLOn && + eolType == GenericEntry::kEOLCR) + { + WMSG0(" (skipping conversion due to matching eolType)\n"); + conv = GenericEntry::kConvertEOLOff; + } + } + ASSERT(conv != GenericEntry::kConvertEOLAuto); + + /* + * The "high ASCII" conversion is either on or off. In this context, + * "on" means "convert all text files", and "off" means "don't convert + * text files". We never convert non-text files. Conversion should + * always be "on" for DOS 3.2/3.3, and "off" for everything else (except + * RDOS, should we choose to make that writeable). + */ + if (conv == GenericEntry::kConvertEOLOff) { + /* fast path */ + WMSG1(" +++ NOT converting text '%s'\n", pathName); + if (fread(*pBuf, fileLen, 1, fp) != 1) { + errMsg.Format("Unable to read '%s': %s.", pathName, strerror(errno)); + delete[] *pBuf; + *pBuf = nil; + goto bail; + } + } else { + /* + * Convert as we go. + * + * Observation: if we copy a binary file to a DOS disk, and force + * the text conversion, we will convert 0x0a to 0x0d, and thence + * to 0x8d. However, we may still have some 0x8a bytes lying around, + * because we don't convert 0x8a in the original file to anything. + * This means that a CR->CRLF or LF->CRLF conversion can't be + * "undone" on a DOS disk. (Not that anyone cares.) + */ + long count = fileLen; + int mask, ic; + bool lastCR = false; + unsigned char* buf = *pBuf; + + if (convHA == GenericEntry::kConvertHAOn) + mask = 0x80; + else + mask = 0x00; + + WMSG2(" +++ Converting text '%s', mask=0x%02x\n", pathName, mask); + + while (count--) { + ic = getc(fp); + + if (ic == kCharCR) { + *buf++ = (unsigned char) (kCharCR | mask); + lastCR = true; + } else if (ic == kCharLF) { + if (!lastCR) + *buf++ = (unsigned char) (kCharCR | mask); + lastCR = false; + } else { + if (ic == '\0') + *buf++ = (unsigned char) ic; // don't conv 0x00 + else + *buf++ = (unsigned char) (ic | mask); + lastCR = false; + } + } + fileLen = buf - *pBuf; + } + + (void) fclose(fp); + + *pLen = fileLen; + +bail: + return errMsg; +} + +/* + * Add a file with the supplied data to the disk image. + * + * Forks that exist but are empty have a length of zero. Forks that don't + * exist have a length of -1. + * + * Called by XferFile and ProcessFileAddData. + */ +DIError +DiskArchive::AddForksToDisk(DiskFS* pDiskFS, const DiskFS::CreateParms* pParms, + const unsigned char* dataBuf, long dataLen, + const unsigned char* rsrcBuf, long rsrcLen) const +{ + DIError dierr = kDIErrNone; + CString replacementFileName; + const int kFileTypeBIN = 0x06; + const int kFileTypeINT = 0xfa; + const int kFileTypeBAS = 0xfc; + A2File* pNewFile = nil; + A2FileDescr* pOpenFile = nil; + DiskFS::CreateParms parmCopy; + + /* + * Make a temporary copy, pointers and all, so we can rewrite some of + * the fields. This is sort of bad, because we're making copies of a + * const char* filename pointer whose underlying storage we're not + * really familiar with. However, so long as we don't try to retain + * it after this function returns we should be fine. + * + * Might be better to make CreateParms a class instead of a struct, + * make the pathName field new[] storage, and write a copy constructor + * for the operation below. This will be fine for now. + */ + memcpy(&parmCopy, pParms, sizeof(parmCopy)); + + if (rsrcLen >= 0) { + ASSERT(parmCopy.storageType == kNuStorageExtended); + } + + /* + * Look for "empty directory holders" that we put into NuFX archives + * when doing disk-to-archive conversions. These make no sense if + * there's no fssep (because it's coming from DOS), or if there's no + * base path, so we can ignore those cases. We can also ignore it if + * the file is forked or is already a directory. + */ + if (parmCopy.fssep != '\0' && parmCopy.storageType == kNuStorageSeedling) { + const char* cp; + cp = strrchr(parmCopy.pathName, parmCopy.fssep); + if (cp != nil) { + if (strcmp(cp+1, kEmptyFolderMarker) == 0 && dataLen == 0) { + /* drop the junk on the end */ + parmCopy.storageType = kNuStorageDirectory; + replacementFileName = parmCopy.pathName; + replacementFileName = + replacementFileName.Left(cp - parmCopy.pathName -1); + parmCopy.pathName = replacementFileName; + parmCopy.fileType = 0x0f; // DIR + parmCopy.access &= ~(A2FileProDOS::kAccessInvisible); + dataLen = -1; + } + } + } + + /* + * If this is a subdir create request (from the clipboard or an "empty + * directory placeholder" in a NuFX archive), handle it here. If we're + * on a filesystem that doesn't have subdirectories, just skip it. + */ + if (parmCopy.storageType == kNuStorageDirectory) { + A2File* pDummyFile; + ASSERT(dataLen < 0 && rsrcLen < 0); + + if (DiskImg::IsHierarchical(pDiskFS->GetDiskImg()->GetFSFormat())) { + dierr = pDiskFS->CreateFile(&parmCopy, &pDummyFile); + if (dierr == kDIErrDirectoryExists) + dierr = kDIErrNone; // dirs are not made unique + goto bail; + } else { + WMSG0(" Ignoring subdir create req on non-hierarchic FS\n"); + goto bail; + } + } + + /* don't try to put resource forks onto a DOS disk */ + if (!DiskImg::HasResourceForks(pDiskFS->GetDiskImg()->GetFSFormat())) { + if (rsrcLen >= 0) { + rsrcLen = -1; + parmCopy.storageType = kNuStorageSeedling; + + if (dataLen < 0) { + /* this was a resource-fork-only file */ + WMSG1("--- nothing left to write for '%s'\n", + parmCopy.pathName); + goto bail; + } + } else { + ASSERT(parmCopy.storageType == kNuStorageSeedling); + } + } + + /* quick kluge to get the right file type on large DOS files */ + if (DiskImg::UsesDOSFileStructure(pDiskFS->GetDiskImg()->GetFSFormat()) && + dataLen >= 65536) + { + if (parmCopy.fileType == kFileTypeBIN || + parmCopy.fileType == kFileTypeINT || + parmCopy.fileType == kFileTypeBAS) + { + WMSG0("+++ switching DOS file type to $f2\n"); + parmCopy.fileType = 0xf2; // DOS 'S' file + } + } + + /* + * Create the file on the disk. The storage type determines whether + * it has data+rsrc forks or just data (there's no such thing in + * ProDOS as "just a resource fork"). There's no need to open the + * fork if we're not going to write to it. + * + * This holds for resource forks as well, because the storage type + * determines whether or not the file is forked, and we've asserted + * that a file with a non-(-1) rsrcLen is forked. + */ + dierr = pDiskFS->CreateFile(&parmCopy, &pNewFile); + if (dierr != kDIErrNone) { + WMSG1(" CreateFile failed: %s\n", DiskImgLib::DIStrError(dierr)); + goto bail; + } + + /* + * Note: if this was an empty directory holder, pNewFile will be set + * to nil. We used to avoid handling this by just not opening the file + * if it had a length of zero. However, DOS 3.3 needs to write some + * kinds of zero-length files, because e.g. a zero-length 'B' file + * actually has 4 bytes of data in it. + * + * Of course, if dataLen is zero then dataBuf is nil, so we need to + * supply a dummy write buffer. None of this is an issue for resource + * forks, because DOS 3.3 doesn't have those. + */ + + if (dataLen > 0 || + (dataLen == 0 && pNewFile != nil)) + { + ASSERT(pNewFile != nil); + unsigned char dummyBuf[1] = { '\0' }; + + dierr = pNewFile->Open(&pOpenFile, false, false); + if (dierr != kDIErrNone) + goto bail; + + pOpenFile->SetProgressUpdater(DiskArchive::ProgressCallback, + dataLen, nil); + + dierr = pOpenFile->Write(dataBuf != nil ? dataBuf : dummyBuf, dataLen); + if (dierr != kDIErrNone) + goto bail; + + dierr = pOpenFile->Close(); + if (dierr != kDIErrNone) + goto bail; + pOpenFile = nil; + } + + if (rsrcLen > 0) { + ASSERT(pNewFile != nil); + + dierr = pNewFile->Open(&pOpenFile, false, true); + if (dierr != kDIErrNone) + goto bail; + + pOpenFile->SetProgressUpdater(DiskArchive::ProgressCallback, + rsrcLen, nil); + + dierr = pOpenFile->Write(rsrcBuf, rsrcLen); + if (dierr != kDIErrNone) + goto bail; + + dierr = pOpenFile->Close(); + if (dierr != kDIErrNone) + goto bail; + pOpenFile = nil; + } + +bail: + if (pOpenFile != nil) + pOpenFile->Close(); + if (dierr != kDIErrNone && pNewFile != nil) { + /* + * Clean up the partially-written file. This does not, of course, + * erase any subdirectories that were created to contain this file. + * Not worth worrying about. + */ + WMSG1(" Deleting newly-created file '%s'\n", parmCopy.pathName); + (void) pDiskFS->DeleteFile(pNewFile); + } + return dierr; +} + +/* + * Fill out a CreateParms structure from a FileDetails structure. + * + * The NuStorageType values correspond exactly to ProDOS storage types, so + * there's no need to convert them. + */ +void +DiskArchive::ConvertFDToCP(const FileDetails* pDetails, + DiskFS::CreateParms* pCreateParms) +{ + pCreateParms->pathName = pDetails->storageName; + pCreateParms->fssep = (char) pDetails->fileSysInfo; + pCreateParms->storageType = pDetails->storageType; + pCreateParms->fileType = pDetails->fileType; + pCreateParms->auxType = pDetails->extraType; + pCreateParms->access = pDetails->access; + pCreateParms->createWhen = NufxArchive::DateTimeToSeconds(&pDetails->createWhen); + pCreateParms->modWhen = NufxArchive::DateTimeToSeconds(&pDetails->modWhen); +} + + +/* + * Add an entry to the end of the FileAddData list. + * + * If "storeName" (the Windows filename with type goodies stripped, but + * without filesystem normalization) matches an entry already in the list, + * we check to see if these are forks of the same file. If they are + * different forks and we don't already have both forks, we put the + * pointer into the "fork pointer" of the existing file rather than adding + * it to the end of the list. + */ +void +DiskArchive::AddToAddDataList(FileAddData* pData) +{ + ASSERT(pData != nil); + ASSERT(pData->GetNext() == nil); + + /* + * Run through the entire existing list, looking for a match. This is + * O(n^2) behavior, but I'm expecting N to be relatively small (under + * 1000 in almost all cases). + */ + //if (strcasecmp(pData->GetDetails()->storageName, "system\\finder") == 0) + // WMSG0("whee\n"); + FileAddData* pSearch = fpAddDataHead; + FileDetails::FileKind dataKind, listKind; + + dataKind = pData->GetDetails()->entryKind; + while (pSearch != nil) { + if (pSearch->GetOtherFork() == nil && + strcmp(pSearch->GetDetails()->storageName, + pData->GetDetails()->storageName) == 0) + { + //NuThreadID dataID = pData->GetDetails()->threadID; + //NuThreadID listID = pSearch->GetDetails()->threadID; + + listKind = pSearch->GetDetails()->entryKind; + + /* got a name match */ + if (dataKind != listKind && + (dataKind == FileDetails::kFileKindDataFork || dataKind == FileDetails::kFileKindRsrcFork) && + (listKind == FileDetails::kFileKindDataFork || listKind == FileDetails::kFileKindRsrcFork)) + { + /* looks good, hook it in here instead of the list */ + WMSG2("--- connecting forks of '%s' and '%s'\n", + pData->GetDetails()->origName, + pSearch->GetDetails()->origName); + pSearch->SetOtherFork(pData); + return; + } + } + + pSearch = pSearch->GetNext(); + } + + if (fpAddDataHead == nil) { + assert(fpAddDataTail == nil); + fpAddDataHead = fpAddDataTail = pData; + } else { + fpAddDataTail->SetNext(pData); + fpAddDataTail = pData; + } +} + +/* + * Free all entries in the FileAddData list. + */ +void +DiskArchive::FreeAddDataList(void) +{ + FileAddData* pData; + FileAddData* pNext; + + pData = fpAddDataHead; + while (pData != nil) { + pNext = pData->GetNext(); + delete pData->GetOtherFork(); + delete pData; + pData = pNext; + } + + fpAddDataHead = fpAddDataTail = nil; +} + + +/* + * =========================================================================== + * DiskArchive -- create subdir + * =========================================================================== + */ + +/* + * Create a subdirectory named "newName" in "pParentEntry". + */ +bool +DiskArchive::CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry, + const char* newName) +{ + ASSERT(newName != nil && strlen(newName) > 0); + DiskEntry* pEntry = (DiskEntry*) pParentEntry; + ASSERT(pEntry != nil); + A2File* pFile = pEntry->GetA2File(); + ASSERT(pFile != nil); + DiskFS* pDiskFS = pFile->GetDiskFS(); + ASSERT(pDiskFS != nil); + + if (!pFile->IsDirectory()) { + ASSERT(false); + return false; + } + + DIError dierr; + A2File* pNewFile = nil; + DiskFS::CreateParms parms; + CString pathName; + time_t now = time(nil); + + /* + * Create the full path. + */ + if (pFile->IsVolumeDirectory()) { + pathName = newName; + } else { + pathName = pParentEntry->GetPathName(); + pathName += pParentEntry->GetFssep(); + pathName += newName; + } + ASSERT(strchr(newName, pParentEntry->GetFssep()) == nil); + + /* using NufxLib constants; they match with ProDOS */ + memset(&parms, 0, sizeof(parms)); + parms.pathName = pathName; + parms.fssep = pParentEntry->GetFssep(); + parms.storageType = kNuStorageDirectory; + parms.fileType = 0x0f; // ProDOS DIR + parms.auxType = 0; + parms.access = kNuAccessUnlocked; + parms.createWhen = now; + parms.modWhen = now; + + dierr = pDiskFS->CreateFile(&parms, &pNewFile); + if (dierr != kDIErrNone) { + CString errMsg; + errMsg.Format("Unable to create subdirectory: %s.\n", + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + return false; + } + + if (InternalReload(pMsgWnd) != 0) + return false; + + return true; +} + + +/* + * =========================================================================== + * DiskArchive -- delete selection + * =========================================================================== + */ + +/* + * Compare DiskEntry display names in descending order (Z-A). + */ +/*static*/ int +DiskArchive::CompareDisplayNamesDesc(const void* ventry1, const void* ventry2) +{ + const DiskEntry* pEntry1 = *((const DiskEntry**) ventry1); + const DiskEntry* pEntry2 = *((const DiskEntry**) ventry2); + + return strcasecmp(pEntry2->GetDisplayName(), pEntry1->GetDisplayName()); +} + +/* + * Delete the records listed in the selection set. + * + * The DiskFS DeleteFile() function will not delete a subdirectory unless + * it is empty. This complicates matters somewhat for us, because the + * selection set isn't in any particular order. We need to sort on the + * pathname and then delete bottom-up. + * + * CiderPress does work to ensure that, if a subdir is selected, everything + * in that subdir is also selected. So if we just delete everything in the + * right order, we should be okay. + */ +bool +DiskArchive::DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) +{ + CString errMsg; + SelectionEntry* pSelEntry; + DiskEntry* pEntry; + DIError dierr; + bool retVal = false; + + SET_PROGRESS_BEGIN(); + + /* + * Start by copying the DiskEntry pointers out of the selection set and + * into an array. The selection set was created such that there is one + * entry in the set for each file. (The file viewer likes to have one + * entry for each thread.) + */ + int numEntries = pSelSet->GetNumEntries(); + ASSERT(numEntries > 0); + DiskEntry** entryArray = new DiskEntry*[numEntries]; + int idx = 0; + + pSelEntry = pSelSet->IterNext(); + while (pSelEntry != nil) { + pEntry = (DiskEntry*) pSelEntry->GetEntry(); + ASSERT(pEntry != nil); + + entryArray[idx++] = pEntry; + WMSG2("Added 0x%08lx '%s'\n", (long) entryArray[idx-1], + entryArray[idx-1]->GetDisplayName()); + + pSelEntry = pSelSet->IterNext(); + } + ASSERT(idx == numEntries); + + /* + * Sort the file array by descending filename. + */ + ::qsort(entryArray, numEntries, sizeof(DiskEntry*), CompareDisplayNamesDesc); + + /* + * Run through the sorted list, deleting each entry. + */ + for (idx = 0; idx < numEntries; idx++) { + A2File* pFile; + + pEntry = entryArray[idx]; + pFile = pEntry->GetA2File(); + + /* + * We shouldn't be here at all if the main volume were opened + * read-only. However, it's possible that the main is read-write + * and our sub-volumes are read-only (probably because we don't + * support write access to the filesystem). + */ + if (!pFile->GetDiskFS()->GetReadWriteSupported()) { + errMsg.Format("Unable to delete '%s' on '%s': operation not supported.", + pEntry->GetDisplayName(), pFile->GetDiskFS()->GetVolumeName()); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + + WMSG2(" Deleting '%s' from '%s'\n", pEntry->GetPathName(), + pFile->GetDiskFS()->GetVolumeName()); + SET_PROGRESS_UPDATE2(0, pEntry->GetPathName(), nil); + + /* + * Ask the DiskFS to delete the file. As soon as this completes, + * "pFile" is invalid and must not be dereferenced. + */ + dierr = pFile->GetDiskFS()->DeleteFile(pFile); + if (dierr != kDIErrNone) { + errMsg.Format("Unable to delete '%s' on '%s': %s.", + pEntry->GetDisplayName(), pFile->GetDiskFS()->GetVolumeName(), + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + SET_PROGRESS_UPDATE(100); + + /* + * Be paranoid and zap the pointer, on the off chance somebody + * tries to redraw the content list from the deleted data. + * + * In practice we don't work this way -- the stuff that gets drawn + * on the screen comes out of GenericEntry, not A2File. If this + * changes we'll need to raise the "reload" flag here, before the + * reload, to prevent the ContentList from chasing a bad pointer. + */ + pEntry->SetA2File(nil); + } + + retVal = true; + +bail: + SET_PROGRESS_END(); + delete[] entryArray; + if (InternalReload(pMsgWnd) != 0) + retVal = false; + + return retVal; +} + +/* + * =========================================================================== + * DiskArchive -- rename files + * =========================================================================== + */ + + /* + * Rename a set of files, one at a time. + * + * If we rename a subdirectory, it could affect the next thing we try to + * rename (because we show the full path). We have to reload our file + * list from the DiskFS after each renamed subdir. The trouble is that + * this invalidates the data displayed in the ContentList, and we won't + * redraw the screen correctly. We can work around the problem by getting + * the pathname directly from the DiskFS instead of from DiskEntry, though + * it's not immediately obvious which is less confusing. + */ +bool +DiskArchive::RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) +{ + CString errMsg; + bool retVal = false; + + WMSG1("Renaming %d entries\n", pSelSet->GetNumEntries()); + + /* + * For each item in the selection set, bring up the "rename" dialog, + * and ask the GenericEntry to process it. + * + * If they hit "cancel" or there's an error, we still flush the + * previous changes. This is so that we don't have to create the + * same sort of deferred-write feature when renaming things in other + * sorts of archives (e.g. disk archives). + */ + SelectionEntry* pSelEntry = pSelSet->IterNext(); + while (pSelEntry != nil) { + RenameEntryDialog renameDlg(pMsgWnd); + DiskEntry* pEntry = (DiskEntry*) pSelEntry->GetEntry(); + + WMSG1(" Renaming '%s'\n", pEntry->GetPathName()); + if (!SetRenameFields(pMsgWnd, pEntry, &renameDlg)) + break; + + int result; + if (pEntry->GetA2File()->IsVolumeDirectory()) + result = IDIGNORE; // don't allow rename of volume dir + else + result = renameDlg.DoModal(); + if (result == IDOK) { + DIError dierr; + DiskFS* pDiskFS; + A2File* pFile; + + pFile = pEntry->GetA2File(); + pDiskFS = pFile->GetDiskFS(); + dierr = pDiskFS->RenameFile(pFile, renameDlg.fNewName); + if (dierr != kDIErrNone) { + errMsg.Format("Unable to rename '%s' to '%s': %s.", + pEntry->GetPathName(), renameDlg.fNewName, + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + WMSG2("Rename of '%s' to '%s' succeeded\n", + pEntry->GetDisplayName(), renameDlg.fNewName); + } else if (result == IDCANCEL) { + WMSG0("Canceling out of remaining renames\n"); + break; + } else { + /* 3rd possibility is IDIGNORE, i.e. skip this entry */ + WMSG1("Skipping rename of '%s'\n", pEntry->GetDisplayName()); + } + + pSelEntry = pSelSet->IterNext(); + } + + /* reload GenericArchive from disk image */ + if (InternalReload(pMsgWnd) == kNuErrNone) + retVal = true; + +bail: + return retVal; +} + +/* + * Set up a RenameEntryDialog for the entry in "*pEntry". + * + * Returns "true" on success, "false" on failure. + */ +bool +DiskArchive::SetRenameFields(CWnd* pMsgWnd, DiskEntry* pEntry, + RenameEntryDialog* pDialog) +{ + DiskFS* pDiskFS; + + ASSERT(pEntry != nil); + + /* + * Figure out if we're allowed to change the entire path. (This is + * doing it the hard way, but what the hell.) + */ + long cap = GetCapability(GenericArchive::kCapCanRenameFullPath); + bool renameFullPath = (cap != 0); + + // a bit round-about, but it works + pDiskFS = pEntry->GetA2File()->GetDiskFS(); + + /* + * Make sure rename is allowed. It's nice to do these *before* putting + * up the rename dialog, so that the user doesn't do a bunch of typing + * before being told that it's pointless. + */ + if (!pDiskFS->GetReadWriteSupported()) { + CString errMsg; + errMsg.Format("Unable to rename '%s': operation not supported.", + pEntry->GetPathName()); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + return false; + } + if (pDiskFS->GetFSDamaged()) { + CString errMsg; + errMsg.Format("Unable to rename '%s': the disk it's on appears to be damaged.", + pEntry->GetPathName()); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + return false; + } + + pDialog->SetCanRenameFullPath(renameFullPath); + pDialog->fOldName = pEntry->GetPathName(); + pDialog->fFssep = pEntry->GetFssep(); + pDialog->fpArchive = this; + pDialog->fpEntry = pEntry; + + return true; +} + +/* + * Verify that the a name is suitable. Called by RenameEntryDialog and + * CreateSubdirDialog. + * + * Tests for context-specific syntax and checks for duplicates. + * + * Returns an empty string on success, or an error message on failure. + */ +CString +DiskArchive::TestPathName(const GenericEntry* pGenericEntry, + const CString& basePath, const CString& newName, char newFssep) const +{ + const DiskEntry* pEntry = (DiskEntry*) pGenericEntry; + DiskImg::FSFormat format; + CString pathName, errMsg; + DiskFS* pDiskFS; + + if (basePath.IsEmpty()) { + pathName = newName; + } else { + pathName = basePath; + pathName += newFssep; + pathName += newName; + } + + pDiskFS = pEntry->GetA2File()->GetDiskFS(); + format = pDiskFS->GetDiskImg()->GetFSFormat(); + + /* look for an existing file, but don't compare against self */ + A2File* existingFile; + existingFile = pDiskFS->GetFileByName(pathName); + if (existingFile != nil && existingFile != pEntry->GetA2File()) { + errMsg = "A file with that name already exists."; + goto bail; + } + + switch (format) { + case DiskImg::kFormatProDOS: + if (!DiskFSProDOS::IsValidFileName(newName)) + errMsg.LoadString(IDS_VALID_FILENAME_PRODOS); + break; + case DiskImg::kFormatDOS33: + case DiskImg::kFormatDOS32: + if (!DiskFSDOS33::IsValidFileName(newName)) + errMsg.LoadString(IDS_VALID_FILENAME_DOS); + break; + case DiskImg::kFormatPascal: + if (!DiskFSPascal::IsValidFileName(newName)) + errMsg.LoadString(IDS_VALID_FILENAME_PASCAL); + break; + case DiskImg::kFormatMacHFS: + if (!DiskFSHFS::IsValidFileName(newName)) + errMsg.LoadString(IDS_VALID_FILENAME_HFS); + break; + default: + errMsg = "Not supported by TestPathName!"; + } + +bail: + return errMsg; +} + + +/* + * =========================================================================== + * DiskArchive -- rename a volume + * =========================================================================== + */ + +/* + * Ask a DiskFS to change its volume name. + * + * Returns "true" on success, "false" on failure. + */ +bool +DiskArchive::RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS, + const char* newName) +{ + DIError dierr; + CString errMsg; + bool retVal = true; + + dierr = pDiskFS->RenameVolume(newName); + if (dierr != kDIErrNone) { + errMsg.Format("Unable to rename volume: %s.\n", + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + retVal = false; + /* fall through to reload anyway */ + } + + /* reload GenericArchive from disk image */ + if (InternalReload(pMsgWnd) != 0) + retVal = false; + + return retVal; +} + +/* + * Test a volume name for validity. + */ +CString +DiskArchive::TestVolumeName(const DiskFS* pDiskFS, + const char* newName) const +{ + DiskImg::FSFormat format; + CString errMsg; + + ASSERT(pDiskFS != nil); + ASSERT(newName != nil); + + format = pDiskFS->GetDiskImg()->GetFSFormat(); + + switch (format) { + case DiskImg::kFormatProDOS: + if (!DiskFSProDOS::IsValidVolumeName(newName)) + errMsg.LoadString(IDS_VALID_VOLNAME_PRODOS); + break; + case DiskImg::kFormatDOS33: + case DiskImg::kFormatDOS32: + if (!DiskFSDOS33::IsValidVolumeName(newName)) + errMsg.LoadString(IDS_VALID_VOLNAME_DOS); + break; + case DiskImg::kFormatPascal: + if (!DiskFSPascal::IsValidVolumeName(newName)) + errMsg.LoadString(IDS_VALID_VOLNAME_PASCAL); + break; + case DiskImg::kFormatMacHFS: + if (!DiskFSHFS::IsValidVolumeName(newName)) + errMsg.LoadString(IDS_VALID_VOLNAME_HFS); + break; + default: + errMsg = "Not supported by TestVolumeName!"; + } + + return errMsg; +} + + +/* + * =========================================================================== + * DiskArchive -- set file properties + * =========================================================================== + */ + +/* + * Set the properties of "pEntry" to what's in "pProps". + * + * [currently only supports file type, aux type, and access flags] + * + * Technically we should reload the GenericArchive from the NufxArchive, + * but the set of changes is pretty small, so we just make them here. + */ +bool +DiskArchive::SetProps(CWnd* pMsgWnd, GenericEntry* pGenericEntry, + const FileProps* pProps) +{ + DIError dierr; + DiskEntry* pEntry = (DiskEntry*) pGenericEntry; + A2File* pFile = pEntry->GetA2File(); + + dierr = pFile->GetDiskFS()->SetFileInfo(pFile, pProps->fileType, + pProps->auxType, pProps->access); + if (dierr != kDIErrNone) { + CString errMsg; + errMsg.Format("Unable to set file info: %s.\n", + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + return false; + } + + /* do this in lieu of reloading GenericArchive */ + pEntry->SetFileType(pFile->GetFileType()); + pEntry->SetAuxType(pFile->GetAuxType()); + pEntry->SetAccess(pFile->GetAccess()); + + /* DOS 3.2/3.3 may change these as well */ + DiskImg::FSFormat fsFormat; + fsFormat = pFile->GetDiskFS()->GetDiskImg()->GetFSFormat(); + if (fsFormat == DiskImg::kFormatDOS32 || fsFormat == DiskImg::kFormatDOS33) { + WMSG0(" (reloading additional fields after DOS SFI)\n"); + pEntry->SetDataForkLen(pFile->GetDataLength()); + pEntry->SetCompressedLen(pFile->GetDataSparseLength()); + pEntry->SetSuspicious(pFile->GetQuality() == A2File::kQualitySuspicious); + } + + /* clear the dirty flag in trivial cases */ + (void) fpPrimaryDiskFS->Flush(DiskImg::kFlushFastOnly); + + return true; +} + + +/* + * =========================================================================== + * DiskArchive -- transfer files to another archive + * =========================================================================== + */ + +/* + * Transfer the selected files out of this archive and into another. + * + * In this case, it's files on a disk (with unspecified filesystem) to a NuFX + * archive. We get the open archive pointer and some options from "pXferOpts". + * + * The selection set was created with the "any" selection criteria, which + * means there's only one entry for each file regardless of whether it's + * forked or not. + */ +GenericArchive::XferStatus +DiskArchive::XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, + ActionProgressDialog* pActionProgress, const XferFileOptions* pXferOpts) +{ + WMSG0("DiskArchive XferSelection!\n"); + unsigned char* dataBuf = nil; + unsigned char* rsrcBuf = nil; + FileDetails fileDetails; + CString errMsg, extractErrMsg, cmpStr; + CString fixedPathName; + XferStatus retval = kXferFailed; + + pXferOpts->fTarget->XferPrepare(pXferOpts); + + SelectionEntry* pSelEntry = pSelSet->IterNext(); + for ( ; pSelEntry != nil; pSelEntry = pSelSet->IterNext()) { + long dataLen=-1, rsrcLen=-1; + DiskEntry* pEntry = (DiskEntry*) pSelEntry->GetEntry(); + int typeOverride = -1; + int result; + + ASSERT(dataBuf == nil); + ASSERT(rsrcBuf == nil); + + if (pEntry->GetDamaged()) { + WMSG1(" XFER skipping damaged entry '%s'\n", + pEntry->GetDisplayName()); + continue; + } + + /* + * Do a quick de-colonizing pass for non-ProDOS volumes, then prepend + * the subvolume name (if any). + */ + fixedPathName = pEntry->GetPathName(); + if (fixedPathName.IsEmpty()) + fixedPathName = _T("(no filename)"); + if (pEntry->GetFSFormat() != DiskImg::kFormatProDOS) + fixedPathName.Replace(PathProposal::kDefaultStoredFssep, '.'); + if (pEntry->GetSubVolName() != nil) { + CString tmpStr; + tmpStr = pEntry->GetSubVolName(); + tmpStr += (char)PathProposal::kDefaultStoredFssep; + tmpStr += fixedPathName; + fixedPathName = tmpStr; + } + + if (pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir) { + /* this is the volume dir */ + WMSG1(" XFER not transferring volume dir '%s'\n", + fixedPathName); + continue; + } else if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory) { + if (pXferOpts->fPreserveEmptyFolders) { + /* if this is an empty directory, create a fake entry */ + cmpStr = fixedPathName; + cmpStr += (char)PathProposal::kDefaultStoredFssep; + + if (pSelSet->CountMatchingPrefix(cmpStr) == 0) { + WMSG1("FOUND empty dir '%s'\n", fixedPathName); + cmpStr += kEmptyFolderMarker; + dataBuf = new unsigned char[1]; + dataLen = 0; + fileDetails.entryKind = FileDetails::kFileKindDataFork; + fileDetails.storageName = cmpStr; + fileDetails.fileType = 0; // NON + fileDetails.access = + pEntry->GetAccess() | GenericEntry::kAccessInvisible; + goto have_stuff2; + } else { + WMSG1("NOT empty dir '%s'\n", fixedPathName); + } + } + + WMSG1(" XFER not transferring directory '%s'\n", + fixedPathName); + continue; + } + + WMSG3(" Xfer '%s' (data=%d rsrc=%d)\n", + fixedPathName, pEntry->GetHasDataFork(), + pEntry->GetHasRsrcFork()); + + dataBuf = nil; + dataLen = 0; + result = pEntry->ExtractThreadToBuffer(GenericEntry::kDataThread, + (char**) &dataBuf, &dataLen, &extractErrMsg); + if (result == IDCANCEL) { + WMSG0("Cancelled during data extract!\n"); + goto bail; /* abort anything that was pending */ + } else if (result != IDOK) { + errMsg.Format("Failed while extracting '%s': %s.", + fixedPathName, extractErrMsg); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + ASSERT(dataBuf != nil); + ASSERT(dataLen >= 0); + +#if 0 + if (pXferOpts->fConvDOSText && + DiskImg::UsesDOSFileStructure(pEntry->GetFSFormat()) && + pEntry->GetFileType() == kFileTypeTXT) + { + /* don't need to convert EOL, so just strip in place */ + long len; + unsigned char* ucp; + + WMSG1(" Converting DOS text in '%s'\n", fixedPathName); + for (ucp = dataBuf, len = dataLen; len > 0; len--, ucp++) + *ucp = *ucp & 0x7f; + } +#endif + +#if 0 // annoying to invoke PTX reformatter from here... ReformatHolder, etc. + if (pXferOpts->fConvPascalText && + pEntry->GetFSFormat() == DiskImg::kFormatPascal && + pEntry->GetFileType() == kFileTypePTX) + { + WMSG1("WOULD CONVERT ptx '%s'\n", fixedPathName); + } +#endif + + if (pEntry->GetHasRsrcFork()) { + rsrcBuf = nil; + rsrcLen = 0; + result = pEntry->ExtractThreadToBuffer(GenericEntry::kRsrcThread, + (char**) &rsrcBuf, &rsrcLen, &extractErrMsg); + if (result == IDCANCEL) { + WMSG0("Cancelled during rsrc extract!\n"); + goto bail; /* abort anything that was pending */ + } else if (result != IDOK) { + errMsg.Format("Failed while extracting '%s': %s.", + fixedPathName, extractErrMsg); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + } else { + ASSERT(rsrcBuf == nil); + } + + if (pEntry->GetHasDataFork() && pEntry->GetHasRsrcFork()) + fileDetails.entryKind = FileDetails::kFileKindBothForks; + else if (pEntry->GetHasDataFork()) + fileDetails.entryKind = FileDetails::kFileKindDataFork; + else if (pEntry->GetHasRsrcFork()) + fileDetails.entryKind = FileDetails::kFileKindRsrcFork; + else { + ASSERT(false); + fileDetails.entryKind = FileDetails::kFileKindUnknown; + } + + /* + * Set up the FileDetails. + */ + fileDetails.storageName = fixedPathName; + fileDetails.fileType = pEntry->GetFileType(); + fileDetails.access = pEntry->GetAccess(); +have_stuff2: + fileDetails.fileSysFmt = pEntry->GetSourceFS(); + fileDetails.fileSysInfo = PathProposal::kDefaultStoredFssep; + fileDetails.extraType = pEntry->GetAuxType(); + fileDetails.storageType = kNuStorageUnknown; /* let NufxLib deal */ + + time_t when; + when = time(nil); + UNIXTimeToDateTime(&when, &fileDetails.archiveWhen); + when = pEntry->GetModWhen(); + UNIXTimeToDateTime(&when, &fileDetails.modWhen); + when = pEntry->GetCreateWhen(); + UNIXTimeToDateTime(&when, &fileDetails.createWhen); + + pActionProgress->SetArcName(fileDetails.storageName); + if (pActionProgress->SetProgress(0) == IDCANCEL) { + retval = kXferCancelled; + goto bail; + } + + errMsg = pXferOpts->fTarget->XferFile(&fileDetails, &dataBuf, dataLen, + &rsrcBuf, rsrcLen); + if (!errMsg.IsEmpty()) { + WMSG0("XferFile failed!\n"); + errMsg.Format("Failed while transferring '%s': %s.", + pEntry->GetDisplayName(), (const char*) errMsg); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + ASSERT(dataBuf == nil); + ASSERT(rsrcBuf == nil); + + if (pActionProgress->SetProgress(100) == IDCANCEL) { + retval = kXferCancelled; + goto bail; + } + } + + //MainWindow* pMainWin; + //pMainWin = (MainWindow*)::AfxGetMainWnd(); + //pMainWin->EventPause(1000); + + retval = kXferOK; + +bail: + if (retval != kXferOK) + pXferOpts->fTarget->XferAbort(pMsgWnd); + else + pXferOpts->fTarget->XferFinish(pMsgWnd); + delete[] dataBuf; + delete[] rsrcBuf; + return retval; +} + +/* + * Prepare for file transfers. + */ +void +DiskArchive::XferPrepare(const XferFileOptions* pXferOpts) +{ + WMSG0("DiskArchive::XferPrepare\n"); + + //fpPrimaryDiskFS->SetParameter(DiskFS::kParmProDOS_AllowLowerCase, + // pXferOpts->fAllowLowerCase); + //fpPrimaryDiskFS->SetParameter(DiskFS::kParmProDOS_AllocSparse, + // pXferOpts->fUseSparseBlocks); + fpPrimaryDiskFS->SetParameter(DiskFS::kParm_CreateUnique, true); + + //fXferStoragePrefix = pXferOpts->fStoragePrefix; + fpXferTargetFS = pXferOpts->fpTargetFS; +} + +/* + * Transfer a file to the disk image. Called from NufxArchive's XferSelection + * and clipboard "paste". + * + * "dataLen" and "rsrcLen" will be -1 if the corresponding fork doesn't + * exist. + * + * Returns 0 on success, nonzero on failure. + * + * On success, *pDataBuf and *pRsrcBuf are freed and set to nil. (It's + * necessary for the interface to work this way because the NufxArchive + * version just tucks the pointers into NufxLib structures.) + */ +CString +DiskArchive::XferFile(FileDetails* pDetails, unsigned char** pDataBuf, + long dataLen, unsigned char** pRsrcBuf, long rsrcLen) +{ + //const int kFileTypeTXT = 0x04; + DiskFS::CreateParms createParms; + DiskFS* pDiskFS; + CString errMsg; + DIError dierr = kDIErrNone; + + WMSG3(" XFER: transfer '%s' (dataLen=%ld rsrcLen=%ld)\n", + pDetails->storageName, dataLen, rsrcLen); + + ASSERT(pDataBuf != nil); + ASSERT(pRsrcBuf != nil); + + /* fill out CreateParms from FileDetails */ + ConvertFDToCP(pDetails, &createParms); + + if (fpXferTargetFS == nil) + pDiskFS = fpPrimaryDiskFS; + else + pDiskFS = fpXferTargetFS; + + /* + * Strip the high ASCII from DOS and RDOS text files, unless we're adding + * them to a DOS disk. Likewise, if we're adding non-DOS text files to + * a DOS disk, we need to add the high bit. + * + * DOS converts both TXT and SRC to 'T', so we have to handle both here. + * Ideally we'd just ask DOS, "do you think this is a text file?", but it's + * not worth adding a new interface just for that. + */ + bool srcIsDOS, dstIsDOS; + srcIsDOS = DiskImg::UsesDOSFileStructure(pDetails->fileSysFmt); + dstIsDOS = DiskImg::UsesDOSFileStructure(pDiskFS->GetDiskImg()->GetFSFormat()); + if (dataLen > 0 && + (pDetails->fileType == kFileTypeTXT || pDetails->fileType == kFileTypeSRC)) + { + unsigned char* ucp = *pDataBuf; + long len = dataLen; + + if (srcIsDOS && !dstIsDOS) { + WMSG1(" Stripping high ASCII from '%s'\n", pDetails->storageName); + + while (len--) + *ucp++ &= 0x7f; + } else if (!srcIsDOS && dstIsDOS) { + WMSG1(" Adding high ASCII to '%s'\n", pDetails->storageName); + + while (len--) { + if (*ucp != '\0') + *ucp |= 0x80; + ucp++; + } + } else if (srcIsDOS && dstIsDOS) { + WMSG1(" --- not altering DOS-to-DOS text '%s'\n", + pDetails->storageName); + } else { + WMSG1(" --- non-DOS transfer '%s'\n", pDetails->storageName); + } + } + + /* add a file with one or two forks */ + if (createParms.storageType == kNuStorageDirectory) { + ASSERT(dataLen < 0 && rsrcLen < 0); + } else { + ASSERT(dataLen >= 0 || rsrcLen >= 0); // at least one fork + } + + /* if we still have something to write, write it */ + dierr = AddForksToDisk(pDiskFS, &createParms, *pDataBuf, dataLen, + *pRsrcBuf, rsrcLen); + if (dierr != kDIErrNone) { + errMsg.Format("%s", DiskImgLib::DIStrError(dierr)); + goto bail; + } + + /* clean up */ + delete[] *pDataBuf; + *pDataBuf = nil; + delete[] *pRsrcBuf; + *pRsrcBuf = nil; + +bail: + return errMsg; +} + + +/* + * Abort our progress. Not really possible, except by throwing the disk + * image away. + */ +void +DiskArchive::XferAbort(CWnd* pMsgWnd) +{ + WMSG0("DiskArchive::XferAbort\n"); + InternalReload(pMsgWnd); +} + +/* + * Transfer is finished. + */ +void +DiskArchive::XferFinish(CWnd* pMsgWnd) +{ + WMSG0("DiskArchive::XferFinish\n"); + InternalReload(pMsgWnd); +} diff --git a/app/DiskArchive.h b/app/DiskArchive.h index f7fc866..f3456c7 100644 --- a/app/DiskArchive.h +++ b/app/DiskArchive.h @@ -20,33 +20,33 @@ class RenameEntryDialog; */ class DiskEntry : public GenericEntry { public: - DiskEntry(A2File* pFile) : fpFile(pFile) - {} - virtual ~DiskEntry(void) {} + DiskEntry(A2File* pFile) : fpFile(pFile) + {} + virtual ~DiskEntry(void) {} - // retrieve thread data - virtual int ExtractThreadToBuffer(int which, char** ppText, long* pLength, - CString* pErrMsg) const; - virtual int ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, - ConvertHighASCII convHA, CString* pErrMsg) const; - virtual long GetSelectionSerial(void) const { return -1; } // idea: T/S block number + // retrieve thread data + virtual int ExtractThreadToBuffer(int which, char** ppText, long* pLength, + CString* pErrMsg) const; + virtual int ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, + ConvertHighASCII convHA, CString* pErrMsg) const; + virtual long GetSelectionSerial(void) const { return -1; } // idea: T/S block number - virtual bool GetFeatureFlag(Feature feature) const; + virtual bool GetFeatureFlag(Feature feature) const; - // return the underlying FS format for this file - virtual DiskImg::FSFormat GetFSFormat(void) const { - ASSERT(fpFile != nil); - return fpFile->GetFSFormat(); - } + // return the underlying FS format for this file + virtual DiskImg::FSFormat GetFSFormat(void) const { + ASSERT(fpFile != nil); + return fpFile->GetFSFormat(); + } - A2File* GetA2File(void) const { return fpFile; } - void SetA2File(A2File* pFile) { fpFile = pFile; } + A2File* GetA2File(void) const { return fpFile; } + void SetA2File(A2File* pFile) { fpFile = pFile; } private: - DIError CopyData(A2FileDescr* pOpenFile, FILE* outfp, ConvertEOL conv, - ConvertHighASCII convHA, CString* pMsg) const; + DIError CopyData(A2FileDescr* pOpenFile, FILE* outfp, ConvertEOL conv, + ConvertHighASCII convHA, CString* pMsg) const; - A2File* fpFile; + A2File* fpFile; }; @@ -55,190 +55,190 @@ private: */ class DiskArchive : public GenericArchive { public: - DiskArchive(void) : fpPrimaryDiskFS(nil), fIsReadOnly(false), - fpAddDataHead(nil), fpAddDataTail(nil) - {} - virtual ~DiskArchive(void) { (void) Close(); } + DiskArchive(void) : fpPrimaryDiskFS(nil), fIsReadOnly(false), + fpAddDataHead(nil), fpAddDataTail(nil) + {} + virtual ~DiskArchive(void) { (void) Close(); } - /* pass this as the "options" value to the New() function */ - typedef struct { - DiskImgLib::DiskImg::FSFormat format; - DiskImgLib::DiskImg::SectorOrder sectorOrder; - } NewOptionsBase; - typedef union { - NewOptionsBase base; + /* pass this as the "options" value to the New() function */ + typedef struct { + DiskImgLib::DiskImg::FSFormat format; + DiskImgLib::DiskImg::SectorOrder sectorOrder; + } NewOptionsBase; + typedef union { + NewOptionsBase base; - struct { - NewOptionsBase base; - long numBlocks; - } blank; - struct { - NewOptionsBase base; - const char* volName; - long numBlocks; - } prodos; - struct { - NewOptionsBase base; - const char* volName; - long numBlocks; - } pascalfs; // "pascal" is reserved token in MSVC++ - struct { - NewOptionsBase base; - const char* volName; - long numBlocks; - } hfs; - struct { - NewOptionsBase base; - int volumeNum; - long numTracks; - int numSectors; - bool allocDOSTracks; - } dos; - } NewOptions; + struct { + NewOptionsBase base; + long numBlocks; + } blank; + struct { + NewOptionsBase base; + const char* volName; + long numBlocks; + } prodos; + struct { + NewOptionsBase base; + const char* volName; + long numBlocks; + } pascalfs; // "pascal" is reserved token in MSVC++ + struct { + NewOptionsBase base; + const char* volName; + long numBlocks; + } hfs; + struct { + NewOptionsBase base; + int volumeNum; + long numTracks; + int numSectors; + bool allocDOSTracks; + } dos; + } NewOptions; - // One-time initialization; returns an error string. - static CString AppInit(void); - // one-time cleanup at app shutdown time - static void AppCleanup(void); + // One-time initialization; returns an error string. + static CString AppInit(void); + // one-time cleanup at app shutdown time + static void AppCleanup(void); - virtual OpenResult Open(const char* filename, bool readOnly, CString* pErrMsg); - virtual CString New(const char* filename, const void* options); - virtual CString Flush(void); - virtual CString Reload(void); - virtual bool IsReadOnly(void) const { return fIsReadOnly; }; - virtual bool IsModified(void) const; - virtual void GetDescription(CString* pStr) const; - virtual bool BulkAdd(ActionProgressDialog* pActionProgress, - const AddFilesDialog* pAddOpts); - virtual bool AddDisk(ActionProgressDialog* pActionProgress, - const AddFilesDialog* pAddOpts) - { ASSERT(false); return false; } - virtual bool CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry, - const char* newName); - virtual bool TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) - { ASSERT(false); return false; } - virtual bool DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); - virtual bool RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); - virtual CString TestPathName(const GenericEntry* pGenericEntry, - const CString& basePath, const CString& newName, char newFssep) const; - virtual bool RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS, - const char* newName); - virtual CString TestVolumeName(const DiskFS* pDiskFS, - const char* newName) const; - virtual bool RecompressSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, - const RecompressOptionsDialog* pRecompOpts) - { ASSERT(false); return false; } - virtual bool GetComment(CWnd* pMsgWnd, const GenericEntry* pEntry, - CString* pStr) - { ASSERT(false); return false; } - virtual bool SetComment(CWnd* pMsgWnd, GenericEntry* pEntry, - const CString& str) - { ASSERT(false); return false; } - virtual bool DeleteComment(CWnd* pMsgWnd, GenericEntry* pEntry) - { ASSERT(false); return false; } - virtual bool SetProps(CWnd* pMsgWnd, GenericEntry* pEntry, - const FileProps* pProps); - virtual void PreferencesChanged(void); - virtual long GetCapability(Capability cap); - virtual XferStatus XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, - ActionProgressDialog* pActionProgress, const XferFileOptions* pXferOpts); + virtual OpenResult Open(const char* filename, bool readOnly, CString* pErrMsg); + virtual CString New(const char* filename, const void* options); + virtual CString Flush(void); + virtual CString Reload(void); + virtual bool IsReadOnly(void) const { return fIsReadOnly; }; + virtual bool IsModified(void) const; + virtual void GetDescription(CString* pStr) const; + virtual bool BulkAdd(ActionProgressDialog* pActionProgress, + const AddFilesDialog* pAddOpts); + virtual bool AddDisk(ActionProgressDialog* pActionProgress, + const AddFilesDialog* pAddOpts) + { ASSERT(false); return false; } + virtual bool CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry, + const char* newName); + virtual bool TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) + { ASSERT(false); return false; } + virtual bool DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); + virtual bool RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); + virtual CString TestPathName(const GenericEntry* pGenericEntry, + const CString& basePath, const CString& newName, char newFssep) const; + virtual bool RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS, + const char* newName); + virtual CString TestVolumeName(const DiskFS* pDiskFS, + const char* newName) const; + virtual bool RecompressSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, + const RecompressOptionsDialog* pRecompOpts) + { ASSERT(false); return false; } + virtual bool GetComment(CWnd* pMsgWnd, const GenericEntry* pEntry, + CString* pStr) + { ASSERT(false); return false; } + virtual bool SetComment(CWnd* pMsgWnd, GenericEntry* pEntry, + const CString& str) + { ASSERT(false); return false; } + virtual bool DeleteComment(CWnd* pMsgWnd, GenericEntry* pEntry) + { ASSERT(false); return false; } + virtual bool SetProps(CWnd* pMsgWnd, GenericEntry* pEntry, + const FileProps* pProps); + virtual void PreferencesChanged(void); + virtual long GetCapability(Capability cap); + virtual XferStatus XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, + ActionProgressDialog* pActionProgress, const XferFileOptions* pXferOpts); - const DiskImg* GetDiskImg(void) const { return &fDiskImg; } - DiskFS* GetDiskFS(void) const { return fpPrimaryDiskFS; } + const DiskImg* GetDiskImg(void) const { return &fDiskImg; } + DiskFS* GetDiskFS(void) const { return fpPrimaryDiskFS; } - /* internal function, used by DiskArchive and DiskEntry */ - static bool ProgressCallback(DiskImgLib::A2FileDescr* pFile, - DiskImgLib::di_off_t max, DiskImgLib::di_off_t current, void* state); + /* internal function, used by DiskArchive and DiskEntry */ + static bool ProgressCallback(DiskImgLib::A2FileDescr* pFile, + DiskImgLib::di_off_t max, DiskImgLib::di_off_t current, void* state); private: - virtual CString Close(void); - virtual void XferPrepare(const XferFileOptions* pXferOpts); - virtual CString XferFile(FileDetails* pDetails, unsigned char** pDataBuf, - long dataLen, unsigned char** pRsrcBuf, long rsrcLen); - virtual void XferAbort(CWnd* pMsgWnd); - virtual void XferFinish(CWnd* pMsgWnd); + virtual CString Close(void); + virtual void XferPrepare(const XferFileOptions* pXferOpts); + virtual CString XferFile(FileDetails* pDetails, unsigned char** pDataBuf, + long dataLen, unsigned char** pRsrcBuf, long rsrcLen); + virtual void XferAbort(CWnd* pMsgWnd); + virtual void XferFinish(CWnd* pMsgWnd); - /* internal function, used during initial scan of volume */ - static bool ScanProgressCallback(void* cookie, const char* str, - int count); + /* internal function, used during initial scan of volume */ + static bool ScanProgressCallback(void* cookie, const char* str, + int count); - /* - * Internal class used to keep track of files we're adding. - */ - class FileAddData { - public: - FileAddData(const FileDetails* pDetails, const char* fsNormalPath) { - fDetails = *pDetails; + /* + * Internal class used to keep track of files we're adding. + */ + class FileAddData { + public: + FileAddData(const FileDetails* pDetails, const char* fsNormalPath) { + fDetails = *pDetails; - fFSNormalPath = fsNormalPath; - fpOtherFork = nil; - fpNext = nil; - } - virtual ~FileAddData(void) {} + fFSNormalPath = fsNormalPath; + fpOtherFork = nil; + fpNext = nil; + } + virtual ~FileAddData(void) {} - FileAddData* GetNext(void) const { return fpNext; } - void SetNext(FileAddData* pNext) { fpNext = pNext; } - FileAddData* GetOtherFork(void) const { return fpOtherFork; } - void SetOtherFork(FileAddData* pData) { fpOtherFork = pData; } + FileAddData* GetNext(void) const { return fpNext; } + void SetNext(FileAddData* pNext) { fpNext = pNext; } + FileAddData* GetOtherFork(void) const { return fpOtherFork; } + void SetOtherFork(FileAddData* pData) { fpOtherFork = pData; } - const FileDetails* GetDetails(void) const { return &fDetails; } - const char* GetFSNormalPath(void) const { return fFSNormalPath; } + const FileDetails* GetDetails(void) const { return &fDetails; } + const char* GetFSNormalPath(void) const { return fFSNormalPath; } - private: - // Three filenames stored here: - // fDetails.origName -- the name of the Windows file - // fDetails.storageName -- the normalized Windows name - // fFSNormalPath -- the FS-normalized version of "storageName" - FileDetails fDetails; - CString fFSNormalPath; + private: + // Three filenames stored here: + // fDetails.origName -- the name of the Windows file + // fDetails.storageName -- the normalized Windows name + // fFSNormalPath -- the FS-normalized version of "storageName" + FileDetails fDetails; + CString fFSNormalPath; - FileAddData* fpOtherFork; - FileAddData* fpNext; - }; + FileAddData* fpOtherFork; + FileAddData* fpNext; + }; - virtual ArchiveKind GetArchiveKind(void) { return kArchiveDiskImage; } - virtual NuError DoAddFile(const AddFilesDialog* pAddOpts, - FileDetails* pDetails); - int InternalReload(CWnd* pMsgWnd); + virtual ArchiveKind GetArchiveKind(void) { return kArchiveDiskImage; } + virtual NuError DoAddFile(const AddFilesDialog* pAddOpts, + FileDetails* pDetails); + int InternalReload(CWnd* pMsgWnd); - static int CompareDisplayNamesDesc(const void* ventry1, const void* ventry2); + static int CompareDisplayNamesDesc(const void* ventry1, const void* ventry2); - int LoadContents(void); - int LoadDiskFSContents(DiskFS* pDiskFS, const char* volName); - void DowncaseSubstring(CString* pStr, int startPos, int endPos, - bool prevWasSpace); - static void DebugMsgHandler(const char* file, int line, const char* msg); + int LoadContents(void); + int LoadDiskFSContents(DiskFS* pDiskFS, const char* volName); + void DowncaseSubstring(CString* pStr, int startPos, int endPos, + bool prevWasSpace); + static void DebugMsgHandler(const char* file, int line, const char* msg); - NuResult HandleReplaceExisting(const A2File* pExisting, - FileDetails* pDetails); - CString ProcessFileAddData(DiskFS* pDiskFS, int addOptsConvEOL); - CString LoadFile(const char* pathName, unsigned char** pBuf, long* pLen, - GenericEntry::ConvertEOL conv, GenericEntry::ConvertHighASCII convHA) const; - DIError AddForksToDisk(DiskFS* pDiskFS, const DiskFS::CreateParms* pParms, - const unsigned char* dataBuf, long dataLen, - const unsigned char* rsrcBuf, long rsrcLen) const; - void AddToAddDataList(FileAddData* pData); - void FreeAddDataList(void); - void ConvertFDToCP(const FileDetails* pDetails, - DiskFS::CreateParms* pCreateParms); + NuResult HandleReplaceExisting(const A2File* pExisting, + FileDetails* pDetails); + CString ProcessFileAddData(DiskFS* pDiskFS, int addOptsConvEOL); + CString LoadFile(const char* pathName, unsigned char** pBuf, long* pLen, + GenericEntry::ConvertEOL conv, GenericEntry::ConvertHighASCII convHA) const; + DIError AddForksToDisk(DiskFS* pDiskFS, const DiskFS::CreateParms* pParms, + const unsigned char* dataBuf, long dataLen, + const unsigned char* rsrcBuf, long rsrcLen) const; + void AddToAddDataList(FileAddData* pData); + void FreeAddDataList(void); + void ConvertFDToCP(const FileDetails* pDetails, + DiskFS::CreateParms* pCreateParms); - bool SetRenameFields(CWnd* pMsgWnd, DiskEntry* pEntry, - RenameEntryDialog* pDialog); + bool SetRenameFields(CWnd* pMsgWnd, DiskEntry* pEntry, + RenameEntryDialog* pDialog); - DiskImg fDiskImg; // DiskImg object for entire disk - DiskFS* fpPrimaryDiskFS; // outermost DiskFS - bool fIsReadOnly; + DiskImg fDiskImg; // DiskImg object for entire disk + DiskFS* fpPrimaryDiskFS; // outermost DiskFS + bool fIsReadOnly; - /* active state while adding files */ - FileAddData* fpAddDataHead; - FileAddData* fpAddDataTail; - bool fOverwriteExisting; - bool fOverwriteNoAsk; + /* active state while adding files */ + FileAddData* fpAddDataHead; + FileAddData* fpAddDataTail; + bool fOverwriteExisting; + bool fOverwriteNoAsk; - /* state during xfer */ - //CString fXferStoragePrefix; - DiskFS* fpXferTargetFS; + /* state during xfer */ + //CString fXferStoragePrefix; + DiskFS* fpXferTargetFS; }; #endif /*__DISK_ARCHIVE__*/ \ No newline at end of file diff --git a/app/DiskConvertDialog.cpp b/app/DiskConvertDialog.cpp index 9609880..f289897 100644 --- a/app/DiskConvertDialog.cpp +++ b/app/DiskConvertDialog.cpp @@ -13,9 +13,9 @@ using namespace DiskImgLib; BEGIN_MESSAGE_MAP(DiskConvertDialog, CDialog) - ON_CONTROL_RANGE(BN_CLICKED, IDC_DISKCONV_DOS, IDC_DISKCONV_DDD, OnChangeRadio) - ON_WM_HELPINFO() - ON_COMMAND(IDHELP, OnHelp) + ON_CONTROL_RANGE(BN_CLICKED, IDC_DISKCONV_DOS, IDC_DISKCONV_DDD, OnChangeRadio) + ON_WM_HELPINFO() + ON_COMMAND(IDHELP, OnHelp) END_MESSAGE_MAP() @@ -25,108 +25,108 @@ END_MESSAGE_MAP() void DiskConvertDialog::Init(const DiskImg* pDiskImg) { - ASSERT(pDiskImg != nil); - const int kMagicNibbles = -1234; - bool hasBlocks = pDiskImg->GetHasBlocks(); - bool hasSectors = pDiskImg->GetHasSectors(); - bool hasNibbles = pDiskImg->GetHasNibbles(); - long diskSizeInSectors; + ASSERT(pDiskImg != nil); + const int kMagicNibbles = -1234; + bool hasBlocks = pDiskImg->GetHasBlocks(); + bool hasSectors = pDiskImg->GetHasSectors(); + bool hasNibbles = pDiskImg->GetHasNibbles(); + long diskSizeInSectors; - ASSERT(fSizeInBlocks == -1); - if (hasBlocks) { - diskSizeInSectors = pDiskImg->GetNumBlocks() * 2; - fSizeInBlocks = diskSizeInSectors / 2; - } else if (hasSectors) { - diskSizeInSectors = - pDiskImg->GetNumTracks() * pDiskImg->GetNumSectPerTrack(); - if (pDiskImg->GetNumSectPerTrack() != 13) - fSizeInBlocks = diskSizeInSectors / 2; - } else { - ASSERT(hasNibbles); - diskSizeInSectors = kMagicNibbles; - } + ASSERT(fSizeInBlocks == -1); + if (hasBlocks) { + diskSizeInSectors = pDiskImg->GetNumBlocks() * 2; + fSizeInBlocks = diskSizeInSectors / 2; + } else if (hasSectors) { + diskSizeInSectors = + pDiskImg->GetNumTracks() * pDiskImg->GetNumSectPerTrack(); + if (pDiskImg->GetNumSectPerTrack() != 13) + fSizeInBlocks = diskSizeInSectors / 2; + } else { + ASSERT(hasNibbles); + diskSizeInSectors = kMagicNibbles; + } - if (diskSizeInSectors >= 8388608) { - /* no conversions for files 2GB and larger except .PO */ - fDiskDescription.Format(IDS_CDESC_BLOCKS, diskSizeInSectors/4); - fAllowUnadornedProDOS = true; - fConvertIdx = kConvProDOSRaw; - } else if (diskSizeInSectors == 35*16) { - /* 140K disk image */ - fDiskDescription.LoadString(IDS_CDESC_140K); - fAllowUnadornedDOS = true; - fAllowUnadornedProDOS = true; - fAllowProDOS2MG = true; - fAllowUnadornedNibble = true; - fAllowNuFX = true; - fAllowTrackStar = true; - fAllowSim2eHDV = true; - fAllowDDD = true; - if (hasNibbles) - fConvertIdx = kConvNibbleRaw; - else - fConvertIdx = kConvDOSRaw; - } else if (diskSizeInSectors == 40*16 && - (pDiskImg->GetFileFormat() == DiskImg::kFileFormatTrackStar || - pDiskImg->GetFileFormat() == DiskImg::kFileFormatFDI)) - { - /* 40-track TrackStar or FDI image; allow conversion to 35-track formats */ - fDiskDescription.LoadString(IDS_CDESC_40TRACK); - ASSERT(pDiskImg->GetHasBlocks()); - fAllowUnadornedDOS = true; - fAllowUnadornedProDOS = true; - fAllowProDOS2MG = true; - fAllowUnadornedNibble = true; - fAllowNuFX = true; - fAllowSim2eHDV = true; - fAllowDDD = true; - fAllowTrackStar = true; - fConvertIdx = kConvDOSRaw; - } else if (diskSizeInSectors == 35*13) { - /* 13-sector 5.25" floppy */ - fDiskDescription.LoadString(IDS_CDEC_140K_13); - fAllowUnadornedNibble = true; - fAllowD13 = true; - fConvertIdx = kConvNibbleRaw; - } else if (diskSizeInSectors == kMagicNibbles) { - /* blob of nibbles with no recognizable format; allow self-convert */ - fDiskDescription.LoadString(IDS_CDEC_RAWNIB); - if (pDiskImg->GetPhysicalFormat() == DiskImg::kPhysicalFormatNib525_6656) - { - fAllowUnadornedNibble = true; - fConvertIdx = kConvNibbleRaw; - } else if (pDiskImg->GetPhysicalFormat() == DiskImg::kPhysicalFormatNib525_Var) - { - fAllowTrackStar = true; - fConvertIdx = kConvTrackStar; - } else if (pDiskImg->GetPhysicalFormat() == DiskImg::kPhysicalFormatNib525_6384) - { - /* don't currently allow .nb2 output */ - WMSG0(" GLITCH: we don't allow self-convert of .nb2 files\n"); - ASSERT(false); - } else { - /* this should be impossible */ - ASSERT(false); - } - } else if (diskSizeInSectors == 3200) { - /* 800K disk image */ - fDiskDescription.LoadString(IDS_CDESC_800K); - fAllowUnadornedDOS = true; - fAllowUnadornedProDOS = true; - fAllowProDOS2MG = true; - fAllowDiskCopy42 = true; - fAllowNuFX = true; - fAllowSim2eHDV = true; - fConvertIdx = kConvProDOS2MG; - } else { - /* odd-sized disk image; could allow DOS if hasSectors */ - fDiskDescription.Format(IDS_CDESC_BLOCKS, diskSizeInSectors/4); - fAllowUnadornedProDOS = true; - fAllowProDOS2MG = true; - fAllowNuFX = true; - fAllowSim2eHDV = true; - fConvertIdx = kConvProDOS2MG; - } + if (diskSizeInSectors >= 8388608) { + /* no conversions for files 2GB and larger except .PO */ + fDiskDescription.Format(IDS_CDESC_BLOCKS, diskSizeInSectors/4); + fAllowUnadornedProDOS = true; + fConvertIdx = kConvProDOSRaw; + } else if (diskSizeInSectors == 35*16) { + /* 140K disk image */ + fDiskDescription.LoadString(IDS_CDESC_140K); + fAllowUnadornedDOS = true; + fAllowUnadornedProDOS = true; + fAllowProDOS2MG = true; + fAllowUnadornedNibble = true; + fAllowNuFX = true; + fAllowTrackStar = true; + fAllowSim2eHDV = true; + fAllowDDD = true; + if (hasNibbles) + fConvertIdx = kConvNibbleRaw; + else + fConvertIdx = kConvDOSRaw; + } else if (diskSizeInSectors == 40*16 && + (pDiskImg->GetFileFormat() == DiskImg::kFileFormatTrackStar || + pDiskImg->GetFileFormat() == DiskImg::kFileFormatFDI)) + { + /* 40-track TrackStar or FDI image; allow conversion to 35-track formats */ + fDiskDescription.LoadString(IDS_CDESC_40TRACK); + ASSERT(pDiskImg->GetHasBlocks()); + fAllowUnadornedDOS = true; + fAllowUnadornedProDOS = true; + fAllowProDOS2MG = true; + fAllowUnadornedNibble = true; + fAllowNuFX = true; + fAllowSim2eHDV = true; + fAllowDDD = true; + fAllowTrackStar = true; + fConvertIdx = kConvDOSRaw; + } else if (diskSizeInSectors == 35*13) { + /* 13-sector 5.25" floppy */ + fDiskDescription.LoadString(IDS_CDEC_140K_13); + fAllowUnadornedNibble = true; + fAllowD13 = true; + fConvertIdx = kConvNibbleRaw; + } else if (diskSizeInSectors == kMagicNibbles) { + /* blob of nibbles with no recognizable format; allow self-convert */ + fDiskDescription.LoadString(IDS_CDEC_RAWNIB); + if (pDiskImg->GetPhysicalFormat() == DiskImg::kPhysicalFormatNib525_6656) + { + fAllowUnadornedNibble = true; + fConvertIdx = kConvNibbleRaw; + } else if (pDiskImg->GetPhysicalFormat() == DiskImg::kPhysicalFormatNib525_Var) + { + fAllowTrackStar = true; + fConvertIdx = kConvTrackStar; + } else if (pDiskImg->GetPhysicalFormat() == DiskImg::kPhysicalFormatNib525_6384) + { + /* don't currently allow .nb2 output */ + WMSG0(" GLITCH: we don't allow self-convert of .nb2 files\n"); + ASSERT(false); + } else { + /* this should be impossible */ + ASSERT(false); + } + } else if (diskSizeInSectors == 3200) { + /* 800K disk image */ + fDiskDescription.LoadString(IDS_CDESC_800K); + fAllowUnadornedDOS = true; + fAllowUnadornedProDOS = true; + fAllowProDOS2MG = true; + fAllowDiskCopy42 = true; + fAllowNuFX = true; + fAllowSim2eHDV = true; + fConvertIdx = kConvProDOS2MG; + } else { + /* odd-sized disk image; could allow DOS if hasSectors */ + fDiskDescription.Format(IDS_CDESC_BLOCKS, diskSizeInSectors/4); + fAllowUnadornedProDOS = true; + fAllowProDOS2MG = true; + fAllowNuFX = true; + fAllowSim2eHDV = true; + fConvertIdx = kConvProDOS2MG; + } } /* @@ -135,13 +135,13 @@ DiskConvertDialog::Init(const DiskImg* pDiskImg) void DiskConvertDialog::Init(int fileCount) { - /* allow everything */ - fAllowUnadornedDOS = fAllowUnadornedProDOS = fAllowProDOS2MG = - fAllowUnadornedNibble = fAllowD13 = fAllowDiskCopy42 = - fAllowNuFX = fAllowTrackStar = fAllowSim2eHDV = fAllowDDD = true; - fConvertIdx = kConvDOSRaw; // default choice == first in list - fBulkFileCount = fileCount; - fDiskDescription.Format("%d images selected", fBulkFileCount); + /* allow everything */ + fAllowUnadornedDOS = fAllowUnadornedProDOS = fAllowProDOS2MG = + fAllowUnadornedNibble = fAllowD13 = fAllowDiskCopy42 = + fAllowNuFX = fAllowTrackStar = fAllowSim2eHDV = fAllowDDD = true; + fConvertIdx = kConvDOSRaw; // default choice == first in list + fBulkFileCount = fileCount; + fDiskDescription.Format("%d images selected", fBulkFileCount); } @@ -151,80 +151,80 @@ DiskConvertDialog::Init(int fileCount) BOOL DiskConvertDialog::OnInitDialog(void) { - CWnd* pWnd; + CWnd* pWnd; - ASSERT(fConvertIdx != -1); // must call Init before DoModal + ASSERT(fConvertIdx != -1); // must call Init before DoModal - if (!fAllowUnadornedDOS) { - pWnd = GetDlgItem(IDC_DISKCONV_DOS); - pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_DISKCONV_DOS2MG); - pWnd->EnableWindow(FALSE); - } - if (!fAllowUnadornedProDOS) { - pWnd = GetDlgItem(IDC_DISKCONV_PRODOS); - pWnd->EnableWindow(FALSE); - } - if (!fAllowProDOS2MG) { - pWnd = GetDlgItem(IDC_DISKCONV_PRODOS2MG); - pWnd->EnableWindow(FALSE); - } - if (!fAllowUnadornedNibble) { - pWnd = GetDlgItem(IDC_DISKCONV_NIB); - pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_DISKCONV_NIB2MG); - pWnd->EnableWindow(FALSE); - } - if (!fAllowD13) { - pWnd = GetDlgItem(IDC_DISKCONV_D13); - pWnd->EnableWindow(FALSE); - } - if (!fAllowDiskCopy42) { - pWnd = GetDlgItem(IDC_DISKCONV_DC42); - pWnd->EnableWindow(FALSE); - } - if (!fAllowNuFX) { - pWnd = GetDlgItem(IDC_DISKCONV_SDK); - pWnd->EnableWindow(FALSE); - } - if (!fAllowTrackStar) { - pWnd = GetDlgItem(IDC_DISKCONV_TRACKSTAR); - pWnd->EnableWindow(FALSE); - } - if (!fAllowSim2eHDV) { - pWnd = GetDlgItem(IDC_DISKCONV_HDV); - pWnd->EnableWindow(FALSE); - } - if (!fAllowDDD) { - pWnd = GetDlgItem(IDC_DISKCONV_DDD); - pWnd->EnableWindow(FALSE); - } + if (!fAllowUnadornedDOS) { + pWnd = GetDlgItem(IDC_DISKCONV_DOS); + pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_DISKCONV_DOS2MG); + pWnd->EnableWindow(FALSE); + } + if (!fAllowUnadornedProDOS) { + pWnd = GetDlgItem(IDC_DISKCONV_PRODOS); + pWnd->EnableWindow(FALSE); + } + if (!fAllowProDOS2MG) { + pWnd = GetDlgItem(IDC_DISKCONV_PRODOS2MG); + pWnd->EnableWindow(FALSE); + } + if (!fAllowUnadornedNibble) { + pWnd = GetDlgItem(IDC_DISKCONV_NIB); + pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_DISKCONV_NIB2MG); + pWnd->EnableWindow(FALSE); + } + if (!fAllowD13) { + pWnd = GetDlgItem(IDC_DISKCONV_D13); + pWnd->EnableWindow(FALSE); + } + if (!fAllowDiskCopy42) { + pWnd = GetDlgItem(IDC_DISKCONV_DC42); + pWnd->EnableWindow(FALSE); + } + if (!fAllowNuFX) { + pWnd = GetDlgItem(IDC_DISKCONV_SDK); + pWnd->EnableWindow(FALSE); + } + if (!fAllowTrackStar) { + pWnd = GetDlgItem(IDC_DISKCONV_TRACKSTAR); + pWnd->EnableWindow(FALSE); + } + if (!fAllowSim2eHDV) { + pWnd = GetDlgItem(IDC_DISKCONV_HDV); + pWnd->EnableWindow(FALSE); + } + if (!fAllowDDD) { + pWnd = GetDlgItem(IDC_DISKCONV_DDD); + pWnd->EnableWindow(FALSE); + } - if (fBulkFileCount < 0) { - pWnd = GetDlgItem(IDC_IMAGE_TYPE); - pWnd->SetWindowText(fDiskDescription); - } else { - CRect rect; - int right; - pWnd = GetDlgItem(IDC_IMAGE_TYPE); - pWnd->GetWindowRect(&rect); - ScreenToClient(&rect); - right = rect.right; - pWnd->DestroyWindow(); + if (fBulkFileCount < 0) { + pWnd = GetDlgItem(IDC_IMAGE_TYPE); + pWnd->SetWindowText(fDiskDescription); + } else { + CRect rect; + int right; + pWnd = GetDlgItem(IDC_IMAGE_TYPE); + pWnd->GetWindowRect(&rect); + ScreenToClient(&rect); + right = rect.right; + pWnd->DestroyWindow(); - pWnd = GetDlgItem(IDC_IMAGE_SIZE_TEXT); - pWnd->GetWindowRect(&rect); - ScreenToClient(&rect); - rect.right = right; - pWnd->MoveWindow(&rect); - pWnd->SetWindowText(fDiskDescription); - } + pWnd = GetDlgItem(IDC_IMAGE_SIZE_TEXT); + pWnd->GetWindowRect(&rect); + ScreenToClient(&rect); + rect.right = right; + pWnd->MoveWindow(&rect); + pWnd->SetWindowText(fDiskDescription); + } - OnChangeRadio(0); // set the gzip box + OnChangeRadio(0); // set the gzip box - CDialog::OnInitDialog(); + CDialog::OnInitDialog(); - return TRUE; + return TRUE; } /* @@ -233,34 +233,34 @@ DiskConvertDialog::OnInitDialog(void) void DiskConvertDialog::DoDataExchange(CDataExchange* pDX) { - DDX_Check(pDX, IDC_DISKCONV_GZIP, fAddGzip); - DDX_Radio(pDX, IDC_DISKCONV_DOS, fConvertIdx); + DDX_Check(pDX, IDC_DISKCONV_GZIP, fAddGzip); + DDX_Radio(pDX, IDC_DISKCONV_DOS, fConvertIdx); - if (pDX->m_bSaveAndValidate) { - switch (fConvertIdx) { - case kConvDOSRaw: fExtension = "do"; break; - case kConvDOS2MG: fExtension = "2mg"; break; - case kConvProDOSRaw: fExtension = "po"; break; - case kConvProDOS2MG: fExtension = "2mg"; break; - case kConvNibbleRaw: fExtension = "nib"; break; - case kConvNibble2MG: fExtension = "2mg"; break; - case kConvD13: fExtension = "d13"; break; - case kConvDiskCopy42: fExtension = "dsk"; break; - case kConvNuFX: fExtension = "sdk"; break; - case kConvTrackStar: fExtension = "app"; break; - case kConvSim2eHDV: fExtension = "hdv"; break; - case kConvDDD: fExtension = "ddd"; break; - default: - fExtension = "???"; - ASSERT(false); - break; - } + if (pDX->m_bSaveAndValidate) { + switch (fConvertIdx) { + case kConvDOSRaw: fExtension = "do"; break; + case kConvDOS2MG: fExtension = "2mg"; break; + case kConvProDOSRaw: fExtension = "po"; break; + case kConvProDOS2MG: fExtension = "2mg"; break; + case kConvNibbleRaw: fExtension = "nib"; break; + case kConvNibble2MG: fExtension = "2mg"; break; + case kConvD13: fExtension = "d13"; break; + case kConvDiskCopy42: fExtension = "dsk"; break; + case kConvNuFX: fExtension = "sdk"; break; + case kConvTrackStar: fExtension = "app"; break; + case kConvSim2eHDV: fExtension = "hdv"; break; + case kConvDDD: fExtension = "ddd"; break; + default: + fExtension = "???"; + ASSERT(false); + break; + } - if (fAddGzip && fConvertIdx != kConvNuFX) - fExtension += ".gz"; + if (fAddGzip && fConvertIdx != kConvNuFX) + fExtension += ".gz"; - WMSG1(" DCD recommending extension '%s'\n", (LPCTSTR) fExtension); - } + WMSG1(" DCD recommending extension '%s'\n", (LPCTSTR) fExtension); + } } /* @@ -273,15 +273,15 @@ DiskConvertDialog::DoDataExchange(CDataExchange* pDX) void DiskConvertDialog::OnChangeRadio(UINT nID) { - CWnd* pGzip = GetDlgItem(IDC_DISKCONV_GZIP); - ASSERT(pGzip != nil); - CButton* pNuFX = (CButton*)GetDlgItem(IDC_DISKCONV_SDK); - ASSERT(pNuFX != nil); + CWnd* pGzip = GetDlgItem(IDC_DISKCONV_GZIP); + ASSERT(pGzip != nil); + CButton* pNuFX = (CButton*)GetDlgItem(IDC_DISKCONV_SDK); + ASSERT(pNuFX != nil); - if (fSizeInBlocks > DiskImgLib::kGzipMax / 512) - pGzip->EnableWindow(FALSE); - else - pGzip->EnableWindow(pNuFX->GetCheck() == BST_UNCHECKED); + if (fSizeInBlocks > DiskImgLib::kGzipMax / 512) + pGzip->EnableWindow(FALSE); + else + pGzip->EnableWindow(pNuFX->GetCheck() == BST_UNCHECKED); } /* @@ -290,8 +290,8 @@ DiskConvertDialog::OnChangeRadio(UINT nID) BOOL DiskConvertDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* @@ -300,8 +300,8 @@ DiskConvertDialog::OnHelpInfo(HELPINFO* lpHelpInfo) void DiskConvertDialog::OnHelp(void) { - if (fBulkFileCount < 0) - WinHelp(HELP_TOPIC_DISK_CONV, HELP_CONTEXT); - else - WinHelp(HELP_TOPIC_BULK_DISK_CONV, HELP_CONTEXT); + if (fBulkFileCount < 0) + WinHelp(HELP_TOPIC_DISK_CONV, HELP_CONTEXT); + else + WinHelp(HELP_TOPIC_BULK_DISK_CONV, HELP_CONTEXT); } diff --git a/app/DiskConvertDialog.h b/app/DiskConvertDialog.h index 34a4f59..5b526ae 100644 --- a/app/DiskConvertDialog.h +++ b/app/DiskConvertDialog.h @@ -17,69 +17,69 @@ */ class DiskConvertDialog : public CDialog { public: - DiskConvertDialog(CWnd* pParentWnd) : CDialog(IDD_DISKCONV, pParentWnd) - { - fAllowUnadornedDOS = fAllowUnadornedProDOS = fAllowProDOS2MG = - fAllowUnadornedNibble = fAllowD13 = fAllowDiskCopy42 = - fAllowNuFX = fAllowTrackStar = fAllowSim2eHDV = fAllowDDD = false; - fAddGzip = FALSE; - fConvertIdx = -1; - fBulkFileCount = -1; - fSizeInBlocks = -1; - } - virtual ~DiskConvertDialog(void) {} + DiskConvertDialog(CWnd* pParentWnd) : CDialog(IDD_DISKCONV, pParentWnd) + { + fAllowUnadornedDOS = fAllowUnadornedProDOS = fAllowProDOS2MG = + fAllowUnadornedNibble = fAllowD13 = fAllowDiskCopy42 = + fAllowNuFX = fAllowTrackStar = fAllowSim2eHDV = fAllowDDD = false; + fAddGzip = FALSE; + fConvertIdx = -1; + fBulkFileCount = -1; + fSizeInBlocks = -1; + } + virtual ~DiskConvertDialog(void) {} - void Init(const DiskImgLib::DiskImg* pDiskImg); // single file init - void Init(int fileCount); // bulk init + void Init(const DiskImgLib::DiskImg* pDiskImg); // single file init + void Init(int fileCount); // bulk init - /* must match up with dialog */ - enum { - kConvDOSRaw = 0, - kConvDOS2MG = 1, - kConvProDOSRaw = 2, - kConvProDOS2MG = 3, - kConvNibbleRaw = 4, - kConvNibble2MG = 5, - kConvD13 = 6, - kConvDiskCopy42 = 7, - kConvNuFX = 8, - kConvTrackStar = 9, - kConvSim2eHDV = 10, - kConvDDD = 11, - }; - int fConvertIdx; + /* must match up with dialog */ + enum { + kConvDOSRaw = 0, + kConvDOS2MG = 1, + kConvProDOSRaw = 2, + kConvProDOS2MG = 3, + kConvNibbleRaw = 4, + kConvNibble2MG = 5, + kConvD13 = 6, + kConvDiskCopy42 = 7, + kConvNuFX = 8, + kConvTrackStar = 9, + kConvSim2eHDV = 10, + kConvDDD = 11, + }; + int fConvertIdx; - BOOL fAddGzip; + BOOL fAddGzip; - // this is set to proper extension for the type chosen (e.g. "do") - CString fExtension; + // this is set to proper extension for the type chosen (e.g. "do") + CString fExtension; private: - BOOL OnInitDialog(void); - void DoDataExchange(CDataExchange* pDX); + BOOL OnInitDialog(void); + void DoDataExchange(CDataExchange* pDX); - afx_msg void OnChangeRadio(UINT nID); - afx_msg void OnHelp(void); + afx_msg void OnChangeRadio(UINT nID); + afx_msg void OnHelp(void); - BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - CString fDiskDescription; - bool fAllowUnadornedDOS; - bool fAllowUnadornedProDOS; - bool fAllowProDOS2MG; - bool fAllowUnadornedNibble; - bool fAllowD13; - bool fAllowDiskCopy42; - bool fAllowNuFX; - bool fAllowTrackStar; - bool fAllowSim2eHDV; - bool fAllowDDD; + CString fDiskDescription; + bool fAllowUnadornedDOS; + bool fAllowUnadornedProDOS; + bool fAllowProDOS2MG; + bool fAllowUnadornedNibble; + bool fAllowD13; + bool fAllowDiskCopy42; + bool fAllowNuFX; + bool fAllowTrackStar; + bool fAllowSim2eHDV; + bool fAllowDDD; - int fBulkFileCount; + int fBulkFileCount; - long fSizeInBlocks; + long fSizeInBlocks; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__DISKCONVERTDIALOG__*/ \ No newline at end of file diff --git a/app/DiskEditDialog.cpp b/app/DiskEditDialog.cpp index 1bbcd60..2dbc3f5 100644 --- a/app/DiskEditDialog.cpp +++ b/app/DiskEditDialog.cpp @@ -27,22 +27,22 @@ /* * =========================================================================== - * DiskEditDialog (base class) + * DiskEditDialog (base class) * =========================================================================== */ BEGIN_MESSAGE_MAP(DiskEditDialog, CDialog) - ON_BN_CLICKED(IDC_DISKEDIT_DONE, OnDone) - ON_BN_CLICKED(IDC_DISKEDIT_HEX, OnHexMode) - ON_BN_CLICKED(IDC_DISKEDIT_DOREAD, OnDoRead) - ON_BN_CLICKED(IDC_DISKEDIT_DOWRITE, OnDoWrite) - ON_BN_CLICKED(IDC_DISKEDIT_PREV, OnReadPrev) - ON_BN_CLICKED(IDC_DISKEDIT_NEXT, OnReadNext) - ON_BN_CLICKED(IDC_DISKEDIT_SUBVOLUME, OnSubVolume) - ON_BN_CLICKED(IDC_DISKEDIT_OPENFILE, OnOpenFile) - ON_BN_CLICKED(IDHELP, OnHelp) - ON_CBN_SELCHANGE(IDC_DISKEDIT_NIBBLE_PARMS, OnNibbleParms) - ON_WM_HELPINFO() + ON_BN_CLICKED(IDC_DISKEDIT_DONE, OnDone) + ON_BN_CLICKED(IDC_DISKEDIT_HEX, OnHexMode) + ON_BN_CLICKED(IDC_DISKEDIT_DOREAD, OnDoRead) + ON_BN_CLICKED(IDC_DISKEDIT_DOWRITE, OnDoWrite) + ON_BN_CLICKED(IDC_DISKEDIT_PREV, OnReadPrev) + ON_BN_CLICKED(IDC_DISKEDIT_NEXT, OnReadNext) + ON_BN_CLICKED(IDC_DISKEDIT_SUBVOLUME, OnSubVolume) + ON_BN_CLICKED(IDC_DISKEDIT_OPENFILE, OnOpenFile) + ON_BN_CLICKED(IDHELP, OnHelp) + ON_CBN_SELCHANGE(IDC_DISKEDIT_NIBBLE_PARMS, OnNibbleParms) + ON_WM_HELPINFO() END_MESSAGE_MAP() /* @@ -51,97 +51,97 @@ END_MESSAGE_MAP() BOOL DiskEditDialog::OnInitDialog(void) { - ASSERT(!fFileName.IsEmpty()); - ASSERT(fpDiskFS != nil); + ASSERT(!fFileName.IsEmpty()); + ASSERT(fpDiskFS != nil); - /* - * Disable the write button. - */ - if (fReadOnly) { - CButton* pButton = (CButton*) GetDlgItem(IDC_DISKEDIT_DOWRITE); - ASSERT(pButton != nil); - pButton->EnableWindow(FALSE); - } + /* + * Disable the write button. + */ + if (fReadOnly) { + CButton* pButton = (CButton*) GetDlgItem(IDC_DISKEDIT_DOWRITE); + ASSERT(pButton != nil); + pButton->EnableWindow(FALSE); + } - /* - * Use modified spin controls so we're not limited to 16 bits. - */ - ReplaceSpinCtrl(&fTrackSpinner, IDC_DISKEDIT_TRACKSPIN, - IDC_DISKEDIT_TRACK); - ReplaceSpinCtrl(&fSectorSpinner, IDC_DISKEDIT_SECTORSPIN, - IDC_DISKEDIT_SECTOR); + /* + * Use modified spin controls so we're not limited to 16 bits. + */ + ReplaceSpinCtrl(&fTrackSpinner, IDC_DISKEDIT_TRACKSPIN, + IDC_DISKEDIT_TRACK); + ReplaceSpinCtrl(&fSectorSpinner, IDC_DISKEDIT_SECTORSPIN, + IDC_DISKEDIT_SECTOR); - /* - * Configure the RichEdit control. - */ - CRichEditCtrl* pEdit = (CRichEditCtrl*) GetDlgItem(IDC_DISKEDIT_EDIT); - ASSERT(pEdit != nil); + /* + * Configure the RichEdit control. + */ + CRichEditCtrl* pEdit = (CRichEditCtrl*) GetDlgItem(IDC_DISKEDIT_EDIT); + ASSERT(pEdit != nil); - /* set the font to 10-point Courier New */ - CHARFORMAT cf; - cf.cbSize = sizeof(CHARFORMAT); - cf.dwMask = CFM_FACE | CFM_SIZE; - ::lstrcpy(cf.szFaceName, "Courier New"); - cf.yHeight = 10 * 20; // point size in twips - BOOL cc = pEdit->SetDefaultCharFormat(cf); - if (cc == FALSE) { - WMSG0("SetDefaultCharFormat failed?\n"); - ASSERT(FALSE); - } + /* set the font to 10-point Courier New */ + CHARFORMAT cf; + cf.cbSize = sizeof(CHARFORMAT); + cf.dwMask = CFM_FACE | CFM_SIZE; + ::lstrcpy(cf.szFaceName, "Courier New"); + cf.yHeight = 10 * 20; // point size in twips + BOOL cc = pEdit->SetDefaultCharFormat(cf); + if (cc == FALSE) { + WMSG0("SetDefaultCharFormat failed?\n"); + ASSERT(FALSE); + } - /* set to read-only */ - pEdit->SetReadOnly(); - /* retain the selection even if we lose focus [can't do this in OnInit] */ - pEdit->SetOptions(ECOOP_OR, ECO_SAVESEL); + /* set to read-only */ + pEdit->SetReadOnly(); + /* retain the selection even if we lose focus [can't do this in OnInit] */ + pEdit->SetOptions(ECOOP_OR, ECO_SAVESEL); - /* - * Disable the sub-volume and/or file open buttons if the DiskFS doesn't - * have the appropriate stuff inside. - */ - if (fpDiskFS->GetNextFile(nil) == nil) { - CWnd* pWnd = GetDlgItem(IDC_DISKEDIT_OPENFILE); - pWnd->EnableWindow(FALSE); - } - if (fpDiskFS->GetNextSubVolume(nil) == nil) { - CWnd* pWnd = GetDlgItem(IDC_DISKEDIT_SUBVOLUME); - pWnd->EnableWindow(FALSE); - } + /* + * Disable the sub-volume and/or file open buttons if the DiskFS doesn't + * have the appropriate stuff inside. + */ + if (fpDiskFS->GetNextFile(nil) == nil) { + CWnd* pWnd = GetDlgItem(IDC_DISKEDIT_OPENFILE); + pWnd->EnableWindow(FALSE); + } + if (fpDiskFS->GetNextSubVolume(nil) == nil) { + CWnd* pWnd = GetDlgItem(IDC_DISKEDIT_SUBVOLUME); + pWnd->EnableWindow(FALSE); + } - /* - * Configure the nibble parm drop-list in an appropriate fashion. - */ - InitNibbleParmList(); + /* + * Configure the nibble parm drop-list in an appropriate fashion. + */ + InitNibbleParmList(); - /* - * If this is a sub-volume edit window, pop us up slightly offset from the - * parent window so the user can see that there's more than one thing - * open. - */ - if (fPositionShift != 0) { - CRect rect; - GetWindowRect(&rect); - rect.top += fPositionShift; - rect.left += fPositionShift; - rect.bottom += fPositionShift; - rect.right += fPositionShift; - MoveWindow(&rect); - } + /* + * If this is a sub-volume edit window, pop us up slightly offset from the + * parent window so the user can see that there's more than one thing + * open. + */ + if (fPositionShift != 0) { + CRect rect; + GetWindowRect(&rect); + rect.top += fPositionShift; + rect.left += fPositionShift; + rect.bottom += fPositionShift; + rect.right += fPositionShift; + MoveWindow(&rect); + } - /* - * Set the window title. - */ - CString title("Disk Viewer - "); - title += fFileName; - if (fpDiskFS->GetVolumeID() != nil) { - title += " ("; - title += fpDiskFS->GetVolumeID(); - title += ")"; - } - SetWindowText(title); + /* + * Set the window title. + */ + CString title("Disk Viewer - "); + title += fFileName; + if (fpDiskFS->GetVolumeID() != nil) { + title += " ("; + title += fpDiskFS->GetVolumeID(); + title += ")"; + } + SetWindowText(title); - return TRUE; + return TRUE; } /* @@ -150,57 +150,57 @@ DiskEditDialog::OnInitDialog(void) void DiskEditDialog::InitNibbleParmList(void) { - ASSERT(fpDiskFS != nil); - DiskImg* pDiskImg = fpDiskFS->GetDiskImg(); - CComboBox* pCombo; + ASSERT(fpDiskFS != nil); + DiskImg* pDiskImg = fpDiskFS->GetDiskImg(); + CComboBox* pCombo; - pCombo = (CComboBox*) GetDlgItem(IDC_DISKEDIT_NIBBLE_PARMS); - ASSERT(pCombo != nil); + pCombo = (CComboBox*) GetDlgItem(IDC_DISKEDIT_NIBBLE_PARMS); + ASSERT(pCombo != nil); - if (pDiskImg->GetHasNibbles()) { - const DiskImg::NibbleDescr* pTable; - const DiskImg::NibbleDescr* pCurrent; - int i, count; + if (pDiskImg->GetHasNibbles()) { + const DiskImg::NibbleDescr* pTable; + const DiskImg::NibbleDescr* pCurrent; + int i, count; - pTable = pDiskImg->GetNibbleDescrTable(&count); - if (pTable == nil || count <= 0) { - WMSG2("WHOOPS: nibble parm got table=0x%08lx, count=%d\n", - (long) pTable, count); - return; - } - pCurrent = pDiskImg->GetNibbleDescr(); + pTable = pDiskImg->GetNibbleDescrTable(&count); + if (pTable == nil || count <= 0) { + WMSG2("WHOOPS: nibble parm got table=0x%08lx, count=%d\n", + (long) pTable, count); + return; + } + pCurrent = pDiskImg->GetNibbleDescr(); - /* configure the selection to match the disk analysis */ - int dflt = -1; - if (pCurrent != nil) { - for (i = 0; i < count; i++) { - if (memcmp(&pTable[i], pCurrent, sizeof(*pCurrent)) == 0) { - WMSG1(" NibbleParm match on entry %d\n", i); - dflt = i; - break; - } - } + /* configure the selection to match the disk analysis */ + int dflt = -1; + if (pCurrent != nil) { + for (i = 0; i < count; i++) { + if (memcmp(&pTable[i], pCurrent, sizeof(*pCurrent)) == 0) { + WMSG1(" NibbleParm match on entry %d\n", i); + dflt = i; + break; + } + } - if (dflt == -1) { - WMSG0(" GLITCH: no match on nibble descr in table?!\n"); - dflt = 0; - } - } + if (dflt == -1) { + WMSG0(" GLITCH: no match on nibble descr in table?!\n"); + dflt = 0; + } + } - for (i = 0; i < count; i++) { - if (pTable[i].numSectors > 0) - pCombo->AddString(pTable[i].description); - else { - /* only expecting this on the last, "custom" entry */ - ASSERT(i == count-1); - } - } - pCombo->SetCurSel(dflt); - } else { - pCombo->AddString("Nibble Parms"); - pCombo->SetCurSel(0); - pCombo->EnableWindow(FALSE); - } + for (i = 0; i < count; i++) { + if (pTable[i].numSectors > 0) + pCombo->AddString(pTable[i].description); + else { + /* only expecting this on the last, "custom" entry */ + ASSERT(i == count-1); + } + } + pCombo->SetCurSel(dflt); + } else { + pCombo->AddString("Nibble Parms"); + pCombo->SetCurSel(0); + pCombo->EnableWindow(FALSE); + } } @@ -210,24 +210,24 @@ DiskEditDialog::InitNibbleParmList(void) int DiskEditDialog::ReplaceSpinCtrl(MySpinCtrl* pNewSpin, int idSpin, int idEdit) { - CSpinButtonCtrl* pSpin; -// CRect rect; - DWORD style; - - pSpin = (CSpinButtonCtrl*)GetDlgItem(idSpin); - if (pSpin == nil) - return -1; -// pSpin->GetWindowRect(&rect); -// ScreenToClient(&rect); - style = pSpin->GetStyle(); - style &= ~(UDS_SETBUDDYINT); - //style |= UDS_AUTOBUDDY; - ASSERT(!(style & UDS_AUTOBUDDY)); - pSpin->DestroyWindow(); - pNewSpin->Create(style, CRect(0,0,0,0), this, idSpin); - pNewSpin->SetBuddy(GetDlgItem(idEdit)); + CSpinButtonCtrl* pSpin; +// CRect rect; + DWORD style; + + pSpin = (CSpinButtonCtrl*)GetDlgItem(idSpin); + if (pSpin == nil) + return -1; +// pSpin->GetWindowRect(&rect); +// ScreenToClient(&rect); + style = pSpin->GetStyle(); + style &= ~(UDS_SETBUDDYINT); + //style |= UDS_AUTOBUDDY; + ASSERT(!(style & UDS_AUTOBUDDY)); + pSpin->DestroyWindow(); + pNewSpin->Create(style, CRect(0,0,0,0), this, idSpin); + pNewSpin->SetBuddy(GetDlgItem(idEdit)); - return 0; + return 0; } /* @@ -236,15 +236,15 @@ DiskEditDialog::ReplaceSpinCtrl(MySpinCtrl* pNewSpin, int idSpin, int idEdit) BOOL DiskEditDialog::PreTranslateMessage(MSG* pMsg) { - if (pMsg->message == WM_KEYDOWN && + if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN) - { - //WMSG0("RETURN!\n"); - LoadData(); - return TRUE; - } + { + //WMSG0("RETURN!\n"); + LoadData(); + return TRUE; + } - return CDialog::PreTranslateMessage(pMsg); + return CDialog::PreTranslateMessage(pMsg); } /* @@ -254,25 +254,25 @@ DiskEditDialog::PreTranslateMessage(MSG* pMsg) BOOL DiskEditDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WMSG4("HELP: size=%d contextType=%d ctrlID=0x%x contextID=0x%08lx\n", - lpHelpInfo->cbSize, lpHelpInfo->iContextType, lpHelpInfo->iCtrlId, - lpHelpInfo->dwContextId); + WMSG4("HELP: size=%d contextType=%d ctrlID=0x%x contextID=0x%08lx\n", + lpHelpInfo->cbSize, lpHelpInfo->iContextType, lpHelpInfo->iCtrlId, + lpHelpInfo->dwContextId); - DWORD context = lpHelpInfo->iCtrlId; + DWORD context = lpHelpInfo->iCtrlId; - /* map all of the track/sector selection stuff to one item */ - if (context == IDC_DISKEDIT_TRACK || - context == IDC_DISKEDIT_TRACKSPIN || - context == IDC_STEXT_TRACK || - context == IDC_DISKEDIT_SECTOR || - context == IDC_DISKEDIT_SECTORSPIN || - context == IDC_STEXT_SECTOR) - { - context = IDC_DISKEDIT_TRACK; - } + /* map all of the track/sector selection stuff to one item */ + if (context == IDC_DISKEDIT_TRACK || + context == IDC_DISKEDIT_TRACKSPIN || + context == IDC_STEXT_TRACK || + context == IDC_DISKEDIT_SECTOR || + context == IDC_DISKEDIT_SECTORSPIN || + context == IDC_STEXT_SECTOR) + { + context = IDC_DISKEDIT_TRACK; + } - WinHelp(context, HELP_CONTEXTPOPUP); - return TRUE; // indicate success?? + WinHelp(context, HELP_CONTEXTPOPUP); + return TRUE; // indicate success?? } /* @@ -281,7 +281,7 @@ DiskEditDialog::OnHelpInfo(HELPINFO* lpHelpInfo) void DiskEditDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_DISKEDIT, HELP_CONTEXT); + WinHelp(HELP_TOPIC_DISKEDIT, HELP_CONTEXT); } /* @@ -291,8 +291,8 @@ DiskEditDialog::OnHelp(void) void DiskEditDialog::OnDone(void) { - WMSG0("DiskEditDialog OnDone\n"); - EndDialog(IDOK); + WMSG0("DiskEditDialog OnDone\n"); + EndDialog(IDOK); } /* @@ -301,18 +301,18 @@ DiskEditDialog::OnDone(void) void DiskEditDialog::OnHexMode(void) { - int base; + int base; - CButton* pButton = (CButton*) GetDlgItem(IDC_DISKEDIT_HEX); - ASSERT(pButton != nil); + CButton* pButton = (CButton*) GetDlgItem(IDC_DISKEDIT_HEX); + ASSERT(pButton != nil); - if (pButton->GetCheck() == 0) - base = 10; - else - base = 16; + if (pButton->GetCheck() == 0) + base = 10; + else + base = 16; - SetSpinMode(IDC_DISKEDIT_TRACKSPIN, base); - SetSpinMode(IDC_DISKEDIT_SECTORSPIN, base); + SetSpinMode(IDC_DISKEDIT_TRACKSPIN, base); + SetSpinMode(IDC_DISKEDIT_SECTORSPIN, base); } /* @@ -321,34 +321,34 @@ DiskEditDialog::OnHexMode(void) void DiskEditDialog::OnSubVolume(void) { - SubVolumeDialog subv(this); - bool showAsBlocks; + SubVolumeDialog subv(this); + bool showAsBlocks; - subv.Setup(fpDiskFS); - if (subv.DoModal() == IDOK) { - WMSG1("SELECTED subv %d\n", subv.fListBoxIndex); - DiskFS::SubVolume* pSubVol = fpDiskFS->GetNextSubVolume(nil); - if (pSubVol == nil) - return; + subv.Setup(fpDiskFS); + if (subv.DoModal() == IDOK) { + WMSG1("SELECTED subv %d\n", subv.fListBoxIndex); + DiskFS::SubVolume* pSubVol = fpDiskFS->GetNextSubVolume(nil); + if (pSubVol == nil) + return; - while (subv.fListBoxIndex-- > 0) { - pSubVol = fpDiskFS->GetNextSubVolume(pSubVol); - } - ASSERT(pSubVol != nil); + while (subv.fListBoxIndex-- > 0) { + pSubVol = fpDiskFS->GetNextSubVolume(pSubVol); + } + ASSERT(pSubVol != nil); - BlockEditDialog blockEdit; - SectorEditDialog sectorEdit; - DiskEditDialog* pEditDialog; + BlockEditDialog blockEdit; + SectorEditDialog sectorEdit; + DiskEditDialog* pEditDialog; - showAsBlocks = pSubVol->GetDiskImg()->ShowAsBlocks(); - if (showAsBlocks) - pEditDialog = &blockEdit; - else - pEditDialog = §orEdit; - pEditDialog->Setup(pSubVol->GetDiskFS(), fpDiskFS->GetVolumeID()); - pEditDialog->SetPositionShift(8); - (void) pEditDialog->DoModal(); - } + showAsBlocks = pSubVol->GetDiskImg()->ShowAsBlocks(); + if (showAsBlocks) + pEditDialog = &blockEdit; + else + pEditDialog = §orEdit; + pEditDialog->Setup(pSubVol->GetDiskFS(), fpDiskFS->GetVolumeID()); + pEditDialog->SetPositionShift(8); + (void) pEditDialog->DoModal(); + } } /* @@ -360,31 +360,31 @@ DiskEditDialog::OnSubVolume(void) void DiskEditDialog::SetSpinMode(int id, int base) { - CString valStr; + CString valStr; - ASSERT(base == 10 || base == 16); + ASSERT(base == 10 || base == 16); - MySpinCtrl* pSpin = (MySpinCtrl*) GetDlgItem(id); - if (pSpin == nil) { - // expected behavior in "block" mode for sector button - WMSG1("Couldn't find spin button %d\n", id); - return; - } + MySpinCtrl* pSpin = (MySpinCtrl*) GetDlgItem(id); + if (pSpin == nil) { + // expected behavior in "block" mode for sector button + WMSG1("Couldn't find spin button %d\n", id); + return; + } - long val = pSpin->GetPos(); - if (val & 0xff000000) { - WMSG0("NOTE: hex transition while value is invalid\n"); - val = 0; - } + long val = pSpin->GetPos(); + if (val & 0xff000000) { + WMSG0("NOTE: hex transition while value is invalid\n"); + val = 0; + } - if (base == 10) - valStr.Format("%d", val); - else - valStr.Format("%X", val); + if (base == 10) + valStr.Format("%d", val); + else + valStr.Format("%X", val); - pSpin->SetBase(base); - pSpin->GetBuddy()->SetWindowText(valStr); - WMSG2("Set spin button base to %d val=%d\n", base, val); + pSpin->SetBase(base); + pSpin->GetBuddy()->SetWindowText(valStr); + WMSG2("Set spin button base to %d val=%d\n", base, val); } /* @@ -396,25 +396,25 @@ DiskEditDialog::SetSpinMode(int id, int base) int DiskEditDialog::ReadSpinner(int id, long* pVal) { - MySpinCtrl* pSpin = (MySpinCtrl*) GetDlgItem(id); - ASSERT(pSpin != nil); + MySpinCtrl* pSpin = (MySpinCtrl*) GetDlgItem(id); + ASSERT(pSpin != nil); - long val = pSpin->GetPos(); - if (val & 0xff000000) { - /* error */ - CString msg; - CString err; - err.LoadString(IDS_ERROR); - int lower, upper; - pSpin->GetRange32(lower, upper); - msg.Format("Please enter a value between %d and %d (0x%x and 0x%x).", - lower, upper, lower, upper); - MessageBox(msg, err, MB_OK|MB_ICONEXCLAMATION); - return -1; - } + long val = pSpin->GetPos(); + if (val & 0xff000000) { + /* error */ + CString msg; + CString err; + err.LoadString(IDS_ERROR); + int lower, upper; + pSpin->GetRange32(lower, upper); + msg.Format("Please enter a value between %d and %d (0x%x and 0x%x).", + lower, upper, lower, upper); + MessageBox(msg, err, MB_OK|MB_ICONEXCLAMATION); + return -1; + } - *pVal = val; - return 0; + *pVal = val; + return 0; } /* @@ -423,15 +423,15 @@ DiskEditDialog::ReadSpinner(int id, long* pVal) void DiskEditDialog::SetSpinner(int id, long val) { - MySpinCtrl* pSpin = (MySpinCtrl*) GetDlgItem(id); - ASSERT(pSpin != nil); + MySpinCtrl* pSpin = (MySpinCtrl*) GetDlgItem(id); + ASSERT(pSpin != nil); - /* sanity check */ - int lower, upper; - pSpin->GetRange32(lower, upper); - ASSERT(val >= lower && val <= upper); + /* sanity check */ + int lower, upper; + pSpin->GetRange32(lower, upper); + ASSERT(val >= lower && val <= upper); - pSpin->SetPos(val); + pSpin->SetPos(val); } /* @@ -440,79 +440,79 @@ DiskEditDialog::SetSpinner(int id, long val) void DiskEditDialog::DisplayData(const unsigned char* srcBuf, int size) { - char textBuf[80 * 16 * 2]; - char* cp; - int i, j; + char textBuf[80 * 16 * 2]; + char* cp; + int i, j; - ASSERT(srcBuf != nil); - ASSERT(size == kSectorSize || size == kBlockSize); + ASSERT(srcBuf != nil); + ASSERT(size == kSectorSize || size == kBlockSize); - CRichEditCtrl* pEdit = (CRichEditCtrl*)GetDlgItem(IDC_DISKEDIT_EDIT); - ASSERT(pEdit != nil); + CRichEditCtrl* pEdit = (CRichEditCtrl*)GetDlgItem(IDC_DISKEDIT_EDIT); + ASSERT(pEdit != nil); - /* - * If we have an alert message, show that instead. - */ - if (!fAlertMsg.IsEmpty()) { - const int kWidth = 72; - int indent = (kWidth/2) - (fAlertMsg.GetLength() / 2); - if (indent < 0) - indent = 0; + /* + * If we have an alert message, show that instead. + */ + if (!fAlertMsg.IsEmpty()) { + const int kWidth = 72; + int indent = (kWidth/2) - (fAlertMsg.GetLength() / 2); + if (indent < 0) + indent = 0; - CString msg = " " - " "; - ASSERT(msg.GetLength() == kWidth); - msg = msg.Left(indent); - msg += fAlertMsg; - for (i = 0; i < (size / 16)-2; i += 2) { - textBuf[i] = '\r'; - textBuf[i+1] = '\n'; - } - strcpy(&textBuf[i], msg); - pEdit->SetWindowText(textBuf); + CString msg = " " + " "; + ASSERT(msg.GetLength() == kWidth); + msg = msg.Left(indent); + msg += fAlertMsg; + for (i = 0; i < (size / 16)-2; i += 2) { + textBuf[i] = '\r'; + textBuf[i+1] = '\n'; + } + strcpy(&textBuf[i], msg); + pEdit->SetWindowText(textBuf); - return; - } + return; + } - /* - * No alert, do the usual thing. - */ - cp = textBuf; - for (i = 0; i < size/16; i++) { - if (size == kSectorSize) { - /* two-nybble addr */ - sprintf(cp, " %02x: %02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x ", - i * 16, - srcBuf[0], srcBuf[1], srcBuf[2], srcBuf[3], - srcBuf[4], srcBuf[5], srcBuf[6], srcBuf[7], - srcBuf[8], srcBuf[9], srcBuf[10], srcBuf[11], - srcBuf[12], srcBuf[13], srcBuf[14], srcBuf[15]); - } else { - /* three-nybble addr */ - sprintf(cp, "%03x: %02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x ", - i * 16, - srcBuf[0], srcBuf[1], srcBuf[2], srcBuf[3], - srcBuf[4], srcBuf[5], srcBuf[6], srcBuf[7], - srcBuf[8], srcBuf[9], srcBuf[10], srcBuf[11], - srcBuf[12], srcBuf[13], srcBuf[14], srcBuf[15]); - } - ASSERT(strlen(cp) == 54); - cp += 54; // strlen(cp) - for (j = 0; j < 16; j++) - *cp++ = PrintableChar(srcBuf[j]); + /* + * No alert, do the usual thing. + */ + cp = textBuf; + for (i = 0; i < size/16; i++) { + if (size == kSectorSize) { + /* two-nybble addr */ + sprintf(cp, " %02x: %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x ", + i * 16, + srcBuf[0], srcBuf[1], srcBuf[2], srcBuf[3], + srcBuf[4], srcBuf[5], srcBuf[6], srcBuf[7], + srcBuf[8], srcBuf[9], srcBuf[10], srcBuf[11], + srcBuf[12], srcBuf[13], srcBuf[14], srcBuf[15]); + } else { + /* three-nybble addr */ + sprintf(cp, "%03x: %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x ", + i * 16, + srcBuf[0], srcBuf[1], srcBuf[2], srcBuf[3], + srcBuf[4], srcBuf[5], srcBuf[6], srcBuf[7], + srcBuf[8], srcBuf[9], srcBuf[10], srcBuf[11], + srcBuf[12], srcBuf[13], srcBuf[14], srcBuf[15]); + } + ASSERT(strlen(cp) == 54); + cp += 54; // strlen(cp) + for (j = 0; j < 16; j++) + *cp++ = PrintableChar(srcBuf[j]); - *cp++ = '\r'; - *cp++ = '\n'; + *cp++ = '\r'; + *cp++ = '\n'; - srcBuf += 16; - } - /* kill the last EOL, so the cursor doesn't move past that line */ - cp--; - *cp = '\0'; + srcBuf += 16; + } + /* kill the last EOL, so the cursor doesn't move past that line */ + cp--; + *cp = '\0'; - pEdit->SetWindowText(textBuf); + pEdit->SetWindowText(textBuf); } /* @@ -521,76 +521,76 @@ DiskEditDialog::DisplayData(const unsigned char* srcBuf, int size) void DiskEditDialog::DisplayNibbleData(const unsigned char* srcBuf, int size) { - ASSERT(srcBuf != nil); - ASSERT(size > 0); - ASSERT(fAlertMsg.IsEmpty()); + ASSERT(srcBuf != nil); + ASSERT(size > 0); + ASSERT(fAlertMsg.IsEmpty()); - int bufSize = ((size+15) / 16) * 80; - char* textBuf = new char[bufSize]; - char* cp; - int i; + int bufSize = ((size+15) / 16) * 80; + char* textBuf = new char[bufSize]; + char* cp; + int i; - if (textBuf == nil) - return; + if (textBuf == nil) + return; - cp = textBuf; - for (i = 0; size > 0; i++) { - if (size >= 16) { - sprintf(cp, "%04x: %02x %02x %02x %02x %02x %02x %02x %02x " - "%02x %02x %02x %02x %02x %02x %02x %02x", - i * 16, - srcBuf[0], srcBuf[1], srcBuf[2], srcBuf[3], - srcBuf[4], srcBuf[5], srcBuf[6], srcBuf[7], - srcBuf[8], srcBuf[9], srcBuf[10], srcBuf[11], - srcBuf[12], srcBuf[13], srcBuf[14], srcBuf[15]); - ASSERT(strlen(cp) == 53); - cp += 53; // strlen(cp) - } else { - sprintf(cp, "%04x:", i * 16); - cp += 5; - for (int j = 0; j < size; j++) { - sprintf(cp, " %02x", srcBuf[j]); - cp += 3; - } - } + cp = textBuf; + for (i = 0; size > 0; i++) { + if (size >= 16) { + sprintf(cp, "%04x: %02x %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x", + i * 16, + srcBuf[0], srcBuf[1], srcBuf[2], srcBuf[3], + srcBuf[4], srcBuf[5], srcBuf[6], srcBuf[7], + srcBuf[8], srcBuf[9], srcBuf[10], srcBuf[11], + srcBuf[12], srcBuf[13], srcBuf[14], srcBuf[15]); + ASSERT(strlen(cp) == 53); + cp += 53; // strlen(cp) + } else { + sprintf(cp, "%04x:", i * 16); + cp += 5; + for (int j = 0; j < size; j++) { + sprintf(cp, " %02x", srcBuf[j]); + cp += 3; + } + } - *cp++ = '\r'; - *cp++ = '\n'; + *cp++ = '\r'; + *cp++ = '\n'; - srcBuf += 16; - size -= 16; - } - /* kill the last EOL, so the cursor doesn't move past that line */ - cp--; - *cp = '\0'; + srcBuf += 16; + size -= 16; + } + /* kill the last EOL, so the cursor doesn't move past that line */ + cp--; + *cp = '\0'; - CRichEditCtrl* pEdit = (CRichEditCtrl*)GetDlgItem(IDC_DISKEDIT_EDIT); - ASSERT(pEdit != nil); - pEdit->SetWindowText(textBuf); + CRichEditCtrl* pEdit = (CRichEditCtrl*)GetDlgItem(IDC_DISKEDIT_EDIT); + ASSERT(pEdit != nil); + pEdit->SetWindowText(textBuf); - /* - * Handle resize of edit box. We have to do this late or the scroll bar - * won't appear under Win98. (Whatever.) - */ - if (fFirstResize) { - fFirstResize = false; + /* + * Handle resize of edit box. We have to do this late or the scroll bar + * won't appear under Win98. (Whatever.) + */ + if (fFirstResize) { + fFirstResize = false; - const int kStretchHeight = 249; - CRect rect; + const int kStretchHeight = 249; + CRect rect; - GetWindowRect(&rect); + GetWindowRect(&rect); - CRect inner; - pEdit->GetRect(&inner); - inner.bottom += kStretchHeight; - pEdit->GetWindowRect(&rect); - ScreenToClient(&rect); - rect.bottom += kStretchHeight; - pEdit->MoveWindow(&rect); - pEdit->SetRect(&inner); - } + CRect inner; + pEdit->GetRect(&inner); + inner.bottom += kStretchHeight; + pEdit->GetWindowRect(&rect); + ScreenToClient(&rect); + rect.bottom += kStretchHeight; + pEdit->MoveWindow(&rect); + pEdit->SetRect(&inner); + } - delete[] textBuf; + delete[] textBuf; } @@ -603,38 +603,38 @@ DiskEditDialog::DisplayNibbleData(const unsigned char* srcBuf, int size) */ DIError DiskEditDialog::OpenFile(const char* fileName, bool openRsrc, A2File** ppFile, - A2FileDescr** ppOpenFile) + A2FileDescr** ppOpenFile) { - A2File* pFile; - A2FileDescr* pOpenFile = nil; + A2File* pFile; + A2FileDescr* pOpenFile = nil; - WMSG2(" OpenFile '%s' rsrc=%d\n", fileName, openRsrc); - pFile = fpDiskFS->GetFileByName(fileName); - if (pFile == nil) { - CString msg, failed; + WMSG2(" OpenFile '%s' rsrc=%d\n", fileName, openRsrc); + pFile = fpDiskFS->GetFileByName(fileName); + if (pFile == nil) { + CString msg, failed; - msg.Format(IDS_DEFILE_FIND_FAILED, fileName); - failed.LoadString(IDS_FAILED); - MessageBox(msg, failed, MB_OK | MB_ICONSTOP); - return kDIErrFileNotFound; - } + msg.Format(IDS_DEFILE_FIND_FAILED, fileName); + failed.LoadString(IDS_FAILED); + MessageBox(msg, failed, MB_OK | MB_ICONSTOP); + return kDIErrFileNotFound; + } - DIError dierr; - dierr = pFile->Open(&pOpenFile, true, openRsrc); - if (dierr != kDIErrNone) { - CString msg, failed; + DIError dierr; + dierr = pFile->Open(&pOpenFile, true, openRsrc); + if (dierr != kDIErrNone) { + CString msg, failed; - msg.Format(IDS_DEFILE_OPEN_FAILED, fileName, - DiskImgLib::DIStrError(dierr)); - failed.LoadString(IDS_FAILED); - MessageBox(msg, failed, MB_OK | MB_ICONSTOP); - return dierr; - } + msg.Format(IDS_DEFILE_OPEN_FAILED, fileName, + DiskImgLib::DIStrError(dierr)); + failed.LoadString(IDS_FAILED); + MessageBox(msg, failed, MB_OK | MB_ICONSTOP); + return dierr; + } - *ppFile = pFile; - *ppOpenFile = pOpenFile; + *ppFile = pFile; + *ppOpenFile = pOpenFile; - return kDIErrNone; + return kDIErrNone; } @@ -646,28 +646,28 @@ DiskEditDialog::OpenFile(const char* fileName, bool openRsrc, A2File** ppFile, void DiskEditDialog::OnNibbleParms(void) { - DiskImg* pDiskImg = fpDiskFS->GetDiskImg(); - CComboBox* pCombo; - int sel; + DiskImg* pDiskImg = fpDiskFS->GetDiskImg(); + CComboBox* pCombo; + int sel; - ASSERT(pDiskImg != nil); - ASSERT(pDiskImg->GetHasNibbles()); + ASSERT(pDiskImg != nil); + ASSERT(pDiskImg->GetHasNibbles()); - pCombo = (CComboBox*) GetDlgItem(IDC_DISKEDIT_NIBBLE_PARMS); - ASSERT(pCombo != nil); + pCombo = (CComboBox*) GetDlgItem(IDC_DISKEDIT_NIBBLE_PARMS); + ASSERT(pCombo != nil); - sel = pCombo->GetCurSel(); - if (sel == CB_ERR) - return; + sel = pCombo->GetCurSel(); + if (sel == CB_ERR) + return; - WMSG1(" OnNibbleParms: entry %d now selected\n", sel); - const DiskImg::NibbleDescr* pNibbleTable; - int count; - pNibbleTable = pDiskImg->GetNibbleDescrTable(&count); - ASSERT(sel < count); - pDiskImg->SetNibbleDescr(sel); + WMSG1(" OnNibbleParms: entry %d now selected\n", sel); + const DiskImg::NibbleDescr* pNibbleTable; + int count; + pNibbleTable = pDiskImg->GetNibbleDescrTable(&count); + ASSERT(sel < count); + pDiskImg->SetNibbleDescr(sel); - LoadData(); + LoadData(); } @@ -678,25 +678,25 @@ DiskEditDialog::OnNibbleParms(void) */ void DiskEditDialog::FillWithPattern(unsigned char* buf, int size, - const char* pattern) + const char* pattern) { - const char* cp; - unsigned char* ucp; + const char* cp; + unsigned char* ucp; - ucp = buf; - cp = pattern; - while (ucp < buf+size) { - *ucp++ = *cp++; - if (*cp == '\0') - cp = pattern; - } + ucp = buf; + cp = pattern; + while (ucp < buf+size) { + *ucp++ = *cp++; + if (*cp == '\0') + cp = pattern; + } } #endif /* * =========================================================================== - * SectorEditDialog + * SectorEditDialog * =========================================================================== */ @@ -706,42 +706,42 @@ DiskEditDialog::FillWithPattern(unsigned char* buf, int size, BOOL SectorEditDialog::OnInitDialog(void) { - /* - * Do base-class construction. - */ - DiskEditDialog::OnInitDialog(); + /* + * Do base-class construction. + */ + DiskEditDialog::OnInitDialog(); - /* - * Change track/sector text. - */ - CString trackStr; - CWnd* pWnd; - trackStr.Format("Track (%d):", fpDiskFS->GetDiskImg()->GetNumTracks()); - pWnd = GetDlgItem(IDC_STEXT_TRACK); - ASSERT(pWnd != nil); - pWnd->SetWindowText(trackStr); - trackStr.Format("Sector (%d):", fpDiskFS->GetDiskImg()->GetNumSectPerTrack()); - pWnd = GetDlgItem(IDC_STEXT_SECTOR); - ASSERT(pWnd != nil); - pWnd->SetWindowText(trackStr); + /* + * Change track/sector text. + */ + CString trackStr; + CWnd* pWnd; + trackStr.Format("Track (%d):", fpDiskFS->GetDiskImg()->GetNumTracks()); + pWnd = GetDlgItem(IDC_STEXT_TRACK); + ASSERT(pWnd != nil); + pWnd->SetWindowText(trackStr); + trackStr.Format("Sector (%d):", fpDiskFS->GetDiskImg()->GetNumSectPerTrack()); + pWnd = GetDlgItem(IDC_STEXT_SECTOR); + ASSERT(pWnd != nil); + pWnd->SetWindowText(trackStr); - /* - * Configure the spin buttons. - */ - MySpinCtrl* pSpin; - pSpin = (MySpinCtrl*)GetDlgItem(IDC_DISKEDIT_TRACKSPIN); - ASSERT(pSpin != nil); - pSpin->SetRange32(0, fpDiskFS->GetDiskImg()->GetNumTracks()-1); - pSpin->SetPos(0); - pSpin = (MySpinCtrl*)GetDlgItem(IDC_DISKEDIT_SECTORSPIN); - ASSERT(pSpin != nil); - pSpin->SetRange32(0, fpDiskFS->GetDiskImg()->GetNumSectPerTrack()-1); - pSpin->SetPos(0); + /* + * Configure the spin buttons. + */ + MySpinCtrl* pSpin; + pSpin = (MySpinCtrl*)GetDlgItem(IDC_DISKEDIT_TRACKSPIN); + ASSERT(pSpin != nil); + pSpin->SetRange32(0, fpDiskFS->GetDiskImg()->GetNumTracks()-1); + pSpin->SetPos(0); + pSpin = (MySpinCtrl*)GetDlgItem(IDC_DISKEDIT_SECTORSPIN); + ASSERT(pSpin != nil); + pSpin->SetRange32(0, fpDiskFS->GetDiskImg()->GetNumSectPerTrack()-1); + pSpin->SetPos(0); - /* give us something to look at */ - LoadData(); + /* give us something to look at */ + LoadData(); - return TRUE; + return TRUE; } /* @@ -752,34 +752,34 @@ SectorEditDialog::OnInitDialog(void) int SectorEditDialog::LoadData(void) { - //WMSG0("SED LoadData\n"); - ASSERT(fpDiskFS != nil); - ASSERT(fpDiskFS->GetDiskImg() != nil); + //WMSG0("SED LoadData\n"); + ASSERT(fpDiskFS != nil); + ASSERT(fpDiskFS->GetDiskImg() != nil); - if (ReadSpinner(IDC_DISKEDIT_TRACKSPIN, &fTrack) != 0) - return -1; - if (ReadSpinner(IDC_DISKEDIT_SECTORSPIN, &fSector) != 0) - return -1; + if (ReadSpinner(IDC_DISKEDIT_TRACKSPIN, &fTrack) != 0) + return -1; + if (ReadSpinner(IDC_DISKEDIT_SECTORSPIN, &fSector) != 0) + return -1; - WMSG2("LoadData reading t=%d s=%d\n", fTrack, fSector); + WMSG2("LoadData reading t=%d s=%d\n", fTrack, fSector); - fAlertMsg = ""; - DIError dierr; - dierr = fpDiskFS->GetDiskImg()->ReadTrackSector(fTrack, fSector, fSectorData); - if (dierr != kDIErrNone) { - WMSG1("SED sector read failed: %s\n", DiskImgLib::DIStrError(dierr)); - //CString msg; - //CString err; - //err.LoadString(IDS_ERROR); - //msg.Format(IDS_DISKEDIT_NOREADTS, fTrack, fSector); - //MessageBox(msg, err, MB_OK|MB_ICONSTOP); - fAlertMsg.LoadString(IDS_DISKEDITMSG_BADSECTOR); - //return -1; - } + fAlertMsg = ""; + DIError dierr; + dierr = fpDiskFS->GetDiskImg()->ReadTrackSector(fTrack, fSector, fSectorData); + if (dierr != kDIErrNone) { + WMSG1("SED sector read failed: %s\n", DiskImgLib::DIStrError(dierr)); + //CString msg; + //CString err; + //err.LoadString(IDS_ERROR); + //msg.Format(IDS_DISKEDIT_NOREADTS, fTrack, fSector); + //MessageBox(msg, err, MB_OK|MB_ICONSTOP); + fAlertMsg.LoadString(IDS_DISKEDITMSG_BADSECTOR); + //return -1; + } - DisplayData(); + DisplayData(); - return 0; + return 0; } /* @@ -788,7 +788,7 @@ SectorEditDialog::LoadData(void) void SectorEditDialog::OnDoRead(void) { - LoadData(); + LoadData(); } /* @@ -797,7 +797,7 @@ SectorEditDialog::OnDoRead(void) void SectorEditDialog::OnDoWrite(void) { - MessageBox("Write!"); + MessageBox("Write!"); } /* @@ -806,20 +806,20 @@ SectorEditDialog::OnDoWrite(void) void SectorEditDialog::OnReadPrev(void) { - if (fTrack == 0 && fSector == 0) - return; + if (fTrack == 0 && fSector == 0) + return; - if (fSector == 0) { - fSector = fpDiskFS->GetDiskImg()->GetNumSectPerTrack() -1; - fTrack--; - } else { - fSector--; - } + if (fSector == 0) { + fSector = fpDiskFS->GetDiskImg()->GetNumSectPerTrack() -1; + fTrack--; + } else { + fSector--; + } - SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack); - SetSpinner(IDC_DISKEDIT_SECTORSPIN, fSector); + SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack); + SetSpinner(IDC_DISKEDIT_SECTORSPIN, fSector); - LoadData(); + LoadData(); } /* @@ -828,23 +828,23 @@ SectorEditDialog::OnReadPrev(void) void SectorEditDialog::OnReadNext(void) { - int numTracks = fpDiskFS->GetDiskImg()->GetNumTracks(); - int numSects = fpDiskFS->GetDiskImg()->GetNumSectPerTrack(); + int numTracks = fpDiskFS->GetDiskImg()->GetNumTracks(); + int numSects = fpDiskFS->GetDiskImg()->GetNumSectPerTrack(); - if (fTrack == numTracks-1 && fSector == numSects-1) - return; + if (fTrack == numTracks-1 && fSector == numSects-1) + return; - if (fSector == numSects-1) { - fSector = 0; - fTrack++; - } else { - fSector++; - } + if (fSector == numSects-1) { + fSector = 0; + fTrack++; + } else { + fSector++; + } - SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack); - SetSpinner(IDC_DISKEDIT_SECTORSPIN, fSector); + SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack); + SetSpinner(IDC_DISKEDIT_SECTORSPIN, fSector); - LoadData(); + LoadData(); } @@ -855,32 +855,32 @@ SectorEditDialog::OnReadNext(void) void SectorEditDialog::OnOpenFile(void) { - DEFileDialog fileDialog(this); + DEFileDialog fileDialog(this); - if (fileDialog.DoModal() == IDOK) { - SectorFileEditDialog fileEdit(this, this); - A2File* pFile; - A2FileDescr* pOpenFile = nil; - DIError dierr; + if (fileDialog.DoModal() == IDOK) { + SectorFileEditDialog fileEdit(this, this); + A2File* pFile; + A2FileDescr* pOpenFile = nil; + DIError dierr; - dierr = OpenFile(fileDialog.fName, fileDialog.fOpenRsrcFork != 0, - &pFile, &pOpenFile); - if (dierr != kDIErrNone) - return; + dierr = OpenFile(fileDialog.fName, fileDialog.fOpenRsrcFork != 0, + &pFile, &pOpenFile); + if (dierr != kDIErrNone) + return; - fileEdit.SetupFile(fileDialog.fName, fileDialog.fOpenRsrcFork != 0, - pFile, pOpenFile); - fileEdit.SetPositionShift(8); - (void) fileEdit.DoModal(); + fileEdit.SetupFile(fileDialog.fName, fileDialog.fOpenRsrcFork != 0, + pFile, pOpenFile); + fileEdit.SetPositionShift(8); + (void) fileEdit.DoModal(); - pOpenFile->Close(); - } + pOpenFile->Close(); + } } /* * =========================================================================== - * SectorFileEditDialog + * SectorFileEditDialog * =========================================================================== */ @@ -890,44 +890,44 @@ SectorEditDialog::OnOpenFile(void) BOOL SectorFileEditDialog::OnInitDialog(void) { - BOOL retval; + BOOL retval; - /* do base class first */ - retval = SectorEditDialog::OnInitDialog(); + /* do base class first */ + retval = SectorEditDialog::OnInitDialog(); - /* disable direct entry of tracks and sectors */ - CWnd* pWnd; - pWnd = GetDlgItem(IDC_DISKEDIT_TRACKSPIN); - ASSERT(pWnd != nil); - pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_DISKEDIT_SECTORSPIN); - ASSERT(pWnd != nil); - pWnd->EnableWindow(FALSE); + /* disable direct entry of tracks and sectors */ + CWnd* pWnd; + pWnd = GetDlgItem(IDC_DISKEDIT_TRACKSPIN); + ASSERT(pWnd != nil); + pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_DISKEDIT_SECTORSPIN); + ASSERT(pWnd != nil); + pWnd->EnableWindow(FALSE); - /* disallow opening of sub-volumes and files */ - pWnd = GetDlgItem(IDC_DISKEDIT_OPENFILE); - pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_DISKEDIT_SUBVOLUME); - pWnd->EnableWindow(FALSE); + /* disallow opening of sub-volumes and files */ + pWnd = GetDlgItem(IDC_DISKEDIT_OPENFILE); + pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_DISKEDIT_SUBVOLUME); + pWnd->EnableWindow(FALSE); - CEdit* pEdit; - pEdit = (CEdit*) GetDlgItem(IDC_DISKEDIT_TRACK); - ASSERT(pEdit != nil); - pEdit->SetReadOnly(TRUE); - pEdit = (CEdit*) GetDlgItem(IDC_DISKEDIT_SECTOR); - ASSERT(pEdit != nil); - pEdit->SetReadOnly(TRUE); + CEdit* pEdit; + pEdit = (CEdit*) GetDlgItem(IDC_DISKEDIT_TRACK); + ASSERT(pEdit != nil); + pEdit->SetReadOnly(TRUE); + pEdit = (CEdit*) GetDlgItem(IDC_DISKEDIT_SECTOR); + ASSERT(pEdit != nil); + pEdit->SetReadOnly(TRUE); - /* set the window title */ - CString title; - CString rsrcIndic; - rsrcIndic.LoadString(IDS_INDIC_RSRC); - title.Format("Disk Viewer - %s%s (%ld bytes)", - fpFile->GetPathName(), // use fpFile version to get case - fOpenRsrcFork ? (LPCTSTR)rsrcIndic : "", fLength); - SetWindowText(title); + /* set the window title */ + CString title; + CString rsrcIndic; + rsrcIndic.LoadString(IDS_INDIC_RSRC); + title.Format("Disk Viewer - %s%s (%ld bytes)", + fpFile->GetPathName(), // use fpFile version to get case + fOpenRsrcFork ? (LPCTSTR)rsrcIndic : "", fLength); + SetWindowText(title); - return retval; + return retval; } /* @@ -938,100 +938,100 @@ SectorFileEditDialog::OnInitDialog(void) int SectorFileEditDialog::LoadData(void) { - ASSERT(fpDiskFS != nil); - ASSERT(fpDiskFS->GetDiskImg() != nil); + ASSERT(fpDiskFS != nil); + ASSERT(fpDiskFS->GetDiskImg() != nil); - DIError dierr; - WMSG1("SFED LoadData reading index=%d\n", fSectorIdx); + DIError dierr; + WMSG1("SFED LoadData reading index=%d\n", fSectorIdx); #if 0 - WMSG1("LoadData reading offset=%d\n", fOffset); - size_t actual = 0; - dierr = fpFile->Seek(fOffset, EmbeddedFD::kSeekSet); - if (dierr == kDIErrNone) { - dierr = fpFile->Read(fSectorData, 1 /*kSectorSize*/, &actual); - } - if (dierr != kDIErrNone) { - CString msg, failed; - failed.LoadString(IDS_FAILED); - msg.Format(IDS_DISKEDIT_FIRDFAILED, DiskImg::DIStrError(dierr)); - MessageBox(msg, failed, MB_OK); - // TO DO: mark contents as invalid, so editing fails - return -1; - } + WMSG1("LoadData reading offset=%d\n", fOffset); + size_t actual = 0; + dierr = fpFile->Seek(fOffset, EmbeddedFD::kSeekSet); + if (dierr == kDIErrNone) { + dierr = fpFile->Read(fSectorData, 1 /*kSectorSize*/, &actual); + } + if (dierr != kDIErrNone) { + CString msg, failed; + failed.LoadString(IDS_FAILED); + msg.Format(IDS_DISKEDIT_FIRDFAILED, DiskImg::DIStrError(dierr)); + MessageBox(msg, failed, MB_OK); + // TO DO: mark contents as invalid, so editing fails + return -1; + } - if (actual != kSectorSize) { - WMSG1(" SFED partial read of %d bytes\n", actual); - ASSERT(actual < kSectorSize && actual >= 0); - } + if (actual != kSectorSize) { + WMSG1(" SFED partial read of %d bytes\n", actual); + ASSERT(actual < kSectorSize && actual >= 0); + } - /* - * We've read the data, but we can't use it. We're a sector editor, - * not a file editor, and we need to get the actual sector data without - * EOF trimming or CP/M 0xe5 removal. - */ - fpFile->GetLastLocationRead(&fTrack, &fSector); - if (fTrack == A2File::kLastWasSparse && fSector == A2File::kLastWasSparse) + /* + * We've read the data, but we can't use it. We're a sector editor, + * not a file editor, and we need to get the actual sector data without + * EOF trimming or CP/M 0xe5 removal. + */ + fpFile->GetLastLocationRead(&fTrack, &fSector); + if (fTrack == A2File::kLastWasSparse && fSector == A2File::kLastWasSparse) - ; + ; #endif - fAlertMsg = ""; + fAlertMsg = ""; - dierr = fpOpenFile->GetStorage(fSectorIdx, &fTrack, &fSector); - if (dierr == kDIErrInvalidIndex && fSectorIdx == 0) { - // no first sector; should only happen on CP/M - //FillWithPattern(fSectorData, sizeof(fSectorData), _T("EMPTY ")); - fAlertMsg.LoadString(IDS_DISKEDITMSG_EMPTY); - } else if (dierr != kDIErrNone) { - CString msg, failed; - failed.LoadString(IDS_FAILED); - msg.Format(IDS_DISKEDIT_FIRDFAILED, DiskImgLib::DIStrError(dierr)); - MessageBox(msg, failed, MB_OK); - fAlertMsg.LoadString(IDS_FAILED); - // TO DO: mark contents as invalid, so editing fails - return -1; - } else { - if (fTrack == 0 && fSector == 0) { - WMSG0("LoadData Sparse sector\n"); - //FillWithPattern(fSectorData, sizeof(fSectorData), _T("SPARSE ")); - fAlertMsg.Format(IDS_DISKEDITMSG_SPARSE, fSectorIdx); - } else { - WMSG2("LoadData reading T=%d S=%d\n", fTrack, fSector); + dierr = fpOpenFile->GetStorage(fSectorIdx, &fTrack, &fSector); + if (dierr == kDIErrInvalidIndex && fSectorIdx == 0) { + // no first sector; should only happen on CP/M + //FillWithPattern(fSectorData, sizeof(fSectorData), _T("EMPTY ")); + fAlertMsg.LoadString(IDS_DISKEDITMSG_EMPTY); + } else if (dierr != kDIErrNone) { + CString msg, failed; + failed.LoadString(IDS_FAILED); + msg.Format(IDS_DISKEDIT_FIRDFAILED, DiskImgLib::DIStrError(dierr)); + MessageBox(msg, failed, MB_OK); + fAlertMsg.LoadString(IDS_FAILED); + // TO DO: mark contents as invalid, so editing fails + return -1; + } else { + if (fTrack == 0 && fSector == 0) { + WMSG0("LoadData Sparse sector\n"); + //FillWithPattern(fSectorData, sizeof(fSectorData), _T("SPARSE ")); + fAlertMsg.Format(IDS_DISKEDITMSG_SPARSE, fSectorIdx); + } else { + WMSG2("LoadData reading T=%d S=%d\n", fTrack, fSector); - dierr = fpDiskFS->GetDiskImg()->ReadTrackSector(fTrack, fSector, - fSectorData); - if (dierr != kDIErrNone) { - //CString msg; - //CString err; - //err.LoadString(IDS_ERROR); - //msg.Format(IDS_DISKEDIT_NOREADTS, fTrack, fSector); - //MessageBox(msg, err, MB_OK|MB_ICONSTOP); - fAlertMsg.LoadString(IDS_DISKEDITMSG_BADSECTOR); - //return -1; - } - } - } + dierr = fpDiskFS->GetDiskImg()->ReadTrackSector(fTrack, fSector, + fSectorData); + if (dierr != kDIErrNone) { + //CString msg; + //CString err; + //err.LoadString(IDS_ERROR); + //msg.Format(IDS_DISKEDIT_NOREADTS, fTrack, fSector); + //MessageBox(msg, err, MB_OK|MB_ICONSTOP); + fAlertMsg.LoadString(IDS_DISKEDITMSG_BADSECTOR); + //return -1; + } + } + } - SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack); - SetSpinner(IDC_DISKEDIT_SECTORSPIN, fSector); + SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack); + SetSpinner(IDC_DISKEDIT_SECTORSPIN, fSector); - CWnd* pWnd; - pWnd = GetDlgItem(IDC_DISKEDIT_PREV); - ASSERT(pWnd != nil); - pWnd->EnableWindow(fSectorIdx > 0); - if (!pWnd->IsWindowEnabled() && GetFocus() == nil) - GetDlgItem(IDC_DISKEDIT_NEXT)->SetFocus(); + CWnd* pWnd; + pWnd = GetDlgItem(IDC_DISKEDIT_PREV); + ASSERT(pWnd != nil); + pWnd->EnableWindow(fSectorIdx > 0); + if (!pWnd->IsWindowEnabled() && GetFocus() == nil) + GetDlgItem(IDC_DISKEDIT_NEXT)->SetFocus(); - pWnd = GetDlgItem(IDC_DISKEDIT_NEXT); - ASSERT(pWnd != nil); - pWnd->EnableWindow(fSectorIdx+1 < fpOpenFile->GetSectorCount()); - if (!pWnd->IsWindowEnabled() && GetFocus() == nil) - GetDlgItem(IDC_DISKEDIT_PREV)->SetFocus(); + pWnd = GetDlgItem(IDC_DISKEDIT_NEXT); + ASSERT(pWnd != nil); + pWnd->EnableWindow(fSectorIdx+1 < fpOpenFile->GetSectorCount()); + if (!pWnd->IsWindowEnabled() && GetFocus() == nil) + GetDlgItem(IDC_DISKEDIT_PREV)->SetFocus(); - DisplayData(); + DisplayData(); - return 0; + return 0; } /* @@ -1040,12 +1040,12 @@ SectorFileEditDialog::LoadData(void) void SectorFileEditDialog::OnReadPrev(void) { - if (fSectorIdx == 0) - return; + if (fSectorIdx == 0) + return; - fSectorIdx--; - ASSERT(fSectorIdx >= 0); - LoadData(); + fSectorIdx--; + ASSERT(fSectorIdx >= 0); + LoadData(); } /* @@ -1054,18 +1054,18 @@ SectorFileEditDialog::OnReadPrev(void) void SectorFileEditDialog::OnReadNext(void) { - if (fSectorIdx+1 >= fpOpenFile->GetSectorCount()) - return; + if (fSectorIdx+1 >= fpOpenFile->GetSectorCount()) + return; - fSectorIdx++; - ASSERT(fSectorIdx < fpOpenFile->GetSectorCount()); - LoadData(); + fSectorIdx++; + ASSERT(fSectorIdx < fpOpenFile->GetSectorCount()); + LoadData(); } /* * =========================================================================== - * BlockEditDialog + * BlockEditDialog * =========================================================================== */ @@ -1076,73 +1076,73 @@ SectorFileEditDialog::OnReadNext(void) BOOL BlockEditDialog::OnInitDialog(void) { - /* - * Get rid of the "sector" input item, and change the "track" input - * item to accept blocks instead. - */ - CWnd* pWnd; + /* + * Get rid of the "sector" input item, and change the "track" input + * item to accept blocks instead. + */ + CWnd* pWnd; - pWnd = GetDlgItem(IDC_STEXT_SECTOR); - pWnd->DestroyWindow(); - pWnd = GetDlgItem(IDC_DISKEDIT_SECTOR); - pWnd->DestroyWindow(); - pWnd = GetDlgItem(IDC_DISKEDIT_SECTORSPIN); - pWnd->DestroyWindow(); + pWnd = GetDlgItem(IDC_STEXT_SECTOR); + pWnd->DestroyWindow(); + pWnd = GetDlgItem(IDC_DISKEDIT_SECTOR); + pWnd->DestroyWindow(); + pWnd = GetDlgItem(IDC_DISKEDIT_SECTORSPIN); + pWnd->DestroyWindow(); - CString blockStr; - //blockStr.LoadString(IDS_BLOCK); - blockStr.Format("Block (%d):", fpDiskFS->GetDiskImg()->GetNumBlocks()); - pWnd = GetDlgItem(IDC_STEXT_TRACK); - ASSERT(pWnd != nil); - pWnd->SetWindowText(blockStr); + CString blockStr; + //blockStr.LoadString(IDS_BLOCK); + blockStr.Format("Block (%d):", fpDiskFS->GetDiskImg()->GetNumBlocks()); + pWnd = GetDlgItem(IDC_STEXT_TRACK); + ASSERT(pWnd != nil); + pWnd->SetWindowText(blockStr); - /* - * Increase the size of the window to accommodate the larger block size. - */ - const int kStretchHeight = 250; - CRect rect; + /* + * Increase the size of the window to accommodate the larger block size. + */ + const int kStretchHeight = 250; + CRect rect; - GetWindowRect(&rect); - rect.bottom += kStretchHeight; - MoveWindow(&rect); + GetWindowRect(&rect); + rect.bottom += kStretchHeight; + MoveWindow(&rect); - CRichEditCtrl* pEdit = (CRichEditCtrl*)GetDlgItem(IDC_DISKEDIT_EDIT); - ASSERT(pEdit != nil); - CRect inner; - pEdit->GetRect(&inner); - inner.bottom += kStretchHeight; - pEdit->GetWindowRect(&rect); - ScreenToClient(&rect); - rect.bottom += kStretchHeight; - pEdit->MoveWindow(&rect); - pEdit->SetRect(&inner); + CRichEditCtrl* pEdit = (CRichEditCtrl*)GetDlgItem(IDC_DISKEDIT_EDIT); + ASSERT(pEdit != nil); + CRect inner; + pEdit->GetRect(&inner); + inner.bottom += kStretchHeight; + pEdit->GetWindowRect(&rect); + ScreenToClient(&rect); + rect.bottom += kStretchHeight; + pEdit->MoveWindow(&rect); + pEdit->SetRect(&inner); - MoveControl(this, IDC_DISKEDIT_DONE, 0, kStretchHeight); - MoveControl(this, IDC_DISKEDIT_OPENFILE, 0, kStretchHeight); - MoveControl(this, IDC_DISKEDIT_SUBVOLUME, 0, kStretchHeight); - MoveControl(this, IDHELP, 0, kStretchHeight); - MoveControl(this, IDC_DISKEDIT_NIBBLE_PARMS, 0, kStretchHeight); + MoveControl(this, IDC_DISKEDIT_DONE, 0, kStretchHeight); + MoveControl(this, IDC_DISKEDIT_OPENFILE, 0, kStretchHeight); + MoveControl(this, IDC_DISKEDIT_SUBVOLUME, 0, kStretchHeight); + MoveControl(this, IDHELP, 0, kStretchHeight); + MoveControl(this, IDC_DISKEDIT_NIBBLE_PARMS, 0, kStretchHeight); - /* - * Do base-class construction. - */ - DiskEditDialog::OnInitDialog(); + /* + * Do base-class construction. + */ + DiskEditDialog::OnInitDialog(); - /* - * Configure the spin button. We use the "track" spin button for blocks. - */ - MySpinCtrl* pSpin; - pSpin = (MySpinCtrl*)GetDlgItem(IDC_DISKEDIT_TRACKSPIN); - ASSERT(pSpin != nil); - pSpin->SetRange32(0, fpDiskFS->GetDiskImg()->GetNumBlocks()-1); - pSpin->SetPos(0); + /* + * Configure the spin button. We use the "track" spin button for blocks. + */ + MySpinCtrl* pSpin; + pSpin = (MySpinCtrl*)GetDlgItem(IDC_DISKEDIT_TRACKSPIN); + ASSERT(pSpin != nil); + pSpin->SetRange32(0, fpDiskFS->GetDiskImg()->GetNumBlocks()-1); + pSpin->SetPos(0); - /* give us something to look at */ - if (LoadData() != 0) { - WMSG0("WHOOPS: LoadData() failed, but we're in OnInitDialog\n"); - } + /* give us something to look at */ + if (LoadData() != 0) { + WMSG0("WHOOPS: LoadData() failed, but we're in OnInitDialog\n"); + } - return TRUE; + return TRUE; } #if 0 @@ -1153,19 +1153,19 @@ BlockEditDialog::OnInitDialog(void) void BlockEditDialog::MoveControl(int id, int deltaX, int deltaY) { - CWnd* pWnd; - CRect rect; + CWnd* pWnd; + CRect rect; - pWnd = GetDlgItem(id); - ASSERT(pWnd != nil); + pWnd = GetDlgItem(id); + ASSERT(pWnd != nil); - pWnd->GetWindowRect(&rect); - ScreenToClient(&rect); - rect.left += deltaX; - rect.right += deltaX; - rect.top += deltaY; - rect.bottom += deltaY; - pWnd->MoveWindow(&rect, TRUE); + pWnd->GetWindowRect(&rect); + ScreenToClient(&rect); + rect.left += deltaX; + rect.right += deltaX; + rect.top += deltaY; + rect.bottom += deltaY; + pWnd->MoveWindow(&rect, TRUE); } #endif @@ -1176,32 +1176,32 @@ BlockEditDialog::MoveControl(int id, int deltaX, int deltaY) int BlockEditDialog::LoadData(void) { - //WMSG0("BED LoadData\n"); - ASSERT(fpDiskFS != nil); - ASSERT(fpDiskFS->GetDiskImg() != nil); + //WMSG0("BED LoadData\n"); + ASSERT(fpDiskFS != nil); + ASSERT(fpDiskFS->GetDiskImg() != nil); - if (ReadSpinner(IDC_DISKEDIT_TRACKSPIN, &fBlock) != 0) - return -1; + if (ReadSpinner(IDC_DISKEDIT_TRACKSPIN, &fBlock) != 0) + return -1; - WMSG1("LoadData reading block=%d\n", fBlock); + WMSG1("LoadData reading block=%d\n", fBlock); - fAlertMsg = ""; - DIError dierr; - dierr = fpDiskFS->GetDiskImg()->ReadBlock(fBlock, fBlockData); - if (dierr != kDIErrNone) { - WMSG1("BED block read failed: %s\n", DiskImgLib::DIStrError(dierr)); - //CString msg; - //CString err; - //err.LoadString(IDS_ERROR); - //msg.Format(IDS_DISKEDIT_NOREADBLOCK, fBlock); - //MessageBox(msg, err, MB_OK|MB_ICONSTOP); - fAlertMsg.LoadString(IDS_DISKEDITMSG_BADBLOCK); - //return -1; - } + fAlertMsg = ""; + DIError dierr; + dierr = fpDiskFS->GetDiskImg()->ReadBlock(fBlock, fBlockData); + if (dierr != kDIErrNone) { + WMSG1("BED block read failed: %s\n", DiskImgLib::DIStrError(dierr)); + //CString msg; + //CString err; + //err.LoadString(IDS_ERROR); + //msg.Format(IDS_DISKEDIT_NOREADBLOCK, fBlock); + //MessageBox(msg, err, MB_OK|MB_ICONSTOP); + fAlertMsg.LoadString(IDS_DISKEDITMSG_BADBLOCK); + //return -1; + } - DisplayData(); + DisplayData(); - return 0; + return 0; } /* @@ -1210,7 +1210,7 @@ BlockEditDialog::LoadData(void) void BlockEditDialog::OnDoRead(void) { - LoadData(); + LoadData(); } /* @@ -1219,7 +1219,7 @@ BlockEditDialog::OnDoRead(void) void BlockEditDialog::OnDoWrite(void) { - MessageBox("Write!"); + MessageBox("Write!"); } /* @@ -1229,12 +1229,12 @@ BlockEditDialog::OnDoWrite(void) void BlockEditDialog::OnReadPrev(void) { - if (fBlock == 0) - return; + if (fBlock == 0) + return; - fBlock--; - SetSpinner(IDC_DISKEDIT_TRACKSPIN, fBlock); - LoadData(); + fBlock--; + SetSpinner(IDC_DISKEDIT_TRACKSPIN, fBlock); + LoadData(); } /* @@ -1243,13 +1243,13 @@ BlockEditDialog::OnReadPrev(void) void BlockEditDialog::OnReadNext(void) { - ASSERT(fpDiskFS != nil); - if (fBlock == fpDiskFS->GetDiskImg()->GetNumBlocks() - 1) - return; + ASSERT(fpDiskFS != nil); + if (fBlock == fpDiskFS->GetDiskImg()->GetNumBlocks() - 1) + return; - fBlock++; - SetSpinner(IDC_DISKEDIT_TRACKSPIN, fBlock); - LoadData(); + fBlock++; + SetSpinner(IDC_DISKEDIT_TRACKSPIN, fBlock); + LoadData(); } /* @@ -1259,32 +1259,32 @@ BlockEditDialog::OnReadNext(void) void BlockEditDialog::OnOpenFile(void) { - DEFileDialog fileDialog(this); + DEFileDialog fileDialog(this); - if (fileDialog.DoModal() == IDOK) { - BlockFileEditDialog fileEdit(this, this); - A2File* pFile; - A2FileDescr* pOpenFile = nil; - DIError dierr; + if (fileDialog.DoModal() == IDOK) { + BlockFileEditDialog fileEdit(this, this); + A2File* pFile; + A2FileDescr* pOpenFile = nil; + DIError dierr; - dierr = OpenFile(fileDialog.fName, fileDialog.fOpenRsrcFork != 0, - &pFile, &pOpenFile); - if (dierr != kDIErrNone) - return; + dierr = OpenFile(fileDialog.fName, fileDialog.fOpenRsrcFork != 0, + &pFile, &pOpenFile); + if (dierr != kDIErrNone) + return; - fileEdit.SetupFile(fileDialog.fName, fileDialog.fOpenRsrcFork != 0, - pFile, pOpenFile); - fileEdit.SetPositionShift(8); - (void) fileEdit.DoModal(); + fileEdit.SetupFile(fileDialog.fName, fileDialog.fOpenRsrcFork != 0, + pFile, pOpenFile); + fileEdit.SetPositionShift(8); + (void) fileEdit.DoModal(); - pOpenFile->Close(); - } + pOpenFile->Close(); + } } /* * =========================================================================== - * BlockFileEditDialog + * BlockFileEditDialog * =========================================================================== */ @@ -1294,38 +1294,38 @@ BlockEditDialog::OnOpenFile(void) BOOL BlockFileEditDialog::OnInitDialog(void) { - BOOL retval; + BOOL retval; - /* do base class first */ - retval = BlockEditDialog::OnInitDialog(); + /* do base class first */ + retval = BlockEditDialog::OnInitDialog(); - /* disable direct entry of tracks and Blocks */ - CWnd* pWnd; - pWnd = GetDlgItem(IDC_DISKEDIT_TRACKSPIN); - ASSERT(pWnd != nil); - pWnd->EnableWindow(FALSE); + /* disable direct entry of tracks and Blocks */ + CWnd* pWnd; + pWnd = GetDlgItem(IDC_DISKEDIT_TRACKSPIN); + ASSERT(pWnd != nil); + pWnd->EnableWindow(FALSE); - /* disallow opening of sub-volumes and files */ - pWnd = GetDlgItem(IDC_DISKEDIT_OPENFILE); - pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_DISKEDIT_SUBVOLUME); - pWnd->EnableWindow(FALSE); + /* disallow opening of sub-volumes and files */ + pWnd = GetDlgItem(IDC_DISKEDIT_OPENFILE); + pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_DISKEDIT_SUBVOLUME); + pWnd->EnableWindow(FALSE); - CEdit* pEdit; - pEdit = (CEdit*) GetDlgItem(IDC_DISKEDIT_TRACK); - ASSERT(pEdit != nil); - pEdit->SetReadOnly(TRUE); + CEdit* pEdit; + pEdit = (CEdit*) GetDlgItem(IDC_DISKEDIT_TRACK); + ASSERT(pEdit != nil); + pEdit->SetReadOnly(TRUE); - /* set the window title */ - CString title; - CString rsrcIndic; - rsrcIndic.LoadString(IDS_INDIC_RSRC); - title.Format("Disk Viewer - %s%s (%ld bytes)", - fpFile->GetPathName(), // use fpFile version to get case - fOpenRsrcFork ? (LPCTSTR)rsrcIndic : "", fLength); - SetWindowText(title); + /* set the window title */ + CString title; + CString rsrcIndic; + rsrcIndic.LoadString(IDS_INDIC_RSRC); + title.Format("Disk Viewer - %s%s (%ld bytes)", + fpFile->GetPathName(), // use fpFile version to get case + fOpenRsrcFork ? (LPCTSTR)rsrcIndic : "", fLength); + SetWindowText(title); - return retval; + return retval; } /* @@ -1336,97 +1336,97 @@ BlockFileEditDialog::OnInitDialog(void) int BlockFileEditDialog::LoadData(void) { - ASSERT(fpDiskFS != nil); - ASSERT(fpDiskFS->GetDiskImg() != nil); + ASSERT(fpDiskFS != nil); + ASSERT(fpDiskFS->GetDiskImg() != nil); - DIError dierr; - WMSG1("BFED LoadData reading index=%d\n", fBlockIdx); + DIError dierr; + WMSG1("BFED LoadData reading index=%d\n", fBlockIdx); #if 0 - WMSG1("LoadData reading offset=%d\n", fOffset); - size_t actual = 0; - dierr = fpFile->Seek(fOffset, EmbeddedFD::kSeekSet); - if (dierr == kDIErrNone) { - dierr = fpFile->Read(fBlockData, 1 /*kBlockSize*/, &actual); - } - if (dierr != kDIErrNone) { - CString msg, failed; - failed.LoadString(IDS_FAILED); - msg.Format(IDS_DISKEDIT_FIRDFAILED, DiskImg::DIStrError(dierr)); - MessageBox(msg, failed, MB_OK); - // TO DO: mark contents as invalid, so editing fails - return -1; - } + WMSG1("LoadData reading offset=%d\n", fOffset); + size_t actual = 0; + dierr = fpFile->Seek(fOffset, EmbeddedFD::kSeekSet); + if (dierr == kDIErrNone) { + dierr = fpFile->Read(fBlockData, 1 /*kBlockSize*/, &actual); + } + if (dierr != kDIErrNone) { + CString msg, failed; + failed.LoadString(IDS_FAILED); + msg.Format(IDS_DISKEDIT_FIRDFAILED, DiskImg::DIStrError(dierr)); + MessageBox(msg, failed, MB_OK); + // TO DO: mark contents as invalid, so editing fails + return -1; + } - if (actual != kBlockSize) { - WMSG1(" BFED partial read of %d bytes\n", actual); - ASSERT(actual < kBlockSize && actual >= 0); - } + if (actual != kBlockSize) { + WMSG1(" BFED partial read of %d bytes\n", actual); + ASSERT(actual < kBlockSize && actual >= 0); + } - /* - * We've read the data, but we can't use it. We're a Block editor, - * not a file editor, and we need to get the actual Block data without - * EOF trimming or CP/M 0xe5 removal. - */ - fpFile->GetLastLocationRead(&fBlock); - if (fBlock == A2File::kLastWasSparse) - ; + /* + * We've read the data, but we can't use it. We're a Block editor, + * not a file editor, and we need to get the actual Block data without + * EOF trimming or CP/M 0xe5 removal. + */ + fpFile->GetLastLocationRead(&fBlock); + if (fBlock == A2File::kLastWasSparse) + ; #endif - fAlertMsg = ""; + fAlertMsg = ""; - dierr = fpOpenFile->GetStorage(fBlockIdx, &fBlock); - if (dierr == kDIErrInvalidIndex && fBlockIdx == 0) { - // no first sector; should only happen on CP/M - //FillWithPattern(fBlockData, sizeof(fBlockData), _T("EMPTY ")); - fAlertMsg.LoadString(IDS_DISKEDITMSG_EMPTY); - } else if (dierr != kDIErrNone) { - CString msg, failed; - failed.LoadString(IDS_FAILED); - msg.Format(IDS_DISKEDIT_FIRDFAILED, DiskImgLib::DIStrError(dierr)); - MessageBox(msg, failed, MB_OK); - fAlertMsg.LoadString(IDS_FAILED); - // TO DO: mark contents as invalid, so editing fails - return -1; - } else { - if (fBlock == 0) { - WMSG0("LoadData Sparse block\n"); - //FillWithPattern(fBlockData, sizeof(fBlockData), _T("SPARSE ")); - fAlertMsg.Format(IDS_DISKEDITMSG_SPARSE, fBlockIdx); - } else { - WMSG1("LoadData reading B=%d\n", fBlock); + dierr = fpOpenFile->GetStorage(fBlockIdx, &fBlock); + if (dierr == kDIErrInvalidIndex && fBlockIdx == 0) { + // no first sector; should only happen on CP/M + //FillWithPattern(fBlockData, sizeof(fBlockData), _T("EMPTY ")); + fAlertMsg.LoadString(IDS_DISKEDITMSG_EMPTY); + } else if (dierr != kDIErrNone) { + CString msg, failed; + failed.LoadString(IDS_FAILED); + msg.Format(IDS_DISKEDIT_FIRDFAILED, DiskImgLib::DIStrError(dierr)); + MessageBox(msg, failed, MB_OK); + fAlertMsg.LoadString(IDS_FAILED); + // TO DO: mark contents as invalid, so editing fails + return -1; + } else { + if (fBlock == 0) { + WMSG0("LoadData Sparse block\n"); + //FillWithPattern(fBlockData, sizeof(fBlockData), _T("SPARSE ")); + fAlertMsg.Format(IDS_DISKEDITMSG_SPARSE, fBlockIdx); + } else { + WMSG1("LoadData reading B=%d\n", fBlock); - dierr = fpDiskFS->GetDiskImg()->ReadBlock(fBlock, fBlockData); - if (dierr != kDIErrNone) { - //CString msg; - //CString err; - //err.LoadString(IDS_ERROR); - //msg.Format(IDS_DISKEDIT_NOREADBLOCK, fBlock); - //MessageBox(msg, err, MB_OK|MB_ICONSTOP); - fAlertMsg.LoadString(IDS_DISKEDITMSG_BADBLOCK); - //return -1; - } - } - } + dierr = fpDiskFS->GetDiskImg()->ReadBlock(fBlock, fBlockData); + if (dierr != kDIErrNone) { + //CString msg; + //CString err; + //err.LoadString(IDS_ERROR); + //msg.Format(IDS_DISKEDIT_NOREADBLOCK, fBlock); + //MessageBox(msg, err, MB_OK|MB_ICONSTOP); + fAlertMsg.LoadString(IDS_DISKEDITMSG_BADBLOCK); + //return -1; + } + } + } - SetSpinner(IDC_DISKEDIT_TRACKSPIN, fBlock); + SetSpinner(IDC_DISKEDIT_TRACKSPIN, fBlock); - CWnd* pWnd; - pWnd = GetDlgItem(IDC_DISKEDIT_PREV); - ASSERT(pWnd != nil); - pWnd->EnableWindow(fBlockIdx > 0); - if (!pWnd->IsWindowEnabled() && GetFocus() == nil) - GetDlgItem(IDC_DISKEDIT_NEXT)->SetFocus(); + CWnd* pWnd; + pWnd = GetDlgItem(IDC_DISKEDIT_PREV); + ASSERT(pWnd != nil); + pWnd->EnableWindow(fBlockIdx > 0); + if (!pWnd->IsWindowEnabled() && GetFocus() == nil) + GetDlgItem(IDC_DISKEDIT_NEXT)->SetFocus(); - pWnd = GetDlgItem(IDC_DISKEDIT_NEXT); - ASSERT(pWnd != nil); - pWnd->EnableWindow(fBlockIdx+1 < fpOpenFile->GetBlockCount()); - if (!pWnd->IsWindowEnabled() && GetFocus() == nil) - GetDlgItem(IDC_DISKEDIT_PREV)->SetFocus(); + pWnd = GetDlgItem(IDC_DISKEDIT_NEXT); + ASSERT(pWnd != nil); + pWnd->EnableWindow(fBlockIdx+1 < fpOpenFile->GetBlockCount()); + if (!pWnd->IsWindowEnabled() && GetFocus() == nil) + GetDlgItem(IDC_DISKEDIT_PREV)->SetFocus(); - DisplayData(); + DisplayData(); - return 0; + return 0; } /* @@ -1435,12 +1435,12 @@ BlockFileEditDialog::LoadData(void) void BlockFileEditDialog::OnReadPrev(void) { - if (fBlockIdx == 0) - return; + if (fBlockIdx == 0) + return; - fBlockIdx--; - ASSERT(fBlockIdx >= 0); - LoadData(); + fBlockIdx--; + ASSERT(fBlockIdx >= 0); + LoadData(); } /* @@ -1449,18 +1449,18 @@ BlockFileEditDialog::OnReadPrev(void) void BlockFileEditDialog::OnReadNext(void) { - if (fBlockIdx+1 >= fpOpenFile->GetBlockCount()) - return; + if (fBlockIdx+1 >= fpOpenFile->GetBlockCount()) + return; - fBlockIdx++; - ASSERT(fBlockIdx < fpOpenFile->GetBlockCount()); - LoadData(); + fBlockIdx++; + ASSERT(fBlockIdx < fpOpenFile->GetBlockCount()); + LoadData(); } /* * =========================================================================== - * NibbleEditDialog + * NibbleEditDialog * =========================================================================== */ @@ -1471,96 +1471,96 @@ BlockFileEditDialog::OnReadNext(void) BOOL NibbleEditDialog::OnInitDialog(void) { - /* - * Get rid of the "sector" input item. - */ - CWnd* pWnd; + /* + * Get rid of the "sector" input item. + */ + CWnd* pWnd; - pWnd = GetDlgItem(IDC_STEXT_SECTOR); - pWnd->DestroyWindow(); - pWnd = GetDlgItem(IDC_DISKEDIT_SECTOR); - pWnd->DestroyWindow(); - pWnd = GetDlgItem(IDC_DISKEDIT_SECTORSPIN); - pWnd->DestroyWindow(); + pWnd = GetDlgItem(IDC_STEXT_SECTOR); + pWnd->DestroyWindow(); + pWnd = GetDlgItem(IDC_DISKEDIT_SECTOR); + pWnd->DestroyWindow(); + pWnd = GetDlgItem(IDC_DISKEDIT_SECTORSPIN); + pWnd->DestroyWindow(); - CString trackStr; - trackStr.Format("Track (%d):", fpDiskFS->GetDiskImg()->GetNumTracks()); - pWnd = GetDlgItem(IDC_STEXT_TRACK); - ASSERT(pWnd != nil); - pWnd->SetWindowText(trackStr); + CString trackStr; + trackStr.Format("Track (%d):", fpDiskFS->GetDiskImg()->GetNumTracks()); + pWnd = GetDlgItem(IDC_STEXT_TRACK); + ASSERT(pWnd != nil); + pWnd->SetWindowText(trackStr); - /* - * Increase the size of the window so it's the same height as blocks. - * - * NOTE: using a pixel constant is probably bad. We want to use something - * like GetTextMetrics, but I'm not sure how to get that without a - * device context. - */ - CRichEditCtrl* pEdit = (CRichEditCtrl*)GetDlgItem(IDC_DISKEDIT_EDIT); - ASSERT(pEdit != nil); - const int kStretchHeight = 249; - CRect rect; + /* + * Increase the size of the window so it's the same height as blocks. + * + * NOTE: using a pixel constant is probably bad. We want to use something + * like GetTextMetrics, but I'm not sure how to get that without a + * device context. + */ + CRichEditCtrl* pEdit = (CRichEditCtrl*)GetDlgItem(IDC_DISKEDIT_EDIT); + ASSERT(pEdit != nil); + const int kStretchHeight = 249; + CRect rect; - GetWindowRect(&rect); - rect.bottom += kStretchHeight; - MoveWindow(&rect); + GetWindowRect(&rect); + rect.bottom += kStretchHeight; + MoveWindow(&rect); - /* - * Must postpone resize of edit ctrl until after data has been loaded, or - * scroll bars fail to appear under Win98. Makes no sense whatsoever, but - * that's Windows for you. - */ + /* + * Must postpone resize of edit ctrl until after data has been loaded, or + * scroll bars fail to appear under Win98. Makes no sense whatsoever, but + * that's Windows for you. + */ #if 0 - CRect inner; - pEdit->GetRect(&inner); - inner.bottom += kStretchHeight; - pEdit->GetWindowRect(&rect); - ScreenToClient(&rect); - rect.bottom += kStretchHeight; - pEdit->MoveWindow(&rect); - pEdit->SetRect(&inner); + CRect inner; + pEdit->GetRect(&inner); + inner.bottom += kStretchHeight; + pEdit->GetWindowRect(&rect); + ScreenToClient(&rect); + rect.bottom += kStretchHeight; + pEdit->MoveWindow(&rect); + pEdit->SetRect(&inner); #endif - /* show the scroll bar */ - pEdit->ShowScrollBar(SB_VERT); + /* show the scroll bar */ + pEdit->ShowScrollBar(SB_VERT); - MoveControl(this, IDC_DISKEDIT_DONE, 0, kStretchHeight); - MoveControl(this, IDC_DISKEDIT_OPENFILE, 0, kStretchHeight); - MoveControl(this, IDC_DISKEDIT_SUBVOLUME, 0, kStretchHeight); - MoveControl(this, IDHELP, 0, kStretchHeight); - MoveControl(this, IDC_DISKEDIT_NIBBLE_PARMS, 0, kStretchHeight); + MoveControl(this, IDC_DISKEDIT_DONE, 0, kStretchHeight); + MoveControl(this, IDC_DISKEDIT_OPENFILE, 0, kStretchHeight); + MoveControl(this, IDC_DISKEDIT_SUBVOLUME, 0, kStretchHeight); + MoveControl(this, IDHELP, 0, kStretchHeight); + MoveControl(this, IDC_DISKEDIT_NIBBLE_PARMS, 0, kStretchHeight); - /* disable opening of files and sub-volumes */ - pWnd = GetDlgItem(IDC_DISKEDIT_OPENFILE); - pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_DISKEDIT_SUBVOLUME); - pWnd->EnableWindow(FALSE); + /* disable opening of files and sub-volumes */ + pWnd = GetDlgItem(IDC_DISKEDIT_OPENFILE); + pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_DISKEDIT_SUBVOLUME); + pWnd->EnableWindow(FALSE); - /* - * Do base-class construction. - */ - DiskEditDialog::OnInitDialog(); + /* + * Do base-class construction. + */ + DiskEditDialog::OnInitDialog(); - /* - * This currently has no effect on the nibble editor. Someday we may - * want to highlight and/or decode address fields. - */ - pWnd = GetDlgItem(IDC_DISKEDIT_NIBBLE_PARMS); - pWnd->EnableWindow(FALSE); + /* + * This currently has no effect on the nibble editor. Someday we may + * want to highlight and/or decode address fields. + */ + pWnd = GetDlgItem(IDC_DISKEDIT_NIBBLE_PARMS); + pWnd->EnableWindow(FALSE); - /* - * Configure the track spin button. - */ - MySpinCtrl* pSpin; - pSpin = (MySpinCtrl*)GetDlgItem(IDC_DISKEDIT_TRACKSPIN); - ASSERT(pSpin != nil); - pSpin->SetRange32(0, fpDiskFS->GetDiskImg()->GetNumTracks()-1); - pSpin->SetPos(0); + /* + * Configure the track spin button. + */ + MySpinCtrl* pSpin; + pSpin = (MySpinCtrl*)GetDlgItem(IDC_DISKEDIT_TRACKSPIN); + ASSERT(pSpin != nil); + pSpin->SetRange32(0, fpDiskFS->GetDiskImg()->GetNumTracks()-1); + pSpin->SetPos(0); - /* give us something to look at */ - LoadData(); + /* give us something to look at */ + LoadData(); - return TRUE; + return TRUE; } /* @@ -1569,27 +1569,27 @@ NibbleEditDialog::OnInitDialog(void) int NibbleEditDialog::LoadData(void) { - //WMSG0("BED LoadData\n"); - ASSERT(fpDiskFS != nil); - ASSERT(fpDiskFS->GetDiskImg() != nil); + //WMSG0("BED LoadData\n"); + ASSERT(fpDiskFS != nil); + ASSERT(fpDiskFS->GetDiskImg() != nil); - if (ReadSpinner(IDC_DISKEDIT_TRACKSPIN, &fTrack) != 0) - return -1; + if (ReadSpinner(IDC_DISKEDIT_TRACKSPIN, &fTrack) != 0) + return -1; - WMSG1("LoadData reading track=%d\n", fTrack); + WMSG1("LoadData reading track=%d\n", fTrack); - fAlertMsg = ""; - DIError dierr; - dierr = fpDiskFS->GetDiskImg()->ReadNibbleTrack(fTrack, fNibbleData, - &fNibbleDataLen); - if (dierr != kDIErrNone) { - WMSG1("NED track read failed: %s\n", DiskImgLib::DIStrError(dierr)); - fAlertMsg.LoadString(IDS_DISKEDITMSG_BADTRACK); - } + fAlertMsg = ""; + DIError dierr; + dierr = fpDiskFS->GetDiskImg()->ReadNibbleTrack(fTrack, fNibbleData, + &fNibbleDataLen); + if (dierr != kDIErrNone) { + WMSG1("NED track read failed: %s\n", DiskImgLib::DIStrError(dierr)); + fAlertMsg.LoadString(IDS_DISKEDITMSG_BADTRACK); + } - DisplayData(); + DisplayData(); - return 0; + return 0; } /* @@ -1598,7 +1598,7 @@ NibbleEditDialog::LoadData(void) void NibbleEditDialog::OnDoRead(void) { - LoadData(); + LoadData(); } /* @@ -1607,7 +1607,7 @@ NibbleEditDialog::OnDoRead(void) void NibbleEditDialog::OnDoWrite(void) { - MessageBox("Write!"); + MessageBox("Write!"); } /* @@ -1617,12 +1617,12 @@ NibbleEditDialog::OnDoWrite(void) void NibbleEditDialog::OnReadPrev(void) { - if (fTrack == 0) - return; + if (fTrack == 0) + return; - fTrack--; - SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack); - LoadData(); + fTrack--; + SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack); + LoadData(); } /* @@ -1631,11 +1631,11 @@ NibbleEditDialog::OnReadPrev(void) void NibbleEditDialog::OnReadNext(void) { - ASSERT(fpDiskFS != nil); - if (fTrack == fpDiskFS->GetDiskImg()->GetNumTracks() - 1) - return; + ASSERT(fpDiskFS != nil); + if (fTrack == fpDiskFS->GetDiskImg()->GetNumTracks() - 1) + return; - fTrack++; - SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack); - LoadData(); + fTrack++; + SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack); + LoadData(); } diff --git a/app/DiskEditDialog.h b/app/DiskEditDialog.h index 5bc397d..2ef12ad 100644 --- a/app/DiskEditDialog.h +++ b/app/DiskEditDialog.h @@ -26,92 +26,92 @@ */ class DiskEditDialog : public CDialog { public: - DiskEditDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL) : - CDialog(nIDTemplate, pParentWnd) - { - fReadOnly = true; - fpDiskFS = nil; - fFileName = ""; - fPositionShift = 0; - fFirstResize = true; - } - virtual ~DiskEditDialog() {} + DiskEditDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL) : + CDialog(nIDTemplate, pParentWnd) + { + fReadOnly = true; + fpDiskFS = nil; + fFileName = ""; + fPositionShift = 0; + fFirstResize = true; + } + virtual ~DiskEditDialog() {} - void Setup(DiskFS* pDiskFS, const char* fileName) { - ASSERT(pDiskFS != nil); - ASSERT(fileName != nil); - fpDiskFS = pDiskFS; - fFileName = fileName; - } + void Setup(DiskFS* pDiskFS, const char* fileName) { + ASSERT(pDiskFS != nil); + ASSERT(fileName != nil); + fpDiskFS = pDiskFS; + fFileName = fileName; + } - enum { kSectorSize=256, kBlockSize=512 }; + enum { kSectorSize=256, kBlockSize=512 }; - virtual int LoadData(void) = 0; + virtual int LoadData(void) = 0; - virtual void DisplayData(void) = 0; - virtual void DisplayData(const unsigned char* buf, int size); - virtual void DisplayNibbleData(const unsigned char* srcBuf, int size); + virtual void DisplayData(void) = 0; + virtual void DisplayData(const unsigned char* buf, int size); + virtual void DisplayNibbleData(const unsigned char* srcBuf, int size); - bool GetReadOnly(void) const { return fReadOnly; } - void SetReadOnly(bool val) { fReadOnly = val; } - int GetPositionShift(void) const { return fPositionShift; } - void SetPositionShift(int val) { fPositionShift = val; } - DiskFS* GetDiskFS(void) const { return fpDiskFS; } - const char* GetFileName(void) const { return fFileName; } + bool GetReadOnly(void) const { return fReadOnly; } + void SetReadOnly(bool val) { fReadOnly = val; } + int GetPositionShift(void) const { return fPositionShift; } + void SetPositionShift(int val) { fPositionShift = val; } + DiskFS* GetDiskFS(void) const { return fpDiskFS; } + const char* GetFileName(void) const { return fFileName; } protected: - // return a low-ASCII character so we can read high-ASCII files - inline char PrintableChar(unsigned char ch) { - if (ch < 0x20) - return '.'; - else if (ch < 0x80) - return ch; - else if (ch < 0xa0 || ch == 0xff) // 0xff becomes 0x7f - return '.'; - else - return ch & 0x7f; - } + // return a low-ASCII character so we can read high-ASCII files + inline char PrintableChar(unsigned char ch) { + if (ch < 0x20) + return '.'; + else if (ch < 0x80) + return ch; + else if (ch < 0xa0 || ch == 0xff) // 0xff becomes 0x7f + return '.'; + else + return ch & 0x7f; + } - // overrides - virtual BOOL OnInitDialog(void); + // overrides + virtual BOOL OnInitDialog(void); - afx_msg virtual BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - afx_msg virtual void OnDone(void); - afx_msg virtual void OnHexMode(void); - afx_msg virtual void OnDoRead(void) = 0; - afx_msg virtual void OnDoWrite(void) = 0; - afx_msg virtual void OnReadPrev(void) = 0; - afx_msg virtual void OnReadNext(void) = 0; - afx_msg virtual void OnSubVolume(void); - afx_msg virtual void OnOpenFile(void) = 0; - afx_msg virtual void OnNibbleParms(void); - afx_msg virtual void OnHelp(void); + afx_msg virtual BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg virtual void OnDone(void); + afx_msg virtual void OnHexMode(void); + afx_msg virtual void OnDoRead(void) = 0; + afx_msg virtual void OnDoWrite(void) = 0; + afx_msg virtual void OnReadPrev(void) = 0; + afx_msg virtual void OnReadNext(void) = 0; + afx_msg virtual void OnSubVolume(void); + afx_msg virtual void OnOpenFile(void) = 0; + afx_msg virtual void OnNibbleParms(void); + afx_msg virtual void OnHelp(void); - virtual BOOL PreTranslateMessage(MSG* pMsg); + virtual BOOL PreTranslateMessage(MSG* pMsg); - void SetSpinMode(int id, int base); - int ReadSpinner(int id, long* pVal); - void SetSpinner(int id, long val); + void SetSpinMode(int id, int base); + int ReadSpinner(int id, long* pVal); + void SetSpinner(int id, long val); - //void FillWithPattern(unsigned char* buf, int size, const char* pattern); - DIError OpenFile(const char* fileName, bool openRsrc, A2File** ppFile, - A2FileDescr** ppOpenFile); + //void FillWithPattern(unsigned char* buf, int size, const char* pattern); + DIError OpenFile(const char* fileName, bool openRsrc, A2File** ppFile, + A2FileDescr** ppOpenFile); - DiskFS* fpDiskFS; - CString fFileName; - CString fAlertMsg; - bool fReadOnly; - int fPositionShift; + DiskFS* fpDiskFS; + CString fFileName; + CString fAlertMsg; + bool fReadOnly; + int fPositionShift; private: - void InitNibbleParmList(void); - int ReplaceSpinCtrl(MySpinCtrl* pNewSpin, int idSpin, int idEdit); - MySpinCtrl fTrackSpinner; - MySpinCtrl fSectorSpinner; - bool fFirstResize; + void InitNibbleParmList(void); + int ReplaceSpinCtrl(MySpinCtrl* pNewSpin, int idSpin, int idEdit); + MySpinCtrl fTrackSpinner; + MySpinCtrl fSectorSpinner; + bool fFirstResize; - //afx_msg void OnPaint(); - DECLARE_MESSAGE_MAP() + //afx_msg void OnPaint(); + DECLARE_MESSAGE_MAP() }; @@ -121,35 +121,35 @@ private: */ class SectorEditDialog : public DiskEditDialog { public: - SectorEditDialog(CWnd* pParentWnd = NULL) : - DiskEditDialog(IDD_DISKEDIT, pParentWnd) - { - fTrack = 0; - fSector = 0; - } - virtual ~SectorEditDialog() {} + SectorEditDialog(CWnd* pParentWnd = NULL) : + DiskEditDialog(IDD_DISKEDIT, pParentWnd) + { + fTrack = 0; + fSector = 0; + } + virtual ~SectorEditDialog() {} - virtual int LoadData(void); // load the current track/sector - virtual void DisplayData(void) { - DiskEditDialog::DisplayData(fSectorData, kSectorSize); - } + virtual int LoadData(void); // load the current track/sector + virtual void DisplayData(void) { + DiskEditDialog::DisplayData(fSectorData, kSectorSize); + } - //void SetTrack(int val) { fTrack = val; } - //void SetSector(int val) { fSector = val; } + //void SetTrack(int val) { fTrack = val; } + //void SetSector(int val) { fSector = val; } - // overrides - virtual BOOL OnInitDialog(void); + // overrides + virtual BOOL OnInitDialog(void); protected: - afx_msg virtual void OnDoRead(void); - afx_msg virtual void OnDoWrite(void); - afx_msg virtual void OnReadPrev(void); - afx_msg virtual void OnReadNext(void); - afx_msg virtual void OnOpenFile(void); + afx_msg virtual void OnDoRead(void); + afx_msg virtual void OnDoWrite(void); + afx_msg virtual void OnReadPrev(void); + afx_msg virtual void OnReadNext(void); + afx_msg virtual void OnOpenFile(void); - long fTrack; - long fSector; - unsigned char fSectorData[kSectorSize]; + long fTrack; + long fSector; + unsigned char fSectorData[kSectorSize]; }; /* @@ -157,44 +157,44 @@ protected: */ class SectorFileEditDialog : public SectorEditDialog { public: - SectorFileEditDialog(SectorEditDialog* pSectEdit, CWnd* pParentWnd = NULL): - SectorEditDialog(pParentWnd) - { - DiskEditDialog::Setup(pSectEdit->GetDiskFS(), - pSectEdit->GetFileName()); - fSectorIdx = 0; - } - virtual ~SectorFileEditDialog() {} + SectorFileEditDialog(SectorEditDialog* pSectEdit, CWnd* pParentWnd = NULL): + SectorEditDialog(pParentWnd) + { + DiskEditDialog::Setup(pSectEdit->GetDiskFS(), + pSectEdit->GetFileName()); + fSectorIdx = 0; + } + virtual ~SectorFileEditDialog() {} - /* we do NOT own pOpenFile, and should not delete it */ - void SetupFile(const char* fileName, bool rsrcFork, A2File* pFile, - A2FileDescr* pOpenFile) - { - fOpenFileName = fileName; - fOpenRsrcFork = rsrcFork; - fpFile = pFile; - fpOpenFile = pOpenFile; - fLength = 0; - if (fpOpenFile->Seek(0, DiskImgLib::kSeekEnd) == kDIErrNone) - fLength = fpOpenFile->Tell(); - } + /* we do NOT own pOpenFile, and should not delete it */ + void SetupFile(const char* fileName, bool rsrcFork, A2File* pFile, + A2FileDescr* pOpenFile) + { + fOpenFileName = fileName; + fOpenRsrcFork = rsrcFork; + fpFile = pFile; + fpOpenFile = pOpenFile; + fLength = 0; + if (fpOpenFile->Seek(0, DiskImgLib::kSeekEnd) == kDIErrNone) + fLength = fpOpenFile->Tell(); + } - virtual int LoadData(void); // load data from the current offset + virtual int LoadData(void); // load data from the current offset private: - // overrides - virtual BOOL OnInitDialog(void); + // overrides + virtual BOOL OnInitDialog(void); - afx_msg virtual void OnReadPrev(void); - afx_msg virtual void OnReadNext(void); + afx_msg virtual void OnReadPrev(void); + afx_msg virtual void OnReadNext(void); - CString fOpenFileName; - bool fOpenRsrcFork; - A2File* fpFile; - A2FileDescr* fpOpenFile; - //long fOffset; - long fSectorIdx; - di_off_t fLength; + CString fOpenFileName; + bool fOpenRsrcFork; + A2File* fpFile; + A2FileDescr* fpOpenFile; + //long fOffset; + long fSectorIdx; + di_off_t fLength; }; @@ -204,32 +204,32 @@ private: */ class BlockEditDialog : public DiskEditDialog { public: - BlockEditDialog(CWnd* pParentWnd = NULL) : - DiskEditDialog(IDD_DISKEDIT, pParentWnd) - { - fBlock = 0; - } - virtual ~BlockEditDialog() {} + BlockEditDialog(CWnd* pParentWnd = NULL) : + DiskEditDialog(IDD_DISKEDIT, pParentWnd) + { + fBlock = 0; + } + virtual ~BlockEditDialog() {} - virtual int LoadData(void); // load the current block - virtual void DisplayData(void) { - DiskEditDialog::DisplayData(fBlockData, kBlockSize); - } + virtual int LoadData(void); // load the current block + virtual void DisplayData(void) { + DiskEditDialog::DisplayData(fBlockData, kBlockSize); + } - // overrides - virtual BOOL OnInitDialog(void); + // overrides + virtual BOOL OnInitDialog(void); protected: - //void MoveControl(int id, int deltaX, int deltaY); + //void MoveControl(int id, int deltaX, int deltaY); - afx_msg virtual void OnDoRead(void); - afx_msg virtual void OnDoWrite(void); - afx_msg virtual void OnReadPrev(void); - afx_msg virtual void OnReadNext(void); - afx_msg virtual void OnOpenFile(void); + afx_msg virtual void OnDoRead(void); + afx_msg virtual void OnDoWrite(void); + afx_msg virtual void OnReadPrev(void); + afx_msg virtual void OnReadNext(void); + afx_msg virtual void OnOpenFile(void); - long fBlock; - unsigned char fBlockData[kBlockSize]; + long fBlock; + unsigned char fBlockData[kBlockSize]; }; @@ -238,44 +238,44 @@ protected: */ class BlockFileEditDialog : public BlockEditDialog { public: - BlockFileEditDialog(BlockEditDialog* pBlockEdit, CWnd* pParentWnd = NULL) : - BlockEditDialog(pParentWnd) - { - DiskEditDialog::Setup(pBlockEdit->GetDiskFS(), - pBlockEdit->GetFileName()); - fBlockIdx = 0; - } - virtual ~BlockFileEditDialog() {} + BlockFileEditDialog(BlockEditDialog* pBlockEdit, CWnd* pParentWnd = NULL) : + BlockEditDialog(pParentWnd) + { + DiskEditDialog::Setup(pBlockEdit->GetDiskFS(), + pBlockEdit->GetFileName()); + fBlockIdx = 0; + } + virtual ~BlockFileEditDialog() {} - /* we do NOT own pOpenFile, and should not delete it */ - void SetupFile(const char* fileName, bool rsrcFork, A2File* pFile, - A2FileDescr* pOpenFile) - { - fOpenFileName = fileName; - fOpenRsrcFork = rsrcFork; - fpFile = pFile; - fpOpenFile = pOpenFile; - fLength = 0; - if (fpOpenFile->Seek(0, DiskImgLib::kSeekEnd) == kDIErrNone) - fLength = fpOpenFile->Tell(); - } + /* we do NOT own pOpenFile, and should not delete it */ + void SetupFile(const char* fileName, bool rsrcFork, A2File* pFile, + A2FileDescr* pOpenFile) + { + fOpenFileName = fileName; + fOpenRsrcFork = rsrcFork; + fpFile = pFile; + fpOpenFile = pOpenFile; + fLength = 0; + if (fpOpenFile->Seek(0, DiskImgLib::kSeekEnd) == kDIErrNone) + fLength = fpOpenFile->Tell(); + } - virtual int LoadData(void); // load data from the current offset + virtual int LoadData(void); // load data from the current offset private: - // overrides - virtual BOOL OnInitDialog(void); + // overrides + virtual BOOL OnInitDialog(void); - afx_msg virtual void OnReadPrev(void); - afx_msg virtual void OnReadNext(void); + afx_msg virtual void OnReadPrev(void); + afx_msg virtual void OnReadNext(void); - CString fOpenFileName; - bool fOpenRsrcFork; - A2File* fpFile; - A2FileDescr* fpOpenFile; - //long fOffset; - long fBlockIdx; - di_off_t fLength; + CString fOpenFileName; + bool fOpenRsrcFork; + A2File* fpFile; + A2FileDescr* fpOpenFile; + //long fOffset; + long fBlockIdx; + di_off_t fLength; }; /* @@ -284,32 +284,32 @@ private: */ class NibbleEditDialog : public DiskEditDialog { public: - NibbleEditDialog(CWnd* pParentWnd = NULL) : - DiskEditDialog(IDD_DISKEDIT, pParentWnd) - { - fTrack = 0; - } - virtual ~NibbleEditDialog() {} + NibbleEditDialog(CWnd* pParentWnd = NULL) : + DiskEditDialog(IDD_DISKEDIT, pParentWnd) + { + fTrack = 0; + } + virtual ~NibbleEditDialog() {} - virtual int LoadData(void); // load the current track/sector - virtual void DisplayData(void) { - DiskEditDialog::DisplayNibbleData(fNibbleData, fNibbleDataLen); - } + virtual int LoadData(void); // load the current track/sector + virtual void DisplayData(void) { + DiskEditDialog::DisplayNibbleData(fNibbleData, fNibbleDataLen); + } - // overrides - virtual BOOL OnInitDialog(void); + // overrides + virtual BOOL OnInitDialog(void); protected: - afx_msg virtual void OnDoRead(void); - afx_msg virtual void OnDoWrite(void); - afx_msg virtual void OnReadPrev(void); - afx_msg virtual void OnReadNext(void); - afx_msg virtual void OnOpenFile(void) { ASSERT(false); } - afx_msg virtual void OnNibbleParms(void) { ASSERT(false); } + afx_msg virtual void OnDoRead(void); + afx_msg virtual void OnDoWrite(void); + afx_msg virtual void OnReadPrev(void); + afx_msg virtual void OnReadNext(void); + afx_msg virtual void OnOpenFile(void) { ASSERT(false); } + afx_msg virtual void OnNibbleParms(void) { ASSERT(false); } - long fTrack; - unsigned char fNibbleData[DiskImgLib::kTrackAllocSize]; - long fNibbleDataLen; + long fTrack; + unsigned char fNibbleData[DiskImgLib::kTrackAllocSize]; + long fNibbleDataLen; }; #endif /*__DISK_EDIT_DIALOG__*/ \ No newline at end of file diff --git a/app/DiskEditOpenDialog.cpp b/app/DiskEditOpenDialog.cpp index c0c7783..f4e2f30 100644 --- a/app/DiskEditOpenDialog.cpp +++ b/app/DiskEditOpenDialog.cpp @@ -10,44 +10,44 @@ #include "DiskEditOpenDialog.h" BEGIN_MESSAGE_MAP(DiskEditOpenDialog, CDialog) - ON_BN_CLICKED(IDC_DEOW_FILE, OnButtonFile) - ON_BN_CLICKED(IDC_DEOW_VOLUME, OnButtonVolume) - ON_BN_CLICKED(IDC_DEOW_CURRENT, OnButtonCurrent) + ON_BN_CLICKED(IDC_DEOW_FILE, OnButtonFile) + ON_BN_CLICKED(IDC_DEOW_VOLUME, OnButtonVolume) + ON_BN_CLICKED(IDC_DEOW_CURRENT, OnButtonCurrent) END_MESSAGE_MAP() BOOL DiskEditOpenDialog::OnInitDialog(void) { - if (!fArchiveOpen) { - CButton* pButton = (CButton*) GetDlgItem(IDC_DEOW_CURRENT); - ASSERT(pButton != nil); - pButton->EnableWindow(FALSE); - } + if (!fArchiveOpen) { + CButton* pButton = (CButton*) GetDlgItem(IDC_DEOW_CURRENT); + ASSERT(pButton != nil); + pButton->EnableWindow(FALSE); + } - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } /* user clicked "open file" button */ void DiskEditOpenDialog::OnButtonFile(void) { - fOpenWhat = kOpenFile; - OnOK(); + fOpenWhat = kOpenFile; + OnOK(); } /* user clicked "open volume" button */ void DiskEditOpenDialog::OnButtonVolume(void) { - fOpenWhat = kOpenVolume; - OnOK(); + fOpenWhat = kOpenVolume; + OnOK(); } /* user clicked "open current" button */ void DiskEditOpenDialog::OnButtonCurrent(void) { - fOpenWhat = kOpenCurrent; - OnOK(); + fOpenWhat = kOpenCurrent; + OnOK(); } diff --git a/app/DiskEditOpenDialog.h b/app/DiskEditOpenDialog.h index b30b8f8..76dc21a 100644 --- a/app/DiskEditOpenDialog.h +++ b/app/DiskEditOpenDialog.h @@ -19,31 +19,31 @@ */ class DiskEditOpenDialog : public CDialog { public: - typedef enum { - kOpenUnknown = 0, - kOpenFile, - kOpenVolume, - kOpenCurrent, - } OpenWhat; + typedef enum { + kOpenUnknown = 0, + kOpenFile, + kOpenVolume, + kOpenCurrent, + } OpenWhat; - DiskEditOpenDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_DISKEDIT_OPENWHICH, pParentWnd), - fArchiveOpen(false), fOpenWhat(kOpenUnknown) - {} + DiskEditOpenDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_DISKEDIT_OPENWHICH, pParentWnd), + fArchiveOpen(false), fOpenWhat(kOpenUnknown) + {} - // set this if the main content list has a file open - bool fArchiveOpen; - // return value -- which button was hit - OpenWhat fOpenWhat; + // set this if the main content list has a file open + bool fArchiveOpen; + // return value -- which button was hit + OpenWhat fOpenWhat; private: - virtual BOOL OnInitDialog(void); + virtual BOOL OnInitDialog(void); - afx_msg void OnButtonFile(void); - afx_msg void OnButtonVolume(void); - afx_msg void OnButtonCurrent(void); + afx_msg void OnButtonFile(void); + afx_msg void OnButtonVolume(void); + afx_msg void OnButtonCurrent(void); - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__DISKEDITOPENDIALOG__*/ diff --git a/app/DiskFSTree.cpp b/app/DiskFSTree.cpp index 6cf4ef8..be7e461 100644 --- a/app/DiskFSTree.cpp +++ b/app/DiskFSTree.cpp @@ -18,11 +18,11 @@ using namespace DiskImgLib; bool DiskFSTree::BuildTree(DiskFS* pDiskFS, CTreeCtrl* pTree) { - ASSERT(pDiskFS != nil); - ASSERT(pTree != nil); + ASSERT(pDiskFS != nil); + ASSERT(pTree != nil); - pTree->SetImageList(&fTreeImageList, TVSIL_NORMAL); - return AddDiskFS(pTree, TVI_ROOT, pDiskFS, 1); + pTree->SetImageList(&fTreeImageList, TVSIL_NORMAL); + return AddDiskFS(pTree, TVI_ROOT, pDiskFS, 1); } /* @@ -35,84 +35,84 @@ DiskFSTree::BuildTree(DiskFS* pDiskFS, CTreeCtrl* pTree) */ bool DiskFSTree::AddDiskFS(CTreeCtrl* pTree, HTREEITEM parent, - DiskImgLib::DiskFS* pDiskFS, int depth) + DiskImgLib::DiskFS* pDiskFS, int depth) { - const DiskFS::SubVolume* pSubVol; - TargetData* pTarget; - HTREEITEM hLocalRoot; - TVITEM tvi; - TVINSERTSTRUCT tvins; + const DiskFS::SubVolume* pSubVol; + TargetData* pTarget; + HTREEITEM hLocalRoot; + TVITEM tvi; + TVINSERTSTRUCT tvins; - /* - * Insert an entry for the current item. - */ - pTarget = AllocTargetData(); - pTarget->kind = kTargetDiskFS; - pTarget->pDiskFS = pDiskFS; - pTarget->pFile = nil; // could also use volume dir for ProDOS - tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; - tvi.pszText = const_cast(pDiskFS->GetVolumeID()); - tvi.cchTextMax = 0; // not needed for insertitem -// tvi.iImage = kTreeImageFolderClosed; -// tvi.iSelectedImage = kTreeImageFolderOpen; - if (pDiskFS->GetReadWriteSupported() && !pDiskFS->GetFSDamaged()) { - tvi.iImage = kTreeImageHardDriveRW; - pTarget->selectable = true; - } else { - tvi.iImage = kTreeImageHardDriveRO; - pTarget->selectable = false; - } - tvi.iSelectedImage = tvi.iImage; - tvi.lParam = (LPARAM) pTarget; - tvins.item = tvi; - tvins.hInsertAfter = parent; - tvins.hParent = parent; - hLocalRoot = pTree->InsertItem(&tvins); - if (hLocalRoot == nil) { - WMSG0("Tree root InsertItem failed\n"); - return false; - } + /* + * Insert an entry for the current item. + */ + pTarget = AllocTargetData(); + pTarget->kind = kTargetDiskFS; + pTarget->pDiskFS = pDiskFS; + pTarget->pFile = nil; // could also use volume dir for ProDOS + tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; + tvi.pszText = const_cast(pDiskFS->GetVolumeID()); + tvi.cchTextMax = 0; // not needed for insertitem +// tvi.iImage = kTreeImageFolderClosed; +// tvi.iSelectedImage = kTreeImageFolderOpen; + if (pDiskFS->GetReadWriteSupported() && !pDiskFS->GetFSDamaged()) { + tvi.iImage = kTreeImageHardDriveRW; + pTarget->selectable = true; + } else { + tvi.iImage = kTreeImageHardDriveRO; + pTarget->selectable = false; + } + tvi.iSelectedImage = tvi.iImage; + tvi.lParam = (LPARAM) pTarget; + tvins.item = tvi; + tvins.hInsertAfter = parent; + tvins.hParent = parent; + hLocalRoot = pTree->InsertItem(&tvins); + if (hLocalRoot == nil) { + WMSG0("Tree root InsertItem failed\n"); + return false; + } - /* - * Scan for and handle all sub-volumes. - */ - pSubVol = pDiskFS->GetNextSubVolume(nil); - while (pSubVol != nil) { - if (!AddDiskFS(pTree, hLocalRoot, pSubVol->GetDiskFS(), depth+1)) - return false; + /* + * Scan for and handle all sub-volumes. + */ + pSubVol = pDiskFS->GetNextSubVolume(nil); + while (pSubVol != nil) { + if (!AddDiskFS(pTree, hLocalRoot, pSubVol->GetDiskFS(), depth+1)) + return false; - pSubVol = pDiskFS->GetNextSubVolume(pSubVol); - } + pSubVol = pDiskFS->GetNextSubVolume(pSubVol); + } - /* - * If this volume has sub-directories, and is read-write, add the subdirs - * to the tree. - * - * We use "depth" rather than "depth+1" because the first subdir entry - * (the volume dir) doesn't get its own entry. We use the disk entry - * to represent the disk's volume dir. - */ - if (fIncludeSubdirs && pDiskFS->GetReadWriteSupported() && - !pDiskFS->GetFSDamaged()) - { - AddSubdir(pTree, hLocalRoot, pDiskFS, nil, depth); - } + /* + * If this volume has sub-directories, and is read-write, add the subdirs + * to the tree. + * + * We use "depth" rather than "depth+1" because the first subdir entry + * (the volume dir) doesn't get its own entry. We use the disk entry + * to represent the disk's volume dir. + */ + if (fIncludeSubdirs && pDiskFS->GetReadWriteSupported() && + !pDiskFS->GetFSDamaged()) + { + AddSubdir(pTree, hLocalRoot, pDiskFS, nil, depth); + } - /* - * If we're above the max expansion depth, expand the node. - */ - if (fExpandDepth == -1 || depth <= fExpandDepth) - pTree->Expand(hLocalRoot, TVE_EXPAND); + /* + * If we're above the max expansion depth, expand the node. + */ + if (fExpandDepth == -1 || depth <= fExpandDepth) + pTree->Expand(hLocalRoot, TVE_EXPAND); - /* - * Finally, if this is the root node, select it. - */ - if (parent == TVI_ROOT) { - pTree->Select(hLocalRoot, TVGN_CARET); - } + /* + * Finally, if this is the root node, select it. + */ + if (parent == TVI_ROOT) { + pTree->Select(hLocalRoot, TVGN_CARET); + } - return true; + return true; } @@ -130,84 +130,84 @@ DiskFSTree::AddDiskFS(CTreeCtrl* pTree, HTREEITEM parent, */ DiskImgLib::A2File* DiskFSTree::AddSubdir(CTreeCtrl* pTree, HTREEITEM parent, - DiskImgLib::DiskFS* pDiskFS, DiskImgLib::A2File* pParentFile, - int depth) + DiskImgLib::DiskFS* pDiskFS, DiskImgLib::A2File* pParentFile, + int depth) { - A2File* pFile; - TargetData* pTarget; - HTREEITEM hLocalRoot; - TVITEM tvi; - TVINSERTSTRUCT tvins; + A2File* pFile; + TargetData* pTarget; + HTREEITEM hLocalRoot; + TVITEM tvi; + TVINSERTSTRUCT tvins; - pFile = pDiskFS->GetNextFile(pParentFile); - if (pFile == nil && pParentFile == nil) { - /* this can happen on an empty DOS 3.3 disk; under ProDOS, we always - have the volume entry */ - /* note pFile will be nil if this happens to be a subdirectory - positioned as the very last file on the disk */ - return nil; - } + pFile = pDiskFS->GetNextFile(pParentFile); + if (pFile == nil && pParentFile == nil) { + /* this can happen on an empty DOS 3.3 disk; under ProDOS, we always + have the volume entry */ + /* note pFile will be nil if this happens to be a subdirectory + positioned as the very last file on the disk */ + return nil; + } - if (pParentFile == nil) { - /* - * This is the root of the disk. We already have a DiskFS entry for - * it, so don't add a new tree item here. - * - * Check to see if this disk has a volume directory entry. - */ - if (pFile->IsVolumeDirectory()) { - pParentFile = pFile; - pFile = pDiskFS->GetNextFile(pFile); - } - hLocalRoot = parent; - } else { - /* - * Add an entry for this subdir (the "parent" entry). - */ - pTarget = AllocTargetData(); - pTarget->kind = kTargetSubdir; - pTarget->selectable = true; - pTarget->pDiskFS = pDiskFS; - pTarget->pFile = pParentFile; - tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; - tvi.pszText = const_cast(pParentFile->GetFileName()); - tvi.cchTextMax = 0; // not needed for insertitem - tvi.iImage = kTreeImageFolderClosed; - tvi.iSelectedImage = kTreeImageFolderOpen; - tvi.lParam = (LPARAM) pTarget; - tvins.item = tvi; - tvins.hInsertAfter = parent; - tvins.hParent = parent; - hLocalRoot = pTree->InsertItem(&tvins); - if (hLocalRoot == nil) { - WMSG1("Tree insert '%s' failed\n", tvi.pszText); - return nil; - } - } + if (pParentFile == nil) { + /* + * This is the root of the disk. We already have a DiskFS entry for + * it, so don't add a new tree item here. + * + * Check to see if this disk has a volume directory entry. + */ + if (pFile->IsVolumeDirectory()) { + pParentFile = pFile; + pFile = pDiskFS->GetNextFile(pFile); + } + hLocalRoot = parent; + } else { + /* + * Add an entry for this subdir (the "parent" entry). + */ + pTarget = AllocTargetData(); + pTarget->kind = kTargetSubdir; + pTarget->selectable = true; + pTarget->pDiskFS = pDiskFS; + pTarget->pFile = pParentFile; + tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM; + tvi.pszText = const_cast(pParentFile->GetFileName()); + tvi.cchTextMax = 0; // not needed for insertitem + tvi.iImage = kTreeImageFolderClosed; + tvi.iSelectedImage = kTreeImageFolderOpen; + tvi.lParam = (LPARAM) pTarget; + tvins.item = tvi; + tvins.hInsertAfter = parent; + tvins.hParent = parent; + hLocalRoot = pTree->InsertItem(&tvins); + if (hLocalRoot == nil) { + WMSG1("Tree insert '%s' failed\n", tvi.pszText); + return nil; + } + } - while (pFile != nil) { - if (pFile->IsDirectory()) { - ASSERT(!pFile->IsVolumeDirectory()); + while (pFile != nil) { + if (pFile->IsDirectory()) { + ASSERT(!pFile->IsVolumeDirectory()); - if (pFile->GetParent() == pParentFile) { - /* this is a subdir of us */ - pFile = AddSubdir(pTree, hLocalRoot, pDiskFS, pFile, depth+1); - if (pFile == nil) - break; // out of while -- disk is done - } else { - /* not one of our subdirs; pop up a level */ - break; // out of while -- subdir is done - } - } else { - pFile = pDiskFS->GetNextFile(pFile); - } - } + if (pFile->GetParent() == pParentFile) { + /* this is a subdir of us */ + pFile = AddSubdir(pTree, hLocalRoot, pDiskFS, pFile, depth+1); + if (pFile == nil) + break; // out of while -- disk is done + } else { + /* not one of our subdirs; pop up a level */ + break; // out of while -- subdir is done + } + } else { + pFile = pDiskFS->GetNextFile(pFile); + } + } - /* expand as appropriate */ - if (fExpandDepth == -1 || depth <= fExpandDepth) - pTree->Expand(hLocalRoot, TVE_EXPAND); + /* expand as appropriate */ + if (fExpandDepth == -1 || depth <= fExpandDepth) + pTree->Expand(hLocalRoot, TVE_EXPAND); - return pFile; + return pFile; } @@ -217,17 +217,17 @@ DiskFSTree::AddSubdir(CTreeCtrl* pTree, HTREEITEM parent, DiskFSTree::TargetData* DiskFSTree::AllocTargetData(void) { - TargetData* pNew = new TargetData; + TargetData* pNew = new TargetData; - if (pNew == nil) - return nil; - memset(pNew, 0, sizeof(*pNew)); + if (pNew == nil) + return nil; + memset(pNew, 0, sizeof(*pNew)); - /* insert it at the head of the list, and update the head pointer */ - pNew->pNext = fpTargetData; - fpTargetData = pNew; + /* insert it at the head of the list, and update the head pointer */ + pNew->pNext = fpTargetData; + fpTargetData = pNew; - return pNew; + return pNew; } /* @@ -238,15 +238,15 @@ DiskFSTree::AllocTargetData(void) void DiskFSTree::FreeAllTargetData(void) { - TargetData* pTarget; - TargetData* pNext; + TargetData* pTarget; + TargetData* pNext; - pTarget = fpTargetData; - while (pTarget != nil) { - pNext = pTarget->pNext; - delete pTarget; - pTarget = pNext; - } + pTarget = fpTargetData; + while (pTarget != nil) { + pNext = pTarget->pNext; + delete pTarget; + pTarget = pNext; + } - fpTargetData = nil; + fpTargetData = nil; } diff --git a/app/DiskFSTree.h b/app/DiskFSTree.h index b4b7750..e286edc 100644 --- a/app/DiskFSTree.h +++ b/app/DiskFSTree.h @@ -19,63 +19,63 @@ */ class DiskFSTree { public: - DiskFSTree(void) { - fIncludeSubdirs = false; - fExpandDepth = 0; + DiskFSTree(void) { + fIncludeSubdirs = false; + fExpandDepth = 0; - fpDiskFS = nil; - fpTargetData = nil; - LoadTreeImages(); - } - virtual ~DiskFSTree(void) { FreeAllTargetData(); } + fpDiskFS = nil; + fpTargetData = nil; + LoadTreeImages(); + } + virtual ~DiskFSTree(void) { FreeAllTargetData(); } - /* - * Create the contents of the tree control. - */ - bool BuildTree(DiskImgLib::DiskFS* pDiskFS, CTreeCtrl* pTree); + /* + * Create the contents of the tree control. + */ + bool BuildTree(DiskImgLib::DiskFS* pDiskFS, CTreeCtrl* pTree); - /* if set, includes folders as well as disks */ - bool fIncludeSubdirs; - /* start with the tree expanded to this depth (0=none, -1=all) */ - int fExpandDepth; + /* if set, includes folders as well as disks */ + bool fIncludeSubdirs; + /* start with the tree expanded to this depth (0=none, -1=all) */ + int fExpandDepth; - typedef enum { - kTargetUnknown = 0, kTargetDiskFS, kTargetSubdir - } TargetKind; - typedef struct TargetData { - TargetKind kind; - bool selectable; - DiskImgLib::DiskFS* pDiskFS; - DiskImgLib::A2File* pFile; + typedef enum { + kTargetUnknown = 0, kTargetDiskFS, kTargetSubdir + } TargetKind; + typedef struct TargetData { + TargetKind kind; + bool selectable; + DiskImgLib::DiskFS* pDiskFS; + DiskImgLib::A2File* pFile; - // easier to keep a list than to chase through the tree - struct TargetData* pNext; - } TargetData; + // easier to keep a list than to chase through the tree + struct TargetData* pNext; + } TargetData; private: - bool AddDiskFS(CTreeCtrl* pTree, HTREEITEM root, - DiskImgLib::DiskFS* pDiskFS, int depth); - DiskImgLib::A2File* AddSubdir(CTreeCtrl* pTree, HTREEITEM parent, - DiskImgLib::DiskFS* pDiskFS, DiskImgLib::A2File* pFile, - int depth); - TargetData* AllocTargetData(void); - void FreeAllTargetData(void); + bool AddDiskFS(CTreeCtrl* pTree, HTREEITEM root, + DiskImgLib::DiskFS* pDiskFS, int depth); + DiskImgLib::A2File* AddSubdir(CTreeCtrl* pTree, HTREEITEM parent, + DiskImgLib::DiskFS* pDiskFS, DiskImgLib::A2File* pFile, + int depth); + TargetData* AllocTargetData(void); + void FreeAllTargetData(void); - void LoadTreeImages(void) { - if (!fTreeImageList.Create(IDB_TREE_PICS, 16, 1, CLR_DEFAULT)) - WMSG0("GLITCH: list image create failed\n"); - fTreeImageList.SetBkColor(::GetSysColor(COLOR_WINDOW)); - } - enum { // defs for IDB_TREE_PICS - kTreeImageFolderClosed = 0, - kTreeImageFolderOpen = 1, - kTreeImageHardDriveRW = 2, - kTreeImageHardDriveRO = 3, - }; - CImageList fTreeImageList; + void LoadTreeImages(void) { + if (!fTreeImageList.Create(IDB_TREE_PICS, 16, 1, CLR_DEFAULT)) + WMSG0("GLITCH: list image create failed\n"); + fTreeImageList.SetBkColor(::GetSysColor(COLOR_WINDOW)); + } + enum { // defs for IDB_TREE_PICS + kTreeImageFolderClosed = 0, + kTreeImageFolderOpen = 1, + kTreeImageHardDriveRW = 2, + kTreeImageHardDriveRO = 3, + }; + CImageList fTreeImageList; - DiskImgLib::DiskFS* fpDiskFS; - TargetData* fpTargetData; + DiskImgLib::DiskFS* fpDiskFS; + TargetData* fpTargetData; }; #endif /*__DISKFSTREE__*/ diff --git a/app/DoneOpenDialog.h b/app/DoneOpenDialog.h index 5d38b0a..de58d4a 100644 --- a/app/DoneOpenDialog.h +++ b/app/DoneOpenDialog.h @@ -10,7 +10,7 @@ class DoneOpenDialog : public CDialog { public: - DoneOpenDialog(CWnd* pParentWnd = NULL) : CDialog(IDD_DONEOPEN, pParentWnd) - {} - virtual ~DoneOpenDialog(void) {} + DoneOpenDialog(CWnd* pParentWnd = NULL) : CDialog(IDD_DONEOPEN, pParentWnd) + {} + virtual ~DoneOpenDialog(void) {} }; diff --git a/app/EOLScanDialog.cpp b/app/EOLScanDialog.cpp index ffc55d0..14d077d 100644 --- a/app/EOLScanDialog.cpp +++ b/app/EOLScanDialog.cpp @@ -14,7 +14,7 @@ #include "HelpTopics.h" BEGIN_MESSAGE_MAP(EOLScanDialog, CDialog) - ON_COMMAND(IDHELP, OnHelp) + ON_COMMAND(IDHELP, OnHelp) END_MESSAGE_MAP() /* @@ -23,30 +23,30 @@ END_MESSAGE_MAP() BOOL EOLScanDialog::OnInitDialog(void) { - CWnd* pWnd; - CString fmt; + CWnd* pWnd; + CString fmt; - fmt.Format("%ld", fCountChars); - pWnd = GetDlgItem(IDC_EOLSCAN_CHARS); - pWnd->SetWindowText(fmt); + fmt.Format("%ld", fCountChars); + pWnd = GetDlgItem(IDC_EOLSCAN_CHARS); + pWnd->SetWindowText(fmt); - fmt.Format("%ld", fCountCR); - pWnd = GetDlgItem(IDC_EOLSCAN_CR); - pWnd->SetWindowText(fmt); + fmt.Format("%ld", fCountCR); + pWnd = GetDlgItem(IDC_EOLSCAN_CR); + pWnd->SetWindowText(fmt); - fmt.Format("%ld", fCountLF); - pWnd = GetDlgItem(IDC_EOLSCAN_LF); - pWnd->SetWindowText(fmt); + fmt.Format("%ld", fCountLF); + pWnd = GetDlgItem(IDC_EOLSCAN_LF); + pWnd->SetWindowText(fmt); - fmt.Format("%ld", fCountCRLF); - pWnd = GetDlgItem(IDC_EOLSCAN_CRLF); - pWnd->SetWindowText(fmt); + fmt.Format("%ld", fCountCRLF); + pWnd = GetDlgItem(IDC_EOLSCAN_CRLF); + pWnd->SetWindowText(fmt); - fmt.Format("%ld", fCountHighASCII); - pWnd = GetDlgItem(IDC_EOLSCAN_HIGHASCII); - pWnd->SetWindowText(fmt); + fmt.Format("%ld", fCountHighASCII); + pWnd = GetDlgItem(IDC_EOLSCAN_HIGHASCII); + pWnd->SetWindowText(fmt); - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } /* @@ -55,5 +55,5 @@ EOLScanDialog::OnInitDialog(void) void EOLScanDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_EOL_SCAN, HELP_CONTEXT); + WinHelp(HELP_TOPIC_EOL_SCAN, HELP_CONTEXT); } diff --git a/app/EOLScanDialog.h b/app/EOLScanDialog.h index 68bb642..b14f5c5 100644 --- a/app/EOLScanDialog.h +++ b/app/EOLScanDialog.h @@ -16,22 +16,22 @@ */ class EOLScanDialog : public CDialog { public: - EOLScanDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_EOLSCAN, pParentWnd) - {} - virtual ~EOLScanDialog(void) {} + EOLScanDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_EOLSCAN, pParentWnd) + {} + virtual ~EOLScanDialog(void) {} - long fCountChars; - long fCountCR; - long fCountLF; - long fCountCRLF; - long fCountHighASCII; + long fCountChars; + long fCountCR; + long fCountLF; + long fCountCRLF; + long fCountHighASCII; private: - BOOL OnInitDialog(void); - afx_msg void OnHelp(void); + BOOL OnInitDialog(void); + afx_msg void OnHelp(void); - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__EOLSCANDIALOG__*/ diff --git a/app/EditAssocDialog.cpp b/app/EditAssocDialog.cpp index c11a7c4..0ddcc9a 100644 --- a/app/EditAssocDialog.cpp +++ b/app/EditAssocDialog.cpp @@ -13,8 +13,8 @@ #include "HelpTopics.h" BEGIN_MESSAGE_MAP(EditAssocDialog, CDialog) - ON_WM_HELPINFO() - ON_COMMAND(IDHELP, OnHelp) + ON_WM_HELPINFO() + ON_COMMAND(IDHELP, OnHelp) END_MESSAGE_MAP() /* this comes from VC++6.0 MSDN help */ @@ -30,33 +30,33 @@ END_MESSAGE_MAP() BOOL EditAssocDialog::OnInitDialog(void) { - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_ASSOCIATION_LIST); + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_ASSOCIATION_LIST); - ASSERT(pListView != nil); - //pListView->ModifyStyleEx(0, LVS_EX_CHECKBOXES); - ListView_SetExtendedListViewStyleEx(pListView->m_hWnd, - LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); + ASSERT(pListView != nil); + //pListView->ModifyStyleEx(0, LVS_EX_CHECKBOXES); + ListView_SetExtendedListViewStyleEx(pListView->m_hWnd, + LVS_EX_CHECKBOXES, LVS_EX_CHECKBOXES); - /* move it over slightly so we see some overlap */ - CRect rect; - GetWindowRect(&rect); - rect.left += 10; - rect.right += 10; - MoveWindow(&rect); + /* move it over slightly so we see some overlap */ + CRect rect; + GetWindowRect(&rect); + rect.left += 10; + rect.right += 10; + MoveWindow(&rect); - /* - * Initialize this before DDX stuff happens. If the caller didn't - * provide a set, load our own. - */ - if (fOurAssociations == nil) { - fOurAssociations = new bool[gMyApp.fRegistry.GetNumFileAssocs()]; - Setup(true); - } else { - Setup(false); - } + /* + * Initialize this before DDX stuff happens. If the caller didn't + * provide a set, load our own. + */ + if (fOurAssociations == nil) { + fOurAssociations = new bool[gMyApp.fRegistry.GetNumFileAssocs()]; + Setup(true); + } else { + Setup(false); + } - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } /* @@ -70,41 +70,41 @@ EditAssocDialog::OnInitDialog(void) void EditAssocDialog::Setup(bool loadAssoc) { - WMSG0("Setup!\n"); + WMSG0("Setup!\n"); - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_ASSOCIATION_LIST); - ASSERT(pListView != nil); + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_ASSOCIATION_LIST); + ASSERT(pListView != nil); - ASSERT(fOurAssociations != nil); + ASSERT(fOurAssociations != nil); - /* two columns */ - CRect rect; - pListView->GetClientRect(&rect); - int width; + /* two columns */ + CRect rect; + pListView->GetClientRect(&rect); + int width; - width = pListView->GetStringWidth("XXExtensionXX"); - pListView->InsertColumn(0, "Extension", LVCFMT_LEFT, width); - pListView->InsertColumn(1, "Association", LVCFMT_LEFT, - rect.Width() - width); + width = pListView->GetStringWidth("XXExtensionXX"); + pListView->InsertColumn(0, "Extension", LVCFMT_LEFT, width); + pListView->InsertColumn(1, "Association", LVCFMT_LEFT, + rect.Width() - width); - int num = gMyApp.fRegistry.GetNumFileAssocs(); - int idx = 0; - while (num--) { - CString ext, handler; - CString dispStr; - bool ours; + int num = gMyApp.fRegistry.GetNumFileAssocs(); + int idx = 0; + while (num--) { + CString ext, handler; + CString dispStr; + bool ours; - gMyApp.fRegistry.GetFileAssoc(idx, &ext, &handler, &ours); + gMyApp.fRegistry.GetFileAssoc(idx, &ext, &handler, &ours); - pListView->InsertItem(idx, ext); - pListView->SetItemText(idx, 1, handler); + pListView->InsertItem(idx, ext); + pListView->SetItemText(idx, 1, handler); - if (loadAssoc) - fOurAssociations[idx] = ours; - idx++; - } + if (loadAssoc) + fOurAssociations[idx] = ours; + idx++; + } - //DeleteAllItems(); // for Reload case + //DeleteAllItems(); // for Reload case } /* @@ -113,31 +113,31 @@ EditAssocDialog::Setup(bool loadAssoc) void EditAssocDialog::DoDataExchange(CDataExchange* pDX) { - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_ASSOCIATION_LIST); + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_ASSOCIATION_LIST); - ASSERT(fOurAssociations != nil); - if (fOurAssociations == nil) - return; + ASSERT(fOurAssociations != nil); + if (fOurAssociations == nil) + return; - int num = gMyApp.fRegistry.GetNumFileAssocs(); + int num = gMyApp.fRegistry.GetNumFileAssocs(); - if (!pDX->m_bSaveAndValidate) { - /* load fixed set of file associations */ - int idx = 0; - while (num--) { - ListView_SetCheckState(pListView->m_hWnd, idx, - fOurAssociations[idx]); - idx++; - } - } else { - /* copy the checkboxes out */ - int idx = 0; - while (num--) { - fOurAssociations[idx] = - (ListView_GetCheckState(pListView->m_hWnd, idx) != 0); - idx++; - } - } + if (!pDX->m_bSaveAndValidate) { + /* load fixed set of file associations */ + int idx = 0; + while (num--) { + ListView_SetCheckState(pListView->m_hWnd, idx, + fOurAssociations[idx]); + idx++; + } + } else { + /* copy the checkboxes out */ + int idx = 0; + while (num--) { + fOurAssociations[idx] = + (ListView_GetCheckState(pListView->m_hWnd, idx) != 0); + idx++; + } + } } /* @@ -146,7 +146,7 @@ EditAssocDialog::DoDataExchange(CDataExchange* pDX) BOOL EditAssocDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - return ShowContextHelp(this, lpHelpInfo); + return ShowContextHelp(this, lpHelpInfo); } /* @@ -155,5 +155,5 @@ EditAssocDialog::OnHelpInfo(HELPINFO* lpHelpInfo) void EditAssocDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_EDIT_ASSOC, HELP_CONTEXT); + WinHelp(HELP_TOPIC_EDIT_ASSOC, HELP_CONTEXT); } diff --git a/app/EditAssocDialog.h b/app/EditAssocDialog.h index 0a78548..c4bd790 100644 --- a/app/EditAssocDialog.h +++ b/app/EditAssocDialog.h @@ -16,30 +16,30 @@ */ class EditAssocDialog : public CDialog { public: - EditAssocDialog(CWnd* pParentWnd = nil) : - CDialog(IDD_ASSOCIATIONS, pParentWnd), - fOurAssociations(nil) - {} - virtual ~EditAssocDialog() { - delete[] fOurAssociations; - } + EditAssocDialog(CWnd* pParentWnd = nil) : + CDialog(IDD_ASSOCIATIONS, pParentWnd), + fOurAssociations(nil) + {} + virtual ~EditAssocDialog() { + delete[] fOurAssociations; + } - // Which associations are ours. This should be left uninitialized; - // Setup() takes care of that. The caller may "steal" the array - // afterward, freeing it with delete[]. - bool* fOurAssociations; + // Which associations are ours. This should be left uninitialized; + // Setup() takes care of that. The caller may "steal" the array + // afterward, freeing it with delete[]. + bool* fOurAssociations; protected: - // overrides - virtual BOOL OnInitDialog(void); - BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - void DoDataExchange(CDataExchange* pDX); + // overrides + virtual BOOL OnInitDialog(void); + BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + void DoDataExchange(CDataExchange* pDX); - afx_msg void OnHelp(void); + afx_msg void OnHelp(void); - void Setup(bool loadAssoc); + void Setup(bool loadAssoc); - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__EDITASSOCDIALOG__*/ \ No newline at end of file diff --git a/app/EditCommentDialog.cpp b/app/EditCommentDialog.cpp index eaec3da..c44d05d 100644 --- a/app/EditCommentDialog.cpp +++ b/app/EditCommentDialog.cpp @@ -11,9 +11,9 @@ #include "HelpTopics.h" BEGIN_MESSAGE_MAP(EditCommentDialog, CDialog) - ON_BN_CLICKED(IDC_COMMENT_DELETE, OnDelete) - ON_WM_HELPINFO() - ON_COMMAND(IDHELP, OnHelp) + ON_BN_CLICKED(IDC_COMMENT_DELETE, OnDelete) + ON_WM_HELPINFO() + ON_COMMAND(IDHELP, OnHelp) END_MESSAGE_MAP() @@ -24,12 +24,12 @@ END_MESSAGE_MAP() BOOL EditCommentDialog::OnInitDialog(void) { - if (fNewComment) { - CWnd* pWnd = GetDlgItem(IDC_COMMENT_DELETE); - pWnd->EnableWindow(FALSE); - } + if (fNewComment) { + CWnd* pWnd = GetDlgItem(IDC_COMMENT_DELETE); + pWnd->EnableWindow(FALSE); + } - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } /* @@ -38,7 +38,7 @@ EditCommentDialog::OnInitDialog(void) void EditCommentDialog::DoDataExchange(CDataExchange* pDX) { - DDX_Text(pDX, IDC_COMMENT_EDIT, fComment); + DDX_Text(pDX, IDC_COMMENT_EDIT, fComment); } /* @@ -47,16 +47,16 @@ EditCommentDialog::DoDataExchange(CDataExchange* pDX) void EditCommentDialog::OnDelete(void) { - CString question, title; - int result; + CString question, title; + int result; - title.LoadString(IDS_EDIT_COMMENT); - question.LoadString(IDS_DEL_COMMENT_OK); - result = MessageBox(question, title, MB_OKCANCEL | MB_ICONQUESTION); - if (result == IDCANCEL) - return; + title.LoadString(IDS_EDIT_COMMENT); + question.LoadString(IDS_DEL_COMMENT_OK); + result = MessageBox(question, title, MB_OKCANCEL | MB_ICONQUESTION); + if (result == IDCANCEL) + return; - EndDialog(kDeleteCommentID); + EndDialog(kDeleteCommentID); } /* @@ -65,8 +65,8 @@ EditCommentDialog::OnDelete(void) BOOL EditCommentDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* @@ -75,5 +75,5 @@ EditCommentDialog::OnHelpInfo(HELPINFO* lpHelpInfo) void EditCommentDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_EDIT_COMMENT, HELP_CONTEXT); + WinHelp(HELP_TOPIC_EDIT_COMMENT, HELP_CONTEXT); } diff --git a/app/EditCommentDialog.h b/app/EditCommentDialog.h index 2591da5..69b89aa 100644 --- a/app/EditCommentDialog.h +++ b/app/EditCommentDialog.h @@ -18,30 +18,30 @@ */ class EditCommentDialog : public CDialog { public: - EditCommentDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_COMMENT_EDIT, pParentWnd) - { - //fComment = ""; - fNewComment = false; - } - virtual ~EditCommentDialog(void) {} + EditCommentDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_COMMENT_EDIT, pParentWnd) + { + //fComment = ""; + fNewComment = false; + } + virtual ~EditCommentDialog(void) {} - enum { kDeleteCommentID = IDC_COMMENT_DELETE }; + enum { kDeleteCommentID = IDC_COMMENT_DELETE }; - CString fComment; - bool fNewComment; // entry doesn't already have one + CString fComment; + bool fNewComment; // entry doesn't already have one protected: - // overrides - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + // overrides + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - afx_msg void OnHelp(void); - afx_msg void OnDelete(void); + afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg void OnHelp(void); + afx_msg void OnDelete(void); private: - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__EDITCOMMENTDIALOG__*/ \ No newline at end of file diff --git a/app/EditPropsDialog.cpp b/app/EditPropsDialog.cpp index 50efa4b..e9d279a 100644 --- a/app/EditPropsDialog.cpp +++ b/app/EditPropsDialog.cpp @@ -14,14 +14,14 @@ using namespace DiskImgLib; BEGIN_MESSAGE_MAP(EditPropsDialog, CDialog) - ON_BN_CLICKED(IDC_PROPS_ACCESS_W, UpdateSimpleAccess) - ON_BN_CLICKED(IDC_PROPS_HFS_MODE, UpdateHFSMode) - ON_CBN_SELCHANGE(IDC_PROPS_FILETYPE, OnTypeChange) - ON_EN_CHANGE(IDC_PROPS_AUXTYPE, OnTypeChange) - ON_EN_CHANGE(IDC_PROPS_HFS_FILETYPE, OnHFSTypeChange) - ON_EN_CHANGE(IDC_PROPS_HFS_AUXTYPE, OnHFSTypeChange) - ON_WM_HELPINFO() - ON_COMMAND(IDHELP, OnHelp) + ON_BN_CLICKED(IDC_PROPS_ACCESS_W, UpdateSimpleAccess) + ON_BN_CLICKED(IDC_PROPS_HFS_MODE, UpdateHFSMode) + ON_CBN_SELCHANGE(IDC_PROPS_FILETYPE, OnTypeChange) + ON_EN_CHANGE(IDC_PROPS_AUXTYPE, OnTypeChange) + ON_EN_CHANGE(IDC_PROPS_HFS_FILETYPE, OnHFSTypeChange) + ON_EN_CHANGE(IDC_PROPS_HFS_AUXTYPE, OnHFSTypeChange) + ON_WM_HELPINFO() + ON_COMMAND(IDHELP, OnHelp) END_MESSAGE_MAP() @@ -31,31 +31,31 @@ END_MESSAGE_MAP() void EditPropsDialog::InitProps(GenericEntry* pEntry) { - fPathName = pEntry->GetPathName(); - fProps.fileType = pEntry->GetFileType(); - fProps.auxType = pEntry->GetAuxType(); - fProps.access = pEntry->GetAccess(); - fProps.createWhen = pEntry->GetCreateWhen(); - fProps.modWhen = pEntry->GetModWhen(); + fPathName = pEntry->GetPathName(); + fProps.fileType = pEntry->GetFileType(); + fProps.auxType = pEntry->GetAuxType(); + fProps.access = pEntry->GetAccess(); + fProps.createWhen = pEntry->GetCreateWhen(); + fProps.modWhen = pEntry->GetModWhen(); - if (!pEntry->GetFeatureFlag(GenericEntry::kFeatureCanChangeType)) - fAllowedTypes = kAllowedNone; - else if (pEntry->GetFeatureFlag(GenericEntry::kFeaturePascalTypes)) - fAllowedTypes = kAllowedPascal; - else if (pEntry->GetFeatureFlag(GenericEntry::kFeatureDOSTypes)) - fAllowedTypes = kAllowedDOS; - else if (pEntry->GetFeatureFlag(GenericEntry::kFeatureHFSTypes)) - fAllowedTypes = kAllowedHFS; // for HFS disks and ShrinkIt archives - else - fAllowedTypes = kAllowedProDOS; - if (!pEntry->GetFeatureFlag(GenericEntry::kFeatureHasFullAccess)) { - if (pEntry->GetFeatureFlag(GenericEntry::kFeatureHasSimpleAccess)) - fSimpleAccess = true; - else - fNoChangeAccess = true; - } - if (pEntry->GetFeatureFlag(GenericEntry::kFeatureHasInvisibleFlag)) - fAllowInvis = true; + if (!pEntry->GetFeatureFlag(GenericEntry::kFeatureCanChangeType)) + fAllowedTypes = kAllowedNone; + else if (pEntry->GetFeatureFlag(GenericEntry::kFeaturePascalTypes)) + fAllowedTypes = kAllowedPascal; + else if (pEntry->GetFeatureFlag(GenericEntry::kFeatureDOSTypes)) + fAllowedTypes = kAllowedDOS; + else if (pEntry->GetFeatureFlag(GenericEntry::kFeatureHFSTypes)) + fAllowedTypes = kAllowedHFS; // for HFS disks and ShrinkIt archives + else + fAllowedTypes = kAllowedProDOS; + if (!pEntry->GetFeatureFlag(GenericEntry::kFeatureHasFullAccess)) { + if (pEntry->GetFeatureFlag(GenericEntry::kFeatureHasSimpleAccess)) + fSimpleAccess = true; + else + fNoChangeAccess = true; + } + if (pEntry->GetFeatureFlag(GenericEntry::kFeatureHasInvisibleFlag)) + fAllowInvis = true; } @@ -69,130 +69,130 @@ EditPropsDialog::InitProps(GenericEntry* pEntry) BOOL EditPropsDialog::OnInitDialog(void) { - static const int kPascalTypes[] = { - 0x00 /*NON*/, 0x01 /*BAD*/, 0x02 /*PCD*/, 0x03 /*PTX*/, - 0xf3 /*$F3*/, 0x05 /*PDA*/, 0xf4 /*$F4*/, 0x08 /*FOT*/, - 0xf5 /*$f5*/ - }; - static const int kDOSTypes[] = { - 0x04 /*TXT*/, 0x06 /*BIN*/, 0xf2 /*$F2*/, 0xf3 /*$F3*/, - 0xf4 /*$F4*/, 0xfa /*INT*/, 0xfc /*BAS*/, 0xfe /*REL*/ - }; - CComboBox* pCombo; - CWnd* pWnd; - int comboIdx; + static const int kPascalTypes[] = { + 0x00 /*NON*/, 0x01 /*BAD*/, 0x02 /*PCD*/, 0x03 /*PTX*/, + 0xf3 /*$F3*/, 0x05 /*PDA*/, 0xf4 /*$F4*/, 0x08 /*FOT*/, + 0xf5 /*$f5*/ + }; + static const int kDOSTypes[] = { + 0x04 /*TXT*/, 0x06 /*BIN*/, 0xf2 /*$F2*/, 0xf3 /*$F3*/, + 0xf4 /*$F4*/, 0xfa /*INT*/, 0xfc /*BAS*/, 0xfe /*REL*/ + }; + CComboBox* pCombo; + CWnd* pWnd; + int comboIdx; - pCombo = (CComboBox*) GetDlgItem(IDC_PROPS_FILETYPE); - ASSERT(pCombo != nil); + pCombo = (CComboBox*) GetDlgItem(IDC_PROPS_FILETYPE); + ASSERT(pCombo != nil); - pCombo->InitStorage(256, 256 * 8); + pCombo->InitStorage(256, 256 * 8); - for (int type = 0; type < 256; type++) { - const char* str; - char buf[10]; + for (int type = 0; type < 256; type++) { + const char* str; + char buf[10]; - if (fAllowedTypes == kAllowedPascal) { - /* not the most efficient way, but it'll do */ - for (int j = 0; j < NELEM(kPascalTypes); j++) { - if (kPascalTypes[j] == type) - break; - } - if (j == NELEM(kPascalTypes)) - continue; - } else if (fAllowedTypes == kAllowedDOS) { - for (int j = 0; j < NELEM(kDOSTypes); j++) { - if (kDOSTypes[j] == type) - break; - } - if (j == NELEM(kDOSTypes)) - continue; - } + if (fAllowedTypes == kAllowedPascal) { + /* not the most efficient way, but it'll do */ + for (int j = 0; j < NELEM(kPascalTypes); j++) { + if (kPascalTypes[j] == type) + break; + } + if (j == NELEM(kPascalTypes)) + continue; + } else if (fAllowedTypes == kAllowedDOS) { + for (int j = 0; j < NELEM(kDOSTypes); j++) { + if (kDOSTypes[j] == type) + break; + } + if (j == NELEM(kDOSTypes)) + continue; + } - str = PathProposal::FileTypeString(type); - if (str[0] == '$') - sprintf(buf, "??? $%02X", type); - else - sprintf(buf, "%s $%02X", str, type); - comboIdx = pCombo->AddString(buf); - pCombo->SetItemData(comboIdx, type); + str = PathProposal::FileTypeString(type); + if (str[0] == '$') + sprintf(buf, "??? $%02X", type); + else + sprintf(buf, "%s $%02X", str, type); + comboIdx = pCombo->AddString(buf); + pCombo->SetItemData(comboIdx, type); - if ((int) fProps.fileType == type) - pCombo->SetCurSel(comboIdx); - } - if (fProps.fileType >= 256) { - if (fAllowedTypes == kAllowedHFS) { - pCombo->SetCurSel(0); - } else { - // unexpected -- bogus data out of DiskFS? - comboIdx = pCombo->AddString("???"); - pCombo->SetCurSel(comboIdx); - pCombo->SetItemData(comboIdx, 256); - } - } + if ((int) fProps.fileType == type) + pCombo->SetCurSel(comboIdx); + } + if (fProps.fileType >= 256) { + if (fAllowedTypes == kAllowedHFS) { + pCombo->SetCurSel(0); + } else { + // unexpected -- bogus data out of DiskFS? + comboIdx = pCombo->AddString("???"); + pCombo->SetCurSel(comboIdx); + pCombo->SetItemData(comboIdx, 256); + } + } - CString dateStr; - pWnd = GetDlgItem(IDC_PROPS_CREATEWHEN); - ASSERT(pWnd != nil); - FormatDate(fProps.createWhen, &dateStr); - pWnd->SetWindowText(dateStr); + CString dateStr; + pWnd = GetDlgItem(IDC_PROPS_CREATEWHEN); + ASSERT(pWnd != nil); + FormatDate(fProps.createWhen, &dateStr); + pWnd->SetWindowText(dateStr); - pWnd = GetDlgItem(IDC_PROPS_MODWHEN); - ASSERT(pWnd != nil); - FormatDate(fProps.modWhen, &dateStr); - pWnd->SetWindowText(dateStr); - //WMSG2("USING DATE '%s' from 0x%08lx\n", dateStr, fProps.modWhen); + pWnd = GetDlgItem(IDC_PROPS_MODWHEN); + ASSERT(pWnd != nil); + FormatDate(fProps.modWhen, &dateStr); + pWnd->SetWindowText(dateStr); + //WMSG2("USING DATE '%s' from 0x%08lx\n", dateStr, fProps.modWhen); - CEdit* pEdit = (CEdit*) GetDlgItem(IDC_PROPS_AUXTYPE); - ASSERT(pEdit != nil); - pEdit->SetLimitText(4); // max len of aux type str - pEdit = (CEdit*) GetDlgItem(IDC_PROPS_HFS_FILETYPE); - pEdit->SetLimitText(4); - pEdit = (CEdit*) GetDlgItem(IDC_PROPS_HFS_AUXTYPE); - pEdit->SetLimitText(4); + CEdit* pEdit = (CEdit*) GetDlgItem(IDC_PROPS_AUXTYPE); + ASSERT(pEdit != nil); + pEdit->SetLimitText(4); // max len of aux type str + pEdit = (CEdit*) GetDlgItem(IDC_PROPS_HFS_FILETYPE); + pEdit->SetLimitText(4); + pEdit = (CEdit*) GetDlgItem(IDC_PROPS_HFS_AUXTYPE); + pEdit->SetLimitText(4); - if (fReadOnly || fAllowedTypes == kAllowedNone) { - pWnd = GetDlgItem(IDC_PROPS_FILETYPE); - pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_PROPS_AUXTYPE); - pWnd->EnableWindow(FALSE); - } else if (fAllowedTypes == kAllowedPascal) { - pWnd = GetDlgItem(IDC_PROPS_AUXTYPE); - pWnd->EnableWindow(FALSE); - } - if (fReadOnly || fSimpleAccess || fNoChangeAccess) { - pWnd = GetDlgItem(IDC_PROPS_ACCESS_R); - pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_PROPS_ACCESS_B); - pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_PROPS_ACCESS_N); - pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_PROPS_ACCESS_D); - pWnd->EnableWindow(FALSE); - } - if (fReadOnly || !fAllowInvis) { - pWnd = GetDlgItem(IDC_PROPS_ACCESS_I); - pWnd->EnableWindow(FALSE); - } - if (fReadOnly || fNoChangeAccess) { - pWnd = GetDlgItem(IDC_PROPS_ACCESS_W); - pWnd->EnableWindow(FALSE); - } - if (fReadOnly) { - pWnd = GetDlgItem(IDOK); - pWnd->EnableWindow(FALSE); + if (fReadOnly || fAllowedTypes == kAllowedNone) { + pWnd = GetDlgItem(IDC_PROPS_FILETYPE); + pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_PROPS_AUXTYPE); + pWnd->EnableWindow(FALSE); + } else if (fAllowedTypes == kAllowedPascal) { + pWnd = GetDlgItem(IDC_PROPS_AUXTYPE); + pWnd->EnableWindow(FALSE); + } + if (fReadOnly || fSimpleAccess || fNoChangeAccess) { + pWnd = GetDlgItem(IDC_PROPS_ACCESS_R); + pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_PROPS_ACCESS_B); + pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_PROPS_ACCESS_N); + pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_PROPS_ACCESS_D); + pWnd->EnableWindow(FALSE); + } + if (fReadOnly || !fAllowInvis) { + pWnd = GetDlgItem(IDC_PROPS_ACCESS_I); + pWnd->EnableWindow(FALSE); + } + if (fReadOnly || fNoChangeAccess) { + pWnd = GetDlgItem(IDC_PROPS_ACCESS_W); + pWnd->EnableWindow(FALSE); + } + if (fReadOnly) { + pWnd = GetDlgItem(IDOK); + pWnd->EnableWindow(FALSE); - CString title; - GetWindowText(/*ref*/ title); - title = title + " (read only)"; - SetWindowText(title); - } + CString title; + GetWindowText(/*ref*/ title); + title = title + " (read only)"; + SetWindowText(title); + } - if (fAllowedTypes != kAllowedHFS) { - CButton* pButton = (CButton*) GetDlgItem(IDC_PROPS_HFS_MODE); - pButton->EnableWindow(FALSE); - } + if (fAllowedTypes != kAllowedHFS) { + CButton* pButton = (CButton*) GetDlgItem(IDC_PROPS_HFS_MODE); + pButton->EnableWindow(FALSE); + } - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } /* @@ -201,143 +201,143 @@ EditPropsDialog::OnInitDialog(void) void EditPropsDialog::DoDataExchange(CDataExchange* pDX) { - int fileTypeIdx; - BOOL accessR, accessW, accessI, accessB, accessN, accessD; - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_PROPS_FILETYPE); + int fileTypeIdx; + BOOL accessR, accessW, accessI, accessB, accessN, accessD; + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_PROPS_FILETYPE); - if (pDX->m_bSaveAndValidate) { - CString appName; - CButton *pButton; - bool typeChanged = false; + if (pDX->m_bSaveAndValidate) { + CString appName; + CButton *pButton; + bool typeChanged = false; - appName.LoadString(IDS_MB_APP_NAME); + appName.LoadString(IDS_MB_APP_NAME); - pButton = (CButton*) GetDlgItem(IDC_PROPS_HFS_MODE); - if (pButton->GetCheck() == BST_CHECKED) { - /* HFS mode */ - CString type, creator; - DDX_Text(pDX, IDC_PROPS_HFS_FILETYPE, type); - DDX_Text(pDX, IDC_PROPS_HFS_AUXTYPE, creator); - if (type.GetLength() != 4 || creator.GetLength() != 4) { - MessageBox("The file and creator types must be exactly" - " 4 characters each.", - appName, MB_OK); - pDX->Fail(); - return; - } - fProps.fileType = ((unsigned char) type[0]) << 24 | - ((unsigned char) type[1]) << 16 | - ((unsigned char) type[2]) << 8 | - ((unsigned char) type[3]); - fProps.auxType = ((unsigned char) creator[0]) << 24 | - ((unsigned char) creator[1]) << 16 | - ((unsigned char) creator[2]) << 8 | - ((unsigned char) creator[3]); - } else { - /* ProDOS mode */ - if (GetAuxType() < 0) { - MessageBox("The AuxType field must be a valid 4-digit" - " hexadecimal number.", - appName, MB_OK); - pDX->Fail(); - return; - } - fProps.auxType = GetAuxType(); + pButton = (CButton*) GetDlgItem(IDC_PROPS_HFS_MODE); + if (pButton->GetCheck() == BST_CHECKED) { + /* HFS mode */ + CString type, creator; + DDX_Text(pDX, IDC_PROPS_HFS_FILETYPE, type); + DDX_Text(pDX, IDC_PROPS_HFS_AUXTYPE, creator); + if (type.GetLength() != 4 || creator.GetLength() != 4) { + MessageBox("The file and creator types must be exactly" + " 4 characters each.", + appName, MB_OK); + pDX->Fail(); + return; + } + fProps.fileType = ((unsigned char) type[0]) << 24 | + ((unsigned char) type[1]) << 16 | + ((unsigned char) type[2]) << 8 | + ((unsigned char) type[3]); + fProps.auxType = ((unsigned char) creator[0]) << 24 | + ((unsigned char) creator[1]) << 16 | + ((unsigned char) creator[2]) << 8 | + ((unsigned char) creator[3]); + } else { + /* ProDOS mode */ + if (GetAuxType() < 0) { + MessageBox("The AuxType field must be a valid 4-digit" + " hexadecimal number.", + appName, MB_OK); + pDX->Fail(); + return; + } + fProps.auxType = GetAuxType(); - /* pull the file type out, but don't disturb >= 256 */ - DDX_CBIndex(pDX, IDC_PROPS_FILETYPE, fileTypeIdx); - if (fileTypeIdx != 256) { - unsigned long oldType = fProps.fileType; - fProps.fileType = pCombo->GetItemData(fileTypeIdx); - if (fProps.fileType != oldType) - typeChanged = true; - } - } + /* pull the file type out, but don't disturb >= 256 */ + DDX_CBIndex(pDX, IDC_PROPS_FILETYPE, fileTypeIdx); + if (fileTypeIdx != 256) { + unsigned long oldType = fProps.fileType; + fProps.fileType = pCombo->GetItemData(fileTypeIdx); + if (fProps.fileType != oldType) + typeChanged = true; + } + } - DDX_Check(pDX, IDC_PROPS_ACCESS_R, accessR); - DDX_Check(pDX, IDC_PROPS_ACCESS_W, accessW); - DDX_Check(pDX, IDC_PROPS_ACCESS_I, accessI); - DDX_Check(pDX, IDC_PROPS_ACCESS_B, accessB); - DDX_Check(pDX, IDC_PROPS_ACCESS_N, accessN); - DDX_Check(pDX, IDC_PROPS_ACCESS_D, accessD); - fProps.access = (accessR ? GenericEntry::kAccessRead : 0) | - (accessW ? GenericEntry::kAccessWrite : 0) | - (accessI ? GenericEntry::kAccessInvisible : 0) | - (accessB ? GenericEntry::kAccessBackup : 0) | - (accessN ? GenericEntry::kAccessRename : 0) | - (accessD ? GenericEntry::kAccessDelete : 0); + DDX_Check(pDX, IDC_PROPS_ACCESS_R, accessR); + DDX_Check(pDX, IDC_PROPS_ACCESS_W, accessW); + DDX_Check(pDX, IDC_PROPS_ACCESS_I, accessI); + DDX_Check(pDX, IDC_PROPS_ACCESS_B, accessB); + DDX_Check(pDX, IDC_PROPS_ACCESS_N, accessN); + DDX_Check(pDX, IDC_PROPS_ACCESS_D, accessD); + fProps.access = (accessR ? GenericEntry::kAccessRead : 0) | + (accessW ? GenericEntry::kAccessWrite : 0) | + (accessI ? GenericEntry::kAccessInvisible : 0) | + (accessB ? GenericEntry::kAccessBackup : 0) | + (accessN ? GenericEntry::kAccessRename : 0) | + (accessD ? GenericEntry::kAccessDelete : 0); - if (fAllowedTypes == kAllowedDOS && typeChanged && - (fProps.fileType == kFileTypeBIN || - fProps.fileType == kFileTypeINT || - fProps.fileType == kFileTypeBAS)) - { - CString msg; - int result; + if (fAllowedTypes == kAllowedDOS && typeChanged && + (fProps.fileType == kFileTypeBIN || + fProps.fileType == kFileTypeINT || + fProps.fileType == kFileTypeBAS)) + { + CString msg; + int result; - msg.LoadString(IDS_PROPS_DOS_TYPE_CHANGE); - result = MessageBox(msg, appName, MB_ICONQUESTION|MB_OKCANCEL); - if (result != IDOK) { - pDX->Fail(); - return; - } - } - } else { - accessR = (fProps.access & GenericEntry::kAccessRead) != 0; - accessW = (fProps.access & GenericEntry::kAccessWrite) != 0; - accessI = (fProps.access & GenericEntry::kAccessInvisible) != 0; - accessB = (fProps.access & GenericEntry::kAccessBackup) != 0; - accessN = (fProps.access & GenericEntry::kAccessRename) != 0; - accessD = (fProps.access & GenericEntry::kAccessDelete) != 0; - DDX_Check(pDX, IDC_PROPS_ACCESS_R, accessR); - DDX_Check(pDX, IDC_PROPS_ACCESS_W, accessW); - DDX_Check(pDX, IDC_PROPS_ACCESS_I, accessI); - DDX_Check(pDX, IDC_PROPS_ACCESS_B, accessB); - DDX_Check(pDX, IDC_PROPS_ACCESS_N, accessN); - DDX_Check(pDX, IDC_PROPS_ACCESS_D, accessD); + msg.LoadString(IDS_PROPS_DOS_TYPE_CHANGE); + result = MessageBox(msg, appName, MB_ICONQUESTION|MB_OKCANCEL); + if (result != IDOK) { + pDX->Fail(); + return; + } + } + } else { + accessR = (fProps.access & GenericEntry::kAccessRead) != 0; + accessW = (fProps.access & GenericEntry::kAccessWrite) != 0; + accessI = (fProps.access & GenericEntry::kAccessInvisible) != 0; + accessB = (fProps.access & GenericEntry::kAccessBackup) != 0; + accessN = (fProps.access & GenericEntry::kAccessRename) != 0; + accessD = (fProps.access & GenericEntry::kAccessDelete) != 0; + DDX_Check(pDX, IDC_PROPS_ACCESS_R, accessR); + DDX_Check(pDX, IDC_PROPS_ACCESS_W, accessW); + DDX_Check(pDX, IDC_PROPS_ACCESS_I, accessI); + DDX_Check(pDX, IDC_PROPS_ACCESS_B, accessB); + DDX_Check(pDX, IDC_PROPS_ACCESS_N, accessN); + DDX_Check(pDX, IDC_PROPS_ACCESS_D, accessD); - if (fAllowedTypes == kAllowedHFS && - (fProps.fileType > 0xff || fProps.auxType > 0xffff)) - { - char type[5], creator[5]; + if (fAllowedTypes == kAllowedHFS && + (fProps.fileType > 0xff || fProps.auxType > 0xffff)) + { + char type[5], creator[5]; - type[0] = (unsigned char) (fProps.fileType >> 24); - type[1] = (unsigned char) (fProps.fileType >> 16); - type[2] = (unsigned char) (fProps.fileType >> 8); - type[3] = (unsigned char) fProps.fileType; - type[4] = '\0'; - creator[0] = (unsigned char) (fProps.auxType >> 24); - creator[1] = (unsigned char) (fProps.auxType >> 16); - creator[2] = (unsigned char) (fProps.auxType >> 8); - creator[3] = (unsigned char) fProps.auxType; - creator[4] = '\0'; + type[0] = (unsigned char) (fProps.fileType >> 24); + type[1] = (unsigned char) (fProps.fileType >> 16); + type[2] = (unsigned char) (fProps.fileType >> 8); + type[3] = (unsigned char) fProps.fileType; + type[4] = '\0'; + creator[0] = (unsigned char) (fProps.auxType >> 24); + creator[1] = (unsigned char) (fProps.auxType >> 16); + creator[2] = (unsigned char) (fProps.auxType >> 8); + creator[3] = (unsigned char) fProps.auxType; + creator[4] = '\0'; - CString tmpStr; - tmpStr = type; - DDX_Text(pDX, IDC_PROPS_HFS_FILETYPE, tmpStr); - tmpStr = creator; - DDX_Text(pDX, IDC_PROPS_HFS_AUXTYPE, tmpStr); - tmpStr = "0000"; - DDX_Text(pDX, IDC_PROPS_AUXTYPE, tmpStr); + CString tmpStr; + tmpStr = type; + DDX_Text(pDX, IDC_PROPS_HFS_FILETYPE, tmpStr); + tmpStr = creator; + DDX_Text(pDX, IDC_PROPS_HFS_AUXTYPE, tmpStr); + tmpStr = "0000"; + DDX_Text(pDX, IDC_PROPS_AUXTYPE, tmpStr); - CButton* pButton = (CButton*) GetDlgItem(IDC_PROPS_HFS_MODE); - pButton->SetCheck(BST_CHECKED); - } else { - //fileTypeIdx = fProps.fileType; - //if (fileTypeIdx > 256) - // fileTypeIdx = 256; - //DDX_CBIndex(pDX, IDC_PROPS_FILETYPE, fileTypeIdx); + CButton* pButton = (CButton*) GetDlgItem(IDC_PROPS_HFS_MODE); + pButton->SetCheck(BST_CHECKED); + } else { + //fileTypeIdx = fProps.fileType; + //if (fileTypeIdx > 256) + // fileTypeIdx = 256; + //DDX_CBIndex(pDX, IDC_PROPS_FILETYPE, fileTypeIdx); - /* write the aux type as a hex string */ - fAuxType.Format("%04X", fProps.auxType); - DDX_Text(pDX, IDC_PROPS_AUXTYPE, fAuxType); - } - OnTypeChange(); // set the description field - UpdateHFSMode(); // set up fields - UpdateSimpleAccess(); // coordinate N/D with W - } + /* write the aux type as a hex string */ + fAuxType.Format("%04X", fProps.auxType); + DDX_Text(pDX, IDC_PROPS_AUXTYPE, fAuxType); + } + OnTypeChange(); // set the description field + UpdateHFSMode(); // set up fields + UpdateSimpleAccess(); // coordinate N/D with W + } - DDX_Text(pDX, IDC_PROPS_PATHNAME, fPathName); + DDX_Text(pDX, IDC_PROPS_PATHNAME, fPathName); } /* @@ -352,38 +352,38 @@ EditPropsDialog::DoDataExchange(CDataExchange* pDX) void EditPropsDialog::OnTypeChange(void) { - static const char* kUnknownFileType = "Unknown file type"; - CComboBox* pCombo; - CWnd* pWnd; - int fileType, fileTypeIdx; - long auxType; - const char* descr = nil; + static const char* kUnknownFileType = "Unknown file type"; + CComboBox* pCombo; + CWnd* pWnd; + int fileType, fileTypeIdx; + long auxType; + const char* descr = nil; - pCombo = (CComboBox*) GetDlgItem(IDC_PROPS_FILETYPE); - ASSERT(pCombo != nil); + pCombo = (CComboBox*) GetDlgItem(IDC_PROPS_FILETYPE); + ASSERT(pCombo != nil); - fileTypeIdx = pCombo->GetCurSel(); - fileType = pCombo->GetItemData(fileTypeIdx); - if (fileType >= 256) { - descr = kUnknownFileType; - } else { - auxType = GetAuxType(); - if (auxType < 0) - auxType = 0; - descr = PathProposal::FileTypeDescription(fileType, auxType); - if (descr == nil) - descr = kUnknownFileType; - } + fileTypeIdx = pCombo->GetCurSel(); + fileType = pCombo->GetItemData(fileTypeIdx); + if (fileType >= 256) { + descr = kUnknownFileType; + } else { + auxType = GetAuxType(); + if (auxType < 0) + auxType = 0; + descr = PathProposal::FileTypeDescription(fileType, auxType); + if (descr == nil) + descr = kUnknownFileType; + } - pWnd = GetDlgItem(IDC_PROPS_TYPEDESCR); - ASSERT(pWnd != nil); - pWnd->SetWindowText(descr); + pWnd = GetDlgItem(IDC_PROPS_TYPEDESCR); + ASSERT(pWnd != nil); + pWnd->SetWindowText(descr); - /* DOS aux type only applies to BIN */ - if (!fReadOnly && fAllowedTypes == kAllowedDOS) { - pWnd = GetDlgItem(IDC_PROPS_AUXTYPE); - pWnd->EnableWindow(fileType == kFileTypeBIN); - } + /* DOS aux type only applies to BIN */ + if (!fReadOnly && fAllowedTypes == kAllowedDOS) { + pWnd = GetDlgItem(IDC_PROPS_AUXTYPE); + pWnd->EnableWindow(fileType == kFileTypeBIN); + } } /* @@ -392,7 +392,7 @@ EditPropsDialog::OnTypeChange(void) void EditPropsDialog::OnHFSTypeChange(void) { - assert(fAllowedTypes == kAllowedHFS); + assert(fAllowedTypes == kAllowedHFS); } /* @@ -401,50 +401,50 @@ EditPropsDialog::OnHFSTypeChange(void) void EditPropsDialog::UpdateHFSMode(void) { - CButton* pButton = (CButton*) GetDlgItem(IDC_PROPS_HFS_MODE); - CComboBox* pCombo; - CWnd* pWnd; + CButton* pButton = (CButton*) GetDlgItem(IDC_PROPS_HFS_MODE); + CComboBox* pCombo; + CWnd* pWnd; - if (pButton->GetCheck() == BST_CHECKED) { - /* switch to HFS mode */ - WMSG0("Switching to HFS mode\n"); - //fHFSMode = true; + if (pButton->GetCheck() == BST_CHECKED) { + /* switch to HFS mode */ + WMSG0("Switching to HFS mode\n"); + //fHFSMode = true; - pWnd = GetDlgItem(IDC_PROPS_HFS_FILETYPE); - pWnd->EnableWindow(TRUE); - pWnd = GetDlgItem(IDC_PROPS_HFS_AUXTYPE); - pWnd->EnableWindow(TRUE); - pWnd = GetDlgItem(IDC_PROPS_HFS_LABEL); - pWnd->EnableWindow(TRUE); + pWnd = GetDlgItem(IDC_PROPS_HFS_FILETYPE); + pWnd->EnableWindow(TRUE); + pWnd = GetDlgItem(IDC_PROPS_HFS_AUXTYPE); + pWnd->EnableWindow(TRUE); + pWnd = GetDlgItem(IDC_PROPS_HFS_LABEL); + pWnd->EnableWindow(TRUE); - /* point the file type at something safe */ - pCombo = (CComboBox*) GetDlgItem(IDC_PROPS_FILETYPE); - pCombo->EnableWindow(FALSE); + /* point the file type at something safe */ + pCombo = (CComboBox*) GetDlgItem(IDC_PROPS_FILETYPE); + pCombo->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_PROPS_AUXTYPE); - pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_PROPS_AUXTYPE); + pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_PROPS_TYPEDESCR); - ASSERT(pWnd != nil); - pWnd->SetWindowText("(HFS type)"); - OnHFSTypeChange(); - } else { - /* switch to ProDOS mode */ - WMSG0("Switching to ProDOS mode\n"); - //fHFSMode = false; - pCombo = (CComboBox*) GetDlgItem(IDC_PROPS_FILETYPE); - pCombo->EnableWindow(TRUE); - pWnd = GetDlgItem(IDC_PROPS_AUXTYPE); - pWnd->EnableWindow(TRUE); + pWnd = GetDlgItem(IDC_PROPS_TYPEDESCR); + ASSERT(pWnd != nil); + pWnd->SetWindowText("(HFS type)"); + OnHFSTypeChange(); + } else { + /* switch to ProDOS mode */ + WMSG0("Switching to ProDOS mode\n"); + //fHFSMode = false; + pCombo = (CComboBox*) GetDlgItem(IDC_PROPS_FILETYPE); + pCombo->EnableWindow(TRUE); + pWnd = GetDlgItem(IDC_PROPS_AUXTYPE); + pWnd->EnableWindow(TRUE); - pWnd = GetDlgItem(IDC_PROPS_HFS_FILETYPE); - pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_PROPS_HFS_AUXTYPE); - pWnd->EnableWindow(FALSE); - pWnd = GetDlgItem(IDC_PROPS_HFS_LABEL); - pWnd->EnableWindow(FALSE); - OnTypeChange(); - } + pWnd = GetDlgItem(IDC_PROPS_HFS_FILETYPE); + pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_PROPS_HFS_AUXTYPE); + pWnd->EnableWindow(FALSE); + pWnd = GetDlgItem(IDC_PROPS_HFS_LABEL); + pWnd->EnableWindow(FALSE); + OnTypeChange(); + } } /* @@ -455,19 +455,19 @@ EditPropsDialog::UpdateHFSMode(void) void EditPropsDialog::UpdateSimpleAccess(void) { - if (!fSimpleAccess) - return; + if (!fSimpleAccess) + return; - CButton* pButton; - UINT checked; + CButton* pButton; + UINT checked; - pButton = (CButton*) GetDlgItem(IDC_PROPS_ACCESS_W); - checked = pButton->GetCheck(); + pButton = (CButton*) GetDlgItem(IDC_PROPS_ACCESS_W); + checked = pButton->GetCheck(); - pButton = (CButton*) GetDlgItem(IDC_PROPS_ACCESS_N); - pButton->SetCheck(checked); - pButton = (CButton*) GetDlgItem(IDC_PROPS_ACCESS_D); - pButton->SetCheck(checked); + pButton = (CButton*) GetDlgItem(IDC_PROPS_ACCESS_N); + pButton->SetCheck(checked); + pButton = (CButton*) GetDlgItem(IDC_PROPS_ACCESS_D); + pButton->SetCheck(checked); } @@ -480,27 +480,27 @@ EditPropsDialog::UpdateSimpleAccess(void) long EditPropsDialog::GetAuxType(void) { - CWnd* pWnd = GetDlgItem(IDC_PROPS_AUXTYPE); - ASSERT(pWnd != nil); + CWnd* pWnd = GetDlgItem(IDC_PROPS_AUXTYPE); + ASSERT(pWnd != nil); - CString aux; - pWnd->GetWindowText(aux); + CString aux; + pWnd->GetWindowText(aux); - const char* str = aux; - char* end; - long val; + const char* str = aux; + char* end; + long val; - if (str[0] == '\0') { - WMSG0(" HEY: blank aux type, returning -1\n"); - return -1; - } - val = strtoul(aux, &end, 16); - if (end != str + strlen(str)) { - WMSG1(" HEY: found some garbage in aux type '%s', returning -1\n", - (LPCTSTR) aux); - return -1; - } - return val; + if (str[0] == '\0') { + WMSG0(" HEY: blank aux type, returning -1\n"); + return -1; + } + val = strtoul(aux, &end, 16); + if (end != str + strlen(str)) { + WMSG1(" HEY: found some garbage in aux type '%s', returning -1\n", + (LPCTSTR) aux); + return -1; + } + return val; } /* @@ -509,8 +509,8 @@ EditPropsDialog::GetAuxType(void) BOOL EditPropsDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* @@ -519,5 +519,5 @@ EditPropsDialog::OnHelpInfo(HELPINFO* lpHelpInfo) void EditPropsDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_EDIT_PROPS, HELP_CONTEXT); + WinHelp(HELP_TOPIC_EDIT_PROPS, HELP_CONTEXT); } diff --git a/app/EditPropsDialog.h b/app/EditPropsDialog.h index 96c3bf9..f98f1aa 100644 --- a/app/EditPropsDialog.h +++ b/app/EditPropsDialog.h @@ -17,72 +17,72 @@ */ class EditPropsDialog : public CDialog { public: - typedef enum AllowedTypes { - kAllowedUnknown = 0, - kAllowedProDOS, // 8-bit type, 16-bit aux - kAllowedHFS, // 32-bit type, 32-bit aux - kAllowedNone, // CP/M - kAllowedPascal, // UCSD Pascal - kAllowedDOS, // DOS 3.2/3.3 - } AllowedTypes; + typedef enum AllowedTypes { + kAllowedUnknown = 0, + kAllowedProDOS, // 8-bit type, 16-bit aux + kAllowedHFS, // 32-bit type, 32-bit aux + kAllowedNone, // CP/M + kAllowedPascal, // UCSD Pascal + kAllowedDOS, // DOS 3.2/3.3 + } AllowedTypes; - EditPropsDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_PROPS_EDIT, pParentWnd) - { - memset(&fProps, 0, sizeof(fProps)); - fReadOnly = false; - fAllowedTypes = kAllowedProDOS; - fSimpleAccess = false; - fNoChangeAccess = false; - fAllowInvis = false; - //fHFSMode = false; - fHFSComboIdx = -1; - } - ~EditPropsDialog(void) {} + EditPropsDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_PROPS_EDIT, pParentWnd) + { + memset(&fProps, 0, sizeof(fProps)); + fReadOnly = false; + fAllowedTypes = kAllowedProDOS; + fSimpleAccess = false; + fNoChangeAccess = false; + fAllowInvis = false; + //fHFSMode = false; + fHFSComboIdx = -1; + } + ~EditPropsDialog(void) {} - /* these get handed to GenericArchive */ - FileProps fProps; + /* these get handed to GenericArchive */ + FileProps fProps; - /* initialize fProps and other fields from pEntry */ - void InitProps(GenericEntry* pEntry); + /* initialize fProps and other fields from pEntry */ + void InitProps(GenericEntry* pEntry); - /* set this to disable editing of all fields */ - bool fReadOnly; + /* set this to disable editing of all fields */ + bool fReadOnly; private: - // overrides - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + // overrides + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - afx_msg void OnTypeChange(void); - afx_msg void OnHFSTypeChange(void); - afx_msg void OnHelp(void); - afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg void OnTypeChange(void); + afx_msg void OnHFSTypeChange(void); + afx_msg void OnHelp(void); + afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - void UpdateSimpleAccess(void); - void UpdateHFSMode(void); - long GetAuxType(void); - //void ShowHFSType(void); + void UpdateSimpleAccess(void); + void UpdateHFSMode(void); + long GetAuxType(void); + //void ShowHFSType(void); - /* what sort of type changes do we allow? */ - AllowedTypes fAllowedTypes; - /* set this to disable access to fields other than 'W' */ - bool fSimpleAccess; - /* set this to disable file access fields */ - bool fNoChangeAccess; - /* this enabled the 'I' flag, independent of other settings */ - bool fAllowInvis; + /* what sort of type changes do we allow? */ + AllowedTypes fAllowedTypes; + /* set this to disable access to fields other than 'W' */ + bool fSimpleAccess; + /* set this to disable file access fields */ + bool fNoChangeAccess; + /* this enabled the 'I' flag, independent of other settings */ + bool fAllowInvis; - /* are we in "ProDOS mode" or "HFS mode"? */ - //bool fHFSMode; - /* fake file type entry that says "(HFS)" */ - int fHFSComboIdx; + /* are we in "ProDOS mode" or "HFS mode"? */ + //bool fHFSMode; + /* fake file type entry that says "(HFS)" */ + int fHFSComboIdx; - /* these are displayed locally */ - CString fPathName; - CString fAuxType; // DDX doesn't do hex conversion + /* these are displayed locally */ + CString fPathName; + CString fAuxType; // DDX doesn't do hex conversion - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__EDITPROPSDIALOG__*/ \ No newline at end of file diff --git a/app/EnterRegDialog.cpp b/app/EnterRegDialog.cpp index f3e1a6d..aff8f55 100644 --- a/app/EnterRegDialog.cpp +++ b/app/EnterRegDialog.cpp @@ -13,10 +13,10 @@ #include "HelpTopics.h" BEGIN_MESSAGE_MAP(EnterRegDialog, CDialog) - ON_EN_CHANGE(IDC_REGENTER_USER, OnUserChange) - ON_EN_CHANGE(IDC_REGENTER_COMPANY, OnCompanyChange) - ON_EN_CHANGE(IDC_REGENTER_REG, OnRegChange) - ON_COMMAND(IDHELP, OnHelp) + ON_EN_CHANGE(IDC_REGENTER_USER, OnUserChange) + ON_EN_CHANGE(IDC_REGENTER_COMPANY, OnCompanyChange) + ON_EN_CHANGE(IDC_REGENTER_REG, OnRegChange) + ON_COMMAND(IDHELP, OnHelp) END_MESSAGE_MAP() @@ -26,27 +26,27 @@ END_MESSAGE_MAP() BOOL EnterRegDialog::OnInitDialog(void) { - //CWnd* pWnd = GetDlgItem(IDOK); - //ASSERT(pWnd != nil); - //pWnd->EnableWindow(false); + //CWnd* pWnd = GetDlgItem(IDOK); + //ASSERT(pWnd != nil); + //pWnd->EnableWindow(false); - fMyEdit.ReplaceDlgCtrl(this, IDC_REGENTER_REG); - fMyEdit.SetProperties(MyEdit::kCapsOnly | MyEdit::kNoWhiteSpace); + fMyEdit.ReplaceDlgCtrl(this, IDC_REGENTER_REG); + fMyEdit.SetProperties(MyEdit::kCapsOnly | MyEdit::kNoWhiteSpace); - /* place a reasonable cap on the field lengths, since these go - straight into the registry */ - CEdit* pEdit; - pEdit = (CEdit*) GetDlgItem(IDC_REGENTER_USER); - ASSERT(pEdit != nil); - pEdit->SetLimitText(120); - pEdit = (CEdit*) GetDlgItem(IDC_REGENTER_COMPANY); - ASSERT(pEdit != nil); - pEdit->SetLimitText(120); - pEdit = (CEdit*) GetDlgItem(IDC_REGENTER_REG); - ASSERT(pEdit != nil); - pEdit->SetLimitText(40); + /* place a reasonable cap on the field lengths, since these go + straight into the registry */ + CEdit* pEdit; + pEdit = (CEdit*) GetDlgItem(IDC_REGENTER_USER); + ASSERT(pEdit != nil); + pEdit->SetLimitText(120); + pEdit = (CEdit*) GetDlgItem(IDC_REGENTER_COMPANY); + ASSERT(pEdit != nil); + pEdit->SetLimitText(120); + pEdit = (CEdit*) GetDlgItem(IDC_REGENTER_REG); + ASSERT(pEdit != nil); + pEdit->SetLimitText(40); - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } /* @@ -56,33 +56,33 @@ EnterRegDialog::OnInitDialog(void) void EnterRegDialog::DoDataExchange(CDataExchange* pDX) { - DDX_Text(pDX, IDC_REGENTER_USER, fUserName); - DDX_Text(pDX, IDC_REGENTER_COMPANY, fCompanyName); - DDX_Text(pDX, IDC_REGENTER_REG, fRegKey); + DDX_Text(pDX, IDC_REGENTER_USER, fUserName); + DDX_Text(pDX, IDC_REGENTER_COMPANY, fCompanyName); + DDX_Text(pDX, IDC_REGENTER_REG, fRegKey); - /* validate the reg field */ - if (pDX->m_bSaveAndValidate) { - ASSERT(!fUserName.IsEmpty()); - ASSERT(!fRegKey.IsEmpty()); + /* validate the reg field */ + if (pDX->m_bSaveAndValidate) { + ASSERT(!fUserName.IsEmpty()); + ASSERT(!fRegKey.IsEmpty()); - if (gMyApp.fRegistry.IsValidRegistrationKey(fUserName, fCompanyName, - fRegKey)) - { - WMSG3("Correct key entered: '%s' '%s' '%s'\n", - (LPCTSTR)fUserName, (LPCTSTR)fCompanyName, (LPCTSTR)fRegKey); - } else { - WMSG0("Incorrect key entered, rejecting\n"); - CString appName, msg; - appName.LoadString(IDS_MB_APP_NAME); - msg.LoadString(IDS_REG_BAD_ENTRY); - MessageBox(msg, appName, MB_ICONWARNING|MB_OK); - pDX->Fail(); - } - } else { - OnUserChange(); - OnCompanyChange(); - OnRegChange(); - } + if (gMyApp.fRegistry.IsValidRegistrationKey(fUserName, fCompanyName, + fRegKey)) + { + WMSG3("Correct key entered: '%s' '%s' '%s'\n", + (LPCTSTR)fUserName, (LPCTSTR)fCompanyName, (LPCTSTR)fRegKey); + } else { + WMSG0("Incorrect key entered, rejecting\n"); + CString appName, msg; + appName.LoadString(IDS_MB_APP_NAME); + msg.LoadString(IDS_REG_BAD_ENTRY); + MessageBox(msg, appName, MB_ICONWARNING|MB_OK); + pDX->Fail(); + } + } else { + OnUserChange(); + OnCompanyChange(); + OnRegChange(); + } } /* @@ -94,37 +94,37 @@ EnterRegDialog::DoDataExchange(CDataExchange* pDX) void EnterRegDialog::HandleEditChange(int editID, int crcID) { - CString userStr, regStr; - CEdit* pEdit; - CWnd* pWnd; + CString userStr, regStr; + CEdit* pEdit; + CWnd* pWnd; - /* - * Update the CRC for the modified control. - */ - pEdit = (CEdit*) GetDlgItem(editID); - ASSERT(pEdit != nil); - pEdit->GetWindowText(userStr); - unsigned short crc; - crc = gMyApp.fRegistry.ComputeStringCRC(userStr); - userStr.Format("%04X", crc); - pWnd = GetDlgItem(crcID); - ASSERT(pWnd != nil); - pWnd->SetWindowText(userStr); + /* + * Update the CRC for the modified control. + */ + pEdit = (CEdit*) GetDlgItem(editID); + ASSERT(pEdit != nil); + pEdit->GetWindowText(userStr); + unsigned short crc; + crc = gMyApp.fRegistry.ComputeStringCRC(userStr); + userStr.Format("%04X", crc); + pWnd = GetDlgItem(crcID); + ASSERT(pWnd != nil); + pWnd->SetWindowText(userStr); - /* - * Update the OK button. - */ - pEdit = (CEdit*) GetDlgItem(IDC_REGENTER_USER); - ASSERT(pEdit != nil); - pEdit->GetWindowText(userStr); + /* + * Update the OK button. + */ + pEdit = (CEdit*) GetDlgItem(IDC_REGENTER_USER); + ASSERT(pEdit != nil); + pEdit->GetWindowText(userStr); - pEdit = (CEdit*) GetDlgItem(IDC_REGENTER_REG); - ASSERT(pEdit != nil); - pEdit->GetWindowText(regStr); + pEdit = (CEdit*) GetDlgItem(IDC_REGENTER_REG); + ASSERT(pEdit != nil); + pEdit->GetWindowText(regStr); - pWnd = GetDlgItem(IDOK); - ASSERT(pWnd != nil); - pWnd->EnableWindow(!userStr.IsEmpty() && !regStr.IsEmpty()); + pWnd = GetDlgItem(IDOK); + ASSERT(pWnd != nil); + pWnd->EnableWindow(!userStr.IsEmpty() && !regStr.IsEmpty()); } /* @@ -133,17 +133,17 @@ EnterRegDialog::HandleEditChange(int editID, int crcID) void EnterRegDialog::OnUserChange(void) { - HandleEditChange(IDC_REGENTER_USER, IDC_REGENTER_USERCRC); + HandleEditChange(IDC_REGENTER_USER, IDC_REGENTER_USERCRC); } void EnterRegDialog::OnCompanyChange(void) { - HandleEditChange(IDC_REGENTER_COMPANY, IDC_REGENTER_COMPCRC); + HandleEditChange(IDC_REGENTER_COMPANY, IDC_REGENTER_COMPCRC); } void EnterRegDialog::OnRegChange(void) { - HandleEditChange(IDC_REGENTER_REG, IDC_REGENTER_REGCRC); + HandleEditChange(IDC_REGENTER_REG, IDC_REGENTER_REGCRC); } @@ -153,7 +153,7 @@ EnterRegDialog::OnRegChange(void) void EnterRegDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_ENTER_REG_DATA, HELP_CONTEXT); + WinHelp(HELP_TOPIC_ENTER_REG_DATA, HELP_CONTEXT); } @@ -167,45 +167,45 @@ EnterRegDialog::OnHelp(void) /*static*/ int EnterRegDialog::GetRegInfo(CWnd* pWnd) { - CString user, company, reg, versions, expire; + CString user, company, reg, versions, expire; - /* - * Get current data (if any). This call only fails if the registry itself - * appears to be generally inaccessible. - */ - if (gMyApp.fRegistry.GetRegistration(&user, &company, ®, &versions, - &expire) != 0) - { - CString msg; - msg.LoadString(IDS_REG_FAILURE); - ShowFailureMsg(pWnd, msg, IDS_FAILED); - return -1; - } + /* + * Get current data (if any). This call only fails if the registry itself + * appears to be generally inaccessible. + */ + if (gMyApp.fRegistry.GetRegistration(&user, &company, ®, &versions, + &expire) != 0) + { + CString msg; + msg.LoadString(IDS_REG_FAILURE); + ShowFailureMsg(pWnd, msg, IDS_FAILED); + return -1; + } - /* - * Post the dialog. - */ - EnterRegDialog dlg(pWnd); - int result = -1; + /* + * Post the dialog. + */ + EnterRegDialog dlg(pWnd); + int result = -1; - if (dlg.DoModal() == IDOK) { - user = dlg.fUserName; - company = dlg.fCompanyName; - reg = dlg.fRegKey; + if (dlg.DoModal() == IDOK) { + user = dlg.fUserName; + company = dlg.fCompanyName; + reg = dlg.fRegKey; - /* data was validated by EnterRegDialog, so just save it to registry */ - if (gMyApp.fRegistry.SetRegistration(user, company, reg, versions, - expire) != 0) - { - CString msg; - msg.LoadString(IDS_REG_FAILURE); - ShowFailureMsg(pWnd, msg, IDS_FAILED); - } else { - result = 0; - } - } + /* data was validated by EnterRegDialog, so just save it to registry */ + if (gMyApp.fRegistry.SetRegistration(user, company, reg, versions, + expire) != 0) + { + CString msg; + msg.LoadString(IDS_REG_FAILURE); + ShowFailureMsg(pWnd, msg, IDS_FAILED); + } else { + result = 0; + } + } - return result; + return result; } #endif /*0*/ \ No newline at end of file diff --git a/app/EnterRegDialog.h b/app/EnterRegDialog.h index b17f3d4..5153cf3 100644 --- a/app/EnterRegDialog.h +++ b/app/EnterRegDialog.h @@ -19,32 +19,32 @@ */ class EnterRegDialog : public CDialog { public: - EnterRegDialog(CWnd* pParent = nil) : CDialog(IDD_REGISTRATION, pParent) - { fDepth = 0; } - virtual ~EnterRegDialog(void) {} + EnterRegDialog(CWnd* pParent = nil) : CDialog(IDD_REGISTRATION, pParent) + { fDepth = 0; } + virtual ~EnterRegDialog(void) {} - CString fUserName; - CString fCompanyName; - CString fRegKey; + CString fUserName; + CString fCompanyName; + CString fRegKey; - static int GetRegInfo(CWnd* pWnd); + static int GetRegInfo(CWnd* pWnd); private: - // overrides - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + // overrides + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - afx_msg void OnUserChange(void); - afx_msg void OnCompanyChange(void); - afx_msg void OnRegChange(void); - afx_msg void OnHelp(void); + afx_msg void OnUserChange(void); + afx_msg void OnCompanyChange(void); + afx_msg void OnRegChange(void); + afx_msg void OnHelp(void); - void HandleEditChange(int editID, int crcID); + void HandleEditChange(int editID, int crcID); - MyEdit fMyEdit; - int fDepth; + MyEdit fMyEdit; + int fDepth; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__ENTERREGDIALOG__*/ \ No newline at end of file diff --git a/app/ExtractOptionsDialog.cpp b/app/ExtractOptionsDialog.cpp index f4b80be..2a63baf 100644 --- a/app/ExtractOptionsDialog.cpp +++ b/app/ExtractOptionsDialog.cpp @@ -12,15 +12,15 @@ #include "ChooseDirDialog.h" BEGIN_MESSAGE_MAP(ExtractOptionsDialog, CDialog) - ON_BN_CLICKED(IDC_EXT_CHOOSE_FOLDER, OnChooseFolder) - ON_BN_CLICKED(IDC_EXT_CONVEOLNONE, OnChangeTextConv) - ON_BN_CLICKED(IDC_EXT_CONVEOLTYPE, OnChangeTextConv) - ON_BN_CLICKED(IDC_EXT_CONVEOLTEXT, OnChangeTextConv) - ON_BN_CLICKED(IDC_EXT_CONVEOLALL, OnChangeTextConv) - ON_BN_CLICKED(IDC_EXT_CONFIG_PRESERVE, OnConfigPreserve) - ON_BN_CLICKED(IDC_EXT_CONFIG_CONVERT, OnConfigConvert) - ON_WM_HELPINFO() - ON_COMMAND(IDHELP, OnHelp) + ON_BN_CLICKED(IDC_EXT_CHOOSE_FOLDER, OnChooseFolder) + ON_BN_CLICKED(IDC_EXT_CONVEOLNONE, OnChangeTextConv) + ON_BN_CLICKED(IDC_EXT_CONVEOLTYPE, OnChangeTextConv) + ON_BN_CLICKED(IDC_EXT_CONVEOLTEXT, OnChangeTextConv) + ON_BN_CLICKED(IDC_EXT_CONVEOLALL, OnChangeTextConv) + ON_BN_CLICKED(IDC_EXT_CONFIG_PRESERVE, OnConfigPreserve) + ON_BN_CLICKED(IDC_EXT_CONFIG_CONVERT, OnConfigConvert) + ON_WM_HELPINFO() + ON_COMMAND(IDHELP, OnHelp) END_MESSAGE_MAP() @@ -33,39 +33,39 @@ END_MESSAGE_MAP() BOOL ExtractOptionsDialog::OnInitDialog(void) { - CString countFmt; - CString selStr; - CWnd* pWnd; + CString countFmt; + CString selStr; + CWnd* pWnd; - /* grab the radio button with the selection count */ - pWnd = GetDlgItem(IDC_EXT_SELECTED); - ASSERT(pWnd != nil); + /* grab the radio button with the selection count */ + pWnd = GetDlgItem(IDC_EXT_SELECTED); + ASSERT(pWnd != nil); - /* set the count string using a string table entry */ - if (fSelectedCount == 1) { - countFmt.LoadString(IDS_EXT_SELECTED_COUNT); - pWnd->SetWindowText(countFmt); - } else { - countFmt.LoadString(IDS_EXT_SELECTED_COUNTS_FMT); - selStr.Format((LPCTSTR) countFmt, fSelectedCount); - pWnd->SetWindowText(selStr); + /* set the count string using a string table entry */ + if (fSelectedCount == 1) { + countFmt.LoadString(IDS_EXT_SELECTED_COUNT); + pWnd->SetWindowText(countFmt); + } else { + countFmt.LoadString(IDS_EXT_SELECTED_COUNTS_FMT); + selStr.Format((LPCTSTR) countFmt, fSelectedCount); + pWnd->SetWindowText(selStr); - if (fSelectedCount == 0) - pWnd->EnableWindow(FALSE); - } + if (fSelectedCount == 0) + pWnd->EnableWindow(FALSE); + } - /* if "no convert" is selected, disable high ASCII button */ - if (fConvEOL == kConvEOLNone) { - pWnd = GetDlgItem(IDC_EXT_CONVHIGHASCII); - pWnd->EnableWindow(false); - } + /* if "no convert" is selected, disable high ASCII button */ + if (fConvEOL == kConvEOLNone) { + pWnd = GetDlgItem(IDC_EXT_CONVHIGHASCII); + pWnd->EnableWindow(false); + } - /* replace the existing button with one of our bitmap buttons */ - fChooseFolderButton.ReplaceDlgCtrl(this, IDC_EXT_CHOOSE_FOLDER); - fChooseFolderButton.SetBitmapID(IDB_CHOOSE_FOLDER); + /* replace the existing button with one of our bitmap buttons */ + fChooseFolderButton.ReplaceDlgCtrl(this, IDC_EXT_CHOOSE_FOLDER); + fChooseFolderButton.SetBitmapID(IDB_CHOOSE_FOLDER); - return CDialog::OnInitDialog(); - //return TRUE; // let Windows set the focus + return CDialog::OnInitDialog(); + //return TRUE; // let Windows set the focus } /* @@ -77,25 +77,25 @@ ExtractOptionsDialog::OnInitDialog(void) void ExtractOptionsDialog::DoDataExchange(CDataExchange* pDX) { - DDX_Text(pDX, IDC_EXT_PATH, fExtractPath); + DDX_Text(pDX, IDC_EXT_PATH, fExtractPath); - DDX_Radio(pDX, IDC_EXT_SELECTED, fFilesToExtract); + DDX_Radio(pDX, IDC_EXT_SELECTED, fFilesToExtract); - DDX_Check(pDX, IDC_EXT_DATAFORK, fIncludeDataForks); - DDX_Check(pDX, IDC_EXT_RSRCFORK, fIncludeRsrcForks); - DDX_Check(pDX, IDC_EXT_DISKIMAGE, fIncludeDiskImages); + DDX_Check(pDX, IDC_EXT_DATAFORK, fIncludeDataForks); + DDX_Check(pDX, IDC_EXT_RSRCFORK, fIncludeRsrcForks); + DDX_Check(pDX, IDC_EXT_DISKIMAGE, fIncludeDiskImages); - DDX_Check(pDX, IDC_EXT_REFORMAT, fEnableReformat); - DDX_Check(pDX, IDC_EXT_DISK_2MG, fDiskTo2MG); + DDX_Check(pDX, IDC_EXT_REFORMAT, fEnableReformat); + DDX_Check(pDX, IDC_EXT_DISK_2MG, fDiskTo2MG); - DDX_Check(pDX, IDC_EXT_ADD_PRESERVE, fAddTypePreservation); - DDX_Check(pDX, IDC_EXT_ADD_EXTEN, fAddExtension); - DDX_Check(pDX, IDC_EXT_STRIP_FOLDER, fStripFolderNames); + DDX_Check(pDX, IDC_EXT_ADD_PRESERVE, fAddTypePreservation); + DDX_Check(pDX, IDC_EXT_ADD_EXTEN, fAddExtension); + DDX_Check(pDX, IDC_EXT_STRIP_FOLDER, fStripFolderNames); - DDX_Radio(pDX, IDC_EXT_CONVEOLNONE, fConvEOL); - DDX_Check(pDX, IDC_EXT_CONVHIGHASCII, fConvHighASCII); + DDX_Radio(pDX, IDC_EXT_CONVEOLNONE, fConvEOL); + DDX_Check(pDX, IDC_EXT_CONVHIGHASCII, fConvHighASCII); - DDX_Check(pDX, IDC_EXT_OVERWRITE_EXIST, fOverwriteExisting); + DDX_Check(pDX, IDC_EXT_OVERWRITE_EXIST, fOverwriteExisting); } /* @@ -104,23 +104,23 @@ ExtractOptionsDialog::DoDataExchange(CDataExchange* pDX) void ExtractOptionsDialog::OnConfigPreserve(void) { - // IDC_EXT_PATH, IDC_EXT_SELECTED - SetDlgButtonCheck(this, IDC_EXT_DATAFORK, BST_CHECKED); - SetDlgButtonCheck(this, IDC_EXT_RSRCFORK, BST_CHECKED); - SetDlgButtonCheck(this, IDC_EXT_DISKIMAGE, BST_CHECKED); - SetDlgButtonCheck(this, IDC_EXT_REFORMAT, BST_UNCHECKED); - SetDlgButtonCheck(this, IDC_EXT_DISK_2MG, BST_UNCHECKED); - SetDlgButtonCheck(this, IDC_EXT_ADD_PRESERVE, BST_CHECKED); - SetDlgButtonCheck(this, IDC_EXT_ADD_EXTEN, BST_UNCHECKED); - //SetDlgButtonCheck(this, IDC_EXT_STRIP_FOLDER, BST_CHECKED); - SetDlgButtonCheck(this, IDC_EXT_CONVEOLNONE, BST_CHECKED); - SetDlgButtonCheck(this, IDC_EXT_CONVEOLTYPE, BST_UNCHECKED); - SetDlgButtonCheck(this, IDC_EXT_CONVEOLTEXT, BST_UNCHECKED); - SetDlgButtonCheck(this, IDC_EXT_CONVEOLALL, BST_UNCHECKED); - SetDlgButtonCheck(this, IDC_EXT_CONVHIGHASCII, BST_UNCHECKED); - //SetDlgButtonCheck(this, IDC_EXT_OVERWRITE_EXIST, BST_CHECKED); + // IDC_EXT_PATH, IDC_EXT_SELECTED + SetDlgButtonCheck(this, IDC_EXT_DATAFORK, BST_CHECKED); + SetDlgButtonCheck(this, IDC_EXT_RSRCFORK, BST_CHECKED); + SetDlgButtonCheck(this, IDC_EXT_DISKIMAGE, BST_CHECKED); + SetDlgButtonCheck(this, IDC_EXT_REFORMAT, BST_UNCHECKED); + SetDlgButtonCheck(this, IDC_EXT_DISK_2MG, BST_UNCHECKED); + SetDlgButtonCheck(this, IDC_EXT_ADD_PRESERVE, BST_CHECKED); + SetDlgButtonCheck(this, IDC_EXT_ADD_EXTEN, BST_UNCHECKED); + //SetDlgButtonCheck(this, IDC_EXT_STRIP_FOLDER, BST_CHECKED); + SetDlgButtonCheck(this, IDC_EXT_CONVEOLNONE, BST_CHECKED); + SetDlgButtonCheck(this, IDC_EXT_CONVEOLTYPE, BST_UNCHECKED); + SetDlgButtonCheck(this, IDC_EXT_CONVEOLTEXT, BST_UNCHECKED); + SetDlgButtonCheck(this, IDC_EXT_CONVEOLALL, BST_UNCHECKED); + SetDlgButtonCheck(this, IDC_EXT_CONVHIGHASCII, BST_UNCHECKED); + //SetDlgButtonCheck(this, IDC_EXT_OVERWRITE_EXIST, BST_CHECKED); - OnChangeTextConv(); + OnChangeTextConv(); } /* @@ -129,23 +129,23 @@ ExtractOptionsDialog::OnConfigPreserve(void) void ExtractOptionsDialog::OnConfigConvert(void) { - // IDC_EXT_PATH, IDC_EXT_SELECTED - SetDlgButtonCheck(this, IDC_EXT_DATAFORK, BST_CHECKED); - SetDlgButtonCheck(this, IDC_EXT_RSRCFORK, BST_UNCHECKED); - SetDlgButtonCheck(this, IDC_EXT_DISKIMAGE, BST_CHECKED); - SetDlgButtonCheck(this, IDC_EXT_REFORMAT, BST_CHECKED); - SetDlgButtonCheck(this, IDC_EXT_DISK_2MG, BST_CHECKED); - SetDlgButtonCheck(this, IDC_EXT_ADD_PRESERVE, BST_UNCHECKED); - SetDlgButtonCheck(this, IDC_EXT_ADD_EXTEN, BST_CHECKED); - //SetDlgButtonCheck(this, IDC_EXT_STRIP_FOLDER, BST_CHECKED); - SetDlgButtonCheck(this, IDC_EXT_CONVEOLNONE, BST_UNCHECKED); - SetDlgButtonCheck(this, IDC_EXT_CONVEOLTYPE, BST_UNCHECKED); - SetDlgButtonCheck(this, IDC_EXT_CONVEOLTEXT, BST_CHECKED); - SetDlgButtonCheck(this, IDC_EXT_CONVEOLALL, BST_UNCHECKED); - SetDlgButtonCheck(this, IDC_EXT_CONVHIGHASCII, BST_CHECKED); - //SetDlgButtonCheck(this, IDC_EXT_OVERWRITE_EXIST, BST_CHECKED); + // IDC_EXT_PATH, IDC_EXT_SELECTED + SetDlgButtonCheck(this, IDC_EXT_DATAFORK, BST_CHECKED); + SetDlgButtonCheck(this, IDC_EXT_RSRCFORK, BST_UNCHECKED); + SetDlgButtonCheck(this, IDC_EXT_DISKIMAGE, BST_CHECKED); + SetDlgButtonCheck(this, IDC_EXT_REFORMAT, BST_CHECKED); + SetDlgButtonCheck(this, IDC_EXT_DISK_2MG, BST_CHECKED); + SetDlgButtonCheck(this, IDC_EXT_ADD_PRESERVE, BST_UNCHECKED); + SetDlgButtonCheck(this, IDC_EXT_ADD_EXTEN, BST_CHECKED); + //SetDlgButtonCheck(this, IDC_EXT_STRIP_FOLDER, BST_CHECKED); + SetDlgButtonCheck(this, IDC_EXT_CONVEOLNONE, BST_UNCHECKED); + SetDlgButtonCheck(this, IDC_EXT_CONVEOLTYPE, BST_UNCHECKED); + SetDlgButtonCheck(this, IDC_EXT_CONVEOLTEXT, BST_CHECKED); + SetDlgButtonCheck(this, IDC_EXT_CONVEOLALL, BST_UNCHECKED); + SetDlgButtonCheck(this, IDC_EXT_CONVHIGHASCII, BST_CHECKED); + //SetDlgButtonCheck(this, IDC_EXT_OVERWRITE_EXIST, BST_CHECKED); - OnChangeTextConv(); + OnChangeTextConv(); } /* @@ -155,13 +155,13 @@ ExtractOptionsDialog::OnConfigConvert(void) void ExtractOptionsDialog::OnChangeTextConv(void) { - CButton* pButton = (CButton*) GetDlgItem(IDC_EXT_CONVEOLNONE); - ASSERT(pButton != nil); - bool convDisabled = (pButton->GetCheck() == BST_CHECKED); + CButton* pButton = (CButton*) GetDlgItem(IDC_EXT_CONVEOLNONE); + ASSERT(pButton != nil); + bool convDisabled = (pButton->GetCheck() == BST_CHECKED); - CWnd* pWnd = GetDlgItem(IDC_EXT_CONVHIGHASCII); - ASSERT(pWnd != nil); - pWnd->EnableWindow(!convDisabled); + CWnd* pWnd = GetDlgItem(IDC_EXT_CONVHIGHASCII); + ASSERT(pWnd != nil); + pWnd->EnableWindow(!convDisabled); } /* @@ -170,22 +170,22 @@ ExtractOptionsDialog::OnChangeTextConv(void) void ExtractOptionsDialog::OnChooseFolder(void) { - ChooseDirDialog chooseDir(this); - CWnd* pEditWnd; - CString editPath; + ChooseDirDialog chooseDir(this); + CWnd* pEditWnd; + CString editPath; - /* get the currently-showing text from the edit field */ - pEditWnd = GetDlgItem(IDC_EXT_PATH); - ASSERT(pEditWnd != nil); - pEditWnd->GetWindowText(editPath); + /* get the currently-showing text from the edit field */ + pEditWnd = GetDlgItem(IDC_EXT_PATH); + ASSERT(pEditWnd != nil); + pEditWnd->GetWindowText(editPath); - chooseDir.SetPathName(editPath); - if (chooseDir.DoModal() == IDOK) { - const char* ccp = chooseDir.GetPathName(); - WMSG1("New extract path chosen = '%s'\n", ccp); + chooseDir.SetPathName(editPath); + if (chooseDir.DoModal() == IDOK) { + const char* ccp = chooseDir.GetPathName(); + WMSG1("New extract path chosen = '%s'\n", ccp); - pEditWnd->SetWindowText(ccp); - } + pEditWnd->SetWindowText(ccp); + } } /* @@ -194,8 +194,8 @@ ExtractOptionsDialog::OnChooseFolder(void) BOOL ExtractOptionsDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* @@ -204,5 +204,5 @@ ExtractOptionsDialog::OnHelpInfo(HELPINFO* lpHelpInfo) void ExtractOptionsDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_EXT_OPTIONS, HELP_CONTEXT); + WinHelp(HELP_TOPIC_EXT_OPTIONS, HELP_CONTEXT); } diff --git a/app/ExtractOptionsDialog.h b/app/ExtractOptionsDialog.h index 80fbcfc..87dd3f8 100644 --- a/app/ExtractOptionsDialog.h +++ b/app/ExtractOptionsDialog.h @@ -17,71 +17,71 @@ */ class ExtractOptionsDialog : public CDialog { public: - ExtractOptionsDialog(int selCount, CWnd* pParentWnd = NULL) : - CDialog(IDD_EXTRACT_FILES, pParentWnd), fSelectedCount(selCount) - { - // init values; these should be overridden before DoModal - fExtractPath = ""; - fFilesToExtract = 0; - fConvEOL = 0; - fConvHighASCII = FALSE; - fIncludeDataForks = fIncludeRsrcForks = fIncludeDiskImages = FALSE; - fEnableReformat = fDiskTo2MG = FALSE; - fAddTypePreservation = fAddExtension = fStripFolderNames = FALSE; - fOverwriteExisting = FALSE; - } - virtual ~ExtractOptionsDialog(void) { - //WMSG0("~ExtractOptionsDialog()\n"); - } + ExtractOptionsDialog(int selCount, CWnd* pParentWnd = NULL) : + CDialog(IDD_EXTRACT_FILES, pParentWnd), fSelectedCount(selCount) + { + // init values; these should be overridden before DoModal + fExtractPath = ""; + fFilesToExtract = 0; + fConvEOL = 0; + fConvHighASCII = FALSE; + fIncludeDataForks = fIncludeRsrcForks = fIncludeDiskImages = FALSE; + fEnableReformat = fDiskTo2MG = FALSE; + fAddTypePreservation = fAddExtension = fStripFolderNames = FALSE; + fOverwriteExisting = FALSE; + } + virtual ~ExtractOptionsDialog(void) { + //WMSG0("~ExtractOptionsDialog()\n"); + } - CString fExtractPath; + CString fExtractPath; - enum { kExtractSelection = 0, kExtractAll = 1 }; - int fFilesToExtract; + enum { kExtractSelection = 0, kExtractAll = 1 }; + int fFilesToExtract; -// enum { kPreserveNone = 0, kPreserveTypes, kPreserveAndExtend }; -// int fTypePreservation; +// enum { kPreserveNone = 0, kPreserveTypes, kPreserveAndExtend }; +// int fTypePreservation; - // this must match tab order of radio buttons in dialog - enum { kConvEOLNone = 0, kConvEOLType, kConvEOLAuto, kConvEOLAll }; - int fConvEOL; - BOOL fConvHighASCII; + // this must match tab order of radio buttons in dialog + enum { kConvEOLNone = 0, kConvEOLType, kConvEOLAuto, kConvEOLAll }; + int fConvEOL; + BOOL fConvHighASCII; -// enum { kDiskImageNoExtract = 0, kDiskImageAsPO = 1, kDiskImageAs2MG }; -// int fDiskImageExtract; +// enum { kDiskImageNoExtract = 0, kDiskImageAsPO = 1, kDiskImageAs2MG }; +// int fDiskImageExtract; - BOOL fIncludeDataForks; - BOOL fIncludeRsrcForks; - BOOL fIncludeDiskImages; + BOOL fIncludeDataForks; + BOOL fIncludeRsrcForks; + BOOL fIncludeDiskImages; - BOOL fEnableReformat; - BOOL fDiskTo2MG; + BOOL fEnableReformat; + BOOL fDiskTo2MG; - BOOL fAddTypePreservation; - BOOL fAddExtension; - BOOL fStripFolderNames; + BOOL fAddTypePreservation; + BOOL fAddExtension; + BOOL fStripFolderNames; - BOOL fOverwriteExisting; + BOOL fOverwriteExisting; - bool ShouldTryReformat(void) const { - return fEnableReformat != 0; - } + bool ShouldTryReformat(void) const { + return fEnableReformat != 0; + } private: - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - afx_msg void OnConfigPreserve(void); - afx_msg void OnConfigConvert(void); - afx_msg void OnChangeTextConv(void); - afx_msg void OnChooseFolder(void); - afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - afx_msg void OnHelp(void); + afx_msg void OnConfigPreserve(void); + afx_msg void OnConfigConvert(void); + afx_msg void OnChangeTextConv(void); + afx_msg void OnChooseFolder(void); + afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg void OnHelp(void); - MyBitmapButton fChooseFolderButton; - int fSelectedCount; + MyBitmapButton fChooseFolderButton; + int fSelectedCount; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__EXTRACT_OPTIONS_DIALOG__*/ \ No newline at end of file diff --git a/app/FileNameConv.cpp b/app/FileNameConv.cpp index 2dcc451..c2196df 100644 --- a/app/FileNameConv.cpp +++ b/app/FileNameConv.cpp @@ -1,1422 +1,1422 @@ -/* - * CiderPress - * Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved. - * See the file LICENSE for distribution terms. - */ -/* - * Filename manipulation, including file type preservation. This is - * substantially ripped from NuLib2, which would be a GPL violation if - * it weren't my code to begin with. - */ -#include "stdafx.h" -#include "FileNameConv.h" -#include "GenericArchive.h" -#include "AddFilesDialog.h" -#include - - -#define WINDOWS_LIKE -/* replace unsupported chars with '%xx' */ -#define kForeignIndic '%' - -/* convert single hex digit char to number */ -#define HexDigit(x) ( !isxdigit((int)(x)) ? -1 : \ - (x) <= '9' ? (x) - '0' : toupper(x) +10 - 'A' ) - -/* convert number from 0-15 to hex digit */ -#define HexConv(x) ( ((unsigned int)(x)) <= 15 ? \ - ( (x) <= 9 ? (x) + '0' : (x) -10 + 'A') : -1 ) - - -/* - * =========================================================================== - * Common definitions - * =========================================================================== - */ - -#define kPreserveIndic '#' /* use # rather than $ for hex indication */ -#define kFilenameExtDelim '.' /* separates extension from filename */ -#define kResourceFlag 'r' -#define kDiskImageFlag 'i' -#define kMaxExtLen 5 /* ".1234" */ -#define kResourceStr _T("_rsrc_") - -/* must be longer then strlen(kResourceStr)... no problem there */ -#define kMaxPathGrowth (sizeof("#XXXXXXXXYYYYYYYYZ")-1 + kMaxExtLen+1) - - -/* ProDOS file type names; must be entirely in upper case */ -static const char gFileTypeNames[256][4] = { - "NON", "BAD", "PCD", "PTX", "TXT", "PDA", "BIN", "FNT", - "FOT", "BA3", "DA3", "WPF", "SOS", "$0D", "$0E", "DIR", - "RPD", "RPI", "AFD", "AFM", "AFR", "SCL", "PFS", "$17", - "$18", "ADB", "AWP", "ASP", "$1C", "$1D", "$1E", "$1F", - "TDM", "$21", "$22", "$23", "$24", "$25", "$26", "$27", - "$28", "$29", "8SC", "8OB", "8IC", "8LD", "P8C", "$2F", - "$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37", - "$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F", - "DIC", "OCR", "FTD", "$43", "$44", "$45", "$46", "$47", - "$48", "$49", "$4A", "$4B", "$4C", "$4D", "$4E", "$4F", - "GWP", "GSS", "GDB", "DRW", "GDP", "HMD", "EDU", "STN", - "HLP", "COM", "CFG", "ANM", "MUM", "ENT", "DVU", "FIN", - "$60", "$61", "$62", "$63", "$64", "$65", "$66", "$67", - "$68", "$69", "$6A", "BIO", "$6C", "TDR", "PRE", "HDV", - "$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77", - "$78", "$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F", - "$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87", - "$88", "$89", "$8A", "$8B", "$8C", "$8D", "$8E", "$8F", - "$90", "$91", "$92", "$93", "$94", "$95", "$96", "$97", - "$98", "$99", "$9A", "$9B", "$9C", "$9D", "$9E", "$9F", - "WP ", "$A1", "$A2", "$A3", "$A4", "$A5", "$A6", "$A7", - "$A8", "$A9", "$AA", "GSB", "TDF", "BDF", "$AE", "$AF", - "SRC", "OBJ", "LIB", "S16", "RTL", "EXE", "PIF", "TIF", - "NDA", "CDA", "TOL", "DVR", "LDF", "FST", "$BE", "DOC", - "PNT", "PIC", "ANI", "PAL", "$C4", "OOG", "SCR", "CDV", - "FON", "FND", "ICN", "$CB", "$CC", "$CD", "$CE", "$CF", - "$D0", "$D1", "$D2", "$D3", "$D4", "MUS", "INS", "MDI", - "SND", "$D9", "$DA", "DBM", "$DC", "DDD", "$DE", "$DF", - "LBR", "$E1", "ATK", "$E3", "$E4", "$E5", "$E6", "$E7", - "$E8", "$E9", "$EA", "$EB", "$EC", "$ED", "R16", "PAS", - "CMD", "$F1", "$F2", "$F3", "$F4", "$F5", "$F6", "$F7", - "$F8", "OS ", "INT", "IVR", "BAS", "VAR", "REL", "SYS" -}; - -/* - * Some file extensions we recognize. When adding files with "extended" - * preservation mode, we try to assign types to files that weren't - * explicitly preserved, but nevertheless have a recognizeable type. - * - * geoff at gwlink.net pointed out that this really ought to be in an external - * file rather than a hard-coded table. Ought to fix that someday. - */ -static const struct { - const char* label; - unsigned short fileType; - unsigned long auxType; - unsigned char flags; -} gRecognizedExtensions[] = { - { "ASM", 0xb0, 0x0003, 0 }, /* APW assembly source */ - { "C", 0xb0, 0x000a, 0 }, /* APW C source */ - { "H", 0xb0, 0x000a, 0 }, /* APW C header */ - { "CPP", 0xb0, 0x0000, 0 }, /* generic source file */ - { "BNY", 0xe0, 0x8000, 0 }, /* Binary II lib */ - { "BQY", 0xe0, 0x8000, 0 }, /* Binary II lib, w/ compress */ - { "BXY", 0xe0, 0x8000, 0 }, /* Binary II wrap around SHK */ - { "BSE", 0xe0, 0x8000, 0 }, /* Binary II wrap around SEA */ - { "SEA", 0xb3, 0xdb07, 0 }, /* GSHK SEA */ - { "TEXT", 0x04, 0x0000, 0 }, /* ASCII Text */ - { "GIF", 0xc0, 0x8006, 0 }, /* GIF image */ - { "JPG", 0x06, 0x0000, 0 }, /* JPEG (nicer than 'NON') */ - { "JPEG", 0x06, 0x0000, 0 }, /* JPEG (nicer than 'NON') */ - //{ "ACU", 0xe0, 0x8001, 0 }, /* ACU archive */ - { "SHK", 0xe0, 0x8002, 0 }, /* ShrinkIt archive */ -}; - - -/* - * Return a pointer to the three-letter representation of the file type name. - * - * Note to self: code down below tests first char for '?'. - */ -/*static*/ const char* -PathProposal::FileTypeString(unsigned long fileType) -{ - if (fileType < NELEM(gFileTypeNames)) - return gFileTypeNames[fileType]; - else - return kUnknownTypeStr; -} - -/* - * Description table. - * - * The first item that matches will be used, but the table is searched - * bottom-up, so it's important to have the most general entry first. - * - * In retrospect, it might have made sense to use the same format as the - * "FTD" file type description file that the IIgs Finder used. Might have - * made sense to just ship that and load it on startup (although copyright - * issues would have to be investigated). - */ -static const struct { - unsigned short fileType; - unsigned short minAuxType; // start of range for which this applies - unsigned short maxAuxType; // end of range - const char* descr; -} gTypeDescriptions[] = { - /*NON*/ { 0x00, 0x0000, 0xffff, "Untyped file" }, - /*BAD*/ { 0x01, 0x0000, 0xffff, "Bad blocks" }, - /*PCD*/ { 0x02, 0x0000, 0xffff, "Pascal code" }, - /*PTX*/ { 0x03, 0x0000, 0xffff, "Pascal text" }, - /*TXT*/ { 0x04, 0x0000, 0xffff, "ASCII text" }, - /*PDA*/ { 0x05, 0x0000, 0xffff, "Pascal data" }, - /*BIN*/ { 0x06, 0x0000, 0xffff, "Binary" }, - /*FNT*/ { 0x07, 0x0000, 0xffff, "Apple /// font" }, - /*FOT*/ { 0x08, 0x0000, 0xffff, "Apple II or /// graphics" }, - /* */ { 0x08, 0x0000, 0x3fff, "Apple II graphics" }, - /* */ { 0x08, 0x4000, 0x4000, "Packed hi-res image" }, - /* */ { 0x08, 0x4001, 0x4001, "Packed double hi-res image" }, - /* */ { 0x08, 0x8001, 0x8001, "Printographer packed HGR file" }, - /* */ { 0x08, 0x8002, 0x8002, "Printographer packed DHGR file" }, - /* */ { 0x08, 0x8003, 0x8003, "Softdisk hi-res image" }, - /* */ { 0x08, 0x8004, 0x8004, "Softdisk double hi-res image" }, - /*BA3*/ { 0x09, 0x0000, 0xffff, "Apple /// BASIC program" }, - /*DA3*/ { 0x0a, 0x0000, 0xffff, "Apple /// BASIC data" }, - /*WPF*/ { 0x0b, 0x0000, 0xffff, "Apple II or /// word processor" }, - /* */ { 0x0b, 0x8001, 0x8001, "Write This Way document" }, - /* */ { 0x0b, 0x8002, 0x8002, "Writing & Publishing document" }, - /*SOS*/ { 0x0c, 0x0000, 0xffff, "Apple /// SOS system" }, - /*DIR*/ { 0x0f, 0x0000, 0xffff, "Folder" }, - /*RPD*/ { 0x10, 0x0000, 0xffff, "Apple /// RPS data" }, - /*RPI*/ { 0x11, 0x0000, 0xffff, "Apple /// RPS index" }, - /*AFD*/ { 0x12, 0x0000, 0xffff, "Apple /// AppleFile discard" }, - /*AFM*/ { 0x13, 0x0000, 0xffff, "Apple /// AppleFile model" }, - /*AFR*/ { 0x14, 0x0000, 0xffff, "Apple /// AppleFile report format" }, - /*SCL*/ { 0x15, 0x0000, 0xffff, "Apple /// screen library" }, - /*PFS*/ { 0x16, 0x0000, 0xffff, "PFS document" }, - /* */ { 0x16, 0x0001, 0x0001, "PFS:File document" }, - /* */ { 0x16, 0x0002, 0x0002, "PFS:Write document" }, - /* */ { 0x16, 0x0003, 0x0003, "PFS:Graph document" }, - /* */ { 0x16, 0x0004, 0x0004, "PFS:Plan document" }, - /* */ { 0x16, 0x0016, 0x0016, "PFS internal data" }, - /*ADB*/ { 0x19, 0x0000, 0xffff, "AppleWorks data base" }, - /*AWP*/ { 0x1a, 0x0000, 0xffff, "AppleWorks word processor" }, - /*ASP*/ { 0x1b, 0x0000, 0xffff, "AppleWorks spreadsheet" }, - /*TDM*/ { 0x20, 0x0000, 0xffff, "Desktop Manager document" }, - /*???*/ { 0x21, 0x0000, 0xffff, "Instant Pascal source" }, - /*???*/ { 0x22, 0x0000, 0xffff, "UCSD Pascal volume" }, - /*???*/ { 0x29, 0x0000, 0xffff, "Apple /// SOS dictionary" }, - /*8SC*/ { 0x2a, 0x0000, 0xffff, "Apple II source code" }, - /* */ { 0x2a, 0x8001, 0x8001, "EBBS command script" }, - /*8OB*/ { 0x2b, 0x0000, 0xffff, "Apple II object code" }, - /* */ { 0x2b, 0x8001, 0x8001, "GBBS Pro object Code" }, - /*8IC*/ { 0x2c, 0x0000, 0xffff, "Apple II interpreted code" }, - /* */ { 0x2c, 0x8003, 0x8003, "APEX Program File" }, - /* */ { 0x2c, 0x8005, 0x8005, "EBBS tokenized command script" }, - /*8LD*/ { 0x2d, 0x0000, 0xffff, "Apple II language data" }, - /* */ { 0x2d, 0x8006, 0x8005, "EBBS message bundle" }, - /* */ { 0x2d, 0x8007, 0x8007, "EBBS compressed message bundle" }, - /*P8C*/ { 0x2e, 0x0000, 0xffff, "ProDOS 8 code module" }, - /* */ { 0x2e, 0x8001, 0x8001, "Davex 8 Command" }, - /*PTP*/ { 0x2e, 0x8002, 0x8002, "Point-to-Point drivers" }, - /*PTP*/ { 0x2e, 0x8003, 0x8003, "Point-to-Point code" }, - /* */ { 0x2e, 0x8004, 0x8004, "Softdisk printer driver" }, - /*DIC*/ { 0x40, 0x0000, 0xffff, "Dictionary file" }, - /*???*/ { 0x41, 0x0000, 0xffff, "OCR data" }, - /* */ { 0x41, 0x8001, 0x8001, "InWords OCR font table" }, - /*FTD*/ { 0x42, 0x0000, 0xffff, "File type names" }, - /*???*/ { 0x43, 0x0000, 0xffff, "Peripheral data" }, - /* */ { 0x43, 0x8001, 0x8001, "Express document" }, - /*???*/ { 0x44, 0x0000, 0xffff, "Personal information" }, - /* */ { 0x44, 0x8001, 0x8001, "ResuMaker personal information" }, - /* */ { 0x44, 0x8002, 0x8002, "ResuMaker resume" }, - /* */ { 0x44, 0x8003, 0x8003, "II Notes document" }, - /* */ { 0x44, 0x8004, 0x8004, "Softdisk scrapbook document" }, - /* */ { 0x44, 0x8005, 0x8005, "Don't Forget document" }, - /* */ { 0x44, 0x80ff, 0x80ff, "What To Do data" }, - /* */ { 0x44, 0xbeef, 0xbeef, "Table Scraps scrapbook" }, - /*???*/ { 0x45, 0x0000, 0xffff, "Mathematical document" }, - /* */ { 0x45, 0x8001, 0x8001, "GSymbolix 3D graph document" }, - /* */ { 0x45, 0x8002, 0x8002, "GSymbolix formula document" }, - /*???*/ { 0x46, 0x0000, 0xffff, "AutoSave profiles" }, - /* */ { 0x46, 0x8001, 0x8001, "AutoSave profiles" }, - /*GWP*/ { 0x50, 0x0000, 0xffff, "Apple IIgs Word Processor" }, - /* */ { 0x50, 0x8001, 0x8001, "DeluxeWrite document" }, - /* */ { 0x50, 0x8003, 0x8003, "Personal Journal document" }, - /* */ { 0x50, 0x8010, 0x8010, "AppleWorks GS word processor" }, - /* */ { 0x50, 0x8011, 0x8011, "Softdisk issue text" }, - /* */ { 0x50, 0x5445, 0x5445, "Teach document" }, - /*GSS*/ { 0x51, 0x0000, 0xffff, "Apple IIgs spreadsheet" }, - /* */ { 0x51, 0x8010, 0x8010, "AppleWorks GS spreadsheet" }, - /* */ { 0x51, 0x2358, 0x2358, "QC Calc spreadsheet " }, - /*GDB*/ { 0x52, 0x0000, 0xffff, "Apple IIgs data base" }, - /* */ { 0x52, 0x8001, 0x8001, "GTv database" }, - /* */ { 0x52, 0x8010, 0x8010, "AppleWorks GS data base" }, - /* */ { 0x52, 0x8011, 0x8011, "AppleWorks GS DB template" }, - /* */ { 0x52, 0x8013, 0x8013, "GSAS database" }, - /* */ { 0x52, 0x8014, 0x8014, "GSAS accounting journals" }, - /* */ { 0x52, 0x8015, 0x8015, "Address Manager document" }, - /* */ { 0x52, 0x8016, 0x8016, "Address Manager defaults" }, - /* */ { 0x52, 0x8017, 0x8017, "Address Manager index" }, - /*DRW*/ { 0x53, 0x0000, 0xffff, "Drawing" }, - /* */ { 0x53, 0x8002, 0x8002, "Graphic Disk Labeler document" }, - /* */ { 0x53, 0x8010, 0x8010, "AppleWorks GS graphics" }, - /*GDP*/ { 0x54, 0x0000, 0xffff, "Desktop publishing" }, - /* */ { 0x54, 0x8002, 0x8002, "GraphicWriter document" }, - /* */ { 0x54, 0x8003, 0x8003, "Label It document" }, - /* */ { 0x54, 0x8010, 0x8010, "AppleWorks GS Page Layout" }, - /* */ { 0x54, 0xdd3e, 0xdd3e, "Medley document" }, - /*HMD*/ { 0x55, 0x0000, 0xffff, "Hypermedia" }, - /* */ { 0x55, 0x0001, 0x0001, "HyperCard IIgs stack" }, - /* */ { 0x55, 0x8001, 0x8001, "Tutor-Tech document" }, - /* */ { 0x55, 0x8002, 0x8002, "HyperStudio document" }, - /* */ { 0x55, 0x8003, 0x8003, "Nexus document" }, - /* */ { 0x55, 0x8004, 0x8004, "HyperSoft stack" }, - /* */ { 0x55, 0x8005, 0x8005, "HyperSoft card" }, - /* */ { 0x55, 0x8006, 0x8006, "HyperSoft external command" }, - /*EDU*/ { 0x56, 0x0000, 0xffff, "Educational Data" }, - /* */ { 0x56, 0x8001, 0x8001, "Tutor-Tech scores" }, - /* */ { 0x56, 0x8007, 0x8007, "GradeBook data" }, - /*STN*/ { 0x57, 0x0000, 0xffff, "Stationery" }, - /* */ { 0x57, 0x8003, 0x8003, "Music Writer format" }, - /*HLP*/ { 0x58, 0x0000, 0xffff, "Help file" }, - /* */ { 0x58, 0x8002, 0x8002, "Davex 8 help file" }, - /* */ { 0x58, 0x8005, 0x8005, "Micol Advanced Basic help file" }, - /* */ { 0x58, 0x8006, 0x8006, "Locator help document" }, - /* */ { 0x58, 0x8007, 0x8007, "Personal Journal help" }, - /* */ { 0x58, 0x8008, 0x8008, "Home Refinancer help" }, - /* */ { 0x58, 0x8009, 0x8009, "The Optimizer help" }, - /* */ { 0x58, 0x800a, 0x800a, "Text Wizard help" }, - /* */ { 0x58, 0x800b, 0x800b, "WordWorks Pro help system" }, - /* */ { 0x58, 0x800c, 0x800c, "Sound Wizard help" }, - /* */ { 0x58, 0x800d, 0x800d, "SeeHear help system" }, - /* */ { 0x58, 0x800e, 0x800e, "QuickForms help system" }, - /* */ { 0x58, 0x800f, 0x800f, "Don't Forget help system" }, - /*COM*/ { 0x59, 0x0000, 0xffff, "Communications file" }, - /* */ { 0x59, 0x8002, 0x8002, "AppleWorks GS communications" }, - /*CFG*/ { 0x5a, 0x0000, 0xffff, "Configuration file" }, - /* */ { 0x5a, 0x0000, 0x0000, "Sound settings files" }, - /* */ { 0x5a, 0x0002, 0x0002, "Battery RAM configuration" }, - /* */ { 0x5a, 0x0003, 0x0003, "AutoLaunch preferences" }, - /* */ { 0x5a, 0x0004, 0x0004, "SetStart preferences" }, - /* */ { 0x5a, 0x0005, 0x0005, "GSBug configuration" }, - /* */ { 0x5a, 0x0006, 0x0006, "Archiver preferences" }, - /* */ { 0x5a, 0x0007, 0x0007, "Archiver table of contents" }, - /* */ { 0x5a, 0x0008, 0x0008, "Font Manager data" }, - /* */ { 0x5a, 0x0009, 0x0009, "Print Manager data" }, - /* */ { 0x5a, 0x000a, 0x000a, "IR preferences" }, - /* */ { 0x5a, 0x8001, 0x8001, "Master Tracks Jr. preferences" }, - /* */ { 0x5a, 0x8002, 0x8002, "GraphicWriter preferences" }, - /* */ { 0x5a, 0x8003, 0x8003, "Z-Link configuration" }, - /* */ { 0x5a, 0x8004, 0x8004, "JumpStart configuration" }, - /* */ { 0x5a, 0x8005, 0x8005, "Davex 8 configuration" }, - /* */ { 0x5a, 0x8006, 0x8006, "Nifty List configuration" }, - /* */ { 0x5a, 0x8007, 0x8007, "GTv videodisc configuration" }, - /* */ { 0x5a, 0x8008, 0x8008, "GTv Workshop configuration" }, - /*PTP*/ { 0x5a, 0x8009, 0x8009, "Point-to-Point preferences" }, - /* */ { 0x5a, 0x800a, 0x800a, "ORCA/Disassembler preferences" }, - /* */ { 0x5a, 0x800b, 0x800b, "SnowTerm preferences" }, - /* */ { 0x5a, 0x800c, 0x800c, "My Word! preferences" }, - /* */ { 0x5a, 0x800d, 0x800d, "Chipmunk configuration" }, - /* */ { 0x5a, 0x8010, 0x8010, "AppleWorks GS configuration" }, - /* */ { 0x5a, 0x8011, 0x8011, "SDE Shell preferences" }, - /* */ { 0x5a, 0x8012, 0x8012, "SDE Editor preferences" }, - /* */ { 0x5a, 0x8013, 0x8013, "SDE system tab ruler" }, - /* */ { 0x5a, 0x8014, 0x8014, "Nexus configuration" }, - /* */ { 0x5a, 0x8015, 0x8015, "DesignMaster preferences" }, - /* */ { 0x5a, 0x801a, 0x801a, "MAX/Edit keyboard template" }, - /* */ { 0x5a, 0x801b, 0x801b, "MAX/Edit tab ruler set" }, - /* */ { 0x5a, 0x801c, 0x801c, "Platinum Paint preferences" }, - /* */ { 0x5a, 0x801d, 0x801d, "Sea Scan 1000" }, - /* */ { 0x5a, 0x801e, 0x801e, "Allison preferences" }, - /* */ { 0x5a, 0x801f, 0x801f, "Gold of the Americas options" }, - /* */ { 0x5a, 0x8021, 0x8021, "GSAS accounting setup" }, - /* */ { 0x5a, 0x8022, 0x8022, "GSAS accounting document" }, - /* */ { 0x5a, 0x8023, 0x8023, "UtilityLaunch preferences" }, - /* */ { 0x5a, 0x8024, 0x8024, "Softdisk configuration" }, - /* */ { 0x5a, 0x8025, 0x8025, "Quit-To configuration" }, - /* */ { 0x5a, 0x8026, 0x8026, "Big Edit Thing" }, - /* */ { 0x5a, 0x8027, 0x8027, "ZMaker preferences" }, - /* */ { 0x5a, 0x8028, 0x8028, "Minstrel configuration" }, - /* */ { 0x5a, 0x8029, 0x8029, "WordWorks Pro preferences" }, - /* */ { 0x5a, 0x802b, 0x802b, "Pointless preferences" }, - /* */ { 0x5a, 0x802c, 0x802c, "Micol Advanced Basic config" }, - /* */ { 0x5a, 0x802e, 0x802e, "Label It configuration" }, - /* */ { 0x5a, 0x802f, 0x802f, "Cool Cursor document" }, - /* */ { 0x5a, 0x8030, 0x8030, "Locator preferences" }, - /* */ { 0x5a, 0x8031, 0x8031, "Replicator preferences" }, - /* */ { 0x5a, 0x8032, 0x8032, "Kangaroo configuration" }, - /* */ { 0x5a, 0x8033, 0x8033, "Kangaroo data" }, - /* */ { 0x5a, 0x8034, 0x8034, "TransProg III configuration" }, - /* */ { 0x5a, 0x8035, 0x8035, "Home Refinancer preferences" }, - /* */ { 0x5a, 0x8036, 0x8036, "Easy Eyes settings" }, - /* */ { 0x5a, 0x8037, 0x8037, "The Optimizer settings" }, - /* */ { 0x5a, 0x8038, 0x8038, "Text Wizard settings" }, - /* */ { 0x5a, 0x803b, 0x803b, "Disk Access II preferences" }, - /* */ { 0x5a, 0x803d, 0x803d, "Quick DA configuration" }, - /* */ { 0x5a, 0x803e, 0x803e, "Crazy 8s preferences" }, - /* */ { 0x5a, 0x803f, 0x803f, "Sound Wizard settings" }, - /* */ { 0x5a, 0x8041, 0x8041, "Quick Window configuration" }, - /* */ { 0x5a, 0x8044, 0x8044, "Universe Master disk map" }, - /* */ { 0x5a, 0x8046, 0x8046, "Autopilot configuration" }, - /* */ { 0x5a, 0x8047, 0x8047, "EGOed preferences" }, - /* */ { 0x5a, 0x8049, 0x8049, "Quick DA preferences" }, - /* */ { 0x5a, 0x804b, 0x804b, "HardPressed volume preferences" }, - /* */ { 0x5a, 0x804c, 0x804c, "HardPressed global preferences" }, - /* */ { 0x5a, 0x804d, 0x804d, "HardPressed profile" }, - /* */ { 0x5a, 0x8050, 0x8050, "Don't Forget settings" }, - /* */ { 0x5a, 0x8052, 0x8052, "ProBOOT preferences" }, - /* */ { 0x5a, 0x8054, 0x8054, "Battery Brain preferences" }, - /* */ { 0x5a, 0x8055, 0x8055, "Rainbow configuration" }, - /* */ { 0x5a, 0x8061, 0x8061, "TypeSet preferences" }, - /* */ { 0x5a, 0x8063, 0x8063, "Cool Cursor preferences" }, - /* */ { 0x5a, 0x806e, 0x806e, "Balloon preferences" }, - /* */ { 0x5a, 0x80fe, 0x80fe, "Special Edition configuration" }, - /* */ { 0x5a, 0x80ff, 0x80ff, "Sun Dial preferences" }, - /*ANM*/ { 0x5b, 0x0000, 0xffff, "Animation file" }, - /* */ { 0x5b, 0x8001, 0x8001, "Cartooners movie" }, - /* */ { 0x5b, 0x8002, 0x8002, "Cartooners actors" }, - /* */ { 0x5b, 0x8005, 0x8005, "Arcade King Super document" }, - /* */ { 0x5b, 0x8006, 0x8006, "Arcade King DHRG document" }, - /* */ { 0x5b, 0x8007, 0x8007, "DreamVision movie" }, - /*MUM*/ { 0x5c, 0x0000, 0xffff, "Multimedia document" }, - /* */ { 0x5c, 0x8001, 0x8001, "GTv multimedia playlist" }, - /*ENT*/ { 0x5d, 0x0000, 0xffff, "Game/Entertainment document" }, - /* */ { 0x5d, 0x8001, 0x8001, "Solitaire Royale document" }, - /* */ { 0x5d, 0x8002, 0x8002, "BattleFront scenario" }, - /* */ { 0x5d, 0x8003, 0x8003, "BattleFront saved game" }, - /* */ { 0x5d, 0x8004, 0x8004, "Gold of the Americas game" }, - /* */ { 0x5d, 0x8006, 0x8006, "Blackjack Tutor document" }, - /* */ { 0x5d, 0x8008, 0x8008, "Canasta document" }, - /* */ { 0x5d, 0x800b, 0x800b, "Word Search document" }, - /* */ { 0x5d, 0x800c, 0x800c, "Tarot deal" }, - /* */ { 0x5d, 0x800d, 0x800d, "Tarot tournament" }, - /* */ { 0x5d, 0x800e, 0x800e, "Full Metal Planet game" }, - /* */ { 0x5d, 0x800f, 0x800f, "Full Metal Planet player" }, - /* */ { 0x5d, 0x8010, 0x8010, "Quizzical high scores" }, - /* */ { 0x5d, 0x8011, 0x8011, "Meltdown high scores" }, - /* */ { 0x5d, 0x8012, 0x8012, "BlockWords high scores" }, - /* */ { 0x5d, 0x8013, 0x8013, "Lift-A-Gon scores" }, - /* */ { 0x5d, 0x8014, 0x8014, "Softdisk Adventure" }, - /* */ { 0x5d, 0x8015, 0x8015, "Blankety Blank document" }, - /* */ { 0x5d, 0x8016, 0x8016, "Son of Star Axe champion" }, - /* */ { 0x5d, 0x8017, 0x8017, "Digit Fidget high scores" }, - /* */ { 0x5d, 0x8018, 0x8018, "Eddie map" }, - /* */ { 0x5d, 0x8019, 0x8019, "Eddie tile set" }, - /* */ { 0x5d, 0x8122, 0x8122, "Wolfenstein 3D scenario" }, - /* */ { 0x5d, 0x8123, 0x8123, "Wolfenstein 3D saved game" }, - /*DVU*/ { 0x5e, 0x0000, 0xffff, "Development utility document" }, - /* */ { 0x5e, 0x0001, 0x0001, "Resource file" }, - /* */ { 0x5e, 0x8001, 0x8001, "ORCA/Disassembler template" }, - /* */ { 0x5e, 0x8003, 0x8003, "DesignMaster document" }, - /* */ { 0x5e, 0x8008, 0x8008, "ORCA/C symbol file" }, - /*FIN*/ { 0x5f, 0x0000, 0xffff, "Financial document" }, - /* */ { 0x5f, 0x8001, 0x8001, "Your Money Matters document" }, - /* */ { 0x5f, 0x8002, 0x8002, "Home Refinancer document" }, - /*BIO*/ { 0x6b, 0x0000, 0xffff, "PC Transporter BIOS" }, - /*TDR*/ { 0x6d, 0x0000, 0xffff, "PC Transporter driver" }, - /*PRE*/ { 0x6e, 0x0000, 0xffff, "PC Transporter pre-boot" }, - /*HDV*/ { 0x6f, 0x0000, 0xffff, "PC Transporter volume" }, - /*WP */ { 0xa0, 0x0000, 0xffff, "WordPerfect document" }, - /*GSB*/ { 0xab, 0x0000, 0xffff, "Apple IIgs BASIC program" }, - /*TDF*/ { 0xac, 0x0000, 0xffff, "Apple IIgs BASIC TDF" }, - /*BDF*/ { 0xad, 0x0000, 0xffff, "Apple IIgs BASIC data" }, - /*SRC*/ { 0xb0, 0x0000, 0xffff, "Apple IIgs source code" }, - /* */ { 0xb0, 0x0001, 0x0001, "APW Text file" }, - /* */ { 0xb0, 0x0003, 0x0003, "APW 65816 Assembly source code" }, - /* */ { 0xb0, 0x0005, 0x0005, "ORCA/Pascal source code" }, - /* */ { 0xb0, 0x0006, 0x0006, "APW command file" }, - /* */ { 0xb0, 0x0008, 0x0008, "ORCA/C source code" }, - /* */ { 0xb0, 0x0009, 0x0009, "APW Linker command file" }, - /* */ { 0xb0, 0x000a, 0x000a, "APW C source code" }, - /* */ { 0xb0, 0x000c, 0x000c, "ORCA/Desktop command file" }, - /* */ { 0xb0, 0x0015, 0x0015, "APW Rez source file" }, - /* */ { 0xb0, 0x0017, 0x0017, "Installer script" }, - /* */ { 0xb0, 0x001e, 0x001e, "TML Pascal source code" }, - /* */ { 0xb0, 0x0116, 0x0116, "ORCA/Disassembler script" }, - /* */ { 0xb0, 0x0503, 0x0503, "SDE Assembler source code" }, - /* */ { 0xb0, 0x0506, 0x0506, "SDE command script" }, - /* */ { 0xb0, 0x0601, 0x0601, "Nifty List data" }, - /* */ { 0xb0, 0x0719, 0x0719, "PostScript file" }, - /*OBJ*/ { 0xb1, 0x0000, 0xffff, "Apple IIgs object code" }, - /*LIB*/ { 0xb2, 0x0000, 0xffff, "Apple IIgs Library file" }, - /*S16*/ { 0xb3, 0x0000, 0xffff, "GS/OS application" }, - /*RTL*/ { 0xb4, 0x0000, 0xffff, "GS/OS run-time library" }, - /*EXE*/ { 0xb5, 0x0000, 0xffff, "GS/OS shell application" }, - /*PIF*/ { 0xb6, 0x0000, 0xffff, "Permanent initialization file" }, - /*TIF*/ { 0xb7, 0x0000, 0xffff, "Temporary initialization file" }, - /*NDA*/ { 0xb8, 0x0000, 0xffff, "New desk accessory" }, - /*CDA*/ { 0xb9, 0x0000, 0xffff, "Classic desk accessory" }, - /*TOL*/ { 0xba, 0x0000, 0xffff, "Tool" }, - /*DVR*/ { 0xbb, 0x0000, 0xffff, "Apple IIgs device driver file" }, - /* */ { 0xbb, 0x7e01, 0x7e01, "GNO/ME terminal device driver" }, - /* */ { 0xbb, 0x7f01, 0x7f01, "GTv videodisc serial driver" }, - /* */ { 0xbb, 0x7f02, 0x7f02, "GTv videodisc game port driver" }, - /*LDF*/ { 0xbc, 0x0000, 0xffff, "Load file (generic)" }, - /* */ { 0xbc, 0x4001, 0x4001, "Nifty List module" }, - /* */ { 0xbc, 0xc001, 0xc001, "Nifty List module" }, - /* */ { 0xbc, 0x4002, 0x4002, "Super Info module" }, - /* */ { 0xbc, 0xc002, 0xc002, "Super Info module" }, - /* */ { 0xbc, 0x4004, 0x4004, "Twilight document" }, - /* */ { 0xbc, 0xc004, 0xc004, "Twilight document" }, - /* */ { 0xbc, 0x4006, 0x4006, "Foundation resource editor" }, - /* */ { 0xbc, 0xc006, 0xc006, "Foundation resource editor" }, - /* */ { 0xbc, 0x4007, 0x4007, "HyperStudio new button action" }, - /* */ { 0xbc, 0xc007, 0xc007, "HyperStudio new button action" }, - /* */ { 0xbc, 0x4008, 0x4008, "HyperStudio screen transition" }, - /* */ { 0xbc, 0xc008, 0xc008, "HyperStudio screen transition" }, - /* */ { 0xbc, 0x4009, 0x4009, "DreamGrafix module" }, - /* */ { 0xbc, 0xc009, 0xc009, "DreamGrafix module" }, - /* */ { 0xbc, 0x400a, 0x400a, "HyperStudio Extra utility" }, - /* */ { 0xbc, 0xc00a, 0xc00a, "HyperStudio Extra utility" }, - /* */ { 0xbc, 0x400f, 0x400f, "HardPressed module" }, - /* */ { 0xbc, 0xc00f, 0xc00f, "HardPressed module" }, - /* */ { 0xbc, 0x4010, 0x4010, "Graphic Exchange translator" }, - /* */ { 0xbc, 0xc010, 0xc010, "Graphic Exchange translator" }, - /* */ { 0xbc, 0x4011, 0x4011, "Desktop Enhancer blanker" }, - /* */ { 0xbc, 0xc011, 0xc011, "Desktop Enhancer blanker" }, - /* */ { 0xbc, 0x4083, 0x4083, "Marinetti link layer module" }, - /* */ { 0xbc, 0xc083, 0xc083, "Marinetti link layer module" }, - /*FST*/ { 0xbd, 0x0000, 0xffff, "GS/OS File System Translator" }, - /*DOC*/ { 0xbf, 0x0000, 0xffff, "GS/OS document" }, - /*PNT*/ { 0xc0, 0x0000, 0xffff, "Packed super hi-res picture" }, - /* */ { 0xc0, 0x0000, 0x0000, "Paintworks packed picture" }, - /* */ { 0xc0, 0x0001, 0x0001, "Packed super hi-res image" }, - /* */ { 0xc0, 0x0002, 0x0002, "Apple Preferred Format picture" }, - /* */ { 0xc0, 0x0003, 0x0003, "Packed QuickDraw II PICT file" }, - /* */ { 0xc0, 0x0080, 0x0080, "TIFF document" }, - /* */ { 0xc0, 0x0081, 0x0081, "JFIF (JPEG) document" }, - /* */ { 0xc0, 0x8001, 0x8001, "GTv background image" }, - /* */ { 0xc0, 0x8005, 0x8005, "DreamGrafix document" }, - /* */ { 0xc0, 0x8006, 0x8006, "GIF document" }, - /*PIC*/ { 0xc1, 0x0000, 0xffff, "Super hi-res picture" }, - /* */ { 0xc1, 0x0000, 0x0000, "Super hi-res screen image" }, - /* */ { 0xc1, 0x0001, 0x0001, "QuickDraw PICT file" }, - /* */ { 0xc1, 0x0002, 0x0002, "Super hi-res 3200-color screen image" }, - /* */ { 0xc1, 0x8001, 0x8001, "Allison raw image doc" }, - /* */ { 0xc1, 0x8002, 0x8002, "ThunderScan image doc" }, - /* */ { 0xc1, 0x8003, 0x8003, "DreamGrafix document" }, - /*ANI*/ { 0xc2, 0x0000, 0xffff, "Paintworks animation" }, - /*PAL*/ { 0xc3, 0x0000, 0xffff, "Paintworks palette" }, - /*OOG*/ { 0xc5, 0x0000, 0xffff, "Object-oriented graphics" }, - /* */ { 0xc5, 0x8000, 0x8000, "Draw Plus document" }, - /* */ { 0xc5, 0xc000, 0xc000, "DYOH architecture doc" }, - /* */ { 0xc5, 0xc001, 0xc001, "DYOH predrawn objects" }, - /* */ { 0xc5, 0xc002, 0xc002, "DYOH custom objects" }, - /* */ { 0xc5, 0xc003, 0xc003, "DYOH clipboard" }, - /* */ { 0xc5, 0xc004, 0xc004, "DYOH interiors document" }, - /* */ { 0xc5, 0xc005, 0xc005, "DYOH patterns" }, - /* */ { 0xc5, 0xc006, 0xc006, "DYOH landscape document" }, - /* */ { 0xc5, 0xc007, 0xc007, "PyWare Document" }, - /*SCR*/ { 0xc6, 0x0000, 0xffff, "Script" }, - /* */ { 0xc6, 0x8001, 0x8001, "Davex 8 script" }, - /* */ { 0xc6, 0x8002, 0x8002, "Universe Master backup script" }, - /* */ { 0xc6, 0x8003, 0x8003, "Universe Master Chain script" }, - /*CDV*/ { 0xc7, 0x0000, 0xffff, "Control Panel document" }, - /*FON*/ { 0xc8, 0x0000, 0xffff, "Font" }, - /* */ { 0xc8, 0x0000, 0x0000, "Font (Standard Apple IIgs QuickDraw II Font)" }, - /* */ { 0xc8, 0x0001, 0x0001, "TrueType font resource" }, - /* */ { 0xc8, 0x0008, 0x0008, "Postscript font resource" }, - /* */ { 0xc8, 0x0081, 0x0081, "TrueType font file" }, - /* */ { 0xc8, 0x0088, 0x0088, "Postscript font file" }, - /*FND*/ { 0xc9, 0x0000, 0xffff, "Finder data" }, - /*ICN*/ { 0xca, 0x0000, 0xffff, "Icons" }, - /*MUS*/ { 0xd5, 0x0000, 0xffff, "Music sequence" }, - /* */ { 0xd5, 0x0000, 0x0000, "Music Construction Set song" }, - /* */ { 0xd5, 0x0001, 0x0001, "MIDI Synth sequence" }, - /* */ { 0xd5, 0x0007, 0x0007, "SoundSmith document" }, - /* */ { 0xd5, 0x8002, 0x8002, "Diversi-Tune sequence" }, - /* */ { 0xd5, 0x8003, 0x8003, "Master Tracks Jr. sequence" }, - /* */ { 0xd5, 0x8004, 0x8004, "Music Writer document" }, - /* */ { 0xd5, 0x8005, 0x8005, "Arcade King Super music" }, - /* */ { 0xd5, 0x8006, 0x8006, "Music Composer file" }, - /*INS*/ { 0xd6, 0x0000, 0xffff, "Instrument" }, - /* */ { 0xd6, 0x0000, 0x0000, "Music Construction Set instrument" }, - /* */ { 0xd6, 0x0001, 0x0001, "MIDI Synth instrument" }, - /* */ { 0xd6, 0x8002, 0x8002, "Diversi-Tune instrument" }, - /*MDI*/ { 0xd7, 0x0000, 0xffff, "MIDI data" }, - /* */ { 0xd7, 0x0000, 0x0000, "MIDI standard data" }, - /* */ { 0xd7, 0x0080, 0x0080, "MIDI System Exclusive data" }, - /* */ { 0xd7, 0x8001, 0x8001, "MasterTracks Pro Sysex file" }, - /*SND*/ { 0xd8, 0x0000, 0xffff, "Sampled sound" }, - /* */ { 0xd8, 0x0000, 0x0000, "Audio IFF document" }, - /* */ { 0xd8, 0x0001, 0x0001, "AIFF-C document" }, - /* */ { 0xd8, 0x0002, 0x0002, "ASIF instrument" }, - /* */ { 0xd8, 0x0003, 0x0003, "Sound resource file" }, - /* */ { 0xd8, 0x0004, 0x0004, "MIDI Synth wave data" }, - /* */ { 0xd8, 0x8001, 0x8001, "HyperStudio sound" }, - /* */ { 0xd8, 0x8002, 0x8002, "Arcade King Super sound" }, - /* */ { 0xd8, 0x8003, 0x8003, "SoundOff! sound bank" }, - /*DBM*/ { 0xdb, 0x0000, 0xffff, "DB Master document" }, - /* */ { 0xdb, 0x0001, 0x0001, "DB Master document" }, - /*???*/ { 0xdd, 0x0000, 0xffff, "DDD Deluxe archive" }, // unofficial - /*LBR*/ { 0xe0, 0x0000, 0xffff, "Archival library" }, - /* */ { 0xe0, 0x0000, 0x0000, "ALU library" }, - /* */ { 0xe0, 0x0001, 0x0001, "AppleSingle file" }, - /* */ { 0xe0, 0x0002, 0x0002, "AppleDouble header file" }, - /* */ { 0xe0, 0x0003, 0x0003, "AppleDouble data file" }, - /* */ { 0xe0, 0x0004, 0x0004, "Archiver archive" }, - /* */ { 0xe0, 0x0005, 0x0005, "DiskCopy 4.2 disk image" }, - /* */ { 0xe0, 0x0100, 0x0100, "Apple 5.25 disk image" }, - /* */ { 0xe0, 0x0101, 0x0101, "Profile 5MB disk image" }, - /* */ { 0xe0, 0x0102, 0x0102, "Profile 10MB disk image" }, - /* */ { 0xe0, 0x0103, 0x0103, "Apple 3.5 disk image" }, - /* */ { 0xe0, 0x0104, 0x0104, "SCSI device image" }, - /* */ { 0xe0, 0x0105, 0x0105, "SCSI hard disk image" }, - /* */ { 0xe0, 0x0106, 0x0106, "SCSI tape image" }, - /* */ { 0xe0, 0x0107, 0x0107, "SCSI CD-ROM image" }, - /* */ { 0xe0, 0x010e, 0x010e, "RAM disk image" }, - /* */ { 0xe0, 0x010f, 0x010f, "ROM disk image" }, - /* */ { 0xe0, 0x0110, 0x0110, "File server image" }, - /* */ { 0xe0, 0x0113, 0x0113, "Hard disk image" }, - /* */ { 0xe0, 0x0114, 0x0114, "Floppy disk image" }, - /* */ { 0xe0, 0x0115, 0x0115, "Tape image" }, - /* */ { 0xe0, 0x011e, 0x011e, "AppleTalk file server image" }, - /* */ { 0xe0, 0x0120, 0x0120, "DiskCopy 6 disk image" }, - /* */ { 0xe0, 0x0130, 0x0130, "Universal Disk Image file" }, - /* */ { 0xe0, 0x8000, 0x8000, "Binary II file" }, - /* */ { 0xe0, 0x8001, 0x8001, "AppleLink ACU document" }, - /* */ { 0xe0, 0x8002, 0x8002, "ShrinkIt (NuFX) document" }, - /* */ { 0xe0, 0x8003, 0x8003, "Universal Disk Image file" }, - /* */ { 0xe0, 0x8004, 0x8004, "Davex archived volume" }, - /* */ { 0xe0, 0x8006, 0x8006, "EZ Backup Saveset doc" }, - /* */ { 0xe0, 0x8007, 0x8007, "ELS DOS 3.3 volume" }, - /* */ { 0xe0, 0x8008, 0x8008, "UtilityWorks document" }, - /* */ { 0xe0, 0x800a, 0x800a, "Replicator document" }, - /* */ { 0xe0, 0x800b, 0x800b, "AutoArk compressed document" }, - /* */ { 0xe0, 0x800d, 0x800d, "HardPressed compressed data (data fork)" }, - /* */ { 0xe0, 0x800e, 0x800e, "HardPressed compressed data (rsrc fork)" }, - /* */ { 0xe0, 0x800f, 0x800f, "HardPressed compressed data (both forks)" }, - /* */ { 0xe0, 0x8010, 0x8010, "LHA archive" }, - /*ATK*/ { 0xe2, 0x0000, 0xffff, "AppleTalk data" }, - /* */ { 0xe2, 0xffff, 0xffff, "EasyMount document" }, - /*R16*/ { 0xee, 0x0000, 0xffff, "EDASM 816 relocatable file" }, - /*PAS*/ { 0xef, 0x0000, 0xffff, "Pascal area" }, - /*CMD*/ { 0xf0, 0x0000, 0xffff, "BASIC command" }, - /*???*/ { 0xf1, 0x0000, 0xffff, "User type #1" }, - /*???*/ { 0xf2, 0x0000, 0xffff, "User type #2" }, - /*???*/ { 0xf3, 0x0000, 0xffff, "User type #3" }, - /*???*/ { 0xf4, 0x0000, 0xffff, "User type #4" }, - /*???*/ { 0xf5, 0x0000, 0xffff, "User type #5" }, - /*???*/ { 0xf6, 0x0000, 0xffff, "User type #6" }, - /*???*/ { 0xf7, 0x0000, 0xffff, "User type #7" }, - /*???*/ { 0xf8, 0x0000, 0xffff, "User type #8" }, - /*OS */ { 0xf9, 0x0000, 0xffff, "GS/OS system file" }, - /*OS */ { 0xfa, 0x0000, 0xffff, "Integer BASIC program" }, - /*OS */ { 0xfb, 0x0000, 0xffff, "Integer BASIC variables" }, - /*OS */ { 0xfc, 0x0000, 0xffff, "AppleSoft BASIC program" }, - /*OS */ { 0xfd, 0x0000, 0xffff, "AppleSoft BASIC variables" }, - /*OS */ { 0xfe, 0x0000, 0xffff, "Relocatable code" }, - /*OS */ { 0xff, 0x0000, 0xffff, "ProDOS 8 application" }, -}; - -/* - * Find an entry in the type description table that matches both file type and - * aux type. If no match is found, nil is returned. - */ -/*static*/ const char* -PathProposal::FileTypeDescription(long fileType, long auxType) -{ - int i; - - for (i = NELEM(gTypeDescriptions)-1; i >= 0; i--) { - if (fileType == gTypeDescriptions[i].fileType && - auxType >= gTypeDescriptions[i].minAuxType && - auxType <= gTypeDescriptions[i].maxAuxType) - { - return gTypeDescriptions[i].descr; - } - } - - return nil; -} - - -/* - * =========================================================================== - * Filename/filetype conversion - * =========================================================================== - */ - -/* - * Convert a pathname pulled out of an archive to something suitable for the - * local filesystem. - * - * The new pathname may be shorter (because characters were removed) or - * longer (if we add a "#XXYYYYZ" extension or replace chars with '%' codes). - */ -void -PathProposal::ArchiveToLocal(void) -{ - char* pathBuf; - const char* startp; - const char* endp; - char* dstp; - int newBufLen; - - /* init output fields */ - fLocalFssep = kLocalFssep; - fLocalPathName = ""; - - /* - * Set up temporary buffer space. The maximum possible expansion - * requires converting all chars to '%' codes and adding the longest - * possible preservation string. - */ - newBufLen = fStoredPathName.GetLength()*3 + kMaxPathGrowth +1; - pathBuf = fLocalPathName.GetBuffer(newBufLen); - ASSERT(pathBuf != nil); - - startp = fStoredPathName; - dstp = pathBuf; - while (*startp == fStoredFssep) { - /* ignore leading path sep; always extract to current dir */ - startp++; - } - - /* normalize all directory components and the filename component */ - while (startp != nil) { - endp = nil; - if (fStoredFssep != '\0') - endp = strchr(startp, fStoredFssep); - if (endp != nil && endp == startp) { - /* zero-length subdir component */ - WMSG1("WARNING: zero-length subdir component in '%s'\n", startp); - startp++; - continue; - } - if (endp != nil) { - /* normalize directory component */ - NormalizeDirectoryName(startp, endp - startp, - fStoredFssep, &dstp, newBufLen); - - *dstp++ = fLocalFssep; - - startp = endp +1; - } else { - /* normalize filename component */ - NormalizeFileName(startp, strlen(startp), - fStoredFssep, &dstp, newBufLen); - *dstp++ = '\0'; - - /* add/replace extension if necessary */ - char extBuf[kMaxPathGrowth +1] = ""; - if (fPreservation) { - AddPreservationString(pathBuf, extBuf); - } else if (fThreadKind == GenericEntry::kRsrcThread) { - /* add this in lieu of the preservation extension */ - strcat(pathBuf, kResourceStr); - } - if (fAddExtension) { - AddTypeExtension(pathBuf, extBuf); - } - ASSERT(strlen(extBuf) <= kMaxPathGrowth); - strcat(pathBuf, extBuf); - - startp = nil; /* we're done, break out of loop */ - } - } - - /* check for overflow */ - ASSERT(dstp - pathBuf <= newBufLen); - - /* - * If "junk paths" is set, drop everything but the last component. - */ - if (fJunkPaths) { - char* lastFssep; - lastFssep = strrchr(pathBuf, fLocalFssep); - if (lastFssep != nil) { - ASSERT(*(lastFssep+1) != '\0'); /* should already have been caught*/ - memmove(pathBuf, lastFssep+1, strlen(lastFssep+1)+1); - } - } - - fLocalPathName.ReleaseBuffer(); -} - -#if defined(WINDOWS_LIKE) -/* - * You can't create files or directories with these names on a FAT filesystem, - * because they're MS-DOS "device special files". - * - * The list comes from the Linux kernel's fs/msdos/namei.c. - * - * The trick is that the name can't start with any of these. That could mean - * that the name is just "aux", or it could be "aux.this.txt". - */ -static const char* gFatReservedNames3[] = { - "CON", "PRN", "NUL", "AUX", nil -}; -static const char* gFatReservedNames4[] = { - "LPT1", "LPT2", "LPT3", "LPT4", "COM1", "COM2", "COM3", "COM4", nil -}; - -/* - * Filename normalization for Win32 filesystems. You can't use [ \/:*?"<>| ] - * or control characters, and it's probably unwise to use high-ASCII stuff. - */ -void -PathProposal::Win32NormalizeFileName(const char* srcp, long srcLen, - char fssep, char** pDstp, long dstLen) -{ - char* dstp = *pDstp; - const char* startp = srcp; - static const char* kInvalid = "\\/:*?\"<>|"; - - /* match on "aux" or "aux.blah" */ - if (srcLen >= 3) { - const char** ppcch; - - for (ppcch = gFatReservedNames3; *ppcch != nil; ppcch++) { - if (strncasecmp(srcp, *ppcch, 3) == 0 && - (srcp[3] == '.' || srcLen == 3)) - { - WMSG1("--- fixing '%s'\n", *ppcch); - if (fPreservation) { - *dstp++ = kForeignIndic; - *dstp++ = '0'; - *dstp++ = '0'; - } else - *dstp++ = '_'; - break; - } - } - } - if (srcLen >= 4) { - const char** ppcch; - - for (ppcch = gFatReservedNames4; *ppcch != nil; ppcch++) { - if (strncasecmp(srcp, *ppcch, 4) == 0 && - (srcp[4] == '.' || srcLen == 4)) - { - WMSG1("--- fixing '%s'\n", *ppcch); - if (fPreservation) { - *dstp++ = kForeignIndic; - *dstp++ = '0'; - *dstp++ = '0'; - } else - *dstp++ = '_'; - break; - } - } - } - - - while (srcLen--) { /* don't go until null found! */ - ASSERT(*srcp != '\0'); - - if (*srcp == kForeignIndic) { - /* change '%' to "%%" */ - if (fPreservation) - *dstp++ = *srcp; - *dstp++ = *srcp++; - } else if (strchr(kInvalid, *srcp) != nil || - *srcp < 0x20 || *srcp >= 0x7f) - { - /* change invalid char to "%2f" or '_' */ - if (fPreservation) { - *dstp++ = kForeignIndic; - *dstp++ = HexConv(*srcp >> 4 & 0x0f); - *dstp++ = HexConv(*srcp & 0x0f); - } else { - *dstp++ = '_'; - } - srcp++; - } else { - /* no need to fiddle with it */ - *dstp++ = *srcp++; - } - } - - *dstp = '\0'; /* end the string, but don't advance past the null */ - ASSERT(*pDstp - dstp <= dstLen); /* make sure we didn't overflow */ - *pDstp = dstp; -} -#endif - - -/* - * Normalize a file name to local filesystem conventions. The input - * is quite possibly *NOT* null-terminated, since it may represent a - * substring of a full pathname. Use "srcLen". - * - * The output filename is copied to *pDstp, which is advanced forward. - * - * The output buffer must be able to hold 3x the original string length. - */ -void -PathProposal::NormalizeFileName(const char* srcp, long srcLen, - char fssep, char** pDstp, long dstLen) -{ - ASSERT(srcp != nil); - ASSERT(srcLen > 0); - ASSERT(dstLen > srcLen); - ASSERT(pDstp != nil); - ASSERT(*pDstp != nil); - -#if defined(UNIX_LIKE) - UNIXNormalizeFileName(srcp, srcLen, fssep, pDstp, dstLen); -#elif defined(WINDOWS_LIKE) - Win32NormalizeFileName(srcp, srcLen, fssep, pDstp, dstLen); -#else - #error "port this" -#endif -} - - -/* - * Normalize a directory name to local filesystem conventions. - */ -void -PathProposal::NormalizeDirectoryName(const char* srcp, long srcLen, - char fssep, char** pDstp, long dstLen) -{ - /* in general, directories and filenames are the same */ - ASSERT(fssep > ' ' && fssep < 0x7f); - NormalizeFileName(srcp, srcLen, fssep, pDstp, dstLen); -} - - -/* - * Add a preservation string. - * - * "pathBuf" is assumed to have enough space to hold the current path - * plus kMaxPathGrowth more. It will be modified in place. - */ -void -PathProposal::AddPreservationString(const char* pathBuf, char* extBuf) -{ - char* cp; - - ASSERT(pathBuf != nil); - ASSERT(extBuf != nil); - ASSERT(fPreservation); - - cp = extBuf + strlen(extBuf); - - /* - * Cons up a preservation string. On some platforms "sprintf" doesn't - * return the #of characters written, so we add it up manually. - */ - if (fFileType < 0x100 && fAuxType < 0x10000) { - sprintf(cp, "%c%02lx%04lx", kPreserveIndic, fFileType, fAuxType); - cp += 7; - } else { - sprintf(cp, "%c%08lx%08lx", kPreserveIndic, fFileType, fAuxType); - cp += 17; - } - - if (fThreadKind == GenericEntry::kRsrcThread) - *cp++ = kResourceFlag; - else if (fThreadKind == GenericEntry::kDiskImageThread) - *cp++ = kDiskImageFlag; - - - /* make sure it's terminated */ - *cp = '\0'; -} - -/* - * Add a ".foo" extension to the filename. - * - * We either need to retain the existing extension (possibly obscured by file - * type preservation) or append an extension based on the ProDOS file type. - */ -void -PathProposal::AddTypeExtension(const char* pathBuf, char* extBuf) -{ - const char* pPathExt = nil; - const char* pWantedExt = nil; - const char* pTypeExt = nil; - char* end; - char* cp; - - cp = extBuf + strlen(extBuf); - - /* - * Find extension in the local filename that we've prepared so far. - * Note FindExtension guarantees there's at least one char after '.'. - */ - pPathExt = FindExtension(pathBuf, fLocalFssep); - if (pPathExt == nil) { - /* - * There's no extension on the filename. Use the standard - * ProDOS type, if one exists for this entry. We don't use - * the table if it's NON, "???", or a hex value. - */ - if (fFileType) { - pTypeExt = FileTypeString(fFileType); - if (pTypeExt[0] == '?' || pTypeExt[0] == '$') - pTypeExt = nil; - } - } else { - pPathExt++; // skip leading '.' - } - - /* - * Figure out what extension we want this file to have. Files of type - * text are *always* ".TXT", and our extracted disk images are always - * ".PO". If it's not one of these two, we either retain the file's - * original extension, or generate one for it from the ProDOS file type. - */ - if (fFileType == 0x04) - pWantedExt = "TXT"; - else if (fThreadKind == GenericEntry::kDiskImageThread) - pWantedExt = "PO"; - else { - /* - * We want to use the extension currently on the file, if it has one. - * If not, use the one from the file type. - */ - if (pPathExt != nil) { - pWantedExt = pPathExt; - } else { - pWantedExt = pTypeExt; - } - } - /* pWantedExt != nil unless we failed to find a pTypeExt */ - - - /* - * Now we know which one we want. Figure out if we want to add it. - */ - if (pWantedExt != nil) { - if (extBuf[0] == '\0' && pPathExt != nil && - strcasecmp(pPathExt, pWantedExt) == 0) - { - /* don't add an extension that's already there */ - pWantedExt = nil; - goto know_ext; - } - - if (strlen(pWantedExt) >= kMaxExtLen) { - /* too long, forget it */ - pWantedExt = nil; - goto know_ext; - } - - /* if it's strictly decimal-numeric, don't use it (.1, .2, etc) */ - (void) strtoul(pWantedExt, &end, 10); - if (*end == '\0') { - pWantedExt = nil; - goto know_ext; - } - - /* if '#' appears in it, don't use it -- it'll confuse us */ - //WMSG2("LOOKING FOR '%c' in '%s'\n", kPreserveIndic, ccp); - const char* ccp = pWantedExt; - while (*ccp != '\0') { - if (*ccp == kPreserveIndic) { - pWantedExt = nil; - goto know_ext; - } - ccp++; - } - } -know_ext: - - /* - * If pWantedExt is non-nil, it points to a filename extension without - * the leading '.'. - */ - if (pWantedExt != nil) { - *cp++ = kFilenameExtDelim; - strcpy(cp, pWantedExt); - //cp += strlen(pWantedExt); - } -} - - -/* - * =========================================================================== - * File type restoration - * =========================================================================== - */ - -typedef bool Boolean; - -/* - * Convert a local path into something suitable for storage in an archive. - * Type preservation strings are interpreted and stripped as appropriate. - * - * This does *not* do filesystem-specific normalization here. (It could, but - * it's better to leave that for later so we can do uniqueification.) - * - * In the current implementation, fStoredPathName will always get smaller, - * but it would be unwise to rely on that. - */ -void -PathProposal::LocalToArchive(const AddFilesDialog* pAddOpts) -{ - Boolean wasPreserved; - Boolean doJunk = false; - Boolean adjusted; - char slashDotDotSlash[5] = "_.._"; - - fStoredPathName = fLocalPathName; - char* livePathStr = fStoredPathName.GetBuffer(0); - - fStoredFssep = kDefaultStoredFssep; - - /* convert '/' to '\' */ - ReplaceFssep(livePathStr, - kAltLocalFssep, //NState_GetAltSystemPathSeparator(pState), - kLocalFssep, //NState_GetSystemPathSeparator(pState), - kLocalFssep); //NState_GetSystemPathSeparator(pState)); - - /* - * Check for file type preservation info in the filename. If present, - * set the file type values and truncate the filename. - */ - wasPreserved = false; - if (pAddOpts->fTypePreservation == AddFilesDialog::kPreserveTypes || - pAddOpts->fTypePreservation == AddFilesDialog::kPreserveAndExtend) - { - wasPreserved = ExtractPreservationString(livePathStr); - } - - /* - * Do a "denormalization" pass, where we convert invalid chars (such - * as '/') from percent-codes back to 8-bit characters. The filename - * will always be the same size or smaller, so we can do it in place. - */ - if (wasPreserved) - DenormalizePath(livePathStr); - - /* - * If we're in "extended" mode, and the file wasn't preserved, take a - * guess at what the file type should be based on the file extension. - */ - if (!wasPreserved && - pAddOpts->fTypePreservation == AddFilesDialog::kPreserveAndExtend) - { - InterpretExtension(livePathStr); - } - - if (fStripDiskImageSuffix) - StripDiskImageSuffix(livePathStr); - - /* - * Strip bad chars off the front of the pathname. Every time we - * remove one thing we potentially expose another, so we have to - * loop until it's sanitized. - * - * The outer loop isn't really necessary under Win32, because you'd - * need to do something like ".\\foo", which isn't allowed. UNIX - * silently allows ".//foo", so this is a problem there. (We could - * probably do away with the inner loops, but those were already - * written when I saw the larger problem.) - */ - do { - adjusted = false; - - /* - * Check for other unpleasantness, such as a leading fssep. - */ - ASSERT(kLocalFssep != '\0'); - while (livePathStr[0] == kLocalFssep) { - /* slide it down, len is (strlen +1), -1 (dropping first char)*/ - memmove(livePathStr, livePathStr+1, strlen(livePathStr)); - adjusted = true; - } - - /* - * Remove leading "./". - */ - while (livePathStr[0] == '.' && livePathStr[1] == kLocalFssep) - { - /* slide it down, len is (strlen +1) -2 (dropping two chars) */ - memmove(livePathStr, livePathStr+2, strlen(livePathStr)-1); - adjusted = true; - } - } while (adjusted); - - /* - * If there's a "/../" present anywhere in the name, junk everything - * but the filename. - * - * This won't catch "foo/bar/..", but that should've been caught as - * a directory anyway. - */ - slashDotDotSlash[0] = kLocalFssep; - slashDotDotSlash[3] = kLocalFssep; - if ((livePathStr[0] == '.' && livePathStr[1] == '.') || - (strstr(livePathStr, slashDotDotSlash) != nil)) - { - WMSG1("Found dot dot in '%s', keeping only filename\n", livePathStr); - doJunk = true; - } - - /* - * Scan for and remove "/./" and trailing "/.". They're filesystem - * no-ops that work just fine under Win32 and UNIX but could confuse - * a IIgs. (Of course, the user could just omit them from the pathname.) - */ - /* TO DO 20030208 */ - - /* - * If "junk paths" is set, drop everything before the last fssep char. - */ - if (pAddOpts->fStripFolderNames || doJunk) { - char* lastFssep; - lastFssep = strrchr(livePathStr, kLocalFssep); - if (lastFssep != nil) { - ASSERT(*(lastFssep+1) != '\0'); /* should already have been caught*/ - memmove(livePathStr, lastFssep+1, strlen(lastFssep+1)+1); - } - } - - /* - * Finally, substitute our generally-accepted path separator in place of - * the local one, stomping on anything with a ':' in it as we do. The - * goal is to avoid having "subdir:foo/bar" turn into "subdir/foo/bar", - * so we change it to "subdirXfoo:bar". Were we a general-purpose - * archiver, this might be a mistake, but we're not. NuFX doesn't really - * give us a choice. - */ - ReplaceFssep(livePathStr, kLocalFssep, - PathProposal::kDefaultStoredFssep, 'X'); - - /* let the CString manage itself again */ - fStoredPathName.ReleaseBuffer(); -} - -/* - * Replace "oldc" with "newc". If we find an instance of "newc" already - * in the string, replace it with "newSubst". - */ -void -PathProposal::ReplaceFssep(char* str, char oldc, char newc, char newSubst) -{ - while (*str != '\0') { - if (*str == oldc) - *str = newc; - else if (*str == newc) - *str = newSubst; - str++; - } -} - - -/* - * Try to figure out what file type is associated with a filename extension. - * - * This checks the standard list of ProDOS types (which should catch things - * like "TXT" and "BIN") and the separate list of recognized extensions. - */ -void -PathProposal::LookupExtension(const char* ext) -{ - char uext3[4]; - int i, extLen; - - extLen = strlen(ext); - ASSERT(extLen > 0); - - /* - * First step is to try to find it in the recognized types list. - */ - for (i = 0; i < NELEM(gRecognizedExtensions); i++) { - if (strcasecmp(ext, gRecognizedExtensions[i].label) == 0) { - fFileType = gRecognizedExtensions[i].fileType; - fAuxType = gRecognizedExtensions[i].auxType; - goto bail; - } - } - - /* - * Second step is to try to find it in the ProDOS types list. - * - * The extension is converted to upper case and padded with spaces. - * - * [do we want to obstruct matching on things like '$f7' here?] - */ - if (extLen <= 3) { - for (i = 2; i >= extLen; i--) - uext3[i] = ' '; - for ( ; i >= 0; i--) - uext3[i] = toupper(ext[i]); - uext3[3] = '\0'; - - /*printf("### converted '%s' to '%s'\n", ext, uext3);*/ - - for (i = 0; i < NELEM(gFileTypeNames); i++) { - if (strcmp(uext3, gFileTypeNames[i]) == 0) { - fFileType = i; - goto bail; - } - } - } - -bail: - return; -} - -/* - * Try to associate some meaning with the file extension. - */ -void -PathProposal::InterpretExtension(const char* pathName) -{ - const char* pExt; - - ASSERT(pathName != nil); - - pExt = FindExtension(pathName, fLocalFssep); - if (pExt != nil) - LookupExtension(pExt+1); -} - - -/* - * Check to see if there's a preservation string on the filename. If so, - * set the filetype and auxtype information, and trim the preservation - * string off. - * - * We have to be careful not to trip on false-positive occurrences of '#' - * in the filename. - */ -Boolean -PathProposal::ExtractPreservationString(char* pathname) -{ - char numBuf[9]; - unsigned long fileType, auxType; - int threadMask; - char* pPreserve; - char* cp; - int digitCount; - - ASSERT(pathname != nil); - - pPreserve = strrchr(pathname, kPreserveIndic); - if (pPreserve == nil) - return false; - - /* count up the #of hex digits */ - digitCount = 0; - for (cp = pPreserve+1; *cp != '\0' && isxdigit((int)*cp); cp++) - digitCount++; - - /* extract the file and aux type */ - switch (digitCount) { - case 6: - /* ProDOS 1-byte type and 2-byte aux */ - memcpy(numBuf, pPreserve+1, 2); - numBuf[2] = 0; - fileType = strtoul(numBuf, &cp, 16); - ASSERT(cp == numBuf + 2); - - auxType = strtoul(pPreserve+3, &cp, 16); - ASSERT(cp == pPreserve + 7); - break; - case 16: - /* HFS 4-byte type and 4-byte creator */ - memcpy(numBuf, pPreserve+1, 8); - numBuf[8] = 0; - fileType = strtoul(numBuf, &cp, 16); - ASSERT(cp == numBuf + 8); - - auxType = strtoul(pPreserve+9, &cp, 16); - ASSERT(cp == pPreserve + 17); - break; - default: - /* not valid */ - return false; - } - - /* check for a threadID specifier */ - //threadID = kNuThreadIDDataFork; - threadMask = GenericEntry::kDataThread; - switch (*cp) { - case kResourceFlag: - //threadID = kNuThreadIDRsrcFork; - threadMask = GenericEntry::kRsrcThread; - cp++; - break; - case kDiskImageFlag: - //threadID = kNuThreadIDDiskImage; - threadMask = GenericEntry::kDiskImageThread; - cp++; - break; - default: - /* do nothing... yet */ - break; - } - - /* make sure we were the very last component */ - switch (*cp) { - case kFilenameExtDelim: /* redundant "-ee" extension */ - case '\0': /* end of string! */ - break; - default: - return false; - } - - /* truncate the original string, and return what we got */ - *pPreserve = '\0'; - fFileType = fileType; - fAuxType = auxType; - fThreadKind = threadMask; - //*pThreadID = threadID; - - return true; -} - - -/* - * Remove NuLib2's normalization magic (e.g. "%2f" for '/'). - * - * This always results in the filename staying the same length or getting - * smaller, so we can do it in place in the buffer. - */ -void -PathProposal::DenormalizePath(char* pathBuf) -{ - const char* srcp; - char* dstp; - char ch; - - srcp = pathBuf; - dstp = pathBuf; - - while (*srcp != '\0') { - if (*srcp == kForeignIndic) { - srcp++; - if (*srcp == kForeignIndic) { - *dstp++ = kForeignIndic; - srcp++; - } else if (isxdigit((int)*srcp)) { - ch = HexDigit(*srcp) << 4; - srcp++; - if (isxdigit((int)*srcp)) { - /* valid, output char */ - ch += HexDigit(*srcp); - *dstp++ = ch; - srcp++; - } else { - /* bogus '%' with trailing hex digit found! */ - *dstp++ = kForeignIndic; - *dstp++ = *(srcp-1); - } - } else { - /* bogus lone '%s' found! */ - *dstp++ = kForeignIndic; - } - - } else { - *dstp++ = *srcp++; - } - } - - *dstp = '\0'; - ASSERT(dstp <= srcp); -} - -/* - * Remove a disk image suffix. - * - * Useful when adding disk images directly from a .SDK or .2MG file. We - * don't want them to retain their original suffix. - */ -void -PathProposal::StripDiskImageSuffix(char* pathName) -{ - static const char diskExt[][4] = { - "SHK", "SDK", "IMG", "PO", "DO", "2MG", "DSK" - }; - char* pExt; - int i; - - pExt = (char*)FindExtension(pathName, fLocalFssep); - if (pExt == nil || pExt == pathName) - return; - - for (i = 0; i < NELEM(diskExt); i++) { - if (strcasecmp(pExt+1, diskExt[i]) == 0) { - WMSG2("Dropping '%s' from '%s'\n", pExt, pathName); - *pExt = '\0'; - return; - } - } -} +/* + * CiderPress + * Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved. + * See the file LICENSE for distribution terms. + */ +/* + * Filename manipulation, including file type preservation. This is + * substantially ripped from NuLib2, which would be a GPL violation if + * it weren't my code to begin with. + */ +#include "stdafx.h" +#include "FileNameConv.h" +#include "GenericArchive.h" +#include "AddFilesDialog.h" +#include + + +#define WINDOWS_LIKE +/* replace unsupported chars with '%xx' */ +#define kForeignIndic '%' + +/* convert single hex digit char to number */ +#define HexDigit(x) ( !isxdigit((int)(x)) ? -1 : \ + (x) <= '9' ? (x) - '0' : toupper(x) +10 - 'A' ) + +/* convert number from 0-15 to hex digit */ +#define HexConv(x) ( ((unsigned int)(x)) <= 15 ? \ + ( (x) <= 9 ? (x) + '0' : (x) -10 + 'A') : -1 ) + + +/* + * =========================================================================== + * Common definitions + * =========================================================================== + */ + +#define kPreserveIndic '#' /* use # rather than $ for hex indication */ +#define kFilenameExtDelim '.' /* separates extension from filename */ +#define kResourceFlag 'r' +#define kDiskImageFlag 'i' +#define kMaxExtLen 5 /* ".1234" */ +#define kResourceStr _T("_rsrc_") + +/* must be longer then strlen(kResourceStr)... no problem there */ +#define kMaxPathGrowth (sizeof("#XXXXXXXXYYYYYYYYZ")-1 + kMaxExtLen+1) + + +/* ProDOS file type names; must be entirely in upper case */ +static const char gFileTypeNames[256][4] = { + "NON", "BAD", "PCD", "PTX", "TXT", "PDA", "BIN", "FNT", + "FOT", "BA3", "DA3", "WPF", "SOS", "$0D", "$0E", "DIR", + "RPD", "RPI", "AFD", "AFM", "AFR", "SCL", "PFS", "$17", + "$18", "ADB", "AWP", "ASP", "$1C", "$1D", "$1E", "$1F", + "TDM", "$21", "$22", "$23", "$24", "$25", "$26", "$27", + "$28", "$29", "8SC", "8OB", "8IC", "8LD", "P8C", "$2F", + "$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37", + "$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F", + "DIC", "OCR", "FTD", "$43", "$44", "$45", "$46", "$47", + "$48", "$49", "$4A", "$4B", "$4C", "$4D", "$4E", "$4F", + "GWP", "GSS", "GDB", "DRW", "GDP", "HMD", "EDU", "STN", + "HLP", "COM", "CFG", "ANM", "MUM", "ENT", "DVU", "FIN", + "$60", "$61", "$62", "$63", "$64", "$65", "$66", "$67", + "$68", "$69", "$6A", "BIO", "$6C", "TDR", "PRE", "HDV", + "$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77", + "$78", "$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F", + "$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87", + "$88", "$89", "$8A", "$8B", "$8C", "$8D", "$8E", "$8F", + "$90", "$91", "$92", "$93", "$94", "$95", "$96", "$97", + "$98", "$99", "$9A", "$9B", "$9C", "$9D", "$9E", "$9F", + "WP ", "$A1", "$A2", "$A3", "$A4", "$A5", "$A6", "$A7", + "$A8", "$A9", "$AA", "GSB", "TDF", "BDF", "$AE", "$AF", + "SRC", "OBJ", "LIB", "S16", "RTL", "EXE", "PIF", "TIF", + "NDA", "CDA", "TOL", "DVR", "LDF", "FST", "$BE", "DOC", + "PNT", "PIC", "ANI", "PAL", "$C4", "OOG", "SCR", "CDV", + "FON", "FND", "ICN", "$CB", "$CC", "$CD", "$CE", "$CF", + "$D0", "$D1", "$D2", "$D3", "$D4", "MUS", "INS", "MDI", + "SND", "$D9", "$DA", "DBM", "$DC", "DDD", "$DE", "$DF", + "LBR", "$E1", "ATK", "$E3", "$E4", "$E5", "$E6", "$E7", + "$E8", "$E9", "$EA", "$EB", "$EC", "$ED", "R16", "PAS", + "CMD", "$F1", "$F2", "$F3", "$F4", "$F5", "$F6", "$F7", + "$F8", "OS ", "INT", "IVR", "BAS", "VAR", "REL", "SYS" +}; + +/* + * Some file extensions we recognize. When adding files with "extended" + * preservation mode, we try to assign types to files that weren't + * explicitly preserved, but nevertheless have a recognizeable type. + * + * geoff at gwlink.net pointed out that this really ought to be in an external + * file rather than a hard-coded table. Ought to fix that someday. + */ +static const struct { + const char* label; + unsigned short fileType; + unsigned long auxType; + unsigned char flags; +} gRecognizedExtensions[] = { + { "ASM", 0xb0, 0x0003, 0 }, /* APW assembly source */ + { "C", 0xb0, 0x000a, 0 }, /* APW C source */ + { "H", 0xb0, 0x000a, 0 }, /* APW C header */ + { "CPP", 0xb0, 0x0000, 0 }, /* generic source file */ + { "BNY", 0xe0, 0x8000, 0 }, /* Binary II lib */ + { "BQY", 0xe0, 0x8000, 0 }, /* Binary II lib, w/ compress */ + { "BXY", 0xe0, 0x8000, 0 }, /* Binary II wrap around SHK */ + { "BSE", 0xe0, 0x8000, 0 }, /* Binary II wrap around SEA */ + { "SEA", 0xb3, 0xdb07, 0 }, /* GSHK SEA */ + { "TEXT", 0x04, 0x0000, 0 }, /* ASCII Text */ + { "GIF", 0xc0, 0x8006, 0 }, /* GIF image */ + { "JPG", 0x06, 0x0000, 0 }, /* JPEG (nicer than 'NON') */ + { "JPEG", 0x06, 0x0000, 0 }, /* JPEG (nicer than 'NON') */ + //{ "ACU", 0xe0, 0x8001, 0 }, /* ACU archive */ + { "SHK", 0xe0, 0x8002, 0 }, /* ShrinkIt archive */ +}; + + +/* + * Return a pointer to the three-letter representation of the file type name. + * + * Note to self: code down below tests first char for '?'. + */ +/*static*/ const char* +PathProposal::FileTypeString(unsigned long fileType) +{ + if (fileType < NELEM(gFileTypeNames)) + return gFileTypeNames[fileType]; + else + return kUnknownTypeStr; +} + +/* + * Description table. + * + * The first item that matches will be used, but the table is searched + * bottom-up, so it's important to have the most general entry first. + * + * In retrospect, it might have made sense to use the same format as the + * "FTD" file type description file that the IIgs Finder used. Might have + * made sense to just ship that and load it on startup (although copyright + * issues would have to be investigated). + */ +static const struct { + unsigned short fileType; + unsigned short minAuxType; // start of range for which this applies + unsigned short maxAuxType; // end of range + const char* descr; +} gTypeDescriptions[] = { + /*NON*/ { 0x00, 0x0000, 0xffff, "Untyped file" }, + /*BAD*/ { 0x01, 0x0000, 0xffff, "Bad blocks" }, + /*PCD*/ { 0x02, 0x0000, 0xffff, "Pascal code" }, + /*PTX*/ { 0x03, 0x0000, 0xffff, "Pascal text" }, + /*TXT*/ { 0x04, 0x0000, 0xffff, "ASCII text" }, + /*PDA*/ { 0x05, 0x0000, 0xffff, "Pascal data" }, + /*BIN*/ { 0x06, 0x0000, 0xffff, "Binary" }, + /*FNT*/ { 0x07, 0x0000, 0xffff, "Apple /// font" }, + /*FOT*/ { 0x08, 0x0000, 0xffff, "Apple II or /// graphics" }, + /* */ { 0x08, 0x0000, 0x3fff, "Apple II graphics" }, + /* */ { 0x08, 0x4000, 0x4000, "Packed hi-res image" }, + /* */ { 0x08, 0x4001, 0x4001, "Packed double hi-res image" }, + /* */ { 0x08, 0x8001, 0x8001, "Printographer packed HGR file" }, + /* */ { 0x08, 0x8002, 0x8002, "Printographer packed DHGR file" }, + /* */ { 0x08, 0x8003, 0x8003, "Softdisk hi-res image" }, + /* */ { 0x08, 0x8004, 0x8004, "Softdisk double hi-res image" }, + /*BA3*/ { 0x09, 0x0000, 0xffff, "Apple /// BASIC program" }, + /*DA3*/ { 0x0a, 0x0000, 0xffff, "Apple /// BASIC data" }, + /*WPF*/ { 0x0b, 0x0000, 0xffff, "Apple II or /// word processor" }, + /* */ { 0x0b, 0x8001, 0x8001, "Write This Way document" }, + /* */ { 0x0b, 0x8002, 0x8002, "Writing & Publishing document" }, + /*SOS*/ { 0x0c, 0x0000, 0xffff, "Apple /// SOS system" }, + /*DIR*/ { 0x0f, 0x0000, 0xffff, "Folder" }, + /*RPD*/ { 0x10, 0x0000, 0xffff, "Apple /// RPS data" }, + /*RPI*/ { 0x11, 0x0000, 0xffff, "Apple /// RPS index" }, + /*AFD*/ { 0x12, 0x0000, 0xffff, "Apple /// AppleFile discard" }, + /*AFM*/ { 0x13, 0x0000, 0xffff, "Apple /// AppleFile model" }, + /*AFR*/ { 0x14, 0x0000, 0xffff, "Apple /// AppleFile report format" }, + /*SCL*/ { 0x15, 0x0000, 0xffff, "Apple /// screen library" }, + /*PFS*/ { 0x16, 0x0000, 0xffff, "PFS document" }, + /* */ { 0x16, 0x0001, 0x0001, "PFS:File document" }, + /* */ { 0x16, 0x0002, 0x0002, "PFS:Write document" }, + /* */ { 0x16, 0x0003, 0x0003, "PFS:Graph document" }, + /* */ { 0x16, 0x0004, 0x0004, "PFS:Plan document" }, + /* */ { 0x16, 0x0016, 0x0016, "PFS internal data" }, + /*ADB*/ { 0x19, 0x0000, 0xffff, "AppleWorks data base" }, + /*AWP*/ { 0x1a, 0x0000, 0xffff, "AppleWorks word processor" }, + /*ASP*/ { 0x1b, 0x0000, 0xffff, "AppleWorks spreadsheet" }, + /*TDM*/ { 0x20, 0x0000, 0xffff, "Desktop Manager document" }, + /*???*/ { 0x21, 0x0000, 0xffff, "Instant Pascal source" }, + /*???*/ { 0x22, 0x0000, 0xffff, "UCSD Pascal volume" }, + /*???*/ { 0x29, 0x0000, 0xffff, "Apple /// SOS dictionary" }, + /*8SC*/ { 0x2a, 0x0000, 0xffff, "Apple II source code" }, + /* */ { 0x2a, 0x8001, 0x8001, "EBBS command script" }, + /*8OB*/ { 0x2b, 0x0000, 0xffff, "Apple II object code" }, + /* */ { 0x2b, 0x8001, 0x8001, "GBBS Pro object Code" }, + /*8IC*/ { 0x2c, 0x0000, 0xffff, "Apple II interpreted code" }, + /* */ { 0x2c, 0x8003, 0x8003, "APEX Program File" }, + /* */ { 0x2c, 0x8005, 0x8005, "EBBS tokenized command script" }, + /*8LD*/ { 0x2d, 0x0000, 0xffff, "Apple II language data" }, + /* */ { 0x2d, 0x8006, 0x8005, "EBBS message bundle" }, + /* */ { 0x2d, 0x8007, 0x8007, "EBBS compressed message bundle" }, + /*P8C*/ { 0x2e, 0x0000, 0xffff, "ProDOS 8 code module" }, + /* */ { 0x2e, 0x8001, 0x8001, "Davex 8 Command" }, + /*PTP*/ { 0x2e, 0x8002, 0x8002, "Point-to-Point drivers" }, + /*PTP*/ { 0x2e, 0x8003, 0x8003, "Point-to-Point code" }, + /* */ { 0x2e, 0x8004, 0x8004, "Softdisk printer driver" }, + /*DIC*/ { 0x40, 0x0000, 0xffff, "Dictionary file" }, + /*???*/ { 0x41, 0x0000, 0xffff, "OCR data" }, + /* */ { 0x41, 0x8001, 0x8001, "InWords OCR font table" }, + /*FTD*/ { 0x42, 0x0000, 0xffff, "File type names" }, + /*???*/ { 0x43, 0x0000, 0xffff, "Peripheral data" }, + /* */ { 0x43, 0x8001, 0x8001, "Express document" }, + /*???*/ { 0x44, 0x0000, 0xffff, "Personal information" }, + /* */ { 0x44, 0x8001, 0x8001, "ResuMaker personal information" }, + /* */ { 0x44, 0x8002, 0x8002, "ResuMaker resume" }, + /* */ { 0x44, 0x8003, 0x8003, "II Notes document" }, + /* */ { 0x44, 0x8004, 0x8004, "Softdisk scrapbook document" }, + /* */ { 0x44, 0x8005, 0x8005, "Don't Forget document" }, + /* */ { 0x44, 0x80ff, 0x80ff, "What To Do data" }, + /* */ { 0x44, 0xbeef, 0xbeef, "Table Scraps scrapbook" }, + /*???*/ { 0x45, 0x0000, 0xffff, "Mathematical document" }, + /* */ { 0x45, 0x8001, 0x8001, "GSymbolix 3D graph document" }, + /* */ { 0x45, 0x8002, 0x8002, "GSymbolix formula document" }, + /*???*/ { 0x46, 0x0000, 0xffff, "AutoSave profiles" }, + /* */ { 0x46, 0x8001, 0x8001, "AutoSave profiles" }, + /*GWP*/ { 0x50, 0x0000, 0xffff, "Apple IIgs Word Processor" }, + /* */ { 0x50, 0x8001, 0x8001, "DeluxeWrite document" }, + /* */ { 0x50, 0x8003, 0x8003, "Personal Journal document" }, + /* */ { 0x50, 0x8010, 0x8010, "AppleWorks GS word processor" }, + /* */ { 0x50, 0x8011, 0x8011, "Softdisk issue text" }, + /* */ { 0x50, 0x5445, 0x5445, "Teach document" }, + /*GSS*/ { 0x51, 0x0000, 0xffff, "Apple IIgs spreadsheet" }, + /* */ { 0x51, 0x8010, 0x8010, "AppleWorks GS spreadsheet" }, + /* */ { 0x51, 0x2358, 0x2358, "QC Calc spreadsheet " }, + /*GDB*/ { 0x52, 0x0000, 0xffff, "Apple IIgs data base" }, + /* */ { 0x52, 0x8001, 0x8001, "GTv database" }, + /* */ { 0x52, 0x8010, 0x8010, "AppleWorks GS data base" }, + /* */ { 0x52, 0x8011, 0x8011, "AppleWorks GS DB template" }, + /* */ { 0x52, 0x8013, 0x8013, "GSAS database" }, + /* */ { 0x52, 0x8014, 0x8014, "GSAS accounting journals" }, + /* */ { 0x52, 0x8015, 0x8015, "Address Manager document" }, + /* */ { 0x52, 0x8016, 0x8016, "Address Manager defaults" }, + /* */ { 0x52, 0x8017, 0x8017, "Address Manager index" }, + /*DRW*/ { 0x53, 0x0000, 0xffff, "Drawing" }, + /* */ { 0x53, 0x8002, 0x8002, "Graphic Disk Labeler document" }, + /* */ { 0x53, 0x8010, 0x8010, "AppleWorks GS graphics" }, + /*GDP*/ { 0x54, 0x0000, 0xffff, "Desktop publishing" }, + /* */ { 0x54, 0x8002, 0x8002, "GraphicWriter document" }, + /* */ { 0x54, 0x8003, 0x8003, "Label It document" }, + /* */ { 0x54, 0x8010, 0x8010, "AppleWorks GS Page Layout" }, + /* */ { 0x54, 0xdd3e, 0xdd3e, "Medley document" }, + /*HMD*/ { 0x55, 0x0000, 0xffff, "Hypermedia" }, + /* */ { 0x55, 0x0001, 0x0001, "HyperCard IIgs stack" }, + /* */ { 0x55, 0x8001, 0x8001, "Tutor-Tech document" }, + /* */ { 0x55, 0x8002, 0x8002, "HyperStudio document" }, + /* */ { 0x55, 0x8003, 0x8003, "Nexus document" }, + /* */ { 0x55, 0x8004, 0x8004, "HyperSoft stack" }, + /* */ { 0x55, 0x8005, 0x8005, "HyperSoft card" }, + /* */ { 0x55, 0x8006, 0x8006, "HyperSoft external command" }, + /*EDU*/ { 0x56, 0x0000, 0xffff, "Educational Data" }, + /* */ { 0x56, 0x8001, 0x8001, "Tutor-Tech scores" }, + /* */ { 0x56, 0x8007, 0x8007, "GradeBook data" }, + /*STN*/ { 0x57, 0x0000, 0xffff, "Stationery" }, + /* */ { 0x57, 0x8003, 0x8003, "Music Writer format" }, + /*HLP*/ { 0x58, 0x0000, 0xffff, "Help file" }, + /* */ { 0x58, 0x8002, 0x8002, "Davex 8 help file" }, + /* */ { 0x58, 0x8005, 0x8005, "Micol Advanced Basic help file" }, + /* */ { 0x58, 0x8006, 0x8006, "Locator help document" }, + /* */ { 0x58, 0x8007, 0x8007, "Personal Journal help" }, + /* */ { 0x58, 0x8008, 0x8008, "Home Refinancer help" }, + /* */ { 0x58, 0x8009, 0x8009, "The Optimizer help" }, + /* */ { 0x58, 0x800a, 0x800a, "Text Wizard help" }, + /* */ { 0x58, 0x800b, 0x800b, "WordWorks Pro help system" }, + /* */ { 0x58, 0x800c, 0x800c, "Sound Wizard help" }, + /* */ { 0x58, 0x800d, 0x800d, "SeeHear help system" }, + /* */ { 0x58, 0x800e, 0x800e, "QuickForms help system" }, + /* */ { 0x58, 0x800f, 0x800f, "Don't Forget help system" }, + /*COM*/ { 0x59, 0x0000, 0xffff, "Communications file" }, + /* */ { 0x59, 0x8002, 0x8002, "AppleWorks GS communications" }, + /*CFG*/ { 0x5a, 0x0000, 0xffff, "Configuration file" }, + /* */ { 0x5a, 0x0000, 0x0000, "Sound settings files" }, + /* */ { 0x5a, 0x0002, 0x0002, "Battery RAM configuration" }, + /* */ { 0x5a, 0x0003, 0x0003, "AutoLaunch preferences" }, + /* */ { 0x5a, 0x0004, 0x0004, "SetStart preferences" }, + /* */ { 0x5a, 0x0005, 0x0005, "GSBug configuration" }, + /* */ { 0x5a, 0x0006, 0x0006, "Archiver preferences" }, + /* */ { 0x5a, 0x0007, 0x0007, "Archiver table of contents" }, + /* */ { 0x5a, 0x0008, 0x0008, "Font Manager data" }, + /* */ { 0x5a, 0x0009, 0x0009, "Print Manager data" }, + /* */ { 0x5a, 0x000a, 0x000a, "IR preferences" }, + /* */ { 0x5a, 0x8001, 0x8001, "Master Tracks Jr. preferences" }, + /* */ { 0x5a, 0x8002, 0x8002, "GraphicWriter preferences" }, + /* */ { 0x5a, 0x8003, 0x8003, "Z-Link configuration" }, + /* */ { 0x5a, 0x8004, 0x8004, "JumpStart configuration" }, + /* */ { 0x5a, 0x8005, 0x8005, "Davex 8 configuration" }, + /* */ { 0x5a, 0x8006, 0x8006, "Nifty List configuration" }, + /* */ { 0x5a, 0x8007, 0x8007, "GTv videodisc configuration" }, + /* */ { 0x5a, 0x8008, 0x8008, "GTv Workshop configuration" }, + /*PTP*/ { 0x5a, 0x8009, 0x8009, "Point-to-Point preferences" }, + /* */ { 0x5a, 0x800a, 0x800a, "ORCA/Disassembler preferences" }, + /* */ { 0x5a, 0x800b, 0x800b, "SnowTerm preferences" }, + /* */ { 0x5a, 0x800c, 0x800c, "My Word! preferences" }, + /* */ { 0x5a, 0x800d, 0x800d, "Chipmunk configuration" }, + /* */ { 0x5a, 0x8010, 0x8010, "AppleWorks GS configuration" }, + /* */ { 0x5a, 0x8011, 0x8011, "SDE Shell preferences" }, + /* */ { 0x5a, 0x8012, 0x8012, "SDE Editor preferences" }, + /* */ { 0x5a, 0x8013, 0x8013, "SDE system tab ruler" }, + /* */ { 0x5a, 0x8014, 0x8014, "Nexus configuration" }, + /* */ { 0x5a, 0x8015, 0x8015, "DesignMaster preferences" }, + /* */ { 0x5a, 0x801a, 0x801a, "MAX/Edit keyboard template" }, + /* */ { 0x5a, 0x801b, 0x801b, "MAX/Edit tab ruler set" }, + /* */ { 0x5a, 0x801c, 0x801c, "Platinum Paint preferences" }, + /* */ { 0x5a, 0x801d, 0x801d, "Sea Scan 1000" }, + /* */ { 0x5a, 0x801e, 0x801e, "Allison preferences" }, + /* */ { 0x5a, 0x801f, 0x801f, "Gold of the Americas options" }, + /* */ { 0x5a, 0x8021, 0x8021, "GSAS accounting setup" }, + /* */ { 0x5a, 0x8022, 0x8022, "GSAS accounting document" }, + /* */ { 0x5a, 0x8023, 0x8023, "UtilityLaunch preferences" }, + /* */ { 0x5a, 0x8024, 0x8024, "Softdisk configuration" }, + /* */ { 0x5a, 0x8025, 0x8025, "Quit-To configuration" }, + /* */ { 0x5a, 0x8026, 0x8026, "Big Edit Thing" }, + /* */ { 0x5a, 0x8027, 0x8027, "ZMaker preferences" }, + /* */ { 0x5a, 0x8028, 0x8028, "Minstrel configuration" }, + /* */ { 0x5a, 0x8029, 0x8029, "WordWorks Pro preferences" }, + /* */ { 0x5a, 0x802b, 0x802b, "Pointless preferences" }, + /* */ { 0x5a, 0x802c, 0x802c, "Micol Advanced Basic config" }, + /* */ { 0x5a, 0x802e, 0x802e, "Label It configuration" }, + /* */ { 0x5a, 0x802f, 0x802f, "Cool Cursor document" }, + /* */ { 0x5a, 0x8030, 0x8030, "Locator preferences" }, + /* */ { 0x5a, 0x8031, 0x8031, "Replicator preferences" }, + /* */ { 0x5a, 0x8032, 0x8032, "Kangaroo configuration" }, + /* */ { 0x5a, 0x8033, 0x8033, "Kangaroo data" }, + /* */ { 0x5a, 0x8034, 0x8034, "TransProg III configuration" }, + /* */ { 0x5a, 0x8035, 0x8035, "Home Refinancer preferences" }, + /* */ { 0x5a, 0x8036, 0x8036, "Easy Eyes settings" }, + /* */ { 0x5a, 0x8037, 0x8037, "The Optimizer settings" }, + /* */ { 0x5a, 0x8038, 0x8038, "Text Wizard settings" }, + /* */ { 0x5a, 0x803b, 0x803b, "Disk Access II preferences" }, + /* */ { 0x5a, 0x803d, 0x803d, "Quick DA configuration" }, + /* */ { 0x5a, 0x803e, 0x803e, "Crazy 8s preferences" }, + /* */ { 0x5a, 0x803f, 0x803f, "Sound Wizard settings" }, + /* */ { 0x5a, 0x8041, 0x8041, "Quick Window configuration" }, + /* */ { 0x5a, 0x8044, 0x8044, "Universe Master disk map" }, + /* */ { 0x5a, 0x8046, 0x8046, "Autopilot configuration" }, + /* */ { 0x5a, 0x8047, 0x8047, "EGOed preferences" }, + /* */ { 0x5a, 0x8049, 0x8049, "Quick DA preferences" }, + /* */ { 0x5a, 0x804b, 0x804b, "HardPressed volume preferences" }, + /* */ { 0x5a, 0x804c, 0x804c, "HardPressed global preferences" }, + /* */ { 0x5a, 0x804d, 0x804d, "HardPressed profile" }, + /* */ { 0x5a, 0x8050, 0x8050, "Don't Forget settings" }, + /* */ { 0x5a, 0x8052, 0x8052, "ProBOOT preferences" }, + /* */ { 0x5a, 0x8054, 0x8054, "Battery Brain preferences" }, + /* */ { 0x5a, 0x8055, 0x8055, "Rainbow configuration" }, + /* */ { 0x5a, 0x8061, 0x8061, "TypeSet preferences" }, + /* */ { 0x5a, 0x8063, 0x8063, "Cool Cursor preferences" }, + /* */ { 0x5a, 0x806e, 0x806e, "Balloon preferences" }, + /* */ { 0x5a, 0x80fe, 0x80fe, "Special Edition configuration" }, + /* */ { 0x5a, 0x80ff, 0x80ff, "Sun Dial preferences" }, + /*ANM*/ { 0x5b, 0x0000, 0xffff, "Animation file" }, + /* */ { 0x5b, 0x8001, 0x8001, "Cartooners movie" }, + /* */ { 0x5b, 0x8002, 0x8002, "Cartooners actors" }, + /* */ { 0x5b, 0x8005, 0x8005, "Arcade King Super document" }, + /* */ { 0x5b, 0x8006, 0x8006, "Arcade King DHRG document" }, + /* */ { 0x5b, 0x8007, 0x8007, "DreamVision movie" }, + /*MUM*/ { 0x5c, 0x0000, 0xffff, "Multimedia document" }, + /* */ { 0x5c, 0x8001, 0x8001, "GTv multimedia playlist" }, + /*ENT*/ { 0x5d, 0x0000, 0xffff, "Game/Entertainment document" }, + /* */ { 0x5d, 0x8001, 0x8001, "Solitaire Royale document" }, + /* */ { 0x5d, 0x8002, 0x8002, "BattleFront scenario" }, + /* */ { 0x5d, 0x8003, 0x8003, "BattleFront saved game" }, + /* */ { 0x5d, 0x8004, 0x8004, "Gold of the Americas game" }, + /* */ { 0x5d, 0x8006, 0x8006, "Blackjack Tutor document" }, + /* */ { 0x5d, 0x8008, 0x8008, "Canasta document" }, + /* */ { 0x5d, 0x800b, 0x800b, "Word Search document" }, + /* */ { 0x5d, 0x800c, 0x800c, "Tarot deal" }, + /* */ { 0x5d, 0x800d, 0x800d, "Tarot tournament" }, + /* */ { 0x5d, 0x800e, 0x800e, "Full Metal Planet game" }, + /* */ { 0x5d, 0x800f, 0x800f, "Full Metal Planet player" }, + /* */ { 0x5d, 0x8010, 0x8010, "Quizzical high scores" }, + /* */ { 0x5d, 0x8011, 0x8011, "Meltdown high scores" }, + /* */ { 0x5d, 0x8012, 0x8012, "BlockWords high scores" }, + /* */ { 0x5d, 0x8013, 0x8013, "Lift-A-Gon scores" }, + /* */ { 0x5d, 0x8014, 0x8014, "Softdisk Adventure" }, + /* */ { 0x5d, 0x8015, 0x8015, "Blankety Blank document" }, + /* */ { 0x5d, 0x8016, 0x8016, "Son of Star Axe champion" }, + /* */ { 0x5d, 0x8017, 0x8017, "Digit Fidget high scores" }, + /* */ { 0x5d, 0x8018, 0x8018, "Eddie map" }, + /* */ { 0x5d, 0x8019, 0x8019, "Eddie tile set" }, + /* */ { 0x5d, 0x8122, 0x8122, "Wolfenstein 3D scenario" }, + /* */ { 0x5d, 0x8123, 0x8123, "Wolfenstein 3D saved game" }, + /*DVU*/ { 0x5e, 0x0000, 0xffff, "Development utility document" }, + /* */ { 0x5e, 0x0001, 0x0001, "Resource file" }, + /* */ { 0x5e, 0x8001, 0x8001, "ORCA/Disassembler template" }, + /* */ { 0x5e, 0x8003, 0x8003, "DesignMaster document" }, + /* */ { 0x5e, 0x8008, 0x8008, "ORCA/C symbol file" }, + /*FIN*/ { 0x5f, 0x0000, 0xffff, "Financial document" }, + /* */ { 0x5f, 0x8001, 0x8001, "Your Money Matters document" }, + /* */ { 0x5f, 0x8002, 0x8002, "Home Refinancer document" }, + /*BIO*/ { 0x6b, 0x0000, 0xffff, "PC Transporter BIOS" }, + /*TDR*/ { 0x6d, 0x0000, 0xffff, "PC Transporter driver" }, + /*PRE*/ { 0x6e, 0x0000, 0xffff, "PC Transporter pre-boot" }, + /*HDV*/ { 0x6f, 0x0000, 0xffff, "PC Transporter volume" }, + /*WP */ { 0xa0, 0x0000, 0xffff, "WordPerfect document" }, + /*GSB*/ { 0xab, 0x0000, 0xffff, "Apple IIgs BASIC program" }, + /*TDF*/ { 0xac, 0x0000, 0xffff, "Apple IIgs BASIC TDF" }, + /*BDF*/ { 0xad, 0x0000, 0xffff, "Apple IIgs BASIC data" }, + /*SRC*/ { 0xb0, 0x0000, 0xffff, "Apple IIgs source code" }, + /* */ { 0xb0, 0x0001, 0x0001, "APW Text file" }, + /* */ { 0xb0, 0x0003, 0x0003, "APW 65816 Assembly source code" }, + /* */ { 0xb0, 0x0005, 0x0005, "ORCA/Pascal source code" }, + /* */ { 0xb0, 0x0006, 0x0006, "APW command file" }, + /* */ { 0xb0, 0x0008, 0x0008, "ORCA/C source code" }, + /* */ { 0xb0, 0x0009, 0x0009, "APW Linker command file" }, + /* */ { 0xb0, 0x000a, 0x000a, "APW C source code" }, + /* */ { 0xb0, 0x000c, 0x000c, "ORCA/Desktop command file" }, + /* */ { 0xb0, 0x0015, 0x0015, "APW Rez source file" }, + /* */ { 0xb0, 0x0017, 0x0017, "Installer script" }, + /* */ { 0xb0, 0x001e, 0x001e, "TML Pascal source code" }, + /* */ { 0xb0, 0x0116, 0x0116, "ORCA/Disassembler script" }, + /* */ { 0xb0, 0x0503, 0x0503, "SDE Assembler source code" }, + /* */ { 0xb0, 0x0506, 0x0506, "SDE command script" }, + /* */ { 0xb0, 0x0601, 0x0601, "Nifty List data" }, + /* */ { 0xb0, 0x0719, 0x0719, "PostScript file" }, + /*OBJ*/ { 0xb1, 0x0000, 0xffff, "Apple IIgs object code" }, + /*LIB*/ { 0xb2, 0x0000, 0xffff, "Apple IIgs Library file" }, + /*S16*/ { 0xb3, 0x0000, 0xffff, "GS/OS application" }, + /*RTL*/ { 0xb4, 0x0000, 0xffff, "GS/OS run-time library" }, + /*EXE*/ { 0xb5, 0x0000, 0xffff, "GS/OS shell application" }, + /*PIF*/ { 0xb6, 0x0000, 0xffff, "Permanent initialization file" }, + /*TIF*/ { 0xb7, 0x0000, 0xffff, "Temporary initialization file" }, + /*NDA*/ { 0xb8, 0x0000, 0xffff, "New desk accessory" }, + /*CDA*/ { 0xb9, 0x0000, 0xffff, "Classic desk accessory" }, + /*TOL*/ { 0xba, 0x0000, 0xffff, "Tool" }, + /*DVR*/ { 0xbb, 0x0000, 0xffff, "Apple IIgs device driver file" }, + /* */ { 0xbb, 0x7e01, 0x7e01, "GNO/ME terminal device driver" }, + /* */ { 0xbb, 0x7f01, 0x7f01, "GTv videodisc serial driver" }, + /* */ { 0xbb, 0x7f02, 0x7f02, "GTv videodisc game port driver" }, + /*LDF*/ { 0xbc, 0x0000, 0xffff, "Load file (generic)" }, + /* */ { 0xbc, 0x4001, 0x4001, "Nifty List module" }, + /* */ { 0xbc, 0xc001, 0xc001, "Nifty List module" }, + /* */ { 0xbc, 0x4002, 0x4002, "Super Info module" }, + /* */ { 0xbc, 0xc002, 0xc002, "Super Info module" }, + /* */ { 0xbc, 0x4004, 0x4004, "Twilight document" }, + /* */ { 0xbc, 0xc004, 0xc004, "Twilight document" }, + /* */ { 0xbc, 0x4006, 0x4006, "Foundation resource editor" }, + /* */ { 0xbc, 0xc006, 0xc006, "Foundation resource editor" }, + /* */ { 0xbc, 0x4007, 0x4007, "HyperStudio new button action" }, + /* */ { 0xbc, 0xc007, 0xc007, "HyperStudio new button action" }, + /* */ { 0xbc, 0x4008, 0x4008, "HyperStudio screen transition" }, + /* */ { 0xbc, 0xc008, 0xc008, "HyperStudio screen transition" }, + /* */ { 0xbc, 0x4009, 0x4009, "DreamGrafix module" }, + /* */ { 0xbc, 0xc009, 0xc009, "DreamGrafix module" }, + /* */ { 0xbc, 0x400a, 0x400a, "HyperStudio Extra utility" }, + /* */ { 0xbc, 0xc00a, 0xc00a, "HyperStudio Extra utility" }, + /* */ { 0xbc, 0x400f, 0x400f, "HardPressed module" }, + /* */ { 0xbc, 0xc00f, 0xc00f, "HardPressed module" }, + /* */ { 0xbc, 0x4010, 0x4010, "Graphic Exchange translator" }, + /* */ { 0xbc, 0xc010, 0xc010, "Graphic Exchange translator" }, + /* */ { 0xbc, 0x4011, 0x4011, "Desktop Enhancer blanker" }, + /* */ { 0xbc, 0xc011, 0xc011, "Desktop Enhancer blanker" }, + /* */ { 0xbc, 0x4083, 0x4083, "Marinetti link layer module" }, + /* */ { 0xbc, 0xc083, 0xc083, "Marinetti link layer module" }, + /*FST*/ { 0xbd, 0x0000, 0xffff, "GS/OS File System Translator" }, + /*DOC*/ { 0xbf, 0x0000, 0xffff, "GS/OS document" }, + /*PNT*/ { 0xc0, 0x0000, 0xffff, "Packed super hi-res picture" }, + /* */ { 0xc0, 0x0000, 0x0000, "Paintworks packed picture" }, + /* */ { 0xc0, 0x0001, 0x0001, "Packed super hi-res image" }, + /* */ { 0xc0, 0x0002, 0x0002, "Apple Preferred Format picture" }, + /* */ { 0xc0, 0x0003, 0x0003, "Packed QuickDraw II PICT file" }, + /* */ { 0xc0, 0x0080, 0x0080, "TIFF document" }, + /* */ { 0xc0, 0x0081, 0x0081, "JFIF (JPEG) document" }, + /* */ { 0xc0, 0x8001, 0x8001, "GTv background image" }, + /* */ { 0xc0, 0x8005, 0x8005, "DreamGrafix document" }, + /* */ { 0xc0, 0x8006, 0x8006, "GIF document" }, + /*PIC*/ { 0xc1, 0x0000, 0xffff, "Super hi-res picture" }, + /* */ { 0xc1, 0x0000, 0x0000, "Super hi-res screen image" }, + /* */ { 0xc1, 0x0001, 0x0001, "QuickDraw PICT file" }, + /* */ { 0xc1, 0x0002, 0x0002, "Super hi-res 3200-color screen image" }, + /* */ { 0xc1, 0x8001, 0x8001, "Allison raw image doc" }, + /* */ { 0xc1, 0x8002, 0x8002, "ThunderScan image doc" }, + /* */ { 0xc1, 0x8003, 0x8003, "DreamGrafix document" }, + /*ANI*/ { 0xc2, 0x0000, 0xffff, "Paintworks animation" }, + /*PAL*/ { 0xc3, 0x0000, 0xffff, "Paintworks palette" }, + /*OOG*/ { 0xc5, 0x0000, 0xffff, "Object-oriented graphics" }, + /* */ { 0xc5, 0x8000, 0x8000, "Draw Plus document" }, + /* */ { 0xc5, 0xc000, 0xc000, "DYOH architecture doc" }, + /* */ { 0xc5, 0xc001, 0xc001, "DYOH predrawn objects" }, + /* */ { 0xc5, 0xc002, 0xc002, "DYOH custom objects" }, + /* */ { 0xc5, 0xc003, 0xc003, "DYOH clipboard" }, + /* */ { 0xc5, 0xc004, 0xc004, "DYOH interiors document" }, + /* */ { 0xc5, 0xc005, 0xc005, "DYOH patterns" }, + /* */ { 0xc5, 0xc006, 0xc006, "DYOH landscape document" }, + /* */ { 0xc5, 0xc007, 0xc007, "PyWare Document" }, + /*SCR*/ { 0xc6, 0x0000, 0xffff, "Script" }, + /* */ { 0xc6, 0x8001, 0x8001, "Davex 8 script" }, + /* */ { 0xc6, 0x8002, 0x8002, "Universe Master backup script" }, + /* */ { 0xc6, 0x8003, 0x8003, "Universe Master Chain script" }, + /*CDV*/ { 0xc7, 0x0000, 0xffff, "Control Panel document" }, + /*FON*/ { 0xc8, 0x0000, 0xffff, "Font" }, + /* */ { 0xc8, 0x0000, 0x0000, "Font (Standard Apple IIgs QuickDraw II Font)" }, + /* */ { 0xc8, 0x0001, 0x0001, "TrueType font resource" }, + /* */ { 0xc8, 0x0008, 0x0008, "Postscript font resource" }, + /* */ { 0xc8, 0x0081, 0x0081, "TrueType font file" }, + /* */ { 0xc8, 0x0088, 0x0088, "Postscript font file" }, + /*FND*/ { 0xc9, 0x0000, 0xffff, "Finder data" }, + /*ICN*/ { 0xca, 0x0000, 0xffff, "Icons" }, + /*MUS*/ { 0xd5, 0x0000, 0xffff, "Music sequence" }, + /* */ { 0xd5, 0x0000, 0x0000, "Music Construction Set song" }, + /* */ { 0xd5, 0x0001, 0x0001, "MIDI Synth sequence" }, + /* */ { 0xd5, 0x0007, 0x0007, "SoundSmith document" }, + /* */ { 0xd5, 0x8002, 0x8002, "Diversi-Tune sequence" }, + /* */ { 0xd5, 0x8003, 0x8003, "Master Tracks Jr. sequence" }, + /* */ { 0xd5, 0x8004, 0x8004, "Music Writer document" }, + /* */ { 0xd5, 0x8005, 0x8005, "Arcade King Super music" }, + /* */ { 0xd5, 0x8006, 0x8006, "Music Composer file" }, + /*INS*/ { 0xd6, 0x0000, 0xffff, "Instrument" }, + /* */ { 0xd6, 0x0000, 0x0000, "Music Construction Set instrument" }, + /* */ { 0xd6, 0x0001, 0x0001, "MIDI Synth instrument" }, + /* */ { 0xd6, 0x8002, 0x8002, "Diversi-Tune instrument" }, + /*MDI*/ { 0xd7, 0x0000, 0xffff, "MIDI data" }, + /* */ { 0xd7, 0x0000, 0x0000, "MIDI standard data" }, + /* */ { 0xd7, 0x0080, 0x0080, "MIDI System Exclusive data" }, + /* */ { 0xd7, 0x8001, 0x8001, "MasterTracks Pro Sysex file" }, + /*SND*/ { 0xd8, 0x0000, 0xffff, "Sampled sound" }, + /* */ { 0xd8, 0x0000, 0x0000, "Audio IFF document" }, + /* */ { 0xd8, 0x0001, 0x0001, "AIFF-C document" }, + /* */ { 0xd8, 0x0002, 0x0002, "ASIF instrument" }, + /* */ { 0xd8, 0x0003, 0x0003, "Sound resource file" }, + /* */ { 0xd8, 0x0004, 0x0004, "MIDI Synth wave data" }, + /* */ { 0xd8, 0x8001, 0x8001, "HyperStudio sound" }, + /* */ { 0xd8, 0x8002, 0x8002, "Arcade King Super sound" }, + /* */ { 0xd8, 0x8003, 0x8003, "SoundOff! sound bank" }, + /*DBM*/ { 0xdb, 0x0000, 0xffff, "DB Master document" }, + /* */ { 0xdb, 0x0001, 0x0001, "DB Master document" }, + /*???*/ { 0xdd, 0x0000, 0xffff, "DDD Deluxe archive" }, // unofficial + /*LBR*/ { 0xe0, 0x0000, 0xffff, "Archival library" }, + /* */ { 0xe0, 0x0000, 0x0000, "ALU library" }, + /* */ { 0xe0, 0x0001, 0x0001, "AppleSingle file" }, + /* */ { 0xe0, 0x0002, 0x0002, "AppleDouble header file" }, + /* */ { 0xe0, 0x0003, 0x0003, "AppleDouble data file" }, + /* */ { 0xe0, 0x0004, 0x0004, "Archiver archive" }, + /* */ { 0xe0, 0x0005, 0x0005, "DiskCopy 4.2 disk image" }, + /* */ { 0xe0, 0x0100, 0x0100, "Apple 5.25 disk image" }, + /* */ { 0xe0, 0x0101, 0x0101, "Profile 5MB disk image" }, + /* */ { 0xe0, 0x0102, 0x0102, "Profile 10MB disk image" }, + /* */ { 0xe0, 0x0103, 0x0103, "Apple 3.5 disk image" }, + /* */ { 0xe0, 0x0104, 0x0104, "SCSI device image" }, + /* */ { 0xe0, 0x0105, 0x0105, "SCSI hard disk image" }, + /* */ { 0xe0, 0x0106, 0x0106, "SCSI tape image" }, + /* */ { 0xe0, 0x0107, 0x0107, "SCSI CD-ROM image" }, + /* */ { 0xe0, 0x010e, 0x010e, "RAM disk image" }, + /* */ { 0xe0, 0x010f, 0x010f, "ROM disk image" }, + /* */ { 0xe0, 0x0110, 0x0110, "File server image" }, + /* */ { 0xe0, 0x0113, 0x0113, "Hard disk image" }, + /* */ { 0xe0, 0x0114, 0x0114, "Floppy disk image" }, + /* */ { 0xe0, 0x0115, 0x0115, "Tape image" }, + /* */ { 0xe0, 0x011e, 0x011e, "AppleTalk file server image" }, + /* */ { 0xe0, 0x0120, 0x0120, "DiskCopy 6 disk image" }, + /* */ { 0xe0, 0x0130, 0x0130, "Universal Disk Image file" }, + /* */ { 0xe0, 0x8000, 0x8000, "Binary II file" }, + /* */ { 0xe0, 0x8001, 0x8001, "AppleLink ACU document" }, + /* */ { 0xe0, 0x8002, 0x8002, "ShrinkIt (NuFX) document" }, + /* */ { 0xe0, 0x8003, 0x8003, "Universal Disk Image file" }, + /* */ { 0xe0, 0x8004, 0x8004, "Davex archived volume" }, + /* */ { 0xe0, 0x8006, 0x8006, "EZ Backup Saveset doc" }, + /* */ { 0xe0, 0x8007, 0x8007, "ELS DOS 3.3 volume" }, + /* */ { 0xe0, 0x8008, 0x8008, "UtilityWorks document" }, + /* */ { 0xe0, 0x800a, 0x800a, "Replicator document" }, + /* */ { 0xe0, 0x800b, 0x800b, "AutoArk compressed document" }, + /* */ { 0xe0, 0x800d, 0x800d, "HardPressed compressed data (data fork)" }, + /* */ { 0xe0, 0x800e, 0x800e, "HardPressed compressed data (rsrc fork)" }, + /* */ { 0xe0, 0x800f, 0x800f, "HardPressed compressed data (both forks)" }, + /* */ { 0xe0, 0x8010, 0x8010, "LHA archive" }, + /*ATK*/ { 0xe2, 0x0000, 0xffff, "AppleTalk data" }, + /* */ { 0xe2, 0xffff, 0xffff, "EasyMount document" }, + /*R16*/ { 0xee, 0x0000, 0xffff, "EDASM 816 relocatable file" }, + /*PAS*/ { 0xef, 0x0000, 0xffff, "Pascal area" }, + /*CMD*/ { 0xf0, 0x0000, 0xffff, "BASIC command" }, + /*???*/ { 0xf1, 0x0000, 0xffff, "User type #1" }, + /*???*/ { 0xf2, 0x0000, 0xffff, "User type #2" }, + /*???*/ { 0xf3, 0x0000, 0xffff, "User type #3" }, + /*???*/ { 0xf4, 0x0000, 0xffff, "User type #4" }, + /*???*/ { 0xf5, 0x0000, 0xffff, "User type #5" }, + /*???*/ { 0xf6, 0x0000, 0xffff, "User type #6" }, + /*???*/ { 0xf7, 0x0000, 0xffff, "User type #7" }, + /*???*/ { 0xf8, 0x0000, 0xffff, "User type #8" }, + /*OS */ { 0xf9, 0x0000, 0xffff, "GS/OS system file" }, + /*OS */ { 0xfa, 0x0000, 0xffff, "Integer BASIC program" }, + /*OS */ { 0xfb, 0x0000, 0xffff, "Integer BASIC variables" }, + /*OS */ { 0xfc, 0x0000, 0xffff, "AppleSoft BASIC program" }, + /*OS */ { 0xfd, 0x0000, 0xffff, "AppleSoft BASIC variables" }, + /*OS */ { 0xfe, 0x0000, 0xffff, "Relocatable code" }, + /*OS */ { 0xff, 0x0000, 0xffff, "ProDOS 8 application" }, +}; + +/* + * Find an entry in the type description table that matches both file type and + * aux type. If no match is found, nil is returned. + */ +/*static*/ const char* +PathProposal::FileTypeDescription(long fileType, long auxType) +{ + int i; + + for (i = NELEM(gTypeDescriptions)-1; i >= 0; i--) { + if (fileType == gTypeDescriptions[i].fileType && + auxType >= gTypeDescriptions[i].minAuxType && + auxType <= gTypeDescriptions[i].maxAuxType) + { + return gTypeDescriptions[i].descr; + } + } + + return nil; +} + + +/* + * =========================================================================== + * Filename/filetype conversion + * =========================================================================== + */ + +/* + * Convert a pathname pulled out of an archive to something suitable for the + * local filesystem. + * + * The new pathname may be shorter (because characters were removed) or + * longer (if we add a "#XXYYYYZ" extension or replace chars with '%' codes). + */ +void +PathProposal::ArchiveToLocal(void) +{ + char* pathBuf; + const char* startp; + const char* endp; + char* dstp; + int newBufLen; + + /* init output fields */ + fLocalFssep = kLocalFssep; + fLocalPathName = ""; + + /* + * Set up temporary buffer space. The maximum possible expansion + * requires converting all chars to '%' codes and adding the longest + * possible preservation string. + */ + newBufLen = fStoredPathName.GetLength()*3 + kMaxPathGrowth +1; + pathBuf = fLocalPathName.GetBuffer(newBufLen); + ASSERT(pathBuf != nil); + + startp = fStoredPathName; + dstp = pathBuf; + while (*startp == fStoredFssep) { + /* ignore leading path sep; always extract to current dir */ + startp++; + } + + /* normalize all directory components and the filename component */ + while (startp != nil) { + endp = nil; + if (fStoredFssep != '\0') + endp = strchr(startp, fStoredFssep); + if (endp != nil && endp == startp) { + /* zero-length subdir component */ + WMSG1("WARNING: zero-length subdir component in '%s'\n", startp); + startp++; + continue; + } + if (endp != nil) { + /* normalize directory component */ + NormalizeDirectoryName(startp, endp - startp, + fStoredFssep, &dstp, newBufLen); + + *dstp++ = fLocalFssep; + + startp = endp +1; + } else { + /* normalize filename component */ + NormalizeFileName(startp, strlen(startp), + fStoredFssep, &dstp, newBufLen); + *dstp++ = '\0'; + + /* add/replace extension if necessary */ + char extBuf[kMaxPathGrowth +1] = ""; + if (fPreservation) { + AddPreservationString(pathBuf, extBuf); + } else if (fThreadKind == GenericEntry::kRsrcThread) { + /* add this in lieu of the preservation extension */ + strcat(pathBuf, kResourceStr); + } + if (fAddExtension) { + AddTypeExtension(pathBuf, extBuf); + } + ASSERT(strlen(extBuf) <= kMaxPathGrowth); + strcat(pathBuf, extBuf); + + startp = nil; /* we're done, break out of loop */ + } + } + + /* check for overflow */ + ASSERT(dstp - pathBuf <= newBufLen); + + /* + * If "junk paths" is set, drop everything but the last component. + */ + if (fJunkPaths) { + char* lastFssep; + lastFssep = strrchr(pathBuf, fLocalFssep); + if (lastFssep != nil) { + ASSERT(*(lastFssep+1) != '\0'); /* should already have been caught*/ + memmove(pathBuf, lastFssep+1, strlen(lastFssep+1)+1); + } + } + + fLocalPathName.ReleaseBuffer(); +} + +#if defined(WINDOWS_LIKE) +/* + * You can't create files or directories with these names on a FAT filesystem, + * because they're MS-DOS "device special files". + * + * The list comes from the Linux kernel's fs/msdos/namei.c. + * + * The trick is that the name can't start with any of these. That could mean + * that the name is just "aux", or it could be "aux.this.txt". + */ +static const char* gFatReservedNames3[] = { + "CON", "PRN", "NUL", "AUX", nil +}; +static const char* gFatReservedNames4[] = { + "LPT1", "LPT2", "LPT3", "LPT4", "COM1", "COM2", "COM3", "COM4", nil +}; + +/* + * Filename normalization for Win32 filesystems. You can't use [ \/:*?"<>| ] + * or control characters, and it's probably unwise to use high-ASCII stuff. + */ +void +PathProposal::Win32NormalizeFileName(const char* srcp, long srcLen, + char fssep, char** pDstp, long dstLen) +{ + char* dstp = *pDstp; + const char* startp = srcp; + static const char* kInvalid = "\\/:*?\"<>|"; + + /* match on "aux" or "aux.blah" */ + if (srcLen >= 3) { + const char** ppcch; + + for (ppcch = gFatReservedNames3; *ppcch != nil; ppcch++) { + if (strncasecmp(srcp, *ppcch, 3) == 0 && + (srcp[3] == '.' || srcLen == 3)) + { + WMSG1("--- fixing '%s'\n", *ppcch); + if (fPreservation) { + *dstp++ = kForeignIndic; + *dstp++ = '0'; + *dstp++ = '0'; + } else + *dstp++ = '_'; + break; + } + } + } + if (srcLen >= 4) { + const char** ppcch; + + for (ppcch = gFatReservedNames4; *ppcch != nil; ppcch++) { + if (strncasecmp(srcp, *ppcch, 4) == 0 && + (srcp[4] == '.' || srcLen == 4)) + { + WMSG1("--- fixing '%s'\n", *ppcch); + if (fPreservation) { + *dstp++ = kForeignIndic; + *dstp++ = '0'; + *dstp++ = '0'; + } else + *dstp++ = '_'; + break; + } + } + } + + + while (srcLen--) { /* don't go until null found! */ + ASSERT(*srcp != '\0'); + + if (*srcp == kForeignIndic) { + /* change '%' to "%%" */ + if (fPreservation) + *dstp++ = *srcp; + *dstp++ = *srcp++; + } else if (strchr(kInvalid, *srcp) != nil || + *srcp < 0x20 || *srcp >= 0x7f) + { + /* change invalid char to "%2f" or '_' */ + if (fPreservation) { + *dstp++ = kForeignIndic; + *dstp++ = HexConv(*srcp >> 4 & 0x0f); + *dstp++ = HexConv(*srcp & 0x0f); + } else { + *dstp++ = '_'; + } + srcp++; + } else { + /* no need to fiddle with it */ + *dstp++ = *srcp++; + } + } + + *dstp = '\0'; /* end the string, but don't advance past the null */ + ASSERT(*pDstp - dstp <= dstLen); /* make sure we didn't overflow */ + *pDstp = dstp; +} +#endif + + +/* + * Normalize a file name to local filesystem conventions. The input + * is quite possibly *NOT* null-terminated, since it may represent a + * substring of a full pathname. Use "srcLen". + * + * The output filename is copied to *pDstp, which is advanced forward. + * + * The output buffer must be able to hold 3x the original string length. + */ +void +PathProposal::NormalizeFileName(const char* srcp, long srcLen, + char fssep, char** pDstp, long dstLen) +{ + ASSERT(srcp != nil); + ASSERT(srcLen > 0); + ASSERT(dstLen > srcLen); + ASSERT(pDstp != nil); + ASSERT(*pDstp != nil); + +#if defined(UNIX_LIKE) + UNIXNormalizeFileName(srcp, srcLen, fssep, pDstp, dstLen); +#elif defined(WINDOWS_LIKE) + Win32NormalizeFileName(srcp, srcLen, fssep, pDstp, dstLen); +#else + #error "port this" +#endif +} + + +/* + * Normalize a directory name to local filesystem conventions. + */ +void +PathProposal::NormalizeDirectoryName(const char* srcp, long srcLen, + char fssep, char** pDstp, long dstLen) +{ + /* in general, directories and filenames are the same */ + ASSERT(fssep > ' ' && fssep < 0x7f); + NormalizeFileName(srcp, srcLen, fssep, pDstp, dstLen); +} + + +/* + * Add a preservation string. + * + * "pathBuf" is assumed to have enough space to hold the current path + * plus kMaxPathGrowth more. It will be modified in place. + */ +void +PathProposal::AddPreservationString(const char* pathBuf, char* extBuf) +{ + char* cp; + + ASSERT(pathBuf != nil); + ASSERT(extBuf != nil); + ASSERT(fPreservation); + + cp = extBuf + strlen(extBuf); + + /* + * Cons up a preservation string. On some platforms "sprintf" doesn't + * return the #of characters written, so we add it up manually. + */ + if (fFileType < 0x100 && fAuxType < 0x10000) { + sprintf(cp, "%c%02lx%04lx", kPreserveIndic, fFileType, fAuxType); + cp += 7; + } else { + sprintf(cp, "%c%08lx%08lx", kPreserveIndic, fFileType, fAuxType); + cp += 17; + } + + if (fThreadKind == GenericEntry::kRsrcThread) + *cp++ = kResourceFlag; + else if (fThreadKind == GenericEntry::kDiskImageThread) + *cp++ = kDiskImageFlag; + + + /* make sure it's terminated */ + *cp = '\0'; +} + +/* + * Add a ".foo" extension to the filename. + * + * We either need to retain the existing extension (possibly obscured by file + * type preservation) or append an extension based on the ProDOS file type. + */ +void +PathProposal::AddTypeExtension(const char* pathBuf, char* extBuf) +{ + const char* pPathExt = nil; + const char* pWantedExt = nil; + const char* pTypeExt = nil; + char* end; + char* cp; + + cp = extBuf + strlen(extBuf); + + /* + * Find extension in the local filename that we've prepared so far. + * Note FindExtension guarantees there's at least one char after '.'. + */ + pPathExt = FindExtension(pathBuf, fLocalFssep); + if (pPathExt == nil) { + /* + * There's no extension on the filename. Use the standard + * ProDOS type, if one exists for this entry. We don't use + * the table if it's NON, "???", or a hex value. + */ + if (fFileType) { + pTypeExt = FileTypeString(fFileType); + if (pTypeExt[0] == '?' || pTypeExt[0] == '$') + pTypeExt = nil; + } + } else { + pPathExt++; // skip leading '.' + } + + /* + * Figure out what extension we want this file to have. Files of type + * text are *always* ".TXT", and our extracted disk images are always + * ".PO". If it's not one of these two, we either retain the file's + * original extension, or generate one for it from the ProDOS file type. + */ + if (fFileType == 0x04) + pWantedExt = "TXT"; + else if (fThreadKind == GenericEntry::kDiskImageThread) + pWantedExt = "PO"; + else { + /* + * We want to use the extension currently on the file, if it has one. + * If not, use the one from the file type. + */ + if (pPathExt != nil) { + pWantedExt = pPathExt; + } else { + pWantedExt = pTypeExt; + } + } + /* pWantedExt != nil unless we failed to find a pTypeExt */ + + + /* + * Now we know which one we want. Figure out if we want to add it. + */ + if (pWantedExt != nil) { + if (extBuf[0] == '\0' && pPathExt != nil && + strcasecmp(pPathExt, pWantedExt) == 0) + { + /* don't add an extension that's already there */ + pWantedExt = nil; + goto know_ext; + } + + if (strlen(pWantedExt) >= kMaxExtLen) { + /* too long, forget it */ + pWantedExt = nil; + goto know_ext; + } + + /* if it's strictly decimal-numeric, don't use it (.1, .2, etc) */ + (void) strtoul(pWantedExt, &end, 10); + if (*end == '\0') { + pWantedExt = nil; + goto know_ext; + } + + /* if '#' appears in it, don't use it -- it'll confuse us */ + //WMSG2("LOOKING FOR '%c' in '%s'\n", kPreserveIndic, ccp); + const char* ccp = pWantedExt; + while (*ccp != '\0') { + if (*ccp == kPreserveIndic) { + pWantedExt = nil; + goto know_ext; + } + ccp++; + } + } +know_ext: + + /* + * If pWantedExt is non-nil, it points to a filename extension without + * the leading '.'. + */ + if (pWantedExt != nil) { + *cp++ = kFilenameExtDelim; + strcpy(cp, pWantedExt); + //cp += strlen(pWantedExt); + } +} + + +/* + * =========================================================================== + * File type restoration + * =========================================================================== + */ + +typedef bool Boolean; + +/* + * Convert a local path into something suitable for storage in an archive. + * Type preservation strings are interpreted and stripped as appropriate. + * + * This does *not* do filesystem-specific normalization here. (It could, but + * it's better to leave that for later so we can do uniqueification.) + * + * In the current implementation, fStoredPathName will always get smaller, + * but it would be unwise to rely on that. + */ +void +PathProposal::LocalToArchive(const AddFilesDialog* pAddOpts) +{ + Boolean wasPreserved; + Boolean doJunk = false; + Boolean adjusted; + char slashDotDotSlash[5] = "_.._"; + + fStoredPathName = fLocalPathName; + char* livePathStr = fStoredPathName.GetBuffer(0); + + fStoredFssep = kDefaultStoredFssep; + + /* convert '/' to '\' */ + ReplaceFssep(livePathStr, + kAltLocalFssep, //NState_GetAltSystemPathSeparator(pState), + kLocalFssep, //NState_GetSystemPathSeparator(pState), + kLocalFssep); //NState_GetSystemPathSeparator(pState)); + + /* + * Check for file type preservation info in the filename. If present, + * set the file type values and truncate the filename. + */ + wasPreserved = false; + if (pAddOpts->fTypePreservation == AddFilesDialog::kPreserveTypes || + pAddOpts->fTypePreservation == AddFilesDialog::kPreserveAndExtend) + { + wasPreserved = ExtractPreservationString(livePathStr); + } + + /* + * Do a "denormalization" pass, where we convert invalid chars (such + * as '/') from percent-codes back to 8-bit characters. The filename + * will always be the same size or smaller, so we can do it in place. + */ + if (wasPreserved) + DenormalizePath(livePathStr); + + /* + * If we're in "extended" mode, and the file wasn't preserved, take a + * guess at what the file type should be based on the file extension. + */ + if (!wasPreserved && + pAddOpts->fTypePreservation == AddFilesDialog::kPreserveAndExtend) + { + InterpretExtension(livePathStr); + } + + if (fStripDiskImageSuffix) + StripDiskImageSuffix(livePathStr); + + /* + * Strip bad chars off the front of the pathname. Every time we + * remove one thing we potentially expose another, so we have to + * loop until it's sanitized. + * + * The outer loop isn't really necessary under Win32, because you'd + * need to do something like ".\\foo", which isn't allowed. UNIX + * silently allows ".//foo", so this is a problem there. (We could + * probably do away with the inner loops, but those were already + * written when I saw the larger problem.) + */ + do { + adjusted = false; + + /* + * Check for other unpleasantness, such as a leading fssep. + */ + ASSERT(kLocalFssep != '\0'); + while (livePathStr[0] == kLocalFssep) { + /* slide it down, len is (strlen +1), -1 (dropping first char)*/ + memmove(livePathStr, livePathStr+1, strlen(livePathStr)); + adjusted = true; + } + + /* + * Remove leading "./". + */ + while (livePathStr[0] == '.' && livePathStr[1] == kLocalFssep) + { + /* slide it down, len is (strlen +1) -2 (dropping two chars) */ + memmove(livePathStr, livePathStr+2, strlen(livePathStr)-1); + adjusted = true; + } + } while (adjusted); + + /* + * If there's a "/../" present anywhere in the name, junk everything + * but the filename. + * + * This won't catch "foo/bar/..", but that should've been caught as + * a directory anyway. + */ + slashDotDotSlash[0] = kLocalFssep; + slashDotDotSlash[3] = kLocalFssep; + if ((livePathStr[0] == '.' && livePathStr[1] == '.') || + (strstr(livePathStr, slashDotDotSlash) != nil)) + { + WMSG1("Found dot dot in '%s', keeping only filename\n", livePathStr); + doJunk = true; + } + + /* + * Scan for and remove "/./" and trailing "/.". They're filesystem + * no-ops that work just fine under Win32 and UNIX but could confuse + * a IIgs. (Of course, the user could just omit them from the pathname.) + */ + /* TO DO 20030208 */ + + /* + * If "junk paths" is set, drop everything before the last fssep char. + */ + if (pAddOpts->fStripFolderNames || doJunk) { + char* lastFssep; + lastFssep = strrchr(livePathStr, kLocalFssep); + if (lastFssep != nil) { + ASSERT(*(lastFssep+1) != '\0'); /* should already have been caught*/ + memmove(livePathStr, lastFssep+1, strlen(lastFssep+1)+1); + } + } + + /* + * Finally, substitute our generally-accepted path separator in place of + * the local one, stomping on anything with a ':' in it as we do. The + * goal is to avoid having "subdir:foo/bar" turn into "subdir/foo/bar", + * so we change it to "subdirXfoo:bar". Were we a general-purpose + * archiver, this might be a mistake, but we're not. NuFX doesn't really + * give us a choice. + */ + ReplaceFssep(livePathStr, kLocalFssep, + PathProposal::kDefaultStoredFssep, 'X'); + + /* let the CString manage itself again */ + fStoredPathName.ReleaseBuffer(); +} + +/* + * Replace "oldc" with "newc". If we find an instance of "newc" already + * in the string, replace it with "newSubst". + */ +void +PathProposal::ReplaceFssep(char* str, char oldc, char newc, char newSubst) +{ + while (*str != '\0') { + if (*str == oldc) + *str = newc; + else if (*str == newc) + *str = newSubst; + str++; + } +} + + +/* + * Try to figure out what file type is associated with a filename extension. + * + * This checks the standard list of ProDOS types (which should catch things + * like "TXT" and "BIN") and the separate list of recognized extensions. + */ +void +PathProposal::LookupExtension(const char* ext) +{ + char uext3[4]; + int i, extLen; + + extLen = strlen(ext); + ASSERT(extLen > 0); + + /* + * First step is to try to find it in the recognized types list. + */ + for (i = 0; i < NELEM(gRecognizedExtensions); i++) { + if (strcasecmp(ext, gRecognizedExtensions[i].label) == 0) { + fFileType = gRecognizedExtensions[i].fileType; + fAuxType = gRecognizedExtensions[i].auxType; + goto bail; + } + } + + /* + * Second step is to try to find it in the ProDOS types list. + * + * The extension is converted to upper case and padded with spaces. + * + * [do we want to obstruct matching on things like '$f7' here?] + */ + if (extLen <= 3) { + for (i = 2; i >= extLen; i--) + uext3[i] = ' '; + for ( ; i >= 0; i--) + uext3[i] = toupper(ext[i]); + uext3[3] = '\0'; + + /*printf("### converted '%s' to '%s'\n", ext, uext3);*/ + + for (i = 0; i < NELEM(gFileTypeNames); i++) { + if (strcmp(uext3, gFileTypeNames[i]) == 0) { + fFileType = i; + goto bail; + } + } + } + +bail: + return; +} + +/* + * Try to associate some meaning with the file extension. + */ +void +PathProposal::InterpretExtension(const char* pathName) +{ + const char* pExt; + + ASSERT(pathName != nil); + + pExt = FindExtension(pathName, fLocalFssep); + if (pExt != nil) + LookupExtension(pExt+1); +} + + +/* + * Check to see if there's a preservation string on the filename. If so, + * set the filetype and auxtype information, and trim the preservation + * string off. + * + * We have to be careful not to trip on false-positive occurrences of '#' + * in the filename. + */ +Boolean +PathProposal::ExtractPreservationString(char* pathname) +{ + char numBuf[9]; + unsigned long fileType, auxType; + int threadMask; + char* pPreserve; + char* cp; + int digitCount; + + ASSERT(pathname != nil); + + pPreserve = strrchr(pathname, kPreserveIndic); + if (pPreserve == nil) + return false; + + /* count up the #of hex digits */ + digitCount = 0; + for (cp = pPreserve+1; *cp != '\0' && isxdigit((int)*cp); cp++) + digitCount++; + + /* extract the file and aux type */ + switch (digitCount) { + case 6: + /* ProDOS 1-byte type and 2-byte aux */ + memcpy(numBuf, pPreserve+1, 2); + numBuf[2] = 0; + fileType = strtoul(numBuf, &cp, 16); + ASSERT(cp == numBuf + 2); + + auxType = strtoul(pPreserve+3, &cp, 16); + ASSERT(cp == pPreserve + 7); + break; + case 16: + /* HFS 4-byte type and 4-byte creator */ + memcpy(numBuf, pPreserve+1, 8); + numBuf[8] = 0; + fileType = strtoul(numBuf, &cp, 16); + ASSERT(cp == numBuf + 8); + + auxType = strtoul(pPreserve+9, &cp, 16); + ASSERT(cp == pPreserve + 17); + break; + default: + /* not valid */ + return false; + } + + /* check for a threadID specifier */ + //threadID = kNuThreadIDDataFork; + threadMask = GenericEntry::kDataThread; + switch (*cp) { + case kResourceFlag: + //threadID = kNuThreadIDRsrcFork; + threadMask = GenericEntry::kRsrcThread; + cp++; + break; + case kDiskImageFlag: + //threadID = kNuThreadIDDiskImage; + threadMask = GenericEntry::kDiskImageThread; + cp++; + break; + default: + /* do nothing... yet */ + break; + } + + /* make sure we were the very last component */ + switch (*cp) { + case kFilenameExtDelim: /* redundant "-ee" extension */ + case '\0': /* end of string! */ + break; + default: + return false; + } + + /* truncate the original string, and return what we got */ + *pPreserve = '\0'; + fFileType = fileType; + fAuxType = auxType; + fThreadKind = threadMask; + //*pThreadID = threadID; + + return true; +} + + +/* + * Remove NuLib2's normalization magic (e.g. "%2f" for '/'). + * + * This always results in the filename staying the same length or getting + * smaller, so we can do it in place in the buffer. + */ +void +PathProposal::DenormalizePath(char* pathBuf) +{ + const char* srcp; + char* dstp; + char ch; + + srcp = pathBuf; + dstp = pathBuf; + + while (*srcp != '\0') { + if (*srcp == kForeignIndic) { + srcp++; + if (*srcp == kForeignIndic) { + *dstp++ = kForeignIndic; + srcp++; + } else if (isxdigit((int)*srcp)) { + ch = HexDigit(*srcp) << 4; + srcp++; + if (isxdigit((int)*srcp)) { + /* valid, output char */ + ch += HexDigit(*srcp); + *dstp++ = ch; + srcp++; + } else { + /* bogus '%' with trailing hex digit found! */ + *dstp++ = kForeignIndic; + *dstp++ = *(srcp-1); + } + } else { + /* bogus lone '%s' found! */ + *dstp++ = kForeignIndic; + } + + } else { + *dstp++ = *srcp++; + } + } + + *dstp = '\0'; + ASSERT(dstp <= srcp); +} + +/* + * Remove a disk image suffix. + * + * Useful when adding disk images directly from a .SDK or .2MG file. We + * don't want them to retain their original suffix. + */ +void +PathProposal::StripDiskImageSuffix(char* pathName) +{ + static const char diskExt[][4] = { + "SHK", "SDK", "IMG", "PO", "DO", "2MG", "DSK" + }; + char* pExt; + int i; + + pExt = (char*)FindExtension(pathName, fLocalFssep); + if (pExt == nil || pExt == pathName) + return; + + for (i = 0; i < NELEM(diskExt); i++) { + if (strcasecmp(pExt+1, diskExt[i]) == 0) { + WMSG2("Dropping '%s' from '%s'\n", pExt, pathName); + *pExt = '\0'; + return; + } + } +} diff --git a/app/FileNameConv.h b/app/FileNameConv.h index 6279582..60dc946 100644 --- a/app/FileNameConv.h +++ b/app/FileNameConv.h @@ -11,129 +11,129 @@ #include "GenericArchive.h" -#define kUnknownTypeStr "???" +#define kUnknownTypeStr "???" /* * Proposal for an output pathname, based on the contents of a GenericEntry. */ class PathProposal { public: - typedef GenericEntry::RecordKind RecordKind; - enum { - kDefaultStoredFssep = ':', - kLocalFssep = '\\', // PATH_SEP - kAltLocalFssep = '/' // PATH_SEP2 - }; + typedef GenericEntry::RecordKind RecordKind; + enum { + kDefaultStoredFssep = ':', + kLocalFssep = '\\', // PATH_SEP + kAltLocalFssep = '/' // PATH_SEP2 + }; - PathProposal(void) { - fStoredPathName = ":BOGUS:"; - fStoredFssep = '['; - fFileType = 256; - fAuxType = 65536; - fThreadKind = 0; + PathProposal(void) { + fStoredPathName = ":BOGUS:"; + fStoredFssep = '['; + fFileType = 256; + fAuxType = 65536; + fThreadKind = 0; - fLocalPathName = ":HOSED:"; - fLocalFssep = ']'; + fLocalPathName = ":HOSED:"; + fLocalFssep = ']'; - fPreservation = false; - fAddExtension = false; - fJunkPaths = false; - fStripDiskImageSuffix = false; - } - virtual ~PathProposal(void) {} + fPreservation = false; + fAddExtension = false; + fJunkPaths = false; + fStripDiskImageSuffix = false; + } + virtual ~PathProposal(void) {} - // init the "extract from archive" side from a GenericEntry struct - void Init(GenericEntry* pEntry) { - fStoredPathName = pEntry->GetPathName(); - fStoredFssep = pEntry->GetFssep(); - //if (fStoredFssep == '\0') // e.g. embedded DOS 3.3 volume - // fStoredFssep = kDefaultStoredFssep; - fFileType = pEntry->GetFileType(); - fAuxType = pEntry->GetAuxType(); - //fThreadKind set from SelectionEntry - // reset the "output" fields - fLocalPathName = ":HOSED:"; - fLocalFssep = ']'; - // I expect these to be as-yet unset; check it - ASSERT(!fPreservation); - ASSERT(!fAddExtension); - ASSERT(!fJunkPaths); - } + // init the "extract from archive" side from a GenericEntry struct + void Init(GenericEntry* pEntry) { + fStoredPathName = pEntry->GetPathName(); + fStoredFssep = pEntry->GetFssep(); + //if (fStoredFssep == '\0') // e.g. embedded DOS 3.3 volume + // fStoredFssep = kDefaultStoredFssep; + fFileType = pEntry->GetFileType(); + fAuxType = pEntry->GetAuxType(); + //fThreadKind set from SelectionEntry + // reset the "output" fields + fLocalPathName = ":HOSED:"; + fLocalFssep = ']'; + // I expect these to be as-yet unset; check it + ASSERT(!fPreservation); + ASSERT(!fAddExtension); + ASSERT(!fJunkPaths); + } - // init the "add to archive" side - void Init(const char* localPathName) { - //ASSERT(basePathName[strlen(basePathName)-1] != kLocalFssep); - //fLocalPathName = localPathName + strlen(basePathName)+1; - fLocalPathName = localPathName; - fLocalFssep = kLocalFssep; - // reset the "output" fields - fStoredPathName = ":HOSED:"; - fStoredFssep = '['; - fFileType = 0; - fAuxType = 0; - fThreadKind = GenericEntry::kDataThread; - // I expect these to be as-yet unset; check it - ASSERT(!fPreservation); - ASSERT(!fAddExtension); - ASSERT(!fJunkPaths); - } + // init the "add to archive" side + void Init(const char* localPathName) { + //ASSERT(basePathName[strlen(basePathName)-1] != kLocalFssep); + //fLocalPathName = localPathName + strlen(basePathName)+1; + fLocalPathName = localPathName; + fLocalFssep = kLocalFssep; + // reset the "output" fields + fStoredPathName = ":HOSED:"; + fStoredFssep = '['; + fFileType = 0; + fAuxType = 0; + fThreadKind = GenericEntry::kDataThread; + // I expect these to be as-yet unset; check it + ASSERT(!fPreservation); + ASSERT(!fAddExtension); + ASSERT(!fJunkPaths); + } - // Convert a partial pathname from the archive to a local partial path. - void ArchiveToLocal(void); - // Same thing, other direction. - void LocalToArchive(const AddFilesDialog* pAddOpts); + // Convert a partial pathname from the archive to a local partial path. + void ArchiveToLocal(void); + // Same thing, other direction. + void LocalToArchive(const AddFilesDialog* pAddOpts); - /* - * Fields for the "archive" side. - */ - // pathname from record or full pathname from disk image - CString fStoredPathName; - // filesystem separator char (or '\0' for things like DOS 3.3) - char fStoredFssep; - // file type, aux type, and what piece of the file this is - unsigned long fFileType; - unsigned long fAuxType; - int fThreadKind; // GenericEntry, e.g. kDataThread + /* + * Fields for the "archive" side. + */ + // pathname from record or full pathname from disk image + CString fStoredPathName; + // filesystem separator char (or '\0' for things like DOS 3.3) + char fStoredFssep; + // file type, aux type, and what piece of the file this is + unsigned long fFileType; + unsigned long fAuxType; + int fThreadKind; // GenericEntry, e.g. kDataThread - /* - * Fields for the "local" Side. - */ - // relative path of file for local filesystem - CString fLocalPathName; - // filesystem separator char for new path (always '\\' for us) - char fLocalFssep; + /* + * Fields for the "local" Side. + */ + // relative path of file for local filesystem + CString fLocalPathName; + // filesystem separator char for new path (always '\\' for us) + char fLocalFssep; - /* - * Flags. - */ - // filename/filetype preservation flags - bool fPreservation; - bool fAddExtension; - bool fJunkPaths; - bool fStripDiskImageSuffix; + /* + * Flags. + */ + // filename/filetype preservation flags + bool fPreservation; + bool fAddExtension; + bool fJunkPaths; + bool fStripDiskImageSuffix; - /* - * Misc utility functions. - */ - static const char* FileTypeString(unsigned long fileType); - static const char* FileTypeDescription(long fileType, long auxType); + /* + * Misc utility functions. + */ + static const char* FileTypeString(unsigned long fileType); + static const char* FileTypeDescription(long fileType, long auxType); private: - void Win32NormalizeFileName(const char* srcp, long srcLen, - char fssep, char** pDstp, long dstLen); - void NormalizeFileName(const char* srcp, long srcLen, - char fssep, char** pDstp, long dstLen); - void NormalizeDirectoryName(const char* srcp, long srcLen, - char fssep, char** pDstp, long dstLen); - void AddPreservationString(const char* pathBuf, char* extBuf); - void AddTypeExtension(const char* pathBuf, char* extBuf); + void Win32NormalizeFileName(const char* srcp, long srcLen, + char fssep, char** pDstp, long dstLen); + void NormalizeFileName(const char* srcp, long srcLen, + char fssep, char** pDstp, long dstLen); + void NormalizeDirectoryName(const char* srcp, long srcLen, + char fssep, char** pDstp, long dstLen); + void AddPreservationString(const char* pathBuf, char* extBuf); + void AddTypeExtension(const char* pathBuf, char* extBuf); - void ReplaceFssep(char* str, char oldc, char newc, char newSubst); - void LookupExtension(const char* ext); - bool ExtractPreservationString(char* pathName); - void InterpretExtension(const char* pathName); - void DenormalizePath(char* pathBuf); - void StripDiskImageSuffix(char* pathName); + void ReplaceFssep(char* str, char oldc, char newc, char newSubst); + void LookupExtension(const char* ext); + bool ExtractPreservationString(char* pathName); + void InterpretExtension(const char* pathName); + void DenormalizePath(char* pathBuf); + void StripDiskImageSuffix(char* pathName); }; #endif /*__FILENAMECONV__*/ \ No newline at end of file diff --git a/app/GenericArchive.cpp b/app/GenericArchive.cpp index 4f9ad76..0586a59 100644 --- a/app/GenericArchive.cpp +++ b/app/GenericArchive.cpp @@ -41,7 +41,7 @@ /* * =========================================================================== - * GenericEntry + * GenericEntry * =========================================================================== */ @@ -50,35 +50,35 @@ */ GenericEntry::GenericEntry(void) { - fPathName = nil; - fFileName = nil; - fFssep = '\0'; - fSubVolName = nil; - fDisplayName = nil; - fFileType = 0; - fAuxType = 0; - fAccess = 0; - fModWhen = kDateNone; - fCreateWhen = kDateNone; - fRecordKind = kRecordKindUnknown; - fFormatStr = "Unknown"; - fCompressedLen = 0; - //fUncompressedLen = 0; - fDataForkLen = fRsrcForkLen = 0; + fPathName = nil; + fFileName = nil; + fFssep = '\0'; + fSubVolName = nil; + fDisplayName = nil; + fFileType = 0; + fAuxType = 0; + fAccess = 0; + fModWhen = kDateNone; + fCreateWhen = kDateNone; + fRecordKind = kRecordKindUnknown; + fFormatStr = "Unknown"; + fCompressedLen = 0; + //fUncompressedLen = 0; + fDataForkLen = fRsrcForkLen = 0; - fSourceFS = DiskImg::kFormatUnknown; + fSourceFS = DiskImg::kFormatUnknown; - fHasDataFork = false; - fHasRsrcFork = false; - fHasDiskImage = false; - fHasComment = false; - fHasNonEmptyComment = false; + fHasDataFork = false; + fHasRsrcFork = false; + fHasDiskImage = false; + fHasComment = false; + fHasNonEmptyComment = false; - fIndex = -1; - fpPrev = nil; - fpNext = nil; + fIndex = -1; + fpPrev = nil; + fpNext = nil; - fDamaged = fSuspicious = false; + fDamaged = fSuspicious = false; } /* @@ -86,9 +86,9 @@ GenericEntry::GenericEntry(void) */ GenericEntry::~GenericEntry(void) { - delete[] fPathName; - delete[] fSubVolName; - delete[] fDisplayName; + delete[] fPathName; + delete[] fSubVolName; + delete[] fDisplayName; } /* @@ -97,74 +97,74 @@ GenericEntry::~GenericEntry(void) void GenericEntry::SetPathName(const char* path) { - ASSERT(path != nil && strlen(path) > 0); - if (fPathName != nil) - delete fPathName; - fPathName = new char[strlen(path)+1]; - strcpy(fPathName, path); - // nuke the derived fields - fFileName = nil; - fFileNameExtension = nil; - delete[] fDisplayName; - fDisplayName = nil; + ASSERT(path != nil && strlen(path) > 0); + if (fPathName != nil) + delete fPathName; + fPathName = new char[strlen(path)+1]; + strcpy(fPathName, path); + // nuke the derived fields + fFileName = nil; + fFileNameExtension = nil; + delete[] fDisplayName; + fDisplayName = nil; - /* - * Warning: to be 100% pedantically correct here, we should NOT do this - * if the fssep char is '_'. However, that may not have been set by - * the time we got here, so to do this "correctly" we'd need to delay - * the underscorage until the first GetPathName call. - */ - const Preferences* pPreferences = GET_PREFERENCES(); - if (pPreferences->GetPrefBool(kPrSpacesToUnder)) - SpacesToUnderscores(fPathName); + /* + * Warning: to be 100% pedantically correct here, we should NOT do this + * if the fssep char is '_'. However, that may not have been set by + * the time we got here, so to do this "correctly" we'd need to delay + * the underscorage until the first GetPathName call. + */ + const Preferences* pPreferences = GET_PREFERENCES(); + if (pPreferences->GetPrefBool(kPrSpacesToUnder)) + SpacesToUnderscores(fPathName); } const char* GenericEntry::GetFileName(void) { - ASSERT(fPathName != nil); - if (fFileName == nil) - fFileName = FilenameOnly(fPathName, fFssep); - return fFileName; + ASSERT(fPathName != nil); + if (fFileName == nil) + fFileName = FilenameOnly(fPathName, fFssep); + return fFileName; } const char* GenericEntry::GetFileNameExtension(void) { - ASSERT(fPathName != nil); - if (fFileNameExtension == nil) - fFileNameExtension = FindExtension(fPathName, fFssep); - return fFileNameExtension; + ASSERT(fPathName != nil); + if (fFileNameExtension == nil) + fFileNameExtension = FindExtension(fPathName, fFssep); + return fFileNameExtension; } void GenericEntry::SetSubVolName(const char* name) { - delete[] fSubVolName; - fSubVolName = nil; - if (name != nil) { - fSubVolName = new char[strlen(name)+1]; - strcpy(fSubVolName, name); - } + delete[] fSubVolName; + fSubVolName = nil; + if (name != nil) { + fSubVolName = new char[strlen(name)+1]; + strcpy(fSubVolName, name); + } } const char* GenericEntry::GetDisplayName(void) const { - ASSERT(fPathName != nil); - if (fDisplayName != nil) - return fDisplayName; + ASSERT(fPathName != nil); + if (fDisplayName != nil) + return fDisplayName; - GenericEntry* pThis = const_cast(this); + GenericEntry* pThis = const_cast(this); - int len = strlen(fPathName) +1; - if (fSubVolName != nil) - len += strlen(fSubVolName) +1; - pThis->fDisplayName = new char[len]; - if (fSubVolName != nil) { - char xtra[2] = { DiskFS::kDIFssep, '\0' }; - strcpy(pThis->fDisplayName, fSubVolName); - strcat(pThis->fDisplayName, xtra); - } else - pThis->fDisplayName[0] = '\0'; - strcat(pThis->fDisplayName, fPathName); - return pThis->fDisplayName; + int len = strlen(fPathName) +1; + if (fSubVolName != nil) + len += strlen(fSubVolName) +1; + pThis->fDisplayName = new char[len]; + if (fSubVolName != nil) { + char xtra[2] = { DiskFS::kDIFssep, '\0' }; + strcpy(pThis->fDisplayName, fSubVolName); + strcat(pThis->fDisplayName, xtra); + } else + pThis->fDisplayName[0] = '\0'; + strcat(pThis->fDisplayName, fPathName); + return pThis->fDisplayName; } /* @@ -173,7 +173,7 @@ GenericEntry::GetDisplayName(void) const const char* GenericEntry::GetFileTypeString(void) const { - return PathProposal::FileTypeString(fFileType); + return PathProposal::FileTypeString(fFileType); } /* @@ -182,11 +182,11 @@ GenericEntry::GetFileTypeString(void) const /*static*/ void GenericEntry::SpacesToUnderscores(char* buf) { - while (*buf != '\0') { - if (*buf == ' ') - *buf = '_'; - buf++; - } + while (*buf != '\0') { + if (*buf == ' ') + *buf = '_'; + buf++; + } } @@ -205,25 +205,25 @@ GenericEntry::SpacesToUnderscores(char* buf) */ /*static*/ bool GenericEntry::CheckHighASCII(const unsigned char* buffer, - unsigned long count) + unsigned long count) { - bool isHighASCII; + bool isHighASCII; - ASSERT(buffer != nil); - ASSERT(count != 0); + ASSERT(buffer != nil); + ASSERT(count != 0); - isHighASCII = true; - while (count--) { - if ((*buffer & 0x80) == 0 && *buffer != 0x20 && *buffer != 0x00) { - WMSG1("Flunking CheckHighASCII on 0x%02x\n", *buffer); - isHighASCII = false; - break; - } - - buffer++; - } + isHighASCII = true; + while (count--) { + if ((*buffer & 0x80) == 0 && *buffer != 0x20 && *buffer != 0x00) { + WMSG1("Flunking CheckHighASCII on 0x%02x\n", *buffer); + isHighASCII = false; + break; + } + + buffer++; + } - return isHighASCII; + return isHighASCII; } /* @@ -245,28 +245,28 @@ GenericEntry::CheckHighASCII(const unsigned char* buffer, * much point in tweaking it to death. */ static const char gIsBinary[256] = { - 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, /* ^@-^O */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P-^_ */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* - / */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - ? */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* P - _ */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - DEL */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 */ + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, /* ^@-^O */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P-^_ */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* - / */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0 - ? */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* P - _ */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - DEL */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x80 */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x90 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xa0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xb0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xc0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xd0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xe0 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0xf0 */ }; -#define kNuMaxUpperASCII 1 /* max #of binary chars per 100 bytes */ -#define kMinConvThreshold 40 /* min of 40 chars for auto-detect */ -#define kCharLF '\n' -#define kCharCR '\r' +#define kNuMaxUpperASCII 1 /* max #of binary chars per 100 bytes */ +#define kMinConvThreshold 40 /* min of 40 chars for auto-detect */ +#define kCharLF '\n' +#define kCharCR '\r' /* * Decide, based on the contents of the buffer, whether we should do an * EOL conversion on the data. @@ -293,83 +293,83 @@ static const char gIsBinary[256] = { */ /*static*/ GenericEntry::ConvertEOL GenericEntry::DetermineConversion(const unsigned char* buffer, long count, - EOLType* pSourceType, ConvertHighASCII* pConvHA) + EOLType* pSourceType, ConvertHighASCII* pConvHA) { - ConvertHighASCII wantConvHA = *pConvHA; - long bufCount, numBinary, numLF, numCR; - bool isHighASCII; - unsigned char val; + ConvertHighASCII wantConvHA = *pConvHA; + long bufCount, numBinary, numLF, numCR; + bool isHighASCII; + unsigned char val; - *pSourceType = kEOLUnknown; - *pConvHA = kConvertHAOff; + *pSourceType = kEOLUnknown; + *pConvHA = kConvertHAOff; - if (count < kMinConvThreshold) - return kConvertEOLOff; + if (count < kMinConvThreshold) + return kConvertEOLOff; /* * Check to see if the buffer is all high-ASCII characters. If it is, * we want to strip characters before we test them below. - * - * If high ASCII conversion is disabled, assume that any high-ASCII - * characters are not meant to be line terminators, i.e. 0x8d != 0x0d. + * + * If high ASCII conversion is disabled, assume that any high-ASCII + * characters are not meant to be line terminators, i.e. 0x8d != 0x0d. */ - if (wantConvHA == kConvertHAOn || wantConvHA == kConvertHAAuto) { + if (wantConvHA == kConvertHAOn || wantConvHA == kConvertHAAuto) { isHighASCII = CheckHighASCII(buffer, count); - WMSG1(" +++ Determined isHighASCII=%d\n", isHighASCII); - } else { - isHighASCII = false; - WMSG0(" +++ Not even checking isHighASCII\n"); - } + WMSG1(" +++ Determined isHighASCII=%d\n", isHighASCII); + } else { + isHighASCII = false; + WMSG0(" +++ Not even checking isHighASCII\n"); + } - bufCount = count; - numBinary = numLF = numCR = 0; - while (bufCount--) { - val = *buffer++; - if (isHighASCII) - val &= 0x7f; - if (gIsBinary[val]) - numBinary++; - if (val == kCharLF) - numLF++; - if (val == kCharCR) - numCR++; - } + bufCount = count; + numBinary = numLF = numCR = 0; + while (bufCount--) { + val = *buffer++; + if (isHighASCII) + val &= 0x7f; + if (gIsBinary[val]) + numBinary++; + if (val == kCharLF) + numLF++; + if (val == kCharCR) + numCR++; + } - /* if #found is > #allowed, it's a binary file */ - if (count < 100) { - /* use simplified check on files between kNuMinConvThreshold and 100 */ - if (numBinary > kNuMaxUpperASCII) - return kConvertEOLOff; - } else if (numBinary > (count / 100) * kNuMaxUpperASCII) - return kConvertEOLOff; + /* if #found is > #allowed, it's a binary file */ + if (count < 100) { + /* use simplified check on files between kNuMinConvThreshold and 100 */ + if (numBinary > kNuMaxUpperASCII) + return kConvertEOLOff; + } else if (numBinary > (count / 100) * kNuMaxUpperASCII) + return kConvertEOLOff; - /* - * If our "convert to" setting is the same as what we're converting - * from, we can turn off the converter and speed things up. - * - * These are simplistic, but this is intended as an optimization. We - * will blow it if the input has lots of CRs and LFs scattered about, - * and they just happen to be in equal amounts, but it's not clear - * to me that an automatic EOL conversion makes sense on that sort - * of file anyway. - * - * None of this applies if we also need to do a high-ASCII conversion, - * because we can't bypass the processing. - */ - if (isHighASCII) { - *pConvHA = kConvertHAOn; - } else { - if (numLF && !numCR) - *pSourceType = kEOLLF; - else if (!numLF && numCR) - *pSourceType = kEOLCR; - else if (numLF && numLF == numCR) - *pSourceType = kEOLCRLF; - else - *pSourceType = kEOLUnknown; - } + /* + * If our "convert to" setting is the same as what we're converting + * from, we can turn off the converter and speed things up. + * + * These are simplistic, but this is intended as an optimization. We + * will blow it if the input has lots of CRs and LFs scattered about, + * and they just happen to be in equal amounts, but it's not clear + * to me that an automatic EOL conversion makes sense on that sort + * of file anyway. + * + * None of this applies if we also need to do a high-ASCII conversion, + * because we can't bypass the processing. + */ + if (isHighASCII) { + *pConvHA = kConvertHAOn; + } else { + if (numLF && !numCR) + *pSourceType = kEOLLF; + else if (!numLF && numCR) + *pSourceType = kEOLCR; + else if (numLF && numLF == numCR) + *pSourceType = kEOLCRLF; + else + *pSourceType = kEOLUnknown; + } - return kConvertEOLOn; + return kConvertEOLOn; } /* @@ -378,8 +378,8 @@ GenericEntry::DetermineConversion(const unsigned char* buffer, long count, static inline void PutEOL(FILE* fp) { - putc(kCharCR, fp); - putc(kCharLF, fp); + putc(kCharCR, fp); + putc(kCharLF, fp); } /* @@ -398,86 +398,86 @@ PutEOL(FILE* fp) */ /*static*/ int GenericEntry::WriteConvert(FILE* fp, const char* buf, size_t len, - ConvertEOL* pConv, ConvertHighASCII* pConvHA, bool* pLastCR) + ConvertEOL* pConv, ConvertHighASCII* pConvHA, bool* pLastCR) { - int err = 0; + int err = 0; - WMSG2("+++ WriteConvert conv=%d convHA=%d\n", *pConv, *pConvHA); + WMSG2("+++ WriteConvert conv=%d convHA=%d\n", *pConv, *pConvHA); - if (len == 0) { - WMSG0("WriteConvert asked to write 0 bytes; returning\n"); - return err; - } + if (len == 0) { + WMSG0("WriteConvert asked to write 0 bytes; returning\n"); + return err; + } - /* if we're in "auto" mode, scan the input for EOL and high ASCII */ - if (*pConv == kConvertEOLAuto) { - EOLType sourceType; - *pConv = DetermineConversion((unsigned char*)buf, len, &sourceType, - pConvHA); - if (*pConv == kConvertEOLOn && sourceType == kEOLCRLF) { - WMSG0(" Auto-detected text conversion from CRLF; disabling\n"); - *pConv = kConvertEOLOff; - } - WMSG2(" Auto-detected EOL conv=%d ha=%d\n", *pConv, *pConvHA); - } else if (*pConvHA == kConvertHAAuto) { - if (*pConv == kConvertEOLOn) { - /* definitely converting EOL, test for high ASCII */ - if (CheckHighASCII((unsigned char*)buf, len)) - *pConvHA = kConvertHAOn; - else - *pConvHA = kConvertHAOff; - } else { - /* not converting EOL, don't convert high ASCII */ - *pConvHA = kConvertHAOff; - } - } - WMSG2("+++ After auto, conv=%d convHA=%d\n", *pConv, *pConvHA); - ASSERT(*pConv == kConvertEOLOn || *pConv == kConvertEOLOff); - ASSERT(*pConvHA == kConvertHAOn || *pConvHA == kConvertHAOff); + /* if we're in "auto" mode, scan the input for EOL and high ASCII */ + if (*pConv == kConvertEOLAuto) { + EOLType sourceType; + *pConv = DetermineConversion((unsigned char*)buf, len, &sourceType, + pConvHA); + if (*pConv == kConvertEOLOn && sourceType == kEOLCRLF) { + WMSG0(" Auto-detected text conversion from CRLF; disabling\n"); + *pConv = kConvertEOLOff; + } + WMSG2(" Auto-detected EOL conv=%d ha=%d\n", *pConv, *pConvHA); + } else if (*pConvHA == kConvertHAAuto) { + if (*pConv == kConvertEOLOn) { + /* definitely converting EOL, test for high ASCII */ + if (CheckHighASCII((unsigned char*)buf, len)) + *pConvHA = kConvertHAOn; + else + *pConvHA = kConvertHAOff; + } else { + /* not converting EOL, don't convert high ASCII */ + *pConvHA = kConvertHAOff; + } + } + WMSG2("+++ After auto, conv=%d convHA=%d\n", *pConv, *pConvHA); + ASSERT(*pConv == kConvertEOLOn || *pConv == kConvertEOLOff); + ASSERT(*pConvHA == kConvertHAOn || *pConvHA == kConvertHAOff); - /* write the output */ - if (*pConv == kConvertEOLOff) { - if (fwrite(buf, len, 1, fp) != 1) { - err = errno; - WMSG1("WriteConvert failed, err=%d\n", errno); - } - } else { - ASSERT(*pConv == kConvertEOLOn); - bool lastCR = *pLastCR; - unsigned char uch; - int mask; + /* write the output */ + if (*pConv == kConvertEOLOff) { + if (fwrite(buf, len, 1, fp) != 1) { + err = errno; + WMSG1("WriteConvert failed, err=%d\n", errno); + } + } else { + ASSERT(*pConv == kConvertEOLOn); + bool lastCR = *pLastCR; + unsigned char uch; + int mask; - if (*pConvHA == kConvertHAOn) - mask = 0x7f; - else - mask = 0xff; + if (*pConvHA == kConvertHAOn) + mask = 0x7f; + else + mask = 0xff; - while (len--) { - uch = (*buf) & mask; + while (len--) { + uch = (*buf) & mask; - if (uch == kCharCR) { - PutEOL(fp); - lastCR = true; - } else if (uch == kCharLF) { - if (!lastCR) - PutEOL(fp); - lastCR = false; - } else { - putc(uch, fp); - lastCR = false; - } - buf++; - } - *pLastCR = lastCR; - } + if (uch == kCharCR) { + PutEOL(fp); + lastCR = true; + } else if (uch == kCharLF) { + if (!lastCR) + PutEOL(fp); + lastCR = false; + } else { + putc(uch, fp); + lastCR = false; + } + buf++; + } + *pLastCR = lastCR; + } - return err; + return err; } /* * =========================================================================== - * GenericArchive + * GenericArchive * =========================================================================== */ @@ -487,28 +487,28 @@ GenericEntry::WriteConvert(FILE* fp, const char* buf, size_t len, void GenericArchive::AddEntry(GenericEntry* pEntry) { - if (fEntryHead == nil) { - ASSERT(fEntryTail == nil); - fEntryHead = pEntry; - fEntryTail = pEntry; - ASSERT(pEntry->GetPrev() == nil); - ASSERT(pEntry->GetNext() == nil); - } else { - ASSERT(fEntryTail != nil); - ASSERT(pEntry->GetPrev() == nil); - pEntry->SetPrev(fEntryTail); - ASSERT(fEntryTail->GetNext() == nil); - fEntryTail->SetNext(pEntry); - fEntryTail = pEntry; - } + if (fEntryHead == nil) { + ASSERT(fEntryTail == nil); + fEntryHead = pEntry; + fEntryTail = pEntry; + ASSERT(pEntry->GetPrev() == nil); + ASSERT(pEntry->GetNext() == nil); + } else { + ASSERT(fEntryTail != nil); + ASSERT(pEntry->GetPrev() == nil); + pEntry->SetPrev(fEntryTail); + ASSERT(fEntryTail->GetNext() == nil); + fEntryTail->SetNext(pEntry); + fEntryTail = pEntry; + } - fNumEntries++; + fNumEntries++; - //if (fEntryIndex != nil) { - // WMSG0("Resetting fEntryIndex\n"); - // delete [] fEntryIndex; - // fEntryIndex = nil; - //} + //if (fEntryIndex != nil) { + // WMSG0("Resetting fEntryIndex\n"); + // delete [] fEntryIndex; + // fEntryIndex = nil; + //} } /* @@ -517,21 +517,21 @@ GenericArchive::AddEntry(GenericEntry* pEntry) void GenericArchive::DeleteEntries(void) { - GenericEntry* pEntry; - GenericEntry* pNext; + GenericEntry* pEntry; + GenericEntry* pNext; - WMSG1("Deleting %d archive entries\n", fNumEntries); + WMSG1("Deleting %d archive entries\n", fNumEntries); - pEntry = GetEntries(); - while (pEntry != nil) { - pNext = pEntry->GetNext(); - delete pEntry; - pEntry = pNext; - } + pEntry = GetEntries(); + while (pEntry != nil) { + pNext = pEntry->GetNext(); + delete pEntry; + pEntry = pNext; + } - //delete [] fEntryIndex; - fNumEntries = 0; - fEntryHead = fEntryTail = nil; + //delete [] fEntryIndex; + fNumEntries = 0; + fEntryHead = fEntryTail = nil; } #if 0 @@ -541,24 +541,24 @@ GenericArchive::DeleteEntries(void) void GenericArchive::CreateIndex(void) { - GenericEntry* pEntry; - int num; + GenericEntry* pEntry; + int num; - WMSG1("Creating entry index (%d entries)\n", fNumEntries); + WMSG1("Creating entry index (%d entries)\n", fNumEntries); - ASSERT(fNumEntries != 0); + ASSERT(fNumEntries != 0); - fEntryIndex = new GenericEntry*[fNumEntries]; - if (fEntryIndex == nil) - return; + fEntryIndex = new GenericEntry*[fNumEntries]; + if (fEntryIndex == nil) + return; - pEntry = GetEntries(); - num = 0; - while (pEntry != nil) { - fEntryIndex[num] = pEntry; - pEntry = pEntry->GetNext(); - num++; - } + pEntry = GetEntries(); + num = 0; + while (pEntry != nil) { + fEntryIndex[num] = pEntry; + pEntry = pEntry->GetNext(); + num++; + } } #endif @@ -576,25 +576,25 @@ GenericArchive::CreateIndex(void) /*static*/ CString GenericArchive::GenDerivedTempName(const char* filename) { - static const char* kTmpTemplate = "CPtmp_XXXXXX"; - CString mangle(filename); - int idx, len; + static const char* kTmpTemplate = "CPtmp_XXXXXX"; + CString mangle(filename); + int idx, len; - ASSERT(filename != nil); + ASSERT(filename != nil); - len = mangle.GetLength(); - ASSERT(len > 0); - idx = mangle.ReverseFind('\\'); - if (idx < 0) { - /* generally shouldn't happen -- we're using full paths */ - return kTmpTemplate; - } else { - mangle.Delete(idx+1, len-(idx+1)); /* delete out to the end */ - mangle += kTmpTemplate; - } - WMSG2("GenDerived: passed '%s' returned '%s'\n", filename, mangle); + len = mangle.GetLength(); + ASSERT(len > 0); + idx = mangle.ReverseFind('\\'); + if (idx < 0) { + /* generally shouldn't happen -- we're using full paths */ + return kTmpTemplate; + } else { + mangle.Delete(idx+1, len-(idx+1)); /* delete out to the end */ + mangle += kTmpTemplate; + } + WMSG2("GenDerived: passed '%s' returned '%s'\n", filename, mangle); - return mangle; + return mangle; } @@ -614,44 +614,44 @@ GenericArchive::GenDerivedTempName(const char* filename) */ /*static*/ int GenericArchive::ComparePaths(const CString& name1, char fssep1, - const CString& name2, char fssep2) + const CString& name2, char fssep2) { - const char* cp1 = name1; - const char* cp2 = name2; + const char* cp1 = name1; + const char* cp2 = name2; - while (*cp1 != '\0' && *cp2 != '\0') { - if (*cp1 == fssep1) { - if (*cp2 != fssep2) { - /* one fssep, one not, no match */ - if (*cp1 == *cp2) - return 1; - else - return *cp1 - *cp2; - } else { - /* both are fssep, it's a match even if ASCII is different */ - } - } else if (*cp2 == fssep2) { - /* one fssep, one not */ - if (*cp1 == *cp2) - return -1; - else - return *cp1 - *cp2; - } else if (tolower(*cp1) != tolower(*cp2)) { - /* mismatch */ - return tolower(*cp1) - tolower(*cp2); - } + while (*cp1 != '\0' && *cp2 != '\0') { + if (*cp1 == fssep1) { + if (*cp2 != fssep2) { + /* one fssep, one not, no match */ + if (*cp1 == *cp2) + return 1; + else + return *cp1 - *cp2; + } else { + /* both are fssep, it's a match even if ASCII is different */ + } + } else if (*cp2 == fssep2) { + /* one fssep, one not */ + if (*cp1 == *cp2) + return -1; + else + return *cp1 - *cp2; + } else if (tolower(*cp1) != tolower(*cp2)) { + /* mismatch */ + return tolower(*cp1) - tolower(*cp2); + } - cp1++; - cp2++; - } + cp1++; + cp2++; + } - return *cp1 - *cp2; + return *cp1 - *cp2; } /* * =========================================================================== - * GenericArchive -- "add files" stuff + * GenericArchive -- "add files" stuff * =========================================================================== */ @@ -675,11 +675,11 @@ GenericArchive::UNIXTimeToDateTime(const time_t* pWhen, NuDateTime* pDateTime) ASSERT(pDateTime != nil); ptm = localtime(pWhen); - if (ptm == nil) { - ASSERT(*pWhen == kDateNone || *pWhen == kDateInvalid); - memset(pDateTime, 0, sizeof(*pDateTime)); - return; - } + if (ptm == nil) { + ASSERT(*pWhen == kDateNone || *pWhen == kDateInvalid); + memset(pDateTime, 0, sizeof(*pDateTime)); + return; + } pDateTime->second = ptm->tm_sec; pDateTime->minute = ptm->tm_min; pDateTime->hour = ptm->tm_hour; @@ -700,106 +700,106 @@ GenericArchive::UNIXTimeToDateTime(const time_t* pWhen, NuDateTime* pDateTime) */ NuError GenericArchive::GetFileDetails(const AddFilesDialog* pAddOpts, - const char* pathname, struct stat* psb, FileDetails* pDetails) + const char* pathname, struct stat* psb, FileDetails* pDetails) { - //char* livePathStr; - time_t now; + //char* livePathStr; + time_t now; - ASSERT(pAddOpts != nil); - ASSERT(pathname != nil); - ASSERT(pDetails != nil); + ASSERT(pAddOpts != nil); + ASSERT(pathname != nil); + ASSERT(pDetails != nil); - /* init to defaults */ - //pDetails->threadID = kNuThreadIDDataFork; - pDetails->entryKind = FileDetails::kFileKindDataFork; - //pDetails->fileSysID = kNuFileSysUnknown; - pDetails->fileSysFmt = DiskImg::kFormatUnknown; - pDetails->fileSysInfo = PathProposal::kDefaultStoredFssep; - pDetails->fileType = 0; - pDetails->extraType = 0; - pDetails->storageType = kNuStorageUnknown; /* let NufxLib worry about it */ - if (psb->st_mode & S_IWUSR) - pDetails->access = kNuAccessUnlocked; - else - pDetails->access = kNuAccessLocked; + /* init to defaults */ + //pDetails->threadID = kNuThreadIDDataFork; + pDetails->entryKind = FileDetails::kFileKindDataFork; + //pDetails->fileSysID = kNuFileSysUnknown; + pDetails->fileSysFmt = DiskImg::kFormatUnknown; + pDetails->fileSysInfo = PathProposal::kDefaultStoredFssep; + pDetails->fileType = 0; + pDetails->extraType = 0; + pDetails->storageType = kNuStorageUnknown; /* let NufxLib worry about it */ + if (psb->st_mode & S_IWUSR) + pDetails->access = kNuAccessUnlocked; + else + pDetails->access = kNuAccessLocked; #if 0 - /* if this is a disk image, fill in disk-specific fields */ - if (NState_GetModAddAsDisk(pState)) { - if ((psb->st_size & 0x1ff) != 0) { - /* reject anything whose size isn't a multiple of 512 bytes */ - printf("NOT storing odd-sized (%ld) file as disk image: %s\n", - (long)psb->st_size, livePathStr); - } else { - /* set fields; note the "preserve" stuff can override this */ - pDetails->threadID = kNuThreadIDDiskImage; - pDetails->storageType = 512; - pDetails->extraType = psb->st_size / 512; - } - } + /* if this is a disk image, fill in disk-specific fields */ + if (NState_GetModAddAsDisk(pState)) { + if ((psb->st_size & 0x1ff) != 0) { + /* reject anything whose size isn't a multiple of 512 bytes */ + printf("NOT storing odd-sized (%ld) file as disk image: %s\n", + (long)psb->st_size, livePathStr); + } else { + /* set fields; note the "preserve" stuff can override this */ + pDetails->threadID = kNuThreadIDDiskImage; + pDetails->storageType = 512; + pDetails->extraType = psb->st_size / 512; + } + } #endif - now = time(nil); - UNIXTimeToDateTime(&now, &pDetails->archiveWhen); - UNIXTimeToDateTime(&psb->st_mtime, &pDetails->modWhen); - UNIXTimeToDateTime(&psb->st_ctime, &pDetails->createWhen); + now = time(nil); + UNIXTimeToDateTime(&now, &pDetails->archiveWhen); + UNIXTimeToDateTime(&psb->st_mtime, &pDetails->modWhen); + UNIXTimeToDateTime(&psb->st_ctime, &pDetails->createWhen); - /* get adjusted filename, along with any preserved type info */ - PathProposal pathProp; - pathProp.Init(pathname); - pathProp.LocalToArchive(pAddOpts); + /* get adjusted filename, along with any preserved type info */ + PathProposal pathProp; + pathProp.Init(pathname); + pathProp.LocalToArchive(pAddOpts); - /* set up the local and archived pathnames */ - pDetails->storageName = ""; - if (!pAddOpts->fStoragePrefix.IsEmpty()) { - pDetails->storageName += pAddOpts->fStoragePrefix; - pDetails->storageName += pathProp.fStoredFssep; - } - pDetails->storageName += pathProp.fStoredPathName; + /* set up the local and archived pathnames */ + pDetails->storageName = ""; + if (!pAddOpts->fStoragePrefix.IsEmpty()) { + pDetails->storageName += pAddOpts->fStoragePrefix; + pDetails->storageName += pathProp.fStoredFssep; + } + pDetails->storageName += pathProp.fStoredPathName; - /* - * Fill in the NuFileDetails struct. - * - * We use GetBuffer to get the string to ensure that the CString object - * doesn't do anything while we're not looking. The string won't be - * modified, and it won't be around for very long, so it's not strictly - * necessary to do this. It is, however, the correct approach. - */ - pDetails->origName = pathname; - pDetails->fileSysInfo = pathProp.fStoredFssep; - pDetails->fileType = pathProp.fFileType; - pDetails->extraType = pathProp.fAuxType; - switch (pathProp.fThreadKind) { - case GenericEntry::kDataThread: - //pDetails->threadID = kNuThreadIDDataFork; - pDetails->entryKind = FileDetails::kFileKindDataFork; - break; - case GenericEntry::kRsrcThread: - //pDetails->threadID = kNuThreadIDRsrcFork; - pDetails->entryKind = FileDetails::kFileKindRsrcFork; - break; - case GenericEntry::kDiskImageThread: - //pDetails->threadID = kNuThreadIDDiskImage; - pDetails->entryKind = FileDetails::kFileKindDiskImage; - break; - default: - ASSERT(false); - // was initialized to default earlier - break; - } + /* + * Fill in the NuFileDetails struct. + * + * We use GetBuffer to get the string to ensure that the CString object + * doesn't do anything while we're not looking. The string won't be + * modified, and it won't be around for very long, so it's not strictly + * necessary to do this. It is, however, the correct approach. + */ + pDetails->origName = pathname; + pDetails->fileSysInfo = pathProp.fStoredFssep; + pDetails->fileType = pathProp.fFileType; + pDetails->extraType = pathProp.fAuxType; + switch (pathProp.fThreadKind) { + case GenericEntry::kDataThread: + //pDetails->threadID = kNuThreadIDDataFork; + pDetails->entryKind = FileDetails::kFileKindDataFork; + break; + case GenericEntry::kRsrcThread: + //pDetails->threadID = kNuThreadIDRsrcFork; + pDetails->entryKind = FileDetails::kFileKindRsrcFork; + break; + case GenericEntry::kDiskImageThread: + //pDetails->threadID = kNuThreadIDDiskImage; + pDetails->entryKind = FileDetails::kFileKindDiskImage; + break; + default: + ASSERT(false); + // was initialized to default earlier + break; + } /*bail:*/ - return kNuErrNone; + return kNuErrNone; } /* * Directory structure and functions, based on zDIR in Info-Zip sources. */ typedef struct Win32dirent { - char d_attr; - char d_name[MAX_PATH]; - int d_first; - HANDLE d_hFindFile; + char d_attr; + char d_name[MAX_PATH]; + int d_first; + HANDLE d_hFindFile; } Win32dirent; static const char* kWildMatchAll = "*.*"; @@ -812,45 +812,45 @@ static const char* kWildMatchAll = "*.*"; Win32dirent* GenericArchive::OpenDir(const char* name) { - Win32dirent* dir = nil; - char* tmpStr = nil; - char* cp; - WIN32_FIND_DATA fnd; + Win32dirent* dir = nil; + char* tmpStr = nil; + char* cp; + WIN32_FIND_DATA fnd; - dir = (Win32dirent*) malloc(sizeof(*dir)); - tmpStr = (char*) malloc(strlen(name) + (2 + sizeof(kWildMatchAll))); - if (dir == nil || tmpStr == nil) - goto failed; + dir = (Win32dirent*) malloc(sizeof(*dir)); + tmpStr = (char*) malloc(strlen(name) + (2 + sizeof(kWildMatchAll))); + if (dir == nil || tmpStr == nil) + goto failed; - strcpy(tmpStr, name); - cp = tmpStr + strlen(tmpStr); + strcpy(tmpStr, name); + cp = tmpStr + strlen(tmpStr); - /* don't end in a colon (e.g. "C:") */ - if ((cp - tmpStr) > 0 && strrchr(tmpStr, ':') == (cp - 1)) - *cp++ = '.'; - /* must end in a slash */ - if ((cp - tmpStr) > 0 && - strrchr(tmpStr, PathProposal::kLocalFssep) != (cp - 1)) - *cp++ = PathProposal::kLocalFssep; + /* don't end in a colon (e.g. "C:") */ + if ((cp - tmpStr) > 0 && strrchr(tmpStr, ':') == (cp - 1)) + *cp++ = '.'; + /* must end in a slash */ + if ((cp - tmpStr) > 0 && + strrchr(tmpStr, PathProposal::kLocalFssep) != (cp - 1)) + *cp++ = PathProposal::kLocalFssep; - strcpy(cp, kWildMatchAll); + strcpy(cp, kWildMatchAll); - dir->d_hFindFile = FindFirstFile(tmpStr, &fnd); - if (dir->d_hFindFile == INVALID_HANDLE_VALUE) - goto failed; + dir->d_hFindFile = FindFirstFile(tmpStr, &fnd); + if (dir->d_hFindFile == INVALID_HANDLE_VALUE) + goto failed; - strcpy(dir->d_name, fnd.cFileName); - dir->d_attr = (unsigned char) fnd.dwFileAttributes; - dir->d_first = 1; + strcpy(dir->d_name, fnd.cFileName); + dir->d_attr = (unsigned char) fnd.dwFileAttributes; + dir->d_first = 1; bail: - free(tmpStr); - return dir; + free(tmpStr); + return dir; failed: - free(dir); - dir = nil; - goto bail; + free(dir); + dir = nil; + goto bail; } /* @@ -861,18 +861,18 @@ failed: Win32dirent* GenericArchive::ReadDir(Win32dirent* dir) { - if (dir->d_first) - dir->d_first = 0; - else { - WIN32_FIND_DATA fnd; + if (dir->d_first) + dir->d_first = 0; + else { + WIN32_FIND_DATA fnd; - if (!FindNextFile(dir->d_hFindFile, &fnd)) - return nil; - strcpy(dir->d_name, fnd.cFileName); - dir->d_attr = (unsigned char) fnd.dwFileAttributes; - } + if (!FindNextFile(dir->d_hFindFile, &fnd)) + return nil; + strcpy(dir->d_name, fnd.cFileName); + dir->d_attr = (unsigned char) fnd.dwFileAttributes; + } - return dir; + return dir; } /* @@ -881,19 +881,19 @@ GenericArchive::ReadDir(Win32dirent* dir) void GenericArchive::CloseDir(Win32dirent* dir) { - if (dir == nil) - return; + if (dir == nil) + return; - FindClose(dir->d_hFindFile); - free(dir); + FindClose(dir->d_hFindFile); + free(dir); } /* might as well blend in with the UNIX version */ -#define DIR_NAME_LEN(dirent) ((int)strlen((dirent)->d_name)) +#define DIR_NAME_LEN(dirent) ((int)strlen((dirent)->d_name)) //static NuError Win32AddFile(NulibState* pState, NuArchive* pArchive, -// const char* pathname); +// const char* pathname); /* @@ -903,62 +903,62 @@ GenericArchive::CloseDir(Win32dirent* dir) */ NuError GenericArchive::Win32AddDirectory(const AddFilesDialog* pAddOpts, - const char* dirName, CString* pErrMsg) + const char* dirName, CString* pErrMsg) { - NuError err = kNuErrNone; - Win32dirent* dirp = nil; - Win32dirent* entry; - char nbuf[MAX_PATH]; /* malloc might be better; this soaks stack */ - char fssep; - int len; + NuError err = kNuErrNone; + Win32dirent* dirp = nil; + Win32dirent* entry; + char nbuf[MAX_PATH]; /* malloc might be better; this soaks stack */ + char fssep; + int len; - ASSERT(pAddOpts != nil); - ASSERT(dirName != nil); + ASSERT(pAddOpts != nil); + ASSERT(dirName != nil); - WMSG1("+++ DESCEND: '%s'\n", dirName); + WMSG1("+++ DESCEND: '%s'\n", dirName); - dirp = OpenDir(dirName); - if (dirp == nil) { - if (errno == ENOTDIR) - err = kNuErrNotDir; - else - err = errno ? (NuError)errno : kNuErrOpenDir; - - pErrMsg->Format("Failed on '%s': %s.", dirName, NuStrError(err)); - goto bail; - } + dirp = OpenDir(dirName); + if (dirp == nil) { + if (errno == ENOTDIR) + err = kNuErrNotDir; + else + err = errno ? (NuError)errno : kNuErrOpenDir; + + pErrMsg->Format("Failed on '%s': %s.", dirName, NuStrError(err)); + goto bail; + } - fssep = PathProposal::kLocalFssep; + fssep = PathProposal::kLocalFssep; - /* could use readdir_r, but we don't care about reentrancy here */ - while ((entry = ReadDir(dirp)) != nil) { - /* skip the dotsies */ - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; + /* could use readdir_r, but we don't care about reentrancy here */ + while ((entry = ReadDir(dirp)) != nil) { + /* skip the dotsies */ + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; - len = strlen(dirName); - if (len + DIR_NAME_LEN(entry) +2 > MAX_PATH) { - err = kNuErrInternal; - WMSG4("ERROR: Filename exceeds %d bytes: %s%c%s", - MAX_PATH, dirName, fssep, entry->d_name); - goto bail; - } + len = strlen(dirName); + if (len + DIR_NAME_LEN(entry) +2 > MAX_PATH) { + err = kNuErrInternal; + WMSG4("ERROR: Filename exceeds %d bytes: %s%c%s", + MAX_PATH, dirName, fssep, entry->d_name); + goto bail; + } - /* form the new name, inserting an fssep if needed */ - strcpy(nbuf, dirName); - if (dirName[len-1] != fssep) - nbuf[len++] = fssep; - strcpy(nbuf+len, entry->d_name); + /* form the new name, inserting an fssep if needed */ + strcpy(nbuf, dirName); + if (dirName[len-1] != fssep) + nbuf[len++] = fssep; + strcpy(nbuf+len, entry->d_name); - err = Win32AddFile(pAddOpts, nbuf, pErrMsg); - if (err != kNuErrNone) - goto bail; - } + err = Win32AddFile(pAddOpts, nbuf, pErrMsg); + if (err != kNuErrNone) + goto bail; + } bail: - if (dirp != nil) - (void)CloseDir(dirp); - return err; + if (dirp != nil) + (void)CloseDir(dirp); + return err; } /* @@ -970,93 +970,93 @@ bail: */ NuError GenericArchive::Win32AddFile(const AddFilesDialog* pAddOpts, - const char* pathname, CString* pErrMsg) + const char* pathname, CString* pErrMsg) { - NuError err = kNuErrNone; - Boolean exists, isDir, isReadable; - FileDetails details; - struct stat sb; + NuError err = kNuErrNone; + Boolean exists, isDir, isReadable; + FileDetails details; + struct stat sb; - ASSERT(pAddOpts != nil); - ASSERT(pathname != nil); + ASSERT(pAddOpts != nil); + ASSERT(pathname != nil); - PathName checkPath(pathname); - int ierr = checkPath.CheckFileStatus(&sb, &exists, &isReadable, &isDir); - if (ierr != 0) { - err = kNuErrGeneric; - pErrMsg->Format("Unexpected error while examining '%s': %s.", pathname, - NuStrError((NuError) ierr)); - goto bail; - } + PathName checkPath(pathname); + int ierr = checkPath.CheckFileStatus(&sb, &exists, &isReadable, &isDir); + if (ierr != 0) { + err = kNuErrGeneric; + pErrMsg->Format("Unexpected error while examining '%s': %s.", pathname, + NuStrError((NuError) ierr)); + goto bail; + } - if (!exists) { - err = kNuErrFileNotFound; - pErrMsg->Format("Couldn't find '%s'", pathname); - goto bail; - } - if (!isReadable) { - err = kNuErrFileNotReadable; - pErrMsg->Format("File '%s' isn't readable.", pathname); - goto bail; - } - if (isDir) { - if (pAddOpts->fIncludeSubfolders) - err = Win32AddDirectory(pAddOpts, pathname, pErrMsg); - goto bail; - } + if (!exists) { + err = kNuErrFileNotFound; + pErrMsg->Format("Couldn't find '%s'", pathname); + goto bail; + } + if (!isReadable) { + err = kNuErrFileNotReadable; + pErrMsg->Format("File '%s' isn't readable.", pathname); + goto bail; + } + if (isDir) { + if (pAddOpts->fIncludeSubfolders) + err = Win32AddDirectory(pAddOpts, pathname, pErrMsg); + goto bail; + } - /* - * We've found a file that we want to add. We need to decide what - * filetype and auxtype it has, and whether or not it's actually the - * resource fork of another file. - */ - WMSG1("+++ ADD '%s'\n", pathname); + /* + * We've found a file that we want to add. We need to decide what + * filetype and auxtype it has, and whether or not it's actually the + * resource fork of another file. + */ + WMSG1("+++ ADD '%s'\n", pathname); - /* - * Fill out the "details" structure. The class has an automatic - * conversion to NuFileDetails, but it relies on the CString storage - * in the FileDetails, so be careful how you use it. - */ - err = GetFileDetails(pAddOpts, pathname, &sb, &details); - if (err != kNuErrNone) - goto bail; + /* + * Fill out the "details" structure. The class has an automatic + * conversion to NuFileDetails, but it relies on the CString storage + * in the FileDetails, so be careful how you use it. + */ + err = GetFileDetails(pAddOpts, pathname, &sb, &details); + if (err != kNuErrNone) + goto bail; - assert(strcmp(pathname, details.origName) == 0); - err = DoAddFile(pAddOpts, &details); - if (err == kNuErrSkipped) // ignore "skipped" result - err = kNuErrNone; - if (err != kNuErrNone) - goto bail; + assert(strcmp(pathname, details.origName) == 0); + err = DoAddFile(pAddOpts, &details); + if (err == kNuErrSkipped) // ignore "skipped" result + err = kNuErrNone; + if (err != kNuErrNone) + goto bail; bail: - if (err != kNuErrNone && pErrMsg->IsEmpty()) { - pErrMsg->Format("Unable to add file '%s': %s.", - pathname, NuStrError(err)); - } - return err; + if (err != kNuErrNone && pErrMsg->IsEmpty()) { + pErrMsg->Format("Unable to add file '%s': %s.", + pathname, NuStrError(err)); + } + return err; } /* * External entry point; just calls the system-specific version. * * [ I figure the GS/OS version will want to pass a copy of the file - * info from the GSOSAddDirectory function back into GSOSAddFile, so we'd - * want to call it from here with a nil pointer indicating that we - * don't yet have the file info. That way we can get the file info - * from the directory read call and won't have to check it again in - * GSOSAddFile. ] + * info from the GSOSAddDirectory function back into GSOSAddFile, so we'd + * want to call it from here with a nil pointer indicating that we + * don't yet have the file info. That way we can get the file info + * from the directory read call and won't have to check it again in + * GSOSAddFile. ] */ NuError GenericArchive::AddFile(const AddFilesDialog* pAddOpts, const char* pathname, - CString* pErrMsg) + CString* pErrMsg) { - *pErrMsg = ""; - return Win32AddFile(pAddOpts, pathname, pErrMsg); + *pErrMsg = ""; + return Win32AddFile(pAddOpts, pathname, pErrMsg); } /* * =========================================================================== - * GenericArchive::FileDetails + * GenericArchive::FileDetails * =========================================================================== */ @@ -1065,14 +1065,14 @@ GenericArchive::AddFile(const AddFilesDialog* pAddOpts, const char* pathname, */ GenericArchive::FileDetails::FileDetails(void) { - //threadID = 0; - entryKind = kFileKindUnknown; - fileSysFmt = DiskImg::kFormatUnknown; - fileSysInfo = storageType = 0; - access = fileType = extraType = 0; - memset(&createWhen, 0, sizeof(createWhen)); - memset(&modWhen, 0, sizeof(modWhen)); - memset(&archiveWhen, 0, sizeof(archiveWhen)); + //threadID = 0; + entryKind = kFileKindUnknown; + fileSysFmt = DiskImg::kFormatUnknown; + fileSysInfo = storageType = 0; + access = fileType = extraType = 0; + memset(&createWhen, 0, sizeof(createWhen)); + memset(&modWhen, 0, sizeof(modWhen)); + memset(&archiveWhen, 0, sizeof(archiveWhen)); } /* @@ -1083,74 +1083,74 @@ GenericArchive::FileDetails::FileDetails(void) */ GenericArchive::FileDetails::operator const NuFileDetails() const { - NuFileDetails details; + NuFileDetails details; - //details.threadID = threadID; - switch (entryKind) { - case kFileKindDataFork: - details.threadID = kNuThreadIDDataFork; - break; - case kFileKindBothForks: // not exactly supported, doesn't really matter - case kFileKindRsrcFork: - details.threadID = kNuThreadIDRsrcFork; - break; - case kFileKindDiskImage: - details.threadID = kNuThreadIDDiskImage; - break; - case kFileKindDirectory: - default: - WMSG1("Invalid entryKind (%d) for NuFileDetails conversion\n", - entryKind); - ASSERT(false); - details.threadID = 0; // that makes it an old-style comment?! - break; - } + //details.threadID = threadID; + switch (entryKind) { + case kFileKindDataFork: + details.threadID = kNuThreadIDDataFork; + break; + case kFileKindBothForks: // not exactly supported, doesn't really matter + case kFileKindRsrcFork: + details.threadID = kNuThreadIDRsrcFork; + break; + case kFileKindDiskImage: + details.threadID = kNuThreadIDDiskImage; + break; + case kFileKindDirectory: + default: + WMSG1("Invalid entryKind (%d) for NuFileDetails conversion\n", + entryKind); + ASSERT(false); + details.threadID = 0; // that makes it an old-style comment?! + break; + } - details.origName = origName; // CString to char* - details.storageName = storageName; // CString to char* - //details.fileSysID = fileSysID; - details.fileSysInfo = fileSysInfo; - details.access = access; - details.fileType = fileType; - details.extraType = extraType; - details.storageType = storageType; - details.createWhen = createWhen; - details.modWhen = modWhen; - details.archiveWhen = archiveWhen; + details.origName = origName; // CString to char* + details.storageName = storageName; // CString to char* + //details.fileSysID = fileSysID; + details.fileSysInfo = fileSysInfo; + details.access = access; + details.fileType = fileType; + details.extraType = extraType; + details.storageType = storageType; + details.createWhen = createWhen; + details.modWhen = modWhen; + details.archiveWhen = archiveWhen; - switch (fileSysFmt) { - case DiskImg::kFormatProDOS: - case DiskImg::kFormatDOS33: - case DiskImg::kFormatDOS32: - case DiskImg::kFormatPascal: - case DiskImg::kFormatMacHFS: - case DiskImg::kFormatMacMFS: - case DiskImg::kFormatLisa: - case DiskImg::kFormatCPM: - //kFormatCharFST - case DiskImg::kFormatMSDOS: - //kFormatHighSierra - case DiskImg::kFormatISO9660: - /* these map directly */ - details.fileSysID = (enum NuFileSysID) fileSysFmt; - break; + switch (fileSysFmt) { + case DiskImg::kFormatProDOS: + case DiskImg::kFormatDOS33: + case DiskImg::kFormatDOS32: + case DiskImg::kFormatPascal: + case DiskImg::kFormatMacHFS: + case DiskImg::kFormatMacMFS: + case DiskImg::kFormatLisa: + case DiskImg::kFormatCPM: + //kFormatCharFST + case DiskImg::kFormatMSDOS: + //kFormatHighSierra + case DiskImg::kFormatISO9660: + /* these map directly */ + details.fileSysID = (enum NuFileSysID) fileSysFmt; + break; - case DiskImg::kFormatRDOS33: - case DiskImg::kFormatRDOS32: - case DiskImg::kFormatRDOS3: - /* these look like DOS33, e.g. text is high-ASCII */ - details.fileSysID = kNuFileSysDOS33; - break; + case DiskImg::kFormatRDOS33: + case DiskImg::kFormatRDOS32: + case DiskImg::kFormatRDOS3: + /* these look like DOS33, e.g. text is high-ASCII */ + details.fileSysID = kNuFileSysDOS33; + break; - default: - details.fileSysID = kNuFileSysUnknown; - break; - } + default: + details.fileSysID = kNuFileSysUnknown; + break; + } - // Return stack copy, which copies into compiler temporary with our - // copy constructor. - return details; + // Return stack copy, which copies into compiler temporary with our + // copy constructor. + return details; } /* @@ -1160,27 +1160,27 @@ GenericArchive::FileDetails::operator const NuFileDetails() const */ /*static*/ void GenericArchive::FileDetails::CopyFields(FileDetails* pDst, - const FileDetails* pSrc) + const FileDetails* pSrc) { - //pDst->threadID = pSrc->threadID; - pDst->entryKind = pSrc->entryKind; - pDst->origName = pSrc->origName; - pDst->storageName = pSrc->storageName; - pDst->fileSysFmt = pSrc->fileSysFmt; - pDst->fileSysInfo = pSrc->fileSysInfo; - pDst->access = pSrc->access; - pDst->fileType = pSrc->fileType; - pDst->extraType = pSrc->extraType; - pDst->storageType = pSrc->storageType; - pDst->createWhen = pSrc->createWhen; - pDst->modWhen = pSrc->modWhen; - pDst->archiveWhen = pSrc->archiveWhen; + //pDst->threadID = pSrc->threadID; + pDst->entryKind = pSrc->entryKind; + pDst->origName = pSrc->origName; + pDst->storageName = pSrc->storageName; + pDst->fileSysFmt = pSrc->fileSysFmt; + pDst->fileSysInfo = pSrc->fileSysInfo; + pDst->access = pSrc->access; + pDst->fileType = pSrc->fileType; + pDst->extraType = pSrc->extraType; + pDst->storageType = pSrc->storageType; + pDst->createWhen = pSrc->createWhen; + pDst->modWhen = pSrc->modWhen; + pDst->archiveWhen = pSrc->archiveWhen; } /* * =========================================================================== - * SelectionSet + * SelectionSet * =========================================================================== */ @@ -1194,19 +1194,19 @@ GenericArchive::FileDetails::CopyFields(FileDetails* pDst, void SelectionSet::CreateFromSelection(ContentList* pContentList, int threadMask) { - WMSG1("CreateFromSelection (threadMask=0x%02x)\n", threadMask); + WMSG1("CreateFromSelection (threadMask=0x%02x)\n", threadMask); - POSITION posn; - posn = pContentList->GetFirstSelectedItemPosition(); - ASSERT(posn != nil); - if (posn == nil) - return; - while (posn != nil) { - int num = pContentList->GetNextSelectedItem(/*ref*/ posn); - GenericEntry* pEntry = (GenericEntry*) pContentList->GetItemData(num); + POSITION posn; + posn = pContentList->GetFirstSelectedItemPosition(); + ASSERT(posn != nil); + if (posn == nil) + return; + while (posn != nil) { + int num = pContentList->GetNextSelectedItem(/*ref*/ posn); + GenericEntry* pEntry = (GenericEntry*) pContentList->GetItemData(num); - AddToSet(pEntry, threadMask); - } + AddToSet(pEntry, threadMask); + } } /* @@ -1215,14 +1215,14 @@ SelectionSet::CreateFromSelection(ContentList* pContentList, int threadMask) void SelectionSet::CreateFromAll(ContentList* pContentList, int threadMask) { - WMSG1("CreateFromAll (threadMask=0x%02x)\n", threadMask); + WMSG1("CreateFromAll (threadMask=0x%02x)\n", threadMask); - int count = pContentList->GetItemCount(); - for (int idx = 0; idx < count; idx++) { - GenericEntry* pEntry = (GenericEntry*) pContentList->GetItemData(idx); + int count = pContentList->GetItemCount(); + for (int idx = 0; idx < count; idx++) { + GenericEntry* pEntry = (GenericEntry*) pContentList->GetItemData(idx); - AddToSet(pEntry, threadMask); - } + AddToSet(pEntry, threadMask); + } } /* @@ -1232,50 +1232,50 @@ SelectionSet::CreateFromAll(ContentList* pContentList, int threadMask) void SelectionSet::AddToSet(GenericEntry* pEntry, int threadMask) { - SelectionEntry* pSelEntry; + SelectionEntry* pSelEntry; - //WMSG1(" Sel '%s'\n", pEntry->GetPathName()); + //WMSG1(" Sel '%s'\n", pEntry->GetPathName()); - if (!(threadMask & GenericEntry::kAllowVolumeDir) && - pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir) - { - /* only include volume dir if specifically requested */ - //WMSG1(" Excluding volume dir '%s' from set\n", pEntry->GetPathName()); - return; - } + if (!(threadMask & GenericEntry::kAllowVolumeDir) && + pEntry->GetRecordKind() == GenericEntry::kRecordKindVolumeDir) + { + /* only include volume dir if specifically requested */ + //WMSG1(" Excluding volume dir '%s' from set\n", pEntry->GetPathName()); + return; + } - if (!(threadMask & GenericEntry::kAllowDirectory) && - pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory) - { - /* only include directories if specifically requested */ - //WMSG1(" Excluding folder '%s' from set\n", pEntry->GetPathName()); - return; - } + if (!(threadMask & GenericEntry::kAllowDirectory) && + pEntry->GetRecordKind() == GenericEntry::kRecordKindDirectory) + { + /* only include directories if specifically requested */ + //WMSG1(" Excluding folder '%s' from set\n", pEntry->GetPathName()); + return; + } - if (!(threadMask & GenericEntry::kAllowDamaged) && pEntry->GetDamaged()) - { - /* only include "damaged" files if specifically requested */ - return; - } + if (!(threadMask & GenericEntry::kAllowDamaged) && pEntry->GetDamaged()) + { + /* only include "damaged" files if specifically requested */ + return; + } - bool doAdd = false; + bool doAdd = false; - if (threadMask & GenericEntry::kAnyThread) - doAdd = true; + if (threadMask & GenericEntry::kAnyThread) + doAdd = true; - if ((threadMask & GenericEntry::kCommentThread) && pEntry->GetHasComment()) - doAdd = true; - if ((threadMask & GenericEntry::kDataThread) && pEntry->GetHasDataFork()) - doAdd = true; - if ((threadMask & GenericEntry::kRsrcThread) && pEntry->GetHasRsrcFork()) - doAdd = true; - if ((threadMask & GenericEntry::kDiskImageThread) && pEntry->GetHasDiskImage()) - doAdd = true; + if ((threadMask & GenericEntry::kCommentThread) && pEntry->GetHasComment()) + doAdd = true; + if ((threadMask & GenericEntry::kDataThread) && pEntry->GetHasDataFork()) + doAdd = true; + if ((threadMask & GenericEntry::kRsrcThread) && pEntry->GetHasRsrcFork()) + doAdd = true; + if ((threadMask & GenericEntry::kDiskImageThread) && pEntry->GetHasDiskImage()) + doAdd = true; - if (doAdd) { - pSelEntry = new SelectionEntry(pEntry); - AddEntry(pSelEntry); - } + if (doAdd) { + pSelEntry = new SelectionEntry(pEntry); + AddEntry(pSelEntry); + } } /* @@ -1284,22 +1284,22 @@ SelectionSet::AddToSet(GenericEntry* pEntry, int threadMask) void SelectionSet::AddEntry(SelectionEntry* pEntry) { - if (fEntryHead == nil) { - ASSERT(fEntryTail == nil); - fEntryHead = pEntry; - fEntryTail = pEntry; - ASSERT(pEntry->GetPrev() == nil); - ASSERT(pEntry->GetNext() == nil); - } else { - ASSERT(fEntryTail != nil); - ASSERT(pEntry->GetPrev() == nil); - pEntry->SetPrev(fEntryTail); - ASSERT(fEntryTail->GetNext() == nil); - fEntryTail->SetNext(pEntry); - fEntryTail = pEntry; - } + if (fEntryHead == nil) { + ASSERT(fEntryTail == nil); + fEntryHead = pEntry; + fEntryTail = pEntry; + ASSERT(pEntry->GetPrev() == nil); + ASSERT(pEntry->GetNext() == nil); + } else { + ASSERT(fEntryTail != nil); + ASSERT(pEntry->GetPrev() == nil); + pEntry->SetPrev(fEntryTail); + ASSERT(fEntryTail->GetNext() == nil); + fEntryTail->SetNext(pEntry); + fEntryTail = pEntry; + } - fNumEntries++; + fNumEntries++; } /* @@ -1308,17 +1308,17 @@ SelectionSet::AddEntry(SelectionEntry* pEntry) void SelectionSet::DeleteEntries(void) { - SelectionEntry* pEntry; - SelectionEntry* pNext; + SelectionEntry* pEntry; + SelectionEntry* pNext; - WMSG0("Deleting selection entries\n"); + WMSG0("Deleting selection entries\n"); - pEntry = GetEntries(); - while (pEntry != nil) { - pNext = pEntry->GetNext(); - delete pEntry; - pEntry = pNext; - } + pEntry = GetEntries(); + while (pEntry != nil) { + pNext = pEntry->GetNext(); + delete pEntry; + pEntry = pNext; + } } /* @@ -1327,21 +1327,21 @@ SelectionSet::DeleteEntries(void) int SelectionSet::CountMatchingPrefix(const char* prefix) { - SelectionEntry* pEntry; - int count = 0; - int len = strlen(prefix); - ASSERT(len > 0); + SelectionEntry* pEntry; + int count = 0; + int len = strlen(prefix); + ASSERT(len > 0); - pEntry = GetEntries(); - while (pEntry != nil) { - GenericEntry* pGeneric = pEntry->GetEntry(); + pEntry = GetEntries(); + while (pEntry != nil) { + GenericEntry* pGeneric = pEntry->GetEntry(); - if (strncasecmp(prefix, pGeneric->GetDisplayName(), len) == 0) - count++; - pEntry = pEntry->GetNext(); - } + if (strncasecmp(prefix, pGeneric->GetDisplayName(), len) == 0) + count++; + pEntry = pEntry->GetNext(); + } - return count; + return count; } /* @@ -1350,13 +1350,13 @@ SelectionSet::CountMatchingPrefix(const char* prefix) void SelectionSet::Dump(void) { - const SelectionEntry* pEntry; + const SelectionEntry* pEntry; - WMSG1("SelectionSet: %d entries\n", fNumEntries); + WMSG1("SelectionSet: %d entries\n", fNumEntries); - pEntry = fEntryHead; - while (pEntry != nil) { - WMSG1(" : name='%s'\n", pEntry->GetEntry()->GetPathName()); - pEntry = pEntry->GetNext(); - } + pEntry = fEntryHead; + while (pEntry != nil) { + WMSG1(" : name='%s'\n", pEntry->GetEntry()->GetPathName()); + pEntry = pEntry->GetNext(); + } } diff --git a/app/GenericArchive.h b/app/GenericArchive.h index 43f4237..61b62ed 100644 --- a/app/GenericArchive.h +++ b/app/GenericArchive.h @@ -39,11 +39,11 @@ const int kFileTypeBAS = 0xfc; * Set of data allowed in file property "set file info" calls. */ typedef struct FileProps { - unsigned long fileType; - unsigned long auxType; - unsigned long access; - time_t createWhen; - time_t modWhen; + unsigned long fileType; + unsigned long auxType; + unsigned long access; + time_t createWhen; + time_t modWhen; } FileProps; /* @@ -51,22 +51,22 @@ typedef struct FileProps { */ class XferFileOptions { public: - XferFileOptions(void) : - fTarget(nil), fPreserveEmptyFolders(false), fpTargetFS(nil) - {} - ~XferFileOptions(void) {} + XferFileOptions(void) : + fTarget(nil), fPreserveEmptyFolders(false), fpTargetFS(nil) + {} + ~XferFileOptions(void) {} - /* where the stuff is going */ - GenericArchive* fTarget; + /* where the stuff is going */ + GenericArchive* fTarget; - /* these really only have meaning when converting disk to file */ - //bool fConvDOSText; - //bool fConvPascalText; - bool fPreserveEmptyFolders; + /* these really only have meaning when converting disk to file */ + //bool fConvDOSText; + //bool fConvPascalText; + bool fPreserveEmptyFolders; - /* only useful when converting files to a disk image */ - //CString fStoragePrefix; - DiskImgLib::DiskFS* fpTargetFS; + /* only useful when converting files to a disk image */ + //CString fStoragePrefix; + DiskImgLib::DiskFS* fpTargetFS; }; @@ -80,198 +80,198 @@ public: */ class GenericEntry { public: - GenericEntry(void); - virtual ~GenericEntry(void); + GenericEntry(void); + virtual ~GenericEntry(void); - /* kinds of files found in archives */ - enum RecordKind { - kRecordKindUnknown = 0, - kRecordKindDisk, - kRecordKindFile, - kRecordKindForkedFile, - kRecordKindDirectory, - kRecordKindVolumeDir, - }; - /* - * Threads we will view or extract (threadMask). This is no longer used - * for viewing files, but still plays a role when extracting. - */ - enum { - // create one entry for each matching thread - kDataThread = 0x01, - kRsrcThread = 0x02, - kDiskImageThread = 0x04, - kCommentThread = 0x08, + /* kinds of files found in archives */ + enum RecordKind { + kRecordKindUnknown = 0, + kRecordKindDisk, + kRecordKindFile, + kRecordKindForkedFile, + kRecordKindDirectory, + kRecordKindVolumeDir, + }; + /* + * Threads we will view or extract (threadMask). This is no longer used + * for viewing files, but still plays a role when extracting. + */ + enum { + // create one entry for each matching thread + kDataThread = 0x01, + kRsrcThread = 0x02, + kDiskImageThread = 0x04, + kCommentThread = 0x08, - // grab any of the above threads - kAnyThread = 0x10, + // grab any of the above threads + kAnyThread = 0x10, - // set this if we allow matches on directory entries - kAllowDirectory = 0x20, + // set this if we allow matches on directory entries + kAllowDirectory = 0x20, - // and volume directory entries - kAllowVolumeDir = 0x40, + // and volume directory entries + kAllowVolumeDir = 0x40, - // set to include "damaged" files - kAllowDamaged = 0x80, - }; - /* EOL conversion mode for threads being extracted */ - typedef enum ConvertEOL { - kConvertUnknown = 0, kConvertEOLOff, kConvertEOLOn, kConvertEOLAuto - } ConvertEOL; - typedef enum EOLType { - kEOLUnknown = 0, kEOLCR, kEOLLF, kEOLCRLF - }; - /* high ASCII conversion mode for threads being extracted */ - typedef enum ConvertHighASCII { - kConvertHAUnknown = 0, kConvertHAOff, kConvertHAOn, kConvertHAAuto - } ConvertHighASCII; + // set to include "damaged" files + kAllowDamaged = 0x80, + }; + /* EOL conversion mode for threads being extracted */ + typedef enum ConvertEOL { + kConvertUnknown = 0, kConvertEOLOff, kConvertEOLOn, kConvertEOLAuto + } ConvertEOL; + typedef enum EOLType { + kEOLUnknown = 0, kEOLCR, kEOLLF, kEOLCRLF + }; + /* high ASCII conversion mode for threads being extracted */ + typedef enum ConvertHighASCII { + kConvertHAUnknown = 0, kConvertHAOff, kConvertHAOn, kConvertHAAuto + } ConvertHighASCII; - /* ProDOS access flags, used for all filesystems */ - enum { - kAccessRead = 0x01, - kAccessWrite = 0x02, - kAccessInvisible = 0x04, - kAccessBackup = 0x20, - kAccessRename = 0x40, - kAccessDelete = 0x80 - }; + /* ProDOS access flags, used for all filesystems */ + enum { + kAccessRead = 0x01, + kAccessWrite = 0x02, + kAccessInvisible = 0x04, + kAccessBackup = 0x20, + kAccessRename = 0x40, + kAccessDelete = 0x80 + }; - /* features supported by underlying archive */ - typedef enum Feature { - kFeatureCanChangeType, - kFeaturePascalTypes, - kFeatureDOSTypes, - kFeatureHFSTypes, - kFeatureHasFullAccess, - kFeatureHasSimpleAccess, // mutually exclusive with FullAccess - kFeatureHasInvisibleFlag, - } Feature; + /* features supported by underlying archive */ + typedef enum Feature { + kFeatureCanChangeType, + kFeaturePascalTypes, + kFeatureDOSTypes, + kFeatureHFSTypes, + kFeatureHasFullAccess, + kFeatureHasSimpleAccess, // mutually exclusive with FullAccess + kFeatureHasInvisibleFlag, + } Feature; - // retrieve thread (or filesystem) data - virtual int ExtractThreadToBuffer(int which, char** ppText, long* pLength, - CString* pErrMsg) const = 0; - virtual int ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, - ConvertHighASCII convHA, CString* pErrMsg) const = 0; + // retrieve thread (or filesystem) data + virtual int ExtractThreadToBuffer(int which, char** ppText, long* pLength, + CString* pErrMsg) const = 0; + virtual int ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, + ConvertHighASCII convHA, CString* pErrMsg) const = 0; - // This helps us retain the ContentList selection across a Reload(). Only - // necessary for read-write archives, since those are the only ones that - // ever need to be reloaded. Value must be nonzero to be used. - virtual long GetSelectionSerial(void) const = 0; + // This helps us retain the ContentList selection across a Reload(). Only + // necessary for read-write archives, since those are the only ones that + // ever need to be reloaded. Value must be nonzero to be used. + virtual long GetSelectionSerial(void) const = 0; - /* are we allowed to change the file/aux type of this entry? */ - /* (may need to generalize this to "changeable attrs" bitmask) */ - virtual bool GetFeatureFlag(Feature feature) const = 0; + /* are we allowed to change the file/aux type of this entry? */ + /* (may need to generalize this to "changeable attrs" bitmask) */ + virtual bool GetFeatureFlag(Feature feature) const = 0; - long GetIndex(void) const { return fIndex; } - void SetIndex(long idx) { fIndex = idx; } + long GetIndex(void) const { return fIndex; } + void SetIndex(long idx) { fIndex = idx; } - const char* GetPathName(void) const { return fPathName; } - void SetPathName(const char* path); - const char* GetFileName(void); - const char* GetFileNameExtension(void); // returns e.g. ".SHK" - void SetSubVolName(const char* name); - const char* GetSubVolName(void) const { return fSubVolName; } - const char* GetDisplayName(void) const; // not really "const" + const char* GetPathName(void) const { return fPathName; } + void SetPathName(const char* path); + const char* GetFileName(void); + const char* GetFileNameExtension(void); // returns e.g. ".SHK" + void SetSubVolName(const char* name); + const char* GetSubVolName(void) const { return fSubVolName; } + const char* GetDisplayName(void) const; // not really "const" - char GetFssep(void) const { return fFssep; } - void SetFssep(char fssep) { fFssep = fssep; } - long GetFileType(void) const { return fFileType; } - void SetFileType(long type) { fFileType = type; } - long GetAuxType(void) const { return fAuxType; } - void SetAuxType(long type) { fAuxType = type; } - long GetAccess(void) const { return fAccess; } - void SetAccess(long access) { fAccess = access; } - time_t GetCreateWhen(void) const { return fCreateWhen; } - void SetCreateWhen(time_t when) { fCreateWhen = when; } - time_t GetModWhen(void) const { return fModWhen; } - void SetModWhen(time_t when) { fModWhen = when; } - RecordKind GetRecordKind(void) const { return fRecordKind; } - void SetRecordKind(RecordKind recordKind) { fRecordKind = recordKind; } - const char* GetFormatStr(void) const { return fFormatStr; } - void SetFormatStr(const char* str) { fFormatStr = str; } // arg not copied, must be static! - LONGLONG GetCompressedLen(void) const { return fCompressedLen; } - void SetCompressedLen(LONGLONG len) { fCompressedLen = len; } - LONGLONG GetUncompressedLen(void) const { - return fDataForkLen + fRsrcForkLen; - } - //void SetUncompressedLen(LONGLONG len) { fUncompressedLen = len; } - LONGLONG GetDataForkLen(void) const { return fDataForkLen; } - void SetDataForkLen(LONGLONG len) { fDataForkLen = len; } - LONGLONG GetRsrcForkLen(void) const { return fRsrcForkLen; } - void SetRsrcForkLen(LONGLONG len) { fRsrcForkLen = len; } + char GetFssep(void) const { return fFssep; } + void SetFssep(char fssep) { fFssep = fssep; } + long GetFileType(void) const { return fFileType; } + void SetFileType(long type) { fFileType = type; } + long GetAuxType(void) const { return fAuxType; } + void SetAuxType(long type) { fAuxType = type; } + long GetAccess(void) const { return fAccess; } + void SetAccess(long access) { fAccess = access; } + time_t GetCreateWhen(void) const { return fCreateWhen; } + void SetCreateWhen(time_t when) { fCreateWhen = when; } + time_t GetModWhen(void) const { return fModWhen; } + void SetModWhen(time_t when) { fModWhen = when; } + RecordKind GetRecordKind(void) const { return fRecordKind; } + void SetRecordKind(RecordKind recordKind) { fRecordKind = recordKind; } + const char* GetFormatStr(void) const { return fFormatStr; } + void SetFormatStr(const char* str) { fFormatStr = str; } // arg not copied, must be static! + LONGLONG GetCompressedLen(void) const { return fCompressedLen; } + void SetCompressedLen(LONGLONG len) { fCompressedLen = len; } + LONGLONG GetUncompressedLen(void) const { + return fDataForkLen + fRsrcForkLen; + } + //void SetUncompressedLen(LONGLONG len) { fUncompressedLen = len; } + LONGLONG GetDataForkLen(void) const { return fDataForkLen; } + void SetDataForkLen(LONGLONG len) { fDataForkLen = len; } + LONGLONG GetRsrcForkLen(void) const { return fRsrcForkLen; } + void SetRsrcForkLen(LONGLONG len) { fRsrcForkLen = len; } - DiskImg::FSFormat GetSourceFS(void) const { return fSourceFS; } - void SetSourceFS(DiskImg::FSFormat fmt) { fSourceFS = fmt; } + DiskImg::FSFormat GetSourceFS(void) const { return fSourceFS; } + void SetSourceFS(DiskImg::FSFormat fmt) { fSourceFS = fmt; } - bool GetHasDataFork(void) const { return fHasDataFork; } - void SetHasDataFork(bool val) { fHasDataFork = val; } - bool GetHasRsrcFork(void) const { return fHasRsrcFork; } - void SetHasRsrcFork(bool val) { fHasRsrcFork = val; } - bool GetHasDiskImage(void) const { return fHasDiskImage; } - void SetHasDiskImage(bool val) { fHasDiskImage = val; } - bool GetHasComment(void) const { return fHasComment; } - void SetHasComment(bool val) { fHasComment = val; } - bool GetHasNonEmptyComment(void) const { return fHasNonEmptyComment; } - void SetHasNonEmptyComment(bool val) { fHasNonEmptyComment = val; } + bool GetHasDataFork(void) const { return fHasDataFork; } + void SetHasDataFork(bool val) { fHasDataFork = val; } + bool GetHasRsrcFork(void) const { return fHasRsrcFork; } + void SetHasRsrcFork(bool val) { fHasRsrcFork = val; } + bool GetHasDiskImage(void) const { return fHasDiskImage; } + void SetHasDiskImage(bool val) { fHasDiskImage = val; } + bool GetHasComment(void) const { return fHasComment; } + void SetHasComment(bool val) { fHasComment = val; } + bool GetHasNonEmptyComment(void) const { return fHasNonEmptyComment; } + void SetHasNonEmptyComment(bool val) { fHasNonEmptyComment = val; } - bool GetDamaged(void) const { return fDamaged; } - void SetDamaged(bool val) { fDamaged = val; } - bool GetSuspicious(void) const { return fSuspicious; } - void SetSuspicious(bool val) { fSuspicious = val; } + bool GetDamaged(void) const { return fDamaged; } + void SetDamaged(bool val) { fDamaged = val; } + bool GetSuspicious(void) const { return fSuspicious; } + void SetSuspicious(bool val) { fSuspicious = val; } - GenericEntry* GetPrev(void) const { return fpPrev; } - void SetPrev(GenericEntry* pEntry) { fpPrev = pEntry; } - GenericEntry* GetNext(void) const { return fpNext; } - void SetNext(GenericEntry* pEntry) { fpNext = pEntry; } + GenericEntry* GetPrev(void) const { return fpPrev; } + void SetPrev(GenericEntry* pEntry) { fpPrev = pEntry; } + GenericEntry* GetNext(void) const { return fpNext; } + void SetNext(GenericEntry* pEntry) { fpNext = pEntry; } - // Utility functions. - const char* GetFileTypeString(void) const; - static bool CheckHighASCII(const unsigned char* buffer, - unsigned long count); + // Utility functions. + const char* GetFileTypeString(void) const; + static bool CheckHighASCII(const unsigned char* buffer, + unsigned long count); - static ConvertEOL DetermineConversion(const unsigned char* buffer, - long count, EOLType* pSourceType, ConvertHighASCII* pConvHA); - static int GenericEntry::WriteConvert(FILE* fp, const char* buf, - size_t len, ConvertEOL* pConv, ConvertHighASCII* pConvHA, - bool* pLastCR); + static ConvertEOL DetermineConversion(const unsigned char* buffer, + long count, EOLType* pSourceType, ConvertHighASCII* pConvHA); + static int GenericEntry::WriteConvert(FILE* fp, const char* buf, + size_t len, ConvertEOL* pConv, ConvertHighASCII* pConvHA, + bool* pLastCR); protected: - static void SpacesToUnderscores(char* buf); + static void SpacesToUnderscores(char* buf); private: - char* fPathName; - const char* fFileName; // points within fPathName - const char* fFileNameExtension; // points within fPathName - char fFssep; - char* fSubVolName; // sub-volume prefix, or nil if none - char* fDisplayName; // combination of sub-vol and path - long fFileType; - long fAuxType; - long fAccess; - time_t fCreateWhen; - time_t fModWhen; - RecordKind fRecordKind; // forked file, disk image, ?? - const char* fFormatStr; // static str; compression or fs format - //LONGLONG fUncompressedLen; - LONGLONG fDataForkLen; // also for disk images - LONGLONG fRsrcForkLen; // set to 0 when nonexistent - LONGLONG fCompressedLen; // data/disk + rsrc - - DiskImg::FSFormat fSourceFS; // if DOS3.3, text files have funky format + char* fPathName; + const char* fFileName; // points within fPathName + const char* fFileNameExtension; // points within fPathName + char fFssep; + char* fSubVolName; // sub-volume prefix, or nil if none + char* fDisplayName; // combination of sub-vol and path + long fFileType; + long fAuxType; + long fAccess; + time_t fCreateWhen; + time_t fModWhen; + RecordKind fRecordKind; // forked file, disk image, ?? + const char* fFormatStr; // static str; compression or fs format + //LONGLONG fUncompressedLen; + LONGLONG fDataForkLen; // also for disk images + LONGLONG fRsrcForkLen; // set to 0 when nonexistent + LONGLONG fCompressedLen; // data/disk + rsrc + + DiskImg::FSFormat fSourceFS; // if DOS3.3, text files have funky format - bool fHasDataFork; - bool fHasRsrcFork; - bool fHasDiskImage; - bool fHasComment; - bool fHasNonEmptyComment; // set if fHasComment and it isn't empty + bool fHasDataFork; + bool fHasRsrcFork; + bool fHasDiskImage; + bool fHasComment; + bool fHasNonEmptyComment; // set if fHasComment and it isn't empty - bool fDamaged; // if set, don't try to open file - bool fSuspicious; // if set, file *might* be damaged + bool fDamaged; // if set, don't try to open file + bool fSuspicious; // if set, file *might* be damaged - long fIndex; // serial index, for sorting "unsorted" view - GenericEntry* fpPrev; - GenericEntry* fpNext; + long fIndex; // serial index, for sorting "unsorted" view + GenericEntry* fpPrev; + GenericEntry* fpNext; }; /* @@ -283,290 +283,290 @@ private: */ class GenericArchive { public: - GenericArchive(void) { - fPathName = nil; - fNumEntries = 0; - fEntryHead = fEntryTail = nil; - fReloadFlag = true; - //fEntryIndex = nil; - } - virtual ~GenericArchive(void) { - //WMSG0("Deleting GenericArchive\n"); - DeleteEntries(); - delete fPathName; - } + GenericArchive(void) { + fPathName = nil; + fNumEntries = 0; + fEntryHead = fEntryTail = nil; + fReloadFlag = true; + //fEntryIndex = nil; + } + virtual ~GenericArchive(void) { + //WMSG0("Deleting GenericArchive\n"); + DeleteEntries(); + delete fPathName; + } - virtual GenericEntry* GetEntries(void) const { - return fEntryHead; - } - virtual long GetNumEntries(void) const { - return fNumEntries; - } - //virtual GenericEntry* GetEntry(long num) { - // ASSERT(num >= 0 && num < fNumEntries); - // if (fEntryIndex == nil) - // CreateIndex(); - // return fEntryIndex[num]; - //} + virtual GenericEntry* GetEntries(void) const { + return fEntryHead; + } + virtual long GetNumEntries(void) const { + return fNumEntries; + } + //virtual GenericEntry* GetEntry(long num) { + // ASSERT(num >= 0 && num < fNumEntries); + // if (fEntryIndex == nil) + // CreateIndex(); + // return fEntryIndex[num]; + //} - typedef enum { - kResultUnknown = 0, - kResultSuccess, // open succeeded - kResultFailure, // open failed - kResultCancel, // open was cancelled by user - kResultFileArchive, // found a file archive rather than disk image - } OpenResult; + typedef enum { + kResultUnknown = 0, + kResultSuccess, // open succeeded + kResultFailure, // open failed + kResultCancel, // open was cancelled by user + kResultFileArchive, // found a file archive rather than disk image + } OpenResult; - // Open an archive and do fun things with the innards. - virtual OpenResult Open(const char* filename, bool readOnly, - CString* pErrMsg) = 0; - // Create a new archive with the specified name. - virtual CString New(const char* filename, const void* options) = 0; - // Flush any unwritten data to disk - virtual CString Flush(void) = 0; - // Force a re-read from the underlying storage. - virtual CString Reload(void) = 0; - // Do we allow modification? - virtual bool IsReadOnly(void) const = 0; - // Does the underlying storage have un-flushed modifications? - virtual bool IsModified(void) const = 0; + // Open an archive and do fun things with the innards. + virtual OpenResult Open(const char* filename, bool readOnly, + CString* pErrMsg) = 0; + // Create a new archive with the specified name. + virtual CString New(const char* filename, const void* options) = 0; + // Flush any unwritten data to disk + virtual CString Flush(void) = 0; + // Force a re-read from the underlying storage. + virtual CString Reload(void) = 0; + // Do we allow modification? + virtual bool IsReadOnly(void) const = 0; + // Does the underlying storage have un-flushed modifications? + virtual bool IsModified(void) const = 0; - virtual bool GetReloadFlag(void) { return fReloadFlag; } - virtual void ClearReloadFlag(void) { fReloadFlag = false; } + virtual bool GetReloadFlag(void) { return fReloadFlag; } + virtual void ClearReloadFlag(void) { fReloadFlag = false; } - // One of these for every sub-class. This is used to ensure that, should - // we need to down-cast an object, we did it correctly (without needing - // to include RTTI support). - typedef enum { - kArchiveUnknown = 0, - kArchiveNuFX, - kArchiveBNY, - kArchiveACU, - kArchiveDiskImage, - } ArchiveKind; - virtual ArchiveKind GetArchiveKind(void) = 0; + // One of these for every sub-class. This is used to ensure that, should + // we need to down-cast an object, we did it correctly (without needing + // to include RTTI support). + typedef enum { + kArchiveUnknown = 0, + kArchiveNuFX, + kArchiveBNY, + kArchiveACU, + kArchiveDiskImage, + } ArchiveKind; + virtual ArchiveKind GetArchiveKind(void) = 0; - // Get a nice description for the title bar. - virtual void GetDescription(CString* pStr) const = 0; + // Get a nice description for the title bar. + virtual void GetDescription(CString* pStr) const = 0; - // Do a bulk add. - virtual bool BulkAdd(ActionProgressDialog* pActionProgress, - const AddFilesDialog* pAddOpts) = 0; - // Do a disk add. - virtual bool AddDisk(ActionProgressDialog* pActionProgress, - const AddFilesDialog* pAddOpts) = 0; - // Create a subdirectory. - virtual bool CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry, - const char* newName) = 0; + // Do a bulk add. + virtual bool BulkAdd(ActionProgressDialog* pActionProgress, + const AddFilesDialog* pAddOpts) = 0; + // Do a disk add. + virtual bool AddDisk(ActionProgressDialog* pActionProgress, + const AddFilesDialog* pAddOpts) = 0; + // Create a subdirectory. + virtual bool CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry, + const char* newName) = 0; - // Test a set of files. - virtual bool TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) = 0; + // Test a set of files. + virtual bool TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) = 0; - // Delete a set of files. - virtual bool DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) = 0; + // Delete a set of files. + virtual bool DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) = 0; - // Rename a set of files. - virtual bool RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) = 0; - virtual CString TestPathName(const GenericEntry* pGenericEntry, - const CString& basePath, const CString& newName, char newFssep) const = 0; + // Rename a set of files. + virtual bool RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) = 0; + virtual CString TestPathName(const GenericEntry* pGenericEntry, + const CString& basePath, const CString& newName, char newFssep) const = 0; - // Rename a volume (or sub-volume) - virtual bool RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS, - const char* newName) = 0; - virtual CString TestVolumeName(const DiskFS* pDiskFS, - const char* newName) const = 0; + // Rename a volume (or sub-volume) + virtual bool RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS, + const char* newName) = 0; + virtual CString TestVolumeName(const DiskFS* pDiskFS, + const char* newName) const = 0; - // Recompress a set of files. - virtual bool RecompressSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, - const RecompressOptionsDialog* pRecompOpts) = 0; + // Recompress a set of files. + virtual bool RecompressSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, + const RecompressOptionsDialog* pRecompOpts) = 0; - // Transfer files out of this archive and into another. - typedef enum { - kXferOK = 0, kXferFailed = 1, kXferCancelled = 2, kXferOutOfSpace = 3 - } XferStatus; - virtual XferStatus XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, - ActionProgressDialog* pActionProgress, - const XferFileOptions* pXferOpts) = 0; + // Transfer files out of this archive and into another. + typedef enum { + kXferOK = 0, kXferFailed = 1, kXferCancelled = 2, kXferOutOfSpace = 3 + } XferStatus; + virtual XferStatus XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, + ActionProgressDialog* pActionProgress, + const XferFileOptions* pXferOpts) = 0; - // Get, set, or delete the comment on an entry. - virtual bool GetComment(CWnd* pMsgWnd, const GenericEntry* pEntry, - CString* pStr) = 0; - virtual bool SetComment(CWnd* pMsgWnd, GenericEntry* pEntry, - const CString& str) = 0; - virtual bool DeleteComment(CWnd* pMsgWnd, GenericEntry* pEntry) = 0; + // Get, set, or delete the comment on an entry. + virtual bool GetComment(CWnd* pMsgWnd, const GenericEntry* pEntry, + CString* pStr) = 0; + virtual bool SetComment(CWnd* pMsgWnd, GenericEntry* pEntry, + const CString& str) = 0; + virtual bool DeleteComment(CWnd* pMsgWnd, GenericEntry* pEntry) = 0; - // Set ProDOS file properties (e.g. file type, access flags). - virtual bool SetProps(CWnd* pMsgWnd, GenericEntry* pEntry, - const FileProps* pProps) = 0; + // Set ProDOS file properties (e.g. file type, access flags). + virtual bool SetProps(CWnd* pMsgWnd, GenericEntry* pEntry, + const FileProps* pProps) = 0; - // Preferences have changed, update library state as needed. - virtual void PreferencesChanged(void) = 0; + // Preferences have changed, update library state as needed. + virtual void PreferencesChanged(void) = 0; - // Determine an archive's capabilities. This is specific to the object - // instance, so this must not be made a static function. - typedef enum { - kCapUnknown = 0, + // Determine an archive's capabilities. This is specific to the object + // instance, so this must not be made a static function. + typedef enum { + kCapUnknown = 0, - kCapCanTest, // NuFX, BNY - kCapCanRenameFullPath, // NuFX, BNY - kCapCanRecompress, // NuFX, BNY - kCapCanEditComment, // NuFX - kCapCanAddDisk, // NuFX - kCapCanConvEOLOnAdd, // Disk - kCapCanCreateSubdir, // Disk - kCapCanRenameVolume, // Disk - } Capability; - virtual long GetCapability(Capability cap) = 0; + kCapCanTest, // NuFX, BNY + kCapCanRenameFullPath, // NuFX, BNY + kCapCanRecompress, // NuFX, BNY + kCapCanEditComment, // NuFX + kCapCanAddDisk, // NuFX + kCapCanConvEOLOnAdd, // Disk + kCapCanCreateSubdir, // Disk + kCapCanRenameVolume, // Disk + } Capability; + virtual long GetCapability(Capability cap) = 0; - // Get the pathname of the file we opened. - const char* GetPathName(void) const { return fPathName; } + // Get the pathname of the file we opened. + const char* GetPathName(void) const { return fPathName; } - // Generic utility function. - static CString GenDerivedTempName(const char* filename); - static int ComparePaths(const CString& name1, char fssep1, - const CString& name2, char fssep2); + // Generic utility function. + static CString GenDerivedTempName(const char* filename); + static int ComparePaths(const CString& name1, char fssep1, + const CString& name2, char fssep2); - void AddEntry(GenericEntry* pEntry); + void AddEntry(GenericEntry* pEntry); - /* - * This class holds details about a file that we're adding. - * - * It's based on the NuFileDetails class from NufxLib (which used to be - * used everywhere). - */ - class FileDetails { - public: - FileDetails(void); - virtual ~FileDetails(void) {} + /* + * This class holds details about a file that we're adding. + * + * It's based on the NuFileDetails class from NufxLib (which used to be + * used everywhere). + */ + class FileDetails { + public: + FileDetails(void); + virtual ~FileDetails(void) {} - /* - * Automatic cast to NuFileDetails. The NuFileDetails structure will - * have a pointer to at least one of our strings, so structures - * filled out this way need to be short-lived. (Yes, this is - * annoying, but it's how NufxLib works.) - */ - operator const NuFileDetails() const; + /* + * Automatic cast to NuFileDetails. The NuFileDetails structure will + * have a pointer to at least one of our strings, so structures + * filled out this way need to be short-lived. (Yes, this is + * annoying, but it's how NufxLib works.) + */ + operator const NuFileDetails() const; - /* - * Provide operator= and copy constructor. This'd be easier without - * the strings. - */ - FileDetails& operator=(const FileDetails& src) { - if (&src != this) - CopyFields(this, &src); - return *this; - } - FileDetails(const FileDetails& src) { - CopyFields(this, &src); - } + /* + * Provide operator= and copy constructor. This'd be easier without + * the strings. + */ + FileDetails& operator=(const FileDetails& src) { + if (&src != this) + CopyFields(this, &src); + return *this; + } + FileDetails(const FileDetails& src) { + CopyFields(this, &src); + } - /* - * What kind of file this is. Files being added to NuFX from Windows - * can't be "BothForks" because each the forks are stored in - * separate files. However, files being transferred from a NuFX - * archive, a disk image, or in from the clipboard can be both. - * - * (NOTE: this gets embedded into clipboard data. If you change - * these values, update the version info in Clipboard.cpp.) - */ - typedef enum FileKind { - kFileKindUnknown = 0, - kFileKindDataFork, - kFileKindRsrcFork, - kFileKindDiskImage, - kFileKindBothForks, - kFileKindDirectory, - } FileKind; + /* + * What kind of file this is. Files being added to NuFX from Windows + * can't be "BothForks" because each the forks are stored in + * separate files. However, files being transferred from a NuFX + * archive, a disk image, or in from the clipboard can be both. + * + * (NOTE: this gets embedded into clipboard data. If you change + * these values, update the version info in Clipboard.cpp.) + */ + typedef enum FileKind { + kFileKindUnknown = 0, + kFileKindDataFork, + kFileKindRsrcFork, + kFileKindDiskImage, + kFileKindBothForks, + kFileKindDirectory, + } FileKind; - /* - * Data fields. While transitioning from general use of NuFileDetails - * (v1.2.x to v2.0) I'm just going to leave these public. - */ - //NuThreadID threadID; /* data, rsrc, disk img? */ - FileKind entryKind; - CString origName; + /* + * Data fields. While transitioning from general use of NuFileDetails + * (v1.2.x to v2.0) I'm just going to leave these public. + */ + //NuThreadID threadID; /* data, rsrc, disk img? */ + FileKind entryKind; + CString origName; - CString storageName; /* normalized (NOT FS-normalized) */ - //NuFileSysID fileSysID; - DiskImg::FSFormat fileSysFmt; - unsigned short fileSysInfo; /* fssep lurks here */ - unsigned long access; - unsigned long fileType; - unsigned long extraType; - unsigned short storageType; /* "Unknown" or disk block size */ - NuDateTime createWhen; - NuDateTime modWhen; - NuDateTime archiveWhen; + CString storageName; /* normalized (NOT FS-normalized) */ + //NuFileSysID fileSysID; + DiskImg::FSFormat fileSysFmt; + unsigned short fileSysInfo; /* fssep lurks here */ + unsigned long access; + unsigned long fileType; + unsigned long extraType; + unsigned short storageType; /* "Unknown" or disk block size */ + NuDateTime createWhen; + NuDateTime modWhen; + NuDateTime archiveWhen; - private: - static void CopyFields(FileDetails* pDst, const FileDetails* pSrc); - }; + private: + static void CopyFields(FileDetails* pDst, const FileDetails* pSrc); + }; - // Transfer files, one at a time, into this archive from another. - virtual void XferPrepare(const XferFileOptions* pXferOpts) = 0; - virtual CString XferFile(FileDetails* pDetails, unsigned char** pDataBuf, - long dataLen, unsigned char** pRsrcBuf, long rsrcLen) = 0; - virtual void XferAbort(CWnd* pMsgWnd) = 0; - virtual void XferFinish(CWnd* pMsgWnd) = 0; - static void UNIXTimeToDateTime(const time_t* pWhen, NuDateTime *pDateTime); + // Transfer files, one at a time, into this archive from another. + virtual void XferPrepare(const XferFileOptions* pXferOpts) = 0; + virtual CString XferFile(FileDetails* pDetails, unsigned char** pDataBuf, + long dataLen, unsigned char** pRsrcBuf, long rsrcLen) = 0; + virtual void XferAbort(CWnd* pMsgWnd) = 0; + virtual void XferFinish(CWnd* pMsgWnd) = 0; + static void UNIXTimeToDateTime(const time_t* pWhen, NuDateTime *pDateTime); protected: - virtual void DeleteEntries(void); + virtual void DeleteEntries(void); - /* NuLib2-derived recursive directory add functions */ - void ReplaceFssep(char* str, char oldc, char newc, char newSubst); - NuError GetFileDetails(const AddFilesDialog* pAddOpts, const char* pathname, - struct stat* psb, FileDetails* pDetails); - Win32dirent* OpenDir(const char* name); - Win32dirent* ReadDir(Win32dirent* dir); - void CloseDir(Win32dirent* dir); - NuError Win32AddDirectory(const AddFilesDialog* pAddOpts, - const char* dirName, CString* pErrMsg); - NuError Win32AddFile(const AddFilesDialog* pAddOpts, - const char* pathname, CString* pErrMsg); - NuError AddFile(const AddFilesDialog* pAddOpts, const char* pathname, - CString* pErrMsg); + /* NuLib2-derived recursive directory add functions */ + void ReplaceFssep(char* str, char oldc, char newc, char newSubst); + NuError GetFileDetails(const AddFilesDialog* pAddOpts, const char* pathname, + struct stat* psb, FileDetails* pDetails); + Win32dirent* OpenDir(const char* name); + Win32dirent* ReadDir(Win32dirent* dir); + void CloseDir(Win32dirent* dir); + NuError Win32AddDirectory(const AddFilesDialog* pAddOpts, + const char* dirName, CString* pErrMsg); + NuError Win32AddFile(const AddFilesDialog* pAddOpts, + const char* pathname, CString* pErrMsg); + NuError AddFile(const AddFilesDialog* pAddOpts, const char* pathname, + CString* pErrMsg); - /* - * Each implementation must provide this. It's called from the generic - * AddFile function with the high-level add options, a partial pathname, - * and a FileDetails structure filled in using Win32 calls. - * - * One call to AddFile can result in multiple calls to DoAddFile if - * the subject of the AddFile call is a directory (and fIncludeSubdirs - * is set). - * - * DoAddFile is not called for subdirectories. The underlying code must - * create directories as needed. - * - * In some cases (such as renaming a file as it is being added) the - * information in "*pDetails" may be modified. - */ - virtual NuError DoAddFile(const AddFilesDialog* pAddOpts, - FileDetails* pDetails) = 0; + /* + * Each implementation must provide this. It's called from the generic + * AddFile function with the high-level add options, a partial pathname, + * and a FileDetails structure filled in using Win32 calls. + * + * One call to AddFile can result in multiple calls to DoAddFile if + * the subject of the AddFile call is a directory (and fIncludeSubdirs + * is set). + * + * DoAddFile is not called for subdirectories. The underlying code must + * create directories as needed. + * + * In some cases (such as renaming a file as it is being added) the + * information in "*pDetails" may be modified. + */ + virtual NuError DoAddFile(const AddFilesDialog* pAddOpts, + FileDetails* pDetails) = 0; - void SetPathName(const char* pathName) { - delete fPathName; - if (pathName != nil) { - fPathName = new char[strlen(pathName)+1]; - strcpy(fPathName, pathName); - } else - fPathName = nil; - } + void SetPathName(const char* pathName) { + delete fPathName; + if (pathName != nil) { + fPathName = new char[strlen(pathName)+1]; + strcpy(fPathName, pathName); + } else + fPathName = nil; + } - bool fReloadFlag; // set after Reload called + bool fReloadFlag; // set after Reload called private: - //virtual void CreateIndex(void); + //virtual void CreateIndex(void); - //CString fNewPathHolder; - //CString fOrigPathHolder; + //CString fNewPathHolder; + //CString fOrigPathHolder; - char* fPathName; - long fNumEntries; - GenericEntry* fEntryHead; - GenericEntry* fEntryTail; - //GenericEntry** fEntryIndex; + char* fPathName; + long fNumEntries; + GenericEntry* fEntryHead; + GenericEntry* fEntryTail; + //GenericEntry** fEntryIndex; }; /* @@ -574,35 +574,35 @@ private: */ class SelectionEntry { public: - SelectionEntry(GenericEntry* pEntry) { - fpEntry = pEntry; - //fThreadKind = threadKind; - //fFilter = filter; - //fReformatName = ""; - fpPrev = fpNext = nil; - } - ~SelectionEntry(void) {} + SelectionEntry(GenericEntry* pEntry) { + fpEntry = pEntry; + //fThreadKind = threadKind; + //fFilter = filter; + //fReformatName = ""; + fpPrev = fpNext = nil; + } + ~SelectionEntry(void) {} - int Reformat(ReformatHolder* pHolder); + int Reformat(ReformatHolder* pHolder); - GenericEntry* GetEntry(void) const { return fpEntry; } - //int GetThreadKind(void) const { return fThreadKind; } - //int GetFilter(void) const { return fFilter; } - //const char* GetReformatName(void) const { return fReformatName; } + GenericEntry* GetEntry(void) const { return fpEntry; } + //int GetThreadKind(void) const { return fThreadKind; } + //int GetFilter(void) const { return fFilter; } + //const char* GetReformatName(void) const { return fReformatName; } - SelectionEntry* GetPrev(void) const { return fpPrev; } - void SetPrev(SelectionEntry* pPrev) { fpPrev = pPrev; } - SelectionEntry* GetNext(void) const { return fpNext; } - void SetNext(SelectionEntry* pNext) { fpNext = pNext; } + SelectionEntry* GetPrev(void) const { return fpPrev; } + void SetPrev(SelectionEntry* pPrev) { fpPrev = pPrev; } + SelectionEntry* GetNext(void) const { return fpNext; } + void SetNext(SelectionEntry* pNext) { fpNext = pNext; } private: - GenericEntry* fpEntry; - //int fThreadKind; // data, rsrc, etc (threadMask) - //int fFilter; // fAllowedFilters, really - //const char* fReformatName; // name of formatting actually applied + GenericEntry* fpEntry; + //int fThreadKind; // data, rsrc, etc (threadMask) + //int fFilter; // fAllowedFilters, really + //const char* fReformatName; // name of formatting actually applied - SelectionEntry* fpPrev; - SelectionEntry* fpNext; + SelectionEntry* fpPrev; + SelectionEntry* fpNext; }; class ContentList; @@ -616,75 +616,75 @@ class ContentList; */ class SelectionSet { public: - SelectionSet(void) { - fNumEntries = 0; - fEntryHead = fEntryTail = fIterCurrent = nil; - } - ~SelectionSet(void) { - DeleteEntries(); - } + SelectionSet(void) { + fNumEntries = 0; + fEntryHead = fEntryTail = fIterCurrent = nil; + } + ~SelectionSet(void) { + DeleteEntries(); + } - // create the set from the selected members of a ContentList - void CreateFromSelection(ContentList* pContentList, int threadMask); - // create the set from all members of a ContentList - void CreateFromAll(ContentList* pContentList, int threadMask); + // create the set from the selected members of a ContentList + void CreateFromSelection(ContentList* pContentList, int threadMask); + // create the set from all members of a ContentList + void CreateFromAll(ContentList* pContentList, int threadMask); - // get the head of the list - SelectionEntry* GetEntries(void) const { return fEntryHead; } + // get the head of the list + SelectionEntry* GetEntries(void) const { return fEntryHead; } - void IterReset(void) { - fIterCurrent = nil; - } - // move to the next or previous entry as part of iterating - SelectionEntry* IterPrev(void) { - if (fIterCurrent == nil) - fIterCurrent = fEntryTail; - else - fIterCurrent = fIterCurrent->GetPrev(); - return fIterCurrent; - } - SelectionEntry* IterNext(void) { - if (fIterCurrent == nil) - fIterCurrent = fEntryHead; - else - fIterCurrent = fIterCurrent->GetNext(); - return fIterCurrent; - } - SelectionEntry* IterCurrent(void) { - return fIterCurrent; - } - bool IterHasPrev(void) const { - if (fIterCurrent == nil) - return fEntryTail != nil; - else - return (fIterCurrent->GetPrev() != nil); - } - bool IterHasNext(void) const { - if (fIterCurrent == nil) - return fEntryHead != nil; - else - return (fIterCurrent->GetNext() != nil); - } + void IterReset(void) { + fIterCurrent = nil; + } + // move to the next or previous entry as part of iterating + SelectionEntry* IterPrev(void) { + if (fIterCurrent == nil) + fIterCurrent = fEntryTail; + else + fIterCurrent = fIterCurrent->GetPrev(); + return fIterCurrent; + } + SelectionEntry* IterNext(void) { + if (fIterCurrent == nil) + fIterCurrent = fEntryHead; + else + fIterCurrent = fIterCurrent->GetNext(); + return fIterCurrent; + } + SelectionEntry* IterCurrent(void) { + return fIterCurrent; + } + bool IterHasPrev(void) const { + if (fIterCurrent == nil) + return fEntryTail != nil; + else + return (fIterCurrent->GetPrev() != nil); + } + bool IterHasNext(void) const { + if (fIterCurrent == nil) + return fEntryHead != nil; + else + return (fIterCurrent->GetNext() != nil); + } - int GetNumEntries(void) const { return fNumEntries; } + int GetNumEntries(void) const { return fNumEntries; } - // count the #of entries whose display name matches "prefix" - int CountMatchingPrefix(const char* prefix); + // count the #of entries whose display name matches "prefix" + int CountMatchingPrefix(const char* prefix); - // debug dump - void Dump(void); + // debug dump + void Dump(void); private: - void AddToSet(GenericEntry* pEntry, int threadMask); + void AddToSet(GenericEntry* pEntry, int threadMask); - void AddEntry(SelectionEntry* pEntry); - void DeleteEntries(void); + void AddEntry(SelectionEntry* pEntry); + void DeleteEntries(void); - int fNumEntries; - SelectionEntry* fIterCurrent; + int fNumEntries; + SelectionEntry* fIterCurrent; - SelectionEntry* fEntryHead; - SelectionEntry* fEntryTail; + SelectionEntry* fEntryHead; + SelectionEntry* fEntryTail; }; #endif /*__GENERIC_ARCHIVE__*/ \ No newline at end of file diff --git a/app/HelpTopics.h b/app/HelpTopics.h index 0a43fb9..14f649f 100644 --- a/app/HelpTopics.h +++ b/app/HelpTopics.h @@ -9,35 +9,35 @@ #ifndef __HELP_TOPICS__ #define __HELP_TOPICS__ -#define HELP_TOPIC_WELCOME 10 -#define HELP_TOPIC_DISKEDIT 13 -#define HELP_TOPIC_PREFS_GENERAL 19 -#define HELP_TOPIC_DISK_IMAGES 20 -#define HELP_TOPIC_PREFS_FVIEW 23 -#define HELP_TOPIC_CREDITS 24 -#define HELP_TOPIC_FILE_VIEWER 25 -#define HELP_TOPIC_PREFS_FILES 28 -#define HELP_TOPIC_PREFS_COMPRESSION 29 -#define HELP_TOPIC_CHOOSE_FOLDER 38 -#define HELP_TOPIC_EXT_OPTIONS 39 -#define HELP_TOPIC_ADD_FILES_DLG 41 -#define HELP_TOPIC_RENAME_ENTRY 42 -#define HELP_TOPIC_EDIT_COMMENT 43 -#define HELP_TOPIC_EDIT_ASSOC 44 -#define HELP_TOPIC_ORDERING_INFO 46 -#define HELP_TOPIC_ENTER_REG_DATA 49 -#define HELP_TOPIC_IMPORT_CASSETTE 111 -#define HELP_TOPIC_IMPORT_BASIC 112 -#define HELP_TOPIC_DISK_CONV 187 -#define HELP_TOPIC_EDIT_PROPS 203 -#define HELP_TOPIC_BULK_DISK_CONV 233 -#define HELP_TOPIC_OPEN_VOLUME 241 -#define HELP_TOPIC_VOLUME_COPIER 245 -#define HELP_TOPIC_IMAGE_CREATOR 247 -#define HELP_TOPIC_CHOOSE_TARGET 257 -#define HELP_TOPIC_ARCHIVE_INFO 258 -#define HELP_TOPIC_PREFS_DISK_IMAGE 259 -#define HELP_TOPIC_RENAME_VOLUME 268 -#define HELP_TOPIC_EOL_SCAN 272 +#define HELP_TOPIC_WELCOME 10 +#define HELP_TOPIC_DISKEDIT 13 +#define HELP_TOPIC_PREFS_GENERAL 19 +#define HELP_TOPIC_DISK_IMAGES 20 +#define HELP_TOPIC_PREFS_FVIEW 23 +#define HELP_TOPIC_CREDITS 24 +#define HELP_TOPIC_FILE_VIEWER 25 +#define HELP_TOPIC_PREFS_FILES 28 +#define HELP_TOPIC_PREFS_COMPRESSION 29 +#define HELP_TOPIC_CHOOSE_FOLDER 38 +#define HELP_TOPIC_EXT_OPTIONS 39 +#define HELP_TOPIC_ADD_FILES_DLG 41 +#define HELP_TOPIC_RENAME_ENTRY 42 +#define HELP_TOPIC_EDIT_COMMENT 43 +#define HELP_TOPIC_EDIT_ASSOC 44 +#define HELP_TOPIC_ORDERING_INFO 46 +#define HELP_TOPIC_ENTER_REG_DATA 49 +#define HELP_TOPIC_IMPORT_CASSETTE 111 +#define HELP_TOPIC_IMPORT_BASIC 112 +#define HELP_TOPIC_DISK_CONV 187 +#define HELP_TOPIC_EDIT_PROPS 203 +#define HELP_TOPIC_BULK_DISK_CONV 233 +#define HELP_TOPIC_OPEN_VOLUME 241 +#define HELP_TOPIC_VOLUME_COPIER 245 +#define HELP_TOPIC_IMAGE_CREATOR 247 +#define HELP_TOPIC_CHOOSE_TARGET 257 +#define HELP_TOPIC_ARCHIVE_INFO 258 +#define HELP_TOPIC_PREFS_DISK_IMAGE 259 +#define HELP_TOPIC_RENAME_VOLUME 268 +#define HELP_TOPIC_EOL_SCAN 272 #endif /*__HELP_TOPICS__*/ diff --git a/app/ImageFormatDialog.cpp b/app/ImageFormatDialog.cpp index 4049244..3d8f14a 100644 --- a/app/ImageFormatDialog.cpp +++ b/app/ImageFormatDialog.cpp @@ -13,8 +13,8 @@ BEGIN_MESSAGE_MAP(ImageFormatDialog, CDialog) - ON_BN_CLICKED(IDC_DECONF_HELP, OnHelp) - ON_WM_HELPINFO() + ON_BN_CLICKED(IDC_DECONF_HELP, OnHelp) + ON_WM_HELPINFO() END_MESSAGE_MAP() @@ -30,84 +30,84 @@ END_MESSAGE_MAP() * to get the text string. That way we'd be consistent. */ typedef struct ImageFormatDialog::ConvTable { - int enumval; // a DiskImg::enum type - const char* name; + int enumval; // a DiskImg::enum type + const char* name; } ConvTable; const int kLastEntry = -1; /* DiskImg::OuterFormat */ static const ConvTable gOuterFormats[] = { - { DiskImg::kOuterFormatUnknown, "Unknown format" }, - { DiskImg::kOuterFormatNone, "(none)" }, -// { DiskImg::kOuterFormatCompress, "UNIX compress" }, - { DiskImg::kOuterFormatGzip, "gzip" }, -// { DiskImg::kOuterFormatBzip2, "bzip2" }, - { DiskImg::kOuterFormatZip, "Zip archive" }, - { kLastEntry, nil } + { DiskImg::kOuterFormatUnknown, "Unknown format" }, + { DiskImg::kOuterFormatNone, "(none)" }, +// { DiskImg::kOuterFormatCompress, "UNIX compress" }, + { DiskImg::kOuterFormatGzip, "gzip" }, +// { DiskImg::kOuterFormatBzip2, "bzip2" }, + { DiskImg::kOuterFormatZip, "Zip archive" }, + { kLastEntry, nil } }; /* DiskImg::FileFormat */ static const ConvTable gFileFormats[] = { - { DiskImg::kFileFormatUnknown, "Unknown format" }, - { DiskImg::kFileFormatUnadorned, "Unadorned raw data" }, - { DiskImg::kFileFormat2MG, "2MG" }, - { DiskImg::kFileFormatNuFX, "NuFX (ShrinkIt)" }, - { DiskImg::kFileFormatDiskCopy42, "DiskCopy 4.2" }, -// { DiskImg::kFileFormatDiskCopy60, "DiskCopy 6.0" }, -// { DiskImg::kFileFormatDavex, "Davex volume image" }, - { DiskImg::kFileFormatSim2eHDV, "Sim //e HDV" }, - { DiskImg::kFileFormatDDD, "DDD" }, - { DiskImg::kFileFormatTrackStar, "TrackStar image" }, - { DiskImg::kFileFormatFDI, "FDI image" }, -// { DiskImg::kFileFormatDDDDeluxe, "DDDDeluxe" }, - { kLastEntry, nil } + { DiskImg::kFileFormatUnknown, "Unknown format" }, + { DiskImg::kFileFormatUnadorned, "Unadorned raw data" }, + { DiskImg::kFileFormat2MG, "2MG" }, + { DiskImg::kFileFormatNuFX, "NuFX (ShrinkIt)" }, + { DiskImg::kFileFormatDiskCopy42, "DiskCopy 4.2" }, +// { DiskImg::kFileFormatDiskCopy60, "DiskCopy 6.0" }, +// { DiskImg::kFileFormatDavex, "Davex volume image" }, + { DiskImg::kFileFormatSim2eHDV, "Sim //e HDV" }, + { DiskImg::kFileFormatDDD, "DDD" }, + { DiskImg::kFileFormatTrackStar, "TrackStar image" }, + { DiskImg::kFileFormatFDI, "FDI image" }, +// { DiskImg::kFileFormatDDDDeluxe, "DDDDeluxe" }, + { kLastEntry, nil } }; /* DiskImg::PhysicalFormat */ static const ConvTable gPhysicalFormats[] = { - { DiskImg::kPhysicalFormatUnknown, "Unknown format" }, - { DiskImg::kPhysicalFormatSectors, "Sectors" }, - { DiskImg::kPhysicalFormatNib525_6656, "Raw nibbles (6656-byte)" }, - { DiskImg::kPhysicalFormatNib525_6384, "Raw nibbles (6384-byte)" }, - { DiskImg::kPhysicalFormatNib525_Var, "Raw nibbles (variable len)" }, - { kLastEntry, nil } + { DiskImg::kPhysicalFormatUnknown, "Unknown format" }, + { DiskImg::kPhysicalFormatSectors, "Sectors" }, + { DiskImg::kPhysicalFormatNib525_6656, "Raw nibbles (6656-byte)" }, + { DiskImg::kPhysicalFormatNib525_6384, "Raw nibbles (6384-byte)" }, + { DiskImg::kPhysicalFormatNib525_Var, "Raw nibbles (variable len)" }, + { kLastEntry, nil } }; /* DiskImg::SectorOrder */ static const ConvTable gSectorOrders[] = { - { DiskImg::kSectorOrderUnknown, "Unknown ordering" }, - { DiskImg::kSectorOrderProDOS, "ProDOS block ordering" }, - { DiskImg::kSectorOrderDOS, "DOS sector ordering" }, - { DiskImg::kSectorOrderCPM, "CP/M block ordering" }, - { DiskImg::kSectorOrderPhysical, "Physical sector ordering" }, - { kLastEntry, nil } + { DiskImg::kSectorOrderUnknown, "Unknown ordering" }, + { DiskImg::kSectorOrderProDOS, "ProDOS block ordering" }, + { DiskImg::kSectorOrderDOS, "DOS sector ordering" }, + { DiskImg::kSectorOrderCPM, "CP/M block ordering" }, + { DiskImg::kSectorOrderPhysical, "Physical sector ordering" }, + { kLastEntry, nil } }; /* DiskImg::FSFormat */ static const ConvTable gFSFormats[] = { - { DiskImg::kFormatUnknown, "Unknown filesystem" }, - { DiskImg::kFormatGenericDOSOrd, "Generic DOS sectors" }, - { DiskImg::kFormatGenericProDOSOrd, "Generic ProDOS blocks" }, - { DiskImg::kFormatGenericPhysicalOrd, "Generic raw sectors" }, - { DiskImg::kFormatGenericCPMOrd, "Generic CP/M blocks" }, - { DiskImg::kFormatProDOS, "ProDOS" }, - { DiskImg::kFormatDOS33, "DOS 3.3" }, - { DiskImg::kFormatDOS32, "DOS 3.2" }, - { DiskImg::kFormatPascal, "Pascal" }, - { DiskImg::kFormatMacHFS, "HFS" }, -// { DiskImg::kFormatMacMFS, "MFS" }, -// { DiskImg::kFormatLisa, "Lisa" }, - { DiskImg::kFormatCPM, "CP/M" }, - { DiskImg::kFormatMSDOS, "MS-DOS FAT" }, -// { DiskImg::kFormatISO9660, "ISO-9660" }, - { DiskImg::kFormatUNIDOS, "UNIDOS (400K DOS x2)" }, - { DiskImg::kFormatOzDOS, "OzDOS (400K DOS x2)" }, - { DiskImg::kFormatCFFA4, "CFFA (4 or 6 partitions)" }, - { DiskImg::kFormatCFFA8, "CFFA (8 partitions)" }, - { DiskImg::kFormatMacPart, "Macintosh partitioned disk" }, - { DiskImg::kFormatMicroDrive, "MicroDrive partitioned disk" }, - { DiskImg::kFormatFocusDrive, "FocusDrive partitioned disk" }, - { DiskImg::kFormatRDOS33, "RDOS 3.3 (16-sector)" }, - { DiskImg::kFormatRDOS32, "RDOS 3.2 (13-sector)" }, - { DiskImg::kFormatRDOS3, "RDOS 3 (cracked 13-sector)" }, - { kLastEntry, nil } + { DiskImg::kFormatUnknown, "Unknown filesystem" }, + { DiskImg::kFormatGenericDOSOrd, "Generic DOS sectors" }, + { DiskImg::kFormatGenericProDOSOrd, "Generic ProDOS blocks" }, + { DiskImg::kFormatGenericPhysicalOrd, "Generic raw sectors" }, + { DiskImg::kFormatGenericCPMOrd, "Generic CP/M blocks" }, + { DiskImg::kFormatProDOS, "ProDOS" }, + { DiskImg::kFormatDOS33, "DOS 3.3" }, + { DiskImg::kFormatDOS32, "DOS 3.2" }, + { DiskImg::kFormatPascal, "Pascal" }, + { DiskImg::kFormatMacHFS, "HFS" }, +// { DiskImg::kFormatMacMFS, "MFS" }, +// { DiskImg::kFormatLisa, "Lisa" }, + { DiskImg::kFormatCPM, "CP/M" }, + { DiskImg::kFormatMSDOS, "MS-DOS FAT" }, +// { DiskImg::kFormatISO9660, "ISO-9660" }, + { DiskImg::kFormatUNIDOS, "UNIDOS (400K DOS x2)" }, + { DiskImg::kFormatOzDOS, "OzDOS (400K DOS x2)" }, + { DiskImg::kFormatCFFA4, "CFFA (4 or 6 partitions)" }, + { DiskImg::kFormatCFFA8, "CFFA (8 partitions)" }, + { DiskImg::kFormatMacPart, "Macintosh partitioned disk" }, + { DiskImg::kFormatMicroDrive, "MicroDrive partitioned disk" }, + { DiskImg::kFormatFocusDrive, "FocusDrive partitioned disk" }, + { DiskImg::kFormatRDOS33, "RDOS 3.3 (16-sector)" }, + { DiskImg::kFormatRDOS32, "RDOS 3.2 (13-sector)" }, + { DiskImg::kFormatRDOS3, "RDOS 3 (cracked 13-sector)" }, + { kLastEntry, nil } }; @@ -117,28 +117,28 @@ static const ConvTable gFSFormats[] = { void ImageFormatDialog::InitializeValues(const DiskImg* pImg) { - fOuterFormat = pImg->GetOuterFormat(); - fFileFormat = pImg->GetFileFormat(); - fPhysicalFormat = pImg->GetPhysicalFormat(); - fSectorOrder = pImg->GetSectorOrder(); - fFSFormat = pImg->GetFSFormat(); + fOuterFormat = pImg->GetOuterFormat(); + fFileFormat = pImg->GetFileFormat(); + fPhysicalFormat = pImg->GetPhysicalFormat(); + fSectorOrder = pImg->GetSectorOrder(); + fFSFormat = pImg->GetFSFormat(); - if (pImg->ShowAsBlocks()) - fDisplayFormat = kShowAsBlocks; - else - fDisplayFormat = kShowAsSectors; - if (!pImg->GetHasBlocks() && !pImg->GetHasSectors()) - fDisplayFormat = kShowAsNibbles; + if (pImg->ShowAsBlocks()) + fDisplayFormat = kShowAsBlocks; + else + fDisplayFormat = kShowAsSectors; + if (!pImg->GetHasBlocks() && !pImg->GetHasSectors()) + fDisplayFormat = kShowAsNibbles; - fHasSectors = pImg->GetHasSectors(); - fHasBlocks = pImg->GetHasBlocks(); - fHasNibbles = pImg->GetHasNibbles(); + fHasSectors = pImg->GetHasSectors(); + fHasBlocks = pImg->GetHasBlocks(); + fHasNibbles = pImg->GetHasNibbles(); - // "Unknown" formats default to sectors, but sometimes it's block-only - if (fDisplayFormat == kShowAsSectors && !fHasSectors) - fDisplayFormat = kShowAsBlocks; + // "Unknown" formats default to sectors, but sometimes it's block-only + if (fDisplayFormat == kShowAsSectors && !fHasSectors) + fDisplayFormat = kShowAsBlocks; - fInitialized = true; + fInitialized = true; } @@ -148,11 +148,11 @@ ImageFormatDialog::InitializeValues(const DiskImg* pImg) BOOL ImageFormatDialog::OnInitDialog(void) { - ASSERT(fInitialized); + ASSERT(fInitialized); - LoadComboBoxes(); + LoadComboBoxes(); - return CDialog::OnInitDialog(); // do DDX/DDV + return CDialog::OnInitDialog(); // do DDX/DDV } /* @@ -165,48 +165,48 @@ ImageFormatDialog::OnInitDialog(void) void ImageFormatDialog::LoadComboBoxes(void) { - CWnd* pWnd; - CButton* pButton; + CWnd* pWnd; + CButton* pButton; - pWnd = GetDlgItem(IDC_DECONF_SOURCE); - ASSERT(pWnd != nil); - pWnd->SetWindowText(fFileSource); + pWnd = GetDlgItem(IDC_DECONF_SOURCE); + ASSERT(pWnd != nil); + pWnd->SetWindowText(fFileSource); - if (fQueryDisplayFormat) { - pButton = (CButton*) GetDlgItem(IDC_DECONF_VIEWASSECTORS); - ASSERT(pButton != nil); - pButton->SetCheck(fDisplayFormat == kShowAsSectors); - if (!fHasSectors) - pButton->EnableWindow(FALSE); + if (fQueryDisplayFormat) { + pButton = (CButton*) GetDlgItem(IDC_DECONF_VIEWASSECTORS); + ASSERT(pButton != nil); + pButton->SetCheck(fDisplayFormat == kShowAsSectors); + if (!fHasSectors) + pButton->EnableWindow(FALSE); - pButton = (CButton*) GetDlgItem(IDC_DECONF_VIEWASBLOCKS); - ASSERT(pButton != nil); - pButton->SetCheck(fDisplayFormat == kShowAsBlocks); - if (!fHasBlocks) - pButton->EnableWindow(FALSE); + pButton = (CButton*) GetDlgItem(IDC_DECONF_VIEWASBLOCKS); + ASSERT(pButton != nil); + pButton->SetCheck(fDisplayFormat == kShowAsBlocks); + if (!fHasBlocks) + pButton->EnableWindow(FALSE); - pButton = (CButton*) GetDlgItem(IDC_DECONF_VIEWASNIBBLES); - ASSERT(pButton != nil); - pButton->SetCheck(fDisplayFormat == kShowAsNibbles); - if (!fHasNibbles) - pButton->EnableWindow(FALSE); - } else { - /* if we don't need to ask, don't show the buttons */ - pWnd = GetDlgItem(IDC_DECONF_VIEWAS); - pWnd->DestroyWindow(); - pWnd = GetDlgItem(IDC_DECONF_VIEWASBLOCKS); - pWnd->DestroyWindow(); - pWnd = GetDlgItem(IDC_DECONF_VIEWASSECTORS); - pWnd->DestroyWindow(); - pWnd = GetDlgItem(IDC_DECONF_VIEWASNIBBLES); - pWnd->DestroyWindow(); - } + pButton = (CButton*) GetDlgItem(IDC_DECONF_VIEWASNIBBLES); + ASSERT(pButton != nil); + pButton->SetCheck(fDisplayFormat == kShowAsNibbles); + if (!fHasNibbles) + pButton->EnableWindow(FALSE); + } else { + /* if we don't need to ask, don't show the buttons */ + pWnd = GetDlgItem(IDC_DECONF_VIEWAS); + pWnd->DestroyWindow(); + pWnd = GetDlgItem(IDC_DECONF_VIEWASBLOCKS); + pWnd->DestroyWindow(); + pWnd = GetDlgItem(IDC_DECONF_VIEWASSECTORS); + pWnd->DestroyWindow(); + pWnd = GetDlgItem(IDC_DECONF_VIEWASNIBBLES); + pWnd->DestroyWindow(); + } - LoadComboBox(IDC_DECONF_OUTERFORMAT, gOuterFormats, fOuterFormat); - LoadComboBox(IDC_DECONF_FILEFORMAT, gFileFormats, fFileFormat); - LoadComboBox(IDC_DECONF_PHYSICAL, gPhysicalFormats, fPhysicalFormat); - LoadComboBox(IDC_DECONF_SECTORORDER, gSectorOrders, fSectorOrder); - LoadComboBox(IDC_DECONF_FSFORMAT, gFSFormats, fFSFormat); + LoadComboBox(IDC_DECONF_OUTERFORMAT, gOuterFormats, fOuterFormat); + LoadComboBox(IDC_DECONF_FILEFORMAT, gFileFormats, fFileFormat); + LoadComboBox(IDC_DECONF_PHYSICAL, gPhysicalFormats, fPhysicalFormat); + LoadComboBox(IDC_DECONF_SECTORORDER, gSectorOrders, fSectorOrder); + LoadComboBox(IDC_DECONF_FSFORMAT, gFSFormats, fFSFormat); } /* @@ -216,41 +216,41 @@ ImageFormatDialog::LoadComboBoxes(void) void ImageFormatDialog::LoadComboBox(int boxID, const ConvTable* pTable, int dflt) { - CComboBox* pCombo; -// const ConvTable* pBaseTable = pTable; - int current = -1; - int idx, idxShift; + CComboBox* pCombo; +// const ConvTable* pBaseTable = pTable; + int current = -1; + int idx, idxShift; - pCombo = (CComboBox*) GetDlgItem(boxID); - ASSERT(pCombo != nil); + pCombo = (CComboBox*) GetDlgItem(boxID); + ASSERT(pCombo != nil); - idx = idxShift = 0; - while (pTable[idx].enumval != kLastEntry) { - /* special-case the generic FS formats */ - if (pTable == gFSFormats && !fAllowGenericFormats && - DiskImg::IsGenericFormat((DiskImg::FSFormat)pTable[idx].enumval)) - { - WMSG1("LoadComboBox skipping '%s'\n", pTable[idx].name); - idxShift++; - } else { - // Note to self: AddString returns the combo box item ID; - // should probably use that instead of doing math. - pCombo->AddString(pTable[idx].name); - pCombo->SetItemData(idx - idxShift, pTable[idx].enumval); - } + idx = idxShift = 0; + while (pTable[idx].enumval != kLastEntry) { + /* special-case the generic FS formats */ + if (pTable == gFSFormats && !fAllowGenericFormats && + DiskImg::IsGenericFormat((DiskImg::FSFormat)pTable[idx].enumval)) + { + WMSG1("LoadComboBox skipping '%s'\n", pTable[idx].name); + idxShift++; + } else { + // Note to self: AddString returns the combo box item ID; + // should probably use that instead of doing math. + pCombo->AddString(pTable[idx].name); + pCombo->SetItemData(idx - idxShift, pTable[idx].enumval); + } - if (pTable[idx].enumval == dflt) - current = idx - idxShift; + if (pTable[idx].enumval == dflt) + current = idx - idxShift; - idx++; - } + idx++; + } - if (current != -1) { - WMSG3(" Set default for %d/%d to %d\n", boxID, dflt, current); - pCombo->SetCurSel(current); - } else { - WMSG2(" No matching default for %d (%d)\n", boxID, dflt); - } + if (current != -1) { + WMSG3(" Set default for %d/%d to %d\n", boxID, dflt, current); + pCombo->SetCurSel(current); + } else { + WMSG2(" No matching default for %d (%d)\n", boxID, dflt); + } } @@ -260,31 +260,31 @@ ImageFormatDialog::LoadComboBox(int boxID, const ConvTable* pTable, int dflt) int ImageFormatDialog::ConvComboSel(int boxID, const ConvTable* pTable) { - CComboBox* pCombo; - int idx, enumval; + CComboBox* pCombo; + int idx, enumval; - pCombo = (CComboBox*) GetDlgItem(boxID); - ASSERT(pCombo != nil); - idx = pCombo->GetCurSel(); + pCombo = (CComboBox*) GetDlgItem(boxID); + ASSERT(pCombo != nil); + idx = pCombo->GetCurSel(); - if (idx < 0) { - /* nothing selected?! */ - ASSERT(false); - return 0; - } + if (idx < 0) { + /* nothing selected?! */ + ASSERT(false); + return 0; + } -// enumval = pTable[idx].enumval; - enumval = pCombo->GetItemData(idx); - ASSERT(enumval >= 0 && enumval < 100); +// enumval = pTable[idx].enumval; + enumval = pCombo->GetItemData(idx); + ASSERT(enumval >= 0 && enumval < 100); - if (pTable != gFSFormats) { - ASSERT(enumval == pTable[idx].enumval); - } + if (pTable != gFSFormats) { + ASSERT(enumval == pTable[idx].enumval); + } - WMSG3(" Returning ev=%d for %d entry '%s'\n", - enumval, boxID, pTable[idx].name); + WMSG3(" Returning ev=%d for %d entry '%s'\n", + enumval, boxID, pTable[idx].name); - return enumval; + return enumval; } /* @@ -294,48 +294,48 @@ ImageFormatDialog::ConvComboSel(int boxID, const ConvTable* pTable) void ImageFormatDialog::OnOK(void) { - CButton* pButton; + CButton* pButton; - if (fQueryDisplayFormat) { - pButton = (CButton*) GetDlgItem(IDC_DECONF_VIEWASSECTORS); - ASSERT(pButton != nil); - if (pButton->GetCheck()) - fDisplayFormat = kShowAsSectors; + if (fQueryDisplayFormat) { + pButton = (CButton*) GetDlgItem(IDC_DECONF_VIEWASSECTORS); + ASSERT(pButton != nil); + if (pButton->GetCheck()) + fDisplayFormat = kShowAsSectors; - pButton = (CButton*) GetDlgItem(IDC_DECONF_VIEWASBLOCKS); - ASSERT(pButton != nil); - if (pButton->GetCheck()) - fDisplayFormat = kShowAsBlocks; + pButton = (CButton*) GetDlgItem(IDC_DECONF_VIEWASBLOCKS); + ASSERT(pButton != nil); + if (pButton->GetCheck()) + fDisplayFormat = kShowAsBlocks; - pButton = (CButton*) GetDlgItem(IDC_DECONF_VIEWASNIBBLES); - ASSERT(pButton != nil); - if (pButton->GetCheck()) - fDisplayFormat = kShowAsNibbles; - } + pButton = (CButton*) GetDlgItem(IDC_DECONF_VIEWASNIBBLES); + ASSERT(pButton != nil); + if (pButton->GetCheck()) + fDisplayFormat = kShowAsNibbles; + } - /* outer format, file format, and physical format are immutable */ + /* outer format, file format, and physical format are immutable */ - fSectorOrder = (DiskImg::SectorOrder) - ConvComboSel(IDC_DECONF_SECTORORDER, gSectorOrders); - fFSFormat = (DiskImg::FSFormat) - ConvComboSel(IDC_DECONF_FSFORMAT, gFSFormats); + fSectorOrder = (DiskImg::SectorOrder) + ConvComboSel(IDC_DECONF_SECTORORDER, gSectorOrders); + fFSFormat = (DiskImg::FSFormat) + ConvComboSel(IDC_DECONF_FSFORMAT, gFSFormats); - if (fSectorOrder == DiskImg::kSectorOrderUnknown) { - MessageBox("You must choose a sector ordering.", "Error", - MB_OK | MB_ICONEXCLAMATION); - return; - } + if (fSectorOrder == DiskImg::kSectorOrderUnknown) { + MessageBox("You must choose a sector ordering.", "Error", + MB_OK | MB_ICONEXCLAMATION); + return; + } - if (fFSFormat == DiskImg::kFormatUnknown && - !fAllowUnknown) - { - MessageBox("You must choose a filesystem format. If not known," - " use one of the 'generic' entries.", - "Error", MB_OK | MB_ICONEXCLAMATION); - return; - } + if (fFSFormat == DiskImg::kFormatUnknown && + !fAllowUnknown) + { + MessageBox("You must choose a filesystem format. If not known," + " use one of the 'generic' entries.", + "Error", MB_OK | MB_ICONEXCLAMATION); + return; + } - CDialog::OnOK(); + CDialog::OnOK(); } /* @@ -345,8 +345,8 @@ ImageFormatDialog::OnOK(void) BOOL ImageFormatDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp(lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // indicate success?? + WinHelp(lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // indicate success?? } /* @@ -355,5 +355,5 @@ ImageFormatDialog::OnHelpInfo(HELPINFO* lpHelpInfo) void ImageFormatDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_DISK_IMAGES, HELP_CONTEXT); + WinHelp(HELP_TOPIC_DISK_IMAGES, HELP_CONTEXT); } diff --git a/app/ImageFormatDialog.h b/app/ImageFormatDialog.h index 1328599..58febaf 100644 --- a/app/ImageFormatDialog.h +++ b/app/ImageFormatDialog.h @@ -20,62 +20,62 @@ using namespace DiskImgLib; */ class ImageFormatDialog : public CDialog { public: - ImageFormatDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_DECONF, pParentWnd) - { - fInitialized = false; - fFileSource = ""; - fAllowUnknown = false; - fOuterFormat = DiskImg::kOuterFormatUnknown; - fFileFormat = DiskImg::kFileFormatUnknown; - fPhysicalFormat = DiskImg::kPhysicalFormatUnknown; - fSectorOrder = DiskImg::kSectorOrderUnknown; - fFSFormat = DiskImg::kFormatUnknown; - fDisplayFormat = kShowAsBlocks; + ImageFormatDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_DECONF, pParentWnd) + { + fInitialized = false; + fFileSource = ""; + fAllowUnknown = false; + fOuterFormat = DiskImg::kOuterFormatUnknown; + fFileFormat = DiskImg::kFileFormatUnknown; + fPhysicalFormat = DiskImg::kPhysicalFormatUnknown; + fSectorOrder = DiskImg::kSectorOrderUnknown; + fFSFormat = DiskImg::kFormatUnknown; + fDisplayFormat = kShowAsBlocks; - fQueryDisplayFormat = true; - fAllowGenericFormats = true; - fHasSectors = fHasBlocks = fHasNibbles = false; - } + fQueryDisplayFormat = true; + fAllowGenericFormats = true; + fHasSectors = fHasBlocks = fHasNibbles = false; + } - // initialize values from a DiskImg - void InitializeValues(const DiskImg* pImg); + // initialize values from a DiskImg + void InitializeValues(const DiskImg* pImg); - bool fInitialized; - CString fFileSource; - bool fAllowUnknown; // allow "unknown" choice? + bool fInitialized; + CString fFileSource; + bool fAllowUnknown; // allow "unknown" choice? - DiskImg::OuterFormat fOuterFormat; - DiskImg::FileFormat fFileFormat; - DiskImg::PhysicalFormat fPhysicalFormat; - DiskImg::SectorOrder fSectorOrder; - DiskImg::FSFormat fFSFormat; + DiskImg::OuterFormat fOuterFormat; + DiskImg::FileFormat fFileFormat; + DiskImg::PhysicalFormat fPhysicalFormat; + DiskImg::SectorOrder fSectorOrder; + DiskImg::FSFormat fFSFormat; - enum { kShowAsBlocks=0, kShowAsSectors=1, kShowAsNibbles=2 }; - int fDisplayFormat; + enum { kShowAsBlocks=0, kShowAsSectors=1, kShowAsNibbles=2 }; + int fDisplayFormat; - void SetQueryDisplayFormat(bool val) { fQueryDisplayFormat = val; } - void SetAllowGenericFormats(bool val) { fAllowGenericFormats = val; } + void SetQueryDisplayFormat(bool val) { fQueryDisplayFormat = val; } + void SetAllowGenericFormats(bool val) { fAllowGenericFormats = val; } protected: - //virtual void DoDataExchange(CDataExchange* pDX); - virtual BOOL OnInitDialog(void); - void OnOK(void); - afx_msg virtual void OnHelp(void); - afx_msg virtual BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + //virtual void DoDataExchange(CDataExchange* pDX); + virtual BOOL OnInitDialog(void); + void OnOK(void); + afx_msg virtual void OnHelp(void); + afx_msg virtual BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - struct ConvTable; - void LoadComboBoxes(void); - void LoadComboBox(int boxID, const ConvTable* pTable, int dflt); - int ConvComboSel(int boxID, const ConvTable* pTable); + struct ConvTable; + void LoadComboBoxes(void); + void LoadComboBox(int boxID, const ConvTable* pTable, int dflt); + int ConvComboSel(int boxID, const ConvTable* pTable); - bool fQueryDisplayFormat; - bool fAllowGenericFormats; - bool fHasSectors; - bool fHasBlocks; - bool fHasNibbles; + bool fQueryDisplayFormat; + bool fAllowGenericFormats; + bool fHasSectors; + bool fHasBlocks; + bool fHasNibbles; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__IMAGEFORMATDIALOG__*/ \ No newline at end of file diff --git a/app/Main.cpp b/app/Main.cpp index f2333a9..239c80f 100644 --- a/app/Main.cpp +++ b/app/Main.cpp @@ -1,2724 +1,2724 @@ -/* - * CiderPress - * Copyright (C) 2007, 2008 by faddenSoft, LLC. All Rights Reserved. - * See the file LICENSE for distribution terms. - */ -/* - * Main window management. - */ -#include "stdafx.h" -#include "Main.h" -#include "MyApp.h" -#include "AboutDialog.h" -#include "NufxArchive.h" -#include "DiskArchive.h" -#include "BNYArchive.h" -#include "ACUArchive.h" -#include "ArchiveInfoDialog.h" -#include "PrefsDialog.h" -#include "EnterRegDialog.h" -#include "OpenVolumeDialog.h" -#include "Print.h" -#include "HelpTopics.h" -#include "../util/UtilLib.h" -#include "resource.h" - -/* use MFC's fancy version of new for debugging */ -//#define new DEBUG_NEW - -static const char* kWebSiteURL = "http://www.faddensoft.com/"; - -/* - * Filters for the "open file" command. In some cases a file may be opened - * in more than one format, so it's necessary to keep track of what the - * file filter was set to when the file was opened. - */ -const char MainWindow::kOpenNuFX[] = - "ShrinkIt Archives (.shk .sdk .bxy .sea .bse)|*.shk;*.sdk;*.bxy;*.sea;*.bse|"; -const char MainWindow::kOpenBinaryII[] = - "Binary II Archives (.bny .bqy .bxy)|*.bny;*.bqy;*.bxy|"; -const char MainWindow::kOpenACU[] = - "ACU Archives (.acu)|*.acu|"; -const char MainWindow::kOpenDiskImage[] = - "Disk Images (.shk .sdk .dsk .po .do .d13 .2mg .img .nib .nb2 .raw .hdv .dc .dc6 .ddd .app .fdi .iso .gz .zip)|" - "*.shk;*.sdk;*.dsk;*.po;*.do;*.d13;*.2mg;*.img;*.nib;*.nb2;*.raw;*.hdv;*.dc;*.dc6;*.ddd;*.app;*.fdi;*.iso;*.gz;*.zip|"; -const char MainWindow::kOpenAll[] = - "All Files (*.*)|*.*|"; -const char MainWindow::kOpenEnd[] = - "|"; - -static const struct { - //const char* extension; - char extension[4]; - FilterIndex idx; -} gExtensionToIndex[] = { - { "shk", kFilterIndexNuFX }, - { "bxy", kFilterIndexNuFX }, - { "bse", kFilterIndexNuFX }, - { "sea", kFilterIndexNuFX }, - { "bny", kFilterIndexBinaryII }, - { "bqy", kFilterIndexBinaryII }, - { "acu", kFilterIndexACU }, - { "dsk", kFilterIndexDiskImage }, - { "po", kFilterIndexDiskImage }, - { "do", kFilterIndexDiskImage }, - { "d13", kFilterIndexDiskImage }, - { "2mg", kFilterIndexDiskImage }, - { "img", kFilterIndexDiskImage }, - { "sdk", kFilterIndexDiskImage }, - { "raw", kFilterIndexDiskImage }, - { "ddd", kFilterIndexDiskImage }, - { "app", kFilterIndexDiskImage }, - { "fdi", kFilterIndexDiskImage }, - { "iso", kFilterIndexDiskImage }, - { "gz", kFilterIndexDiskImage }, // assume disk image inside - { "zip", kFilterIndexDiskImage }, // assume disk image inside -}; - -const char* MainWindow::kModeNuFX = _T("nufx"); -const char* MainWindow::kModeBinaryII = _T("bin2"); -const char* MainWindow::kModeACU = _T("acu"); -const char* MainWindow::kModeDiskImage = _T("disk"); - - -/* - * =========================================================================== - * MainWindow - * =========================================================================== - */ - -static const UINT gFindReplaceID = RegisterWindowMessage(FINDMSGSTRING); - -BEGIN_MESSAGE_MAP(MainWindow, CFrameWnd) - ON_WM_CREATE() - ON_MESSAGE(WMU_LATE_INIT, OnLateInit) - //ON_MESSAGE(WMU_CLOSE_MAIN_DIALOG, OnCloseMainDialog) - ON_WM_SIZE() - ON_WM_GETMINMAXINFO() - ON_WM_PAINT() - //ON_WM_MOUSEWHEEL() - ON_WM_SETFOCUS() - ON_WM_HELPINFO() - ON_WM_QUERYENDSESSION() - ON_WM_ENDSESSION() - ON_REGISTERED_MESSAGE(gFindReplaceID, OnFindDialogMessage) - ON_COMMAND( IDM_FILE_NEW_ARCHIVE, OnFileNewArchive) - ON_COMMAND( IDM_FILE_OPEN, OnFileOpen) - ON_COMMAND( IDM_FILE_OPEN_VOLUME, OnFileOpenVolume) - ON_UPDATE_COMMAND_UI(IDM_FILE_OPEN_VOLUME, OnUpdateFileOpenVolume) - ON_COMMAND( IDM_FILE_REOPEN, OnFileReopen) - ON_UPDATE_COMMAND_UI(IDM_FILE_REOPEN, OnUpdateFileReopen) - ON_COMMAND( IDM_FILE_SAVE, OnFileSave) - ON_UPDATE_COMMAND_UI(IDM_FILE_SAVE, OnUpdateFileSave) - ON_COMMAND( IDM_FILE_CLOSE, OnFileClose) - ON_UPDATE_COMMAND_UI(IDM_FILE_CLOSE, OnUpdateFileClose) - ON_COMMAND( IDM_FILE_ARCHIVEINFO, OnFileArchiveInfo) - ON_UPDATE_COMMAND_UI(IDM_FILE_ARCHIVEINFO, OnUpdateFileArchiveInfo) - ON_COMMAND( IDM_FILE_PRINT, OnFilePrint) - ON_UPDATE_COMMAND_UI(IDM_FILE_PRINT, OnUpdateFilePrint) - ON_COMMAND( IDM_FILE_EXIT, OnFileExit) - ON_COMMAND( IDM_EDIT_COPY, OnEditCopy) - ON_UPDATE_COMMAND_UI(IDM_EDIT_COPY, OnUpdateEditCopy) - ON_COMMAND( IDM_EDIT_PASTE, OnEditPaste) - ON_UPDATE_COMMAND_UI(IDM_EDIT_PASTE, OnUpdateEditPaste) - ON_COMMAND( IDM_EDIT_PASTE_SPECIAL, OnEditPasteSpecial) - ON_UPDATE_COMMAND_UI(IDM_EDIT_PASTE_SPECIAL, OnUpdateEditPasteSpecial) - ON_COMMAND( IDM_EDIT_FIND, OnEditFind) - ON_UPDATE_COMMAND_UI(IDM_EDIT_FIND, OnUpdateEditFind) - ON_COMMAND( IDM_EDIT_SELECT_ALL, OnEditSelectAll) - ON_UPDATE_COMMAND_UI(IDM_EDIT_SELECT_ALL, OnUpdateEditSelectAll) - ON_COMMAND( IDM_EDIT_INVERT_SELECTION, OnEditInvertSelection) - ON_UPDATE_COMMAND_UI(IDM_EDIT_INVERT_SELECTION, OnUpdateEditInvertSelection) - ON_COMMAND( IDM_EDIT_PREFERENCES, OnEditPreferences) - ON_COMMAND_RANGE( IDM_SORT_PATHNAME, IDM_SORT_ORIGINAL, OnEditSort) - ON_UPDATE_COMMAND_UI_RANGE(IDM_SORT_PATHNAME, IDM_SORT_ORIGINAL, OnUpdateEditSort) - ON_COMMAND( IDM_ACTIONS_VIEW, OnActionsView) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_VIEW, OnUpdateActionsView) - ON_COMMAND( IDM_ACTIONS_ADD_FILES, OnActionsAddFiles) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_ADD_FILES, OnUpdateActionsAddFiles) - ON_COMMAND( IDM_ACTIONS_ADD_DISKS, OnActionsAddDisks) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_ADD_DISKS, OnUpdateActionsAddDisks) - ON_COMMAND( IDM_ACTIONS_CREATE_SUBDIR, OnActionsCreateSubdir) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_CREATE_SUBDIR, OnUpdateActionsCreateSubdir) - ON_COMMAND( IDM_ACTIONS_EXTRACT, OnActionsExtract) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_EXTRACT, OnUpdateActionsExtract) - ON_COMMAND( IDM_ACTIONS_TEST, OnActionsTest) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_TEST, OnUpdateActionsTest) - ON_COMMAND( IDM_ACTIONS_DELETE, OnActionsDelete) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_DELETE, OnUpdateActionsDelete) - ON_COMMAND( IDM_ACTIONS_RENAME, OnActionsRename) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_RENAME, OnUpdateActionsRename) - ON_COMMAND( IDM_ACTIONS_RECOMPRESS, OnActionsRecompress) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_RECOMPRESS, OnUpdateActionsRecompress) - ON_COMMAND( IDM_ACTIONS_OPENASDISK, OnActionsOpenAsDisk) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_OPENASDISK, OnUpdateActionsOpenAsDisk) - ON_COMMAND( IDM_ACTIONS_EDIT_COMMENT, OnActionsEditComment) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_EDIT_COMMENT, OnUpdateActionsEditComment) - ON_COMMAND( IDM_ACTIONS_EDIT_PROPS, OnActionsEditProps) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_EDIT_PROPS, OnUpdateActionsEditProps) - ON_COMMAND( IDM_ACTIONS_RENAME_VOLUME, OnActionsRenameVolume) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_RENAME_VOLUME, OnUpdateActionsRenameVolume) - ON_COMMAND( IDM_ACTIONS_CONV_DISK, OnActionsConvDisk) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_CONV_DISK, OnUpdateActionsConvDisk) - ON_COMMAND( IDM_ACTIONS_CONV_FILE, OnActionsConvFile) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_CONV_FILE, OnUpdateActionsConvFile) - ON_COMMAND( IDM_ACTIONS_CONV_TOWAV, OnActionsConvToWav) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_CONV_TOWAV, OnUpdateActionsConvToWav) - ON_COMMAND( IDM_ACTIONS_CONV_FROMWAV, OnActionsConvFromWav) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_CONV_FROMWAV, OnUpdateActionsConvFromWav) - ON_COMMAND( IDM_ACTIONS_IMPORT_BAS, OnActionsImportBAS) - ON_UPDATE_COMMAND_UI(IDM_ACTIONS_IMPORT_BAS, OnUpdateActionsImportBAS) - ON_COMMAND( IDM_TOOLS_DISKEDIT, OnToolsDiskEdit) - ON_COMMAND( IDM_TOOLS_IMAGECREATOR, OnToolsDiskImageCreator) - ON_COMMAND( IDM_TOOLS_DISKCONV, OnToolsDiskConv) - ON_COMMAND( IDM_TOOLS_BULKDISKCONV, OnToolsBulkDiskConv) - ON_COMMAND( IDM_TOOLS_SST_MERGE, OnToolsSSTMerge) - ON_COMMAND( IDM_TOOLS_VOLUMECOPIER_VOLUME, OnToolsVolumeCopierVolume) - ON_COMMAND( IDM_TOOLS_VOLUMECOPIER_FILE, OnToolsVolumeCopierFile) - ON_COMMAND( IDM_TOOLS_EOLSCANNER, OnToolsEOLScanner) - ON_COMMAND( IDM_TOOLS_TWOIMGPROPS, OnToolsTwoImgProps) - ON_COMMAND( IDM_HELP_CONTENTS, OnHelpContents) - ON_COMMAND( IDM_HELP_WEBSITE, OnHelpWebSite) - ON_COMMAND( IDM_HELP_ORDERING, OnHelpOrdering) - ON_COMMAND( IDM_HELP_ABOUT, OnHelpAbout) -// ON_COMMAND( IDM_RTCLK_DEFAULT, OnRtClkDefault) - - /* this is required to allow "Help" button to work in PropertySheets (!) */ -// ON_COMMAND(ID_HELP, OnHelp) - ON_COMMAND(ID_HELP_FINDER, CFrameWnd::OnHelpFinder) - ON_COMMAND(ID_HELP, CFrameWnd::OnHelp) - ON_COMMAND(ID_CONTEXT_HELP, CFrameWnd::OnContextHelp) - ON_COMMAND(ID_DEFAULT_HELP, CFrameWnd::OnHelpFinder) -END_MESSAGE_MAP() - - -/* - * MainWindow constructor. Creates the main window and sets - * its properties. - */ -MainWindow::MainWindow() -{ - static const char* kAppName = _T("CiderPress"); - - fpContentList = nil; - fpOpenArchive = nil; - //fpSelSet = nil; - fpActionProgress = nil; - fpProgressCounter = nil; - fpFindDialog = nil; - - fFindDown = true; - fFindMatchCase = false; - fFindMatchWholeWord = false; - - fAbortPrinting = false; - fhDevMode = nil; - fhDevNames = nil; - fNeedReopen = false; - - CString wndClass = AfxRegisterWndClass( - CS_DBLCLKS /*| CS_HREDRAW | CS_VREDRAW*/, - gMyApp.LoadStandardCursor(IDC_ARROW), - NULL /*(HBRUSH) (COLOR_WINDOW + 1)*/, - gMyApp.LoadIcon(IDR_MAINFRAME) ); - - Create(wndClass, kAppName, WS_OVERLAPPEDWINDOW /*| WS_CLIPCHILDREN*/, - rectDefault, NULL, MAKEINTRESOURCE(IDR_MAINFRAME)); - - LoadAccelTable(MAKEINTRESOURCE(IDR_MAINFRAME)); - - // initialize some OLE garbage - AfxOleInit(); - - // required by MFC if Rich Edit controls are used - AfxInitRichEdit(); - - // required?? - //AfxEnableControlContainer(); - - SetCPTitle(); - - int cc = PostMessage(WMU_LATE_INIT, 0, 0); - ASSERT(cc != 0); -} - -/* - * MainWindow destructor. Close the archive if one is open, but don't try - * to shut down any controls in child windows. By this point, Windows has - * already snuffed them. - */ -MainWindow::~MainWindow() -{ - WMSG0("~MainWindow\n"); - - //WMSG0("MainWindow destructor\n"); - CloseArchiveWOControls(); - - int cc; - cc = ::WinHelp(m_hWnd, ::AfxGetApp()->m_pszHelpFilePath, HELP_QUIT, 0); - WMSG1("Turning off WinHelp returned %d\n", cc); - - // free stuff used by print dialog - ::GlobalFree(fhDevMode); - ::GlobalFree(fhDevNames); - - fPreferences.SaveToRegistry(); - WMSG0("MainWindow destructor complete\n"); -} - - -/* - * Override the pre-create function to tweak the window style. - */ -BOOL -MainWindow::PreCreateWindow(CREATESTRUCT& cs) -{ - BOOL res = CFrameWnd::PreCreateWindow(cs); - - cs.dwExStyle &= ~(WS_EX_CLIENTEDGE); - - return res; -} - -/* - * Override GetClientRect so we can factor in the status and tool bars. - */ -void -MainWindow::GetClientRect(LPRECT lpRect) const -{ - CRect sizeRect; - int toolBarHeight, statusBarHeight; - - fToolBar.GetWindowRect(&sizeRect); - toolBarHeight = sizeRect.bottom - sizeRect.top; - fStatusBar.GetWindowRect(&sizeRect); - statusBarHeight = sizeRect.bottom - sizeRect.top; - - //WMSG2("HEIGHTS = %d/%d\n", toolBarHeight, statusBarHeight); - CFrameWnd::GetClientRect(lpRect); - lpRect->top += toolBarHeight; - lpRect->bottom -= statusBarHeight; -} - - -/* - * Do some idle processing. - */ -void -MainWindow::DoIdle(void) -{ - /* - * Make sure that the filename field in the content list is always - * visible, since that what the user clicks on to select things. Would - * be nice to have a way to prevent it, but for now we'll just shove - * things back where they're supposed to be. - */ - if (fpContentList != nil) { - /* get the current column 0 width, with current user adjustments */ - fpContentList->ExportColumnWidths(); - int width = fPreferences.GetColumnLayout()->GetColumnWidth(0); - - if (width >= 0 && width < ColumnLayout::kMinCol0Width) { - /* column is too small, but don't change it until user lets mouse up */ - if (::GetAsyncKeyState(VK_LBUTTON) >= 0) { - WMSG0("Resetting column 0 width\n"); - fPreferences.GetColumnLayout()->SetColumnWidth(0, - ColumnLayout::kMinCol0Width); - fpContentList->NewColumnWidths(); - } - } - } - - /* - * Put an asterisk at the end of the title if we have an open archive - * and it has pending modifications. Remove it if nothing is pending. - */ - if (fpOpenArchive != nil) { - CString title; - int len; - - GetWindowText(/*ref*/ title); - len = title.GetLength(); - if (len > 0 && title.GetAt(len-1) == '*') { - if (!fpOpenArchive->IsModified()) { - /* remove the asterisk and the preceeding space */ - title.Delete(len-2, 2); - SetWindowText(title); - } - } else { - if (fpOpenArchive->IsModified()) { - /* add an asterisk */ - title += " *"; - SetWindowText(title); - } - } - } -} - - -/* - * Handle command-line arguments. - * - * Usage: - * CiderPress [[-temparc] [-mode {nufx,bin2,disk}] [-dispname name] filename] - */ -void -MainWindow::ProcessCommandLine(void) -{ - /* - * Get the command line and break it down into an argument vector. - */ - const char* cmdLine = ::GetCommandLine(); - if (cmdLine == nil || strlen(cmdLine) == 0) - return; - - char* mangle = strdup(cmdLine); - if (mangle == nil) - return; - - WMSG1("Mangling '%s'\n", mangle); - char* argv[8]; - int argc = 8; - VectorizeString(mangle, argv, &argc); - - WMSG0("Args:\n"); - for (int i = 0; i < argc; i++) { - WMSG2(" %d '%s'\n", i, argv[i]); - } - - /* - * Figure out what the arguments are. - */ - const char* filename = nil; - const char* dispName = nil; - int filterIndex = kFilterIndexGeneric; - bool temp = false; - - for (i = 1; i < argc; i++) { - if (argv[i][0] == '-') { - if (strcasecmp(argv[i], "-mode") == 0) { - if (i == argc-1) { - WMSG0("WARNING: -mode specified without mode\n"); - } else - i++; - if (strcasecmp(argv[i], kModeNuFX) == 0) - filterIndex = kFilterIndexNuFX; - else if (strcasecmp(argv[i], kModeBinaryII) == 0) - filterIndex = kFilterIndexBinaryII; - else if (strcasecmp(argv[i], kModeACU) == 0) - filterIndex = kFilterIndexACU; - else if (strcasecmp(argv[i], kModeDiskImage) == 0) - filterIndex = kFilterIndexDiskImage; - else { - WMSG1("WARNING: unrecognized mode '%s'\n", argv[i]); - } - } else if (strcasecmp(argv[i], "-dispname") == 0) { - if (i == argc-1) { - WMSG0("WARNING: -dispname specified without name\n"); - } else - i++; - dispName = argv[i]; - } else if (strcasecmp(argv[i], "-temparc") == 0) { - temp = true; - } else if (strcasecmp(argv[i], "-install") == 0) { - // see MyApp::InitInstance - WMSG0("Got '-install' flag, doing nothing\n"); - } else if (strcasecmp(argv[i], "-uninstall") == 0) { - // see MyApp::InitInstance - WMSG0("Got '-uninstall' flag, doing nothing\n"); - } else { - WMSG1("WARNING: unrecognized flag '%s'\n", argv[i]); - } - } else { - /* must be the filename */ - if (i != argc-1) { - WMSG1("WARNING: ignoring extra arguments (e.g. '%s')\n", - argv[i+1]); - } - filename = argv[i]; - break; - } - } - if (argc != 1 && filename == nil) { - WMSG0("WARNING: args specified but no filename found\n"); - } - - WMSG0("Argument handling:\n"); - WMSG3(" index=%d temp=%d filename='%s'\n", - filterIndex, temp, filename == nil ? "(nil)" : filename); - - if (filename != nil) { - PathName path(filename); - CString ext = path.GetExtension(); - - // drop the leading '.' from the extension - if (ext.Left(1) == ".") - ext.Delete(0, 1); - - /* load the archive, mandating read-only if it's a temporary file */ - if (LoadArchive(filename, ext, filterIndex, temp, false) == 0) { - /* success, update title bar */ - if (temp) - fOpenArchivePathName = path.GetFileName(); - else - fOpenArchivePathName = filename; - if (dispName != nil) - fOpenArchivePathName = dispName; - SetCPTitle(fOpenArchivePathName, fpOpenArchive); - } - - /* if it's a temporary file, arrange to have it deleted before exit */ - if (temp) { - int len = strlen(filename); - - if (len > 4 && strcasecmp(filename + (len-4), ".tmp") == 0) { - fDeleteList.Add(filename); - } else { - WMSG1("NOT adding '%s' to DeleteList -- does not end in '.tmp'\n", - filename); - } - } - } - - free(mangle); -} - - -/* - * =================================== - * Command handlers - * =================================== - */ - -const int kProgressPane = 1; - -/* - * OnCreate handler. Used to add a toolbar and status bar. - */ -int -MainWindow::OnCreate(LPCREATESTRUCT lpcs) -{ - WMSG0("Now in OnCreate!\n"); - if (CFrameWnd::OnCreate(lpcs) == -1) - return -1; - - /* - * Create the tool bar. - */ -#if 0 - static UINT buttonList[] = { - IDM_FILE_OPEN, - IDM_FILE_NEW_ARCHIVE, - // spacer - IDM_FILE_PRINT, - }; -#endif - fToolBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_TOP | - CBRS_TOOLTIPS | CBRS_FLYBY); - fToolBar.LoadToolBar(IDR_TOOLBAR1); - - /* - * Create the status bar. - */ - static UINT indicators[] = { ID_SEPARATOR, ID_INDICATOR_COMPLETE }; - fStatusBar.Create(this); - fStatusBar.SetIndicators(indicators, NELEM(indicators)); - //fStatusBar.SetPaneInfo(0, ID_SEPARATOR, SBPS_NOBORDERS | SBPS_STRETCH, 0); - - fStatusBar.SetPaneText(kProgressPane, ""); - - return 0; -} - - -/* - * Catch a message sent to inspire us to perform one-time initializations of - * preferences and libraries. - * - * We're doing this the long way around because we want to be able to - * put up a dialog box if the version is bad. If we tried to handle this - * in the constructor we'd be acting before the window was fully created. - */ -LONG -MainWindow::OnLateInit(UINT, LONG) -{ - CString result; - CString appName; - CString niftyListFile; - - appName.LoadString(IDS_MB_APP_NAME); - - WMSG0("----- late init begins -----\n"); - - /* - * Handle all other messages. This gives the framework a chance to dim - * all of the toolbar buttons. This is especially useful when opening - * a file from the command line that doesn't exist, causing an error - * dialog and blocking main window messages. - */ - PeekAndPump(); - - /* - * Initialize libraries. This includes a version check. - */ - result = NufxArchive::AppInit(); - if (!result.IsEmpty()) - goto fail; - result = DiskArchive::AppInit(); - if (!result.IsEmpty()) - goto fail; - result = BnyArchive::AppInit(); - if (!result.IsEmpty()) - goto fail; - - niftyListFile = gMyApp.GetExeBaseName(); - niftyListFile += "NList.Data"; - if (!NiftyList::AppInit(niftyListFile)) { - CString file2 = niftyListFile + ".TXT"; - if (!NiftyList::AppInit(file2)) { - CString msg; - msg.Format(IDS_NLIST_DATA_FAILED, niftyListFile, file2); - MessageBox(msg, appName, MB_OK); - } - } - - /* - * Read preferences from registry. - */ - fPreferences.LoadFromRegistry(); - - /* - * Check to see if we're registered; if we're not, and we've expired, it's - * time to bail out. - */ - MyRegistry::RegStatus regStatus; - //regStatus = gMyApp.fRegistry.CheckRegistration(&result); - regStatus = MyRegistry::kRegValid; - WMSG1("CheckRegistration returned %d\n", regStatus); - switch (regStatus) { - case MyRegistry::kRegNotSet: - case MyRegistry::kRegValid: - ASSERT(result.IsEmpty()); - break; - case MyRegistry::kRegExpired: - case MyRegistry::kRegInvalid: - MessageBox(result, appName, MB_OK|MB_ICONINFORMATION); - WMSG0("FORCING REG\n"); -#if 0 - if (EnterRegDialog::GetRegInfo(this) != 0) { - result = ""; - goto fail; - } -#endif - SetCPTitle(); // update title bar with new reg info - break; - case MyRegistry::kRegFailed: - ASSERT(!result.IsEmpty()); - goto fail; - default: - ASSERT(false); - CString confused; - confused.Format("Registration check failed. %s", (LPCTSTR) result); - result = confused; - goto fail; - } - - /* - * Process command-line options, possibly loading an archive. - */ - ProcessCommandLine(); - - return 0; - -fail: - if (!result.IsEmpty()) - ShowFailureMsg(this, result, IDS_FAILED); - int cc = PostMessage(WM_CLOSE, 0, 0); - ASSERT(cc != 0); - - return 0; -} - - -/* - * The system wants to know if we're okay with shutting down. - * - * Return TRUE if it's okay to shut down, FALSE otherwise. - */ -BOOL -MainWindow::OnQueryEndSession(void) -{ - WMSG0("Got QueryEndSession\n"); - return TRUE; -} - -/* - * Notification of shutdown (or not). - */ -void -MainWindow::OnEndSession(BOOL bEnding) -{ - WMSG1("Got EndSession (bEnding=%d)\n", bEnding); - - if (bEnding) { - CloseArchiveWOControls(); - - fPreferences.SaveToRegistry(); - } -} - -/* - * The main window is resizing. We don't automatically redraw on resize, - * so we will need to update the client region. If it's filled with a - * control, the control's resize & redraw function will take care of it. - * If not, we need to explicitly invalidate the client region so the - * window will repaint itself. - */ -void -MainWindow::OnSize(UINT nType, int cx, int cy) -{ - CFrameWnd::OnSize(nType, cx, cy); - ResizeClientArea(); -} -void -MainWindow::ResizeClientArea(void) -{ - CRect sizeRect; - - GetClientRect(&sizeRect); - if (fpContentList != NULL) - fpContentList->MoveWindow(sizeRect); - else - Invalidate(false); -} - -/* - * Restrict the minimum window size to something reasonable. - */ -void -MainWindow::OnGetMinMaxInfo(MINMAXINFO* pMMI) -{ - pMMI->ptMinTrackSize.x = 256; - pMMI->ptMinTrackSize.y = 192; -} - -/* - * Repaint the main window. - */ -void -MainWindow::OnPaint(void) -{ - CPaintDC dc(this); - CRect clientRect; - - GetClientRect(&clientRect); - - /* - * If there's no control in the window, fill in the client area with - * what looks like an empty MDI client rect. - */ - if (fpContentList == nil) { - DrawEmptyClientArea(&dc, clientRect); - } - -#if 0 - CPen pen(PS_SOLID, 1, RGB(255, 0, 0)); // red pen, 1 pixel wide - CPen* pOldPen = dc.SelectObject(&pen); - - dc.MoveTo(clientRect.left, clientRect.top); - dc.LineTo(clientRect.right-1, clientRect.top); - dc.LineTo(clientRect.right, clientRect.bottom); - dc.LineTo(clientRect.left, clientRect.bottom-1); - dc.LineTo(clientRect.left, clientRect.top); - - dc.SelectObject(pOldPen); -#endif -} - -#if 0 -afx_msg BOOL -MainWindow::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) -{ - WMSG0("MOUSE WHEEL\n"); - return FALSE; - - WPARAM wparam; - LPARAM lparam; - - wparam = nFlags | (zDelta << 16); - lparam = pt.x | (pt.y << 16); - if (fpContentList != nil) - fpContentList->SendMessage(WM_MOUSEWHEEL, wparam, lparam); - return CWnd::OnMouseWheel(nFlags, zDelta, pt); -// return TRUE; -} -#endif - -/* - * Make sure open controls keep the input focus. - */ -void -MainWindow::OnSetFocus(CWnd* /*pOldWnd*/) -{ - if (fpContentList != nil) { - WMSG0("Returning focus to ContentList\n"); - fpContentList->SetFocus(); - } -} - -/* - * User hit F1. We don't currently have context-sensitive help on the main page. - */ -BOOL -MainWindow::OnHelpInfo(HELPINFO* /*lpHelpInfo*/) -{ - //WinHelp(0, HELP_FINDER); - WinHelp(HELP_TOPIC_WELCOME, HELP_CONTEXT); - return TRUE; // dunno what this means -} - -#if 0 -/* - * Catch-all Help handler, necessary to allow CPropertySheet to display a - * "Help" button. (WTF?) - */ -LONG -MainWindow::OnHelp(UINT wParam, LONG lParam) -{ - HELPINFO* lpHelpInfo = (HELPINFO*) lParam; - - DWORD context = lpHelpInfo->iCtrlId; - WMSG1("MainWindow OnHelp (context=%d)\n", context); - WinHelp(context, HELP_CONTEXTPOPUP); - - return TRUE; // yes, we handled it -} -#endif - -/* - * Handle Edit->Preferences by popping up a property sheet. - */ -void -MainWindow::OnEditPreferences(void) -{ - PrefsSheet ps; - ColumnLayout* pColLayout = fPreferences.GetColumnLayout(); - - /* pull any user header tweaks out of list so we can configure prefs */ - if (fpContentList != nil) - fpContentList->ExportColumnWidths(); - - /* set up PrefsGeneralPage */ - for (int i = 0; i < kNumVisibleColumns; i++) { - ps.fGeneralPage.fColumn[i] = (pColLayout->GetColumnWidth(i) != 0); - } - ps.fGeneralPage.fMimicShrinkIt = fPreferences.GetPrefBool(kPrMimicShrinkIt); - ps.fGeneralPage.fBadMacSHK = fPreferences.GetPrefBool(kPrBadMacSHK); - ps.fGeneralPage.fReduceSHKErrorChecks = fPreferences.GetPrefBool(kPrReduceSHKErrorChecks); - ps.fGeneralPage.fCoerceDOSFilenames = fPreferences.GetPrefBool(kPrCoerceDOSFilenames); - ps.fGeneralPage.fSpacesToUnder = fPreferences.GetPrefBool(kPrSpacesToUnder); - ps.fGeneralPage.fPasteJunkPaths = fPreferences.GetPrefBool(kPrPasteJunkPaths); - ps.fGeneralPage.fBeepOnSuccess = fPreferences.GetPrefBool(kPrBeepOnSuccess); - - /* set up PrefsDiskImagePage */ - ps.fDiskImagePage.fQueryImageFormat = fPreferences.GetPrefBool(kPrQueryImageFormat); - ps.fDiskImagePage.fOpenVolumeRO = fPreferences.GetPrefBool(kPrOpenVolumeRO); - ps.fDiskImagePage.fOpenVolumePhys0 = fPreferences.GetPrefBool(kPrOpenVolumePhys0); - ps.fDiskImagePage.fProDOSAllowLower = fPreferences.GetPrefBool(kPrProDOSAllowLower); - ps.fDiskImagePage.fProDOSUseSparse = fPreferences.GetPrefBool(kPrProDOSUseSparse); - - /* set up PrefsCompressionPage */ - ps.fCompressionPage.fCompressType = fPreferences.GetPrefLong(kPrCompressionType); - - /* set up PrefsFviewPage */ - ps.fFviewPage.fMaxViewFileSizeKB = - (fPreferences.GetPrefLong(kPrMaxViewFileSize) + 1023) / 1024; - ps.fFviewPage.fNoWrapText = fPreferences.GetPrefBool(kPrNoWrapText); - - ps.fFviewPage.fHighlightHexDump = fPreferences.GetPrefBool(kPrHighlightHexDump); - ps.fFviewPage.fHighlightBASIC = fPreferences.GetPrefBool(kPrHighlightBASIC); - ps.fFviewPage.fConvDisasmOneByteBrkCop = fPreferences.GetPrefBool(kPrDisasmOneByteBrkCop); - ps.fFviewPage.fConvHiResBlackWhite = fPreferences.GetPrefBool(kPrConvHiResBlackWhite); - ps.fFviewPage.fConvDHRAlgorithm = fPreferences.GetPrefLong(kPrConvDHRAlgorithm); - ps.fFviewPage.fRelaxGfxTypeCheck = fPreferences.GetPrefBool(kPrRelaxGfxTypeCheck); -// ps.fFviewPage.fEOLConvRaw = fPreferences.GetPrefBool(kPrEOLConvRaw); -// ps.fFviewPage.fConvHighASCII = fPreferences.GetPrefBool(kPrConvHighASCII); - ps.fFviewPage.fConvTextEOL_HA = fPreferences.GetPrefBool(kPrConvTextEOL_HA); - ps.fFviewPage.fConvCPMText = fPreferences.GetPrefBool(kPrConvCPMText); - ps.fFviewPage.fConvPascalText = fPreferences.GetPrefBool(kPrConvPascalText); - ps.fFviewPage.fConvPascalCode = fPreferences.GetPrefBool(kPrConvPascalCode); - ps.fFviewPage.fConvApplesoft = fPreferences.GetPrefBool(kPrConvApplesoft); - ps.fFviewPage.fConvInteger = fPreferences.GetPrefBool(kPrConvInteger); - ps.fFviewPage.fConvBusiness = fPreferences.GetPrefBool(kPrConvBusiness); - ps.fFviewPage.fConvGWP = fPreferences.GetPrefBool(kPrConvGWP); - ps.fFviewPage.fConvText8 = fPreferences.GetPrefBool(kPrConvText8); - ps.fFviewPage.fConvAWP = fPreferences.GetPrefBool(kPrConvAWP); - ps.fFviewPage.fConvADB = fPreferences.GetPrefBool(kPrConvADB); - ps.fFviewPage.fConvASP = fPreferences.GetPrefBool(kPrConvASP); - ps.fFviewPage.fConvSCAssem = fPreferences.GetPrefBool(kPrConvSCAssem); - ps.fFviewPage.fConvDisasm = fPreferences.GetPrefBool(kPrConvDisasm); - ps.fFviewPage.fConvHiRes = fPreferences.GetPrefBool(kPrConvHiRes); - ps.fFviewPage.fConvDHR = fPreferences.GetPrefBool(kPrConvDHR); - ps.fFviewPage.fConvSHR = fPreferences.GetPrefBool(kPrConvSHR); - ps.fFviewPage.fConvPrintShop = fPreferences.GetPrefBool(kPrConvPrintShop); - ps.fFviewPage.fConvMacPaint = fPreferences.GetPrefBool(kPrConvMacPaint); - ps.fFviewPage.fConvProDOSFolder = fPreferences.GetPrefBool(kPrConvProDOSFolder); - ps.fFviewPage.fConvResources = fPreferences.GetPrefBool(kPrConvResources); - - /* set up PrefsFilesPage */ - ps.fFilesPage.fTempPath = fPreferences.GetPrefString(kPrTempPath); - ps.fFilesPage.fExtViewerExts = fPreferences.GetPrefString(kPrExtViewerExts); - - if (ps.DoModal() == IDOK) - ApplyNow(&ps); -} - -/* - * Apply a change from the preferences sheet. - */ -void -MainWindow::ApplyNow(PrefsSheet* pPS) -{ - bool mustReload = false; - - //WMSG0("APPLY CHANGES\n"); - - ColumnLayout* pColLayout = fPreferences.GetColumnLayout(); - - if (pPS->fGeneralPage.fDefaultsPushed) { - /* reset all sizes to defaults, then factor in checkboxes */ - WMSG0(" Resetting all widths to defaults\n"); - - /* copy defaults over */ - for (int i = 0; i < kNumVisibleColumns; i++) - pColLayout->SetColumnWidth(i, ColumnLayout::kWidthDefaulted); - } - - /* handle column checkboxes */ - for (int i = 0; i < kNumVisibleColumns; i++) { - if (pColLayout->GetColumnWidth(i) == 0 && - pPS->fGeneralPage.fColumn[i]) - { - /* restore column */ - WMSG1(" Column %d restored\n", i); - pColLayout->SetColumnWidth(i, ColumnLayout::kWidthDefaulted); - } else if (pColLayout->GetColumnWidth(i) != 0 && - !pPS->fGeneralPage.fColumn[i]) - { - /* disable column */ - WMSG1(" Column %d hidden\n", i); - pColLayout->SetColumnWidth(i, 0); - } - } - if (fpContentList != nil) - fpContentList->NewColumnWidths(); - fPreferences.SetPrefBool(kPrMimicShrinkIt, - pPS->fGeneralPage.fMimicShrinkIt != 0); - fPreferences.SetPrefBool(kPrBadMacSHK, pPS->fGeneralPage.fBadMacSHK != 0); - fPreferences.SetPrefBool(kPrReduceSHKErrorChecks, - pPS->fGeneralPage.fReduceSHKErrorChecks != 0); - if (fPreferences.GetPrefBool(kPrCoerceDOSFilenames)!= - (pPS->fGeneralPage.fCoerceDOSFilenames != 0)) - { - WMSG1("DOS filename coercion pref now %d\n", - pPS->fGeneralPage.fCoerceDOSFilenames); - fPreferences.SetPrefBool(kPrCoerceDOSFilenames, - pPS->fGeneralPage.fCoerceDOSFilenames != 0); - mustReload = true; - } - if (fPreferences.GetPrefBool(kPrSpacesToUnder) != - (pPS->fGeneralPage.fSpacesToUnder != 0)) - { - WMSG1("Spaces-to-underscores now %d\n", pPS->fGeneralPage.fSpacesToUnder); - fPreferences.SetPrefBool(kPrSpacesToUnder, pPS->fGeneralPage.fSpacesToUnder != 0); - mustReload = true; - } - fPreferences.SetPrefBool(kPrPasteJunkPaths, pPS->fGeneralPage.fPasteJunkPaths != 0); - fPreferences.SetPrefBool(kPrBeepOnSuccess, pPS->fGeneralPage.fBeepOnSuccess != 0); - - if (pPS->fGeneralPage.fOurAssociations != nil) { - WMSG0("NEW ASSOCIATIONS!\n"); - - for (int assoc = 0; assoc < gMyApp.fRegistry.GetNumFileAssocs(); assoc++) - { - gMyApp.fRegistry.SetFileAssoc(assoc, - pPS->fGeneralPage.fOurAssociations[assoc]); - } - - /* delete them so, if they hit "apply" again, we only update once */ - delete[] pPS->fGeneralPage.fOurAssociations; - pPS->fGeneralPage.fOurAssociations = nil; - } - - fPreferences.SetPrefBool(kPrQueryImageFormat, pPS->fDiskImagePage.fQueryImageFormat != 0); - fPreferences.SetPrefBool(kPrOpenVolumeRO, pPS->fDiskImagePage.fOpenVolumeRO != 0); - fPreferences.SetPrefBool(kPrOpenVolumePhys0, pPS->fDiskImagePage.fOpenVolumePhys0 != 0); - fPreferences.SetPrefBool(kPrProDOSAllowLower, pPS->fDiskImagePage.fProDOSAllowLower != 0); - fPreferences.SetPrefBool(kPrProDOSUseSparse, pPS->fDiskImagePage.fProDOSUseSparse != 0); - - fPreferences.SetPrefLong(kPrCompressionType, pPS->fCompressionPage.fCompressType); - - fPreferences.SetPrefLong(kPrMaxViewFileSize, pPS->fFviewPage.fMaxViewFileSizeKB * 1024); - fPreferences.SetPrefBool(kPrNoWrapText, pPS->fFviewPage.fNoWrapText != 0); - - fPreferences.SetPrefBool(kPrHighlightHexDump, pPS->fFviewPage.fHighlightHexDump != 0); - fPreferences.SetPrefBool(kPrHighlightBASIC, pPS->fFviewPage.fHighlightBASIC != 0); - fPreferences.SetPrefBool(kPrDisasmOneByteBrkCop, pPS->fFviewPage.fConvDisasmOneByteBrkCop != 0); - fPreferences.SetPrefBool(kPrConvHiResBlackWhite, pPS->fFviewPage.fConvHiResBlackWhite != 0); - fPreferences.SetPrefLong(kPrConvDHRAlgorithm, pPS->fFviewPage.fConvDHRAlgorithm); - fPreferences.SetPrefBool(kPrRelaxGfxTypeCheck, pPS->fFviewPage.fRelaxGfxTypeCheck != 0); -// fPreferences.SetPrefBool(kPrEOLConvRaw, pPS->fFviewPage.fEOLConvRaw != 0); -// fPreferences.SetPrefBool(kPrConvHighASCII, pPS->fFviewPage.fConvHighASCII != 0); - fPreferences.SetPrefBool(kPrConvTextEOL_HA, pPS->fFviewPage.fConvTextEOL_HA != 0); - fPreferences.SetPrefBool(kPrConvCPMText, pPS->fFviewPage.fConvCPMText != 0); - fPreferences.SetPrefBool(kPrConvPascalText, pPS->fFviewPage.fConvPascalText != 0); - fPreferences.SetPrefBool(kPrConvPascalCode, pPS->fFviewPage.fConvPascalCode != 0); - fPreferences.SetPrefBool(kPrConvApplesoft, pPS->fFviewPage.fConvApplesoft != 0); - fPreferences.SetPrefBool(kPrConvInteger, pPS->fFviewPage.fConvInteger != 0); - fPreferences.SetPrefBool(kPrConvBusiness, pPS->fFviewPage.fConvBusiness != 0); - fPreferences.SetPrefBool(kPrConvGWP, pPS->fFviewPage.fConvGWP != 0); - fPreferences.SetPrefBool(kPrConvText8, pPS->fFviewPage.fConvText8 != 0); - fPreferences.SetPrefBool(kPrConvAWP, pPS->fFviewPage.fConvAWP != 0); - fPreferences.SetPrefBool(kPrConvADB, pPS->fFviewPage.fConvADB != 0); - fPreferences.SetPrefBool(kPrConvASP, pPS->fFviewPage.fConvASP != 0); - fPreferences.SetPrefBool(kPrConvSCAssem, pPS->fFviewPage.fConvSCAssem != 0); - fPreferences.SetPrefBool(kPrConvDisasm, pPS->fFviewPage.fConvDisasm != 0); - fPreferences.SetPrefBool(kPrConvHiRes, pPS->fFviewPage.fConvHiRes != 0); - fPreferences.SetPrefBool(kPrConvDHR, pPS->fFviewPage.fConvDHR != 0); - fPreferences.SetPrefBool(kPrConvSHR, pPS->fFviewPage.fConvSHR != 0); - fPreferences.SetPrefBool(kPrConvPrintShop, pPS->fFviewPage.fConvPrintShop != 0); - fPreferences.SetPrefBool(kPrConvMacPaint, pPS->fFviewPage.fConvMacPaint != 0); - fPreferences.SetPrefBool(kPrConvProDOSFolder, pPS->fFviewPage.fConvProDOSFolder != 0); - fPreferences.SetPrefBool(kPrConvResources, pPS->fFviewPage.fConvResources != 0); - - fPreferences.SetPrefString(kPrTempPath, pPS->fFilesPage.fTempPath); - WMSG1("--- Temp path now '%s'\n", fPreferences.GetPrefString(kPrTempPath)); - fPreferences.SetPrefString(kPrExtViewerExts, pPS->fFilesPage.fExtViewerExts); - - -// if ((pPS->fGeneralPage.fShowToolbarText != 0) != fPreferences.GetShowToolbarText()) { -// fPreferences.SetShowToolbarText(pPS->fGeneralPage.fShowToolbarText != 0); -// //SetToolbarTextMode(); -// ResizeClientArea(); -// } - - /* allow open archive to track changes to preferences */ - if (fpOpenArchive != nil) - fpOpenArchive->PreferencesChanged(); - - if (mustReload) { - WMSG0("Preferences apply requesting GA/CL reload\n"); - if (fpOpenArchive != nil) - fpOpenArchive->Reload(); - if (fpContentList != nil) - fpContentList->Reload(); - } - - /* export to registry */ - fPreferences.SaveToRegistry(); - - //Invalidate(); -} - -/* - * Handle IDM_EDIT_FIND. - */ -void -MainWindow::OnEditFind(void) -{ - DWORD flags = 0; - - if (fpFindDialog != nil) - return; - - if (fFindDown) - flags |= FR_DOWN; - if (fFindMatchCase) - flags |= FR_MATCHCASE; - if (fFindMatchWholeWord) - flags |= FR_WHOLEWORD; - - fpFindDialog = new CFindReplaceDialog; - - fpFindDialog->Create(TRUE, // "find" only - fFindLastStr, // default string to search for - NULL, // default string to replace - flags, // flags - this); // parent -} -void -MainWindow::OnUpdateEditFind(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(fpOpenArchive != nil); -} - -/* - * Handle activity in the modeless "find" dialog. - */ -LRESULT -MainWindow::OnFindDialogMessage(WPARAM wParam, LPARAM lParam) -{ - assert(fpFindDialog != nil); - - fFindDown = (fpFindDialog->SearchDown() != 0); - fFindMatchCase = (fpFindDialog->MatchCase() != 0); - fFindMatchWholeWord = (fpFindDialog->MatchWholeWord() != 0); - - if (fpFindDialog->IsTerminating()) { - fpFindDialog = nil; - return 0; - } - - if (fpFindDialog->FindNext()) { - fFindLastStr = fpFindDialog->GetFindString(); - fpContentList->FindNext(fFindLastStr, fFindDown, fFindMatchCase, - fFindMatchWholeWord); - } else { - WMSG0("Unexpected find dialog activity\n"); - } - - return 0; -} - - -/* - * Handle IDM_SORT_*. - * - * The "sort" enu item should really only be active if we have a file open. - */ -void -MainWindow::OnEditSort(UINT id) -{ - WMSG1("EDIT SORT %d\n", id); - - ASSERT(id >= IDM_SORT_PATHNAME && id <= IDM_SORT_ORIGINAL); - fPreferences.GetColumnLayout()->SetSortColumn(id - IDM_SORT_PATHNAME); - fPreferences.GetColumnLayout()->SetAscending(true); - if (fpContentList != nil) - fpContentList->NewSortOrder(); -} -void -MainWindow::OnUpdateEditSort(CCmdUI* pCmdUI) -{ - unsigned int column = fPreferences.GetColumnLayout()->GetSortColumn(); - - pCmdUI->SetCheck(pCmdUI->m_nID - IDM_SORT_PATHNAME == column); -} - -/* - * Open the help file. - */ -void -MainWindow::OnHelpContents(void) -{ - WinHelp(0, HELP_FINDER); -} - -/* - * Go to the faddenSoft web site. - */ -void -MainWindow::OnHelpWebSite(void) -{ - int err; - - err = (int) ::ShellExecute(m_hWnd, _T("open"), kWebSiteURL, NULL, NULL, - SW_SHOWNORMAL); - if (err <= 32) { - CString msg; - if (err == ERROR_FILE_NOT_FOUND) { - msg = "Windows call failed: web browser not found. (Sometimes" - " it mistakenly reports this when IE is not the default" - " browser.)"; - ShowFailureMsg(this, msg, IDS_FAILED); - } else { - msg.Format("Unable to launch web browser (err=%d).", err); - ShowFailureMsg(this, msg, IDS_FAILED); - } - } -} - -/* - * Show ordering info (ka-ching!). - */ -void -MainWindow::OnHelpOrdering(void) -{ - WinHelp(HELP_TOPIC_ORDERING_INFO, HELP_CONTEXT); -} - -/* - * Pop up the About box. - */ -void -MainWindow::OnHelpAbout(void) -{ - int result; - - AboutDialog dlg(this); - - result = dlg.DoModal(); - WMSG1("HelpAbout returned %d\n", result); - - /* - * User could've changed registration. If we're showing the registered - * user name in the title bar, update it. - */ - if (fpOpenArchive == nil) - SetCPTitle(); -} - -/* - * Create a new SHK archive, using a "save as" dialog to select the name. - */ -void -MainWindow::OnFileNewArchive(void) -{ - CString filename, saveFolder, errStr; - GenericArchive* pOpenArchive; - CString errMsg; - - CFileDialog dlg(FALSE, _T("shk"), NULL, - OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, - "ShrinkIt Archives (*.shk)|*.shk||", this); - - dlg.m_ofn.lpstrTitle = "New Archive"; - dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); - - if (dlg.DoModal() != IDOK) - goto bail; - - saveFolder = dlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); - - filename = dlg.GetPathName(); - WMSG1("NEW FILE '%s'\n", filename); - - /* remove file if it already exists */ - errMsg = RemoveFile(filename); - if (!errMsg.IsEmpty()) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } - - pOpenArchive = new NufxArchive; - errStr = pOpenArchive->New(filename, nil); - if (!errStr.IsEmpty()) { - CString failed; - failed.LoadString(IDS_FAILED); - MessageBox(errStr, failed, MB_ICONERROR); - - delete pOpenArchive; - } else { - SwitchContentList(pOpenArchive); - fOpenArchivePathName = dlg.GetPathName(); - SetCPTitle(fOpenArchivePathName, fpOpenArchive); - } - -bail: - WMSG0("--- OnFileNewArchive done\n"); -} - - -/* - * Handle request to open an archive or disk image. - */ -void -MainWindow::OnFileOpen(void) -{ - CString openFilters; - CString saveFolder; - - /* set up filters; the order is significant */ - openFilters = kOpenNuFX; - openFilters += kOpenBinaryII; - openFilters += kOpenACU; - openFilters += kOpenDiskImage; - openFilters += kOpenAll; - openFilters += kOpenEnd; - CFileDialog dlg(TRUE, "shk", NULL, - OFN_FILEMUSTEXIST, openFilters, this); - - dlg.m_ofn.nFilterIndex = fPreferences.GetPrefLong(kPrLastOpenFilterIndex); - dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); - - if (dlg.DoModal() != IDOK) - goto bail; - - fPreferences.SetPrefLong(kPrLastOpenFilterIndex, dlg.m_ofn.nFilterIndex); - saveFolder = dlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); - - DoOpenArchive(dlg.GetPathName(), dlg.GetFileExt(), - dlg.m_ofn.nFilterIndex, dlg.GetReadOnlyPref() != 0); - -bail: - WMSG0("--- OnFileOpen done\n"); -} - -/* - * Handle request to open a raw disk volume. - */ -void -MainWindow::OnFileOpenVolume(void) -{ - WMSG0("--- OnFileOpenVolume\n"); - - int result; - - OpenVolumeDialog dlg(this); - - result = dlg.DoModal(); - if (result != IDOK) - goto bail; - - //DiskImg::SetAllowWritePhys0(fPreferences.GetPrefBool(kPrOpenVolumePhys0)); - DoOpenVolume(dlg.fChosenDrive, dlg.fReadOnly != 0); - -bail: - return; -} -void -MainWindow::OnUpdateFileOpenVolume(CCmdUI* pCmdUI) -{ - // don't really need this function - pCmdUI->Enable(TRUE); -} - -/* - * Open an archive. - */ -void -MainWindow::DoOpenArchive(const char* pathName, const char* ext, - int filterIndex, bool readOnly) -{ - if (LoadArchive(pathName, ext, filterIndex, readOnly, false) == 0) { - /* success, update title bar */ - fOpenArchivePathName = pathName; - SetCPTitle(fOpenArchivePathName, fpOpenArchive); - } else { - /* some failures will close an open archive */ - //if (fpOpenArchive == nil) - // SetCPTitle(); - } -} - -/* - * Save any pending changes. - * - * This may be called directly from tools, so don't assume that the - * conditions checked for in OnUpdateFileSave hold here. - */ -void -MainWindow::OnFileReopen(void) -{ - ReopenArchive(); -} -void -MainWindow::OnUpdateFileReopen(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(fpOpenArchive != nil); -} - - -/* - * Save any pending changes. - * - * This may be called directly from tools, so don't assume that the - * conditions checked for in OnUpdateFileSave hold here. - */ -void -MainWindow::OnFileSave(void) -{ - CString errMsg; - - if (fpOpenArchive == nil) - return; - - { - CWaitCursor waitc; - errMsg = fpOpenArchive->Flush(); - } - if (!errMsg.IsEmpty()) - ShowFailureMsg(this, errMsg, IDS_FAILED); - - // update the title bar - DoIdle(); -} -void -MainWindow::OnUpdateFileSave(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(fpOpenArchive != nil && fpOpenArchive->IsModified()); -} - -/* - * Close current archive or disk image. - */ -void -MainWindow::OnFileClose(void) -{ - CloseArchive(); - //SetCPTitle(); - WMSG0("--- OnFileClose done\n"); -} -void -MainWindow::OnUpdateFileClose(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(fpOpenArchive != nil); -} - - -/* - * Show detailed information on the current archive. - */ -void -MainWindow::OnFileArchiveInfo(void) -{ - ArchiveInfoDialog* pDlg = nil; - ASSERT(fpOpenArchive != nil); - - switch (fpOpenArchive->GetArchiveKind()) { - case GenericArchive::kArchiveNuFX: - pDlg = new NufxArchiveInfoDialog((NufxArchive*) fpOpenArchive, this); - break; - case GenericArchive::kArchiveDiskImage: - pDlg = new DiskArchiveInfoDialog((DiskArchive*) fpOpenArchive, this); - break; - case GenericArchive::kArchiveBNY: - pDlg = new BnyArchiveInfoDialog((BnyArchive*) fpOpenArchive, this); - break; - case GenericArchive::kArchiveACU: - pDlg = new AcuArchiveInfoDialog((AcuArchive*) fpOpenArchive, this); - break; - default: - WMSG1("Unexpected archive type %d\n", fpOpenArchive->GetArchiveKind()); - ASSERT(false); - return; - }; - - pDlg->DoModal(); - - delete pDlg; -} -void -MainWindow::OnUpdateFileArchiveInfo(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(fpContentList != nil); -} - -/* - * Print the contents of the current archive. - */ -void -MainWindow::OnFilePrint(void) -{ - PrintListing(fpContentList); -} -void -MainWindow::OnUpdateFilePrint(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(fpContentList != nil && fpContentList->GetItemCount() > 0); -} - -/* - * Print a ContentList. - */ -void -MainWindow::PrintListing(const ContentList* pContentList) -{ - CPrintDialog dlg(FALSE); // use CPrintDialogEx for Win2K? CPageSetUpDialog? - PrintContentList pcl; - CDC dc; - int itemCount, numPages; - - itemCount = pContentList->GetItemCount(); - numPages = (itemCount + (pcl.GetLinesPerPage()-1)) / pcl.GetLinesPerPage(); - - dlg.m_pd.nFromPage = dlg.m_pd.nMinPage = 1; - dlg.m_pd.nToPage = dlg.m_pd.nMaxPage = numPages; - - dlg.m_pd.hDevMode = fhDevMode; - dlg.m_pd.hDevNames = fhDevNames; - dlg.m_pd.Flags |= PD_USEDEVMODECOPIESANDCOLLATE; - dlg.m_pd.Flags &= ~(PD_NOPAGENUMS); - if (dlg.DoModal() != IDOK) - return; - if (dc.Attach(dlg.GetPrinterDC()) != TRUE) { - CString msg; - msg.LoadString(IDS_PRINTER_NOT_USABLE); - ShowFailureMsg(this, msg, IDS_FAILED); - return; - } - - pcl.Setup(&dc, this); - if (dlg.m_pd.Flags & PD_PAGENUMS) - pcl.Print(pContentList, dlg.m_pd.nFromPage, dlg.m_pd.nToPage); - else - pcl.Print(pContentList); - - fhDevMode = dlg.m_pd.hDevMode; - fhDevNames = dlg.m_pd.hDevNames; -} - - -/* - * Handle Exit item by sending a close request. - */ -void -MainWindow::OnFileExit(void) -{ - SendMessage(WM_CLOSE, 0, 0); -} - - -/* - * Select everything in the content list. - */ -void -MainWindow::OnEditSelectAll(void) -{ - ASSERT(fpContentList != nil); - fpContentList->SelectAll(); -} -void -MainWindow::OnUpdateEditSelectAll(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(fpContentList != nil); -} - -/* - * Invert the content list selection. - */ -void -MainWindow::OnEditInvertSelection(void) -{ - ASSERT(fpContentList != nil); - fpContentList->InvertSelection(); -} -void -MainWindow::OnUpdateEditInvertSelection(CCmdUI* pCmdUI) -{ - pCmdUI->Enable(fpContentList != nil); -} - - -/* - * Get the one selected item from the current display. Primarily useful - * for the double-click handler, but also used for "action" menu items - * that insist on operating on a single menu item (edit prefs, create subdir). - * - * Returns nil if the item couldn't be found or if more than one item was - * selected. - */ -GenericEntry* -MainWindow::GetSelectedItem(ContentList* pContentList) -{ - if (pContentList->GetSelectedCount() != 1) - return nil; - - POSITION posn; - posn = pContentList->GetFirstSelectedItemPosition(); - if (posn == nil) { - ASSERT(false); - return nil; - } - int num = pContentList->GetNextSelectedItem(/*ref*/ posn); - GenericEntry* pEntry = (GenericEntry*) pContentList->GetItemData(num); - if (pEntry == nil) { - WMSG1(" Glitch: couldn't find entry %d\n", num); - ASSERT(false); - } - - return pEntry; -} - -/* - * Handle a double-click. - * - * Individual items get special treatment, multiple items just get handed off - * to the file viewer. - */ -void -MainWindow::HandleDoubleClick(void) -{ - bool handled = false; - - ASSERT(fpContentList != nil); - if (fpContentList->GetSelectedCount() == 0) { - /* nothing selected, they double-clicked outside first column */ - WMSG0("Double-click but nothing selected\n"); - return; - } - if (fpContentList->GetSelectedCount() != 1) { - /* multiple items, just bring up viewer */ - HandleView(); - return; - } - - /* - * Find the GenericEntry that corresponds to this item. - */ - GenericEntry* pEntry = GetSelectedItem(fpContentList); - if (pEntry == nil) - return; - - WMSG1(" Double-click GOT '%s'\n", pEntry->GetPathName()); - const char* ext; - long fileType, auxType; - - ext = FindExtension(pEntry->GetPathName(), pEntry->GetFssep()); - fileType = pEntry->GetFileType(); - auxType = pEntry->GetAuxType(); - - /* // unit tests for MatchSemicolonList - MatchSemicolonList("gif; jpeg; jpg", "jpeg"); - MatchSemicolonList("gif; jpeg; jpg", "jpg"); - MatchSemicolonList("gif; jpeg; jpg", "gif"); - MatchSemicolonList("gif;jpeg;jpg", "gif;"); - MatchSemicolonList("gif; jpeg; jpg", "jpe"); - MatchSemicolonList("gif; jpeg; jpg", "jpegx"); - MatchSemicolonList("gif; jpeg; jpg", "jp"); - MatchSemicolonList("gif; jpeg; jpg", "jpgx"); - MatchSemicolonList("gif; jpeg; jpg", "if"); - MatchSemicolonList("gif; jpeg; jpg", "gifs"); - MatchSemicolonList("gif, jpeg; jpg", "jpeg"); - MatchSemicolonList("", "jpeg"); - MatchSemicolonList(";", "jpeg"); - MatchSemicolonList("gif, jpeg; jpg", ""); - */ - - /* - * Figure out what to do with it. - */ - CString extViewerExts; - extViewerExts = fPreferences.GetPrefString(kPrExtViewerExts); - if (ext != nil && MatchSemicolonList(extViewerExts, ext+1)) { - WMSG1(" Launching external viewer for '%s'\n", ext); - TmpExtractForExternal(pEntry); - handled = true; - } else if (pEntry->GetRecordKind() == GenericEntry::kRecordKindFile) { - if ((ext != nil && ( - stricmp(ext, ".shk") == 0 || - stricmp(ext, ".sdk") == 0 || - stricmp(ext, ".bxy") == 0 )) || - (fileType == 0xe0 && auxType == 0x8002)) - { - WMSG0(" Guessing NuFX\n"); - TmpExtractAndOpen(pEntry, GenericEntry::kDataThread, kModeNuFX); - handled = true; - } else - if ((ext != nil && ( - stricmp(ext, ".bny") == 0 || - stricmp(ext, ".bqy") == 0 )) || - (fileType == 0xe0 && auxType == 0x8000)) - { - WMSG0(" Guessing Binary II\n"); - TmpExtractAndOpen(pEntry, GenericEntry::kDataThread, kModeBinaryII); - handled = true; - } else - if ((ext != nil && ( - stricmp(ext, ".acu") == 0 )) || - (fileType == 0xe0 && auxType == 0x8001)) - { - WMSG0(" Guessing ACU\n"); - TmpExtractAndOpen(pEntry, GenericEntry::kDataThread, kModeACU); - handled = true; - } else - if (fileType == 0x64496d67 && auxType == 0x64437079 && - pEntry->GetUncompressedLen() == 819284) - { - /* type is dImg, creator is dCpy, length is 800K + DC stuff */ - WMSG0(" Looks like a disk image\n"); - TmpExtractAndOpen(pEntry, GenericEntry::kDataThread, kModeDiskImage); - handled = true; - } - } else if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDisk) { - WMSG0(" Opening archived disk image\n"); - TmpExtractAndOpen(pEntry, GenericEntry::kDiskImageThread, kModeDiskImage); - handled = true; - } - - if (!handled) { - // standard viewer - HandleView(); - } - - /* set "/t" temp flag and delete afterward, warning user (?) */ -} - -/* - * Extract a record to the temp folder and open it with a new instance of - * CiderPress. We might want to extract disk images as 2MG files to take - * the mystery out of opening them, but since they're coming out of a - * ShrinkIt archive they're pretty un-mysterious anyway. - * - * We tell the new instance to open it read-only, and flag it for - * deletion on exit. - * - * Returns 0 on success, nonzero error status on failure. - */ -int -MainWindow::TmpExtractAndOpen(GenericEntry* pEntry, int threadKind, - const char* modeStr) -{ - CString dispName; - bool mustDelete = false; - - /* - * Get the name to display in the title bar. Double quotes will - * screw it up, so we have to replace them. (We could escape them, - * but then we'd also have to escape the escape char.) - */ - dispName = pEntry->GetFileName(); - dispName.Replace('"', '_'); - - char nameBuf[MAX_PATH]; - UINT unique; - unique = GetTempFileName(fPreferences.GetPrefString(kPrTempPath), - "CPfile", 0, nameBuf); - if (unique == 0) { - DWORD dwerr = ::GetLastError(); - WMSG2("GetTempFileName failed on '%s' (err=%ld)\n", - fPreferences.GetPrefString(kPrTempPath), dwerr); - return dwerr; - } - mustDelete = true; - - /* - * Open the temp file and extract the data into it. - */ - CString errMsg; - int result; - FILE* fp; - - fp = fopen(nameBuf, "wb"); - if (fp != nil) { - WMSG2("Extracting to '%s' (unique=%d)\n", nameBuf, unique); - result = pEntry->ExtractThreadToFile(threadKind, fp, - GenericEntry::kConvertEOLOff, GenericEntry::kConvertHAOff, - &errMsg); - fclose(fp); - if (result == IDOK) { - /* success */ - CString parameters; - - parameters.Format("-mode %s -dispname \"%s\" -temparc \"%s\"", - modeStr, dispName, nameBuf); - int err; - - err = (int) ::ShellExecute(m_hWnd, _T("open"), - gMyApp.GetExeFileName(), parameters, NULL, - SW_SHOWNORMAL); - if (err <= 32) { - CString msg; - msg.Format("Unable to launch CiderPress (err=%d).", err); - ShowFailureMsg(this, msg, IDS_FAILED); - } else { - /* during dev, "missing DLL" causes false-positive success */ - WMSG0("Successfully launched CiderPress\n"); - mustDelete = false; // up to newly-launched app - } - } else { - ShowFailureMsg(this, errMsg, IDS_FAILED); - } - } else { - CString msg; - msg.Format("Unable to open temp file '%s'.", nameBuf); - ::ShowFailureMsg(this, msg, IDS_FAILED); - } - - if (mustDelete) { - WMSG1("Deleting '%s'\n", nameBuf); - unlink(nameBuf); - } - - return 0; -} - -/* - * Extract a record to the temp folder and open it with an external viewer. - * The file must be created with the correct extension so ShellExecute - * does the right thing. - * - * The files will be added to the "delete on exit" list, so that they will - * be cleaned up when CiderPress exits (assuming the external viewer no longer - * has them open). - * - * The GetTempFileName function creates a uniquely-named temp file. We - * create a file that has that name plus an extension. To ensure that we - * don't try to use the same temp filename twice, we have to hold off on - * deleting the unused .tmp files until we're ready to delete the - * corresponding .gif (or whatever) files. Thus, each invocation of this - * function creates two files and two entries in the delete-on-exit set. - * - * Returns 0 on success, nonzero error status on failure. - */ -int -MainWindow::TmpExtractForExternal(GenericEntry* pEntry) -{ - const char* ext; - - ext = FindExtension(pEntry->GetPathName(), pEntry->GetFssep()); - - char nameBuf[MAX_PATH]; - UINT unique; - unique = GetTempFileName(fPreferences.GetPrefString(kPrTempPath), - "CPfile", 0, nameBuf); - if (unique == 0) { - DWORD dwerr = ::GetLastError(); - WMSG2("GetTempFileName failed on '%s' (err=%ld)\n", - fPreferences.GetPrefString(kPrTempPath), dwerr); - return dwerr; - } - fDeleteList.Add(nameBuf); // file is created by GetTempFileName - - strcat(nameBuf, ext); - - /* - * Open the temp file and extract the data into it. - */ - CString errMsg; - int result; - FILE* fp; - - fp = fopen(nameBuf, "wb"); - if (fp != nil) { - fDeleteList.Add(nameBuf); // second file created by fopen - WMSG2("Extracting to '%s' (unique=%d)\n", nameBuf, unique); - result = pEntry->ExtractThreadToFile(GenericEntry::kDataThread, fp, - GenericEntry::kConvertEOLOff, GenericEntry::kConvertHAOff, - &errMsg); - fclose(fp); - if (result == IDOK) { - /* success */ - int err; - - err = (int) ::ShellExecute(m_hWnd, _T("open"), nameBuf, NULL, - NULL, SW_SHOWNORMAL); - if (err <= 32) { - CString msg; - msg.Format("Unable to launch external viewer (err=%d).", err); - ShowFailureMsg(this, msg, IDS_FAILED); - } else { - WMSG0("Successfully launched external viewer\n"); - } - } else { - ShowFailureMsg(this, errMsg, IDS_FAILED); - } - } else { - CString msg; - msg.Format("Unable to open temp file '%s'.", nameBuf); - ShowFailureMsg(this, msg, IDS_FAILED); - } - - return 0; -} - -#if 0 -/* - * Handle a "default action" selection from the right-click menu. The - * action only applies to the record that was clicked on, so we need to - * retrieve that from the control. - */ -void -MainWindow::OnRtClkDefault(void) -{ - int idx; - - ASSERT(fpContentList != nil); - - idx = fpContentList->GetRightClickItem(); - ASSERT(idx != -1); - WMSG1("OnRtClkDefault %d\n", idx); - - fpContentList->ClearRightClickItem(); -} -#endif - - -/* - * =================================== - * Progress meter - * =================================== - */ - -/* - * There are two different mechanisms for reporting progress: ActionProgress - * dialogs (for adding/extracting files) and a small box in the lower - * right-hand corner (for opening archives). These functions will set - * the progress in the active action progress dialog if it exists, or - * will set the percentage in the window frame if not. - */ - -void -MainWindow::SetProgressBegin(void) -{ - if (fpActionProgress != nil) - fpActionProgress->SetProgress(0); - else - fStatusBar.SetPaneText(kProgressPane, "--%"); - //WMSG0(" Complete: BEGIN\n"); - - /* redraw stuff with the changes */ - (void) PeekAndPump(); -} - -int -MainWindow::SetProgressUpdate(int percent, const char* oldName, - const char* newName) -{ - int status = IDOK; - - if (fpActionProgress != nil) { - status = fpActionProgress->SetProgress(percent); - if (oldName != nil) - fpActionProgress->SetArcName(oldName); - if (newName != nil) - fpActionProgress->SetFileName(newName); - } else { - char buf[8]; - sprintf(buf, "%d%%", percent); - fStatusBar.SetPaneText(kProgressPane, buf); - //WMSG1(" Complete: %s\n", buf); - } - - if (!PeekAndPump()) { - WMSG0("SetProgressUpdate: shutdown?!\n"); - } - - //EventPause(10); // DEBUG DEBUG - return status; -} - -void -MainWindow::SetProgressEnd(void) -{ - if (fpActionProgress != nil) - fpActionProgress->SetProgress(100); - else - fStatusBar.SetPaneText(kProgressPane, ""); -// EventPause(100); // DEBUG DEBUG - //WMSG0(" Complete: END\n"); -} - - -/* - * Set a number in the "progress counter". Useful for loading large archives - * where we're not sure how much stuff is left, so showing a percentage is - * hard. - * - * Pass in -1 to erase the counter. - * - * Returns "true" if we'd like things to continue. - */ -bool -MainWindow::SetProgressCounter(const char* str, long val) -{ - /* if the main window is enabled, user could activate menus */ - ASSERT(!IsWindowEnabled()); - - if (fpProgressCounter != nil) { - //WMSG2("SetProgressCounter '%s' %d\n", str, val); - CString msg; - - if (str != nil) - fpProgressCounter->SetCounterFormat(str); - fpProgressCounter->SetCount((int) val); - } else { - if (val < 0) { - fStatusBar.SetPaneText(kProgressPane, ""); - } else { - CString tmpStr; - tmpStr.Format("%ld", val); - fStatusBar.SetPaneText(kProgressPane, tmpStr); - } - } - - if (!PeekAndPump()) { - WMSG0("SetProgressCounter: shutdown?!\n"); - } - //EventPause(10); // DEBUG DEBUG - - if (fpProgressCounter != nil) - return !fpProgressCounter->GetCancel(); - else - return true; -} - - -/* - * Allow events to flow through the message queue whenever the - * progress meter gets updated. This will allow us to redraw with - * reasonable frequency. - * - * Calling this can result in other code being called, such as Windows - * message handlers, which can lead to reentrancy problems. Make sure - * you're adequately semaphored before calling here. - * - * Returns TRUE if all is well, FALSE if we're trying to quit. - */ -BOOL -MainWindow::PeekAndPump(void) -{ - MSG msg; - - while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { - if (!AfxGetApp()->PumpMessage()) { - ::PostQuitMessage(0); - return FALSE; - } - } - - LONG lIdle = 0; - while (AfxGetApp()->OnIdle(lIdle++)) - ; - return TRUE; -} - -/* - * Go to sleep for a little bit, waking up 100x per second to check - * the idle loop. - */ -void -MainWindow::EventPause(int duration) -{ - int count = duration / 10; - - for (int i = 0; i < count; i++) { - PeekAndPump(); - ::Sleep(10); - } -} - -/* - * Printer abort procedure; allows us to abort a print job. The DC - * SetAbortProc() function calls here periodically. The return value from - * this function determine whether or not printing halts. - * - * This checks a global "print cancel" variable, which is set by our print - * cancel button dialog. - * - * If this returns TRUE, printing continues; FALSE, and printing aborts. - */ -/*static*/ BOOL CALLBACK -MainWindow::PrintAbortProc(HDC hDC, int nCode) -{ - MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); - - pMain->PeekAndPump(); - if (pMain->GetAbortPrinting()) { - WMSG0("PrintAbortProc returning FALSE (abort printing)\n"); - return FALSE; - } - WMSG0(" PrintAbortProc returning TRUE (continue printing)\n"); - return TRUE; -} - -/* - * =================================== - * Support functions - * =================================== - */ - -/* - * Draw what looks like an empty client area. - */ -void -MainWindow::DrawEmptyClientArea(CDC* pDC, const CRect& clientRect) -{ - CBrush brush; - brush.CreateSolidBrush(::GetSysColor(COLOR_APPWORKSPACE)); // dk gray - CBrush* pOldBrush = pDC->SelectObject(&brush); - pDC->FillRect(&clientRect, &brush); - pDC->SelectObject(pOldBrush); - - CPen penWH(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT)); // white - CPen penLG(PS_SOLID, 1, ::GetSysColor(COLOR_3DLIGHT)); // lt gray - CPen penDG(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW)); // dk gray - CPen penBL(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW)); // near-black - CPen* pOldPen = pDC->SelectObject(&penWH); - //pDC->SelectObject(&penWH); - pDC->MoveTo(clientRect.right-1, clientRect.top); - pDC->LineTo(clientRect.right-1, clientRect.bottom-1); - pDC->LineTo(clientRect.left-1, clientRect.bottom-1); - pDC->SelectObject(&penBL); - pDC->MoveTo(clientRect.right-3, clientRect.top+1); - pDC->LineTo(clientRect.left+1, clientRect.top+1); - pDC->LineTo(clientRect.left+1, clientRect.bottom-2); - pDC->SelectObject(&penLG); - pDC->MoveTo(clientRect.right-2, clientRect.top+1); - pDC->LineTo(clientRect.right-2, clientRect.bottom-2); - pDC->LineTo(clientRect.left, clientRect.bottom-2); - pDC->SelectObject(&penDG); - pDC->MoveTo(clientRect.right-2, clientRect.top); - pDC->LineTo(clientRect.left, clientRect.top); - pDC->LineTo(clientRect.left, clientRect.bottom-1); - - pDC->SelectObject(pOldPen); -} - -/* - * Load an archive, using the appropriate GenericArchive subclass. If - * "createFile" is "true", a new archive file will be created (and must - * not already exist!). - * - * "filename" is the full path to the file, "extension" is the - * filetype component of the name (without the leading '.'), "filterIndex" - * is the offset into the set of filename filters used in the standard - * file dialog, "readOnly" reflects the state of the stdfile dialog - * checkbox, and "createFile" is set to true by the "New Archive" command. - * - * Returns 0 on success, nonzero on failure. - */ -int -MainWindow::LoadArchive(const char* fileName, const char* extension, - int filterIndex, bool readOnly, bool createFile) -{ - GenericArchive::OpenResult openResult; - int result = -1; - GenericArchive* pOpenArchive = nil; - int origFilterIndex = filterIndex; - CString errStr, appName; - - appName.LoadString(IDS_MB_APP_NAME); - - WMSG3("LoadArchive: '%s' ro=%d idx=%d\n", fileName, readOnly, filterIndex); - - /* close any existing archive to avoid weirdness from re-open */ - CloseArchive(); - - /* - * If they used the "All Files (*.*)" filter, we have to guess based - * on the file type. - * - * IDEA: change the current "filterIndex ==" stuff to a type-specific - * model, then do type-scanning here. Code later on takes the type - * and opens it. That way we can do the trivial "it must be" handling - * up here, and maybe do a little "open it up and see" stuff as well. - * In general, though, if we don't recognize the extension, it's - * probably a disk image. - */ - if (filterIndex == kFilterIndexGeneric) { - int i; - - for (i = 0; i < NELEM(gExtensionToIndex); i++) { - if (strcasecmp(extension, gExtensionToIndex[i].extension) == 0) { - filterIndex = gExtensionToIndex[i].idx; - break; - } - } - - if (i == NELEM(gExtensionToIndex)) - filterIndex = kFilterIndexDiskImage; - } - -try_again: - if (filterIndex == kFilterIndexBinaryII) { - /* try Binary II and nothing else */ - ASSERT(!createFile); - WMSG0(" Trying Binary II\n"); - pOpenArchive = new BnyArchive; - openResult = pOpenArchive->Open(fileName, readOnly, &errStr); - if (openResult != GenericArchive::kResultSuccess) { - if (!errStr.IsEmpty()) - ShowFailureMsg(this, errStr, IDS_FAILED); - result = -1; - goto bail; - } - } else - if (filterIndex == kFilterIndexACU) { - /* try ACU and nothing else */ - ASSERT(!createFile); - WMSG0(" Trying ACU\n"); - pOpenArchive = new AcuArchive; - openResult = pOpenArchive->Open(fileName, readOnly, &errStr); - if (openResult != GenericArchive::kResultSuccess) { - if (!errStr.IsEmpty()) - ShowFailureMsg(this, errStr, IDS_FAILED); - result = -1; - goto bail; - } - } else - if (filterIndex == kFilterIndexDiskImage) { - /* try various disk image formats */ - ASSERT(!createFile); - WMSG0(" Trying disk images\n"); - - pOpenArchive = new DiskArchive; - openResult = pOpenArchive->Open(fileName, readOnly, &errStr); - if (openResult == GenericArchive::kResultCancel) { - result = -1; - goto bail; - } else if (openResult == GenericArchive::kResultFileArchive) { - delete pOpenArchive; - pOpenArchive = nil; - - if (strcasecmp(extension, "zip") == 0) { - errStr = "ZIP archives with multiple files are not supported."; - MessageBox(errStr, appName, MB_OK|MB_ICONINFORMATION); - result = -1; - goto bail; - } else { - /* assume some variation of a ShrinkIt archive */ - // msg.LoadString(IDS_OPEN_AS_NUFX); <-- with MB_OKCANCEL - filterIndex = kFilterIndexNuFX; - goto try_again; - } - - } else if (openResult != GenericArchive::kResultSuccess) { - if (filterIndex != origFilterIndex) { - /* - * Kluge: assume we guessed disk image and were wrong. - */ - errStr = "File doesn't appear to be a valid archive" - " or disk image."; - } - if (!errStr.IsEmpty()) - ShowFailureMsg(this, errStr, IDS_FAILED); - result = -1; - goto bail; - } - } else - if (filterIndex == kFilterIndexNuFX) { - /* try NuFX (including its embedded-in-BNY form) */ - WMSG0(" Trying NuFX\n"); - - pOpenArchive = new NufxArchive; - openResult = pOpenArchive->Open(fileName, readOnly, &errStr); - if (openResult != GenericArchive::kResultSuccess) { - if (!errStr.IsEmpty()) - ShowFailureMsg(this, errStr, IDS_FAILED); - result = -1; - goto bail; - } - - } else { - ASSERT(FALSE); - result = -1; - goto bail; - } - - SwitchContentList(pOpenArchive); - - pOpenArchive = nil; - result = 0; - -bail: - if (pOpenArchive != nil) { - ASSERT(result != 0); - delete pOpenArchive; - } - return result; -} - -/* - * Open a raw disk volume. Useful for ProDOS-formatted 1.44MB floppy disks - * and CFFA flash cards. - * - * Assume it's a disk image -- it'd be a weird place for a ShrinkIt archive. - * CFFA cards can actually hold multiple volumes, but that's all taken care - * of inside the diskimg DLL. - * - * Returns 0 on success, nonzero on failure. - */ -int -MainWindow::DoOpenVolume(CString drive, bool readOnly) -{ - int result = -1; - - ASSERT(drive.GetLength() > 0); - - CString errStr; - //char filename[4] = "_:\\"; - //filename[0] = driveLetter; - - WMSG2("FileOpenVolume '%s' %d\n", (const char*)drive, readOnly); - - /* close existing archive */ - CloseArchive(); - - GenericArchive* pOpenArchive = nil; - pOpenArchive = new DiskArchive; - { - CWaitCursor waitc; - GenericArchive::OpenResult openResult; - - openResult = pOpenArchive->Open(drive, readOnly, &errStr); - if (openResult == GenericArchive::kResultCancel) { - // this bubbles out of the format confirmation dialog - goto bail; - } else if (openResult != GenericArchive::kResultSuccess) { - if (!errStr.IsEmpty()) - ShowFailureMsg(this, errStr, IDS_FAILED); - goto bail; - } - } - - // success! - SwitchContentList(pOpenArchive); - pOpenArchive = nil; - fOpenArchivePathName = drive; - result = 0; - - fOpenArchivePathName = drive; - SetCPTitle(fOpenArchivePathName, fpOpenArchive); - -bail: - if (pOpenArchive != nil) { - ASSERT(result != 0); - delete pOpenArchive; - } - return result; -} - - -/* - * Close and re-open the current archive. - */ -void -MainWindow::ReopenArchive(void) -{ - if (fpOpenArchive == nil) { - ASSERT(false); - return; - } - - /* clear the flag, regardless of success or failure */ - fNeedReopen = false; - - GenericArchive* pOpenArchive = nil; - CString pathName = fpOpenArchive->GetPathName(); - bool readOnly = fpOpenArchive->IsReadOnly(); - GenericArchive::ArchiveKind archiveKind = fpOpenArchive->GetArchiveKind(); - GenericArchive::OpenResult openResult; - CString errStr; - - /* if the open fails we *don't* want to leave the previous content up */ - WMSG3("Reopening '%s' ro=%d kind=%d\n", pathName, readOnly, archiveKind); - CloseArchive(); - - switch (archiveKind) { - case GenericArchive::kArchiveDiskImage: - pOpenArchive = new DiskArchive; - break; - case GenericArchive::kArchiveNuFX: - pOpenArchive = new NufxArchive; - break; - case GenericArchive::kArchiveBNY: - pOpenArchive = new BnyArchive; - break; - default: - ASSERT(false); - return; - } - - openResult = pOpenArchive->Open(pathName, readOnly, &errStr); - if (openResult == GenericArchive::kResultCancel) { - // this bubbles out of the format confirmation dialog - goto bail; - } else if (openResult != GenericArchive::kResultSuccess) { - if (!errStr.IsEmpty()) - ShowFailureMsg(this, errStr, IDS_FAILED); - goto bail; - } - - WMSG0(" Reopen was successful\n"); - SwitchContentList(pOpenArchive); - pOpenArchive = nil; - SetCPTitle(pathName, fpOpenArchive); - -bail: - delete pOpenArchive; -} - -/* - * Determine whether "path" matches the pathname of the currently open archive. - */ -bool -MainWindow::IsOpenPathName(const char* path) -{ - if (fpOpenArchive == nil) - return false; - - if (stricmp(path, fpOpenArchive->GetPathName()) == 0) - return true; - - return false; -} - - -/* - * Switch the content list to a new archive, closing the previous if one - * was already open. - */ -void -MainWindow::SwitchContentList(GenericArchive* pOpenArchive) -{ - assert(pOpenArchive != nil); - - /* - * We've got an archive opened successfully. If we already had one - * open, shut it. (This assumes that closing an archive is a simple - * matter of closing files and freeing storage. If we needed to do - * something that might fail, like flush changes, we should've done - * that before getting this far to avoid confusion.) - */ - if (fpOpenArchive != nil) - CloseArchive(); - - ASSERT(fpOpenArchive == nil); - ASSERT(fpContentList == nil); - - /* - * Without this we get an assertion failure in CImageList::Attach if we - * call here from ReopenArchive. I think Windows needs to do some - * cleanup, though I don't understand how the reopen case differs from - * the usual case. Maybe there's more stuff pending in the "reopen" - * case? In any event, this seems to work, which is all you can hope - * for from MFC. It does, however, make the screen flash, which it - * didn't do before. - * - * UPDATE: this tripped once while I was debugging, even with this. The - * PeekAndPump function does force the idle loop to run, so I'm not sure - * why it failed, unless the debugger somehow affected the idle - * processing. Yuck. - * - * The screen flash bugged me so I took it back out. And the assert - * didn't hit. I really, really love Windows. - */ - //PeekAndPump(); - - - fpContentList = new ContentList(pOpenArchive, - fPreferences.GetColumnLayout()); - - CRect sizeRect; - GetClientRect(&sizeRect); - fpContentList->Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL, - sizeRect, this, IDC_CONTENT_LIST); - - fpOpenArchive = pOpenArchive; -} - - -/* - * Close the existing archive file, but don't try to shut down the child - * windows. This should really only be used from the destructor. - */ -void -MainWindow::CloseArchiveWOControls(void) -{ - if (fpOpenArchive != nil) { - //fpOpenArchive->Close(); - WMSG0("Deleting OpenArchive\n"); - delete fpOpenArchive; - fpOpenArchive = nil; - } -} - -/* - * Close the existing archive file, and throw out the control we're - * using to display it. - */ -void -MainWindow::CloseArchive(void) -{ - CWaitCursor waitc; // closing large compressed archive can be slow - - // destroy the ContentList - if (fpContentList != nil) { - WMSG0("Destroying ContentList\n"); - fpContentList->DestroyWindow(); // auto-cleanup invokes "delete" - fpContentList = nil; - } - - // destroy the GenericArchive - CloseArchiveWOControls(); - - // reset the title bar - SetCPTitle(); -} - - -/* - * Set the title bar on the main window. - * - * "pathname" is often different from pOpenArchive->GetPathName(), especially - * when we were launched from another instance of CiderPress and handed a - * temp file whose name we're trying to conceal. - */ -void -MainWindow::SetCPTitle(const char* pathname, GenericArchive* pOpenArchive) -{ - ASSERT(pathname != nil); - CString title; - CString archiveDescription; - CString appName; - - appName.LoadString(IDS_MB_APP_NAME); - - pOpenArchive->GetDescription(&archiveDescription); - title.Format(_T("%s - %s (%s)"), appName, pathname, archiveDescription); - - if (fpOpenArchive->IsReadOnly()) { - CString readOnly; - readOnly.LoadString(IDS_READONLY); - title += _T(" "); - title += readOnly; - } - - SetWindowText(title); -} - -/* - * Set the title bar to something boring when nothing is open. - */ -void -MainWindow::SetCPTitle(void) -{ - CString appName, regName, title; - CString user, company, reg, versions, expire; - -#if 0 - if (gMyApp.fRegistry.GetRegistration(&user, &company, ®, &versions, - &expire) == 0) - { - if (reg.IsEmpty()) { - regName += _T(" (unregistered)"); - } else { - regName += _T(" (registered to "); - regName += user; - regName += _T(")"); - // include company? - } - } -#endif - - appName.LoadString(IDS_MB_APP_NAME); - title = appName + regName; - SetWindowText(title); -} - -/* - * Come up with a title to put at the top of a printout. This is essentially - * the same as the window title, but without some flags (e.g. "read-only"). - */ -CString -MainWindow::GetPrintTitle(void) -{ - CString title; - CString archiveDescription; - CString appName; - - if (fpOpenArchive == nil) { - ASSERT(false); - return title; - } - - appName.LoadString(IDS_MB_APP_NAME); - - fpOpenArchive->GetDescription(&archiveDescription); - title.Format(_T("%s - %s (%s)"), - appName, fOpenArchivePathName, archiveDescription); - - return title; -} - - -/* - * After successful completion of a command, make a happy noise (but only - * if we're configured to do so). - */ -void -MainWindow::SuccessBeep(void) -{ - const Preferences* pPreferences = GET_PREFERENCES(); - - if (pPreferences->GetPrefBool(kPrBeepOnSuccess)) { - WMSG0("\n"); - ::MessageBeep(MB_OK); - } -} - -/* - * If something fails, make noise if we're configured for loudness. - */ -void -MainWindow::FailureBeep(void) -{ - const Preferences* pPreferences = GET_PREFERENCES(); - - if (pPreferences->GetPrefBool(kPrBeepOnSuccess)) { - WMSG0("\n"); - ::MessageBeep(MB_ICONEXCLAMATION); // maybe MB_ICONHAND? - } -} - -/* - * Remove a file. Returns a helpful error string on failure. - * - * The absence of the file is not considered an error. - */ -CString -MainWindow::RemoveFile(const char* fileName) -{ - CString errMsg; - - int cc; - cc = unlink(fileName); - if (cc < 0 && errno != ENOENT) { - int err = errno; - WMSG2("Failed removing file '%s', errno=%d\n", fileName, err); - errMsg.Format("Unable to remove '%s': %s.", - fileName, strerror(err)); - if (err == EACCES) - errMsg += "\n\n(Make sure the file isn't open.)"; - } - - return errMsg; -} - - -/* - * Configure a ReformatHolder based on the current preferences. - */ -/*static*/ void -MainWindow::ConfigureReformatFromPreferences(ReformatHolder* pReformat) -{ - const Preferences* pPreferences = GET_PREFERENCES(); - - pReformat->SetReformatAllowed(ReformatHolder::kReformatRaw, true); - pReformat->SetReformatAllowed(ReformatHolder::kReformatHexDump, true); - - pReformat->SetReformatAllowed(ReformatHolder::kReformatTextEOL_HA, - pPreferences->GetPrefBool(kPrConvTextEOL_HA)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatResourceFork, - pPreferences->GetPrefBool(kPrConvResources)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatProDOSDirectory, - pPreferences->GetPrefBool(kPrConvProDOSFolder)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatPascalText, - pPreferences->GetPrefBool(kPrConvPascalText)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatPascalCode, - pPreferences->GetPrefBool(kPrConvPascalCode)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatCPMText, - pPreferences->GetPrefBool(kPrConvCPMText)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatApplesoft, - pPreferences->GetPrefBool(kPrConvApplesoft)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatApplesoft_Hilite, - pPreferences->GetPrefBool(kPrConvApplesoft)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatInteger, - pPreferences->GetPrefBool(kPrConvInteger)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatInteger_Hilite, - pPreferences->GetPrefBool(kPrConvInteger)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatBusiness, - pPreferences->GetPrefBool(kPrConvBusiness)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatBusiness_Hilite, - pPreferences->GetPrefBool(kPrConvBusiness)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatSCAssem, - pPreferences->GetPrefBool(kPrConvSCAssem)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatMerlin, - pPreferences->GetPrefBool(kPrConvSCAssem)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatLISA2, - pPreferences->GetPrefBool(kPrConvSCAssem)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatLISA3, - pPreferences->GetPrefBool(kPrConvSCAssem)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatLISA4, - pPreferences->GetPrefBool(kPrConvSCAssem)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatMonitor8, - pPreferences->GetPrefBool(kPrConvDisasm)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatDisasmMerlin8, - pPreferences->GetPrefBool(kPrConvDisasm)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatMonitor16Long, - pPreferences->GetPrefBool(kPrConvDisasm)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatMonitor16Short, - pPreferences->GetPrefBool(kPrConvDisasm)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatDisasmOrcam16, - pPreferences->GetPrefBool(kPrConvDisasm)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatAWGS_WP, - pPreferences->GetPrefBool(kPrConvGWP)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatTeach, - pPreferences->GetPrefBool(kPrConvGWP)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatGWP, - pPreferences->GetPrefBool(kPrConvGWP)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatMagicWindow, - pPreferences->GetPrefBool(kPrConvText8)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatGutenberg, - pPreferences->GetPrefBool(kPrConvGutenberg)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatAWP, - pPreferences->GetPrefBool(kPrConvAWP)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatAWP, - pPreferences->GetPrefBool(kPrConvAWP)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatADB, - pPreferences->GetPrefBool(kPrConvADB)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatASP, - pPreferences->GetPrefBool(kPrConvASP)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatHiRes, - pPreferences->GetPrefBool(kPrConvHiRes)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatHiRes_BW, - pPreferences->GetPrefBool(kPrConvHiRes)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatDHR_Latched, - pPreferences->GetPrefBool(kPrConvDHR)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatDHR_BW, - pPreferences->GetPrefBool(kPrConvDHR)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatDHR_Plain140, - pPreferences->GetPrefBool(kPrConvDHR)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatDHR_Window, - pPreferences->GetPrefBool(kPrConvDHR)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_PIC, - pPreferences->GetPrefBool(kPrConvSHR)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_JEQ, - pPreferences->GetPrefBool(kPrConvSHR)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_Paintworks, - pPreferences->GetPrefBool(kPrConvSHR)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_Packed, - pPreferences->GetPrefBool(kPrConvSHR)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_APF, - pPreferences->GetPrefBool(kPrConvSHR)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_3200, - pPreferences->GetPrefBool(kPrConvSHR)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_3201, - pPreferences->GetPrefBool(kPrConvSHR)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_DG256, - pPreferences->GetPrefBool(kPrConvSHR)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_DG3200, - pPreferences->GetPrefBool(kPrConvSHR)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatPrintShop, - pPreferences->GetPrefBool(kPrConvPrintShop)); - pReformat->SetReformatAllowed(ReformatHolder::kReformatMacPaint, - pPreferences->GetPrefBool(kPrConvMacPaint)); - - pReformat->SetOption(ReformatHolder::kOptHiliteHexDump, - pPreferences->GetPrefBool(kPrHighlightHexDump)); - pReformat->SetOption(ReformatHolder::kOptHiliteBASIC, - pPreferences->GetPrefBool(kPrHighlightBASIC)); - pReformat->SetOption(ReformatHolder::kOptHiResBW, - pPreferences->GetPrefBool(kPrConvHiResBlackWhite)); - pReformat->SetOption(ReformatHolder::kOptDHRAlgorithm, - pPreferences->GetPrefLong(kPrConvDHRAlgorithm)); - pReformat->SetOption(ReformatHolder::kOptRelaxGfxTypeCheck, - pPreferences->GetPrefBool(kPrRelaxGfxTypeCheck)); - pReformat->SetOption(ReformatHolder::kOptOneByteBrkCop, - pPreferences->GetPrefBool(kPrDisasmOneByteBrkCop)); -} - -/* - * Convert a DiskImg format spec into a ReformatHolder SourceFormat. - */ -/*static*/ ReformatHolder::SourceFormat -MainWindow::ReformatterSourceFormat(DiskImg::FSFormat format) -{ - /* - * Gutenberg both UsesDOSFileStructure and is formatted with - * kFormatGutenberg, so check for the latter first. - */ - if (format == DiskImg::kFormatGutenberg) - return ReformatHolder::kSourceFormatGutenberg; - else if (DiskImg::UsesDOSFileStructure(format)) - return ReformatHolder::kSourceFormatDOS; - else if (format == DiskImg::kFormatCPM) - return ReformatHolder::kSourceFormatCPM; - else - return ReformatHolder::kSourceFormatGeneric; -} +/* + * CiderPress + * Copyright (C) 2007, 2008 by faddenSoft, LLC. All Rights Reserved. + * See the file LICENSE for distribution terms. + */ +/* + * Main window management. + */ +#include "stdafx.h" +#include "Main.h" +#include "MyApp.h" +#include "AboutDialog.h" +#include "NufxArchive.h" +#include "DiskArchive.h" +#include "BNYArchive.h" +#include "ACUArchive.h" +#include "ArchiveInfoDialog.h" +#include "PrefsDialog.h" +#include "EnterRegDialog.h" +#include "OpenVolumeDialog.h" +#include "Print.h" +#include "HelpTopics.h" +#include "../util/UtilLib.h" +#include "resource.h" + +/* use MFC's fancy version of new for debugging */ +//#define new DEBUG_NEW + +static const char* kWebSiteURL = "http://www.faddensoft.com/"; + +/* + * Filters for the "open file" command. In some cases a file may be opened + * in more than one format, so it's necessary to keep track of what the + * file filter was set to when the file was opened. + */ +const char MainWindow::kOpenNuFX[] = + "ShrinkIt Archives (.shk .sdk .bxy .sea .bse)|*.shk;*.sdk;*.bxy;*.sea;*.bse|"; +const char MainWindow::kOpenBinaryII[] = + "Binary II Archives (.bny .bqy .bxy)|*.bny;*.bqy;*.bxy|"; +const char MainWindow::kOpenACU[] = + "ACU Archives (.acu)|*.acu|"; +const char MainWindow::kOpenDiskImage[] = + "Disk Images (.shk .sdk .dsk .po .do .d13 .2mg .img .nib .nb2 .raw .hdv .dc .dc6 .ddd .app .fdi .iso .gz .zip)|" + "*.shk;*.sdk;*.dsk;*.po;*.do;*.d13;*.2mg;*.img;*.nib;*.nb2;*.raw;*.hdv;*.dc;*.dc6;*.ddd;*.app;*.fdi;*.iso;*.gz;*.zip|"; +const char MainWindow::kOpenAll[] = + "All Files (*.*)|*.*|"; +const char MainWindow::kOpenEnd[] = + "|"; + +static const struct { + //const char* extension; + char extension[4]; + FilterIndex idx; +} gExtensionToIndex[] = { + { "shk", kFilterIndexNuFX }, + { "bxy", kFilterIndexNuFX }, + { "bse", kFilterIndexNuFX }, + { "sea", kFilterIndexNuFX }, + { "bny", kFilterIndexBinaryII }, + { "bqy", kFilterIndexBinaryII }, + { "acu", kFilterIndexACU }, + { "dsk", kFilterIndexDiskImage }, + { "po", kFilterIndexDiskImage }, + { "do", kFilterIndexDiskImage }, + { "d13", kFilterIndexDiskImage }, + { "2mg", kFilterIndexDiskImage }, + { "img", kFilterIndexDiskImage }, + { "sdk", kFilterIndexDiskImage }, + { "raw", kFilterIndexDiskImage }, + { "ddd", kFilterIndexDiskImage }, + { "app", kFilterIndexDiskImage }, + { "fdi", kFilterIndexDiskImage }, + { "iso", kFilterIndexDiskImage }, + { "gz", kFilterIndexDiskImage }, // assume disk image inside + { "zip", kFilterIndexDiskImage }, // assume disk image inside +}; + +const char* MainWindow::kModeNuFX = _T("nufx"); +const char* MainWindow::kModeBinaryII = _T("bin2"); +const char* MainWindow::kModeACU = _T("acu"); +const char* MainWindow::kModeDiskImage = _T("disk"); + + +/* + * =========================================================================== + * MainWindow + * =========================================================================== + */ + +static const UINT gFindReplaceID = RegisterWindowMessage(FINDMSGSTRING); + +BEGIN_MESSAGE_MAP(MainWindow, CFrameWnd) + ON_WM_CREATE() + ON_MESSAGE(WMU_LATE_INIT, OnLateInit) + //ON_MESSAGE(WMU_CLOSE_MAIN_DIALOG, OnCloseMainDialog) + ON_WM_SIZE() + ON_WM_GETMINMAXINFO() + ON_WM_PAINT() + //ON_WM_MOUSEWHEEL() + ON_WM_SETFOCUS() + ON_WM_HELPINFO() + ON_WM_QUERYENDSESSION() + ON_WM_ENDSESSION() + ON_REGISTERED_MESSAGE(gFindReplaceID, OnFindDialogMessage) + ON_COMMAND( IDM_FILE_NEW_ARCHIVE, OnFileNewArchive) + ON_COMMAND( IDM_FILE_OPEN, OnFileOpen) + ON_COMMAND( IDM_FILE_OPEN_VOLUME, OnFileOpenVolume) + ON_UPDATE_COMMAND_UI(IDM_FILE_OPEN_VOLUME, OnUpdateFileOpenVolume) + ON_COMMAND( IDM_FILE_REOPEN, OnFileReopen) + ON_UPDATE_COMMAND_UI(IDM_FILE_REOPEN, OnUpdateFileReopen) + ON_COMMAND( IDM_FILE_SAVE, OnFileSave) + ON_UPDATE_COMMAND_UI(IDM_FILE_SAVE, OnUpdateFileSave) + ON_COMMAND( IDM_FILE_CLOSE, OnFileClose) + ON_UPDATE_COMMAND_UI(IDM_FILE_CLOSE, OnUpdateFileClose) + ON_COMMAND( IDM_FILE_ARCHIVEINFO, OnFileArchiveInfo) + ON_UPDATE_COMMAND_UI(IDM_FILE_ARCHIVEINFO, OnUpdateFileArchiveInfo) + ON_COMMAND( IDM_FILE_PRINT, OnFilePrint) + ON_UPDATE_COMMAND_UI(IDM_FILE_PRINT, OnUpdateFilePrint) + ON_COMMAND( IDM_FILE_EXIT, OnFileExit) + ON_COMMAND( IDM_EDIT_COPY, OnEditCopy) + ON_UPDATE_COMMAND_UI(IDM_EDIT_COPY, OnUpdateEditCopy) + ON_COMMAND( IDM_EDIT_PASTE, OnEditPaste) + ON_UPDATE_COMMAND_UI(IDM_EDIT_PASTE, OnUpdateEditPaste) + ON_COMMAND( IDM_EDIT_PASTE_SPECIAL, OnEditPasteSpecial) + ON_UPDATE_COMMAND_UI(IDM_EDIT_PASTE_SPECIAL, OnUpdateEditPasteSpecial) + ON_COMMAND( IDM_EDIT_FIND, OnEditFind) + ON_UPDATE_COMMAND_UI(IDM_EDIT_FIND, OnUpdateEditFind) + ON_COMMAND( IDM_EDIT_SELECT_ALL, OnEditSelectAll) + ON_UPDATE_COMMAND_UI(IDM_EDIT_SELECT_ALL, OnUpdateEditSelectAll) + ON_COMMAND( IDM_EDIT_INVERT_SELECTION, OnEditInvertSelection) + ON_UPDATE_COMMAND_UI(IDM_EDIT_INVERT_SELECTION, OnUpdateEditInvertSelection) + ON_COMMAND( IDM_EDIT_PREFERENCES, OnEditPreferences) + ON_COMMAND_RANGE( IDM_SORT_PATHNAME, IDM_SORT_ORIGINAL, OnEditSort) + ON_UPDATE_COMMAND_UI_RANGE(IDM_SORT_PATHNAME, IDM_SORT_ORIGINAL, OnUpdateEditSort) + ON_COMMAND( IDM_ACTIONS_VIEW, OnActionsView) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_VIEW, OnUpdateActionsView) + ON_COMMAND( IDM_ACTIONS_ADD_FILES, OnActionsAddFiles) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_ADD_FILES, OnUpdateActionsAddFiles) + ON_COMMAND( IDM_ACTIONS_ADD_DISKS, OnActionsAddDisks) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_ADD_DISKS, OnUpdateActionsAddDisks) + ON_COMMAND( IDM_ACTIONS_CREATE_SUBDIR, OnActionsCreateSubdir) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_CREATE_SUBDIR, OnUpdateActionsCreateSubdir) + ON_COMMAND( IDM_ACTIONS_EXTRACT, OnActionsExtract) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_EXTRACT, OnUpdateActionsExtract) + ON_COMMAND( IDM_ACTIONS_TEST, OnActionsTest) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_TEST, OnUpdateActionsTest) + ON_COMMAND( IDM_ACTIONS_DELETE, OnActionsDelete) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_DELETE, OnUpdateActionsDelete) + ON_COMMAND( IDM_ACTIONS_RENAME, OnActionsRename) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_RENAME, OnUpdateActionsRename) + ON_COMMAND( IDM_ACTIONS_RECOMPRESS, OnActionsRecompress) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_RECOMPRESS, OnUpdateActionsRecompress) + ON_COMMAND( IDM_ACTIONS_OPENASDISK, OnActionsOpenAsDisk) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_OPENASDISK, OnUpdateActionsOpenAsDisk) + ON_COMMAND( IDM_ACTIONS_EDIT_COMMENT, OnActionsEditComment) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_EDIT_COMMENT, OnUpdateActionsEditComment) + ON_COMMAND( IDM_ACTIONS_EDIT_PROPS, OnActionsEditProps) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_EDIT_PROPS, OnUpdateActionsEditProps) + ON_COMMAND( IDM_ACTIONS_RENAME_VOLUME, OnActionsRenameVolume) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_RENAME_VOLUME, OnUpdateActionsRenameVolume) + ON_COMMAND( IDM_ACTIONS_CONV_DISK, OnActionsConvDisk) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_CONV_DISK, OnUpdateActionsConvDisk) + ON_COMMAND( IDM_ACTIONS_CONV_FILE, OnActionsConvFile) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_CONV_FILE, OnUpdateActionsConvFile) + ON_COMMAND( IDM_ACTIONS_CONV_TOWAV, OnActionsConvToWav) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_CONV_TOWAV, OnUpdateActionsConvToWav) + ON_COMMAND( IDM_ACTIONS_CONV_FROMWAV, OnActionsConvFromWav) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_CONV_FROMWAV, OnUpdateActionsConvFromWav) + ON_COMMAND( IDM_ACTIONS_IMPORT_BAS, OnActionsImportBAS) + ON_UPDATE_COMMAND_UI(IDM_ACTIONS_IMPORT_BAS, OnUpdateActionsImportBAS) + ON_COMMAND( IDM_TOOLS_DISKEDIT, OnToolsDiskEdit) + ON_COMMAND( IDM_TOOLS_IMAGECREATOR, OnToolsDiskImageCreator) + ON_COMMAND( IDM_TOOLS_DISKCONV, OnToolsDiskConv) + ON_COMMAND( IDM_TOOLS_BULKDISKCONV, OnToolsBulkDiskConv) + ON_COMMAND( IDM_TOOLS_SST_MERGE, OnToolsSSTMerge) + ON_COMMAND( IDM_TOOLS_VOLUMECOPIER_VOLUME, OnToolsVolumeCopierVolume) + ON_COMMAND( IDM_TOOLS_VOLUMECOPIER_FILE, OnToolsVolumeCopierFile) + ON_COMMAND( IDM_TOOLS_EOLSCANNER, OnToolsEOLScanner) + ON_COMMAND( IDM_TOOLS_TWOIMGPROPS, OnToolsTwoImgProps) + ON_COMMAND( IDM_HELP_CONTENTS, OnHelpContents) + ON_COMMAND( IDM_HELP_WEBSITE, OnHelpWebSite) + ON_COMMAND( IDM_HELP_ORDERING, OnHelpOrdering) + ON_COMMAND( IDM_HELP_ABOUT, OnHelpAbout) +// ON_COMMAND( IDM_RTCLK_DEFAULT, OnRtClkDefault) + + /* this is required to allow "Help" button to work in PropertySheets (!) */ +// ON_COMMAND(ID_HELP, OnHelp) + ON_COMMAND(ID_HELP_FINDER, CFrameWnd::OnHelpFinder) + ON_COMMAND(ID_HELP, CFrameWnd::OnHelp) + ON_COMMAND(ID_CONTEXT_HELP, CFrameWnd::OnContextHelp) + ON_COMMAND(ID_DEFAULT_HELP, CFrameWnd::OnHelpFinder) +END_MESSAGE_MAP() + + +/* + * MainWindow constructor. Creates the main window and sets + * its properties. + */ +MainWindow::MainWindow() +{ + static const char* kAppName = _T("CiderPress"); + + fpContentList = nil; + fpOpenArchive = nil; + //fpSelSet = nil; + fpActionProgress = nil; + fpProgressCounter = nil; + fpFindDialog = nil; + + fFindDown = true; + fFindMatchCase = false; + fFindMatchWholeWord = false; + + fAbortPrinting = false; + fhDevMode = nil; + fhDevNames = nil; + fNeedReopen = false; + + CString wndClass = AfxRegisterWndClass( + CS_DBLCLKS /*| CS_HREDRAW | CS_VREDRAW*/, + gMyApp.LoadStandardCursor(IDC_ARROW), + NULL /*(HBRUSH) (COLOR_WINDOW + 1)*/, + gMyApp.LoadIcon(IDR_MAINFRAME) ); + + Create(wndClass, kAppName, WS_OVERLAPPEDWINDOW /*| WS_CLIPCHILDREN*/, + rectDefault, NULL, MAKEINTRESOURCE(IDR_MAINFRAME)); + + LoadAccelTable(MAKEINTRESOURCE(IDR_MAINFRAME)); + + // initialize some OLE garbage + AfxOleInit(); + + // required by MFC if Rich Edit controls are used + AfxInitRichEdit(); + + // required?? + //AfxEnableControlContainer(); + + SetCPTitle(); + + int cc = PostMessage(WMU_LATE_INIT, 0, 0); + ASSERT(cc != 0); +} + +/* + * MainWindow destructor. Close the archive if one is open, but don't try + * to shut down any controls in child windows. By this point, Windows has + * already snuffed them. + */ +MainWindow::~MainWindow() +{ + WMSG0("~MainWindow\n"); + + //WMSG0("MainWindow destructor\n"); + CloseArchiveWOControls(); + + int cc; + cc = ::WinHelp(m_hWnd, ::AfxGetApp()->m_pszHelpFilePath, HELP_QUIT, 0); + WMSG1("Turning off WinHelp returned %d\n", cc); + + // free stuff used by print dialog + ::GlobalFree(fhDevMode); + ::GlobalFree(fhDevNames); + + fPreferences.SaveToRegistry(); + WMSG0("MainWindow destructor complete\n"); +} + + +/* + * Override the pre-create function to tweak the window style. + */ +BOOL +MainWindow::PreCreateWindow(CREATESTRUCT& cs) +{ + BOOL res = CFrameWnd::PreCreateWindow(cs); + + cs.dwExStyle &= ~(WS_EX_CLIENTEDGE); + + return res; +} + +/* + * Override GetClientRect so we can factor in the status and tool bars. + */ +void +MainWindow::GetClientRect(LPRECT lpRect) const +{ + CRect sizeRect; + int toolBarHeight, statusBarHeight; + + fToolBar.GetWindowRect(&sizeRect); + toolBarHeight = sizeRect.bottom - sizeRect.top; + fStatusBar.GetWindowRect(&sizeRect); + statusBarHeight = sizeRect.bottom - sizeRect.top; + + //WMSG2("HEIGHTS = %d/%d\n", toolBarHeight, statusBarHeight); + CFrameWnd::GetClientRect(lpRect); + lpRect->top += toolBarHeight; + lpRect->bottom -= statusBarHeight; +} + + +/* + * Do some idle processing. + */ +void +MainWindow::DoIdle(void) +{ + /* + * Make sure that the filename field in the content list is always + * visible, since that what the user clicks on to select things. Would + * be nice to have a way to prevent it, but for now we'll just shove + * things back where they're supposed to be. + */ + if (fpContentList != nil) { + /* get the current column 0 width, with current user adjustments */ + fpContentList->ExportColumnWidths(); + int width = fPreferences.GetColumnLayout()->GetColumnWidth(0); + + if (width >= 0 && width < ColumnLayout::kMinCol0Width) { + /* column is too small, but don't change it until user lets mouse up */ + if (::GetAsyncKeyState(VK_LBUTTON) >= 0) { + WMSG0("Resetting column 0 width\n"); + fPreferences.GetColumnLayout()->SetColumnWidth(0, + ColumnLayout::kMinCol0Width); + fpContentList->NewColumnWidths(); + } + } + } + + /* + * Put an asterisk at the end of the title if we have an open archive + * and it has pending modifications. Remove it if nothing is pending. + */ + if (fpOpenArchive != nil) { + CString title; + int len; + + GetWindowText(/*ref*/ title); + len = title.GetLength(); + if (len > 0 && title.GetAt(len-1) == '*') { + if (!fpOpenArchive->IsModified()) { + /* remove the asterisk and the preceeding space */ + title.Delete(len-2, 2); + SetWindowText(title); + } + } else { + if (fpOpenArchive->IsModified()) { + /* add an asterisk */ + title += " *"; + SetWindowText(title); + } + } + } +} + + +/* + * Handle command-line arguments. + * + * Usage: + * CiderPress [[-temparc] [-mode {nufx,bin2,disk}] [-dispname name] filename] + */ +void +MainWindow::ProcessCommandLine(void) +{ + /* + * Get the command line and break it down into an argument vector. + */ + const char* cmdLine = ::GetCommandLine(); + if (cmdLine == nil || strlen(cmdLine) == 0) + return; + + char* mangle = strdup(cmdLine); + if (mangle == nil) + return; + + WMSG1("Mangling '%s'\n", mangle); + char* argv[8]; + int argc = 8; + VectorizeString(mangle, argv, &argc); + + WMSG0("Args:\n"); + for (int i = 0; i < argc; i++) { + WMSG2(" %d '%s'\n", i, argv[i]); + } + + /* + * Figure out what the arguments are. + */ + const char* filename = nil; + const char* dispName = nil; + int filterIndex = kFilterIndexGeneric; + bool temp = false; + + for (i = 1; i < argc; i++) { + if (argv[i][0] == '-') { + if (strcasecmp(argv[i], "-mode") == 0) { + if (i == argc-1) { + WMSG0("WARNING: -mode specified without mode\n"); + } else + i++; + if (strcasecmp(argv[i], kModeNuFX) == 0) + filterIndex = kFilterIndexNuFX; + else if (strcasecmp(argv[i], kModeBinaryII) == 0) + filterIndex = kFilterIndexBinaryII; + else if (strcasecmp(argv[i], kModeACU) == 0) + filterIndex = kFilterIndexACU; + else if (strcasecmp(argv[i], kModeDiskImage) == 0) + filterIndex = kFilterIndexDiskImage; + else { + WMSG1("WARNING: unrecognized mode '%s'\n", argv[i]); + } + } else if (strcasecmp(argv[i], "-dispname") == 0) { + if (i == argc-1) { + WMSG0("WARNING: -dispname specified without name\n"); + } else + i++; + dispName = argv[i]; + } else if (strcasecmp(argv[i], "-temparc") == 0) { + temp = true; + } else if (strcasecmp(argv[i], "-install") == 0) { + // see MyApp::InitInstance + WMSG0("Got '-install' flag, doing nothing\n"); + } else if (strcasecmp(argv[i], "-uninstall") == 0) { + // see MyApp::InitInstance + WMSG0("Got '-uninstall' flag, doing nothing\n"); + } else { + WMSG1("WARNING: unrecognized flag '%s'\n", argv[i]); + } + } else { + /* must be the filename */ + if (i != argc-1) { + WMSG1("WARNING: ignoring extra arguments (e.g. '%s')\n", + argv[i+1]); + } + filename = argv[i]; + break; + } + } + if (argc != 1 && filename == nil) { + WMSG0("WARNING: args specified but no filename found\n"); + } + + WMSG0("Argument handling:\n"); + WMSG3(" index=%d temp=%d filename='%s'\n", + filterIndex, temp, filename == nil ? "(nil)" : filename); + + if (filename != nil) { + PathName path(filename); + CString ext = path.GetExtension(); + + // drop the leading '.' from the extension + if (ext.Left(1) == ".") + ext.Delete(0, 1); + + /* load the archive, mandating read-only if it's a temporary file */ + if (LoadArchive(filename, ext, filterIndex, temp, false) == 0) { + /* success, update title bar */ + if (temp) + fOpenArchivePathName = path.GetFileName(); + else + fOpenArchivePathName = filename; + if (dispName != nil) + fOpenArchivePathName = dispName; + SetCPTitle(fOpenArchivePathName, fpOpenArchive); + } + + /* if it's a temporary file, arrange to have it deleted before exit */ + if (temp) { + int len = strlen(filename); + + if (len > 4 && strcasecmp(filename + (len-4), ".tmp") == 0) { + fDeleteList.Add(filename); + } else { + WMSG1("NOT adding '%s' to DeleteList -- does not end in '.tmp'\n", + filename); + } + } + } + + free(mangle); +} + + +/* + * =================================== + * Command handlers + * =================================== + */ + +const int kProgressPane = 1; + +/* + * OnCreate handler. Used to add a toolbar and status bar. + */ +int +MainWindow::OnCreate(LPCREATESTRUCT lpcs) +{ + WMSG0("Now in OnCreate!\n"); + if (CFrameWnd::OnCreate(lpcs) == -1) + return -1; + + /* + * Create the tool bar. + */ +#if 0 + static UINT buttonList[] = { + IDM_FILE_OPEN, + IDM_FILE_NEW_ARCHIVE, + // spacer + IDM_FILE_PRINT, + }; +#endif + fToolBar.Create(this, WS_CHILD | WS_VISIBLE | CBRS_TOP | + CBRS_TOOLTIPS | CBRS_FLYBY); + fToolBar.LoadToolBar(IDR_TOOLBAR1); + + /* + * Create the status bar. + */ + static UINT indicators[] = { ID_SEPARATOR, ID_INDICATOR_COMPLETE }; + fStatusBar.Create(this); + fStatusBar.SetIndicators(indicators, NELEM(indicators)); + //fStatusBar.SetPaneInfo(0, ID_SEPARATOR, SBPS_NOBORDERS | SBPS_STRETCH, 0); + + fStatusBar.SetPaneText(kProgressPane, ""); + + return 0; +} + + +/* + * Catch a message sent to inspire us to perform one-time initializations of + * preferences and libraries. + * + * We're doing this the long way around because we want to be able to + * put up a dialog box if the version is bad. If we tried to handle this + * in the constructor we'd be acting before the window was fully created. + */ +LONG +MainWindow::OnLateInit(UINT, LONG) +{ + CString result; + CString appName; + CString niftyListFile; + + appName.LoadString(IDS_MB_APP_NAME); + + WMSG0("----- late init begins -----\n"); + + /* + * Handle all other messages. This gives the framework a chance to dim + * all of the toolbar buttons. This is especially useful when opening + * a file from the command line that doesn't exist, causing an error + * dialog and blocking main window messages. + */ + PeekAndPump(); + + /* + * Initialize libraries. This includes a version check. + */ + result = NufxArchive::AppInit(); + if (!result.IsEmpty()) + goto fail; + result = DiskArchive::AppInit(); + if (!result.IsEmpty()) + goto fail; + result = BnyArchive::AppInit(); + if (!result.IsEmpty()) + goto fail; + + niftyListFile = gMyApp.GetExeBaseName(); + niftyListFile += "NList.Data"; + if (!NiftyList::AppInit(niftyListFile)) { + CString file2 = niftyListFile + ".TXT"; + if (!NiftyList::AppInit(file2)) { + CString msg; + msg.Format(IDS_NLIST_DATA_FAILED, niftyListFile, file2); + MessageBox(msg, appName, MB_OK); + } + } + + /* + * Read preferences from registry. + */ + fPreferences.LoadFromRegistry(); + + /* + * Check to see if we're registered; if we're not, and we've expired, it's + * time to bail out. + */ + MyRegistry::RegStatus regStatus; + //regStatus = gMyApp.fRegistry.CheckRegistration(&result); + regStatus = MyRegistry::kRegValid; + WMSG1("CheckRegistration returned %d\n", regStatus); + switch (regStatus) { + case MyRegistry::kRegNotSet: + case MyRegistry::kRegValid: + ASSERT(result.IsEmpty()); + break; + case MyRegistry::kRegExpired: + case MyRegistry::kRegInvalid: + MessageBox(result, appName, MB_OK|MB_ICONINFORMATION); + WMSG0("FORCING REG\n"); +#if 0 + if (EnterRegDialog::GetRegInfo(this) != 0) { + result = ""; + goto fail; + } +#endif + SetCPTitle(); // update title bar with new reg info + break; + case MyRegistry::kRegFailed: + ASSERT(!result.IsEmpty()); + goto fail; + default: + ASSERT(false); + CString confused; + confused.Format("Registration check failed. %s", (LPCTSTR) result); + result = confused; + goto fail; + } + + /* + * Process command-line options, possibly loading an archive. + */ + ProcessCommandLine(); + + return 0; + +fail: + if (!result.IsEmpty()) + ShowFailureMsg(this, result, IDS_FAILED); + int cc = PostMessage(WM_CLOSE, 0, 0); + ASSERT(cc != 0); + + return 0; +} + + +/* + * The system wants to know if we're okay with shutting down. + * + * Return TRUE if it's okay to shut down, FALSE otherwise. + */ +BOOL +MainWindow::OnQueryEndSession(void) +{ + WMSG0("Got QueryEndSession\n"); + return TRUE; +} + +/* + * Notification of shutdown (or not). + */ +void +MainWindow::OnEndSession(BOOL bEnding) +{ + WMSG1("Got EndSession (bEnding=%d)\n", bEnding); + + if (bEnding) { + CloseArchiveWOControls(); + + fPreferences.SaveToRegistry(); + } +} + +/* + * The main window is resizing. We don't automatically redraw on resize, + * so we will need to update the client region. If it's filled with a + * control, the control's resize & redraw function will take care of it. + * If not, we need to explicitly invalidate the client region so the + * window will repaint itself. + */ +void +MainWindow::OnSize(UINT nType, int cx, int cy) +{ + CFrameWnd::OnSize(nType, cx, cy); + ResizeClientArea(); +} +void +MainWindow::ResizeClientArea(void) +{ + CRect sizeRect; + + GetClientRect(&sizeRect); + if (fpContentList != NULL) + fpContentList->MoveWindow(sizeRect); + else + Invalidate(false); +} + +/* + * Restrict the minimum window size to something reasonable. + */ +void +MainWindow::OnGetMinMaxInfo(MINMAXINFO* pMMI) +{ + pMMI->ptMinTrackSize.x = 256; + pMMI->ptMinTrackSize.y = 192; +} + +/* + * Repaint the main window. + */ +void +MainWindow::OnPaint(void) +{ + CPaintDC dc(this); + CRect clientRect; + + GetClientRect(&clientRect); + + /* + * If there's no control in the window, fill in the client area with + * what looks like an empty MDI client rect. + */ + if (fpContentList == nil) { + DrawEmptyClientArea(&dc, clientRect); + } + +#if 0 + CPen pen(PS_SOLID, 1, RGB(255, 0, 0)); // red pen, 1 pixel wide + CPen* pOldPen = dc.SelectObject(&pen); + + dc.MoveTo(clientRect.left, clientRect.top); + dc.LineTo(clientRect.right-1, clientRect.top); + dc.LineTo(clientRect.right, clientRect.bottom); + dc.LineTo(clientRect.left, clientRect.bottom-1); + dc.LineTo(clientRect.left, clientRect.top); + + dc.SelectObject(pOldPen); +#endif +} + +#if 0 +afx_msg BOOL +MainWindow::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) +{ + WMSG0("MOUSE WHEEL\n"); + return FALSE; + + WPARAM wparam; + LPARAM lparam; + + wparam = nFlags | (zDelta << 16); + lparam = pt.x | (pt.y << 16); + if (fpContentList != nil) + fpContentList->SendMessage(WM_MOUSEWHEEL, wparam, lparam); + return CWnd::OnMouseWheel(nFlags, zDelta, pt); +// return TRUE; +} +#endif + +/* + * Make sure open controls keep the input focus. + */ +void +MainWindow::OnSetFocus(CWnd* /*pOldWnd*/) +{ + if (fpContentList != nil) { + WMSG0("Returning focus to ContentList\n"); + fpContentList->SetFocus(); + } +} + +/* + * User hit F1. We don't currently have context-sensitive help on the main page. + */ +BOOL +MainWindow::OnHelpInfo(HELPINFO* /*lpHelpInfo*/) +{ + //WinHelp(0, HELP_FINDER); + WinHelp(HELP_TOPIC_WELCOME, HELP_CONTEXT); + return TRUE; // dunno what this means +} + +#if 0 +/* + * Catch-all Help handler, necessary to allow CPropertySheet to display a + * "Help" button. (WTF?) + */ +LONG +MainWindow::OnHelp(UINT wParam, LONG lParam) +{ + HELPINFO* lpHelpInfo = (HELPINFO*) lParam; + + DWORD context = lpHelpInfo->iCtrlId; + WMSG1("MainWindow OnHelp (context=%d)\n", context); + WinHelp(context, HELP_CONTEXTPOPUP); + + return TRUE; // yes, we handled it +} +#endif + +/* + * Handle Edit->Preferences by popping up a property sheet. + */ +void +MainWindow::OnEditPreferences(void) +{ + PrefsSheet ps; + ColumnLayout* pColLayout = fPreferences.GetColumnLayout(); + + /* pull any user header tweaks out of list so we can configure prefs */ + if (fpContentList != nil) + fpContentList->ExportColumnWidths(); + + /* set up PrefsGeneralPage */ + for (int i = 0; i < kNumVisibleColumns; i++) { + ps.fGeneralPage.fColumn[i] = (pColLayout->GetColumnWidth(i) != 0); + } + ps.fGeneralPage.fMimicShrinkIt = fPreferences.GetPrefBool(kPrMimicShrinkIt); + ps.fGeneralPage.fBadMacSHK = fPreferences.GetPrefBool(kPrBadMacSHK); + ps.fGeneralPage.fReduceSHKErrorChecks = fPreferences.GetPrefBool(kPrReduceSHKErrorChecks); + ps.fGeneralPage.fCoerceDOSFilenames = fPreferences.GetPrefBool(kPrCoerceDOSFilenames); + ps.fGeneralPage.fSpacesToUnder = fPreferences.GetPrefBool(kPrSpacesToUnder); + ps.fGeneralPage.fPasteJunkPaths = fPreferences.GetPrefBool(kPrPasteJunkPaths); + ps.fGeneralPage.fBeepOnSuccess = fPreferences.GetPrefBool(kPrBeepOnSuccess); + + /* set up PrefsDiskImagePage */ + ps.fDiskImagePage.fQueryImageFormat = fPreferences.GetPrefBool(kPrQueryImageFormat); + ps.fDiskImagePage.fOpenVolumeRO = fPreferences.GetPrefBool(kPrOpenVolumeRO); + ps.fDiskImagePage.fOpenVolumePhys0 = fPreferences.GetPrefBool(kPrOpenVolumePhys0); + ps.fDiskImagePage.fProDOSAllowLower = fPreferences.GetPrefBool(kPrProDOSAllowLower); + ps.fDiskImagePage.fProDOSUseSparse = fPreferences.GetPrefBool(kPrProDOSUseSparse); + + /* set up PrefsCompressionPage */ + ps.fCompressionPage.fCompressType = fPreferences.GetPrefLong(kPrCompressionType); + + /* set up PrefsFviewPage */ + ps.fFviewPage.fMaxViewFileSizeKB = + (fPreferences.GetPrefLong(kPrMaxViewFileSize) + 1023) / 1024; + ps.fFviewPage.fNoWrapText = fPreferences.GetPrefBool(kPrNoWrapText); + + ps.fFviewPage.fHighlightHexDump = fPreferences.GetPrefBool(kPrHighlightHexDump); + ps.fFviewPage.fHighlightBASIC = fPreferences.GetPrefBool(kPrHighlightBASIC); + ps.fFviewPage.fConvDisasmOneByteBrkCop = fPreferences.GetPrefBool(kPrDisasmOneByteBrkCop); + ps.fFviewPage.fConvHiResBlackWhite = fPreferences.GetPrefBool(kPrConvHiResBlackWhite); + ps.fFviewPage.fConvDHRAlgorithm = fPreferences.GetPrefLong(kPrConvDHRAlgorithm); + ps.fFviewPage.fRelaxGfxTypeCheck = fPreferences.GetPrefBool(kPrRelaxGfxTypeCheck); +// ps.fFviewPage.fEOLConvRaw = fPreferences.GetPrefBool(kPrEOLConvRaw); +// ps.fFviewPage.fConvHighASCII = fPreferences.GetPrefBool(kPrConvHighASCII); + ps.fFviewPage.fConvTextEOL_HA = fPreferences.GetPrefBool(kPrConvTextEOL_HA); + ps.fFviewPage.fConvCPMText = fPreferences.GetPrefBool(kPrConvCPMText); + ps.fFviewPage.fConvPascalText = fPreferences.GetPrefBool(kPrConvPascalText); + ps.fFviewPage.fConvPascalCode = fPreferences.GetPrefBool(kPrConvPascalCode); + ps.fFviewPage.fConvApplesoft = fPreferences.GetPrefBool(kPrConvApplesoft); + ps.fFviewPage.fConvInteger = fPreferences.GetPrefBool(kPrConvInteger); + ps.fFviewPage.fConvBusiness = fPreferences.GetPrefBool(kPrConvBusiness); + ps.fFviewPage.fConvGWP = fPreferences.GetPrefBool(kPrConvGWP); + ps.fFviewPage.fConvText8 = fPreferences.GetPrefBool(kPrConvText8); + ps.fFviewPage.fConvAWP = fPreferences.GetPrefBool(kPrConvAWP); + ps.fFviewPage.fConvADB = fPreferences.GetPrefBool(kPrConvADB); + ps.fFviewPage.fConvASP = fPreferences.GetPrefBool(kPrConvASP); + ps.fFviewPage.fConvSCAssem = fPreferences.GetPrefBool(kPrConvSCAssem); + ps.fFviewPage.fConvDisasm = fPreferences.GetPrefBool(kPrConvDisasm); + ps.fFviewPage.fConvHiRes = fPreferences.GetPrefBool(kPrConvHiRes); + ps.fFviewPage.fConvDHR = fPreferences.GetPrefBool(kPrConvDHR); + ps.fFviewPage.fConvSHR = fPreferences.GetPrefBool(kPrConvSHR); + ps.fFviewPage.fConvPrintShop = fPreferences.GetPrefBool(kPrConvPrintShop); + ps.fFviewPage.fConvMacPaint = fPreferences.GetPrefBool(kPrConvMacPaint); + ps.fFviewPage.fConvProDOSFolder = fPreferences.GetPrefBool(kPrConvProDOSFolder); + ps.fFviewPage.fConvResources = fPreferences.GetPrefBool(kPrConvResources); + + /* set up PrefsFilesPage */ + ps.fFilesPage.fTempPath = fPreferences.GetPrefString(kPrTempPath); + ps.fFilesPage.fExtViewerExts = fPreferences.GetPrefString(kPrExtViewerExts); + + if (ps.DoModal() == IDOK) + ApplyNow(&ps); +} + +/* + * Apply a change from the preferences sheet. + */ +void +MainWindow::ApplyNow(PrefsSheet* pPS) +{ + bool mustReload = false; + + //WMSG0("APPLY CHANGES\n"); + + ColumnLayout* pColLayout = fPreferences.GetColumnLayout(); + + if (pPS->fGeneralPage.fDefaultsPushed) { + /* reset all sizes to defaults, then factor in checkboxes */ + WMSG0(" Resetting all widths to defaults\n"); + + /* copy defaults over */ + for (int i = 0; i < kNumVisibleColumns; i++) + pColLayout->SetColumnWidth(i, ColumnLayout::kWidthDefaulted); + } + + /* handle column checkboxes */ + for (int i = 0; i < kNumVisibleColumns; i++) { + if (pColLayout->GetColumnWidth(i) == 0 && + pPS->fGeneralPage.fColumn[i]) + { + /* restore column */ + WMSG1(" Column %d restored\n", i); + pColLayout->SetColumnWidth(i, ColumnLayout::kWidthDefaulted); + } else if (pColLayout->GetColumnWidth(i) != 0 && + !pPS->fGeneralPage.fColumn[i]) + { + /* disable column */ + WMSG1(" Column %d hidden\n", i); + pColLayout->SetColumnWidth(i, 0); + } + } + if (fpContentList != nil) + fpContentList->NewColumnWidths(); + fPreferences.SetPrefBool(kPrMimicShrinkIt, + pPS->fGeneralPage.fMimicShrinkIt != 0); + fPreferences.SetPrefBool(kPrBadMacSHK, pPS->fGeneralPage.fBadMacSHK != 0); + fPreferences.SetPrefBool(kPrReduceSHKErrorChecks, + pPS->fGeneralPage.fReduceSHKErrorChecks != 0); + if (fPreferences.GetPrefBool(kPrCoerceDOSFilenames)!= + (pPS->fGeneralPage.fCoerceDOSFilenames != 0)) + { + WMSG1("DOS filename coercion pref now %d\n", + pPS->fGeneralPage.fCoerceDOSFilenames); + fPreferences.SetPrefBool(kPrCoerceDOSFilenames, + pPS->fGeneralPage.fCoerceDOSFilenames != 0); + mustReload = true; + } + if (fPreferences.GetPrefBool(kPrSpacesToUnder) != + (pPS->fGeneralPage.fSpacesToUnder != 0)) + { + WMSG1("Spaces-to-underscores now %d\n", pPS->fGeneralPage.fSpacesToUnder); + fPreferences.SetPrefBool(kPrSpacesToUnder, pPS->fGeneralPage.fSpacesToUnder != 0); + mustReload = true; + } + fPreferences.SetPrefBool(kPrPasteJunkPaths, pPS->fGeneralPage.fPasteJunkPaths != 0); + fPreferences.SetPrefBool(kPrBeepOnSuccess, pPS->fGeneralPage.fBeepOnSuccess != 0); + + if (pPS->fGeneralPage.fOurAssociations != nil) { + WMSG0("NEW ASSOCIATIONS!\n"); + + for (int assoc = 0; assoc < gMyApp.fRegistry.GetNumFileAssocs(); assoc++) + { + gMyApp.fRegistry.SetFileAssoc(assoc, + pPS->fGeneralPage.fOurAssociations[assoc]); + } + + /* delete them so, if they hit "apply" again, we only update once */ + delete[] pPS->fGeneralPage.fOurAssociations; + pPS->fGeneralPage.fOurAssociations = nil; + } + + fPreferences.SetPrefBool(kPrQueryImageFormat, pPS->fDiskImagePage.fQueryImageFormat != 0); + fPreferences.SetPrefBool(kPrOpenVolumeRO, pPS->fDiskImagePage.fOpenVolumeRO != 0); + fPreferences.SetPrefBool(kPrOpenVolumePhys0, pPS->fDiskImagePage.fOpenVolumePhys0 != 0); + fPreferences.SetPrefBool(kPrProDOSAllowLower, pPS->fDiskImagePage.fProDOSAllowLower != 0); + fPreferences.SetPrefBool(kPrProDOSUseSparse, pPS->fDiskImagePage.fProDOSUseSparse != 0); + + fPreferences.SetPrefLong(kPrCompressionType, pPS->fCompressionPage.fCompressType); + + fPreferences.SetPrefLong(kPrMaxViewFileSize, pPS->fFviewPage.fMaxViewFileSizeKB * 1024); + fPreferences.SetPrefBool(kPrNoWrapText, pPS->fFviewPage.fNoWrapText != 0); + + fPreferences.SetPrefBool(kPrHighlightHexDump, pPS->fFviewPage.fHighlightHexDump != 0); + fPreferences.SetPrefBool(kPrHighlightBASIC, pPS->fFviewPage.fHighlightBASIC != 0); + fPreferences.SetPrefBool(kPrDisasmOneByteBrkCop, pPS->fFviewPage.fConvDisasmOneByteBrkCop != 0); + fPreferences.SetPrefBool(kPrConvHiResBlackWhite, pPS->fFviewPage.fConvHiResBlackWhite != 0); + fPreferences.SetPrefLong(kPrConvDHRAlgorithm, pPS->fFviewPage.fConvDHRAlgorithm); + fPreferences.SetPrefBool(kPrRelaxGfxTypeCheck, pPS->fFviewPage.fRelaxGfxTypeCheck != 0); +// fPreferences.SetPrefBool(kPrEOLConvRaw, pPS->fFviewPage.fEOLConvRaw != 0); +// fPreferences.SetPrefBool(kPrConvHighASCII, pPS->fFviewPage.fConvHighASCII != 0); + fPreferences.SetPrefBool(kPrConvTextEOL_HA, pPS->fFviewPage.fConvTextEOL_HA != 0); + fPreferences.SetPrefBool(kPrConvCPMText, pPS->fFviewPage.fConvCPMText != 0); + fPreferences.SetPrefBool(kPrConvPascalText, pPS->fFviewPage.fConvPascalText != 0); + fPreferences.SetPrefBool(kPrConvPascalCode, pPS->fFviewPage.fConvPascalCode != 0); + fPreferences.SetPrefBool(kPrConvApplesoft, pPS->fFviewPage.fConvApplesoft != 0); + fPreferences.SetPrefBool(kPrConvInteger, pPS->fFviewPage.fConvInteger != 0); + fPreferences.SetPrefBool(kPrConvBusiness, pPS->fFviewPage.fConvBusiness != 0); + fPreferences.SetPrefBool(kPrConvGWP, pPS->fFviewPage.fConvGWP != 0); + fPreferences.SetPrefBool(kPrConvText8, pPS->fFviewPage.fConvText8 != 0); + fPreferences.SetPrefBool(kPrConvAWP, pPS->fFviewPage.fConvAWP != 0); + fPreferences.SetPrefBool(kPrConvADB, pPS->fFviewPage.fConvADB != 0); + fPreferences.SetPrefBool(kPrConvASP, pPS->fFviewPage.fConvASP != 0); + fPreferences.SetPrefBool(kPrConvSCAssem, pPS->fFviewPage.fConvSCAssem != 0); + fPreferences.SetPrefBool(kPrConvDisasm, pPS->fFviewPage.fConvDisasm != 0); + fPreferences.SetPrefBool(kPrConvHiRes, pPS->fFviewPage.fConvHiRes != 0); + fPreferences.SetPrefBool(kPrConvDHR, pPS->fFviewPage.fConvDHR != 0); + fPreferences.SetPrefBool(kPrConvSHR, pPS->fFviewPage.fConvSHR != 0); + fPreferences.SetPrefBool(kPrConvPrintShop, pPS->fFviewPage.fConvPrintShop != 0); + fPreferences.SetPrefBool(kPrConvMacPaint, pPS->fFviewPage.fConvMacPaint != 0); + fPreferences.SetPrefBool(kPrConvProDOSFolder, pPS->fFviewPage.fConvProDOSFolder != 0); + fPreferences.SetPrefBool(kPrConvResources, pPS->fFviewPage.fConvResources != 0); + + fPreferences.SetPrefString(kPrTempPath, pPS->fFilesPage.fTempPath); + WMSG1("--- Temp path now '%s'\n", fPreferences.GetPrefString(kPrTempPath)); + fPreferences.SetPrefString(kPrExtViewerExts, pPS->fFilesPage.fExtViewerExts); + + +// if ((pPS->fGeneralPage.fShowToolbarText != 0) != fPreferences.GetShowToolbarText()) { +// fPreferences.SetShowToolbarText(pPS->fGeneralPage.fShowToolbarText != 0); +// //SetToolbarTextMode(); +// ResizeClientArea(); +// } + + /* allow open archive to track changes to preferences */ + if (fpOpenArchive != nil) + fpOpenArchive->PreferencesChanged(); + + if (mustReload) { + WMSG0("Preferences apply requesting GA/CL reload\n"); + if (fpOpenArchive != nil) + fpOpenArchive->Reload(); + if (fpContentList != nil) + fpContentList->Reload(); + } + + /* export to registry */ + fPreferences.SaveToRegistry(); + + //Invalidate(); +} + +/* + * Handle IDM_EDIT_FIND. + */ +void +MainWindow::OnEditFind(void) +{ + DWORD flags = 0; + + if (fpFindDialog != nil) + return; + + if (fFindDown) + flags |= FR_DOWN; + if (fFindMatchCase) + flags |= FR_MATCHCASE; + if (fFindMatchWholeWord) + flags |= FR_WHOLEWORD; + + fpFindDialog = new CFindReplaceDialog; + + fpFindDialog->Create(TRUE, // "find" only + fFindLastStr, // default string to search for + NULL, // default string to replace + flags, // flags + this); // parent +} +void +MainWindow::OnUpdateEditFind(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(fpOpenArchive != nil); +} + +/* + * Handle activity in the modeless "find" dialog. + */ +LRESULT +MainWindow::OnFindDialogMessage(WPARAM wParam, LPARAM lParam) +{ + assert(fpFindDialog != nil); + + fFindDown = (fpFindDialog->SearchDown() != 0); + fFindMatchCase = (fpFindDialog->MatchCase() != 0); + fFindMatchWholeWord = (fpFindDialog->MatchWholeWord() != 0); + + if (fpFindDialog->IsTerminating()) { + fpFindDialog = nil; + return 0; + } + + if (fpFindDialog->FindNext()) { + fFindLastStr = fpFindDialog->GetFindString(); + fpContentList->FindNext(fFindLastStr, fFindDown, fFindMatchCase, + fFindMatchWholeWord); + } else { + WMSG0("Unexpected find dialog activity\n"); + } + + return 0; +} + + +/* + * Handle IDM_SORT_*. + * + * The "sort" enu item should really only be active if we have a file open. + */ +void +MainWindow::OnEditSort(UINT id) +{ + WMSG1("EDIT SORT %d\n", id); + + ASSERT(id >= IDM_SORT_PATHNAME && id <= IDM_SORT_ORIGINAL); + fPreferences.GetColumnLayout()->SetSortColumn(id - IDM_SORT_PATHNAME); + fPreferences.GetColumnLayout()->SetAscending(true); + if (fpContentList != nil) + fpContentList->NewSortOrder(); +} +void +MainWindow::OnUpdateEditSort(CCmdUI* pCmdUI) +{ + unsigned int column = fPreferences.GetColumnLayout()->GetSortColumn(); + + pCmdUI->SetCheck(pCmdUI->m_nID - IDM_SORT_PATHNAME == column); +} + +/* + * Open the help file. + */ +void +MainWindow::OnHelpContents(void) +{ + WinHelp(0, HELP_FINDER); +} + +/* + * Go to the faddenSoft web site. + */ +void +MainWindow::OnHelpWebSite(void) +{ + int err; + + err = (int) ::ShellExecute(m_hWnd, _T("open"), kWebSiteURL, NULL, NULL, + SW_SHOWNORMAL); + if (err <= 32) { + CString msg; + if (err == ERROR_FILE_NOT_FOUND) { + msg = "Windows call failed: web browser not found. (Sometimes" + " it mistakenly reports this when IE is not the default" + " browser.)"; + ShowFailureMsg(this, msg, IDS_FAILED); + } else { + msg.Format("Unable to launch web browser (err=%d).", err); + ShowFailureMsg(this, msg, IDS_FAILED); + } + } +} + +/* + * Show ordering info (ka-ching!). + */ +void +MainWindow::OnHelpOrdering(void) +{ + WinHelp(HELP_TOPIC_ORDERING_INFO, HELP_CONTEXT); +} + +/* + * Pop up the About box. + */ +void +MainWindow::OnHelpAbout(void) +{ + int result; + + AboutDialog dlg(this); + + result = dlg.DoModal(); + WMSG1("HelpAbout returned %d\n", result); + + /* + * User could've changed registration. If we're showing the registered + * user name in the title bar, update it. + */ + if (fpOpenArchive == nil) + SetCPTitle(); +} + +/* + * Create a new SHK archive, using a "save as" dialog to select the name. + */ +void +MainWindow::OnFileNewArchive(void) +{ + CString filename, saveFolder, errStr; + GenericArchive* pOpenArchive; + CString errMsg; + + CFileDialog dlg(FALSE, _T("shk"), NULL, + OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, + "ShrinkIt Archives (*.shk)|*.shk||", this); + + dlg.m_ofn.lpstrTitle = "New Archive"; + dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); + + if (dlg.DoModal() != IDOK) + goto bail; + + saveFolder = dlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); + + filename = dlg.GetPathName(); + WMSG1("NEW FILE '%s'\n", filename); + + /* remove file if it already exists */ + errMsg = RemoveFile(filename); + if (!errMsg.IsEmpty()) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } + + pOpenArchive = new NufxArchive; + errStr = pOpenArchive->New(filename, nil); + if (!errStr.IsEmpty()) { + CString failed; + failed.LoadString(IDS_FAILED); + MessageBox(errStr, failed, MB_ICONERROR); + + delete pOpenArchive; + } else { + SwitchContentList(pOpenArchive); + fOpenArchivePathName = dlg.GetPathName(); + SetCPTitle(fOpenArchivePathName, fpOpenArchive); + } + +bail: + WMSG0("--- OnFileNewArchive done\n"); +} + + +/* + * Handle request to open an archive or disk image. + */ +void +MainWindow::OnFileOpen(void) +{ + CString openFilters; + CString saveFolder; + + /* set up filters; the order is significant */ + openFilters = kOpenNuFX; + openFilters += kOpenBinaryII; + openFilters += kOpenACU; + openFilters += kOpenDiskImage; + openFilters += kOpenAll; + openFilters += kOpenEnd; + CFileDialog dlg(TRUE, "shk", NULL, + OFN_FILEMUSTEXIST, openFilters, this); + + dlg.m_ofn.nFilterIndex = fPreferences.GetPrefLong(kPrLastOpenFilterIndex); + dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); + + if (dlg.DoModal() != IDOK) + goto bail; + + fPreferences.SetPrefLong(kPrLastOpenFilterIndex, dlg.m_ofn.nFilterIndex); + saveFolder = dlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); + + DoOpenArchive(dlg.GetPathName(), dlg.GetFileExt(), + dlg.m_ofn.nFilterIndex, dlg.GetReadOnlyPref() != 0); + +bail: + WMSG0("--- OnFileOpen done\n"); +} + +/* + * Handle request to open a raw disk volume. + */ +void +MainWindow::OnFileOpenVolume(void) +{ + WMSG0("--- OnFileOpenVolume\n"); + + int result; + + OpenVolumeDialog dlg(this); + + result = dlg.DoModal(); + if (result != IDOK) + goto bail; + + //DiskImg::SetAllowWritePhys0(fPreferences.GetPrefBool(kPrOpenVolumePhys0)); + DoOpenVolume(dlg.fChosenDrive, dlg.fReadOnly != 0); + +bail: + return; +} +void +MainWindow::OnUpdateFileOpenVolume(CCmdUI* pCmdUI) +{ + // don't really need this function + pCmdUI->Enable(TRUE); +} + +/* + * Open an archive. + */ +void +MainWindow::DoOpenArchive(const char* pathName, const char* ext, + int filterIndex, bool readOnly) +{ + if (LoadArchive(pathName, ext, filterIndex, readOnly, false) == 0) { + /* success, update title bar */ + fOpenArchivePathName = pathName; + SetCPTitle(fOpenArchivePathName, fpOpenArchive); + } else { + /* some failures will close an open archive */ + //if (fpOpenArchive == nil) + // SetCPTitle(); + } +} + +/* + * Save any pending changes. + * + * This may be called directly from tools, so don't assume that the + * conditions checked for in OnUpdateFileSave hold here. + */ +void +MainWindow::OnFileReopen(void) +{ + ReopenArchive(); +} +void +MainWindow::OnUpdateFileReopen(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(fpOpenArchive != nil); +} + + +/* + * Save any pending changes. + * + * This may be called directly from tools, so don't assume that the + * conditions checked for in OnUpdateFileSave hold here. + */ +void +MainWindow::OnFileSave(void) +{ + CString errMsg; + + if (fpOpenArchive == nil) + return; + + { + CWaitCursor waitc; + errMsg = fpOpenArchive->Flush(); + } + if (!errMsg.IsEmpty()) + ShowFailureMsg(this, errMsg, IDS_FAILED); + + // update the title bar + DoIdle(); +} +void +MainWindow::OnUpdateFileSave(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(fpOpenArchive != nil && fpOpenArchive->IsModified()); +} + +/* + * Close current archive or disk image. + */ +void +MainWindow::OnFileClose(void) +{ + CloseArchive(); + //SetCPTitle(); + WMSG0("--- OnFileClose done\n"); +} +void +MainWindow::OnUpdateFileClose(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(fpOpenArchive != nil); +} + + +/* + * Show detailed information on the current archive. + */ +void +MainWindow::OnFileArchiveInfo(void) +{ + ArchiveInfoDialog* pDlg = nil; + ASSERT(fpOpenArchive != nil); + + switch (fpOpenArchive->GetArchiveKind()) { + case GenericArchive::kArchiveNuFX: + pDlg = new NufxArchiveInfoDialog((NufxArchive*) fpOpenArchive, this); + break; + case GenericArchive::kArchiveDiskImage: + pDlg = new DiskArchiveInfoDialog((DiskArchive*) fpOpenArchive, this); + break; + case GenericArchive::kArchiveBNY: + pDlg = new BnyArchiveInfoDialog((BnyArchive*) fpOpenArchive, this); + break; + case GenericArchive::kArchiveACU: + pDlg = new AcuArchiveInfoDialog((AcuArchive*) fpOpenArchive, this); + break; + default: + WMSG1("Unexpected archive type %d\n", fpOpenArchive->GetArchiveKind()); + ASSERT(false); + return; + }; + + pDlg->DoModal(); + + delete pDlg; +} +void +MainWindow::OnUpdateFileArchiveInfo(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(fpContentList != nil); +} + +/* + * Print the contents of the current archive. + */ +void +MainWindow::OnFilePrint(void) +{ + PrintListing(fpContentList); +} +void +MainWindow::OnUpdateFilePrint(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(fpContentList != nil && fpContentList->GetItemCount() > 0); +} + +/* + * Print a ContentList. + */ +void +MainWindow::PrintListing(const ContentList* pContentList) +{ + CPrintDialog dlg(FALSE); // use CPrintDialogEx for Win2K? CPageSetUpDialog? + PrintContentList pcl; + CDC dc; + int itemCount, numPages; + + itemCount = pContentList->GetItemCount(); + numPages = (itemCount + (pcl.GetLinesPerPage()-1)) / pcl.GetLinesPerPage(); + + dlg.m_pd.nFromPage = dlg.m_pd.nMinPage = 1; + dlg.m_pd.nToPage = dlg.m_pd.nMaxPage = numPages; + + dlg.m_pd.hDevMode = fhDevMode; + dlg.m_pd.hDevNames = fhDevNames; + dlg.m_pd.Flags |= PD_USEDEVMODECOPIESANDCOLLATE; + dlg.m_pd.Flags &= ~(PD_NOPAGENUMS); + if (dlg.DoModal() != IDOK) + return; + if (dc.Attach(dlg.GetPrinterDC()) != TRUE) { + CString msg; + msg.LoadString(IDS_PRINTER_NOT_USABLE); + ShowFailureMsg(this, msg, IDS_FAILED); + return; + } + + pcl.Setup(&dc, this); + if (dlg.m_pd.Flags & PD_PAGENUMS) + pcl.Print(pContentList, dlg.m_pd.nFromPage, dlg.m_pd.nToPage); + else + pcl.Print(pContentList); + + fhDevMode = dlg.m_pd.hDevMode; + fhDevNames = dlg.m_pd.hDevNames; +} + + +/* + * Handle Exit item by sending a close request. + */ +void +MainWindow::OnFileExit(void) +{ + SendMessage(WM_CLOSE, 0, 0); +} + + +/* + * Select everything in the content list. + */ +void +MainWindow::OnEditSelectAll(void) +{ + ASSERT(fpContentList != nil); + fpContentList->SelectAll(); +} +void +MainWindow::OnUpdateEditSelectAll(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(fpContentList != nil); +} + +/* + * Invert the content list selection. + */ +void +MainWindow::OnEditInvertSelection(void) +{ + ASSERT(fpContentList != nil); + fpContentList->InvertSelection(); +} +void +MainWindow::OnUpdateEditInvertSelection(CCmdUI* pCmdUI) +{ + pCmdUI->Enable(fpContentList != nil); +} + + +/* + * Get the one selected item from the current display. Primarily useful + * for the double-click handler, but also used for "action" menu items + * that insist on operating on a single menu item (edit prefs, create subdir). + * + * Returns nil if the item couldn't be found or if more than one item was + * selected. + */ +GenericEntry* +MainWindow::GetSelectedItem(ContentList* pContentList) +{ + if (pContentList->GetSelectedCount() != 1) + return nil; + + POSITION posn; + posn = pContentList->GetFirstSelectedItemPosition(); + if (posn == nil) { + ASSERT(false); + return nil; + } + int num = pContentList->GetNextSelectedItem(/*ref*/ posn); + GenericEntry* pEntry = (GenericEntry*) pContentList->GetItemData(num); + if (pEntry == nil) { + WMSG1(" Glitch: couldn't find entry %d\n", num); + ASSERT(false); + } + + return pEntry; +} + +/* + * Handle a double-click. + * + * Individual items get special treatment, multiple items just get handed off + * to the file viewer. + */ +void +MainWindow::HandleDoubleClick(void) +{ + bool handled = false; + + ASSERT(fpContentList != nil); + if (fpContentList->GetSelectedCount() == 0) { + /* nothing selected, they double-clicked outside first column */ + WMSG0("Double-click but nothing selected\n"); + return; + } + if (fpContentList->GetSelectedCount() != 1) { + /* multiple items, just bring up viewer */ + HandleView(); + return; + } + + /* + * Find the GenericEntry that corresponds to this item. + */ + GenericEntry* pEntry = GetSelectedItem(fpContentList); + if (pEntry == nil) + return; + + WMSG1(" Double-click GOT '%s'\n", pEntry->GetPathName()); + const char* ext; + long fileType, auxType; + + ext = FindExtension(pEntry->GetPathName(), pEntry->GetFssep()); + fileType = pEntry->GetFileType(); + auxType = pEntry->GetAuxType(); + + /* // unit tests for MatchSemicolonList + MatchSemicolonList("gif; jpeg; jpg", "jpeg"); + MatchSemicolonList("gif; jpeg; jpg", "jpg"); + MatchSemicolonList("gif; jpeg; jpg", "gif"); + MatchSemicolonList("gif;jpeg;jpg", "gif;"); + MatchSemicolonList("gif; jpeg; jpg", "jpe"); + MatchSemicolonList("gif; jpeg; jpg", "jpegx"); + MatchSemicolonList("gif; jpeg; jpg", "jp"); + MatchSemicolonList("gif; jpeg; jpg", "jpgx"); + MatchSemicolonList("gif; jpeg; jpg", "if"); + MatchSemicolonList("gif; jpeg; jpg", "gifs"); + MatchSemicolonList("gif, jpeg; jpg", "jpeg"); + MatchSemicolonList("", "jpeg"); + MatchSemicolonList(";", "jpeg"); + MatchSemicolonList("gif, jpeg; jpg", ""); + */ + + /* + * Figure out what to do with it. + */ + CString extViewerExts; + extViewerExts = fPreferences.GetPrefString(kPrExtViewerExts); + if (ext != nil && MatchSemicolonList(extViewerExts, ext+1)) { + WMSG1(" Launching external viewer for '%s'\n", ext); + TmpExtractForExternal(pEntry); + handled = true; + } else if (pEntry->GetRecordKind() == GenericEntry::kRecordKindFile) { + if ((ext != nil && ( + stricmp(ext, ".shk") == 0 || + stricmp(ext, ".sdk") == 0 || + stricmp(ext, ".bxy") == 0 )) || + (fileType == 0xe0 && auxType == 0x8002)) + { + WMSG0(" Guessing NuFX\n"); + TmpExtractAndOpen(pEntry, GenericEntry::kDataThread, kModeNuFX); + handled = true; + } else + if ((ext != nil && ( + stricmp(ext, ".bny") == 0 || + stricmp(ext, ".bqy") == 0 )) || + (fileType == 0xe0 && auxType == 0x8000)) + { + WMSG0(" Guessing Binary II\n"); + TmpExtractAndOpen(pEntry, GenericEntry::kDataThread, kModeBinaryII); + handled = true; + } else + if ((ext != nil && ( + stricmp(ext, ".acu") == 0 )) || + (fileType == 0xe0 && auxType == 0x8001)) + { + WMSG0(" Guessing ACU\n"); + TmpExtractAndOpen(pEntry, GenericEntry::kDataThread, kModeACU); + handled = true; + } else + if (fileType == 0x64496d67 && auxType == 0x64437079 && + pEntry->GetUncompressedLen() == 819284) + { + /* type is dImg, creator is dCpy, length is 800K + DC stuff */ + WMSG0(" Looks like a disk image\n"); + TmpExtractAndOpen(pEntry, GenericEntry::kDataThread, kModeDiskImage); + handled = true; + } + } else if (pEntry->GetRecordKind() == GenericEntry::kRecordKindDisk) { + WMSG0(" Opening archived disk image\n"); + TmpExtractAndOpen(pEntry, GenericEntry::kDiskImageThread, kModeDiskImage); + handled = true; + } + + if (!handled) { + // standard viewer + HandleView(); + } + + /* set "/t" temp flag and delete afterward, warning user (?) */ +} + +/* + * Extract a record to the temp folder and open it with a new instance of + * CiderPress. We might want to extract disk images as 2MG files to take + * the mystery out of opening them, but since they're coming out of a + * ShrinkIt archive they're pretty un-mysterious anyway. + * + * We tell the new instance to open it read-only, and flag it for + * deletion on exit. + * + * Returns 0 on success, nonzero error status on failure. + */ +int +MainWindow::TmpExtractAndOpen(GenericEntry* pEntry, int threadKind, + const char* modeStr) +{ + CString dispName; + bool mustDelete = false; + + /* + * Get the name to display in the title bar. Double quotes will + * screw it up, so we have to replace them. (We could escape them, + * but then we'd also have to escape the escape char.) + */ + dispName = pEntry->GetFileName(); + dispName.Replace('"', '_'); + + char nameBuf[MAX_PATH]; + UINT unique; + unique = GetTempFileName(fPreferences.GetPrefString(kPrTempPath), + "CPfile", 0, nameBuf); + if (unique == 0) { + DWORD dwerr = ::GetLastError(); + WMSG2("GetTempFileName failed on '%s' (err=%ld)\n", + fPreferences.GetPrefString(kPrTempPath), dwerr); + return dwerr; + } + mustDelete = true; + + /* + * Open the temp file and extract the data into it. + */ + CString errMsg; + int result; + FILE* fp; + + fp = fopen(nameBuf, "wb"); + if (fp != nil) { + WMSG2("Extracting to '%s' (unique=%d)\n", nameBuf, unique); + result = pEntry->ExtractThreadToFile(threadKind, fp, + GenericEntry::kConvertEOLOff, GenericEntry::kConvertHAOff, + &errMsg); + fclose(fp); + if (result == IDOK) { + /* success */ + CString parameters; + + parameters.Format("-mode %s -dispname \"%s\" -temparc \"%s\"", + modeStr, dispName, nameBuf); + int err; + + err = (int) ::ShellExecute(m_hWnd, _T("open"), + gMyApp.GetExeFileName(), parameters, NULL, + SW_SHOWNORMAL); + if (err <= 32) { + CString msg; + msg.Format("Unable to launch CiderPress (err=%d).", err); + ShowFailureMsg(this, msg, IDS_FAILED); + } else { + /* during dev, "missing DLL" causes false-positive success */ + WMSG0("Successfully launched CiderPress\n"); + mustDelete = false; // up to newly-launched app + } + } else { + ShowFailureMsg(this, errMsg, IDS_FAILED); + } + } else { + CString msg; + msg.Format("Unable to open temp file '%s'.", nameBuf); + ::ShowFailureMsg(this, msg, IDS_FAILED); + } + + if (mustDelete) { + WMSG1("Deleting '%s'\n", nameBuf); + unlink(nameBuf); + } + + return 0; +} + +/* + * Extract a record to the temp folder and open it with an external viewer. + * The file must be created with the correct extension so ShellExecute + * does the right thing. + * + * The files will be added to the "delete on exit" list, so that they will + * be cleaned up when CiderPress exits (assuming the external viewer no longer + * has them open). + * + * The GetTempFileName function creates a uniquely-named temp file. We + * create a file that has that name plus an extension. To ensure that we + * don't try to use the same temp filename twice, we have to hold off on + * deleting the unused .tmp files until we're ready to delete the + * corresponding .gif (or whatever) files. Thus, each invocation of this + * function creates two files and two entries in the delete-on-exit set. + * + * Returns 0 on success, nonzero error status on failure. + */ +int +MainWindow::TmpExtractForExternal(GenericEntry* pEntry) +{ + const char* ext; + + ext = FindExtension(pEntry->GetPathName(), pEntry->GetFssep()); + + char nameBuf[MAX_PATH]; + UINT unique; + unique = GetTempFileName(fPreferences.GetPrefString(kPrTempPath), + "CPfile", 0, nameBuf); + if (unique == 0) { + DWORD dwerr = ::GetLastError(); + WMSG2("GetTempFileName failed on '%s' (err=%ld)\n", + fPreferences.GetPrefString(kPrTempPath), dwerr); + return dwerr; + } + fDeleteList.Add(nameBuf); // file is created by GetTempFileName + + strcat(nameBuf, ext); + + /* + * Open the temp file and extract the data into it. + */ + CString errMsg; + int result; + FILE* fp; + + fp = fopen(nameBuf, "wb"); + if (fp != nil) { + fDeleteList.Add(nameBuf); // second file created by fopen + WMSG2("Extracting to '%s' (unique=%d)\n", nameBuf, unique); + result = pEntry->ExtractThreadToFile(GenericEntry::kDataThread, fp, + GenericEntry::kConvertEOLOff, GenericEntry::kConvertHAOff, + &errMsg); + fclose(fp); + if (result == IDOK) { + /* success */ + int err; + + err = (int) ::ShellExecute(m_hWnd, _T("open"), nameBuf, NULL, + NULL, SW_SHOWNORMAL); + if (err <= 32) { + CString msg; + msg.Format("Unable to launch external viewer (err=%d).", err); + ShowFailureMsg(this, msg, IDS_FAILED); + } else { + WMSG0("Successfully launched external viewer\n"); + } + } else { + ShowFailureMsg(this, errMsg, IDS_FAILED); + } + } else { + CString msg; + msg.Format("Unable to open temp file '%s'.", nameBuf); + ShowFailureMsg(this, msg, IDS_FAILED); + } + + return 0; +} + +#if 0 +/* + * Handle a "default action" selection from the right-click menu. The + * action only applies to the record that was clicked on, so we need to + * retrieve that from the control. + */ +void +MainWindow::OnRtClkDefault(void) +{ + int idx; + + ASSERT(fpContentList != nil); + + idx = fpContentList->GetRightClickItem(); + ASSERT(idx != -1); + WMSG1("OnRtClkDefault %d\n", idx); + + fpContentList->ClearRightClickItem(); +} +#endif + + +/* + * =================================== + * Progress meter + * =================================== + */ + +/* + * There are two different mechanisms for reporting progress: ActionProgress + * dialogs (for adding/extracting files) and a small box in the lower + * right-hand corner (for opening archives). These functions will set + * the progress in the active action progress dialog if it exists, or + * will set the percentage in the window frame if not. + */ + +void +MainWindow::SetProgressBegin(void) +{ + if (fpActionProgress != nil) + fpActionProgress->SetProgress(0); + else + fStatusBar.SetPaneText(kProgressPane, "--%"); + //WMSG0(" Complete: BEGIN\n"); + + /* redraw stuff with the changes */ + (void) PeekAndPump(); +} + +int +MainWindow::SetProgressUpdate(int percent, const char* oldName, + const char* newName) +{ + int status = IDOK; + + if (fpActionProgress != nil) { + status = fpActionProgress->SetProgress(percent); + if (oldName != nil) + fpActionProgress->SetArcName(oldName); + if (newName != nil) + fpActionProgress->SetFileName(newName); + } else { + char buf[8]; + sprintf(buf, "%d%%", percent); + fStatusBar.SetPaneText(kProgressPane, buf); + //WMSG1(" Complete: %s\n", buf); + } + + if (!PeekAndPump()) { + WMSG0("SetProgressUpdate: shutdown?!\n"); + } + + //EventPause(10); // DEBUG DEBUG + return status; +} + +void +MainWindow::SetProgressEnd(void) +{ + if (fpActionProgress != nil) + fpActionProgress->SetProgress(100); + else + fStatusBar.SetPaneText(kProgressPane, ""); +// EventPause(100); // DEBUG DEBUG + //WMSG0(" Complete: END\n"); +} + + +/* + * Set a number in the "progress counter". Useful for loading large archives + * where we're not sure how much stuff is left, so showing a percentage is + * hard. + * + * Pass in -1 to erase the counter. + * + * Returns "true" if we'd like things to continue. + */ +bool +MainWindow::SetProgressCounter(const char* str, long val) +{ + /* if the main window is enabled, user could activate menus */ + ASSERT(!IsWindowEnabled()); + + if (fpProgressCounter != nil) { + //WMSG2("SetProgressCounter '%s' %d\n", str, val); + CString msg; + + if (str != nil) + fpProgressCounter->SetCounterFormat(str); + fpProgressCounter->SetCount((int) val); + } else { + if (val < 0) { + fStatusBar.SetPaneText(kProgressPane, ""); + } else { + CString tmpStr; + tmpStr.Format("%ld", val); + fStatusBar.SetPaneText(kProgressPane, tmpStr); + } + } + + if (!PeekAndPump()) { + WMSG0("SetProgressCounter: shutdown?!\n"); + } + //EventPause(10); // DEBUG DEBUG + + if (fpProgressCounter != nil) + return !fpProgressCounter->GetCancel(); + else + return true; +} + + +/* + * Allow events to flow through the message queue whenever the + * progress meter gets updated. This will allow us to redraw with + * reasonable frequency. + * + * Calling this can result in other code being called, such as Windows + * message handlers, which can lead to reentrancy problems. Make sure + * you're adequately semaphored before calling here. + * + * Returns TRUE if all is well, FALSE if we're trying to quit. + */ +BOOL +MainWindow::PeekAndPump(void) +{ + MSG msg; + + while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { + if (!AfxGetApp()->PumpMessage()) { + ::PostQuitMessage(0); + return FALSE; + } + } + + LONG lIdle = 0; + while (AfxGetApp()->OnIdle(lIdle++)) + ; + return TRUE; +} + +/* + * Go to sleep for a little bit, waking up 100x per second to check + * the idle loop. + */ +void +MainWindow::EventPause(int duration) +{ + int count = duration / 10; + + for (int i = 0; i < count; i++) { + PeekAndPump(); + ::Sleep(10); + } +} + +/* + * Printer abort procedure; allows us to abort a print job. The DC + * SetAbortProc() function calls here periodically. The return value from + * this function determine whether or not printing halts. + * + * This checks a global "print cancel" variable, which is set by our print + * cancel button dialog. + * + * If this returns TRUE, printing continues; FALSE, and printing aborts. + */ +/*static*/ BOOL CALLBACK +MainWindow::PrintAbortProc(HDC hDC, int nCode) +{ + MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); + + pMain->PeekAndPump(); + if (pMain->GetAbortPrinting()) { + WMSG0("PrintAbortProc returning FALSE (abort printing)\n"); + return FALSE; + } + WMSG0(" PrintAbortProc returning TRUE (continue printing)\n"); + return TRUE; +} + +/* + * =================================== + * Support functions + * =================================== + */ + +/* + * Draw what looks like an empty client area. + */ +void +MainWindow::DrawEmptyClientArea(CDC* pDC, const CRect& clientRect) +{ + CBrush brush; + brush.CreateSolidBrush(::GetSysColor(COLOR_APPWORKSPACE)); // dk gray + CBrush* pOldBrush = pDC->SelectObject(&brush); + pDC->FillRect(&clientRect, &brush); + pDC->SelectObject(pOldBrush); + + CPen penWH(PS_SOLID, 1, ::GetSysColor(COLOR_3DHIGHLIGHT)); // white + CPen penLG(PS_SOLID, 1, ::GetSysColor(COLOR_3DLIGHT)); // lt gray + CPen penDG(PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW)); // dk gray + CPen penBL(PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW)); // near-black + CPen* pOldPen = pDC->SelectObject(&penWH); + //pDC->SelectObject(&penWH); + pDC->MoveTo(clientRect.right-1, clientRect.top); + pDC->LineTo(clientRect.right-1, clientRect.bottom-1); + pDC->LineTo(clientRect.left-1, clientRect.bottom-1); + pDC->SelectObject(&penBL); + pDC->MoveTo(clientRect.right-3, clientRect.top+1); + pDC->LineTo(clientRect.left+1, clientRect.top+1); + pDC->LineTo(clientRect.left+1, clientRect.bottom-2); + pDC->SelectObject(&penLG); + pDC->MoveTo(clientRect.right-2, clientRect.top+1); + pDC->LineTo(clientRect.right-2, clientRect.bottom-2); + pDC->LineTo(clientRect.left, clientRect.bottom-2); + pDC->SelectObject(&penDG); + pDC->MoveTo(clientRect.right-2, clientRect.top); + pDC->LineTo(clientRect.left, clientRect.top); + pDC->LineTo(clientRect.left, clientRect.bottom-1); + + pDC->SelectObject(pOldPen); +} + +/* + * Load an archive, using the appropriate GenericArchive subclass. If + * "createFile" is "true", a new archive file will be created (and must + * not already exist!). + * + * "filename" is the full path to the file, "extension" is the + * filetype component of the name (without the leading '.'), "filterIndex" + * is the offset into the set of filename filters used in the standard + * file dialog, "readOnly" reflects the state of the stdfile dialog + * checkbox, and "createFile" is set to true by the "New Archive" command. + * + * Returns 0 on success, nonzero on failure. + */ +int +MainWindow::LoadArchive(const char* fileName, const char* extension, + int filterIndex, bool readOnly, bool createFile) +{ + GenericArchive::OpenResult openResult; + int result = -1; + GenericArchive* pOpenArchive = nil; + int origFilterIndex = filterIndex; + CString errStr, appName; + + appName.LoadString(IDS_MB_APP_NAME); + + WMSG3("LoadArchive: '%s' ro=%d idx=%d\n", fileName, readOnly, filterIndex); + + /* close any existing archive to avoid weirdness from re-open */ + CloseArchive(); + + /* + * If they used the "All Files (*.*)" filter, we have to guess based + * on the file type. + * + * IDEA: change the current "filterIndex ==" stuff to a type-specific + * model, then do type-scanning here. Code later on takes the type + * and opens it. That way we can do the trivial "it must be" handling + * up here, and maybe do a little "open it up and see" stuff as well. + * In general, though, if we don't recognize the extension, it's + * probably a disk image. + */ + if (filterIndex == kFilterIndexGeneric) { + int i; + + for (i = 0; i < NELEM(gExtensionToIndex); i++) { + if (strcasecmp(extension, gExtensionToIndex[i].extension) == 0) { + filterIndex = gExtensionToIndex[i].idx; + break; + } + } + + if (i == NELEM(gExtensionToIndex)) + filterIndex = kFilterIndexDiskImage; + } + +try_again: + if (filterIndex == kFilterIndexBinaryII) { + /* try Binary II and nothing else */ + ASSERT(!createFile); + WMSG0(" Trying Binary II\n"); + pOpenArchive = new BnyArchive; + openResult = pOpenArchive->Open(fileName, readOnly, &errStr); + if (openResult != GenericArchive::kResultSuccess) { + if (!errStr.IsEmpty()) + ShowFailureMsg(this, errStr, IDS_FAILED); + result = -1; + goto bail; + } + } else + if (filterIndex == kFilterIndexACU) { + /* try ACU and nothing else */ + ASSERT(!createFile); + WMSG0(" Trying ACU\n"); + pOpenArchive = new AcuArchive; + openResult = pOpenArchive->Open(fileName, readOnly, &errStr); + if (openResult != GenericArchive::kResultSuccess) { + if (!errStr.IsEmpty()) + ShowFailureMsg(this, errStr, IDS_FAILED); + result = -1; + goto bail; + } + } else + if (filterIndex == kFilterIndexDiskImage) { + /* try various disk image formats */ + ASSERT(!createFile); + WMSG0(" Trying disk images\n"); + + pOpenArchive = new DiskArchive; + openResult = pOpenArchive->Open(fileName, readOnly, &errStr); + if (openResult == GenericArchive::kResultCancel) { + result = -1; + goto bail; + } else if (openResult == GenericArchive::kResultFileArchive) { + delete pOpenArchive; + pOpenArchive = nil; + + if (strcasecmp(extension, "zip") == 0) { + errStr = "ZIP archives with multiple files are not supported."; + MessageBox(errStr, appName, MB_OK|MB_ICONINFORMATION); + result = -1; + goto bail; + } else { + /* assume some variation of a ShrinkIt archive */ + // msg.LoadString(IDS_OPEN_AS_NUFX); <-- with MB_OKCANCEL + filterIndex = kFilterIndexNuFX; + goto try_again; + } + + } else if (openResult != GenericArchive::kResultSuccess) { + if (filterIndex != origFilterIndex) { + /* + * Kluge: assume we guessed disk image and were wrong. + */ + errStr = "File doesn't appear to be a valid archive" + " or disk image."; + } + if (!errStr.IsEmpty()) + ShowFailureMsg(this, errStr, IDS_FAILED); + result = -1; + goto bail; + } + } else + if (filterIndex == kFilterIndexNuFX) { + /* try NuFX (including its embedded-in-BNY form) */ + WMSG0(" Trying NuFX\n"); + + pOpenArchive = new NufxArchive; + openResult = pOpenArchive->Open(fileName, readOnly, &errStr); + if (openResult != GenericArchive::kResultSuccess) { + if (!errStr.IsEmpty()) + ShowFailureMsg(this, errStr, IDS_FAILED); + result = -1; + goto bail; + } + + } else { + ASSERT(FALSE); + result = -1; + goto bail; + } + + SwitchContentList(pOpenArchive); + + pOpenArchive = nil; + result = 0; + +bail: + if (pOpenArchive != nil) { + ASSERT(result != 0); + delete pOpenArchive; + } + return result; +} + +/* + * Open a raw disk volume. Useful for ProDOS-formatted 1.44MB floppy disks + * and CFFA flash cards. + * + * Assume it's a disk image -- it'd be a weird place for a ShrinkIt archive. + * CFFA cards can actually hold multiple volumes, but that's all taken care + * of inside the diskimg DLL. + * + * Returns 0 on success, nonzero on failure. + */ +int +MainWindow::DoOpenVolume(CString drive, bool readOnly) +{ + int result = -1; + + ASSERT(drive.GetLength() > 0); + + CString errStr; + //char filename[4] = "_:\\"; + //filename[0] = driveLetter; + + WMSG2("FileOpenVolume '%s' %d\n", (const char*)drive, readOnly); + + /* close existing archive */ + CloseArchive(); + + GenericArchive* pOpenArchive = nil; + pOpenArchive = new DiskArchive; + { + CWaitCursor waitc; + GenericArchive::OpenResult openResult; + + openResult = pOpenArchive->Open(drive, readOnly, &errStr); + if (openResult == GenericArchive::kResultCancel) { + // this bubbles out of the format confirmation dialog + goto bail; + } else if (openResult != GenericArchive::kResultSuccess) { + if (!errStr.IsEmpty()) + ShowFailureMsg(this, errStr, IDS_FAILED); + goto bail; + } + } + + // success! + SwitchContentList(pOpenArchive); + pOpenArchive = nil; + fOpenArchivePathName = drive; + result = 0; + + fOpenArchivePathName = drive; + SetCPTitle(fOpenArchivePathName, fpOpenArchive); + +bail: + if (pOpenArchive != nil) { + ASSERT(result != 0); + delete pOpenArchive; + } + return result; +} + + +/* + * Close and re-open the current archive. + */ +void +MainWindow::ReopenArchive(void) +{ + if (fpOpenArchive == nil) { + ASSERT(false); + return; + } + + /* clear the flag, regardless of success or failure */ + fNeedReopen = false; + + GenericArchive* pOpenArchive = nil; + CString pathName = fpOpenArchive->GetPathName(); + bool readOnly = fpOpenArchive->IsReadOnly(); + GenericArchive::ArchiveKind archiveKind = fpOpenArchive->GetArchiveKind(); + GenericArchive::OpenResult openResult; + CString errStr; + + /* if the open fails we *don't* want to leave the previous content up */ + WMSG3("Reopening '%s' ro=%d kind=%d\n", pathName, readOnly, archiveKind); + CloseArchive(); + + switch (archiveKind) { + case GenericArchive::kArchiveDiskImage: + pOpenArchive = new DiskArchive; + break; + case GenericArchive::kArchiveNuFX: + pOpenArchive = new NufxArchive; + break; + case GenericArchive::kArchiveBNY: + pOpenArchive = new BnyArchive; + break; + default: + ASSERT(false); + return; + } + + openResult = pOpenArchive->Open(pathName, readOnly, &errStr); + if (openResult == GenericArchive::kResultCancel) { + // this bubbles out of the format confirmation dialog + goto bail; + } else if (openResult != GenericArchive::kResultSuccess) { + if (!errStr.IsEmpty()) + ShowFailureMsg(this, errStr, IDS_FAILED); + goto bail; + } + + WMSG0(" Reopen was successful\n"); + SwitchContentList(pOpenArchive); + pOpenArchive = nil; + SetCPTitle(pathName, fpOpenArchive); + +bail: + delete pOpenArchive; +} + +/* + * Determine whether "path" matches the pathname of the currently open archive. + */ +bool +MainWindow::IsOpenPathName(const char* path) +{ + if (fpOpenArchive == nil) + return false; + + if (stricmp(path, fpOpenArchive->GetPathName()) == 0) + return true; + + return false; +} + + +/* + * Switch the content list to a new archive, closing the previous if one + * was already open. + */ +void +MainWindow::SwitchContentList(GenericArchive* pOpenArchive) +{ + assert(pOpenArchive != nil); + + /* + * We've got an archive opened successfully. If we already had one + * open, shut it. (This assumes that closing an archive is a simple + * matter of closing files and freeing storage. If we needed to do + * something that might fail, like flush changes, we should've done + * that before getting this far to avoid confusion.) + */ + if (fpOpenArchive != nil) + CloseArchive(); + + ASSERT(fpOpenArchive == nil); + ASSERT(fpContentList == nil); + + /* + * Without this we get an assertion failure in CImageList::Attach if we + * call here from ReopenArchive. I think Windows needs to do some + * cleanup, though I don't understand how the reopen case differs from + * the usual case. Maybe there's more stuff pending in the "reopen" + * case? In any event, this seems to work, which is all you can hope + * for from MFC. It does, however, make the screen flash, which it + * didn't do before. + * + * UPDATE: this tripped once while I was debugging, even with this. The + * PeekAndPump function does force the idle loop to run, so I'm not sure + * why it failed, unless the debugger somehow affected the idle + * processing. Yuck. + * + * The screen flash bugged me so I took it back out. And the assert + * didn't hit. I really, really love Windows. + */ + //PeekAndPump(); + + + fpContentList = new ContentList(pOpenArchive, + fPreferences.GetColumnLayout()); + + CRect sizeRect; + GetClientRect(&sizeRect); + fpContentList->Create(WS_CHILD | WS_VISIBLE | WS_VSCROLL, + sizeRect, this, IDC_CONTENT_LIST); + + fpOpenArchive = pOpenArchive; +} + + +/* + * Close the existing archive file, but don't try to shut down the child + * windows. This should really only be used from the destructor. + */ +void +MainWindow::CloseArchiveWOControls(void) +{ + if (fpOpenArchive != nil) { + //fpOpenArchive->Close(); + WMSG0("Deleting OpenArchive\n"); + delete fpOpenArchive; + fpOpenArchive = nil; + } +} + +/* + * Close the existing archive file, and throw out the control we're + * using to display it. + */ +void +MainWindow::CloseArchive(void) +{ + CWaitCursor waitc; // closing large compressed archive can be slow + + // destroy the ContentList + if (fpContentList != nil) { + WMSG0("Destroying ContentList\n"); + fpContentList->DestroyWindow(); // auto-cleanup invokes "delete" + fpContentList = nil; + } + + // destroy the GenericArchive + CloseArchiveWOControls(); + + // reset the title bar + SetCPTitle(); +} + + +/* + * Set the title bar on the main window. + * + * "pathname" is often different from pOpenArchive->GetPathName(), especially + * when we were launched from another instance of CiderPress and handed a + * temp file whose name we're trying to conceal. + */ +void +MainWindow::SetCPTitle(const char* pathname, GenericArchive* pOpenArchive) +{ + ASSERT(pathname != nil); + CString title; + CString archiveDescription; + CString appName; + + appName.LoadString(IDS_MB_APP_NAME); + + pOpenArchive->GetDescription(&archiveDescription); + title.Format(_T("%s - %s (%s)"), appName, pathname, archiveDescription); + + if (fpOpenArchive->IsReadOnly()) { + CString readOnly; + readOnly.LoadString(IDS_READONLY); + title += _T(" "); + title += readOnly; + } + + SetWindowText(title); +} + +/* + * Set the title bar to something boring when nothing is open. + */ +void +MainWindow::SetCPTitle(void) +{ + CString appName, regName, title; + CString user, company, reg, versions, expire; + +#if 0 + if (gMyApp.fRegistry.GetRegistration(&user, &company, ®, &versions, + &expire) == 0) + { + if (reg.IsEmpty()) { + regName += _T(" (unregistered)"); + } else { + regName += _T(" (registered to "); + regName += user; + regName += _T(")"); + // include company? + } + } +#endif + + appName.LoadString(IDS_MB_APP_NAME); + title = appName + regName; + SetWindowText(title); +} + +/* + * Come up with a title to put at the top of a printout. This is essentially + * the same as the window title, but without some flags (e.g. "read-only"). + */ +CString +MainWindow::GetPrintTitle(void) +{ + CString title; + CString archiveDescription; + CString appName; + + if (fpOpenArchive == nil) { + ASSERT(false); + return title; + } + + appName.LoadString(IDS_MB_APP_NAME); + + fpOpenArchive->GetDescription(&archiveDescription); + title.Format(_T("%s - %s (%s)"), + appName, fOpenArchivePathName, archiveDescription); + + return title; +} + + +/* + * After successful completion of a command, make a happy noise (but only + * if we're configured to do so). + */ +void +MainWindow::SuccessBeep(void) +{ + const Preferences* pPreferences = GET_PREFERENCES(); + + if (pPreferences->GetPrefBool(kPrBeepOnSuccess)) { + WMSG0("\n"); + ::MessageBeep(MB_OK); + } +} + +/* + * If something fails, make noise if we're configured for loudness. + */ +void +MainWindow::FailureBeep(void) +{ + const Preferences* pPreferences = GET_PREFERENCES(); + + if (pPreferences->GetPrefBool(kPrBeepOnSuccess)) { + WMSG0("\n"); + ::MessageBeep(MB_ICONEXCLAMATION); // maybe MB_ICONHAND? + } +} + +/* + * Remove a file. Returns a helpful error string on failure. + * + * The absence of the file is not considered an error. + */ +CString +MainWindow::RemoveFile(const char* fileName) +{ + CString errMsg; + + int cc; + cc = unlink(fileName); + if (cc < 0 && errno != ENOENT) { + int err = errno; + WMSG2("Failed removing file '%s', errno=%d\n", fileName, err); + errMsg.Format("Unable to remove '%s': %s.", + fileName, strerror(err)); + if (err == EACCES) + errMsg += "\n\n(Make sure the file isn't open.)"; + } + + return errMsg; +} + + +/* + * Configure a ReformatHolder based on the current preferences. + */ +/*static*/ void +MainWindow::ConfigureReformatFromPreferences(ReformatHolder* pReformat) +{ + const Preferences* pPreferences = GET_PREFERENCES(); + + pReformat->SetReformatAllowed(ReformatHolder::kReformatRaw, true); + pReformat->SetReformatAllowed(ReformatHolder::kReformatHexDump, true); + + pReformat->SetReformatAllowed(ReformatHolder::kReformatTextEOL_HA, + pPreferences->GetPrefBool(kPrConvTextEOL_HA)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatResourceFork, + pPreferences->GetPrefBool(kPrConvResources)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatProDOSDirectory, + pPreferences->GetPrefBool(kPrConvProDOSFolder)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatPascalText, + pPreferences->GetPrefBool(kPrConvPascalText)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatPascalCode, + pPreferences->GetPrefBool(kPrConvPascalCode)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatCPMText, + pPreferences->GetPrefBool(kPrConvCPMText)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatApplesoft, + pPreferences->GetPrefBool(kPrConvApplesoft)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatApplesoft_Hilite, + pPreferences->GetPrefBool(kPrConvApplesoft)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatInteger, + pPreferences->GetPrefBool(kPrConvInteger)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatInteger_Hilite, + pPreferences->GetPrefBool(kPrConvInteger)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatBusiness, + pPreferences->GetPrefBool(kPrConvBusiness)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatBusiness_Hilite, + pPreferences->GetPrefBool(kPrConvBusiness)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatSCAssem, + pPreferences->GetPrefBool(kPrConvSCAssem)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatMerlin, + pPreferences->GetPrefBool(kPrConvSCAssem)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatLISA2, + pPreferences->GetPrefBool(kPrConvSCAssem)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatLISA3, + pPreferences->GetPrefBool(kPrConvSCAssem)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatLISA4, + pPreferences->GetPrefBool(kPrConvSCAssem)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatMonitor8, + pPreferences->GetPrefBool(kPrConvDisasm)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatDisasmMerlin8, + pPreferences->GetPrefBool(kPrConvDisasm)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatMonitor16Long, + pPreferences->GetPrefBool(kPrConvDisasm)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatMonitor16Short, + pPreferences->GetPrefBool(kPrConvDisasm)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatDisasmOrcam16, + pPreferences->GetPrefBool(kPrConvDisasm)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatAWGS_WP, + pPreferences->GetPrefBool(kPrConvGWP)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatTeach, + pPreferences->GetPrefBool(kPrConvGWP)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatGWP, + pPreferences->GetPrefBool(kPrConvGWP)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatMagicWindow, + pPreferences->GetPrefBool(kPrConvText8)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatGutenberg, + pPreferences->GetPrefBool(kPrConvGutenberg)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatAWP, + pPreferences->GetPrefBool(kPrConvAWP)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatAWP, + pPreferences->GetPrefBool(kPrConvAWP)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatADB, + pPreferences->GetPrefBool(kPrConvADB)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatASP, + pPreferences->GetPrefBool(kPrConvASP)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatHiRes, + pPreferences->GetPrefBool(kPrConvHiRes)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatHiRes_BW, + pPreferences->GetPrefBool(kPrConvHiRes)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatDHR_Latched, + pPreferences->GetPrefBool(kPrConvDHR)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatDHR_BW, + pPreferences->GetPrefBool(kPrConvDHR)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatDHR_Plain140, + pPreferences->GetPrefBool(kPrConvDHR)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatDHR_Window, + pPreferences->GetPrefBool(kPrConvDHR)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_PIC, + pPreferences->GetPrefBool(kPrConvSHR)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_JEQ, + pPreferences->GetPrefBool(kPrConvSHR)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_Paintworks, + pPreferences->GetPrefBool(kPrConvSHR)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_Packed, + pPreferences->GetPrefBool(kPrConvSHR)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_APF, + pPreferences->GetPrefBool(kPrConvSHR)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_3200, + pPreferences->GetPrefBool(kPrConvSHR)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_3201, + pPreferences->GetPrefBool(kPrConvSHR)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_DG256, + pPreferences->GetPrefBool(kPrConvSHR)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatSHR_DG3200, + pPreferences->GetPrefBool(kPrConvSHR)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatPrintShop, + pPreferences->GetPrefBool(kPrConvPrintShop)); + pReformat->SetReformatAllowed(ReformatHolder::kReformatMacPaint, + pPreferences->GetPrefBool(kPrConvMacPaint)); + + pReformat->SetOption(ReformatHolder::kOptHiliteHexDump, + pPreferences->GetPrefBool(kPrHighlightHexDump)); + pReformat->SetOption(ReformatHolder::kOptHiliteBASIC, + pPreferences->GetPrefBool(kPrHighlightBASIC)); + pReformat->SetOption(ReformatHolder::kOptHiResBW, + pPreferences->GetPrefBool(kPrConvHiResBlackWhite)); + pReformat->SetOption(ReformatHolder::kOptDHRAlgorithm, + pPreferences->GetPrefLong(kPrConvDHRAlgorithm)); + pReformat->SetOption(ReformatHolder::kOptRelaxGfxTypeCheck, + pPreferences->GetPrefBool(kPrRelaxGfxTypeCheck)); + pReformat->SetOption(ReformatHolder::kOptOneByteBrkCop, + pPreferences->GetPrefBool(kPrDisasmOneByteBrkCop)); +} + +/* + * Convert a DiskImg format spec into a ReformatHolder SourceFormat. + */ +/*static*/ ReformatHolder::SourceFormat +MainWindow::ReformatterSourceFormat(DiskImg::FSFormat format) +{ + /* + * Gutenberg both UsesDOSFileStructure and is formatted with + * kFormatGutenberg, so check for the latter first. + */ + if (format == DiskImg::kFormatGutenberg) + return ReformatHolder::kSourceFormatGutenberg; + else if (DiskImg::UsesDOSFileStructure(format)) + return ReformatHolder::kSourceFormatDOS; + else if (format == DiskImg::kFormatCPM) + return ReformatHolder::kSourceFormatCPM; + else + return ReformatHolder::kSourceFormatGeneric; +} diff --git a/app/Main.h b/app/Main.h index ed5a663..10a8770 100644 --- a/app/Main.h +++ b/app/Main.h @@ -22,18 +22,18 @@ //#include "ProgressCancelDialog.h" /* user-defined window messages */ -#define WMU_LATE_INIT (WM_USER+0) -#define WMU_START (WM_USER+1) // used by ActionProgressDialog +#define WMU_LATE_INIT (WM_USER+0) +#define WMU_START (WM_USER+1) // used by ActionProgressDialog typedef enum { - kFilterIndexNuFX = 1, - kFilterIndexBinaryII = 2, - kFilterIndexACU = 3, - kFilterIndexDiskImage = 4, - kFilterIndexGeneric = 5, // *.* filter used + kFilterIndexNuFX = 1, + kFilterIndexBinaryII = 2, + kFilterIndexACU = 3, + kFilterIndexDiskImage = 4, + kFilterIndexGeneric = 5, // *.* filter used } FilterIndex; -struct FileCollectionEntry; // fwd +struct FileCollectionEntry; // fwd /* * The main UI window. @@ -41,393 +41,393 @@ struct FileCollectionEntry; // fwd class MainWindow : public CFrameWnd { public: - MainWindow(void); - ~MainWindow(void); + MainWindow(void); + ~MainWindow(void); - // Overridden functions - BOOL PreCreateWindow(CREATESTRUCT& cs); - //BOOL OnCreateClient( LPCREATESTRUCT lpcs, CCreateContext* pContext ); - void GetClientRect(LPRECT lpRect) const; + // Overridden functions + BOOL PreCreateWindow(CREATESTRUCT& cs); + //BOOL OnCreateClient( LPCREATESTRUCT lpcs, CCreateContext* pContext ); + void GetClientRect(LPRECT lpRect) const; - // get a pointer to the preferences - const Preferences* GetPreferences(void) const { return &fPreferences; } - Preferences* GetPreferencesWr(void) { return &fPreferences; } - // apply an update from the Preferences pages - void ApplyNow(PrefsSheet*); + // get a pointer to the preferences + const Preferences* GetPreferences(void) const { return &fPreferences; } + Preferences* GetPreferencesWr(void) { return &fPreferences; } + // apply an update from the Preferences pages + void ApplyNow(PrefsSheet*); - // get the text of the next file in the selection list - int GetPrevFileText(ReformatHolder* pHolder, CString* pTitle); - int GetNextFileText(ReformatHolder* pHolder, CString* pTitle); + // get the text of the next file in the selection list + int GetPrevFileText(ReformatHolder* pHolder, CString* pTitle); + int GetNextFileText(ReformatHolder* pHolder, CString* pTitle); - // update the progress meter - void SetProgressBegin(void); - int SetProgressUpdate(int percent, const char* oldName, - const char* newName); - void SetProgressEnd(void); + // update the progress meter + void SetProgressBegin(void); + int SetProgressUpdate(int percent, const char* oldName, + const char* newName); + void SetProgressEnd(void); - // update the progress counter - bool SetProgressCounter(const char* fmt, long val); + // update the progress counter + bool SetProgressCounter(const char* fmt, long val); - // handle a double-click in the content view - void HandleDoubleClick(void); + // handle a double-click in the content view + void HandleDoubleClick(void); - // do some idle processing - void DoIdle(void); + // do some idle processing + void DoIdle(void); - // return the title to put at the top of a printout - CString GetPrintTitle(void); + // return the title to put at the top of a printout + CString GetPrintTitle(void); - // raise flag to abort the current print job - void SetAbortPrinting(bool val) { fAbortPrinting = val; } - bool GetAbortPrinting(void) const { return fAbortPrinting; } - static BOOL CALLBACK PrintAbortProc(HDC hDC, int nCode); - bool fAbortPrinting; - // track printer choice - HANDLE fhDevMode; - HANDLE fhDevNames; + // raise flag to abort the current print job + void SetAbortPrinting(bool val) { fAbortPrinting = val; } + bool GetAbortPrinting(void) const { return fAbortPrinting; } + static BOOL CALLBACK PrintAbortProc(HDC hDC, int nCode); + bool fAbortPrinting; + // track printer choice + HANDLE fhDevMode; + HANDLE fhDevNames; - // set flag to abort current operation - //void SetAbortOperation(bool val) { fAbortOperation = val; } - //bool fAbortOperation; + // set flag to abort current operation + //void SetAbortOperation(bool val) { fAbortOperation = val; } + //bool fAbortOperation; - // pause, for debugging - void EventPause(int duration); + // pause, for debugging + void EventPause(int duration); - ContentList* GetContentList(void) const { return fpContentList; } + ContentList* GetContentList(void) const { return fpContentList; } - void SetActionProgressDialog(ActionProgressDialog* pActionProgress) { - fpActionProgress = pActionProgress; - } - void SetProgressCounterDialog(ProgressCounterDialog* pProgressCounter) { - fpProgressCounter = pProgressCounter; - } - GenericArchive* GetOpenArchive(void) const { return fpOpenArchive; } + void SetActionProgressDialog(ActionProgressDialog* pActionProgress) { + fpActionProgress = pActionProgress; + } + void SetProgressCounterDialog(ProgressCounterDialog* pProgressCounter) { + fpProgressCounter = pProgressCounter; + } + GenericArchive* GetOpenArchive(void) const { return fpOpenArchive; } - int GetFileParts(const GenericEntry* pEntry, - ReformatHolder** ppHolder) const; + int GetFileParts(const GenericEntry* pEntry, + ReformatHolder** ppHolder) const; - // force processing of pending messages - BOOL PeekAndPump(); + // force processing of pending messages + BOOL PeekAndPump(); - // make a happy noise after successful execution of a command - void SuccessBeep(void); - // make a not-so-happy noise - void FailureBeep(void); + // make a happy noise after successful execution of a command + void SuccessBeep(void); + // make a not-so-happy noise + void FailureBeep(void); - // remove a file, returning a helpful message on failure - CString RemoveFile(const char* fileName); + // remove a file, returning a helpful message on failure + CString RemoveFile(const char* fileName); - // choose the place to put a file - bool ChooseAddTarget(DiskImgLib::A2File** ppTargetSubdir, - DiskImgLib::DiskFS** ppDiskFS); + // choose the place to put a file + bool ChooseAddTarget(DiskImgLib::A2File** ppTargetSubdir, + DiskImgLib::DiskFS** ppDiskFS); - // try a disk image override dialog - int TryDiskImgOverride(DiskImg* pImg, const char* fileSource, - DiskImg::FSFormat defaultFormat, int* pDisplayFormat, - bool allowUnknown, CString* pErrMsg); - // copy all blocks from one disk image to another - DIError CopyDiskImage(DiskImg* pDstImg, DiskImg* pSrcImg, bool bulk, - bool partial, ProgressCancelDialog* pPCDialog); + // try a disk image override dialog + int TryDiskImgOverride(DiskImg* pImg, const char* fileSource, + DiskImg::FSFormat defaultFormat, int* pDisplayFormat, + bool allowUnknown, CString* pErrMsg); + // copy all blocks from one disk image to another + DIError CopyDiskImage(DiskImg* pDstImg, DiskImg* pSrcImg, bool bulk, + bool partial, ProgressCancelDialog* pPCDialog); - // does the currently open archive pathname match? - bool IsOpenPathName(const char* path); - // raise a flag to cause a full reload of the open file - void SetReopenFlag(void) { fNeedReopen = true; } + // does the currently open archive pathname match? + bool IsOpenPathName(const char* path); + // raise a flag to cause a full reload of the open file + void SetReopenFlag(void) { fNeedReopen = true; } - static void ConfigureReformatFromPreferences(ReformatHolder* pReformat); - static ReformatHolder::SourceFormat ReformatterSourceFormat(DiskImg::FSFormat format); + static void ConfigureReformatFromPreferences(ReformatHolder* pReformat); + static ReformatHolder::SourceFormat ReformatterSourceFormat(DiskImg::FSFormat format); - // save a buffer of data as a file in a disk image or file archive - static bool SaveToArchive(GenericArchive::FileDetails* pDetails, - const unsigned char* dataBuf, long dataLen, - const unsigned char* rsrcBuf, long rsrcLen, - CString& errMsg, CWnd* pDialog); + // save a buffer of data as a file in a disk image or file archive + static bool SaveToArchive(GenericArchive::FileDetails* pDetails, + const unsigned char* dataBuf, long dataLen, + const unsigned char* rsrcBuf, long rsrcLen, + CString& errMsg, CWnd* pDialog); - static const char kOpenNuFX[]; - static const char kOpenBinaryII[]; - static const char kOpenACU[]; - static const char kOpenDiskImage[]; - static const char kOpenAll[]; - static const char kOpenEnd[]; + static const char kOpenNuFX[]; + static const char kOpenBinaryII[]; + static const char kOpenACU[]; + static const char kOpenDiskImage[]; + static const char kOpenAll[]; + static const char kOpenEnd[]; private: - static const char* kModeNuFX; - static const char* kModeBinaryII; - static const char* kModeACU; - static const char* kModeDiskImage; + static const char* kModeNuFX; + static const char* kModeBinaryII; + static const char* kModeACU; + static const char* kModeDiskImage; - // Command handlers - afx_msg int OnCreate(LPCREATESTRUCT lpcs); - afx_msg LONG OnLateInit(UINT, LONG); - //afx_msg LONG OnCloseMainDialog(UINT, LONG); - afx_msg void OnSize(UINT nType, int cx, int cy); - afx_msg void OnGetMinMaxInfo(MINMAXINFO* pMMI); - afx_msg void OnPaint(void); - //afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); - afx_msg void OnSetFocus(CWnd* pOldWnd); - afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - afx_msg BOOL OnQueryEndSession(void); - afx_msg void OnEndSession(BOOL bEnding); - afx_msg LRESULT OnFindDialogMessage(WPARAM wParam, LPARAM lParam); - //afx_msg LONG OnHelp(UINT wParam, LONG lParam); - afx_msg void OnFileNewArchive(void); - afx_msg void OnFileOpen(void); - afx_msg void OnFileOpenVolume(void); - afx_msg void OnUpdateFileOpenVolume(CCmdUI* pCmdUI); - afx_msg void OnFileReopen(void); - afx_msg void OnUpdateFileReopen(CCmdUI* pCmdUI); - afx_msg void OnFileSave(void); - afx_msg void OnUpdateFileSave(CCmdUI* pCmdUI); - afx_msg void OnFileClose(void); - afx_msg void OnUpdateFileClose(CCmdUI* pCmdUI); - afx_msg void OnFileArchiveInfo(void); - afx_msg void OnUpdateFileArchiveInfo(CCmdUI* pCmdUI); - afx_msg void OnFilePrint(void); - afx_msg void OnUpdateFilePrint(CCmdUI* pCmdUI); - afx_msg void OnFileExit(void); - afx_msg void OnEditCopy(void); - afx_msg void OnUpdateEditCopy(CCmdUI* pCmdUI); - afx_msg void OnEditPaste(void); - afx_msg void OnUpdateEditPaste(CCmdUI* pCmdUI); - afx_msg void OnEditPasteSpecial(void); - afx_msg void OnUpdateEditPasteSpecial(CCmdUI* pCmdUI); - afx_msg void OnEditFind(void); - afx_msg void OnUpdateEditFind(CCmdUI* pCmdUI); - afx_msg void OnEditSelectAll(void); - afx_msg void OnUpdateEditSelectAll(CCmdUI* pCmdUI); - afx_msg void OnEditInvertSelection(void); - afx_msg void OnUpdateEditInvertSelection(CCmdUI* pCmdUI); - afx_msg void OnEditPreferences(void); - afx_msg void OnEditSort(UINT id); - afx_msg void OnUpdateEditSort(CCmdUI* pCmdUI); - afx_msg void OnActionsView(void); - afx_msg void OnUpdateActionsView(CCmdUI* pCmdUI); - afx_msg void OnActionsOpenAsDisk(void); - afx_msg void OnUpdateActionsOpenAsDisk(CCmdUI* pCmdUI); - afx_msg void OnActionsAddFiles(void); - afx_msg void OnUpdateActionsAddFiles(CCmdUI* pCmdUI); - afx_msg void OnActionsAddDisks(void); - afx_msg void OnUpdateActionsAddDisks(CCmdUI* pCmdUI); - afx_msg void OnActionsCreateSubdir(void); - afx_msg void OnUpdateActionsCreateSubdir(CCmdUI* pCmdUI); - afx_msg void OnActionsExtract(void); - afx_msg void OnUpdateActionsExtract(CCmdUI* pCmdUI); - afx_msg void OnActionsTest(void); - afx_msg void OnUpdateActionsTest(CCmdUI* pCmdUI); - afx_msg void OnActionsDelete(void); - afx_msg void OnUpdateActionsDelete(CCmdUI* pCmdUI); - afx_msg void OnActionsRename(void); - afx_msg void OnUpdateActionsRename(CCmdUI* pCmdUI); - afx_msg void OnActionsEditComment(void); - afx_msg void OnUpdateActionsEditComment(CCmdUI* pCmdUI); - afx_msg void OnActionsEditProps(void); - afx_msg void OnUpdateActionsEditProps(CCmdUI* pCmdUI); - afx_msg void OnActionsRenameVolume(void); - afx_msg void OnUpdateActionsRenameVolume(CCmdUI* pCmdUI); - afx_msg void OnActionsRecompress(void); - afx_msg void OnUpdateActionsRecompress(CCmdUI* pCmdUI); - afx_msg void OnActionsConvDisk(void); - afx_msg void OnUpdateActionsConvDisk(CCmdUI* pCmdUI); - afx_msg void OnActionsConvFile(void); - afx_msg void OnUpdateActionsConvFile(CCmdUI* pCmdUI); - afx_msg void OnActionsConvToWav(void); - afx_msg void OnUpdateActionsConvToWav(CCmdUI* pCmdUI); - afx_msg void OnActionsConvFromWav(void); - afx_msg void OnUpdateActionsConvFromWav(CCmdUI* pCmdUI); - afx_msg void OnActionsImportBAS(void); - afx_msg void OnUpdateActionsImportBAS(CCmdUI* pCmdUI); - afx_msg void OnToolsDiskEdit(void); - afx_msg void OnToolsDiskConv(void); - afx_msg void OnToolsBulkDiskConv(void); - afx_msg void OnToolsSSTMerge(void); - afx_msg void OnToolsVolumeCopierVolume(void); - afx_msg void OnToolsVolumeCopierFile(void); - afx_msg void OnToolsEOLScanner(void); - afx_msg void OnToolsTwoImgProps(void); - afx_msg void OnToolsDiskImageCreator(void); - afx_msg void OnHelpContents(void); - afx_msg void OnHelpWebSite(void); - afx_msg void OnHelpOrdering(void); - afx_msg void OnHelpAbout(void); - afx_msg void OnRtClkDefault(void); + // Command handlers + afx_msg int OnCreate(LPCREATESTRUCT lpcs); + afx_msg LONG OnLateInit(UINT, LONG); + //afx_msg LONG OnCloseMainDialog(UINT, LONG); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnGetMinMaxInfo(MINMAXINFO* pMMI); + afx_msg void OnPaint(void); + //afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); + afx_msg void OnSetFocus(CWnd* pOldWnd); + afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg BOOL OnQueryEndSession(void); + afx_msg void OnEndSession(BOOL bEnding); + afx_msg LRESULT OnFindDialogMessage(WPARAM wParam, LPARAM lParam); + //afx_msg LONG OnHelp(UINT wParam, LONG lParam); + afx_msg void OnFileNewArchive(void); + afx_msg void OnFileOpen(void); + afx_msg void OnFileOpenVolume(void); + afx_msg void OnUpdateFileOpenVolume(CCmdUI* pCmdUI); + afx_msg void OnFileReopen(void); + afx_msg void OnUpdateFileReopen(CCmdUI* pCmdUI); + afx_msg void OnFileSave(void); + afx_msg void OnUpdateFileSave(CCmdUI* pCmdUI); + afx_msg void OnFileClose(void); + afx_msg void OnUpdateFileClose(CCmdUI* pCmdUI); + afx_msg void OnFileArchiveInfo(void); + afx_msg void OnUpdateFileArchiveInfo(CCmdUI* pCmdUI); + afx_msg void OnFilePrint(void); + afx_msg void OnUpdateFilePrint(CCmdUI* pCmdUI); + afx_msg void OnFileExit(void); + afx_msg void OnEditCopy(void); + afx_msg void OnUpdateEditCopy(CCmdUI* pCmdUI); + afx_msg void OnEditPaste(void); + afx_msg void OnUpdateEditPaste(CCmdUI* pCmdUI); + afx_msg void OnEditPasteSpecial(void); + afx_msg void OnUpdateEditPasteSpecial(CCmdUI* pCmdUI); + afx_msg void OnEditFind(void); + afx_msg void OnUpdateEditFind(CCmdUI* pCmdUI); + afx_msg void OnEditSelectAll(void); + afx_msg void OnUpdateEditSelectAll(CCmdUI* pCmdUI); + afx_msg void OnEditInvertSelection(void); + afx_msg void OnUpdateEditInvertSelection(CCmdUI* pCmdUI); + afx_msg void OnEditPreferences(void); + afx_msg void OnEditSort(UINT id); + afx_msg void OnUpdateEditSort(CCmdUI* pCmdUI); + afx_msg void OnActionsView(void); + afx_msg void OnUpdateActionsView(CCmdUI* pCmdUI); + afx_msg void OnActionsOpenAsDisk(void); + afx_msg void OnUpdateActionsOpenAsDisk(CCmdUI* pCmdUI); + afx_msg void OnActionsAddFiles(void); + afx_msg void OnUpdateActionsAddFiles(CCmdUI* pCmdUI); + afx_msg void OnActionsAddDisks(void); + afx_msg void OnUpdateActionsAddDisks(CCmdUI* pCmdUI); + afx_msg void OnActionsCreateSubdir(void); + afx_msg void OnUpdateActionsCreateSubdir(CCmdUI* pCmdUI); + afx_msg void OnActionsExtract(void); + afx_msg void OnUpdateActionsExtract(CCmdUI* pCmdUI); + afx_msg void OnActionsTest(void); + afx_msg void OnUpdateActionsTest(CCmdUI* pCmdUI); + afx_msg void OnActionsDelete(void); + afx_msg void OnUpdateActionsDelete(CCmdUI* pCmdUI); + afx_msg void OnActionsRename(void); + afx_msg void OnUpdateActionsRename(CCmdUI* pCmdUI); + afx_msg void OnActionsEditComment(void); + afx_msg void OnUpdateActionsEditComment(CCmdUI* pCmdUI); + afx_msg void OnActionsEditProps(void); + afx_msg void OnUpdateActionsEditProps(CCmdUI* pCmdUI); + afx_msg void OnActionsRenameVolume(void); + afx_msg void OnUpdateActionsRenameVolume(CCmdUI* pCmdUI); + afx_msg void OnActionsRecompress(void); + afx_msg void OnUpdateActionsRecompress(CCmdUI* pCmdUI); + afx_msg void OnActionsConvDisk(void); + afx_msg void OnUpdateActionsConvDisk(CCmdUI* pCmdUI); + afx_msg void OnActionsConvFile(void); + afx_msg void OnUpdateActionsConvFile(CCmdUI* pCmdUI); + afx_msg void OnActionsConvToWav(void); + afx_msg void OnUpdateActionsConvToWav(CCmdUI* pCmdUI); + afx_msg void OnActionsConvFromWav(void); + afx_msg void OnUpdateActionsConvFromWav(CCmdUI* pCmdUI); + afx_msg void OnActionsImportBAS(void); + afx_msg void OnUpdateActionsImportBAS(CCmdUI* pCmdUI); + afx_msg void OnToolsDiskEdit(void); + afx_msg void OnToolsDiskConv(void); + afx_msg void OnToolsBulkDiskConv(void); + afx_msg void OnToolsSSTMerge(void); + afx_msg void OnToolsVolumeCopierVolume(void); + afx_msg void OnToolsVolumeCopierFile(void); + afx_msg void OnToolsEOLScanner(void); + afx_msg void OnToolsTwoImgProps(void); + afx_msg void OnToolsDiskImageCreator(void); + afx_msg void OnHelpContents(void); + afx_msg void OnHelpWebSite(void); + afx_msg void OnHelpOrdering(void); + afx_msg void OnHelpAbout(void); + afx_msg void OnRtClkDefault(void); - void ProcessCommandLine(void); - void ResizeClientArea(void); - void DrawEmptyClientArea(CDC* pDC, const CRect& clientRect); - int TmpExtractAndOpen(GenericEntry* pEntry, int threadKind, - const char* modeStr); - int TmpExtractForExternal(GenericEntry* pEntry); - void DoOpenArchive(const char* pathName, const char* ext, - int filterIndex, bool readOnly); - int LoadArchive(const char* filename, const char* extension, - int filterIndex, bool readOnly, bool createFile); - int DoOpenVolume(CString drive, bool readOnly); - void SwitchContentList(GenericArchive* pOpenArchive); - void CloseArchiveWOControls(void); - void CloseArchive(void); - void SetCPTitle(const char* pathname, GenericArchive* pArchive); - void SetCPTitle(void); - GenericEntry* GetSelectedItem(ContentList* pContentList); - void HandleView(void); + void ProcessCommandLine(void); + void ResizeClientArea(void); + void DrawEmptyClientArea(CDC* pDC, const CRect& clientRect); + int TmpExtractAndOpen(GenericEntry* pEntry, int threadKind, + const char* modeStr); + int TmpExtractForExternal(GenericEntry* pEntry); + void DoOpenArchive(const char* pathName, const char* ext, + int filterIndex, bool readOnly); + int LoadArchive(const char* filename, const char* extension, + int filterIndex, bool readOnly, bool createFile); + int DoOpenVolume(CString drive, bool readOnly); + void SwitchContentList(GenericArchive* pOpenArchive); + void CloseArchiveWOControls(void); + void CloseArchive(void); + void SetCPTitle(const char* pathname, GenericArchive* pArchive); + void SetCPTitle(void); + GenericEntry* GetSelectedItem(ContentList* pContentList); + void HandleView(void); - void DeleteFileOnExit(const char* name); + void DeleteFileOnExit(const char* name); - void ReopenArchive(void); + void ReopenArchive(void); - /* some stuff from Actions.cpp */ - //int GetFileText(SelectionEntry* pSelEntry, ReformatHolder* pHolder, - // CString* pTitle); - void GetFilePart(const GenericEntry* pEntry, int whichThread, - ReformatHolder* pHolder) const; + /* some stuff from Actions.cpp */ + //int GetFileText(SelectionEntry* pSelEntry, ReformatHolder* pHolder, + // CString* pTitle); + void GetFilePart(const GenericEntry* pEntry, int whichThread, + ReformatHolder* pHolder) const; - void DoBulkExtract(SelectionSet* pSelSet, - const ExtractOptionsDialog* pExtOpts); - bool ExtractEntry(GenericEntry* pEntry, int thread, - ReformatHolder* pHolder, const ExtractOptionsDialog* pExtOpts, - bool* pOverwriteExisting, bool* pOvwrForAll); - int OpenOutputFile(CString* pOutputPath, const PathProposal& pathProp, - time_t arcFileModWhen, bool* pOverwriteExisting, bool* pOvwrForAll, - FILE** pFp); - bool DoBulkRecompress(ActionProgressDialog* pActionProgress, - SelectionSet* pSelSet, const RecompressOptionsDialog* pRecompOpts); - void CalcTotalSize(LONGLONG* pUncomp, LONGLONG* pComp) const; + void DoBulkExtract(SelectionSet* pSelSet, + const ExtractOptionsDialog* pExtOpts); + bool ExtractEntry(GenericEntry* pEntry, int thread, + ReformatHolder* pHolder, const ExtractOptionsDialog* pExtOpts, + bool* pOverwriteExisting, bool* pOvwrForAll); + int OpenOutputFile(CString* pOutputPath, const PathProposal& pathProp, + time_t arcFileModWhen, bool* pOverwriteExisting, bool* pOvwrForAll, + FILE** pFp); + bool DoBulkRecompress(ActionProgressDialog* pActionProgress, + SelectionSet* pSelSet, const RecompressOptionsDialog* pRecompOpts); + void CalcTotalSize(LONGLONG* pUncomp, LONGLONG* pComp) const; - /* some stuff from Clipboard.cpp */ - CString CreateFileList(SelectionSet* pSelSet); - static CString DblDblQuote(const char* str); - long GetClipboardContentLen(void); - HGLOBAL CreateFileCollection(SelectionSet* pSelSet); - CString CopyToCollection(GenericEntry* pEntry, void** pBuf, long* pBufLen); - void DoPaste(bool pasteJunkPaths); - CString ProcessClipboard(const void* vbuf, long bufLen, - bool pasteJunkPaths); - CString ProcessClipboardEntry(const FileCollectionEntry* pCollEnt, - const char* pathName, const unsigned char* buf, long remLen); + /* some stuff from Clipboard.cpp */ + CString CreateFileList(SelectionSet* pSelSet); + static CString DblDblQuote(const char* str); + long GetClipboardContentLen(void); + HGLOBAL CreateFileCollection(SelectionSet* pSelSet); + CString CopyToCollection(GenericEntry* pEntry, void** pBuf, long* pBufLen); + void DoPaste(bool pasteJunkPaths); + CString ProcessClipboard(const void* vbuf, long bufLen, + bool pasteJunkPaths); + CString ProcessClipboardEntry(const FileCollectionEntry* pCollEnt, + const char* pathName, const unsigned char* buf, long remLen); - /* some stuff from Tools.cpp */ - int DetermineImageSettings(int convertIdx, bool addGzip, - DiskImg::OuterFormat* pOuterFormat, DiskImg::FileFormat* pFileFormat, - DiskImg::PhysicalFormat* pPhysicalFormat, - DiskImg::SectorOrder* pSectorOrder); - void BulkConvertImage(const char* pathName, const char* targetDir, - const DiskConvertDialog& convDlg, CString* pErrMsg); - int SSTOpenImage(int seqNum, DiskImg* pDiskImg); - int SSTLoadData(int seqNum, DiskImg* pDiskImg, unsigned char* trackBuf, - long* pBadCount); - long SSTGetBufOffset(int track); - long SSTCountBadBytes(const unsigned char* sctBuf, int count); - void SSTProcessTrackData(unsigned char* trackBuf); - void VolumeCopier(bool openFile); - bool EditTwoImgProps(const char* fileName); + /* some stuff from Tools.cpp */ + int DetermineImageSettings(int convertIdx, bool addGzip, + DiskImg::OuterFormat* pOuterFormat, DiskImg::FileFormat* pFileFormat, + DiskImg::PhysicalFormat* pPhysicalFormat, + DiskImg::SectorOrder* pSectorOrder); + void BulkConvertImage(const char* pathName, const char* targetDir, + const DiskConvertDialog& convDlg, CString* pErrMsg); + int SSTOpenImage(int seqNum, DiskImg* pDiskImg); + int SSTLoadData(int seqNum, DiskImg* pDiskImg, unsigned char* trackBuf, + long* pBadCount); + long SSTGetBufOffset(int track); + long SSTCountBadBytes(const unsigned char* sctBuf, int count); + void SSTProcessTrackData(unsigned char* trackBuf); + void VolumeCopier(bool openFile); + bool EditTwoImgProps(const char* fileName); - void PrintListing(const ContentList* pContentList); + void PrintListing(const ContentList* pContentList); - // set when one of the tools modifies the file we have open - bool fNeedReopen; + // set when one of the tools modifies the file we have open + bool fNeedReopen; - CToolBar fToolBar; - CStatusBar fStatusBar; + CToolBar fToolBar; + CStatusBar fStatusBar; - // currently-open archive, if any - GenericArchive* fpOpenArchive; - // name of open archive, for display only -- if this is a temporary - // file launched from another instance of CP, this won't be the name - // of an actual file on disk. - CString fOpenArchivePathName; // for display only + // currently-open archive, if any + GenericArchive* fpOpenArchive; + // name of open archive, for display only -- if this is a temporary + // file launched from another instance of CP, this won't be the name + // of an actual file on disk. + CString fOpenArchivePathName; // for display only - // archive viewer, open when file is open - // NOTE: make a super-class for a tree-structured display or other - // kinds of display, so we can avoid the if/then/else. Rename - // ContentList to DetailList or FlatList or something. - ContentList* fpContentList; + // archive viewer, open when file is open + // NOTE: make a super-class for a tree-structured display or other + // kinds of display, so we can avoid the if/then/else. Rename + // ContentList to DetailList or FlatList or something. + ContentList* fpContentList; - // currently selected set of goodies; used when viewing, extracting, etc. - //SelectionSet* fpSelSet; + // currently selected set of goodies; used when viewing, extracting, etc. + //SelectionSet* fpSelSet; - // action progress meter, if any - ActionProgressDialog* fpActionProgress; + // action progress meter, if any + ActionProgressDialog* fpActionProgress; - // progress counter meter, if any - ProgressCounterDialog* fpProgressCounter; + // progress counter meter, if any + ProgressCounterDialog* fpProgressCounter; - // modeless standard "find" dialog - CFindReplaceDialog* fpFindDialog; - CString fFindLastStr; - bool fFindDown; - bool fFindMatchCase; - bool fFindMatchWholeWord; + // modeless standard "find" dialog + CFindReplaceDialog* fpFindDialog; + CString fFindLastStr; + bool fFindDown; + bool fFindMatchCase; + bool fFindMatchWholeWord; - // our preferences - Preferences fPreferences; + // our preferences + Preferences fPreferences; - /* - * Manage a list of files that must be deleted before we exit. - */ - class DeleteList { - private: - class DeleteListNode { - public: - DeleteListNode(const CString& name) : fName(name), - fPrev(nil), fNext(nil) {} - ~DeleteListNode(void) {} + /* + * Manage a list of files that must be deleted before we exit. + */ + class DeleteList { + private: + class DeleteListNode { + public: + DeleteListNode(const CString& name) : fName(name), + fPrev(nil), fNext(nil) {} + ~DeleteListNode(void) {} - DeleteListNode* fPrev; - DeleteListNode* fNext; - CString fName; - }; + DeleteListNode* fPrev; + DeleteListNode* fNext; + CString fName; + }; - public: - DeleteList(void) { fHead = nil; } - ~DeleteList(void) { - WMSG1("Processing DeleteList (head=0x%08lx)\n", fHead); - DeleteListNode* pNode = fHead; - DeleteListNode* pNext; + public: + DeleteList(void) { fHead = nil; } + ~DeleteList(void) { + WMSG1("Processing DeleteList (head=0x%08lx)\n", fHead); + DeleteListNode* pNode = fHead; + DeleteListNode* pNext; - while (pNode != nil) { - pNext = pNode->fNext; - if (unlink(pNode->fName) != 0) { - WMSG2(" WARNING: delete of '%s' failed, err=%d\n", - pNode->fName, errno); - } else { - WMSG1(" Deleted '%s'\n", pNode->fName); - } - delete pNode; - pNode = pNext; - } - WMSG0("Processing DeleteList completed\n"); - } + while (pNode != nil) { + pNext = pNode->fNext; + if (unlink(pNode->fName) != 0) { + WMSG2(" WARNING: delete of '%s' failed, err=%d\n", + pNode->fName, errno); + } else { + WMSG1(" Deleted '%s'\n", pNode->fName); + } + delete pNode; + pNode = pNext; + } + WMSG0("Processing DeleteList completed\n"); + } - void Add(const CString& name) { - DeleteListNode* pNode = new DeleteListNode(name); - if (fHead != nil) { - fHead->fPrev = pNode; - pNode->fNext = fHead; - } - fHead = pNode; - WMSG1("Delete-on-exit '%s'\n", (LPCTSTR) name); - } + void Add(const CString& name) { + DeleteListNode* pNode = new DeleteListNode(name); + if (fHead != nil) { + fHead->fPrev = pNode; + pNode->fNext = fHead; + } + fHead = pNode; + WMSG1("Delete-on-exit '%s'\n", (LPCTSTR) name); + } - DeleteListNode* fHead; - }; - DeleteList fDeleteList; + DeleteListNode* fHead; + }; + DeleteList fDeleteList; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #define GET_MAIN_WINDOW() ((MainWindow*)::AfxGetMainWnd()) #define SET_PROGRESS_BEGIN() ((MainWindow*)::AfxGetMainWnd())->SetProgressBegin() #define SET_PROGRESS_UPDATE(perc) \ - ((MainWindow*)::AfxGetMainWnd())->SetProgressUpdate(perc, nil, nil) + ((MainWindow*)::AfxGetMainWnd())->SetProgressUpdate(perc, nil, nil) #define SET_PROGRESS_UPDATE2(perc, oldName, newName) \ - ((MainWindow*)::AfxGetMainWnd())->SetProgressUpdate(perc, oldName, newName) + ((MainWindow*)::AfxGetMainWnd())->SetProgressUpdate(perc, oldName, newName) #define SET_PROGRESS_END() ((MainWindow*)::AfxGetMainWnd())->SetProgressEnd() #define SET_PROGRESS_COUNTER(val) \ - ((MainWindow*)::AfxGetMainWnd())->SetProgressCounter(nil, val) + ((MainWindow*)::AfxGetMainWnd())->SetProgressCounter(nil, val) #define SET_PROGRESS_COUNTER_2(fmt, val) \ - ((MainWindow*)::AfxGetMainWnd())->SetProgressCounter(fmt, val) + ((MainWindow*)::AfxGetMainWnd())->SetProgressCounter(fmt, val) #define GET_PREFERENCES() ((MainWindow*)::AfxGetMainWnd())->GetPreferences() #define GET_PREFERENCES_WR() ((MainWindow*)::AfxGetMainWnd())->GetPreferencesWr() diff --git a/app/MyApp.cpp b/app/MyApp.cpp index 4da463a..48fc652 100644 --- a/app/MyApp.cpp +++ b/app/MyApp.cpp @@ -28,45 +28,45 @@ int gPid = -1; */ MyApp::MyApp(LPCTSTR lpszAppName) : CWinApp(lpszAppName) { - const int kStaleLog = 8 * 60 * 60; + const int kStaleLog = 8 * 60 * 60; - //fclose(fopen("c:\\cp-myapp.txt", "w")); + //fclose(fopen("c:\\cp-myapp.txt", "w")); - time_t now; - now = time(nil); + time_t now; + now = time(nil); #ifdef _DEBUG_LOG - PathName debugPath(kDebugLog); - time_t when = debugPath.GetModWhen(); - if (when > 0 && now - when > kStaleLog) { - /* log file is more than 8 hours old, remove it */ - /* [consider opening it and truncating with chsize() instead, so we - don't hose somebody's custom access permissions. ++ATM 20041015] */ - unlink(kDebugLog); - } - gLog = fopen(kDebugLog, "a"); - if (gLog == nil) - abort(); - ::setvbuf(gLog, nil, _IONBF, 0); + PathName debugPath(kDebugLog); + time_t when = debugPath.GetModWhen(); + if (when > 0 && now - when > kStaleLog) { + /* log file is more than 8 hours old, remove it */ + /* [consider opening it and truncating with chsize() instead, so we + don't hose somebody's custom access permissions. ++ATM 20041015] */ + unlink(kDebugLog); + } + gLog = fopen(kDebugLog, "a"); + if (gLog == nil) + abort(); + ::setvbuf(gLog, nil, _IONBF, 0); - gPid = ::getpid(); - fprintf(gLog, "\n"); - if (when > 0) { - WMSG2("(Log file was %.3f hours old; logs are reset after %.3f)\n", - (now - when) / 3600.0, kStaleLog / 3600.0); - } + gPid = ::getpid(); + fprintf(gLog, "\n"); + if (when > 0) { + WMSG2("(Log file was %.3f hours old; logs are reset after %.3f)\n", + (now - when) / 3600.0, kStaleLog / 3600.0); + } #endif - WMSG5("CiderPress v%d.%d.%d%s started at %.24s\n", - kAppMajorVersion, kAppMinorVersion, kAppBugVersion, - kAppDevString, ctime(&now)); + WMSG5("CiderPress v%d.%d.%d%s started at %.24s\n", + kAppMajorVersion, kAppMinorVersion, kAppBugVersion, + kAppDevString, ctime(&now)); - int tmpDbgFlag; - // enable memory leak detection + int tmpDbgFlag; + // enable memory leak detection tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF; _CrtSetDbgFlag(tmpDbgFlag); - WMSG0("Leak detection enabled\n"); + WMSG0("Leak detection enabled\n"); } /* @@ -74,13 +74,13 @@ MyApp::MyApp(LPCTSTR lpszAppName) : CWinApp(lpszAppName) */ MyApp::~MyApp(void) { - DiskArchive::AppCleanup(); - NiftyList::AppCleanup(); + DiskArchive::AppCleanup(); + NiftyList::AppCleanup(); - WMSG0("SHUTTING DOWN\n\n"); + WMSG0("SHUTTING DOWN\n\n"); #ifdef _DEBUG_LOG - if (gLog != nil) - fclose(gLog); + if (gLog != nil) + fclose(gLog); #endif } @@ -93,87 +93,87 @@ MyApp::~MyApp(void) BOOL MyApp::InitInstance(void) { - //fclose(fopen("c:\\cp-initinstance.txt", "w")); + //fclose(fopen("c:\\cp-initinstance.txt", "w")); - //_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); + //_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG); - m_pMainWnd = new MainWindow; - m_pMainWnd->ShowWindow(m_nCmdShow); - m_pMainWnd->UpdateWindow(); + m_pMainWnd = new MainWindow; + m_pMainWnd->ShowWindow(m_nCmdShow); + m_pMainWnd->UpdateWindow(); - WMSG0("Happily in InitInstance!\n"); + WMSG0("Happily in InitInstance!\n"); - /* find our .EXE file */ - //HMODULE hModule = ::GetModuleHandle(NULL); - char buf[MAX_PATH]; - if (::GetModuleFileName(nil /*hModule*/, buf, sizeof(buf)) != 0) { - WMSG1("Module name is '%s'\n", buf); - fExeFileName = buf; + /* find our .EXE file */ + //HMODULE hModule = ::GetModuleHandle(NULL); + char buf[MAX_PATH]; + if (::GetModuleFileName(nil /*hModule*/, buf, sizeof(buf)) != 0) { + WMSG1("Module name is '%s'\n", buf); + fExeFileName = buf; - char* cp = strrchr(buf, '\\'); - if (cp == nil) - fExeBaseName = ""; - else - fExeBaseName = fExeFileName.Left(cp - buf +1); - } else { - WMSG1("BIG problem: GetModuleFileName failed (err=%ld)\n", - ::GetLastError()); - } + char* cp = strrchr(buf, '\\'); + if (cp == nil) + fExeBaseName = ""; + else + fExeBaseName = fExeFileName.Left(cp - buf +1); + } else { + WMSG1("BIG problem: GetModuleFileName failed (err=%ld)\n", + ::GetLastError()); + } - LogModuleLocation("riched.dll"); - LogModuleLocation("riched20.dll"); - LogModuleLocation("riched32.dll"); + LogModuleLocation("riched.dll"); + LogModuleLocation("riched20.dll"); + LogModuleLocation("riched32.dll"); #if 0 - /* find our .INI file by tweaking the EXE path */ - char* cp = strrchr(buf, '\\'); - if (cp == nil) - cp = buf; - else - cp++; - if (cp + ::lstrlen(_T("CiderPress.INI")) >= buf+sizeof(buf)) - return FALSE; - ::lstrcpy(cp, _T("CiderPress.INI")); + /* find our .INI file by tweaking the EXE path */ + char* cp = strrchr(buf, '\\'); + if (cp == nil) + cp = buf; + else + cp++; + if (cp + ::lstrlen(_T("CiderPress.INI")) >= buf+sizeof(buf)) + return FALSE; + ::lstrcpy(cp, _T("CiderPress.INI")); - free((void*)m_pszProfileName); - m_pszProfileName = strdup(buf); - WMSG1("Profile name is '%s'\n", m_pszProfileName); + free((void*)m_pszProfileName); + m_pszProfileName = strdup(buf); + WMSG1("Profile name is '%s'\n", m_pszProfileName); - if (!WriteProfileString("SectionOne", "MyEntry", "test")) - WMSG0("WriteProfileString failed\n"); + if (!WriteProfileString("SectionOne", "MyEntry", "test")) + WMSG0("WriteProfileString failed\n"); #endif - SetRegistryKey(fRegistry.GetAppRegistryKey()); + SetRegistryKey(fRegistry.GetAppRegistryKey()); - //WMSG1("Registry key is '%s'\n", m_pszRegistryKey); - //WMSG1("Profile name is '%s'\n", m_pszProfileName); - WMSG1("Short command line is '%s'\n", m_lpCmdLine); - //WMSG1("CP app name is '%s'\n", m_pszAppName); - //WMSG1("CP exe name is '%s'\n", m_pszExeName); - WMSG1("CP help file is '%s'\n", m_pszHelpFilePath); - WMSG1("Command line is '%s'\n", ::GetCommandLine()); + //WMSG1("Registry key is '%s'\n", m_pszRegistryKey); + //WMSG1("Profile name is '%s'\n", m_pszProfileName); + WMSG1("Short command line is '%s'\n", m_lpCmdLine); + //WMSG1("CP app name is '%s'\n", m_pszAppName); + //WMSG1("CP exe name is '%s'\n", m_pszExeName); + WMSG1("CP help file is '%s'\n", m_pszHelpFilePath); + WMSG1("Command line is '%s'\n", ::GetCommandLine()); - //if (!WriteProfileString("SectionOne", "MyEntry", "test")) - // WMSG0("WriteProfileString failed\n"); + //if (!WriteProfileString("SectionOne", "MyEntry", "test")) + // WMSG0("WriteProfileString failed\n"); - /* - * If we're installing or uninstalling, do what we need to and then - * bail immediately. This will hemorrhage memory, but I'm sure the - * incredibly robust Windows environment will take it in stride. - */ - if (strcmp(m_lpCmdLine, _T("-install")) == 0) { - WMSG0("Invoked with INSTALL flag\n"); - fRegistry.OneTimeInstall(); - exit(0); - } else if (strcmp(m_lpCmdLine, _T("-uninstall")) == 0) { - WMSG0("Invoked with UNINSTALL flag\n"); - fRegistry.OneTimeUninstall(); - exit(1); // tell DeployMaster to continue with uninstall - } + /* + * If we're installing or uninstalling, do what we need to and then + * bail immediately. This will hemorrhage memory, but I'm sure the + * incredibly robust Windows environment will take it in stride. + */ + if (strcmp(m_lpCmdLine, _T("-install")) == 0) { + WMSG0("Invoked with INSTALL flag\n"); + fRegistry.OneTimeInstall(); + exit(0); + } else if (strcmp(m_lpCmdLine, _T("-uninstall")) == 0) { + WMSG0("Invoked with UNINSTALL flag\n"); + fRegistry.OneTimeUninstall(); + exit(1); // tell DeployMaster to continue with uninstall + } - fRegistry.FixBasicSettings(); + fRegistry.FixBasicSettings(); - return TRUE; + return TRUE; } /* @@ -184,17 +184,17 @@ MyApp::InitInstance(void) void MyApp::LogModuleLocation(const char* name) { - HMODULE hModule; - char fileNameBuf[256]; - hModule = ::GetModuleHandle(name); - if (hModule != nil && - ::GetModuleFileName(hModule, fileNameBuf, sizeof(fileNameBuf)) != 0) - { - // GetModuleHandle does not increase ref count, so no need to release - WMSG2("Module '%s' loaded from '%s'\n", name, fileNameBuf); - } else { - WMSG1("Module '%s' not loaded\n", name); - } + HMODULE hModule; + char fileNameBuf[256]; + hModule = ::GetModuleHandle(name); + if (hModule != nil && + ::GetModuleFileName(hModule, fileNameBuf, sizeof(fileNameBuf)) != 0) + { + // GetModuleHandle does not increase ref count, so no need to release + WMSG2("Module '%s' loaded from '%s'\n", name, fileNameBuf); + } else { + WMSG1("Module '%s' not loaded\n", name); + } } /* @@ -203,19 +203,19 @@ MyApp::LogModuleLocation(const char* name) BOOL MyApp::OnIdle(LONG lCount) { - BOOL bMore = CWinApp::OnIdle(lCount); + BOOL bMore = CWinApp::OnIdle(lCount); - //if (lCount == 0) { - // WMSG1("IDLE lcount=%d\n", lCount); - //} + //if (lCount == 0) { + // WMSG1("IDLE lcount=%d\n", lCount); + //} - /* - * If MFC is done, we take a swing. - */ - if (bMore == false) { - /* downcast */ - ((MainWindow*)m_pMainWnd)->DoIdle(); - } + /* + * If MFC is done, we take a swing. + */ + if (bMore == false) { + /* downcast */ + ((MainWindow*)m_pMainWnd)->DoIdle(); + } - return bMore; + return bMore; } diff --git a/app/MyApp.h b/app/MyApp.h index b12ec90..2191da1 100644 --- a/app/MyApp.h +++ b/app/MyApp.h @@ -12,15 +12,15 @@ #include "Registry.h" #if defined(_DEBUG_LOG) -//#define kDebugLog "C:\\test\\cplog.txt" -#define kDebugLog "C:\\cplog.txt" +//#define kDebugLog "C:\\test\\cplog.txt" +#define kDebugLog "C:\\cplog.txt" #endif /* CiderPress version numbers */ -#define kAppMajorVersion 3 -#define kAppMinorVersion 0 -#define kAppBugVersion 1 -#define kAppDevString "" +#define kAppMajorVersion 3 +#define kAppMinorVersion 0 +#define kAppBugVersion 1 +#define kAppDevString "" /* * Windows application object. @@ -28,23 +28,23 @@ class MyApp: public CWinApp { public: - MyApp(LPCTSTR lpszAppName = NULL); - virtual ~MyApp(void); + MyApp(LPCTSTR lpszAppName = NULL); + virtual ~MyApp(void); - MyRegistry fRegistry; + MyRegistry fRegistry; - const char* GetExeFileName(void) const { return fExeFileName; } - const char* GetExeBaseName(void) const { return fExeBaseName; } + const char* GetExeFileName(void) const { return fExeFileName; } + const char* GetExeBaseName(void) const { return fExeBaseName; } private: - // Overridden functions - virtual BOOL InitInstance(void); - virtual BOOL OnIdle(LONG lCount); + // Overridden functions + virtual BOOL InitInstance(void); + virtual BOOL OnIdle(LONG lCount); - void LogModuleLocation(const char* name); + void LogModuleLocation(const char* name); - CString fExeFileName; - CString fExeBaseName; + CString fExeFileName; + CString fExeBaseName; }; extern MyApp gMyApp; diff --git a/app/NewDiskSize.cpp b/app/NewDiskSize.cpp index 9920c99..6d27090 100644 --- a/app/NewDiskSize.cpp +++ b/app/NewDiskSize.cpp @@ -16,14 +16,14 @@ * These must be in ascending order. */ /*static*/ const NewDiskSize::RadioCtrlMap NewDiskSize::kCtrlMap[] = { - { IDC_CONVDISK_140K, 280 }, - { IDC_CONVDISK_800K, 1600 }, - { IDC_CONVDISK_1440K, 2880 }, - { IDC_CONVDISK_5MB, 10240 }, - { IDC_CONVDISK_16MB, 32768 }, - { IDC_CONVDISK_20MB, 40960 }, - { IDC_CONVDISK_32MB, 65535 }, - { IDC_CONVDISK_SPECIFY, kSpecified }, + { IDC_CONVDISK_140K, 280 }, + { IDC_CONVDISK_800K, 1600 }, + { IDC_CONVDISK_1440K, 2880 }, + { IDC_CONVDISK_5MB, 10240 }, + { IDC_CONVDISK_16MB, 32768 }, + { IDC_CONVDISK_20MB, 40960 }, + { IDC_CONVDISK_32MB, 65535 }, + { IDC_CONVDISK_SPECIFY, kSpecified }, }; static const kEditBoxID = IDC_CONVDISK_SPECIFY_EDIT; @@ -33,7 +33,7 @@ static const kEditBoxID = IDC_CONVDISK_SPECIFY_EDIT; /*static*/ unsigned int NewDiskSize::GetNumSizeEntries(void) { - return NELEM(kCtrlMap); + return NELEM(kCtrlMap); } /* @@ -42,20 +42,20 @@ NewDiskSize::GetNumSizeEntries(void) /*static*/ long NewDiskSize::GetDiskSizeByIndex(int idx) { - ASSERT(idx >= 0 && idx < NELEM(kCtrlMap)); - return kCtrlMap[idx].blocks; + ASSERT(idx >= 0 && idx < NELEM(kCtrlMap)); + return kCtrlMap[idx].blocks; } /*static*/ void NewDiskSize::EnableButtons(CDialog* pDialog, BOOL state /*=true*/) { - CWnd* pWnd; + CWnd* pWnd; - for (int i = 0; i < NELEM(kCtrlMap); i++) { - pWnd = pDialog->GetDlgItem(kCtrlMap[i].ctrlID); - if (pWnd != nil) - pWnd->EnableWindow(state); - } + for (int i = 0; i < NELEM(kCtrlMap); i++) { + pWnd = pDialog->GetDlgItem(kCtrlMap[i].ctrlID); + if (pWnd != nil) + pWnd->EnableWindow(state); + } } /* @@ -73,47 +73,47 @@ NewDiskSize::EnableButtons(CDialog* pDialog, BOOL state /*=true*/) */ /*static*/ void NewDiskSize::EnableButtons_ProDOS(CDialog* pDialog, long totalBlocks, - long blocksUsed) + long blocksUsed) { - CButton* pButton; - long usedWithoutBitmap = blocksUsed - GetNumBitmapBlocks_ProDOS(totalBlocks); - bool first = true; + CButton* pButton; + long usedWithoutBitmap = blocksUsed - GetNumBitmapBlocks_ProDOS(totalBlocks); + bool first = true; - WMSG3("EnableButtons_ProDOS total=%ld used=%ld usedw/o=%ld\n", - totalBlocks, blocksUsed, usedWithoutBitmap); + WMSG3("EnableButtons_ProDOS total=%ld used=%ld usedw/o=%ld\n", + totalBlocks, blocksUsed, usedWithoutBitmap); - for (int i = 0; i < NELEM(kCtrlMap); i++) { - pButton = (CButton*) pDialog->GetDlgItem(kCtrlMap[i].ctrlID); - if (pButton == nil) { - WMSG1("WARNING: couldn't find ctrlID %d\n", kCtrlMap[i].ctrlID); - continue; - } + for (int i = 0; i < NELEM(kCtrlMap); i++) { + pButton = (CButton*) pDialog->GetDlgItem(kCtrlMap[i].ctrlID); + if (pButton == nil) { + WMSG1("WARNING: couldn't find ctrlID %d\n", kCtrlMap[i].ctrlID); + continue; + } - if (kCtrlMap[i].blocks == kSpecified) { - pButton->SetCheck(BST_UNCHECKED); - pButton->EnableWindow(TRUE); - CWnd* pWnd = pDialog->GetDlgItem(kEditBoxID); - pWnd->EnableWindow(FALSE); - continue; - } + if (kCtrlMap[i].blocks == kSpecified) { + pButton->SetCheck(BST_UNCHECKED); + pButton->EnableWindow(TRUE); + CWnd* pWnd = pDialog->GetDlgItem(kEditBoxID); + pWnd->EnableWindow(FALSE); + continue; + } - if (usedWithoutBitmap + GetNumBitmapBlocks_ProDOS(kCtrlMap[i].blocks) <= - kCtrlMap[i].blocks) - { - pButton->EnableWindow(TRUE); - if (first) { - pButton->SetCheck(BST_CHECKED); - first = false; - } else { - pButton->SetCheck(BST_UNCHECKED); - } - } else { - pButton->EnableWindow(FALSE); - pButton->SetCheck(BST_UNCHECKED); - } - } + if (usedWithoutBitmap + GetNumBitmapBlocks_ProDOS(kCtrlMap[i].blocks) <= + kCtrlMap[i].blocks) + { + pButton->EnableWindow(TRUE); + if (first) { + pButton->SetCheck(BST_CHECKED); + first = false; + } else { + pButton->SetCheck(BST_UNCHECKED); + } + } else { + pButton->EnableWindow(FALSE); + pButton->SetCheck(BST_UNCHECKED); + } + } - UpdateSpecifyEdit(pDialog); + UpdateSpecifyEdit(pDialog); } /* @@ -121,10 +121,10 @@ NewDiskSize::EnableButtons_ProDOS(CDialog* pDialog, long totalBlocks, */ /*static*/long NewDiskSize::GetNumBitmapBlocks_ProDOS(long totalBlocks) { - ASSERT(totalBlocks > 0); - const int kBitsPerBlock = 512 * 8; - int numBlocks = (totalBlocks + kBitsPerBlock-1) / kBitsPerBlock; - return numBlocks; + ASSERT(totalBlocks > 0); + const int kBitsPerBlock = 512 * 8; + int numBlocks = (totalBlocks + kBitsPerBlock-1) / kBitsPerBlock; + return numBlocks; } @@ -134,33 +134,33 @@ NewDiskSize::GetNumBitmapBlocks_ProDOS(long totalBlocks) { /*static*/ void NewDiskSize::UpdateSpecifyEdit(CDialog* pDialog) { - CEdit* pEdit = (CEdit*) pDialog->GetDlgItem(kEditBoxID); - int i; + CEdit* pEdit = (CEdit*) pDialog->GetDlgItem(kEditBoxID); + int i; - if (pEdit == nil) { - ASSERT(false); - return; - } + if (pEdit == nil) { + ASSERT(false); + return; + } - for (i = 0; i < NELEM(kCtrlMap); i++) { - CButton* pButton = (CButton*) pDialog->GetDlgItem(kCtrlMap[i].ctrlID); - if (pButton == nil) { - WMSG1("WARNING: couldn't find ctrlID %d\n", kCtrlMap[i].ctrlID); - continue; - } + for (i = 0; i < NELEM(kCtrlMap); i++) { + CButton* pButton = (CButton*) pDialog->GetDlgItem(kCtrlMap[i].ctrlID); + if (pButton == nil) { + WMSG1("WARNING: couldn't find ctrlID %d\n", kCtrlMap[i].ctrlID); + continue; + } - if (pButton->GetCheck() == BST_CHECKED) { - if (kCtrlMap[i].blocks == kSpecified) - return; - break; - } - } - if (i == NELEM(kCtrlMap)) { - WMSG0("WARNING: couldn't find a checked radio button\n"); - return; - } + if (pButton->GetCheck() == BST_CHECKED) { + if (kCtrlMap[i].blocks == kSpecified) + return; + break; + } + } + if (i == NELEM(kCtrlMap)) { + WMSG0("WARNING: couldn't find a checked radio button\n"); + return; + } - CString fmt; - fmt.Format("%ld", kCtrlMap[i].blocks); - pEdit->SetWindowText(fmt); + CString fmt; + fmt.Format("%ld", kCtrlMap[i].blocks); + pEdit->SetWindowText(fmt); } diff --git a/app/NewDiskSize.h b/app/NewDiskSize.h index dd83169..5b59869 100644 --- a/app/NewDiskSize.h +++ b/app/NewDiskSize.h @@ -14,25 +14,25 @@ */ class NewDiskSize { public: - NewDiskSize(void) { ASSERT(false); } + NewDiskSize(void) { ASSERT(false); } - static unsigned int GetNumSizeEntries(void); - static long GetDiskSizeByIndex(int idx); - enum { kSpecified = -1 }; + static unsigned int GetNumSizeEntries(void); + static long GetDiskSizeByIndex(int idx); + enum { kSpecified = -1 }; - static void EnableButtons(CDialog* pDialog, BOOL state = true); - static void EnableButtons_ProDOS(CDialog* pDialog, long totalBlocks, - long blocksUsed); - static long GetNumBitmapBlocks_ProDOS(long totalBlocks); - static void UpdateSpecifyEdit(CDialog* pDialog); + static void EnableButtons(CDialog* pDialog, BOOL state = true); + static void EnableButtons_ProDOS(CDialog* pDialog, long totalBlocks, + long blocksUsed); + static long GetNumBitmapBlocks_ProDOS(long totalBlocks); + static void UpdateSpecifyEdit(CDialog* pDialog); private: - typedef struct { - int ctrlID; - long blocks; - } RadioCtrlMap; + typedef struct { + int ctrlID; + long blocks; + } RadioCtrlMap; - static const RadioCtrlMap kCtrlMap[]; + static const RadioCtrlMap kCtrlMap[]; }; #endif /*__NEWDISKSIZE__*/ \ No newline at end of file diff --git a/app/NewFolderDialog.cpp b/app/NewFolderDialog.cpp index af050e4..c52de47 100644 --- a/app/NewFolderDialog.cpp +++ b/app/NewFolderDialog.cpp @@ -10,7 +10,7 @@ #include "NewFolderDialog.h" BEGIN_MESSAGE_MAP(NewFolderDialog, CDialog) - ON_WM_HELPINFO() + ON_WM_HELPINFO() END_MESSAGE_MAP() /* @@ -31,45 +31,45 @@ END_MESSAGE_MAP() void NewFolderDialog::DoDataExchange(CDataExchange* pDX) { - if (!pDX->m_bSaveAndValidate) - DDX_Text(pDX, IDC_NEWFOLDER_CURDIR, fCurrentFolder); + if (!pDX->m_bSaveAndValidate) + DDX_Text(pDX, IDC_NEWFOLDER_CURDIR, fCurrentFolder); - DDX_Text(pDX, IDC_NEWFOLDER_NAME, fNewFolder); + DDX_Text(pDX, IDC_NEWFOLDER_NAME, fNewFolder); - /* validate the new folder by creating it */ - if (pDX->m_bSaveAndValidate) { - if (fNewFolder.IsEmpty()) { - MessageBox("No name entered, not creating new folder.", - "CiderPress", MB_OK); - // fall out of DoModal with fFolderCreated==false - } else if (fNewFolder.Find('\\') >= 0 || - fNewFolder.Find('/') >= 0) - { - MessageBox("Folder names may not contain '/' or '\\'.", - "CiderPress", MB_OK); - pDX->Fail(); - } else { - fNewFullPath = fCurrentFolder; - if (fNewFullPath.Right(1) != "\\") - fNewFullPath += "\\"; - fNewFullPath += fNewFolder; - WMSG1("CREATING '%s'\n", fNewFullPath); - if (!::CreateDirectory(fNewFullPath, nil)) { - /* show the sometimes-bizarre Windows error string */ - CString msg, errStr, failed; - DWORD dwerr = ::GetLastError(); - GetWin32ErrorString(dwerr, &errStr); - msg.Format("Unable to create folder '%s': %s", - fNewFolder, errStr); - failed.LoadString(IDS_FAILED); - MessageBox(msg, failed, MB_OK | MB_ICONERROR); - pDX->Fail(); - } else { - /* success! */ - fFolderCreated = true; - } - } - } + /* validate the new folder by creating it */ + if (pDX->m_bSaveAndValidate) { + if (fNewFolder.IsEmpty()) { + MessageBox("No name entered, not creating new folder.", + "CiderPress", MB_OK); + // fall out of DoModal with fFolderCreated==false + } else if (fNewFolder.Find('\\') >= 0 || + fNewFolder.Find('/') >= 0) + { + MessageBox("Folder names may not contain '/' or '\\'.", + "CiderPress", MB_OK); + pDX->Fail(); + } else { + fNewFullPath = fCurrentFolder; + if (fNewFullPath.Right(1) != "\\") + fNewFullPath += "\\"; + fNewFullPath += fNewFolder; + WMSG1("CREATING '%s'\n", fNewFullPath); + if (!::CreateDirectory(fNewFullPath, nil)) { + /* show the sometimes-bizarre Windows error string */ + CString msg, errStr, failed; + DWORD dwerr = ::GetLastError(); + GetWin32ErrorString(dwerr, &errStr); + msg.Format("Unable to create folder '%s': %s", + fNewFolder, errStr); + failed.LoadString(IDS_FAILED); + MessageBox(msg, failed, MB_OK | MB_ICONERROR); + pDX->Fail(); + } else { + /* success! */ + fFolderCreated = true; + } + } + } } @@ -79,6 +79,6 @@ NewFolderDialog::DoDataExchange(CDataExchange* pDX) BOOL NewFolderDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } diff --git a/app/NewFolderDialog.h b/app/NewFolderDialog.h index 4c24535..3da0f0e 100644 --- a/app/NewFolderDialog.h +++ b/app/NewFolderDialog.h @@ -19,32 +19,32 @@ */ class NewFolderDialog : public CDialog { public: - NewFolderDialog(CWnd* pParent = NULL) : CDialog(IDD_NEWFOLDER, pParent) { - fCurrentFolder = ""; - fNewFolder = ""; - fFolderCreated = false; - } - virtual ~NewFolderDialog(void) {} + NewFolderDialog(CWnd* pParent = NULL) : CDialog(IDD_NEWFOLDER, pParent) { + fCurrentFolder = ""; + fNewFolder = ""; + fFolderCreated = false; + } + virtual ~NewFolderDialog(void) {} - bool GetFolderCreated(void) const { return fFolderCreated; } + bool GetFolderCreated(void) const { return fFolderCreated; } - // set to CWD before calling DoModal - CString fCurrentFolder; + // set to CWD before calling DoModal + CString fCurrentFolder; - // filename (NOT pathname) of new folder (DDXed in edit ctrl) - CString fNewFolder; + // filename (NOT pathname) of new folder (DDXed in edit ctrl) + CString fNewFolder; - // full pathname of new folder, valid if fFolderCreated is true - CString fNewFullPath; + // full pathname of new folder, valid if fFolderCreated is true + CString fNewFullPath; protected: - void DoDataExchange(CDataExchange* pDX); - BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + void DoDataExchange(CDataExchange* pDX); + BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - // on exit, set to "true" if we created the folder in "fNewFolder" - bool fFolderCreated; + // on exit, set to "true" if we created the folder in "fNewFolder" + bool fFolderCreated; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__NEWFOLDERDIALOG__*/ \ No newline at end of file diff --git a/app/NufxArchive.cpp b/app/NufxArchive.cpp index 47c08ca..fa4965d 100644 --- a/app/NufxArchive.cpp +++ b/app/NufxArchive.cpp @@ -25,7 +25,7 @@ const unsigned char kNufxNoFssep = 0xff; /* * =========================================================================== - * NufxEntry + * NufxEntry * =========================================================================== */ @@ -47,105 +47,105 @@ const unsigned char kNufxNoFssep = 0xff; */ int NufxEntry::ExtractThreadToBuffer(int which, char** ppText, long* pLength, - CString* pErrMsg) const + CString* pErrMsg) const { - NuError nerr; - char* dataBuf = nil; - NuDataSink* pDataSink = nil; - NuThread thread; - unsigned long actualThreadEOF; - NuThreadIdx threadIdx; - bool needAlloc = true; - int result = -1; + NuError nerr; + char* dataBuf = nil; + NuDataSink* pDataSink = nil; + NuThread thread; + unsigned long actualThreadEOF; + NuThreadIdx threadIdx; + bool needAlloc = true; + int result = -1; - ASSERT(IDOK != -1 && IDCANCEL != -1); // make sure return vals don't clash + ASSERT(IDOK != -1 && IDCANCEL != -1); // make sure return vals don't clash - if (*ppText != nil) - needAlloc = false; + if (*ppText != nil) + needAlloc = false; - FindThreadInfo(which, &thread, pErrMsg); - if (!pErrMsg->IsEmpty()) - goto bail; - threadIdx = thread.threadIdx; - actualThreadEOF = thread.actualThreadEOF; + FindThreadInfo(which, &thread, pErrMsg); + if (!pErrMsg->IsEmpty()) + goto bail; + threadIdx = thread.threadIdx; + actualThreadEOF = thread.actualThreadEOF; - /* - * We've got the right thread. Create an appropriately-sized buffer - * and extract the data into it (WITHOUT doing EOL conversion). - * - * First check for a length of zero. - */ - if (actualThreadEOF == 0) { - WMSG0("Empty thread\n"); - if (needAlloc) { - *ppText = new char[1]; - **ppText = '\0'; - } - *pLength = 0; - result = IDOK; - goto bail; - } + /* + * We've got the right thread. Create an appropriately-sized buffer + * and extract the data into it (WITHOUT doing EOL conversion). + * + * First check for a length of zero. + */ + if (actualThreadEOF == 0) { + WMSG0("Empty thread\n"); + if (needAlloc) { + *ppText = new char[1]; + **ppText = '\0'; + } + *pLength = 0; + result = IDOK; + goto bail; + } - if (needAlloc) { - dataBuf = new char[actualThreadEOF]; - if (dataBuf == nil) { - pErrMsg->Format("allocation of %ld bytes failed", - actualThreadEOF); - goto bail; - } - } else { - if (*pLength < (long) actualThreadEOF) { - pErrMsg->Format("buf size %ld too short (%ld)", - *pLength, actualThreadEOF); - goto bail; - } - dataBuf = *ppText; - } - nerr = NuCreateDataSinkForBuffer(true, kNuConvertOff, - (unsigned char*)dataBuf, actualThreadEOF, &pDataSink); - if (nerr != kNuErrNone) { - pErrMsg->Format("unable to create buffer data sink: %s", - NuStrError(nerr)); - goto bail; - } + if (needAlloc) { + dataBuf = new char[actualThreadEOF]; + if (dataBuf == nil) { + pErrMsg->Format("allocation of %ld bytes failed", + actualThreadEOF); + goto bail; + } + } else { + if (*pLength < (long) actualThreadEOF) { + pErrMsg->Format("buf size %ld too short (%ld)", + *pLength, actualThreadEOF); + goto bail; + } + dataBuf = *ppText; + } + nerr = NuCreateDataSinkForBuffer(true, kNuConvertOff, + (unsigned char*)dataBuf, actualThreadEOF, &pDataSink); + if (nerr != kNuErrNone) { + pErrMsg->Format("unable to create buffer data sink: %s", + NuStrError(nerr)); + goto bail; + } - SET_PROGRESS_BEGIN(); - nerr = NuExtractThread(fpArchive, threadIdx, pDataSink); - if (nerr != kNuErrNone) { - if (nerr == kNuErrAborted) { - result = IDCANCEL; - //::sprintf(errorBuf, "Cancelled.\n"); - } else if (nerr == kNuErrBadFormat) { - pErrMsg->Format("The compression method used on this file is not supported " - "by your copy of \"nufxlib2.dll\". For more information, " - "please visit us on the web at " - "http://www.faddensoft.com/ciderpress/"); - } else { - pErrMsg->Format("unable to extract thread %ld: %s", - threadIdx, NuStrError(nerr)); - } - goto bail; - } + SET_PROGRESS_BEGIN(); + nerr = NuExtractThread(fpArchive, threadIdx, pDataSink); + if (nerr != kNuErrNone) { + if (nerr == kNuErrAborted) { + result = IDCANCEL; + //::sprintf(errorBuf, "Cancelled.\n"); + } else if (nerr == kNuErrBadFormat) { + pErrMsg->Format("The compression method used on this file is not supported " + "by your copy of \"nufxlib2.dll\". For more information, " + "please visit us on the web at " + "http://www.faddensoft.com/ciderpress/"); + } else { + pErrMsg->Format("unable to extract thread %ld: %s", + threadIdx, NuStrError(nerr)); + } + goto bail; + } - if (needAlloc) - *ppText = dataBuf; - *pLength = actualThreadEOF; - result = IDOK; + if (needAlloc) + *ppText = dataBuf; + *pLength = actualThreadEOF; + result = IDOK; bail: - if (result == IDOK) { - SET_PROGRESS_END(); - ASSERT(pErrMsg->IsEmpty()); - } else { - ASSERT(result == IDCANCEL || !pErrMsg->IsEmpty()); - if (needAlloc) { - delete[] dataBuf; - ASSERT(*ppText == nil); - } - } - if (pDataSink != nil) - NuFreeDataSink(pDataSink); - return result; + if (result == IDOK) { + SET_PROGRESS_END(); + ASSERT(pErrMsg->IsEmpty()); + } else { + ASSERT(result == IDCANCEL || !pErrMsg->IsEmpty()); + if (needAlloc) { + delete[] dataBuf; + ASSERT(*ppText == nil); + } + } + if (pDataSink != nil) + NuFreeDataSink(pDataSink); + return result; } /* @@ -158,105 +158,105 @@ bail: */ int NufxEntry::ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, - ConvertHighASCII convHA, CString* pErrMsg) const + ConvertHighASCII convHA, CString* pErrMsg) const { - NuDataSink* pDataSink = nil; - NuError nerr; - NuThread thread; - unsigned long actualThreadEOF; - NuThreadIdx threadIdx; - int result = -1; + NuDataSink* pDataSink = nil; + NuError nerr; + NuThread thread; + unsigned long actualThreadEOF; + NuThreadIdx threadIdx; + int result = -1; - ASSERT(outfp != nil); + ASSERT(outfp != nil); - //CString errMsg; - FindThreadInfo(which, &thread, pErrMsg); - if (!pErrMsg->IsEmpty()) - goto bail; - threadIdx = thread.threadIdx; - actualThreadEOF = thread.actualThreadEOF; + //CString errMsg; + FindThreadInfo(which, &thread, pErrMsg); + if (!pErrMsg->IsEmpty()) + goto bail; + threadIdx = thread.threadIdx; + actualThreadEOF = thread.actualThreadEOF; - /* we've got the right thread, see if it's empty */ - if (actualThreadEOF == 0) { - WMSG0("Empty thread\n"); - result = IDOK; - goto bail; - } + /* we've got the right thread, see if it's empty */ + if (actualThreadEOF == 0) { + WMSG0("Empty thread\n"); + result = IDOK; + goto bail; + } - /* set EOL conversion flags */ - NuValue nuConv; - switch (conv) { - case kConvertEOLOff: nuConv = kNuConvertOff; break; - case kConvertEOLOn: nuConv = kNuConvertOn; break; - case kConvertEOLAuto: nuConv = kNuConvertAuto; break; - default: - ASSERT(false); - pErrMsg->Format("internal error: bad conv flag %d", conv); - goto bail; - } - if (which == kDiskImageThread) { - /* override the above; never EOL-convert a disk image */ - nuConv = kNuConvertOff; - } + /* set EOL conversion flags */ + NuValue nuConv; + switch (conv) { + case kConvertEOLOff: nuConv = kNuConvertOff; break; + case kConvertEOLOn: nuConv = kNuConvertOn; break; + case kConvertEOLAuto: nuConv = kNuConvertAuto; break; + default: + ASSERT(false); + pErrMsg->Format("internal error: bad conv flag %d", conv); + goto bail; + } + if (which == kDiskImageThread) { + /* override the above; never EOL-convert a disk image */ + nuConv = kNuConvertOff; + } - switch (convHA) { - case kConvertHAOff: - nerr = NuSetValue(fpArchive, kNuValueStripHighASCII, false); - break; - case kConvertHAOn: - case kConvertHAAuto: - nerr = NuSetValue(fpArchive, kNuValueStripHighASCII, true); - break; - default: - ASSERT(false); - pErrMsg->Format("internal error: bad convHA flag %d", convHA); - goto bail; - } + switch (convHA) { + case kConvertHAOff: + nerr = NuSetValue(fpArchive, kNuValueStripHighASCII, false); + break; + case kConvertHAOn: + case kConvertHAAuto: + nerr = NuSetValue(fpArchive, kNuValueStripHighASCII, true); + break; + default: + ASSERT(false); + pErrMsg->Format("internal error: bad convHA flag %d", convHA); + goto bail; + } - /* make sure we convert to CRLF */ - nerr = NuSetValue(fpArchive, kNuValueEOL, kNuEOLCRLF); // for Win32 - if (nerr != kNuErrNone) { - pErrMsg->Format("failed setting EOL value: %s", NuStrError(nerr)); - goto bail; - } + /* make sure we convert to CRLF */ + nerr = NuSetValue(fpArchive, kNuValueEOL, kNuEOLCRLF); // for Win32 + if (nerr != kNuErrNone) { + pErrMsg->Format("failed setting EOL value: %s", NuStrError(nerr)); + goto bail; + } - /* create a data sink for "outfp" */ - nerr = NuCreateDataSinkForFP(true, nuConv, outfp, &pDataSink); - if (nerr != kNuErrNone) { - pErrMsg->Format("unable to create FP data sink: %s", - NuStrError(nerr)); - goto bail; - } - - /* extract the thread to the file */ - SET_PROGRESS_BEGIN(); - nerr = NuExtractThread(fpArchive, threadIdx, pDataSink); - if (nerr != kNuErrNone) { - if (nerr == kNuErrAborted) { - /* user hit the "cancel" button */ - *pErrMsg = _T("cancelled"); - result = IDCANCEL; - } else if (nerr == kNuErrBadFormat) { - pErrMsg->Format("The compression method used on this file is not supported " - "by your copy of \"nufxlib2.dll\". For more information, " - "please visit us on the web at " - "http://www.faddensoft.com/ciderpress/"); - } else { - pErrMsg->Format("unable to extract thread %ld: %s", - threadIdx, NuStrError(nerr)); - } - goto bail; - } + /* create a data sink for "outfp" */ + nerr = NuCreateDataSinkForFP(true, nuConv, outfp, &pDataSink); + if (nerr != kNuErrNone) { + pErrMsg->Format("unable to create FP data sink: %s", + NuStrError(nerr)); + goto bail; + } + + /* extract the thread to the file */ + SET_PROGRESS_BEGIN(); + nerr = NuExtractThread(fpArchive, threadIdx, pDataSink); + if (nerr != kNuErrNone) { + if (nerr == kNuErrAborted) { + /* user hit the "cancel" button */ + *pErrMsg = _T("cancelled"); + result = IDCANCEL; + } else if (nerr == kNuErrBadFormat) { + pErrMsg->Format("The compression method used on this file is not supported " + "by your copy of \"nufxlib2.dll\". For more information, " + "please visit us on the web at " + "http://www.faddensoft.com/ciderpress/"); + } else { + pErrMsg->Format("unable to extract thread %ld: %s", + threadIdx, NuStrError(nerr)); + } + goto bail; + } - result = IDOK; + result = IDOK; bail: - if (result == IDOK) { - SET_PROGRESS_END(); - } - if (pDataSink != nil) - NuFreeDataSink(pDataSink); - return result; + if (result == IDOK) { + SET_PROGRESS_END(); + } + if (pDataSink != nil) + NuFreeDataSink(pDataSink); + return result; } /* @@ -271,56 +271,56 @@ bail: */ void NufxEntry::FindThreadInfo(int which, NuThread* pRetThread, - CString* pErrMsg) const + CString* pErrMsg) const { - NuError nerr; + NuError nerr; - ASSERT(pErrMsg->IsEmpty()); + ASSERT(pErrMsg->IsEmpty()); - /* - * Retrieve the record from the archive. - */ - const NuRecord* pRecord; - nerr = NuGetRecord(fpArchive, fRecordIdx, &pRecord); - if (nerr != kNuErrNone) { - pErrMsg->Format("NufxLib unable to locate record %ld: %s", - fRecordIdx, NuStrError(nerr)); - goto bail; - } + /* + * Retrieve the record from the archive. + */ + const NuRecord* pRecord; + nerr = NuGetRecord(fpArchive, fRecordIdx, &pRecord); + if (nerr != kNuErrNone) { + pErrMsg->Format("NufxLib unable to locate record %ld: %s", + fRecordIdx, NuStrError(nerr)); + goto bail; + } - /* - * Find the right thread. - */ - const NuThread* pThread; - unsigned long wantedThreadID; - switch (which) { - case kDataThread: wantedThreadID = kNuThreadIDDataFork; break; - case kRsrcThread: wantedThreadID = kNuThreadIDRsrcFork; break; - case kDiskImageThread: wantedThreadID = kNuThreadIDDiskImage; break; - case kCommentThread: wantedThreadID = kNuThreadIDComment; break; - default: - pErrMsg->Format("looking for bogus thread 0x%02x", which); - goto bail; - } + /* + * Find the right thread. + */ + const NuThread* pThread; + unsigned long wantedThreadID; + switch (which) { + case kDataThread: wantedThreadID = kNuThreadIDDataFork; break; + case kRsrcThread: wantedThreadID = kNuThreadIDRsrcFork; break; + case kDiskImageThread: wantedThreadID = kNuThreadIDDiskImage; break; + case kCommentThread: wantedThreadID = kNuThreadIDComment; break; + default: + pErrMsg->Format("looking for bogus thread 0x%02x", which); + goto bail; + } - int i; - pThread = nil; - for (i = 0; i < (int)NuRecordGetNumThreads(pRecord); i++) { - pThread = NuGetThread(pRecord, i); - if (NuGetThreadID(pThread) == wantedThreadID) - break; - } - if (i == (int)NuRecordGetNumThreads(pRecord)) { - /* didn't find the thread we wanted */ - pErrMsg->Format("searched %d threads but couldn't find 0x%02x", - NuRecordGetNumThreads(pRecord), which); - goto bail; - } + int i; + pThread = nil; + for (i = 0; i < (int)NuRecordGetNumThreads(pRecord); i++) { + pThread = NuGetThread(pRecord, i); + if (NuGetThreadID(pThread) == wantedThreadID) + break; + } + if (i == (int)NuRecordGetNumThreads(pRecord)) { + /* didn't find the thread we wanted */ + pErrMsg->Format("searched %d threads but couldn't find 0x%02x", + NuRecordGetNumThreads(pRecord), which); + goto bail; + } - memcpy(pRetThread, pThread, sizeof(*pRetThread)); + memcpy(pRetThread, pThread, sizeof(*pRetThread)); bail: - return; + return; } @@ -328,18 +328,18 @@ bail: // "unc", "squ", "lz1", "lz2", "u12", "u16", "dfl", "bzp" //}; static const char* gFormatNames[] = { - "Uncompr", "Squeeze", "LZW/1", "LZW/2", "LZC-12", - "LZC-16", "Deflate", "Bzip2" + "Uncompr", "Squeeze", "LZW/1", "LZW/2", "LZC-12", + "LZC-16", "Deflate", "Bzip2" }; /* * Analyze the contents of a record to determine if it's a disk, file, - * or "other". Compute the total compressed and uncompressed lengths + * or "other". Compute the total compressed and uncompressed lengths * of all data threads. Return the "best" format. * * The "best format" and "record type" stuff assume that the entire * record contains only a disk thread or a file thread, and that any - * format is interesting so long as it isn't "no compression". In + * format is interesting so long as it isn't "no compression". In * general these will be true, because ShrinkIt and NuLib create files * this way. * @@ -355,88 +355,88 @@ static const char* gFormatNames[] = { void NufxEntry::AnalyzeRecord(const NuRecord* pRecord) { - const NuThread* pThread; - NuThreadID threadID; - unsigned long idx; - RecordKind recordKind; - unsigned long uncompressedLen; - unsigned long compressedLen; - unsigned short format; + const NuThread* pThread; + NuThreadID threadID; + unsigned long idx; + RecordKind recordKind; + unsigned long uncompressedLen; + unsigned long compressedLen; + unsigned short format; - recordKind = kRecordKindUnknown; - uncompressedLen = compressedLen = 0; - format = kNuThreadFormatUncompressed; + recordKind = kRecordKindUnknown; + uncompressedLen = compressedLen = 0; + format = kNuThreadFormatUncompressed; - for (idx = 0; idx < pRecord->recTotalThreads; idx++) { - pThread = NuGetThread(pRecord, idx); - ASSERT(pThread != nil); + for (idx = 0; idx < pRecord->recTotalThreads; idx++) { + pThread = NuGetThread(pRecord, idx); + ASSERT(pThread != nil); - threadID = NuMakeThreadID(pThread->thThreadClass, - pThread->thThreadKind); + threadID = NuMakeThreadID(pThread->thThreadClass, + pThread->thThreadKind); - if (pThread->thThreadClass == kNuThreadClassData) { - /* replace what's there if this might be more interesting */ - if (format == kNuThreadFormatUncompressed) - format = (unsigned short) pThread->thThreadFormat; + if (pThread->thThreadClass == kNuThreadClassData) { + /* replace what's there if this might be more interesting */ + if (format == kNuThreadFormatUncompressed) + format = (unsigned short) pThread->thThreadFormat; - if (threadID == kNuThreadIDRsrcFork) - recordKind = kRecordKindForkedFile; - else if (threadID == kNuThreadIDDiskImage) - recordKind = kRecordKindDisk; - else if (threadID == kNuThreadIDDataFork && - recordKind == kRecordKindUnknown) - recordKind = kRecordKindFile; + if (threadID == kNuThreadIDRsrcFork) + recordKind = kRecordKindForkedFile; + else if (threadID == kNuThreadIDDiskImage) + recordKind = kRecordKindDisk; + else if (threadID == kNuThreadIDDataFork && + recordKind == kRecordKindUnknown) + recordKind = kRecordKindFile; - /* sum up, so we get both forks of forked files */ - //uncompressedLen += pThread->actualThreadEOF; - compressedLen += pThread->thCompThreadEOF; - } + /* sum up, so we get both forks of forked files */ + //uncompressedLen += pThread->actualThreadEOF; + compressedLen += pThread->thCompThreadEOF; + } - if (threadID == kNuThreadIDDataFork) { - if (!GetHasDataFork() && !GetHasDiskImage()) { - SetHasDataFork(true); - SetDataForkLen(pThread->actualThreadEOF); - } else { - WMSG0("WARNING: ignoring second disk image / data fork\n"); - } - } - if (threadID == kNuThreadIDRsrcFork) { - if (!GetHasRsrcFork()) { - SetHasRsrcFork(true); - SetRsrcForkLen(pThread->actualThreadEOF); - } else { - WMSG0("WARNING: ignoring second data fork\n"); - } - } - if (threadID == kNuThreadIDDiskImage) { - if (!GetHasDiskImage() && !GetHasDataFork()) { - SetHasDiskImage(true); - SetDataForkLen(pThread->actualThreadEOF); - } else { - WMSG0("WARNING: ignoring second disk image / data fork\n"); - } - } - if (threadID == kNuThreadIDComment) { - SetHasComment(true); - if (pThread->actualThreadEOF != 0) - SetHasNonEmptyComment(true); - } - } + if (threadID == kNuThreadIDDataFork) { + if (!GetHasDataFork() && !GetHasDiskImage()) { + SetHasDataFork(true); + SetDataForkLen(pThread->actualThreadEOF); + } else { + WMSG0("WARNING: ignoring second disk image / data fork\n"); + } + } + if (threadID == kNuThreadIDRsrcFork) { + if (!GetHasRsrcFork()) { + SetHasRsrcFork(true); + SetRsrcForkLen(pThread->actualThreadEOF); + } else { + WMSG0("WARNING: ignoring second data fork\n"); + } + } + if (threadID == kNuThreadIDDiskImage) { + if (!GetHasDiskImage() && !GetHasDataFork()) { + SetHasDiskImage(true); + SetDataForkLen(pThread->actualThreadEOF); + } else { + WMSG0("WARNING: ignoring second disk image / data fork\n"); + } + } + if (threadID == kNuThreadIDComment) { + SetHasComment(true); + if (pThread->actualThreadEOF != 0) + SetHasNonEmptyComment(true); + } + } - SetRecordKind(recordKind); - //SetUncompressedLen(uncompressedLen); - SetCompressedLen(compressedLen); + SetRecordKind(recordKind); + //SetUncompressedLen(uncompressedLen); + SetCompressedLen(compressedLen); - if (format >= 0 && format < NELEM(gFormatNames)) - SetFormatStr(gFormatNames[format]); - else - SetFormatStr("Unknown"); + if (format >= 0 && format < NELEM(gFormatNames)) + SetFormatStr(gFormatNames[format]); + else + SetFormatStr("Unknown"); } /* * =========================================================================== - * NufxArchive + * NufxArchive * =========================================================================== */ @@ -452,33 +452,33 @@ NufxEntry::AnalyzeRecord(const NuRecord* pRecord) /*static*/ CString NufxArchive::AppInit(void) { - NuError nerr; - CString result(""); - long major, minor, bug; + NuError nerr; + CString result(""); + long major, minor, bug; - nerr = NuGetVersion(&major, &minor, &bug, NULL, NULL); - if (nerr != kNuErrNone) { - result = "Unable to get version number from NufxLib."; - goto bail; - } + nerr = NuGetVersion(&major, &minor, &bug, NULL, NULL); + if (nerr != kNuErrNone) { + result = "Unable to get version number from NufxLib."; + goto bail; + } - if (major != kNuVersionMajor || minor < kNuVersionMinor) { - result.Format("Older or incompatible version of NufxLib DLL found.\r\r" - "Wanted v%d.%d.x, found %ld.%ld.%ld.", - kNuVersionMajor, kNuVersionMinor, - major, minor, bug); - goto bail; - } - if (bug != kNuVersionBug) { - WMSG2("Different 'bug' version (built vX.X.%d, dll vX.X.%d)\n", - kNuVersionBug, bug); - } + if (major != kNuVersionMajor || minor < kNuVersionMinor) { + result.Format("Older or incompatible version of NufxLib DLL found.\r\r" + "Wanted v%d.%d.x, found %ld.%ld.%ld.", + kNuVersionMajor, kNuVersionMinor, + major, minor, bug); + goto bail; + } + if (bug != kNuVersionBug) { + WMSG2("Different 'bug' version (built vX.X.%d, dll vX.X.%d)\n", + kNuVersionBug, bug); + } - /* set NufxLib's global error message handler */ - NuSetGlobalErrorMessageHandler(NufxErrorMsgHandler); + /* set NufxLib's global error message handler */ + NuSetGlobalErrorMessageHandler(NufxErrorMsgHandler); bail: - return result; + return result; } @@ -491,40 +491,40 @@ bail: /*static*/ bool NufxArchive::IsCompressionSupported(NuThreadFormat format) { - NuFeature feature; + NuFeature feature; - switch (format) { - case kNuThreadFormatUncompressed: - return true; + switch (format) { + case kNuThreadFormatUncompressed: + return true; - case kNuThreadFormatHuffmanSQ: - feature = kNuFeatureCompressSQ; - break; - case kNuThreadFormatLZW1: - case kNuThreadFormatLZW2: - feature = kNuFeatureCompressLZW; - break; - case kNuThreadFormatLZC12: - case kNuThreadFormatLZC16: - feature = kNuFeatureCompressLZC; - break; - case kNuThreadFormatDeflate: - feature = kNuFeatureCompressDeflate; - break; - case kNuThreadFormatBzip2: - feature = kNuFeatureCompressBzip2; - break; + case kNuThreadFormatHuffmanSQ: + feature = kNuFeatureCompressSQ; + break; + case kNuThreadFormatLZW1: + case kNuThreadFormatLZW2: + feature = kNuFeatureCompressLZW; + break; + case kNuThreadFormatLZC12: + case kNuThreadFormatLZC16: + feature = kNuFeatureCompressLZC; + break; + case kNuThreadFormatDeflate: + feature = kNuFeatureCompressDeflate; + break; + case kNuThreadFormatBzip2: + feature = kNuFeatureCompressBzip2; + break; - default: - ASSERT(false); - return false; - } + default: + ASSERT(false); + return false; + } - NuError nerr; - nerr = NuTestFeature(feature); - if (nerr == kNuErrNone) - return true; - return false; + NuError nerr; + nerr = NuTestFeature(feature); + if (nerr == kNuErrNone) + return true; + return false; } /* @@ -534,29 +534,29 @@ NuResult NufxArchive::NufxErrorMsgHandler(NuArchive* /*pArchive*/, void* vErrorMessage) { #if defined(_DEBUG_LOG) - const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage; - CString msg(pErrorMessage->message); - - msg += "\n"; + const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage; + CString msg(pErrorMessage->message); + + msg += "\n"; - if (pErrorMessage->isDebug) - msg = "[D] " + msg; - fprintf(gLog, "%05u NufxLib %s(%d) : %s", - gPid, pErrorMessage->file, pErrorMessage->line, msg); + if (pErrorMessage->isDebug) + msg = "[D] " + msg; + fprintf(gLog, "%05u NufxLib %s(%d) : %s", + gPid, pErrorMessage->file, pErrorMessage->line, msg); #elif defined(_DEBUG) - const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage; - CString msg(pErrorMessage->message); - - msg += "\n"; + const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage; + CString msg(pErrorMessage->message); + + msg += "\n"; - if (pErrorMessage->isDebug) - msg = "[D] " + msg; - _CrtDbgReport(_CRT_WARN, pErrorMessage->file, pErrorMessage->line, - pErrorMessage->function, msg); + if (pErrorMessage->isDebug) + msg = "[D] " + msg; + _CrtDbgReport(_CRT_WARN, pErrorMessage->file, pErrorMessage->line, + pErrorMessage->function, msg); #endif - return kNuOK; + return kNuOK; } /* @@ -567,58 +567,58 @@ NufxArchive::NufxErrorMsgHandler(NuArchive* /*pArchive*/, void* vErrorMessage) /*static*/NuResult NufxArchive::ProgressUpdater(NuArchive* pArchive, void* vpProgress) { - const NuProgressData* pProgress = (const NuProgressData*) vpProgress; - NufxArchive* pThis; - MainWindow* pMainWin = (MainWindow*)::AfxGetMainWnd(); - int status; - const char* oldName; - const char* newName; - int perc; + const NuProgressData* pProgress = (const NuProgressData*) vpProgress; + NufxArchive* pThis; + MainWindow* pMainWin = (MainWindow*)::AfxGetMainWnd(); + int status; + const char* oldName; + const char* newName; + int perc; - ASSERT(pProgress != nil); - ASSERT(pMainWin != nil); + ASSERT(pProgress != nil); + ASSERT(pMainWin != nil); - ASSERT(pArchive != nil); - (void) NuGetExtraData(pArchive, (void**) &pThis); - ASSERT(pThis != nil); + ASSERT(pArchive != nil); + (void) NuGetExtraData(pArchive, (void**) &pThis); + ASSERT(pThis != nil); - oldName = newName = nil; - if (pProgress->operation == kNuOpAdd) { - oldName = pProgress->origPathname; - newName = pProgress->pathname; - if (pThis->fProgressAsRecompress) - oldName = "-"; - } else if (pProgress->operation == kNuOpTest) { - oldName = pProgress->pathname; - } else if (pProgress->operation == kNuOpExtract) { - if (pThis->fProgressAsRecompress) { - oldName = pProgress->origPathname; - newName = "-"; - } - } + oldName = newName = nil; + if (pProgress->operation == kNuOpAdd) { + oldName = pProgress->origPathname; + newName = pProgress->pathname; + if (pThis->fProgressAsRecompress) + oldName = "-"; + } else if (pProgress->operation == kNuOpTest) { + oldName = pProgress->pathname; + } else if (pProgress->operation == kNuOpExtract) { + if (pThis->fProgressAsRecompress) { + oldName = pProgress->origPathname; + newName = "-"; + } + } - perc = pProgress->percentComplete; - if (pProgress->state == kNuProgressDone) - perc = 100; + perc = pProgress->percentComplete; + if (pProgress->state == kNuProgressDone) + perc = 100; - //WMSG3("Progress: %d%% '%s' '%s'\n", perc, - // oldName == nil ? "(nil)" : oldName, - // newName == nil ? "(nil)" : newName); + //WMSG3("Progress: %d%% '%s' '%s'\n", perc, + // oldName == nil ? "(nil)" : oldName, + // newName == nil ? "(nil)" : newName); - //status = pMainWin->SetProgressUpdate(perc, oldName, newName); - status = SET_PROGRESS_UPDATE2(perc, oldName, newName); + //status = pMainWin->SetProgressUpdate(perc, oldName, newName); + status = SET_PROGRESS_UPDATE2(perc, oldName, newName); - /* check to see if user hit the "cancel" button on the progress dialog */ - if (pProgress->state == kNuProgressAborted) { - WMSG0("(looks like we're aborting)\n"); - ASSERT(status == IDCANCEL); - } - - if (status == IDCANCEL) { - WMSG0("Signaling NufxLib to abort\n"); - return kNuAbort; - } else - return kNuOK; + /* check to see if user hit the "cancel" button on the progress dialog */ + if (pProgress->state == kNuProgressAborted) { + WMSG0("(looks like we're aborting)\n"); + ASSERT(status == IDCANCEL); + } + + if (status == IDCANCEL) { + WMSG0("Signaling NufxLib to abort\n"); + return kNuAbort; + } else + return kNuOK; } @@ -630,56 +630,56 @@ NufxArchive::ProgressUpdater(NuArchive* pArchive, void* vpProgress) GenericArchive::OpenResult NufxArchive::Open(const char* filename, bool readOnly, CString* pErrMsg) { - NuError nerr; - CString errMsg; + NuError nerr; + CString errMsg; - ASSERT(fpArchive == nil); + ASSERT(fpArchive == nil); - if (!readOnly) { - CString tmpname = GenDerivedTempName(filename); - WMSG2("Opening file '%s' rw (tmp='%s')\n", filename, tmpname); - fIsReadOnly = false; - nerr = NuOpenRW(filename, tmpname, 0, &fpArchive); - } - if (nerr == kNuErrFileAccessDenied || nerr == EACCES) { - WMSG0("Read-write failed with access denied, trying read-only\n"); - readOnly = true; - } - if (readOnly) { - WMSG1("Opening file '%s' ro\n", filename); - fIsReadOnly = true; - nerr = NuOpenRO(filename, &fpArchive); - } - if (nerr != kNuErrNone) { - errMsg = "Unable to open '"; - errMsg += filename; - errMsg += "': "; - errMsg += NuStrError(nerr); - goto bail; - } else { - //WMSG0("FILE OPEN SUCCESS\n"); - } + if (!readOnly) { + CString tmpname = GenDerivedTempName(filename); + WMSG2("Opening file '%s' rw (tmp='%s')\n", filename, tmpname); + fIsReadOnly = false; + nerr = NuOpenRW(filename, tmpname, 0, &fpArchive); + } + if (nerr == kNuErrFileAccessDenied || nerr == EACCES) { + WMSG0("Read-write failed with access denied, trying read-only\n"); + readOnly = true; + } + if (readOnly) { + WMSG1("Opening file '%s' ro\n", filename); + fIsReadOnly = true; + nerr = NuOpenRO(filename, &fpArchive); + } + if (nerr != kNuErrNone) { + errMsg = "Unable to open '"; + errMsg += filename; + errMsg += "': "; + errMsg += NuStrError(nerr); + goto bail; + } else { + //WMSG0("FILE OPEN SUCCESS\n"); + } - nerr = SetCallbacks(); - if (nerr != kNuErrNone) { - errMsg = "Callback init failed"; - goto bail; - } + nerr = SetCallbacks(); + if (nerr != kNuErrNone) { + errMsg = "Callback init failed"; + goto bail; + } - nerr = LoadContents(); - if (nerr != kNuErrNone) { - errMsg = "Failed reading archive contents: "; - errMsg += NuStrError(nerr); - } + nerr = LoadContents(); + if (nerr != kNuErrNone) { + errMsg = "Failed reading archive contents: "; + errMsg += NuStrError(nerr); + } - SetPathName(filename); + SetPathName(filename); bail: - *pErrMsg = errMsg; - if (!errMsg.IsEmpty()) - return kResultFailure; - else - return kResultSuccess; + *pErrMsg = errMsg; + if (!errMsg.IsEmpty()) + return kResultFailure; + else + return kResultSuccess; } @@ -691,37 +691,37 @@ bail: CString NufxArchive::New(const char* filename, const void* options) { - NuError nerr; - CString retmsg(""); + NuError nerr; + CString retmsg(""); - ASSERT(fpArchive == nil); - ASSERT(options == nil); + ASSERT(fpArchive == nil); + ASSERT(options == nil); - CString tmpname = GenDerivedTempName(filename); - WMSG2("Creating file '%s' (tmp='%s')\n", filename, tmpname); - fIsReadOnly = false; - nerr = NuOpenRW(filename, tmpname, kNuOpenCreat | kNuOpenExcl, &fpArchive); - if (nerr != kNuErrNone) { - retmsg = "Unable to open '"; - retmsg += filename; - retmsg += "': "; - retmsg += NuStrError(nerr); - goto bail; - } else { - WMSG0("NEW FILE SUCCESS\n"); - } + CString tmpname = GenDerivedTempName(filename); + WMSG2("Creating file '%s' (tmp='%s')\n", filename, tmpname); + fIsReadOnly = false; + nerr = NuOpenRW(filename, tmpname, kNuOpenCreat | kNuOpenExcl, &fpArchive); + if (nerr != kNuErrNone) { + retmsg = "Unable to open '"; + retmsg += filename; + retmsg += "': "; + retmsg += NuStrError(nerr); + goto bail; + } else { + WMSG0("NEW FILE SUCCESS\n"); + } - nerr = SetCallbacks(); - if (nerr != kNuErrNone) { - retmsg = "Callback init failed"; - goto bail; - } + nerr = SetCallbacks(); + if (nerr != kNuErrNone) { + retmsg = "Callback init failed"; + goto bail; + } - SetPathName(filename); + SetPathName(filename); bail: - return retmsg; + return retmsg; } /* @@ -730,33 +730,33 @@ bail: NuError NufxArchive::SetCallbacks(void) { - NuError nerr; + NuError nerr; nerr = NuSetExtraData(fpArchive, this); - if (nerr != kNuErrNone) - goto bail; + if (nerr != kNuErrNone) + goto bail; // nerr = NuSetSelectionFilter(fpArchive, SelectionFilter); -// if (nerr != kNuErrNone) -// goto bail; +// if (nerr != kNuErrNone) +// goto bail; // nerr = NuSetOutputPathnameFilter(fpArchive, OutputPathnameFilter); -// if (nerr != kNuErrNone) -// goto bail; +// if (nerr != kNuErrNone) +// goto bail; NuSetProgressUpdater(fpArchive, ProgressUpdater); // nerr = NuSetErrorHandler(fpArchive, ErrorHandler); -// if (nerr != kNuErrNone) -// goto bail; +// if (nerr != kNuErrNone) +// goto bail; NuSetErrorMessageHandler(fpArchive, NufxErrorMsgHandler); - /* let NufxLib worry about buggy records without data threads */ - nerr = NuSetValue(fpArchive, kNuValueMaskDataless, kNuValueTrue); - if (nerr != kNuErrNone) - goto bail; + /* let NufxLib worry about buggy records without data threads */ + nerr = NuSetValue(fpArchive, kNuValueMaskDataless, kNuValueTrue); + if (nerr != kNuErrNone) + goto bail; - /* set any values based on Preferences values */ - PreferencesChanged(); + /* set any values based on Preferences values */ + PreferencesChanged(); bail: - return nerr; + return nerr; } /* @@ -767,25 +767,25 @@ bail: void NufxArchive::PreferencesChanged(void) { - NuError nerr; - const Preferences* pPreferences = GET_PREFERENCES(); - bool val; + NuError nerr; + const Preferences* pPreferences = GET_PREFERENCES(); + bool val; - val = pPreferences->GetPrefBool(kPrMimicShrinkIt); + val = pPreferences->GetPrefBool(kPrMimicShrinkIt); nerr = NuSetValue(fpArchive, kNuValueMimicSHK, val); - if (nerr != kNuErrNone) { - WMSG2("NuSetValue(kNuValueMimicSHK, %d) failed, err=%d\n", val, nerr); - ASSERT(false); - } else { - WMSG1("Set MimicShrinkIt to %d\n", val); - } + if (nerr != kNuErrNone) { + WMSG2("NuSetValue(kNuValueMimicSHK, %d) failed, err=%d\n", val, nerr); + ASSERT(false); + } else { + WMSG1("Set MimicShrinkIt to %d\n", val); + } - val = pPreferences->GetPrefBool(kPrReduceSHKErrorChecks); + val = pPreferences->GetPrefBool(kPrReduceSHKErrorChecks); NuSetValue(fpArchive, kNuValueIgnoreLZW2Len, val); NuSetValue(fpArchive, kNuValueIgnoreCRC, val); - val = pPreferences->GetPrefBool(kPrBadMacSHK); - NuSetValue(fpArchive, kNuValueHandleBadMac, val); + val = pPreferences->GetPrefBool(kPrBadMacSHK); + NuSetValue(fpArchive, kNuValueHandleBadMac, val); } /* @@ -794,36 +794,36 @@ NufxArchive::PreferencesChanged(void) long NufxArchive::GetCapability(Capability cap) { - switch (cap) { - case kCapCanTest: - return true; - break; - case kCapCanRenameFullPath: - return true; - break; - case kCapCanRecompress: - return true; - break; - case kCapCanEditComment: - return true; - break; - case kCapCanAddDisk: - return true; - break; - case kCapCanConvEOLOnAdd: - return false; - break; - case kCapCanCreateSubdir: - return false; - break; - case kCapCanRenameVolume: - return false; - break; - default: - ASSERT(false); - return -1; - break; - } + switch (cap) { + case kCapCanTest: + return true; + break; + case kCapCanRenameFullPath: + return true; + break; + case kCapCanRecompress: + return true; + break; + case kCapCanEditComment: + return true; + break; + case kCapCanAddDisk: + return true; + break; + case kCapCanConvEOLOnAdd: + return false; + break; + case kCapCanCreateSubdir: + return false; + break; + case kCapCanRenameVolume: + return false; + break; + default: + ASSERT(false); + return -1; + break; + } } /* @@ -835,29 +835,29 @@ NufxArchive::GetCapability(Capability cap) NuError NufxArchive::LoadContents(void) { - long counter = 0; - NuError result; + long counter = 0; + NuError result; - WMSG0("NufxArchive LoadContents\n"); - ASSERT(fpArchive != nil); + WMSG0("NufxArchive LoadContents\n"); + ASSERT(fpArchive != nil); - { - MainWindow* pMain = GET_MAIN_WINDOW(); - ExclusiveModelessDialog* pWaitDlg = new ExclusiveModelessDialog; - pWaitDlg->Create(IDD_LOADING, pMain); - pWaitDlg->CenterWindow(); - pMain->PeekAndPump(); // redraw - CWaitCursor waitc; + { + MainWindow* pMain = GET_MAIN_WINDOW(); + ExclusiveModelessDialog* pWaitDlg = new ExclusiveModelessDialog; + pWaitDlg->Create(IDD_LOADING, pMain); + pWaitDlg->CenterWindow(); + pMain->PeekAndPump(); // redraw + CWaitCursor waitc; - result = NuContents(fpArchive, ContentFunc); + result = NuContents(fpArchive, ContentFunc); - SET_PROGRESS_COUNTER(-1); + SET_PROGRESS_COUNTER(-1); - pWaitDlg->DestroyWindow(); - //pMain->PeekAndPump(); // redraw - } + pWaitDlg->DestroyWindow(); + //pMain->PeekAndPump(); // redraw + } - return result; + return result; } /* @@ -866,23 +866,23 @@ NufxArchive::LoadContents(void) CString NufxArchive::Reload(void) { - NuError nerr; - CString errMsg; + NuError nerr; + CString errMsg; - fReloadFlag = true; // tell everybody that cached data is invalid + fReloadFlag = true; // tell everybody that cached data is invalid - DeleteEntries(); // a GenericArchive operation + DeleteEntries(); // a GenericArchive operation - nerr = LoadContents(); - if (nerr != kNuErrNone) { - errMsg.Format("ERROR: unable to reload archive contents: %s.", - NuStrError(nerr)); + nerr = LoadContents(); + if (nerr != kNuErrNone) { + errMsg.Format("ERROR: unable to reload archive contents: %s.", + NuStrError(nerr)); - DeleteEntries(); - fIsReadOnly = true; - } + DeleteEntries(); + fIsReadOnly = true; + } - return errMsg; + return errMsg; } /* @@ -892,16 +892,16 @@ NufxArchive::Reload(void) NuError NufxArchive::InternalReload(CWnd* pMsgWnd) { - CString errMsg; + CString errMsg; - errMsg = Reload(); + errMsg = Reload(); - if (!errMsg.IsEmpty()) { - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - return kNuErrGeneric; - } + if (!errMsg.IsEmpty()) { + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + return kNuErrGeneric; + } - return kNuErrNone; + return kNuErrNone; } /* @@ -910,40 +910,40 @@ NufxArchive::InternalReload(CWnd* pMsgWnd) NuResult NufxArchive::ContentFunc(NuArchive* pArchive, void* vpRecord) { - const NuRecord* pRecord = (const NuRecord*) vpRecord; - NufxArchive* pThis; - NufxEntry* pNewEntry; + const NuRecord* pRecord = (const NuRecord*) vpRecord; + NufxArchive* pThis; + NufxEntry* pNewEntry; - ASSERT(pArchive != nil); - ASSERT(vpRecord != nil); + ASSERT(pArchive != nil); + ASSERT(vpRecord != nil); - NuGetExtraData(pArchive, (void**) &pThis); + NuGetExtraData(pArchive, (void**) &pThis); - pNewEntry = new NufxEntry(pArchive); + pNewEntry = new NufxEntry(pArchive); - pNewEntry->SetPathName(pRecord->filename); - pNewEntry->SetFssep(NuGetSepFromSysInfo(pRecord->recFileSysInfo)); - pNewEntry->SetFileType(pRecord->recFileType); - pNewEntry->SetAuxType(pRecord->recExtraType); - pNewEntry->SetAccess(pRecord->recAccess); - pNewEntry->SetCreateWhen(DateTimeToSeconds(&pRecord->recCreateWhen)); - pNewEntry->SetModWhen(DateTimeToSeconds(&pRecord->recModWhen)); + pNewEntry->SetPathName(pRecord->filename); + pNewEntry->SetFssep(NuGetSepFromSysInfo(pRecord->recFileSysInfo)); + pNewEntry->SetFileType(pRecord->recFileType); + pNewEntry->SetAuxType(pRecord->recExtraType); + pNewEntry->SetAccess(pRecord->recAccess); + pNewEntry->SetCreateWhen(DateTimeToSeconds(&pRecord->recCreateWhen)); + pNewEntry->SetModWhen(DateTimeToSeconds(&pRecord->recModWhen)); - /* - * Our files are always ProDOS format. This is especially important - * when cutting & pasting, so that the DOS high ASCII converter gets - * invoked at appropriate times. - */ - pNewEntry->SetSourceFS(DiskImg::kFormatProDOS); + /* + * Our files are always ProDOS format. This is especially important + * when cutting & pasting, so that the DOS high ASCII converter gets + * invoked at appropriate times. + */ + pNewEntry->SetSourceFS(DiskImg::kFormatProDOS); - pNewEntry->AnalyzeRecord(pRecord); - pNewEntry->SetRecordIdx(pRecord->recordIdx); + pNewEntry->AnalyzeRecord(pRecord); + pNewEntry->SetRecordIdx(pRecord->recordIdx); - pThis->AddEntry(pNewEntry); - if ((pThis->GetNumEntries() % 10) == 0) - SET_PROGRESS_COUNTER(pThis->GetNumEntries()); + pThis->AddEntry(pNewEntry); + if ((pThis->GetNumEntries() % 10) == 0) + SET_PROGRESS_COUNTER(pThis->GetNumEntries()); - return kNuOK; + return kNuOK; } /* @@ -952,48 +952,48 @@ NufxArchive::ContentFunc(NuArchive* pArchive, void* vpRecord) /*static*/ time_t NufxArchive::DateTimeToSeconds(const NuDateTime* pDateTime) { - if (pDateTime->second == 0 && - pDateTime->minute == 0 && - pDateTime->hour == 0 && - pDateTime->year == 0 && - pDateTime->day == 0 && - pDateTime->month == 0 && - pDateTime->extra == 0 && - pDateTime->weekDay == 0) - { - return kDateNone; - } + if (pDateTime->second == 0 && + pDateTime->minute == 0 && + pDateTime->hour == 0 && + pDateTime->year == 0 && + pDateTime->day == 0 && + pDateTime->month == 0 && + pDateTime->extra == 0 && + pDateTime->weekDay == 0) + { + return kDateNone; + } - int year; - if (pDateTime->year < 40) - year = pDateTime->year + 2000; - else - year = pDateTime->year + 1900; + int year; + if (pDateTime->year < 40) + year = pDateTime->year + 2000; + else + year = pDateTime->year + 1900; - if (year < 1969) { - /* - * Years like 1963 are valid on an Apple II but cannot be represented - * as a time_t, which starts in 1970. (Depending on GMT offsets, - * it actually starts a few hours earlier at the end of 1969.) - * - * I'm catching this here because of an assert in the CTime - * constructor. The constructor seems to do the right thing, and the - * assert won't be present in the shipping version, but it's annoying - * during debugging. - */ - //WMSG1(" Ignoring funky year %ld\n", year); - return kDateInvalid; - } - if (pDateTime->month > 11) - return kDateInvalid; + if (year < 1969) { + /* + * Years like 1963 are valid on an Apple II but cannot be represented + * as a time_t, which starts in 1970. (Depending on GMT offsets, + * it actually starts a few hours earlier at the end of 1969.) + * + * I'm catching this here because of an assert in the CTime + * constructor. The constructor seems to do the right thing, and the + * assert won't be present in the shipping version, but it's annoying + * during debugging. + */ + //WMSG1(" Ignoring funky year %ld\n", year); + return kDateInvalid; + } + if (pDateTime->month > 11) + return kDateInvalid; - CTime modTime(year, - pDateTime->month+1, - pDateTime->day+1, - pDateTime->hour, - pDateTime->minute, - pDateTime->second); - return (time_t) modTime.GetTime(); + CTime modTime(year, + pDateTime->month+1, + pDateTime->day+1, + pDateTime->hour, + pDateTime->minute, + pDateTime->second); + return (time_t) modTime.GetTime(); } /* @@ -1003,14 +1003,14 @@ NufxArchive::DateTimeToSeconds(const NuDateTime* pDateTime) /*static*/ NuResult NufxArchive::ArrayDeleteHandler(NuArchive* pArchive, void* ptr) { - delete[] ptr; - return kNuOK; + delete[] ptr; + return kNuOK; } /* * =========================================================================== - * NufxArchive -- add files (or disks) + * NufxArchive -- add files (or disks) * =========================================================================== */ @@ -1025,95 +1025,95 @@ NufxArchive::ArrayDeleteHandler(NuArchive* pArchive, void* ptr) */ bool NufxArchive::BulkAdd(ActionProgressDialog* pActionProgress, - const AddFilesDialog* pAddOpts) + const AddFilesDialog* pAddOpts) { - NuError nerr; - CString errMsg; - char curDir[MAX_PATH] = ""; - bool retVal = false; + NuError nerr; + CString errMsg; + char curDir[MAX_PATH] = ""; + bool retVal = false; - WMSG2("Opts: '%s' typePres=%d\n", - pAddOpts->fStoragePrefix, pAddOpts->fTypePreservation); - WMSG3(" sub=%d strip=%d ovwr=%d\n", - pAddOpts->fIncludeSubfolders, pAddOpts->fStripFolderNames, - pAddOpts->fOverwriteExisting); + WMSG2("Opts: '%s' typePres=%d\n", + pAddOpts->fStoragePrefix, pAddOpts->fTypePreservation); + WMSG3(" sub=%d strip=%d ovwr=%d\n", + pAddOpts->fIncludeSubfolders, pAddOpts->fStripFolderNames, + pAddOpts->fOverwriteExisting); - AddPrep(pActionProgress, pAddOpts); + AddPrep(pActionProgress, pAddOpts); - pActionProgress->SetArcName("(Scanning files to be added...)"); - pActionProgress->SetFileName(""); + pActionProgress->SetArcName("(Scanning files to be added...)"); + pActionProgress->SetFileName(""); - /* initialize count */ - fNumAdded = 0; + /* initialize count */ + fNumAdded = 0; - const char* buf = pAddOpts->GetFileNames(); - WMSG2("Selected path = '%s' (offset=%d)\n", buf, - pAddOpts->GetFileNameOffset()); + const char* buf = pAddOpts->GetFileNames(); + WMSG2("Selected path = '%s' (offset=%d)\n", buf, + pAddOpts->GetFileNameOffset()); - if (GetCurrentDirectory(sizeof(curDir), curDir) == 0) { - errMsg = "Unable to get current directory.\n"; - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - if (SetCurrentDirectory(buf) == false) { - errMsg.Format("Unable to set current directory to '%s'.\n", buf); - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - goto bail; - } + if (GetCurrentDirectory(sizeof(curDir), curDir) == 0) { + errMsg = "Unable to get current directory.\n"; + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + if (SetCurrentDirectory(buf) == false) { + errMsg.Format("Unable to set current directory to '%s'.\n", buf); + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + goto bail; + } - buf += pAddOpts->GetFileNameOffset(); - while (*buf != '\0') { - WMSG1(" file '%s'\n", buf); + buf += pAddOpts->GetFileNameOffset(); + while (*buf != '\0') { + WMSG1(" file '%s'\n", buf); - /* this just provides the list of files to NufxLib */ - nerr = AddFile(pAddOpts, buf, &errMsg); - if (nerr != kNuErrNone) { - if (errMsg.IsEmpty()) - errMsg.Format("Failed while adding file '%s': %s.", - (LPCTSTR) buf, NuStrError(nerr)); - if (nerr != kNuErrAborted) { - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - } - goto bail; - } + /* this just provides the list of files to NufxLib */ + nerr = AddFile(pAddOpts, buf, &errMsg); + if (nerr != kNuErrNone) { + if (errMsg.IsEmpty()) + errMsg.Format("Failed while adding file '%s': %s.", + (LPCTSTR) buf, NuStrError(nerr)); + if (nerr != kNuErrAborted) { + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + } + goto bail; + } - buf += strlen(buf)+1; - } + buf += strlen(buf)+1; + } - /* actually do the work */ - long statusFlags; - nerr = NuFlush(fpArchive, &statusFlags); - if (nerr != kNuErrNone) { - if (nerr != kNuErrAborted) { - errMsg.Format("Unable to add files: %s.", NuStrError(nerr)); - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - } + /* actually do the work */ + long statusFlags; + nerr = NuFlush(fpArchive, &statusFlags); + if (nerr != kNuErrNone) { + if (nerr != kNuErrAborted) { + errMsg.Format("Unable to add files: %s.", NuStrError(nerr)); + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + } - /* see if it got converted to read-only status */ - if (statusFlags & kNuFlushReadOnly) - fIsReadOnly = true; - goto bail; - } + /* see if it got converted to read-only status */ + if (statusFlags & kNuFlushReadOnly) + fIsReadOnly = true; + goto bail; + } - if (!fNumAdded) { - errMsg = "No files added.\n"; - fpMsgWnd->MessageBox(errMsg, "CiderPress", MB_OK | MB_ICONWARNING); - } else { - if (InternalReload(fpMsgWnd) == kNuErrNone) - retVal = true; - else - errMsg = "Reload failed."; - } + if (!fNumAdded) { + errMsg = "No files added.\n"; + fpMsgWnd->MessageBox(errMsg, "CiderPress", MB_OK | MB_ICONWARNING); + } else { + if (InternalReload(fpMsgWnd) == kNuErrNone) + retVal = true; + else + errMsg = "Reload failed."; + } bail: - NuAbort(fpArchive); // abort anything that didn't get flushed - if (SetCurrentDirectory(curDir) == false) { - errMsg.Format("Unable to reset current directory to '%s'.\n", buf); - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - // bummer, but don't signal failure - } - AddFinish(); - return retVal; + NuAbort(fpArchive); // abort anything that didn't get flushed + if (SetCurrentDirectory(curDir) == false) { + errMsg.Format("Unable to reset current directory to '%s'.\n", buf); + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + // bummer, but don't signal failure + } + AddFinish(); + return retVal; } /* @@ -1121,172 +1121,172 @@ bail: */ bool NufxArchive::AddDisk(ActionProgressDialog* pActionProgress, - const AddFilesDialog* pAddOpts) + const AddFilesDialog* pAddOpts) { - NuError nerr; - CString errMsg; - const int kBlockSize = 512; - PathProposal pathProp; - PathName pathName; - DiskImg* pDiskImg; - NuDataSource* pSource = nil; - unsigned char* diskData = nil; - char curDir[MAX_PATH] = "\\"; - bool retVal = false; + NuError nerr; + CString errMsg; + const int kBlockSize = 512; + PathProposal pathProp; + PathName pathName; + DiskImg* pDiskImg; + NuDataSource* pSource = nil; + unsigned char* diskData = nil; + char curDir[MAX_PATH] = "\\"; + bool retVal = false; - WMSG2("AddDisk: '%s' %d\n", pAddOpts->GetFileNames(), - pAddOpts->GetFileNameOffset()); - WMSG2("Opts: '%s' type=%d\n", - pAddOpts->fStoragePrefix, pAddOpts->fTypePreservation); - WMSG3(" sub=%d strip=%d ovwr=%d\n", - pAddOpts->fIncludeSubfolders, pAddOpts->fStripFolderNames, - pAddOpts->fOverwriteExisting); + WMSG2("AddDisk: '%s' %d\n", pAddOpts->GetFileNames(), + pAddOpts->GetFileNameOffset()); + WMSG2("Opts: '%s' type=%d\n", + pAddOpts->fStoragePrefix, pAddOpts->fTypePreservation); + WMSG3(" sub=%d strip=%d ovwr=%d\n", + pAddOpts->fIncludeSubfolders, pAddOpts->fStripFolderNames, + pAddOpts->fOverwriteExisting); - pDiskImg = pAddOpts->fpDiskImg; - ASSERT(pDiskImg != nil); + pDiskImg = pAddOpts->fpDiskImg; + ASSERT(pDiskImg != nil); - /* allocate storage for the disk */ - diskData = new unsigned char[pDiskImg->GetNumBlocks() * kBlockSize]; - if (diskData == nil) { - errMsg.Format("Unable to allocate %d bytes.", - pDiskImg->GetNumBlocks() * kBlockSize); - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - goto bail; - } + /* allocate storage for the disk */ + diskData = new unsigned char[pDiskImg->GetNumBlocks() * kBlockSize]; + if (diskData == nil) { + errMsg.Format("Unable to allocate %d bytes.", + pDiskImg->GetNumBlocks() * kBlockSize); + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + goto bail; + } - /* prepare to add */ - AddPrep(pActionProgress, pAddOpts); + /* prepare to add */ + AddPrep(pActionProgress, pAddOpts); - const char* buf; - buf = pAddOpts->GetFileNames(); - WMSG2("Selected path = '%s' (offset=%d)\n", buf, - pAddOpts->GetFileNameOffset()); + const char* buf; + buf = pAddOpts->GetFileNames(); + WMSG2("Selected path = '%s' (offset=%d)\n", buf, + pAddOpts->GetFileNameOffset()); - if (GetCurrentDirectory(sizeof(curDir), curDir) == 0) { - errMsg = "Unable to get current directory.\n"; - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - if (SetCurrentDirectory(buf) == false) { - errMsg.Format("Unable to set current directory to '%s'.\n", buf); - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - goto bail; - } + if (GetCurrentDirectory(sizeof(curDir), curDir) == 0) { + errMsg = "Unable to get current directory.\n"; + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + if (SetCurrentDirectory(buf) == false) { + errMsg.Format("Unable to set current directory to '%s'.\n", buf); + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + goto bail; + } - buf += pAddOpts->GetFileNameOffset(); - WMSG1(" file '%s'\n", buf); + buf += pAddOpts->GetFileNameOffset(); + WMSG1(" file '%s'\n", buf); - /* strip off preservation stuff, and ignore it */ - pathProp.Init(buf); - pathProp.fStripDiskImageSuffix = true; - pathProp.LocalToArchive(pAddOpts); + /* strip off preservation stuff, and ignore it */ + pathProp.Init(buf); + pathProp.fStripDiskImageSuffix = true; + pathProp.LocalToArchive(pAddOpts); - /* fill in the necessary file details */ - NuFileDetails details; - memset(&details, 0, sizeof(details)); - details.threadID = kNuThreadIDDiskImage; - details.storageType = kBlockSize; - details.access = kNuAccessUnlocked; - details.extraType = pAddOpts->fpDiskImg->GetNumBlocks(); - details.origName = buf; - details.storageName = pathProp.fStoredPathName; - details.fileSysID = kNuFileSysUnknown; - details.fileSysInfo = PathProposal::kDefaultStoredFssep; + /* fill in the necessary file details */ + NuFileDetails details; + memset(&details, 0, sizeof(details)); + details.threadID = kNuThreadIDDiskImage; + details.storageType = kBlockSize; + details.access = kNuAccessUnlocked; + details.extraType = pAddOpts->fpDiskImg->GetNumBlocks(); + details.origName = buf; + details.storageName = pathProp.fStoredPathName; + details.fileSysID = kNuFileSysUnknown; + details.fileSysInfo = PathProposal::kDefaultStoredFssep; - time_t now, then; + time_t now, then; - pathName = buf; - now = time(nil); - then = pathName.GetModWhen(); - UNIXTimeToDateTime(&now, &details.archiveWhen); - UNIXTimeToDateTime(&then, &details.modWhen); - UNIXTimeToDateTime(&then, &details.createWhen); + pathName = buf; + now = time(nil); + then = pathName.GetModWhen(); + UNIXTimeToDateTime(&now, &details.archiveWhen); + UNIXTimeToDateTime(&then, &details.modWhen); + UNIXTimeToDateTime(&then, &details.createWhen); - /* set up the progress updater */ - pActionProgress->SetArcName(details.storageName); - pActionProgress->SetFileName(details.origName); + /* set up the progress updater */ + pActionProgress->SetArcName(details.storageName); + pActionProgress->SetFileName(details.origName); - /* read the disk now that we have progress update titles in place */ - int block, numBadBlocks; - unsigned char* bufPtr; - numBadBlocks = 0; - for (block = 0, bufPtr = diskData; block < pDiskImg->GetNumBlocks(); block++) - { - DIError dierr; - dierr = pDiskImg->ReadBlock(block, bufPtr); - if (dierr != kDIErrNone) - numBadBlocks++; - bufPtr += kBlockSize; - } - if (numBadBlocks > 0) { - CString appName, msg; - appName.LoadString(IDS_MB_APP_NAME); - msg.Format("Skipped %ld unreadable block%s.", numBadBlocks, - numBadBlocks == 1 ? "" : "s"); - fpMsgWnd->MessageBox(msg, appName, MB_OK | MB_ICONWARNING); - // keep going -- just a warning - } + /* read the disk now that we have progress update titles in place */ + int block, numBadBlocks; + unsigned char* bufPtr; + numBadBlocks = 0; + for (block = 0, bufPtr = diskData; block < pDiskImg->GetNumBlocks(); block++) + { + DIError dierr; + dierr = pDiskImg->ReadBlock(block, bufPtr); + if (dierr != kDIErrNone) + numBadBlocks++; + bufPtr += kBlockSize; + } + if (numBadBlocks > 0) { + CString appName, msg; + appName.LoadString(IDS_MB_APP_NAME); + msg.Format("Skipped %ld unreadable block%s.", numBadBlocks, + numBadBlocks == 1 ? "" : "s"); + fpMsgWnd->MessageBox(msg, appName, MB_OK | MB_ICONWARNING); + // keep going -- just a warning + } - /* create a data source for the disk */ - nerr = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, 0, - diskData, 0, pAddOpts->fpDiskImg->GetNumBlocks() * kBlockSize, - nil, &pSource); - if (nerr != kNuErrNone) { - errMsg = "Unable to create NufxLib data source."; - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - goto bail; - } + /* create a data source for the disk */ + nerr = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, 0, + diskData, 0, pAddOpts->fpDiskImg->GetNumBlocks() * kBlockSize, + nil, &pSource); + if (nerr != kNuErrNone) { + errMsg = "Unable to create NufxLib data source."; + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + goto bail; + } - /* add the record; name conflicts cause the error handler to fire */ - NuRecordIdx recordIdx; - nerr = NuAddRecord(fpArchive, &details, &recordIdx); - if (nerr != kNuErrNone) { - if (nerr != kNuErrAborted) { - errMsg.Format("Failed adding record: %s.", NuStrError(nerr)); - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - } - goto bail; - } + /* add the record; name conflicts cause the error handler to fire */ + NuRecordIdx recordIdx; + nerr = NuAddRecord(fpArchive, &details, &recordIdx); + if (nerr != kNuErrNone) { + if (nerr != kNuErrAborted) { + errMsg.Format("Failed adding record: %s.", NuStrError(nerr)); + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + } + goto bail; + } - /* do the compression */ - nerr = NuAddThread(fpArchive, recordIdx, kNuThreadIDDiskImage, - pSource, nil); - if (nerr != kNuErrNone) { - errMsg.Format("Failed adding thread: %s.", NuStrError(nerr)); - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - pSource = nil; /* NufxLib owns it now */ + /* do the compression */ + nerr = NuAddThread(fpArchive, recordIdx, kNuThreadIDDiskImage, + pSource, nil); + if (nerr != kNuErrNone) { + errMsg.Format("Failed adding thread: %s.", NuStrError(nerr)); + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + pSource = nil; /* NufxLib owns it now */ - /* actually do the work */ - long statusFlags; - nerr = NuFlush(fpArchive, &statusFlags); - if (nerr != kNuErrNone) { - if (nerr != kNuErrAborted) { - errMsg.Format("Unable to add disk: %s.", NuStrError(nerr)); - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - } + /* actually do the work */ + long statusFlags; + nerr = NuFlush(fpArchive, &statusFlags); + if (nerr != kNuErrNone) { + if (nerr != kNuErrAborted) { + errMsg.Format("Unable to add disk: %s.", NuStrError(nerr)); + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + } - /* see if it got converted to read-only status */ - if (statusFlags & kNuFlushReadOnly) - fIsReadOnly = true; - goto bail; - } + /* see if it got converted to read-only status */ + if (statusFlags & kNuFlushReadOnly) + fIsReadOnly = true; + goto bail; + } - if (InternalReload(fpMsgWnd) == kNuErrNone) - retVal = true; + if (InternalReload(fpMsgWnd) == kNuErrNone) + retVal = true; bail: - delete[] diskData; - NuAbort(fpArchive); // abort anything that didn't get flushed - NuFreeDataSource(pSource); - if (SetCurrentDirectory(curDir) == false) { - errMsg.Format("Unable to reset current directory to '%s'.\n", buf); - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - // bummer - } - AddFinish(); - return retVal; + delete[] diskData; + NuAbort(fpArchive); // abort anything that didn't get flushed + NuFreeDataSource(pSource); + if (SetCurrentDirectory(curDir) == false) { + errMsg.Format("Unable to reset current directory to '%s'.\n", buf); + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + // bummer + } + AddFinish(); + return retVal; } /* @@ -1296,54 +1296,54 @@ bail: */ NuError NufxArchive::DoAddFile(const AddFilesDialog* pAddOpts, - FileDetails* pDetails) + FileDetails* pDetails) { - NuError err; - NuRecordIdx recordIdx = 0; - NuFileDetails nuFileDetails; - + NuError err; + NuRecordIdx recordIdx = 0; + NuFileDetails nuFileDetails; + retry: - nuFileDetails = *pDetails; // stuff class contents into struct - err = NuAddFile(fpArchive, pDetails->origName /*pathname*/, - &nuFileDetails, false, &recordIdx); + nuFileDetails = *pDetails; // stuff class contents into struct + err = NuAddFile(fpArchive, pDetails->origName /*pathname*/, + &nuFileDetails, false, &recordIdx); - if (err == kNuErrNone) { - fNumAdded++; - } else if (err == kNuErrSkipped) { - /* "maybe overwrite" UI causes this if user declines */ - // fall through with the error - WMSG1("DoAddFile: skipped '%s'\n", pDetails->origName); - } else if (err == kNuErrRecordExists) { - AddClashDialog dlg; + if (err == kNuErrNone) { + fNumAdded++; + } else if (err == kNuErrSkipped) { + /* "maybe overwrite" UI causes this if user declines */ + // fall through with the error + WMSG1("DoAddFile: skipped '%s'\n", pDetails->origName); + } else if (err == kNuErrRecordExists) { + AddClashDialog dlg; - dlg.fWindowsName = pDetails->origName; - dlg.fStorageName = pDetails->storageName; - if (dlg.DoModal() != IDOK) { - err = kNuErrAborted; - goto bail_quiet; - } - if (dlg.fDoRename) { - WMSG1("add clash: rename to '%s'\n", (const char*) dlg.fNewName); - pDetails->storageName = dlg.fNewName; - goto retry; - } else { - WMSG0("add clash: skip"); - err = kNuErrSkipped; - // fall through with error - } - } - //if (err != kNuErrNone) - // goto bail; + dlg.fWindowsName = pDetails->origName; + dlg.fStorageName = pDetails->storageName; + if (dlg.DoModal() != IDOK) { + err = kNuErrAborted; + goto bail_quiet; + } + if (dlg.fDoRename) { + WMSG1("add clash: rename to '%s'\n", (const char*) dlg.fNewName); + pDetails->storageName = dlg.fNewName; + goto retry; + } else { + WMSG0("add clash: skip"); + err = kNuErrSkipped; + // fall through with error + } + } + //if (err != kNuErrNone) + // goto bail; //bail: - if (err != kNuErrNone && err != kNuErrAborted && err != kNuErrSkipped) { - CString msg; - msg.Format("Unable to add file '%s': %s.", pDetails->origName, - NuStrError(err)); - ShowFailureMsg(fpMsgWnd, msg, IDS_FAILED); - } + if (err != kNuErrNone && err != kNuErrAborted && err != kNuErrSkipped) { + CString msg; + msg.Format("Unable to add file '%s': %s.", pDetails->origName, + NuStrError(err)); + ShowFailureMsg(fpMsgWnd, msg, IDS_FAILED); + } bail_quiet: - return err; + return err; } /* @@ -1352,36 +1352,36 @@ bail_quiet: void NufxArchive::AddPrep(CWnd* pMsgWnd, const AddFilesDialog* pAddOpts) { - NuError nerr; - const Preferences* pPreferences = GET_PREFERENCES(); - int defaultCompression; + NuError nerr; + const Preferences* pPreferences = GET_PREFERENCES(); + int defaultCompression; - ASSERT(fpArchive != nil); + ASSERT(fpArchive != nil); - fpMsgWnd = pMsgWnd; - ASSERT(fpMsgWnd != nil); + fpMsgWnd = pMsgWnd; + ASSERT(fpMsgWnd != nil); - fpAddOpts = pAddOpts; - ASSERT(fpAddOpts != nil); + fpAddOpts = pAddOpts; + ASSERT(fpAddOpts != nil); - //fBulkProgress = true; + //fBulkProgress = true; - defaultCompression = pPreferences->GetPrefLong(kPrCompressionType); - nerr = NuSetValue(fpArchive, kNuValueDataCompression, - defaultCompression + kNuCompressNone); - if (nerr != kNuErrNone) { - WMSG1("GLITCH: unable to set compression type to %d\n", - defaultCompression); - /* keep going */ - } + defaultCompression = pPreferences->GetPrefLong(kPrCompressionType); + nerr = NuSetValue(fpArchive, kNuValueDataCompression, + defaultCompression + kNuCompressNone); + if (nerr != kNuErrNone) { + WMSG1("GLITCH: unable to set compression type to %d\n", + defaultCompression); + /* keep going */ + } - if (pAddOpts->fOverwriteExisting) - NuSetValue(fpArchive, kNuValueHandleExisting, kNuAlwaysOverwrite); - else - NuSetValue(fpArchive, kNuValueHandleExisting, kNuMaybeOverwrite); + if (pAddOpts->fOverwriteExisting) + NuSetValue(fpArchive, kNuValueHandleExisting, kNuAlwaysOverwrite); + else + NuSetValue(fpArchive, kNuValueHandleExisting, kNuMaybeOverwrite); NuSetErrorHandler(fpArchive, BulkAddErrorHandler); - NuSetExtraData(fpArchive, this); + NuSetExtraData(fpArchive, this); } /* @@ -1393,10 +1393,10 @@ void NufxArchive::AddFinish(void) { NuSetErrorHandler(fpArchive, nil); - NuSetValue(fpArchive, kNuValueHandleExisting, kNuMaybeOverwrite); - fpMsgWnd = nil; - fpAddOpts = nil; - //fBulkProgress = false; + NuSetValue(fpArchive, kNuValueHandleExisting, kNuMaybeOverwrite); + fpMsgWnd = nil; + fpAddOpts = nil; + //fBulkProgress = false; } @@ -1406,44 +1406,44 @@ NufxArchive::AddFinish(void) /*static*/ NuResult NufxArchive::BulkAddErrorHandler(NuArchive* pArchive, void* vErrorStatus) { - const NuErrorStatus* pErrorStatus = (const NuErrorStatus*)vErrorStatus; - NufxArchive* pThis; - NuResult result; + const NuErrorStatus* pErrorStatus = (const NuErrorStatus*)vErrorStatus; + NufxArchive* pThis; + NuResult result; - ASSERT(pArchive != nil); - (void) NuGetExtraData(pArchive, (void**) &pThis); - ASSERT(pThis != nil); - ASSERT(pArchive == pThis->fpArchive); + ASSERT(pArchive != nil); + (void) NuGetExtraData(pArchive, (void**) &pThis); + ASSERT(pThis != nil); + ASSERT(pArchive == pThis->fpArchive); - /* default action is to abort the current operation */ - result = kNuAbort; + /* default action is to abort the current operation */ + result = kNuAbort; - /* - * When adding files, the NuAddFile and NuAddRecord calls can return - * immediate, specific results for a single add. The only reasons for - * calling here are to decide if an existing record should be replaced - * or not (without even an option to rename), or to decide what to do - * when the NuFlush call runs into a problem while adding a file. - */ - if (pErrorStatus->operation != kNuOpAdd) { - ASSERT(false); - return kNuAbort; - } + /* + * When adding files, the NuAddFile and NuAddRecord calls can return + * immediate, specific results for a single add. The only reasons for + * calling here are to decide if an existing record should be replaced + * or not (without even an option to rename), or to decide what to do + * when the NuFlush call runs into a problem while adding a file. + */ + if (pErrorStatus->operation != kNuOpAdd) { + ASSERT(false); + return kNuAbort; + } - if (pErrorStatus->err == kNuErrRecordExists) { - /* if they want to update or freshen, don't hassle them */ - //if (NState_GetModFreshen(pState) || NState_GetModUpdate(pState)) - if (pThis->fpAddOpts->fOverwriteExisting) { - ASSERT(false); // should be handled by AddPrep()/NufxLib - result = kNuOverwrite; - } else - result = pThis->HandleReplaceExisting(pErrorStatus); - } else if (pErrorStatus->err == kNuErrFileNotFound) { - /* file was specified with NuAdd but removed during NuFlush */ - result = pThis->HandleAddNotFound(pErrorStatus); - } + if (pErrorStatus->err == kNuErrRecordExists) { + /* if they want to update or freshen, don't hassle them */ + //if (NState_GetModFreshen(pState) || NState_GetModUpdate(pState)) + if (pThis->fpAddOpts->fOverwriteExisting) { + ASSERT(false); // should be handled by AddPrep()/NufxLib + result = kNuOverwrite; + } else + result = pThis->HandleReplaceExisting(pErrorStatus); + } else if (pErrorStatus->err == kNuErrFileNotFound) { + /* file was specified with NuAdd but removed during NuFlush */ + result = pThis->HandleAddNotFound(pErrorStatus); + } - return result; + return result; } /* @@ -1453,58 +1453,58 @@ NufxArchive::BulkAddErrorHandler(NuArchive* pArchive, void* vErrorStatus) NuResult NufxArchive::HandleReplaceExisting(const NuErrorStatus* pErrorStatus) { - NuResult result = kNuOK; + NuResult result = kNuOK; - ASSERT(pErrorStatus != nil); - ASSERT(pErrorStatus->pathname != nil); + ASSERT(pErrorStatus != nil); + ASSERT(pErrorStatus->pathname != nil); - ASSERT(pErrorStatus->canOverwrite); - ASSERT(pErrorStatus->canSkip); - ASSERT(pErrorStatus->canAbort); - ASSERT(!pErrorStatus->canRename); + ASSERT(pErrorStatus->canOverwrite); + ASSERT(pErrorStatus->canSkip); + ASSERT(pErrorStatus->canAbort); + ASSERT(!pErrorStatus->canRename); - /* no firm policy, ask the user */ - ConfirmOverwriteDialog confOvwr; - PathName path(pErrorStatus->pathname); - - confOvwr.fExistingFile = pErrorStatus->pRecord->filename; - confOvwr.fExistingFileModWhen = - DateTimeToSeconds(&pErrorStatus->pRecord->recModWhen); - if (pErrorStatus->origPathname != nil) { - confOvwr.fNewFileSource = pErrorStatus->origPathname; - PathName checkPath(confOvwr.fNewFileSource); - confOvwr.fNewFileModWhen = checkPath.GetModWhen(); - } else { - confOvwr.fNewFileSource = "???"; - confOvwr.fNewFileModWhen = kDateNone; - } + /* no firm policy, ask the user */ + ConfirmOverwriteDialog confOvwr; + PathName path(pErrorStatus->pathname); + + confOvwr.fExistingFile = pErrorStatus->pRecord->filename; + confOvwr.fExistingFileModWhen = + DateTimeToSeconds(&pErrorStatus->pRecord->recModWhen); + if (pErrorStatus->origPathname != nil) { + confOvwr.fNewFileSource = pErrorStatus->origPathname; + PathName checkPath(confOvwr.fNewFileSource); + confOvwr.fNewFileModWhen = checkPath.GetModWhen(); + } else { + confOvwr.fNewFileSource = "???"; + confOvwr.fNewFileModWhen = kDateNone; + } - confOvwr.fAllowRename = false; - if (confOvwr.DoModal() == IDCANCEL) { - result = kNuAbort; - goto bail; - } - if (confOvwr.fResultRename) { - ASSERT(false); - result = kNuAbort; - goto bail; - } - if (confOvwr.fResultApplyToAll) { - if (confOvwr.fResultOverwrite) { - (void) NuSetValue(fpArchive, kNuValueHandleExisting, - kNuAlwaysOverwrite); - } else { - (void) NuSetValue(fpArchive, kNuValueHandleExisting, - kNuNeverOverwrite); - } - } - if (confOvwr.fResultOverwrite) - result = kNuOverwrite; - else - result = kNuSkip; + confOvwr.fAllowRename = false; + if (confOvwr.DoModal() == IDCANCEL) { + result = kNuAbort; + goto bail; + } + if (confOvwr.fResultRename) { + ASSERT(false); + result = kNuAbort; + goto bail; + } + if (confOvwr.fResultApplyToAll) { + if (confOvwr.fResultOverwrite) { + (void) NuSetValue(fpArchive, kNuValueHandleExisting, + kNuAlwaysOverwrite); + } else { + (void) NuSetValue(fpArchive, kNuValueHandleExisting, + kNuNeverOverwrite); + } + } + if (confOvwr.fResultOverwrite) + result = kNuOverwrite; + else + result = kNuSkip; bail: - return result; + return result; } /* @@ -1515,19 +1515,19 @@ bail: NuResult NufxArchive::HandleAddNotFound(const NuErrorStatus* pErrorStatus) { - CString errMsg; + CString errMsg; - errMsg.Format("Failed while adding '%s': file no longer exists.", - pErrorStatus->pathname); - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + errMsg.Format("Failed while adding '%s': file no longer exists.", + pErrorStatus->pathname); + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - return kNuAbort; + return kNuAbort; } /* * =========================================================================== - * NufxArchive -- test files + * NufxArchive -- test files * =========================================================================== */ @@ -1537,54 +1537,54 @@ NufxArchive::HandleAddNotFound(const NuErrorStatus* pErrorStatus) bool NufxArchive::TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) { - NuError nerr; - NufxEntry* pEntry; - CString errMsg; - bool retVal = false; + NuError nerr; + NufxEntry* pEntry; + CString errMsg; + bool retVal = false; - ASSERT(fpArchive != nil); + ASSERT(fpArchive != nil); - WMSG1("Testing %d entries\n", pSelSet->GetNumEntries()); + WMSG1("Testing %d entries\n", pSelSet->GetNumEntries()); - SelectionEntry* pSelEntry = pSelSet->IterNext(); - while (pSelEntry != nil) { - pEntry = (NufxEntry*) pSelEntry->GetEntry(); + SelectionEntry* pSelEntry = pSelSet->IterNext(); + while (pSelEntry != nil) { + pEntry = (NufxEntry*) pSelEntry->GetEntry(); - WMSG2(" Testing %ld '%s'\n", pEntry->GetRecordIdx(), - pEntry->GetPathName()); - nerr = NuTestRecord(fpArchive, pEntry->GetRecordIdx()); - if (nerr != kNuErrNone) { - if (nerr == kNuErrAborted) { - CString title; - title.LoadString(IDS_MB_APP_NAME); - errMsg = "Cancelled."; - pMsgWnd->MessageBox(errMsg, title, MB_OK); - } else { - errMsg.Format("Failed while testing '%s': %s.", - pEntry->GetPathName(), NuStrError(nerr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - } - goto bail; - } + WMSG2(" Testing %ld '%s'\n", pEntry->GetRecordIdx(), + pEntry->GetPathName()); + nerr = NuTestRecord(fpArchive, pEntry->GetRecordIdx()); + if (nerr != kNuErrNone) { + if (nerr == kNuErrAborted) { + CString title; + title.LoadString(IDS_MB_APP_NAME); + errMsg = "Cancelled."; + pMsgWnd->MessageBox(errMsg, title, MB_OK); + } else { + errMsg.Format("Failed while testing '%s': %s.", + pEntry->GetPathName(), NuStrError(nerr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + } + goto bail; + } - pSelEntry = pSelSet->IterNext(); - } + pSelEntry = pSelSet->IterNext(); + } - /* show success message */ - errMsg.Format("Tested %d file%s, no errors found.", - pSelSet->GetNumEntries(), - pSelSet->GetNumEntries() == 1 ? "" : "s"); - pMsgWnd->MessageBox(errMsg); - retVal = true; + /* show success message */ + errMsg.Format("Tested %d file%s, no errors found.", + pSelSet->GetNumEntries(), + pSelSet->GetNumEntries() == 1 ? "" : "s"); + pMsgWnd->MessageBox(errMsg); + retVal = true; bail: - return retVal; + return retVal; } /* * =========================================================================== - * NufxArchive -- delete files + * NufxArchive -- delete files * =========================================================================== */ @@ -1594,56 +1594,56 @@ bail: bool NufxArchive::DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) { - NuError nerr; - NufxEntry* pEntry; - CString errMsg; - bool retVal = false; + NuError nerr; + NufxEntry* pEntry; + CString errMsg; + bool retVal = false; - ASSERT(fpArchive != nil); + ASSERT(fpArchive != nil); - WMSG1("Deleting %d entries\n", pSelSet->GetNumEntries()); + WMSG1("Deleting %d entries\n", pSelSet->GetNumEntries()); - /* mark entries for deletion */ - SelectionEntry* pSelEntry = pSelSet->IterNext(); - while (pSelEntry != nil) { - pEntry = (NufxEntry*) pSelEntry->GetEntry(); + /* mark entries for deletion */ + SelectionEntry* pSelEntry = pSelSet->IterNext(); + while (pSelEntry != nil) { + pEntry = (NufxEntry*) pSelEntry->GetEntry(); - WMSG2(" Deleting %ld '%s'\n", pEntry->GetRecordIdx(), - pEntry->GetPathName()); - nerr = NuDeleteRecord(fpArchive, pEntry->GetRecordIdx()); - if (nerr != kNuErrNone) { - errMsg.Format("Unable to delete record %d: %s.", - pEntry->GetRecordIdx(), NuStrError(nerr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } + WMSG2(" Deleting %ld '%s'\n", pEntry->GetRecordIdx(), + pEntry->GetPathName()); + nerr = NuDeleteRecord(fpArchive, pEntry->GetRecordIdx()); + if (nerr != kNuErrNone) { + errMsg.Format("Unable to delete record %d: %s.", + pEntry->GetRecordIdx(), NuStrError(nerr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } - pSelEntry = pSelSet->IterNext(); - } + pSelEntry = pSelSet->IterNext(); + } - /* actually do the delete */ - long statusFlags; - nerr = NuFlush(fpArchive, &statusFlags); - if (nerr != kNuErrNone) { - errMsg.Format("Unable to delete all files: %s.", NuStrError(nerr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + /* actually do the delete */ + long statusFlags; + nerr = NuFlush(fpArchive, &statusFlags); + if (nerr != kNuErrNone) { + errMsg.Format("Unable to delete all files: %s.", NuStrError(nerr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - /* see if it got converted to read-only status */ - if (statusFlags & kNuFlushReadOnly) - fIsReadOnly = true; - } + /* see if it got converted to read-only status */ + if (statusFlags & kNuFlushReadOnly) + fIsReadOnly = true; + } - if (InternalReload(fpMsgWnd) == kNuErrNone) - retVal = true; + if (InternalReload(fpMsgWnd) == kNuErrNone) + retVal = true; bail: - return retVal; + return retVal; } /* * =========================================================================== - * NufxArchive -- rename files + * NufxArchive -- rename files * =========================================================================== */ @@ -1653,92 +1653,92 @@ bail: bool NufxArchive::RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) { - CString errMsg; - NuError nerr; - bool retVal = false; + CString errMsg; + NuError nerr; + bool retVal = false; - ASSERT(fpArchive != nil); + ASSERT(fpArchive != nil); - WMSG1("Renaming %d entries\n", pSelSet->GetNumEntries()); + WMSG1("Renaming %d entries\n", pSelSet->GetNumEntries()); - /* - * Figure out if we're allowed to change the entire path. (This is - * doing it the hard way, but what the hell.) - */ - long cap = GetCapability(GenericArchive::kCapCanRenameFullPath); - bool renameFullPath = (cap != 0); + /* + * Figure out if we're allowed to change the entire path. (This is + * doing it the hard way, but what the hell.) + */ + long cap = GetCapability(GenericArchive::kCapCanRenameFullPath); + bool renameFullPath = (cap != 0); - WMSG1("Rename, fullpath=%d\n", renameFullPath); + WMSG1("Rename, fullpath=%d\n", renameFullPath); - /* - * For each item in the selection set, bring up the "rename" dialog, - * and ask the GenericEntry to process it. - * - * If they hit "cancel" or there's an error, we still flush the - * previous changes. This is so that we don't have to create the - * same sort of deferred-write feature when renaming things in other - * sorts of archives (e.g. disk archives). - */ - SelectionEntry* pSelEntry = pSelSet->IterNext(); - while (pSelEntry != nil) { - NufxEntry* pEntry = (NufxEntry*) pSelEntry->GetEntry(); - WMSG1(" Renaming '%s'\n", pEntry->GetPathName()); + /* + * For each item in the selection set, bring up the "rename" dialog, + * and ask the GenericEntry to process it. + * + * If they hit "cancel" or there's an error, we still flush the + * previous changes. This is so that we don't have to create the + * same sort of deferred-write feature when renaming things in other + * sorts of archives (e.g. disk archives). + */ + SelectionEntry* pSelEntry = pSelSet->IterNext(); + while (pSelEntry != nil) { + NufxEntry* pEntry = (NufxEntry*) pSelEntry->GetEntry(); + WMSG1(" Renaming '%s'\n", pEntry->GetPathName()); - RenameEntryDialog renameDlg(pMsgWnd); - renameDlg.SetCanRenameFullPath(renameFullPath); - renameDlg.SetCanChangeFssep(true); - renameDlg.fOldName = pEntry->GetPathName(); - renameDlg.fFssep = pEntry->GetFssep(); - renameDlg.fpArchive = this; - renameDlg.fpEntry = pEntry; + RenameEntryDialog renameDlg(pMsgWnd); + renameDlg.SetCanRenameFullPath(renameFullPath); + renameDlg.SetCanChangeFssep(true); + renameDlg.fOldName = pEntry->GetPathName(); + renameDlg.fFssep = pEntry->GetFssep(); + renameDlg.fpArchive = this; + renameDlg.fpEntry = pEntry; - int result = renameDlg.DoModal(); - if (result == IDOK) { - if (renameDlg.fFssep == '\0') - renameDlg.fFssep = kNufxNoFssep; - nerr = NuRename(fpArchive, pEntry->GetRecordIdx(), - renameDlg.fNewName, renameDlg.fFssep); - if (nerr != kNuErrNone) { - errMsg.Format("Unable to rename '%s': %s.", pEntry->GetPathName(), - NuStrError(nerr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - break; - } - WMSG2("Rename of '%s' to '%s' succeeded\n", - pEntry->GetDisplayName(), renameDlg.fNewName); - } else if (result == IDCANCEL) { - WMSG0("Canceling out of remaining renames\n"); - break; - } else { - /* 3rd possibility is IDIGNORE, i.e. skip this entry */ - WMSG1("Skipping rename of '%s'\n", pEntry->GetDisplayName()); - } + int result = renameDlg.DoModal(); + if (result == IDOK) { + if (renameDlg.fFssep == '\0') + renameDlg.fFssep = kNufxNoFssep; + nerr = NuRename(fpArchive, pEntry->GetRecordIdx(), + renameDlg.fNewName, renameDlg.fFssep); + if (nerr != kNuErrNone) { + errMsg.Format("Unable to rename '%s': %s.", pEntry->GetPathName(), + NuStrError(nerr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + break; + } + WMSG2("Rename of '%s' to '%s' succeeded\n", + pEntry->GetDisplayName(), renameDlg.fNewName); + } else if (result == IDCANCEL) { + WMSG0("Canceling out of remaining renames\n"); + break; + } else { + /* 3rd possibility is IDIGNORE, i.e. skip this entry */ + WMSG1("Skipping rename of '%s'\n", pEntry->GetDisplayName()); + } - pSelEntry = pSelSet->IterNext(); - } + pSelEntry = pSelSet->IterNext(); + } - /* flush pending rename calls */ - { - CWaitCursor waitc; + /* flush pending rename calls */ + { + CWaitCursor waitc; - long statusFlags; - nerr = NuFlush(fpArchive, &statusFlags); - if (nerr != kNuErrNone) { - errMsg.Format("Unable to rename all files: %s.", - NuStrError(nerr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + long statusFlags; + nerr = NuFlush(fpArchive, &statusFlags); + if (nerr != kNuErrNone) { + errMsg.Format("Unable to rename all files: %s.", + NuStrError(nerr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - /* see if it got converted to read-only status */ - if (statusFlags & kNuFlushReadOnly) - fIsReadOnly = true; - } - } + /* see if it got converted to read-only status */ + if (statusFlags & kNuFlushReadOnly) + fIsReadOnly = true; + } + } - /* reload GenericArchive from NufxLib */ - if (InternalReload(fpMsgWnd) == kNuErrNone) - retVal = true; + /* reload GenericArchive from NufxLib */ + if (InternalReload(fpMsgWnd) == kNuErrNone) + retVal = true; - return retVal; + return retVal; } @@ -1751,56 +1751,56 @@ NufxArchive::RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet) */ CString NufxArchive::TestPathName(const GenericEntry* pGenericEntry, - const CString& basePath, const CString& newName, char newFssep) const + const CString& basePath, const CString& newName, char newFssep) const { - CString errMsg(""); - ASSERT(pGenericEntry != nil); + CString errMsg(""); + ASSERT(pGenericEntry != nil); - ASSERT(basePath.IsEmpty()); + ASSERT(basePath.IsEmpty()); - /* can't start or end with fssep */ - if (newName.Left(1) == newFssep || newName.Right(1) == newFssep) { - errMsg.Format("Names in NuFX archives may not start or end with a " - "path separator character (%c).", - newFssep); - goto bail; - } + /* can't start or end with fssep */ + if (newName.Left(1) == newFssep || newName.Right(1) == newFssep) { + errMsg.Format("Names in NuFX archives may not start or end with a " + "path separator character (%c).", + newFssep); + goto bail; + } - /* if it's a disk image, don't allow complex paths */ - if (pGenericEntry->GetRecordKind() == GenericEntry::kRecordKindDisk) { - if (newName.Find(newFssep) != -1) { - errMsg.Format("Disk image names may not contain a path separator " - "character (%c).", - newFssep); - goto bail; - } - } + /* if it's a disk image, don't allow complex paths */ + if (pGenericEntry->GetRecordKind() == GenericEntry::kRecordKindDisk) { + if (newName.Find(newFssep) != -1) { + errMsg.Format("Disk image names may not contain a path separator " + "character (%c).", + newFssep); + goto bail; + } + } - /* - * Test for case-sensitive name collisions. Each individual path - * component must be compared - */ - GenericEntry* pEntry; - pEntry = GetEntries(); - while (pEntry != nil) { - if (pEntry != pGenericEntry && - ComparePaths(pEntry->GetPathName(), pEntry->GetFssep(), - newName, newFssep) == 0) - { - errMsg.Format("An entry with that name already exists."); - } + /* + * Test for case-sensitive name collisions. Each individual path + * component must be compared + */ + GenericEntry* pEntry; + pEntry = GetEntries(); + while (pEntry != nil) { + if (pEntry != pGenericEntry && + ComparePaths(pEntry->GetPathName(), pEntry->GetFssep(), + newName, newFssep) == 0) + { + errMsg.Format("An entry with that name already exists."); + } - pEntry = pEntry->GetNext(); - } + pEntry = pEntry->GetNext(); + } bail: - return errMsg; + return errMsg; } /* * =========================================================================== - * NufxArchive -- recompress + * NufxArchive -- recompress * =========================================================================== */ @@ -1820,126 +1820,126 @@ bail: */ bool NufxArchive::RecompressSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, - const RecompressOptionsDialog* pRecompOpts) + const RecompressOptionsDialog* pRecompOpts) { - const int kMaxSizeInMemory = 2 * 1024 * 1024; // 2MB - CString errMsg; - NuError nerr; - bool retVal = false; + const int kMaxSizeInMemory = 2 * 1024 * 1024; // 2MB + CString errMsg; + NuError nerr; + bool retVal = false; - /* set the compression type */ - nerr = NuSetValue(fpArchive, kNuValueDataCompression, - pRecompOpts->fCompressionType + kNuCompressNone); - if (nerr != kNuErrNone) { - WMSG1("GLITCH: unable to set compression type to %d\n", - pRecompOpts->fCompressionType); - /* keep going */ - } + /* set the compression type */ + nerr = NuSetValue(fpArchive, kNuValueDataCompression, + pRecompOpts->fCompressionType + kNuCompressNone); + if (nerr != kNuErrNone) { + WMSG1("GLITCH: unable to set compression type to %d\n", + pRecompOpts->fCompressionType); + /* keep going */ + } - fProgressAsRecompress = true; + fProgressAsRecompress = true; - /* - * Loop over all items in the selection set. Because the selection - * set has one entry for each interesting thread, we don't need to - * pry the NuRecord open and play with it. - * - * We should only be here for data forks, resource forks, and disk - * images. Comments and filenames are not compressed, and so cannot - * be recompressed. - */ - SelectionEntry* pSelEntry = pSelSet->IterNext(); - long sizeInMemory = 0; - bool result = true; - NufxEntry* pEntry = nil; - for ( ; pSelEntry != nil; pSelEntry = pSelSet->IterNext()) { - pEntry = (NufxEntry*) pSelEntry->GetEntry(); + /* + * Loop over all items in the selection set. Because the selection + * set has one entry for each interesting thread, we don't need to + * pry the NuRecord open and play with it. + * + * We should only be here for data forks, resource forks, and disk + * images. Comments and filenames are not compressed, and so cannot + * be recompressed. + */ + SelectionEntry* pSelEntry = pSelSet->IterNext(); + long sizeInMemory = 0; + bool result = true; + NufxEntry* pEntry = nil; + for ( ; pSelEntry != nil; pSelEntry = pSelSet->IterNext()) { + pEntry = (NufxEntry*) pSelEntry->GetEntry(); - /* - * Compress each thread in turn. - */ - if (pEntry->GetHasDataFork()) { - result = RecompressThread(pEntry, GenericEntry::kDataThread, - pRecompOpts, &sizeInMemory, &errMsg); - if (!result) - break; - } - if (pEntry->GetHasRsrcFork()) { - result = RecompressThread(pEntry, GenericEntry::kRsrcThread, - pRecompOpts, &sizeInMemory, &errMsg); - if (!result) - break; - } - if (pEntry->GetHasDiskImage()) { - result = RecompressThread(pEntry, GenericEntry::kDiskImageThread, - pRecompOpts, &sizeInMemory, &errMsg); - if (!result) - break; - } - /* don't do anything with comments */ + /* + * Compress each thread in turn. + */ + if (pEntry->GetHasDataFork()) { + result = RecompressThread(pEntry, GenericEntry::kDataThread, + pRecompOpts, &sizeInMemory, &errMsg); + if (!result) + break; + } + if (pEntry->GetHasRsrcFork()) { + result = RecompressThread(pEntry, GenericEntry::kRsrcThread, + pRecompOpts, &sizeInMemory, &errMsg); + if (!result) + break; + } + if (pEntry->GetHasDiskImage()) { + result = RecompressThread(pEntry, GenericEntry::kDiskImageThread, + pRecompOpts, &sizeInMemory, &errMsg); + if (!result) + break; + } + /* don't do anything with comments */ - /* if we're sitting on too much, push it out */ - if (sizeInMemory > kMaxSizeInMemory) { - /* flush anything pending */ - long statusFlags; - nerr = NuFlush(fpArchive, &statusFlags); - if (nerr != kNuErrNone) { - if (nerr != kNuErrAborted) { - errMsg.Format("Unable to recompress all files: %s.", - NuStrError(nerr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - } else { - WMSG0("Cancelled out of sub-flush/compress\n"); - } + /* if we're sitting on too much, push it out */ + if (sizeInMemory > kMaxSizeInMemory) { + /* flush anything pending */ + long statusFlags; + nerr = NuFlush(fpArchive, &statusFlags); + if (nerr != kNuErrNone) { + if (nerr != kNuErrAborted) { + errMsg.Format("Unable to recompress all files: %s.", + NuStrError(nerr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + } else { + WMSG0("Cancelled out of sub-flush/compress\n"); + } - /* see if it got converted to read-only status */ - if (statusFlags & kNuFlushReadOnly) - fIsReadOnly = true; + /* see if it got converted to read-only status */ + if (statusFlags & kNuFlushReadOnly) + fIsReadOnly = true; - goto bail; - } + goto bail; + } - sizeInMemory = 0; - } - } + sizeInMemory = 0; + } + } - /* handle errors that threw us out of the while loop */ - if (!result) { - ASSERT(pEntry != nil); - CString dispStr; - dispStr.Format("Failed while recompressing '%s': %s.", - pEntry->GetDisplayName(), errMsg); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } + /* handle errors that threw us out of the while loop */ + if (!result) { + ASSERT(pEntry != nil); + CString dispStr; + dispStr.Format("Failed while recompressing '%s': %s.", + pEntry->GetDisplayName(), errMsg); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } - /* flush anything pending */ - long statusFlags; - nerr = NuFlush(fpArchive, &statusFlags); - if (nerr != kNuErrNone) { - if (nerr != kNuErrAborted) { - errMsg.Format("Unable to recompress all files: %s.", - NuStrError(nerr)); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - } else { - WMSG0("Cancelled out of flush/compress\n"); - } + /* flush anything pending */ + long statusFlags; + nerr = NuFlush(fpArchive, &statusFlags); + if (nerr != kNuErrNone) { + if (nerr != kNuErrAborted) { + errMsg.Format("Unable to recompress all files: %s.", + NuStrError(nerr)); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + } else { + WMSG0("Cancelled out of flush/compress\n"); + } - /* see if it got converted to read-only status */ - if (statusFlags & kNuFlushReadOnly) - fIsReadOnly = true; - } else { - retVal = true; - } + /* see if it got converted to read-only status */ + if (statusFlags & kNuFlushReadOnly) + fIsReadOnly = true; + } else { + retVal = true; + } bail: - /* abort anything that didn't get flushed */ - NuAbort(fpArchive); - /* reload to pick up changes */ - (void) InternalReload(pMsgWnd); + /* abort anything that didn't get flushed */ + NuAbort(fpArchive); + /* reload to pick up changes */ + (void) InternalReload(pMsgWnd); - fProgressAsRecompress = false; - return retVal; + fProgressAsRecompress = false; + return retVal; } /* @@ -1949,94 +1949,94 @@ bail: */ bool NufxArchive::RecompressThread(NufxEntry* pEntry, int threadKind, - const RecompressOptionsDialog* pRecompOpts, long* pSizeInMemory, - CString* pErrMsg) + const RecompressOptionsDialog* pRecompOpts, long* pSizeInMemory, + CString* pErrMsg) { - NuThread thread; - NuThreadID threadID; - NuError nerr; - NuDataSource* pSource = nil; - CString subErrMsg; - bool retVal = false; - char* buf = nil; - long len = 0; + NuThread thread; + NuThreadID threadID; + NuError nerr; + NuDataSource* pSource = nil; + CString subErrMsg; + bool retVal = false; + char* buf = nil; + long len = 0; - WMSG2(" Recompressing %ld '%s'\n", pEntry->GetRecordIdx(), - pEntry->GetDisplayName()); + WMSG2(" Recompressing %ld '%s'\n", pEntry->GetRecordIdx(), + pEntry->GetDisplayName()); - /* get a copy of the thread header */ - pEntry->FindThreadInfo(threadKind, &thread, pErrMsg); - if (!pErrMsg->IsEmpty()) { - pErrMsg->Format("Unable to locate thread for %s (type %d)", - pEntry->GetDisplayName(), threadKind); - goto bail; - } - threadID = NuGetThreadID(&thread); + /* get a copy of the thread header */ + pEntry->FindThreadInfo(threadKind, &thread, pErrMsg); + if (!pErrMsg->IsEmpty()) { + pErrMsg->Format("Unable to locate thread for %s (type %d)", + pEntry->GetDisplayName(), threadKind); + goto bail; + } + threadID = NuGetThreadID(&thread); - /* if it's already in the target format, skip it */ - if (thread.thThreadFormat == pRecompOpts->fCompressionType) { - WMSG2("Skipping (fmt=%d) '%s'\n", - pRecompOpts->fCompressionType, pEntry->GetDisplayName()); - return true; - } + /* if it's already in the target format, skip it */ + if (thread.thThreadFormat == pRecompOpts->fCompressionType) { + WMSG2("Skipping (fmt=%d) '%s'\n", + pRecompOpts->fCompressionType, pEntry->GetDisplayName()); + return true; + } - /* extract the thread */ - int result; - result = pEntry->ExtractThreadToBuffer(threadKind, &buf, &len, &subErrMsg); - if (result == IDCANCEL) { - WMSG0("Cancelled during extract!\n"); - ASSERT(buf == nil); - goto bail; /* abort anything that was pending */ - } else if (result != IDOK) { - pErrMsg->Format("Failed while extracting '%s': %s", - pEntry->GetDisplayName(), subErrMsg); - goto bail; - } - *pSizeInMemory += len; + /* extract the thread */ + int result; + result = pEntry->ExtractThreadToBuffer(threadKind, &buf, &len, &subErrMsg); + if (result == IDCANCEL) { + WMSG0("Cancelled during extract!\n"); + ASSERT(buf == nil); + goto bail; /* abort anything that was pending */ + } else if (result != IDOK) { + pErrMsg->Format("Failed while extracting '%s': %s", + pEntry->GetDisplayName(), subErrMsg); + goto bail; + } + *pSizeInMemory += len; - /* create a data source for it */ - nerr = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, - 0, (const unsigned char*)buf, 0, len, ArrayDeleteHandler, - &pSource); - if (nerr != kNuErrNone) { - pErrMsg->Format("Unable to create NufxLib data source (len=%d).", - len); - goto bail; - } - buf = nil; // data source owns it now + /* create a data source for it */ + nerr = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, + 0, (const unsigned char*)buf, 0, len, ArrayDeleteHandler, + &pSource); + if (nerr != kNuErrNone) { + pErrMsg->Format("Unable to create NufxLib data source (len=%d).", + len); + goto bail; + } + buf = nil; // data source owns it now - /* delete the existing thread */ - //WMSG1("+++ DELETE threadIdx=%d\n", thread.threadIdx); - nerr = NuDeleteThread(fpArchive, thread.threadIdx); - if (nerr != kNuErrNone) { - pErrMsg->Format("Unable to delete thread %d: %s", - pEntry->GetRecordIdx(), NuStrError(nerr)); - goto bail; - } + /* delete the existing thread */ + //WMSG1("+++ DELETE threadIdx=%d\n", thread.threadIdx); + nerr = NuDeleteThread(fpArchive, thread.threadIdx); + if (nerr != kNuErrNone) { + pErrMsg->Format("Unable to delete thread %d: %s", + pEntry->GetRecordIdx(), NuStrError(nerr)); + goto bail; + } - /* mark the new thread for addition */ - //WMSG1("+++ ADD threadID=0x%08lx\n", threadID); - nerr = NuAddThread(fpArchive, pEntry->GetRecordIdx(), threadID, - pSource, nil); - if (nerr != kNuErrNone) { - pErrMsg->Format("Unable to add thread type %d: %s", - threadID, NuStrError(nerr)); - goto bail; - } - pSource = nil; // now owned by nufxlib + /* mark the new thread for addition */ + //WMSG1("+++ ADD threadID=0x%08lx\n", threadID); + nerr = NuAddThread(fpArchive, pEntry->GetRecordIdx(), threadID, + pSource, nil); + if (nerr != kNuErrNone) { + pErrMsg->Format("Unable to add thread type %d: %s", + threadID, NuStrError(nerr)); + goto bail; + } + pSource = nil; // now owned by nufxlib - /* at this point, we just wait for the flush in the outer loop */ - retVal = true; + /* at this point, we just wait for the flush in the outer loop */ + retVal = true; bail: - NuFreeDataSource(pSource); - return retVal; + NuFreeDataSource(pSource); + return retVal; } /* * =========================================================================== - * NufxArchive -- transfer files to another archive + * NufxArchive -- transfer files to another archive * =========================================================================== */ @@ -2050,164 +2050,164 @@ bail: */ GenericArchive::XferStatus NufxArchive::XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, - ActionProgressDialog* pActionProgress, const XferFileOptions* pXferOpts) + ActionProgressDialog* pActionProgress, const XferFileOptions* pXferOpts) { - WMSG0("NufxArchive XferSelection!\n"); - XferStatus retval = kXferFailed; - unsigned char* dataBuf = nil; - unsigned char* rsrcBuf = nil; - CString errMsg, dispMsg; + WMSG0("NufxArchive XferSelection!\n"); + XferStatus retval = kXferFailed; + unsigned char* dataBuf = nil; + unsigned char* rsrcBuf = nil; + CString errMsg, dispMsg; - pXferOpts->fTarget->XferPrepare(pXferOpts); + pXferOpts->fTarget->XferPrepare(pXferOpts); - SelectionEntry* pSelEntry = pSelSet->IterNext(); - for ( ; pSelEntry != nil; pSelEntry = pSelSet->IterNext()) { - long dataLen=-1, rsrcLen=-1; - NufxEntry* pEntry = (NufxEntry*) pSelEntry->GetEntry(); - FileDetails fileDetails; - CString errMsg; + SelectionEntry* pSelEntry = pSelSet->IterNext(); + for ( ; pSelEntry != nil; pSelEntry = pSelSet->IterNext()) { + long dataLen=-1, rsrcLen=-1; + NufxEntry* pEntry = (NufxEntry*) pSelEntry->GetEntry(); + FileDetails fileDetails; + CString errMsg; - ASSERT(dataBuf == nil); - ASSERT(rsrcBuf == nil); + ASSERT(dataBuf == nil); + ASSERT(rsrcBuf == nil); - /* in case we start handling CRC errors better */ - if (pEntry->GetDamaged()) { - WMSG1(" XFER skipping damaged entry '%s'\n", - pEntry->GetDisplayName()); - continue; - } + /* in case we start handling CRC errors better */ + if (pEntry->GetDamaged()) { + WMSG1(" XFER skipping damaged entry '%s'\n", + pEntry->GetDisplayName()); + continue; + } - WMSG1(" XFER converting '%s'\n", pEntry->GetDisplayName()); + WMSG1(" XFER converting '%s'\n", pEntry->GetDisplayName()); - fileDetails.storageName = pEntry->GetDisplayName(); - fileDetails.fileType = pEntry->GetFileType(); - fileDetails.fileSysFmt = DiskImg::kFormatUnknown; - fileDetails.fileSysInfo = PathProposal::kDefaultStoredFssep; - fileDetails.access = pEntry->GetAccess(); - fileDetails.extraType = pEntry->GetAuxType(); - fileDetails.storageType = kNuStorageSeedling; + fileDetails.storageName = pEntry->GetDisplayName(); + fileDetails.fileType = pEntry->GetFileType(); + fileDetails.fileSysFmt = DiskImg::kFormatUnknown; + fileDetails.fileSysInfo = PathProposal::kDefaultStoredFssep; + fileDetails.access = pEntry->GetAccess(); + fileDetails.extraType = pEntry->GetAuxType(); + fileDetails.storageType = kNuStorageSeedling; - time_t when; - when = time(nil); - UNIXTimeToDateTime(&when, &fileDetails.archiveWhen); - when = pEntry->GetModWhen(); - UNIXTimeToDateTime(&when, &fileDetails.modWhen); - when = pEntry->GetCreateWhen(); - UNIXTimeToDateTime(&when, &fileDetails.createWhen); + time_t when; + when = time(nil); + UNIXTimeToDateTime(&when, &fileDetails.archiveWhen); + when = pEntry->GetModWhen(); + UNIXTimeToDateTime(&when, &fileDetails.modWhen); + when = pEntry->GetCreateWhen(); + UNIXTimeToDateTime(&when, &fileDetails.createWhen); - pActionProgress->SetArcName(fileDetails.storageName); - if (pActionProgress->SetProgress(0) == IDCANCEL) { - retval = kXferCancelled; - goto bail; - } + pActionProgress->SetArcName(fileDetails.storageName); + if (pActionProgress->SetProgress(0) == IDCANCEL) { + retval = kXferCancelled; + goto bail; + } - /* - * Handle all relevant threads in this record. We assume it's either - * a data/rsrc pair or a disk image. - */ - if (pEntry->GetHasDataFork()) { - /* - * Found a data thread. - */ - int result; - dataBuf = nil; - dataLen = 0; - result = pEntry->ExtractThreadToBuffer(GenericEntry::kDataThread, - (char**) &dataBuf, &dataLen, &errMsg); - if (result == IDCANCEL) { - WMSG0("Cancelled during data extract!\n"); - retval = kXferCancelled; - goto bail; /* abort anything that was pending */ - } else if (result != IDOK) { - dispMsg.Format("Failed while extracting '%s': %s.", - pEntry->GetDisplayName(), errMsg); - ShowFailureMsg(pMsgWnd, dispMsg, IDS_FAILED); - goto bail; - } - ASSERT(dataBuf != nil); - ASSERT(dataLen >= 0); + /* + * Handle all relevant threads in this record. We assume it's either + * a data/rsrc pair or a disk image. + */ + if (pEntry->GetHasDataFork()) { + /* + * Found a data thread. + */ + int result; + dataBuf = nil; + dataLen = 0; + result = pEntry->ExtractThreadToBuffer(GenericEntry::kDataThread, + (char**) &dataBuf, &dataLen, &errMsg); + if (result == IDCANCEL) { + WMSG0("Cancelled during data extract!\n"); + retval = kXferCancelled; + goto bail; /* abort anything that was pending */ + } else if (result != IDOK) { + dispMsg.Format("Failed while extracting '%s': %s.", + pEntry->GetDisplayName(), errMsg); + ShowFailureMsg(pMsgWnd, dispMsg, IDS_FAILED); + goto bail; + } + ASSERT(dataBuf != nil); + ASSERT(dataLen >= 0); - } else if (pEntry->GetHasDiskImage()) { - /* - * No data thread found. Look for a disk image. - */ - int result; - dataBuf = nil; - dataLen = 0; - result = pEntry->ExtractThreadToBuffer(GenericEntry::kDiskImageThread, - (char**) &dataBuf, &dataLen, &errMsg); - if (result == IDCANCEL) { - WMSG0("Cancelled during data extract!\n"); - goto bail; /* abort anything that was pending */ - } else if (result != IDOK) { - dispMsg.Format("Failed while extracting '%s': %s.", - pEntry->GetDisplayName(), errMsg); - ShowFailureMsg(pMsgWnd, dispMsg, IDS_FAILED); - goto bail; - } - ASSERT(dataBuf != nil); - ASSERT(dataLen >= 0); - } + } else if (pEntry->GetHasDiskImage()) { + /* + * No data thread found. Look for a disk image. + */ + int result; + dataBuf = nil; + dataLen = 0; + result = pEntry->ExtractThreadToBuffer(GenericEntry::kDiskImageThread, + (char**) &dataBuf, &dataLen, &errMsg); + if (result == IDCANCEL) { + WMSG0("Cancelled during data extract!\n"); + goto bail; /* abort anything that was pending */ + } else if (result != IDOK) { + dispMsg.Format("Failed while extracting '%s': %s.", + pEntry->GetDisplayName(), errMsg); + ShowFailureMsg(pMsgWnd, dispMsg, IDS_FAILED); + goto bail; + } + ASSERT(dataBuf != nil); + ASSERT(dataLen >= 0); + } - /* - * See if there's a resource fork in here (either by itself or - * with a data fork). - */ - if (pEntry->GetHasRsrcFork()) { - int result; - rsrcBuf = nil; - rsrcLen = 0; - result = pEntry->ExtractThreadToBuffer(GenericEntry::kRsrcThread, - (char**) &rsrcBuf, &rsrcLen, &errMsg); - if (result == IDCANCEL) { - WMSG0("Cancelled during rsrc extract!\n"); - goto bail; /* abort anything that was pending */ - } else if (result != IDOK) { - dispMsg.Format("Failed while extracting '%s': %s.", - pEntry->GetDisplayName(), errMsg); - ShowFailureMsg(pMsgWnd, dispMsg, IDS_FAILED); - goto bail; - } + /* + * See if there's a resource fork in here (either by itself or + * with a data fork). + */ + if (pEntry->GetHasRsrcFork()) { + int result; + rsrcBuf = nil; + rsrcLen = 0; + result = pEntry->ExtractThreadToBuffer(GenericEntry::kRsrcThread, + (char**) &rsrcBuf, &rsrcLen, &errMsg); + if (result == IDCANCEL) { + WMSG0("Cancelled during rsrc extract!\n"); + goto bail; /* abort anything that was pending */ + } else if (result != IDOK) { + dispMsg.Format("Failed while extracting '%s': %s.", + pEntry->GetDisplayName(), errMsg); + ShowFailureMsg(pMsgWnd, dispMsg, IDS_FAILED); + goto bail; + } - fileDetails.storageType = kNuStorageExtended; - } else { - ASSERT(rsrcBuf == nil); - } + fileDetails.storageType = kNuStorageExtended; + } else { + ASSERT(rsrcBuf == nil); + } - if (dataLen < 0 && rsrcLen < 0) { - WMSG1(" XFER: WARNING: nothing worth transferring in '%s'\n", - pEntry->GetDisplayName()); - continue; - } + if (dataLen < 0 && rsrcLen < 0) { + WMSG1(" XFER: WARNING: nothing worth transferring in '%s'\n", + pEntry->GetDisplayName()); + continue; + } - errMsg = pXferOpts->fTarget->XferFile(&fileDetails, &dataBuf, dataLen, - &rsrcBuf, rsrcLen); - if (!errMsg.IsEmpty()) { - WMSG0("XferFile failed!\n"); - errMsg.Format("Failed while transferring '%s': %s.", - pEntry->GetDisplayName(), (const char*) errMsg); - ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - ASSERT(dataBuf == nil); - ASSERT(rsrcBuf == nil); + errMsg = pXferOpts->fTarget->XferFile(&fileDetails, &dataBuf, dataLen, + &rsrcBuf, rsrcLen); + if (!errMsg.IsEmpty()) { + WMSG0("XferFile failed!\n"); + errMsg.Format("Failed while transferring '%s': %s.", + pEntry->GetDisplayName(), (const char*) errMsg); + ShowFailureMsg(pMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + ASSERT(dataBuf == nil); + ASSERT(rsrcBuf == nil); - if (pActionProgress->SetProgress(100) == IDCANCEL) { - retval = kXferCancelled; - goto bail; - } - } + if (pActionProgress->SetProgress(100) == IDCANCEL) { + retval = kXferCancelled; + goto bail; + } + } - retval = kXferOK; + retval = kXferOK; bail: - if (retval != kXferOK) - pXferOpts->fTarget->XferAbort(pMsgWnd); - else - pXferOpts->fTarget->XferFinish(pMsgWnd); - delete[] dataBuf; - delete[] rsrcBuf; - return retval; + if (retval != kXferOK) + pXferOpts->fTarget->XferAbort(pMsgWnd); + else + pXferOpts->fTarget->XferFinish(pMsgWnd); + delete[] dataBuf; + delete[] rsrcBuf; + return retval; } /* @@ -2219,8 +2219,8 @@ bail: void NufxArchive::XferPrepare(const XferFileOptions* pXferOpts) { - WMSG0(" NufxArchive::XferPrepare\n"); - (void) NuSetValue(fpArchive, kNuValueAllowDuplicates, true); + WMSG0(" NufxArchive::XferPrepare\n"); + (void) NuSetValue(fpArchive, kNuValueAllowDuplicates, true); } /* @@ -2235,136 +2235,136 @@ NufxArchive::XferPrepare(const XferFileOptions* pXferOpts) */ CString NufxArchive::XferFile(FileDetails* pDetails, unsigned char** pDataBuf, - long dataLen, unsigned char** pRsrcBuf, long rsrcLen) + long dataLen, unsigned char** pRsrcBuf, long rsrcLen) { - NuError nerr; - const int kFileTypeTXT = 0x04; - NuDataSource* pSource = nil; - CString errMsg; + NuError nerr; + const int kFileTypeTXT = 0x04; + NuDataSource* pSource = nil; + CString errMsg; - WMSG1(" NufxArchive::XferFile '%s'\n", pDetails->storageName); - WMSG4(" dataBuf=0x%08lx dataLen=%ld rsrcBuf=0x%08lx rsrcLen=%ld\n", - *pDataBuf, dataLen, *pRsrcBuf, rsrcLen); - ASSERT(pDataBuf != nil); - ASSERT(pRsrcBuf != nil); + WMSG1(" NufxArchive::XferFile '%s'\n", pDetails->storageName); + WMSG4(" dataBuf=0x%08lx dataLen=%ld rsrcBuf=0x%08lx rsrcLen=%ld\n", + *pDataBuf, dataLen, *pRsrcBuf, rsrcLen); + ASSERT(pDataBuf != nil); + ASSERT(pRsrcBuf != nil); - /* NuFX doesn't explicitly store directories */ - if (pDetails->entryKind == FileDetails::kFileKindDirectory) { - delete[] *pDataBuf; - delete[] *pRsrcBuf; - *pDataBuf = *pRsrcBuf = nil; - goto bail; - } + /* NuFX doesn't explicitly store directories */ + if (pDetails->entryKind == FileDetails::kFileKindDirectory) { + delete[] *pDataBuf; + delete[] *pRsrcBuf; + *pDataBuf = *pRsrcBuf = nil; + goto bail; + } - ASSERT(dataLen >= 0 || rsrcLen >= 0); - ASSERT(*pDataBuf != nil || *pRsrcBuf != nil); + ASSERT(dataLen >= 0 || rsrcLen >= 0); + ASSERT(*pDataBuf != nil || *pRsrcBuf != nil); - /* add the record; we have "allow duplicates" enabled for clashes */ - NuRecordIdx recordIdx; - NuFileDetails nuFileDetails; - nuFileDetails = *pDetails; + /* add the record; we have "allow duplicates" enabled for clashes */ + NuRecordIdx recordIdx; + NuFileDetails nuFileDetails; + nuFileDetails = *pDetails; - /* - * Odd bit of trivia: NufxLib refuses to accept an fssep of '\0'. It - * really wants to have one. Which is annoying, since files coming - * from DOS or Pascal don't have one. We therefore need to supply - * one, so we provide 0xff on the theory that nobody in their right - * mind would have it in an Apple II filename. - * - * Since we don't strip Pascal and ProDOS names down when we load - * the disks, it's possible the for 0xff to occur if the disk got - * damaged. For ProDOS we don't care, since it has an fssep, but - * Pascal could be at risk. DOS and RDOS are sanitized and so should - * be okay. - * - * One issue: we don't currently allow changing the fssep when renaming - * a file. We need to fix this, or else there's no way to rename a - * file into a subdirectory once it has been pasted in this way. - */ - if (NuGetSepFromSysInfo(nuFileDetails.fileSysInfo) == 0) { - nuFileDetails.fileSysInfo = - NuSetSepInSysInfo(nuFileDetails.fileSysInfo, kNufxNoFssep); - } + /* + * Odd bit of trivia: NufxLib refuses to accept an fssep of '\0'. It + * really wants to have one. Which is annoying, since files coming + * from DOS or Pascal don't have one. We therefore need to supply + * one, so we provide 0xff on the theory that nobody in their right + * mind would have it in an Apple II filename. + * + * Since we don't strip Pascal and ProDOS names down when we load + * the disks, it's possible the for 0xff to occur if the disk got + * damaged. For ProDOS we don't care, since it has an fssep, but + * Pascal could be at risk. DOS and RDOS are sanitized and so should + * be okay. + * + * One issue: we don't currently allow changing the fssep when renaming + * a file. We need to fix this, or else there's no way to rename a + * file into a subdirectory once it has been pasted in this way. + */ + if (NuGetSepFromSysInfo(nuFileDetails.fileSysInfo) == 0) { + nuFileDetails.fileSysInfo = + NuSetSepInSysInfo(nuFileDetails.fileSysInfo, kNufxNoFssep); + } - nerr = NuAddRecord(fpArchive, &nuFileDetails, &recordIdx); - if (nerr != kNuErrNone) { - if (nerr != kNuErrAborted) { - errMsg.Format("Failed adding record: %s", NuStrError(nerr)); - //ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - } - // else the add was cancelled - goto bail; - } + nerr = NuAddRecord(fpArchive, &nuFileDetails, &recordIdx); + if (nerr != kNuErrNone) { + if (nerr != kNuErrAborted) { + errMsg.Format("Failed adding record: %s", NuStrError(nerr)); + //ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + } + // else the add was cancelled + goto bail; + } - if (dataLen >= 0) { - ASSERT(*pDataBuf != nil); + if (dataLen >= 0) { + ASSERT(*pDataBuf != nil); - /* strip the high ASCII from DOS and RDOS text files */ - if (pDetails->entryKind != FileDetails::kFileKindDiskImage && - pDetails->fileType == kFileTypeTXT && - DiskImg::UsesDOSFileStructure(pDetails->fileSysFmt)) - { - WMSG1(" Stripping high ASCII from '%s'\n", pDetails->storageName); - unsigned char* ucp = *pDataBuf; - long len = dataLen; + /* strip the high ASCII from DOS and RDOS text files */ + if (pDetails->entryKind != FileDetails::kFileKindDiskImage && + pDetails->fileType == kFileTypeTXT && + DiskImg::UsesDOSFileStructure(pDetails->fileSysFmt)) + { + WMSG1(" Stripping high ASCII from '%s'\n", pDetails->storageName); + unsigned char* ucp = *pDataBuf; + long len = dataLen; - while (len--) - *ucp++ &= 0x7f; - } + while (len--) + *ucp++ &= 0x7f; + } - /* create a data source for the data fork; might be zero len */ - nerr = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, 0, - *pDataBuf, 0, dataLen, ArrayDeleteHandler, &pSource); - if (nerr != kNuErrNone) { - errMsg = "Unable to create NufxLib data source."; - //ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - *pDataBuf = nil; /* owned by data source */ + /* create a data source for the data fork; might be zero len */ + nerr = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, 0, + *pDataBuf, 0, dataLen, ArrayDeleteHandler, &pSource); + if (nerr != kNuErrNone) { + errMsg = "Unable to create NufxLib data source."; + //ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + *pDataBuf = nil; /* owned by data source */ - /* add the data fork, as a disk image if appropriate */ - NuThreadID targetID; - if (pDetails->entryKind == FileDetails::kFileKindDiskImage) - targetID = kNuThreadIDDiskImage; - else - targetID = kNuThreadIDDataFork; + /* add the data fork, as a disk image if appropriate */ + NuThreadID targetID; + if (pDetails->entryKind == FileDetails::kFileKindDiskImage) + targetID = kNuThreadIDDiskImage; + else + targetID = kNuThreadIDDataFork; - nerr = NuAddThread(fpArchive, recordIdx, targetID, pSource, nil); - if (nerr != kNuErrNone) { - errMsg.Format("Failed adding thread: %s.", NuStrError(nerr)); - //ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - pSource = nil; /* NufxLib owns it now */ - } + nerr = NuAddThread(fpArchive, recordIdx, targetID, pSource, nil); + if (nerr != kNuErrNone) { + errMsg.Format("Failed adding thread: %s.", NuStrError(nerr)); + //ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + pSource = nil; /* NufxLib owns it now */ + } - /* add the resource fork, if one was provided */ - if (rsrcLen >= 0) { - ASSERT(*pRsrcBuf != nil); + /* add the resource fork, if one was provided */ + if (rsrcLen >= 0) { + ASSERT(*pRsrcBuf != nil); - nerr = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, 0, - *pRsrcBuf, 0, rsrcLen, ArrayDeleteHandler, &pSource); - if (nerr != kNuErrNone) { - errMsg = "Unable to create NufxLib data source."; - //ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - *pRsrcBuf = nil; /* owned by data source */ + nerr = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, 0, + *pRsrcBuf, 0, rsrcLen, ArrayDeleteHandler, &pSource); + if (nerr != kNuErrNone) { + errMsg = "Unable to create NufxLib data source."; + //ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + *pRsrcBuf = nil; /* owned by data source */ - /* add the data fork */ - nerr = NuAddThread(fpArchive, recordIdx, kNuThreadIDRsrcFork, - pSource, nil); - if (nerr != kNuErrNone) { - errMsg.Format("Failed adding thread: %s.", NuStrError(nerr)); - //ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - goto bail; - } - pSource = nil; /* NufxLib owns it now */ - } + /* add the data fork */ + nerr = NuAddThread(fpArchive, recordIdx, kNuThreadIDRsrcFork, + pSource, nil); + if (nerr != kNuErrNone) { + errMsg.Format("Failed adding thread: %s.", NuStrError(nerr)); + //ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + goto bail; + } + pSource = nil; /* NufxLib owns it now */ + } bail: - NuFreeDataSource(pSource); - return errMsg; + NuFreeDataSource(pSource); + return errMsg; } /* @@ -2376,16 +2376,16 @@ bail: void NufxArchive::XferAbort(CWnd* pMsgWnd) { - NuError nerr; - CString errMsg; + NuError nerr; + CString errMsg; - WMSG0(" NufxArchive::XferAbort\n"); + WMSG0(" NufxArchive::XferAbort\n"); - nerr = NuAbort(fpArchive); - if (nerr != kNuErrNone) { - errMsg.Format("Failed while aborting procedure: %s.", NuStrError(nerr)); - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - } + nerr = NuAbort(fpArchive); + if (nerr != kNuErrNone) { + errMsg.Format("Failed while aborting procedure: %s.", NuStrError(nerr)); + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + } } /* @@ -2394,36 +2394,36 @@ NufxArchive::XferAbort(CWnd* pMsgWnd) void NufxArchive::XferFinish(CWnd* pMsgWnd) { - NuError nerr; - CString errMsg; + NuError nerr; + CString errMsg; - WMSG0(" NufxArchive::XferFinish\n"); + WMSG0(" NufxArchive::XferFinish\n"); - /* actually do the work */ - long statusFlags; - nerr = NuFlush(fpArchive, &statusFlags); - if (nerr != kNuErrNone) { - if (nerr != kNuErrAborted) { - errMsg.Format("Unable to add file: %s.", NuStrError(nerr)); - ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); - } + /* actually do the work */ + long statusFlags; + nerr = NuFlush(fpArchive, &statusFlags); + if (nerr != kNuErrNone) { + if (nerr != kNuErrAborted) { + errMsg.Format("Unable to add file: %s.", NuStrError(nerr)); + ShowFailureMsg(fpMsgWnd, errMsg, IDS_FAILED); + } - /* see if it got converted to read-only status */ - if (statusFlags & kNuFlushReadOnly) - fIsReadOnly = true; - goto bail; - } + /* see if it got converted to read-only status */ + if (statusFlags & kNuFlushReadOnly) + fIsReadOnly = true; + goto bail; + } - (void) InternalReload(fpMsgWnd); + (void) InternalReload(fpMsgWnd); bail: - return; + return; } /* * =========================================================================== - * NufxArchive -- add/update/delete comments + * NufxArchive -- add/update/delete comments * =========================================================================== */ @@ -2434,49 +2434,49 @@ bail: */ bool NufxArchive::GetComment(CWnd* pMsgWnd, const GenericEntry* pGenericEntry, - CString* pStr) + CString* pStr) { - NufxEntry* pEntry = (NufxEntry*) pGenericEntry; - CString errMsg; - const char* kNewEOL = "\r\n"; - int result; - char* buf; - long len; + NufxEntry* pEntry = (NufxEntry*) pGenericEntry; + CString errMsg; + const char* kNewEOL = "\r\n"; + int result; + char* buf; + long len; - ASSERT(pGenericEntry->GetHasComment()); + ASSERT(pGenericEntry->GetHasComment()); - /* use standard extract function to pull comment out */ - buf = nil; - len = 0; - result = pEntry->ExtractThreadToBuffer(GenericEntry::kCommentThread, - &buf, &len, &errMsg); - if (result != IDOK) { - WMSG1("Failed getting comment: %s\n", buf); - ASSERT(buf == nil); - return false; - } + /* use standard extract function to pull comment out */ + buf = nil; + len = 0; + result = pEntry->ExtractThreadToBuffer(GenericEntry::kCommentThread, + &buf, &len, &errMsg); + if (result != IDOK) { + WMSG1("Failed getting comment: %s\n", buf); + ASSERT(buf == nil); + return false; + } - /* convert EOL and add '\0' */ - CString convStr; - const char* ccp; + /* convert EOL and add '\0' */ + CString convStr; + const char* ccp; - ccp = buf; - while (len-- && *ccp != '\0') { - if (len > 1 && *ccp == '\r' && *(ccp+1) == '\n') { - ccp++; - len--; - convStr += kNewEOL; - } else if (*ccp == '\r' || *ccp == '\n') { - convStr += kNewEOL; - } else { - convStr += *ccp; - } - ccp++; - } + ccp = buf; + while (len-- && *ccp != '\0') { + if (len > 1 && *ccp == '\r' && *(ccp+1) == '\n') { + ccp++; + len--; + convStr += kNewEOL; + } else if (*ccp == '\r' || *ccp == '\n') { + convStr += kNewEOL; + } else { + convStr += *ccp; + } + ccp++; + } - *pStr = convStr; - delete[] buf; - return true; + *pStr = convStr; + delete[] buf; + return true; } /* @@ -2495,94 +2495,94 @@ NufxArchive::GetComment(CWnd* pMsgWnd, const GenericEntry* pGenericEntry, */ bool NufxArchive::SetComment(CWnd* pMsgWnd, GenericEntry* pGenericEntry, - const CString& str) + const CString& str) { - NuDataSource* pSource = nil; - NufxEntry* pEntry = (NufxEntry*) pGenericEntry; - NuError nerr; - bool retVal = false; + NuDataSource* pSource = nil; + NufxEntry* pEntry = (NufxEntry*) pGenericEntry; + NuError nerr; + bool retVal = false; - /* convert CRLF to CR */ - CString newStr(str); - char* srcp; - char* dstp; - srcp = dstp = newStr.GetBuffer(0); - while (*srcp != '\0') { - if (*srcp == '\r' && *(srcp+1) == '\n') { - srcp++; - *dstp = '\r'; - } else { - *dstp = *srcp; - } - srcp++; - dstp++; - } - *dstp = '\0'; - newStr.ReleaseBuffer(); + /* convert CRLF to CR */ + CString newStr(str); + char* srcp; + char* dstp; + srcp = dstp = newStr.GetBuffer(0); + while (*srcp != '\0') { + if (*srcp == '\r' && *(srcp+1) == '\n') { + srcp++; + *dstp = '\r'; + } else { + *dstp = *srcp; + } + srcp++; + dstp++; + } + *dstp = '\0'; + newStr.ReleaseBuffer(); - /* get the thread info */ - CString errMsg; - NuThread thread; - NuThreadIdx threadIdx; + /* get the thread info */ + CString errMsg; + NuThread thread; + NuThreadIdx threadIdx; - pEntry->FindThreadInfo(GenericEntry::kCommentThread, &thread, &errMsg); - threadIdx = thread.threadIdx; - if (errMsg.IsEmpty()) { - /* delete existing thread */ - nerr = NuDeleteThread(fpArchive, threadIdx); - if (nerr != kNuErrNone) { - errMsg.Format("Unable to delete thread: %s.", NuStrError(nerr)); - goto bail; - } - } + pEntry->FindThreadInfo(GenericEntry::kCommentThread, &thread, &errMsg); + threadIdx = thread.threadIdx; + if (errMsg.IsEmpty()) { + /* delete existing thread */ + nerr = NuDeleteThread(fpArchive, threadIdx); + if (nerr != kNuErrNone) { + errMsg.Format("Unable to delete thread: %s.", NuStrError(nerr)); + goto bail; + } + } - /* set a maximum pre-size value for the thread */ - long maxLen; - maxLen = ((newStr.GetLength() + 99) / 100) * 100; - if (maxLen < 200) - maxLen = 200; + /* set a maximum pre-size value for the thread */ + long maxLen; + maxLen = ((newStr.GetLength() + 99) / 100) * 100; + if (maxLen < 200) + maxLen = 200; - /* create a data source to write from */ - nerr = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, - maxLen, (const unsigned char*)(const char*)newStr, 0, - newStr.GetLength(), nil, &pSource); - if (nerr != kNuErrNone) { - errMsg.Format("Unable to create NufxLib data source (len=%d, maxLen=%d).", - newStr.GetLength(), maxLen); - goto bail; - } + /* create a data source to write from */ + nerr = NuCreateDataSourceForBuffer(kNuThreadFormatUncompressed, + maxLen, (const unsigned char*)(const char*)newStr, 0, + newStr.GetLength(), nil, &pSource); + if (nerr != kNuErrNone) { + errMsg.Format("Unable to create NufxLib data source (len=%d, maxLen=%d).", + newStr.GetLength(), maxLen); + goto bail; + } - /* add the new thread */ - nerr = NuAddThread(fpArchive, pEntry->GetRecordIdx(), - kNuThreadIDComment, pSource, nil); - if (nerr != kNuErrNone) { - errMsg.Format("Unable to add comment thread: %s.", - NuStrError(nerr)); - goto bail; - } - pSource = nil; // nufxlib owns it now + /* add the new thread */ + nerr = NuAddThread(fpArchive, pEntry->GetRecordIdx(), + kNuThreadIDComment, pSource, nil); + if (nerr != kNuErrNone) { + errMsg.Format("Unable to add comment thread: %s.", + NuStrError(nerr)); + goto bail; + } + pSource = nil; // nufxlib owns it now - /* flush changes */ - long statusFlags; - nerr = NuFlush(fpArchive, &statusFlags); - if (nerr != kNuErrNone) { - errMsg.Format("Unable to flush comment changes: %s.", - NuStrError(nerr)); - goto bail; - } + /* flush changes */ + long statusFlags; + nerr = NuFlush(fpArchive, &statusFlags); + if (nerr != kNuErrNone) { + errMsg.Format("Unable to flush comment changes: %s.", + NuStrError(nerr)); + goto bail; + } - /* reload GenericArchive from NufxLib */ - if (InternalReload(fpMsgWnd) == kNuErrNone) - retVal = true; + /* reload GenericArchive from NufxLib */ + if (InternalReload(fpMsgWnd) == kNuErrNone) + retVal = true; bail: - NuFreeDataSource(pSource); - if (!retVal) { - WMSG1("FAILED: %s\n", (LPCTSTR) errMsg); - NuAbort(fpArchive); - } - return retVal; + NuFreeDataSource(pSource); + if (!retVal) { + WMSG1("FAILED: %s\n", (LPCTSTR) errMsg); + NuAbort(fpArchive); + } + return retVal; } /* @@ -2593,43 +2593,43 @@ bail: bool NufxArchive::DeleteComment(CWnd* pMsgWnd, GenericEntry* pGenericEntry) { - CString errMsg; - NuError nerr; - NufxEntry* pEntry = (NufxEntry*) pGenericEntry; - NuThread thread; - NuThreadIdx threadIdx; - bool retVal = false; + CString errMsg; + NuError nerr; + NufxEntry* pEntry = (NufxEntry*) pGenericEntry; + NuThread thread; + NuThreadIdx threadIdx; + bool retVal = false; - pEntry->FindThreadInfo(GenericEntry::kCommentThread, &thread, &errMsg); - if (!errMsg.IsEmpty()) - goto bail; - threadIdx = thread.threadIdx; + pEntry->FindThreadInfo(GenericEntry::kCommentThread, &thread, &errMsg); + if (!errMsg.IsEmpty()) + goto bail; + threadIdx = thread.threadIdx; - nerr = NuDeleteThread(fpArchive, threadIdx); - if (nerr != kNuErrNone) { - errMsg.Format("Unable to delete thread: %s.", NuStrError(nerr)); - goto bail; - } + nerr = NuDeleteThread(fpArchive, threadIdx); + if (nerr != kNuErrNone) { + errMsg.Format("Unable to delete thread: %s.", NuStrError(nerr)); + goto bail; + } - /* flush changes */ - long statusFlags; - nerr = NuFlush(fpArchive, &statusFlags); - if (nerr != kNuErrNone) { - errMsg.Format("Unable to flush comment deletion: %s.", - NuStrError(nerr)); - goto bail; - } + /* flush changes */ + long statusFlags; + nerr = NuFlush(fpArchive, &statusFlags); + if (nerr != kNuErrNone) { + errMsg.Format("Unable to flush comment deletion: %s.", + NuStrError(nerr)); + goto bail; + } - /* reload GenericArchive from NufxLib */ - if (InternalReload(pMsgWnd) == kNuErrNone) - retVal = true; + /* reload GenericArchive from NufxLib */ + if (InternalReload(pMsgWnd) == kNuErrNone) + retVal = true; bail: - if (retVal != 0) { - WMSG1("FAILED: %s\n", (LPCTSTR) errMsg); - NuAbort(fpArchive); - } - return retVal; + if (retVal != 0) { + WMSG1("FAILED: %s\n", (LPCTSTR) errMsg); + NuAbort(fpArchive); + } + return retVal; } @@ -2646,52 +2646,52 @@ bail: */ bool NufxArchive::SetProps(CWnd* pMsgWnd, GenericEntry* pEntry, - const FileProps* pProps) + const FileProps* pProps) { - NuError nerr; - NufxEntry* pNufxEntry = (NufxEntry*) pEntry; - const NuRecord* pRecord; - NuRecordAttr recordAttr; + NuError nerr; + NufxEntry* pNufxEntry = (NufxEntry*) pEntry; + const NuRecord* pRecord; + NuRecordAttr recordAttr; - WMSG3(" SET fileType=0x%02x auxType=0x%04x access=0x%02x\n", - pProps->fileType, pProps->auxType, pProps->access); + WMSG3(" SET fileType=0x%02x auxType=0x%04x access=0x%02x\n", + pProps->fileType, pProps->auxType, pProps->access); - nerr = NuGetRecord(fpArchive, pNufxEntry->GetRecordIdx(), &pRecord); - if (nerr != kNuErrNone) { - WMSG2("ERROR: couldn't find recordIdx %ld: %s\n", - pNufxEntry->GetRecordIdx(), NuStrError(nerr)); - return false; - } + nerr = NuGetRecord(fpArchive, pNufxEntry->GetRecordIdx(), &pRecord); + if (nerr != kNuErrNone) { + WMSG2("ERROR: couldn't find recordIdx %ld: %s\n", + pNufxEntry->GetRecordIdx(), NuStrError(nerr)); + return false; + } - NuRecordCopyAttr(&recordAttr, pRecord); - recordAttr.fileType = pProps->fileType; - recordAttr.extraType = pProps->auxType; - recordAttr.access = pProps->access; + NuRecordCopyAttr(&recordAttr, pRecord); + recordAttr.fileType = pProps->fileType; + recordAttr.extraType = pProps->auxType; + recordAttr.access = pProps->access; - nerr = NuSetRecordAttr(fpArchive, pNufxEntry->GetRecordIdx(), &recordAttr); - if (nerr != kNuErrNone) { - WMSG2("ERROR: couldn't set recordAttr %ld: %s\n", - pNufxEntry->GetRecordIdx(), NuStrError(nerr)); - return false; - } + nerr = NuSetRecordAttr(fpArchive, pNufxEntry->GetRecordIdx(), &recordAttr); + if (nerr != kNuErrNone) { + WMSG2("ERROR: couldn't set recordAttr %ld: %s\n", + pNufxEntry->GetRecordIdx(), NuStrError(nerr)); + return false; + } - long statusFlags; - nerr = NuFlush(fpArchive, &statusFlags); - if (nerr != kNuErrNone) { - WMSG1("ERROR: NuFlush failed: %s\n", NuStrError(nerr)); + long statusFlags; + nerr = NuFlush(fpArchive, &statusFlags); + if (nerr != kNuErrNone) { + WMSG1("ERROR: NuFlush failed: %s\n", NuStrError(nerr)); - /* see if it got converted to read-only status */ - if (statusFlags & kNuFlushReadOnly) - fIsReadOnly = true; - return false; - } + /* see if it got converted to read-only status */ + if (statusFlags & kNuFlushReadOnly) + fIsReadOnly = true; + return false; + } - WMSG0("Props set\n"); + WMSG0("Props set\n"); - /* do this in lieu of reloading GenericArchive */ - pEntry->SetFileType(pProps->fileType); - pEntry->SetAuxType(pProps->auxType); - pEntry->SetAccess(pProps->access); + /* do this in lieu of reloading GenericArchive */ + pEntry->SetFileType(pProps->fileType); + pEntry->SetAuxType(pProps->auxType); + pEntry->SetAccess(pProps->access); - return true; + return true; } diff --git a/app/NufxArchive.h b/app/NufxArchive.h index 959d2f4..fc846d8 100644 --- a/app/NufxArchive.h +++ b/app/NufxArchive.h @@ -10,7 +10,7 @@ #define __NUFX_ARCHIVE__ #include "GenericArchive.h" -#include "../prebuilt/NufxLib.h" // ideally this wouldn't be here, only in .cpp +#include "../prebuilt/NufxLib.h" // ideally this wouldn't be here, only in .cpp /* @@ -18,39 +18,39 @@ */ class NufxEntry : public GenericEntry { public: - NufxEntry(NuArchive* pArchive) : fpArchive(pArchive) - {} - virtual ~NufxEntry(void) {} + NufxEntry(NuArchive* pArchive) : fpArchive(pArchive) + {} + virtual ~NufxEntry(void) {} - NuRecordIdx GetRecordIdx(void) const { return fRecordIdx; } - void SetRecordIdx(NuRecordIdx idx) { fRecordIdx = idx; } + NuRecordIdx GetRecordIdx(void) const { return fRecordIdx; } + void SetRecordIdx(NuRecordIdx idx) { fRecordIdx = idx; } - // retrieve thread data - virtual int ExtractThreadToBuffer(int which, char** ppText, long* pLength, - CString* pErrMsg) const; - virtual int ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, - ConvertHighASCII convHA, CString* pErrMsg) const; - virtual long GetSelectionSerial(void) const { return fRecordIdx; } + // retrieve thread data + virtual int ExtractThreadToBuffer(int which, char** ppText, long* pLength, + CString* pErrMsg) const; + virtual int ExtractThreadToFile(int which, FILE* outfp, ConvertEOL conv, + ConvertHighASCII convHA, CString* pErrMsg) const; + virtual long GetSelectionSerial(void) const { return fRecordIdx; } - virtual bool GetFeatureFlag(Feature feature) const { - if (feature == kFeaturePascalTypes || feature == kFeatureDOSTypes || - feature == kFeatureHasSimpleAccess) - return false; - else - return true; - } + virtual bool GetFeatureFlag(Feature feature) const { + if (feature == kFeaturePascalTypes || feature == kFeatureDOSTypes || + feature == kFeatureHasSimpleAccess) + return false; + else + return true; + } - // This fills out several GenericEntry fields based on the contents - // of "*pRecord". - void AnalyzeRecord(const NuRecord* pRecord); + // This fills out several GenericEntry fields based on the contents + // of "*pRecord". + void AnalyzeRecord(const NuRecord* pRecord); - friend class NufxArchive; + friend class NufxArchive; private: - void FindThreadInfo(int which, NuThread* pThread, CString* pErrMsg) const; + void FindThreadInfo(int which, NuThread* pThread, CString* pErrMsg) const; - NuRecordIdx fRecordIdx; // unique record index - NuArchive* fpArchive; + NuRecordIdx fRecordIdx; // unique record index + NuArchive* fpArchive; }; @@ -59,123 +59,123 @@ private: */ class NufxArchive : public GenericArchive { public: - NufxArchive(void) : - fpArchive(nil), - fIsReadOnly(false), - fProgressAsRecompress(false), - fNumAdded(-1), - fpMsgWnd(nil), - fpAddOpts(nil) - {} - virtual ~NufxArchive(void) { (void) Close(); } + NufxArchive(void) : + fpArchive(nil), + fIsReadOnly(false), + fProgressAsRecompress(false), + fNumAdded(-1), + fpMsgWnd(nil), + fpAddOpts(nil) + {} + virtual ~NufxArchive(void) { (void) Close(); } - // One-time initialization; returns an error string. - static CString AppInit(void); + // One-time initialization; returns an error string. + static CString AppInit(void); - virtual OpenResult Open(const char* filename, bool readOnly, - CString* pErrMsg); - virtual CString New(const char* filename, const void* options); - virtual CString Flush(void) { return ""; } - virtual CString Reload(void); - virtual bool IsReadOnly(void) const { return fIsReadOnly; }; - virtual bool IsModified(void) const { return false; } - virtual void GetDescription(CString* pStr) const { *pStr = "NuFX"; } - virtual bool BulkAdd(ActionProgressDialog* pActionProgress, - const AddFilesDialog* pAddOpts); - virtual bool AddDisk(ActionProgressDialog* pActionProgress, - const AddFilesDialog* pAddOpts); - virtual bool CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry, - const char* newName) - { ASSERT(false); return false; } - virtual bool TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); - virtual bool DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); - virtual bool RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); - virtual CString TestPathName(const GenericEntry* pGenericEntry, - const CString& basePath, const CString& newName, char newFssep) const; - virtual bool RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS, - const char* newName) - { ASSERT(false); return false; } - virtual CString TestVolumeName(const DiskFS* pDiskFS, - const char* newName) const - { ASSERT(false); return "!"; } - virtual bool RecompressSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, - const RecompressOptionsDialog* pRecompOpts); - virtual XferStatus XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, - ActionProgressDialog* pActionProgress, const XferFileOptions* pXferOpts); - virtual bool GetComment(CWnd* pMsgWnd, const GenericEntry* pEntry, - CString* pStr); - virtual bool SetComment(CWnd* pMsgWnd, GenericEntry* pEntry, - const CString& str); - virtual bool DeleteComment(CWnd* pMsgWnd, GenericEntry* pEntry); - virtual bool SetProps(CWnd* pMsgWnd, GenericEntry* pEntry, - const FileProps* pProps); - virtual void PreferencesChanged(void); - virtual long GetCapability(Capability cap); + virtual OpenResult Open(const char* filename, bool readOnly, + CString* pErrMsg); + virtual CString New(const char* filename, const void* options); + virtual CString Flush(void) { return ""; } + virtual CString Reload(void); + virtual bool IsReadOnly(void) const { return fIsReadOnly; }; + virtual bool IsModified(void) const { return false; } + virtual void GetDescription(CString* pStr) const { *pStr = "NuFX"; } + virtual bool BulkAdd(ActionProgressDialog* pActionProgress, + const AddFilesDialog* pAddOpts); + virtual bool AddDisk(ActionProgressDialog* pActionProgress, + const AddFilesDialog* pAddOpts); + virtual bool CreateSubdir(CWnd* pMsgWnd, GenericEntry* pParentEntry, + const char* newName) + { ASSERT(false); return false; } + virtual bool TestSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); + virtual bool DeleteSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); + virtual bool RenameSelection(CWnd* pMsgWnd, SelectionSet* pSelSet); + virtual CString TestPathName(const GenericEntry* pGenericEntry, + const CString& basePath, const CString& newName, char newFssep) const; + virtual bool RenameVolume(CWnd* pMsgWnd, DiskFS* pDiskFS, + const char* newName) + { ASSERT(false); return false; } + virtual CString TestVolumeName(const DiskFS* pDiskFS, + const char* newName) const + { ASSERT(false); return "!"; } + virtual bool RecompressSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, + const RecompressOptionsDialog* pRecompOpts); + virtual XferStatus XferSelection(CWnd* pMsgWnd, SelectionSet* pSelSet, + ActionProgressDialog* pActionProgress, const XferFileOptions* pXferOpts); + virtual bool GetComment(CWnd* pMsgWnd, const GenericEntry* pEntry, + CString* pStr); + virtual bool SetComment(CWnd* pMsgWnd, GenericEntry* pEntry, + const CString& str); + virtual bool DeleteComment(CWnd* pMsgWnd, GenericEntry* pEntry); + virtual bool SetProps(CWnd* pMsgWnd, GenericEntry* pEntry, + const FileProps* pProps); + virtual void PreferencesChanged(void); + virtual long GetCapability(Capability cap); - // try not to use this - NuArchive* GetNuArchivePointer(void) const { return fpArchive; } + // try not to use this + NuArchive* GetNuArchivePointer(void) const { return fpArchive; } - // determine whether a particular type of compression is supported - static bool IsCompressionSupported(NuThreadFormat format); + // determine whether a particular type of compression is supported + static bool IsCompressionSupported(NuThreadFormat format); - // convert from DateTime format to time_t - static time_t DateTimeToSeconds(const NuDateTime* pDateTime); + // convert from DateTime format to time_t + static time_t DateTimeToSeconds(const NuDateTime* pDateTime); private: - virtual CString Close(void) { - if (fpArchive != nil) { - WMSG0("Closing archive (aborting any un-flushed changes)\n"); - NuAbort(fpArchive); - NuClose(fpArchive); - fpArchive = nil; - } - return ""; - } - bool RecompressThread(NufxEntry* pEntry, int threadKind, - const RecompressOptionsDialog* pRecompOpts, long* pSizeInMemory, - CString* pErrMsg); + virtual CString Close(void) { + if (fpArchive != nil) { + WMSG0("Closing archive (aborting any un-flushed changes)\n"); + NuAbort(fpArchive); + NuClose(fpArchive); + fpArchive = nil; + } + return ""; + } + bool RecompressThread(NufxEntry* pEntry, int threadKind, + const RecompressOptionsDialog* pRecompOpts, long* pSizeInMemory, + CString* pErrMsg); - virtual void XferPrepare(const XferFileOptions* pXferOpts); - virtual CString XferFile(FileDetails* pDetails, unsigned char** pDataBuf, - long dataLen, unsigned char** pRsrcBuf, long rsrcLen); - virtual void XferAbort(CWnd* pMsgWnd); - virtual void XferFinish(CWnd* pMsgWnd); + virtual void XferPrepare(const XferFileOptions* pXferOpts); + virtual CString XferFile(FileDetails* pDetails, unsigned char** pDataBuf, + long dataLen, unsigned char** pRsrcBuf, long rsrcLen); + virtual void XferAbort(CWnd* pMsgWnd); + virtual void XferFinish(CWnd* pMsgWnd); - virtual ArchiveKind GetArchiveKind(void) { return kArchiveNuFX; } - void AddPrep(CWnd* pWnd, const AddFilesDialog* pAddOpts); - void AddFinish(void); - virtual NuError DoAddFile(const AddFilesDialog* pAddOpts, - FileDetails* pDetails); + virtual ArchiveKind GetArchiveKind(void) { return kArchiveNuFX; } + void AddPrep(CWnd* pWnd, const AddFilesDialog* pAddOpts); + void AddFinish(void); + virtual NuError DoAddFile(const AddFilesDialog* pAddOpts, + FileDetails* pDetails); - static NuResult BulkAddErrorHandler(NuArchive* pArchive, void* vErrorStatus); - NuResult HandleReplaceExisting(const NuErrorStatus* pErrorStatus); - NuResult HandleAddNotFound(const NuErrorStatus* pErrorStatus); + static NuResult BulkAddErrorHandler(NuArchive* pArchive, void* vErrorStatus); + NuResult HandleReplaceExisting(const NuErrorStatus* pErrorStatus); + NuResult HandleAddNotFound(const NuErrorStatus* pErrorStatus); - NuError LoadContents(void); - NuError InternalReload(CWnd* pMsgWnd); - static NuResult ContentFunc(NuArchive* pArchive, void* vpRecord); + NuError LoadContents(void); + NuError InternalReload(CWnd* pMsgWnd); + static NuResult ContentFunc(NuArchive* pArchive, void* vpRecord); - NuError SetCallbacks(void); + NuError SetCallbacks(void); - // handle progress update messages - static NuResult ProgressUpdater(NuArchive* pArchive, void* vpProgress); + // handle progress update messages + static NuResult ProgressUpdater(NuArchive* pArchive, void* vpProgress); - // handle errors and debug messages from NufxLib. - static NuResult NufxErrorMsgHandler(NuArchive* pArchive, - void* vErrorMessage); + // handle errors and debug messages from NufxLib. + static NuResult NufxErrorMsgHandler(NuArchive* pArchive, + void* vErrorMessage); - // handle a DataSource resource release request - static NuResult ArrayDeleteHandler(NuArchive* pArchive, void* ptr); + // handle a DataSource resource release request + static NuResult ArrayDeleteHandler(NuArchive* pArchive, void* ptr); - NuArchive* fpArchive; - bool fIsReadOnly; + NuArchive* fpArchive; + bool fIsReadOnly; - bool fProgressAsRecompress; // tweak progress updater + bool fProgressAsRecompress; // tweak progress updater - /* state while adding files */ - int fNumAdded; - CWnd* fpMsgWnd; - const AddFilesDialog* fpAddOpts; + /* state while adding files */ + int fNumAdded; + CWnd* fpMsgWnd; + const AddFilesDialog* fpAddOpts; }; #endif /*__NUFX_ARCHIVE__*/ \ No newline at end of file diff --git a/app/OpenVolumeDialog.cpp b/app/OpenVolumeDialog.cpp index 24ee9e8..0941e9b 100644 --- a/app/OpenVolumeDialog.cpp +++ b/app/OpenVolumeDialog.cpp @@ -10,17 +10,17 @@ #include "OpenVolumeDialog.h" #include "HelpTopics.h" #include "Main.h" -#include "../diskimg/Win32Extra.h" // need disk geometry calls +#include "../diskimg/Win32Extra.h" // need disk geometry calls #include "../diskimg/ASPI.h" //#include "resource.h" BEGIN_MESSAGE_MAP(OpenVolumeDialog, CDialog) - ON_COMMAND(IDHELP, OnHelp) - //ON_NOTIFY(NM_CLICK, IDC_VOLUME_LIST, OnListClick) - ON_NOTIFY(LVN_ITEMCHANGED, IDC_VOLUME_LIST, OnListChange) - ON_NOTIFY(NM_DBLCLK, IDC_VOLUME_LIST, OnListDblClick) - ON_CBN_SELCHANGE(IDC_VOLUME_FILTER, OnVolumeFilterSelChange) + ON_COMMAND(IDHELP, OnHelp) + //ON_NOTIFY(NM_CLICK, IDC_VOLUME_LIST, OnListClick) + ON_NOTIFY(LVN_ITEMCHANGED, IDC_VOLUME_LIST, OnListChange) + ON_NOTIFY(NM_DBLCLK, IDC_VOLUME_LIST, OnListDblClick) + ON_CBN_SELCHANGE(IDC_VOLUME_FILTER, OnVolumeFilterSelChange) END_MESSAGE_MAP() @@ -30,59 +30,59 @@ END_MESSAGE_MAP() BOOL OpenVolumeDialog::OnInitDialog(void) { - CDialog::OnInitDialog(); // do any DDX init stuff - const Preferences* pPreferences = GET_PREFERENCES(); - long defaultFilter; + CDialog::OnInitDialog(); // do any DDX init stuff + const Preferences* pPreferences = GET_PREFERENCES(); + long defaultFilter; - /* highlight/select entire line, not just filename */ - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST); - ASSERT(pListView != nil); + /* highlight/select entire line, not just filename */ + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST); + ASSERT(pListView != nil); - ListView_SetExtendedListViewStyleEx(pListView->m_hWnd, - LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); + ListView_SetExtendedListViewStyleEx(pListView->m_hWnd, + LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); - /* disable the OK button until they click on something */ - CButton* pButton = (CButton*) GetDlgItem(IDOK); - ASSERT(pButton != nil); + /* disable the OK button until they click on something */ + CButton* pButton = (CButton*) GetDlgItem(IDOK); + ASSERT(pButton != nil); - pButton->EnableWindow(FALSE); + pButton->EnableWindow(FALSE); - /* if the read-only state is fixed, don't let them change it */ - if (!fAllowROChange) { - CButton* pButton; - pButton = (CButton*) GetDlgItem(IDC_OPENVOL_READONLY); - ASSERT(pButton != nil); - pButton->EnableWindow(FALSE); - } + /* if the read-only state is fixed, don't let them change it */ + if (!fAllowROChange) { + CButton* pButton; + pButton = (CButton*) GetDlgItem(IDC_OPENVOL_READONLY); + ASSERT(pButton != nil); + pButton->EnableWindow(FALSE); + } - /* prep the combo box */ - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_VOLUME_FILTER); - ASSERT(pCombo != nil); - defaultFilter = pPreferences->GetPrefLong(kPrVolumeFilter); - if (defaultFilter >= kBoth && defaultFilter <= kPhysical) - pCombo->SetCurSel(defaultFilter); - else { - WMSG1("GLITCH: invalid defaultFilter in prefs (%d)\n", defaultFilter); - pCombo->SetCurSel(kLogical); - } + /* prep the combo box */ + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_VOLUME_FILTER); + ASSERT(pCombo != nil); + defaultFilter = pPreferences->GetPrefLong(kPrVolumeFilter); + if (defaultFilter >= kBoth && defaultFilter <= kPhysical) + pCombo->SetCurSel(defaultFilter); + else { + WMSG1("GLITCH: invalid defaultFilter in prefs (%d)\n", defaultFilter); + pCombo->SetCurSel(kLogical); + } - /* two columns */ - CRect rect; - pListView->GetClientRect(&rect); - int width; + /* two columns */ + CRect rect; + pListView->GetClientRect(&rect); + int width; - width = pListView->GetStringWidth("XXVolume or Device NameXXmmmmmm"); - pListView->InsertColumn(0, "Volume or Device Name", LVCFMT_LEFT, width); - pListView->InsertColumn(1, "Remarks", LVCFMT_LEFT, - rect.Width() - width - ::GetSystemMetrics(SM_CXVSCROLL)); + width = pListView->GetStringWidth("XXVolume or Device NameXXmmmmmm"); + pListView->InsertColumn(0, "Volume or Device Name", LVCFMT_LEFT, width); + pListView->InsertColumn(1, "Remarks", LVCFMT_LEFT, + rect.Width() - width - ::GetSystemMetrics(SM_CXVSCROLL)); - // Load the drive list. - LoadDriveList(); + // Load the drive list. + LoadDriveList(); - // Kluge the physical drive 0 stuff. - DiskImg::SetAllowWritePhys0(GET_PREFERENCES()->GetPrefBool(kPrOpenVolumePhys0)); + // Kluge the physical drive 0 stuff. + DiskImg::SetAllowWritePhys0(GET_PREFERENCES()->GetPrefBool(kPrOpenVolumePhys0)); - return TRUE; + return TRUE; } /* @@ -91,8 +91,8 @@ OpenVolumeDialog::OnInitDialog(void) void OpenVolumeDialog::DoDataExchange(CDataExchange* pDX) { - DDX_Check(pDX, IDC_OPENVOL_READONLY, fReadOnly); - WMSG1("DoDataExchange: fReadOnly==%d\n", fReadOnly); + DDX_Check(pDX, IDC_OPENVOL_READONLY, fReadOnly); + WMSG1("DoDataExchange: fReadOnly==%d\n", fReadOnly); } /* @@ -101,28 +101,28 @@ OpenVolumeDialog::DoDataExchange(CDataExchange* pDX) void OpenVolumeDialog::LoadDriveList(void) { - CWaitCursor waitc; - CComboBox* pCombo; - CListCtrl* pListView; - int itemIndex = 0; - int filterSelection; + CWaitCursor waitc; + CComboBox* pCombo; + CListCtrl* pListView; + int itemIndex = 0; + int filterSelection; - pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST); - ASSERT(pListView != nil); - pCombo = (CComboBox*) GetDlgItem(IDC_VOLUME_FILTER); - ASSERT(pCombo != nil); + pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST); + ASSERT(pListView != nil); + pCombo = (CComboBox*) GetDlgItem(IDC_VOLUME_FILTER); + ASSERT(pCombo != nil); - pListView->DeleteAllItems(); + pListView->DeleteAllItems(); - /* - * Load the logical and physical drive sets as needed. Do the "physical" - * set first because it's usually what we want. - */ - filterSelection = pCombo->GetCurSel(); - if (filterSelection == kPhysical || filterSelection == kBoth) - LoadPhysicalDriveList(pListView, &itemIndex); - if (filterSelection == kLogical || filterSelection == kBoth) - LoadLogicalDriveList(pListView, &itemIndex); + /* + * Load the logical and physical drive sets as needed. Do the "physical" + * set first because it's usually what we want. + */ + filterSelection = pCombo->GetCurSel(); + if (filterSelection == kPhysical || filterSelection == kBoth) + LoadPhysicalDriveList(pListView, &itemIndex); + if (filterSelection == kLogical || filterSelection == kBoth) + LoadLogicalDriveList(pListView, &itemIndex); } /* @@ -132,158 +132,158 @@ OpenVolumeDialog::LoadDriveList(void) bool OpenVolumeDialog::LoadLogicalDriveList(CListCtrl* pListView, int* pItemIndex) { - DWORD drivesAvailable; - bool isWin9x = IsWin9x(); - int itemIndex = *pItemIndex; + DWORD drivesAvailable; + bool isWin9x = IsWin9x(); + int itemIndex = *pItemIndex; - ASSERT(pListView != nil); + ASSERT(pListView != nil); - drivesAvailable = GetLogicalDrives(); - if (drivesAvailable == 0) { - WMSG1("GetLogicalDrives failed, err=0x%08lx\n", drivesAvailable); - return false; - } - WMSG1("GetLogicalDrives returned 0x%08lx\n", drivesAvailable); + drivesAvailable = GetLogicalDrives(); + if (drivesAvailable == 0) { + WMSG1("GetLogicalDrives failed, err=0x%08lx\n", drivesAvailable); + return false; + } + WMSG1("GetLogicalDrives returned 0x%08lx\n", drivesAvailable); - // SetErrorMode(SEM_FAILCRITICALERRORS) + // SetErrorMode(SEM_FAILCRITICALERRORS) - /* run through the list, from A-Z */ - int i; - for (i = 0; i < kMaxLogicalDrives; i++) { - fVolumeInfo[i].driveType = DRIVE_UNKNOWN; + /* run through the list, from A-Z */ + int i; + for (i = 0; i < kMaxLogicalDrives; i++) { + fVolumeInfo[i].driveType = DRIVE_UNKNOWN; - if ((drivesAvailable >> i) & 0x01) { - char driveName[] = "_:\\"; - driveName[0] = 'A' + i; + if ((drivesAvailable >> i) & 0x01) { + char driveName[] = "_:\\"; + driveName[0] = 'A' + i; - unsigned int driveType; - const char* driveTypeComment = nil; - BOOL result; + unsigned int driveType; + const char* driveTypeComment = nil; + BOOL result; - driveType = fVolumeInfo[i].driveType = GetDriveType(driveName); - switch (driveType) { - case DRIVE_UNKNOWN: - // The drive type cannot be determined. - break; - case DRIVE_NO_ROOT_DIR: - // The root path is invalid. For example, no volume is mounted at the path. - break; - case DRIVE_REMOVABLE: - // The disk can be removed from the drive. - driveTypeComment = "Removable"; - break; - case DRIVE_FIXED: - // The disk cannot be removed from the drive. - driveTypeComment = "Local Disk"; - break; - case DRIVE_REMOTE: - // The drive is a remote (network) drive. - driveTypeComment = "Network"; - break; - case DRIVE_CDROM: - // The drive is a CD-ROM drive. - driveTypeComment = "CD-ROM"; - break; - case DRIVE_RAMDISK: - // The drive is a RAM disk. - break; - default: - WMSG1("UNKNOWN DRIVE TYPE %d\n", driveType); - break; - } + driveType = fVolumeInfo[i].driveType = GetDriveType(driveName); + switch (driveType) { + case DRIVE_UNKNOWN: + // The drive type cannot be determined. + break; + case DRIVE_NO_ROOT_DIR: + // The root path is invalid. For example, no volume is mounted at the path. + break; + case DRIVE_REMOVABLE: + // The disk can be removed from the drive. + driveTypeComment = "Removable"; + break; + case DRIVE_FIXED: + // The disk cannot be removed from the drive. + driveTypeComment = "Local Disk"; + break; + case DRIVE_REMOTE: + // The drive is a remote (network) drive. + driveTypeComment = "Network"; + break; + case DRIVE_CDROM: + // The drive is a CD-ROM drive. + driveTypeComment = "CD-ROM"; + break; + case DRIVE_RAMDISK: + // The drive is a RAM disk. + break; + default: + WMSG1("UNKNOWN DRIVE TYPE %d\n", driveType); + break; + } - if (driveType == DRIVE_CDROM && !DiskImgLib::Global::GetHasSPTI()) { - /* use "physical" device via ASPI instead */ - WMSG1("Not including CD-ROM '%s' in logical drive list\n", - driveName); - continue; - } + if (driveType == DRIVE_CDROM && !DiskImgLib::Global::GetHasSPTI()) { + /* use "physical" device via ASPI instead */ + WMSG1("Not including CD-ROM '%s' in logical drive list\n", + driveName); + continue; + } - char volNameBuf[256]; - char fsNameBuf[64]; - const char* errorComment = nil; - //DWORD fsFlags; - CString entryName, entryRemarks; + char volNameBuf[256]; + char fsNameBuf[64]; + const char* errorComment = nil; + //DWORD fsFlags; + CString entryName, entryRemarks; - result = ::GetVolumeInformation(driveName, volNameBuf, - sizeof(volNameBuf), NULL, NULL, NULL /*&fsFlags*/, fsNameBuf, - sizeof(fsNameBuf)); - if (result == FALSE) { - DWORD err = GetLastError(); - if (err == ERROR_UNRECOGNIZED_VOLUME) { - // Win2K: media exists but format not recognized - errorComment = "Non-Windows format"; - } else if (err == ERROR_NOT_READY) { - // Win2K: device exists but no media loaded - if (isWin9x) { - WMSG1("Not showing drive '%s': not ready\n", - driveName); - continue; // safer not to show it - } else - errorComment = "Not ready"; - } else if (err == ERROR_PATH_NOT_FOUND /*Win2K*/ || - err == ERROR_INVALID_DATA /*Win98*/) - { - // Win2K/Win98: device letter not in use - WMSG1("GetVolumeInformation '%s': nothing there\n", - driveName); - continue; - } else if (err == ERROR_INVALID_PARAMETER) { - // Win2K: device is already open - //WMSG1("GetVolumeInformation '%s': currently open??\n", - // driveName); - errorComment = "(currently open?)"; - //continue; - } else if (err == ERROR_ACCESS_DENIED) { - // Win2K: disk is open no-read-sharing elsewhere - errorComment = "(already open read-write)"; - } else if (err == ERROR_GEN_FAILURE) { - // Win98: floppy format not recognzied - // --> we don't want to access ProDOS floppies via A: in - // Win98, so we skip it here - WMSG1("GetVolumeInformation '%s': general failure\n", - driveName); - continue; - } else if (err == ERROR_INVALID_FUNCTION) { - // Win2K: CD-ROM with HFS - if (driveType == DRIVE_CDROM) - errorComment = "Non-Windows format"; - else - errorComment = "(invalid disc?)"; - } else { - WMSG2("GetVolumeInformation '%s' failed: %ld\n", - driveName, GetLastError()); - continue; - } - ASSERT(errorComment != nil); + result = ::GetVolumeInformation(driveName, volNameBuf, + sizeof(volNameBuf), NULL, NULL, NULL /*&fsFlags*/, fsNameBuf, + sizeof(fsNameBuf)); + if (result == FALSE) { + DWORD err = GetLastError(); + if (err == ERROR_UNRECOGNIZED_VOLUME) { + // Win2K: media exists but format not recognized + errorComment = "Non-Windows format"; + } else if (err == ERROR_NOT_READY) { + // Win2K: device exists but no media loaded + if (isWin9x) { + WMSG1("Not showing drive '%s': not ready\n", + driveName); + continue; // safer not to show it + } else + errorComment = "Not ready"; + } else if (err == ERROR_PATH_NOT_FOUND /*Win2K*/ || + err == ERROR_INVALID_DATA /*Win98*/) + { + // Win2K/Win98: device letter not in use + WMSG1("GetVolumeInformation '%s': nothing there\n", + driveName); + continue; + } else if (err == ERROR_INVALID_PARAMETER) { + // Win2K: device is already open + //WMSG1("GetVolumeInformation '%s': currently open??\n", + // driveName); + errorComment = "(currently open?)"; + //continue; + } else if (err == ERROR_ACCESS_DENIED) { + // Win2K: disk is open no-read-sharing elsewhere + errorComment = "(already open read-write)"; + } else if (err == ERROR_GEN_FAILURE) { + // Win98: floppy format not recognzied + // --> we don't want to access ProDOS floppies via A: in + // Win98, so we skip it here + WMSG1("GetVolumeInformation '%s': general failure\n", + driveName); + continue; + } else if (err == ERROR_INVALID_FUNCTION) { + // Win2K: CD-ROM with HFS + if (driveType == DRIVE_CDROM) + errorComment = "Non-Windows format"; + else + errorComment = "(invalid disc?)"; + } else { + WMSG2("GetVolumeInformation '%s' failed: %ld\n", + driveName, GetLastError()); + continue; + } + ASSERT(errorComment != nil); - entryName.Format("(%c:)", 'A' + i); - if (driveTypeComment != nil) - entryRemarks.Format("%s - %s", driveTypeComment, - errorComment); - else - entryRemarks.Format("%s", errorComment); - } else { - entryName.Format("%s (%c:)", volNameBuf, 'A' + i); - if (driveTypeComment != nil) - entryRemarks.Format("%s", driveTypeComment); - else - entryRemarks = ""; - } + entryName.Format("(%c:)", 'A' + i); + if (driveTypeComment != nil) + entryRemarks.Format("%s - %s", driveTypeComment, + errorComment); + else + entryRemarks.Format("%s", errorComment); + } else { + entryName.Format("%s (%c:)", volNameBuf, 'A' + i); + if (driveTypeComment != nil) + entryRemarks.Format("%s", driveTypeComment); + else + entryRemarks = ""; + } - pListView->InsertItem(itemIndex, entryName); - pListView->SetItemText(itemIndex, 1, entryRemarks); - pListView->SetItemData(itemIndex, (DWORD) i + 'A'); + pListView->InsertItem(itemIndex, entryName); + pListView->SetItemText(itemIndex, 1, entryRemarks); + pListView->SetItemData(itemIndex, (DWORD) i + 'A'); //WMSG1("%%%% added logical %d\n", itemIndex); - itemIndex++; - } else { - WMSG1(" (drive %c not available)\n", i + 'A'); - } - } + itemIndex++; + } else { + WMSG1(" (drive %c not available)\n", i + 'A'); + } + } - *pItemIndex = itemIndex; + *pItemIndex = itemIndex; - return true; + return true; } /* @@ -298,111 +298,111 @@ OpenVolumeDialog::LoadLogicalDriveList(CListCtrl* pListView, int* pItemIndex) bool OpenVolumeDialog::LoadPhysicalDriveList(CListCtrl* pListView, int* pItemIndex) { - bool isWin9x = IsWin9x(); - int itemIndex = *pItemIndex; - int i; + bool isWin9x = IsWin9x(); + int itemIndex = *pItemIndex; + int i; - if (isWin9x) { - // fairly arbitrary choices - const int kMaxFloppies = 4; - const int kMaxHardDrives = 8; + if (isWin9x) { + // fairly arbitrary choices + const int kMaxFloppies = 4; + const int kMaxHardDrives = 8; - for (i = 0; i < kMaxFloppies; i++) { - CString driveName, remark; - bool result; + for (i = 0; i < kMaxFloppies; i++) { + CString driveName, remark; + bool result; - result = HasPhysicalDriveWin9x(i, &remark); - if (result) { - driveName.Format("Floppy disk %d", i); - pListView->InsertItem(itemIndex, driveName); - pListView->SetItemText(itemIndex, 1, remark); - pListView->SetItemData(itemIndex, (DWORD) i); + result = HasPhysicalDriveWin9x(i, &remark); + if (result) { + driveName.Format("Floppy disk %d", i); + pListView->InsertItem(itemIndex, driveName); + pListView->SetItemText(itemIndex, 1, remark); + pListView->SetItemData(itemIndex, (DWORD) i); //WMSG1("%%%% added floppy %d\n", itemIndex); - itemIndex++; - } - } - for (i = 0; i < kMaxHardDrives; i++) { - CString driveName, remark; - bool result; + itemIndex++; + } + } + for (i = 0; i < kMaxHardDrives; i++) { + CString driveName, remark; + bool result; - result = HasPhysicalDriveWin9x(i + 128, &remark); - if (result) { - driveName.Format("Hard drive %d", i); - pListView->InsertItem(itemIndex, driveName); - pListView->SetItemText(itemIndex, 1, remark); - pListView->SetItemData(itemIndex, (DWORD) i + 128); + result = HasPhysicalDriveWin9x(i + 128, &remark); + if (result) { + driveName.Format("Hard drive %d", i); + pListView->InsertItem(itemIndex, driveName); + pListView->SetItemText(itemIndex, 1, remark); + pListView->SetItemData(itemIndex, (DWORD) i + 128); //WMSG1("%%%% added HD %d\n", itemIndex); - itemIndex++; - } - } - } else { - for (i = 0; i < kMaxPhysicalDrives; i++) { - CString driveName, remark; - bool result; + itemIndex++; + } + } + } else { + for (i = 0; i < kMaxPhysicalDrives; i++) { + CString driveName, remark; + bool result; - result = HasPhysicalDriveWin2K(i + 128, &remark); - if (result) { - driveName.Format("Physical disk %d", i); - pListView->InsertItem(itemIndex, driveName); - pListView->SetItemText(itemIndex, 1, remark); - pListView->SetItemData(itemIndex, (DWORD) i + 128); // HD volume - itemIndex++; - } - } - } + result = HasPhysicalDriveWin2K(i + 128, &remark); + if (result) { + driveName.Format("Physical disk %d", i); + pListView->InsertItem(itemIndex, driveName); + pListView->SetItemText(itemIndex, 1, remark); + pListView->SetItemData(itemIndex, (DWORD) i + 128); // HD volume + itemIndex++; + } + } + } - if (DiskImgLib::Global::GetHasASPI()) { - DIError dierr; - DiskImgLib::ASPI* pASPI = DiskImgLib::Global::GetASPI(); - ASPIDevice* deviceArray = nil; - int numDevices; + if (DiskImgLib::Global::GetHasASPI()) { + DIError dierr; + DiskImgLib::ASPI* pASPI = DiskImgLib::Global::GetASPI(); + ASPIDevice* deviceArray = nil; + int numDevices; - dierr = pASPI->GetAccessibleDevices( - ASPI::kDevMaskCDROM | ASPI::kDevMaskHardDrive, - &deviceArray, &numDevices); - if (dierr == kDIErrNone) { - WMSG1("Adding %d ASPI CD-ROM devices\n", numDevices); - for (i = 0; i < numDevices; i++) { - CString driveName, remark; - CString addr, vendor, product; - DWORD aspiAddr; + dierr = pASPI->GetAccessibleDevices( + ASPI::kDevMaskCDROM | ASPI::kDevMaskHardDrive, + &deviceArray, &numDevices); + if (dierr == kDIErrNone) { + WMSG1("Adding %d ASPI CD-ROM devices\n", numDevices); + for (i = 0; i < numDevices; i++) { + CString driveName, remark; + CString addr, vendor, product; + DWORD aspiAddr; - addr.Format("ASPI %d:%d:%d", - deviceArray[i].GetAdapter(), - deviceArray[i].GetTarget(), - deviceArray[i].GetLun()); - vendor = deviceArray[i].GetVendorID(); - vendor.TrimRight(); - product = deviceArray[i].GetProductID(); - product.TrimRight(); + addr.Format("ASPI %d:%d:%d", + deviceArray[i].GetAdapter(), + deviceArray[i].GetTarget(), + deviceArray[i].GetLun()); + vendor = deviceArray[i].GetVendorID(); + vendor.TrimRight(); + product = deviceArray[i].GetProductID(); + product.TrimRight(); - driveName.Format("%s %s", vendor, product); - if (deviceArray[i].GetDeviceType() == ASPIDevice::kTypeCDROM) - remark = "CD-ROM"; - else if (deviceArray[i].GetDeviceType() == ASPIDevice::kTypeDASD) - remark = "Direct-access device"; - if (!deviceArray[i].GetDeviceReady()) - remark += " - Not ready"; + driveName.Format("%s %s", vendor, product); + if (deviceArray[i].GetDeviceType() == ASPIDevice::kTypeCDROM) + remark = "CD-ROM"; + else if (deviceArray[i].GetDeviceType() == ASPIDevice::kTypeDASD) + remark = "Direct-access device"; + if (!deviceArray[i].GetDeviceReady()) + remark += " - Not ready"; - aspiAddr = (DWORD) 0xaa << 24 | - (DWORD) deviceArray[i].GetAdapter() << 16 | - (DWORD) deviceArray[i].GetTarget() << 8 | - (DWORD) deviceArray[i].GetLun(); - //WMSG2("ADDR for '%s' is 0x%08lx\n", - // (const char*) driveName, aspiAddr); + aspiAddr = (DWORD) 0xaa << 24 | + (DWORD) deviceArray[i].GetAdapter() << 16 | + (DWORD) deviceArray[i].GetTarget() << 8 | + (DWORD) deviceArray[i].GetLun(); + //WMSG2("ADDR for '%s' is 0x%08lx\n", + // (const char*) driveName, aspiAddr); - pListView->InsertItem(itemIndex, driveName); - pListView->SetItemText(itemIndex, 1, remark); - pListView->SetItemData(itemIndex, aspiAddr); - itemIndex++; - } - } + pListView->InsertItem(itemIndex, driveName); + pListView->SetItemText(itemIndex, 1, remark); + pListView->SetItemData(itemIndex, aspiAddr); + itemIndex++; + } + } - delete[] deviceArray; - } + delete[] deviceArray; + } - *pItemIndex = itemIndex; - return true; + *pItemIndex = itemIndex; + return true; } /* @@ -414,69 +414,69 @@ OpenVolumeDialog::LoadPhysicalDriveList(CListCtrl* pListView, int* pItemIndex) bool OpenVolumeDialog::HasPhysicalDriveWin9x(int unit, CString* pRemark) { - HANDLE handle = nil; - const int VWIN32_DIOC_DOS_INT13 = 4; - const int CARRY_FLAG = 1; - BOOL result; - typedef struct _DIOC_REGISTERS { - DWORD reg_EBX; - DWORD reg_EDX; - DWORD reg_ECX; - DWORD reg_EAX; - DWORD reg_EDI; - DWORD reg_ESI; - DWORD reg_Flags; - } DIOC_REGISTERS, *PDIOC_REGISTERS; - DIOC_REGISTERS reg = {0}; - DWORD lastError, cb; - unsigned char buf[512]; + HANDLE handle = nil; + const int VWIN32_DIOC_DOS_INT13 = 4; + const int CARRY_FLAG = 1; + BOOL result; + typedef struct _DIOC_REGISTERS { + DWORD reg_EBX; + DWORD reg_EDX; + DWORD reg_ECX; + DWORD reg_EAX; + DWORD reg_EDI; + DWORD reg_ESI; + DWORD reg_Flags; + } DIOC_REGISTERS, *PDIOC_REGISTERS; + DIOC_REGISTERS reg = {0}; + DWORD lastError, cb; + unsigned char buf[512]; - if (unit > 4) - return false; // floppy drives only + if (unit > 4) + return false; // floppy drives only - handle = CreateFile("\\\\.\\vwin32", 0, 0, NULL, - OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL); - if (handle == INVALID_HANDLE_VALUE) { - WMSG1(" Unable to open vwin32: %ld\n", ::GetLastError()); - return false; - } + handle = CreateFile("\\\\.\\vwin32", 0, 0, NULL, + OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL); + if (handle == INVALID_HANDLE_VALUE) { + WMSG1(" Unable to open vwin32: %ld\n", ::GetLastError()); + return false; + } -#if 0 // didn't do what I wanted - reg.reg_EAX = MAKEWORD(0, 0x00); // func 0x00 == reset controller - reg.reg_EDX = MAKEWORD(unit, 0); // specify driver - result = DeviceIoControl(handle, VWIN32_DIOC_DOS_INT13, ®, - sizeof(reg), ®, sizeof(reg), &cb, 0); - WMSG3(" DriveReset(drive=0x%02x) result=%d carry=%d\n", - unit, result, reg.reg_Flags & CARRY_FLAG); +#if 0 // didn't do what I wanted + reg.reg_EAX = MAKEWORD(0, 0x00); // func 0x00 == reset controller + reg.reg_EDX = MAKEWORD(unit, 0); // specify driver + result = DeviceIoControl(handle, VWIN32_DIOC_DOS_INT13, ®, + sizeof(reg), ®, sizeof(reg), &cb, 0); + WMSG3(" DriveReset(drive=0x%02x) result=%d carry=%d\n", + unit, result, reg.reg_Flags & CARRY_FLAG); #endif - reg.reg_EAX = MAKEWORD(1, 0x02); // read 1 sector - reg.reg_EBX = (DWORD) buf; - reg.reg_ECX = MAKEWORD(1, 0); // sector 0 (+1), cylinder 0 - reg.reg_EDX = MAKEWORD(unit, 0); // head + reg.reg_EAX = MAKEWORD(1, 0x02); // read 1 sector + reg.reg_EBX = (DWORD) buf; + reg.reg_ECX = MAKEWORD(1, 0); // sector 0 (+1), cylinder 0 + reg.reg_EDX = MAKEWORD(unit, 0); // head - result = DeviceIoControl(handle, VWIN32_DIOC_DOS_INT13, ®, - sizeof(reg), ®, sizeof(reg), &cb, 0); - lastError = GetLastError(); - ::CloseHandle(handle); + result = DeviceIoControl(handle, VWIN32_DIOC_DOS_INT13, ®, + sizeof(reg), ®, sizeof(reg), &cb, 0); + lastError = GetLastError(); + ::CloseHandle(handle); - if (result == 0 || (reg.reg_Flags & CARRY_FLAG)) { - int ah = HIBYTE(reg.reg_EAX); - WMSG4(" DevIoCtrl(unit=%02xh) failed: result=%d lastErr=%d Flags=0x%08lx\n", - unit, result, lastError, reg.reg_Flags); - WMSG3(" AH=%d (EAX=0x%08lx) byte=0x%02x\n", ah, reg.reg_EAX, buf[0]); - if (ah != 1) { - // failure code 1 means "invalid parameter", drive doesn't exist - // mine returns 128, "timeout", when no disk is in the drive - *pRemark = "Not ready"; - return true; - } else - return false; - } + if (result == 0 || (reg.reg_Flags & CARRY_FLAG)) { + int ah = HIBYTE(reg.reg_EAX); + WMSG4(" DevIoCtrl(unit=%02xh) failed: result=%d lastErr=%d Flags=0x%08lx\n", + unit, result, lastError, reg.reg_Flags); + WMSG3(" AH=%d (EAX=0x%08lx) byte=0x%02x\n", ah, reg.reg_EAX, buf[0]); + if (ah != 1) { + // failure code 1 means "invalid parameter", drive doesn't exist + // mine returns 128, "timeout", when no disk is in the drive + *pRemark = "Not ready"; + return true; + } else + return false; + } - *pRemark = "Removable"; + *pRemark = "Removable"; - return true; + return true; } /* @@ -488,95 +488,95 @@ OpenVolumeDialog::HasPhysicalDriveWin9x(int unit, CString* pRemark) bool OpenVolumeDialog::HasPhysicalDriveWin2K(int unit, CString* pRemark) { - HANDLE hDevice; // handle to the drive to be examined - DISK_GEOMETRY dg; // disk drive geometry structure - DISK_GEOMETRY_EX dge; // extended geometry request buffer - BOOL result; // results flag - DWORD junk; // discard results - LONGLONG diskSize; // size of the drive, in bytes - CString fileName; - DWORD err; + HANDLE hDevice; // handle to the drive to be examined + DISK_GEOMETRY dg; // disk drive geometry structure + DISK_GEOMETRY_EX dge; // extended geometry request buffer + BOOL result; // results flag + DWORD junk; // discard results + LONGLONG diskSize; // size of the drive, in bytes + CString fileName; + DWORD err; - /* - * See if the drive is there. - */ - ASSERT(unit >= 128 && unit < 160); // arbitrary max - fileName.Format("\\\\.\\PhysicalDrive%d", unit - 128); + /* + * See if the drive is there. + */ + ASSERT(unit >= 128 && unit < 160); // arbitrary max + fileName.Format("\\\\.\\PhysicalDrive%d", unit - 128); - hDevice = ::CreateFile((const char*) fileName, // drive to open - 0, // no access to the drive - FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode - NULL, // default security attributes - OPEN_EXISTING, // disposition - 0, // file attributes - NULL); // do not copy file attributes + hDevice = ::CreateFile((const char*) fileName, // drive to open + 0, // no access to the drive + FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode + NULL, // default security attributes + OPEN_EXISTING, // disposition + 0, // file attributes + NULL); // do not copy file attributes - if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive - return false; + if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive + return false; - /* - * Try to get the drive geometry. First try with the fancy WinXP call, - * then fall back to the Win2K call if it doesn't exist. - */ - result = ::DeviceIoControl(hDevice, - IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, - NULL, 0, // input buffer - &dge, sizeof(dge), // output buffer - &junk, // # bytes returned - (LPOVERLAPPED) NULL); // synchronous I/O - if (result) { - diskSize = dge.DiskSize.QuadPart; - WMSG1(" EX results for device %02xh\n", unit); - WMSG2(" Disk size = %I64d (bytes) = %I64d (MB)\n", - diskSize, diskSize / (1024*1024)); - if (diskSize > 1024*1024*1024) - pRemark->Format("Size is %.2fGB", - (double) diskSize / (1024.0 * 1024.0 * 1024.0)); - else - pRemark->Format("Size is %.2fMB", - (double) diskSize / (1024.0 * 1024.0)); - } else { - // Win2K shows ERROR_INVALID_FUNCTION or ERROR_NOT_SUPPORTED - WMSG1("IOCTL_DISK_GET_DRIVE_GEOMETRY_EX failed, error was %ld\n", - GetLastError()); - result = ::DeviceIoControl(hDevice, // device to be queried - IOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to perform - NULL, 0, // no input buffer - &dg, sizeof(dg), // output buffer - &junk, // # bytes returned - (LPOVERLAPPED) NULL); // synchronous I/O + /* + * Try to get the drive geometry. First try with the fancy WinXP call, + * then fall back to the Win2K call if it doesn't exist. + */ + result = ::DeviceIoControl(hDevice, + IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, + NULL, 0, // input buffer + &dge, sizeof(dge), // output buffer + &junk, // # bytes returned + (LPOVERLAPPED) NULL); // synchronous I/O + if (result) { + diskSize = dge.DiskSize.QuadPart; + WMSG1(" EX results for device %02xh\n", unit); + WMSG2(" Disk size = %I64d (bytes) = %I64d (MB)\n", + diskSize, diskSize / (1024*1024)); + if (diskSize > 1024*1024*1024) + pRemark->Format("Size is %.2fGB", + (double) diskSize / (1024.0 * 1024.0 * 1024.0)); + else + pRemark->Format("Size is %.2fMB", + (double) diskSize / (1024.0 * 1024.0)); + } else { + // Win2K shows ERROR_INVALID_FUNCTION or ERROR_NOT_SUPPORTED + WMSG1("IOCTL_DISK_GET_DRIVE_GEOMETRY_EX failed, error was %ld\n", + GetLastError()); + result = ::DeviceIoControl(hDevice, // device to be queried + IOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to perform + NULL, 0, // no input buffer + &dg, sizeof(dg), // output buffer + &junk, // # bytes returned + (LPOVERLAPPED) NULL); // synchronous I/O - if (result) { - WMSG1(" Results for device %02xh\n", unit); - WMSG1(" Cylinders = %I64d\n", dg.Cylinders); - WMSG1(" Tracks per cylinder = %ld\n", (ULONG) dg.TracksPerCylinder); - WMSG1(" Sectors per track = %ld\n", (ULONG) dg.SectorsPerTrack); - WMSG1(" Bytes per sector = %ld\n", (ULONG) dg.BytesPerSector); + if (result) { + WMSG1(" Results for device %02xh\n", unit); + WMSG1(" Cylinders = %I64d\n", dg.Cylinders); + WMSG1(" Tracks per cylinder = %ld\n", (ULONG) dg.TracksPerCylinder); + WMSG1(" Sectors per track = %ld\n", (ULONG) dg.SectorsPerTrack); + WMSG1(" Bytes per sector = %ld\n", (ULONG) dg.BytesPerSector); - diskSize = dg.Cylinders.QuadPart * (ULONG)dg.TracksPerCylinder * - (ULONG)dg.SectorsPerTrack * (ULONG)dg.BytesPerSector; - WMSG2("Disk size = %I64d (bytes) = %I64d (MB)\n", diskSize, - diskSize / (1024 * 1024)); - if (diskSize > 1024*1024*1024) - pRemark->Format("Size is %.2fGB", - (double) diskSize / (1024.0 * 1024.0 * 1024.0)); - else - pRemark->Format("Size is %.2fMB", - (double) diskSize / (1024.0 * 1024.0)); - } else { - err = GetLastError(); - } - } + diskSize = dg.Cylinders.QuadPart * (ULONG)dg.TracksPerCylinder * + (ULONG)dg.SectorsPerTrack * (ULONG)dg.BytesPerSector; + WMSG2("Disk size = %I64d (bytes) = %I64d (MB)\n", diskSize, + diskSize / (1024 * 1024)); + if (diskSize > 1024*1024*1024) + pRemark->Format("Size is %.2fGB", + (double) diskSize / (1024.0 * 1024.0 * 1024.0)); + else + pRemark->Format("Size is %.2fMB", + (double) diskSize / (1024.0 * 1024.0)); + } else { + err = GetLastError(); + } + } - ::CloseHandle(hDevice); + ::CloseHandle(hDevice); - if (!result) { - WMSG1("DeviceIoControl(IOCTL_DISK_GET_DRIVE_GEOMETRY) failed (err=%ld)\n", - err); - *pRemark = "Not ready"; - } + if (!result) { + WMSG1("DeviceIoControl(IOCTL_DISK_GET_DRIVE_GEOMETRY) failed (err=%ld)\n", + err); + *pRemark = "Not ready"; + } - return true; + return true; } @@ -586,12 +586,12 @@ OpenVolumeDialog::HasPhysicalDriveWin2K(int unit, CString* pRemark) void OpenVolumeDialog::OnListChange(NMHDR*, LRESULT* pResult) { - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST); - CButton* pButton = (CButton*) GetDlgItem(IDOK); - pButton->EnableWindow(pListView->GetSelectedCount() != 0); - //WMSG1("ENABLE %d\n", pListView->GetSelectedCount() != 0); + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST); + CButton* pButton = (CButton*) GetDlgItem(IDOK); + pButton->EnableWindow(pListView->GetSelectedCount() != 0); + //WMSG1("ENABLE %d\n", pListView->GetSelectedCount() != 0); - *pResult = 0; + *pResult = 0; } /* @@ -600,15 +600,15 @@ OpenVolumeDialog::OnListChange(NMHDR*, LRESULT* pResult) void OpenVolumeDialog::OnListDblClick(NMHDR* pNotifyStruct, LRESULT* pResult) { - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST); - CButton* pButton = (CButton*) GetDlgItem(IDOK); + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST); + CButton* pButton = (CButton*) GetDlgItem(IDOK); - if (pListView->GetSelectedCount() != 0) { - pButton->EnableWindow(); - OnOK(); - } + if (pListView->GetSelectedCount() != 0) { + pButton->EnableWindow(); + OnOK(); + } - *pResult = 0; + *pResult = 0; } /* @@ -617,10 +617,10 @@ OpenVolumeDialog::OnListDblClick(NMHDR* pNotifyStruct, LRESULT* pResult) void OpenVolumeDialog::OnVolumeFilterSelChange(void) { - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_VOLUME_FILTER); - ASSERT(pCombo != nil); - WMSG1("+++ SELECTION IS NOW %d\n", pCombo->GetCurSel()); - LoadDriveList(); + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_VOLUME_FILTER); + ASSERT(pCombo != nil); + WMSG1("+++ SELECTION IS NOW %d\n", pCombo->GetCurSel()); + LoadDriveList(); } /* @@ -629,83 +629,83 @@ OpenVolumeDialog::OnVolumeFilterSelChange(void) void OpenVolumeDialog::OnOK(void) { - /* - * Figure out the (zero-based) drive letter. - */ - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST); - ASSERT(pListView != nil); + /* + * Figure out the (zero-based) drive letter. + */ + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUME_LIST); + ASSERT(pListView != nil); - if (pListView->GetSelectedCount() != 1) { - CString msg, failed; - failed.LoadString(IDS_FAILED); - msg.LoadString(IDS_VOLUME_SELECT_ONE); - MessageBox(msg, failed, MB_OK); - return; - } + if (pListView->GetSelectedCount() != 1) { + CString msg, failed; + failed.LoadString(IDS_FAILED); + msg.LoadString(IDS_VOLUME_SELECT_ONE); + MessageBox(msg, failed, MB_OK); + return; + } - POSITION posn; - posn = pListView->GetFirstSelectedItemPosition(); - if (posn == nil) { - ASSERT(false); - return; - } - int num = pListView->GetNextSelectedItem(posn); - DWORD driveID = pListView->GetItemData(num); - UINT formatID = 0; + POSITION posn; + posn = pListView->GetFirstSelectedItemPosition(); + if (posn == nil) { + ASSERT(false); + return; + } + int num = pListView->GetNextSelectedItem(posn); + DWORD driveID = pListView->GetItemData(num); + UINT formatID = 0; - if (HIBYTE(HIWORD(driveID)) == 0xaa) { - fChosenDrive.Format("%s%d:%d:%d\\", - DiskImgLib::kASPIDev, - LOBYTE(HIWORD(driveID)), - HIBYTE(LOWORD(driveID)), - LOBYTE(LOWORD(driveID))); - //ForceReadOnly(true); - } else if (driveID >= 'A' && driveID <= 'Z') { - /* - * Do we want to let them do this? We show some logical drives - * that we don't want them to actually use. - */ - switch (fVolumeInfo[driveID-'A'].driveType) { - case DRIVE_REMOVABLE: - case DRIVE_FIXED: - break; // allow - case DRIVE_CDROM: //formatID = IDS_VOLUME_NO_CDROM; - ForceReadOnly(true); - break; - case DRIVE_REMOTE: formatID = IDS_VOLUME_NO_REMOTE; - break; - case DRIVE_RAMDISK: formatID = IDS_VOLUME_NO_RAMDISK; - break; - case DRIVE_UNKNOWN: - case DRIVE_NO_ROOT_DIR: - default: formatID = IDS_VOLUME_NO_GENERIC; - break; - } + if (HIBYTE(HIWORD(driveID)) == 0xaa) { + fChosenDrive.Format("%s%d:%d:%d\\", + DiskImgLib::kASPIDev, + LOBYTE(HIWORD(driveID)), + HIBYTE(LOWORD(driveID)), + LOBYTE(LOWORD(driveID))); + //ForceReadOnly(true); + } else if (driveID >= 'A' && driveID <= 'Z') { + /* + * Do we want to let them do this? We show some logical drives + * that we don't want them to actually use. + */ + switch (fVolumeInfo[driveID-'A'].driveType) { + case DRIVE_REMOVABLE: + case DRIVE_FIXED: + break; // allow + case DRIVE_CDROM: //formatID = IDS_VOLUME_NO_CDROM; + ForceReadOnly(true); + break; + case DRIVE_REMOTE: formatID = IDS_VOLUME_NO_REMOTE; + break; + case DRIVE_RAMDISK: formatID = IDS_VOLUME_NO_RAMDISK; + break; + case DRIVE_UNKNOWN: + case DRIVE_NO_ROOT_DIR: + default: formatID = IDS_VOLUME_NO_GENERIC; + break; + } - fChosenDrive.Format("%c:\\", driveID); - } else if ((driveID >= 0 && driveID < 4) || - (driveID >= 0x80 && driveID < 0x88)) - { - fChosenDrive.Format("%02x:\\", driveID); - } else { - ASSERT(false); - return; - } + fChosenDrive.Format("%c:\\", driveID); + } else if ((driveID >= 0 && driveID < 4) || + (driveID >= 0x80 && driveID < 0x88)) + { + fChosenDrive.Format("%02x:\\", driveID); + } else { + ASSERT(false); + return; + } - if (formatID != 0) { - CString msg, notAllowed; + if (formatID != 0) { + CString msg, notAllowed; - notAllowed.LoadString(IDS_NOT_ALLOWED); - msg.LoadString(formatID); - MessageBox(msg, notAllowed, MB_OK); - } else { - Preferences* pPreferences = GET_PREFERENCES_WR(); - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_VOLUME_FILTER); - pPreferences->SetPrefLong(kPrVolumeFilter, pCombo->GetCurSel()); - WMSG1("SETTING PREF TO %ld\n", pCombo->GetCurSel()); + notAllowed.LoadString(IDS_NOT_ALLOWED); + msg.LoadString(formatID); + MessageBox(msg, notAllowed, MB_OK); + } else { + Preferences* pPreferences = GET_PREFERENCES_WR(); + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_VOLUME_FILTER); + pPreferences->SetPrefLong(kPrVolumeFilter, pCombo->GetCurSel()); + WMSG1("SETTING PREF TO %ld\n", pCombo->GetCurSel()); - CDialog::OnOK(); - } + CDialog::OnOK(); + } } @@ -715,7 +715,7 @@ OpenVolumeDialog::OnOK(void) void OpenVolumeDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_OPEN_VOLUME, HELP_CONTEXT); + WinHelp(HELP_TOPIC_OPEN_VOLUME, HELP_CONTEXT); } @@ -725,12 +725,12 @@ OpenVolumeDialog::OnHelp(void) void OpenVolumeDialog::ForceReadOnly(bool readOnly) const { - CButton* pButton = (CButton*) GetDlgItem(IDC_OPENVOL_READONLY); - ASSERT(pButton != nil); + CButton* pButton = (CButton*) GetDlgItem(IDC_OPENVOL_READONLY); + ASSERT(pButton != nil); - if (readOnly) - pButton->SetCheck(BST_CHECKED); - else - pButton->SetCheck(BST_UNCHECKED); - WMSG1("FORCED READ ONLY %d\n", readOnly); + if (readOnly) + pButton->SetCheck(BST_CHECKED); + else + pButton->SetCheck(BST_UNCHECKED); + WMSG1("FORCED READ ONLY %d\n", readOnly); } diff --git a/app/OpenVolumeDialog.h b/app/OpenVolumeDialog.h index 169dcc8..776ec5a 100644 --- a/app/OpenVolumeDialog.h +++ b/app/OpenVolumeDialog.h @@ -18,53 +18,53 @@ */ class OpenVolumeDialog : public CDialog { public: - OpenVolumeDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_OPENVOLUMEDLG, pParentWnd), - fChosenDrive(""), - fAllowROChange(true) - { - Preferences* pPreferences = GET_PREFERENCES_WR(); - fReadOnly = pPreferences->GetPrefBool(kPrOpenVolumeRO); - } + OpenVolumeDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_OPENVOLUMEDLG, pParentWnd), + fChosenDrive(""), + fAllowROChange(true) + { + Preferences* pPreferences = GET_PREFERENCES_WR(); + fReadOnly = pPreferences->GetPrefBool(kPrOpenVolumeRO); + } - // Result: drive to open (e.g. "A:\" or "80:\") - CString fChosenDrive; + // Result: drive to open (e.g. "A:\" or "80:\") + CString fChosenDrive; - // Did the user check "read only"? (sets default and holds return val) - BOOL fReadOnly; - // Set before calling DoModal to disable "read only" checkbox - bool fAllowROChange; + // Did the user check "read only"? (sets default and holds return val) + BOOL fReadOnly; + // Set before calling DoModal to disable "read only" checkbox + bool fAllowROChange; protected: - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); - virtual void OnOK(void); - - afx_msg void OnHelp(void); - afx_msg void OnListChange(NMHDR* pNotifyStruct, LRESULT* pResult); - afx_msg void OnListDblClick(NMHDR* pNotifyStruct, LRESULT* pResult); - afx_msg void OnVolumeFilterSelChange(void); + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); + virtual void OnOK(void); + + afx_msg void OnHelp(void); + afx_msg void OnListChange(NMHDR* pNotifyStruct, LRESULT* pResult); + afx_msg void OnListDblClick(NMHDR* pNotifyStruct, LRESULT* pResult); + afx_msg void OnVolumeFilterSelChange(void); - // 0 is default; numbers must match up with pop-up menu order - // order also matters for range test in OnInitDialog - enum { kBoth=0, kLogical=1, kPhysical=2 }; - // common constants - enum { kMaxLogicalDrives = 26, kMaxPhysicalDrives = 8 }; + // 0 is default; numbers must match up with pop-up menu order + // order also matters for range test in OnInitDialog + enum { kBoth=0, kLogical=1, kPhysical=2 }; + // common constants + enum { kMaxLogicalDrives = 26, kMaxPhysicalDrives = 8 }; - void LoadDriveList(void); - bool LoadLogicalDriveList(CListCtrl* pListView, int* pItemIndex); - bool LoadPhysicalDriveList(CListCtrl* pListView, int* pItemIndex); - bool HasPhysicalDriveWin9x(int unit, CString* pRemark); - bool HasPhysicalDriveWin2K(int unit, CString* pRemark); + void LoadDriveList(void); + bool LoadLogicalDriveList(CListCtrl* pListView, int* pItemIndex); + bool LoadPhysicalDriveList(CListCtrl* pListView, int* pItemIndex); + bool HasPhysicalDriveWin9x(int unit, CString* pRemark); + bool HasPhysicalDriveWin2K(int unit, CString* pRemark); - void ForceReadOnly(bool readOnly) const; + void ForceReadOnly(bool readOnly) const; - struct { - unsigned int driveType; - } fVolumeInfo[kMaxLogicalDrives]; + struct { + unsigned int driveType; + } fVolumeInfo[kMaxLogicalDrives]; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__OPEN_VOLUME_DIALOG__*/ \ No newline at end of file diff --git a/app/PasteSpecialDialog.cpp b/app/PasteSpecialDialog.cpp index a101ab1..053445e 100644 --- a/app/PasteSpecialDialog.cpp +++ b/app/PasteSpecialDialog.cpp @@ -16,14 +16,14 @@ END_MESSAGE_MAP() BOOL PasteSpecialDialog::OnInitDialog(void) { - CString countStr; - CWnd* pWnd; + CString countStr; + CWnd* pWnd; - countStr.Format(IDS_PASTE_SPECIAL_COUNT, 3); - pWnd = GetDlgItem(IDC_PASTE_SPECIAL_COUNT); - pWnd->SetWindowText(countStr); + countStr.Format(IDS_PASTE_SPECIAL_COUNT, 3); + pWnd = GetDlgItem(IDC_PASTE_SPECIAL_COUNT); + pWnd->SetWindowText(countStr); - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } #endif @@ -33,22 +33,22 @@ PasteSpecialDialog::OnInitDialog(void) void PasteSpecialDialog::DoDataExchange(CDataExchange* pDX) { - if (!pDX->m_bSaveAndValidate) { - UINT ctrlId; + if (!pDX->m_bSaveAndValidate) { + UINT ctrlId; - if (fPasteHow == kPastePaths) - ctrlId = IDC_PASTE_SPECIAL_PATHS; - else - ctrlId = IDC_PASTE_SPECIAL_NOPATHS; + if (fPasteHow == kPastePaths) + ctrlId = IDC_PASTE_SPECIAL_PATHS; + else + ctrlId = IDC_PASTE_SPECIAL_NOPATHS; - CButton* pButton = (CButton*) GetDlgItem(ctrlId); - pButton->SetCheck(BST_CHECKED); - } else { - CButton* pButton = (CButton*) GetDlgItem(IDC_PASTE_SPECIAL_PATHS); + CButton* pButton = (CButton*) GetDlgItem(ctrlId); + pButton->SetCheck(BST_CHECKED); + } else { + CButton* pButton = (CButton*) GetDlgItem(IDC_PASTE_SPECIAL_PATHS); - if (pButton->GetCheck() == BST_CHECKED) - fPasteHow = kPastePaths; - else - fPasteHow = kPasteNoPaths; - } + if (pButton->GetCheck() == BST_CHECKED) + fPasteHow = kPastePaths; + else + fPasteHow = kPasteNoPaths; + } } diff --git a/app/PasteSpecialDialog.h b/app/PasteSpecialDialog.h index 08c9a12..be26493 100644 --- a/app/PasteSpecialDialog.h +++ b/app/PasteSpecialDialog.h @@ -16,26 +16,26 @@ */ class PasteSpecialDialog : public CDialog { public: - PasteSpecialDialog(CWnd* pParentWnd = nil) : - CDialog(IDD_PASTE_SPECIAL, pParentWnd), - fPasteHow(kPastePaths) - {} - virtual ~PasteSpecialDialog() {} + PasteSpecialDialog(CWnd* pParentWnd = nil) : + CDialog(IDD_PASTE_SPECIAL, pParentWnd), + fPasteHow(kPastePaths) + {} + virtual ~PasteSpecialDialog() {} - /* right now this is boolean, but that may change */ - /* (e.g. "paste clipboard contents into new text file") */ - enum { - kPasteUnknown = 0, - kPastePaths, - kPasteNoPaths, - }; - int fPasteHow; + /* right now this is boolean, but that may change */ + /* (e.g. "paste clipboard contents into new text file") */ + enum { + kPasteUnknown = 0, + kPastePaths, + kPasteNoPaths, + }; + int fPasteHow; protected: - //virtual BOOL OnInitDialog(void); - void DoDataExchange(CDataExchange* pDX); + //virtual BOOL OnInitDialog(void); + void DoDataExchange(CDataExchange* pDX); - //DECLARE_MESSAGE_MAP() + //DECLARE_MESSAGE_MAP() }; #endif /*__PASTESPECIALDIALOG__*/ \ No newline at end of file diff --git a/app/Preferences.cpp b/app/Preferences.cpp index 5007a79..f9f5e51 100644 --- a/app/Preferences.cpp +++ b/app/Preferences.cpp @@ -1,622 +1,622 @@ -/* - * CiderPress - * Copyright (C) 2007, 2008 by faddenSoft, LLC. All Rights Reserved. - * See the file LICENSE for distribution terms. - */ -/* - * Save and restore preferences from the config file. - */ -#include "stdafx.h" -#include "Preferences.h" -#include "NufxArchive.h" -#include "MyApp.h" -#include "../util/UtilLib.h" - -static const char* kDefaultTempPath = "."; - -/* registry section for columns */ -static const char* kColumnSect = _T("columns"); -/* registry section for file add options */ -static const char* kAddSect = _T("add"); -/* registry section for extraction options */ -static const char* kExtractSect = _T("extract"); -/* registry section for view options */ -static const char* kViewSect = _T("view"); -/* registry section for logical/physical volume operations */ -static const char* kVolumeSect = _T("volume"); -/* registry section for file-to-disk options */ -//static const char* kConvDiskSect = _T("conv-disk"); -/* registry section for disk-to-file options */ -static const char* kConvFileSect = _T("conv-file"); -/* registry section for folders */ -static const char* kFolderSect = _T("folders"); -/* registry section for preferences on property pages */ -static const char* kPrefsSect = _T("prefs"); -/* registry section for miscellaneous settings */ -static const char* kMiscSect = _T("misc"); - - -/* - * Map PrefNum to type and registry string. - * - * To make life easier, we require that the PrefNum (first entry) match the - * offset in the table. That way instead of searching for a match we can just - * index into the table. - */ -const Preferences::PrefMap Preferences::fPrefMaps[kPrefNumLastEntry] = { - /**/ { kPrefNumUnknown, kPTNone, nil, nil }, - - { kPrAddIncludeSubFolders, kBool, kAddSect, _T("include-sub-folders") }, - { kPrAddStripFolderNames, kBool, kAddSect, _T("strip-folder-names") }, - { kPrAddOverwriteExisting, kBool, kAddSect, _T("overwrite-existing") }, - { kPrAddTypePreservation, kLong, kAddSect, _T("type-preservation") }, - { kPrAddConvEOL, kLong, kAddSect, _T("conv-eol") }, - -// { kPrExtractPath, kString, kExtractSect, _T("path") }, - { kPrExtractConvEOL, kLong, kExtractSect, _T("conv-eol") }, - { kPrExtractConvHighASCII, kBool, kExtractSect, _T("conv-high-ascii") }, - { kPrExtractIncludeData, kBool, kExtractSect, _T("include-data") }, - { kPrExtractIncludeRsrc, kBool, kExtractSect, _T("include-rsrc") }, - { kPrExtractIncludeDisk, kBool, kExtractSect, _T("include-disk") }, - { kPrExtractEnableReformat, kBool, kExtractSect, _T("enable-reformat") }, - { kPrExtractDiskTo2MG, kBool, kExtractSect, _T("disk-to-2mg") }, - { kPrExtractAddTypePreservation, kBool, kExtractSect, _T("add-type-preservation") }, - { kPrExtractAddExtension, kBool, kExtractSect, _T("add-extension") }, - { kPrExtractStripFolderNames, kBool, kExtractSect, _T("strip-folder-names") }, - { kPrExtractOverwriteExisting, kBool, kExtractSect, _T("overwrite-existing") }, - -// { kPrViewIncludeDataForks, kBool, kViewSect, _T("include-data-forks") }, -// { kPrViewIncludeRsrcForks, kBool, kViewSect, _T("include-rsrc-forks") }, -// { kPrViewIncludeDiskImages, kBool, kViewSect, _T("include-disk-images") }, -// { kPrViewIncludeComments, kBool, kViewSect, _T("include-comments") }, - - { kPrConvFileEmptyFolders, kBool, kConvFileSect, _T("preserve-empty-folders") }, - - { kPrOpenArchiveFolder, kString, kFolderSect, _T("open-archive") }, - { kPrConvertArchiveFolder, kString, kFolderSect, _T("convert-archive") }, - { kPrAddFileFolder, kString, kFolderSect, _T("add-file") }, - { kPrExtractFileFolder, kString, kFolderSect, _T("extract-file") }, - - { kPrVolumeFilter, kLong, kVolumeSect, _T("open-filter") }, - //{ kPrVolumeReadOnly, kBool, kVolumeSect, _T("read-only") }, - - { kPrCassetteAlgorithm, kLong, kVolumeSect, _T("cassette-algorithm") }, - { kPrOpenWAVFolder, kString, kFolderSect, _T("open-wav") }, - - { kPrMimicShrinkIt, kBool, kPrefsSect, _T("mimic-shrinkit") }, - { kPrBadMacSHK, kBool, kPrefsSect, _T("bad-mac-shk") }, - { kPrReduceSHKErrorChecks, kBool, kPrefsSect, _T("reduce-shk-error-checks") }, - { kPrCoerceDOSFilenames, kBool, kPrefsSect, _T("coerce-dos-filenames") }, - { kPrSpacesToUnder, kBool, kPrefsSect, _T("spaces-to-under") }, - { kPrPasteJunkPaths, kBool, kPrefsSect, _T("paste-junk-paths") }, - { kPrBeepOnSuccess, kBool, kPrefsSect, _T("beep-on-success") }, - - { kPrQueryImageFormat, kBool, kPrefsSect, _T("query-image-format") }, - { kPrOpenVolumeRO, kBool, kPrefsSect, _T("open-volume-ro") }, - { kPrOpenVolumePhys0, kBool, kPrefsSect, _T("open-volume-phys0") }, - { kPrProDOSAllowLower, kBool, kPrefsSect, _T("prodos-allow-lower") }, - { kPrProDOSUseSparse, kBool, kPrefsSect, _T("prodos-use-sparse") }, - - { kPrCompressionType, kLong, kPrefsSect, _T("compression-type") }, - - { kPrMaxViewFileSize, kLong, kPrefsSect, _T("max-view-file-size") }, - { kPrNoWrapText, kBool, kPrefsSect, _T("no-wrap-text") }, - - { kPrHighlightHexDump, kBool, kPrefsSect, _T("highlight-hex-dump") }, - { kPrHighlightBASIC, kBool, kPrefsSect, _T("highlight-basic") }, - { kPrConvHiResBlackWhite, kBool, kPrefsSect, _T("conv-hi-res-black-white") }, - { kPrConvDHRAlgorithm, kLong, kPrefsSect, _T("dhr-algorithm") }, - { kPrRelaxGfxTypeCheck, kBool, kPrefsSect, _T("relax-gfx-type-check") }, - { kPrDisasmOneByteBrkCop, kBool, kPrefsSect, _T("disasm-onebytebrkcop") }, - //{ kPrEOLConvRaw, kBool, kPrefsSect, _T("eol-conv-raw") }, - { kPrConvTextEOL_HA, kBool, kPrefsSect, _T("conv-eol-ha") }, - { kPrConvPascalText, kBool, kPrefsSect, _T("conv-pascal-text") }, - { kPrConvPascalCode, kBool, kPrefsSect, _T("conv-pascal-code") }, - { kPrConvCPMText, kBool, kPrefsSect, _T("conv-cpm-text") }, - { kPrConvApplesoft, kBool, kPrefsSect, _T("conv-applesoft") }, - { kPrConvInteger, kBool, kPrefsSect, _T("conv-integer") }, - { kPrConvBusiness, kBool, kPrefsSect, _T("conv-business") }, - { kPrConvGWP, kBool, kPrefsSect, _T("conv-gwp") }, - { kPrConvText8, kBool, kPrefsSect, _T("conv-text8") }, - { kPrConvGutenberg, kBool, kPrefsSect, _T("conv-gutenberg") }, - { kPrConvAWP, kBool, kPrefsSect, _T("conv-awp") }, - { kPrConvADB, kBool, kPrefsSect, _T("conv-adb") }, - { kPrConvASP, kBool, kPrefsSect, _T("conv-asp") }, - { kPrConvSCAssem, kBool, kPrefsSect, _T("conv-scassem") }, - { kPrConvDisasm, kBool, kPrefsSect, _T("conv-disasm") }, - { kPrConvHiRes, kBool, kPrefsSect, _T("conv-hi-res") }, - { kPrConvDHR, kBool, kPrefsSect, _T("conv-dhr") }, - { kPrConvSHR, kBool, kPrefsSect, _T("conv-shr") }, - { kPrConvPrintShop, kBool, kPrefsSect, _T("conv-print-shop") }, - { kPrConvMacPaint, kBool, kPrefsSect, _T("conv-mac-paint") }, - { kPrConvProDOSFolder, kBool, kPrefsSect, _T("conv-prodos-folder") }, - { kPrConvResources, kBool, kPrefsSect, _T("conv-resources") }, - - { kPrTempPath, kString, kPrefsSect, _T("temp-path") }, - { kPrExtViewerExts, kString, kPrefsSect, _T("extviewer-exts") }, - - { kPrLastOpenFilterIndex, kLong, kMiscSect, _T("open-filter-index") }, - - /**/ { kPrefNumLastRegistry, kPTNone, nil, nil }, - - { kPrViewTextTypeFace, kString, nil, nil }, - { kPrViewTextPointSize, kLong, nil, nil }, - { kPrFileViewerWidth, kLong, nil, nil }, - { kPrFileViewerHeight, kLong, nil, nil }, - { kPrDiskImageCreateFormat, kLong, nil, nil }, -}; - -/* - * Constructor. There should be only one Preferences object in the - * application, so this should only be run once. - */ -Preferences::Preferences(void) -{ - WMSG0("Initializing Preferences\n"); - - ScanPrefMaps(); // sanity-check the table - memset(fValues, 0, sizeof(fValues)); - - SetPrefBool(kPrAddIncludeSubFolders, true); - SetPrefBool(kPrAddStripFolderNames, false); - SetPrefBool(kPrAddOverwriteExisting, false); - SetPrefLong(kPrAddTypePreservation, 1); // kPreserveTypes - SetPrefLong(kPrAddConvEOL, 1); // kConvEOLType - - InitFolders(); // set default add/extract folders; overriden by reg - SetPrefLong(kPrExtractConvEOL, 0); // kConvEOLNone - SetPrefBool(kPrExtractConvHighASCII, true); - SetPrefBool(kPrExtractIncludeData, true); - SetPrefBool(kPrExtractIncludeRsrc, false); - SetPrefBool(kPrExtractIncludeDisk, true); - SetPrefBool(kPrExtractEnableReformat, false); - SetPrefBool(kPrExtractDiskTo2MG, false); - SetPrefBool(kPrExtractAddTypePreservation, true); - SetPrefBool(kPrExtractAddExtension, false); - SetPrefBool(kPrExtractStripFolderNames, false); - SetPrefBool(kPrExtractOverwriteExisting, false); - -// SetPrefBool(kPrViewIncludeDataForks, true); -// SetPrefBool(kPrViewIncludeRsrcForks, false); -// SetPrefBool(kPrViewIncludeDiskImages, false); -// SetPrefBool(kPrViewIncludeComments, false); - - SetPrefBool(kPrConvFileEmptyFolders, true); - - // string kPrOpenArchiveFolder - // string kPrAddFileFolder - // string kPrExtractFileFolder - - SetPrefLong(kPrVolumeFilter, 0); - //SetPrefBool(kPrVolumeReadOnly, true); - - SetPrefLong(kPrCassetteAlgorithm, 0); - // string kPrOpenWAVFolder - - SetPrefBool(kPrMimicShrinkIt, false); - SetPrefBool(kPrBadMacSHK, false); - SetPrefBool(kPrReduceSHKErrorChecks, false); - SetPrefBool(kPrCoerceDOSFilenames, false); - SetPrefBool(kPrSpacesToUnder, false); - SetPrefBool(kPrPasteJunkPaths, true); - SetPrefBool(kPrBeepOnSuccess, true); - - SetPrefBool(kPrQueryImageFormat, false); - SetPrefBool(kPrOpenVolumeRO, true); - SetPrefBool(kPrOpenVolumePhys0, false); - SetPrefBool(kPrProDOSAllowLower, false); - SetPrefBool(kPrProDOSUseSparse, true); - - SetPrefLong(kPrCompressionType, DefaultCompressionType()); - - SetPrefLong(kPrMaxViewFileSize, 1024*1024); // 1MB - SetPrefBool(kPrNoWrapText, false); - - SetPrefBool(kPrHighlightHexDump, false); - SetPrefBool(kPrHighlightBASIC, false); - SetPrefBool(kPrConvHiResBlackWhite, false); - SetPrefLong(kPrConvDHRAlgorithm, 1); // latched - SetPrefBool(kPrRelaxGfxTypeCheck, true); - SetPrefBool(kPrDisasmOneByteBrkCop, false); - //SetPrefBool(kPrEOLConvRaw, true); - SetPrefBool(kPrConvTextEOL_HA, true); - SetPrefBool(kPrConvPascalText, true); - SetPrefBool(kPrConvPascalCode, true); - SetPrefBool(kPrConvCPMText, true); - SetPrefBool(kPrConvApplesoft, true); - SetPrefBool(kPrConvInteger, true); - SetPrefBool(kPrConvBusiness, true); - SetPrefBool(kPrConvGWP, true); - SetPrefBool(kPrConvText8, true); - SetPrefBool(kPrConvGutenberg, true); - SetPrefBool(kPrConvAWP, true); - SetPrefBool(kPrConvADB, true); - SetPrefBool(kPrConvASP, true); - SetPrefBool(kPrConvSCAssem, true); - SetPrefBool(kPrConvDisasm, true); - SetPrefBool(kPrConvHiRes, true); - SetPrefBool(kPrConvDHR, true); - SetPrefBool(kPrConvSHR, true); - SetPrefBool(kPrConvPrintShop, true); - SetPrefBool(kPrConvMacPaint, true); - SetPrefBool(kPrConvProDOSFolder, true); - SetPrefBool(kPrConvResources, true); - - InitTempPath(); // set default for kPrTempPath - SetPrefString(kPrExtViewerExts, "gif; jpg; jpeg"); - - SetPrefLong(kPrLastOpenFilterIndex, 0); - - SetPrefString(kPrViewTextTypeFace, "Courier New"); - SetPrefLong(kPrViewTextPointSize, 10); - long width = 680; /* exact width for 80-column text */ - long height = 510; /* exact height for file viewer to show IIgs graphic */ - if (GetSystemMetrics(SM_CXSCREEN) < width) - width = GetSystemMetrics(SM_CXSCREEN); - if (GetSystemMetrics(SM_CYSCREEN) < height) - height = GetSystemMetrics(SM_CYSCREEN); // may overlap system bar - //width = 640; height = 480; - SetPrefLong(kPrFileViewerWidth, width); - SetPrefLong(kPrFileViewerHeight, height); - SetPrefLong(kPrDiskImageCreateFormat, -1); -} - - -/* - * ========================================================================== - * ColumnLayout - * ========================================================================== - */ - -/* - * Restore column widths. - */ -void -ColumnLayout::LoadFromRegistry(const char* section) -{ - char numBuf[8]; - int i; - - for (i = 0; i < kNumVisibleColumns; i++) { - sprintf(numBuf, "%d", i); - - fColumnWidth[i] = gMyApp.GetProfileInt(section, numBuf, - fColumnWidth[i]); - fColumnWidth[i] = gMyApp.GetProfileInt(section, numBuf, - fColumnWidth[i]); - } - fSortColumn = gMyApp.GetProfileInt(section, _T("sort-column"), fSortColumn); - fAscending = (gMyApp.GetProfileInt(section, _T("ascending"), fAscending) != 0); -} - -/* - * Store column widths. - */ -void -ColumnLayout::SaveToRegistry(const char* section) -{ - char numBuf[8]; - int i; - - for (i = 0; i < kNumVisibleColumns; i++) { - sprintf(numBuf, "%d", i); - - gMyApp.WriteProfileInt(section, numBuf, fColumnWidth[i]); - } - gMyApp.WriteProfileInt(section, _T("sort-column"), fSortColumn); - gMyApp.WriteProfileInt(section, _T("ascending"), fAscending); -} - - -/* - * ========================================================================== - * Preferences - * ========================================================================== - */ - -/* - * Get a default value for the temp path. - */ -void -Preferences::InitTempPath(void) -{ - char buf[MAX_PATH]; - DWORD len; - CString tempPath; - - len = ::GetTempPath(sizeof(buf), buf); - if (len == 0) { - DWORD err = ::GetLastError(); - WMSG1("GetTempPath failed, err=%d\n", err); - tempPath = kDefaultTempPath; - } else if (len >= sizeof(buf)) { - /* sheesh! */ - WMSG1("GetTempPath wants a %d-byte buffer\n", len); - tempPath = kDefaultTempPath; - } else { - tempPath = buf; - } - - PathName path(tempPath); - WMSG1("Temp path is '%s'\n", tempPath); - path.SFNToLFN(); - tempPath = path.GetPathName(); - - WMSG1("Temp path (long form) is '%s'\n", tempPath); - - SetPrefString(kPrTempPath, tempPath); - -// ::GetFullPathName(fTempPath, sizeof(buf), buf, &foo); -// ::SetCurrentDirectory(buf); -// ::GetCurrentDirectory(sizeof(buf2), buf2); -} - -/* - * Set default values for the various folders. - */ -void -Preferences::InitFolders(void) -{ - CString path; - - if (GetMyDocuments(&path)) { - SetPrefString(kPrOpenArchiveFolder, path); - SetPrefString(kPrConvertArchiveFolder, path); - SetPrefString(kPrAddFileFolder, path); - SetPrefString(kPrExtractFileFolder, path); - SetPrefString(kPrOpenWAVFolder, path); - } else { - char buf[MAX_PATH]; - ::GetCurrentDirectory(sizeof(buf), buf); - SetPrefString(kPrOpenArchiveFolder, buf); - SetPrefString(kPrConvertArchiveFolder, buf); - SetPrefString(kPrAddFileFolder, buf); - SetPrefString(kPrExtractFileFolder, buf); - SetPrefString(kPrOpenWAVFolder, buf); - } - - WMSG1("Default folder is '%s'\n", GetPrefString(kPrExtractFileFolder)); -} - -/* - * Get the path to the "My Documents" folder. - */ -bool -Preferences::GetMyDocuments(CString* pPath) -{ - LPITEMIDLIST pidl = nil; - LPMALLOC lpMalloc = nil; - HRESULT hr; - bool result = false; - - hr = ::SHGetMalloc(&lpMalloc); - if (FAILED(hr)) - return nil; - - hr = SHGetSpecialFolderLocation(nil, CSIDL_PERSONAL, &pidl); - if (FAILED(hr)) { - WMSG0("WARNING: unable to get CSIDL_PERSONAL\n"); - goto bail; - } - - result = (Pidl::GetPath(pidl, pPath) != FALSE); - if (!result) { - WMSG0("WARNING: unable to convert CSIDL_PERSONAL to path\n"); - /* fall through with "result" */ - } - -bail: - lpMalloc->Free(pidl); - lpMalloc->Release(); - return result; -} - -/* - * Determine the type of compression to use as a default, based on what this - * version of NufxLib supports. - * - * Note this happens *before* the AppInit call, so we should restrict this to - * things that are version-safe for all of NufxLib v2.x. - */ -int -Preferences::DefaultCompressionType(void) -{ - if (NufxArchive::IsCompressionSupported(kNuThreadFormatLZW2)) - return kNuThreadFormatLZW2; - else - return kNuThreadFormatUncompressed; -} - -/* - * Preference getters and setters. - */ -bool -Preferences::GetPrefBool(PrefNum num) const -{ - if (!ValidateEntry(num, kBool)) - return false; - //return (bool) (fValues[num]); - return (bool) ((long) (fValues[num]) != 0); -} -void -Preferences::SetPrefBool(PrefNum num, bool val) -{ - if (!ValidateEntry(num, kBool)) - return; - fValues[num] = (void*) val; -} -long -Preferences::GetPrefLong(PrefNum num) const -{ - if (!ValidateEntry(num, kLong)) - return -1; - return (long) fValues[num]; -} -void -Preferences::SetPrefLong(PrefNum num, long val) -{ - if (!ValidateEntry(num, kLong)) - return; - fValues[num] = (void*) val; -} -const char* -Preferences::GetPrefString(PrefNum num) const -{ - if (!ValidateEntry(num, kString)) - return nil; - return (const char*) fValues[num]; -} -void -Preferences::SetPrefString(PrefNum num, const char* str) -{ - if (!ValidateEntry(num, kString)) - return; - free(fValues[num]); - if (str == nil) - fValues[num] = nil; - else { - fValues[num] = new char[strlen(str) +1]; - if (fValues[num] != nil) - strcpy((char*)fValues[num], str); - } -} - -/* - * Free storage for any string entries. - */ -void -Preferences::FreeStringValues(void) -{ - int i; - - for (i = 0; i < kPrefNumLastEntry; i++) { - if (fPrefMaps[i].type == kString) { - delete[] fValues[i]; - } - } -} - - -/* - * Do a quick scan of the PrefMaps to identify duplicate, misplaced, and - * missing entries. - */ -void -Preferences::ScanPrefMaps(void) -{ - int i, j; - - /* scan PrefNum */ - for (i = 0; i < kPrefNumLastEntry; i++) { - if (fPrefMaps[i].num != i) { - WMSG2("HEY: PrefMaps[%d] has num=%d\n", i, fPrefMaps[i].num); - ASSERT(false); - break; - } - } - - /* look for duplicate strings */ - for (i = 0; i < kPrefNumLastEntry; i++) { - for (j = i+1; j < kPrefNumLastEntry; j++) { - if (fPrefMaps[i].registryKey == nil || - fPrefMaps[j].registryKey == nil) - { - continue; - } - if (strcasecmp(fPrefMaps[i].registryKey, - fPrefMaps[j].registryKey) == 0 && - strcasecmp(fPrefMaps[i].registrySection, - fPrefMaps[j].registrySection) == 0) - { - WMSG4("HEY: PrefMaps[%d] and [%d] both have '%s'/'%s'\n", - i, j, fPrefMaps[i].registrySection, - fPrefMaps[i].registryKey); - ASSERT(false); - break; - } - } - } -} - -/* - * Load preferences from the registry. - */ -int -Preferences::LoadFromRegistry(void) -{ - CString sval; - bool bval; - long lval; - - WMSG0("Loading preferences from registry\n"); - - fColumnLayout.LoadFromRegistry(kColumnSect); - - int i; - for (i = 0; i < kPrefNumLastRegistry; i++) { - if (fPrefMaps[i].registryKey == nil) - continue; - - switch (fPrefMaps[i].type) { - case kBool: - bval = GetPrefBool(fPrefMaps[i].num); - SetPrefBool(fPrefMaps[i].num, - GetBool(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, bval)); - break; - case kLong: - lval = GetPrefLong(fPrefMaps[i].num); - SetPrefLong(fPrefMaps[i].num, - GetInt(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, lval)); - break; - case kString: - sval = GetPrefString(fPrefMaps[i].num); - SetPrefString(fPrefMaps[i].num, - GetString(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, sval)); - break; - default: - WMSG2("Invalid type %d on num=%d\n", fPrefMaps[i].type, i); - ASSERT(false); - break; - } - } - - return 0; -} - -/* - * Save preferences to the registry. - */ -int -Preferences::SaveToRegistry(void) -{ - WMSG0("Saving preferences to registry\n"); - - fColumnLayout.SaveToRegistry(kColumnSect); - - int i; - for (i = 0; i < kPrefNumLastRegistry; i++) { - if (fPrefMaps[i].registryKey == nil) - continue; - - switch (fPrefMaps[i].type) { - case kBool: - WriteBool(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, - GetPrefBool(fPrefMaps[i].num)); - break; - case kLong: - WriteInt(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, - GetPrefLong(fPrefMaps[i].num)); - break; - case kString: - WriteString(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, - GetPrefString(fPrefMaps[i].num)); - break; - default: - WMSG2("Invalid type %d on num=%d\n", fPrefMaps[i].type, i); - ASSERT(false); - break; - } - } - - return 0; -} +/* + * CiderPress + * Copyright (C) 2007, 2008 by faddenSoft, LLC. All Rights Reserved. + * See the file LICENSE for distribution terms. + */ +/* + * Save and restore preferences from the config file. + */ +#include "stdafx.h" +#include "Preferences.h" +#include "NufxArchive.h" +#include "MyApp.h" +#include "../util/UtilLib.h" + +static const char* kDefaultTempPath = "."; + +/* registry section for columns */ +static const char* kColumnSect = _T("columns"); +/* registry section for file add options */ +static const char* kAddSect = _T("add"); +/* registry section for extraction options */ +static const char* kExtractSect = _T("extract"); +/* registry section for view options */ +static const char* kViewSect = _T("view"); +/* registry section for logical/physical volume operations */ +static const char* kVolumeSect = _T("volume"); +/* registry section for file-to-disk options */ +//static const char* kConvDiskSect = _T("conv-disk"); +/* registry section for disk-to-file options */ +static const char* kConvFileSect = _T("conv-file"); +/* registry section for folders */ +static const char* kFolderSect = _T("folders"); +/* registry section for preferences on property pages */ +static const char* kPrefsSect = _T("prefs"); +/* registry section for miscellaneous settings */ +static const char* kMiscSect = _T("misc"); + + +/* + * Map PrefNum to type and registry string. + * + * To make life easier, we require that the PrefNum (first entry) match the + * offset in the table. That way instead of searching for a match we can just + * index into the table. + */ +const Preferences::PrefMap Preferences::fPrefMaps[kPrefNumLastEntry] = { + /**/ { kPrefNumUnknown, kPTNone, nil, nil }, + + { kPrAddIncludeSubFolders, kBool, kAddSect, _T("include-sub-folders") }, + { kPrAddStripFolderNames, kBool, kAddSect, _T("strip-folder-names") }, + { kPrAddOverwriteExisting, kBool, kAddSect, _T("overwrite-existing") }, + { kPrAddTypePreservation, kLong, kAddSect, _T("type-preservation") }, + { kPrAddConvEOL, kLong, kAddSect, _T("conv-eol") }, + +// { kPrExtractPath, kString, kExtractSect, _T("path") }, + { kPrExtractConvEOL, kLong, kExtractSect, _T("conv-eol") }, + { kPrExtractConvHighASCII, kBool, kExtractSect, _T("conv-high-ascii") }, + { kPrExtractIncludeData, kBool, kExtractSect, _T("include-data") }, + { kPrExtractIncludeRsrc, kBool, kExtractSect, _T("include-rsrc") }, + { kPrExtractIncludeDisk, kBool, kExtractSect, _T("include-disk") }, + { kPrExtractEnableReformat, kBool, kExtractSect, _T("enable-reformat") }, + { kPrExtractDiskTo2MG, kBool, kExtractSect, _T("disk-to-2mg") }, + { kPrExtractAddTypePreservation, kBool, kExtractSect, _T("add-type-preservation") }, + { kPrExtractAddExtension, kBool, kExtractSect, _T("add-extension") }, + { kPrExtractStripFolderNames, kBool, kExtractSect, _T("strip-folder-names") }, + { kPrExtractOverwriteExisting, kBool, kExtractSect, _T("overwrite-existing") }, + +// { kPrViewIncludeDataForks, kBool, kViewSect, _T("include-data-forks") }, +// { kPrViewIncludeRsrcForks, kBool, kViewSect, _T("include-rsrc-forks") }, +// { kPrViewIncludeDiskImages, kBool, kViewSect, _T("include-disk-images") }, +// { kPrViewIncludeComments, kBool, kViewSect, _T("include-comments") }, + + { kPrConvFileEmptyFolders, kBool, kConvFileSect, _T("preserve-empty-folders") }, + + { kPrOpenArchiveFolder, kString, kFolderSect, _T("open-archive") }, + { kPrConvertArchiveFolder, kString, kFolderSect, _T("convert-archive") }, + { kPrAddFileFolder, kString, kFolderSect, _T("add-file") }, + { kPrExtractFileFolder, kString, kFolderSect, _T("extract-file") }, + + { kPrVolumeFilter, kLong, kVolumeSect, _T("open-filter") }, + //{ kPrVolumeReadOnly, kBool, kVolumeSect, _T("read-only") }, + + { kPrCassetteAlgorithm, kLong, kVolumeSect, _T("cassette-algorithm") }, + { kPrOpenWAVFolder, kString, kFolderSect, _T("open-wav") }, + + { kPrMimicShrinkIt, kBool, kPrefsSect, _T("mimic-shrinkit") }, + { kPrBadMacSHK, kBool, kPrefsSect, _T("bad-mac-shk") }, + { kPrReduceSHKErrorChecks, kBool, kPrefsSect, _T("reduce-shk-error-checks") }, + { kPrCoerceDOSFilenames, kBool, kPrefsSect, _T("coerce-dos-filenames") }, + { kPrSpacesToUnder, kBool, kPrefsSect, _T("spaces-to-under") }, + { kPrPasteJunkPaths, kBool, kPrefsSect, _T("paste-junk-paths") }, + { kPrBeepOnSuccess, kBool, kPrefsSect, _T("beep-on-success") }, + + { kPrQueryImageFormat, kBool, kPrefsSect, _T("query-image-format") }, + { kPrOpenVolumeRO, kBool, kPrefsSect, _T("open-volume-ro") }, + { kPrOpenVolumePhys0, kBool, kPrefsSect, _T("open-volume-phys0") }, + { kPrProDOSAllowLower, kBool, kPrefsSect, _T("prodos-allow-lower") }, + { kPrProDOSUseSparse, kBool, kPrefsSect, _T("prodos-use-sparse") }, + + { kPrCompressionType, kLong, kPrefsSect, _T("compression-type") }, + + { kPrMaxViewFileSize, kLong, kPrefsSect, _T("max-view-file-size") }, + { kPrNoWrapText, kBool, kPrefsSect, _T("no-wrap-text") }, + + { kPrHighlightHexDump, kBool, kPrefsSect, _T("highlight-hex-dump") }, + { kPrHighlightBASIC, kBool, kPrefsSect, _T("highlight-basic") }, + { kPrConvHiResBlackWhite, kBool, kPrefsSect, _T("conv-hi-res-black-white") }, + { kPrConvDHRAlgorithm, kLong, kPrefsSect, _T("dhr-algorithm") }, + { kPrRelaxGfxTypeCheck, kBool, kPrefsSect, _T("relax-gfx-type-check") }, + { kPrDisasmOneByteBrkCop, kBool, kPrefsSect, _T("disasm-onebytebrkcop") }, + //{ kPrEOLConvRaw, kBool, kPrefsSect, _T("eol-conv-raw") }, + { kPrConvTextEOL_HA, kBool, kPrefsSect, _T("conv-eol-ha") }, + { kPrConvPascalText, kBool, kPrefsSect, _T("conv-pascal-text") }, + { kPrConvPascalCode, kBool, kPrefsSect, _T("conv-pascal-code") }, + { kPrConvCPMText, kBool, kPrefsSect, _T("conv-cpm-text") }, + { kPrConvApplesoft, kBool, kPrefsSect, _T("conv-applesoft") }, + { kPrConvInteger, kBool, kPrefsSect, _T("conv-integer") }, + { kPrConvBusiness, kBool, kPrefsSect, _T("conv-business") }, + { kPrConvGWP, kBool, kPrefsSect, _T("conv-gwp") }, + { kPrConvText8, kBool, kPrefsSect, _T("conv-text8") }, + { kPrConvGutenberg, kBool, kPrefsSect, _T("conv-gutenberg") }, + { kPrConvAWP, kBool, kPrefsSect, _T("conv-awp") }, + { kPrConvADB, kBool, kPrefsSect, _T("conv-adb") }, + { kPrConvASP, kBool, kPrefsSect, _T("conv-asp") }, + { kPrConvSCAssem, kBool, kPrefsSect, _T("conv-scassem") }, + { kPrConvDisasm, kBool, kPrefsSect, _T("conv-disasm") }, + { kPrConvHiRes, kBool, kPrefsSect, _T("conv-hi-res") }, + { kPrConvDHR, kBool, kPrefsSect, _T("conv-dhr") }, + { kPrConvSHR, kBool, kPrefsSect, _T("conv-shr") }, + { kPrConvPrintShop, kBool, kPrefsSect, _T("conv-print-shop") }, + { kPrConvMacPaint, kBool, kPrefsSect, _T("conv-mac-paint") }, + { kPrConvProDOSFolder, kBool, kPrefsSect, _T("conv-prodos-folder") }, + { kPrConvResources, kBool, kPrefsSect, _T("conv-resources") }, + + { kPrTempPath, kString, kPrefsSect, _T("temp-path") }, + { kPrExtViewerExts, kString, kPrefsSect, _T("extviewer-exts") }, + + { kPrLastOpenFilterIndex, kLong, kMiscSect, _T("open-filter-index") }, + + /**/ { kPrefNumLastRegistry, kPTNone, nil, nil }, + + { kPrViewTextTypeFace, kString, nil, nil }, + { kPrViewTextPointSize, kLong, nil, nil }, + { kPrFileViewerWidth, kLong, nil, nil }, + { kPrFileViewerHeight, kLong, nil, nil }, + { kPrDiskImageCreateFormat, kLong, nil, nil }, +}; + +/* + * Constructor. There should be only one Preferences object in the + * application, so this should only be run once. + */ +Preferences::Preferences(void) +{ + WMSG0("Initializing Preferences\n"); + + ScanPrefMaps(); // sanity-check the table + memset(fValues, 0, sizeof(fValues)); + + SetPrefBool(kPrAddIncludeSubFolders, true); + SetPrefBool(kPrAddStripFolderNames, false); + SetPrefBool(kPrAddOverwriteExisting, false); + SetPrefLong(kPrAddTypePreservation, 1); // kPreserveTypes + SetPrefLong(kPrAddConvEOL, 1); // kConvEOLType + + InitFolders(); // set default add/extract folders; overriden by reg + SetPrefLong(kPrExtractConvEOL, 0); // kConvEOLNone + SetPrefBool(kPrExtractConvHighASCII, true); + SetPrefBool(kPrExtractIncludeData, true); + SetPrefBool(kPrExtractIncludeRsrc, false); + SetPrefBool(kPrExtractIncludeDisk, true); + SetPrefBool(kPrExtractEnableReformat, false); + SetPrefBool(kPrExtractDiskTo2MG, false); + SetPrefBool(kPrExtractAddTypePreservation, true); + SetPrefBool(kPrExtractAddExtension, false); + SetPrefBool(kPrExtractStripFolderNames, false); + SetPrefBool(kPrExtractOverwriteExisting, false); + +// SetPrefBool(kPrViewIncludeDataForks, true); +// SetPrefBool(kPrViewIncludeRsrcForks, false); +// SetPrefBool(kPrViewIncludeDiskImages, false); +// SetPrefBool(kPrViewIncludeComments, false); + + SetPrefBool(kPrConvFileEmptyFolders, true); + + // string kPrOpenArchiveFolder + // string kPrAddFileFolder + // string kPrExtractFileFolder + + SetPrefLong(kPrVolumeFilter, 0); + //SetPrefBool(kPrVolumeReadOnly, true); + + SetPrefLong(kPrCassetteAlgorithm, 0); + // string kPrOpenWAVFolder + + SetPrefBool(kPrMimicShrinkIt, false); + SetPrefBool(kPrBadMacSHK, false); + SetPrefBool(kPrReduceSHKErrorChecks, false); + SetPrefBool(kPrCoerceDOSFilenames, false); + SetPrefBool(kPrSpacesToUnder, false); + SetPrefBool(kPrPasteJunkPaths, true); + SetPrefBool(kPrBeepOnSuccess, true); + + SetPrefBool(kPrQueryImageFormat, false); + SetPrefBool(kPrOpenVolumeRO, true); + SetPrefBool(kPrOpenVolumePhys0, false); + SetPrefBool(kPrProDOSAllowLower, false); + SetPrefBool(kPrProDOSUseSparse, true); + + SetPrefLong(kPrCompressionType, DefaultCompressionType()); + + SetPrefLong(kPrMaxViewFileSize, 1024*1024); // 1MB + SetPrefBool(kPrNoWrapText, false); + + SetPrefBool(kPrHighlightHexDump, false); + SetPrefBool(kPrHighlightBASIC, false); + SetPrefBool(kPrConvHiResBlackWhite, false); + SetPrefLong(kPrConvDHRAlgorithm, 1); // latched + SetPrefBool(kPrRelaxGfxTypeCheck, true); + SetPrefBool(kPrDisasmOneByteBrkCop, false); + //SetPrefBool(kPrEOLConvRaw, true); + SetPrefBool(kPrConvTextEOL_HA, true); + SetPrefBool(kPrConvPascalText, true); + SetPrefBool(kPrConvPascalCode, true); + SetPrefBool(kPrConvCPMText, true); + SetPrefBool(kPrConvApplesoft, true); + SetPrefBool(kPrConvInteger, true); + SetPrefBool(kPrConvBusiness, true); + SetPrefBool(kPrConvGWP, true); + SetPrefBool(kPrConvText8, true); + SetPrefBool(kPrConvGutenberg, true); + SetPrefBool(kPrConvAWP, true); + SetPrefBool(kPrConvADB, true); + SetPrefBool(kPrConvASP, true); + SetPrefBool(kPrConvSCAssem, true); + SetPrefBool(kPrConvDisasm, true); + SetPrefBool(kPrConvHiRes, true); + SetPrefBool(kPrConvDHR, true); + SetPrefBool(kPrConvSHR, true); + SetPrefBool(kPrConvPrintShop, true); + SetPrefBool(kPrConvMacPaint, true); + SetPrefBool(kPrConvProDOSFolder, true); + SetPrefBool(kPrConvResources, true); + + InitTempPath(); // set default for kPrTempPath + SetPrefString(kPrExtViewerExts, "gif; jpg; jpeg"); + + SetPrefLong(kPrLastOpenFilterIndex, 0); + + SetPrefString(kPrViewTextTypeFace, "Courier New"); + SetPrefLong(kPrViewTextPointSize, 10); + long width = 680; /* exact width for 80-column text */ + long height = 510; /* exact height for file viewer to show IIgs graphic */ + if (GetSystemMetrics(SM_CXSCREEN) < width) + width = GetSystemMetrics(SM_CXSCREEN); + if (GetSystemMetrics(SM_CYSCREEN) < height) + height = GetSystemMetrics(SM_CYSCREEN); // may overlap system bar + //width = 640; height = 480; + SetPrefLong(kPrFileViewerWidth, width); + SetPrefLong(kPrFileViewerHeight, height); + SetPrefLong(kPrDiskImageCreateFormat, -1); +} + + +/* + * ========================================================================== + * ColumnLayout + * ========================================================================== + */ + +/* + * Restore column widths. + */ +void +ColumnLayout::LoadFromRegistry(const char* section) +{ + char numBuf[8]; + int i; + + for (i = 0; i < kNumVisibleColumns; i++) { + sprintf(numBuf, "%d", i); + + fColumnWidth[i] = gMyApp.GetProfileInt(section, numBuf, + fColumnWidth[i]); + fColumnWidth[i] = gMyApp.GetProfileInt(section, numBuf, + fColumnWidth[i]); + } + fSortColumn = gMyApp.GetProfileInt(section, _T("sort-column"), fSortColumn); + fAscending = (gMyApp.GetProfileInt(section, _T("ascending"), fAscending) != 0); +} + +/* + * Store column widths. + */ +void +ColumnLayout::SaveToRegistry(const char* section) +{ + char numBuf[8]; + int i; + + for (i = 0; i < kNumVisibleColumns; i++) { + sprintf(numBuf, "%d", i); + + gMyApp.WriteProfileInt(section, numBuf, fColumnWidth[i]); + } + gMyApp.WriteProfileInt(section, _T("sort-column"), fSortColumn); + gMyApp.WriteProfileInt(section, _T("ascending"), fAscending); +} + + +/* + * ========================================================================== + * Preferences + * ========================================================================== + */ + +/* + * Get a default value for the temp path. + */ +void +Preferences::InitTempPath(void) +{ + char buf[MAX_PATH]; + DWORD len; + CString tempPath; + + len = ::GetTempPath(sizeof(buf), buf); + if (len == 0) { + DWORD err = ::GetLastError(); + WMSG1("GetTempPath failed, err=%d\n", err); + tempPath = kDefaultTempPath; + } else if (len >= sizeof(buf)) { + /* sheesh! */ + WMSG1("GetTempPath wants a %d-byte buffer\n", len); + tempPath = kDefaultTempPath; + } else { + tempPath = buf; + } + + PathName path(tempPath); + WMSG1("Temp path is '%s'\n", tempPath); + path.SFNToLFN(); + tempPath = path.GetPathName(); + + WMSG1("Temp path (long form) is '%s'\n", tempPath); + + SetPrefString(kPrTempPath, tempPath); + +// ::GetFullPathName(fTempPath, sizeof(buf), buf, &foo); +// ::SetCurrentDirectory(buf); +// ::GetCurrentDirectory(sizeof(buf2), buf2); +} + +/* + * Set default values for the various folders. + */ +void +Preferences::InitFolders(void) +{ + CString path; + + if (GetMyDocuments(&path)) { + SetPrefString(kPrOpenArchiveFolder, path); + SetPrefString(kPrConvertArchiveFolder, path); + SetPrefString(kPrAddFileFolder, path); + SetPrefString(kPrExtractFileFolder, path); + SetPrefString(kPrOpenWAVFolder, path); + } else { + char buf[MAX_PATH]; + ::GetCurrentDirectory(sizeof(buf), buf); + SetPrefString(kPrOpenArchiveFolder, buf); + SetPrefString(kPrConvertArchiveFolder, buf); + SetPrefString(kPrAddFileFolder, buf); + SetPrefString(kPrExtractFileFolder, buf); + SetPrefString(kPrOpenWAVFolder, buf); + } + + WMSG1("Default folder is '%s'\n", GetPrefString(kPrExtractFileFolder)); +} + +/* + * Get the path to the "My Documents" folder. + */ +bool +Preferences::GetMyDocuments(CString* pPath) +{ + LPITEMIDLIST pidl = nil; + LPMALLOC lpMalloc = nil; + HRESULT hr; + bool result = false; + + hr = ::SHGetMalloc(&lpMalloc); + if (FAILED(hr)) + return nil; + + hr = SHGetSpecialFolderLocation(nil, CSIDL_PERSONAL, &pidl); + if (FAILED(hr)) { + WMSG0("WARNING: unable to get CSIDL_PERSONAL\n"); + goto bail; + } + + result = (Pidl::GetPath(pidl, pPath) != FALSE); + if (!result) { + WMSG0("WARNING: unable to convert CSIDL_PERSONAL to path\n"); + /* fall through with "result" */ + } + +bail: + lpMalloc->Free(pidl); + lpMalloc->Release(); + return result; +} + +/* + * Determine the type of compression to use as a default, based on what this + * version of NufxLib supports. + * + * Note this happens *before* the AppInit call, so we should restrict this to + * things that are version-safe for all of NufxLib v2.x. + */ +int +Preferences::DefaultCompressionType(void) +{ + if (NufxArchive::IsCompressionSupported(kNuThreadFormatLZW2)) + return kNuThreadFormatLZW2; + else + return kNuThreadFormatUncompressed; +} + +/* + * Preference getters and setters. + */ +bool +Preferences::GetPrefBool(PrefNum num) const +{ + if (!ValidateEntry(num, kBool)) + return false; + //return (bool) (fValues[num]); + return (bool) ((long) (fValues[num]) != 0); +} +void +Preferences::SetPrefBool(PrefNum num, bool val) +{ + if (!ValidateEntry(num, kBool)) + return; + fValues[num] = (void*) val; +} +long +Preferences::GetPrefLong(PrefNum num) const +{ + if (!ValidateEntry(num, kLong)) + return -1; + return (long) fValues[num]; +} +void +Preferences::SetPrefLong(PrefNum num, long val) +{ + if (!ValidateEntry(num, kLong)) + return; + fValues[num] = (void*) val; +} +const char* +Preferences::GetPrefString(PrefNum num) const +{ + if (!ValidateEntry(num, kString)) + return nil; + return (const char*) fValues[num]; +} +void +Preferences::SetPrefString(PrefNum num, const char* str) +{ + if (!ValidateEntry(num, kString)) + return; + free(fValues[num]); + if (str == nil) + fValues[num] = nil; + else { + fValues[num] = new char[strlen(str) +1]; + if (fValues[num] != nil) + strcpy((char*)fValues[num], str); + } +} + +/* + * Free storage for any string entries. + */ +void +Preferences::FreeStringValues(void) +{ + int i; + + for (i = 0; i < kPrefNumLastEntry; i++) { + if (fPrefMaps[i].type == kString) { + delete[] fValues[i]; + } + } +} + + +/* + * Do a quick scan of the PrefMaps to identify duplicate, misplaced, and + * missing entries. + */ +void +Preferences::ScanPrefMaps(void) +{ + int i, j; + + /* scan PrefNum */ + for (i = 0; i < kPrefNumLastEntry; i++) { + if (fPrefMaps[i].num != i) { + WMSG2("HEY: PrefMaps[%d] has num=%d\n", i, fPrefMaps[i].num); + ASSERT(false); + break; + } + } + + /* look for duplicate strings */ + for (i = 0; i < kPrefNumLastEntry; i++) { + for (j = i+1; j < kPrefNumLastEntry; j++) { + if (fPrefMaps[i].registryKey == nil || + fPrefMaps[j].registryKey == nil) + { + continue; + } + if (strcasecmp(fPrefMaps[i].registryKey, + fPrefMaps[j].registryKey) == 0 && + strcasecmp(fPrefMaps[i].registrySection, + fPrefMaps[j].registrySection) == 0) + { + WMSG4("HEY: PrefMaps[%d] and [%d] both have '%s'/'%s'\n", + i, j, fPrefMaps[i].registrySection, + fPrefMaps[i].registryKey); + ASSERT(false); + break; + } + } + } +} + +/* + * Load preferences from the registry. + */ +int +Preferences::LoadFromRegistry(void) +{ + CString sval; + bool bval; + long lval; + + WMSG0("Loading preferences from registry\n"); + + fColumnLayout.LoadFromRegistry(kColumnSect); + + int i; + for (i = 0; i < kPrefNumLastRegistry; i++) { + if (fPrefMaps[i].registryKey == nil) + continue; + + switch (fPrefMaps[i].type) { + case kBool: + bval = GetPrefBool(fPrefMaps[i].num); + SetPrefBool(fPrefMaps[i].num, + GetBool(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, bval)); + break; + case kLong: + lval = GetPrefLong(fPrefMaps[i].num); + SetPrefLong(fPrefMaps[i].num, + GetInt(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, lval)); + break; + case kString: + sval = GetPrefString(fPrefMaps[i].num); + SetPrefString(fPrefMaps[i].num, + GetString(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, sval)); + break; + default: + WMSG2("Invalid type %d on num=%d\n", fPrefMaps[i].type, i); + ASSERT(false); + break; + } + } + + return 0; +} + +/* + * Save preferences to the registry. + */ +int +Preferences::SaveToRegistry(void) +{ + WMSG0("Saving preferences to registry\n"); + + fColumnLayout.SaveToRegistry(kColumnSect); + + int i; + for (i = 0; i < kPrefNumLastRegistry; i++) { + if (fPrefMaps[i].registryKey == nil) + continue; + + switch (fPrefMaps[i].type) { + case kBool: + WriteBool(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, + GetPrefBool(fPrefMaps[i].num)); + break; + case kLong: + WriteInt(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, + GetPrefLong(fPrefMaps[i].num)); + break; + case kString: + WriteString(fPrefMaps[i].registrySection, fPrefMaps[i].registryKey, + GetPrefString(fPrefMaps[i].num)); + break; + default: + WMSG2("Invalid type %d on num=%d\n", fPrefMaps[i].type, i); + ASSERT(false); + break; + } + } + + return 0; +} diff --git a/app/Preferences.h b/app/Preferences.h index d92741e..6609b6c 100644 --- a/app/Preferences.h +++ b/app/Preferences.h @@ -1,300 +1,300 @@ -/* - * CiderPress - * Copyright (C) 2007, 2008 by faddenSoft, LLC. All Rights Reserved. - * See the file LICENSE for distribution terms. - */ -/* - * Keep track of user preferences. - * - * How to add a new preference item: - * - Add an entry to the PrefNum enum, below. - * - Add a corresponding entry to Preferences::fPrefMaps, adding a new - * section to the registry if appropriate. - * - Add a default value to Preferences::Preferences. If not specified, - * strings will be nil and numeric values will be zero. - */ -#ifndef __PREFERENCES__ -#define __PREFERENCES__ - -#include "MyApp.h" - -class ContentList; - -/* - * Number of visible columns. (We no longer have "invisible" columns, so the - * name is somewhat misleading.) - * - * This is used widely. Update with care. - */ -const int kNumVisibleColumns = 9; - -/* - * Used to save & restore column layout and sorting preferences for - * the ContentList class. - */ -class ColumnLayout { -public: - ColumnLayout(void) { - for (int i = 0; i < kNumVisibleColumns; i++) - fColumnWidth[i] = kWidthDefaulted; - fSortColumn = kNumVisibleColumns; // means "use original order" - fAscending = true; - } - ~ColumnLayout(void) {} - - void LoadFromRegistry(const char* section); - void SaveToRegistry(const char* section); - - int GetColumnWidth(int col) const { - ASSERT(col >= 0 && col < kNumVisibleColumns); - return fColumnWidth[col]; - } - void SetColumnWidth(int col, int width) { - ASSERT(col >= 0 && col < kNumVisibleColumns); - ASSERT(width >= 0 || width == kWidthDefaulted); - fColumnWidth[col] = width; - } - - int GetSortColumn(void) const { return fSortColumn; } - void SetSortColumn(int col) { - ASSERT(col >= 0 && col <= kNumVisibleColumns); - fSortColumn = col; - } - bool GetAscending(void) const { return fAscending; } - void SetAscending(bool val) { fAscending = val; } - - /* column width value used to flag "defaulted" status */ - enum { kWidthDefaulted = -1 }; - /* minimium width of column 0 (pathname) */ - enum { kMinCol0Width = 50 }; - -private: - // Create a dummy list control to get default column widths. - void DetermineDefaultWidths(ContentList* pList); - - int fColumnWidth[kNumVisibleColumns]; - int fSortColumn; - bool fAscending; -}; - - -/* - * Preferences type enumeration. - * - * This is logically part of the Preferences object, but it's annoying to - * have to specify the scope resolution operator everywhere. - */ -typedef enum { - /**/ kPrefNumUnknown = 0, - -/* these are saved in the registry */ - - // sticky settings for add file options - kPrAddIncludeSubFolders, // bool - kPrAddStripFolderNames, // bool - kPrAddOverwriteExisting, // bool - kPrAddTypePreservation, // long - kPrAddConvEOL, // long - - // sticky settings for file extraction - //kPrExtractPath, // string - kPrExtractConvEOL, // long - kPrExtractConvHighASCII, // bool - kPrExtractIncludeData, // bool - kPrExtractIncludeRsrc, // bool - kPrExtractIncludeDisk, // bool - kPrExtractEnableReformat, // bool - kPrExtractDiskTo2MG, // bool - kPrExtractAddTypePreservation, // bool - kPrExtractAddExtension, // bool - kPrExtractStripFolderNames, // bool - kPrExtractOverwriteExisting, // bool - -// // view file options -// kPrViewIncludeDataForks, // bool -// kPrViewIncludeRsrcForks, // bool -// kPrViewIncludeDiskImages, // bool -// kPrViewIncludeComments, // bool - - // convert disk image to file archive - //kPrConvFileConvDOSText, // bool - //kPrConvFileConvPascalText, // bool - kPrConvFileEmptyFolders, // bool - - // folders for CFileDialog initialization - kPrOpenArchiveFolder, // string - kPrConvertArchiveFolder, // string - kPrAddFileFolder, // string - kPrExtractFileFolder, // string - - // logical/physical volume prefs - kPrVolumeFilter, // long - //kPrVolumeReadOnly, // bool - - // cassette import/export prefs - kPrCassetteAlgorithm, // long - kPrOpenWAVFolder, // string - - // items from the Preferences propertypages (must be saved/restored) - kPrMimicShrinkIt, // bool - kPrBadMacSHK, // bool - kPrReduceSHKErrorChecks, // bool - kPrCoerceDOSFilenames, // bool - kPrSpacesToUnder, // bool - kPrPasteJunkPaths, // bool - kPrBeepOnSuccess, // bool - - kPrQueryImageFormat, // bool - kPrOpenVolumeRO, // bool - kPrOpenVolumePhys0, // bool - kPrProDOSAllowLower, // bool - kPrProDOSUseSparse, // bool - - kPrCompressionType, // long - - kPrMaxViewFileSize, // long - kPrNoWrapText, // bool - - kPrHighlightHexDump, // bool - kPrHighlightBASIC, // bool - kPrConvHiResBlackWhite, // bool - kPrConvDHRAlgorithm, // long - kPrRelaxGfxTypeCheck, // bool - kPrDisasmOneByteBrkCop, // bool - //kPrEOLConvRaw, // bool - kPrConvTextEOL_HA, // bool - kPrConvPascalText, // bool - kPrConvPascalCode, // bool - kPrConvCPMText, // bool - kPrConvApplesoft, // bool - kPrConvInteger, // bool - kPrConvBusiness, // bool - kPrConvGWP, // bool - kPrConvText8, // bool - kPrConvGutenberg, // bool - kPrConvAWP, // bool - kPrConvADB, // bool - kPrConvASP, // bool - kPrConvSCAssem, // bool - kPrConvDisasm, // bool - kPrConvHiRes, // bool - kPrConvDHR, // bool - kPrConvSHR, // bool - kPrConvPrintShop, // bool - kPrConvMacPaint, // bool - kPrConvProDOSFolder, // bool - kPrConvResources, // bool - - kPrTempPath, // string - kPrExtViewerExts, // string - - // open file dialog - kPrLastOpenFilterIndex, // long - - /**/ kPrefNumLastRegistry, -/* these are temporary settings, not saved in the registry */ - - // sticky settings for internal file viewer (ViewFilesDialog) - kPrViewTextTypeFace, // string - kPrViewTextPointSize, // long - kPrFileViewerWidth, // long - kPrFileViewerHeight, // long - - // sticky setting for disk image creator - kPrDiskImageCreateFormat, // long - - /**/ kPrefNumLastEntry -} PrefNum; - - -/* - * Container for preferences. - */ -class Preferences { -public: - Preferences(void); - ~Preferences(void) { - FreeStringValues(); - } - - // Load/save preferences from/to registry. - int LoadFromRegistry(void); - int SaveToRegistry(void); - - ColumnLayout* GetColumnLayout(void) { return &fColumnLayout; } - //bool GetShowToolbarText(void) const { return fShowToolbarText; } - //void SetShowToolbarText(bool val) { fShowToolbarText = val; } - - bool GetPrefBool(PrefNum num) const; - void SetPrefBool(PrefNum num, bool val); - long GetPrefLong(PrefNum num) const; - void SetPrefLong(PrefNum num, long val); - const char* GetPrefString(PrefNum num) const; - void SetPrefString(PrefNum num, const char* str); - - -private: - void InitTempPath(void); - void InitFolders(void); - bool GetMyDocuments(CString* pPath); - int DefaultCompressionType(void); - void FreeStringValues(void); - - /* - * Internal data structure used to manage preferences. - */ - typedef enum { kPTNone, kBool, kLong, kString } PrefType; - typedef struct PrefMap { - PrefNum num; - PrefType type; - const char* registrySection; - const char* registryKey; - } PrefMap; - static const PrefMap fPrefMaps[kPrefNumLastEntry]; - void ScanPrefMaps(void); - - // this holds the actual values - void* fValues[kPrefNumLastEntry]; - - // verify that the entry exists and has the expected type - bool ValidateEntry(PrefNum num, PrefType type) const { - if (num <= kPrefNumUnknown || num >= kPrefNumLastEntry) { - ASSERT(false); - return false; - } - if (fPrefMaps[num].type != type) { - ASSERT(false); - return false; - } - return true; - } - - // column widths for ContentList - ColumnLayout fColumnLayout; - - /* - * Registry helpers. - */ - UINT GetInt(const char* section, const char* key, int dflt) { - return gMyApp.GetProfileInt(section, key, dflt); - } - bool GetBool(const char* section, const char* key, bool dflt) { - return (gMyApp.GetProfileInt(section, key, dflt) != 0); - } - CString GetString(const char* section, const char* key, - const char* dflt) - { - return gMyApp.GetProfileString(section, key, dflt); - } - BOOL WriteInt(const char* section, const char* key, int value) { - return gMyApp.WriteProfileInt(section, key, value); - } - BOOL WriteBool(const char* section, const char* key, bool value) { - return gMyApp.WriteProfileInt(section, key, value); - } - BOOL WriteString(const char* section, const char* key, const char* value) { - return gMyApp.WriteProfileString(section, key, value); - } -}; - +/* + * CiderPress + * Copyright (C) 2007, 2008 by faddenSoft, LLC. All Rights Reserved. + * See the file LICENSE for distribution terms. + */ +/* + * Keep track of user preferences. + * + * How to add a new preference item: + * - Add an entry to the PrefNum enum, below. + * - Add a corresponding entry to Preferences::fPrefMaps, adding a new + * section to the registry if appropriate. + * - Add a default value to Preferences::Preferences. If not specified, + * strings will be nil and numeric values will be zero. + */ +#ifndef __PREFERENCES__ +#define __PREFERENCES__ + +#include "MyApp.h" + +class ContentList; + +/* + * Number of visible columns. (We no longer have "invisible" columns, so the + * name is somewhat misleading.) + * + * This is used widely. Update with care. + */ +const int kNumVisibleColumns = 9; + +/* + * Used to save & restore column layout and sorting preferences for + * the ContentList class. + */ +class ColumnLayout { +public: + ColumnLayout(void) { + for (int i = 0; i < kNumVisibleColumns; i++) + fColumnWidth[i] = kWidthDefaulted; + fSortColumn = kNumVisibleColumns; // means "use original order" + fAscending = true; + } + ~ColumnLayout(void) {} + + void LoadFromRegistry(const char* section); + void SaveToRegistry(const char* section); + + int GetColumnWidth(int col) const { + ASSERT(col >= 0 && col < kNumVisibleColumns); + return fColumnWidth[col]; + } + void SetColumnWidth(int col, int width) { + ASSERT(col >= 0 && col < kNumVisibleColumns); + ASSERT(width >= 0 || width == kWidthDefaulted); + fColumnWidth[col] = width; + } + + int GetSortColumn(void) const { return fSortColumn; } + void SetSortColumn(int col) { + ASSERT(col >= 0 && col <= kNumVisibleColumns); + fSortColumn = col; + } + bool GetAscending(void) const { return fAscending; } + void SetAscending(bool val) { fAscending = val; } + + /* column width value used to flag "defaulted" status */ + enum { kWidthDefaulted = -1 }; + /* minimium width of column 0 (pathname) */ + enum { kMinCol0Width = 50 }; + +private: + // Create a dummy list control to get default column widths. + void DetermineDefaultWidths(ContentList* pList); + + int fColumnWidth[kNumVisibleColumns]; + int fSortColumn; + bool fAscending; +}; + + +/* + * Preferences type enumeration. + * + * This is logically part of the Preferences object, but it's annoying to + * have to specify the scope resolution operator everywhere. + */ +typedef enum { + /**/ kPrefNumUnknown = 0, + +/* these are saved in the registry */ + + // sticky settings for add file options + kPrAddIncludeSubFolders, // bool + kPrAddStripFolderNames, // bool + kPrAddOverwriteExisting, // bool + kPrAddTypePreservation, // long + kPrAddConvEOL, // long + + // sticky settings for file extraction + //kPrExtractPath, // string + kPrExtractConvEOL, // long + kPrExtractConvHighASCII, // bool + kPrExtractIncludeData, // bool + kPrExtractIncludeRsrc, // bool + kPrExtractIncludeDisk, // bool + kPrExtractEnableReformat, // bool + kPrExtractDiskTo2MG, // bool + kPrExtractAddTypePreservation, // bool + kPrExtractAddExtension, // bool + kPrExtractStripFolderNames, // bool + kPrExtractOverwriteExisting, // bool + +// // view file options +// kPrViewIncludeDataForks, // bool +// kPrViewIncludeRsrcForks, // bool +// kPrViewIncludeDiskImages, // bool +// kPrViewIncludeComments, // bool + + // convert disk image to file archive + //kPrConvFileConvDOSText, // bool + //kPrConvFileConvPascalText, // bool + kPrConvFileEmptyFolders, // bool + + // folders for CFileDialog initialization + kPrOpenArchiveFolder, // string + kPrConvertArchiveFolder, // string + kPrAddFileFolder, // string + kPrExtractFileFolder, // string + + // logical/physical volume prefs + kPrVolumeFilter, // long + //kPrVolumeReadOnly, // bool + + // cassette import/export prefs + kPrCassetteAlgorithm, // long + kPrOpenWAVFolder, // string + + // items from the Preferences propertypages (must be saved/restored) + kPrMimicShrinkIt, // bool + kPrBadMacSHK, // bool + kPrReduceSHKErrorChecks, // bool + kPrCoerceDOSFilenames, // bool + kPrSpacesToUnder, // bool + kPrPasteJunkPaths, // bool + kPrBeepOnSuccess, // bool + + kPrQueryImageFormat, // bool + kPrOpenVolumeRO, // bool + kPrOpenVolumePhys0, // bool + kPrProDOSAllowLower, // bool + kPrProDOSUseSparse, // bool + + kPrCompressionType, // long + + kPrMaxViewFileSize, // long + kPrNoWrapText, // bool + + kPrHighlightHexDump, // bool + kPrHighlightBASIC, // bool + kPrConvHiResBlackWhite, // bool + kPrConvDHRAlgorithm, // long + kPrRelaxGfxTypeCheck, // bool + kPrDisasmOneByteBrkCop, // bool + //kPrEOLConvRaw, // bool + kPrConvTextEOL_HA, // bool + kPrConvPascalText, // bool + kPrConvPascalCode, // bool + kPrConvCPMText, // bool + kPrConvApplesoft, // bool + kPrConvInteger, // bool + kPrConvBusiness, // bool + kPrConvGWP, // bool + kPrConvText8, // bool + kPrConvGutenberg, // bool + kPrConvAWP, // bool + kPrConvADB, // bool + kPrConvASP, // bool + kPrConvSCAssem, // bool + kPrConvDisasm, // bool + kPrConvHiRes, // bool + kPrConvDHR, // bool + kPrConvSHR, // bool + kPrConvPrintShop, // bool + kPrConvMacPaint, // bool + kPrConvProDOSFolder, // bool + kPrConvResources, // bool + + kPrTempPath, // string + kPrExtViewerExts, // string + + // open file dialog + kPrLastOpenFilterIndex, // long + + /**/ kPrefNumLastRegistry, +/* these are temporary settings, not saved in the registry */ + + // sticky settings for internal file viewer (ViewFilesDialog) + kPrViewTextTypeFace, // string + kPrViewTextPointSize, // long + kPrFileViewerWidth, // long + kPrFileViewerHeight, // long + + // sticky setting for disk image creator + kPrDiskImageCreateFormat, // long + + /**/ kPrefNumLastEntry +} PrefNum; + + +/* + * Container for preferences. + */ +class Preferences { +public: + Preferences(void); + ~Preferences(void) { + FreeStringValues(); + } + + // Load/save preferences from/to registry. + int LoadFromRegistry(void); + int SaveToRegistry(void); + + ColumnLayout* GetColumnLayout(void) { return &fColumnLayout; } + //bool GetShowToolbarText(void) const { return fShowToolbarText; } + //void SetShowToolbarText(bool val) { fShowToolbarText = val; } + + bool GetPrefBool(PrefNum num) const; + void SetPrefBool(PrefNum num, bool val); + long GetPrefLong(PrefNum num) const; + void SetPrefLong(PrefNum num, long val); + const char* GetPrefString(PrefNum num) const; + void SetPrefString(PrefNum num, const char* str); + + +private: + void InitTempPath(void); + void InitFolders(void); + bool GetMyDocuments(CString* pPath); + int DefaultCompressionType(void); + void FreeStringValues(void); + + /* + * Internal data structure used to manage preferences. + */ + typedef enum { kPTNone, kBool, kLong, kString } PrefType; + typedef struct PrefMap { + PrefNum num; + PrefType type; + const char* registrySection; + const char* registryKey; + } PrefMap; + static const PrefMap fPrefMaps[kPrefNumLastEntry]; + void ScanPrefMaps(void); + + // this holds the actual values + void* fValues[kPrefNumLastEntry]; + + // verify that the entry exists and has the expected type + bool ValidateEntry(PrefNum num, PrefType type) const { + if (num <= kPrefNumUnknown || num >= kPrefNumLastEntry) { + ASSERT(false); + return false; + } + if (fPrefMaps[num].type != type) { + ASSERT(false); + return false; + } + return true; + } + + // column widths for ContentList + ColumnLayout fColumnLayout; + + /* + * Registry helpers. + */ + UINT GetInt(const char* section, const char* key, int dflt) { + return gMyApp.GetProfileInt(section, key, dflt); + } + bool GetBool(const char* section, const char* key, bool dflt) { + return (gMyApp.GetProfileInt(section, key, dflt) != 0); + } + CString GetString(const char* section, const char* key, + const char* dflt) + { + return gMyApp.GetProfileString(section, key, dflt); + } + BOOL WriteInt(const char* section, const char* key, int value) { + return gMyApp.WriteProfileInt(section, key, value); + } + BOOL WriteBool(const char* section, const char* key, bool value) { + return gMyApp.WriteProfileInt(section, key, value); + } + BOOL WriteString(const char* section, const char* key, const char* value) { + return gMyApp.WriteProfileString(section, key, value); + } +}; + #endif /*__PREFERENCES__*/ \ No newline at end of file diff --git a/app/PrefsDialog.cpp b/app/PrefsDialog.cpp index 19271f7..89f3823 100644 --- a/app/PrefsDialog.cpp +++ b/app/PrefsDialog.cpp @@ -14,28 +14,28 @@ #include "NufxArchive.h" #include "HelpTopics.h" #include "resource.h" -#include // need WM_COMMANDHELP +#include // need WM_COMMANDHELP /* * =========================================================================== - * PrefsGeneralPage + * PrefsGeneralPage * =========================================================================== */ BEGIN_MESSAGE_MAP(PrefsGeneralPage, CPropertyPage) - ON_CONTROL_RANGE(BN_CLICKED, IDC_COL_PATHNAME, IDC_COL_ACCESS, OnChangeRange) - ON_BN_CLICKED(IDC_PREF_SHRINKIT_COMPAT, OnChange) - ON_BN_CLICKED(IDC_PREF_REDUCE_SHK_ERROR_CHECKS, OnChange) - ON_BN_CLICKED(IDC_PREF_SHK_BAD_MAC, OnChange) - ON_BN_CLICKED(IDC_PREF_COERCE_DOS, OnChange) - ON_BN_CLICKED(IDC_PREF_SPACES_TO_UNDER, OnChange) - ON_BN_CLICKED(IDC_PREF_PASTE_JUNKPATHS, OnChange) - ON_BN_CLICKED(IDC_PREF_SUCCESS_BEEP, OnChange) - ON_BN_CLICKED(IDC_COL_DEFAULTS, OnDefaults) - ON_BN_CLICKED(IDC_PREF_ASSOCIATIONS, OnAssociations) - ON_MESSAGE(WM_HELP, OnHelp) - ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp) + ON_CONTROL_RANGE(BN_CLICKED, IDC_COL_PATHNAME, IDC_COL_ACCESS, OnChangeRange) + ON_BN_CLICKED(IDC_PREF_SHRINKIT_COMPAT, OnChange) + ON_BN_CLICKED(IDC_PREF_REDUCE_SHK_ERROR_CHECKS, OnChange) + ON_BN_CLICKED(IDC_PREF_SHK_BAD_MAC, OnChange) + ON_BN_CLICKED(IDC_PREF_COERCE_DOS, OnChange) + ON_BN_CLICKED(IDC_PREF_SPACES_TO_UNDER, OnChange) + ON_BN_CLICKED(IDC_PREF_PASTE_JUNKPATHS, OnChange) + ON_BN_CLICKED(IDC_PREF_SUCCESS_BEEP, OnChange) + ON_BN_CLICKED(IDC_COL_DEFAULTS, OnDefaults) + ON_BN_CLICKED(IDC_PREF_ASSOCIATIONS, OnAssociations) + ON_MESSAGE(WM_HELP, OnHelp) + ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp) END_MESSAGE_MAP() @@ -46,12 +46,12 @@ END_MESSAGE_MAP() void PrefsGeneralPage::OnChange(void) { - SetModified(TRUE); + SetModified(TRUE); } void PrefsGeneralPage::OnChangeRange(UINT nID) { - SetModified(TRUE); + SetModified(TRUE); } /* @@ -65,22 +65,22 @@ PrefsGeneralPage::OnChangeRange(UINT nID) void PrefsGeneralPage::OnDefaults(void) { - WMSG0("DEFAULTS!\n"); + WMSG0("DEFAULTS!\n"); - CButton* pButton; + CButton* pButton; - fDefaultsPushed = true; + fDefaultsPushed = true; - ASSERT(IDC_COL_ACCESS == IDC_COL_PATHNAME + (kNumVisibleColumns-1)); + ASSERT(IDC_COL_ACCESS == IDC_COL_PATHNAME + (kNumVisibleColumns-1)); - /* assumes that the controls are numbered sequentially */ - for (int i = 0; i < kNumVisibleColumns; i++) { - pButton = (CButton*) GetDlgItem(IDC_COL_PATHNAME+i); - ASSERT(pButton != nil); - pButton->SetCheck(1); // 0=unchecked, 1=checked, 2=indeterminate - } + /* assumes that the controls are numbered sequentially */ + for (int i = 0; i < kNumVisibleColumns; i++) { + pButton = (CButton*) GetDlgItem(IDC_COL_PATHNAME+i); + ASSERT(pButton != nil); + pButton->SetCheck(1); // 0=unchecked, 1=checked, 2=indeterminate + } - SetModified(TRUE); + SetModified(TRUE); } /* @@ -91,18 +91,18 @@ PrefsGeneralPage::OnDefaults(void) void PrefsGeneralPage::OnAssociations(void) { - EditAssocDialog assocDlg; + EditAssocDialog assocDlg; - assocDlg.fOurAssociations = fOurAssociations; - fOurAssociations = nil; + assocDlg.fOurAssociations = fOurAssociations; + fOurAssociations = nil; - if (assocDlg.DoModal() == IDOK) { - // steal the modified associations - delete[] fOurAssociations; - fOurAssociations = assocDlg.fOurAssociations; - assocDlg.fOurAssociations = nil; - SetModified(TRUE); - } + if (assocDlg.DoModal() == IDOK) { + // steal the modified associations + delete[] fOurAssociations; + fOurAssociations = assocDlg.fOurAssociations; + assocDlg.fOurAssociations = nil; + SetModified(TRUE); + } } /* @@ -114,26 +114,26 @@ PrefsGeneralPage::OnAssociations(void) void PrefsGeneralPage::DoDataExchange(CDataExchange* pDX) { - fReady = true; + fReady = true; - ASSERT(NELEM(fColumn) == 9); - DDX_Check(pDX, IDC_COL_PATHNAME, fColumn[0]); - DDX_Check(pDX, IDC_COL_TYPE, fColumn[1]); - DDX_Check(pDX, IDC_COL_AUXTYPE, fColumn[2]); - DDX_Check(pDX, IDC_COL_MODDATE, fColumn[3]); - DDX_Check(pDX, IDC_COL_FORMAT, fColumn[4]); - DDX_Check(pDX, IDC_COL_SIZE, fColumn[5]); - DDX_Check(pDX, IDC_COL_RATIO, fColumn[6]); - DDX_Check(pDX, IDC_COL_PACKED, fColumn[7]); - DDX_Check(pDX, IDC_COL_ACCESS, fColumn[8]); + ASSERT(NELEM(fColumn) == 9); + DDX_Check(pDX, IDC_COL_PATHNAME, fColumn[0]); + DDX_Check(pDX, IDC_COL_TYPE, fColumn[1]); + DDX_Check(pDX, IDC_COL_AUXTYPE, fColumn[2]); + DDX_Check(pDX, IDC_COL_MODDATE, fColumn[3]); + DDX_Check(pDX, IDC_COL_FORMAT, fColumn[4]); + DDX_Check(pDX, IDC_COL_SIZE, fColumn[5]); + DDX_Check(pDX, IDC_COL_RATIO, fColumn[6]); + DDX_Check(pDX, IDC_COL_PACKED, fColumn[7]); + DDX_Check(pDX, IDC_COL_ACCESS, fColumn[8]); - DDX_Check(pDX, IDC_PREF_SHRINKIT_COMPAT, fMimicShrinkIt); - DDX_Check(pDX, IDC_PREF_SHK_BAD_MAC, fBadMacSHK); - DDX_Check(pDX, IDC_PREF_REDUCE_SHK_ERROR_CHECKS, fReduceSHKErrorChecks); - DDX_Check(pDX, IDC_PREF_COERCE_DOS, fCoerceDOSFilenames); - DDX_Check(pDX, IDC_PREF_SPACES_TO_UNDER, fSpacesToUnder); - DDX_Check(pDX, IDC_PREF_PASTE_JUNKPATHS, fPasteJunkPaths); - DDX_Check(pDX, IDC_PREF_SUCCESS_BEEP, fBeepOnSuccess); + DDX_Check(pDX, IDC_PREF_SHRINKIT_COMPAT, fMimicShrinkIt); + DDX_Check(pDX, IDC_PREF_SHK_BAD_MAC, fBadMacSHK); + DDX_Check(pDX, IDC_PREF_REDUCE_SHK_ERROR_CHECKS, fReduceSHKErrorChecks); + DDX_Check(pDX, IDC_PREF_COERCE_DOS, fCoerceDOSFilenames); + DDX_Check(pDX, IDC_PREF_SPACES_TO_UNDER, fSpacesToUnder); + DDX_Check(pDX, IDC_PREF_PASTE_JUNKPATHS, fPasteJunkPaths); + DDX_Check(pDX, IDC_PREF_SUCCESS_BEEP, fBeepOnSuccess); } /* @@ -142,8 +142,8 @@ PrefsGeneralPage::DoDataExchange(CDataExchange* pDX) LONG PrefsGeneralPage::OnHelp(UINT wParam, LONG lParam) { - WinHelp((DWORD) ((HELPINFO*) lParam)->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) ((HELPINFO*) lParam)->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* * User pressed the PropertySheet "Help" button. @@ -151,25 +151,25 @@ PrefsGeneralPage::OnHelp(UINT wParam, LONG lParam) LONG PrefsGeneralPage::OnCommandHelp(UINT, LONG) { - WinHelp(HELP_TOPIC_PREFS_GENERAL, HELP_CONTEXT); - return 0; // doesn't matter + WinHelp(HELP_TOPIC_PREFS_GENERAL, HELP_CONTEXT); + return 0; // doesn't matter } /* * =========================================================================== - * PrefsDiskImagePage + * PrefsDiskImagePage * =========================================================================== */ BEGIN_MESSAGE_MAP(PrefsDiskImagePage, CPropertyPage) - ON_BN_CLICKED(IDC_PDISK_CONFIRM_FORMAT, OnChange) - ON_BN_CLICKED(IDC_PDISK_OPENVOL_RO, OnChange) - ON_BN_CLICKED(IDC_PDISK_OPENVOL_PHYS0, OnChange) - ON_BN_CLICKED(IDC_PDISK_PRODOS_ALLOWLOWER, OnChange) - ON_BN_CLICKED(IDC_PDISK_PRODOS_USESPARSE, OnChange) - ON_MESSAGE(WM_HELP, OnHelp) - ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp) + ON_BN_CLICKED(IDC_PDISK_CONFIRM_FORMAT, OnChange) + ON_BN_CLICKED(IDC_PDISK_OPENVOL_RO, OnChange) + ON_BN_CLICKED(IDC_PDISK_OPENVOL_PHYS0, OnChange) + ON_BN_CLICKED(IDC_PDISK_PRODOS_ALLOWLOWER, OnChange) + ON_BN_CLICKED(IDC_PDISK_PRODOS_USESPARSE, OnChange) + ON_MESSAGE(WM_HELP, OnHelp) + ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp) END_MESSAGE_MAP() /* @@ -178,8 +178,8 @@ END_MESSAGE_MAP() BOOL PrefsDiskImagePage::OnInitDialog(void) { - //WMSG0("OnInit!\n"); - return CPropertyPage::OnInitDialog(); + //WMSG0("OnInit!\n"); + return CPropertyPage::OnInitDialog(); } /* @@ -188,14 +188,14 @@ PrefsDiskImagePage::OnInitDialog(void) void PrefsDiskImagePage::OnChange(void) { - WMSG0("OnChange\n"); - SetModified(TRUE); + WMSG0("OnChange\n"); + SetModified(TRUE); } //void //PrefsDiskImagePage::OnChangeRange(UINT nID) //{ -// WMSG1("OnChangeRange id=%d\n", nID); -// SetModified(TRUE); +// WMSG1("OnChangeRange id=%d\n", nID); +// SetModified(TRUE); //} @@ -205,12 +205,12 @@ PrefsDiskImagePage::OnChange(void) void PrefsDiskImagePage::DoDataExchange(CDataExchange* pDX) { - fReady = true; - DDX_Check(pDX, IDC_PDISK_CONFIRM_FORMAT, fQueryImageFormat); - DDX_Check(pDX, IDC_PDISK_OPENVOL_RO, fOpenVolumeRO); - DDX_Check(pDX, IDC_PDISK_OPENVOL_PHYS0, fOpenVolumePhys0); - DDX_Check(pDX, IDC_PDISK_PRODOS_ALLOWLOWER, fProDOSAllowLower); - DDX_Check(pDX, IDC_PDISK_PRODOS_USESPARSE, fProDOSUseSparse); + fReady = true; + DDX_Check(pDX, IDC_PDISK_CONFIRM_FORMAT, fQueryImageFormat); + DDX_Check(pDX, IDC_PDISK_OPENVOL_RO, fOpenVolumeRO); + DDX_Check(pDX, IDC_PDISK_OPENVOL_PHYS0, fOpenVolumePhys0); + DDX_Check(pDX, IDC_PDISK_PRODOS_ALLOWLOWER, fProDOSAllowLower); + DDX_Check(pDX, IDC_PDISK_PRODOS_USESPARSE, fProDOSUseSparse); } /* @@ -219,8 +219,8 @@ PrefsDiskImagePage::DoDataExchange(CDataExchange* pDX) LONG PrefsDiskImagePage::OnHelp(UINT wParam, LONG lParam) { - WinHelp((DWORD) ((HELPINFO*) lParam)->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) ((HELPINFO*) lParam)->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* * User pressed the PropertySheet "Help" button. @@ -228,21 +228,21 @@ PrefsDiskImagePage::OnHelp(UINT wParam, LONG lParam) LONG PrefsDiskImagePage::OnCommandHelp(UINT, LONG) { - WinHelp(HELP_TOPIC_PREFS_DISK_IMAGE, HELP_CONTEXT); - return 0; // doesn't matter + WinHelp(HELP_TOPIC_PREFS_DISK_IMAGE, HELP_CONTEXT); + return 0; // doesn't matter } /* * =========================================================================== - * PrefsCompressionPage + * PrefsCompressionPage * =========================================================================== */ BEGIN_MESSAGE_MAP(PrefsCompressionPage, CPropertyPage) - ON_CONTROL_RANGE(BN_CLICKED, IDC_DEFC_UNCOMPRESSED, IDC_DEFC_BZIP2, OnChangeRange) - ON_MESSAGE(WM_HELP, OnHelp) - ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp) + ON_CONTROL_RANGE(BN_CLICKED, IDC_DEFC_UNCOMPRESSED, IDC_DEFC_BZIP2, OnChangeRange) + ON_MESSAGE(WM_HELP, OnHelp) + ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp) END_MESSAGE_MAP() @@ -252,45 +252,45 @@ END_MESSAGE_MAP() BOOL PrefsCompressionPage::OnInitDialog(void) { - if (!NufxArchive::IsCompressionSupported(kNuThreadFormatHuffmanSQ)) { - DisableWnd(IDC_DEFC_SQUEEZE); - if (fCompressType == kNuThreadFormatHuffmanSQ) - fCompressType = kNuThreadFormatUncompressed; - } - if (!NufxArchive::IsCompressionSupported(kNuThreadFormatLZW1)) { - DisableWnd(IDC_DEFC_LZW1); - if (fCompressType == kNuThreadFormatLZW1) - fCompressType = kNuThreadFormatUncompressed; - } - if (!NufxArchive::IsCompressionSupported(kNuThreadFormatLZW2)) { - DisableWnd(IDC_DEFC_LZW2); - if (fCompressType == kNuThreadFormatLZW2) { - fCompressType = kNuThreadFormatUncompressed; - } - } - if (!NufxArchive::IsCompressionSupported(kNuThreadFormatLZC12)) { - DisableWnd(IDC_DEFC_LZC12); - if (fCompressType == kNuThreadFormatLZC12) - fCompressType = kNuThreadFormatUncompressed; - } - if (!NufxArchive::IsCompressionSupported(kNuThreadFormatLZC16)) { - DisableWnd(IDC_DEFC_LZC16); - if (fCompressType == kNuThreadFormatLZC16) - fCompressType = kNuThreadFormatUncompressed; - } - if (!NufxArchive::IsCompressionSupported(kNuThreadFormatDeflate)) { - DisableWnd(IDC_DEFC_DEFLATE); - if (fCompressType == kNuThreadFormatDeflate) - fCompressType = kNuThreadFormatUncompressed; - } - if (!NufxArchive::IsCompressionSupported(kNuThreadFormatBzip2)) { - DisableWnd(IDC_DEFC_BZIP2); - if (fCompressType == kNuThreadFormatBzip2) - fCompressType = kNuThreadFormatUncompressed; - } + if (!NufxArchive::IsCompressionSupported(kNuThreadFormatHuffmanSQ)) { + DisableWnd(IDC_DEFC_SQUEEZE); + if (fCompressType == kNuThreadFormatHuffmanSQ) + fCompressType = kNuThreadFormatUncompressed; + } + if (!NufxArchive::IsCompressionSupported(kNuThreadFormatLZW1)) { + DisableWnd(IDC_DEFC_LZW1); + if (fCompressType == kNuThreadFormatLZW1) + fCompressType = kNuThreadFormatUncompressed; + } + if (!NufxArchive::IsCompressionSupported(kNuThreadFormatLZW2)) { + DisableWnd(IDC_DEFC_LZW2); + if (fCompressType == kNuThreadFormatLZW2) { + fCompressType = kNuThreadFormatUncompressed; + } + } + if (!NufxArchive::IsCompressionSupported(kNuThreadFormatLZC12)) { + DisableWnd(IDC_DEFC_LZC12); + if (fCompressType == kNuThreadFormatLZC12) + fCompressType = kNuThreadFormatUncompressed; + } + if (!NufxArchive::IsCompressionSupported(kNuThreadFormatLZC16)) { + DisableWnd(IDC_DEFC_LZC16); + if (fCompressType == kNuThreadFormatLZC16) + fCompressType = kNuThreadFormatUncompressed; + } + if (!NufxArchive::IsCompressionSupported(kNuThreadFormatDeflate)) { + DisableWnd(IDC_DEFC_DEFLATE); + if (fCompressType == kNuThreadFormatDeflate) + fCompressType = kNuThreadFormatUncompressed; + } + if (!NufxArchive::IsCompressionSupported(kNuThreadFormatBzip2)) { + DisableWnd(IDC_DEFC_BZIP2); + if (fCompressType == kNuThreadFormatBzip2) + fCompressType = kNuThreadFormatUncompressed; + } - /* now invoke DoDataExchange with our modified fCompressType */ - return CPropertyPage::OnInitDialog(); + /* now invoke DoDataExchange with our modified fCompressType */ + return CPropertyPage::OnInitDialog(); } /* @@ -299,13 +299,13 @@ PrefsCompressionPage::OnInitDialog(void) void PrefsCompressionPage::DisableWnd(int id) { - CWnd* pWnd; - pWnd = GetDlgItem(id); - if (pWnd == nil) { - ASSERT(false); - return; - } - pWnd->EnableWindow(FALSE); + CWnd* pWnd; + pWnd = GetDlgItem(id); + if (pWnd == nil) { + ASSERT(false); + return; + } + pWnd->EnableWindow(FALSE); } /* @@ -314,7 +314,7 @@ PrefsCompressionPage::DisableWnd(int id) void PrefsCompressionPage::OnChangeRange(UINT nID) { - SetModified(TRUE); + SetModified(TRUE); } /* @@ -326,9 +326,9 @@ PrefsCompressionPage::OnChangeRange(UINT nID) void PrefsCompressionPage::DoDataExchange(CDataExchange* pDX) { - //WMSG0("OnInit comp!\n"); - fReady = true; - DDX_Radio(pDX, IDC_DEFC_UNCOMPRESSED, fCompressType); + //WMSG0("OnInit comp!\n"); + fReady = true; + DDX_Radio(pDX, IDC_DEFC_UNCOMPRESSED, fCompressType); } /* @@ -337,8 +337,8 @@ PrefsCompressionPage::DoDataExchange(CDataExchange* pDX) LONG PrefsCompressionPage::OnHelp(UINT wParam, LONG lParam) { - WinHelp((DWORD) ((HELPINFO*) lParam)->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) ((HELPINFO*) lParam)->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* * User pressed the PropertySheet "Help" button. @@ -346,24 +346,24 @@ PrefsCompressionPage::OnHelp(UINT wParam, LONG lParam) LONG PrefsCompressionPage::OnCommandHelp(UINT, LONG) { - WinHelp(HELP_TOPIC_PREFS_COMPRESSION, HELP_CONTEXT); - return 0; // doesn't matter + WinHelp(HELP_TOPIC_PREFS_COMPRESSION, HELP_CONTEXT); + return 0; // doesn't matter } /* * =========================================================================== - * PrefsFviewPage + * PrefsFviewPage * =========================================================================== */ BEGIN_MESSAGE_MAP(PrefsFviewPage, CPropertyPage) - ON_CONTROL_RANGE(BN_CLICKED, IDC_PVIEW_NOWRAP_TEXT, IDC_PVIEW_HIRES_BW, OnChangeRange) - ON_CONTROL_RANGE(BN_CLICKED, IDC_PVIEW_HITEXT, IDC_PVIEW_TEXT8, OnChangeRange) - ON_EN_CHANGE(IDC_PVIEW_SIZE_EDIT, OnChange) - ON_CBN_SELCHANGE(IDC_PVIEW_DHR_CONV_COMBO, OnChange) - ON_MESSAGE(WM_HELP, OnHelp) - ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp) + ON_CONTROL_RANGE(BN_CLICKED, IDC_PVIEW_NOWRAP_TEXT, IDC_PVIEW_HIRES_BW, OnChangeRange) + ON_CONTROL_RANGE(BN_CLICKED, IDC_PVIEW_HITEXT, IDC_PVIEW_TEXT8, OnChangeRange) + ON_EN_CHANGE(IDC_PVIEW_SIZE_EDIT, OnChange) + ON_CBN_SELCHANGE(IDC_PVIEW_DHR_CONV_COMBO, OnChange) + ON_MESSAGE(WM_HELP, OnHelp) + ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp) END_MESSAGE_MAP() /* @@ -372,22 +372,22 @@ END_MESSAGE_MAP() BOOL PrefsFviewPage::OnInitDialog(void) { - //WMSG0("OnInit!\n"); - CSpinButtonCtrl* pSpin; + //WMSG0("OnInit!\n"); + CSpinButtonCtrl* pSpin; - //WMSG0("Configuring spin\n"); + //WMSG0("Configuring spin\n"); - pSpin = (CSpinButtonCtrl*) GetDlgItem(IDC_PVIEW_SIZE_SPIN); - ASSERT(pSpin != nil); + pSpin = (CSpinButtonCtrl*) GetDlgItem(IDC_PVIEW_SIZE_SPIN); + ASSERT(pSpin != nil); - UDACCEL uda; - uda.nSec = 0; - uda.nInc = 64; - pSpin->SetRange(1, 32767); - pSpin->SetAccel(1, &uda); - WMSG0("OnInit done!\n"); + UDACCEL uda; + uda.nSec = 0; + uda.nInc = 64; + pSpin->SetRange(1, 32767); + pSpin->SetAccel(1, &uda); + WMSG0("OnInit done!\n"); - return CPropertyPage::OnInitDialog(); + return CPropertyPage::OnInitDialog(); } /* @@ -396,14 +396,14 @@ PrefsFviewPage::OnInitDialog(void) void PrefsFviewPage::OnChange(void) { - WMSG0("OnChange\n"); - SetModified(TRUE); + WMSG0("OnChange\n"); + SetModified(TRUE); } void PrefsFviewPage::OnChangeRange(UINT nID) { - WMSG1("OnChangeRange id=%d\n", nID); - SetModified(TRUE); + WMSG1("OnChangeRange id=%d\n", nID); + SetModified(TRUE); } @@ -413,40 +413,40 @@ PrefsFviewPage::OnChangeRange(UINT nID) void PrefsFviewPage::DoDataExchange(CDataExchange* pDX) { - fReady = true; - //DDX_Check(pDX, IDC_PVIEW_EOL_RAW, fEOLConvRaw); - DDX_Check(pDX, IDC_PVIEW_NOWRAP_TEXT, fNoWrapText); - DDX_Check(pDX, IDC_PVIEW_BOLD_HEXDUMP, fHighlightHexDump); - DDX_Check(pDX, IDC_PVIEW_BOLD_BASIC, fHighlightBASIC); - DDX_Check(pDX, IDC_PVIEW_DISASM_ONEBYTEBRKCOP, fConvDisasmOneByteBrkCop); - DDX_Check(pDX, IDC_PVIEW_HIRES_BW, fConvHiResBlackWhite); - DDX_CBIndex(pDX, IDC_PVIEW_DHR_CONV_COMBO, fConvDHRAlgorithm); + fReady = true; + //DDX_Check(pDX, IDC_PVIEW_EOL_RAW, fEOLConvRaw); + DDX_Check(pDX, IDC_PVIEW_NOWRAP_TEXT, fNoWrapText); + DDX_Check(pDX, IDC_PVIEW_BOLD_HEXDUMP, fHighlightHexDump); + DDX_Check(pDX, IDC_PVIEW_BOLD_BASIC, fHighlightBASIC); + DDX_Check(pDX, IDC_PVIEW_DISASM_ONEBYTEBRKCOP, fConvDisasmOneByteBrkCop); + DDX_Check(pDX, IDC_PVIEW_HIRES_BW, fConvHiResBlackWhite); + DDX_CBIndex(pDX, IDC_PVIEW_DHR_CONV_COMBO, fConvDHRAlgorithm); - DDX_Check(pDX, IDC_PVIEW_HITEXT, fConvTextEOL_HA); - DDX_Check(pDX, IDC_PVIEW_CPMTEXT, fConvCPMText); - DDX_Check(pDX, IDC_PVIEW_PASCALTEXT, fConvPascalText); - DDX_Check(pDX, IDC_PVIEW_PASCALCODE, fConvPascalCode); - DDX_Check(pDX, IDC_PVIEW_APPLESOFT, fConvApplesoft); - DDX_Check(pDX, IDC_PVIEW_INTEGER, fConvInteger); - DDX_Check(pDX, IDC_PVIEW_GWP, fConvGWP); - DDX_Check(pDX, IDC_PVIEW_TEXT8, fConvText8); - DDX_Check(pDX, IDC_PVIEW_AWP, fConvAWP); - DDX_Check(pDX, IDC_PVIEW_ADB, fConvADB); - DDX_Check(pDX, IDC_PVIEW_ASP, fConvASP); - DDX_Check(pDX, IDC_PVIEW_SCASSEM, fConvSCAssem); - DDX_Check(pDX, IDC_PVIEW_DISASM, fConvDisasm); + DDX_Check(pDX, IDC_PVIEW_HITEXT, fConvTextEOL_HA); + DDX_Check(pDX, IDC_PVIEW_CPMTEXT, fConvCPMText); + DDX_Check(pDX, IDC_PVIEW_PASCALTEXT, fConvPascalText); + DDX_Check(pDX, IDC_PVIEW_PASCALCODE, fConvPascalCode); + DDX_Check(pDX, IDC_PVIEW_APPLESOFT, fConvApplesoft); + DDX_Check(pDX, IDC_PVIEW_INTEGER, fConvInteger); + DDX_Check(pDX, IDC_PVIEW_GWP, fConvGWP); + DDX_Check(pDX, IDC_PVIEW_TEXT8, fConvText8); + DDX_Check(pDX, IDC_PVIEW_AWP, fConvAWP); + DDX_Check(pDX, IDC_PVIEW_ADB, fConvADB); + DDX_Check(pDX, IDC_PVIEW_ASP, fConvASP); + DDX_Check(pDX, IDC_PVIEW_SCASSEM, fConvSCAssem); + DDX_Check(pDX, IDC_PVIEW_DISASM, fConvDisasm); - DDX_Check(pDX, IDC_PVIEW_HIRES, fConvHiRes); - DDX_Check(pDX, IDC_PVIEW_DHR, fConvDHR); - DDX_Check(pDX, IDC_PVIEW_SHR, fConvSHR); - DDX_Check(pDX, IDC_PVIEW_PRINTSHOP, fConvPrintShop); - DDX_Check(pDX, IDC_PVIEW_MACPAINT, fConvMacPaint); - DDX_Check(pDX, IDC_PVIEW_PRODOSFOLDER, fConvProDOSFolder); - DDX_Check(pDX, IDC_PVIEW_RESOURCES, fConvResources); - DDX_Check(pDX, IDC_PVIEW_RELAX_GFX, fRelaxGfxTypeCheck); + DDX_Check(pDX, IDC_PVIEW_HIRES, fConvHiRes); + DDX_Check(pDX, IDC_PVIEW_DHR, fConvDHR); + DDX_Check(pDX, IDC_PVIEW_SHR, fConvSHR); + DDX_Check(pDX, IDC_PVIEW_PRINTSHOP, fConvPrintShop); + DDX_Check(pDX, IDC_PVIEW_MACPAINT, fConvMacPaint); + DDX_Check(pDX, IDC_PVIEW_PRODOSFOLDER, fConvProDOSFolder); + DDX_Check(pDX, IDC_PVIEW_RESOURCES, fConvResources); + DDX_Check(pDX, IDC_PVIEW_RELAX_GFX, fRelaxGfxTypeCheck); - DDX_Text(pDX, IDC_PVIEW_SIZE_EDIT, fMaxViewFileSizeKB); - DDV_MinMaxUInt(pDX, fMaxViewFileSizeKB, 1, 32767); + DDX_Text(pDX, IDC_PVIEW_SIZE_EDIT, fMaxViewFileSizeKB); + DDV_MinMaxUInt(pDX, fMaxViewFileSizeKB, 1, 32767); } /* @@ -455,8 +455,8 @@ PrefsFviewPage::DoDataExchange(CDataExchange* pDX) LONG PrefsFviewPage::OnHelp(UINT wParam, LONG lParam) { - WinHelp((DWORD) ((HELPINFO*) lParam)->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) ((HELPINFO*) lParam)->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* * User pressed the PropertySheet "Help" button. @@ -464,23 +464,23 @@ PrefsFviewPage::OnHelp(UINT wParam, LONG lParam) LONG PrefsFviewPage::OnCommandHelp(UINT, LONG) { - WinHelp(HELP_TOPIC_PREFS_FVIEW, HELP_CONTEXT); - return 0; // doesn't matter + WinHelp(HELP_TOPIC_PREFS_FVIEW, HELP_CONTEXT); + return 0; // doesn't matter } /* * =========================================================================== - * PrefsFilesPage + * PrefsFilesPage * =========================================================================== */ BEGIN_MESSAGE_MAP(PrefsFilesPage, CPropertyPage) - ON_EN_CHANGE(IDC_PREF_TEMP_FOLDER, OnChange) - ON_EN_CHANGE(IDC_PREF_EXTVIEWER_EXTS, OnChange) - ON_BN_CLICKED(IDC_PREF_CHOOSE_TEMP_FOLDER, OnChooseFolder) - ON_MESSAGE(WM_HELP, OnHelp) - ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp) + ON_EN_CHANGE(IDC_PREF_TEMP_FOLDER, OnChange) + ON_EN_CHANGE(IDC_PREF_EXTVIEWER_EXTS, OnChange) + ON_BN_CLICKED(IDC_PREF_CHOOSE_TEMP_FOLDER, OnChooseFolder) + ON_MESSAGE(WM_HELP, OnHelp) + ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp) END_MESSAGE_MAP() @@ -490,10 +490,10 @@ END_MESSAGE_MAP() BOOL PrefsFilesPage::OnInitDialog(void) { - fChooseFolderButton.ReplaceDlgCtrl(this, IDC_PREF_CHOOSE_TEMP_FOLDER); - fChooseFolderButton.SetBitmapID(IDB_CHOOSE_FOLDER); + fChooseFolderButton.ReplaceDlgCtrl(this, IDC_PREF_CHOOSE_TEMP_FOLDER); + fChooseFolderButton.SetBitmapID(IDB_CHOOSE_FOLDER); - return CPropertyPage::OnInitDialog(); + return CPropertyPage::OnInitDialog(); } /* @@ -502,7 +502,7 @@ PrefsFilesPage::OnInitDialog(void) void PrefsFilesPage::OnChange(void) { - SetModified(TRUE); + SetModified(TRUE); } /* @@ -511,22 +511,22 @@ PrefsFilesPage::OnChange(void) void PrefsFilesPage::DoDataExchange(CDataExchange* pDX) { - fReady = true; - DDX_Text(pDX, IDC_PREF_TEMP_FOLDER, fTempPath); - DDX_Text(pDX, IDC_PREF_EXTVIEWER_EXTS, fExtViewerExts); + fReady = true; + DDX_Text(pDX, IDC_PREF_TEMP_FOLDER, fTempPath); + DDX_Text(pDX, IDC_PREF_EXTVIEWER_EXTS, fExtViewerExts); - /* validate the path field */ - if (pDX->m_bSaveAndValidate) { - if (fTempPath.IsEmpty()) { - CString appName; - appName.LoadString(IDS_MB_APP_NAME); - MessageBox("You must specify a path for temp files", - appName, MB_OK); - pDX->Fail(); - } + /* validate the path field */ + if (pDX->m_bSaveAndValidate) { + if (fTempPath.IsEmpty()) { + CString appName; + appName.LoadString(IDS_MB_APP_NAME); + MessageBox("You must specify a path for temp files", + appName, MB_OK); + pDX->Fail(); + } - // we *could* try to validate the path here... - } + // we *could* try to validate the path here... + } } /* @@ -535,25 +535,25 @@ PrefsFilesPage::DoDataExchange(CDataExchange* pDX) void PrefsFilesPage::OnChooseFolder(void) { - ChooseDirDialog chooseDir(this); - CWnd* pEditWnd; - CString editPath; + ChooseDirDialog chooseDir(this); + CWnd* pEditWnd; + CString editPath; - /* get the currently-showing text from the edit field */ - pEditWnd = GetDlgItem(IDC_PREF_TEMP_FOLDER); - ASSERT(pEditWnd != nil); - pEditWnd->GetWindowText(editPath); + /* get the currently-showing text from the edit field */ + pEditWnd = GetDlgItem(IDC_PREF_TEMP_FOLDER); + ASSERT(pEditWnd != nil); + pEditWnd->GetWindowText(editPath); - chooseDir.SetPathName(editPath); - if (chooseDir.DoModal() == IDOK) { - const char* ccp = chooseDir.GetPathName(); - WMSG1("New temp path chosen = '%s'\n", ccp); + chooseDir.SetPathName(editPath); + if (chooseDir.DoModal() == IDOK) { + const char* ccp = chooseDir.GetPathName(); + WMSG1("New temp path chosen = '%s'\n", ccp); - pEditWnd->SetWindowText(ccp); + pEditWnd->SetWindowText(ccp); - // activate the "apply" button - OnChange(); - } + // activate the "apply" button + OnChange(); + } } /* @@ -562,8 +562,8 @@ PrefsFilesPage::OnChooseFolder(void) LONG PrefsFilesPage::OnHelp(UINT wParam, LONG lParam) { - WinHelp((DWORD) ((HELPINFO*) lParam)->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) ((HELPINFO*) lParam)->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* * User pressed the PropertySheet "Help" button. @@ -571,38 +571,38 @@ PrefsFilesPage::OnHelp(UINT wParam, LONG lParam) LONG PrefsFilesPage::OnCommandHelp(UINT, LONG) { - WinHelp(HELP_TOPIC_PREFS_FILES, HELP_CONTEXT); - return 0; // doesn't matter + WinHelp(HELP_TOPIC_PREFS_FILES, HELP_CONTEXT); + return 0; // doesn't matter } /* * =========================================================================== - * PrefsSheet + * PrefsSheet * =========================================================================== */ BEGIN_MESSAGE_MAP(PrefsSheet, CPropertySheet) - ON_WM_NCCREATE() - ON_BN_CLICKED(ID_APPLY_NOW, OnApplyNow) - ON_COMMAND(ID_HELP, OnIDHelp) - ON_MESSAGE(WM_HELP, OnHelp) + ON_WM_NCCREATE() + ON_BN_CLICKED(ID_APPLY_NOW, OnApplyNow) + ON_COMMAND(ID_HELP, OnIDHelp) + ON_MESSAGE(WM_HELP, OnHelp) END_MESSAGE_MAP() /* * Construct the preferences dialog from the individual pages. */ PrefsSheet::PrefsSheet(CWnd* pParentWnd) : - CPropertySheet("Preferences", pParentWnd) + CPropertySheet("Preferences", pParentWnd) { - AddPage(&fGeneralPage); - AddPage(&fDiskImagePage); - AddPage(&fFviewPage); - AddPage(&fCompressionPage); - AddPage(&fFilesPage); + AddPage(&fGeneralPage); + AddPage(&fDiskImagePage); + AddPage(&fFviewPage); + AddPage(&fCompressionPage); + AddPage(&fFilesPage); - /* this happens automatically with appropriate ID_HELP handlers */ - //m_psh.dwFlags |= PSH_HASHELP; + /* this happens automatically with appropriate ID_HELP handlers */ + //m_psh.dwFlags |= PSH_HASHELP; } /* @@ -614,10 +614,10 @@ PrefsSheet::PrefsSheet(CWnd* pParentWnd) : BOOL PrefsSheet::OnNcCreate(LPCREATESTRUCT cs) { - //WMSG0("PrefsSheet OnNcCreate\n"); - BOOL val = CPropertySheet::OnNcCreate(cs); - ModifyStyleEx(0, WS_EX_CONTEXTHELP); - return val; + //WMSG0("PrefsSheet OnNcCreate\n"); + BOOL val = CPropertySheet::OnNcCreate(cs); + ModifyStyleEx(0, WS_EX_CONTEXTHELP); + return val; } /* @@ -631,49 +631,49 @@ PrefsSheet::OnNcCreate(LPCREATESTRUCT cs) void PrefsSheet::OnApplyNow(void) { - BOOL result; + BOOL result; - if (fGeneralPage.fReady) { - //WMSG0("Apply to general?\n"); - result = fGeneralPage.UpdateData(TRUE); - if (!result) - return; - } - if (fDiskImagePage.fReady) { - //WMSG0("Apply to disk images?\n"); - result = fDiskImagePage.UpdateData(TRUE); - if (!result) - return; - } - if (fCompressionPage.fReady) { - //WMSG0("Apply to compression?\n"); - result = fCompressionPage.UpdateData(TRUE); - if (!result) - return; - } - if (fFviewPage.fReady) { - //WMSG0("Apply to fview?\n"); - result = fFviewPage.UpdateData(TRUE); - if (!result) - return; - } + if (fGeneralPage.fReady) { + //WMSG0("Apply to general?\n"); + result = fGeneralPage.UpdateData(TRUE); + if (!result) + return; + } + if (fDiskImagePage.fReady) { + //WMSG0("Apply to disk images?\n"); + result = fDiskImagePage.UpdateData(TRUE); + if (!result) + return; + } + if (fCompressionPage.fReady) { + //WMSG0("Apply to compression?\n"); + result = fCompressionPage.UpdateData(TRUE); + if (!result) + return; + } + if (fFviewPage.fReady) { + //WMSG0("Apply to fview?\n"); + result = fFviewPage.UpdateData(TRUE); + if (!result) + return; + } - if (fFilesPage.fReady) { - //WMSG0("Apply to fview?\n"); - result = fFilesPage.UpdateData(TRUE); - if (!result) - return; - } + if (fFilesPage.fReady) { + //WMSG0("Apply to fview?\n"); + result = fFilesPage.UpdateData(TRUE); + if (!result) + return; + } - /* reset all to "unmodified" state */ - WMSG0("All 'applies' were successful\n"); - ((MainWindow*) AfxGetMainWnd())->ApplyNow(this); - fGeneralPage.SetModified(FALSE); - fGeneralPage.fDefaultsPushed = false; - fDiskImagePage.SetModified(FALSE); - fCompressionPage.SetModified(FALSE); - fFviewPage.SetModified(FALSE); - fFilesPage.SetModified(FALSE); + /* reset all to "unmodified" state */ + WMSG0("All 'applies' were successful\n"); + ((MainWindow*) AfxGetMainWnd())->ApplyNow(this); + fGeneralPage.SetModified(FALSE); + fGeneralPage.fDefaultsPushed = false; + fDiskImagePage.SetModified(FALSE); + fCompressionPage.SetModified(FALSE); + fFviewPage.SetModified(FALSE); + fFilesPage.SetModified(FALSE); } /* @@ -692,7 +692,7 @@ PrefsSheet::OnApplyNow(void) void PrefsSheet::OnIDHelp(void) { - WMSG0("PrefsSheet OnIDHelp\n"); + WMSG0("PrefsSheet OnIDHelp\n"); SendMessage(WM_COMMANDHELP); } @@ -703,11 +703,11 @@ PrefsSheet::OnIDHelp(void) LONG PrefsSheet::OnHelp(UINT wParam, LONG lParam) { - HELPINFO* lpHelpInfo = (HELPINFO*) lParam; + HELPINFO* lpHelpInfo = (HELPINFO*) lParam; - WMSG0("PrefsSheet OnHelp\n"); - DWORD context = lpHelpInfo->iCtrlId; - WinHelp(context, HELP_CONTEXTPOPUP); + WMSG0("PrefsSheet OnHelp\n"); + DWORD context = lpHelpInfo->iCtrlId; + WinHelp(context, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + return TRUE; // yes, we handled it } diff --git a/app/PrefsDialog.h b/app/PrefsDialog.h index fa91084..cf95eae 100644 --- a/app/PrefsDialog.h +++ b/app/PrefsDialog.h @@ -1,242 +1,242 @@ -/* - * CiderPress - * Copyright (C) 2007, 2008 by faddenSoft, LLC. All Rights Reserved. - * See the file LICENSE for distribution terms. - */ -/* - * Classes to support the Preferences property pages. - */ -#ifndef __PREFSDIALOG__ -#define __PREFSDIALOG__ - -#include "Preferences.h" -#include "../util/UtilLib.h" -#include "resource.h" - -/* - * The "general" page, which controls how we display information to the user. - */ -class PrefsGeneralPage : public CPropertyPage -{ -public: - PrefsGeneralPage(void) : - CPropertyPage(IDD_PREF_GENERAL), - fReady(false), - fMimicShrinkIt(FALSE), - fBadMacSHK(FALSE), - fReduceSHKErrorChecks(FALSE), - fCoerceDOSFilenames(FALSE), - fSpacesToUnder(FALSE), - fDefaultsPushed(FALSE), - fOurAssociations(nil) - {} - virtual ~PrefsGeneralPage(void) { - delete[] fOurAssociations; - } - - bool fReady; - - // fields on this page - BOOL fColumn[kNumVisibleColumns]; - BOOL fMimicShrinkIt; - BOOL fBadMacSHK; - BOOL fReduceSHKErrorChecks; - BOOL fCoerceDOSFilenames; - BOOL fSpacesToUnder; - BOOL fPasteJunkPaths; - BOOL fBeepOnSuccess; - BOOL fDefaultsPushed; - - // initialized if we opened the file associations edit page - bool* fOurAssociations; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); - - afx_msg void OnChange(void); - afx_msg void OnChangeRange(UINT); - afx_msg void OnDefaults(void); - afx_msg void OnAssociations(void); - afx_msg LONG OnHelp(UINT wParam, LONG lParam); - afx_msg LONG OnCommandHelp(UINT wParam, LONG lParam); - - DECLARE_MESSAGE_MAP() -}; - -/* - * The "disk image" page, for selecting disk image preferences. - */ -class PrefsDiskImagePage : public CPropertyPage -{ -public: - PrefsDiskImagePage(void) : - CPropertyPage(IDD_PREF_DISKIMAGE), - fReady(false), - fQueryImageFormat(FALSE), - fOpenVolumeRO(FALSE), - fProDOSAllowLower(FALSE), - fProDOSUseSparse(FALSE) - {} - - bool fReady; - - BOOL fQueryImageFormat; - BOOL fOpenVolumeRO; - BOOL fOpenVolumePhys0; - BOOL fProDOSAllowLower; - BOOL fProDOSUseSparse; - -protected: - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); - - afx_msg void OnChange(void); - //afx_msg void OnChangeRange(UINT); - afx_msg LONG OnHelp(UINT wParam, LONG lParam); - afx_msg LONG OnCommandHelp(UINT wParam, LONG lParam); - - DECLARE_MESSAGE_MAP() -}; - -/* - * The "compression" page, which lets the user choose a default compression - * method. - */ -class PrefsCompressionPage : public CPropertyPage -{ -public: - PrefsCompressionPage(void) : - CPropertyPage(IDD_PREF_COMPRESSION), fReady(false) - {} - - bool fReady; - - int fCompressType; // radio button index - -protected: - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); - - afx_msg void OnChangeRange(UINT); - afx_msg LONG OnHelp(UINT wParam, LONG lParam); - afx_msg LONG OnCommandHelp(UINT wParam, LONG lParam); - -private: - void DisableWnd(int id); - - DECLARE_MESSAGE_MAP() -}; - -/* - * The "fview" page, for selecting preferences for the internal file viewer. - */ -class PrefsFviewPage : public CPropertyPage -{ -public: - PrefsFviewPage(void) : - CPropertyPage(IDD_PREF_FVIEW), fReady(false) - {} - bool fReady; - - BOOL fEOLConvRaw; - BOOL fNoWrapText; - BOOL fHighlightHexDump; - BOOL fHighlightBASIC; - BOOL fConvDisasmOneByteBrkCop; - BOOL fConvHiResBlackWhite; - int fConvDHRAlgorithm; // drop list - - BOOL fConvTextEOL_HA; - BOOL fConvCPMText; - BOOL fConvPascalText; - BOOL fConvPascalCode; - BOOL fConvApplesoft; - BOOL fConvInteger; - BOOL fConvBusiness; - BOOL fConvGWP; - BOOL fConvText8; - BOOL fConvAWP; - BOOL fConvADB; - BOOL fConvASP; - BOOL fConvSCAssem; - BOOL fConvDisasm; - - BOOL fConvHiRes; - BOOL fConvDHR; - BOOL fConvSHR; - BOOL fConvPrintShop; - BOOL fConvMacPaint; - BOOL fConvProDOSFolder; - BOOL fConvResources; - BOOL fRelaxGfxTypeCheck; - - UINT fMaxViewFileSizeKB; - -protected: - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); - - afx_msg void OnChange(void); - afx_msg void OnChangeRange(UINT); - afx_msg LONG OnHelp(UINT wParam, LONG lParam); - afx_msg LONG OnCommandHelp(UINT wParam, LONG lParam); - - DECLARE_MESSAGE_MAP() -}; - -/* - * The "compression" page, which lets the user choose a default compression - * method for NuFX archives. - */ -class PrefsFilesPage : public CPropertyPage -{ -public: - PrefsFilesPage(void) : - CPropertyPage(IDD_PREF_FILES), fReady(false) - {} - - bool fReady; - - CString fTempPath; - CString fExtViewerExts; - -protected: - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); - - afx_msg void OnChange(void); - afx_msg void OnChooseFolder(void); - afx_msg LONG OnHelp(UINT wParam, LONG lParam); - afx_msg LONG OnCommandHelp(UINT wParam, LONG lParam); - - MyBitmapButton fChooseFolderButton; - - DECLARE_MESSAGE_MAP() -}; - - -/* - * Property sheet that wraps around the preferences pages. - */ -class PrefsSheet : public CPropertySheet -{ -public: - PrefsSheet(CWnd* pParentWnd = NULL); - - PrefsGeneralPage fGeneralPage; - PrefsDiskImagePage fDiskImagePage; - PrefsCompressionPage fCompressionPage; - PrefsFviewPage fFviewPage; - PrefsFilesPage fFilesPage; - -protected: - BOOL OnNcCreate(LPCREATESTRUCT cs); - - afx_msg void OnApplyNow(); - LONG OnHelp(UINT wParam, LONG lParam); - void OnIDHelp(void); - - DECLARE_MESSAGE_MAP() -}; - +/* + * CiderPress + * Copyright (C) 2007, 2008 by faddenSoft, LLC. All Rights Reserved. + * See the file LICENSE for distribution terms. + */ +/* + * Classes to support the Preferences property pages. + */ +#ifndef __PREFSDIALOG__ +#define __PREFSDIALOG__ + +#include "Preferences.h" +#include "../util/UtilLib.h" +#include "resource.h" + +/* + * The "general" page, which controls how we display information to the user. + */ +class PrefsGeneralPage : public CPropertyPage +{ +public: + PrefsGeneralPage(void) : + CPropertyPage(IDD_PREF_GENERAL), + fReady(false), + fMimicShrinkIt(FALSE), + fBadMacSHK(FALSE), + fReduceSHKErrorChecks(FALSE), + fCoerceDOSFilenames(FALSE), + fSpacesToUnder(FALSE), + fDefaultsPushed(FALSE), + fOurAssociations(nil) + {} + virtual ~PrefsGeneralPage(void) { + delete[] fOurAssociations; + } + + bool fReady; + + // fields on this page + BOOL fColumn[kNumVisibleColumns]; + BOOL fMimicShrinkIt; + BOOL fBadMacSHK; + BOOL fReduceSHKErrorChecks; + BOOL fCoerceDOSFilenames; + BOOL fSpacesToUnder; + BOOL fPasteJunkPaths; + BOOL fBeepOnSuccess; + BOOL fDefaultsPushed; + + // initialized if we opened the file associations edit page + bool* fOurAssociations; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); + + afx_msg void OnChange(void); + afx_msg void OnChangeRange(UINT); + afx_msg void OnDefaults(void); + afx_msg void OnAssociations(void); + afx_msg LONG OnHelp(UINT wParam, LONG lParam); + afx_msg LONG OnCommandHelp(UINT wParam, LONG lParam); + + DECLARE_MESSAGE_MAP() +}; + +/* + * The "disk image" page, for selecting disk image preferences. + */ +class PrefsDiskImagePage : public CPropertyPage +{ +public: + PrefsDiskImagePage(void) : + CPropertyPage(IDD_PREF_DISKIMAGE), + fReady(false), + fQueryImageFormat(FALSE), + fOpenVolumeRO(FALSE), + fProDOSAllowLower(FALSE), + fProDOSUseSparse(FALSE) + {} + + bool fReady; + + BOOL fQueryImageFormat; + BOOL fOpenVolumeRO; + BOOL fOpenVolumePhys0; + BOOL fProDOSAllowLower; + BOOL fProDOSUseSparse; + +protected: + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); + + afx_msg void OnChange(void); + //afx_msg void OnChangeRange(UINT); + afx_msg LONG OnHelp(UINT wParam, LONG lParam); + afx_msg LONG OnCommandHelp(UINT wParam, LONG lParam); + + DECLARE_MESSAGE_MAP() +}; + +/* + * The "compression" page, which lets the user choose a default compression + * method. + */ +class PrefsCompressionPage : public CPropertyPage +{ +public: + PrefsCompressionPage(void) : + CPropertyPage(IDD_PREF_COMPRESSION), fReady(false) + {} + + bool fReady; + + int fCompressType; // radio button index + +protected: + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); + + afx_msg void OnChangeRange(UINT); + afx_msg LONG OnHelp(UINT wParam, LONG lParam); + afx_msg LONG OnCommandHelp(UINT wParam, LONG lParam); + +private: + void DisableWnd(int id); + + DECLARE_MESSAGE_MAP() +}; + +/* + * The "fview" page, for selecting preferences for the internal file viewer. + */ +class PrefsFviewPage : public CPropertyPage +{ +public: + PrefsFviewPage(void) : + CPropertyPage(IDD_PREF_FVIEW), fReady(false) + {} + bool fReady; + + BOOL fEOLConvRaw; + BOOL fNoWrapText; + BOOL fHighlightHexDump; + BOOL fHighlightBASIC; + BOOL fConvDisasmOneByteBrkCop; + BOOL fConvHiResBlackWhite; + int fConvDHRAlgorithm; // drop list + + BOOL fConvTextEOL_HA; + BOOL fConvCPMText; + BOOL fConvPascalText; + BOOL fConvPascalCode; + BOOL fConvApplesoft; + BOOL fConvInteger; + BOOL fConvBusiness; + BOOL fConvGWP; + BOOL fConvText8; + BOOL fConvAWP; + BOOL fConvADB; + BOOL fConvASP; + BOOL fConvSCAssem; + BOOL fConvDisasm; + + BOOL fConvHiRes; + BOOL fConvDHR; + BOOL fConvSHR; + BOOL fConvPrintShop; + BOOL fConvMacPaint; + BOOL fConvProDOSFolder; + BOOL fConvResources; + BOOL fRelaxGfxTypeCheck; + + UINT fMaxViewFileSizeKB; + +protected: + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); + + afx_msg void OnChange(void); + afx_msg void OnChangeRange(UINT); + afx_msg LONG OnHelp(UINT wParam, LONG lParam); + afx_msg LONG OnCommandHelp(UINT wParam, LONG lParam); + + DECLARE_MESSAGE_MAP() +}; + +/* + * The "compression" page, which lets the user choose a default compression + * method for NuFX archives. + */ +class PrefsFilesPage : public CPropertyPage +{ +public: + PrefsFilesPage(void) : + CPropertyPage(IDD_PREF_FILES), fReady(false) + {} + + bool fReady; + + CString fTempPath; + CString fExtViewerExts; + +protected: + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); + + afx_msg void OnChange(void); + afx_msg void OnChooseFolder(void); + afx_msg LONG OnHelp(UINT wParam, LONG lParam); + afx_msg LONG OnCommandHelp(UINT wParam, LONG lParam); + + MyBitmapButton fChooseFolderButton; + + DECLARE_MESSAGE_MAP() +}; + + +/* + * Property sheet that wraps around the preferences pages. + */ +class PrefsSheet : public CPropertySheet +{ +public: + PrefsSheet(CWnd* pParentWnd = NULL); + + PrefsGeneralPage fGeneralPage; + PrefsDiskImagePage fDiskImagePage; + PrefsCompressionPage fCompressionPage; + PrefsFviewPage fFviewPage; + PrefsFilesPage fFilesPage; + +protected: + BOOL OnNcCreate(LPCREATESTRUCT cs); + + afx_msg void OnApplyNow(); + LONG OnHelp(UINT wParam, LONG lParam); + void OnIDHelp(void); + + DECLARE_MESSAGE_MAP() +}; + #endif /*__PREFSDIALOG__*/ \ No newline at end of file diff --git a/app/Print.cpp b/app/Print.cpp index 0ab6470..3501f58 100644 --- a/app/Print.cpp +++ b/app/Print.cpp @@ -14,7 +14,7 @@ /* * ========================================================================== - * PrintStuff + * PrintStuff * ========================================================================== */ @@ -27,21 +27,21 @@ void PrintStuff::InitBasics(CDC* pDC) { - ASSERT(pDC != nil); - ASSERT(fpDC == nil); + ASSERT(pDC != nil); + ASSERT(fpDC == nil); - fpDC = pDC; + fpDC = pDC; - /* make sure we're in MM_TEXT mode */ - pDC->SetMapMode(MM_TEXT); + /* make sure we're in MM_TEXT mode */ + pDC->SetMapMode(MM_TEXT); - /* get device capabilities; logPixels is e.g. 300 */ - fVertRes = pDC->GetDeviceCaps(VERTRES); - fHorzRes = pDC->GetDeviceCaps(HORZRES); - fLogPixelsX = pDC->GetDeviceCaps(LOGPIXELSX); - fLogPixelsY = pDC->GetDeviceCaps(LOGPIXELSY); - WMSG4("+++ logPixelsX=%d logPixelsY=%d fHorzRes=%d fVertRes=%d\n", - fLogPixelsX, fLogPixelsY, fHorzRes, fVertRes); + /* get device capabilities; logPixels is e.g. 300 */ + fVertRes = pDC->GetDeviceCaps(VERTRES); + fHorzRes = pDC->GetDeviceCaps(HORZRES); + fLogPixelsX = pDC->GetDeviceCaps(LOGPIXELSX); + fLogPixelsY = pDC->GetDeviceCaps(LOGPIXELSY); + WMSG4("+++ logPixelsX=%d logPixelsY=%d fHorzRes=%d fVertRes=%d\n", + fLogPixelsX, fLogPixelsY, fHorzRes, fVertRes); } /* @@ -50,24 +50,24 @@ PrintStuff::InitBasics(CDC* pDC) void PrintStuff::CreateFontByNumLines(CFont* pFont, int numLines) { - ASSERT(pFont != nil); - ASSERT(numLines > 0); - ASSERT(fpDC != nil); + ASSERT(pFont != nil); + ASSERT(numLines > 0); + ASSERT(fpDC != nil); - /* required height */ - int reqCharHeight; - reqCharHeight = (fVertRes + numLines/2) / numLines; + /* required height */ + int reqCharHeight; + reqCharHeight = (fVertRes + numLines/2) / numLines; - /* magic fudge factor */ - int fudge = reqCharHeight / 24; - WMSG2(" Reducing reqCharHeight from %d to %d\n", - reqCharHeight, reqCharHeight - fudge); - reqCharHeight -= fudge; + /* magic fudge factor */ + int fudge = reqCharHeight / 24; + WMSG2(" Reducing reqCharHeight from %d to %d\n", + reqCharHeight, reqCharHeight - fudge); + reqCharHeight -= fudge; - pFont->CreateFont(reqCharHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, - DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, - DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, kTimesNewRoman); - /*fpOldFont =*/ fpDC->SelectObject(pFont); + pFont->CreateFont(reqCharHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, + DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, + DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, kTimesNewRoman); + /*fpOldFont =*/ fpDC->SelectObject(pFont); } @@ -77,9 +77,9 @@ PrintStuff::CreateFontByNumLines(CFont* pFont, int numLines) int PrintStuff::StringWidth(const CString& str) { - CSize size; - size = fpDC->GetTextExtent(str); - return size.cx; + CSize size; + size = fpDC->GetTextExtent(str); + return size.cx; } /* @@ -89,52 +89,52 @@ PrintStuff::StringWidth(const CString& str) int PrintStuff::TrimString(CString* pStr, int width, bool addOnLeft) { - static const char* kEllipsis = "..."; - CString newStr; - int strWidth; - CSize size; + static const char* kEllipsis = "..."; + CString newStr; + int strWidth; + CSize size; - size = fpDC->GetTextExtent(kEllipsis); + size = fpDC->GetTextExtent(kEllipsis); - if (width < size.cx) { - ASSERT(false); - return width; - } + if (width < size.cx) { + ASSERT(false); + return width; + } - newStr = *pStr; + newStr = *pStr; - /* - * Do a linear search. This would probably be better served with a - * binary search or at least a good textmetric-based guess. - */ - strWidth = StringWidth(newStr); - while (strWidth > width) { - if (pStr->IsEmpty()) { - ASSERT(false); - return width; - } - if (addOnLeft) { - *pStr = pStr->Right(pStr->GetLength() -1); - newStr = kEllipsis + *pStr; - } else { - *pStr = pStr->Left(pStr->GetLength() -1); - newStr = *pStr + kEllipsis; - } + /* + * Do a linear search. This would probably be better served with a + * binary search or at least a good textmetric-based guess. + */ + strWidth = StringWidth(newStr); + while (strWidth > width) { + if (pStr->IsEmpty()) { + ASSERT(false); + return width; + } + if (addOnLeft) { + *pStr = pStr->Right(pStr->GetLength() -1); + newStr = kEllipsis + *pStr; + } else { + *pStr = pStr->Left(pStr->GetLength() -1); + newStr = *pStr + kEllipsis; + } - if (!addOnLeft) { - WMSG1("Now trying '%s'\n", (LPCTSTR) newStr); - } - strWidth = StringWidth(newStr); - } + if (!addOnLeft) { + WMSG1("Now trying '%s'\n", (LPCTSTR) newStr); + } + strWidth = StringWidth(newStr); + } - *pStr = newStr; - return strWidth; + *pStr = newStr; + return strWidth; } /* * ========================================================================== - * PrintContentList + * PrintContentList * ========================================================================== */ @@ -144,25 +144,25 @@ PrintStuff::TrimString(CString* pStr, int width, bool addOnLeft) void PrintContentList::Setup(CDC* pDC, CWnd* pParent) { - /* init base class */ - InitBasics(pDC); + /* init base class */ + InitBasics(pDC); - /* init our stuff */ - CreateFontByNumLines(&fPrintFont, kTargetLinesPerPage); + /* init our stuff */ + CreateFontByNumLines(&fPrintFont, kTargetLinesPerPage); - fpParentWnd = pParent; + fpParentWnd = pParent; - /* compute text metrics */ - TEXTMETRIC metrics; - pDC->GetTextMetrics(&metrics); - fCharHeight = metrics.tmHeight + metrics.tmExternalLeading; - fLinesPerPage = fVertRes / fCharHeight; + /* compute text metrics */ + TEXTMETRIC metrics; + pDC->GetTextMetrics(&metrics); + fCharHeight = metrics.tmHeight + metrics.tmExternalLeading; + fLinesPerPage = fVertRes / fCharHeight; - WMSG2("fVertRes=%d, fCharHeight=%d\n", fVertRes, fCharHeight); + WMSG2("fVertRes=%d, fCharHeight=%d\n", fVertRes, fCharHeight); - /* set up our slightly reduced lines per page */ - ASSERT(fLinesPerPage > kHeaderLines+1); - fCLLinesPerPage = fLinesPerPage - kHeaderLines; + /* set up our slightly reduced lines per page */ + ASSERT(fLinesPerPage > kHeaderLines+1); + fCLLinesPerPage = fLinesPerPage - kHeaderLines; } /* @@ -171,16 +171,16 @@ PrintContentList::Setup(CDC* pDC, CWnd* pParent) void PrintContentList::CalcNumPages(void) { - /* set up our local goodies */ - ASSERT(fpContentList != nil); - int numLines = fpContentList->GetItemCount(); - ASSERT(numLines > 0); + /* set up our local goodies */ + ASSERT(fpContentList != nil); + int numLines = fpContentList->GetItemCount(); + ASSERT(numLines > 0); - fNumPages = (numLines + fCLLinesPerPage -1) / fCLLinesPerPage; - ASSERT(fNumPages > 0); + fNumPages = (numLines + fCLLinesPerPage -1) / fCLLinesPerPage; + ASSERT(fNumPages > 0); - WMSG3("Using numLines=%d, fNumPages=%d, fCLLinesPerPage=%d\n", - numLines, fNumPages, fCLLinesPerPage); + WMSG3("Using numLines=%d, fNumPages=%d, fCLLinesPerPage=%d\n", + numLines, fNumPages, fCLLinesPerPage); } /* @@ -191,22 +191,22 @@ PrintContentList::CalcNumPages(void) int PrintContentList::Print(const ContentList* pContentList) { - fpContentList = pContentList; - CalcNumPages(); + fpContentList = pContentList; + CalcNumPages(); - fFromPage = 1; - fToPage = fNumPages; - return StartPrint(); + fFromPage = 1; + fToPage = fNumPages; + return StartPrint(); } int PrintContentList::Print(const ContentList* pContentList, int fromPage, int toPage) { - fpContentList = pContentList; - CalcNumPages(); + fpContentList = pContentList; + CalcNumPages(); - fFromPage = fromPage; - fToPage = toPage; - return StartPrint(); + fFromPage = fromPage; + fToPage = toPage; + return StartPrint(); } /* @@ -215,65 +215,65 @@ PrintContentList::Print(const ContentList* pContentList, int fromPage, int toPag int PrintContentList::StartPrint(void) { - MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); - BOOL bres; - int jobID; - int result = -1; + MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); + BOOL bres; + int jobID; + int result = -1; - ASSERT(fFromPage >= 1); - ASSERT(fToPage <= fNumPages); + ASSERT(fFromPage >= 1); + ASSERT(fToPage <= fNumPages); - // clear the abort flag - pMain->SetAbortPrinting(false); + // clear the abort flag + pMain->SetAbortPrinting(false); - // obstruct input to the main window - fpParentWnd->EnableWindow(FALSE); + // obstruct input to the main window + fpParentWnd->EnableWindow(FALSE); - // create a print-cancel dialog -// PrintCancelDialog* pPCD = new PrintCancelDialog; - CancelDialog* pPCD = new CancelDialog; - bres = pPCD->Create(&pMain->fAbortPrinting, IDD_PRINT_CANCEL, fpParentWnd); - if (bres == FALSE) { - WMSG0("WARNING: PrintCancelDialog init failed\n"); - } else { - fpDC->SetAbortProc(pMain->PrintAbortProc); - } + // create a print-cancel dialog +// PrintCancelDialog* pPCD = new PrintCancelDialog; + CancelDialog* pPCD = new CancelDialog; + bres = pPCD->Create(&pMain->fAbortPrinting, IDD_PRINT_CANCEL, fpParentWnd); + if (bres == FALSE) { + WMSG0("WARNING: PrintCancelDialog init failed\n"); + } else { + fpDC->SetAbortProc(pMain->PrintAbortProc); + } - fDocTitle = pMain->GetPrintTitle(); + fDocTitle = pMain->GetPrintTitle(); - // set up the print job - CString printTitle; - printTitle.LoadString(IDS_PRINT_CL_JOB_TITLE); - DOCINFO di; - ::ZeroMemory(&di, sizeof(DOCINFO)); - di.cbSize = sizeof(DOCINFO); - di.lpszDocName = printTitle; + // set up the print job + CString printTitle; + printTitle.LoadString(IDS_PRINT_CL_JOB_TITLE); + DOCINFO di; + ::ZeroMemory(&di, sizeof(DOCINFO)); + di.cbSize = sizeof(DOCINFO); + di.lpszDocName = printTitle; - jobID = fpDC->StartDoc(&di); - if (jobID <= 0) { - WMSG0("Got invalid jobID from StartDoc\n"); - goto bail; - } - WMSG1("Got jobID=%d\n", jobID); + jobID = fpDC->StartDoc(&di); + if (jobID <= 0) { + WMSG0("Got invalid jobID from StartDoc\n"); + goto bail; + } + WMSG1("Got jobID=%d\n", jobID); - // do the printing - if (DoPrint() != 0) { - WMSG0("Printing was aborted\n"); - fpDC->AbortDoc(); - } else { - WMSG0("Printing was successful\n"); - fpDC->EndDoc(); - result = 0; - } + // do the printing + if (DoPrint() != 0) { + WMSG0("Printing was aborted\n"); + fpDC->AbortDoc(); + } else { + WMSG0("Printing was successful\n"); + fpDC->EndDoc(); + result = 0; + } bail: - // destroy print-cancel dialog and restore main window - fpParentWnd->EnableWindow(TRUE); - //fpParentWnd->SetActiveWindow(); - if (pPCD != nil) - pPCD->DestroyWindow(); + // destroy print-cancel dialog and restore main window + fpParentWnd->EnableWindow(TRUE); + //fpParentWnd->SetActiveWindow(); + if (pPCD != nil) + pPCD->DestroyWindow(); - return result; + return result; } @@ -285,30 +285,30 @@ bail: int PrintContentList::DoPrint(void) { - WMSG2("Printing from page=%d to page=%d\n", fFromPage, fToPage); + WMSG2("Printing from page=%d to page=%d\n", fFromPage, fToPage); - for (int page = fFromPage; page <= fToPage; page++) { - if (fpDC->StartPage() <= 0) { - WMSG0("StartPage returned <= 0, returning -1\n"); - return -1; - } + for (int page = fFromPage; page <= fToPage; page++) { + if (fpDC->StartPage() <= 0) { + WMSG0("StartPage returned <= 0, returning -1\n"); + return -1; + } - DoPrintPage(page); + DoPrintPage(page); - // delay so we can test "cancel" button -// { -// MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); -// pMain->EventPause(1000); -// } + // delay so we can test "cancel" button +// { +// MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); +// pMain->EventPause(1000); +// } - if (fpDC->EndPage() <= 0) { - WMSG0("EndPage returned <= 0, returning -1\n"); - return -1; - } - } + if (fpDC->EndPage() <= 0) { + WMSG0("EndPage returned <= 0, returning -1\n"); + return -1; + } + } - return 0; + return 0; } /* @@ -317,116 +317,116 @@ PrintContentList::DoPrint(void) void PrintContentList::DoPrintPage(int page) { - /* - * Column widths, on an arbitrary scale. These will be - * scaled appropriately for the page resolution. - */ - static const struct { - const char* name; - int width; - bool rightJust; - } kColumnWidths[kNumVisibleColumns] = { - { "Pathname", 250, false }, // 200 - { "Type", 40, false }, // 44 - { "Auxtype", 47, false }, // 42 - { "Mod Date", 96, false }, // 99 - { "Format", 52, false }, // 54 - { "Size", 55, true }, // 60 - { "Ratio", 40, true }, // 41 - { "Packed", 55, true }, // 60 - { "Access", 39, false }, // 53 upper, 45 lower - }; - const int kBorderWidth = 3; + /* + * Column widths, on an arbitrary scale. These will be + * scaled appropriately for the page resolution. + */ + static const struct { + const char* name; + int width; + bool rightJust; + } kColumnWidths[kNumVisibleColumns] = { + { "Pathname", 250, false }, // 200 + { "Type", 40, false }, // 44 + { "Auxtype", 47, false }, // 42 + { "Mod Date", 96, false }, // 99 + { "Format", 52, false }, // 54 + { "Size", 55, true }, // 60 + { "Ratio", 40, true }, // 41 + { "Packed", 55, true }, // 60 + { "Access", 39, false }, // 53 upper, 45 lower + }; + const int kBorderWidth = 3; - /* normalize */ - float widthMult; - int totalWidth; + /* normalize */ + float widthMult; + int totalWidth; - totalWidth = 0; - for (int i = 0; i < NELEM(kColumnWidths); i++) - totalWidth += kColumnWidths[i].width; + totalWidth = 0; + for (int i = 0; i < NELEM(kColumnWidths); i++) + totalWidth += kColumnWidths[i].width; - widthMult = (float) fHorzRes / totalWidth; - WMSG3("totalWidth=%d, fHorzRes=%d, mult=%.3f\n", - totalWidth, fHorzRes, widthMult); + widthMult = (float) fHorzRes / totalWidth; + WMSG3("totalWidth=%d, fHorzRes=%d, mult=%.3f\n", + totalWidth, fHorzRes, widthMult); - /* - * Calculate some goodies. - */ - int start, end; - start = (page-1) * fCLLinesPerPage; - end = start + fCLLinesPerPage; - if (end >= fpContentList->GetItemCount()) - end = fpContentList->GetItemCount()-1; + /* + * Calculate some goodies. + */ + int start, end; + start = (page-1) * fCLLinesPerPage; + end = start + fCLLinesPerPage; + if (end >= fpContentList->GetItemCount()) + end = fpContentList->GetItemCount()-1; - int offset, nextOffset, cellWidth, border; - border = (int) (kBorderWidth * widthMult); + int offset, nextOffset, cellWidth, border; + border = (int) (kBorderWidth * widthMult); - /* - * Print page header. - */ - fpDC->TextOut(0, 1 * fCharHeight, fDocTitle); - CString pageNum; - pageNum.Format("Page %d/%d", page, fNumPages); - int pageNumWidth = StringWidth(pageNum); - fpDC->TextOut(fHorzRes - pageNumWidth, 1 * fCharHeight, pageNum); + /* + * Print page header. + */ + fpDC->TextOut(0, 1 * fCharHeight, fDocTitle); + CString pageNum; + pageNum.Format("Page %d/%d", page, fNumPages); + int pageNumWidth = StringWidth(pageNum); + fpDC->TextOut(fHorzRes - pageNumWidth, 1 * fCharHeight, pageNum); - /* - * Print data. - */ - for (int row = -1; row < fCLLinesPerPage && start + row <= end; row++) { - CString text; - offset = 0; + /* + * Print data. + */ + for (int row = -1; row < fCLLinesPerPage && start + row <= end; row++) { + CString text; + offset = 0; - for (int col = 0; col < kNumVisibleColumns; col++) { - cellWidth = (int) ((float)kColumnWidths[col].width * widthMult); - nextOffset = offset + cellWidth; - if (col != kNumVisibleColumns-1) - cellWidth -= border; - if (col == 0) - cellWidth -= (border*2); // extra border on pathname + for (int col = 0; col < kNumVisibleColumns; col++) { + cellWidth = (int) ((float)kColumnWidths[col].width * widthMult); + nextOffset = offset + cellWidth; + if (col != kNumVisibleColumns-1) + cellWidth -= border; + if (col == 0) + cellWidth -= (border*2); // extra border on pathname - int yOffset; - if (row == -1) { - text = kColumnWidths[col].name; - yOffset = (row+kHeaderLines-1) * fCharHeight; - } else { - text = fpContentList->GetItemText(start + row, col); - yOffset = (row+kHeaderLines) * fCharHeight; - } + int yOffset; + if (row == -1) { + text = kColumnWidths[col].name; + yOffset = (row+kHeaderLines-1) * fCharHeight; + } else { + text = fpContentList->GetItemText(start + row, col); + yOffset = (row+kHeaderLines) * fCharHeight; + } - int strWidth; - strWidth = TrimString(&text, cellWidth, col == 0); + int strWidth; + strWidth = TrimString(&text, cellWidth, col == 0); - if (kColumnWidths[col].rightJust) - fpDC->TextOut((offset + cellWidth) - strWidth, yOffset, text); - else - fpDC->TextOut(offset, yOffset, text); + if (kColumnWidths[col].rightJust) + fpDC->TextOut((offset + cellWidth) - strWidth, yOffset, text); + else + fpDC->TextOut(offset, yOffset, text); - offset = nextOffset; - } - } + offset = nextOffset; + } + } - /* - * Add some fancy lines. - */ - CPen penBlack(PS_SOLID, 1, RGB(0, 0, 0)); - CPen* pOldPen = fpDC->SelectObject(&penBlack); - fpDC->MoveTo(0, (int) (fCharHeight * (kHeaderLines - 0.5))); - fpDC->LineTo(fHorzRes, (int) (fCharHeight * (kHeaderLines - 0.5))); + /* + * Add some fancy lines. + */ + CPen penBlack(PS_SOLID, 1, RGB(0, 0, 0)); + CPen* pOldPen = fpDC->SelectObject(&penBlack); + fpDC->MoveTo(0, (int) (fCharHeight * (kHeaderLines - 0.5))); + fpDC->LineTo(fHorzRes, (int) (fCharHeight * (kHeaderLines - 0.5))); - //fpDC->MoveTo(0, 0); - //fpDC->LineTo(fHorzRes, fVertRes); - //fpDC->MoveTo(fHorzRes-1, 0); - //fpDC->LineTo(0, fVertRes); + //fpDC->MoveTo(0, 0); + //fpDC->LineTo(fHorzRes, fVertRes); + //fpDC->MoveTo(fHorzRes-1, 0); + //fpDC->LineTo(0, fVertRes); - fpDC->SelectObject(pOldPen); + fpDC->SelectObject(pOldPen); } /* * ========================================================================== - * PrintRichEdit + * PrintRichEdit * ========================================================================== */ @@ -436,30 +436,30 @@ PrintContentList::DoPrintPage(int page) void PrintRichEdit::Setup(CDC* pDC, CWnd* pParent) { - /* preflighting can cause this to be initialized twice */ - fpDC = nil; + /* preflighting can cause this to be initialized twice */ + fpDC = nil; - /* init base class */ - InitBasics(pDC); + /* init base class */ + InitBasics(pDC); - if (!fInitialized) { - /* - * Find a nice font for the title area. - */ - const int kPointSize = 10; - int fontHeight; - BOOL result; + if (!fInitialized) { + /* + * Find a nice font for the title area. + */ + const int kPointSize = 10; + int fontHeight; + BOOL result; - fontHeight = -MulDiv(kPointSize, fLogPixelsY, 72); + fontHeight = -MulDiv(kPointSize, fLogPixelsY, 72); - result = fTitleFont.CreateFont(fontHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, - DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, - DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, kTimesNewRoman); - ASSERT(result); // everybody has Times New Roman - } + result = fTitleFont.CreateFont(fontHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, + DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, + DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, kTimesNewRoman); + ASSERT(result); // everybody has Times New Roman + } - fpParentWnd = pParent; - fInitialized = true; + fpParentWnd = pParent; + fInitialized = true; } /* @@ -468,11 +468,11 @@ PrintRichEdit::Setup(CDC* pDC, CWnd* pParent) int PrintRichEdit::PrintPreflight(CRichEditCtrl* pREC, int* pNumPages) { - fStartChar = 0; - fEndChar = -1; - fStartPage = 0; - fEndPage = -1; - return StartPrint(pREC, "(test)", pNumPages, false); + fStartChar = 0; + fEndChar = -1; + fStartPage = 0; + fEndPage = -1; + return StartPrint(pREC, "(test)", pNumPages, false); } /* @@ -481,11 +481,11 @@ PrintRichEdit::PrintPreflight(CRichEditCtrl* pREC, int* pNumPages) int PrintRichEdit::PrintAll(CRichEditCtrl* pREC, const char* title) { - fStartChar = 0; - fEndChar = -1; - fStartPage = 0; - fEndPage = -1; - return StartPrint(pREC, title, nil, true); + fStartChar = 0; + fEndChar = -1; + fStartPage = 0; + fEndPage = -1; + return StartPrint(pREC, title, nil, true); } /* @@ -493,13 +493,13 @@ PrintRichEdit::PrintAll(CRichEditCtrl* pREC, const char* title) */ int PrintRichEdit::PrintPages(CRichEditCtrl* pREC, const char* title, - int startPage, int endPage) + int startPage, int endPage) { - fStartChar = 0; - fEndChar = -1; - fStartPage = startPage; - fEndPage = endPage; - return StartPrint(pREC, title, nil, true); + fStartChar = 0; + fEndChar = -1; + fStartPage = startPage; + fEndPage = endPage; + return StartPrint(pREC, title, nil, true); } /* @@ -507,13 +507,13 @@ PrintRichEdit::PrintPages(CRichEditCtrl* pREC, const char* title, */ int PrintRichEdit::PrintSelection(CRichEditCtrl* pREC, const char* title, - long startChar, long endChar) + long startChar, long endChar) { - fStartChar = startChar; - fEndChar = endChar; - fStartPage = 0; - fEndPage = -1; - return StartPrint(pREC, title, nil, true); + fStartChar = startChar; + fEndChar = endChar; + fStartPage = 0; + fEndPage = -1; + return StartPrint(pREC, title, nil, true); } /* @@ -521,37 +521,37 @@ PrintRichEdit::PrintSelection(CRichEditCtrl* pREC, const char* title, */ int PrintRichEdit::StartPrint(CRichEditCtrl* pREC, const char* title, - int* pNumPages, bool doPrint) + int* pNumPages, bool doPrint) { - CancelDialog* pPCD = nil; - MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); - int result; + CancelDialog* pPCD = nil; + MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); + int result; - /* set up the print cancel dialog */ - if (doPrint) { - BOOL bres; + /* set up the print cancel dialog */ + if (doPrint) { + BOOL bres; - /* disable main UI */ - fpParentWnd->EnableWindow(FALSE); + /* disable main UI */ + fpParentWnd->EnableWindow(FALSE); - pPCD = new CancelDialog; - bres = pPCD->Create(&pMain->fAbortPrinting, IDD_PRINT_CANCEL, - fpParentWnd); + pPCD = new CancelDialog; + bres = pPCD->Create(&pMain->fAbortPrinting, IDD_PRINT_CANCEL, + fpParentWnd); - /* set up the DC's print abort callback */ - if (bres != FALSE) - fpDC->SetAbortProc(pMain->PrintAbortProc); - } + /* set up the DC's print abort callback */ + if (bres != FALSE) + fpDC->SetAbortProc(pMain->PrintAbortProc); + } - result = DoPrint(pREC, title, pNumPages, doPrint); + result = DoPrint(pREC, title, pNumPages, doPrint); - if (doPrint) { - fpParentWnd->EnableWindow(TRUE); - if (pPCD != nil) - pPCD->DestroyWindow(); - } + if (doPrint) { + fpParentWnd->EnableWindow(TRUE); + if (pPCD != nil) + pPCD->DestroyWindow(); + } - return result; + return result; } /* @@ -560,51 +560,51 @@ PrintRichEdit::StartPrint(CRichEditCtrl* pREC, const char* title, void PrintRichEdit::PrintPrep(FORMATRANGE* pFR) { - CFont* pOldFont; + CFont* pOldFont; - /* make sure we're in MM_TEXT mode */ - fpDC->SetMapMode(MM_TEXT); + /* make sure we're in MM_TEXT mode */ + fpDC->SetMapMode(MM_TEXT); - TEXTMETRIC metrics; - pOldFont = fpDC->SelectObject(&fTitleFont); - fpDC->GetTextMetrics(&metrics); - fCharHeight = metrics.tmHeight + metrics.tmExternalLeading; - fpDC->SelectObject(pOldFont); - //WMSG1("CHAR HEIGHT is %d\n", fCharHeight); + TEXTMETRIC metrics; + pOldFont = fpDC->SelectObject(&fTitleFont); + fpDC->GetTextMetrics(&metrics); + fCharHeight = metrics.tmHeight + metrics.tmExternalLeading; + fpDC->SelectObject(pOldFont); + //WMSG1("CHAR HEIGHT is %d\n", fCharHeight); - /* compute fLeftMargin and fRightMargin */ - ComputeMargins(); + /* compute fLeftMargin and fRightMargin */ + ComputeMargins(); - /* - * Set up the FORMATRANGE values. The Rich Edit stuff likes to have - * measurements in TWIPS, whereas the printer is using DC pixel - * values. fLogPixels_ tells us how many pixels per inch. - */ - memset(pFR, 0, sizeof(FORMATRANGE)); - pFR->hdc = pFR->hdcTarget = fpDC->m_hDC; + /* + * Set up the FORMATRANGE values. The Rich Edit stuff likes to have + * measurements in TWIPS, whereas the printer is using DC pixel + * values. fLogPixels_ tells us how many pixels per inch. + */ + memset(pFR, 0, sizeof(FORMATRANGE)); + pFR->hdc = pFR->hdcTarget = fpDC->m_hDC; - /* - * Set frame for printable area, in TWIPS. The printer DC will set - * its own "reasonable" margins, so the area here is not the entire - * sheet of paper. - */ - pFR->rcPage.left = pFR->rcPage.top = 0; - pFR->rcPage.right = (fHorzRes * kTwipsPerInch) / fLogPixelsX; - pFR->rcPage.bottom = (fVertRes * kTwipsPerInch) / fLogPixelsY; + /* + * Set frame for printable area, in TWIPS. The printer DC will set + * its own "reasonable" margins, so the area here is not the entire + * sheet of paper. + */ + pFR->rcPage.left = pFR->rcPage.top = 0; + pFR->rcPage.right = (fHorzRes * kTwipsPerInch) / fLogPixelsX; + pFR->rcPage.bottom = (fVertRes * kTwipsPerInch) / fLogPixelsY; - long topOffset = (long) ((fCharHeight * 1.5 * kTwipsPerInch) / fLogPixelsY); - pFR->rc.top = pFR->rcPage.top + topOffset; - pFR->rc.bottom = pFR->rcPage.bottom; - pFR->rc.left = pFR->rcPage.left + (fLeftMargin * kTwipsPerInch) / fLogPixelsX; - pFR->rc.right = pFR->rcPage.right - (fRightMargin * kTwipsPerInch) / fLogPixelsX; + long topOffset = (long) ((fCharHeight * 1.5 * kTwipsPerInch) / fLogPixelsY); + pFR->rc.top = pFR->rcPage.top + topOffset; + pFR->rc.bottom = pFR->rcPage.bottom; + pFR->rc.left = pFR->rcPage.left + (fLeftMargin * kTwipsPerInch) / fLogPixelsX; + pFR->rc.right = pFR->rcPage.right - (fRightMargin * kTwipsPerInch) / fLogPixelsX; - WMSG2("PRINTABLE AREA is %d wide x %d high (twips)\n", - pFR->rc.right - pFR->rc.left, pFR->rc.bottom - pFR->rc.top); - WMSG2("FRAME is %d wide x %d high (twips)\n", - pFR->rcPage.right - pFR->rcPage.left, pFR->rcPage.bottom - pFR->rcPage.top); + WMSG2("PRINTABLE AREA is %d wide x %d high (twips)\n", + pFR->rc.right - pFR->rc.left, pFR->rc.bottom - pFR->rc.top); + WMSG2("FRAME is %d wide x %d high (twips)\n", + pFR->rcPage.right - pFR->rcPage.left, pFR->rcPage.bottom - pFR->rcPage.top); - pFR->chrg.cpMin = fStartChar; - pFR->chrg.cpMax = fEndChar; + pFR->chrg.cpMin = fStartChar; + pFR->chrg.cpMax = fEndChar; } /* @@ -616,50 +616,50 @@ PrintRichEdit::PrintPrep(FORMATRANGE* pFR) void PrintRichEdit::ComputeMargins(void) { - CFont tmpFont; - CFont* pOldFont; - int char80width, fontHeight, totalMargin; - BOOL result; + CFont tmpFont; + CFont* pOldFont; + int char80width, fontHeight, totalMargin; + BOOL result; - fontHeight = -MulDiv(10, fLogPixelsY, 72); + fontHeight = -MulDiv(10, fLogPixelsY, 72); - result = tmpFont.CreateFont(fontHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, - DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, - DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, kCourierNew); - ASSERT(result); + result = tmpFont.CreateFont(fontHeight, 0, 0, 0, FW_NORMAL, 0, 0, 0, + DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_CHARACTER_PRECIS, + DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, kCourierNew); + ASSERT(result); - pOldFont = fpDC->SelectObject(&tmpFont); - // in theory we could compute one 'X' * 80; this seems more reliable - char str[81]; - for (int i = 0; i < 80; i++) - str[i] = 'X'; - str[i] = '\0'; - char80width = StringWidth(str); - fpDC->SelectObject(pOldFont); + pOldFont = fpDC->SelectObject(&tmpFont); + // in theory we could compute one 'X' * 80; this seems more reliable + char str[81]; + for (int i = 0; i < 80; i++) + str[i] = 'X'; + str[i] = '\0'; + char80width = StringWidth(str); + fpDC->SelectObject(pOldFont); - //WMSG1("char80 string width=%d\n", char80width); + //WMSG1("char80 string width=%d\n", char80width); - /* - * If there's not enough room on the page, set the margins to zero. - * If the margins required exceed two inches, just set the margin - * to one inch on either side. - */ - totalMargin = fHorzRes - char80width; - if (totalMargin < 0) { - WMSG0(" Page not wide enough, setting margins to zero\n"); - fLeftMargin = fRightMargin = 0; - } else if (totalMargin > fLogPixelsX * 2) { - WMSG0(" Page too wide, setting margins to 1 inch\n"); - fLeftMargin = fRightMargin = fLogPixelsX; - } else { - // try to get leftMargin equal to 1/2" - fLeftMargin = totalMargin / 2; - if (fLeftMargin > fLogPixelsX / 2) - fLeftMargin = fLogPixelsX / 2; - fRightMargin = totalMargin - fLeftMargin -1; - WMSG3(" +++ Margins (in %d pixels/inch) are left=%ld right=%ld\n", - fLogPixelsX, fLeftMargin, fRightMargin); - } + /* + * If there's not enough room on the page, set the margins to zero. + * If the margins required exceed two inches, just set the margin + * to one inch on either side. + */ + totalMargin = fHorzRes - char80width; + if (totalMargin < 0) { + WMSG0(" Page not wide enough, setting margins to zero\n"); + fLeftMargin = fRightMargin = 0; + } else if (totalMargin > fLogPixelsX * 2) { + WMSG0(" Page too wide, setting margins to 1 inch\n"); + fLeftMargin = fRightMargin = fLogPixelsX; + } else { + // try to get leftMargin equal to 1/2" + fLeftMargin = totalMargin / 2; + if (fLeftMargin > fLogPixelsX / 2) + fLeftMargin = fLogPixelsX / 2; + fRightMargin = totalMargin - fLeftMargin -1; + WMSG3(" +++ Margins (in %d pixels/inch) are left=%ld right=%ld\n", + fLogPixelsX, fLeftMargin, fRightMargin); + } } /* @@ -669,153 +669,153 @@ PrintRichEdit::ComputeMargins(void) */ int PrintRichEdit::DoPrint(CRichEditCtrl* pREC, const char* title, - int* pNumPages, bool doPrint) + int* pNumPages, bool doPrint) { - FORMATRANGE fr; - DOCINFO di; - long textLength, textPrinted, lastTextPrinted; - int pageNum; + FORMATRANGE fr; + DOCINFO di; + long textLength, textPrinted, lastTextPrinted; + int pageNum; - WMSG2("DoPrint: title='%s' doPrint=%d\n", title, doPrint); - WMSG4(" startChar=%d endChar=%d startPage=%d endPage=%d\n", - fStartChar, fEndChar, fStartPage, fEndPage); + WMSG2("DoPrint: title='%s' doPrint=%d\n", title, doPrint); + WMSG4(" startChar=%d endChar=%d startPage=%d endPage=%d\n", + fStartChar, fEndChar, fStartPage, fEndPage); - /* - * Get the title font and fill out the FORMATRANGE structure. - */ - PrintPrep(&fr); + /* + * Get the title font and fill out the FORMATRANGE structure. + */ + PrintPrep(&fr); - /* fill out a DOCINFO */ - memset(&di, 0, sizeof(di)); - di.cbSize = sizeof(DOCINFO); - di.lpszDocName = title; + /* fill out a DOCINFO */ + memset(&di, 0, sizeof(di)); + di.cbSize = sizeof(DOCINFO); + di.lpszDocName = title; - if (doPrint) - fpDC->StartDoc(&di); + if (doPrint) + fpDC->StartDoc(&di); - /* - * Here's the really strange part of the affair. The GetTextLength call - * shown in the MSFT KB article doesn't return the correct number of - * characters. The CRichEditView code in MFC uses a GetTextLengthEx - * call, which is documented as being part of the CRichEditCtrl but - * doesn't appear in the header files. Call it the hard way. - * - * If you print a "raw" file with carriage returns, and you use version - * 5.30.23.1200 of "riched20.dll", you get "9609" from GetTextLength and - * "9528" from GetTextLengthEx when the document's length is 9528 and - * there are 81 carriage returns. The value you want to use is 9528, - * because the print code doesn't double-up the count on CRs. - * - * If instead you use version 5.30.23.1215, you get the same answer - * from both calls, and printing works fine. - * - * GetTextLengthEx is part of "riched20.dll". Win9x uses "riched32.dll", - * which doesn't support the call. - */ + /* + * Here's the really strange part of the affair. The GetTextLength call + * shown in the MSFT KB article doesn't return the correct number of + * characters. The CRichEditView code in MFC uses a GetTextLengthEx + * call, which is documented as being part of the CRichEditCtrl but + * doesn't appear in the header files. Call it the hard way. + * + * If you print a "raw" file with carriage returns, and you use version + * 5.30.23.1200 of "riched20.dll", you get "9609" from GetTextLength and + * "9528" from GetTextLengthEx when the document's length is 9528 and + * there are 81 carriage returns. The value you want to use is 9528, + * because the print code doesn't double-up the count on CRs. + * + * If instead you use version 5.30.23.1215, you get the same answer + * from both calls, and printing works fine. + * + * GetTextLengthEx is part of "riched20.dll". Win9x uses "riched32.dll", + * which doesn't support the call. + */ #ifdef _UNICODE # error "should be code page 1200, not CP_ACP" #endif - GETTEXTLENGTHEX exLenReq; - long basicTextLength, extdTextLength; - basicTextLength = pREC->GetTextLength(); - exLenReq.flags = GTL_PRECISE | GTL_NUMCHARS; - exLenReq.codepage = CP_ACP; - extdTextLength = (long)::SendMessage(pREC->m_hWnd, EM_GETTEXTLENGTHEX, - (WPARAM) &exLenReq, (LPARAM) NULL); - WMSG2("RichEdit text length: std=%ld extd=%ld\n", - basicTextLength, extdTextLength); + GETTEXTLENGTHEX exLenReq; + long basicTextLength, extdTextLength; + basicTextLength = pREC->GetTextLength(); + exLenReq.flags = GTL_PRECISE | GTL_NUMCHARS; + exLenReq.codepage = CP_ACP; + extdTextLength = (long)::SendMessage(pREC->m_hWnd, EM_GETTEXTLENGTHEX, + (WPARAM) &exLenReq, (LPARAM) NULL); + WMSG2("RichEdit text length: std=%ld extd=%ld\n", + basicTextLength, extdTextLength); - if (fEndChar == -1) { - if (extdTextLength > 0) - textLength = extdTextLength; - else - textLength = basicTextLength; - } else - textLength = fEndChar - fStartChar; + if (fEndChar == -1) { + if (extdTextLength > 0) + textLength = extdTextLength; + else + textLength = basicTextLength; + } else + textLength = fEndChar - fStartChar; - WMSG1(" +++ starting while loop, textLength=%ld\n", textLength); - pageNum = 0; - lastTextPrinted = -1; - do { - bool skipPage = false; - pageNum++; - WMSG1(" +++ while loop: pageNum is %d\n", pageNum); + WMSG1(" +++ starting while loop, textLength=%ld\n", textLength); + pageNum = 0; + lastTextPrinted = -1; + do { + bool skipPage = false; + pageNum++; + WMSG1(" +++ while loop: pageNum is %d\n", pageNum); - if (fEndPage > 0) { - if (pageNum < fStartPage) - skipPage = true; - if (pageNum > fEndPage) - break; // out of while, ending print - } + if (fEndPage > 0) { + if (pageNum < fStartPage) + skipPage = true; + if (pageNum > fEndPage) + break; // out of while, ending print + } - if (doPrint && !skipPage) { - fpDC->StartPage(); + if (doPrint && !skipPage) { + fpDC->StartPage(); - CFont* pOldFont = fpDC->SelectObject(&fTitleFont); - fpDC->TextOut(0, 0 * fCharHeight, title); - CString pageNumStr; - pageNumStr.Format("Page %d", pageNum); - int pageNumWidth = StringWidth(pageNumStr); - fpDC->TextOut(fHorzRes - pageNumWidth, 0 * fCharHeight, pageNumStr); - fpDC->SelectObject(pOldFont); + CFont* pOldFont = fpDC->SelectObject(&fTitleFont); + fpDC->TextOut(0, 0 * fCharHeight, title); + CString pageNumStr; + pageNumStr.Format("Page %d", pageNum); + int pageNumWidth = StringWidth(pageNumStr); + fpDC->TextOut(fHorzRes - pageNumWidth, 0 * fCharHeight, pageNumStr); + fpDC->SelectObject(pOldFont); - CPen penBlack(PS_SOLID, 1, RGB(0, 0, 0)); - CPen* pOldPen = fpDC->SelectObject(&penBlack); - int ycoord = (int) (fCharHeight * 1.25); - fpDC->MoveTo(0, ycoord-1); - fpDC->LineTo(fHorzRes, ycoord-1); - fpDC->MoveTo(0, ycoord); - fpDC->LineTo(fHorzRes, ycoord); + CPen penBlack(PS_SOLID, 1, RGB(0, 0, 0)); + CPen* pOldPen = fpDC->SelectObject(&penBlack); + int ycoord = (int) (fCharHeight * 1.25); + fpDC->MoveTo(0, ycoord-1); + fpDC->LineTo(fHorzRes, ycoord-1); + fpDC->MoveTo(0, ycoord); + fpDC->LineTo(fHorzRes, ycoord); - fpDC->SelectObject(pOldPen); - } + fpDC->SelectObject(pOldPen); + } - //WMSG1(" +++ calling FormatRange(%d)\n", doPrint && !skipPage); - //LogHexDump(&fr, sizeof(fr)); + //WMSG1(" +++ calling FormatRange(%d)\n", doPrint && !skipPage); + //LogHexDump(&fr, sizeof(fr)); - /* print a page full of RichEdit stuff */ - textPrinted = pREC->FormatRange(&fr, doPrint && !skipPage); - WMSG1(" +++ returned from FormatRange (textPrinted=%d)\n", - textPrinted); - if (textPrinted <= lastTextPrinted) { - /* the earlier StartPage can't be undone, so we'll get an - extra blank page at the very end */ - WMSG3("GLITCH: no new text printed (printed=%ld, last=%ld, len=%ld)\n", - textPrinted, lastTextPrinted, textLength); - pageNum--; // fix page count estimator - break; - } - lastTextPrinted = textPrinted; + /* print a page full of RichEdit stuff */ + textPrinted = pREC->FormatRange(&fr, doPrint && !skipPage); + WMSG1(" +++ returned from FormatRange (textPrinted=%d)\n", + textPrinted); + if (textPrinted <= lastTextPrinted) { + /* the earlier StartPage can't be undone, so we'll get an + extra blank page at the very end */ + WMSG3("GLITCH: no new text printed (printed=%ld, last=%ld, len=%ld)\n", + textPrinted, lastTextPrinted, textLength); + pageNum--; // fix page count estimator + break; + } + lastTextPrinted = textPrinted; - // delay so we can test "cancel" button - //((MainWindow*)::AfxGetMainWnd())->EventPause(1000); + // delay so we can test "cancel" button + //((MainWindow*)::AfxGetMainWnd())->EventPause(1000); - if (doPrint && !skipPage) { - if (fpDC->EndPage() <= 0) { - /* the "cancel" button was hit */ - WMSG0("EndPage returned <= 0 (cancelled)\n"); - fpDC->AbortDoc(); - return -1; - } - } + if (doPrint && !skipPage) { + if (fpDC->EndPage() <= 0) { + /* the "cancel" button was hit */ + WMSG0("EndPage returned <= 0 (cancelled)\n"); + fpDC->AbortDoc(); + return -1; + } + } - if (textPrinted < textLength) { - fr.chrg.cpMin = textPrinted; - fr.chrg.cpMax = fEndChar; // -1 if nothing selected - } - } while (textPrinted < textLength); + if (textPrinted < textLength) { + fr.chrg.cpMin = textPrinted; + fr.chrg.cpMax = fEndChar; // -1 if nothing selected + } + } while (textPrinted < textLength); - //WMSG0(" +++ calling FormatRange(nil, FALSE)\n"); - pREC->FormatRange(nil, FALSE); - //WMSG0(" +++ returned from final FormatRange\n"); + //WMSG0(" +++ calling FormatRange(nil, FALSE)\n"); + pREC->FormatRange(nil, FALSE); + //WMSG0(" +++ returned from final FormatRange\n"); - if (doPrint) - fpDC->EndDoc(); + if (doPrint) + fpDC->EndDoc(); - if (pNumPages != nil) - *pNumPages = pageNum; + if (pNumPages != nil) + *pNumPages = pageNum; - WMSG1("Printing completed (textPrinted=%ld)\n", textPrinted); + WMSG1("Printing completed (textPrinted=%ld)\n", textPrinted); - return 0; + return 0; } diff --git a/app/Print.h b/app/Print.h index abd2a49..13a4482 100644 --- a/app/Print.h +++ b/app/Print.h @@ -18,38 +18,38 @@ */ class PrintStuff { protected: - PrintStuff(void) : fpDC(nil) {} - virtual ~PrintStuff(void) {} + PrintStuff(void) : fpDC(nil) {} + virtual ~PrintStuff(void) {} - /* get basic goodies, based on the DC */ - virtual void InitBasics(CDC* pDC); + /* get basic goodies, based on the DC */ + virtual void InitBasics(CDC* pDC); - // Trim a string until it's <= width; returns final width. - int TrimString(CString* pStr, int width, bool addOnLeft = false); + // Trim a string until it's <= width; returns final width. + int TrimString(CString* pStr, int width, bool addOnLeft = false); - // Fills in blank "pFont" object with font that tries to get us N - // lines per page. - void CreateFontByNumLines(CFont* pFont, int numLines); + // Fills in blank "pFont" object with font that tries to get us N + // lines per page. + void CreateFontByNumLines(CFont* pFont, int numLines); - int StringWidth(const CString& str); + int StringWidth(const CString& str); - static const char* kCourierNew; - static const char* kTimesNewRoman; + static const char* kCourierNew; + static const char* kTimesNewRoman; - enum { - kTwipsPerInch = 1440 - }; + enum { + kTwipsPerInch = 1440 + }; - /* the printer DC */ - CDC* fpDC; + /* the printer DC */ + CDC* fpDC; - //CFont* fpOldFont; + //CFont* fpOldFont; - /* some stuff gleaned from fpDC */ - int fVertRes; - int fHorzRes; - int fLogPixelsX; - int fLogPixelsY; + /* some stuff gleaned from fpDC */ + int fVertRes; + int fHorzRes; + int fLogPixelsX; + int fLogPixelsY; }; @@ -58,43 +58,43 @@ protected: */ class PrintContentList : public PrintStuff { public: - PrintContentList(void) : fpContentList(nil), fCLLinesPerPage(0) {} - virtual ~PrintContentList(void) {} + PrintContentList(void) : fpContentList(nil), fCLLinesPerPage(0) {} + virtual ~PrintContentList(void) {} - /* set the DC and the parent window (for the cancel box) */ - virtual void Setup(CDC* pDC, CWnd* pParent); + /* set the DC and the parent window (for the cancel box) */ + virtual void Setup(CDC* pDC, CWnd* pParent); - int Print(const ContentList* pContentList); - int Print(const ContentList* pContentList, int fromPage, int toPage); + int Print(const ContentList* pContentList); + int Print(const ContentList* pContentList, int fromPage, int toPage); - /* this is used to set up the page range selection in print dialog */ - static int GetLinesPerPage(void) { - return kTargetLinesPerPage - kHeaderLines; - } + /* this is used to set up the page range selection in print dialog */ + static int GetLinesPerPage(void) { + return kTargetLinesPerPage - kHeaderLines; + } private: - void CalcNumPages(void); - int StartPrint(void); - int DoPrint(void); - void DoPrintPage(int page); + void CalcNumPages(void); + int StartPrint(void); + int DoPrint(void); + void DoPrintPage(int page); - enum { - kHeaderLines = 4, // lines of header stuff on each page - kTargetLinesPerPage = 64, // use fLinesPerPage for actual value - }; + enum { + kHeaderLines = 4, // lines of header stuff on each page + kTargetLinesPerPage = 64, // use fLinesPerPage for actual value + }; - CWnd* fpParentWnd; - CFont fPrintFont; - int fLinesPerPage; - int fCharHeight; - int fEllipsisWidth; + CWnd* fpParentWnd; + CFont fPrintFont; + int fLinesPerPage; + int fCharHeight; + int fEllipsisWidth; - const ContentList* fpContentList; - CString fDocTitle; - int fCLLinesPerPage; // fLinesPerPage - kHeaderLines - int fNumPages; - int fFromPage; - int fToPage; + const ContentList* fpContentList; + CString fDocTitle; + int fCLLinesPerPage; // fLinesPerPage - kHeaderLines + int fNumPages; + int fFromPage; + int fToPage; }; @@ -103,41 +103,41 @@ private: */ class PrintRichEdit : public PrintStuff { public: - PrintRichEdit(void) : fInitialized(false), fpParentWnd(nil) {} - virtual ~PrintRichEdit(void) {} + PrintRichEdit(void) : fInitialized(false), fpParentWnd(nil) {} + virtual ~PrintRichEdit(void) {} - /* set the DC and the parent window (for the cancel box) */ - virtual void Setup(CDC* pDC, CWnd* pParent); + /* set the DC and the parent window (for the cancel box) */ + virtual void Setup(CDC* pDC, CWnd* pParent); - /* - * Commence printing. - */ - int PrintPreflight(CRichEditCtrl* pREC, int* pNumPages); - int PrintAll(CRichEditCtrl* pREC, const char* title); - int PrintPages(CRichEditCtrl* pREC, const char* title, int startPage, - int endPage); - int PrintSelection(CRichEditCtrl* pREC, const char* title, long startChar, - long endChar); + /* + * Commence printing. + */ + int PrintPreflight(CRichEditCtrl* pREC, int* pNumPages); + int PrintAll(CRichEditCtrl* pREC, const char* title); + int PrintPages(CRichEditCtrl* pREC, const char* title, int startPage, + int endPage); + int PrintSelection(CRichEditCtrl* pREC, const char* title, long startChar, + long endChar); private: - int StartPrint(CRichEditCtrl* pREC, const char* title, - int* pNumPages, bool doPrint); - void PrintPrep(FORMATRANGE* pFR); - void ComputeMargins(void); - int DoPrint(CRichEditCtrl* pREC, const char* title, int* pNumPages, - bool doPrint); + int StartPrint(CRichEditCtrl* pREC, const char* title, + int* pNumPages, bool doPrint); + void PrintPrep(FORMATRANGE* pFR); + void ComputeMargins(void); + int DoPrint(CRichEditCtrl* pREC, const char* title, int* pNumPages, + bool doPrint); - bool fInitialized; - CFont fTitleFont; - int fCharHeight; - int fLeftMargin; - int fRightMargin; + bool fInitialized; + CFont fTitleFont; + int fCharHeight; + int fLeftMargin; + int fRightMargin; - CWnd* fpParentWnd; - int fStartChar; - int fEndChar; - int fStartPage; - int fEndPage; + CWnd* fpParentWnd; + int fStartChar; + int fEndChar; + int fStartPage; + int fEndPage; }; #endif /*__PRINT__*/ \ No newline at end of file diff --git a/app/ProgressCounterDialog.h b/app/ProgressCounterDialog.h index 438005f..e021e7f 100644 --- a/app/ProgressCounterDialog.h +++ b/app/ProgressCounterDialog.h @@ -17,54 +17,54 @@ */ class ProgressCounterDialog : public CancelDialog { public: - BOOL Create(const CString& descr, CWnd* pParentWnd = NULL) { - fpParentWnd = pParentWnd; - fDescr = descr; - fCountFormat = "%d"; - fCancel = false; + BOOL Create(const CString& descr, CWnd* pParentWnd = NULL) { + fpParentWnd = pParentWnd; + fDescr = descr; + fCountFormat = "%d"; + fCancel = false; - /* disable the parent window before we're created */ - if (pParentWnd != NULL) - pParentWnd->EnableWindow(FALSE); - return CancelDialog::Create(&fCancel, IDD_PROGRESS_COUNTER, - pParentWnd); - } - /* enable the parent window before we're destroyed */ - virtual BOOL DestroyWindow(void) { - if (fpParentWnd != nil) - fpParentWnd->EnableWindow(TRUE); - return ModelessDialog::DestroyWindow(); - } + /* disable the parent window before we're created */ + if (pParentWnd != NULL) + pParentWnd->EnableWindow(FALSE); + return CancelDialog::Create(&fCancel, IDD_PROGRESS_COUNTER, + pParentWnd); + } + /* enable the parent window before we're destroyed */ + virtual BOOL DestroyWindow(void) { + if (fpParentWnd != nil) + fpParentWnd->EnableWindow(TRUE); + return ModelessDialog::DestroyWindow(); + } - /* set a format string, e.g. "Processing file %d" */ - void SetCounterFormat(const CString& fmt) { fCountFormat = fmt; } + /* set a format string, e.g. "Processing file %d" */ + void SetCounterFormat(const CString& fmt) { fCountFormat = fmt; } - /* set the current count */ - void SetCount(int count) { - CString msg; - msg.Format(fCountFormat, count); - GetDlgItem(IDC_PROGRESS_COUNTER_COUNT)->SetWindowText(msg); - } + /* set the current count */ + void SetCount(int count) { + CString msg; + msg.Format(fCountFormat, count); + GetDlgItem(IDC_PROGRESS_COUNTER_COUNT)->SetWindowText(msg); + } - /* get the status of the "cancelled" flag */ - bool GetCancel(void) const { return fCancel; } + /* get the status of the "cancelled" flag */ + bool GetCancel(void) const { return fCancel; } private: - BOOL OnInitDialog(void) { - CancelDialog::OnInitDialog(); + BOOL OnInitDialog(void) { + CancelDialog::OnInitDialog(); - CWnd* pWnd = GetDlgItem(IDC_PROGRESS_COUNTER_DESC); - pWnd->SetWindowText(fDescr); - pWnd = GetDlgItem(IDC_PROGRESS_COUNTER_COUNT); - pWnd->SetWindowText(""); - pWnd->SetFocus(); // get focus off of the Cancel button - return FALSE; // accept our focus - } + CWnd* pWnd = GetDlgItem(IDC_PROGRESS_COUNTER_DESC); + pWnd->SetWindowText(fDescr); + pWnd = GetDlgItem(IDC_PROGRESS_COUNTER_COUNT); + pWnd->SetWindowText(""); + pWnd->SetFocus(); // get focus off of the Cancel button + return FALSE; // accept our focus + } - CWnd* fpParentWnd; - CString fDescr; - CString fCountFormat; - bool fCancel; + CWnd* fpParentWnd; + CString fDescr; + CString fCountFormat; + bool fCancel; }; #endif /*__PROGRESSCOUNTERDIALOG__*/ diff --git a/app/RecompressOptionsDialog.cpp b/app/RecompressOptionsDialog.cpp index 7bb6696..dbb47fd 100644 --- a/app/RecompressOptionsDialog.cpp +++ b/app/RecompressOptionsDialog.cpp @@ -12,8 +12,8 @@ #include "HelpTopics.h" //BEGIN_MESSAGE_MAP(UseSelectionDialog, CDialog) -// ON_WM_HELPINFO() -// //ON_COMMAND(IDHELP, OnHelp) +// ON_WM_HELPINFO() +// //ON_COMMAND(IDHELP, OnHelp) //END_MESSAGE_MAP() @@ -23,9 +23,9 @@ BOOL RecompressOptionsDialog::OnInitDialog(void) { - fCompressionIdx = LoadComboBox((NuThreadFormat) fCompressionType); + fCompressionIdx = LoadComboBox((NuThreadFormat) fCompressionType); - return UseSelectionDialog::OnInitDialog(); + return UseSelectionDialog::OnInitDialog(); } /* @@ -37,40 +37,40 @@ RecompressOptionsDialog::OnInitDialog(void) int RecompressOptionsDialog::LoadComboBox(NuThreadFormat fmt) { - static const struct { - NuThreadFormat format; - const char* name; - } kComboStrings[] = { - { kNuThreadFormatUncompressed, "No compression" }, - { kNuThreadFormatHuffmanSQ, "Squeeze" }, - { kNuThreadFormatLZW1, "Dynamic LZW/1" }, - { kNuThreadFormatLZW2, "Dynamic LZW/2" }, - { kNuThreadFormatLZC12, "12-bit LZC" }, - { kNuThreadFormatLZC16, "16-bit LZC" }, - { kNuThreadFormatDeflate, "Deflate" }, - { kNuThreadFormatBzip2, "Bzip2" }, - }; + static const struct { + NuThreadFormat format; + const char* name; + } kComboStrings[] = { + { kNuThreadFormatUncompressed, "No compression" }, + { kNuThreadFormatHuffmanSQ, "Squeeze" }, + { kNuThreadFormatLZW1, "Dynamic LZW/1" }, + { kNuThreadFormatLZW2, "Dynamic LZW/2" }, + { kNuThreadFormatLZC12, "12-bit LZC" }, + { kNuThreadFormatLZC16, "16-bit LZC" }, + { kNuThreadFormatDeflate, "Deflate" }, + { kNuThreadFormatBzip2, "Bzip2" }, + }; - CComboBox* pCombo; - int idx, comboIdx; - int retIdx = 0; + CComboBox* pCombo; + int idx, comboIdx; + int retIdx = 0; - pCombo = (CComboBox*) GetDlgItem(IDC_RECOMP_COMP); - ASSERT(pCombo != nil); + pCombo = (CComboBox*) GetDlgItem(IDC_RECOMP_COMP); + ASSERT(pCombo != nil); - for (idx = comboIdx = 0; idx < NELEM(kComboStrings); idx++) { - if (NufxArchive::IsCompressionSupported(kComboStrings[idx].format)) { - pCombo->AddString(kComboStrings[idx].name); - pCombo->SetItemData(comboIdx, kComboStrings[idx].format); + for (idx = comboIdx = 0; idx < NELEM(kComboStrings); idx++) { + if (NufxArchive::IsCompressionSupported(kComboStrings[idx].format)) { + pCombo->AddString(kComboStrings[idx].name); + pCombo->SetItemData(comboIdx, kComboStrings[idx].format); - if (kComboStrings[idx].format == fmt) - retIdx = comboIdx; + if (kComboStrings[idx].format == fmt) + retIdx = comboIdx; - comboIdx++; - } - } + comboIdx++; + } + } - return retIdx; + return retIdx; } /* @@ -79,17 +79,17 @@ RecompressOptionsDialog::LoadComboBox(NuThreadFormat fmt) void RecompressOptionsDialog::DoDataExchange(CDataExchange* pDX) { - DDX_CBIndex(pDX, IDC_RECOMP_COMP, fCompressionIdx); + DDX_CBIndex(pDX, IDC_RECOMP_COMP, fCompressionIdx); - if (pDX->m_bSaveAndValidate) { - CComboBox* pCombo; - pCombo = (CComboBox*) GetDlgItem(IDC_RECOMP_COMP); - ASSERT(pCombo != nil); + if (pDX->m_bSaveAndValidate) { + CComboBox* pCombo; + pCombo = (CComboBox*) GetDlgItem(IDC_RECOMP_COMP); + ASSERT(pCombo != nil); - fCompressionType = pCombo->GetItemData(fCompressionIdx); - WMSG2("DDX got type=%d from combo index %d\n", - fCompressionType, fCompressionIdx); - } + fCompressionType = pCombo->GetItemData(fCompressionIdx); + WMSG2("DDX got type=%d from combo index %d\n", + fCompressionType, fCompressionIdx); + } - UseSelectionDialog::DoDataExchange(pDX); + UseSelectionDialog::DoDataExchange(pDX); } diff --git a/app/RecompressOptionsDialog.h b/app/RecompressOptionsDialog.h index 6682cb9..18aaf8c 100644 --- a/app/RecompressOptionsDialog.h +++ b/app/RecompressOptionsDialog.h @@ -19,25 +19,25 @@ */ class RecompressOptionsDialog : public UseSelectionDialog { public: - RecompressOptionsDialog(int selCount, CWnd* pParentWnd = NULL) : - UseSelectionDialog(selCount, pParentWnd, IDD_RECOMPRESS_OPTS) - { - fCompressionType = 0; - } - virtual ~RecompressOptionsDialog(void) {} + RecompressOptionsDialog(int selCount, CWnd* pParentWnd = NULL) : + UseSelectionDialog(selCount, pParentWnd, IDD_RECOMPRESS_OPTS) + { + fCompressionType = 0; + } + virtual ~RecompressOptionsDialog(void) {} - // maps directly to NuThreadFormat enum - int fCompressionType; + // maps directly to NuThreadFormat enum + int fCompressionType; private: - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - int LoadComboBox(NuThreadFormat fmt); + int LoadComboBox(NuThreadFormat fmt); - int fCompressionIdx; // drop list index + int fCompressionIdx; // drop list index - //DECLARE_MESSAGE_MAP() + //DECLARE_MESSAGE_MAP() }; #endif /*__RECOMPRESS_OPTIONS_DIALOG__*/ \ No newline at end of file diff --git a/app/Registry.cpp b/app/Registry.cpp index a38b567..1840cfd 100644 --- a/app/Registry.cpp +++ b/app/Registry.cpp @@ -11,9 +11,9 @@ #include "Main.h" #include "MyApp.h" -#define kRegAppName "CiderPress" -#define kRegExeName "CiderPress.exe" -#define kCompanyName "faddenSoft" +#define kRegAppName "CiderPress" +#define kRegExeName "CiderPress.exe" +#define kCompanyName "faddenSoft" static const char* kRegKeyCPKVersions = _T("vrs"); static const char* kRegKeyCPKExpire = _T("epr"); @@ -21,23 +21,23 @@ static const char* kRegKeyCPKExpire = _T("epr"); /* * Application path. Add two keys: * - * (default) = FullPathName - * Full pathname of the executable file. - * Path = Path - * The $PATH that will be in effect when the program starts (but only if - * launched from the Windows explorer). + * (default) = FullPathName + * Full pathname of the executable file. + * Path = Path + * The $PATH that will be in effect when the program starts (but only if + * launched from the Windows explorer). */ static const char* kAppKeyBase = - _T("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\" kRegExeName); + _T("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\" kRegExeName); /* * Local settings. App stuff goes in the per-user key, registration info is * in the per-machine key. */ static const char* kMachineSettingsBaseKey = - _T("HKEY_LOCAL_MACHINE\\SOFTWARE\\" kCompanyName "\\" kRegAppName); + _T("HKEY_LOCAL_MACHINE\\SOFTWARE\\" kCompanyName "\\" kRegAppName); static const char* kUserSettingsBaseKey = - _T("HKEY_CURRENT_USER\\Software\\" kCompanyName "\\" kRegAppName); + _T("HKEY_CURRENT_USER\\Software\\" kCompanyName "\\" kRegAppName); /* * Set this key + ".XXX" to (Default)=AppID. This associates the file @@ -64,49 +64,49 @@ static const char* kRegKeyCPKStr = "CPK"; * Table of file type associations. They will appear in the UI in the same * order that they appear here, so try to maintain alphabetical order. */ -#define kAppIDNuFX _T("CiderPress.NuFX") -#define kAppIDDiskImage _T("CiderPress.DiskImage") -#define kAppIDBinaryII _T("CiderPress.BinaryII") -#define kNoAssociation _T("(no association)") +#define kAppIDNuFX _T("CiderPress.NuFX") +#define kAppIDDiskImage _T("CiderPress.DiskImage") +#define kAppIDBinaryII _T("CiderPress.BinaryII") +#define kNoAssociation _T("(no association)") const MyRegistry::FileTypeAssoc MyRegistry::kFileTypeAssoc[] = { - { _T(".2MG"), kAppIDDiskImage }, - { _T(".APP"), kAppIDDiskImage }, - { _T(".BNY"), kAppIDBinaryII }, - { _T(".BQY"), kAppIDBinaryII }, - { _T(".BSE"), kAppIDNuFX }, - { _T(".BXY"), kAppIDNuFX }, - { _T(".D13"), kAppIDDiskImage }, - { _T(".DDD"), kAppIDDiskImage }, - { _T(".DO"), kAppIDDiskImage }, - { _T(".DSK"), kAppIDDiskImage }, - { _T(".FDI"), kAppIDDiskImage }, - { _T(".HDV"), kAppIDDiskImage }, - { _T(".IMG"), kAppIDDiskImage }, - { _T(".NIB"), kAppIDDiskImage }, - { _T(".PO"), kAppIDDiskImage }, - { _T(".SDK"), kAppIDDiskImage }, - { _T(".SEA"), kAppIDNuFX }, - { _T(".SHK"), kAppIDNuFX }, -// { _T(".DC"), kAppIDDiskImage }, -// { _T(".DC6"), kAppIDDiskImage }, -// { _T(".GZ"), kAppIDDiskImage }, -// { _T(".NB2"), kAppIDDiskImage }, -// { _T(".RAW"), kAppIDDiskImage }, -// { _T(".ZIP"), kAppIDDiskImage }, + { _T(".2MG"), kAppIDDiskImage }, + { _T(".APP"), kAppIDDiskImage }, + { _T(".BNY"), kAppIDBinaryII }, + { _T(".BQY"), kAppIDBinaryII }, + { _T(".BSE"), kAppIDNuFX }, + { _T(".BXY"), kAppIDNuFX }, + { _T(".D13"), kAppIDDiskImage }, + { _T(".DDD"), kAppIDDiskImage }, + { _T(".DO"), kAppIDDiskImage }, + { _T(".DSK"), kAppIDDiskImage }, + { _T(".FDI"), kAppIDDiskImage }, + { _T(".HDV"), kAppIDDiskImage }, + { _T(".IMG"), kAppIDDiskImage }, + { _T(".NIB"), kAppIDDiskImage }, + { _T(".PO"), kAppIDDiskImage }, + { _T(".SDK"), kAppIDDiskImage }, + { _T(".SEA"), kAppIDNuFX }, + { _T(".SHK"), kAppIDNuFX }, +// { _T(".DC"), kAppIDDiskImage }, +// { _T(".DC6"), kAppIDDiskImage }, +// { _T(".GZ"), kAppIDDiskImage }, +// { _T(".NB2"), kAppIDDiskImage }, +// { _T(".RAW"), kAppIDDiskImage }, +// { _T(".ZIP"), kAppIDDiskImage }, }; static const struct { - const char* user; - const char* reg; + const char* user; + const char* reg; } gBadKeys[] = { - { "Nimrod Bonehead", "CP1-68C069-62CC9444" }, - { "Connie Tan", "CP1-877B2C-A428FFD6" }, + { "Nimrod Bonehead", "CP1-68C069-62CC9444" }, + { "Connie Tan", "CP1-877B2C-A428FFD6" }, }; /* * ========================================================================== - * One-time install/uninstall + * One-time install/uninstall * ========================================================================== */ @@ -121,32 +121,32 @@ static const struct { void MyRegistry::OneTimeInstall(void) const { - /* start by stomping on our appIDs */ - WMSG0(" Removing appIDs\n"); - RegDeleteKeyNT(HKEY_CLASSES_ROOT, kAppIDNuFX); - RegDeleteKeyNT(HKEY_CLASSES_ROOT, kAppIDDiskImage); - RegDeleteKeyNT(HKEY_CLASSES_ROOT, kAppIDBinaryII); + /* start by stomping on our appIDs */ + WMSG0(" Removing appIDs\n"); + RegDeleteKeyNT(HKEY_CLASSES_ROOT, kAppIDNuFX); + RegDeleteKeyNT(HKEY_CLASSES_ROOT, kAppIDDiskImage); + RegDeleteKeyNT(HKEY_CLASSES_ROOT, kAppIDBinaryII); - /* configure the appIDs */ - FixBasicSettings(); + /* configure the appIDs */ + FixBasicSettings(); - /* configure extensions */ - int i, res; - for (i = 0; i < NELEM(kFileTypeAssoc); i++) { - HKEY hExtKey; - res = RegOpenKeyEx(HKEY_CLASSES_ROOT, kFileTypeAssoc[i].ext, 0, - KEY_READ, &hExtKey); - if (res == ERROR_SUCCESS) { - WMSG1(" Found existing HKCR\\'%s', leaving alone\n", - kFileTypeAssoc[i].ext); - RegCloseKey(hExtKey); - } else if (res == ERROR_FILE_NOT_FOUND) { - OwnExtension(kFileTypeAssoc[i].ext, kFileTypeAssoc[i].appID); - } else { - WMSG2(" Got error %ld opening HKCR\\'%s', leaving alone\n", - res, kFileTypeAssoc[i].ext); - } - } + /* configure extensions */ + int i, res; + for (i = 0; i < NELEM(kFileTypeAssoc); i++) { + HKEY hExtKey; + res = RegOpenKeyEx(HKEY_CLASSES_ROOT, kFileTypeAssoc[i].ext, 0, + KEY_READ, &hExtKey); + if (res == ERROR_SUCCESS) { + WMSG1(" Found existing HKCR\\'%s', leaving alone\n", + kFileTypeAssoc[i].ext); + RegCloseKey(hExtKey); + } else if (res == ERROR_FILE_NOT_FOUND) { + OwnExtension(kFileTypeAssoc[i].ext, kFileTypeAssoc[i].appID); + } else { + WMSG2(" Got error %ld opening HKCR\\'%s', leaving alone\n", + res, kFileTypeAssoc[i].ext); + } + } } /* @@ -161,29 +161,29 @@ MyRegistry::OneTimeInstall(void) const void MyRegistry::OneTimeUninstall(void) const { - /* drop any associations we hold */ - int i; - for (i = 0; i < NELEM(kFileTypeAssoc); i++) { - CString ext, handler; - bool ours; + /* drop any associations we hold */ + int i; + for (i = 0; i < NELEM(kFileTypeAssoc); i++) { + CString ext, handler; + bool ours; - GetFileAssoc(i, &ext, &handler, &ours); - if (ours) { - DisownExtension(ext); - } - } + GetFileAssoc(i, &ext, &handler, &ours); + if (ours) { + DisownExtension(ext); + } + } - /* remove our appIDs */ - WMSG0(" Removing appIDs\n"); - RegDeleteKeyNT(HKEY_CLASSES_ROOT, kAppIDNuFX); - RegDeleteKeyNT(HKEY_CLASSES_ROOT, kAppIDDiskImage); - RegDeleteKeyNT(HKEY_CLASSES_ROOT, kAppIDBinaryII); + /* remove our appIDs */ + WMSG0(" Removing appIDs\n"); + RegDeleteKeyNT(HKEY_CLASSES_ROOT, kAppIDNuFX); + RegDeleteKeyNT(HKEY_CLASSES_ROOT, kAppIDDiskImage); + RegDeleteKeyNT(HKEY_CLASSES_ROOT, kAppIDBinaryII); } /* * ========================================================================== - * Shareware registration logic + * Shareware registration logic * ========================================================================== */ @@ -191,7 +191,7 @@ MyRegistry::OneTimeUninstall(void) const /* * ========================================================================== - * Windows shell game + * Windows shell game * ========================================================================== */ @@ -204,7 +204,7 @@ MyRegistry::OneTimeUninstall(void) const const char* MyRegistry::GetAppRegistryKey(void) const { - return kCompanyName; + return kCompanyName; } /* @@ -213,9 +213,9 @@ MyRegistry::GetAppRegistryKey(void) const bool MyRegistry::IsOurAppID(const char* id) const { - return (strcasecmp(id, kAppIDNuFX) == 0 || - strcasecmp(id, kAppIDDiskImage) == 0 || - strcasecmp(id, kAppIDBinaryII) == 0); + return (strcasecmp(id, kAppIDNuFX) == 0 || + strcasecmp(id, kAppIDDiskImage) == 0 || + strcasecmp(id, kAppIDBinaryII) == 0); } /* @@ -229,14 +229,14 @@ MyRegistry::IsOurAppID(const char* id) const void MyRegistry::FixBasicSettings(void) const { - const char* exeName = gMyApp.GetExeFileName(); - ASSERT(exeName != nil && strlen(exeName) > 0); + const char* exeName = gMyApp.GetExeFileName(); + ASSERT(exeName != nil && strlen(exeName) > 0); - WMSG0("Fixing any missing file type AppID entries in registry\n"); + WMSG0("Fixing any missing file type AppID entries in registry\n"); - ConfigureAppID(kAppIDNuFX, "NuFX Archive (CiderPress)", exeName, 1); - ConfigureAppID(kAppIDBinaryII, "Binary II (CiderPress)", exeName, 2); - ConfigureAppID(kAppIDDiskImage, "Disk Image (CiderPress)", exeName, 3); + ConfigureAppID(kAppIDNuFX, "NuFX Archive (CiderPress)", exeName, 1); + ConfigureAppID(kAppIDBinaryII, "Binary II (CiderPress)", exeName, 2); + ConfigureAppID(kAppIDDiskImage, "Disk Image (CiderPress)", exeName, 3); } /* @@ -244,54 +244,54 @@ MyRegistry::FixBasicSettings(void) const */ void MyRegistry::ConfigureAppID(const char* appID, const char* descr, - const char* exeName, int iconIdx) const + const char* exeName, int iconIdx) const { - WMSG2(" Configuring '%s' for '%s'\n", appID, exeName); + WMSG2(" Configuring '%s' for '%s'\n", appID, exeName); - HKEY hAppKey = nil; - HKEY hIconKey = nil; + HKEY hAppKey = nil; + HKEY hIconKey = nil; - DWORD dw; - if (RegCreateKeyEx(HKEY_CLASSES_ROOT, appID, 0, REG_NONE, - REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, - &hAppKey, &dw) == ERROR_SUCCESS) - { - ConfigureAppIDSubFields(hAppKey, descr, exeName); + DWORD dw; + if (RegCreateKeyEx(HKEY_CLASSES_ROOT, appID, 0, REG_NONE, + REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, + &hAppKey, &dw) == ERROR_SUCCESS) + { + ConfigureAppIDSubFields(hAppKey, descr, exeName); - if (RegCreateKeyEx(hAppKey, kDefaultIcon, 0, REG_NONE, - REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, - &hIconKey, &dw) == ERROR_SUCCESS) - { - DWORD type, size; - unsigned char buf[256]; - long res; + if (RegCreateKeyEx(hAppKey, kDefaultIcon, 0, REG_NONE, + REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, + &hIconKey, &dw) == ERROR_SUCCESS) + { + DWORD type, size; + unsigned char buf[256]; + long res; - size = sizeof(buf); - res = RegQueryValueEx(hIconKey, "", nil, &type, buf, &size); - if (res == ERROR_SUCCESS && size > 1) { - WMSG1(" Icon for '%s' already exists, not altering\n", appID); - } else { - CString iconStr; - iconStr.Format("%s,%d", exeName, iconIdx); + size = sizeof(buf); + res = RegQueryValueEx(hIconKey, "", nil, &type, buf, &size); + if (res == ERROR_SUCCESS && size > 1) { + WMSG1(" Icon for '%s' already exists, not altering\n", appID); + } else { + CString iconStr; + iconStr.Format("%s,%d", exeName, iconIdx); - if (RegSetValueEx(hIconKey, "", 0, REG_SZ, (const unsigned char*) - (const char*) iconStr, strlen(iconStr)) == ERROR_SUCCESS) - { - WMSG2(" Set icon for '%s' to '%s'\n", appID, (LPCTSTR) iconStr); - } else { - WMSG2(" WARNING: unable to set DefaultIcon for '%s' to '%s'\n", - appID, (LPCTSTR) iconStr); - } - } - } else { - WMSG1("WARNING: couldn't set up DefaultIcon for '%s'\n", appID); - } - } else { - WMSG1("WARNING: couldn't create AppID='%s'\n", appID); - } + if (RegSetValueEx(hIconKey, "", 0, REG_SZ, (const unsigned char*) + (const char*) iconStr, strlen(iconStr)) == ERROR_SUCCESS) + { + WMSG2(" Set icon for '%s' to '%s'\n", appID, (LPCTSTR) iconStr); + } else { + WMSG2(" WARNING: unable to set DefaultIcon for '%s' to '%s'\n", + appID, (LPCTSTR) iconStr); + } + } + } else { + WMSG1("WARNING: couldn't set up DefaultIcon for '%s'\n", appID); + } + } else { + WMSG1("WARNING: couldn't create AppID='%s'\n", appID); + } - RegCloseKey(hIconKey); - RegCloseKey(hAppKey); + RegCloseKey(hIconKey); + RegCloseKey(hAppKey); } /* @@ -300,62 +300,62 @@ MyRegistry::ConfigureAppID(const char* appID, const char* descr, */ void MyRegistry::ConfigureAppIDSubFields(HKEY hAppKey, const char* descr, - const char* exeName) const + const char* exeName) const { - HKEY hShellKey, hOpenKey, hCommandKey; - DWORD dw; + HKEY hShellKey, hOpenKey, hCommandKey; + DWORD dw; - ASSERT(hAppKey != nil); - ASSERT(descr != nil); - ASSERT(exeName != nil); - hShellKey = hOpenKey = hCommandKey = nil; - - if (RegSetValueEx(hAppKey, "", 0, REG_SZ, (const unsigned char*) descr, - strlen(descr)) != ERROR_SUCCESS) - { - WMSG1(" WARNING: unable to set description to '%s'\n", descr); - } + ASSERT(hAppKey != nil); + ASSERT(descr != nil); + ASSERT(exeName != nil); + hShellKey = hOpenKey = hCommandKey = nil; + + if (RegSetValueEx(hAppKey, "", 0, REG_SZ, (const unsigned char*) descr, + strlen(descr)) != ERROR_SUCCESS) + { + WMSG1(" WARNING: unable to set description to '%s'\n", descr); + } - if (RegCreateKeyEx(hAppKey, _T("shell"), 0, REG_NONE, - REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, - &hShellKey, &dw) == ERROR_SUCCESS) - { - if (RegCreateKeyEx(hShellKey, _T("open"), 0, REG_NONE, - REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, - &hOpenKey, &dw) == ERROR_SUCCESS) - { - if (RegCreateKeyEx(hOpenKey, _T("command"), 0, REG_NONE, - REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, - &hCommandKey, &dw) == ERROR_SUCCESS) - { - DWORD type, size; - unsigned char buf[MAX_PATH+8]; - long res; + if (RegCreateKeyEx(hAppKey, _T("shell"), 0, REG_NONE, + REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, + &hShellKey, &dw) == ERROR_SUCCESS) + { + if (RegCreateKeyEx(hShellKey, _T("open"), 0, REG_NONE, + REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, + &hOpenKey, &dw) == ERROR_SUCCESS) + { + if (RegCreateKeyEx(hOpenKey, _T("command"), 0, REG_NONE, + REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, + &hCommandKey, &dw) == ERROR_SUCCESS) + { + DWORD type, size; + unsigned char buf[MAX_PATH+8]; + long res; - size = sizeof(buf); - res = RegQueryValueEx(hCommandKey, "", nil, &type, buf, &size); - if (res == ERROR_SUCCESS && size > 1) { - WMSG1(" Command already exists, not altering ('%s')\n", buf); - } else { - CString openCmd; + size = sizeof(buf); + res = RegQueryValueEx(hCommandKey, "", nil, &type, buf, &size); + if (res == ERROR_SUCCESS && size > 1) { + WMSG1(" Command already exists, not altering ('%s')\n", buf); + } else { + CString openCmd; - openCmd.Format("\"%s\" \"%%1\"", exeName); - if (RegSetValueEx(hCommandKey, "", 0, REG_SZ, - (const unsigned char*) (const char*) openCmd, - strlen(openCmd)) == ERROR_SUCCESS) - { - WMSG1(" Set command to '%s'\n", openCmd); - } else { - WMSG1(" WARNING: unable to set open cmd '%s'\n", openCmd); - } - } - } - } - } + openCmd.Format("\"%s\" \"%%1\"", exeName); + if (RegSetValueEx(hCommandKey, "", 0, REG_SZ, + (const unsigned char*) (const char*) openCmd, + strlen(openCmd)) == ERROR_SUCCESS) + { + WMSG1(" Set command to '%s'\n", openCmd); + } else { + WMSG1(" WARNING: unable to set open cmd '%s'\n", openCmd); + } + } + } + } + } - RegCloseKey(hCommandKey); - RegCloseKey(hOpenKey); - RegCloseKey(hShellKey); + RegCloseKey(hCommandKey); + RegCloseKey(hOpenKey); + RegCloseKey(hShellKey); } @@ -365,7 +365,7 @@ MyRegistry::ConfigureAppIDSubFields(HKEY hAppKey, const char* descr, int MyRegistry::GetNumFileAssocs(void) const { - return NELEM(kFileTypeAssoc); + return NELEM(kFileTypeAssoc); } #if 0 @@ -378,22 +378,22 @@ MyRegistry::GetNumFileAssocs(void) const */ void MyRegistry::GetFileAssoc(int idx, CString* pExt, CString* pHandler, - bool* pOurs) const + bool* pOurs) const { - char buf[MAX_PATH]; + char buf[MAX_PATH]; - *pExt = kFileTypeAssoc[idx].ext; - *pHandler = ""; - *pOurs = false; + *pExt = kFileTypeAssoc[idx].ext; + *pHandler = ""; + *pOurs = false; - HINSTANCE res = FindExecutable(*pExt, "\\", buf); - if ((long) res > 32) { - WMSG1("Executable is '%s'\n", buf); - *pHandler = buf; - } else { - WMSG1("FindExecutable failed (err=%d)\n", res); - *pHandler = kNoAssociation; - } + HINSTANCE res = FindExecutable(*pExt, "\\", buf); + if ((long) res > 32) { + WMSG1("Executable is '%s'\n", buf); + *pHandler = buf; + } else { + WMSG1("FindExecutable failed (err=%d)\n", res); + *pHandler = kNoAssociation; + } } #endif @@ -411,45 +411,45 @@ MyRegistry::GetFileAssoc(int idx, CString* pExt, CString* pHandler, */ void MyRegistry::GetFileAssoc(int idx, CString* pExt, CString* pHandler, - bool* pOurs) const + bool* pOurs) const { - ASSERT(idx >= 0 && idx < NELEM(kFileTypeAssoc)); - long res; + ASSERT(idx >= 0 && idx < NELEM(kFileTypeAssoc)); + long res; - *pExt = kFileTypeAssoc[idx].ext; - *pHandler = ""; + *pExt = kFileTypeAssoc[idx].ext; + *pHandler = ""; - CString appID; - HKEY hExtKey = nil; + CString appID; + HKEY hExtKey = nil; - res = RegOpenKeyEx(HKEY_CLASSES_ROOT, *pExt, 0, KEY_READ, &hExtKey); - if (res == ERROR_SUCCESS) { - unsigned char buf[260]; - DWORD type, size; + res = RegOpenKeyEx(HKEY_CLASSES_ROOT, *pExt, 0, KEY_READ, &hExtKey); + if (res == ERROR_SUCCESS) { + unsigned char buf[260]; + DWORD type, size; - size = sizeof(buf); - res = RegQueryValueEx(hExtKey, "", nil, &type, buf, &size); - if (res == ERROR_SUCCESS) { - WMSG1(" Got '%s'\n", buf); - appID = buf; + size = sizeof(buf); + res = RegQueryValueEx(hExtKey, "", nil, &type, buf, &size); + if (res == ERROR_SUCCESS) { + WMSG1(" Got '%s'\n", buf); + appID = buf; - if (GetAssocAppName(appID, pHandler) != 0) - *pHandler = appID; - } else { - WMSG1("RegQueryValueEx failed on '%s'\n", (LPCTSTR) *pExt); - } - } else { - WMSG1(" RegOpenKeyEx failed on '%s'\n", *pExt); - } + if (GetAssocAppName(appID, pHandler) != 0) + *pHandler = appID; + } else { + WMSG1("RegQueryValueEx failed on '%s'\n", (LPCTSTR) *pExt); + } + } else { + WMSG1(" RegOpenKeyEx failed on '%s'\n", *pExt); + } - *pOurs = false; - if (pHandler->IsEmpty()) { - *pHandler = kNoAssociation; - } else { - *pOurs = IsOurAppID(appID); - } + *pOurs = false; + if (pHandler->IsEmpty()) { + *pHandler = kNoAssociation; + } else { + *pOurs = IsOurAppID(appID); + } - RegCloseKey(hExtKey); + RegCloseKey(hExtKey); } /* @@ -460,45 +460,45 @@ MyRegistry::GetFileAssoc(int idx, CString* pExt, CString* pHandler, int MyRegistry::GetAssocAppName(const CString& appID, CString* pCmd) const { - CString keyName; - unsigned char buf[260]; - DWORD type, size = sizeof(buf); - HKEY hAppKey = nil; - long res; - int result = -1; + CString keyName; + unsigned char buf[260]; + DWORD type, size = sizeof(buf); + HKEY hAppKey = nil; + long res; + int result = -1; - keyName = appID + "\\shell\\open\\command"; + keyName = appID + "\\shell\\open\\command"; - res = RegOpenKeyEx(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ, &hAppKey); - if (res == ERROR_SUCCESS) { - res = RegQueryValueEx(hAppKey, "", nil, &type, buf, &size); - if (res == ERROR_SUCCESS) { - CString cmd(buf); - int pos; + res = RegOpenKeyEx(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ, &hAppKey); + if (res == ERROR_SUCCESS) { + res = RegQueryValueEx(hAppKey, "", nil, &type, buf, &size); + if (res == ERROR_SUCCESS) { + CString cmd(buf); + int pos; - /* cut it down to just the EXE name */ - ReduceToToken(&cmd); + /* cut it down to just the EXE name */ + ReduceToToken(&cmd); - pos = cmd.ReverseFind('\\'); - if (pos != -1 && pos != cmd.GetLength()-1) { - cmd = cmd.Right(cmd.GetLength() - pos -1); - } + pos = cmd.ReverseFind('\\'); + if (pos != -1 && pos != cmd.GetLength()-1) { + cmd = cmd.Right(cmd.GetLength() - pos -1); + } - *pCmd = cmd; - result = 0; - } else { - WMSG1("Unable to open shell\\open\\command for '%s'\n", appID); - } - } else { - CString errBuf; - GetWin32ErrorString(res, &errBuf); + *pCmd = cmd; + result = 0; + } else { + WMSG1("Unable to open shell\\open\\command for '%s'\n", appID); + } + } else { + CString errBuf; + GetWin32ErrorString(res, &errBuf); - WMSG2("Unable to open AppID key '%s' (%s)\n", - keyName, (LPCTSTR) errBuf); - } + WMSG2("Unable to open AppID key '%s' (%s)\n", + keyName, (LPCTSTR) errBuf); + } - RegCloseKey(hAppKey); - return result; + RegCloseKey(hAppKey); + return result; } /* @@ -507,55 +507,55 @@ MyRegistry::GetAssocAppName(const CString& appID, CString* pCmd) const void MyRegistry::ReduceToToken(CString* pStr) const { - char* argv[1]; - int argc = 1; - char* mangle = strdup(*pStr); + char* argv[1]; + int argc = 1; + char* mangle = strdup(*pStr); - VectorizeString(mangle, argv, &argc); + VectorizeString(mangle, argv, &argc); - if (argc == 1) - *pStr = argv[0]; + if (argc == 1) + *pStr = argv[0]; - free(mangle); + free(mangle); } /* * Set the state of a file association. There are four possibilities: * - * - We own it, we want to keep owning it: do nothing. - * - We don't own it, we want to keep not owning it: do nothing. - * - We own it, we don't want it anymore: remove ".xxx" entry. - * - We don't own it, we want to own it: remove ".xxx" entry and replace it. + * - We own it, we want to keep owning it: do nothing. + * - We don't own it, we want to keep not owning it: do nothing. + * - We own it, we don't want it anymore: remove ".xxx" entry. + * - We don't own it, we want to own it: remove ".xxx" entry and replace it. * * Returns 0 on success, nonzero on failure. */ int MyRegistry::SetFileAssoc(int idx, bool wantIt) const { - const char* ext; - bool weOwnIt; - int result = 0; + const char* ext; + bool weOwnIt; + int result = 0; - ASSERT(idx >= 0 && idx < NELEM(kFileTypeAssoc)); + ASSERT(idx >= 0 && idx < NELEM(kFileTypeAssoc)); - ext = kFileTypeAssoc[idx].ext; - weOwnIt = GetAssocState(ext); - WMSG3("SetFileAssoc: ext='%s' own=%d want=%d\n", ext, weOwnIt, wantIt); + ext = kFileTypeAssoc[idx].ext; + weOwnIt = GetAssocState(ext); + WMSG3("SetFileAssoc: ext='%s' own=%d want=%d\n", ext, weOwnIt, wantIt); - if (weOwnIt && !wantIt) { - /* reset it */ - WMSG1(" SetFileAssoc: clearing '%s'\n", ext); - result = DisownExtension(ext); - } else if (!weOwnIt && wantIt) { - /* take it */ - WMSG1(" SetFileAssoc: taking '%s'\n", ext); - result = OwnExtension(ext, kFileTypeAssoc[idx].appID); - } else { - WMSG1(" SetFileAssoc: do nothing with '%s'\n", ext); - /* do nothing */ - } + if (weOwnIt && !wantIt) { + /* reset it */ + WMSG1(" SetFileAssoc: clearing '%s'\n", ext); + result = DisownExtension(ext); + } else if (!weOwnIt && wantIt) { + /* take it */ + WMSG1(" SetFileAssoc: taking '%s'\n", ext); + result = OwnExtension(ext, kFileTypeAssoc[idx].appID); + } else { + WMSG1(" SetFileAssoc: do nothing with '%s'\n", ext); + /* do nothing */ + } - return 0; + return 0; } /* @@ -568,26 +568,26 @@ MyRegistry::SetFileAssoc(int idx, bool wantIt) const bool MyRegistry::GetAssocState(const char* ext) const { - unsigned char buf[260]; - HKEY hExtKey = nil; - DWORD type, size; - int res; - bool result = false; + unsigned char buf[260]; + HKEY hExtKey = nil; + DWORD type, size; + int res; + bool result = false; - res = RegOpenKeyEx(HKEY_CLASSES_ROOT, ext, 0, KEY_READ, &hExtKey); - if (res == ERROR_SUCCESS) { - size = sizeof(buf); - res = RegQueryValueEx(hExtKey, "", nil, &type, buf, &size); - if (res == ERROR_SUCCESS && type == REG_SZ) { - /* compare it to known appID values */ - WMSG2(" Found '%s', testing '%s'\n", ext, buf); - if (IsOurAppID((char*)buf)) - result = true; - } - } + res = RegOpenKeyEx(HKEY_CLASSES_ROOT, ext, 0, KEY_READ, &hExtKey); + if (res == ERROR_SUCCESS) { + size = sizeof(buf); + res = RegQueryValueEx(hExtKey, "", nil, &type, buf, &size); + if (res == ERROR_SUCCESS && type == REG_SZ) { + /* compare it to known appID values */ + WMSG2(" Found '%s', testing '%s'\n", ext, buf); + if (IsOurAppID((char*)buf)) + result = true; + } + } - RegCloseKey(hExtKey); - return result; + RegCloseKey(hExtKey); + return result; } /* @@ -600,19 +600,19 @@ MyRegistry::GetAssocState(const char* ext) const int MyRegistry::DisownExtension(const char* ext) const { - ASSERT(ext != nil); - ASSERT(ext[0] == '.'); - if (ext == nil || strlen(ext) < 2) - return -1; + ASSERT(ext != nil); + ASSERT(ext[0] == '.'); + if (ext == nil || strlen(ext) < 2) + return -1; - if (RegDeleteKeyNT(HKEY_CLASSES_ROOT, ext) == ERROR_SUCCESS) { - WMSG1(" HKCR\\%s subtree deleted\n", ext); - } else { - WMSG1(" Failed deleting HKCR\\'%s'\n", ext); - return -1; - } + if (RegDeleteKeyNT(HKEY_CLASSES_ROOT, ext) == ERROR_SUCCESS) { + WMSG1(" HKCR\\%s subtree deleted\n", ext); + } else { + WMSG1(" Failed deleting HKCR\\'%s'\n", ext); + return -1; + } - return 0; + return 0; } /* @@ -623,45 +623,45 @@ MyRegistry::DisownExtension(const char* ext) const int MyRegistry::OwnExtension(const char* ext, const char* appID) const { - ASSERT(ext != nil); - ASSERT(ext[0] == '.'); - if (ext == nil || strlen(ext) < 2) - return -1; + ASSERT(ext != nil); + ASSERT(ext[0] == '.'); + if (ext == nil || strlen(ext) < 2) + return -1; - HKEY hExtKey = nil; - DWORD dw; - int res, result = -1; + HKEY hExtKey = nil; + DWORD dw; + int res, result = -1; - /* delete the old key (which might be a hierarchy) */ - res = RegDeleteKeyNT(HKEY_CLASSES_ROOT, ext); - if (res == ERROR_SUCCESS) { - WMSG1(" HKCR\\%s subtree deleted\n", ext); - } else if (res == ERROR_FILE_NOT_FOUND) { - WMSG1(" No HKCR\\%s subtree to delete\n", ext); - } else { - WMSG1(" Failed deleting HKCR\\'%s'\n", ext); - goto bail; - } + /* delete the old key (which might be a hierarchy) */ + res = RegDeleteKeyNT(HKEY_CLASSES_ROOT, ext); + if (res == ERROR_SUCCESS) { + WMSG1(" HKCR\\%s subtree deleted\n", ext); + } else if (res == ERROR_FILE_NOT_FOUND) { + WMSG1(" No HKCR\\%s subtree to delete\n", ext); + } else { + WMSG1(" Failed deleting HKCR\\'%s'\n", ext); + goto bail; + } - /* set the new key */ - if (RegCreateKeyEx(HKEY_CLASSES_ROOT, ext, 0, REG_NONE, - REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, - &hExtKey, &dw) == ERROR_SUCCESS) - { - res = RegSetValueEx(hExtKey, "", 0, REG_SZ, - (const unsigned char*) appID, strlen(appID)); - if (res == ERROR_SUCCESS) { - WMSG2(" Set '%s' to '%s'\n", ext, appID); - result = 0; - } else { - WMSG3("Failed setting '%s' to '%s' (res=%d)\n", ext, appID, res); - goto bail; - } - } + /* set the new key */ + if (RegCreateKeyEx(HKEY_CLASSES_ROOT, ext, 0, REG_NONE, + REG_OPTION_NON_VOLATILE, KEY_WRITE|KEY_READ, NULL, + &hExtKey, &dw) == ERROR_SUCCESS) + { + res = RegSetValueEx(hExtKey, "", 0, REG_SZ, + (const unsigned char*) appID, strlen(appID)); + if (res == ERROR_SUCCESS) { + WMSG2(" Set '%s' to '%s'\n", ext, appID); + result = 0; + } else { + WMSG3("Failed setting '%s' to '%s' (res=%d)\n", ext, appID, res); + goto bail; + } + } bail: - RegCloseKey(hExtKey); - return result; + RegCloseKey(hExtKey); + return result; } @@ -674,50 +674,50 @@ bail: // without error by another application in both Windows 95 and // Windows NT. This is by design. // -#define MAX_KEY_LENGTH 256 // not in any header I can find ++ATM +#define MAX_KEY_LENGTH 256 // not in any header I can find ++ATM DWORD MyRegistry::RegDeleteKeyNT(HKEY hStartKey, LPCTSTR pKeyName) const { - DWORD dwRtn, dwSubKeyLength; - LPTSTR pSubKey = NULL; - TCHAR szSubKey[MAX_KEY_LENGTH]; // (256) this should be dynamic. - HKEY hKey; - - // Do not allow NULL or empty key name - if ( pKeyName && lstrlen(pKeyName)) - { - if( (dwRtn=RegOpenKeyEx(hStartKey,pKeyName, - 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &hKey )) == ERROR_SUCCESS) - { - while (dwRtn == ERROR_SUCCESS ) - { - dwSubKeyLength = MAX_KEY_LENGTH; - dwRtn=RegEnumKeyEx( - hKey, - 0, // always index zero, because we're deleting it - szSubKey, - &dwSubKeyLength, - NULL, - NULL, - NULL, - NULL - ); - - if(dwRtn == ERROR_NO_MORE_ITEMS) - { - dwRtn = RegDeleteKey(hStartKey, pKeyName); - break; - } - else if(dwRtn == ERROR_SUCCESS) - dwRtn=RegDeleteKeyNT(hKey, szSubKey); - } - RegCloseKey(hKey); - // Do not save return code because error - // has already occurred - } - } - else - dwRtn = ERROR_BADKEY; - - return dwRtn; + DWORD dwRtn, dwSubKeyLength; + LPTSTR pSubKey = NULL; + TCHAR szSubKey[MAX_KEY_LENGTH]; // (256) this should be dynamic. + HKEY hKey; + + // Do not allow NULL or empty key name + if ( pKeyName && lstrlen(pKeyName)) + { + if( (dwRtn=RegOpenKeyEx(hStartKey,pKeyName, + 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &hKey )) == ERROR_SUCCESS) + { + while (dwRtn == ERROR_SUCCESS ) + { + dwSubKeyLength = MAX_KEY_LENGTH; + dwRtn=RegEnumKeyEx( + hKey, + 0, // always index zero, because we're deleting it + szSubKey, + &dwSubKeyLength, + NULL, + NULL, + NULL, + NULL + ); + + if(dwRtn == ERROR_NO_MORE_ITEMS) + { + dwRtn = RegDeleteKey(hStartKey, pKeyName); + break; + } + else if(dwRtn == ERROR_SUCCESS) + dwRtn=RegDeleteKeyNT(hKey, szSubKey); + } + RegCloseKey(hKey); + // Do not save return code because error + // has already occurred + } + } + else + dwRtn = ERROR_BADKEY; + + return dwRtn; } diff --git a/app/Registry.h b/app/Registry.h index 42540a4..c83b90c 100644 --- a/app/Registry.h +++ b/app/Registry.h @@ -16,70 +16,70 @@ */ class MyRegistry { public: - MyRegistry(void) {} - ~MyRegistry(void) {} + MyRegistry(void) {} + ~MyRegistry(void) {} - typedef enum RegStatus { - kRegUnknown = 0, - kRegNotSet, // unregistered - kRegExpired, // unregistered, expired - kRegValid, // registration present and valid - kRegInvalid, // registration present, but invalid (!) - kRegFailed, // error occurred during registration - } RegStatus; + typedef enum RegStatus { + kRegUnknown = 0, + kRegNotSet, // unregistered + kRegExpired, // unregistered, expired + kRegValid, // registration present and valid + kRegInvalid, // registration present, but invalid (!) + kRegFailed, // error occurred during registration + } RegStatus; - void OneTimeInstall(void) const; - void OneTimeUninstall(void) const; + void OneTimeInstall(void) const; + void OneTimeUninstall(void) const; - /* - int GetRegistration(CString* pUser, CString* pCompany, - CString* pReg, CString* pVersions, CString* pExpire); - int SetRegistration(const CString& user, const CString& company, - const CString& reg, const CString& versions, const CString& expire); - RegStatus CheckRegistration(CString* pResult); - bool IsValidRegistrationKey(const CString& user, - const CString& company, const CString& reg); - */ + /* + int GetRegistration(CString* pUser, CString* pCompany, + CString* pReg, CString* pVersions, CString* pExpire); + int SetRegistration(const CString& user, const CString& company, + const CString& reg, const CString& versions, const CString& expire); + RegStatus CheckRegistration(CString* pResult); + bool IsValidRegistrationKey(const CString& user, + const CString& company, const CString& reg); + */ - // Get the registry key to be used for our application. - const char* GetAppRegistryKey(void) const; + // Get the registry key to be used for our application. + const char* GetAppRegistryKey(void) const; - // Fix basic settings, e.g. HKCR AppID classes. - void FixBasicSettings(void) const; + // Fix basic settings, e.g. HKCR AppID classes. + void FixBasicSettings(void) const; - int GetNumFileAssocs(void) const; - void GetFileAssoc(int idx, CString* pExt, CString* pHandler, - bool* pOurs) const; - int SetFileAssoc(int idx, bool wantIt) const; + int GetNumFileAssocs(void) const; + void GetFileAssoc(int idx, CString* pExt, CString* pHandler, + bool* pOurs) const; + int SetFileAssoc(int idx, bool wantIt) const; - static unsigned short ComputeStringCRC(const char* str); + static unsigned short ComputeStringCRC(const char* str); private: - typedef struct FileTypeAssoc { - const char* ext; // e.g. ".SHK" - const char* appID; // e.g. "CiderPress.NuFX" - } FileTypeAssoc; + typedef struct FileTypeAssoc { + const char* ext; // e.g. ".SHK" + const char* appID; // e.g. "CiderPress.NuFX" + } FileTypeAssoc; - static const FileTypeAssoc kFileTypeAssoc[]; + static const FileTypeAssoc kFileTypeAssoc[]; - bool IsOurAppID(const char* id) const; - void ConfigureAppID(const char* appID, const char* descr, - const char* exeName, int iconIdx) const; - void ConfigureAppIDSubFields(HKEY hAppKey, const char* descr, - const char* exeName) const; - int GetAssocAppName(const CString& appID, CString* pCmd) const; - void ReduceToToken(CString* pStr) const; - bool GetAssocState(const char* ext) const; - int DisownExtension(const char* ext) const; - int OwnExtension(const char* ext, const char* appID) const; - DWORD RegDeleteKeyNT(HKEY hStartKey, LPCTSTR pKeyName) const; + bool IsOurAppID(const char* id) const; + void ConfigureAppID(const char* appID, const char* descr, + const char* exeName, int iconIdx) const; + void ConfigureAppIDSubFields(HKEY hAppKey, const char* descr, + const char* exeName) const; + int GetAssocAppName(const CString& appID, CString* pCmd) const; + void ReduceToToken(CString* pStr) const; + bool GetAssocState(const char* ext) const; + int DisownExtension(const char* ext) const; + int OwnExtension(const char* ext, const char* appID) const; + DWORD RegDeleteKeyNT(HKEY hStartKey, LPCTSTR pKeyName) const; - /* key validation */ - static unsigned short CalcCRC16(unsigned short seed, - const unsigned char* ptr, int count); - static char* StripStrings(const char* str1, const char* str2); - void ComputeKey(const char* chBuf, int salt, long* pKeyLo, long* pKeyHi); - int VerifyKey(const char* user, const char* company, const char* key); + /* key validation */ + static unsigned short CalcCRC16(unsigned short seed, + const unsigned char* ptr, int count); + static char* StripStrings(const char* str1, const char* str2); + void ComputeKey(const char* chBuf, int salt, long* pKeyLo, long* pKeyHi); + int VerifyKey(const char* user, const char* company, const char* key); }; #endif /*__REGISTRY__*/ \ No newline at end of file diff --git a/app/RenameEntryDialog.cpp b/app/RenameEntryDialog.cpp index 297a690..ac7c8a2 100644 --- a/app/RenameEntryDialog.cpp +++ b/app/RenameEntryDialog.cpp @@ -11,9 +11,9 @@ #include "HelpTopics.h" BEGIN_MESSAGE_MAP(RenameEntryDialog, CDialog) - ON_WM_HELPINFO() - ON_COMMAND(IDHELP, OnHelp) - ON_BN_CLICKED(IDC_RENAME_SKIP, OnSkip) + ON_WM_HELPINFO() + ON_COMMAND(IDHELP, OnHelp) + ON_BN_CLICKED(IDC_RENAME_SKIP, OnSkip) END_MESSAGE_MAP() @@ -23,43 +23,43 @@ END_MESSAGE_MAP() BOOL RenameEntryDialog::OnInitDialog(void) { - ASSERT(fBasePath.IsEmpty()); - fOldFile = fOldName; - fFssepStr = fFssep; + ASSERT(fBasePath.IsEmpty()); + fOldFile = fOldName; + fFssepStr = fFssep; - CEdit* pEdit = (CEdit*) GetDlgItem(IDC_RENAME_PATHSEP); - pEdit->SetReadOnly(!fCanChangeFssep); - pEdit->LimitText(1); + CEdit* pEdit = (CEdit*) GetDlgItem(IDC_RENAME_PATHSEP); + pEdit->SetReadOnly(!fCanChangeFssep); + pEdit->LimitText(1); - /* if they can't rename the full path, only give them the file name */ - if (fCanRenameFullPath || fFssep == '\0') { - fNewName = fOldName; - // fBasePath is empty - } else { - int offset; + /* if they can't rename the full path, only give them the file name */ + if (fCanRenameFullPath || fFssep == '\0') { + fNewName = fOldName; + // fBasePath is empty + } else { + int offset; - offset = fOldName.ReverseFind(fFssep); - if (offset < fOldName.GetLength()) { - fBasePath = fOldName.Left(offset); - fNewName = fOldName.Right(fOldName.GetLength() - (offset+1)); - } else { - /* weird -- filename ended with an fssep? */ - ASSERT(false); // debugbreak - // fBasePath is empty - fNewName = fOldName; - } - } + offset = fOldName.ReverseFind(fFssep); + if (offset < fOldName.GetLength()) { + fBasePath = fOldName.Left(offset); + fNewName = fOldName.Right(fOldName.GetLength() - (offset+1)); + } else { + /* weird -- filename ended with an fssep? */ + ASSERT(false); // debugbreak + // fBasePath is empty + fNewName = fOldName; + } + } - /* do the DoDataExchange stuff */ - CDialog::OnInitDialog(); + /* do the DoDataExchange stuff */ + CDialog::OnInitDialog(); - /* select the editable text and set the focus */ - pEdit = (CEdit*) GetDlgItem(IDC_RENAME_NEW); - ASSERT(pEdit != nil); - pEdit->SetSel(0, -1); - pEdit->SetFocus(); + /* select the editable text and set the focus */ + pEdit = (CEdit*) GetDlgItem(IDC_RENAME_NEW); + ASSERT(pEdit != nil); + pEdit->SetSel(0, -1); + pEdit->SetFocus(); - return FALSE; // we set the focus + return FALSE; // we set the focus } /* @@ -68,41 +68,41 @@ RenameEntryDialog::OnInitDialog(void) void RenameEntryDialog::DoDataExchange(CDataExchange* pDX) { - CString msg, failed; + CString msg, failed; - msg = ""; - failed.LoadString(IDS_MB_APP_NAME); + msg = ""; + failed.LoadString(IDS_MB_APP_NAME); - /* fNewName must come last, or the focus will be set on the wrong field - when we return after failure */ - DDX_Text(pDX, IDC_RENAME_OLD, fOldFile); - DDX_Text(pDX, IDC_RENAME_PATHSEP, fFssepStr); - DDX_Text(pDX, IDC_RENAME_NEW, fNewName); + /* fNewName must come last, or the focus will be set on the wrong field + when we return after failure */ + DDX_Text(pDX, IDC_RENAME_OLD, fOldFile); + DDX_Text(pDX, IDC_RENAME_PATHSEP, fFssepStr); + DDX_Text(pDX, IDC_RENAME_NEW, fNewName); - /* validate the path field */ - if (pDX->m_bSaveAndValidate) { - if (fNewName.IsEmpty()) { - msg = "You must specify a new name."; - goto fail; - } + /* validate the path field */ + if (pDX->m_bSaveAndValidate) { + if (fNewName.IsEmpty()) { + msg = "You must specify a new name."; + goto fail; + } - msg = fpArchive->TestPathName(fpEntry, fBasePath, fNewName, fFssep); - if (!msg.IsEmpty()) - goto fail; + msg = fpArchive->TestPathName(fpEntry, fBasePath, fNewName, fFssep); + if (!msg.IsEmpty()) + goto fail; - if (fFssepStr.IsEmpty()) - fFssep = '\0'; - else - fFssep = fFssepStr.GetAt(0); // could be '\0', that's okay - } + if (fFssepStr.IsEmpty()) + fFssep = '\0'; + else + fFssep = fFssepStr.GetAt(0); // could be '\0', that's okay + } - return; + return; fail: - ASSERT(!msg.IsEmpty()); - MessageBox(msg, failed, MB_OK); - pDX->Fail(); - return; + ASSERT(!msg.IsEmpty()); + MessageBox(msg, failed, MB_OK); + pDX->Fail(); + return; } /* @@ -112,7 +112,7 @@ fail: void RenameEntryDialog::OnSkip(void) { - EndDialog(IDIGNORE); + EndDialog(IDIGNORE); } /* @@ -121,8 +121,8 @@ RenameEntryDialog::OnSkip(void) BOOL RenameEntryDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* @@ -131,5 +131,5 @@ RenameEntryDialog::OnHelpInfo(HELPINFO* lpHelpInfo) void RenameEntryDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_RENAME_ENTRY, HELP_CONTEXT); + WinHelp(HELP_TOPIC_RENAME_ENTRY, HELP_CONTEXT); } diff --git a/app/RenameEntryDialog.h b/app/RenameEntryDialog.h index d2d221d..e414a2b 100644 --- a/app/RenameEntryDialog.h +++ b/app/RenameEntryDialog.h @@ -25,46 +25,46 @@ */ class RenameEntryDialog : public CDialog { public: - RenameEntryDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_RENAME_ENTRY, pParentWnd) - { - fFssep = '='; - //fNewNameLimit = 0; - fpArchive = nil; - fpEntry = nil; - fCanRenameFullPath = false; - fCanChangeFssep = false; - } - virtual ~RenameEntryDialog(void) {} + RenameEntryDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_RENAME_ENTRY, pParentWnd) + { + fFssep = '='; + //fNewNameLimit = 0; + fpArchive = nil; + fpEntry = nil; + fCanRenameFullPath = false; + fCanChangeFssep = false; + } + virtual ~RenameEntryDialog(void) {} - void SetCanRenameFullPath(bool val) { fCanRenameFullPath = val; } - void SetCanChangeFssep(bool val) { fCanChangeFssep = val; } + void SetCanRenameFullPath(bool val) { fCanRenameFullPath = val; } + void SetCanChangeFssep(bool val) { fCanChangeFssep = val; } - CString fOldName; - char fFssep; - CString fNewName; - //int fNewNameLimit; // max #of chars accepted, or 0 - const GenericArchive* fpArchive; - const GenericEntry* fpEntry; + CString fOldName; + char fFssep; + CString fNewName; + //int fNewNameLimit; // max #of chars accepted, or 0 + const GenericArchive* fpArchive; + const GenericEntry* fpEntry; protected: - // overrides - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + // overrides + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - afx_msg void OnSkip(void); - afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - afx_msg void OnHelp(void); + afx_msg void OnSkip(void); + afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg void OnHelp(void); private: - //CString fOldPath; // pathname component, or empty if canRenFull - CString fOldFile; // filename component, or full name if ^^^ - CString fBasePath; - CString fFssepStr; - bool fCanRenameFullPath; - bool fCanChangeFssep; + //CString fOldPath; // pathname component, or empty if canRenFull + CString fOldFile; // filename component, or full name if ^^^ + CString fBasePath; + CString fFssepStr; + bool fCanRenameFullPath; + bool fCanChangeFssep; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__RENAMEENTRYDIALOG__*/ diff --git a/app/RenameVolumeDialog.cpp b/app/RenameVolumeDialog.cpp index eddd436..e3b7c38 100644 --- a/app/RenameVolumeDialog.cpp +++ b/app/RenameVolumeDialog.cpp @@ -20,9 +20,9 @@ #include "HelpTopics.h" BEGIN_MESSAGE_MAP(RenameVolumeDialog, CDialog) - ON_NOTIFY(TVN_SELCHANGED, IDC_RENAMEVOL_TREE, OnSelChanged) - ON_BN_CLICKED(IDHELP, OnHelp) - ON_WM_HELPINFO() + ON_NOTIFY(TVN_SELCHANGED, IDC_RENAMEVOL_TREE, OnSelChanged) + ON_BN_CLICKED(IDHELP, OnHelp) + ON_WM_HELPINFO() END_MESSAGE_MAP() /* @@ -31,31 +31,31 @@ END_MESSAGE_MAP() BOOL RenameVolumeDialog::OnInitDialog(void) { - /* do the DoDataExchange stuff */ - CDialog::OnInitDialog(); + /* do the DoDataExchange stuff */ + CDialog::OnInitDialog(); - CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_RENAMEVOL_TREE); - DiskImgLib::DiskFS* pDiskFS = fpArchive->GetDiskFS(); + CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_RENAMEVOL_TREE); + DiskImgLib::DiskFS* pDiskFS = fpArchive->GetDiskFS(); - ASSERT(pTree != nil); + ASSERT(pTree != nil); - fDiskFSTree.fIncludeSubdirs = false; - fDiskFSTree.fExpandDepth = -1; - if (!fDiskFSTree.BuildTree(pDiskFS, pTree)) { - WMSG0("Tree load failed!\n"); - OnCancel(); - } + fDiskFSTree.fIncludeSubdirs = false; + fDiskFSTree.fExpandDepth = -1; + if (!fDiskFSTree.BuildTree(pDiskFS, pTree)) { + WMSG0("Tree load failed!\n"); + OnCancel(); + } - int count = pTree->GetCount(); - WMSG1("ChooseAddTargetDialog tree has %d items\n", count); + int count = pTree->GetCount(); + WMSG1("ChooseAddTargetDialog tree has %d items\n", count); - /* select the default text and set the focus */ - CEdit* pEdit = (CEdit*) GetDlgItem(IDC_RENAMEVOL_NEW); - ASSERT(pEdit != nil); - pEdit->SetSel(0, -1); - pEdit->SetFocus(); + /* select the default text and set the focus */ + CEdit* pEdit = (CEdit*) GetDlgItem(IDC_RENAMEVOL_NEW); + ASSERT(pEdit != nil); + pEdit->SetSel(0, -1); + pEdit->SetFocus(); - return FALSE; // we set the focus + return FALSE; // we set the focus } /* @@ -64,70 +64,70 @@ RenameVolumeDialog::OnInitDialog(void) void RenameVolumeDialog::DoDataExchange(CDataExchange* pDX) { - CString msg, failed; - //DiskImgLib::DiskFS* pDiskFS = fpArchive->GetDiskFS(); + CString msg, failed; + //DiskImgLib::DiskFS* pDiskFS = fpArchive->GetDiskFS(); - msg = ""; - failed.LoadString(IDS_MB_APP_NAME); + msg = ""; + failed.LoadString(IDS_MB_APP_NAME); - /* put fNewName last so it gets the focus after failure */ - DDX_Text(pDX, IDC_RENAMEVOL_NEW, fNewName); + /* put fNewName last so it gets the focus after failure */ + DDX_Text(pDX, IDC_RENAMEVOL_NEW, fNewName); - /* validate the path field */ - if (pDX->m_bSaveAndValidate) { - /* - * Make sure they chose a volume that can be modified. - */ - CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_RENAMEVOL_TREE); - CString errMsg, appName; - appName.LoadString(IDS_MB_APP_NAME); + /* validate the path field */ + if (pDX->m_bSaveAndValidate) { + /* + * Make sure they chose a volume that can be modified. + */ + CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_RENAMEVOL_TREE); + CString errMsg, appName; + appName.LoadString(IDS_MB_APP_NAME); - HTREEITEM selected; - selected = pTree->GetSelectedItem(); - if (selected == nil) { - errMsg = "Please select a disk to rename."; - MessageBox(errMsg, appName, MB_OK); - pDX->Fail(); - return; - } + HTREEITEM selected; + selected = pTree->GetSelectedItem(); + if (selected == nil) { + errMsg = "Please select a disk to rename."; + MessageBox(errMsg, appName, MB_OK); + pDX->Fail(); + return; + } - DiskFSTree::TargetData* pTargetData; - pTargetData = (DiskFSTree::TargetData*) pTree->GetItemData(selected); - if (!pTargetData->selectable) { - errMsg = "You can't rename that volume."; - MessageBox(errMsg, appName, MB_OK); - pDX->Fail(); - return; - } - ASSERT(pTargetData->kind == DiskFSTree::kTargetDiskFS); + DiskFSTree::TargetData* pTargetData; + pTargetData = (DiskFSTree::TargetData*) pTree->GetItemData(selected); + if (!pTargetData->selectable) { + errMsg = "You can't rename that volume."; + MessageBox(errMsg, appName, MB_OK); + pDX->Fail(); + return; + } + ASSERT(pTargetData->kind == DiskFSTree::kTargetDiskFS); - /* - * Verify that the new name is okay. (Do this *after* checking the - * volume above to avoid spurious complaints about unsupported - * filesystems.) - */ - if (fNewName.IsEmpty()) { - msg = "You must specify a new name."; - goto fail; - } - msg = fpArchive->TestVolumeName(pTargetData->pDiskFS, fNewName); - if (!msg.IsEmpty()) - goto fail; + /* + * Verify that the new name is okay. (Do this *after* checking the + * volume above to avoid spurious complaints about unsupported + * filesystems.) + */ + if (fNewName.IsEmpty()) { + msg = "You must specify a new name."; + goto fail; + } + msg = fpArchive->TestVolumeName(pTargetData->pDiskFS, fNewName); + if (!msg.IsEmpty()) + goto fail; - /* - * Looks good. Fill in the answer. - */ - fpChosenDiskFS = pTargetData->pDiskFS; - } + /* + * Looks good. Fill in the answer. + */ + fpChosenDiskFS = pTargetData->pDiskFS; + } - return; + return; fail: - ASSERT(!msg.IsEmpty()); - MessageBox(msg, failed, MB_OK); - pDX->Fail(); - return; + ASSERT(!msg.IsEmpty()); + MessageBox(msg, failed, MB_OK); + pDX->Fail(); + return; } /* @@ -137,27 +137,27 @@ fail: void RenameVolumeDialog::OnSelChanged(NMHDR* pnmh, LRESULT* pResult) { - CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_RENAMEVOL_TREE); - HTREEITEM selected; - CString newText; + CTreeCtrl* pTree = (CTreeCtrl*) GetDlgItem(IDC_RENAMEVOL_TREE); + HTREEITEM selected; + CString newText; - selected = pTree->GetSelectedItem(); - if (selected != nil) { - DiskFSTree::TargetData* pTargetData; - pTargetData = (DiskFSTree::TargetData*) pTree->GetItemData(selected); - if (pTargetData->selectable) { - newText = pTargetData->pDiskFS->GetBareVolumeName(); - } else { - newText = ""; - } - } - - CEdit* pEdit = (CEdit*) GetDlgItem(IDC_RENAMEVOL_NEW); - ASSERT(pEdit != nil); - pEdit->SetWindowText(newText); - pEdit->SetSel(0, -1); + selected = pTree->GetSelectedItem(); + if (selected != nil) { + DiskFSTree::TargetData* pTargetData; + pTargetData = (DiskFSTree::TargetData*) pTree->GetItemData(selected); + if (pTargetData->selectable) { + newText = pTargetData->pDiskFS->GetBareVolumeName(); + } else { + newText = ""; + } + } + + CEdit* pEdit = (CEdit*) GetDlgItem(IDC_RENAMEVOL_NEW); + ASSERT(pEdit != nil); + pEdit->SetWindowText(newText); + pEdit->SetSel(0, -1); - *pResult = 0; + *pResult = 0; } /* @@ -166,8 +166,8 @@ RenameVolumeDialog::OnSelChanged(NMHDR* pnmh, LRESULT* pResult) BOOL RenameVolumeDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } /* @@ -176,5 +176,5 @@ RenameVolumeDialog::OnHelpInfo(HELPINFO* lpHelpInfo) void RenameVolumeDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_RENAME_VOLUME, HELP_CONTEXT); + WinHelp(HELP_TOPIC_RENAME_VOLUME, HELP_CONTEXT); } diff --git a/app/RenameVolumeDialog.h b/app/RenameVolumeDialog.h index 520e7a6..9f13bf5 100644 --- a/app/RenameVolumeDialog.h +++ b/app/RenameVolumeDialog.h @@ -20,31 +20,31 @@ class DiskArchive; */ class RenameVolumeDialog : public CDialog { public: - RenameVolumeDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_RENAME_VOLUME, pParentWnd) - { - fpArchive = nil; - } - virtual ~RenameVolumeDialog(void) {} + RenameVolumeDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_RENAME_VOLUME, pParentWnd) + { + fpArchive = nil; + } + virtual ~RenameVolumeDialog(void) {} - const DiskArchive* fpArchive; - CString fNewName; - DiskImgLib::DiskFS* fpChosenDiskFS; + const DiskArchive* fpArchive; + CString fNewName; + DiskImgLib::DiskFS* fpChosenDiskFS; protected: - // overrides - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + // overrides + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - afx_msg void OnSelChanged(NMHDR* pnmh, LRESULT* pResult); - afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - afx_msg void OnHelp(void); + afx_msg void OnSelChanged(NMHDR* pnmh, LRESULT* pResult); + afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg void OnHelp(void); - DiskFSTree fDiskFSTree; + DiskFSTree fDiskFSTree; private: - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__RENAMEVOLUME__*/ diff --git a/app/Squeeze.cpp b/app/Squeeze.cpp index ca5a6a9..6d61345 100644 --- a/app/Squeeze.cpp +++ b/app/Squeeze.cpp @@ -15,17 +15,17 @@ #include "Squeeze.h" #include "NufxArchive.h" -#define kSqBufferSize 8192 /* must hold full SQ header, and % 128 */ +#define kSqBufferSize 8192 /* must hold full SQ header, and % 128 */ -#define kNuSQMagic 0xff76 /* magic value for file header */ -#define kNuSQRLEDelim 0x90 /* RLE delimiter */ -#define kNuSQEOFToken 256 /* distinguished stop symbol */ -#define kNuSQNumVals 257 /* 256 symbols + stop */ +#define kNuSQMagic 0xff76 /* magic value for file header */ +#define kNuSQRLEDelim 0x90 /* RLE delimiter */ +#define kNuSQEOFToken 256 /* distinguished stop symbol */ +#define kNuSQNumVals 257 /* 256 symbols + stop */ /* * =========================================================================== - * Unsqueeze + * Unsqueeze * =========================================================================== */ @@ -33,20 +33,20 @@ * State during uncompression. */ typedef struct USQState { - unsigned long dataInBuffer; - unsigned char* dataPtr; - int bitPosn; - int bits; + unsigned long dataInBuffer; + unsigned char* dataPtr; + int bitPosn; + int bits; - /* - * Decoding tree; first "nodeCount" values are populated. Positive - * values are indices to another node in the tree, negative values - * are literals (+1 because "negative zero" doesn't work well). - */ - int nodeCount; - struct { - short child[2]; /* left/right kids, must be signed 16-bit */ - } decTree[kNuSQNumVals-1]; + /* + * Decoding tree; first "nodeCount" values are populated. Positive + * values are indices to another node in the tree, negative values + * are literals (+1 because "negative zero" doesn't work well). + */ + int nodeCount; + struct { + short child[2]; /* left/right kids, must be signed 16-bit */ + } decTree[kNuSQNumVals-1]; } USQState; @@ -56,34 +56,34 @@ typedef struct USQState { static NuError USQDecodeHuffSymbol(USQState* pUsqState, int* pVal) { - short val = 0; - int bits, bitPosn; + short val = 0; + int bits, bitPosn; - bits = pUsqState->bits; /* local copy */ - bitPosn = pUsqState->bitPosn; + bits = pUsqState->bits; /* local copy */ + bitPosn = pUsqState->bitPosn; - do { - if (++bitPosn > 7) { - /* grab the next byte and use that */ - bits = *pUsqState->dataPtr++; - bitPosn = 0; - if (!pUsqState->dataInBuffer--) - return kNuErrBufferUnderrun; + do { + if (++bitPosn > 7) { + /* grab the next byte and use that */ + bits = *pUsqState->dataPtr++; + bitPosn = 0; + if (!pUsqState->dataInBuffer--) + return kNuErrBufferUnderrun; - val = pUsqState->decTree[val].child[1 & bits]; - } else { - /* still got bits; shift right and use it */ - val = pUsqState->decTree[val].child[1 & (bits >>= 1)]; - } - } while (val >= 0); + val = pUsqState->decTree[val].child[1 & bits]; + } else { + /* still got bits; shift right and use it */ + val = pUsqState->decTree[val].child[1 & (bits >>= 1)]; + } + } while (val >= 0); - /* val is negative literal; add one to make it zero-based then negate it */ - *pVal = -(val + 1); + /* val is negative literal; add one to make it zero-based then negate it */ + *pVal = -(val + 1); - pUsqState->bits = bits; - pUsqState->bitPosn = bitPosn; + pUsqState->bits = bits; + pUsqState->bitPosn = bitPosn; - return kNuErrNone; + return kNuErrNone; } @@ -93,14 +93,14 @@ USQDecodeHuffSymbol(USQState* pUsqState, int* pVal) static inline NuError USQReadShort(USQState* pUsqState, short* pShort) { - if (pUsqState->dataInBuffer < 2) - return kNuErrBufferUnderrun; + if (pUsqState->dataInBuffer < 2) + return kNuErrBufferUnderrun; - *pShort = *pUsqState->dataPtr++; - *pShort |= (*pUsqState->dataPtr++) << 8; - pUsqState->dataInBuffer -= 2; + *pShort = *pUsqState->dataPtr++; + *pShort |= (*pUsqState->dataPtr++) << 8; + pUsqState->dataInBuffer -= 2; - return kNuErrNone; + return kNuErrNone; } /* @@ -110,17 +110,17 @@ USQReadShort(USQState* pUsqState, short* pShort) static NuError SQRead(FILE* fp, void* buf, size_t nbyte) { - size_t result; + size_t result; - ASSERT(buf != nil); - ASSERT(nbyte > 0); - ASSERT(fp != nil); + ASSERT(buf != nil); + ASSERT(nbyte > 0); + ASSERT(fp != nil); - errno = 0; - result = fread(buf, 1, nbyte, fp); - if (result != nbyte) - return errno ? (NuError)errno : kNuErrFileRead; - return kNuErrNone; + errno = 0; + result = fread(buf, 1, nbyte, fp); + if (result != nbyte) + return errno ? (NuError)errno : kNuErrFileRead; + return kNuErrNone; } @@ -134,278 +134,278 @@ SQRead(FILE* fp, void* buf, size_t nbyte) */ NuError UnSqueeze(FILE* fp, unsigned long realEOF, ExpandBuffer* outExp, - bool fullSqHeader, int blockSize) + bool fullSqHeader, int blockSize) { - NuError err = kNuErrNone; - USQState usqState; - unsigned long compRemaining, getSize; - unsigned short magic, fileChecksum, checksum; // fullSqHeader only - short nodeCount; - int i, inrep; - unsigned char* tmpBuf = nil; - unsigned char lastc = 0; + NuError err = kNuErrNone; + USQState usqState; + unsigned long compRemaining, getSize; + unsigned short magic, fileChecksum, checksum; // fullSqHeader only + short nodeCount; + int i, inrep; + unsigned char* tmpBuf = nil; + unsigned char lastc = 0; - tmpBuf = (unsigned char*) malloc(kSqBufferSize); - if (tmpBuf == nil) { - err = kNuErrMalloc; - goto bail; - } + tmpBuf = (unsigned char*) malloc(kSqBufferSize); + if (tmpBuf == nil) { + err = kNuErrMalloc; + goto bail; + } - usqState.dataInBuffer = 0; - usqState.dataPtr = tmpBuf; + usqState.dataInBuffer = 0; + usqState.dataPtr = tmpBuf; - compRemaining = realEOF; - if ((fullSqHeader && compRemaining < 8) || - (!fullSqHeader && compRemaining < 3)) - { - err = kNuErrBadData; - WMSG0("too short to be valid SQ data\n"); - goto bail; - } + compRemaining = realEOF; + if ((fullSqHeader && compRemaining < 8) || + (!fullSqHeader && compRemaining < 3)) + { + err = kNuErrBadData; + WMSG0("too short to be valid SQ data\n"); + goto bail; + } - /* - * Round up to the nearest 128-byte boundary. We need to read - * everything out of the file in case this is a streaming archive. - * Because the compressed data has an embedded stop symbol, it's okay - * to "overrun" the expansion code. - */ - if (blockSize != 0) { - compRemaining = - ((compRemaining + blockSize-1) / blockSize) * blockSize; - } + /* + * Round up to the nearest 128-byte boundary. We need to read + * everything out of the file in case this is a streaming archive. + * Because the compressed data has an embedded stop symbol, it's okay + * to "overrun" the expansion code. + */ + if (blockSize != 0) { + compRemaining = + ((compRemaining + blockSize-1) / blockSize) * blockSize; + } - /* want to grab up to kSqBufferSize bytes */ - if (compRemaining > kSqBufferSize) - getSize = kSqBufferSize; - else - getSize = compRemaining; + /* want to grab up to kSqBufferSize bytes */ + if (compRemaining > kSqBufferSize) + getSize = kSqBufferSize; + else + getSize = compRemaining; - /* - * Grab a big chunk. "compRemaining" is the amount of compressed - * data left in the file, usqState.dataInBuffer is the amount of - * compressed data left in the buffer. - * - * For BNY, we want to read 128-byte blocks. - */ - if (getSize) { - ASSERT(getSize <= kSqBufferSize); - err = SQRead(fp, usqState.dataPtr, getSize); - if (err != kNuErrNone) { - WMSG1("failed reading compressed data (%ld bytes)\n", getSize); - goto bail; - } - usqState.dataInBuffer += getSize; - if (getSize > compRemaining) - compRemaining = 0; - else - compRemaining -= getSize; - } + /* + * Grab a big chunk. "compRemaining" is the amount of compressed + * data left in the file, usqState.dataInBuffer is the amount of + * compressed data left in the buffer. + * + * For BNY, we want to read 128-byte blocks. + */ + if (getSize) { + ASSERT(getSize <= kSqBufferSize); + err = SQRead(fp, usqState.dataPtr, getSize); + if (err != kNuErrNone) { + WMSG1("failed reading compressed data (%ld bytes)\n", getSize); + goto bail; + } + usqState.dataInBuffer += getSize; + if (getSize > compRemaining) + compRemaining = 0; + else + compRemaining -= getSize; + } - /* reset dataPtr */ - usqState.dataPtr = tmpBuf; + /* reset dataPtr */ + usqState.dataPtr = tmpBuf; - /* - * Read the header. We assume that the header will fit in the - * compression buffer ( sq allowed 300+ for the filename, plus - * 257*2 for the tree, plus misc). - */ - ASSERT(kSqBufferSize > 1200); - if (fullSqHeader) { - err = USQReadShort(&usqState, (short*)&magic); - if (err != kNuErrNone) - goto bail; - if (magic != kNuSQMagic) { - err = kNuErrBadData; - WMSG0("bad magic number in SQ block\n"); - goto bail; - } + /* + * Read the header. We assume that the header will fit in the + * compression buffer ( sq allowed 300+ for the filename, plus + * 257*2 for the tree, plus misc). + */ + ASSERT(kSqBufferSize > 1200); + if (fullSqHeader) { + err = USQReadShort(&usqState, (short*)&magic); + if (err != kNuErrNone) + goto bail; + if (magic != kNuSQMagic) { + err = kNuErrBadData; + WMSG0("bad magic number in SQ block\n"); + goto bail; + } - err = USQReadShort(&usqState, (short*)&fileChecksum); - if (err != kNuErrNone) - goto bail; + err = USQReadShort(&usqState, (short*)&fileChecksum); + if (err != kNuErrNone) + goto bail; - checksum = 0; + checksum = 0; - /* skip over the filename */ - while (*usqState.dataPtr++ != '\0') - usqState.dataInBuffer--; - usqState.dataInBuffer--; - } + /* skip over the filename */ + while (*usqState.dataPtr++ != '\0') + usqState.dataInBuffer--; + usqState.dataInBuffer--; + } - err = USQReadShort(&usqState, &nodeCount); - if (err != kNuErrNone) - goto bail; - if (nodeCount < 0 || nodeCount >= kNuSQNumVals) { - err = kNuErrBadData; - WMSG1("invalid decode tree in SQ (%d nodes)\n", nodeCount); - goto bail; - } - usqState.nodeCount = nodeCount; + err = USQReadShort(&usqState, &nodeCount); + if (err != kNuErrNone) + goto bail; + if (nodeCount < 0 || nodeCount >= kNuSQNumVals) { + err = kNuErrBadData; + WMSG1("invalid decode tree in SQ (%d nodes)\n", nodeCount); + goto bail; + } + usqState.nodeCount = nodeCount; - /* initialize for possibly empty tree (only happens on an empty file) */ - usqState.decTree[0].child[0] = -(kNuSQEOFToken+1); - usqState.decTree[0].child[1] = -(kNuSQEOFToken+1); + /* initialize for possibly empty tree (only happens on an empty file) */ + usqState.decTree[0].child[0] = -(kNuSQEOFToken+1); + usqState.decTree[0].child[1] = -(kNuSQEOFToken+1); - /* read the nodes, ignoring "read errors" until we're done */ - for (i = 0; i < nodeCount; i++) { - err = USQReadShort(&usqState, &usqState.decTree[i].child[0]); - err = USQReadShort(&usqState, &usqState.decTree[i].child[1]); - } - if (err != kNuErrNone) { - err = kNuErrBadData; - WMSG0("SQ data looks truncated at tree\n"); - goto bail; - } + /* read the nodes, ignoring "read errors" until we're done */ + for (i = 0; i < nodeCount; i++) { + err = USQReadShort(&usqState, &usqState.decTree[i].child[0]); + err = USQReadShort(&usqState, &usqState.decTree[i].child[1]); + } + if (err != kNuErrNone) { + err = kNuErrBadData; + WMSG0("SQ data looks truncated at tree\n"); + goto bail; + } - usqState.bitPosn = 99; /* force an immediate read */ + usqState.bitPosn = 99; /* force an immediate read */ - /* - * Start pulling data out of the file. We have to Huffman-decode - * the input, and then feed that into an RLE expander. - * - * A completely lopsided (and broken) Huffman tree could require - * 256 tree descents, so we want to try to ensure we have at least 256 - * bits in the buffer. Otherwise, we could get a false buffer underrun - * indication back from DecodeHuffSymbol. - * - * The SQ sources actually guarantee that a code will fit entirely - * in 16 bits, but there's no reason not to use the larger value. - */ - inrep = false; - while (1) { - int val; + /* + * Start pulling data out of the file. We have to Huffman-decode + * the input, and then feed that into an RLE expander. + * + * A completely lopsided (and broken) Huffman tree could require + * 256 tree descents, so we want to try to ensure we have at least 256 + * bits in the buffer. Otherwise, we could get a false buffer underrun + * indication back from DecodeHuffSymbol. + * + * The SQ sources actually guarantee that a code will fit entirely + * in 16 bits, but there's no reason not to use the larger value. + */ + inrep = false; + while (1) { + int val; - if (usqState.dataInBuffer < 65 && compRemaining) { - /* - * Less than 256 bits, but there's more in the file. - * - * First thing we do is slide the old data to the start of - * the buffer. - */ - if (usqState.dataInBuffer) { - ASSERT(tmpBuf != usqState.dataPtr); - memmove(tmpBuf, usqState.dataPtr, usqState.dataInBuffer); - } - usqState.dataPtr = tmpBuf; + if (usqState.dataInBuffer < 65 && compRemaining) { + /* + * Less than 256 bits, but there's more in the file. + * + * First thing we do is slide the old data to the start of + * the buffer. + */ + if (usqState.dataInBuffer) { + ASSERT(tmpBuf != usqState.dataPtr); + memmove(tmpBuf, usqState.dataPtr, usqState.dataInBuffer); + } + usqState.dataPtr = tmpBuf; - /* - * Next we read as much as we can. - */ - if (kSqBufferSize - usqState.dataInBuffer < compRemaining) - getSize = kSqBufferSize - usqState.dataInBuffer; - else - getSize = compRemaining; + /* + * Next we read as much as we can. + */ + if (kSqBufferSize - usqState.dataInBuffer < compRemaining) + getSize = kSqBufferSize - usqState.dataInBuffer; + else + getSize = compRemaining; - ASSERT(getSize <= kSqBufferSize); - //WMSG2("Reading from offset=%ld (compRem=%ld)\n", - // ftell(fp), compRemaining); - err = SQRead(fp, usqState.dataPtr + usqState.dataInBuffer, - getSize); - if (err != kNuErrNone) { - WMSG2("failed reading compressed data (%ld bytes, err=%d)\n", - getSize, err); - goto bail; - } - usqState.dataInBuffer += getSize; - if (getSize > compRemaining) - compRemaining = 0; - else - compRemaining -= getSize; + ASSERT(getSize <= kSqBufferSize); + //WMSG2("Reading from offset=%ld (compRem=%ld)\n", + // ftell(fp), compRemaining); + err = SQRead(fp, usqState.dataPtr + usqState.dataInBuffer, + getSize); + if (err != kNuErrNone) { + WMSG2("failed reading compressed data (%ld bytes, err=%d)\n", + getSize, err); + goto bail; + } + usqState.dataInBuffer += getSize; + if (getSize > compRemaining) + compRemaining = 0; + else + compRemaining -= getSize; - ASSERT(compRemaining < 32767*65536); - ASSERT(usqState.dataInBuffer <= kSqBufferSize); - } + ASSERT(compRemaining < 32767*65536); + ASSERT(usqState.dataInBuffer <= kSqBufferSize); + } - err = USQDecodeHuffSymbol(&usqState, &val); - if (err != kNuErrNone) { - WMSG0("failed decoding huff symbol\n"); - goto bail; - } + err = USQDecodeHuffSymbol(&usqState, &val); + if (err != kNuErrNone) { + WMSG0("failed decoding huff symbol\n"); + goto bail; + } - if (val == kNuSQEOFToken) - break; + if (val == kNuSQEOFToken) + break; - /* - * Feed the symbol into the RLE decoder. - */ - if (inrep) { - /* - * Last char was RLE delim, handle this specially. We use - * --val instead of val-- because we already emitted the - * first occurrence of the char (right before the RLE delim). - */ - if (val == 0) { - /* special case -- just an escaped RLE delim */ - lastc = kNuSQRLEDelim; - val = 2; - } - while (--val) { - /*if (pCrc != nil) - *pCrc = Nu_CalcCRC16(*pCrc, &lastc, 1);*/ - if (outExp != nil) - outExp->Putc(lastc); - if (fullSqHeader) { - checksum += lastc; - } - } - inrep = false; - } else { - /* last char was ordinary */ - if (val == kNuSQRLEDelim) { - /* set a flag and catch the count the next time around */ - inrep = true; - } else { - lastc = val; - /*if (pCrc != nil) - *pCrc = Nu_CalcCRC16(*pCrc, &lastc, 1);*/ - if (outExp != nil) - outExp->Putc(lastc); - if (fullSqHeader) { - checksum += lastc; - } - } - } + /* + * Feed the symbol into the RLE decoder. + */ + if (inrep) { + /* + * Last char was RLE delim, handle this specially. We use + * --val instead of val-- because we already emitted the + * first occurrence of the char (right before the RLE delim). + */ + if (val == 0) { + /* special case -- just an escaped RLE delim */ + lastc = kNuSQRLEDelim; + val = 2; + } + while (--val) { + /*if (pCrc != nil) + *pCrc = Nu_CalcCRC16(*pCrc, &lastc, 1);*/ + if (outExp != nil) + outExp->Putc(lastc); + if (fullSqHeader) { + checksum += lastc; + } + } + inrep = false; + } else { + /* last char was ordinary */ + if (val == kNuSQRLEDelim) { + /* set a flag and catch the count the next time around */ + inrep = true; + } else { + lastc = val; + /*if (pCrc != nil) + *pCrc = Nu_CalcCRC16(*pCrc, &lastc, 1);*/ + if (outExp != nil) + outExp->Putc(lastc); + if (fullSqHeader) { + checksum += lastc; + } + } + } - } + } - if (inrep) { - err = kNuErrBadData; - WMSG0("got stop symbol when run length expected\n"); - goto bail; - } + if (inrep) { + err = kNuErrBadData; + WMSG0("got stop symbol when run length expected\n"); + goto bail; + } - if (fullSqHeader) { - /* verify the checksum stored in the SQ file */ - if (checksum != fileChecksum) { - err = kNuErrBadDataCRC; - WMSG2("expected 0x%04x, got 0x%04x (SQ)\n", fileChecksum, checksum); - goto bail; - } else { - WMSG1("--- SQ checksums match (0x%04x)\n", checksum); - } - } + if (fullSqHeader) { + /* verify the checksum stored in the SQ file */ + if (checksum != fileChecksum) { + err = kNuErrBadDataCRC; + WMSG2("expected 0x%04x, got 0x%04x (SQ)\n", fileChecksum, checksum); + goto bail; + } else { + WMSG1("--- SQ checksums match (0x%04x)\n", checksum); + } + } - /* - * Gobble up any unused bytes in the last 128-byte block. There - * shouldn't be more than that left over. - */ - if (compRemaining > kSqBufferSize) { - err = kNuErrBadData; - WMSG1("wow: found %ld bytes left over\n", compRemaining); - goto bail; - } - if (compRemaining) { - WMSG1("+++ slurping up last %ld bytes\n", compRemaining); - err = SQRead(fp, tmpBuf, compRemaining); - if (err != kNuErrNone) { - WMSG0("failed reading leftovers\n"); - goto bail; - } - } + /* + * Gobble up any unused bytes in the last 128-byte block. There + * shouldn't be more than that left over. + */ + if (compRemaining > kSqBufferSize) { + err = kNuErrBadData; + WMSG1("wow: found %ld bytes left over\n", compRemaining); + goto bail; + } + if (compRemaining) { + WMSG1("+++ slurping up last %ld bytes\n", compRemaining); + err = SQRead(fp, tmpBuf, compRemaining); + if (err != kNuErrNone) { + WMSG0("failed reading leftovers\n"); + goto bail; + } + } bail: - //if (outfp != nil) - // fflush(outfp); - free(tmpBuf); - return err; + //if (outfp != nil) + // fflush(outfp); + free(tmpBuf); + return err; } diff --git a/app/Squeeze.h b/app/Squeeze.h index 827bfb0..9e53435 100644 --- a/app/Squeeze.h +++ b/app/Squeeze.h @@ -10,6 +10,6 @@ #define __SQUEEZE__ NuError UnSqueeze(FILE* fp, unsigned long realEOF, ExpandBuffer* outExp, - bool fullSqHeader, int blockSize); + bool fullSqHeader, int blockSize); #endif /*__SQUEEZE__*/ diff --git a/app/StdAfx.cpp b/app/StdAfx.cpp index ebc3fd8..29f4e9c 100644 --- a/app/StdAfx.cpp +++ b/app/StdAfx.cpp @@ -4,8 +4,8 @@ * See the file LICENSE for distribution terms. */ // stdafx.cpp : source file that includes just the standard includes -// diskimg.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information +// diskimg.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information #include "stdafx.h" diff --git a/app/StdAfx.h b/app/StdAfx.h index ddd5c67..d258492 100644 --- a/app/StdAfx.h +++ b/app/StdAfx.h @@ -16,7 +16,7 @@ #endif // _MSC_VER > 1000 // Insert your headers here -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #define VC_EXTRALEAN #include diff --git a/app/SubVolumeDialog.cpp b/app/SubVolumeDialog.cpp index 0302602..2b92eb4 100644 --- a/app/SubVolumeDialog.cpp +++ b/app/SubVolumeDialog.cpp @@ -15,7 +15,7 @@ BEGIN_MESSAGE_MAP(SubVolumeDialog, CDialog) - ON_LBN_DBLCLK(IDC_SUBV_LIST, OnItemDoubleClicked) + ON_LBN_DBLCLK(IDC_SUBV_LIST, OnItemDoubleClicked) END_MESSAGE_MAP() @@ -25,24 +25,24 @@ END_MESSAGE_MAP() BOOL SubVolumeDialog::OnInitDialog(void) { - ASSERT(fpDiskFS != nil); + ASSERT(fpDiskFS != nil); - CListBox* pListBox = (CListBox*) GetDlgItem(IDC_SUBV_LIST); - ASSERT(pListBox != nil); + CListBox* pListBox = (CListBox*) GetDlgItem(IDC_SUBV_LIST); + ASSERT(pListBox != nil); -// if (pListBox->SetTabStops(12) != TRUE) { -// ASSERT(false); -// } +// if (pListBox->SetTabStops(12) != TRUE) { +// ASSERT(false); +// } - DiskFS::SubVolume* pSubVol = fpDiskFS->GetNextSubVolume(nil); - ASSERT(pSubVol != nil); // shouldn't be here otherwise - while (pSubVol != nil) { - pListBox->AddString(pSubVol->GetDiskFS()->GetVolumeID()); + DiskFS::SubVolume* pSubVol = fpDiskFS->GetNextSubVolume(nil); + ASSERT(pSubVol != nil); // shouldn't be here otherwise + while (pSubVol != nil) { + pListBox->AddString(pSubVol->GetDiskFS()->GetVolumeID()); - pSubVol = fpDiskFS->GetNextSubVolume(pSubVol); - } + pSubVol = fpDiskFS->GetNextSubVolume(pSubVol); + } - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } /* @@ -51,7 +51,7 @@ SubVolumeDialog::OnInitDialog(void) void SubVolumeDialog::DoDataExchange(CDataExchange* pDX) { - DDX_LBIndex(pDX, IDC_SUBV_LIST, fListBoxIndex); + DDX_LBIndex(pDX, IDC_SUBV_LIST, fListBoxIndex); } /* @@ -60,5 +60,5 @@ SubVolumeDialog::DoDataExchange(CDataExchange* pDX) void SubVolumeDialog::OnItemDoubleClicked(void) { - OnOK(); + OnOK(); } diff --git a/app/SubVolumeDialog.h b/app/SubVolumeDialog.h index c25cab6..c816ecb 100644 --- a/app/SubVolumeDialog.h +++ b/app/SubVolumeDialog.h @@ -19,29 +19,29 @@ using namespace DiskImgLib; */ class SubVolumeDialog : public CDialog { public: - SubVolumeDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_SUBV, pParentWnd) - { - fListBoxIndex = 0; - } - virtual ~SubVolumeDialog(void) {} + SubVolumeDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_SUBV, pParentWnd) + { + fListBoxIndex = 0; + } + virtual ~SubVolumeDialog(void) {} - void Setup(DiskFS* pDiskFS) { fpDiskFS = pDiskFS; } + void Setup(DiskFS* pDiskFS) { fpDiskFS = pDiskFS; } - /* so long as we don't sort the list, this number is enough */ - int fListBoxIndex; + /* so long as we don't sort the list, this number is enough */ + int fListBoxIndex; protected: - // overrides - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + // overrides + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - afx_msg void OnItemDoubleClicked(void); + afx_msg void OnItemDoubleClicked(void); private: - DiskFS* fpDiskFS; + DiskFS* fpDiskFS; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__SUBVOLUMEDIALOG__*/ \ No newline at end of file diff --git a/app/Tools.cpp b/app/Tools.cpp index f5b7aa2..6bfcd97 100644 --- a/app/Tools.cpp +++ b/app/Tools.cpp @@ -23,7 +23,7 @@ #include "DiskArchive.h" #include "EOLScanDialog.h" #include "TwoImgPropsDialog.h" -#include // need chsize() for TwoImgProps +#include // need chsize() for TwoImgProps /* @@ -38,60 +38,60 @@ */ int MainWindow::TryDiskImgOverride(DiskImg* pImg, const char* fileSource, - DiskImg::FSFormat defaultFormat, int* pDisplayFormat, bool allowUnknown, - CString* pErrMsg) + DiskImg::FSFormat defaultFormat, int* pDisplayFormat, bool allowUnknown, + CString* pErrMsg) { - ImageFormatDialog imf; + ImageFormatDialog imf; - *pErrMsg = ""; - imf.InitializeValues(pImg); - imf.fFileSource = fileSource; - imf.fAllowUnknown = allowUnknown; - if (pDisplayFormat == nil) - imf.SetQueryDisplayFormat(false); + *pErrMsg = ""; + imf.InitializeValues(pImg); + imf.fFileSource = fileSource; + imf.fAllowUnknown = allowUnknown; + if (pDisplayFormat == nil) + imf.SetQueryDisplayFormat(false); - /* don't show "unknown format" if we have a default value */ - if (defaultFormat != DiskImg::kFormatUnknown && - imf.fFSFormat == DiskImg::kFormatUnknown) - { - imf.fFSFormat = defaultFormat; - } + /* don't show "unknown format" if we have a default value */ + if (defaultFormat != DiskImg::kFormatUnknown && + imf.fFSFormat == DiskImg::kFormatUnknown) + { + imf.fFSFormat = defaultFormat; + } - WMSG2(" On entry, sectord=%d format=%d\n", - imf.fSectorOrder, imf.fFSFormat); + WMSG2(" On entry, sectord=%d format=%d\n", + imf.fSectorOrder, imf.fFSFormat); - if (imf.DoModal() != IDOK) { - WMSG0(" User bailed on IMF dialog\n"); - return IDCANCEL; - } + if (imf.DoModal() != IDOK) { + WMSG0(" User bailed on IMF dialog\n"); + return IDCANCEL; + } - WMSG2(" On exit, sectord=%d format=%d\n", - imf.fSectorOrder, imf.fFSFormat); + WMSG2(" On exit, sectord=%d format=%d\n", + imf.fSectorOrder, imf.fFSFormat); - if (pDisplayFormat != nil) - *pDisplayFormat = imf.fDisplayFormat; - if (imf.fSectorOrder != pImg->GetSectorOrder() || - imf.fFSFormat != pImg->GetFSFormat()) - { - WMSG0("Initial values overridden, forcing img format\n"); - DIError dierr; - dierr = pImg->OverrideFormat(pImg->GetPhysicalFormat(), imf.fFSFormat, - imf.fSectorOrder); - if (dierr != kDIErrNone) { - pErrMsg->Format("Unable to access disk image using selected" - " parameters. Error: %s.", - DiskImgLib::DIStrError(dierr)); - // fall through to "return IDOK" - } - } + if (pDisplayFormat != nil) + *pDisplayFormat = imf.fDisplayFormat; + if (imf.fSectorOrder != pImg->GetSectorOrder() || + imf.fFSFormat != pImg->GetFSFormat()) + { + WMSG0("Initial values overridden, forcing img format\n"); + DIError dierr; + dierr = pImg->OverrideFormat(pImg->GetPhysicalFormat(), imf.fFSFormat, + imf.fSectorOrder); + if (dierr != kDIErrNone) { + pErrMsg->Format("Unable to access disk image using selected" + " parameters. Error: %s.", + DiskImgLib::DIStrError(dierr)); + // fall through to "return IDOK" + } + } - return IDOK; + return IDOK; } /* * ========================================================================== - * Disk Editor + * Disk Editor * ========================================================================== */ @@ -101,251 +101,251 @@ MainWindow::TryDiskImgOverride(DiskImg* pImg, const char* fileSource, void MainWindow::OnToolsDiskEdit(void) { - DIError dierr; - DiskImg img; - CString loadName, saveFolder; - CString failed, errMsg; - DiskEditOpenDialog diskEditOpen(this); - /* create three, show one */ - BlockEditDialog blockEdit(this); - SectorEditDialog sectorEdit(this); - NibbleEditDialog nibbleEdit(this); - DiskEditDialog* pEditDialog; - int displayFormat; - bool readOnly = true; + DIError dierr; + DiskImg img; + CString loadName, saveFolder; + CString failed, errMsg; + DiskEditOpenDialog diskEditOpen(this); + /* create three, show one */ + BlockEditDialog blockEdit(this); + SectorEditDialog sectorEdit(this); + NibbleEditDialog nibbleEdit(this); + DiskEditDialog* pEditDialog; + int displayFormat; + bool readOnly = true; - /* flush current archive in case that's what we're planning to edit */ - OnFileSave(); + /* flush current archive in case that's what we're planning to edit */ + OnFileSave(); - failed.LoadString(IDS_FAILED); + failed.LoadString(IDS_FAILED); - diskEditOpen.fArchiveOpen = false; - if (fpOpenArchive != nil && - fpOpenArchive->GetArchiveKind() == GenericArchive::kArchiveDiskImage) - { - diskEditOpen.fArchiveOpen = true; - } + diskEditOpen.fArchiveOpen = false; + if (fpOpenArchive != nil && + fpOpenArchive->GetArchiveKind() == GenericArchive::kArchiveDiskImage) + { + diskEditOpen.fArchiveOpen = true; + } - if (diskEditOpen.DoModal() != IDOK) - goto bail; + if (diskEditOpen.DoModal() != IDOK) + goto bail; - /* - * Choose something to open, based on "fOpenWhat". - */ - if (diskEditOpen.fOpenWhat == DiskEditOpenDialog::kOpenFile) { - CString openFilters, saveFolder; + /* + * Choose something to open, based on "fOpenWhat". + */ + if (diskEditOpen.fOpenWhat == DiskEditOpenDialog::kOpenFile) { + CString openFilters, saveFolder; - openFilters = kOpenDiskImage; - openFilters += kOpenAll; - openFilters += kOpenEnd; - CFileDialog dlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); + openFilters = kOpenDiskImage; + openFilters += kOpenAll; + openFilters += kOpenEnd; + CFileDialog dlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); - /* for now, everything is read-only */ - dlg.m_ofn.Flags |= OFN_HIDEREADONLY; - dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); + /* for now, everything is read-only */ + dlg.m_ofn.Flags |= OFN_HIDEREADONLY; + dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); - if (dlg.DoModal() != IDOK) - goto bail; + if (dlg.DoModal() != IDOK) + goto bail; - loadName = dlg.GetPathName(); - readOnly = true; // add to file dialog + loadName = dlg.GetPathName(); + readOnly = true; // add to file dialog - saveFolder = dlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); - } else if (diskEditOpen.fOpenWhat == DiskEditOpenDialog::kOpenVolume) { - OpenVolumeDialog dlg(this); - int result; + saveFolder = dlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); + } else if (diskEditOpen.fOpenWhat == DiskEditOpenDialog::kOpenVolume) { + OpenVolumeDialog dlg(this); + int result; - result = dlg.DoModal(); - if (result != IDOK) - goto bail; + result = dlg.DoModal(); + if (result != IDOK) + goto bail; - loadName = dlg.fChosenDrive; - readOnly = (dlg.fReadOnly != 0); - } else if (diskEditOpen.fOpenWhat == DiskEditOpenDialog::kOpenCurrent) { - // get values from currently open archive - loadName = fpOpenArchive->GetPathName(); - readOnly = fpOpenArchive->IsReadOnly(); - } else { - WMSG1("GLITCH: unexpected fOpenWhat %d\n", diskEditOpen.fOpenWhat); - ASSERT(false); - goto bail; - } + loadName = dlg.fChosenDrive; + readOnly = (dlg.fReadOnly != 0); + } else if (diskEditOpen.fOpenWhat == DiskEditOpenDialog::kOpenCurrent) { + // get values from currently open archive + loadName = fpOpenArchive->GetPathName(); + readOnly = fpOpenArchive->IsReadOnly(); + } else { + WMSG1("GLITCH: unexpected fOpenWhat %d\n", diskEditOpen.fOpenWhat); + ASSERT(false); + goto bail; + } - WMSG3("Disk editor what=%d name='%s' ro=%d\n", - diskEditOpen.fOpenWhat, loadName, readOnly); + WMSG3("Disk editor what=%d name='%s' ro=%d\n", + diskEditOpen.fOpenWhat, loadName, readOnly); #if 1 - { - CWaitCursor waitc; - /* open the image file and analyze it */ - dierr = img.OpenImage(loadName, PathProposal::kLocalFssep, true); - } + { + CWaitCursor waitc; + /* open the image file and analyze it */ + dierr = img.OpenImage(loadName, PathProposal::kLocalFssep, true); + } #else - /* quick test of memory-buffer-based interface */ - FILE* tmpfp; - char* phatbuf; - long length; + /* quick test of memory-buffer-based interface */ + FILE* tmpfp; + char* phatbuf; + long length; - tmpfp = fopen(loadName, "rb"); - ASSERT(tmpfp != nil); - fseek(tmpfp, 0, SEEK_END); - length = ftell(tmpfp); - rewind(tmpfp); - WMSG1(" PHATBUF %d\n", length); - phatbuf = new char[length]; - if (fread(phatbuf, length, 1, tmpfp) != 1) - WMSG1("FREAD FAILED %d\n", errno); - fclose(tmpfp); - dierr = img.OpenImage(phatbuf, length, true); + tmpfp = fopen(loadName, "rb"); + ASSERT(tmpfp != nil); + fseek(tmpfp, 0, SEEK_END); + length = ftell(tmpfp); + rewind(tmpfp); + WMSG1(" PHATBUF %d\n", length); + phatbuf = new char[length]; + if (fread(phatbuf, length, 1, tmpfp) != 1) + WMSG1("FREAD FAILED %d\n", errno); + fclose(tmpfp); + dierr = img.OpenImage(phatbuf, length, true); #endif - if (dierr != kDIErrNone) { - errMsg.Format("Unable to open disk image: %s.", - DiskImgLib::DIStrError(dierr)); - MessageBox(errMsg, failed, MB_OK|MB_ICONSTOP); - goto bail; - } + if (dierr != kDIErrNone) { + errMsg.Format("Unable to open disk image: %s.", + DiskImgLib::DIStrError(dierr)); + MessageBox(errMsg, failed, MB_OK|MB_ICONSTOP); + goto bail; + } #if 0 - { - /* - * TEST - set custom entry to match Sheila NIB image. We have to - * do this here so that the disk routines can analyze the disk - * correctly. We need a way to enter these parameters in the - * disk editor and then re-analyze the image. (Not to mention a way - * to flip in and out of block/sector/nibble mode.) - */ - DiskImg::NibbleDescr sheilaDescr = - { - "H.A.L. Labs (Sheila)", - 16, - { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, - 0x00, // checksum seed - true, // verify checksum - true, // verify track - 2, // epilog verify count - { 0xd5, 0xaa, 0xda }, { 0xde, 0xaa, 0xeb }, - 0x00, // checksum seed - true, // verify checksum - 2, // epilog verify count - DiskImg::kNibbleEnc62, - DiskImg::kNibbleSpecialNone, - }; - /* same thing, but for original 13-sector Zork */ - DiskImg::NibbleDescr zork13Descr = - { - "Zork 13-sector", - 13, - { 0xd5, 0xaa, 0xb5 }, { 0xde, 0xaa, 0xeb }, - 0x00, - false, - false, - 0, - { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, - 0x1f, - true, - 0, - DiskImg::kNibbleEnc53, - DiskImg::kNibbleSpecialNone, - }; + { + /* + * TEST - set custom entry to match Sheila NIB image. We have to + * do this here so that the disk routines can analyze the disk + * correctly. We need a way to enter these parameters in the + * disk editor and then re-analyze the image. (Not to mention a way + * to flip in and out of block/sector/nibble mode.) + */ + DiskImg::NibbleDescr sheilaDescr = + { + "H.A.L. Labs (Sheila)", + 16, + { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, + 0x00, // checksum seed + true, // verify checksum + true, // verify track + 2, // epilog verify count + { 0xd5, 0xaa, 0xda }, { 0xde, 0xaa, 0xeb }, + 0x00, // checksum seed + true, // verify checksum + 2, // epilog verify count + DiskImg::kNibbleEnc62, + DiskImg::kNibbleSpecialNone, + }; + /* same thing, but for original 13-sector Zork */ + DiskImg::NibbleDescr zork13Descr = + { + "Zork 13-sector", + 13, + { 0xd5, 0xaa, 0xb5 }, { 0xde, 0xaa, 0xeb }, + 0x00, + false, + false, + 0, + { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, + 0x1f, + true, + 0, + DiskImg::kNibbleEnc53, + DiskImg::kNibbleSpecialNone, + }; - img.SetCustomNibbleDescr(&zork13Descr); - } + img.SetCustomNibbleDescr(&zork13Descr); + } #endif - if (img.AnalyzeImage() != kDIErrNone) { - errMsg.Format("The file '%s' doesn't seem to hold a valid disk image.", - loadName); - MessageBox(errMsg, failed, MB_OK|MB_ICONSTOP); - goto bail; - } + if (img.AnalyzeImage() != kDIErrNone) { + errMsg.Format("The file '%s' doesn't seem to hold a valid disk image.", + loadName); + MessageBox(errMsg, failed, MB_OK|MB_ICONSTOP); + goto bail; + } - if (img.ShowAsBlocks()) - displayFormat = ImageFormatDialog::kShowAsBlocks; - else - displayFormat = ImageFormatDialog::kShowAsSectors; + if (img.ShowAsBlocks()) + displayFormat = ImageFormatDialog::kShowAsBlocks; + else + displayFormat = ImageFormatDialog::kShowAsSectors; - /* if they can't do anything but view nibbles, don't demand an fs format */ - bool allowUnknown; - allowUnknown = false; - if (!img.GetHasSectors() && !img.GetHasBlocks() && img.GetHasNibbles()) - allowUnknown = true; + /* if they can't do anything but view nibbles, don't demand an fs format */ + bool allowUnknown; + allowUnknown = false; + if (!img.GetHasSectors() && !img.GetHasBlocks() && img.GetHasNibbles()) + allowUnknown = true; - /* - * If requested (or necessary), verify the format. - */ - if (img.GetFSFormat() == DiskImg::kFormatUnknown || - img.GetSectorOrder() == DiskImg::kSectorOrderUnknown || - fPreferences.GetPrefBool(kPrQueryImageFormat)) - { - if (TryDiskImgOverride(&img, loadName, DiskImg::kFormatUnknown, - &displayFormat, allowUnknown, &errMsg) != IDOK) - { - goto bail; - } - if (!errMsg.IsEmpty()) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } - } + /* + * If requested (or necessary), verify the format. + */ + if (img.GetFSFormat() == DiskImg::kFormatUnknown || + img.GetSectorOrder() == DiskImg::kSectorOrderUnknown || + fPreferences.GetPrefBool(kPrQueryImageFormat)) + { + if (TryDiskImgOverride(&img, loadName, DiskImg::kFormatUnknown, + &displayFormat, allowUnknown, &errMsg) != IDOK) + { + goto bail; + } + if (!errMsg.IsEmpty()) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } + } - /* select edit dialog type, based on blocks vs. sectors */ - if (displayFormat == ImageFormatDialog::kShowAsSectors) - pEditDialog = §orEdit; - else if (displayFormat == ImageFormatDialog::kShowAsBlocks) - pEditDialog = &blockEdit; - else - pEditDialog = &nibbleEdit; + /* select edit dialog type, based on blocks vs. sectors */ + if (displayFormat == ImageFormatDialog::kShowAsSectors) + pEditDialog = §orEdit; + else if (displayFormat == ImageFormatDialog::kShowAsBlocks) + pEditDialog = &blockEdit; + else + pEditDialog = &nibbleEdit; - /* - * Create an appropriate DiskFS object and hand it to the edit dialog. - */ - DiskFS* pDiskFS; - pDiskFS = img.OpenAppropriateDiskFS(true); - if (pDiskFS == nil) { - WMSG0("HEY: OpenAppropriateDiskFS failed!\n"); - goto bail; - } + /* + * Create an appropriate DiskFS object and hand it to the edit dialog. + */ + DiskFS* pDiskFS; + pDiskFS = img.OpenAppropriateDiskFS(true); + if (pDiskFS == nil) { + WMSG0("HEY: OpenAppropriateDiskFS failed!\n"); + goto bail; + } - pDiskFS->SetScanForSubVolumes(DiskFS::kScanSubEnabled); + pDiskFS->SetScanForSubVolumes(DiskFS::kScanSubEnabled); - { - CWaitCursor wait; // big ProDOS volumes can be slow - dierr = pDiskFS->Initialize(&img, DiskFS::kInitFull); - } - if (dierr != kDIErrNone) { - errMsg.Format("Warning: error during disk scan: %s.", - DiskImgLib::DIStrError(dierr)); - MessageBox(errMsg, failed, MB_OK | MB_ICONEXCLAMATION); - /* keep going */ - } - pEditDialog->Setup(pDiskFS, loadName); - (void) pEditDialog->DoModal(); + { + CWaitCursor wait; // big ProDOS volumes can be slow + dierr = pDiskFS->Initialize(&img, DiskFS::kInitFull); + } + if (dierr != kDIErrNone) { + errMsg.Format("Warning: error during disk scan: %s.", + DiskImgLib::DIStrError(dierr)); + MessageBox(errMsg, failed, MB_OK | MB_ICONEXCLAMATION); + /* keep going */ + } + pEditDialog->Setup(pDiskFS, loadName); + (void) pEditDialog->DoModal(); - delete pDiskFS; + delete pDiskFS; - /* - * FUTURE: if we edited the file we have open in the contentlist, - * we need to post a warning and/or close it in the contentlist. - * Or maybe just re-open it? Allow that as an option. - */ + /* + * FUTURE: if we edited the file we have open in the contentlist, + * we need to post a warning and/or close it in the contentlist. + * Or maybe just re-open it? Allow that as an option. + */ bail: #if 0 - delete phatbuf; + delete phatbuf; #endif - return; + return; } /* * ========================================================================== - * Disk Converter + * Disk Converter * ========================================================================== */ @@ -355,407 +355,407 @@ bail: void MainWindow::OnToolsDiskConv(void) { - DIError dierr; - CString openFilters, errMsg; - CString loadName, saveName, saveFolder; - DiskImg srcImg, dstImg; - DiskConvertDialog convDlg(this); - CString storageName; + DIError dierr; + CString openFilters, errMsg; + CString loadName, saveName, saveFolder; + DiskImg srcImg, dstImg; + DiskConvertDialog convDlg(this); + CString storageName; - /* flush current archive in case that's what we're planning to convert */ - OnFileSave(); + /* flush current archive in case that's what we're planning to convert */ + OnFileSave(); - dstImg.SetNuFXCompressionType(fPreferences.GetPrefLong(kPrCompressionType)); + dstImg.SetNuFXCompressionType(fPreferences.GetPrefLong(kPrCompressionType)); - /* - * Select the image to convert. - */ - openFilters = kOpenDiskImage; - openFilters += kOpenAll; - openFilters += kOpenEnd; - CFileDialog dlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); + /* + * Select the image to convert. + */ + openFilters = kOpenDiskImage; + openFilters += kOpenAll; + openFilters += kOpenEnd; + CFileDialog dlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); - /* for now, everything is read-only */ - dlg.m_ofn.Flags |= OFN_HIDEREADONLY; - dlg.m_ofn.lpstrTitle = "Select image to convert"; - dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); + /* for now, everything is read-only */ + dlg.m_ofn.Flags |= OFN_HIDEREADONLY; + dlg.m_ofn.lpstrTitle = "Select image to convert"; + dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); - if (dlg.DoModal() != IDOK) - goto bail; - loadName = dlg.GetPathName(); + if (dlg.DoModal() != IDOK) + goto bail; + loadName = dlg.GetPathName(); - saveFolder = dlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); + saveFolder = dlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); - /* open the image file and analyze it */ - dierr = srcImg.OpenImage(loadName, PathProposal::kLocalFssep, true); - if (dierr != kDIErrNone) { - errMsg.Format("Unable to open disk image: %s.", - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + /* open the image file and analyze it */ + dierr = srcImg.OpenImage(loadName, PathProposal::kLocalFssep, true); + if (dierr != kDIErrNone) { + errMsg.Format("Unable to open disk image: %s.", + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - if (srcImg.AnalyzeImage() != kDIErrNone) { - errMsg.Format("The file '%s' doesn't seem to hold a valid disk image.", - loadName); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + if (srcImg.AnalyzeImage() != kDIErrNone) { + errMsg.Format("The file '%s' doesn't seem to hold a valid disk image.", + loadName); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - /* - * If confirm image format is set, or we can't figure out the sector - * ordering, prompt the user. - */ - if (srcImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown || - fPreferences.GetPrefBool(kPrQueryImageFormat)) - { - if (TryDiskImgOverride(&srcImg, loadName, DiskImg::kFormatGenericProDOSOrd, - nil, false, &errMsg) != IDOK) - { - goto bail; - } - if (!errMsg.IsEmpty()) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } - } + /* + * If confirm image format is set, or we can't figure out the sector + * ordering, prompt the user. + */ + if (srcImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown || + fPreferences.GetPrefBool(kPrQueryImageFormat)) + { + if (TryDiskImgOverride(&srcImg, loadName, DiskImg::kFormatGenericProDOSOrd, + nil, false, &errMsg) != IDOK) + { + goto bail; + } + if (!errMsg.IsEmpty()) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } + } - /* - * If this is a ProDOS volume, use the disk volume name as the default - * value for "storageName" (which is used for NuFX archives and DC42). - */ - if (srcImg.GetFSFormat() == DiskImg::kFormatProDOS) { - CWaitCursor waitc; - DiskFS* pDiskFS = srcImg.OpenAppropriateDiskFS(); - // use "headerOnly", which gets the volume name - dierr = pDiskFS->Initialize(&srcImg, DiskFS::kInitHeaderOnly); - if (dierr == kDIErrNone) { - storageName = pDiskFS->GetVolumeName(); - } - delete pDiskFS; - } else { - /* use filename as storageName (exception for DiskCopy42 later) */ - storageName = FilenameOnly(loadName, '\\'); - } - WMSG1(" Using '%s' as storageName\n", storageName); + /* + * If this is a ProDOS volume, use the disk volume name as the default + * value for "storageName" (which is used for NuFX archives and DC42). + */ + if (srcImg.GetFSFormat() == DiskImg::kFormatProDOS) { + CWaitCursor waitc; + DiskFS* pDiskFS = srcImg.OpenAppropriateDiskFS(); + // use "headerOnly", which gets the volume name + dierr = pDiskFS->Initialize(&srcImg, DiskFS::kInitHeaderOnly); + if (dierr == kDIErrNone) { + storageName = pDiskFS->GetVolumeName(); + } + delete pDiskFS; + } else { + /* use filename as storageName (exception for DiskCopy42 later) */ + storageName = FilenameOnly(loadName, '\\'); + } + WMSG1(" Using '%s' as storageName\n", storageName); /* transfer the DOS volume num, if one was set */ dstImg.SetDOSVolumeNum(srcImg.GetDOSVolumeNum()); WMSG1("DOS volume number set to %d\n", dstImg.GetDOSVolumeNum()); - DiskImg::FSFormat origFSFormat; - origFSFormat = srcImg.GetFSFormat(); + DiskImg::FSFormat origFSFormat; + origFSFormat = srcImg.GetFSFormat(); - /* - * The converter always tries to read and write images as if they were - * ProDOS blocks. This way the only sector ordering changes are caused by - * differences in the sector ordering, rather than differences in the - * assumed filesystem types (which may not be knowable). - */ - dierr = srcImg.OverrideFormat(srcImg.GetPhysicalFormat(), - DiskImg::kFormatGenericProDOSOrd, srcImg.GetSectorOrder()); - if (dierr != kDIErrNone) { - errMsg.Format("Internal error: couldn't switch to generic ProDOS: %s.", - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + /* + * The converter always tries to read and write images as if they were + * ProDOS blocks. This way the only sector ordering changes are caused by + * differences in the sector ordering, rather than differences in the + * assumed filesystem types (which may not be knowable). + */ + dierr = srcImg.OverrideFormat(srcImg.GetPhysicalFormat(), + DiskImg::kFormatGenericProDOSOrd, srcImg.GetSectorOrder()); + if (dierr != kDIErrNone) { + errMsg.Format("Internal error: couldn't switch to generic ProDOS: %s.", + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - /* - * Put up a dialog to figure out what we want to do with this image. - * - * We have a fair amount of faith that this will not pick impossible - * combinations. If we do, we will fail later on in CreateImage. - */ - convDlg.Init(&srcImg); - if (convDlg.DoModal() != IDOK) { - WMSG0(" User bailed out of convert dialog\n"); - goto bail; - } + /* + * Put up a dialog to figure out what we want to do with this image. + * + * We have a fair amount of faith that this will not pick impossible + * combinations. If we do, we will fail later on in CreateImage. + */ + convDlg.Init(&srcImg); + if (convDlg.DoModal() != IDOK) { + WMSG0(" User bailed out of convert dialog\n"); + goto bail; + } - /* - * Examine their choices. - */ - DiskImg::OuterFormat outerFormat; - DiskImg::FileFormat fileFormat; - DiskImg::PhysicalFormat physicalFormat; - DiskImg::SectorOrder sectorOrder; + /* + * Examine their choices. + */ + DiskImg::OuterFormat outerFormat; + DiskImg::FileFormat fileFormat; + DiskImg::PhysicalFormat physicalFormat; + DiskImg::SectorOrder sectorOrder; - if (DetermineImageSettings(convDlg.fConvertIdx, (convDlg.fAddGzip != 0), - &outerFormat, &fileFormat, &physicalFormat, §orOrder) != 0) - { - goto bail; - } + if (DetermineImageSettings(convDlg.fConvertIdx, (convDlg.fAddGzip != 0), + &outerFormat, &fileFormat, &physicalFormat, §orOrder) != 0) + { + goto bail; + } const DiskImg::NibbleDescr* pNibbleDescr; - pNibbleDescr = srcImg.GetNibbleDescr(); - if (pNibbleDescr == nil && DiskImg::IsNibbleFormat(physicalFormat)) { - /* - * We're writing to a nibble format, so we have to decide how the - * disk should be formatted. The source doesn't specify it, so we - * use generic 13- or 16-sector, defaulting to the latter when in - * doubt. - */ - if (srcImg.GetHasSectors() && srcImg.GetNumSectPerTrack() == 13) { - pNibbleDescr = DiskImg::GetStdNibbleDescr( - DiskImg::kNibbleDescrDOS32Std); - } else { - pNibbleDescr = DiskImg::GetStdNibbleDescr( - DiskImg::kNibbleDescrDOS33Std); - } - } - WMSG2(" NibbleDescr is 0x%08lx (%s)\n", (long) pNibbleDescr, - pNibbleDescr != nil ? pNibbleDescr->description : "---"); + pNibbleDescr = srcImg.GetNibbleDescr(); + if (pNibbleDescr == nil && DiskImg::IsNibbleFormat(physicalFormat)) { + /* + * We're writing to a nibble format, so we have to decide how the + * disk should be formatted. The source doesn't specify it, so we + * use generic 13- or 16-sector, defaulting to the latter when in + * doubt. + */ + if (srcImg.GetHasSectors() && srcImg.GetNumSectPerTrack() == 13) { + pNibbleDescr = DiskImg::GetStdNibbleDescr( + DiskImg::kNibbleDescrDOS32Std); + } else { + pNibbleDescr = DiskImg::GetStdNibbleDescr( + DiskImg::kNibbleDescrDOS33Std); + } + } + WMSG2(" NibbleDescr is 0x%08lx (%s)\n", (long) pNibbleDescr, + pNibbleDescr != nil ? pNibbleDescr->description : "---"); - if (srcImg.GetFileFormat() == DiskImg::kFileFormatTrackStar && - fileFormat != DiskImg::kFileFormatTrackStar) - { - /* converting from TrackStar to anything else */ - CString msg, appName; - msg.LoadString(IDS_TRACKSTAR_TO_OTHER_WARNING); - appName.LoadString(IDS_MB_APP_NAME); - if (MessageBox(msg, appName, MB_OKCANCEL | MB_ICONWARNING) != IDOK) { - WMSG0(" User bailed after trackstar-to-other warning\n"); - goto bail; - } - } else if (srcImg.GetFileFormat() == DiskImg::kFileFormatFDI && - fileFormat != DiskImg::kFileFormatTrackStar && - srcImg.GetNumBlocks() != 1600) - { - /* converting from 5.25" FDI to anything but TrackStar */ - CString msg, appName; - msg.LoadString(IDS_FDI_TO_OTHER_WARNING); - appName.LoadString(IDS_MB_APP_NAME); - if (MessageBox(msg, appName, MB_OKCANCEL | MB_ICONWARNING) != IDOK) { - WMSG0(" User bailed after fdi-to-other warning\n"); - goto bail; - } - } else if (srcImg.GetHasNibbles() && DiskImg::IsSectorFormat(physicalFormat)) - { - /* converting from nibble to non-nibble format */ - CString msg, appName; - msg.LoadString(IDS_NIBBLE_TO_SECTOR_WARNING); - appName.LoadString(IDS_MB_APP_NAME); - if (MessageBox(msg, appName, MB_OKCANCEL | MB_ICONWARNING) != IDOK) { - WMSG0(" User bailed after nibble-to-sector warning\n"); - goto bail; - } - } else if (srcImg.GetHasNibbles() && - DiskImg::IsNibbleFormat(physicalFormat) && - srcImg.GetPhysicalFormat() != physicalFormat) - { - /* converting between differing nibble formats */ - CString msg, appName; - msg.LoadString(IDS_DIFFERENT_NIBBLE_WARNING); - appName.LoadString(IDS_MB_APP_NAME); - if (MessageBox(msg, appName, MB_OKCANCEL | MB_ICONWARNING) != IDOK) { - WMSG0(" User bailed after differing-nibbles warning\n"); - goto bail; - } - } + if (srcImg.GetFileFormat() == DiskImg::kFileFormatTrackStar && + fileFormat != DiskImg::kFileFormatTrackStar) + { + /* converting from TrackStar to anything else */ + CString msg, appName; + msg.LoadString(IDS_TRACKSTAR_TO_OTHER_WARNING); + appName.LoadString(IDS_MB_APP_NAME); + if (MessageBox(msg, appName, MB_OKCANCEL | MB_ICONWARNING) != IDOK) { + WMSG0(" User bailed after trackstar-to-other warning\n"); + goto bail; + } + } else if (srcImg.GetFileFormat() == DiskImg::kFileFormatFDI && + fileFormat != DiskImg::kFileFormatTrackStar && + srcImg.GetNumBlocks() != 1600) + { + /* converting from 5.25" FDI to anything but TrackStar */ + CString msg, appName; + msg.LoadString(IDS_FDI_TO_OTHER_WARNING); + appName.LoadString(IDS_MB_APP_NAME); + if (MessageBox(msg, appName, MB_OKCANCEL | MB_ICONWARNING) != IDOK) { + WMSG0(" User bailed after fdi-to-other warning\n"); + goto bail; + } + } else if (srcImg.GetHasNibbles() && DiskImg::IsSectorFormat(physicalFormat)) + { + /* converting from nibble to non-nibble format */ + CString msg, appName; + msg.LoadString(IDS_NIBBLE_TO_SECTOR_WARNING); + appName.LoadString(IDS_MB_APP_NAME); + if (MessageBox(msg, appName, MB_OKCANCEL | MB_ICONWARNING) != IDOK) { + WMSG0(" User bailed after nibble-to-sector warning\n"); + goto bail; + } + } else if (srcImg.GetHasNibbles() && + DiskImg::IsNibbleFormat(physicalFormat) && + srcImg.GetPhysicalFormat() != physicalFormat) + { + /* converting between differing nibble formats */ + CString msg, appName; + msg.LoadString(IDS_DIFFERENT_NIBBLE_WARNING); + appName.LoadString(IDS_MB_APP_NAME); + if (MessageBox(msg, appName, MB_OKCANCEL | MB_ICONWARNING) != IDOK) { + WMSG0(" User bailed after differing-nibbles warning\n"); + goto bail; + } + } - /* - * If the source is a UNIDOS volume and the target format is DiskCopy 4.2, - * use DOS sector ordering instead of ProDOS block ordering. For some - * reason the disks come out that way. - */ - if (origFSFormat == DiskImg::kFormatUNIDOS && - fileFormat == DiskImg::kFileFormatDiskCopy42) - { - WMSG0(" Switching to DOS sector ordering for UNIDOS/DiskCopy42"); - sectorOrder = DiskImg::kSectorOrderDOS; - } - if (origFSFormat != DiskImg::kFormatProDOS && - fileFormat == DiskImg::kFileFormatDiskCopy42) - { - WMSG0(" Nuking storage name for non-ProDOS DiskCopy42 image"); - storageName = ""; // want to use "-not a mac disk" for non-ProDOS - } + /* + * If the source is a UNIDOS volume and the target format is DiskCopy 4.2, + * use DOS sector ordering instead of ProDOS block ordering. For some + * reason the disks come out that way. + */ + if (origFSFormat == DiskImg::kFormatUNIDOS && + fileFormat == DiskImg::kFileFormatDiskCopy42) + { + WMSG0(" Switching to DOS sector ordering for UNIDOS/DiskCopy42"); + sectorOrder = DiskImg::kSectorOrderDOS; + } + if (origFSFormat != DiskImg::kFormatProDOS && + fileFormat == DiskImg::kFileFormatDiskCopy42) + { + WMSG0(" Nuking storage name for non-ProDOS DiskCopy42 image"); + storageName = ""; // want to use "-not a mac disk" for non-ProDOS + } - /* - * Pick file to save into. - */ - { - CFileDialog saveDlg(FALSE, convDlg.fExtension, NULL, - OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, - "All Files (*.*)|*.*||", this); + /* + * Pick file to save into. + */ + { + CFileDialog saveDlg(FALSE, convDlg.fExtension, NULL, + OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, + "All Files (*.*)|*.*||", this); - CString saveFolder; - CString title = "New disk image (."; - title += convDlg.fExtension; - title += ")"; + CString saveFolder; + CString title = "New disk image (."; + title += convDlg.fExtension; + title += ")"; - saveDlg.m_ofn.lpstrTitle = title; - saveDlg.m_ofn.lpstrInitialDir = - fPreferences.GetPrefString(kPrConvertArchiveFolder); - - if (saveDlg.DoModal() != IDOK) { - WMSG0(" User bailed out of image save dialog\n"); - goto bail; - } + saveDlg.m_ofn.lpstrTitle = title; + saveDlg.m_ofn.lpstrInitialDir = + fPreferences.GetPrefString(kPrConvertArchiveFolder); + + if (saveDlg.DoModal() != IDOK) { + WMSG0(" User bailed out of image save dialog\n"); + goto bail; + } - saveFolder = saveDlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(saveDlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrConvertArchiveFolder, saveFolder); + saveFolder = saveDlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(saveDlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrConvertArchiveFolder, saveFolder); - saveName = saveDlg.GetPathName(); - } - WMSG1("File will be saved to '%s'\n", saveName); + saveName = saveDlg.GetPathName(); + } + WMSG1("File will be saved to '%s'\n", saveName); - /* DiskImgLib does not like it if file already exists */ - errMsg = RemoveFile(saveName); - if (!errMsg.IsEmpty()) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + /* DiskImgLib does not like it if file already exists */ + errMsg = RemoveFile(saveName); + if (!errMsg.IsEmpty()) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - /* - * Create the image file. Adjust the number of tracks if we're - * copying to or from TrackStar or FDI images. - */ - int dstNumTracks; - int dstNumBlocks; - bool isPartial; - dstNumTracks = srcImg.GetNumTracks(); - dstNumBlocks = srcImg.GetNumBlocks(); - isPartial = false; + /* + * Create the image file. Adjust the number of tracks if we're + * copying to or from TrackStar or FDI images. + */ + int dstNumTracks; + int dstNumBlocks; + bool isPartial; + dstNumTracks = srcImg.GetNumTracks(); + dstNumBlocks = srcImg.GetNumBlocks(); + isPartial = false; - if (srcImg.GetFileFormat() == DiskImg::kFileFormatTrackStar && - fileFormat != DiskImg::kFileFormatTrackStar && - srcImg.GetNumTracks() == 40) - { - /* from TrackStar to other */ - dstNumTracks = 35; - dstNumBlocks = 280; - isPartial = true; - } - if (srcImg.GetFileFormat() == DiskImg::kFileFormatFDI && - fileFormat != DiskImg::kFileFormatFDI && - srcImg.GetNumTracks() != 35 && srcImg.GetNumBlocks() != 1600) - { - /* from 5.25" FDI to other */ - dstNumTracks = 35; - dstNumBlocks = 280; - isPartial = true; - } + if (srcImg.GetFileFormat() == DiskImg::kFileFormatTrackStar && + fileFormat != DiskImg::kFileFormatTrackStar && + srcImg.GetNumTracks() == 40) + { + /* from TrackStar to other */ + dstNumTracks = 35; + dstNumBlocks = 280; + isPartial = true; + } + if (srcImg.GetFileFormat() == DiskImg::kFileFormatFDI && + fileFormat != DiskImg::kFileFormatFDI && + srcImg.GetNumTracks() != 35 && srcImg.GetNumBlocks() != 1600) + { + /* from 5.25" FDI to other */ + dstNumTracks = 35; + dstNumBlocks = 280; + isPartial = true; + } - if (srcImg.GetFileFormat() != DiskImg::kFileFormatTrackStar && - fileFormat == DiskImg::kFileFormatTrackStar && - dstNumTracks == 35) - { - /* from other to TrackStar */ - isPartial = true; - } + if (srcImg.GetFileFormat() != DiskImg::kFileFormatTrackStar && + fileFormat == DiskImg::kFileFormatTrackStar && + dstNumTracks == 35) + { + /* from other to TrackStar */ + isPartial = true; + } - if (srcImg.GetHasNibbles() && - DiskImg::IsNibbleFormat(physicalFormat) && - physicalFormat == srcImg.GetPhysicalFormat()) - { - /* - * For nibble-to-nibble with the same track format, copy it as - * a collection of tracks. - */ - dierr = dstImg.CreateImage(saveName, storageName, - outerFormat, - fileFormat, - physicalFormat, - pNibbleDescr, - sectorOrder, - DiskImg::kFormatGenericProDOSOrd, - dstNumTracks, srcImg.GetNumSectPerTrack(), - false /* must format */); - } else if (srcImg.GetHasBlocks()) { - /* - * For general case, copy as a block image, converting in and out of - * nibbles as needed. - */ - dierr = dstImg.CreateImage(saveName, storageName, - outerFormat, - fileFormat, - physicalFormat, - pNibbleDescr, - sectorOrder, - DiskImg::kFormatGenericProDOSOrd, - dstNumBlocks, - false /* only needed for nibble?? */); - } else if (srcImg.GetHasSectors()) { - /* - * We should only get here when converting to/from D13. We have to - * special-case this because this was originally written to support - * block copying as the lowest common denominator. D13 screwed - * everything up. :-) - */ - dierr = dstImg.CreateImage(saveName, storageName, - outerFormat, - fileFormat, - physicalFormat, - pNibbleDescr, - sectorOrder, - DiskImg::kFormatGenericProDOSOrd, // needs to match above - dstNumTracks, srcImg.GetNumSectPerTrack(), - false /* only need for dest=nibble? */); - } else { - /* - * Generally speaking, we don't allow the user to make choices that - * would get us here. In particular, the UI should not allow the - * user to convert directly between nibble formats when the source - * image doesn't have a recognizeable block format. - */ - ASSERT(false); - dierr = kDIErrInternal; - } - if (dierr != kDIErrNone) { - errMsg.Format("Couldn't create disk image: %s.", - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + if (srcImg.GetHasNibbles() && + DiskImg::IsNibbleFormat(physicalFormat) && + physicalFormat == srcImg.GetPhysicalFormat()) + { + /* + * For nibble-to-nibble with the same track format, copy it as + * a collection of tracks. + */ + dierr = dstImg.CreateImage(saveName, storageName, + outerFormat, + fileFormat, + physicalFormat, + pNibbleDescr, + sectorOrder, + DiskImg::kFormatGenericProDOSOrd, + dstNumTracks, srcImg.GetNumSectPerTrack(), + false /* must format */); + } else if (srcImg.GetHasBlocks()) { + /* + * For general case, copy as a block image, converting in and out of + * nibbles as needed. + */ + dierr = dstImg.CreateImage(saveName, storageName, + outerFormat, + fileFormat, + physicalFormat, + pNibbleDescr, + sectorOrder, + DiskImg::kFormatGenericProDOSOrd, + dstNumBlocks, + false /* only needed for nibble?? */); + } else if (srcImg.GetHasSectors()) { + /* + * We should only get here when converting to/from D13. We have to + * special-case this because this was originally written to support + * block copying as the lowest common denominator. D13 screwed + * everything up. :-) + */ + dierr = dstImg.CreateImage(saveName, storageName, + outerFormat, + fileFormat, + physicalFormat, + pNibbleDescr, + sectorOrder, + DiskImg::kFormatGenericProDOSOrd, // needs to match above + dstNumTracks, srcImg.GetNumSectPerTrack(), + false /* only need for dest=nibble? */); + } else { + /* + * Generally speaking, we don't allow the user to make choices that + * would get us here. In particular, the UI should not allow the + * user to convert directly between nibble formats when the source + * image doesn't have a recognizeable block format. + */ + ASSERT(false); + dierr = kDIErrInternal; + } + if (dierr != kDIErrNone) { + errMsg.Format("Couldn't create disk image: %s.", + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - /* - * Do the actual copy, either as blocks or tracks. - */ - dierr = CopyDiskImage(&dstImg, &srcImg, false, isPartial, nil); - if (dierr != kDIErrNone) { - errMsg.Format("Copy failed: %s.", DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + /* + * Do the actual copy, either as blocks or tracks. + */ + dierr = CopyDiskImage(&dstImg, &srcImg, false, isPartial, nil); + if (dierr != kDIErrNone) { + errMsg.Format("Copy failed: %s.", DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } dierr = srcImg.CloseImage(); if (dierr != kDIErrNone) { errMsg.Format("ERROR: srcImg close failed (err=%d)\n", dierr); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; } dierr = dstImg.CloseImage(); if (dierr != kDIErrNone) { errMsg.Format("ERROR: dstImg close failed (err=%d)\n", dierr); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; } - SuccessBeep(); + SuccessBeep(); - /* - * We're done. Give them the opportunity to open the disk image they - * just created. - */ - { - DoneOpenDialog doneOpen(this); + /* + * We're done. Give them the opportunity to open the disk image they + * just created. + */ + { + DoneOpenDialog doneOpen(this); - if (doneOpen.DoModal() == IDOK) { - WMSG1(" At user request, opening '%s'\n", saveName); + if (doneOpen.DoModal() == IDOK) { + WMSG1(" At user request, opening '%s'\n", saveName); - DoOpenArchive(saveName, convDlg.fExtension, - kFilterIndexDiskImage, false); - } - } + DoOpenArchive(saveName, convDlg.fExtension, + kFilterIndexDiskImage, false); + } + } bail: - return; + return; } /* @@ -766,88 +766,88 @@ bail: */ int MainWindow::DetermineImageSettings(int convertIdx, bool addGzip, - DiskImg::OuterFormat* pOuterFormat, DiskImg::FileFormat* pFileFormat, - DiskImg::PhysicalFormat* pPhysicalFormat, - DiskImg::SectorOrder* pSectorOrder) + DiskImg::OuterFormat* pOuterFormat, DiskImg::FileFormat* pFileFormat, + DiskImg::PhysicalFormat* pPhysicalFormat, + DiskImg::SectorOrder* pSectorOrder) { - if (addGzip) - *pOuterFormat = DiskImg::kOuterFormatGzip; - else - *pOuterFormat = DiskImg::kOuterFormatNone; + if (addGzip) + *pOuterFormat = DiskImg::kOuterFormatGzip; + else + *pOuterFormat = DiskImg::kOuterFormatNone; - switch (convertIdx) { - case DiskConvertDialog::kConvDOSRaw: - *pFileFormat = DiskImg::kFileFormatUnadorned; - *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; - *pSectorOrder = DiskImg::kSectorOrderDOS; - break; - case DiskConvertDialog::kConvDOS2MG: - *pFileFormat = DiskImg::kFileFormat2MG; - *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; - *pSectorOrder = DiskImg::kSectorOrderDOS; - break; - case DiskConvertDialog::kConvProDOSRaw: - *pFileFormat = DiskImg::kFileFormatUnadorned; - *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; - *pSectorOrder = DiskImg::kSectorOrderProDOS; - break; - case DiskConvertDialog::kConvProDOS2MG: - *pFileFormat = DiskImg::kFileFormat2MG; - *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; - *pSectorOrder = DiskImg::kSectorOrderProDOS; - break; - case DiskConvertDialog::kConvNibbleRaw: - *pFileFormat = DiskImg::kFileFormatUnadorned; - *pPhysicalFormat = DiskImg::kPhysicalFormatNib525_6656; - *pSectorOrder = DiskImg::kSectorOrderPhysical; - break; - case DiskConvertDialog::kConvNibble2MG: - *pFileFormat = DiskImg::kFileFormat2MG; - *pPhysicalFormat = DiskImg::kPhysicalFormatNib525_6656; - *pSectorOrder = DiskImg::kSectorOrderPhysical; - break; - case DiskConvertDialog::kConvD13: - *pFileFormat = DiskImg::kFileFormatUnadorned; - *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; - *pSectorOrder = DiskImg::kSectorOrderDOS; - break; - case DiskConvertDialog::kConvDiskCopy42: - *pFileFormat = DiskImg::kFileFormatDiskCopy42; - *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; - *pSectorOrder = DiskImg::kSectorOrderProDOS; - break; - case DiskConvertDialog::kConvTrackStar: - *pFileFormat = DiskImg::kFileFormatTrackStar; - *pPhysicalFormat = DiskImg::kPhysicalFormatNib525_Var; - *pSectorOrder = DiskImg::kSectorOrderPhysical; - break; - case DiskConvertDialog::kConvNuFX: - *pFileFormat = DiskImg::kFileFormatNuFX; - *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; - *pSectorOrder = DiskImg::kSectorOrderProDOS; - break; - case DiskConvertDialog::kConvSim2eHDV: - *pFileFormat = DiskImg::kFileFormatSim2eHDV; - *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; - *pSectorOrder = DiskImg::kSectorOrderProDOS; - break; - case DiskConvertDialog::kConvDDD: - *pFileFormat = DiskImg::kFileFormatDDD; - *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; - *pSectorOrder = DiskImg::kSectorOrderDOS; - break; - default: - ASSERT(false); - WMSG1(" WHOA: invalid conv type %d\n", convertIdx); - return -1; - } + switch (convertIdx) { + case DiskConvertDialog::kConvDOSRaw: + *pFileFormat = DiskImg::kFileFormatUnadorned; + *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; + *pSectorOrder = DiskImg::kSectorOrderDOS; + break; + case DiskConvertDialog::kConvDOS2MG: + *pFileFormat = DiskImg::kFileFormat2MG; + *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; + *pSectorOrder = DiskImg::kSectorOrderDOS; + break; + case DiskConvertDialog::kConvProDOSRaw: + *pFileFormat = DiskImg::kFileFormatUnadorned; + *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; + *pSectorOrder = DiskImg::kSectorOrderProDOS; + break; + case DiskConvertDialog::kConvProDOS2MG: + *pFileFormat = DiskImg::kFileFormat2MG; + *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; + *pSectorOrder = DiskImg::kSectorOrderProDOS; + break; + case DiskConvertDialog::kConvNibbleRaw: + *pFileFormat = DiskImg::kFileFormatUnadorned; + *pPhysicalFormat = DiskImg::kPhysicalFormatNib525_6656; + *pSectorOrder = DiskImg::kSectorOrderPhysical; + break; + case DiskConvertDialog::kConvNibble2MG: + *pFileFormat = DiskImg::kFileFormat2MG; + *pPhysicalFormat = DiskImg::kPhysicalFormatNib525_6656; + *pSectorOrder = DiskImg::kSectorOrderPhysical; + break; + case DiskConvertDialog::kConvD13: + *pFileFormat = DiskImg::kFileFormatUnadorned; + *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; + *pSectorOrder = DiskImg::kSectorOrderDOS; + break; + case DiskConvertDialog::kConvDiskCopy42: + *pFileFormat = DiskImg::kFileFormatDiskCopy42; + *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; + *pSectorOrder = DiskImg::kSectorOrderProDOS; + break; + case DiskConvertDialog::kConvTrackStar: + *pFileFormat = DiskImg::kFileFormatTrackStar; + *pPhysicalFormat = DiskImg::kPhysicalFormatNib525_Var; + *pSectorOrder = DiskImg::kSectorOrderPhysical; + break; + case DiskConvertDialog::kConvNuFX: + *pFileFormat = DiskImg::kFileFormatNuFX; + *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; + *pSectorOrder = DiskImg::kSectorOrderProDOS; + break; + case DiskConvertDialog::kConvSim2eHDV: + *pFileFormat = DiskImg::kFileFormatSim2eHDV; + *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; + *pSectorOrder = DiskImg::kSectorOrderProDOS; + break; + case DiskConvertDialog::kConvDDD: + *pFileFormat = DiskImg::kFileFormatDDD; + *pPhysicalFormat = DiskImg::kPhysicalFormatSectors; + *pSectorOrder = DiskImg::kSectorOrderDOS; + break; + default: + ASSERT(false); + WMSG1(" WHOA: invalid conv type %d\n", convertIdx); + return -1; + } - return 0; + return 0; } static inline int MIN(int val1, int val2) { - return (val1 < val2) ? val1 : val2; + return (val1 < val2) ? val1 : val2; } /* @@ -861,199 +861,199 @@ static inline int MIN(int val1, int val2) */ DIError MainWindow::CopyDiskImage(DiskImg* pDstImg, DiskImg* pSrcImg, bool bulk, - bool partial, ProgressCancelDialog* pPCDialog) + bool partial, ProgressCancelDialog* pPCDialog) { - DIError dierr = kDIErrNone; - CString errMsg; - unsigned char* dataBuf = nil; + DIError dierr = kDIErrNone; + CString errMsg; + unsigned char* dataBuf = nil; - if (pSrcImg->GetHasNibbles() && pDstImg->GetHasNibbles() && - pSrcImg->GetPhysicalFormat() == pDstImg->GetPhysicalFormat()) - { - /* - * Copy as a series of nibble tracks. - * - * NOTE: we could do better here for 6384 to ".app", but in - * practice nobody cares anyway. - */ - if (!partial) { - ASSERT(pSrcImg->GetNumTracks() == pDstImg->GetNumTracks()); - } + if (pSrcImg->GetHasNibbles() && pDstImg->GetHasNibbles() && + pSrcImg->GetPhysicalFormat() == pDstImg->GetPhysicalFormat()) + { + /* + * Copy as a series of nibble tracks. + * + * NOTE: we could do better here for 6384 to ".app", but in + * practice nobody cares anyway. + */ + if (!partial) { + ASSERT(pSrcImg->GetNumTracks() == pDstImg->GetNumTracks()); + } - //unsigned char trackBuf[kTrackAllocSize]; - long trackLen; - int numTracks; + //unsigned char trackBuf[kTrackAllocSize]; + long trackLen; + int numTracks; - dataBuf = new unsigned char[kTrackAllocSize]; - if (dataBuf == nil) { - dierr = kDIErrMalloc; - goto bail; - } - - numTracks = MIN(pSrcImg->GetNumTracks(), pDstImg->GetNumTracks()); - WMSG1("Nibble track copy (%d tracks)\n", numTracks); - for (int track = 0; track < numTracks; track++) { - dierr = pSrcImg->ReadNibbleTrack(track, dataBuf, &trackLen); - if (dierr != kDIErrNone) { - errMsg.Format("ERROR: read on track %d failed (err=%d)\n", - track, dierr); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } - dierr = pDstImg->WriteNibbleTrack(track, dataBuf, trackLen); - if (dierr != kDIErrNone) { - errMsg.Format("ERROR: write on track %d failed (err=%d)\n", - track, dierr); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + dataBuf = new unsigned char[kTrackAllocSize]; + if (dataBuf == nil) { + dierr = kDIErrMalloc; + goto bail; + } + + numTracks = MIN(pSrcImg->GetNumTracks(), pDstImg->GetNumTracks()); + WMSG1("Nibble track copy (%d tracks)\n", numTracks); + for (int track = 0; track < numTracks; track++) { + dierr = pSrcImg->ReadNibbleTrack(track, dataBuf, &trackLen); + if (dierr != kDIErrNone) { + errMsg.Format("ERROR: read on track %d failed (err=%d)\n", + track, dierr); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } + dierr = pDstImg->WriteNibbleTrack(track, dataBuf, trackLen); + if (dierr != kDIErrNone) { + errMsg.Format("ERROR: write on track %d failed (err=%d)\n", + track, dierr); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - /* these aren't slow enough that we need progress updating */ - } - } else if (!pSrcImg->GetHasBlocks() || !pDstImg->GetHasBlocks()) { - /* - * Do a sector copy, for D13 images (which can't be accessed as blocks). - */ - if (!partial) { - ASSERT(pSrcImg->GetNumTracks() == pDstImg->GetNumTracks()); - ASSERT(pSrcImg->GetNumSectPerTrack() == pDstImg->GetNumSectPerTrack()); - } + /* these aren't slow enough that we need progress updating */ + } + } else if (!pSrcImg->GetHasBlocks() || !pDstImg->GetHasBlocks()) { + /* + * Do a sector copy, for D13 images (which can't be accessed as blocks). + */ + if (!partial) { + ASSERT(pSrcImg->GetNumTracks() == pDstImg->GetNumTracks()); + ASSERT(pSrcImg->GetNumSectPerTrack() == pDstImg->GetNumSectPerTrack()); + } - long numTracks, numSectPerTrack; - int numBadSectors = 0; + long numTracks, numSectPerTrack; + int numBadSectors = 0; - dataBuf = new unsigned char[256]; // one sector - if (dataBuf == nil) { - dierr = kDIErrMalloc; - goto bail; - } - - numTracks = MIN(pSrcImg->GetNumTracks(), pDstImg->GetNumTracks()); - numSectPerTrack = MIN(pSrcImg->GetNumSectPerTrack(), - pDstImg->GetNumSectPerTrack()); - WMSG2("Sector copy (%d tracks / %d sectors)\n", - numTracks, numSectPerTrack); - for (int track = 0; track < numTracks; track++) { - for (int sector = 0; sector < numSectPerTrack; sector++) { - dierr = pSrcImg->ReadTrackSector(track, sector, dataBuf); - if (dierr != kDIErrNone) { - WMSG2("Bad sector T=%d S=%d\n", track, sector); - numBadSectors++; - dierr = kDIErrNone; - memset(dataBuf, 0, 256); - } - dierr = pDstImg->WriteTrackSector(track, sector, dataBuf); - if (dierr != kDIErrNone) { - errMsg.Format("ERROR: write of T=%d S=%d failed (err=%d)\n", - track, sector, dierr); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } - } + dataBuf = new unsigned char[256]; // one sector + if (dataBuf == nil) { + dierr = kDIErrMalloc; + goto bail; + } + + numTracks = MIN(pSrcImg->GetNumTracks(), pDstImg->GetNumTracks()); + numSectPerTrack = MIN(pSrcImg->GetNumSectPerTrack(), + pDstImg->GetNumSectPerTrack()); + WMSG2("Sector copy (%d tracks / %d sectors)\n", + numTracks, numSectPerTrack); + for (int track = 0; track < numTracks; track++) { + for (int sector = 0; sector < numSectPerTrack; sector++) { + dierr = pSrcImg->ReadTrackSector(track, sector, dataBuf); + if (dierr != kDIErrNone) { + WMSG2("Bad sector T=%d S=%d\n", track, sector); + numBadSectors++; + dierr = kDIErrNone; + memset(dataBuf, 0, 256); + } + dierr = pDstImg->WriteTrackSector(track, sector, dataBuf); + if (dierr != kDIErrNone) { + errMsg.Format("ERROR: write of T=%d S=%d failed (err=%d)\n", + track, sector, dierr); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } + } - /* these aren't slow enough that we need progress updating */ - } + /* these aren't slow enough that we need progress updating */ + } - if (!bulk && numBadSectors != 0) { - CString appName; - appName.LoadString(IDS_MB_APP_NAME); - errMsg.Format("Skipped %ld unreadable sector%s.", numBadSectors, - numBadSectors == 1 ? "" : "s"); - MessageBox(errMsg, appName, MB_OK | MB_ICONWARNING); - } - } else { - /* - * Do a block copy, copying multiple blocks at a time for performance. - */ - if (!partial) { - ASSERT(pSrcImg->GetNumBlocks() == pDstImg->GetNumBlocks()); - } + if (!bulk && numBadSectors != 0) { + CString appName; + appName.LoadString(IDS_MB_APP_NAME); + errMsg.Format("Skipped %ld unreadable sector%s.", numBadSectors, + numBadSectors == 1 ? "" : "s"); + MessageBox(errMsg, appName, MB_OK | MB_ICONWARNING); + } + } else { + /* + * Do a block copy, copying multiple blocks at a time for performance. + */ + if (!partial) { + ASSERT(pSrcImg->GetNumBlocks() == pDstImg->GetNumBlocks()); + } - //unsigned char blkBuf[512]; - long numBadBlocks = 0; - long numBlocks; - int blocksPerRead; + //unsigned char blkBuf[512]; + long numBadBlocks = 0; + long numBlocks; + int blocksPerRead; - numBlocks = MIN(pSrcImg->GetNumBlocks(), pDstImg->GetNumBlocks()); - if (numBlocks <= 2880) - blocksPerRead = 9; // better granularity (one floppy track) - else - blocksPerRead = 64; // 32K per read; max seems to be 64K? + numBlocks = MIN(pSrcImg->GetNumBlocks(), pDstImg->GetNumBlocks()); + if (numBlocks <= 2880) + blocksPerRead = 9; // better granularity (one floppy track) + else + blocksPerRead = 64; // 32K per read; max seems to be 64K? - dataBuf = new unsigned char[blocksPerRead * 512]; - if (dataBuf == nil) { - dierr = kDIErrMalloc; - goto bail; - } + dataBuf = new unsigned char[blocksPerRead * 512]; + if (dataBuf == nil) { + dierr = kDIErrMalloc; + goto bail; + } - WMSG2("--- BLOCK COPY (%ld blocks, %d per)\n", - numBlocks, blocksPerRead); - for (long block = 0; block < numBlocks; ) { - long blocksThisTime = blocksPerRead; - if (block + blocksThisTime > numBlocks) - blocksThisTime = numBlocks - block; + WMSG2("--- BLOCK COPY (%ld blocks, %d per)\n", + numBlocks, blocksPerRead); + for (long block = 0; block < numBlocks; ) { + long blocksThisTime = blocksPerRead; + if (block + blocksThisTime > numBlocks) + blocksThisTime = numBlocks - block; - dierr = pSrcImg->ReadBlocks(block, blocksThisTime, dataBuf); - if (dierr != kDIErrNone) { - if (blocksThisTime != 1) { - /* - * Media with errors. Drop to one block per read. - */ - WMSG2(" Bad sector encountered at %ld(%ld), slowing\n", - block, blocksThisTime); - blocksThisTime = blocksPerRead = 1; - continue; // retry this block - } - numBadBlocks++; - dierr = kDIErrNone; - memset(dataBuf, 0, 512); - } - dierr = pDstImg->WriteBlocks(block, blocksThisTime, dataBuf); - if (dierr != kDIErrNone) { - if (dierr != kDIErrWriteProtected) { - errMsg.Format("ERROR: write of block %ld failed (%s)\n", - block, DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - } - goto bail; - } + dierr = pSrcImg->ReadBlocks(block, blocksThisTime, dataBuf); + if (dierr != kDIErrNone) { + if (blocksThisTime != 1) { + /* + * Media with errors. Drop to one block per read. + */ + WMSG2(" Bad sector encountered at %ld(%ld), slowing\n", + block, blocksThisTime); + blocksThisTime = blocksPerRead = 1; + continue; // retry this block + } + numBadBlocks++; + dierr = kDIErrNone; + memset(dataBuf, 0, 512); + } + dierr = pDstImg->WriteBlocks(block, blocksThisTime, dataBuf); + if (dierr != kDIErrNone) { + if (dierr != kDIErrWriteProtected) { + errMsg.Format("ERROR: write of block %ld failed (%s)\n", + block, DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + } + goto bail; + } - /* if we have a cancel dialog, keep it lively */ - if (pPCDialog != nil && (block % 18) == 0) { - int status; - PeekAndPump(); - LONGLONG bigBlock = block; - bigBlock = bigBlock * ProgressCancelDialog::kProgressResolution; - status = pPCDialog->SetProgress((int)(bigBlock / numBlocks)); - if (status == IDCANCEL) { - dierr = kDIErrCancelled; // pretend it came from DiskImg - goto bail; - } - } else if (bulk && (block % 512) == 0) { - PeekAndPump(); - } + /* if we have a cancel dialog, keep it lively */ + if (pPCDialog != nil && (block % 18) == 0) { + int status; + PeekAndPump(); + LONGLONG bigBlock = block; + bigBlock = bigBlock * ProgressCancelDialog::kProgressResolution; + status = pPCDialog->SetProgress((int)(bigBlock / numBlocks)); + if (status == IDCANCEL) { + dierr = kDIErrCancelled; // pretend it came from DiskImg + goto bail; + } + } else if (bulk && (block % 512) == 0) { + PeekAndPump(); + } - block += blocksThisTime; - } + block += blocksThisTime; + } - if (!bulk && numBadBlocks != 0) { - CString appName; - appName.LoadString(IDS_MB_APP_NAME); - errMsg.Format("Skipped %ld unreadable block%s.", numBadBlocks, - numBadBlocks == 1 ? "" : "s"); - MessageBox(errMsg, appName, MB_OK | MB_ICONWARNING); - } - } + if (!bulk && numBadBlocks != 0) { + CString appName; + appName.LoadString(IDS_MB_APP_NAME); + errMsg.Format("Skipped %ld unreadable block%s.", numBadBlocks, + numBadBlocks == 1 ? "" : "s"); + MessageBox(errMsg, appName, MB_OK | MB_ICONWARNING); + } + } bail: - delete[] dataBuf; - return dierr; + delete[] dataBuf; + return dierr; } /* * ========================================================================== - * Bulk disk convert + * Bulk disk convert * ========================================================================== */ @@ -1062,28 +1062,28 @@ bail: */ class BulkConvCancelDialog : public CancelDialog { public: - BOOL Create(CWnd* pParentWnd = NULL) { - fAbortOperation = false; - return CancelDialog::Create(&fAbortOperation, - IDD_BULKCONV, pParentWnd); - } + BOOL Create(CWnd* pParentWnd = NULL) { + fAbortOperation = false; + return CancelDialog::Create(&fAbortOperation, + IDD_BULKCONV, pParentWnd); + } - void SetCurrentFile(const char* fileName) { - CWnd* pWnd = GetDlgItem(IDC_BULKCONV_PATHNAME); - ASSERT(pWnd != nil); - pWnd->SetWindowText(fileName); - } + void SetCurrentFile(const char* fileName) { + CWnd* pWnd = GetDlgItem(IDC_BULKCONV_PATHNAME); + ASSERT(pWnd != nil); + pWnd->SetWindowText(fileName); + } - bool fAbortOperation; + bool fAbortOperation; private: - void OnOK(void) { - WMSG0("Ignoring BulkConvCancelDialog OnOK\n"); - } + void OnOK(void) { + WMSG0("Ignoring BulkConvCancelDialog OnOK\n"); + } - MainWindow* GetMainWindow(void) const { - return (MainWindow*)::AfxGetMainWnd(); - } + MainWindow* GetMainWindow(void) const { + return (MainWindow*)::AfxGetMainWnd(); + } }; /* @@ -1092,131 +1092,131 @@ private: void MainWindow::OnToolsBulkDiskConv(void) { - const int kFileNameBufSize = 32768; - DiskConvertDialog convDlg(this); - ChooseDirDialog chooseDirDlg(this); - BulkConvCancelDialog* pCancelDialog = new BulkConvCancelDialog; // on heap - CString openFilters, errMsg; - CString saveFolder, targetDir; - int nameCount; + const int kFileNameBufSize = 32768; + DiskConvertDialog convDlg(this); + ChooseDirDialog chooseDirDlg(this); + BulkConvCancelDialog* pCancelDialog = new BulkConvCancelDialog; // on heap + CString openFilters, errMsg; + CString saveFolder, targetDir; + int nameCount; - /* flush current archive in case that's what we're planning to convert */ - OnFileSave(); + /* flush current archive in case that's what we're planning to convert */ + OnFileSave(); - /* - * Select the set of images to convert. - */ - openFilters = kOpenDiskImage; - openFilters += kOpenAll; - openFilters += kOpenEnd; - CFileDialog dlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); + /* + * Select the set of images to convert. + */ + openFilters = kOpenDiskImage; + openFilters += kOpenAll; + openFilters += kOpenEnd; + CFileDialog dlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); - dlg.m_ofn.lpstrFile = new char[kFileNameBufSize]; - dlg.m_ofn.lpstrFile[0] = dlg.m_ofn.lpstrFile[1] = '\0'; - dlg.m_ofn.nMaxFile = kFileNameBufSize; - dlg.m_ofn.Flags |= OFN_HIDEREADONLY; // open all images as read-only - dlg.m_ofn.Flags |= OFN_ALLOWMULTISELECT; - dlg.m_ofn.lpstrTitle = "Select images to convert"; - dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); + dlg.m_ofn.lpstrFile = new char[kFileNameBufSize]; + dlg.m_ofn.lpstrFile[0] = dlg.m_ofn.lpstrFile[1] = '\0'; + dlg.m_ofn.nMaxFile = kFileNameBufSize; + dlg.m_ofn.Flags |= OFN_HIDEREADONLY; // open all images as read-only + dlg.m_ofn.Flags |= OFN_ALLOWMULTISELECT; + dlg.m_ofn.lpstrTitle = "Select images to convert"; + dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); - if (dlg.DoModal() != IDOK) - goto bail; + if (dlg.DoModal() != IDOK) + goto bail; - saveFolder = dlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); + saveFolder = dlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); - /* count up the number of entries */ - POSITION posn; - posn = dlg.GetStartPosition(); - nameCount = 0; - while (posn != nil) { - CString pathName; - pathName = dlg.GetNextPathName(posn); - nameCount++; - } - WMSG1("BulkConv got nameCount=%d\n", nameCount); + /* count up the number of entries */ + POSITION posn; + posn = dlg.GetStartPosition(); + nameCount = 0; + while (posn != nil) { + CString pathName; + pathName = dlg.GetNextPathName(posn); + nameCount++; + } + WMSG1("BulkConv got nameCount=%d\n", nameCount); - /* - * Choose the target directory. - * - * We use the "convert archive" folder by default. - */ - chooseDirDlg.SetPathName(fPreferences.GetPrefString(kPrConvertArchiveFolder)); - if (chooseDirDlg.DoModal() != IDOK) - goto bail; + /* + * Choose the target directory. + * + * We use the "convert archive" folder by default. + */ + chooseDirDlg.SetPathName(fPreferences.GetPrefString(kPrConvertArchiveFolder)); + if (chooseDirDlg.DoModal() != IDOK) + goto bail; - targetDir = chooseDirDlg.GetPathName(); - fPreferences.SetPrefString(kPrConvertArchiveFolder, targetDir); + targetDir = chooseDirDlg.GetPathName(); + fPreferences.SetPrefString(kPrConvertArchiveFolder, targetDir); - /* - * Put up a dialog to select the target conversion format. - * - * It is up to the user to select a format that matches the selected - * files. If it doesn't (e.g. converting an 800K floppy to DDD format), - * the process will fail later on. - */ - convDlg.Init(nameCount); - if (convDlg.DoModal() != IDOK) { - WMSG0(" User bailed out of convert dialog\n"); - goto bail; - } + /* + * Put up a dialog to select the target conversion format. + * + * It is up to the user to select a format that matches the selected + * files. If it doesn't (e.g. converting an 800K floppy to DDD format), + * the process will fail later on. + */ + convDlg.Init(nameCount); + if (convDlg.DoModal() != IDOK) { + WMSG0(" User bailed out of convert dialog\n"); + goto bail; + } - /* initialize cancel dialog, and disable main window */ - EnableWindow(FALSE); - if (pCancelDialog->Create(this) == FALSE) { - WMSG0("Cancel dialog init failed?!\n"); - ASSERT(false); - goto bail; - } + /* initialize cancel dialog, and disable main window */ + EnableWindow(FALSE); + if (pCancelDialog->Create(this) == FALSE) { + WMSG0("Cancel dialog init failed?!\n"); + ASSERT(false); + goto bail; + } - /* - * Loop through all selected files and convert them one at a time. - */ - posn = dlg.GetStartPosition(); - while (posn != nil) { - CString pathName; - pathName = dlg.GetNextPathName(posn); - WMSG1(" BulkConv: source path='%s'\n", pathName); + /* + * Loop through all selected files and convert them one at a time. + */ + posn = dlg.GetStartPosition(); + while (posn != nil) { + CString pathName; + pathName = dlg.GetNextPathName(posn); + WMSG1(" BulkConv: source path='%s'\n", pathName); - pCancelDialog->SetCurrentFile(FilenameOnly(pathName, '\\')); - PeekAndPump(); - if (pCancelDialog->fAbortOperation) - break; - BulkConvertImage(pathName, targetDir, convDlg, &errMsg); + pCancelDialog->SetCurrentFile(FilenameOnly(pathName, '\\')); + PeekAndPump(); + if (pCancelDialog->fAbortOperation) + break; + BulkConvertImage(pathName, targetDir, convDlg, &errMsg); - if (!errMsg.IsEmpty()) { - /* show error message, do OK/Cancel */ - /* do we need to delete the output file on failure? In general - we can't, because we could have failed because the file - already existed. */ - CString failed; - int res; + if (!errMsg.IsEmpty()) { + /* show error message, do OK/Cancel */ + /* do we need to delete the output file on failure? In general + we can't, because we could have failed because the file + already existed. */ + CString failed; + int res; - failed.LoadString(IDS_FAILED); - errMsg += "\n\nSource file: "; - errMsg += pathName; - errMsg += "\n\nClick OK to skip this and continue, or Cancel to " - "stop now."; - res = pCancelDialog->MessageBox(errMsg, - failed, MB_OKCANCEL | MB_ICONERROR); - if (res != IDOK) - goto bail; - } - } + failed.LoadString(IDS_FAILED); + errMsg += "\n\nSource file: "; + errMsg += pathName; + errMsg += "\n\nClick OK to skip this and continue, or Cancel to " + "stop now."; + res = pCancelDialog->MessageBox(errMsg, + failed, MB_OKCANCEL | MB_ICONERROR); + if (res != IDOK) + goto bail; + } + } - if (!pCancelDialog->fAbortOperation) - SuccessBeep(); + if (!pCancelDialog->fAbortOperation) + SuccessBeep(); bail: - // restore the main window to prominence - EnableWindow(TRUE); - //SetActiveWindow(); - if (pCancelDialog != nil) - pCancelDialog->DestroyWindow(); + // restore the main window to prominence + EnableWindow(TRUE); + //SetActiveWindow(); + if (pCancelDialog != nil) + pCancelDialog->DestroyWindow(); - delete[] dlg.m_ofn.lpstrFile; - return; + delete[] dlg.m_ofn.lpstrFile; + return; } /* @@ -1229,299 +1229,299 @@ bail: */ void MainWindow::BulkConvertImage(const char* pathName, const char* targetDir, - const DiskConvertDialog& convDlg, CString* pErrMsg) + const DiskConvertDialog& convDlg, CString* pErrMsg) { - DIError dierr; - CString saveName; - DiskImg srcImg, dstImg; - CString storageName; - PathName srcPath(pathName); - CString fileName, ext; + DIError dierr; + CString saveName; + DiskImg srcImg, dstImg; + CString storageName; + PathName srcPath(pathName); + CString fileName, ext; - *pErrMsg = ""; + *pErrMsg = ""; - dstImg.SetNuFXCompressionType( - fPreferences.GetPrefLong(kPrCompressionType)); + dstImg.SetNuFXCompressionType( + fPreferences.GetPrefLong(kPrCompressionType)); - /* open the image file and analyze it */ - dierr = srcImg.OpenImage(pathName, PathProposal::kLocalFssep, true); - if (dierr != kDIErrNone) { - pErrMsg->Format("Unable to open disk image: %s.", - DiskImgLib::DIStrError(dierr)); - goto bail; - } + /* open the image file and analyze it */ + dierr = srcImg.OpenImage(pathName, PathProposal::kLocalFssep, true); + if (dierr != kDIErrNone) { + pErrMsg->Format("Unable to open disk image: %s.", + DiskImgLib::DIStrError(dierr)); + goto bail; + } - if (srcImg.AnalyzeImage() != kDIErrNone) { - pErrMsg->Format("The file doesn't seem to hold a valid disk image."); - goto bail; - } + if (srcImg.AnalyzeImage() != kDIErrNone) { + pErrMsg->Format("The file doesn't seem to hold a valid disk image."); + goto bail; + } -#if 0 // don't feel like posting this UI - /* - * If we can't figure out the sector ordering, prompt the user. Don't - * go into it if they have "confirm format" selected, since that would be - * annoying. If they need to confirm it, they can use the one-at-a-time - * interface. - */ - if (srcImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown) { - if (TryDiskImgOverride(&srcImg, pathName, DiskImg::kFormatGenericProDOSOrd, - nil, pErrMsg) != IDOK) - { - *pErrMsg = "Image conversion cancelled."; - } - if (!pErrMsg->IsEmpty()) - goto bail; - } +#if 0 // don't feel like posting this UI + /* + * If we can't figure out the sector ordering, prompt the user. Don't + * go into it if they have "confirm format" selected, since that would be + * annoying. If they need to confirm it, they can use the one-at-a-time + * interface. + */ + if (srcImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown) { + if (TryDiskImgOverride(&srcImg, pathName, DiskImg::kFormatGenericProDOSOrd, + nil, pErrMsg) != IDOK) + { + *pErrMsg = "Image conversion cancelled."; + } + if (!pErrMsg->IsEmpty()) + goto bail; + } #else - if (srcImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown) { - *pErrMsg = "Could not determine the disk image sector ordering. You " - "may need to change the file extension."; - goto bail; - } + if (srcImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown) { + *pErrMsg = "Could not determine the disk image sector ordering. You " + "may need to change the file extension."; + goto bail; + } #endif - /* transfer the DOS volume num, if one was set */ - dstImg.SetDOSVolumeNum(srcImg.GetDOSVolumeNum()); - WMSG1("DOS volume number set to %d\n", dstImg.GetDOSVolumeNum()); + /* transfer the DOS volume num, if one was set */ + dstImg.SetDOSVolumeNum(srcImg.GetDOSVolumeNum()); + WMSG1("DOS volume number set to %d\n", dstImg.GetDOSVolumeNum()); - DiskImg::FSFormat origFSFormat; - origFSFormat = srcImg.GetFSFormat(); + DiskImg::FSFormat origFSFormat; + origFSFormat = srcImg.GetFSFormat(); - /* - * The converter always tries to read and write images as if they were - * ProDOS blocks. This way the only sector ordering changes are caused by - * differences in the sector ordering, rather than differences in the - * assumed filesystem types (which may not be knowable). - */ - dierr = srcImg.OverrideFormat(srcImg.GetPhysicalFormat(), - DiskImg::kFormatGenericProDOSOrd, srcImg.GetSectorOrder()); - if (dierr != kDIErrNone) { - pErrMsg->Format("Internal error: couldn't switch to generic ProDOS: %s.", - DiskImgLib::DIStrError(dierr)); - goto bail; - } + /* + * The converter always tries to read and write images as if they were + * ProDOS blocks. This way the only sector ordering changes are caused by + * differences in the sector ordering, rather than differences in the + * assumed filesystem types (which may not be knowable). + */ + dierr = srcImg.OverrideFormat(srcImg.GetPhysicalFormat(), + DiskImg::kFormatGenericProDOSOrd, srcImg.GetSectorOrder()); + if (dierr != kDIErrNone) { + pErrMsg->Format("Internal error: couldn't switch to generic ProDOS: %s.", + DiskImgLib::DIStrError(dierr)); + goto bail; + } - /* - * Examine their choices. - */ - DiskImg::OuterFormat outerFormat; - DiskImg::FileFormat fileFormat; - DiskImg::PhysicalFormat physicalFormat; - DiskImg::SectorOrder sectorOrder; + /* + * Examine their choices. + */ + DiskImg::OuterFormat outerFormat; + DiskImg::FileFormat fileFormat; + DiskImg::PhysicalFormat physicalFormat; + DiskImg::SectorOrder sectorOrder; - if (DetermineImageSettings(convDlg.fConvertIdx, (convDlg.fAddGzip != 0), - &outerFormat, &fileFormat, &physicalFormat, §orOrder) != 0) - { - *pErrMsg = "Odd: couldn't configure image settings"; - goto bail; - } + if (DetermineImageSettings(convDlg.fConvertIdx, (convDlg.fAddGzip != 0), + &outerFormat, &fileFormat, &physicalFormat, §orOrder) != 0) + { + *pErrMsg = "Odd: couldn't configure image settings"; + goto bail; + } - const DiskImg::NibbleDescr* pNibbleDescr; - pNibbleDescr = srcImg.GetNibbleDescr(); - if (pNibbleDescr == nil && DiskImg::IsNibbleFormat(physicalFormat)) { - /* - * We're writing to a nibble format, so we have to decide how the - * disk should be formatted. The source doesn't specify it, so we - * use generic 13- or 16-sector, defaulting to the latter when in - * doubt. - */ - if (srcImg.GetHasSectors() && srcImg.GetNumSectPerTrack() == 13) { - pNibbleDescr = DiskImg::GetStdNibbleDescr( - DiskImg::kNibbleDescrDOS32Std); - } else { - pNibbleDescr = DiskImg::GetStdNibbleDescr( - DiskImg::kNibbleDescrDOS33Std); - } - } - WMSG2(" NibbleDescr is 0x%08lx (%s)\n", (long) pNibbleDescr, - pNibbleDescr != nil ? pNibbleDescr->description : "---"); + const DiskImg::NibbleDescr* pNibbleDescr; + pNibbleDescr = srcImg.GetNibbleDescr(); + if (pNibbleDescr == nil && DiskImg::IsNibbleFormat(physicalFormat)) { + /* + * We're writing to a nibble format, so we have to decide how the + * disk should be formatted. The source doesn't specify it, so we + * use generic 13- or 16-sector, defaulting to the latter when in + * doubt. + */ + if (srcImg.GetHasSectors() && srcImg.GetNumSectPerTrack() == 13) { + pNibbleDescr = DiskImg::GetStdNibbleDescr( + DiskImg::kNibbleDescrDOS32Std); + } else { + pNibbleDescr = DiskImg::GetStdNibbleDescr( + DiskImg::kNibbleDescrDOS33Std); + } + } + WMSG2(" NibbleDescr is 0x%08lx (%s)\n", (long) pNibbleDescr, + pNibbleDescr != nil ? pNibbleDescr->description : "---"); - /* - * Create the new filename based on the old filename. - */ - saveName = targetDir; - if (saveName.Right(1) != '\\') - saveName += '\\'; - fileName = srcPath.GetFileName(); - ext = srcPath.GetExtension(); // extension, including '.' - if (ext.CompareNoCase(".gz") == 0) { - /* got a .gz, see if there's anything else in front of it */ - CString tmpName, ext2; - tmpName = srcPath.GetPathName(); - tmpName = tmpName.Left(tmpName.GetLength() - ext.GetLength()); - PathName tmpPath(tmpName); - ext2 = tmpPath.GetExtension(); - if (ext2.GetLength() >= 2 && ext2.GetLength() <= 4) - ext = ext2 + ext; + /* + * Create the new filename based on the old filename. + */ + saveName = targetDir; + if (saveName.Right(1) != '\\') + saveName += '\\'; + fileName = srcPath.GetFileName(); + ext = srcPath.GetExtension(); // extension, including '.' + if (ext.CompareNoCase(".gz") == 0) { + /* got a .gz, see if there's anything else in front of it */ + CString tmpName, ext2; + tmpName = srcPath.GetPathName(); + tmpName = tmpName.Left(tmpName.GetLength() - ext.GetLength()); + PathName tmpPath(tmpName); + ext2 = tmpPath.GetExtension(); + if (ext2.GetLength() >= 2 && ext2.GetLength() <= 4) + ext = ext2 + ext; - saveName += fileName.Left(fileName.GetLength() - ext.GetLength()); - } else { - if (ext.GetLength() < 2 || ext.GetLength() > 4) { - /* no meaningful extension */ - saveName += fileName; - } else { - saveName += fileName.Left(fileName.GetLength() - ext.GetLength()); - } - } - storageName = FilenameOnly(saveName, '\\'); // grab this for SHK name - saveName += '.'; - saveName += convDlg.fExtension; - WMSG2(" Bulk converting '%s' to '%s'\n", pathName, saveName); + saveName += fileName.Left(fileName.GetLength() - ext.GetLength()); + } else { + if (ext.GetLength() < 2 || ext.GetLength() > 4) { + /* no meaningful extension */ + saveName += fileName; + } else { + saveName += fileName.Left(fileName.GetLength() - ext.GetLength()); + } + } + storageName = FilenameOnly(saveName, '\\'); // grab this for SHK name + saveName += '.'; + saveName += convDlg.fExtension; + WMSG2(" Bulk converting '%s' to '%s'\n", pathName, saveName); - /* - * If this is a ProDOS volume, use the disk volume name as the default - * value for "storageName" (which is only used for NuFX archives). - */ - if (srcImg.GetFSFormat() == DiskImg::kFormatProDOS) { - CWaitCursor waitc; - DiskFS* pDiskFS = srcImg.OpenAppropriateDiskFS(); - // set "headerOnly" since we only need the volume name - dierr = pDiskFS->Initialize(&srcImg, DiskFS::kInitHeaderOnly); - if (dierr == kDIErrNone) { - storageName = pDiskFS->GetVolumeName(); - } - delete pDiskFS; - } else { - /* just use storageName as set earlier, unless target is DiskCopy42 */ - if (fileFormat == DiskImg::kFileFormatDiskCopy42) - storageName = ""; // want to use "not a mac disk" for non-ProDOS - } - WMSG1(" Using '%s' as storageName\n", storageName); + /* + * If this is a ProDOS volume, use the disk volume name as the default + * value for "storageName" (which is only used for NuFX archives). + */ + if (srcImg.GetFSFormat() == DiskImg::kFormatProDOS) { + CWaitCursor waitc; + DiskFS* pDiskFS = srcImg.OpenAppropriateDiskFS(); + // set "headerOnly" since we only need the volume name + dierr = pDiskFS->Initialize(&srcImg, DiskFS::kInitHeaderOnly); + if (dierr == kDIErrNone) { + storageName = pDiskFS->GetVolumeName(); + } + delete pDiskFS; + } else { + /* just use storageName as set earlier, unless target is DiskCopy42 */ + if (fileFormat == DiskImg::kFileFormatDiskCopy42) + storageName = ""; // want to use "not a mac disk" for non-ProDOS + } + WMSG1(" Using '%s' as storageName\n", storageName); - /* - * If the source is a UNIDOS volume and the target format is DiskCopy 4.2, - * use DOS sector ordering instead of ProDOS block ordering. For some - * reason the disks come out that way. - */ - if (origFSFormat == DiskImg::kFormatUNIDOS && - fileFormat == DiskImg::kFileFormatDiskCopy42) - { - WMSG0(" Switching to DOS sector ordering for UNIDOS/DiskCopy42"); - sectorOrder = DiskImg::kSectorOrderDOS; - } + /* + * If the source is a UNIDOS volume and the target format is DiskCopy 4.2, + * use DOS sector ordering instead of ProDOS block ordering. For some + * reason the disks come out that way. + */ + if (origFSFormat == DiskImg::kFormatUNIDOS && + fileFormat == DiskImg::kFileFormatDiskCopy42) + { + WMSG0(" Switching to DOS sector ordering for UNIDOS/DiskCopy42"); + sectorOrder = DiskImg::kSectorOrderDOS; + } - /* - * Create the image file. Adjust the number of tracks if we're - * copying to or from a TrackStar image. - */ - int dstNumTracks; - int dstNumBlocks; - bool isPartial; - dstNumTracks = srcImg.GetNumTracks(); - dstNumBlocks = srcImg.GetNumBlocks(); - isPartial = false; + /* + * Create the image file. Adjust the number of tracks if we're + * copying to or from a TrackStar image. + */ + int dstNumTracks; + int dstNumBlocks; + bool isPartial; + dstNumTracks = srcImg.GetNumTracks(); + dstNumBlocks = srcImg.GetNumBlocks(); + isPartial = false; - if (srcImg.GetFileFormat() == DiskImg::kFileFormatTrackStar && - fileFormat != DiskImg::kFileFormatTrackStar && - srcImg.GetNumTracks() == 40) - { - /* from TrackStar to other */ - dstNumTracks = 35; - dstNumBlocks = 280; - isPartial = true; - } - if (srcImg.GetFileFormat() == DiskImg::kFileFormatFDI && - fileFormat != DiskImg::kFileFormatTrackStar && - srcImg.GetNumTracks() != 35 && srcImg.GetNumBlocks() != 1600) - { - /* from 5.25" FDI to other */ - dstNumTracks = 35; - dstNumBlocks = 280; - isPartial = true; - } + if (srcImg.GetFileFormat() == DiskImg::kFileFormatTrackStar && + fileFormat != DiskImg::kFileFormatTrackStar && + srcImg.GetNumTracks() == 40) + { + /* from TrackStar to other */ + dstNumTracks = 35; + dstNumBlocks = 280; + isPartial = true; + } + if (srcImg.GetFileFormat() == DiskImg::kFileFormatFDI && + fileFormat != DiskImg::kFileFormatTrackStar && + srcImg.GetNumTracks() != 35 && srcImg.GetNumBlocks() != 1600) + { + /* from 5.25" FDI to other */ + dstNumTracks = 35; + dstNumBlocks = 280; + isPartial = true; + } - if (srcImg.GetFileFormat() != DiskImg::kFileFormatTrackStar && - fileFormat == DiskImg::kFileFormatTrackStar && - dstNumTracks == 35) - { - /* other to TrackStar */ - isPartial = true; - } + if (srcImg.GetFileFormat() != DiskImg::kFileFormatTrackStar && + fileFormat == DiskImg::kFileFormatTrackStar && + dstNumTracks == 35) + { + /* other to TrackStar */ + isPartial = true; + } - if (srcImg.GetHasNibbles() && - DiskImg::IsNibbleFormat(physicalFormat) && - physicalFormat == srcImg.GetPhysicalFormat()) - { - /* for nibble-to-nibble with the same track format, copy it - as collection of tracks */ - dierr = dstImg.CreateImage(saveName, storageName, - outerFormat, - fileFormat, - physicalFormat, - pNibbleDescr, - sectorOrder, - DiskImg::kFormatGenericProDOSOrd, - srcImg.GetNumTracks(), srcImg.GetNumSectPerTrack(), - false /* must format */); - } else if (srcImg.GetHasBlocks()) { - /* for general case, create as a block image */ - ASSERT(srcImg.GetHasBlocks()); - dierr = dstImg.CreateImage(saveName, storageName, - outerFormat, - fileFormat, - physicalFormat, - pNibbleDescr, - sectorOrder, - DiskImg::kFormatGenericProDOSOrd, - srcImg.GetNumBlocks(), - false /* only need for nibble? */); - } else if (srcImg.GetHasSectors()) { - /* - * We should only get here when converting to/from D13. We have to - * special-case this because this was originally written to support - * block copying as the lowest common denominator. D13 screwed - * everything up. :-) - */ - dierr = dstImg.CreateImage(saveName, storageName, - outerFormat, - fileFormat, - physicalFormat, - pNibbleDescr, - sectorOrder, - DiskImg::kFormatGenericProDOSOrd, // needs to match above - dstNumTracks, srcImg.GetNumSectPerTrack(), - false /* only need for dest=nibble? */); - } else { - /* e.g. unrecognizeable nibble to blocks */ - *pErrMsg = "Could not convert to requested format."; - goto bail; - } - if (dierr != kDIErrNone) { - if (dierr == kDIErrInvalidCreateReq) - *pErrMsg = "Could not convert to requested format."; - else - pErrMsg->Format("Couldn't construct disk image: %s.", - DiskImgLib::DIStrError(dierr)); - goto bail; - } + if (srcImg.GetHasNibbles() && + DiskImg::IsNibbleFormat(physicalFormat) && + physicalFormat == srcImg.GetPhysicalFormat()) + { + /* for nibble-to-nibble with the same track format, copy it + as collection of tracks */ + dierr = dstImg.CreateImage(saveName, storageName, + outerFormat, + fileFormat, + physicalFormat, + pNibbleDescr, + sectorOrder, + DiskImg::kFormatGenericProDOSOrd, + srcImg.GetNumTracks(), srcImg.GetNumSectPerTrack(), + false /* must format */); + } else if (srcImg.GetHasBlocks()) { + /* for general case, create as a block image */ + ASSERT(srcImg.GetHasBlocks()); + dierr = dstImg.CreateImage(saveName, storageName, + outerFormat, + fileFormat, + physicalFormat, + pNibbleDescr, + sectorOrder, + DiskImg::kFormatGenericProDOSOrd, + srcImg.GetNumBlocks(), + false /* only need for nibble? */); + } else if (srcImg.GetHasSectors()) { + /* + * We should only get here when converting to/from D13. We have to + * special-case this because this was originally written to support + * block copying as the lowest common denominator. D13 screwed + * everything up. :-) + */ + dierr = dstImg.CreateImage(saveName, storageName, + outerFormat, + fileFormat, + physicalFormat, + pNibbleDescr, + sectorOrder, + DiskImg::kFormatGenericProDOSOrd, // needs to match above + dstNumTracks, srcImg.GetNumSectPerTrack(), + false /* only need for dest=nibble? */); + } else { + /* e.g. unrecognizeable nibble to blocks */ + *pErrMsg = "Could not convert to requested format."; + goto bail; + } + if (dierr != kDIErrNone) { + if (dierr == kDIErrInvalidCreateReq) + *pErrMsg = "Could not convert to requested format."; + else + pErrMsg->Format("Couldn't construct disk image: %s.", + DiskImgLib::DIStrError(dierr)); + goto bail; + } - /* - * Do the actual copy, either as blocks or tracks. - */ - dierr = CopyDiskImage(&dstImg, &srcImg, true, isPartial, nil); - if (dierr != kDIErrNone) - goto bail; + /* + * Do the actual copy, either as blocks or tracks. + */ + dierr = CopyDiskImage(&dstImg, &srcImg, true, isPartial, nil); + if (dierr != kDIErrNone) + goto bail; - dierr = dstImg.CloseImage(); - if (dierr != kDIErrNone) { - pErrMsg->Format("ERROR: dstImg close failed (err=%d)\n", dierr); - goto bail; - } + dierr = dstImg.CloseImage(); + if (dierr != kDIErrNone) { + pErrMsg->Format("ERROR: dstImg close failed (err=%d)\n", dierr); + goto bail; + } - dierr = srcImg.CloseImage(); - if (dierr != kDIErrNone) { - pErrMsg->Format("ERROR: srcImg close failed (err=%d)\n", dierr); - goto bail; - } + dierr = srcImg.CloseImage(); + if (dierr != kDIErrNone) { + pErrMsg->Format("ERROR: srcImg close failed (err=%d)\n", dierr); + goto bail; + } bail: - return; + return; } /* * ========================================================================== - * SST Merge + * SST Merge * ========================================================================== */ @@ -1535,117 +1535,117 @@ const int kSSTTrackLen = 6656; void MainWindow::OnToolsSSTMerge(void) { - const int kBadCountThreshold = 3072; - DiskImg srcImg0, srcImg1; - CString appName, saveName, saveFolder, errMsg; + const int kBadCountThreshold = 3072; + DiskImg srcImg0, srcImg1; + CString appName, saveName, saveFolder, errMsg; unsigned char* trackBuf = nil; - long badCount; + long badCount; - // no need to flush -- can't really open raw SST images + // no need to flush -- can't really open raw SST images - CFileDialog saveDlg(FALSE, _T("nib"), NULL, - OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, - "All Files (*.*)|*.*||", this); + CFileDialog saveDlg(FALSE, _T("nib"), NULL, + OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, + "All Files (*.*)|*.*||", this); - appName.LoadString(IDS_MB_APP_NAME); + appName.LoadString(IDS_MB_APP_NAME); trackBuf = new unsigned char[kSSTNumTracks * kSSTTrackLen]; - if (trackBuf == nil) - goto bail; + if (trackBuf == nil) + goto bail; - /* - * Open the two images and verify that they are what they seem. - */ - badCount = 0; - if (SSTOpenImage(0, &srcImg0) != 0) - goto bail; + /* + * Open the two images and verify that they are what they seem. + */ + badCount = 0; + if (SSTOpenImage(0, &srcImg0) != 0) + goto bail; if (SSTLoadData(0, &srcImg0, trackBuf, &badCount) != 0) - goto bail; - WMSG1("FOUND %ld bad bytes in part 0\n", badCount); - if (badCount > kBadCountThreshold) { - errMsg.LoadString(IDS_BAD_SST_IMAGE); - if (MessageBox(errMsg, appName, MB_OKCANCEL | MB_ICONWARNING) != IDOK) - goto bail; - } + goto bail; + WMSG1("FOUND %ld bad bytes in part 0\n", badCount); + if (badCount > kBadCountThreshold) { + errMsg.LoadString(IDS_BAD_SST_IMAGE); + if (MessageBox(errMsg, appName, MB_OKCANCEL | MB_ICONWARNING) != IDOK) + goto bail; + } - badCount = 0; - if (SSTOpenImage(1, &srcImg1) != 0) - goto bail; + badCount = 0; + if (SSTOpenImage(1, &srcImg1) != 0) + goto bail; if (SSTLoadData(1, &srcImg1, trackBuf, &badCount) != 0) - goto bail; - WMSG1("FOUND %ld bad bytes in part 1\n", badCount); - if (badCount > kBadCountThreshold) { - errMsg.LoadString(IDS_BAD_SST_IMAGE); - if (MessageBox(errMsg, appName, MB_OKCANCEL | MB_ICONWARNING) != IDOK) - goto bail; - } + goto bail; + WMSG1("FOUND %ld bad bytes in part 1\n", badCount); + if (badCount > kBadCountThreshold) { + errMsg.LoadString(IDS_BAD_SST_IMAGE); + if (MessageBox(errMsg, appName, MB_OKCANCEL | MB_ICONWARNING) != IDOK) + goto bail; + } - /* - * Realign the tracks and OR 0x80 to everything. - */ + /* + * Realign the tracks and OR 0x80 to everything. + */ SSTProcessTrackData(trackBuf); - /* - * Pick the output file and write the buffer to it. - */ - saveDlg.m_ofn.lpstrTitle = _T("Save .NIB disk image as..."); - saveDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); - if (saveDlg.DoModal() != IDOK) { - WMSG0(" User bailed out of image save dialog\n"); - goto bail; - } - saveFolder = saveDlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(saveDlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); + /* + * Pick the output file and write the buffer to it. + */ + saveDlg.m_ofn.lpstrTitle = _T("Save .NIB disk image as..."); + saveDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); + if (saveDlg.DoModal() != IDOK) { + WMSG0(" User bailed out of image save dialog\n"); + goto bail; + } + saveFolder = saveDlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(saveDlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); - saveName = saveDlg.GetPathName(); - WMSG1("File will be saved to '%s'\n", saveName); + saveName = saveDlg.GetPathName(); + WMSG1("File will be saved to '%s'\n", saveName); - /* remove the file if it exists */ - errMsg = RemoveFile(saveName); - if (!errMsg.IsEmpty()) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + /* remove the file if it exists */ + errMsg = RemoveFile(saveName); + if (!errMsg.IsEmpty()) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - FILE* fp; - fp = fopen(saveName, "wb"); - if (fp == nil) { - errMsg.Format("Unable to create '%s': %s.", - saveName, strerror(errno)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + FILE* fp; + fp = fopen(saveName, "wb"); + if (fp == nil) { + errMsg.Format("Unable to create '%s': %s.", + saveName, strerror(errno)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } if (fwrite(trackBuf, kSSTNumTracks * kSSTTrackLen, 1, fp) != 1) { - errMsg.Format("Failed while writing to new image file: %s.", - strerror(errno)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - fclose(fp); - goto bail; - } + errMsg.Format("Failed while writing to new image file: %s.", + strerror(errno)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + fclose(fp); + goto bail; + } - fclose(fp); + fclose(fp); - SuccessBeep(); + SuccessBeep(); - /* - * We're done. Give them the opportunity to open the disk image they - * just created. - */ - { - DoneOpenDialog doneOpen(this); + /* + * We're done. Give them the opportunity to open the disk image they + * just created. + */ + { + DoneOpenDialog doneOpen(this); - if (doneOpen.DoModal() == IDOK) { - WMSG1(" At user request, opening '%s'\n", saveName); + if (doneOpen.DoModal() == IDOK) { + WMSG1(" At user request, opening '%s'\n", saveName); - DoOpenArchive(saveName, "nib", kFilterIndexDiskImage, false); - } - } + DoOpenArchive(saveName, "nib", kFilterIndexDiskImage, false); + } + } bail: delete[] trackBuf; - return; + return; } /* @@ -1658,97 +1658,97 @@ bail: int MainWindow::SSTOpenImage(int seqNum, DiskImg* pDiskImg) { - DIError dierr; - int result = -1; - CString openFilters, errMsg; - CString loadName, saveFolder; + DIError dierr; + int result = -1; + CString openFilters, errMsg; + CString loadName, saveFolder; - /* - * Select the image to convert. - */ - openFilters = kOpenDiskImage; - openFilters += kOpenAll; - openFilters += kOpenEnd; - CFileDialog dlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); + /* + * Select the image to convert. + */ + openFilters = kOpenDiskImage; + openFilters += kOpenAll; + openFilters += kOpenEnd; + CFileDialog dlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); - dlg.m_ofn.Flags |= OFN_HIDEREADONLY; - if (seqNum == 0) - dlg.m_ofn.lpstrTitle = "Select first SST image"; - else - dlg.m_ofn.lpstrTitle = "Select second SST image"; - dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); + dlg.m_ofn.Flags |= OFN_HIDEREADONLY; + if (seqNum == 0) + dlg.m_ofn.lpstrTitle = "Select first SST image"; + else + dlg.m_ofn.lpstrTitle = "Select second SST image"; + dlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); - if (dlg.DoModal() != IDOK) - goto bail; - loadName = dlg.GetPathName(); + if (dlg.DoModal() != IDOK) + goto bail; + loadName = dlg.GetPathName(); - saveFolder = dlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); + saveFolder = dlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); - /* open the image file and analyze it */ - dierr = pDiskImg->OpenImage(loadName, PathProposal::kLocalFssep, true); - if (dierr != kDIErrNone) { - errMsg.Format("Unable to open disk image: %s.", - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + /* open the image file and analyze it */ + dierr = pDiskImg->OpenImage(loadName, PathProposal::kLocalFssep, true); + if (dierr != kDIErrNone) { + errMsg.Format("Unable to open disk image: %s.", + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - if (pDiskImg->AnalyzeImage() != kDIErrNone) { - errMsg.Format("The file '%s' doesn't seem to hold a valid disk image.", - loadName); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + if (pDiskImg->AnalyzeImage() != kDIErrNone) { + errMsg.Format("The file '%s' doesn't seem to hold a valid disk image.", + loadName); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - /* - * If confirm image format is set, or we can't figure out the sector - * ordering, prompt the user. - */ - if (pDiskImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown || - fPreferences.GetPrefBool(kPrQueryImageFormat)) - { - if (TryDiskImgOverride(pDiskImg, loadName, - DiskImg::kFormatGenericDOSOrd, nil, false, &errMsg) != IDOK) - { - goto bail; - } - if (!errMsg.IsEmpty()) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } - } + /* + * If confirm image format is set, or we can't figure out the sector + * ordering, prompt the user. + */ + if (pDiskImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown || + fPreferences.GetPrefBool(kPrQueryImageFormat)) + { + if (TryDiskImgOverride(pDiskImg, loadName, + DiskImg::kFormatGenericDOSOrd, nil, false, &errMsg) != IDOK) + { + goto bail; + } + if (!errMsg.IsEmpty()) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } + } if (pDiskImg->GetFSFormat() != DiskImg::kFormatUnknown && - !DiskImg::IsGenericFormat(pDiskImg->GetFSFormat())) - { - errMsg = "This disk image appears to have a valid filesystem. SST" - " images are just raw track dumps."; - ShowFailureMsg(this, errMsg, IDS_FAILED); + !DiskImg::IsGenericFormat(pDiskImg->GetFSFormat())) + { + errMsg = "This disk image appears to have a valid filesystem. SST" + " images are just raw track dumps."; + ShowFailureMsg(this, errMsg, IDS_FAILED); goto bail; } if (pDiskImg->GetNumTracks() != kSSTNumTracks || pDiskImg->GetNumSectPerTrack() != kSSTNumSectPerTrack) { errMsg = "ERROR: only 5.25\" floppy disk images can be SST inputs."; - ShowFailureMsg(this, errMsg, IDS_FAILED); + ShowFailureMsg(this, errMsg, IDS_FAILED); goto bail; } - /* use DOS filesystem sector ordering */ + /* use DOS filesystem sector ordering */ dierr = pDiskImg->OverrideFormat(pDiskImg->GetPhysicalFormat(), DiskImg::kFormatGenericDOSOrd, pDiskImg->GetSectorOrder()); if (dierr != kDIErrNone) { errMsg = "ERROR: internal failure: format override failed."; - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; } - result = 0; + result = 0; bail: - return result; + return result; } /* @@ -1761,7 +1761,7 @@ bail: */ int MainWindow::SSTLoadData(int seqNum, DiskImg* pDiskImg, unsigned char* trackBuf, - long* pBadCount) + long* pBadCount) { DIError dierr; unsigned char sctBuf[256]; @@ -1784,7 +1784,7 @@ MainWindow::SSTLoadData(int seqNum, DiskImg* pDiskImg, unsigned char* trackBuf, return -1; } - *pBadCount += SSTCountBadBytes(sctBuf, 256); + *pBadCount += SSTCountBadBytes(sctBuf, 256); memcpy(trackBuf + bufOffset, sctBuf, 256); bufOffset += 256; @@ -1798,9 +1798,9 @@ MainWindow::SSTLoadData(int seqNum, DiskImg* pDiskImg, unsigned char* trackBuf, return -1; } - *pBadCount += SSTCountBadBytes(sctBuf, 256); + *pBadCount += SSTCountBadBytes(sctBuf, 256); - memcpy(trackBuf + bufOffset, sctBuf, 256); + memcpy(trackBuf + bufOffset, sctBuf, 256); bufOffset += 256; } } @@ -1852,17 +1852,17 @@ MainWindow::SSTGetBufOffset(int track) long MainWindow::SSTCountBadBytes(const unsigned char* sctBuf, int count) { - long badCount = 0; - unsigned char uch; + long badCount = 0; + unsigned char uch; - while (count--) { - uch = (*sctBuf) | 0x80; - if (uch >= 0x80 && uch <= 0x92) - badCount++; - sctBuf++; - } + while (count--) { + uch = (*sctBuf) | 0x80; + if (uch >= 0x80 && uch <= 0x92) + badCount++; + sctBuf++; + } - return badCount; + return badCount; } /* @@ -1932,19 +1932,19 @@ MainWindow::SSTProcessTrackData(unsigned char* trackBuf) /* * ========================================================================== - * Volume Copier + * Volume Copier * ========================================================================== */ void MainWindow::OnToolsVolumeCopierVolume(void) { - VolumeCopier(false); + VolumeCopier(false); } void MainWindow::OnToolsVolumeCopierFile(void) { - VolumeCopier(true); + VolumeCopier(true); } /* @@ -1953,135 +1953,135 @@ MainWindow::OnToolsVolumeCopierFile(void) void MainWindow::VolumeCopier(bool openFile) { - VolumeCopyDialog copyDlg(this); - DiskImg srcImg; - //DiskFS* pDiskFS = nil; - DIError dierr; - CString failed, errMsg, msg; - CString deviceName; - bool readOnly = false; - int result; + VolumeCopyDialog copyDlg(this); + DiskImg srcImg; + //DiskFS* pDiskFS = nil; + DIError dierr; + CString failed, errMsg, msg; + CString deviceName; + bool readOnly = false; + int result; - /* flush current archive in case that's what we're planning to edit */ - OnFileSave(); + /* flush current archive in case that's what we're planning to edit */ + OnFileSave(); - failed.LoadString(IDS_FAILED); + failed.LoadString(IDS_FAILED); - if (!openFile) { - /* - * Select the volume to manipulate. - */ - OpenVolumeDialog openVolDlg(this); - //openVolDlg.fReadOnly = false; - //openVolDlg.fAllowROChange = true; - result = openVolDlg.DoModal(); - if (result != IDOK) - goto bail; - deviceName = openVolDlg.fChosenDrive; - readOnly = (openVolDlg.fReadOnly != 0); - } else { - /* - * Open a disk image file instead. - */ - CString openFilters; - openFilters = kOpenDiskImage; - openFilters += kOpenAll; - openFilters += kOpenEnd; - CFileDialog fileDlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); + if (!openFile) { + /* + * Select the volume to manipulate. + */ + OpenVolumeDialog openVolDlg(this); + //openVolDlg.fReadOnly = false; + //openVolDlg.fAllowROChange = true; + result = openVolDlg.DoModal(); + if (result != IDOK) + goto bail; + deviceName = openVolDlg.fChosenDrive; + readOnly = (openVolDlg.fReadOnly != 0); + } else { + /* + * Open a disk image file instead. + */ + CString openFilters; + openFilters = kOpenDiskImage; + openFilters += kOpenAll; + openFilters += kOpenEnd; + CFileDialog fileDlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); - //dlg.m_ofn.Flags |= OFN_HIDEREADONLY; - fileDlg.m_ofn.Flags &= ~(OFN_READONLY); - fileDlg.m_ofn.lpstrTitle = "Select disk image file"; - fileDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); + //dlg.m_ofn.Flags |= OFN_HIDEREADONLY; + fileDlg.m_ofn.Flags &= ~(OFN_READONLY); + fileDlg.m_ofn.lpstrTitle = "Select disk image file"; + fileDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); - if (fileDlg.DoModal() != IDOK) - goto bail; - deviceName = fileDlg.GetPathName(); - readOnly = (fileDlg.GetReadOnlyPref() != 0); - } + if (fileDlg.DoModal() != IDOK) + goto bail; + deviceName = fileDlg.GetPathName(); + readOnly = (fileDlg.GetReadOnlyPref() != 0); + } - /* - * Open the disk image and figure out what it is. - */ - { - CWaitCursor waitc; + /* + * Open the disk image and figure out what it is. + */ + { + CWaitCursor waitc; - DiskImg::SetAllowWritePhys0(false); + DiskImg::SetAllowWritePhys0(false); - dierr = srcImg.OpenImage(deviceName, '\0', readOnly); - if (dierr == kDIErrAccessDenied) { - if (openFile) { - errMsg.Format("Unable to open '%s': %s (try opening the file" - " with 'Read Only' checked).", deviceName, - DiskImgLib::DIStrError(dierr)); - } else if (!IsWin9x() && !openFile) { - errMsg.Format("Unable to open '%s': %s (make sure you have" - " administrator privileges).", deviceName, - DiskImgLib::DIStrError(dierr)); - } else { - errMsg.Format("Unable to open '%s': %s.", deviceName, - DiskImgLib::DIStrError(dierr)); - } - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } else if (dierr != kDIErrNone) { - errMsg.Format("Unable to open '%s': %s.", deviceName, - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + dierr = srcImg.OpenImage(deviceName, '\0', readOnly); + if (dierr == kDIErrAccessDenied) { + if (openFile) { + errMsg.Format("Unable to open '%s': %s (try opening the file" + " with 'Read Only' checked).", deviceName, + DiskImgLib::DIStrError(dierr)); + } else if (!IsWin9x() && !openFile) { + errMsg.Format("Unable to open '%s': %s (make sure you have" + " administrator privileges).", deviceName, + DiskImgLib::DIStrError(dierr)); + } else { + errMsg.Format("Unable to open '%s': %s.", deviceName, + DiskImgLib::DIStrError(dierr)); + } + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } else if (dierr != kDIErrNone) { + errMsg.Format("Unable to open '%s': %s.", deviceName, + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - /* analyze it to get #of blocks and determine the FS */ - if (srcImg.AnalyzeImage() != kDIErrNone) { - errMsg.Format("There isn't a valid disk image here?!?"); - MessageBox(errMsg, failed, MB_OK|MB_ICONSTOP); - goto bail; - } - } + /* analyze it to get #of blocks and determine the FS */ + if (srcImg.AnalyzeImage() != kDIErrNone) { + errMsg.Format("There isn't a valid disk image here?!?"); + MessageBox(errMsg, failed, MB_OK|MB_ICONSTOP); + goto bail; + } + } - /* - * If requested (or necessary), verify the format. - */ - if (srcImg.GetFSFormat() == DiskImg::kFormatUnknown || - srcImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown || - fPreferences.GetPrefBool(kPrQueryImageFormat)) - { - if (TryDiskImgOverride(&srcImg, deviceName, DiskImg::kFormatUnknown, - nil, true, &errMsg) != IDOK) - { - goto bail; - } - if (!errMsg.IsEmpty()) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } - } + /* + * If requested (or necessary), verify the format. + */ + if (srcImg.GetFSFormat() == DiskImg::kFormatUnknown || + srcImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown || + fPreferences.GetPrefBool(kPrQueryImageFormat)) + { + if (TryDiskImgOverride(&srcImg, deviceName, DiskImg::kFormatUnknown, + nil, true, &errMsg) != IDOK) + { + goto bail; + } + if (!errMsg.IsEmpty()) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } + } - /* - * Hand the DiskImg object off to the volume copier dialog. - */ - copyDlg.fpDiskImg = &srcImg; - copyDlg.fPathName = deviceName; - (void) copyDlg.DoModal(); + /* + * Hand the DiskImg object off to the volume copier dialog. + */ + copyDlg.fpDiskImg = &srcImg; + copyDlg.fPathName = deviceName; + (void) copyDlg.DoModal(); - /* - * The volume copier could have modified our open file. If it has, - * we need to close and reopen the archive. - */ - srcImg.CloseImage(); // could interfere with volume reopen - if (fNeedReopen) { - PeekAndPump(); // clear out dialog - ReopenArchive(); - } + /* + * The volume copier could have modified our open file. If it has, + * we need to close and reopen the archive. + */ + srcImg.CloseImage(); // could interfere with volume reopen + if (fNeedReopen) { + PeekAndPump(); // clear out dialog + ReopenArchive(); + } bail: - return; + return; } /* * ========================================================================== - * Disk image creator + * Disk image creator * ========================================================================== */ @@ -2091,180 +2091,180 @@ bail: void MainWindow::OnToolsDiskImageCreator(void) { - CreateImageDialog createDlg(this); - DiskArchive* pNewArchive = nil; + CreateImageDialog createDlg(this); + DiskArchive* pNewArchive = nil; - createDlg.fDiskFormatIdx = - fPreferences.GetPrefLong(kPrDiskImageCreateFormat); - if (createDlg.fDiskFormatIdx < 0) - createDlg.fDiskFormatIdx = CreateImageDialog::kFmtProDOS; + createDlg.fDiskFormatIdx = + fPreferences.GetPrefLong(kPrDiskImageCreateFormat); + if (createDlg.fDiskFormatIdx < 0) + createDlg.fDiskFormatIdx = CreateImageDialog::kFmtProDOS; - /* - * Ask the user what sort of disk they'd like to create. - */ - if (createDlg.DoModal() != IDOK) - return; + /* + * Ask the user what sort of disk they'd like to create. + */ + if (createDlg.DoModal() != IDOK) + return; - fPreferences.SetPrefLong(kPrDiskImageCreateFormat, createDlg.fDiskFormatIdx); + fPreferences.SetPrefLong(kPrDiskImageCreateFormat, createDlg.fDiskFormatIdx); - /* - * Set up the options struct. We set base.sectorOrder later. - */ - assert(createDlg.fNumBlocks > 0); + /* + * Set up the options struct. We set base.sectorOrder later. + */ + assert(createDlg.fNumBlocks > 0); - DiskArchive::NewOptions options; - memset(&options, 0, sizeof(options)); - switch (createDlg.fDiskFormatIdx) { - case CreateImageDialog::kFmtBlank: - options.base.format = DiskImg::kFormatUnknown; - options.blank.numBlocks = createDlg.fNumBlocks; - break; - case CreateImageDialog::kFmtProDOS: - options.base.format = DiskImg::kFormatProDOS; - options.prodos.numBlocks = createDlg.fNumBlocks; - options.prodos.volName = createDlg.fVolName_ProDOS; - break; - case CreateImageDialog::kFmtPascal: - options.base.format = DiskImg::kFormatPascal; - options.pascalfs.numBlocks = createDlg.fNumBlocks; - options.pascalfs.volName = createDlg.fVolName_Pascal; - break; - case CreateImageDialog::kFmtHFS: - options.base.format = DiskImg::kFormatMacHFS; - options.hfs.numBlocks = createDlg.fNumBlocks; - options.hfs.volName = createDlg.fVolName_HFS; - break; - case CreateImageDialog::kFmtDOS32: - options.base.format = DiskImg::kFormatDOS32; - options.dos.volumeNum = createDlg.fDOSVolumeNum; - options.dos.allocDOSTracks = (createDlg.fAllocTracks_DOS != 0); - options.dos.numTracks = 35; - options.dos.numSectors = 13; - break; - case CreateImageDialog::kFmtDOS33: - options.base.format = DiskImg::kFormatDOS33; - options.dos.volumeNum = createDlg.fDOSVolumeNum; - options.dos.allocDOSTracks = (createDlg.fAllocTracks_DOS != 0); - if (createDlg.fNumBlocks <= 400) { - ASSERT(createDlg.fNumBlocks % 8 == 0); - options.dos.numTracks = createDlg.fNumBlocks / 8; - options.dos.numSectors = 16; - } else if (createDlg.fNumBlocks <= 800) { - ASSERT(createDlg.fNumBlocks % 16 == 0); - options.dos.numTracks = createDlg.fNumBlocks / 16; - options.dos.numSectors = 32; - options.dos.allocDOSTracks = false; - } else { - ASSERT(false); - return; - } - break; - default: - WMSG1("Invalid fDiskFormatIdx %d from CreateImageDialog\n", - createDlg.fDiskFormatIdx); - ASSERT(false); - return; - } + DiskArchive::NewOptions options; + memset(&options, 0, sizeof(options)); + switch (createDlg.fDiskFormatIdx) { + case CreateImageDialog::kFmtBlank: + options.base.format = DiskImg::kFormatUnknown; + options.blank.numBlocks = createDlg.fNumBlocks; + break; + case CreateImageDialog::kFmtProDOS: + options.base.format = DiskImg::kFormatProDOS; + options.prodos.numBlocks = createDlg.fNumBlocks; + options.prodos.volName = createDlg.fVolName_ProDOS; + break; + case CreateImageDialog::kFmtPascal: + options.base.format = DiskImg::kFormatPascal; + options.pascalfs.numBlocks = createDlg.fNumBlocks; + options.pascalfs.volName = createDlg.fVolName_Pascal; + break; + case CreateImageDialog::kFmtHFS: + options.base.format = DiskImg::kFormatMacHFS; + options.hfs.numBlocks = createDlg.fNumBlocks; + options.hfs.volName = createDlg.fVolName_HFS; + break; + case CreateImageDialog::kFmtDOS32: + options.base.format = DiskImg::kFormatDOS32; + options.dos.volumeNum = createDlg.fDOSVolumeNum; + options.dos.allocDOSTracks = (createDlg.fAllocTracks_DOS != 0); + options.dos.numTracks = 35; + options.dos.numSectors = 13; + break; + case CreateImageDialog::kFmtDOS33: + options.base.format = DiskImg::kFormatDOS33; + options.dos.volumeNum = createDlg.fDOSVolumeNum; + options.dos.allocDOSTracks = (createDlg.fAllocTracks_DOS != 0); + if (createDlg.fNumBlocks <= 400) { + ASSERT(createDlg.fNumBlocks % 8 == 0); + options.dos.numTracks = createDlg.fNumBlocks / 8; + options.dos.numSectors = 16; + } else if (createDlg.fNumBlocks <= 800) { + ASSERT(createDlg.fNumBlocks % 16 == 0); + options.dos.numTracks = createDlg.fNumBlocks / 16; + options.dos.numSectors = 32; + options.dos.allocDOSTracks = false; + } else { + ASSERT(false); + return; + } + break; + default: + WMSG1("Invalid fDiskFormatIdx %d from CreateImageDialog\n", + createDlg.fDiskFormatIdx); + ASSERT(false); + return; + } - /* - * Select the file to store it in. - */ - CString filename, saveFolder, errStr; - int filterIndex = 1; - CString formats; + /* + * Select the file to store it in. + */ + CString filename, saveFolder, errStr; + int filterIndex = 1; + CString formats; - if (createDlg.fDiskFormatIdx == CreateImageDialog::kFmtDOS32) { - formats = "13-sector disk (*.d13)|*.d13|"; - } else { - formats = "ProDOS-ordered image (*.po)|*.po|"; - if (createDlg.fNumBlocks == 280) { - formats += "DOS-ordered image (*.do)|*.do|"; - filterIndex = 2; - } - } - formats += "|"; + if (createDlg.fDiskFormatIdx == CreateImageDialog::kFmtDOS32) { + formats = "13-sector disk (*.d13)|*.d13|"; + } else { + formats = "ProDOS-ordered image (*.po)|*.po|"; + if (createDlg.fNumBlocks == 280) { + formats += "DOS-ordered image (*.do)|*.do|"; + filterIndex = 2; + } + } + formats += "|"; - CFileDialog saveDlg(FALSE, _T("po"), NULL, - OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, - formats, this); - saveDlg.m_ofn.lpstrTitle = "New Disk Image"; - saveDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); - saveDlg.m_ofn.nFilterIndex = filterIndex; + CFileDialog saveDlg(FALSE, _T("po"), NULL, + OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, + formats, this); + saveDlg.m_ofn.lpstrTitle = "New Disk Image"; + saveDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); + saveDlg.m_ofn.nFilterIndex = filterIndex; - if (saveDlg.DoModal() != IDOK) { - WMSG0(" User cancelled xfer from image create dialog\n"); - return; - } + if (saveDlg.DoModal() != IDOK) { + WMSG0(" User cancelled xfer from image create dialog\n"); + return; + } - saveFolder = saveDlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(saveDlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); + saveFolder = saveDlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(saveDlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); - filename = saveDlg.GetPathName(); - WMSG2(" Will xfer to file '%s' (filterIndex=%d)\n", - filename, saveDlg.m_ofn.nFilterIndex); + filename = saveDlg.GetPathName(); + WMSG2(" Will xfer to file '%s' (filterIndex=%d)\n", + filename, saveDlg.m_ofn.nFilterIndex); - if (createDlg.fDiskFormatIdx == CreateImageDialog::kFmtDOS32) { - options.base.sectorOrder = DiskImg::kSectorOrderDOS; - } else { - if (saveDlg.m_ofn.nFilterIndex == 2) - options.base.sectorOrder = DiskImg::kSectorOrderDOS; - else - options.base.sectorOrder = DiskImg::kSectorOrderProDOS; - } + if (createDlg.fDiskFormatIdx == CreateImageDialog::kFmtDOS32) { + options.base.sectorOrder = DiskImg::kSectorOrderDOS; + } else { + if (saveDlg.m_ofn.nFilterIndex == 2) + options.base.sectorOrder = DiskImg::kSectorOrderDOS; + else + options.base.sectorOrder = DiskImg::kSectorOrderProDOS; + } - /* remove file if it already exists */ - CString errMsg; - errMsg = RemoveFile(filename); - if (!errMsg.IsEmpty()) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - return; - } + /* remove file if it already exists */ + CString errMsg; + errMsg = RemoveFile(filename); + if (!errMsg.IsEmpty()) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + return; + } - pNewArchive = new DiskArchive; + pNewArchive = new DiskArchive; - /* create the new archive, showing a "busy" message */ - { - ExclusiveModelessDialog* pWaitDlg = new ExclusiveModelessDialog; - pWaitDlg->Create(IDD_FORMATTING, this); - pWaitDlg->CenterWindow(); - PeekAndPump(); // redraw - CWaitCursor waitc; + /* create the new archive, showing a "busy" message */ + { + ExclusiveModelessDialog* pWaitDlg = new ExclusiveModelessDialog; + pWaitDlg->Create(IDD_FORMATTING, this); + pWaitDlg->CenterWindow(); + PeekAndPump(); // redraw + CWaitCursor waitc; - errStr = pNewArchive->New(filename, &options); + errStr = pNewArchive->New(filename, &options); - pWaitDlg->DestroyWindow(); - //PeekAndPump(); // redraw - } + pWaitDlg->DestroyWindow(); + //PeekAndPump(); // redraw + } - delete pNewArchive; // close it, either way - if (!errStr.IsEmpty()) { - ShowFailureMsg(this, errStr, IDS_FAILED); - (void) unlink(filename); - } else { - WMSG0("Disk image created successfully\n"); + delete pNewArchive; // close it, either way + if (!errStr.IsEmpty()) { + ShowFailureMsg(this, errStr, IDS_FAILED); + (void) unlink(filename); + } else { + WMSG0("Disk image created successfully\n"); #if 0 - SuccessBeep(); + SuccessBeep(); - /* give them the opportunity to open the new disk image */ - DoneOpenDialog doneOpen(this); + /* give them the opportunity to open the new disk image */ + DoneOpenDialog doneOpen(this); - if (doneOpen.DoModal() == IDOK) { - WMSG1(" At user request, opening '%s'\n", filename); + if (doneOpen.DoModal() == IDOK) { + WMSG1(" At user request, opening '%s'\n", filename); - DoOpenArchive(filename, "dsk", kFilterIndexDiskImage, false); - } + DoOpenArchive(filename, "dsk", kFilterIndexDiskImage, false); + } #else - if (createDlg.fDiskFormatIdx != CreateImageDialog::kFmtBlank) - DoOpenArchive(filename, "dsk", kFilterIndexDiskImage, false); + if (createDlg.fDiskFormatIdx != CreateImageDialog::kFmtBlank) + DoOpenArchive(filename, "dsk", kFilterIndexDiskImage, false); #endif - } + } } /* * ========================================================================== - * EOL scanner + * EOL scanner * ========================================================================== */ @@ -2276,87 +2276,87 @@ MainWindow::OnToolsDiskImageCreator(void) void MainWindow::OnToolsEOLScanner(void) { - CString fileName, saveFolder, errMsg; + CString fileName, saveFolder, errMsg; - CString openFilters; - openFilters = kOpenAll; - openFilters += kOpenEnd; - CFileDialog fileDlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); + CString openFilters; + openFilters = kOpenAll; + openFilters += kOpenEnd; + CFileDialog fileDlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); - fileDlg.m_ofn.Flags |= OFN_HIDEREADONLY; - //fileDlg.m_ofn.Flags &= ~(OFN_READONLY); - fileDlg.m_ofn.lpstrTitle = "Select file to scan"; - fileDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); + fileDlg.m_ofn.Flags |= OFN_HIDEREADONLY; + //fileDlg.m_ofn.Flags &= ~(OFN_READONLY); + fileDlg.m_ofn.lpstrTitle = "Select file to scan"; + fileDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); - if (fileDlg.DoModal() != IDOK) - return; - fileName = fileDlg.GetPathName(); + if (fileDlg.DoModal() != IDOK) + return; + fileName = fileDlg.GetPathName(); - saveFolder = fileDlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(fileDlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); + saveFolder = fileDlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(fileDlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); - WMSG1("Scanning '%s'\n", (const char*) fileName); + WMSG1("Scanning '%s'\n", (const char*) fileName); - FILE* fp; - fp = fopen(fileName, "rb"); - if (fp == nil) { - errMsg.Format("Unable to open '%s': %s.", fileName, strerror(errno)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - return; - } + FILE* fp; + fp = fopen(fileName, "rb"); + if (fp == nil) { + errMsg.Format("Unable to open '%s': %s.", fileName, strerror(errno)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + return; + } - long numCR, numLF, numCRLF, numHAChars, numChars; - bool lastCR; - int ic; + long numCR, numLF, numCRLF, numHAChars, numChars; + bool lastCR; + int ic; - /* - * Plow through the file, counting up characters. - */ - numCR = numLF = numCRLF = numChars = numHAChars = 0; - lastCR = false; - while (true) { - ic = getc(fp); - if (ic == EOF) - break; + /* + * Plow through the file, counting up characters. + */ + numCR = numLF = numCRLF = numChars = numHAChars = 0; + lastCR = false; + while (true) { + ic = getc(fp); + if (ic == EOF) + break; - if ((ic & 0x80) != 0) - numHAChars++; + if ((ic & 0x80) != 0) + numHAChars++; - if (ic == '\r') { - lastCR = true; - numCR++; - } else if (ic == '\n') { - if (lastCR) { - numCR--; - numCRLF++; - lastCR = false; - } else { - numLF++; - } - } else { - lastCR = false; - } - numChars++; - } - fclose(fp); + if (ic == '\r') { + lastCR = true; + numCR++; + } else if (ic == '\n') { + if (lastCR) { + numCR--; + numCRLF++; + lastCR = false; + } else { + numLF++; + } + } else { + lastCR = false; + } + numChars++; + } + fclose(fp); - WMSG4("Got CR=%ld LF=%ld CRLF=%ld (numChars=%ld)\n", - numCR, numLF, numCRLF, numChars); + WMSG4("Got CR=%ld LF=%ld CRLF=%ld (numChars=%ld)\n", + numCR, numLF, numCRLF, numChars); - EOLScanDialog output; - output.fCountCR = numCR; - output.fCountLF = numLF; - output.fCountCRLF = numCRLF; - output.fCountChars = numChars; - output.fCountHighASCII = numHAChars; - (void) output.DoModal(); + EOLScanDialog output; + output.fCountCR = numCR; + output.fCountLF = numLF; + output.fCountCRLF = numCRLF; + output.fCountChars = numChars; + output.fCountHighASCII = numHAChars; + (void) output.DoModal(); } /* * ========================================================================== - * 2MG disk image properties editor + * 2MG disk image properties editor * ========================================================================== */ @@ -2366,43 +2366,43 @@ MainWindow::OnToolsEOLScanner(void) void MainWindow::OnToolsTwoImgProps(void) { - CString fileName, saveFolder, errMsg; - CString openFilters; + CString fileName, saveFolder, errMsg; + CString openFilters; - /* flush current archive in case that's what we're planning to edit */ - OnFileSave(); + /* flush current archive in case that's what we're planning to edit */ + OnFileSave(); - /* - * Select the file to open. - */ - openFilters = "2MG Disk Images (.2mg .2img)|*.2mg;*.2img|"; - openFilters += kOpenAll; - openFilters += kOpenEnd; - CFileDialog fileDlg(TRUE, "2mg", NULL, OFN_FILEMUSTEXIST, openFilters, this); + /* + * Select the file to open. + */ + openFilters = "2MG Disk Images (.2mg .2img)|*.2mg;*.2img|"; + openFilters += kOpenAll; + openFilters += kOpenEnd; + CFileDialog fileDlg(TRUE, "2mg", NULL, OFN_FILEMUSTEXIST, openFilters, this); - fileDlg.m_ofn.Flags |= OFN_HIDEREADONLY; - //fileDlg.m_ofn.Flags &= ~(OFN_READONLY); - fileDlg.m_ofn.lpstrTitle = "Select file to edit"; - fileDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); + fileDlg.m_ofn.Flags |= OFN_HIDEREADONLY; + //fileDlg.m_ofn.Flags &= ~(OFN_READONLY); + fileDlg.m_ofn.lpstrTitle = "Select file to edit"; + fileDlg.m_ofn.lpstrInitialDir = fPreferences.GetPrefString(kPrOpenArchiveFolder); - if (fileDlg.DoModal() != IDOK) - return; - fileName = fileDlg.GetPathName(); + if (fileDlg.DoModal() != IDOK) + return; + fileName = fileDlg.GetPathName(); - saveFolder = fileDlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(fileDlg.m_ofn.nFileOffset); - fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); + saveFolder = fileDlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(fileDlg.m_ofn.nFileOffset); + fPreferences.SetPrefString(kPrOpenArchiveFolder, saveFolder); - /* - * Open it up. - */ - bool changed; - changed = EditTwoImgProps(fileName); + /* + * Open it up. + */ + bool changed; + changed = EditTwoImgProps(fileName); - if (changed && IsOpenPathName(fileName)) { - PeekAndPump(); // clear out dialog - ReopenArchive(); - } + if (changed && IsOpenPathName(fileName)) { + PeekAndPump(); // clear out dialog + ReopenArchive(); + } } /* @@ -2413,83 +2413,83 @@ MainWindow::OnToolsTwoImgProps(void) bool MainWindow::EditTwoImgProps(const char* fileName) { - TwoImgPropsDialog dialog; - TwoImgHeader header; - FILE* fp = nil; - bool dirty = false; - CString errMsg; - long totalLength; - bool readOnly = false; + TwoImgPropsDialog dialog; + TwoImgHeader header; + FILE* fp = nil; + bool dirty = false; + CString errMsg; + long totalLength; + bool readOnly = false; - WMSG1("EditTwoImgProps '%s'\n", fileName); - fp = fopen(fileName, "r+b"); - if (fp == nil) { - int firstError = errno; - fp = fopen(fileName, "rb"); - if (fp == nil) { - errMsg.Format("Unable to open '%s': %s.", - fileName, strerror(firstError)); - goto bail; - } else - readOnly = true; - } + WMSG1("EditTwoImgProps '%s'\n", fileName); + fp = fopen(fileName, "r+b"); + if (fp == nil) { + int firstError = errno; + fp = fopen(fileName, "rb"); + if (fp == nil) { + errMsg.Format("Unable to open '%s': %s.", + fileName, strerror(firstError)); + goto bail; + } else + readOnly = true; + } - fseek(fp, 0, SEEK_END); - totalLength = ftell(fp); - rewind(fp); + fseek(fp, 0, SEEK_END); + totalLength = ftell(fp); + rewind(fp); - if (header.ReadHeader(fp, totalLength) != 0) { - errMsg.Format("Unable to process 2MG header in '%s'" - " (are you sure this is in 2MG format?).", - fileName); - goto bail; - } + if (header.ReadHeader(fp, totalLength) != 0) { + errMsg.Format("Unable to process 2MG header in '%s'" + " (are you sure this is in 2MG format?).", + fileName); + goto bail; + } - dialog.Setup(&header, readOnly); - if (dialog.DoModal() == IDOK) { - long result; - //header.SetCreatorChunk("fubar", 5); - header.DumpHeader(); + dialog.Setup(&header, readOnly); + if (dialog.DoModal() == IDOK) { + long result; + //header.SetCreatorChunk("fubar", 5); + header.DumpHeader(); - rewind(fp); - if (header.WriteHeader(fp) != 0) { - errMsg = "Unable to write 2MG header"; - goto bail; - } + rewind(fp); + if (header.WriteHeader(fp) != 0) { + errMsg = "Unable to write 2MG header"; + goto bail; + } - /* - * Clip off the footer. They might have had one before but don't - * have one now. If they do have one now we'll add it back in a - * second. - */ - result = fseek(fp, header.fDataOffset + header.fDataLen, SEEK_SET); - if (result < 0) { - errMsg = "Unable to seek to end of 2MG file"; - goto bail; - } - dirty = true; + /* + * Clip off the footer. They might have had one before but don't + * have one now. If they do have one now we'll add it back in a + * second. + */ + result = fseek(fp, header.fDataOffset + header.fDataLen, SEEK_SET); + if (result < 0) { + errMsg = "Unable to seek to end of 2MG file"; + goto bail; + } + dirty = true; - if (::chsize(fileno(fp), ftell(fp)) != 0) { - errMsg = "Unable to truncate 2MG file before writing footer"; - goto bail; - } + if (::chsize(fileno(fp), ftell(fp)) != 0) { + errMsg = "Unable to truncate 2MG file before writing footer"; + goto bail; + } - if (header.fCmtLen || header.fCreatorLen) { - if (header.WriteFooter(fp) != 0) { - errMsg = "Unable to write 2MG footer"; - goto bail; - } - } + if (header.fCmtLen || header.fCreatorLen) { + if (header.WriteFooter(fp) != 0) { + errMsg = "Unable to write 2MG footer"; + goto bail; + } + } - WMSG0("2MG success!\n"); - } + WMSG0("2MG success!\n"); + } bail: - if (fp != nil) - fclose(fp); - if (!errMsg.IsEmpty()) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - } + if (fp != nil) + fclose(fp); + if (!errMsg.IsEmpty()) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + } - return dirty; + return dirty; } diff --git a/app/TwoImgPropsDialog.cpp b/app/TwoImgPropsDialog.cpp index b5080a6..631091a 100644 --- a/app/TwoImgPropsDialog.cpp +++ b/app/TwoImgPropsDialog.cpp @@ -10,11 +10,11 @@ #include "TwoImgPropsDialog.h" BEGIN_MESSAGE_MAP(TwoImgPropsDialog, CDialog) - ON_BN_CLICKED(IDC_TWOIMG_LOCKED, OnChange) - ON_BN_CLICKED(IDC_TWOIMG_DOSVOLSET, OnChange) - ON_EN_CHANGE(IDC_TWOIMG_DOSVOLNUM, OnChange) - ON_EN_CHANGE(IDC_TWOIMG_COMMENT, OnChange) - ON_WM_HELPINFO() + ON_BN_CLICKED(IDC_TWOIMG_LOCKED, OnChange) + ON_BN_CLICKED(IDC_TWOIMG_DOSVOLSET, OnChange) + ON_EN_CHANGE(IDC_TWOIMG_DOSVOLNUM, OnChange) + ON_EN_CHANGE(IDC_TWOIMG_COMMENT, OnChange) + ON_WM_HELPINFO() END_MESSAGE_MAP() @@ -24,61 +24,61 @@ END_MESSAGE_MAP() BOOL TwoImgPropsDialog::OnInitDialog(void) { - CWnd* pWnd; - CEdit* pEdit; - CString tmpStr; + CWnd* pWnd; + CEdit* pEdit; + CString tmpStr; - ASSERT(fpHeader != nil); + ASSERT(fpHeader != nil); - /* - * Set up the static fields. - */ - pWnd = GetDlgItem(IDC_TWOIMG_CREATOR); - tmpStr.Format("'%s'", fpHeader->GetCreatorStr()); - pWnd->SetWindowText(tmpStr); + /* + * Set up the static fields. + */ + pWnd = GetDlgItem(IDC_TWOIMG_CREATOR); + tmpStr.Format("'%s'", fpHeader->GetCreatorStr()); + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_TWOIMG_VERSION); - tmpStr.Format("%d", fpHeader->fVersion); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_TWOIMG_VERSION); + tmpStr.Format("%d", fpHeader->fVersion); + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_TWOIMG_FORMAT); - switch (fpHeader->fImageFormat) { - case TwoImgHeader::kImageFormatDOS: tmpStr = "DOS order sectors"; break; - case TwoImgHeader::kImageFormatProDOS: tmpStr = "ProDOS order sectors"; break; - case TwoImgHeader::kImageFormatNibble: tmpStr = "Raw nibbles"; break; - default: tmpStr = "Unknown"; break; - } - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_TWOIMG_FORMAT); + switch (fpHeader->fImageFormat) { + case TwoImgHeader::kImageFormatDOS: tmpStr = "DOS order sectors"; break; + case TwoImgHeader::kImageFormatProDOS: tmpStr = "ProDOS order sectors"; break; + case TwoImgHeader::kImageFormatNibble: tmpStr = "Raw nibbles"; break; + default: tmpStr = "Unknown"; break; + } + pWnd->SetWindowText(tmpStr); - pWnd = GetDlgItem(IDC_TWOIMG_BLOCKS); - tmpStr.Format("%d", fpHeader->fNumBlocks); - pWnd->SetWindowText(tmpStr); + pWnd = GetDlgItem(IDC_TWOIMG_BLOCKS); + tmpStr.Format("%d", fpHeader->fNumBlocks); + pWnd->SetWindowText(tmpStr); - /* - * Restrict the edit field. - */ - pEdit = (CEdit*) GetDlgItem(IDC_TWOIMG_DOSVOLNUM); - pEdit->LimitText(3); // 1-254 + /* + * Restrict the edit field. + */ + pEdit = (CEdit*) GetDlgItem(IDC_TWOIMG_DOSVOLNUM); + pEdit->LimitText(3); // 1-254 - /* - * Disable the "Save" button. - */ - pWnd = GetDlgItem(IDOK); - pWnd->EnableWindow(FALSE); + /* + * Disable the "Save" button. + */ + pWnd = GetDlgItem(IDOK); + pWnd->EnableWindow(FALSE); - /* for read-only mode, all buttons are disabled */ - if (fReadOnly) { - GetDlgItem(IDC_TWOIMG_LOCKED)->EnableWindow(FALSE); - GetDlgItem(IDC_TWOIMG_DOSVOLSET)->EnableWindow(FALSE); - GetDlgItem(IDC_TWOIMG_COMMENT)->EnableWindow(FALSE); - GetDlgItem(IDC_TWOIMG_DOSVOLNUM)->EnableWindow(FALSE); + /* for read-only mode, all buttons are disabled */ + if (fReadOnly) { + GetDlgItem(IDC_TWOIMG_LOCKED)->EnableWindow(FALSE); + GetDlgItem(IDC_TWOIMG_DOSVOLSET)->EnableWindow(FALSE); + GetDlgItem(IDC_TWOIMG_COMMENT)->EnableWindow(FALSE); + GetDlgItem(IDC_TWOIMG_DOSVOLNUM)->EnableWindow(FALSE); - GetWindowText(tmpStr); - tmpStr += " (read-only)"; - SetWindowText(tmpStr); - } + GetWindowText(tmpStr); + tmpStr += " (read-only)"; + SetWindowText(tmpStr); + } - return CDialog::OnInitDialog(); + return CDialog::OnInitDialog(); } /* @@ -87,66 +87,66 @@ TwoImgPropsDialog::OnInitDialog(void) void TwoImgPropsDialog::DoDataExchange(CDataExchange* pDX) { - BOOL locked, dosVolSet; - CString comment; - int dosVolNum; + BOOL locked, dosVolSet; + CString comment; + int dosVolNum; - if (pDX->m_bSaveAndValidate) { - DDX_Check(pDX, IDC_TWOIMG_LOCKED, locked); - DDX_Check(pDX, IDC_TWOIMG_DOSVOLSET, dosVolSet); - DDX_Text(pDX, IDC_TWOIMG_COMMENT, comment); - DDX_Text(pDX, IDC_TWOIMG_DOSVOLNUM, dosVolNum); + if (pDX->m_bSaveAndValidate) { + DDX_Check(pDX, IDC_TWOIMG_LOCKED, locked); + DDX_Check(pDX, IDC_TWOIMG_DOSVOLSET, dosVolSet); + DDX_Text(pDX, IDC_TWOIMG_COMMENT, comment); + DDX_Text(pDX, IDC_TWOIMG_DOSVOLNUM, dosVolNum); - WMSG1("GOT dosVolNum = %d\n", dosVolNum); + WMSG1("GOT dosVolNum = %d\n", dosVolNum); - fpHeader->fFlags &= ~(TwoImgHeader::kFlagLocked); - if (locked) - fpHeader->fFlags |= TwoImgHeader::kFlagLocked; + fpHeader->fFlags &= ~(TwoImgHeader::kFlagLocked); + if (locked) + fpHeader->fFlags |= TwoImgHeader::kFlagLocked; - fpHeader->fFlags &= ~(TwoImgHeader::kDOSVolumeMask); - fpHeader->fFlags &= ~(TwoImgHeader::kDOSVolumeSet); - if (dosVolSet) { - fpHeader->fFlags |= TwoImgHeader::kDOSVolumeSet; - fpHeader->fFlags |= (dosVolNum & TwoImgHeader::kDOSVolumeMask); + fpHeader->fFlags &= ~(TwoImgHeader::kDOSVolumeMask); + fpHeader->fFlags &= ~(TwoImgHeader::kDOSVolumeSet); + if (dosVolSet) { + fpHeader->fFlags |= TwoImgHeader::kDOSVolumeSet; + fpHeader->fFlags |= (dosVolNum & TwoImgHeader::kDOSVolumeMask); - CString appStr, errMsg; - if (dosVolNum < 1 || dosVolNum > 254) { - appStr.LoadString(IDS_MB_APP_NAME); - errMsg.LoadString(IDS_VALID_VOLNAME_DOS); - MessageBox(errMsg, appStr, MB_OK); - pDX->Fail(); - } else { - fpHeader->SetDOSVolumeNum(dosVolNum); - } - } + CString appStr, errMsg; + if (dosVolNum < 1 || dosVolNum > 254) { + appStr.LoadString(IDS_MB_APP_NAME); + errMsg.LoadString(IDS_VALID_VOLNAME_DOS); + MessageBox(errMsg, appStr, MB_OK); + pDX->Fail(); + } else { + fpHeader->SetDOSVolumeNum(dosVolNum); + } + } - if (!comment.IsEmpty()) - fpHeader->SetComment(comment); - else - fpHeader->SetComment(nil); - } else { - CWnd* pWnd; + if (!comment.IsEmpty()) + fpHeader->SetComment(comment); + else + fpHeader->SetComment(nil); + } else { + CWnd* pWnd; - locked = (fpHeader->fFlags & TwoImgHeader::kFlagLocked) != 0; - dosVolSet = (fpHeader->fFlags & TwoImgHeader::kDOSVolumeSet) != 0; - comment = fpHeader->GetComment(); - if (dosVolSet) - dosVolNum = fpHeader->GetDOSVolumeNum(); - else - dosVolNum = TwoImgHeader::kDefaultVolumeNum; + locked = (fpHeader->fFlags & TwoImgHeader::kFlagLocked) != 0; + dosVolSet = (fpHeader->fFlags & TwoImgHeader::kDOSVolumeSet) != 0; + comment = fpHeader->GetComment(); + if (dosVolSet) + dosVolNum = fpHeader->GetDOSVolumeNum(); + else + dosVolNum = TwoImgHeader::kDefaultVolumeNum; - DDX_Check(pDX, IDC_TWOIMG_LOCKED, locked); - DDX_Check(pDX, IDC_TWOIMG_DOSVOLSET, dosVolSet); - DDX_Text(pDX, IDC_TWOIMG_COMMENT, comment); - DDX_Text(pDX, IDC_TWOIMG_DOSVOLNUM, dosVolNum); + DDX_Check(pDX, IDC_TWOIMG_LOCKED, locked); + DDX_Check(pDX, IDC_TWOIMG_DOSVOLSET, dosVolSet); + DDX_Text(pDX, IDC_TWOIMG_COMMENT, comment); + DDX_Text(pDX, IDC_TWOIMG_DOSVOLNUM, dosVolNum); - /* set initial state of dos volume number edit field */ - if (!fReadOnly) { - pWnd = GetDlgItem(IDC_TWOIMG_DOSVOLNUM); - pWnd->EnableWindow(dosVolSet); - } - } + /* set initial state of dos volume number edit field */ + if (!fReadOnly) { + pWnd = GetDlgItem(IDC_TWOIMG_DOSVOLNUM); + pWnd->EnableWindow(dosVolSet); + } + } } /* @@ -155,16 +155,16 @@ TwoImgPropsDialog::DoDataExchange(CDataExchange* pDX) void TwoImgPropsDialog::OnChange(void) { - CButton* pButton; - UINT checked; + CButton* pButton; + UINT checked; - ASSERT(!fReadOnly); + ASSERT(!fReadOnly); - GetDlgItem(IDOK)->EnableWindow(TRUE); + GetDlgItem(IDOK)->EnableWindow(TRUE); - pButton = (CButton*) GetDlgItem(IDC_TWOIMG_DOSVOLSET); - checked = pButton->GetCheck(); - GetDlgItem(IDC_TWOIMG_DOSVOLNUM)->EnableWindow(checked == BST_CHECKED); + pButton = (CButton*) GetDlgItem(IDC_TWOIMG_DOSVOLSET); + checked = pButton->GetCheck(); + GetDlgItem(IDC_TWOIMG_DOSVOLNUM)->EnableWindow(checked == BST_CHECKED); } /* @@ -173,6 +173,6 @@ TwoImgPropsDialog::OnChange(void) BOOL TwoImgPropsDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } diff --git a/app/TwoImgPropsDialog.h b/app/TwoImgPropsDialog.h index de82919..af10693 100644 --- a/app/TwoImgPropsDialog.h +++ b/app/TwoImgPropsDialog.h @@ -20,30 +20,30 @@ */ class TwoImgPropsDialog : public CDialog { public: - TwoImgPropsDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_TWOIMG_PROPS, pParentWnd), - fpHeader(NULL), fReadOnly(false) - {} + TwoImgPropsDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_TWOIMG_PROPS, pParentWnd), + fpHeader(NULL), fReadOnly(false) + {} - void Setup(TwoImgHeader* pHeader, bool readOnly) { - fpHeader = pHeader; - fReadOnly = readOnly; - } + void Setup(TwoImgHeader* pHeader, bool readOnly) { + fpHeader = pHeader; + fReadOnly = readOnly; + } protected: - // overrides - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + // overrides + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - afx_msg void OnChange(void); + afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + afx_msg void OnChange(void); - TwoImgHeader* fpHeader; - bool fReadOnly; - //bool fModified; + TwoImgHeader* fpHeader; + bool fReadOnly; + //bool fModified; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__TWOIMG_PROPS_DIALOG__*/ \ No newline at end of file diff --git a/app/UseSelectionDialog.cpp b/app/UseSelectionDialog.cpp index 1e0af26..916c4e2 100644 --- a/app/UseSelectionDialog.cpp +++ b/app/UseSelectionDialog.cpp @@ -11,8 +11,8 @@ #include "HelpTopics.h" BEGIN_MESSAGE_MAP(UseSelectionDialog, CDialog) - ON_WM_HELPINFO() - //ON_COMMAND(IDHELP, OnHelp) + ON_WM_HELPINFO() + //ON_COMMAND(IDHELP, OnHelp) END_MESSAGE_MAP() @@ -25,44 +25,44 @@ END_MESSAGE_MAP() BOOL UseSelectionDialog::OnInitDialog(void) { - CString str; - CString selStr; - CWnd* pWnd; + CString str; + CString selStr; + CWnd* pWnd; - CDialog::OnInitDialog(); + CDialog::OnInitDialog(); - /* grab the radio button with the selection count */ - pWnd = GetDlgItem(IDC_USE_SELECTED); - ASSERT(pWnd != nil); + /* grab the radio button with the selection count */ + pWnd = GetDlgItem(IDC_USE_SELECTED); + ASSERT(pWnd != nil); - /* set the string using a string table entry */ - if (fSelectedCount == 1) { - str.LoadString(fSelCountID); - pWnd->SetWindowText(str); - } else { - str.LoadString(fSelCountsID); - selStr.Format((LPCTSTR) str, fSelectedCount); - pWnd->SetWindowText(selStr); + /* set the string using a string table entry */ + if (fSelectedCount == 1) { + str.LoadString(fSelCountID); + pWnd->SetWindowText(str); + } else { + str.LoadString(fSelCountsID); + selStr.Format((LPCTSTR) str, fSelectedCount); + pWnd->SetWindowText(selStr); - if (fSelectedCount == 0) - pWnd->EnableWindow(FALSE); - } + if (fSelectedCount == 0) + pWnd->EnableWindow(FALSE); + } - /* set the other strings */ - str.LoadString(fTitleID); - SetWindowText(str); + /* set the other strings */ + str.LoadString(fTitleID); + SetWindowText(str); - pWnd = GetDlgItem(IDC_USE_ALL); - ASSERT(pWnd != nil); - str.LoadString(fAllID); - pWnd->SetWindowText(str); + pWnd = GetDlgItem(IDC_USE_ALL); + ASSERT(pWnd != nil); + str.LoadString(fAllID); + pWnd->SetWindowText(str); - pWnd = GetDlgItem(IDOK); - ASSERT(pWnd != nil); - str.LoadString(fOkLabelID); - pWnd->SetWindowText(str); + pWnd = GetDlgItem(IDOK); + ASSERT(pWnd != nil); + str.LoadString(fOkLabelID); + pWnd->SetWindowText(str); - return TRUE; + return TRUE; } /* @@ -71,7 +71,7 @@ UseSelectionDialog::OnInitDialog(void) void UseSelectionDialog::DoDataExchange(CDataExchange* pDX) { - DDX_Radio(pDX, IDC_USE_SELECTED, fFilesToAction); + DDX_Radio(pDX, IDC_USE_SELECTED, fFilesToAction); } /* @@ -80,6 +80,6 @@ UseSelectionDialog::DoDataExchange(CDataExchange* pDX) BOOL UseSelectionDialog::OnHelpInfo(HELPINFO* lpHelpInfo) { - WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); - return TRUE; // yes, we handled it + WinHelp((DWORD) lpHelpInfo->iCtrlId, HELP_CONTEXTPOPUP); + return TRUE; // yes, we handled it } diff --git a/app/UseSelectionDialog.h b/app/UseSelectionDialog.h index b50bf66..d286e31 100644 --- a/app/UseSelectionDialog.h +++ b/app/UseSelectionDialog.h @@ -17,46 +17,46 @@ */ class UseSelectionDialog : public CDialog { public: - UseSelectionDialog(int selCount, CWnd* pParentWnd = NULL, int rsrcID = IDD_USE_SELECTION) : - CDialog(rsrcID, pParentWnd), fSelectedCount(selCount) - { - // init values; these should be overridden before DoModal - fFilesToAction = 0; - } - virtual ~UseSelectionDialog(void) {} + UseSelectionDialog(int selCount, CWnd* pParentWnd = NULL, int rsrcID = IDD_USE_SELECTION) : + CDialog(rsrcID, pParentWnd), fSelectedCount(selCount) + { + // init values; these should be overridden before DoModal + fFilesToAction = 0; + } + virtual ~UseSelectionDialog(void) {} - // set up dialog parameters; must be called before DoModal - void Setup(int titleID, int okLabelID, int countID, int countsID, - int allID) - { - fTitleID = titleID; - fOkLabelID = okLabelID; - fSelCountID = countID; - fSelCountsID = countsID; - fAllID = allID; - } + // set up dialog parameters; must be called before DoModal + void Setup(int titleID, int okLabelID, int countID, int countsID, + int allID) + { + fTitleID = titleID; + fOkLabelID = okLabelID; + fSelCountID = countID; + fSelCountsID = countsID; + fAllID = allID; + } - enum { kActionSelection = 0, kActionAll = 1 }; - int fFilesToAction; + enum { kActionSelection = 0, kActionAll = 1 }; + int fFilesToAction; protected: - virtual BOOL OnInitDialog(void); - virtual void DoDataExchange(CDataExchange* pDX); + virtual BOOL OnInitDialog(void); + virtual void DoDataExchange(CDataExchange* pDX); - afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); - //afx_msg void OnHelp(void); + afx_msg BOOL OnHelpInfo(HELPINFO* lpHelpInfo); + //afx_msg void OnHelp(void); private: - int fSelectedCount; + int fSelectedCount; - /* dialog parameters */ - int fTitleID; - int fOkLabelID; - int fSelCountID; - int fSelCountsID; - int fAllID; + /* dialog parameters */ + int fTitleID; + int fOkLabelID; + int fSelCountID; + int fSelCountsID; + int fAllID; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__USE_SELECTION_DIALOG__*/ \ No newline at end of file diff --git a/app/ViewFilesDialog.cpp b/app/ViewFilesDialog.cpp index c062d34..11f24d3 100644 --- a/app/ViewFilesDialog.cpp +++ b/app/ViewFilesDialog.cpp @@ -16,31 +16,31 @@ /* * =========================================================================== - * ViewFilesDialog + * ViewFilesDialog * =========================================================================== */ static const UINT gFindReplaceID = RegisterWindowMessage(FINDMSGSTRING); BEGIN_MESSAGE_MAP(ViewFilesDialog, CDialog) - ON_WM_CREATE() - ON_WM_DESTROY() - ON_WM_SIZE() - ON_WM_GETMINMAXINFO() - ON_REGISTERED_MESSAGE(gFindReplaceID, OnFindDialogMessage) - ON_COMMAND(IDC_FVIEW_NEXT, OnFviewNext) - ON_COMMAND(IDC_FVIEW_PREV, OnFviewPrev) - ON_COMMAND(IDC_FVIEW_FONT, OnFviewFont) - ON_COMMAND(IDC_FVIEW_PRINT, OnFviewPrint) - ON_COMMAND(IDC_FVIEW_FIND, OnFviewFind) - ON_BN_CLICKED(IDC_FVIEW_DATA, OnFviewData) - ON_BN_CLICKED(IDC_FVIEW_RSRC, OnFviewRsrc) - ON_BN_CLICKED(IDC_FVIEW_CMMT, OnFviewCmmt) - ON_COMMAND(IDC_FVIEW_FMT_BEST, OnFviewFmtBest) - ON_COMMAND(IDC_FVIEW_FMT_HEX, OnFviewFmtHex) - ON_COMMAND(IDC_FVIEW_FMT_RAW, OnFviewFmtRaw) - ON_CBN_SELCHANGE(IDC_FVIEW_FORMATSEL, OnFormatSelChange) - ON_COMMAND(IDHELP, OnHelp) + ON_WM_CREATE() + ON_WM_DESTROY() + ON_WM_SIZE() + ON_WM_GETMINMAXINFO() + ON_REGISTERED_MESSAGE(gFindReplaceID, OnFindDialogMessage) + ON_COMMAND(IDC_FVIEW_NEXT, OnFviewNext) + ON_COMMAND(IDC_FVIEW_PREV, OnFviewPrev) + ON_COMMAND(IDC_FVIEW_FONT, OnFviewFont) + ON_COMMAND(IDC_FVIEW_PRINT, OnFviewPrint) + ON_COMMAND(IDC_FVIEW_FIND, OnFviewFind) + ON_BN_CLICKED(IDC_FVIEW_DATA, OnFviewData) + ON_BN_CLICKED(IDC_FVIEW_RSRC, OnFviewRsrc) + ON_BN_CLICKED(IDC_FVIEW_CMMT, OnFviewCmmt) + ON_COMMAND(IDC_FVIEW_FMT_BEST, OnFviewFmtBest) + ON_COMMAND(IDC_FVIEW_FMT_HEX, OnFviewFmtHex) + ON_COMMAND(IDC_FVIEW_FMT_RAW, OnFviewFmtRaw) + ON_CBN_SELCHANGE(IDC_FVIEW_FORMATSEL, OnFormatSelChange) + ON_COMMAND(IDHELP, OnHelp) END_MESSAGE_MAP() /* @@ -49,57 +49,57 @@ END_MESSAGE_MAP() BOOL ViewFilesDialog::OnInitDialog(void) { - WMSG0("Now in VFD OnInitDialog!\n"); + WMSG0("Now in VFD OnInitDialog!\n"); - ASSERT(fpSelSet != nil); + ASSERT(fpSelSet != nil); - /* delete dummy control and insert our own with modded styles */ - CRichEditCtrl* pEdit = (CRichEditCtrl*)GetDlgItem(IDC_FVIEW_EDITBOX); - ASSERT(pEdit != nil); - CRect rect; - pEdit->GetWindowRect(&rect); - pEdit->DestroyWindow(); - ScreenToClient(&rect); + /* delete dummy control and insert our own with modded styles */ + CRichEditCtrl* pEdit = (CRichEditCtrl*)GetDlgItem(IDC_FVIEW_EDITBOX); + ASSERT(pEdit != nil); + CRect rect; + pEdit->GetWindowRect(&rect); + pEdit->DestroyWindow(); + ScreenToClient(&rect); - DWORD styles = ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | + DWORD styles = ES_MULTILINE | ES_AUTOVSCROLL | ES_READONLY | WS_BORDER | WS_VSCROLL | WS_VISIBLE | WS_TABSTOP | - ES_NOHIDESEL; - if (fNoWrapText) - styles |= ES_AUTOHSCROLL | WS_HSCROLL; - fEditCtrl.Create(styles, rect, this, IDC_FVIEW_EDITBOX); - fEditCtrl.SetFocus(); - /* - * HEY: I think we can do this with pEdit->ShowScrollBar(SB_BOTH) !! - * Could also use GetWindowLong/SetWindowLong to change the window style; - * probably need a SetWindowPos to cause changes to flush. - */ + ES_NOHIDESEL; + if (fNoWrapText) + styles |= ES_AUTOHSCROLL | WS_HSCROLL; + fEditCtrl.Create(styles, rect, this, IDC_FVIEW_EDITBOX); + fEditCtrl.SetFocus(); + /* + * HEY: I think we can do this with pEdit->ShowScrollBar(SB_BOTH) !! + * Could also use GetWindowLong/SetWindowLong to change the window style; + * probably need a SetWindowPos to cause changes to flush. + */ - /* - * We want to adjust the size of the window to match the last size used. - * However, if we do this after creating the edit dialog but before it - * actually has data to display, then when we stuff data into it the - * scroll bar goodies are all out of whack. - */ - fFirstResize = true; + /* + * We want to adjust the size of the window to match the last size used. + * However, if we do this after creating the edit dialog but before it + * actually has data to display, then when we stuff data into it the + * scroll bar goodies are all out of whack. + */ + fFirstResize = true; #if 0 - const Preferences* pPreferences = GET_PREFERENCES(); - long width = pPreferences->GetFileViewerWidth(); - long height = pPreferences->GetFileViewerHeight(); - CRect fullRect; - GetWindowRect(&fullRect); - WMSG2(" VFD pre-size %dx%d\n", fullRect.Width(), fullRect.Height()); - fullRect.right = fullRect.left + width; - fullRect.bottom = fullRect.top + height; - MoveWindow(fullRect, FALSE); + const Preferences* pPreferences = GET_PREFERENCES(); + long width = pPreferences->GetFileViewerWidth(); + long height = pPreferences->GetFileViewerHeight(); + CRect fullRect; + GetWindowRect(&fullRect); + WMSG2(" VFD pre-size %dx%d\n", fullRect.Width(), fullRect.Height()); + fullRect.right = fullRect.left + width; + fullRect.bottom = fullRect.top + height; + MoveWindow(fullRect, FALSE); #endif - // This invokes UpdateData, which calls DoDataExchange, which leads to - // the StreamIn call. So don't do this until everything else is ready. - CDialog::OnInitDialog(); + // This invokes UpdateData, which calls DoDataExchange, which leads to + // the StreamIn call. So don't do this until everything else is ready. + CDialog::OnInitDialog(); - WMSG0("VFD OnInitDialog done\n"); - return FALSE; // don't let Windows set the focus + WMSG0("VFD OnInitDialog done\n"); + return FALSE; // don't let Windows set the focus } @@ -109,23 +109,23 @@ ViewFilesDialog::OnInitDialog(void) int ViewFilesDialog::OnCreate(LPCREATESTRUCT lpcs) { - WMSG0("VFD OnCreate\n"); + WMSG0("VFD OnCreate\n"); - HICON hIcon; - hIcon = ::AfxGetApp()->LoadIcon(IDI_FILE_VIEWER); - SetIcon(hIcon, TRUE); + HICON hIcon; + hIcon = ::AfxGetApp()->LoadIcon(IDI_FILE_VIEWER); + SetIcon(hIcon, TRUE); - GetClientRect(&fLastWinSize); + GetClientRect(&fLastWinSize); - CRect initRect(fLastWinSize); - initRect.left = initRect.right - ::GetSystemMetrics(SM_CXVSCROLL); - initRect.top = initRect.bottom - ::GetSystemMetrics(SM_CYHSCROLL); - fGripper.Create(WS_CHILD | WS_VISIBLE | - SBS_SIZEBOX | SBS_SIZEBOXBOTTOMRIGHTALIGN | SBS_SIZEGRIP, - initRect, this, AFX_IDW_SIZE_BOX); + CRect initRect(fLastWinSize); + initRect.left = initRect.right - ::GetSystemMetrics(SM_CXVSCROLL); + initRect.top = initRect.bottom - ::GetSystemMetrics(SM_CYHSCROLL); + fGripper.Create(WS_CHILD | WS_VISIBLE | + SBS_SIZEBOX | SBS_SIZEBOXBOTTOMRIGHTALIGN | SBS_SIZEGRIP, + initRect, this, AFX_IDW_SIZE_BOX); - WMSG0("VFD OnCreate done\n"); - return 0; + WMSG0("VFD OnCreate done\n"); + return 0; } /* @@ -134,14 +134,14 @@ ViewFilesDialog::OnCreate(LPCREATESTRUCT lpcs) void ViewFilesDialog::OnDestroy(void) { - Preferences* pPreferences = GET_PREFERENCES_WR(); - CRect rect; - GetWindowRect(&rect); + Preferences* pPreferences = GET_PREFERENCES_WR(); + CRect rect; + GetWindowRect(&rect); - pPreferences->SetPrefLong(kPrFileViewerWidth, rect.Width()); - pPreferences->SetPrefLong(kPrFileViewerHeight, rect.Height()); + pPreferences->SetPrefLong(kPrFileViewerWidth, rect.Width()); + pPreferences->SetPrefLong(kPrFileViewerHeight, rect.Height()); - CDialog::OnDestroy(); + CDialog::OnDestroy(); } /* @@ -153,24 +153,24 @@ ViewFilesDialog::OnDestroy(void) void ViewFilesDialog::OnOK(void) { - if (fBusy) - MessageBeep(-1); - else { - CRect rect; + if (fBusy) + MessageBeep(-1); + else { + CRect rect; - GetWindowRect(&rect); - WMSG2(" VFD size now %dx%d\n", rect.Width(), rect.Height()); + GetWindowRect(&rect); + WMSG2(" VFD size now %dx%d\n", rect.Width(), rect.Height()); - CDialog::OnOK(); - } + CDialog::OnOK(); + } } void ViewFilesDialog::OnCancel(void) { - if (fBusy) - MessageBeep(-1); - else - CDialog::OnCancel(); + if (fBusy) + MessageBeep(-1); + else + CDialog::OnCancel(); } @@ -180,8 +180,8 @@ ViewFilesDialog::OnCancel(void) void ViewFilesDialog::OnGetMinMaxInfo(MINMAXINFO* pMMI) { - pMMI->ptMinTrackSize.x = 664; - pMMI->ptMinTrackSize.y = 200; + pMMI->ptMinTrackSize.x = 664; + pMMI->ptMinTrackSize.y = 200; } /* @@ -191,25 +191,25 @@ ViewFilesDialog::OnGetMinMaxInfo(MINMAXINFO* pMMI) void ViewFilesDialog::OnSize(UINT nType, int cx, int cy) { - CDialog::OnSize(nType, cx, cy); + CDialog::OnSize(nType, cx, cy); - //WMSG2("Dialog: old size %d,%d\n", - // fLastWinSize.Width(), fLastWinSize.Height()); - WMSG2("Dialog: new size %d,%d\n", cx, cy); + //WMSG2("Dialog: old size %d,%d\n", + // fLastWinSize.Width(), fLastWinSize.Height()); + WMSG2("Dialog: new size %d,%d\n", cx, cy); - if (fLastWinSize.Width() == cx && fLastWinSize.Height() == cy) { - WMSG0("VFD OnSize: no change\n"); - return; - } + if (fLastWinSize.Width() == cx && fLastWinSize.Height() == cy) { + WMSG0("VFD OnSize: no change\n"); + return; + } - int deltaX, deltaY; - deltaX = cx - fLastWinSize.Width(); - deltaY = cy - fLastWinSize.Height(); - //WMSG2("Delta is %d,%d\n", deltaX, deltaY); + int deltaX, deltaY; + deltaX = cx - fLastWinSize.Width(); + deltaY = cy - fLastWinSize.Height(); + //WMSG2("Delta is %d,%d\n", deltaX, deltaY); - ShiftControls(deltaX, deltaY); + ShiftControls(deltaX, deltaY); - GetClientRect(&fLastWinSize); + GetClientRect(&fLastWinSize); } /* @@ -220,57 +220,57 @@ ViewFilesDialog::OnSize(UINT nType, int cx, int cy) void ViewFilesDialog::ShiftControls(int deltaX, int deltaY) { - HDWP hdwp; + HDWP hdwp; - /* - * Use deferred reposn so that they don't end up drawing on top of each - * other and getting all weird. - * - * IMPORTANT: the DeferWindowPos stuff changes the tab order of the - * items in the window. The controls must be added in the reverse - * order in which they appear in the window. - */ - hdwp = BeginDeferWindowPos(15); - hdwp = MoveControl(hdwp, this, AFX_IDW_SIZE_BOX, deltaX, deltaY); - hdwp = MoveControl(hdwp, this, IDHELP, deltaX, deltaY); - hdwp = MoveControl(hdwp, this, IDC_FVIEW_FONT, deltaX, deltaY); - hdwp = MoveControl(hdwp, this, IDC_FVIEW_PRINT, deltaX, deltaY); - hdwp = MoveControl(hdwp, this, IDC_FVIEW_FIND, deltaX, deltaY); - hdwp = MoveControl(hdwp, this, IDC_FVIEW_FMT_RAW, 0, deltaY); - hdwp = MoveControl(hdwp, this, IDC_FVIEW_FMT_HEX, 0, deltaY); - hdwp = MoveControl(hdwp, this, IDC_FVIEW_FMT_BEST, 0, deltaY); - hdwp = MoveControl(hdwp, this, IDC_FVIEW_PREV, 0, deltaY); - hdwp = MoveControl(hdwp, this, IDC_FVIEW_NEXT, 0, deltaY); - hdwp = MoveControl(hdwp, this, IDC_FVIEW_CMMT, 0, deltaY); - hdwp = MoveControl(hdwp, this, IDC_FVIEW_RSRC, 0, deltaY); - hdwp = MoveControl(hdwp, this, IDC_FVIEW_DATA, 0, deltaY); - hdwp = MoveStretchControl(hdwp, this, IDC_FVIEW_FORMATSEL, 0, deltaY, deltaX, 0); - hdwp = StretchControl(hdwp, this, IDC_FVIEW_EDITBOX, deltaX, deltaY); - hdwp = MoveControl(hdwp, this, IDOK, deltaX, deltaY); - if (!EndDeferWindowPos(hdwp)) { - WMSG0("EndDeferWindowPos failed\n"); - } + /* + * Use deferred reposn so that they don't end up drawing on top of each + * other and getting all weird. + * + * IMPORTANT: the DeferWindowPos stuff changes the tab order of the + * items in the window. The controls must be added in the reverse + * order in which they appear in the window. + */ + hdwp = BeginDeferWindowPos(15); + hdwp = MoveControl(hdwp, this, AFX_IDW_SIZE_BOX, deltaX, deltaY); + hdwp = MoveControl(hdwp, this, IDHELP, deltaX, deltaY); + hdwp = MoveControl(hdwp, this, IDC_FVIEW_FONT, deltaX, deltaY); + hdwp = MoveControl(hdwp, this, IDC_FVIEW_PRINT, deltaX, deltaY); + hdwp = MoveControl(hdwp, this, IDC_FVIEW_FIND, deltaX, deltaY); + hdwp = MoveControl(hdwp, this, IDC_FVIEW_FMT_RAW, 0, deltaY); + hdwp = MoveControl(hdwp, this, IDC_FVIEW_FMT_HEX, 0, deltaY); + hdwp = MoveControl(hdwp, this, IDC_FVIEW_FMT_BEST, 0, deltaY); + hdwp = MoveControl(hdwp, this, IDC_FVIEW_PREV, 0, deltaY); + hdwp = MoveControl(hdwp, this, IDC_FVIEW_NEXT, 0, deltaY); + hdwp = MoveControl(hdwp, this, IDC_FVIEW_CMMT, 0, deltaY); + hdwp = MoveControl(hdwp, this, IDC_FVIEW_RSRC, 0, deltaY); + hdwp = MoveControl(hdwp, this, IDC_FVIEW_DATA, 0, deltaY); + hdwp = MoveStretchControl(hdwp, this, IDC_FVIEW_FORMATSEL, 0, deltaY, deltaX, 0); + hdwp = StretchControl(hdwp, this, IDC_FVIEW_EDITBOX, deltaX, deltaY); + hdwp = MoveControl(hdwp, this, IDOK, deltaX, deltaY); + if (!EndDeferWindowPos(hdwp)) { + WMSG0("EndDeferWindowPos failed\n"); + } - /* - * Work around buggy CRichEdit controls. The inner edit area is only - * resized when the box is shrunk, not when it's expanded, and the - * results are inconsistent between Win98 and Win2K. - * - * Set the internal size equal to the size of the entire edit box. - * This should be large enough to make everything work right, but small - * enough to avoid funky scrolling behavior. (If you want to set this - * more precisely, don't forget that scroll bars are not part of the - * edit control client area, and their sizes must be factored in.) - */ - CRect rect; - CRichEditCtrl* pEdit = (CRichEditCtrl*) GetDlgItem(IDC_FVIEW_EDITBOX); - ASSERT(pEdit != nil); - //pEdit->GetClientRect(&rect); - pEdit->GetWindowRect(&rect); - //GetClientRect(&rect); - rect.left = 2; - rect.top = 2; - pEdit->SetRect(&rect); + /* + * Work around buggy CRichEdit controls. The inner edit area is only + * resized when the box is shrunk, not when it's expanded, and the + * results are inconsistent between Win98 and Win2K. + * + * Set the internal size equal to the size of the entire edit box. + * This should be large enough to make everything work right, but small + * enough to avoid funky scrolling behavior. (If you want to set this + * more precisely, don't forget that scroll bars are not part of the + * edit control client area, and their sizes must be factored in.) + */ + CRect rect; + CRichEditCtrl* pEdit = (CRichEditCtrl*) GetDlgItem(IDC_FVIEW_EDITBOX); + ASSERT(pEdit != nil); + //pEdit->GetClientRect(&rect); + pEdit->GetWindowRect(&rect); + //GetClientRect(&rect); + rect.left = 2; + rect.top = 2; + pEdit->SetRect(&rect); } @@ -280,32 +280,32 @@ ViewFilesDialog::ShiftControls(int deltaX, int deltaY) void ViewFilesDialog::DoDataExchange(CDataExchange* pDX) { - CDialog::DoDataExchange(pDX); + CDialog::DoDataExchange(pDX); - if (pDX->m_bSaveAndValidate) { - WMSG0("COPY OUT\n"); - } else { - WMSG0("COPY IN\n"); - OnFviewNext(); - } + if (pDX->m_bSaveAndValidate) { + WMSG0("COPY OUT\n"); + } else { + WMSG0("COPY IN\n"); + OnFviewNext(); + } } static void DumpBitmapInfo(HBITMAP hBitmap) { - BITMAP info; - CBitmap* pBitmap = CBitmap::FromHandle(hBitmap); - int gotten; + BITMAP info; + CBitmap* pBitmap = CBitmap::FromHandle(hBitmap); + int gotten; - gotten = pBitmap->GetObject(sizeof(info), &info); + gotten = pBitmap->GetObject(sizeof(info), &info); - WMSG2("DumpBitmapInfo: gotten=%d of %d\n", gotten, sizeof(info)); - WMSG1(" bmType = %d\n", info.bmType); - WMSG2(" bmWidth=%d, bmHeight=%d\n", info.bmWidth, info.bmHeight); - WMSG1(" bmWidthBytes=%d\n", info.bmWidthBytes); - WMSG1(" bmPlanes=%d\n", info.bmPlanes); - WMSG1(" bmBitsPixel=%d\n", info.bmBitsPixel); - WMSG1(" bmPits = 0x%08lx\n", info.bmBits); + WMSG2("DumpBitmapInfo: gotten=%d of %d\n", gotten, sizeof(info)); + WMSG1(" bmType = %d\n", info.bmType); + WMSG2(" bmWidth=%d, bmHeight=%d\n", info.bmWidth, info.bmHeight); + WMSG1(" bmWidthBytes=%d\n", info.bmWidthBytes); + WMSG1(" bmPlanes=%d\n", info.bmPlanes); + WMSG1(" bmBitsPixel=%d\n", info.bmBitsPixel); + WMSG1(" bmPits = 0x%08lx\n", info.bmBits); } @@ -318,309 +318,309 @@ DumpBitmapInfo(HBITMAP hBitmap) void ViewFilesDialog::DisplayText(const char* fileName) { - CWaitCursor wait; // streaming of big files can take a little while - bool errFlg; - bool emptyFlg = false; - bool editHadFocus = false; - - ASSERT(fpOutput != nil); - ASSERT(fileName != nil); + CWaitCursor wait; // streaming of big files can take a little while + bool errFlg; + bool emptyFlg = false; + bool editHadFocus = false; + + ASSERT(fpOutput != nil); + ASSERT(fileName != nil); - errFlg = fpOutput->GetOutputKind() == ReformatOutput::kOutputErrorMsg; + errFlg = fpOutput->GetOutputKind() == ReformatOutput::kOutputErrorMsg; - ASSERT(fpOutput->GetOutputKind() != ReformatOutput::kOutputUnknown); + ASSERT(fpOutput->GetOutputKind() != ReformatOutput::kOutputUnknown); - CRichEditCtrl* pEdit = (CRichEditCtrl*) GetDlgItem(IDC_FVIEW_EDITBOX); - ASSERT(pEdit != nil); + CRichEditCtrl* pEdit = (CRichEditCtrl*) GetDlgItem(IDC_FVIEW_EDITBOX); + ASSERT(pEdit != nil); - /* retain the selection even if we lose focus [can't do this in OnInit] */ - pEdit->SetOptions(ECOOP_OR, ECO_SAVESEL); + /* retain the selection even if we lose focus [can't do this in OnInit] */ + pEdit->SetOptions(ECOOP_OR, ECO_SAVESEL); #if 0 - /* - * Start by trashing anything that's there. Not strictly necessary, - * but it prevents the control from trying to maintain the old stuff - * in an undo buffer. (Not entirely sure if a stream-in operation is - * undoable, but it costs very little to be certain.) - * - * UPDATE: I turned this off because it was dinging the speaker (?!). - * Might be doing that because it's in read-only mode. - */ - pEdit->SetSel(0, -1); - pEdit->Clear(); - pEdit->EmptyUndoBuffer(); + /* + * Start by trashing anything that's there. Not strictly necessary, + * but it prevents the control from trying to maintain the old stuff + * in an undo buffer. (Not entirely sure if a stream-in operation is + * undoable, but it costs very little to be certain.) + * + * UPDATE: I turned this off because it was dinging the speaker (?!). + * Might be doing that because it's in read-only mode. + */ + pEdit->SetSel(0, -1); + pEdit->Clear(); + pEdit->EmptyUndoBuffer(); #endif - /* - * There's a redraw flash that goes away if you change the input - * focus to something other than the edit ctrl. (Move between large - * files; it looks like you can see the text being selected and - * hightlighted. The control doesn't have an "always highlight" flag - * set, so if the focus is on a different control it doesn't light up.) - * - * Since we're currently forcing the focus to be on the edit ctrl later - * on, we just jam it to something else here. If nothing has the focus, - * as can happen if we click on "resource fork" and then Alt-N to a - * file without a resource fork, we force the focus to return to the - * edit window. - * - * NOTE: this would look a little better if we used the Prev/Next - * buttons to hold the temporary focus, but we need to know which key - * the user hit. We could also create a bogus control, move it into - * negative space where it will be invisible, and use that as a "focus - * holder". - */ - CWnd* pFocusWnd = GetFocus(); - if (pFocusWnd == nil || pFocusWnd->m_hWnd == pEdit->m_hWnd) { - editHadFocus = true; - GetDlgItem(IDOK)->SetFocus(); - } + /* + * There's a redraw flash that goes away if you change the input + * focus to something other than the edit ctrl. (Move between large + * files; it looks like you can see the text being selected and + * hightlighted. The control doesn't have an "always highlight" flag + * set, so if the focus is on a different control it doesn't light up.) + * + * Since we're currently forcing the focus to be on the edit ctrl later + * on, we just jam it to something else here. If nothing has the focus, + * as can happen if we click on "resource fork" and then Alt-N to a + * file without a resource fork, we force the focus to return to the + * edit window. + * + * NOTE: this would look a little better if we used the Prev/Next + * buttons to hold the temporary focus, but we need to know which key + * the user hit. We could also create a bogus control, move it into + * negative space where it will be invisible, and use that as a "focus + * holder". + */ + CWnd* pFocusWnd = GetFocus(); + if (pFocusWnd == nil || pFocusWnd->m_hWnd == pEdit->m_hWnd) { + editHadFocus = true; + GetDlgItem(IDOK)->SetFocus(); + } - /* - * The text color isn't getting reset when we reload the control. I - * can't find a "set default text color" call, so I'm reformatting - * part of the buffer. - * - * Here's the weird part: it doesn't seem to matter what color I - * set it to under Win2K. It reverts to black so long as I do anything - * here. Under Win98, it uses the new color. - */ - //if (0) - { - CHARFORMAT cf; - cf.cbSize = sizeof(CHARFORMAT); - cf.dwMask = CFM_COLOR; - cf.crTextColor = RGB(0, 0, 0); - pEdit->SetSel(0, 1); // must select at least one char - pEdit->SetSelectionCharFormat(cf); - } + /* + * The text color isn't getting reset when we reload the control. I + * can't find a "set default text color" call, so I'm reformatting + * part of the buffer. + * + * Here's the weird part: it doesn't seem to matter what color I + * set it to under Win2K. It reverts to black so long as I do anything + * here. Under Win98, it uses the new color. + */ + //if (0) + { + CHARFORMAT cf; + cf.cbSize = sizeof(CHARFORMAT); + cf.dwMask = CFM_COLOR; + cf.crTextColor = RGB(0, 0, 0); + pEdit->SetSel(0, 1); // must select at least one char + pEdit->SetSelectionCharFormat(cf); + } - /* - * Add the appropriate data. If the "bitmap" flag is set, use the - * MyDIBitmap pointer instead. - */ - if (fpOutput->GetOutputKind() == ReformatOutput::kOutputBitmap) { - CClientDC dcScreen(this); - HBITMAP hBitmap; + /* + * Add the appropriate data. If the "bitmap" flag is set, use the + * MyDIBitmap pointer instead. + */ + if (fpOutput->GetOutputKind() == ReformatOutput::kOutputBitmap) { + CClientDC dcScreen(this); + HBITMAP hBitmap; - if (fpRichEditOle == nil) { - /* can't do this in OnInitDialog -- m_pWnd isn't initialized */ - fpRichEditOle = pEdit->GetIRichEditOle(); - ASSERT(fpRichEditOle != nil); - } + if (fpRichEditOle == nil) { + /* can't do this in OnInitDialog -- m_pWnd isn't initialized */ + fpRichEditOle = pEdit->GetIRichEditOle(); + ASSERT(fpRichEditOle != nil); + } - //FILE* fp = fopen("C:/test/output.bmp", "wb"); - //if (fp != nil) { - // pDib->WriteToFile(fp); - // fclose(fp); - //} - - hBitmap = fpOutput->GetDIB()->ConvertToDDB(dcScreen.m_hDC); - if (hBitmap == nil) { - WMSG0("ConvertToDDB failed!\n"); - pEdit->SetWindowText("Internal error."); - errFlg = true; - } else { - //DumpBitmapInfo(hBitmap); - //DumpBitmapInfo(pDib->GetHandle()); + //FILE* fp = fopen("C:/test/output.bmp", "wb"); + //if (fp != nil) { + // pDib->WriteToFile(fp); + // fclose(fp); + //} + + hBitmap = fpOutput->GetDIB()->ConvertToDDB(dcScreen.m_hDC); + if (hBitmap == nil) { + WMSG0("ConvertToDDB failed!\n"); + pEdit->SetWindowText("Internal error."); + errFlg = true; + } else { + //DumpBitmapInfo(hBitmap); + //DumpBitmapInfo(pDib->GetHandle()); - WMSG0("Inserting bitmap\n"); - pEdit->SetWindowText(""); - CImageDataObject::InsertBitmap(fpRichEditOle, hBitmap); + WMSG0("Inserting bitmap\n"); + pEdit->SetWindowText(""); + CImageDataObject::InsertBitmap(fpRichEditOle, hBitmap); - /* RichEditCtrl has it now */ - ::DeleteObject(hBitmap); - } - } else { - /* - * Stream the data in, using the appropriate format. Since we don't - * have the "replace selection" flag set, this replaces everything - * that's currently in there. - * - * We can't use SetWindowText() unless we're willing to forgo viewing - * of binary files in "raw" form. There doesn't seem to be any other - * difference between the two approaches. - */ - const char* textBuf; - long textLen; - int streamFormat; + /* RichEditCtrl has it now */ + ::DeleteObject(hBitmap); + } + } else { + /* + * Stream the data in, using the appropriate format. Since we don't + * have the "replace selection" flag set, this replaces everything + * that's currently in there. + * + * We can't use SetWindowText() unless we're willing to forgo viewing + * of binary files in "raw" form. There doesn't seem to be any other + * difference between the two approaches. + */ + const char* textBuf; + long textLen; + int streamFormat; - textBuf = fpOutput->GetTextBuf(); - textLen = fpOutput->GetTextLen(); - streamFormat = SF_TEXT; - if (fpOutput->GetOutputKind() == ReformatOutput::kOutputRTF) - streamFormat = SF_RTF; - if (fpOutput->GetTextLen() == 0) { - textBuf = _T("(file is empty)"); - textLen = strlen(textBuf); - emptyFlg = true; - EnableFormatSelection(FALSE); - } - if (fpOutput->GetOutputKind() == ReformatOutput::kOutputErrorMsg) - EnableFormatSelection(FALSE); + textBuf = fpOutput->GetTextBuf(); + textLen = fpOutput->GetTextLen(); + streamFormat = SF_TEXT; + if (fpOutput->GetOutputKind() == ReformatOutput::kOutputRTF) + streamFormat = SF_RTF; + if (fpOutput->GetTextLen() == 0) { + textBuf = _T("(file is empty)"); + textLen = strlen(textBuf); + emptyFlg = true; + EnableFormatSelection(FALSE); + } + if (fpOutput->GetOutputKind() == ReformatOutput::kOutputErrorMsg) + EnableFormatSelection(FALSE); - /* make sure the control will hold everything we throw at it */ - pEdit->LimitText(textLen+1); - WMSG2("Streaming %ld bytes (kind=%d)\n", - textLen, fpOutput->GetOutputKind()); + /* make sure the control will hold everything we throw at it */ + pEdit->LimitText(textLen+1); + WMSG2("Streaming %ld bytes (kind=%d)\n", + textLen, fpOutput->GetOutputKind()); - /* clear this early to avoid loading onto yellow */ - if (errFlg) - pEdit->SetBackgroundColor(FALSE, RGB(255, 255, 0)); - else if (emptyFlg) - pEdit->SetBackgroundColor(FALSE, RGB(192, 192, 192)); - else - pEdit->SetBackgroundColor(TRUE, 0); + /* clear this early to avoid loading onto yellow */ + if (errFlg) + pEdit->SetBackgroundColor(FALSE, RGB(255, 255, 0)); + else if (emptyFlg) + pEdit->SetBackgroundColor(FALSE, RGB(192, 192, 192)); + else + pEdit->SetBackgroundColor(TRUE, 0); - RichEditXfer xfer(textBuf, textLen); - EDITSTREAM es; - es.dwCookie = (DWORD) &xfer; - es.dwError = 0; - es.pfnCallback = RichEditXfer::EditStreamCallback; - long count; - count = pEdit->StreamIn(streamFormat, es); - WMSG2("StreamIn returned count=%ld dwError=%d\n", count, es.dwError); + RichEditXfer xfer(textBuf, textLen); + EDITSTREAM es; + es.dwCookie = (DWORD) &xfer; + es.dwError = 0; + es.pfnCallback = RichEditXfer::EditStreamCallback; + long count; + count = pEdit->StreamIn(streamFormat, es); + WMSG2("StreamIn returned count=%ld dwError=%d\n", count, es.dwError); - if (es.dwError != 0) { - /* a -16 error can happen if the type is RTF but contents are not */ - char errorText[256]; + if (es.dwError != 0) { + /* a -16 error can happen if the type is RTF but contents are not */ + char errorText[256]; - sprintf(errorText, - "ERROR: failed while loading data (err=0x%08lx)\n" - "(File contents might be too big for Windows to display)\n", - es.dwError); - RichEditXfer errXfer(errorText, strlen(errorText)); - es.dwCookie = (DWORD) &errXfer; - es.dwError = 0; + sprintf(errorText, + "ERROR: failed while loading data (err=0x%08lx)\n" + "(File contents might be too big for Windows to display)\n", + es.dwError); + RichEditXfer errXfer(errorText, strlen(errorText)); + es.dwCookie = (DWORD) &errXfer; + es.dwError = 0; - count = pEdit->StreamIn(SF_TEXT, es); - WMSG2("Error StreamIn returned count=%ld dwError=%d\n", count, es.dwError); + count = pEdit->StreamIn(SF_TEXT, es); + WMSG2("Error StreamIn returned count=%ld dwError=%d\n", count, es.dwError); - errFlg = true; - } + errFlg = true; + } - //pEdit->SetSel(0, 0); - } + //pEdit->SetSel(0, 0); + } - /* move us back to the top */ - pEdit->LineScroll(-pEdit->GetFirstVisibleLine()); + /* move us back to the top */ + pEdit->LineScroll(-pEdit->GetFirstVisibleLine()); - /* just in case it's trying to hold on to something */ - pEdit->EmptyUndoBuffer(); + /* just in case it's trying to hold on to something */ + pEdit->EmptyUndoBuffer(); - /* work around bug that creates unnecessary scroll bars */ - pEdit->SetScrollRange(SB_VERT, 0, 0, TRUE); - pEdit->SetScrollRange(SB_HORZ, 0, 0, TRUE); + /* work around bug that creates unnecessary scroll bars */ + pEdit->SetScrollRange(SB_VERT, 0, 0, TRUE); + pEdit->SetScrollRange(SB_HORZ, 0, 0, TRUE); - /* display the entire message in the user's selected font */ - if (!fpOutput->GetMultipleFontsFlag()) { - // adjust the font, stripping default boldness from SF_TEXT - NewFontSelected(fpOutput->GetOutputKind() != ReformatOutput::kOutputRTF); - } + /* display the entire message in the user's selected font */ + if (!fpOutput->GetMultipleFontsFlag()) { + // adjust the font, stripping default boldness from SF_TEXT + NewFontSelected(fpOutput->GetOutputKind() != ReformatOutput::kOutputRTF); + } - /* enable/disable the scroll bars */ - //pEdit->EnableScrollBar(SB_BOTH, ESB_DISABLE_BOTH); + /* enable/disable the scroll bars */ + //pEdit->EnableScrollBar(SB_BOTH, ESB_DISABLE_BOTH); - if (errFlg) - pEdit->SetBackgroundColor(FALSE, RGB(255, 255, 0)); - else if (emptyFlg) - pEdit->SetBackgroundColor(FALSE, RGB(192, 192, 192)); - else - pEdit->SetBackgroundColor(TRUE, 0); + if (errFlg) + pEdit->SetBackgroundColor(FALSE, RGB(255, 255, 0)); + else if (emptyFlg) + pEdit->SetBackgroundColor(FALSE, RGB(192, 192, 192)); + else + pEdit->SetBackgroundColor(TRUE, 0); - /* - * Work around a Windows bug that prevents the scroll bars from - * being displayed immediately. This makes them appear, but the - * vertical scroll bar comes out funky on short files (fixed with - * the SetScrollRange call above). - * - * Best guess: when the edit box is resized, it chooses the scroll bar - * configuration based on the currently-loaded data. If you resize it - * and *then* add data, you're stuck with the previous scroll bar - * values. This doesn't quite make sense though... - * - * This works: - * - Set up dialog. - * - Load data. - * - Do minor twiddling. - * - Resize box significantly. - * - * This works: - * - (box already has data in it) - * - Load new data. - * - Do minor twiddling. - * - * This doesn't: - * - Set up dialog - * - Resize box significantly. - * - Load data. - * - Do minor twiddling. - * - * There might be some first-time setup issues in here. Hard to say. - * Anything related to RichEdit controls is extremely fragile, and must - * be tested with a variety of inputs, preference settings, and under - * at least Win98 and Win2K (which are *very* different). - */ - if (fFirstResize) { - /* adjust the size of the window to match the last size used */ - const Preferences* pPreferences = GET_PREFERENCES(); - long width = pPreferences->GetPrefLong(kPrFileViewerWidth); - long height = pPreferences->GetPrefLong(kPrFileViewerHeight); - CRect fullRect; - GetWindowRect(&fullRect); - //WMSG2(" VFD pre-size %dx%d\n", fullRect.Width(), fullRect.Height()); - fullRect.right = fullRect.left + width; - fullRect.bottom = fullRect.top + height; - MoveWindow(fullRect, TRUE); + /* + * Work around a Windows bug that prevents the scroll bars from + * being displayed immediately. This makes them appear, but the + * vertical scroll bar comes out funky on short files (fixed with + * the SetScrollRange call above). + * + * Best guess: when the edit box is resized, it chooses the scroll bar + * configuration based on the currently-loaded data. If you resize it + * and *then* add data, you're stuck with the previous scroll bar + * values. This doesn't quite make sense though... + * + * This works: + * - Set up dialog. + * - Load data. + * - Do minor twiddling. + * - Resize box significantly. + * + * This works: + * - (box already has data in it) + * - Load new data. + * - Do minor twiddling. + * + * This doesn't: + * - Set up dialog + * - Resize box significantly. + * - Load data. + * - Do minor twiddling. + * + * There might be some first-time setup issues in here. Hard to say. + * Anything related to RichEdit controls is extremely fragile, and must + * be tested with a variety of inputs, preference settings, and under + * at least Win98 and Win2K (which are *very* different). + */ + if (fFirstResize) { + /* adjust the size of the window to match the last size used */ + const Preferences* pPreferences = GET_PREFERENCES(); + long width = pPreferences->GetPrefLong(kPrFileViewerWidth); + long height = pPreferences->GetPrefLong(kPrFileViewerHeight); + CRect fullRect; + GetWindowRect(&fullRect); + //WMSG2(" VFD pre-size %dx%d\n", fullRect.Width(), fullRect.Height()); + fullRect.right = fullRect.left + width; + fullRect.bottom = fullRect.top + height; + MoveWindow(fullRect, TRUE); - editHadFocus = true; // force focus on edit box + editHadFocus = true; // force focus on edit box - fFirstResize = false; - } else { - /* this should be enough */ - ShiftControls(0, 0); - } - - if (fpOutput->GetOutputKind() == ReformatOutput::kOutputBitmap) { - /* get the cursor off of the image */ - pEdit->SetSel(-1, -1); - } + fFirstResize = false; + } else { + /* this should be enough */ + ShiftControls(0, 0); + } + + if (fpOutput->GetOutputKind() == ReformatOutput::kOutputBitmap) { + /* get the cursor off of the image */ + pEdit->SetSel(-1, -1); + } - /* - * We want the focus to be on the text window so keyboard selection - * commands work. However, it's also nice to be able to arrow through - * the format selection box. - */ - if (editHadFocus) - pEdit->SetFocus(); + /* + * We want the focus to be on the text window so keyboard selection + * commands work. However, it's also nice to be able to arrow through + * the format selection box. + */ + if (editHadFocus) + pEdit->SetFocus(); - fTitle = fileName; - //if (fpOutput->GetOutputKind() == ReformatOutput::kOutputText || - // fpOutput->GetOutputKind() == ReformatOutput::kOutputRTF || - // fpOutput->GetOutputKind() == ReformatOutput::kOutputCSV || - // fpOutput->GetOutputKind() == ReformatOutput::kOutputBitmap || - // fpOutput->GetOutputKind() == ReformatOutput::kOutputRaw) - //{ - // not for error messages - fTitle += _T(" ["); - fTitle += fpOutput->GetFormatDescr(); - fTitle += _T("]"); - //} else if (fpOutput->GetOutputKind() == ReformatOutput::kOutputRaw) { - // fTitle += _T(" [Raw]"); - //} + fTitle = fileName; + //if (fpOutput->GetOutputKind() == ReformatOutput::kOutputText || + // fpOutput->GetOutputKind() == ReformatOutput::kOutputRTF || + // fpOutput->GetOutputKind() == ReformatOutput::kOutputCSV || + // fpOutput->GetOutputKind() == ReformatOutput::kOutputBitmap || + // fpOutput->GetOutputKind() == ReformatOutput::kOutputRaw) + //{ + // not for error messages + fTitle += _T(" ["); + fTitle += fpOutput->GetFormatDescr(); + fTitle += _T("]"); + //} else if (fpOutput->GetOutputKind() == ReformatOutput::kOutputRaw) { + // fTitle += _T(" [Raw]"); + //} - CString winTitle = _T("File Viewer - "); - winTitle += fTitle; - SetWindowText(winTitle); + CString winTitle = _T("File Viewer - "); + winTitle += fTitle; + SetWindowText(winTitle); - /* - * Enable or disable the next/prev buttons. - */ - CButton* pButton; - pButton = (CButton*) GetDlgItem(IDC_FVIEW_PREV); - pButton->EnableWindow(fpSelSet->IterHasPrev()); - pButton = (CButton*) GetDlgItem(IDC_FVIEW_NEXT); - pButton->EnableWindow(fpSelSet->IterHasNext()); + /* + * Enable or disable the next/prev buttons. + */ + CButton* pButton; + pButton = (CButton*) GetDlgItem(IDC_FVIEW_PREV); + pButton->EnableWindow(fpSelSet->IterHasPrev()); + pButton = (CButton*) GetDlgItem(IDC_FVIEW_NEXT); + pButton->EnableWindow(fpSelSet->IterHasNext()); } /* @@ -631,55 +631,55 @@ ViewFilesDialog::DisplayText(const char* fileName) void ViewFilesDialog::OnFviewNext(void) { - ReformatHolder::ReformatPart part; - ReformatHolder::ReformatID id; - int result; + ReformatHolder::ReformatPart part; + ReformatHolder::ReformatID id; + int result; - if (fBusy) { - WMSG0("BUSY!\n"); - return; - } + if (fBusy) { + WMSG0("BUSY!\n"); + return; + } - fBusy = true; + fBusy = true; - if (!fpSelSet->IterHasNext()) { - ASSERT(false); - return; - } + if (!fpSelSet->IterHasNext()) { + ASSERT(false); + return; + } - /* - * Get the pieces of the file. - */ - SelectionEntry* pSelEntry = fpSelSet->IterNext(); - GenericEntry* pEntry = pSelEntry->GetEntry(); - result = ReformatPrep(pEntry); + /* + * Get the pieces of the file. + */ + SelectionEntry* pSelEntry = fpSelSet->IterNext(); + GenericEntry* pEntry = pSelEntry->GetEntry(); + result = ReformatPrep(pEntry); #if 0 - { - // for debugging -- simulate failure - result = -1; - delete fpHolder; - fpHolder = nil; - delete fpOutput; - fpOutput = nil; - } + { + // for debugging -- simulate failure + result = -1; + delete fpHolder; + fpHolder = nil; + delete fpOutput; + fpOutput = nil; + } #endif - fBusy = false; - if (result != 0) { - ASSERT(fpHolder == nil); - ASSERT(fpOutput == nil); - return; - } + fBusy = false; + if (result != 0) { + ASSERT(fpHolder == nil); + ASSERT(fpOutput == nil); + return; + } - /* - * Format a piece. - */ - ConfigurePartButtons(pSelEntry->GetEntry()); - part = GetSelectedPart(); - id = ConfigureFormatSel(part); - Reformat(pSelEntry->GetEntry(), part, id); + /* + * Format a piece. + */ + ConfigurePartButtons(pSelEntry->GetEntry()); + part = GetSelectedPart(); + id = ConfigureFormatSel(part); + Reformat(pSelEntry->GetEntry(), part, id); - DisplayText(pSelEntry->GetEntry()->GetDisplayName()); + DisplayText(pSelEntry->GetEntry()->GetDisplayName()); } /* @@ -688,45 +688,45 @@ ViewFilesDialog::OnFviewNext(void) void ViewFilesDialog::OnFviewPrev(void) { - ReformatHolder::ReformatPart part; - ReformatHolder::ReformatID id; - int result; + ReformatHolder::ReformatPart part; + ReformatHolder::ReformatID id; + int result; - if (fBusy) { - WMSG0("BUSY!\n"); - return; - } + if (fBusy) { + WMSG0("BUSY!\n"); + return; + } - fBusy = true; + fBusy = true; - if (!fpSelSet->IterHasPrev()) { - ASSERT(false); - return; - } + if (!fpSelSet->IterHasPrev()) { + ASSERT(false); + return; + } - /* - * Get the pieces of the file. - */ - SelectionEntry* pSelEntry = fpSelSet->IterPrev(); - GenericEntry* pEntry = pSelEntry->GetEntry(); - result = ReformatPrep(pEntry); + /* + * Get the pieces of the file. + */ + SelectionEntry* pSelEntry = fpSelSet->IterPrev(); + GenericEntry* pEntry = pSelEntry->GetEntry(); + result = ReformatPrep(pEntry); - fBusy = false; - if (result != 0) { - ASSERT(fpHolder == nil); - ASSERT(fpOutput == nil); - return; - } + fBusy = false; + if (result != 0) { + ASSERT(fpHolder == nil); + ASSERT(fpOutput == nil); + return; + } - /* - * Format a piece. - */ - ConfigurePartButtons(pEntry); - part = GetSelectedPart(); - id = ConfigureFormatSel(part); - Reformat(pEntry, part, id); + /* + * Format a piece. + */ + ConfigurePartButtons(pEntry); + part = GetSelectedPart(); + id = ConfigureFormatSel(part); + Reformat(pEntry, part, id); - DisplayText(pEntry->GetDisplayName()); + DisplayText(pEntry->GetDisplayName()); } /* @@ -741,53 +741,53 @@ ViewFilesDialog::OnFviewPrev(void) void ViewFilesDialog::ConfigurePartButtons(const GenericEntry* pEntry) { - int id = 0; + int id = 0; - CButton* pDataWnd = (CButton*) GetDlgItem(IDC_FVIEW_DATA); - CButton* pRsrcWnd = (CButton*) GetDlgItem(IDC_FVIEW_RSRC); - CButton* pCmmtWnd = (CButton*) GetDlgItem(IDC_FVIEW_CMMT); - ASSERT(pDataWnd != nil && pRsrcWnd != nil && pCmmtWnd != nil); + CButton* pDataWnd = (CButton*) GetDlgItem(IDC_FVIEW_DATA); + CButton* pRsrcWnd = (CButton*) GetDlgItem(IDC_FVIEW_RSRC); + CButton* pCmmtWnd = (CButton*) GetDlgItem(IDC_FVIEW_CMMT); + ASSERT(pDataWnd != nil && pRsrcWnd != nil && pCmmtWnd != nil); - /* figure out what was checked before, ignoring if it's not available */ - if (pDataWnd->GetCheck() == BST_CHECKED && pEntry->GetHasDataFork()) - id = IDC_FVIEW_DATA; - else if (pRsrcWnd->GetCheck() == BST_CHECKED && pEntry->GetHasRsrcFork()) - id = IDC_FVIEW_RSRC; - else if (pCmmtWnd->GetCheck() == BST_CHECKED && pEntry->GetHasComment()) - id = IDC_FVIEW_CMMT; + /* figure out what was checked before, ignoring if it's not available */ + if (pDataWnd->GetCheck() == BST_CHECKED && pEntry->GetHasDataFork()) + id = IDC_FVIEW_DATA; + else if (pRsrcWnd->GetCheck() == BST_CHECKED && pEntry->GetHasRsrcFork()) + id = IDC_FVIEW_RSRC; + else if (pCmmtWnd->GetCheck() == BST_CHECKED && pEntry->GetHasComment()) + id = IDC_FVIEW_CMMT; - /* couldn't keep previous check, find a new one */ - if (id == 0) { - if (pEntry->GetHasDataFork()) - id = IDC_FVIEW_DATA; - else if (pEntry->GetHasRsrcFork()) - id = IDC_FVIEW_RSRC; - else if (pEntry->GetHasComment()) - id = IDC_FVIEW_CMMT; - // else leave it set to 0 - } + /* couldn't keep previous check, find a new one */ + if (id == 0) { + if (pEntry->GetHasDataFork()) + id = IDC_FVIEW_DATA; + else if (pEntry->GetHasRsrcFork()) + id = IDC_FVIEW_RSRC; + else if (pEntry->GetHasComment()) + id = IDC_FVIEW_CMMT; + // else leave it set to 0 + } - /* set up the dialog */ - pDataWnd->SetCheck(BST_UNCHECKED); - pRsrcWnd->SetCheck(BST_UNCHECKED); - pCmmtWnd->SetCheck(BST_UNCHECKED); + /* set up the dialog */ + pDataWnd->SetCheck(BST_UNCHECKED); + pRsrcWnd->SetCheck(BST_UNCHECKED); + pCmmtWnd->SetCheck(BST_UNCHECKED); - if (pEntry == nil) { - pDataWnd->EnableWindow(FALSE); - pRsrcWnd->EnableWindow(FALSE); - pCmmtWnd->EnableWindow(FALSE); - } else { - pDataWnd->EnableWindow(pEntry->GetHasDataFork()); - pRsrcWnd->EnableWindow(pEntry->GetHasRsrcFork()); - pCmmtWnd->EnableWindow(pEntry->GetHasComment()); - } + if (pEntry == nil) { + pDataWnd->EnableWindow(FALSE); + pRsrcWnd->EnableWindow(FALSE); + pCmmtWnd->EnableWindow(FALSE); + } else { + pDataWnd->EnableWindow(pEntry->GetHasDataFork()); + pRsrcWnd->EnableWindow(pEntry->GetHasRsrcFork()); + pCmmtWnd->EnableWindow(pEntry->GetHasComment()); + } - if (id == IDC_FVIEW_RSRC) - pRsrcWnd->SetCheck(BST_CHECKED); - else if (id == IDC_FVIEW_CMMT) - pCmmtWnd->SetCheck(BST_CHECKED); - else - pDataWnd->SetCheck(BST_CHECKED); + if (id == IDC_FVIEW_RSRC) + pRsrcWnd->SetCheck(BST_CHECKED); + else if (id == IDC_FVIEW_CMMT) + pCmmtWnd->SetCheck(BST_CHECKED); + else + pDataWnd->SetCheck(BST_CHECKED); } /* @@ -798,21 +798,21 @@ ViewFilesDialog::ConfigurePartButtons(const GenericEntry* pEntry) ReformatHolder::ReformatPart ViewFilesDialog::GetSelectedPart(void) { - CButton* pDataWnd = (CButton*) GetDlgItem(IDC_FVIEW_DATA); - CButton* pRsrcWnd = (CButton*) GetDlgItem(IDC_FVIEW_RSRC); - CButton* pCmmtWnd = (CButton*) GetDlgItem(IDC_FVIEW_CMMT); - ASSERT(pDataWnd != nil && pRsrcWnd != nil && pCmmtWnd != nil); + CButton* pDataWnd = (CButton*) GetDlgItem(IDC_FVIEW_DATA); + CButton* pRsrcWnd = (CButton*) GetDlgItem(IDC_FVIEW_RSRC); + CButton* pCmmtWnd = (CButton*) GetDlgItem(IDC_FVIEW_CMMT); + ASSERT(pDataWnd != nil && pRsrcWnd != nil && pCmmtWnd != nil); - if (pDataWnd->GetCheck() == BST_CHECKED) - return ReformatHolder::kPartData; - else if (pRsrcWnd->GetCheck() == BST_CHECKED) - return ReformatHolder::kPartRsrc; - else if (pCmmtWnd->GetCheck() == BST_CHECKED) - return ReformatHolder::kPartCmmt; - else { - assert(false); - return ReformatHolder::kPartData; - } + if (pDataWnd->GetCheck() == BST_CHECKED) + return ReformatHolder::kPartData; + else if (pRsrcWnd->GetCheck() == BST_CHECKED) + return ReformatHolder::kPartRsrc; + else if (pCmmtWnd->GetCheck() == BST_CHECKED) + return ReformatHolder::kPartCmmt; + else { + assert(false); + return ReformatHolder::kPartData; + } } /* @@ -824,35 +824,35 @@ ViewFilesDialog::GetSelectedPart(void) int ViewFilesDialog::ReformatPrep(GenericEntry* pEntry) { - CWaitCursor waitc; // can be slow reading data from floppy - MainWindow* pMainWindow = GET_MAIN_WINDOW(); - int result; + CWaitCursor waitc; // can be slow reading data from floppy + MainWindow* pMainWindow = GET_MAIN_WINDOW(); + int result; - delete fpHolder; - fpHolder = nil; + delete fpHolder; + fpHolder = nil; - result = pMainWindow->GetFileParts(pEntry, &fpHolder); - if (result != 0) { - WMSG0("GetFileParts(prev) failed!\n"); - ASSERT(fpHolder == nil); - return -1; - } + result = pMainWindow->GetFileParts(pEntry, &fpHolder); + if (result != 0) { + WMSG0("GetFileParts(prev) failed!\n"); + ASSERT(fpHolder == nil); + return -1; + } - /* set up the ReformatHolder */ - MainWindow::ConfigureReformatFromPreferences(fpHolder); + /* set up the ReformatHolder */ + MainWindow::ConfigureReformatFromPreferences(fpHolder); - /* prep for applicability test */ - fpHolder->SetSourceAttributes( - pEntry->GetFileType(), - pEntry->GetAuxType(), - MainWindow::ReformatterSourceFormat(pEntry->GetSourceFS()), - pEntry->GetFileNameExtension()); + /* prep for applicability test */ + fpHolder->SetSourceAttributes( + pEntry->GetFileType(), + pEntry->GetAuxType(), + MainWindow::ReformatterSourceFormat(pEntry->GetSourceFS()), + pEntry->GetFileNameExtension()); - /* figure out which reformatters apply to this file */ - WMSG0("Testing reformatters\n"); - fpHolder->TestApplicability(); + /* figure out which reformatters apply to this file */ + WMSG0("Testing reformatters\n"); + fpHolder->TestApplicability(); - return 0; + return 0; } /* @@ -862,45 +862,45 @@ ViewFilesDialog::ReformatPrep(GenericEntry* pEntry) */ int ViewFilesDialog::Reformat(const GenericEntry* pEntry, - ReformatHolder::ReformatPart part, ReformatHolder::ReformatID id) + ReformatHolder::ReformatPart part, ReformatHolder::ReformatID id) { - CWaitCursor waitc; + CWaitCursor waitc; - delete fpOutput; - fpOutput = nil; + delete fpOutput; + fpOutput = nil; - /* run the best one */ - fpOutput = fpHolder->Apply(part, id); + /* run the best one */ + fpOutput = fpHolder->Apply(part, id); //bail: - if (fpOutput != nil) { - // success -- do some sanity checks - switch (fpOutput->GetOutputKind()) { - case ReformatOutput::kOutputText: - case ReformatOutput::kOutputRTF: - case ReformatOutput::kOutputCSV: - case ReformatOutput::kOutputErrorMsg: - ASSERT(fpOutput->GetTextBuf() != nil); - ASSERT(fpOutput->GetDIB() == nil); - break; - case ReformatOutput::kOutputBitmap: - ASSERT(fpOutput->GetDIB() != nil); - ASSERT(fpOutput->GetTextBuf() == nil); - break; - case ReformatOutput::kOutputRaw: - // text buf might be nil - ASSERT(fpOutput->GetDIB() == nil); - break; - } - return 0; - } else { - /* shouldn't get here; handle it if we do */ - static const char* kFailMsg = _T("Internal error\r\n"); - fpOutput = new ReformatOutput; - fpOutput->SetTextBuf((char*) kFailMsg, strlen(kFailMsg), false); - fpOutput->SetOutputKind(ReformatOutput::kOutputErrorMsg); - return -1; - } + if (fpOutput != nil) { + // success -- do some sanity checks + switch (fpOutput->GetOutputKind()) { + case ReformatOutput::kOutputText: + case ReformatOutput::kOutputRTF: + case ReformatOutput::kOutputCSV: + case ReformatOutput::kOutputErrorMsg: + ASSERT(fpOutput->GetTextBuf() != nil); + ASSERT(fpOutput->GetDIB() == nil); + break; + case ReformatOutput::kOutputBitmap: + ASSERT(fpOutput->GetDIB() != nil); + ASSERT(fpOutput->GetTextBuf() == nil); + break; + case ReformatOutput::kOutputRaw: + // text buf might be nil + ASSERT(fpOutput->GetDIB() == nil); + break; + } + return 0; + } else { + /* shouldn't get here; handle it if we do */ + static const char* kFailMsg = _T("Internal error\r\n"); + fpOutput = new ReformatOutput; + fpOutput->SetTextBuf((char*) kFailMsg, strlen(kFailMsg), false); + fpOutput->SetOutputKind(ReformatOutput::kOutputErrorMsg); + return -1; + } } /* @@ -920,87 +920,87 @@ ViewFilesDialog::Reformat(const GenericEntry* pEntry, ReformatHolder::ReformatID ViewFilesDialog::ConfigureFormatSel(ReformatHolder::ReformatPart part) { - //ReformatHolder::ReformatID prevID = ReformatHolder::kReformatUnknown; - ReformatHolder::ReformatID returnID = ReformatHolder::kReformatRaw; - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_FVIEW_FORMATSEL); + //ReformatHolder::ReformatID prevID = ReformatHolder::kReformatUnknown; + ReformatHolder::ReformatID returnID = ReformatHolder::kReformatRaw; + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_FVIEW_FORMATSEL); - WMSG0("--- ConfigureFormatSel\n"); + WMSG0("--- ConfigureFormatSel\n"); - //int sel; - //sel = pCombo->GetCurSel(); - //if (sel != CB_ERR) - // prevID = (ReformatHolder::ReformatID) pCombo->GetItemData(sel); - //WMSG1(" prevID = %d\n", prevID); + //int sel; + //sel = pCombo->GetCurSel(); + //if (sel != CB_ERR) + // prevID = (ReformatHolder::ReformatID) pCombo->GetItemData(sel); + //WMSG1(" prevID = %d\n", prevID); - EnableFormatSelection(TRUE); - pCombo->ResetContent(); + EnableFormatSelection(TRUE); + pCombo->ResetContent(); - /* - * Fill out the combo box with the reformatter entries. - * - * There's probably a way to do this that doesn't involve abusing - * enums, but this'll do for now. - */ - int applyIdx, idIdx; - bool preferred = true; - int comboIdx; - for (applyIdx = ReformatHolder::kApplicMAX; - applyIdx > ReformatHolder::kApplicNot; /*no incr*/) - { - if (applyIdx == ReformatHolder::kApplicMAX) - goto skip; - if (applyIdx == ReformatHolder::kApplicUnknown) - goto skip; + /* + * Fill out the combo box with the reformatter entries. + * + * There's probably a way to do this that doesn't involve abusing + * enums, but this'll do for now. + */ + int applyIdx, idIdx; + bool preferred = true; + int comboIdx; + for (applyIdx = ReformatHolder::kApplicMAX; + applyIdx > ReformatHolder::kApplicNot; /*no incr*/) + { + if (applyIdx == ReformatHolder::kApplicMAX) + goto skip; + if (applyIdx == ReformatHolder::kApplicUnknown) + goto skip; - int testApplies; + int testApplies; - testApplies = applyIdx; - if (preferred) - testApplies |= ReformatHolder::kApplicPreferred; + testApplies = applyIdx; + if (preferred) + testApplies |= ReformatHolder::kApplicPreferred; - for (idIdx = 0; idIdx < ReformatHolder::kReformatMAX; idIdx++) { - if (idIdx == ReformatHolder::kReformatUnknown) - continue; + for (idIdx = 0; idIdx < ReformatHolder::kReformatMAX; idIdx++) { + if (idIdx == ReformatHolder::kReformatUnknown) + continue; - ReformatHolder::ReformatApplies applies; + ReformatHolder::ReformatApplies applies; - applies = fpHolder->GetApplic(part, - (ReformatHolder::ReformatID) idIdx); - if ((int) applies == testApplies) { - /* match! */ - CString str; - //WMSG2("MATCH at %d (0x%02x)\n", idIdx, testApplies); - str.Format("%s", - ReformatHolder::GetReformatName((ReformatHolder::ReformatID) idIdx)); - comboIdx = pCombo->AddString(str); - pCombo->SetItemData(comboIdx, idIdx); + applies = fpHolder->GetApplic(part, + (ReformatHolder::ReformatID) idIdx); + if ((int) applies == testApplies) { + /* match! */ + CString str; + //WMSG2("MATCH at %d (0x%02x)\n", idIdx, testApplies); + str.Format("%s", + ReformatHolder::GetReformatName((ReformatHolder::ReformatID) idIdx)); + comboIdx = pCombo->AddString(str); + pCombo->SetItemData(comboIdx, idIdx); - /* define initial selection as best item */ - if (comboIdx == 0) - pCombo->SetCurSel(comboIdx); + /* define initial selection as best item */ + if (comboIdx == 0) + pCombo->SetCurSel(comboIdx); - //if (idIdx == (int) prevID && - // applyIdx == ReformatHolder::kApplicAlways) - //{ - // WMSG0(" Found 'always' prevID, selecting\n"); - // pCombo->SetCurSel(comboIdx); - //} - } - } + //if (idIdx == (int) prevID && + // applyIdx == ReformatHolder::kApplicAlways) + //{ + // WMSG0(" Found 'always' prevID, selecting\n"); + // pCombo->SetCurSel(comboIdx); + //} + } + } skip: - if (!preferred) - applyIdx--; - preferred = !preferred; - } + if (!preferred) + applyIdx--; + preferred = !preferred; + } - /* return whatever we now have selected */ - int sel = pCombo->GetCurSel(); - WMSG1(" At end, sel is %d\n", sel); - if (sel != CB_ERR) - returnID = (ReformatHolder::ReformatID) pCombo->GetItemData(sel); + /* return whatever we now have selected */ + int sel = pCombo->GetCurSel(); + WMSG1(" At end, sel is %d\n", sel); + if (sel != CB_ERR) + returnID = (ReformatHolder::ReformatID) pCombo->GetItemData(sel); - return returnID; + return returnID; } /* @@ -1011,20 +1011,20 @@ skip: void ViewFilesDialog::OnFormatSelChange(void) { - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_FVIEW_FORMATSEL); - ASSERT(pCombo != nil); - WMSG1("+++ SELECTION IS NOW %d\n", pCombo->GetCurSel()); + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_FVIEW_FORMATSEL); + ASSERT(pCombo != nil); + WMSG1("+++ SELECTION IS NOW %d\n", pCombo->GetCurSel()); - SelectionEntry* pSelEntry = fpSelSet->IterCurrent(); - GenericEntry* pEntry = pSelEntry->GetEntry(); - ReformatHolder::ReformatPart part; - ReformatHolder::ReformatID id; + SelectionEntry* pSelEntry = fpSelSet->IterCurrent(); + GenericEntry* pEntry = pSelEntry->GetEntry(); + ReformatHolder::ReformatPart part; + ReformatHolder::ReformatID id; - part = GetSelectedPart(); - id = (ReformatHolder::ReformatID) pCombo->GetItemData(pCombo->GetCurSel()); - Reformat(pEntry, part, id); + part = GetSelectedPart(); + id = (ReformatHolder::ReformatID) pCombo->GetItemData(pCombo->GetCurSel()); + Reformat(pEntry, part, id); - DisplayText(pEntry->GetDisplayName()); + DisplayText(pEntry->GetDisplayName()); } /* @@ -1033,35 +1033,35 @@ ViewFilesDialog::OnFormatSelChange(void) void ViewFilesDialog::OnFviewData(void) { - ForkSelectCommon(ReformatHolder::kPartData); + ForkSelectCommon(ReformatHolder::kPartData); } void ViewFilesDialog::OnFviewRsrc(void) { - ForkSelectCommon(ReformatHolder::kPartRsrc); + ForkSelectCommon(ReformatHolder::kPartRsrc); } void ViewFilesDialog::OnFviewCmmt(void) { - ForkSelectCommon(ReformatHolder::kPartCmmt); + ForkSelectCommon(ReformatHolder::kPartCmmt); } void ViewFilesDialog::ForkSelectCommon(ReformatHolder::ReformatPart part) { - GenericEntry* pEntry; - ReformatHolder::ReformatID id; + GenericEntry* pEntry; + ReformatHolder::ReformatID id; - WMSG1("Switching to file part=%d\n", part); - ASSERT(fpHolder != nil); - ASSERT(fpSelSet != nil); - ASSERT(fpSelSet->IterCurrent() != nil); - pEntry = fpSelSet->IterCurrent()->GetEntry(); - ASSERT(pEntry != nil); + WMSG1("Switching to file part=%d\n", part); + ASSERT(fpHolder != nil); + ASSERT(fpSelSet != nil); + ASSERT(fpSelSet->IterCurrent() != nil); + pEntry = fpSelSet->IterCurrent()->GetEntry(); + ASSERT(pEntry != nil); - id = ConfigureFormatSel(part); + id = ConfigureFormatSel(part); - Reformat(pEntry, part, id); - DisplayText(pEntry->GetDisplayName()); + Reformat(pEntry, part, id); + DisplayText(pEntry->GetDisplayName()); } /* @@ -1070,10 +1070,10 @@ ViewFilesDialog::ForkSelectCommon(ReformatHolder::ReformatPart part) void ViewFilesDialog::OnFviewFmtBest(void) { - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_FVIEW_FORMATSEL); - pCombo->SetCurSel(0); // best is always at the top - OnFormatSelChange(); - pCombo->SetFocus(); + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_FVIEW_FORMATSEL); + pCombo->SetCurSel(0); // best is always at the top + OnFormatSelChange(); + pCombo->SetFocus(); } /* @@ -1082,13 +1082,13 @@ ViewFilesDialog::OnFviewFmtBest(void) void ViewFilesDialog::OnFviewFmtHex(void) { - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_FVIEW_FORMATSEL); - int sel = FindByVal(pCombo, ReformatHolder::kReformatHexDump); - if (sel < 0) - sel = 0; - pCombo->SetCurSel(sel); - OnFormatSelChange(); - pCombo->SetFocus(); + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_FVIEW_FORMATSEL); + int sel = FindByVal(pCombo, ReformatHolder::kReformatHexDump); + if (sel < 0) + sel = 0; + pCombo->SetCurSel(sel); + OnFormatSelChange(); + pCombo->SetFocus(); } /* @@ -1097,13 +1097,13 @@ ViewFilesDialog::OnFviewFmtHex(void) void ViewFilesDialog::OnFviewFmtRaw(void) { - CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_FVIEW_FORMATSEL); - int sel = FindByVal(pCombo, ReformatHolder::kReformatRaw); - if (sel < 0) - sel = 0; - pCombo->SetCurSel(sel); - OnFormatSelChange(); - pCombo->SetFocus(); + CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_FVIEW_FORMATSEL); + int sel = FindByVal(pCombo, ReformatHolder::kReformatRaw); + if (sel < 0) + sel = 0; + pCombo->SetCurSel(sel); + OnFormatSelChange(); + pCombo->SetFocus(); } /* @@ -1112,10 +1112,10 @@ ViewFilesDialog::OnFviewFmtRaw(void) void ViewFilesDialog::EnableFormatSelection(BOOL enable) { - GetDlgItem(IDC_FVIEW_FORMATSEL)->EnableWindow(enable); - GetDlgItem(IDC_FVIEW_FMT_BEST)->EnableWindow(enable); - GetDlgItem(IDC_FVIEW_FMT_HEX)->EnableWindow(enable); - GetDlgItem(IDC_FVIEW_FMT_RAW)->EnableWindow(enable); + GetDlgItem(IDC_FVIEW_FORMATSEL)->EnableWindow(enable); + GetDlgItem(IDC_FVIEW_FMT_BEST)->EnableWindow(enable); + GetDlgItem(IDC_FVIEW_FMT_HEX)->EnableWindow(enable); + GetDlgItem(IDC_FVIEW_FMT_RAW)->EnableWindow(enable); } /* @@ -1126,14 +1126,14 @@ ViewFilesDialog::EnableFormatSelection(BOOL enable) int ViewFilesDialog::FindByVal(CComboBox* pCombo, DWORD val) { - int count = pCombo->GetCount(); - int i; + int count = pCombo->GetCount(); + int i; - for (i = 0; i < count; i++) { - if (pCombo->GetItemData(i) == val) - return i; - } - return -1; + for (i = 0; i < count; i++) { + if (pCombo->GetItemData(i) == val) + return i; + } + return -1; } /* @@ -1143,27 +1143,27 @@ ViewFilesDialog::FindByVal(CComboBox* pCombo, DWORD val) void ViewFilesDialog::OnFviewFont(void) { - LOGFONT logFont; - CFont font; + LOGFONT logFont; + CFont font; - /* - * Create a LOGFONT structure with the desired default characteristics, - * then use that to initialize the font dialog. - */ - CreateSimpleFont(&font, this, fTypeFace, fPointSize); - font.GetLogFont(&logFont); + /* + * Create a LOGFONT structure with the desired default characteristics, + * then use that to initialize the font dialog. + */ + CreateSimpleFont(&font, this, fTypeFace, fPointSize); + font.GetLogFont(&logFont); - CFontDialog fontDlg(&logFont); - fontDlg.m_cf.Flags &= ~(CF_EFFECTS); + CFontDialog fontDlg(&logFont); + fontDlg.m_cf.Flags &= ~(CF_EFFECTS); - if (fontDlg.DoModal() == IDOK) { - //fontDlg.GetCurrentFont(&logFont); - fTypeFace = fontDlg.GetFaceName(); - fPointSize = fontDlg.GetSize() / 10; - WMSG2("Now using %d-point '%s'\n", fPointSize, (const char*)fTypeFace); + if (fontDlg.DoModal() == IDOK) { + //fontDlg.GetCurrentFont(&logFont); + fTypeFace = fontDlg.GetFaceName(); + fPointSize = fontDlg.GetSize() / 10; + WMSG2("Now using %d-point '%s'\n", fPointSize, (const char*)fTypeFace); - NewFontSelected(false); - } + NewFontSelected(false); + } } @@ -1173,21 +1173,21 @@ ViewFilesDialog::OnFviewFont(void) void ViewFilesDialog::NewFontSelected(bool resetBold) { - CRichEditCtrl* pEdit = (CRichEditCtrl*) GetDlgItem(IDC_FVIEW_EDITBOX); - ASSERT(pEdit != nil); + CRichEditCtrl* pEdit = (CRichEditCtrl*) GetDlgItem(IDC_FVIEW_EDITBOX); + ASSERT(pEdit != nil); - CHARFORMAT cf; - cf.cbSize = sizeof(CHARFORMAT); - cf.dwMask = CFM_FACE | CFM_SIZE; - if (resetBold) { - cf.dwMask |= CFM_BOLD; - cf.dwEffects = 0; - } - ::lstrcpy(cf.szFaceName, fTypeFace); - cf.yHeight = fPointSize * 20; // in twips - pEdit->SetSel(0, -1); // select all - pEdit->SetSelectionCharFormat(cf); - pEdit->SetSel(0, 0); // unselect + CHARFORMAT cf; + cf.cbSize = sizeof(CHARFORMAT); + cf.dwMask = CFM_FACE | CFM_SIZE; + if (resetBold) { + cf.dwMask |= CFM_BOLD; + cf.dwEffects = 0; + } + ::lstrcpy(cf.szFaceName, fTypeFace); + cf.yHeight = fPointSize * 20; // in twips + pEdit->SetSel(0, -1); // select all + pEdit->SetSelectionCharFormat(cf); + pEdit->SetSel(0, 0); // unselect } @@ -1197,88 +1197,88 @@ ViewFilesDialog::NewFontSelected(bool resetBold) void ViewFilesDialog::OnFviewPrint(void) { - MainWindow* pMainWindow = GET_MAIN_WINDOW(); - CPrintDialog dlg(FALSE); // use CPrintDialogEx for Win2K? CPageSetUpDialog? - PrintRichEdit pre; - CDC dc; - int numPages; + MainWindow* pMainWindow = GET_MAIN_WINDOW(); + CPrintDialog dlg(FALSE); // use CPrintDialogEx for Win2K? CPageSetUpDialog? + PrintRichEdit pre; + CDC dc; + int numPages; - dlg.m_pd.nFromPage = dlg.m_pd.nMinPage = 1; - dlg.m_pd.nToPage = dlg.m_pd.nMaxPage = 1; + dlg.m_pd.nFromPage = dlg.m_pd.nMinPage = 1; + dlg.m_pd.nToPage = dlg.m_pd.nMaxPage = 1; - /* - * Getting the expected number of pages requires a print test-run. - * However, if we use GetDefaults to get the DC, the call to DoModal - * returns immediately with IDCANCEL. So, we do our pre-flighting - * in a separate DC with a separate print dialog object. - */ - { - CPrintDialog countDlg(FALSE); - CDC countDC; + /* + * Getting the expected number of pages requires a print test-run. + * However, if we use GetDefaults to get the DC, the call to DoModal + * returns immediately with IDCANCEL. So, we do our pre-flighting + * in a separate DC with a separate print dialog object. + */ + { + CPrintDialog countDlg(FALSE); + CDC countDC; - dlg.m_pd.hDevMode = pMainWindow->fhDevMode; - dlg.m_pd.hDevNames = pMainWindow->fhDevNames; + dlg.m_pd.hDevMode = pMainWindow->fhDevMode; + dlg.m_pd.hDevNames = pMainWindow->fhDevNames; - if (countDlg.GetDefaults() == TRUE) { - CWaitCursor waitc; + if (countDlg.GetDefaults() == TRUE) { + CWaitCursor waitc; - if (countDC.Attach(countDlg.GetPrinterDC()) != TRUE) { - ASSERT(false); - } - pre.Setup(&countDC, this); - pre.PrintPreflight(&fEditCtrl, &numPages); - WMSG1("Default printer generated %d pages\n", numPages); + if (countDC.Attach(countDlg.GetPrinterDC()) != TRUE) { + ASSERT(false); + } + pre.Setup(&countDC, this); + pre.PrintPreflight(&fEditCtrl, &numPages); + WMSG1("Default printer generated %d pages\n", numPages); - dlg.m_pd.nToPage = dlg.m_pd.nMaxPage = numPages; - } + dlg.m_pd.nToPage = dlg.m_pd.nMaxPage = numPages; + } - pMainWindow->fhDevMode = dlg.m_pd.hDevMode; - pMainWindow->fhDevNames = dlg.m_pd.hDevNames; - } + pMainWindow->fhDevMode = dlg.m_pd.hDevMode; + pMainWindow->fhDevNames = dlg.m_pd.hDevNames; + } - long startChar, endChar; - fEditCtrl.GetSel(/*ref*/startChar, /*ref*/endChar); + long startChar, endChar; + fEditCtrl.GetSel(/*ref*/startChar, /*ref*/endChar); - if (endChar != startChar) { - WMSG2("GetSel returned start=%ld end=%ld\n", startChar, endChar); - dlg.m_pd.Flags &= ~(PD_NOSELECTION); - } + if (endChar != startChar) { + WMSG2("GetSel returned start=%ld end=%ld\n", startChar, endChar); + dlg.m_pd.Flags &= ~(PD_NOSELECTION); + } - dlg.m_pd.hDevMode = pMainWindow->fhDevMode; - dlg.m_pd.hDevNames = pMainWindow->fhDevNames; - dlg.m_pd.Flags |= PD_USEDEVMODECOPIESANDCOLLATE; - dlg.m_pd.Flags &= ~(PD_NOPAGENUMS); + dlg.m_pd.hDevMode = pMainWindow->fhDevMode; + dlg.m_pd.hDevNames = pMainWindow->fhDevNames; + dlg.m_pd.Flags |= PD_USEDEVMODECOPIESANDCOLLATE; + dlg.m_pd.Flags &= ~(PD_NOPAGENUMS); - /* - * Show them the print dialog. - */ - if (dlg.DoModal() != IDOK) - return; + /* + * Show them the print dialog. + */ + if (dlg.DoModal() != IDOK) + return; - /* - * Grab the chosen printer and prep ourselves. - */ - if (dc.Attach(dlg.GetPrinterDC()) != TRUE) { - CString msg; - msg.LoadString(IDS_PRINTER_NOT_USABLE); - ShowFailureMsg(this, msg, IDS_FAILED); - return; - } - pre.Setup(&dc, this); + /* + * Grab the chosen printer and prep ourselves. + */ + if (dc.Attach(dlg.GetPrinterDC()) != TRUE) { + CString msg; + msg.LoadString(IDS_PRINTER_NOT_USABLE); + ShowFailureMsg(this, msg, IDS_FAILED); + return; + } + pre.Setup(&dc, this); - /* - * Do the printing. - */ - if (dlg.PrintRange()) - pre.PrintPages(&fEditCtrl, fTitle, dlg.GetFromPage(), dlg.GetToPage()); - else if (dlg.PrintSelection()) - pre.PrintSelection(&fEditCtrl, fTitle, startChar, endChar); - else // dlg.PrintAll() - pre.PrintAll(&fEditCtrl, fTitle); + /* + * Do the printing. + */ + if (dlg.PrintRange()) + pre.PrintPages(&fEditCtrl, fTitle, dlg.GetFromPage(), dlg.GetToPage()); + else if (dlg.PrintSelection()) + pre.PrintSelection(&fEditCtrl, fTitle, startChar, endChar); + else // dlg.PrintAll() + pre.PrintAll(&fEditCtrl, fTitle); - pMainWindow->fhDevMode = dlg.m_pd.hDevMode; - pMainWindow->fhDevNames = dlg.m_pd.hDevNames; + pMainWindow->fhDevMode = dlg.m_pd.hDevMode; + pMainWindow->fhDevNames = dlg.m_pd.hDevNames; } /* @@ -1287,31 +1287,31 @@ ViewFilesDialog::OnFviewPrint(void) void ViewFilesDialog::OnFviewFind(void) { - DWORD flags = 0; + DWORD flags = 0; - if (fpFindDialog != nil) - return; + if (fpFindDialog != nil) + return; - if (fFindDown) - flags |= FR_DOWN; - if (fFindMatchCase) - flags |= FR_MATCHCASE; - if (fFindMatchWholeWord) - flags |= FR_WHOLEWORD; + if (fFindDown) + flags |= FR_DOWN; + if (fFindMatchCase) + flags |= FR_MATCHCASE; + if (fFindMatchWholeWord) + flags |= FR_WHOLEWORD; - /* - * I can't get this to work with FindText(). There's a lot of questions - * about this on web sites. Probably safest to just disable it. - */ - flags |= FR_HIDEUPDOWN; + /* + * I can't get this to work with FindText(). There's a lot of questions + * about this on web sites. Probably safest to just disable it. + */ + flags |= FR_HIDEUPDOWN; - fpFindDialog = new CFindReplaceDialog; + fpFindDialog = new CFindReplaceDialog; - fpFindDialog->Create(TRUE, // "find" only - fFindLastStr, // default string to search for - NULL, // default string to replace - flags, // flags - this); // parent + fpFindDialog->Create(TRUE, // "find" only + fFindLastStr, // default string to search for + NULL, // default string to replace + flags, // flags + this); // parent } /* @@ -1320,26 +1320,26 @@ ViewFilesDialog::OnFviewFind(void) LRESULT ViewFilesDialog::OnFindDialogMessage(WPARAM wParam, LPARAM lParam) { - assert(fpFindDialog != nil); + assert(fpFindDialog != nil); - fFindDown = (fpFindDialog->SearchDown() != 0); - fFindMatchCase = (fpFindDialog->MatchCase() != 0); - fFindMatchWholeWord = (fpFindDialog->MatchWholeWord() != 0); + fFindDown = (fpFindDialog->SearchDown() != 0); + fFindMatchCase = (fpFindDialog->MatchCase() != 0); + fFindMatchWholeWord = (fpFindDialog->MatchWholeWord() != 0); - if (fpFindDialog->IsTerminating()) { - WMSG0("VFD find dialog closing\n"); - fpFindDialog = nil; - return 0; - } + if (fpFindDialog->IsTerminating()) { + WMSG0("VFD find dialog closing\n"); + fpFindDialog = nil; + return 0; + } - if (fpFindDialog->FindNext()) { - fFindLastStr = fpFindDialog->GetFindString(); - FindNext(fFindLastStr, fFindDown, fFindMatchCase, fFindMatchWholeWord); - } else { - WMSG0("Unexpected find dialog activity\n"); - } + if (fpFindDialog->FindNext()) { + fFindLastStr = fpFindDialog->GetFindString(); + FindNext(fFindLastStr, fFindDown, fFindMatchCase, fFindMatchWholeWord); + } else { + WMSG0("Unexpected find dialog activity\n"); + } - return 0; + return 0; } @@ -1348,59 +1348,59 @@ ViewFilesDialog::OnFindDialogMessage(WPARAM wParam, LPARAM lParam) */ void ViewFilesDialog::FindNext(const char* str, bool down, bool matchCase, - bool wholeWord) + bool wholeWord) { - WMSG4("FindText '%s' d=%d c=%d w=%d\n", str, down, matchCase, wholeWord); + WMSG4("FindText '%s' d=%d c=%d w=%d\n", str, down, matchCase, wholeWord); - FINDTEXTEX findTextEx = { 0 }; - CHARRANGE selChrg; - DWORD flags = 0; - long start, result; + FINDTEXTEX findTextEx = { 0 }; + CHARRANGE selChrg; + DWORD flags = 0; + long start, result; - if (matchCase) - flags |= FR_MATCHCASE; - if (wholeWord) - flags |= FR_WHOLEWORD; + if (matchCase) + flags |= FR_MATCHCASE; + if (wholeWord) + flags |= FR_WHOLEWORD; - fEditCtrl.GetSel(selChrg); - WMSG2(" selection is %ld,%ld\n", - selChrg.cpMin, selChrg.cpMax); - if (selChrg.cpMin == selChrg.cpMax) - start = selChrg.cpMin; // start at caret - else - start = selChrg.cpMin +1; // start past selection + fEditCtrl.GetSel(selChrg); + WMSG2(" selection is %ld,%ld\n", + selChrg.cpMin, selChrg.cpMax); + if (selChrg.cpMin == selChrg.cpMax) + start = selChrg.cpMin; // start at caret + else + start = selChrg.cpMin +1; // start past selection - findTextEx.chrg.cpMin = start; - findTextEx.chrg.cpMax = -1; - findTextEx.lpstrText = const_cast(str); + findTextEx.chrg.cpMin = start; + findTextEx.chrg.cpMax = -1; + findTextEx.lpstrText = const_cast(str); - /* MSVC++6 claims FindText doesn't exist, even though it's in the header */ - //result = fEditCtrl.FindText(flags, &findTextEx); - result = fEditCtrl.SendMessage(EM_FINDTEXTEX, (WPARAM) flags, - (LPARAM) &findTextEx); + /* MSVC++6 claims FindText doesn't exist, even though it's in the header */ + //result = fEditCtrl.FindText(flags, &findTextEx); + result = fEditCtrl.SendMessage(EM_FINDTEXTEX, (WPARAM) flags, + (LPARAM) &findTextEx); - if (result == -1) { - /* didn't find it, wrap around to start */ - findTextEx.chrg.cpMin = 0; - findTextEx.chrg.cpMax = -1; - findTextEx.lpstrText = const_cast(str); - result = fEditCtrl.SendMessage(EM_FINDTEXTEX, (WPARAM) flags, - (LPARAM) &findTextEx); - } + if (result == -1) { + /* didn't find it, wrap around to start */ + findTextEx.chrg.cpMin = 0; + findTextEx.chrg.cpMax = -1; + findTextEx.lpstrText = const_cast(str); + result = fEditCtrl.SendMessage(EM_FINDTEXTEX, (WPARAM) flags, + (LPARAM) &findTextEx); + } - WMSG3(" result=%ld min=%ld max=%ld\n", result, - findTextEx.chrgText.cpMin, findTextEx.chrgText.cpMax); - if (result != -1) { - /* select the text we found */ - fEditCtrl.SetSel(findTextEx.chrgText); - } else { - /* remove selection, leaving caret at start of sel */ - selChrg.cpMax = selChrg.cpMin; - fEditCtrl.SetSel(selChrg); + WMSG3(" result=%ld min=%ld max=%ld\n", result, + findTextEx.chrgText.cpMin, findTextEx.chrgText.cpMax); + if (result != -1) { + /* select the text we found */ + fEditCtrl.SetSel(findTextEx.chrgText); + } else { + /* remove selection, leaving caret at start of sel */ + selChrg.cpMax = selChrg.cpMin; + fEditCtrl.SetSel(selChrg); - MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); - pMain->FailureBeep(); - } + MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); + pMain->FailureBeep(); + } } /* @@ -1409,5 +1409,5 @@ ViewFilesDialog::FindNext(const char* str, bool down, bool matchCase, void ViewFilesDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_FILE_VIEWER, HELP_CONTEXT); + WinHelp(HELP_TOPIC_FILE_VIEWER, HELP_CONTEXT); } diff --git a/app/ViewFilesDialog.h b/app/ViewFilesDialog.h index 17e519c..38f5ac7 100644 --- a/app/ViewFilesDialog.h +++ b/app/ViewFilesDialog.h @@ -22,135 +22,135 @@ class MainWindow; */ class ViewFilesDialog : public CDialog { public: - ViewFilesDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_FILE_VIEWER, pParentWnd) - { - //fpMainWindow = nil; - fpSelSet = nil; - fpHolder = nil; - fpOutput = nil; - fTypeFace = ""; - fPointSize = 0; - fNoWrapText = false; - fBusy = false; - fpRichEditOle = nil; - fFirstResize = false; + ViewFilesDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_FILE_VIEWER, pParentWnd) + { + //fpMainWindow = nil; + fpSelSet = nil; + fpHolder = nil; + fpOutput = nil; + fTypeFace = ""; + fPointSize = 0; + fNoWrapText = false; + fBusy = false; + fpRichEditOle = nil; + fFirstResize = false; - fpFindDialog = nil; - fFindDown = false; - fFindMatchCase = false; - fFindMatchWholeWord = false; - } - virtual ~ViewFilesDialog(void) { - delete fpHolder; - delete fpOutput; - // Windows will handle destruction of fpFindDialog (child window) - } + fpFindDialog = nil; + fFindDown = false; + fFindMatchCase = false; + fFindMatchWholeWord = false; + } + virtual ~ViewFilesDialog(void) { + delete fpHolder; + delete fpOutput; + // Windows will handle destruction of fpFindDialog (child window) + } - void SetSelectionSet(SelectionSet* pSelSet) { fpSelSet = pSelSet; } + void SetSelectionSet(SelectionSet* pSelSet) { fpSelSet = pSelSet; } - CString GetTextTypeFace(void) const { return fTypeFace; } - void SetTextTypeFace(const char* name) { fTypeFace = name; } - int GetTextPointSize(void) const { return fPointSize; } - void SetTextPointSize(int size) { fPointSize = size; } - //bool GetNoWrapText(void) const { return fNoWrapText; } - void SetNoWrapText(bool val) { fNoWrapText = val; } + CString GetTextTypeFace(void) const { return fTypeFace; } + void SetTextTypeFace(const char* name) { fTypeFace = name; } + int GetTextPointSize(void) const { return fPointSize; } + void SetTextPointSize(int size) { fPointSize = size; } + //bool GetNoWrapText(void) const { return fNoWrapText; } + void SetNoWrapText(bool val) { fNoWrapText = val; } protected: - // overrides - virtual BOOL OnInitDialog(void); - virtual void OnOK(void); - virtual void OnCancel(void); - virtual void DoDataExchange(CDataExchange* pDX); + // overrides + virtual BOOL OnInitDialog(void); + virtual void OnOK(void); + virtual void OnCancel(void); + virtual void DoDataExchange(CDataExchange* pDX); - afx_msg int OnCreate(LPCREATESTRUCT lpcs); - afx_msg void OnDestroy(void); - afx_msg void OnSize(UINT nType, int cx, int cy); - afx_msg void OnGetMinMaxInfo(MINMAXINFO* pMMI); + afx_msg int OnCreate(LPCREATESTRUCT lpcs); + afx_msg void OnDestroy(void); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnGetMinMaxInfo(MINMAXINFO* pMMI); - afx_msg void OnFviewNext(void); - afx_msg void OnFviewPrev(void); - afx_msg void OnFviewFont(void); - afx_msg void OnFviewPrint(void); - afx_msg void OnFviewFind(void); - afx_msg void OnFviewData(void); - afx_msg void OnFviewRsrc(void); - afx_msg void OnFviewCmmt(void); - afx_msg void OnFviewFmtBest(void); - afx_msg void OnFviewFmtHex(void); - afx_msg void OnFviewFmtRaw(void); - afx_msg void OnFormatSelChange(void); - afx_msg void OnHelp(void); - //afx_msg void OnFviewWrap(void); - afx_msg LRESULT OnFindDialogMessage(WPARAM wParam, LPARAM lParam); + afx_msg void OnFviewNext(void); + afx_msg void OnFviewPrev(void); + afx_msg void OnFviewFont(void); + afx_msg void OnFviewPrint(void); + afx_msg void OnFviewFind(void); + afx_msg void OnFviewData(void); + afx_msg void OnFviewRsrc(void); + afx_msg void OnFviewCmmt(void); + afx_msg void OnFviewFmtBest(void); + afx_msg void OnFviewFmtHex(void); + afx_msg void OnFviewFmtRaw(void); + afx_msg void OnFormatSelChange(void); + afx_msg void OnHelp(void); + //afx_msg void OnFviewWrap(void); + afx_msg LRESULT OnFindDialogMessage(WPARAM wParam, LPARAM lParam); private: - void ShiftControls(int deltaX, int deltaY); - //void MoveControl(int id, int deltaX, int deltaY); - //void StretchControl(int id, int deltaX, int deltaY); - void NewFontSelected(bool resetBold); - void DisplayText(const char* fileName); - int ReformatPrep(GenericEntry* pEntry); - int Reformat(const GenericEntry* pEntry, - ReformatHolder::ReformatPart part, ReformatHolder::ReformatID id); - void ConfigurePartButtons(const GenericEntry* pEntry); - ReformatHolder::ReformatPart GetSelectedPart(void); - void ForkSelectCommon(ReformatHolder::ReformatPart part); - ReformatHolder::ReformatID ConfigureFormatSel( - ReformatHolder::ReformatPart part); - int FindByVal(CComboBox* pCombo, DWORD val); - void EnableFormatSelection(BOOL enable); - void FindNext(const char* str, bool down, bool matchCase, - bool wholeWord); + void ShiftControls(int deltaX, int deltaY); + //void MoveControl(int id, int deltaX, int deltaY); + //void StretchControl(int id, int deltaX, int deltaY); + void NewFontSelected(bool resetBold); + void DisplayText(const char* fileName); + int ReformatPrep(GenericEntry* pEntry); + int Reformat(const GenericEntry* pEntry, + ReformatHolder::ReformatPart part, ReformatHolder::ReformatID id); + void ConfigurePartButtons(const GenericEntry* pEntry); + ReformatHolder::ReformatPart GetSelectedPart(void); + void ForkSelectCommon(ReformatHolder::ReformatPart part); + ReformatHolder::ReformatID ConfigureFormatSel( + ReformatHolder::ReformatPart part); + int FindByVal(CComboBox* pCombo, DWORD val); + void EnableFormatSelection(BOOL enable); + void FindNext(const char* str, bool down, bool matchCase, + bool wholeWord); - // pointer to main window, so we can ask for text to view - //MainWindow* fpMainWindow; + // pointer to main window, so we can ask for text to view + //MainWindow* fpMainWindow; - // stuff to display - SelectionSet* fpSelSet; + // stuff to display + SelectionSet* fpSelSet; - // edit control - CRichEditCtrl fEditCtrl; + // edit control + CRichEditCtrl fEditCtrl; - // currently loaded file - ReformatHolder* fpHolder; + // currently loaded file + ReformatHolder* fpHolder; - // most recent conversion - ReformatOutput* fpOutput; + // most recent conversion + ReformatOutput* fpOutput; - // current title of window - CString fTitle; + // current title of window + CString fTitle; - // used to display a "gripper" in the bottom right of the dialog - CGripper fGripper; + // used to display a "gripper" in the bottom right of the dialog + CGripper fGripper; - // last size of the window, so we can shift things around - CRect fLastWinSize; + // last size of the window, so we can shift things around + CRect fLastWinSize; - // font characteristics - CString fTypeFace; // name of font - int fPointSize; // size, in points + // font characteristics + CString fTypeFace; // name of font + int fPointSize; // size, in points - // do we want to scroll or wrap? - bool fNoWrapText; + // do we want to scroll or wrap? + bool fNoWrapText; - // the message pump in the progress updater can cause NufxLib reentrancy - // (alternate solution: disable the window while we load stuff) - bool fBusy; + // the message pump in the progress updater can cause NufxLib reentrancy + // (alternate solution: disable the window while we load stuff) + bool fBusy; - // this is *really* annoying - bool fFirstResize; + // this is *really* annoying + bool fFirstResize; - // used for stuffing images in; points at something inside RichEdit ctrl - IRichEditOle* fpRichEditOle; + // used for stuffing images in; points at something inside RichEdit ctrl + IRichEditOle* fpRichEditOle; - CFindReplaceDialog* fpFindDialog; - CString fFindLastStr; - bool fFindDown; - bool fFindMatchCase; - bool fFindMatchWholeWord; + CFindReplaceDialog* fpFindDialog; + CString fFindLastStr; + bool fFindDown; + bool fFindMatchCase; + bool fFindMatchWholeWord; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__VIEWFILESDIALOG__*/ \ No newline at end of file diff --git a/app/VolumeCopyDialog.cpp b/app/VolumeCopyDialog.cpp index 4cd3cd2..8f862d0 100644 --- a/app/VolumeCopyDialog.cpp +++ b/app/VolumeCopyDialog.cpp @@ -18,11 +18,11 @@ BEGIN_MESSAGE_MAP(VolumeCopyDialog, CDialog) - ON_COMMAND(IDHELP, OnHelp) - ON_COMMAND(IDC_VOLUEMCOPYSEL_TOFILE, OnCopyToFile) - ON_COMMAND(IDC_VOLUEMCOPYSEL_FROMFILE, OnCopyFromFile) - ON_NOTIFY(LVN_ITEMCHANGED, IDC_VOLUMECOPYSEL_LIST, OnListChange) - ON_MESSAGE(WMU_DIALOG_READY, OnDialogReady) + ON_COMMAND(IDHELP, OnHelp) + ON_COMMAND(IDC_VOLUEMCOPYSEL_TOFILE, OnCopyToFile) + ON_COMMAND(IDC_VOLUEMCOPYSEL_FROMFILE, OnCopyFromFile) + ON_NOTIFY(LVN_ITEMCHANGED, IDC_VOLUMECOPYSEL_LIST, OnListChange) + ON_MESSAGE(WMU_DIALOG_READY, OnDialogReady) END_MESSAGE_MAP() @@ -31,31 +31,31 @@ END_MESSAGE_MAP() */ class VolumeXferProgressDialog : public ProgressCancelDialog { public: - BOOL Create(CWnd* pParentWnd = NULL) { - fAbortOperation = false; - return ProgressCancelDialog::Create(&fAbortOperation, - IDD_VOLUMECOPYPROG, IDC_VOLUMECOPYPROG_PROGRESS, pParentWnd); - } + BOOL Create(CWnd* pParentWnd = NULL) { + fAbortOperation = false; + return ProgressCancelDialog::Create(&fAbortOperation, + IDD_VOLUMECOPYPROG, IDC_VOLUMECOPYPROG_PROGRESS, pParentWnd); + } - void SetCurrentFiles(const char* fromName, const char* toName) { - CWnd* pWnd = GetDlgItem(IDC_VOLUMECOPYPROG_FROM); - ASSERT(pWnd != nil); - pWnd->SetWindowText(fromName); - pWnd = GetDlgItem(IDC_VOLUMECOPYPROG_TO); - ASSERT(pWnd != nil); - pWnd->SetWindowText(toName); - } + void SetCurrentFiles(const char* fromName, const char* toName) { + CWnd* pWnd = GetDlgItem(IDC_VOLUMECOPYPROG_FROM); + ASSERT(pWnd != nil); + pWnd->SetWindowText(fromName); + pWnd = GetDlgItem(IDC_VOLUMECOPYPROG_TO); + ASSERT(pWnd != nil); + pWnd->SetWindowText(toName); + } private: - void OnOK(void) { - WMSG0("Ignoring VolumeXferProgressDialog OnOK\n"); - } + void OnOK(void) { + WMSG0("Ignoring VolumeXferProgressDialog OnOK\n"); + } - MainWindow* GetMainWindow(void) const { - return (MainWindow*)::AfxGetMainWnd(); - } + MainWindow* GetMainWindow(void) const { + return (MainWindow*)::AfxGetMainWnd(); + } - bool fAbortOperation; + bool fAbortOperation; }; @@ -65,67 +65,67 @@ private: BOOL VolumeCopyDialog::OnInitDialog(void) { - CRect rect; + CRect rect; - //this->GetWindowRect(&rect); - //WMSG4("RECT is %d, %d, %d, %d\n", rect.left, rect.top, rect.bottom, rect.right); + //this->GetWindowRect(&rect); + //WMSG4("RECT is %d, %d, %d, %d\n", rect.left, rect.top, rect.bottom, rect.right); - ASSERT(fpDiskImg != nil); - ScanDiskInfo(false); + ASSERT(fpDiskImg != nil); + ScanDiskInfo(false); - CDialog::OnInitDialog(); // does DDX init + CDialog::OnInitDialog(); // does DDX init - CButton* pButton; - pButton = (CButton*) GetDlgItem(IDC_VOLUEMCOPYSEL_FROMFILE); - pButton->EnableWindow(FALSE); - pButton = (CButton*) GetDlgItem(IDC_VOLUEMCOPYSEL_TOFILE); - pButton->EnableWindow(FALSE); + CButton* pButton; + pButton = (CButton*) GetDlgItem(IDC_VOLUEMCOPYSEL_FROMFILE); + pButton->EnableWindow(FALSE); + pButton = (CButton*) GetDlgItem(IDC_VOLUEMCOPYSEL_TOFILE); + pButton->EnableWindow(FALSE); - CString newTitle; - GetWindowText(newTitle); - newTitle += " - "; - newTitle += fPathName; - SetWindowText(newTitle); + CString newTitle; + GetWindowText(newTitle); + newTitle += " - "; + newTitle += fPathName; + SetWindowText(newTitle); - /* - * Prep the listview control. - * - * Columns: - * [icon] Volume name | Format | Size (MB/GB) | Block count - */ - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUMECOPYSEL_LIST); - ASSERT(pListView != nil); - ListView_SetExtendedListViewStyleEx(pListView->m_hWnd, - LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); + /* + * Prep the listview control. + * + * Columns: + * [icon] Volume name | Format | Size (MB/GB) | Block count + */ + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUMECOPYSEL_LIST); + ASSERT(pListView != nil); + ListView_SetExtendedListViewStyleEx(pListView->m_hWnd, + LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT); - int width1, width2, width3; - //CRect rect; + int width1, width2, width3; + //CRect rect; - pListView->GetClientRect(&rect); - width1 = pListView->GetStringWidth("XXVolume NameXXmmmmm"); - width2 = pListView->GetStringWidth("XXFormatXXmmmmmmmmmm"); - width3 = pListView->GetStringWidth("XXSizeXXmmm"); - //width4 = pListView->GetStringWidth("XXBlock CountXX"); + pListView->GetClientRect(&rect); + width1 = pListView->GetStringWidth("XXVolume NameXXmmmmm"); + width2 = pListView->GetStringWidth("XXFormatXXmmmmmmmmmm"); + width3 = pListView->GetStringWidth("XXSizeXXmmm"); + //width4 = pListView->GetStringWidth("XXBlock CountXX"); - pListView->InsertColumn(0, "Volume Name", LVCFMT_LEFT, width1); - pListView->InsertColumn(1, "Format", LVCFMT_LEFT, width2); - pListView->InsertColumn(2, "Size", LVCFMT_LEFT, width3); - pListView->InsertColumn(3, "Block Count", LVCFMT_LEFT, - rect.Width() - (width1+width2+width3) - - ::GetSystemMetrics(SM_CXVSCROLL) ); + pListView->InsertColumn(0, "Volume Name", LVCFMT_LEFT, width1); + pListView->InsertColumn(1, "Format", LVCFMT_LEFT, width2); + pListView->InsertColumn(2, "Size", LVCFMT_LEFT, width3); + pListView->InsertColumn(3, "Block Count", LVCFMT_LEFT, + rect.Width() - (width1+width2+width3) + - ::GetSystemMetrics(SM_CXVSCROLL) ); - /* add images for list; this MUST be loaded before header images */ - LoadListImages(); - pListView->SetImageList(&fListImageList, LVSIL_SMALL); + /* add images for list; this MUST be loaded before header images */ + LoadListImages(); + pListView->SetImageList(&fListImageList, LVSIL_SMALL); - LoadList(); + LoadList(); - CenterWindow(); + CenterWindow(); - int cc = PostMessage(WMU_DIALOG_READY, 0, 0); - ASSERT(cc != 0); + int cc = PostMessage(WMU_DIALOG_READY, 0, 0); + ASSERT(cc != 0); - return TRUE; + return TRUE; } /* @@ -136,21 +136,21 @@ VolumeCopyDialog::OnInitDialog(void) void VolumeCopyDialog::OnOK(void) { - Cleanup(); - CDialog::OnOK(); + Cleanup(); + CDialog::OnOK(); } void VolumeCopyDialog::OnCancel(void) { - Cleanup(); - CDialog::OnCancel(); + Cleanup(); + CDialog::OnCancel(); } void VolumeCopyDialog::Cleanup(void) { - WMSG0(" VolumeCopyDialog is done, cleaning up DiskFS\n"); - delete fpDiskFS; - fpDiskFS = nil; + WMSG0(" VolumeCopyDialog is done, cleaning up DiskFS\n"); + delete fpDiskFS; + fpDiskFS = nil; } /* @@ -159,26 +159,26 @@ VolumeCopyDialog::Cleanup(void) void VolumeCopyDialog::OnListChange(NMHDR*, LRESULT* pResult) { - //CRect rect; - //this->GetWindowRect(&rect); - //WMSG4("RECT is %d, %d, %d, %d\n", rect.left, rect.top, rect.bottom, rect.right); + //CRect rect; + //this->GetWindowRect(&rect); + //WMSG4("RECT is %d, %d, %d, %d\n", rect.left, rect.top, rect.bottom, rect.right); - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUMECOPYSEL_LIST); - ASSERT(pListView != nil); - CButton* pButton; - UINT selectedCount; + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUMECOPYSEL_LIST); + ASSERT(pListView != nil); + CButton* pButton; + UINT selectedCount; - selectedCount = pListView->GetSelectedCount(); - - pButton = (CButton*) GetDlgItem(IDC_VOLUEMCOPYSEL_TOFILE); - pButton->EnableWindow(selectedCount != 0); + selectedCount = pListView->GetSelectedCount(); + + pButton = (CButton*) GetDlgItem(IDC_VOLUEMCOPYSEL_TOFILE); + pButton->EnableWindow(selectedCount != 0); - if (!fpDiskImg->GetReadOnly()) { - pButton = (CButton*) GetDlgItem(IDC_VOLUEMCOPYSEL_FROMFILE); - pButton->EnableWindow(selectedCount != 0); - } + if (!fpDiskImg->GetReadOnly()) { + pButton = (CButton*) GetDlgItem(IDC_VOLUEMCOPYSEL_FROMFILE); + pButton->EnableWindow(selectedCount != 0); + } - *pResult = 0; + *pResult = 0; } /* @@ -196,97 +196,97 @@ VolumeCopyDialog::OnListChange(NMHDR*, LRESULT* pResult) void VolumeCopyDialog::ScanDiskInfo(bool scanTop) { - const Preferences* pPreferences = GET_PREFERENCES(); - MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); - DIError dierr; - CString errMsg, failed; + const Preferences* pPreferences = GET_PREFERENCES(); + MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); + DIError dierr; + CString errMsg, failed; - assert(fpDiskImg != nil); - assert(fpDiskFS == nil); + assert(fpDiskImg != nil); + assert(fpDiskFS == nil); - if (scanTop) { - DiskImg::FSFormat oldFormat; - oldFormat = fpDiskImg->GetFSFormat(); + if (scanTop) { + DiskImg::FSFormat oldFormat; + oldFormat = fpDiskImg->GetFSFormat(); - /* check to see if the top-level FS has changed */ - fpDiskImg->AnalyzeImageFS(); + /* check to see if the top-level FS has changed */ + fpDiskImg->AnalyzeImageFS(); - /* - * If requested (or necessary), verify the format. We only do this - * if we think the format has changed. This is possible, e.g. if - * somebody drops an MS-DOS volume into the first partition of a - * CFFA disk. - */ - if (oldFormat != fpDiskImg->GetFSFormat() && - (fpDiskImg->GetFSFormat() == DiskImg::kFormatUnknown || - fpDiskImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown || - pPreferences->GetPrefBool(kPrQueryImageFormat))) - { - // ignore them if they hit "cancel" - (void) pMain->TryDiskImgOverride(fpDiskImg, fPathName, - DiskImg::kFormatUnknown, nil, true, &errMsg); - if (!errMsg.IsEmpty()) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - return; - } - } - } + /* + * If requested (or necessary), verify the format. We only do this + * if we think the format has changed. This is possible, e.g. if + * somebody drops an MS-DOS volume into the first partition of a + * CFFA disk. + */ + if (oldFormat != fpDiskImg->GetFSFormat() && + (fpDiskImg->GetFSFormat() == DiskImg::kFormatUnknown || + fpDiskImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown || + pPreferences->GetPrefBool(kPrQueryImageFormat))) + { + // ignore them if they hit "cancel" + (void) pMain->TryDiskImgOverride(fpDiskImg, fPathName, + DiskImg::kFormatUnknown, nil, true, &errMsg); + if (!errMsg.IsEmpty()) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + return; + } + } + } - /* - * Creating the "busy" window here is problematic, because we get called - * from OnInitDialog, at which point our window isn't yet established. - * Since we're modal, we disabled MainWindow, which means that when the - * "busy" box goes away there's no CiderPress window to take control. As - * a result we get a nasty flash. - * - * The only way around this is to defer the destruction of the modeless - * dialog until after we become visible. - */ - bool deferDestroy = false; - if (!IsWindowVisible() || !IsWindowEnabled()) { - WMSG0(" Deferring destroy on wait dialog\n"); - deferDestroy = true; - } else { - WMSG0(" Not deferring destroy on wait dialog\n"); - } + /* + * Creating the "busy" window here is problematic, because we get called + * from OnInitDialog, at which point our window isn't yet established. + * Since we're modal, we disabled MainWindow, which means that when the + * "busy" box goes away there's no CiderPress window to take control. As + * a result we get a nasty flash. + * + * The only way around this is to defer the destruction of the modeless + * dialog until after we become visible. + */ + bool deferDestroy = false; + if (!IsWindowVisible() || !IsWindowEnabled()) { + WMSG0(" Deferring destroy on wait dialog\n"); + deferDestroy = true; + } else { + WMSG0(" Not deferring destroy on wait dialog\n"); + } - fpWaitDlg = new ExclusiveModelessDialog; - fpWaitDlg->Create(IDD_LOADING, this); - fpWaitDlg->CenterWindow(pMain); - pMain->PeekAndPump(); + fpWaitDlg = new ExclusiveModelessDialog; + fpWaitDlg->Create(IDD_LOADING, this); + fpWaitDlg->CenterWindow(pMain); + pMain->PeekAndPump(); - CWaitCursor waitc; + CWaitCursor waitc; - /* - * Create an appropriate DiskFS object. We only need to do this to get - * the sub-volume info, which is unfortunate since it can be slow. - */ - fpDiskFS = fpDiskImg->OpenAppropriateDiskFS(true); - if (fpDiskFS == nil) { - WMSG0("HEY: OpenAppropriateDiskFS failed!\n"); - /* this is fatal, but there's no easy way to die */ - /* (could we do a DestroyWindow from here?) */ - /* at any rate, with "allowUnknown" set, this shouldn't happen */ - } else { - fpDiskFS->SetScanForSubVolumes(DiskFS::kScanSubContainerOnly); + /* + * Create an appropriate DiskFS object. We only need to do this to get + * the sub-volume info, which is unfortunate since it can be slow. + */ + fpDiskFS = fpDiskImg->OpenAppropriateDiskFS(true); + if (fpDiskFS == nil) { + WMSG0("HEY: OpenAppropriateDiskFS failed!\n"); + /* this is fatal, but there's no easy way to die */ + /* (could we do a DestroyWindow from here?) */ + /* at any rate, with "allowUnknown" set, this shouldn't happen */ + } else { + fpDiskFS->SetScanForSubVolumes(DiskFS::kScanSubContainerOnly); - dierr = fpDiskFS->Initialize(fpDiskImg, DiskFS::kInitFull); - if (dierr != kDIErrNone) { - CString appName, msg; - appName.LoadString(IDS_MB_APP_NAME); - msg.Format("Warning: error during disk scan: %s.", - DiskImgLib::DIStrError(dierr)); - fpWaitDlg->MessageBox(msg, appName, MB_OK | MB_ICONEXCLAMATION); - /* keep going */ - } - } + dierr = fpDiskFS->Initialize(fpDiskImg, DiskFS::kInitFull); + if (dierr != kDIErrNone) { + CString appName, msg; + appName.LoadString(IDS_MB_APP_NAME); + msg.Format("Warning: error during disk scan: %s.", + DiskImgLib::DIStrError(dierr)); + fpWaitDlg->MessageBox(msg, appName, MB_OK | MB_ICONEXCLAMATION); + /* keep going */ + } + } - if (!deferDestroy && fpWaitDlg != nil) { - fpWaitDlg->DestroyWindow(); - fpWaitDlg = nil; - } + if (!deferDestroy && fpWaitDlg != nil) { + fpWaitDlg->DestroyWindow(); + fpWaitDlg = nil; + } - return; + return; } /* @@ -296,12 +296,12 @@ VolumeCopyDialog::ScanDiskInfo(bool scanTop) LONG VolumeCopyDialog::OnDialogReady(UINT, LONG) { - if (fpWaitDlg != nil) { - WMSG0("OnDialogReady found active window, destroying\n"); - fpWaitDlg->DestroyWindow(); - fpWaitDlg = nil; - } - return 0; + if (fpWaitDlg != nil) { + WMSG0("OnDialogReady found active window, destroying\n"); + fpWaitDlg->DestroyWindow(); + fpWaitDlg = nil; + } + return 0; } /* @@ -315,32 +315,32 @@ VolumeCopyDialog::OnDialogReady(UINT, LONG) void VolumeCopyDialog::LoadList(void) { - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUMECOPYSEL_LIST); - ASSERT(pListView != nil); - int itemIndex = 0; + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUMECOPYSEL_LIST); + ASSERT(pListView != nil); + int itemIndex = 0; - CString unknown = "(unknown)"; + CString unknown = "(unknown)"; - pListView->DeleteAllItems(); - if (fpDiskFS == nil) { - /* can only happen if imported volume is unrecognizeable */ - return; - } + pListView->DeleteAllItems(); + if (fpDiskFS == nil) { + /* can only happen if imported volume is unrecognizeable */ + return; + } - AddToList(pListView, fpDiskImg, fpDiskFS, &itemIndex); + AddToList(pListView, fpDiskImg, fpDiskFS, &itemIndex); - DiskImgLib::DiskFS::SubVolume* pSubVolume; - pSubVolume = fpDiskFS->GetNextSubVolume(nil); - while (pSubVolume != nil) { - if (pSubVolume->GetDiskFS() == nil) { - WMSG0("WARNING: sub-volume DiskFS is nil?!\n"); - assert(false); - } else { - AddToList(pListView, pSubVolume->GetDiskImg(), - pSubVolume->GetDiskFS(), &itemIndex); - } - pSubVolume = fpDiskFS->GetNextSubVolume(pSubVolume); - } + DiskImgLib::DiskFS::SubVolume* pSubVolume; + pSubVolume = fpDiskFS->GetNextSubVolume(nil); + while (pSubVolume != nil) { + if (pSubVolume->GetDiskFS() == nil) { + WMSG0("WARNING: sub-volume DiskFS is nil?!\n"); + assert(false); + } else { + AddToList(pListView, pSubVolume->GetDiskImg(), + pSubVolume->GetDiskFS(), &itemIndex); + } + pSubVolume = fpDiskFS->GetNextSubVolume(pSubVolume); + } } /* @@ -348,36 +348,36 @@ VolumeCopyDialog::LoadList(void) */ void VolumeCopyDialog::AddToList(CListCtrl* pListView, DiskImg* pDiskImg, - DiskFS* pDiskFS, int* pIndex) + DiskFS* pDiskFS, int* pIndex) { - CString volName, format, sizeStr, blocksStr; - long numBlocks; + CString volName, format, sizeStr, blocksStr; + long numBlocks; - assert(pListView != nil); - assert(pDiskImg != nil); - assert(pDiskFS != nil); - assert(pIndex != nil); + assert(pListView != nil); + assert(pDiskImg != nil); + assert(pDiskFS != nil); + assert(pIndex != nil); - numBlocks = pDiskImg->GetNumBlocks(); + numBlocks = pDiskImg->GetNumBlocks(); - volName = pDiskFS->GetVolumeName(); - format = DiskImg::ToString(pDiskImg->GetFSFormat()); - blocksStr.Format("%ld", pDiskImg->GetNumBlocks()); - if (numBlocks > 1024*1024*2) - sizeStr.Format("%.2fGB", (double) numBlocks / (1024.0*1024.0*2.0)); - else if (numBlocks > 1024*2) - sizeStr.Format("%.2fMB", (double) numBlocks / (1024.0*2.0)); - else - sizeStr.Format("%.2fKB", (double) numBlocks / 2.0); + volName = pDiskFS->GetVolumeName(); + format = DiskImg::ToString(pDiskImg->GetFSFormat()); + blocksStr.Format("%ld", pDiskImg->GetNumBlocks()); + if (numBlocks > 1024*1024*2) + sizeStr.Format("%.2fGB", (double) numBlocks / (1024.0*1024.0*2.0)); + else if (numBlocks > 1024*2) + sizeStr.Format("%.2fMB", (double) numBlocks / (1024.0*2.0)); + else + sizeStr.Format("%.2fKB", (double) numBlocks / 2.0); - /* add entry; first entry is the whole volume */ - pListView->InsertItem(*pIndex, volName, - *pIndex == 0 ? kListIconVolume : kListIconSubVolume); - pListView->SetItemText(*pIndex, 1, format); - pListView->SetItemText(*pIndex, 2, sizeStr); - pListView->SetItemText(*pIndex, 3, blocksStr); - pListView->SetItemData(*pIndex, (DWORD) pDiskFS); - (*pIndex)++; + /* add entry; first entry is the whole volume */ + pListView->InsertItem(*pIndex, volName, + *pIndex == 0 ? kListIconVolume : kListIconSubVolume); + pListView->SetItemText(*pIndex, 1, format); + pListView->SetItemText(*pIndex, 2, sizeStr); + pListView->SetItemText(*pIndex, 3, blocksStr); + pListView->SetItemData(*pIndex, (DWORD) pDiskFS); + (*pIndex)++; } @@ -390,28 +390,28 @@ VolumeCopyDialog::AddToList(CListCtrl* pListView, DiskImg* pDiskImg, bool VolumeCopyDialog::GetSelectedDisk(DiskImg** ppDiskImg, DiskFS** ppDiskFS) { - CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUMECOPYSEL_LIST); - ASSERT(pListView != nil); + CListCtrl* pListView = (CListCtrl*) GetDlgItem(IDC_VOLUMECOPYSEL_LIST); + ASSERT(pListView != nil); - ASSERT(ppDiskImg != nil); - ASSERT(ppDiskFS != nil); + ASSERT(ppDiskImg != nil); + ASSERT(ppDiskFS != nil); - if (pListView->GetSelectedCount() != 1) - return false; + if (pListView->GetSelectedCount() != 1) + return false; - POSITION posn; - posn = pListView->GetFirstSelectedItemPosition(); - if (posn == nil) { - ASSERT(false); - return false; - } - int num = pListView->GetNextSelectedItem(posn); - DWORD data = pListView->GetItemData(num); + POSITION posn; + posn = pListView->GetFirstSelectedItemPosition(); + if (posn == nil) { + ASSERT(false); + return false; + } + int num = pListView->GetNextSelectedItem(posn); + DWORD data = pListView->GetItemData(num); - *ppDiskFS = (DiskFS*) data; - assert(*ppDiskFS != nil); - *ppDiskImg = (*ppDiskFS)->GetDiskImg(); - return true; + *ppDiskFS = (DiskFS*) data; + assert(*ppDiskFS != nil); + *ppDiskImg = (*ppDiskFS)->GetDiskImg(); + return true; } /* @@ -420,7 +420,7 @@ VolumeCopyDialog::GetSelectedDisk(DiskImg** ppDiskImg, DiskFS** ppDiskFS) void VolumeCopyDialog::OnHelp(void) { - WinHelp(HELP_TOPIC_VOLUME_COPIER, HELP_CONTEXT); + WinHelp(HELP_TOPIC_VOLUME_COPIER, HELP_CONTEXT); } @@ -431,179 +431,179 @@ VolumeCopyDialog::OnHelp(void) void VolumeCopyDialog::OnCopyToFile(void) { - VolumeXferProgressDialog* pProgressDialog = nil; - Preferences* pPreferences = GET_PREFERENCES_WR(); - MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); - DiskImg::FSFormat originalFormat = DiskImg::kFormatUnknown; - DiskImg* pSrcImg = nil; - DiskFS* pSrcFS = nil; - DiskImg dstImg; - DIError dierr; - CString errMsg, saveName, msg, srcName; - int result; + VolumeXferProgressDialog* pProgressDialog = nil; + Preferences* pPreferences = GET_PREFERENCES_WR(); + MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); + DiskImg::FSFormat originalFormat = DiskImg::kFormatUnknown; + DiskImg* pSrcImg = nil; + DiskFS* pSrcFS = nil; + DiskImg dstImg; + DIError dierr; + CString errMsg, saveName, msg, srcName; + int result; - result = GetSelectedDisk(&pSrcImg, &pSrcFS); - if (!result) - return; - assert(pSrcImg != nil); - assert(pSrcFS != nil); + result = GetSelectedDisk(&pSrcImg, &pSrcFS); + if (!result) + return; + assert(pSrcImg != nil); + assert(pSrcFS != nil); - srcName = pSrcFS->GetVolumeName(); + srcName = pSrcFS->GetVolumeName(); - /* force the format to be generic ProDOS-ordered blocks */ - originalFormat = pSrcImg->GetFSFormat(); - dierr = pSrcImg->OverrideFormat(pSrcImg->GetPhysicalFormat(), - DiskImg::kFormatGenericProDOSOrd, pSrcImg->GetSectorOrder()); - if (dierr != kDIErrNone) { - errMsg.Format("Internal error: couldn't switch to generic ProDOS: %s.", - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } - WMSG2("Logical volume '%s' has %d 512-byte blocks\n", - srcName, pSrcImg->GetNumBlocks()); + /* force the format to be generic ProDOS-ordered blocks */ + originalFormat = pSrcImg->GetFSFormat(); + dierr = pSrcImg->OverrideFormat(pSrcImg->GetPhysicalFormat(), + DiskImg::kFormatGenericProDOSOrd, pSrcImg->GetSectorOrder()); + if (dierr != kDIErrNone) { + errMsg.Format("Internal error: couldn't switch to generic ProDOS: %s.", + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } + WMSG2("Logical volume '%s' has %d 512-byte blocks\n", + srcName, pSrcImg->GetNumBlocks()); - /* - * Select file to write blocks to. - */ - { - CFileDialog saveDlg(FALSE, "po", NULL, - OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, - "All Files (*.*)|*.*||", this); + /* + * Select file to write blocks to. + */ + { + CFileDialog saveDlg(FALSE, "po", NULL, + OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN|OFN_HIDEREADONLY, + "All Files (*.*)|*.*||", this); - CString saveFolder; - static char* title = "New disk image (.po)"; + CString saveFolder; + static char* title = "New disk image (.po)"; - saveDlg.m_ofn.lpstrTitle = title; - saveDlg.m_ofn.lpstrInitialDir = - pPreferences->GetPrefString(kPrOpenArchiveFolder); - - if (saveDlg.DoModal() != IDOK) { - WMSG0(" User bailed out of image save dialog\n"); - goto bail; - } + saveDlg.m_ofn.lpstrTitle = title; + saveDlg.m_ofn.lpstrInitialDir = + pPreferences->GetPrefString(kPrOpenArchiveFolder); + + if (saveDlg.DoModal() != IDOK) { + WMSG0(" User bailed out of image save dialog\n"); + goto bail; + } - saveFolder = saveDlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(saveDlg.m_ofn.nFileOffset); - pPreferences->SetPrefString(kPrOpenArchiveFolder, saveFolder); + saveFolder = saveDlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(saveDlg.m_ofn.nFileOffset); + pPreferences->SetPrefString(kPrOpenArchiveFolder, saveFolder); - saveName = saveDlg.GetPathName(); - } - WMSG1("File will be saved to '%s'\n", saveName); + saveName = saveDlg.GetPathName(); + } + WMSG1("File will be saved to '%s'\n", saveName); - /* DiskImgLib does not like it if file already exists */ - errMsg = pMain->RemoveFile(saveName); - if (!errMsg.IsEmpty()) { - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + /* DiskImgLib does not like it if file already exists */ + errMsg = pMain->RemoveFile(saveName); + if (!errMsg.IsEmpty()) { + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - /* - * Create a block image with the expected number of blocks. - */ - int dstNumBlocks; - dstNumBlocks = pSrcImg->GetNumBlocks(); + /* + * Create a block image with the expected number of blocks. + */ + int dstNumBlocks; + dstNumBlocks = pSrcImg->GetNumBlocks(); - { - ExclusiveModelessDialog* pWaitDlg = new ExclusiveModelessDialog; - pWaitDlg->Create(IDD_FORMATTING, this); - pWaitDlg->CenterWindow(pMain); - pMain->PeekAndPump(); // redraw - CWaitCursor waitc; + { + ExclusiveModelessDialog* pWaitDlg = new ExclusiveModelessDialog; + pWaitDlg->Create(IDD_FORMATTING, this); + pWaitDlg->CenterWindow(pMain); + pMain->PeekAndPump(); // redraw + CWaitCursor waitc; - dierr = dstImg.CreateImage(saveName, nil, - DiskImg::kOuterFormatNone, - DiskImg::kFileFormatUnadorned, - DiskImg::kPhysicalFormatSectors, - nil, - DiskImg::kSectorOrderProDOS, - DiskImg::kFormatGenericProDOSOrd, - dstNumBlocks, - true /* don't need to erase contents */); + dierr = dstImg.CreateImage(saveName, nil, + DiskImg::kOuterFormatNone, + DiskImg::kFileFormatUnadorned, + DiskImg::kPhysicalFormatSectors, + nil, + DiskImg::kSectorOrderProDOS, + DiskImg::kFormatGenericProDOSOrd, + dstNumBlocks, + true /* don't need to erase contents */); - pWaitDlg->DestroyWindow(); - //pMain->PeekAndPump(); // redraw - } - if (dierr != kDIErrNone) { - errMsg.Format("Couldn't create disk image: %s.", - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + pWaitDlg->DestroyWindow(); + //pMain->PeekAndPump(); // redraw + } + if (dierr != kDIErrNone) { + errMsg.Format("Couldn't create disk image: %s.", + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - /* initialize cancel dialog, and disable main window */ - pProgressDialog = new VolumeXferProgressDialog; - EnableWindow(FALSE); - if (pProgressDialog->Create(this) == FALSE) { - WMSG0("Progress dialog init failed?!\n"); - ASSERT(false); - goto bail; - } - pProgressDialog->SetCurrentFiles(srcName, saveName); + /* initialize cancel dialog, and disable main window */ + pProgressDialog = new VolumeXferProgressDialog; + EnableWindow(FALSE); + if (pProgressDialog->Create(this) == FALSE) { + WMSG0("Progress dialog init failed?!\n"); + ASSERT(false); + goto bail; + } + pProgressDialog->SetCurrentFiles(srcName, saveName); - time_t startWhen, endWhen; - startWhen = time(nil); + time_t startWhen, endWhen; + startWhen = time(nil); - /* - * Do the actual block copy. - */ - dierr = pMain->CopyDiskImage(&dstImg, pSrcImg, false, false, pProgressDialog); - if (dierr != kDIErrNone) { - if (dierr == kDIErrCancelled) { - errMsg.LoadString(IDS_OPERATION_CANCELLED); - ShowFailureMsg(pProgressDialog, errMsg, IDS_CANCELLED); - // remove the partially-written file - dstImg.CloseImage(); - unlink(saveName); - } else { - errMsg.Format("Copy failed: %s.", DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(pProgressDialog, errMsg, IDS_FAILED); - } - goto bail; - } + /* + * Do the actual block copy. + */ + dierr = pMain->CopyDiskImage(&dstImg, pSrcImg, false, false, pProgressDialog); + if (dierr != kDIErrNone) { + if (dierr == kDIErrCancelled) { + errMsg.LoadString(IDS_OPERATION_CANCELLED); + ShowFailureMsg(pProgressDialog, errMsg, IDS_CANCELLED); + // remove the partially-written file + dstImg.CloseImage(); + unlink(saveName); + } else { + errMsg.Format("Copy failed: %s.", DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(pProgressDialog, errMsg, IDS_FAILED); + } + goto bail; + } dierr = dstImg.CloseImage(); if (dierr != kDIErrNone) { errMsg.Format("ERROR: dstImg close failed (err=%d)\n", dierr); - ShowFailureMsg(pProgressDialog, errMsg, IDS_FAILED); - goto bail; + ShowFailureMsg(pProgressDialog, errMsg, IDS_FAILED); + goto bail; } - /* put elapsed time in the debug log */ - endWhen = time(nil); - float elapsed; - if (endWhen == startWhen) - elapsed = 1.0; - else - elapsed = (float) (endWhen - startWhen); - msg.Format("Copied %ld blocks in %ld seconds (%.2fKB/sec)", - pSrcImg->GetNumBlocks(), endWhen - startWhen, - (pSrcImg->GetNumBlocks() / 2.0) / elapsed); - WMSG1("%s\n", (const char*) msg); + /* put elapsed time in the debug log */ + endWhen = time(nil); + float elapsed; + if (endWhen == startWhen) + elapsed = 1.0; + else + elapsed = (float) (endWhen - startWhen); + msg.Format("Copied %ld blocks in %ld seconds (%.2fKB/sec)", + pSrcImg->GetNumBlocks(), endWhen - startWhen, + (pSrcImg->GetNumBlocks() / 2.0) / elapsed); + WMSG1("%s\n", (const char*) msg); #ifdef _DEBUG - pProgressDialog->MessageBox(msg, "DEBUG: elapsed time", MB_OK); + pProgressDialog->MessageBox(msg, "DEBUG: elapsed time", MB_OK); #endif - pMain->SuccessBeep(); + pMain->SuccessBeep(); bail: - // restore the dialog window to prominence - EnableWindow(TRUE); - //SetActiveWindow(); - if (pProgressDialog != nil) - pProgressDialog->DestroyWindow(); + // restore the dialog window to prominence + EnableWindow(TRUE); + //SetActiveWindow(); + if (pProgressDialog != nil) + pProgressDialog->DestroyWindow(); - /* un-override the source disk */ - if (originalFormat != DiskImg::kFormatUnknown) { - dierr = pSrcImg->OverrideFormat(pSrcImg->GetPhysicalFormat(), - originalFormat, pSrcImg->GetSectorOrder()); - if (dierr != kDIErrNone) { - WMSG1("ERROR: couldn't un-override source image (dierr=%d)\n", dierr); - // not much else to do; should be okay - } - } - return; + /* un-override the source disk */ + if (originalFormat != DiskImg::kFormatUnknown) { + dierr = pSrcImg->OverrideFormat(pSrcImg->GetPhysicalFormat(), + originalFormat, pSrcImg->GetSectorOrder()); + if (dierr != kDIErrNone) { + WMSG1("ERROR: couldn't un-override source image (dierr=%d)\n", dierr); + // not much else to do; should be okay + } + } + return; } @@ -614,267 +614,267 @@ bail: void VolumeCopyDialog::OnCopyFromFile(void) { - VolumeXferProgressDialog* pProgressDialog = nil; - Preferences* pPreferences = GET_PREFERENCES_WR(); - MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); - //DiskImg::FSFormat originalFormat = DiskImg::kFormatUnknown; - CString openFilters; - CString loadName, targetName, errMsg, warning; - DiskImg* pDstImg = nil; - DiskFS* pDstFS = nil; - DiskImg srcImg; - DIError dierr; - int result; - bool needReload = false; - bool isPartial = false; + VolumeXferProgressDialog* pProgressDialog = nil; + Preferences* pPreferences = GET_PREFERENCES_WR(); + MainWindow* pMain = (MainWindow*)::AfxGetMainWnd(); + //DiskImg::FSFormat originalFormat = DiskImg::kFormatUnknown; + CString openFilters; + CString loadName, targetName, errMsg, warning; + DiskImg* pDstImg = nil; + DiskFS* pDstFS = nil; + DiskImg srcImg; + DIError dierr; + int result; + bool needReload = false; + bool isPartial = false; - warning.LoadString(IDS_WARNING); + warning.LoadString(IDS_WARNING); - /* - * Get the DiskImg and DiskFS pointers for the selected partition out of - * the control. The storage for these is part of fpDiskFS, which holds - * the tree of subvolumes. - */ - result = GetSelectedDisk(&pDstImg, &pDstFS); - if (!result) - return; + /* + * Get the DiskImg and DiskFS pointers for the selected partition out of + * the control. The storage for these is part of fpDiskFS, which holds + * the tree of subvolumes. + */ + result = GetSelectedDisk(&pDstImg, &pDstFS); + if (!result) + return; -// if (pDstFS == nil) -// targetName = "the target volume"; -// else - targetName = pDstFS->GetVolumeName(); +// if (pDstFS == nil) +// targetName = "the target volume"; +// else + targetName = pDstFS->GetVolumeName(); - /* - * Select the image to copy from. - */ - openFilters = MainWindow::kOpenDiskImage; - openFilters += MainWindow::kOpenAll; - openFilters += MainWindow::kOpenEnd; - CFileDialog dlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); + /* + * Select the image to copy from. + */ + openFilters = MainWindow::kOpenDiskImage; + openFilters += MainWindow::kOpenAll; + openFilters += MainWindow::kOpenEnd; + CFileDialog dlg(TRUE, "dsk", NULL, OFN_FILEMUSTEXIST, openFilters, this); - /* source file gets opened read-only */ - dlg.m_ofn.Flags |= OFN_HIDEREADONLY; - dlg.m_ofn.lpstrTitle = "Select image to copy from"; - dlg.m_ofn.lpstrInitialDir = pPreferences->GetPrefString(kPrOpenArchiveFolder); + /* source file gets opened read-only */ + dlg.m_ofn.Flags |= OFN_HIDEREADONLY; + dlg.m_ofn.lpstrTitle = "Select image to copy from"; + dlg.m_ofn.lpstrInitialDir = pPreferences->GetPrefString(kPrOpenArchiveFolder); - if (dlg.DoModal() != IDOK) - goto bail; - loadName = dlg.GetPathName(); + if (dlg.DoModal() != IDOK) + goto bail; + loadName = dlg.GetPathName(); - { - CWaitCursor waitc; - CString saveFolder; + { + CWaitCursor waitc; + CString saveFolder; - /* open the image file and analyze it */ - dierr = srcImg.OpenImage(loadName, PathProposal::kLocalFssep, true); - if (dierr != kDIErrNone) { - errMsg.Format("Unable to open disk image: %s.", - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + /* open the image file and analyze it */ + dierr = srcImg.OpenImage(loadName, PathProposal::kLocalFssep, true); + if (dierr != kDIErrNone) { + errMsg.Format("Unable to open disk image: %s.", + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - if (srcImg.AnalyzeImage() != kDIErrNone) { - errMsg.Format("The file '%s' doesn't seem to hold a valid disk image.", - loadName); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + if (srcImg.AnalyzeImage() != kDIErrNone) { + errMsg.Format("The file '%s' doesn't seem to hold a valid disk image.", + loadName); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - // save our folder choice in the preferences file - saveFolder = dlg.m_ofn.lpstrFile; - saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); - pPreferences->SetPrefString(kPrOpenArchiveFolder, saveFolder); - } + // save our folder choice in the preferences file + saveFolder = dlg.m_ofn.lpstrFile; + saveFolder = saveFolder.Left(dlg.m_ofn.nFileOffset); + pPreferences->SetPrefString(kPrOpenArchiveFolder, saveFolder); + } - /* - * Require that the input be block-addressable. This isn't really the - * right test, because it's conceivable that somebody would want to put - * a nibble image onto a disk volume. I can't think of a good reason - * to do this -- you can't just splat a fixed-track-length .NIB file - * onto a 5.25" disk, assuming you could get the drive to work on a PC - * in the first place -- so I'm going to take the simple way out. The - * right test is to verify that the EOF on the input is the same as the - * EOF on the output. - */ - if (!srcImg.GetHasBlocks()) { - errMsg = "The disk image must be block-oriented. Nibble images" - " cannot be copied."; - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + /* + * Require that the input be block-addressable. This isn't really the + * right test, because it's conceivable that somebody would want to put + * a nibble image onto a disk volume. I can't think of a good reason + * to do this -- you can't just splat a fixed-track-length .NIB file + * onto a 5.25" disk, assuming you could get the drive to work on a PC + * in the first place -- so I'm going to take the simple way out. The + * right test is to verify that the EOF on the input is the same as the + * EOF on the output. + */ + if (!srcImg.GetHasBlocks()) { + errMsg = "The disk image must be block-oriented. Nibble images" + " cannot be copied."; + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - /* force source volume to generic ProDOS blocks */ - dierr = srcImg.OverrideFormat(srcImg.GetPhysicalFormat(), - DiskImg::kFormatGenericProDOSOrd, srcImg.GetSectorOrder()); - if (dierr != kDIErrNone) { - errMsg.Format("Internal error: couldn't switch source to generic ProDOS: %s.", - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } - WMSG2("Source image '%s' has %d 512-byte blocks\n", - loadName, srcImg.GetNumBlocks()); + /* force source volume to generic ProDOS blocks */ + dierr = srcImg.OverrideFormat(srcImg.GetPhysicalFormat(), + DiskImg::kFormatGenericProDOSOrd, srcImg.GetSectorOrder()); + if (dierr != kDIErrNone) { + errMsg.Format("Internal error: couldn't switch source to generic ProDOS: %s.", + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } + WMSG2("Source image '%s' has %d 512-byte blocks\n", + loadName, srcImg.GetNumBlocks()); - WMSG1("Target volume has %d 512-byte blocks\n", pDstImg->GetNumBlocks()); + WMSG1("Target volume has %d 512-byte blocks\n", pDstImg->GetNumBlocks()); - if (srcImg.GetNumBlocks() > pDstImg->GetNumBlocks()) { - errMsg.Format("Error: the disk image file has %ld blocks, but the" - " target volume holds %ld blocks. The target must" - " have more space than the input file.", - srcImg.GetNumBlocks(), pDstImg->GetNumBlocks()); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } - if (pDstImg->GetNumBlocks() >= DiskImgLib::kVolumeMaxBlocks) { - errMsg.Format("Error: for safety reasons, copying disk images to" - " larger volumes is not supported when the target" - " is 8GB or larger."); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + if (srcImg.GetNumBlocks() > pDstImg->GetNumBlocks()) { + errMsg.Format("Error: the disk image file has %ld blocks, but the" + " target volume holds %ld blocks. The target must" + " have more space than the input file.", + srcImg.GetNumBlocks(), pDstImg->GetNumBlocks()); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } + if (pDstImg->GetNumBlocks() >= DiskImgLib::kVolumeMaxBlocks) { + errMsg.Format("Error: for safety reasons, copying disk images to" + " larger volumes is not supported when the target" + " is 8GB or larger."); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - if (srcImg.GetNumBlocks() != pDstImg->GetNumBlocks()) { - errMsg.LoadString(IDS_WARNING); - errMsg.Format("The disk image file has %ld blocks, but the target" - " volume holds %ld blocks. The leftover space may be" - " wasted, and non-ProDOS volumes may not be identified" - " correctly. Do you wish to continue?", - srcImg.GetNumBlocks(), pDstImg->GetNumBlocks()); - result = MessageBox(errMsg, warning, MB_OKCANCEL | MB_ICONQUESTION); - if (result != IDOK) { - WMSG0("User chickened out of oversized disk copy\n"); - goto bail; - } - isPartial = true; - } + if (srcImg.GetNumBlocks() != pDstImg->GetNumBlocks()) { + errMsg.LoadString(IDS_WARNING); + errMsg.Format("The disk image file has %ld blocks, but the target" + " volume holds %ld blocks. The leftover space may be" + " wasted, and non-ProDOS volumes may not be identified" + " correctly. Do you wish to continue?", + srcImg.GetNumBlocks(), pDstImg->GetNumBlocks()); + result = MessageBox(errMsg, warning, MB_OKCANCEL | MB_ICONQUESTION); + if (result != IDOK) { + WMSG0("User chickened out of oversized disk copy\n"); + goto bail; + } + isPartial = true; + } - errMsg.LoadString(IDS_WARNING); - errMsg.Format("You are about to overwrite volume %s with the" - " contents of '%s'. This will destroy all data on" - " %s. Are you sure you wish to continue?", - targetName, loadName, targetName); - result = MessageBox(errMsg, warning, MB_OKCANCEL | MB_ICONEXCLAMATION); - if (result != IDOK) { - WMSG0("User chickened out of disk copy\n"); - goto bail; - } + errMsg.LoadString(IDS_WARNING); + errMsg.Format("You are about to overwrite volume %s with the" + " contents of '%s'. This will destroy all data on" + " %s. Are you sure you wish to continue?", + targetName, loadName, targetName); + result = MessageBox(errMsg, warning, MB_OKCANCEL | MB_ICONEXCLAMATION); + if (result != IDOK) { + WMSG0("User chickened out of disk copy\n"); + goto bail; + } - /* force the target disk image to be generic ProDOS-ordered blocks */ - dierr = pDstImg->OverrideFormat(pDstImg->GetPhysicalFormat(), - DiskImg::kFormatGenericProDOSOrd, pDstImg->GetSectorOrder()); - if (dierr != kDIErrNone) { - errMsg.Format("Internal error: couldn't switch target to generic ProDOS: %s.", - DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } + /* force the target disk image to be generic ProDOS-ordered blocks */ + dierr = pDstImg->OverrideFormat(pDstImg->GetPhysicalFormat(), + DiskImg::kFormatGenericProDOSOrd, pDstImg->GetSectorOrder()); + if (dierr != kDIErrNone) { + errMsg.Format("Internal error: couldn't switch target to generic ProDOS: %s.", + DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } - /* from here on out, before we exit we must re-analyze this volume */ - needReload = true; + /* from here on out, before we exit we must re-analyze this volume */ + needReload = true; - // redraw main to erase previous dialog - pMain->PeekAndPump(); + // redraw main to erase previous dialog + pMain->PeekAndPump(); - /* initialize cancel dialog, and disable dialog */ - pProgressDialog = new VolumeXferProgressDialog; - EnableWindow(FALSE); - if (pProgressDialog->Create(this) == FALSE) { - WMSG0("Progress dialog init failed?!\n"); - ASSERT(false); - return; - } -// if (pDstFS == nil) -// pProgressDialog->SetCurrentFiles(loadName, "target"); -// else - pProgressDialog->SetCurrentFiles(loadName, targetName); + /* initialize cancel dialog, and disable dialog */ + pProgressDialog = new VolumeXferProgressDialog; + EnableWindow(FALSE); + if (pProgressDialog->Create(this) == FALSE) { + WMSG0("Progress dialog init failed?!\n"); + ASSERT(false); + return; + } +// if (pDstFS == nil) +// pProgressDialog->SetCurrentFiles(loadName, "target"); +// else + pProgressDialog->SetCurrentFiles(loadName, targetName); - /* - * We want to delete fpDiskFS now, but we can't because it's holding the - * storage for the DiskImg/DiskFS pointers in the subvolume list. We - * flush it to ensure that it won't try to write to the disk after the - * copy completes. - */ - fpDiskFS->Flush(DiskImg::kFlushAll); + /* + * We want to delete fpDiskFS now, but we can't because it's holding the + * storage for the DiskImg/DiskFS pointers in the subvolume list. We + * flush it to ensure that it won't try to write to the disk after the + * copy completes. + */ + fpDiskFS->Flush(DiskImg::kFlushAll); - time_t startWhen, endWhen; - startWhen = time(nil); + time_t startWhen, endWhen; + startWhen = time(nil); - /* - * Do the actual block copy. - */ - dierr = pMain->CopyDiskImage(pDstImg, &srcImg, false, isPartial, - pProgressDialog); - if (dierr != kDIErrNone) { - if (dierr == kDIErrCancelled) { - errMsg.LoadString(IDS_OPERATION_CANCELLED); - ShowFailureMsg(pProgressDialog, errMsg, IDS_CANCELLED); - } else { - errMsg.Format("Copy failed: %s.", DiskImgLib::DIStrError(dierr)); - ShowFailureMsg(pProgressDialog, errMsg, IDS_FAILED); - } - goto bail; - } + /* + * Do the actual block copy. + */ + dierr = pMain->CopyDiskImage(pDstImg, &srcImg, false, isPartial, + pProgressDialog); + if (dierr != kDIErrNone) { + if (dierr == kDIErrCancelled) { + errMsg.LoadString(IDS_OPERATION_CANCELLED); + ShowFailureMsg(pProgressDialog, errMsg, IDS_CANCELLED); + } else { + errMsg.Format("Copy failed: %s.", DiskImgLib::DIStrError(dierr)); + ShowFailureMsg(pProgressDialog, errMsg, IDS_FAILED); + } + goto bail; + } dierr = srcImg.CloseImage(); if (dierr != kDIErrNone) { errMsg.Format("ERROR: srcImg close failed (err=%d)\n", dierr); - ShowFailureMsg(pProgressDialog, errMsg, IDS_FAILED); - goto bail; + ShowFailureMsg(pProgressDialog, errMsg, IDS_FAILED); + goto bail; } - endWhen = time(nil); - float elapsed; - if (endWhen == startWhen) - elapsed = 1.0; - else - elapsed = (float) (endWhen - startWhen); - errMsg.Format("Copied %ld blocks in %ld seconds (%.2fKB/sec)", - srcImg.GetNumBlocks(), endWhen - startWhen, - (srcImg.GetNumBlocks() / 2.0) / elapsed); - WMSG1("%s\n", (const char*) errMsg); + endWhen = time(nil); + float elapsed; + if (endWhen == startWhen) + elapsed = 1.0; + else + elapsed = (float) (endWhen - startWhen); + errMsg.Format("Copied %ld blocks in %ld seconds (%.2fKB/sec)", + srcImg.GetNumBlocks(), endWhen - startWhen, + (srcImg.GetNumBlocks() / 2.0) / elapsed); + WMSG1("%s\n", (const char*) errMsg); #ifdef _DEBUG - pProgressDialog->MessageBox(errMsg, "DEBUG: elapsed time", MB_OK); + pProgressDialog->MessageBox(errMsg, "DEBUG: elapsed time", MB_OK); #endif - pMain->SuccessBeep(); + pMain->SuccessBeep(); - /* - * If a DiskFS insists on privately caching stuff (e.g. libhfs), we could - * end up corrupting the image we just wrote. We use SetAllReadOnly() to - * ensure that nothing will be written before we delete the DiskFS. - */ - assert(!fpDiskImg->GetReadOnly()); - fpDiskFS->SetAllReadOnly(true); - delete fpDiskFS; - fpDiskFS = nil; - assert(fpDiskImg->GetReadOnly()); - fpDiskImg->SetReadOnly(false); + /* + * If a DiskFS insists on privately caching stuff (e.g. libhfs), we could + * end up corrupting the image we just wrote. We use SetAllReadOnly() to + * ensure that nothing will be written before we delete the DiskFS. + */ + assert(!fpDiskImg->GetReadOnly()); + fpDiskFS->SetAllReadOnly(true); + delete fpDiskFS; + fpDiskFS = nil; + assert(fpDiskImg->GetReadOnly()); + fpDiskImg->SetReadOnly(false); bail: - // restore the dialog window to prominence - EnableWindow(TRUE); - //SetActiveWindow(); - if (pProgressDialog != nil) - pProgressDialog->DestroyWindow(); + // restore the dialog window to prominence + EnableWindow(TRUE); + //SetActiveWindow(); + if (pProgressDialog != nil) + pProgressDialog->DestroyWindow(); - /* - * Force a reload. We need to reload the disk information, then reload - * the list contents. - * - * By design, anything that would require un-overriding the format of - * the target DiskImg requires reloading it completely. Sort of heavy- - * handed, but it's reliable. - */ - if (needReload) { - WMSG0("RELOAD dialog\n"); - ScanDiskInfo(true); // reopens fpDiskFS - LoadList(); + /* + * Force a reload. We need to reload the disk information, then reload + * the list contents. + * + * By design, anything that would require un-overriding the format of + * the target DiskImg requires reloading it completely. Sort of heavy- + * handed, but it's reliable. + */ + if (needReload) { + WMSG0("RELOAD dialog\n"); + ScanDiskInfo(true); // reopens fpDiskFS + LoadList(); - /* will we need to reopen the currently-open file list archive? */ - if (pMain->IsOpenPathName(fPathName)) - pMain->SetReopenFlag(); - } - return; + /* will we need to reopen the currently-open file list archive? */ + if (pMain->IsOpenPathName(fPathName)) + pMain->SetReopenFlag(); + } + return; } diff --git a/app/VolumeCopyDialog.h b/app/VolumeCopyDialog.h index d766929..dc935bd 100644 --- a/app/VolumeCopyDialog.h +++ b/app/VolumeCopyDialog.h @@ -20,61 +20,61 @@ */ class VolumeCopyDialog : public CDialog { public: - VolumeCopyDialog(CWnd* pParentWnd = NULL) : - CDialog(IDD_VOLUMECOPYSEL, pParentWnd), - fpDiskImg(nil), - fpDiskFS(nil), - fpWaitDlg(nil) - {} - ~VolumeCopyDialog(void) { assert(fpDiskFS == nil); } + VolumeCopyDialog(CWnd* pParentWnd = NULL) : + CDialog(IDD_VOLUMECOPYSEL, pParentWnd), + fpDiskImg(nil), + fpDiskFS(nil), + fpWaitDlg(nil) + {} + ~VolumeCopyDialog(void) { assert(fpDiskFS == nil); } - /* disk image to work with; we don't own it */ - DiskImgLib::DiskImg* fpDiskImg; - /* path name of input disk image or volume; mainly for display */ - CString fPathName; + /* disk image to work with; we don't own it */ + DiskImgLib::DiskImg* fpDiskImg; + /* path name of input disk image or volume; mainly for display */ + CString fPathName; protected: - virtual BOOL OnInitDialog(void); - //virtual void DoDataExchange(CDataExchange* pDX); - virtual void OnOK(void); - virtual void OnCancel(void); + virtual BOOL OnInitDialog(void); + //virtual void DoDataExchange(CDataExchange* pDX); + virtual void OnOK(void); + virtual void OnCancel(void); - void Cleanup(void); - - enum { WMU_DIALOG_READY = WM_USER+2 }; + void Cleanup(void); + + enum { WMU_DIALOG_READY = WM_USER+2 }; - afx_msg void OnHelp(void); - afx_msg void OnListChange(NMHDR* pNotifyStruct, LRESULT* pResult); - afx_msg void OnCopyToFile(void); - afx_msg void OnCopyFromFile(void); + afx_msg void OnHelp(void); + afx_msg void OnListChange(NMHDR* pNotifyStruct, LRESULT* pResult); + afx_msg void OnCopyToFile(void); + afx_msg void OnCopyFromFile(void); - afx_msg LONG OnDialogReady(UINT, LONG); + afx_msg LONG OnDialogReady(UINT, LONG); - void ScanDiskInfo(bool scanTop); - void LoadList(void); - void AddToList(CListCtrl* pListView, DiskImgLib::DiskImg* pDiskImg, - DiskImgLib::DiskFS* pDiskFS, int* pIndex); - bool GetSelectedDisk(DiskImgLib::DiskImg** ppDstImg, - DiskImgLib::DiskFS** ppDiskFS); + void ScanDiskInfo(bool scanTop); + void LoadList(void); + void AddToList(CListCtrl* pListView, DiskImgLib::DiskImg* pDiskImg, + DiskImgLib::DiskFS* pDiskFS, int* pIndex); + bool GetSelectedDisk(DiskImgLib::DiskImg** ppDstImg, + DiskImgLib::DiskFS** ppDiskFS); - // Load images to be used in the list. Apparently this must be called - // before we try to load any header images. - void LoadListImages(void) { - if (!fListImageList.Create(IDB_VOL_PICS, 16, 1, CLR_DEFAULT)) - WMSG0("GLITCH: list image create failed\n"); - fListImageList.SetBkColor(::GetSysColor(COLOR_WINDOW)); - } - enum { // defs for IDB_VOL_PICS - kListIconVolume = 0, - kListIconSubVolume = 1, - }; - CImageList fListImageList; + // Load images to be used in the list. Apparently this must be called + // before we try to load any header images. + void LoadListImages(void) { + if (!fListImageList.Create(IDB_VOL_PICS, 16, 1, CLR_DEFAULT)) + WMSG0("GLITCH: list image create failed\n"); + fListImageList.SetBkColor(::GetSysColor(COLOR_WINDOW)); + } + enum { // defs for IDB_VOL_PICS + kListIconVolume = 0, + kListIconSubVolume = 1, + }; + CImageList fListImageList; - DiskImgLib::DiskFS* fpDiskFS; + DiskImgLib::DiskFS* fpDiskFS; - ModelessDialog* fpWaitDlg; + ModelessDialog* fpWaitDlg; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__VOLUMECOPYDIALOG*/ diff --git a/diskimg/ASPI.cpp b/diskimg/ASPI.cpp index b1f870e..6fa26e5 100644 --- a/diskimg/ASPI.cpp +++ b/diskimg/ASPI.cpp @@ -7,11 +7,11 @@ * ASPI I/O functions. * * Some notes on ASPI stuff: - * - The Nero ASPI provides an interface for IDE hard drives. It also - * throws in a couple of mystery devices on a host adapter at the end. - * It has "unknown" device type and doesn't respond to SCSI device - * inquiries, so it's easy to ignore. - * - The Win98 generic ASPI only finds CD-ROM drives on the IDE bus. + * - The Nero ASPI provides an interface for IDE hard drives. It also + * throws in a couple of mystery devices on a host adapter at the end. + * It has "unknown" device type and doesn't respond to SCSI device + * inquiries, so it's easy to ignore. + * - The Win98 generic ASPI only finds CD-ROM drives on the IDE bus. */ #include "StdAfx.h" #ifdef _WIN32 @@ -28,62 +28,62 @@ DIError ASPI::Init(void) { - DWORD aspiStatus; - static const char* kASPIDllName = "wnaspi32.dll"; + DWORD aspiStatus; + static const char* kASPIDllName = "wnaspi32.dll"; - /* - * Try to load the DLL. - */ - fhASPI = ::LoadLibrary(kASPIDllName); - if (fhASPI == nil) { - DWORD lastErr = ::GetLastError(); - if (lastErr == ERROR_MOD_NOT_FOUND) { - WMSG1("ASPI DLL '%s' not found\n", kASPIDllName); - } else { - WMSG2("ASPI LoadLibrary(%s) failed (err=%ld)\n", - kASPIDllName, GetLastError()); - } - return kDIErrGeneric; - } + /* + * Try to load the DLL. + */ + fhASPI = ::LoadLibrary(kASPIDllName); + if (fhASPI == nil) { + DWORD lastErr = ::GetLastError(); + if (lastErr == ERROR_MOD_NOT_FOUND) { + WMSG1("ASPI DLL '%s' not found\n", kASPIDllName); + } else { + WMSG2("ASPI LoadLibrary(%s) failed (err=%ld)\n", + kASPIDllName, GetLastError()); + } + return kDIErrGeneric; + } - GetASPI32SupportInfo = (DWORD(*)(void))::GetProcAddress(fhASPI, "GetASPI32SupportInfo"); - SendASPI32Command = (DWORD(*)(LPSRB))::GetProcAddress(fhASPI, "SendASPI32Command"); - GetASPI32DLLVersion = (DWORD(*)(void))::GetProcAddress(fhASPI, "GetASPI32DLLVersion"); - if (GetASPI32SupportInfo == nil || SendASPI32Command == nil) { - WMSG0("ASPI functions not found in dll\n"); - ::FreeLibrary(fhASPI); - fhASPI = nil; - return kDIErrGeneric; - } + GetASPI32SupportInfo = (DWORD(*)(void))::GetProcAddress(fhASPI, "GetASPI32SupportInfo"); + SendASPI32Command = (DWORD(*)(LPSRB))::GetProcAddress(fhASPI, "SendASPI32Command"); + GetASPI32DLLVersion = (DWORD(*)(void))::GetProcAddress(fhASPI, "GetASPI32DLLVersion"); + if (GetASPI32SupportInfo == nil || SendASPI32Command == nil) { + WMSG0("ASPI functions not found in dll\n"); + ::FreeLibrary(fhASPI); + fhASPI = nil; + return kDIErrGeneric; + } - if (GetASPI32DLLVersion != nil) { - fASPIVersion = GetASPI32DLLVersion(); - WMSG4(" ASPI version is %d.%d.%d.%d\n", - fASPIVersion & 0x0ff, - (fASPIVersion >> 8) & 0xff, - (fASPIVersion >> 16) & 0xff, - (fASPIVersion >> 24) & 0xff); - } else { - WMSG0("ASPI WARNING: couldn't find GetASPI32DLLVersion interface\n"); - } + if (GetASPI32DLLVersion != nil) { + fASPIVersion = GetASPI32DLLVersion(); + WMSG4(" ASPI version is %d.%d.%d.%d\n", + fASPIVersion & 0x0ff, + (fASPIVersion >> 8) & 0xff, + (fASPIVersion >> 16) & 0xff, + (fASPIVersion >> 24) & 0xff); + } else { + WMSG0("ASPI WARNING: couldn't find GetASPI32DLLVersion interface\n"); + } - /* - * Successfully loaded the library. Start it up and see if it works. - */ - aspiStatus = GetASPI32SupportInfo(); - if (HIBYTE(LOWORD(aspiStatus)) != SS_COMP) { - WMSG1("ASPI loaded but not working (status=%d)\n", - HIBYTE(LOWORD(aspiStatus))); - ::FreeLibrary(fhASPI); - fhASPI = nil; - return kDIErrASPIFailure; - } + /* + * Successfully loaded the library. Start it up and see if it works. + */ + aspiStatus = GetASPI32SupportInfo(); + if (HIBYTE(LOWORD(aspiStatus)) != SS_COMP) { + WMSG1("ASPI loaded but not working (status=%d)\n", + HIBYTE(LOWORD(aspiStatus))); + ::FreeLibrary(fhASPI); + fhASPI = nil; + return kDIErrASPIFailure; + } - fHostAdapterCount = LOBYTE(LOWORD(aspiStatus)); - WMSG1("ASPI loaded successfully, hostAdapterCount=%d\n", - fHostAdapterCount); + fHostAdapterCount = LOBYTE(LOWORD(aspiStatus)); + WMSG1("ASPI loaded successfully, hostAdapterCount=%d\n", + fHostAdapterCount); - return kDIErrNone; + return kDIErrNone; } /* @@ -91,11 +91,11 @@ ASPI::Init(void) */ ASPI::~ASPI(void) { - if (fhASPI != nil) { - WMSG0("Unloading ASPI DLL\n"); - ::FreeLibrary(fhASPI); - fhASPI = nil; - } + if (fhASPI != nil) { + WMSG0("Unloading ASPI DLL\n"); + ::FreeLibrary(fhASPI); + fhASPI = nil; + } } @@ -107,34 +107,34 @@ ASPI::~ASPI(void) DIError ASPI::HostAdapterInquiry(unsigned char adapter, AdapterInfo* pAdapterInfo) { - SRB_HAInquiry req; - DWORD result; + SRB_HAInquiry req; + DWORD result; - assert(adapter >= 0 && adapter < kMaxAdapters); + assert(adapter >= 0 && adapter < kMaxAdapters); - memset(&req, 0, sizeof(req)); - req.SRB_Cmd = SC_HA_INQUIRY; - req.SRB_HaId = adapter; + memset(&req, 0, sizeof(req)); + req.SRB_Cmd = SC_HA_INQUIRY; + req.SRB_HaId = adapter; - result = SendASPI32Command(&req); - if (result != SS_COMP) { - WMSG2("ASPI(SC_HA_INQUIRY on %d) failed with result=0x%lx\n", - adapter, result); - return kDIErrASPIFailure; - } + result = SendASPI32Command(&req); + if (result != SS_COMP) { + WMSG2("ASPI(SC_HA_INQUIRY on %d) failed with result=0x%lx\n", + adapter, result); + return kDIErrASPIFailure; + } - pAdapterInfo->adapterScsiID = req.HA_SCSI_ID; - memcpy(pAdapterInfo->managerID, req.HA_ManagerId, - sizeof(pAdapterInfo->managerID)-1); - pAdapterInfo->managerID[sizeof(pAdapterInfo->managerID)-1] = '\0'; - memcpy(pAdapterInfo->identifier, req.HA_Identifier, - sizeof(pAdapterInfo->identifier)-1); - pAdapterInfo->identifier[sizeof(pAdapterInfo->identifier)-1] = '\0'; - pAdapterInfo->maxTargets = req.HA_Unique[3]; - pAdapterInfo->bufferAlignment = - (unsigned short) req.HA_Unique[1] << 8 | req.HA_Unique[0]; + pAdapterInfo->adapterScsiID = req.HA_SCSI_ID; + memcpy(pAdapterInfo->managerID, req.HA_ManagerId, + sizeof(pAdapterInfo->managerID)-1); + pAdapterInfo->managerID[sizeof(pAdapterInfo->managerID)-1] = '\0'; + memcpy(pAdapterInfo->identifier, req.HA_Identifier, + sizeof(pAdapterInfo->identifier)-1); + pAdapterInfo->identifier[sizeof(pAdapterInfo->identifier)-1] = '\0'; + pAdapterInfo->maxTargets = req.HA_Unique[3]; + pAdapterInfo->bufferAlignment = + (unsigned short) req.HA_Unique[1] << 8 | req.HA_Unique[0]; - return kDIErrNone; + return kDIErrNone; } /* @@ -142,29 +142,29 @@ ASPI::HostAdapterInquiry(unsigned char adapter, AdapterInfo* pAdapterInfo) */ DIError ASPI::GetDeviceType(unsigned char adapter, unsigned char target, - unsigned char lun, unsigned char* pType) + unsigned char lun, unsigned char* pType) { - SRB_GDEVBlock req; - DWORD result; + SRB_GDEVBlock req; + DWORD result; - assert(adapter >= 0 && adapter < kMaxAdapters); - assert(target >= 0 && target < kMaxTargets); - assert(lun >= 0 && lun < kMaxLuns); - assert(pType != nil); + assert(adapter >= 0 && adapter < kMaxAdapters); + assert(target >= 0 && target < kMaxTargets); + assert(lun >= 0 && lun < kMaxLuns); + assert(pType != nil); - memset(&req, 0, sizeof(req)); - req.SRB_Cmd = SC_GET_DEV_TYPE; - req.SRB_HaId = adapter; - req.SRB_Target = target; - req.SRB_Lun = lun; + memset(&req, 0, sizeof(req)); + req.SRB_Cmd = SC_GET_DEV_TYPE; + req.SRB_HaId = adapter; + req.SRB_Target = target; + req.SRB_Lun = lun; - result = SendASPI32Command(&req); - if (result != SS_COMP) - return kDIErrASPIFailure; + result = SendASPI32Command(&req); + if (result != SS_COMP) + return kDIErrASPIFailure; - *pType = req.SRB_DeviceType; + *pType = req.SRB_DeviceType; - return kDIErrNone; + return kDIErrNone; } /* @@ -173,20 +173,20 @@ ASPI::GetDeviceType(unsigned char adapter, unsigned char target, const char* ASPI::DeviceTypeToString(unsigned char deviceType) { - switch (deviceType) { - case kScsiDevTypeDASD: return "Disk device"; - case kScsiDevTypeSEQD: return "Tape device"; - case kScsiDevTypePRNT: return "Printer"; - case kScsiDevTypePROC: return "Processor"; - case kScsiDevTypeWORM: return "Write-once read-multiple"; - case kScsiDevTypeCDROM: return "CD-ROM device"; - case kScsiDevTypeSCAN: return "Scanner device"; - case kScsiDevTypeOPTI: return "Optical memory device"; - case kScsiDevTypeJUKE: return "Medium changer device"; - case kScsiDevTypeCOMM: return "Communications device"; - case kScsiDevTypeUNKNOWN: return "Unknown or no device type"; - default: return "Invalid type"; - } + switch (deviceType) { + case kScsiDevTypeDASD: return "Disk device"; + case kScsiDevTypeSEQD: return "Tape device"; + case kScsiDevTypePRNT: return "Printer"; + case kScsiDevTypePROC: return "Processor"; + case kScsiDevTypeWORM: return "Write-once read-multiple"; + case kScsiDevTypeCDROM: return "CD-ROM device"; + case kScsiDevTypeSCAN: return "Scanner device"; + case kScsiDevTypeOPTI: return "Optical memory device"; + case kScsiDevTypeJUKE: return "Medium changer device"; + case kScsiDevTypeCOMM: return "Communications device"; + case kScsiDevTypeUNKNOWN: return "Unknown or no device type"; + default: return "Invalid type"; + } } /* @@ -194,51 +194,51 @@ ASPI::DeviceTypeToString(unsigned char deviceType) */ DIError ASPI::DeviceInquiry(unsigned char adapter, unsigned char target, - unsigned char lun, Inquiry* pInquiry) + unsigned char lun, Inquiry* pInquiry) { - DIError dierr; - SRB_ExecSCSICmd srb; - CDB6Inquiry* pCDB; - unsigned char buf[96]; // enough to hold everything of interest, and more - CDB_InquiryData* pInqData = (CDB_InquiryData*) buf; + DIError dierr; + SRB_ExecSCSICmd srb; + CDB6Inquiry* pCDB; + unsigned char buf[96]; // enough to hold everything of interest, and more + CDB_InquiryData* pInqData = (CDB_InquiryData*) buf; - assert(sizeof(CDB6Inquiry) == 6); + assert(sizeof(CDB6Inquiry) == 6); - memset(&srb, 0, sizeof(srb)); - srb.SRB_Cmd = SC_EXEC_SCSI_CMD; - srb.SRB_HaId = adapter; - srb.SRB_Target = target; - srb.SRB_Lun = lun; - srb.SRB_Flags = SRB_DIR_IN; - srb.SRB_BufLen = sizeof(buf); - srb.SRB_BufPointer = buf; - srb.SRB_SenseLen = SENSE_LEN; - srb.SRB_CDBLen = sizeof(*pCDB); + memset(&srb, 0, sizeof(srb)); + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_HaId = adapter; + srb.SRB_Target = target; + srb.SRB_Lun = lun; + srb.SRB_Flags = SRB_DIR_IN; + srb.SRB_BufLen = sizeof(buf); + srb.SRB_BufPointer = buf; + srb.SRB_SenseLen = SENSE_LEN; + srb.SRB_CDBLen = sizeof(*pCDB); - pCDB = (CDB6Inquiry*) srb.CDBByte; - pCDB->operationCode = kScsiOpInquiry; - pCDB->allocationLength = sizeof(buf); + pCDB = (CDB6Inquiry*) srb.CDBByte; + pCDB->operationCode = kScsiOpInquiry; + pCDB->allocationLength = sizeof(buf); - // Don't set pCDB->logicalUnitNumber. It's only there for SCSI-1 - // devices. SCSI-2 uses an IDENTIFY command; I gather ASPI is doing - // this for us. + // Don't set pCDB->logicalUnitNumber. It's only there for SCSI-1 + // devices. SCSI-2 uses an IDENTIFY command; I gather ASPI is doing + // this for us. - dierr = ExecSCSICommand(&srb); - if (dierr != kDIErrNone) - return dierr; + dierr = ExecSCSICommand(&srb); + if (dierr != kDIErrNone) + return dierr; - memcpy(pInquiry->vendorID, pInqData->vendorId, - sizeof(pInquiry->vendorID)-1); - pInquiry->vendorID[sizeof(pInquiry->vendorID)-1] = '\0'; - memcpy(pInquiry->productID, pInqData->productId, - sizeof(pInquiry->productID)-1); - pInquiry->productID[sizeof(pInquiry->productID)-1] = '\0'; - pInquiry->productRevision[0] = pInqData->productRevisionLevel[0]; - pInquiry->productRevision[1] = pInqData->productRevisionLevel[1]; - pInquiry->productRevision[2] = pInqData->productRevisionLevel[2]; - pInquiry->productRevision[3] = pInqData->productRevisionLevel[3]; + memcpy(pInquiry->vendorID, pInqData->vendorId, + sizeof(pInquiry->vendorID)-1); + pInquiry->vendorID[sizeof(pInquiry->vendorID)-1] = '\0'; + memcpy(pInquiry->productID, pInqData->productId, + sizeof(pInquiry->productID)-1); + pInquiry->productID[sizeof(pInquiry->productID)-1] = '\0'; + pInquiry->productRevision[0] = pInqData->productRevisionLevel[0]; + pInquiry->productRevision[1] = pInqData->productRevisionLevel[1]; + pInquiry->productRevision[2] = pInqData->productRevisionLevel[2]; + pInquiry->productRevision[3] = pInqData->productRevisionLevel[3]; - return kDIErrNone; + return kDIErrNone; } @@ -247,46 +247,46 @@ ASPI::DeviceInquiry(unsigned char adapter, unsigned char target, */ DIError ASPI::GetDeviceCapacity(unsigned char adapter, unsigned char target, - unsigned char lun, unsigned long* pLastBlock, unsigned long* pBlockSize) + unsigned char lun, unsigned long* pLastBlock, unsigned long* pBlockSize) { - DIError dierr; - SRB_ExecSCSICmd srb; - CDB10* pCDB; - CDB_ReadCapacityData dataBuf; + DIError dierr; + SRB_ExecSCSICmd srb; + CDB10* pCDB; + CDB_ReadCapacityData dataBuf; - assert(sizeof(dataBuf) == 8); // READ CAPACITY returns two longs - assert(sizeof(CDB10) == 10); + assert(sizeof(dataBuf) == 8); // READ CAPACITY returns two longs + assert(sizeof(CDB10) == 10); - memset(&srb, 0, sizeof(srb)); - srb.SRB_Cmd = SC_EXEC_SCSI_CMD; - srb.SRB_HaId = adapter; - srb.SRB_Target = target; - srb.SRB_Lun = lun; - srb.SRB_Flags = SRB_DIR_IN; - srb.SRB_BufLen = sizeof(dataBuf); - srb.SRB_BufPointer = (unsigned char*)&dataBuf; - srb.SRB_SenseLen = SENSE_LEN; - srb.SRB_CDBLen = sizeof(*pCDB); + memset(&srb, 0, sizeof(srb)); + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_HaId = adapter; + srb.SRB_Target = target; + srb.SRB_Lun = lun; + srb.SRB_Flags = SRB_DIR_IN; + srb.SRB_BufLen = sizeof(dataBuf); + srb.SRB_BufPointer = (unsigned char*)&dataBuf; + srb.SRB_SenseLen = SENSE_LEN; + srb.SRB_CDBLen = sizeof(*pCDB); - pCDB = (CDB10*) srb.CDBByte; - pCDB->operationCode = kScsiOpReadCapacity; - // rest of CDB is zero + pCDB = (CDB10*) srb.CDBByte; + pCDB->operationCode = kScsiOpReadCapacity; + // rest of CDB is zero - dierr = ExecSCSICommand(&srb); - if (dierr != kDIErrNone) - return dierr; + dierr = ExecSCSICommand(&srb); + if (dierr != kDIErrNone) + return dierr; - *pLastBlock = - (unsigned long) dataBuf.logicalBlockAddr0 << 24 | - (unsigned long) dataBuf.logicalBlockAddr1 << 16 | - (unsigned long) dataBuf.logicalBlockAddr2 << 8 | - (unsigned long) dataBuf.logicalBlockAddr3; - *pBlockSize = - (unsigned long) dataBuf.bytesPerBlock0 << 24 | - (unsigned long) dataBuf.bytesPerBlock1 << 16 | - (unsigned long) dataBuf.bytesPerBlock2 << 8 | - (unsigned long) dataBuf.bytesPerBlock3; - return kDIErrNone; + *pLastBlock = + (unsigned long) dataBuf.logicalBlockAddr0 << 24 | + (unsigned long) dataBuf.logicalBlockAddr1 << 16 | + (unsigned long) dataBuf.logicalBlockAddr2 << 8 | + (unsigned long) dataBuf.logicalBlockAddr3; + *pBlockSize = + (unsigned long) dataBuf.bytesPerBlock0 << 24 | + (unsigned long) dataBuf.bytesPerBlock1 << 16 | + (unsigned long) dataBuf.bytesPerBlock2 << 8 | + (unsigned long) dataBuf.bytesPerBlock3; + return kDIErrNone; } /* @@ -296,56 +296,56 @@ ASPI::GetDeviceCapacity(unsigned char adapter, unsigned char target, */ DIError ASPI::TestUnitReady(unsigned char adapter, unsigned char target, - unsigned char lun, bool* pReady) + unsigned char lun, bool* pReady) { - DIError dierr; - SRB_ExecSCSICmd srb; - CDB6* pCDB; + DIError dierr; + SRB_ExecSCSICmd srb; + CDB6* pCDB; - assert(sizeof(CDB6) == 6); + assert(sizeof(CDB6) == 6); - memset(&srb, 0, sizeof(srb)); - srb.SRB_Cmd = SC_EXEC_SCSI_CMD; - srb.SRB_HaId = adapter; - srb.SRB_Target = target; - srb.SRB_Lun = lun; - srb.SRB_Flags = 0; //SRB_DIR_IN; - srb.SRB_BufLen = 0; - srb.SRB_BufPointer = nil; - srb.SRB_SenseLen = SENSE_LEN; - srb.SRB_CDBLen = sizeof(*pCDB); + memset(&srb, 0, sizeof(srb)); + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_HaId = adapter; + srb.SRB_Target = target; + srb.SRB_Lun = lun; + srb.SRB_Flags = 0; //SRB_DIR_IN; + srb.SRB_BufLen = 0; + srb.SRB_BufPointer = nil; + srb.SRB_SenseLen = SENSE_LEN; + srb.SRB_CDBLen = sizeof(*pCDB); - pCDB = (CDB6*) srb.CDBByte; - pCDB->operationCode = kScsiOpTestUnitReady; - // rest of CDB is zero + pCDB = (CDB6*) srb.CDBByte; + pCDB->operationCode = kScsiOpTestUnitReady; + // rest of CDB is zero - dierr = ExecSCSICommand(&srb); - if (dierr != kDIErrNone) { - const CDB_SenseData* pSense = (const CDB_SenseData*) srb.SenseArea; + dierr = ExecSCSICommand(&srb); + if (dierr != kDIErrNone) { + const CDB_SenseData* pSense = (const CDB_SenseData*) srb.SenseArea; - if (srb.SRB_TargStat == kScsiStatCheckCondition && - pSense->senseKey == kScsiSenseNotReady) - { - // expect pSense->additionalSenseCode to be - // kScsiAdSenseNoMediaInDevice; no need to check it really. - WMSG3(" ASPI TestUnitReady: drive %d:%d:%d is NOT ready\n", - adapter, target, lun); - } else { - WMSG3(" ASPI TestUnitReady failed, status=0x%02x sense=0x%02x ASC=0x%02x\n", - srb.SRB_TargStat, pSense->senseKey, - pSense->additionalSenseCode); - } - *pReady = false; - } else { - const CDB_SenseData* pSense = (const CDB_SenseData*) srb.SenseArea; - WMSG3(" ASPI TestUnitReady: drive %d:%d:%d is ready\n", - adapter, target, lun); - //WMSG3(" status=0x%02x sense=0x%02x ASC=0x%02x\n", - // srb.SRB_TargStat, pSense->senseKey, pSense->additionalSenseCode); - *pReady = true; - } + if (srb.SRB_TargStat == kScsiStatCheckCondition && + pSense->senseKey == kScsiSenseNotReady) + { + // expect pSense->additionalSenseCode to be + // kScsiAdSenseNoMediaInDevice; no need to check it really. + WMSG3(" ASPI TestUnitReady: drive %d:%d:%d is NOT ready\n", + adapter, target, lun); + } else { + WMSG3(" ASPI TestUnitReady failed, status=0x%02x sense=0x%02x ASC=0x%02x\n", + srb.SRB_TargStat, pSense->senseKey, + pSense->additionalSenseCode); + } + *pReady = false; + } else { + const CDB_SenseData* pSense = (const CDB_SenseData*) srb.SenseArea; + WMSG3(" ASPI TestUnitReady: drive %d:%d:%d is ready\n", + adapter, target, lun); + //WMSG3(" status=0x%02x sense=0x%02x ASC=0x%02x\n", + // srb.SRB_TargStat, pSense->senseKey, pSense->additionalSenseCode); + *pReady = true; + } - return kDIErrNone; + return kDIErrNone; } /* @@ -357,41 +357,41 @@ ASPI::TestUnitReady(unsigned char adapter, unsigned char target, */ DIError ASPI::ReadBlocks(unsigned char adapter, unsigned char target, - unsigned char lun, long startBlock, short numBlocks, long blockSize, - void* buf) + unsigned char lun, long startBlock, short numBlocks, long blockSize, + void* buf) { - SRB_ExecSCSICmd srb; - CDB10* pCDB; + SRB_ExecSCSICmd srb; + CDB10* pCDB; - //WMSG3(" ASPI ReadBlocks start=%ld num=%d (size=%d)\n", - // startBlock, numBlocks, blockSize); + //WMSG3(" ASPI ReadBlocks start=%ld num=%d (size=%d)\n", + // startBlock, numBlocks, blockSize); - assert(sizeof(CDB10) == 10); - assert(startBlock >= 0); - assert(numBlocks > 0); - assert(buf != nil); + assert(sizeof(CDB10) == 10); + assert(startBlock >= 0); + assert(numBlocks > 0); + assert(buf != nil); - memset(&srb, 0, sizeof(srb)); - srb.SRB_Cmd = SC_EXEC_SCSI_CMD; - srb.SRB_HaId = adapter; - srb.SRB_Target = target; - srb.SRB_Lun = lun; - srb.SRB_Flags = SRB_DIR_IN; - srb.SRB_BufLen = numBlocks * blockSize; - srb.SRB_BufPointer = (unsigned char*)buf; - srb.SRB_SenseLen = SENSE_LEN; - srb.SRB_CDBLen = sizeof(*pCDB); + memset(&srb, 0, sizeof(srb)); + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_HaId = adapter; + srb.SRB_Target = target; + srb.SRB_Lun = lun; + srb.SRB_Flags = SRB_DIR_IN; + srb.SRB_BufLen = numBlocks * blockSize; + srb.SRB_BufPointer = (unsigned char*)buf; + srb.SRB_SenseLen = SENSE_LEN; + srb.SRB_CDBLen = sizeof(*pCDB); - pCDB = (CDB10*) srb.CDBByte; - pCDB->operationCode = kScsiOpRead; - pCDB->logicalBlockAddr0 = (unsigned char) (startBlock >> 24); // MSB - pCDB->logicalBlockAddr1 = (unsigned char) (startBlock >> 16); - pCDB->logicalBlockAddr2 = (unsigned char) (startBlock >> 8); - pCDB->logicalBlockAddr3 = (unsigned char) startBlock; // LSB - pCDB->transferLength0 = (unsigned char) (numBlocks >> 8); // MSB - pCDB->transferLength1 = (unsigned char) numBlocks; // LSB + pCDB = (CDB10*) srb.CDBByte; + pCDB->operationCode = kScsiOpRead; + pCDB->logicalBlockAddr0 = (unsigned char) (startBlock >> 24); // MSB + pCDB->logicalBlockAddr1 = (unsigned char) (startBlock >> 16); + pCDB->logicalBlockAddr2 = (unsigned char) (startBlock >> 8); + pCDB->logicalBlockAddr3 = (unsigned char) startBlock; // LSB + pCDB->transferLength0 = (unsigned char) (numBlocks >> 8); // MSB + pCDB->transferLength1 = (unsigned char) numBlocks; // LSB - return ExecSCSICommand(&srb); + return ExecSCSICommand(&srb); } /* @@ -399,41 +399,41 @@ ASPI::ReadBlocks(unsigned char adapter, unsigned char target, */ DIError ASPI::WriteBlocks(unsigned char adapter, unsigned char target, - unsigned char lun, long startBlock, short numBlocks, long blockSize, - const void* buf) + unsigned char lun, long startBlock, short numBlocks, long blockSize, + const void* buf) { - SRB_ExecSCSICmd srb; - CDB10* pCDB; + SRB_ExecSCSICmd srb; + CDB10* pCDB; - WMSG3(" ASPI WriteBlocks start=%ld num=%d (size=%d)\n", - startBlock, numBlocks, blockSize); + WMSG3(" ASPI WriteBlocks start=%ld num=%d (size=%d)\n", + startBlock, numBlocks, blockSize); - assert(sizeof(CDB10) == 10); - assert(startBlock >= 0); - assert(numBlocks > 0); - assert(buf != nil); + assert(sizeof(CDB10) == 10); + assert(startBlock >= 0); + assert(numBlocks > 0); + assert(buf != nil); - memset(&srb, 0, sizeof(srb)); - srb.SRB_Cmd = SC_EXEC_SCSI_CMD; - srb.SRB_HaId = adapter; - srb.SRB_Target = target; - srb.SRB_Lun = lun; - srb.SRB_Flags = SRB_DIR_IN; - srb.SRB_BufLen = numBlocks * blockSize; - srb.SRB_BufPointer = (unsigned char*)buf; - srb.SRB_SenseLen = SENSE_LEN; - srb.SRB_CDBLen = sizeof(*pCDB); + memset(&srb, 0, sizeof(srb)); + srb.SRB_Cmd = SC_EXEC_SCSI_CMD; + srb.SRB_HaId = adapter; + srb.SRB_Target = target; + srb.SRB_Lun = lun; + srb.SRB_Flags = SRB_DIR_IN; + srb.SRB_BufLen = numBlocks * blockSize; + srb.SRB_BufPointer = (unsigned char*)buf; + srb.SRB_SenseLen = SENSE_LEN; + srb.SRB_CDBLen = sizeof(*pCDB); - pCDB = (CDB10*) srb.CDBByte; - pCDB->operationCode = kScsiOpWrite; - pCDB->logicalBlockAddr0 = (unsigned char) (startBlock >> 24); // MSB - pCDB->logicalBlockAddr1 = (unsigned char) (startBlock >> 16); - pCDB->logicalBlockAddr2 = (unsigned char) (startBlock >> 8); - pCDB->logicalBlockAddr3 = (unsigned char) startBlock; // LSB - pCDB->transferLength0 = (unsigned char) (numBlocks >> 8); // MSB - pCDB->transferLength1 = (unsigned char) numBlocks; // LSB + pCDB = (CDB10*) srb.CDBByte; + pCDB->operationCode = kScsiOpWrite; + pCDB->logicalBlockAddr0 = (unsigned char) (startBlock >> 24); // MSB + pCDB->logicalBlockAddr1 = (unsigned char) (startBlock >> 16); + pCDB->logicalBlockAddr2 = (unsigned char) (startBlock >> 8); + pCDB->logicalBlockAddr3 = (unsigned char) startBlock; // LSB + pCDB->transferLength0 = (unsigned char) (numBlocks >> 8); // MSB + pCDB->transferLength1 = (unsigned char) numBlocks; // LSB - return ExecSCSICommand(&srb); + return ExecSCSICommand(&srb); } @@ -449,71 +449,71 @@ ASPI::WriteBlocks(unsigned char adapter, unsigned char target, DIError ASPI::ExecSCSICommand(SRB_ExecSCSICmd* pSRB) { - HANDLE completionEvent = nil; - DWORD eventStatus; - DWORD aspiStatus; + HANDLE completionEvent = nil; + DWORD eventStatus; + DWORD aspiStatus; - assert(pSRB->SRB_Cmd == SC_EXEC_SCSI_CMD); - assert(pSRB->SRB_Flags == SRB_DIR_IN || - pSRB->SRB_Flags == SRB_DIR_OUT || - pSRB->SRB_Flags == 0); + assert(pSRB->SRB_Cmd == SC_EXEC_SCSI_CMD); + assert(pSRB->SRB_Flags == SRB_DIR_IN || + pSRB->SRB_Flags == SRB_DIR_OUT || + pSRB->SRB_Flags == 0); - /* - * Set up event-waiting stuff, as described in the Adaptec ASPI docs. - */ - pSRB->SRB_Flags |= SRB_EVENT_NOTIFY; + /* + * Set up event-waiting stuff, as described in the Adaptec ASPI docs. + */ + pSRB->SRB_Flags |= SRB_EVENT_NOTIFY; completionEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); - if (completionEvent == nil) { - WMSG0("Failed creating a completion event?\n"); - return kDIErrGeneric; - } + if (completionEvent == nil) { + WMSG0("Failed creating a completion event?\n"); + return kDIErrGeneric; + } - pSRB->SRB_PostProc = completionEvent; + pSRB->SRB_PostProc = completionEvent; - /* - * Send the request. - */ - (void)SendASPI32Command((LPSRB) pSRB); - aspiStatus = pSRB->SRB_Status; - if (aspiStatus == SS_PENDING) { - //WMSG0(" (waiting for completion)\n"); - eventStatus = ::WaitForSingleObject(completionEvent, kTimeout * 1000); + /* + * Send the request. + */ + (void)SendASPI32Command((LPSRB) pSRB); + aspiStatus = pSRB->SRB_Status; + if (aspiStatus == SS_PENDING) { + //WMSG0(" (waiting for completion)\n"); + eventStatus = ::WaitForSingleObject(completionEvent, kTimeout * 1000); - ::CloseHandle(completionEvent); + ::CloseHandle(completionEvent); - if (eventStatus == WAIT_TIMEOUT) { - WMSG0(" ASPI exec timed out!\n"); - return kDIErrSCSIFailure; - } else if (eventStatus != WAIT_OBJECT_0) { - WMSG1(" ASPI exec returned weird wait state %ld\n", eventStatus); - return kDIErrGeneric; - } - } + if (eventStatus == WAIT_TIMEOUT) { + WMSG0(" ASPI exec timed out!\n"); + return kDIErrSCSIFailure; + } else if (eventStatus != WAIT_OBJECT_0) { + WMSG1(" ASPI exec returned weird wait state %ld\n", eventStatus); + return kDIErrGeneric; + } + } - /* - * Check the final status. - */ - aspiStatus = pSRB->SRB_Status; + /* + * Check the final status. + */ + aspiStatus = pSRB->SRB_Status; - if (aspiStatus == SS_COMP) { - /* success! */ - } else if (aspiStatus == SS_ERR) { - const CDB_SenseData* pSense = (const CDB_SenseData*) pSRB->SenseArea; + if (aspiStatus == SS_COMP) { + /* success! */ + } else if (aspiStatus == SS_ERR) { + const CDB_SenseData* pSense = (const CDB_SenseData*) pSRB->SenseArea; - WMSG4(" ASPI SCSI command 0x%02x failed: scsiStatus=0x%02x" - " senseKey=0x%02x ASC=0x%02x\n", - pSRB->CDBByte[0], pSRB->SRB_TargStat, - pSense->senseKey, pSense->additionalSenseCode); - return kDIErrSCSIFailure; - } else { - // SS_ABORTED, SS_ABORT_FAIL, SS_NO_DEVICE, ... - WMSG3(" ASPI failed on command 0x%02x: aspiStatus=%d scsiStatus=%d\n", - pSRB->CDBByte[0], aspiStatus, pSRB->SRB_TargStat); - return kDIErrASPIFailure; - } + WMSG4(" ASPI SCSI command 0x%02x failed: scsiStatus=0x%02x" + " senseKey=0x%02x ASC=0x%02x\n", + pSRB->CDBByte[0], pSRB->SRB_TargStat, + pSense->senseKey, pSense->additionalSenseCode); + return kDIErrSCSIFailure; + } else { + // SS_ABORTED, SS_ABORT_FAIL, SS_NO_DEVICE, ... + WMSG3(" ASPI failed on command 0x%02x: aspiStatus=%d scsiStatus=%d\n", + pSRB->CDBByte[0], aspiStatus, pSRB->SRB_TargStat); + return kDIErrASPIFailure; + } - return kDIErrNone; + return kDIErrNone; } @@ -524,103 +524,103 @@ ASPI::ExecSCSICommand(SRB_ExecSCSICmd* pSRB) */ DIError ASPI::GetAccessibleDevices(int deviceMask, ASPIDevice** ppDeviceArray, - int* pNumDevices) + int* pNumDevices) { - DIError dierr; - ASPIDevice* deviceArray = nil; - int idx = 0; + DIError dierr; + ASPIDevice* deviceArray = nil; + int idx = 0; - assert(deviceMask != 0); - assert((deviceMask & ~(kDevMaskCDROM | kDevMaskHardDrive)) == 0); - assert(ppDeviceArray != nil); - assert(pNumDevices != nil); + assert(deviceMask != 0); + assert((deviceMask & ~(kDevMaskCDROM | kDevMaskHardDrive)) == 0); + assert(ppDeviceArray != nil); + assert(pNumDevices != nil); - deviceArray = new ASPIDevice[kMaxAccessibleDrives]; - if (deviceArray == nil) - return kDIErrMalloc; + deviceArray = new ASPIDevice[kMaxAccessibleDrives]; + if (deviceArray == nil) + return kDIErrMalloc; - WMSG1("ASPI scanning %d host adapters\n", fHostAdapterCount); + WMSG1("ASPI scanning %d host adapters\n", fHostAdapterCount); - for (int ha = 0; ha < fHostAdapterCount; ha++) { - AdapterInfo adi; + for (int ha = 0; ha < fHostAdapterCount; ha++) { + AdapterInfo adi; - dierr = HostAdapterInquiry(ha, &adi); - if (dierr != kDIErrNone) { - WMSG1(" ASPI inquiry on %d failed\n", ha); - continue; - } + dierr = HostAdapterInquiry(ha, &adi); + if (dierr != kDIErrNone) { + WMSG1(" ASPI inquiry on %d failed\n", ha); + continue; + } - WMSG2(" ASPI host adapter %d (SCSI ID=%d)\n", ha, adi.adapterScsiID); - WMSG2(" identifier='%s' managerID='%s'\n", - adi.identifier, adi.managerID); - WMSG2(" maxTargets=%d bufferAlignment=%d\n", - adi.maxTargets, adi.bufferAlignment); + WMSG2(" ASPI host adapter %d (SCSI ID=%d)\n", ha, adi.adapterScsiID); + WMSG2(" identifier='%s' managerID='%s'\n", + adi.identifier, adi.managerID); + WMSG2(" maxTargets=%d bufferAlignment=%d\n", + adi.maxTargets, adi.bufferAlignment); - int maxTargets = adi.maxTargets; - if (!maxTargets) { - /* Win98 ASPI reports zero here for ATAPI */ - maxTargets = 8; - } - if (maxTargets > kMaxTargets) - maxTargets = kMaxTargets; - for (int targ = 0; targ < maxTargets; targ++) { - for (int lun = 0; lun < kMaxLuns; lun++) { - Inquiry inq; - unsigned char deviceType; - char addrString[48]; - bool deviceReady; + int maxTargets = adi.maxTargets; + if (!maxTargets) { + /* Win98 ASPI reports zero here for ATAPI */ + maxTargets = 8; + } + if (maxTargets > kMaxTargets) + maxTargets = kMaxTargets; + for (int targ = 0; targ < maxTargets; targ++) { + for (int lun = 0; lun < kMaxLuns; lun++) { + Inquiry inq; + unsigned char deviceType; + char addrString[48]; + bool deviceReady; - dierr = GetDeviceType(ha, targ, lun, &deviceType); - if (dierr != kDIErrNone) - continue; + dierr = GetDeviceType(ha, targ, lun, &deviceType); + if (dierr != kDIErrNone) + continue; - sprintf(addrString, "%d:%d:%d", ha, targ, lun); + sprintf(addrString, "%d:%d:%d", ha, targ, lun); - dierr = DeviceInquiry(ha, targ, lun, &inq); - if (dierr != kDIErrNone) { - WMSG2(" ASPI DeviceInquiry for '%s' (type=%d) failed\n", - addrString, deviceType); - continue; - } + dierr = DeviceInquiry(ha, targ, lun, &inq); + if (dierr != kDIErrNone) { + WMSG2(" ASPI DeviceInquiry for '%s' (type=%d) failed\n", + addrString, deviceType); + continue; + } - WMSG4(" Device %s is %s '%s' '%s'\n", - addrString, DeviceTypeToString(deviceType), - inq.vendorID, inq.productID); + WMSG4(" Device %s is %s '%s' '%s'\n", + addrString, DeviceTypeToString(deviceType), + inq.vendorID, inq.productID); - if ((deviceMask & kDevMaskCDROM) != 0 && - deviceType == kScsiDevTypeCDROM) - { - /* found CD-ROM */ - } else if ((deviceMask & kDevMaskHardDrive) != 0 && - deviceType == kScsiDevTypeDASD) - { - /* found hard drive */ - } else - continue; + if ((deviceMask & kDevMaskCDROM) != 0 && + deviceType == kScsiDevTypeCDROM) + { + /* found CD-ROM */ + } else if ((deviceMask & kDevMaskHardDrive) != 0 && + deviceType == kScsiDevTypeDASD) + { + /* found hard drive */ + } else + continue; - if (idx >= kMaxAccessibleDrives) { - WMSG0("GLITCH: ran out of places to stuff CD-ROM drives\n"); - assert(false); - goto done; - } + if (idx >= kMaxAccessibleDrives) { + WMSG0("GLITCH: ran out of places to stuff CD-ROM drives\n"); + assert(false); + goto done; + } - dierr = TestUnitReady(ha, targ, lun, &deviceReady); - if (dierr != kDIErrNone) { - WMSG1(" ASPI TestUnitReady for '%s' failed\n", addrString); - continue; - } + dierr = TestUnitReady(ha, targ, lun, &deviceReady); + if (dierr != kDIErrNone) { + WMSG1(" ASPI TestUnitReady for '%s' failed\n", addrString); + continue; + } - deviceArray[idx].Init(ha, targ, lun, inq.vendorID, - inq.productID, deviceType, deviceReady); - idx++; - } - } - } + deviceArray[idx].Init(ha, targ, lun, inq.vendorID, + inq.productID, deviceType, deviceReady); + idx++; + } + } + } done: - *ppDeviceArray = deviceArray; - *pNumDevices = idx; - return kDIErrNone; + *ppDeviceArray = deviceArray; + *pNumDevices = idx; + return kDIErrNone; } #endif /*_WIN32*/ diff --git a/diskimg/ASPI.h b/diskimg/ASPI.h index 3384304..42375e0 100644 --- a/diskimg/ASPI.h +++ b/diskimg/ASPI.h @@ -29,7 +29,7 @@ namespace DiskImgLib { #ifndef __WNASPI32_H__ -struct SRB_ExecSCSICmd; // fwd +struct SRB_ExecSCSICmd; // fwd #endif namespace DiskImgLib { @@ -39,55 +39,55 @@ namespace DiskImgLib { */ class DISKIMG_API ASPIDevice { public: - ASPIDevice(void) : fVendorID(nil), fProductID(nil), - fAdapter(0xff), fTarget(0xff), fLun(0xff), fDeviceReady(false) - {} - virtual ~ASPIDevice(void) { - delete[] fVendorID; - delete[] fProductID; - } + ASPIDevice(void) : fVendorID(nil), fProductID(nil), + fAdapter(0xff), fTarget(0xff), fLun(0xff), fDeviceReady(false) + {} + virtual ~ASPIDevice(void) { + delete[] fVendorID; + delete[] fProductID; + } - void Init(unsigned char adapter, unsigned char target, unsigned char lun, - const unsigned char* vendor, unsigned const char* product, - int deviceType, bool ready) - { - fAdapter = adapter; - fTarget = target; - fLun = lun; - assert(fVendorID == nil); - fVendorID = new char[strlen((const char*)vendor)+1]; - strcpy(fVendorID, (const char*)vendor); - assert(fProductID == nil); - fProductID = new char[strlen((const char*)product)+1]; - strcpy(fProductID, (const char*)product); - fDeviceReady = ready; - fDeviceType = deviceType; - } + void Init(unsigned char adapter, unsigned char target, unsigned char lun, + const unsigned char* vendor, unsigned const char* product, + int deviceType, bool ready) + { + fAdapter = adapter; + fTarget = target; + fLun = lun; + assert(fVendorID == nil); + fVendorID = new char[strlen((const char*)vendor)+1]; + strcpy(fVendorID, (const char*)vendor); + assert(fProductID == nil); + fProductID = new char[strlen((const char*)product)+1]; + strcpy(fProductID, (const char*)product); + fDeviceReady = ready; + fDeviceType = deviceType; + } - enum { - kTypeDASD = 0, // kScsiDevTypeDASD - kTypeCDROM = 5, // kScsiDevTypeCDROM - }; + enum { + kTypeDASD = 0, // kScsiDevTypeDASD + kTypeCDROM = 5, // kScsiDevTypeCDROM + }; - unsigned char GetAdapter(void) const { return fAdapter; } - unsigned char GetTarget(void) const { return fTarget; } - unsigned char GetLun(void) const { return fLun; } - const char* GetVendorID(void) const { return fVendorID; } - const char* GetProductID(void) const { return fProductID; } - bool GetDeviceReady(void) const { return fDeviceReady; } - int GetDeviceType(void) const { return fDeviceType; } + unsigned char GetAdapter(void) const { return fAdapter; } + unsigned char GetTarget(void) const { return fTarget; } + unsigned char GetLun(void) const { return fLun; } + const char* GetVendorID(void) const { return fVendorID; } + const char* GetProductID(void) const { return fProductID; } + bool GetDeviceReady(void) const { return fDeviceReady; } + int GetDeviceType(void) const { return fDeviceType; } private: - // strings from SCSI inquiry, padded with spaces at end - char* fVendorID; - char* fProductID; + // strings from SCSI inquiry, padded with spaces at end + char* fVendorID; + char* fProductID; - unsigned char fAdapter; // physical or logical host adapter (0-15) - unsigned char fTarget; // SCSI ID on adapter (0-15) - unsigned char fLun; // logical unit (0-7) + unsigned char fAdapter; // physical or logical host adapter (0-15) + unsigned char fTarget; // SCSI ID on adapter (0-15) + unsigned char fLun; // logical unit (0-7) - int fDeviceType; // e.g. kScsiDevTypeCDROM - bool fDeviceReady; + int fDeviceType; // e.g. kScsiDevTypeCDROM + bool fDeviceReady; }; /* @@ -97,99 +97,99 @@ private: */ class DISKIMG_API ASPI { public: - ASPI(void) : - fhASPI(nil), - GetASPI32SupportInfo(nil), - SendASPI32Command(nil), - GetASPI32DLLVersion(nil), - fASPIVersion(0), - fHostAdapterCount(-1) - {} - virtual ~ASPI(void); + ASPI(void) : + fhASPI(nil), + GetASPI32SupportInfo(nil), + SendASPI32Command(nil), + GetASPI32DLLVersion(nil), + fASPIVersion(0), + fHostAdapterCount(-1) + {} + virtual ~ASPI(void); - // load ASPI DLL if it exists - DIError Init(void); + // load ASPI DLL if it exists + DIError Init(void); - // return the version returned by the loaded DLL - DWORD GetVersion(void) const { - assert(fhASPI != nil); - return fASPIVersion; - } + // return the version returned by the loaded DLL + DWORD GetVersion(void) const { + assert(fhASPI != nil); + return fASPIVersion; + } - // Return an *array* of ASPIDevice structures for drives in system; - // the caller is expected to delete[] it when done. - enum { kDevMaskCDROM = 0x01, kDevMaskHardDrive = 0x02 }; - DIError GetAccessibleDevices(int deviceMask, ASPIDevice** ppDeviceArray, - int* pNumDevices); + // Return an *array* of ASPIDevice structures for drives in system; + // the caller is expected to delete[] it when done. + enum { kDevMaskCDROM = 0x01, kDevMaskHardDrive = 0x02 }; + DIError GetAccessibleDevices(int deviceMask, ASPIDevice** ppDeviceArray, + int* pNumDevices); - // Get the type of the device (DTYPE_*, 0x00-0x1f) using ASPI query - DIError GetDeviceType(unsigned char adapter, unsigned char target, - unsigned char lun, unsigned char* pType); - // convert DTYPE_* to a string - const char* DeviceTypeToString(unsigned char deviceType); + // Get the type of the device (DTYPE_*, 0x00-0x1f) using ASPI query + DIError GetDeviceType(unsigned char adapter, unsigned char target, + unsigned char lun, unsigned char* pType); + // convert DTYPE_* to a string + const char* DeviceTypeToString(unsigned char deviceType); - // Get the capacity, expressed as the highest-available LBA and the device - // block size. - DIError GetDeviceCapacity(unsigned char adapter, unsigned char target, - unsigned char lun, unsigned long* pLastBlock, unsigned long* pBlockSize); + // Get the capacity, expressed as the highest-available LBA and the device + // block size. + DIError GetDeviceCapacity(unsigned char adapter, unsigned char target, + unsigned char lun, unsigned long* pLastBlock, unsigned long* pBlockSize); - // Read blocks from the device. - DIError ReadBlocks(unsigned char adapter, unsigned char target, - unsigned char lun, long startBlock, short numBlocks, long blockSize, - void* buf); + // Read blocks from the device. + DIError ReadBlocks(unsigned char adapter, unsigned char target, + unsigned char lun, long startBlock, short numBlocks, long blockSize, + void* buf); - // Write blocks to the device. - DIError WriteBlocks(unsigned char adapter, unsigned char target, - unsigned char lun, long startBlock, short numBlocks, long blockSize, - const void* buf); + // Write blocks to the device. + DIError WriteBlocks(unsigned char adapter, unsigned char target, + unsigned char lun, long startBlock, short numBlocks, long blockSize, + const void* buf); private: - /* - * The interesting bits that come out of an SC_HA_INQUIRY request. - */ - typedef struct AdapterInfo { - unsigned char adapterScsiID; // SCSI ID of the adapter itself - unsigned char managerID[16+1]; // string describing manager - unsigned char identifier[16+1]; // string describing host adapter - unsigned char maxTargets; // max #of targets on this adapter - unsigned short bufferAlignment; // buffer alignment requirement - } AdapterInfo; - /* - * The interesting bits from a SCSI device INQUIRY command. - */ - typedef struct Inquiry { - unsigned char vendorID[8+1]; // vendor ID string - unsigned char productID[16+1]; // product ID string - unsigned char productRevision[4]; // product revision bytes - } Inquiry; + /* + * The interesting bits that come out of an SC_HA_INQUIRY request. + */ + typedef struct AdapterInfo { + unsigned char adapterScsiID; // SCSI ID of the adapter itself + unsigned char managerID[16+1]; // string describing manager + unsigned char identifier[16+1]; // string describing host adapter + unsigned char maxTargets; // max #of targets on this adapter + unsigned short bufferAlignment; // buffer alignment requirement + } AdapterInfo; + /* + * The interesting bits from a SCSI device INQUIRY command. + */ + typedef struct Inquiry { + unsigned char vendorID[8+1]; // vendor ID string + unsigned char productID[16+1]; // product ID string + unsigned char productRevision[4]; // product revision bytes + } Inquiry; - // Issue an ASPI adapter inquiry request. - DIError HostAdapterInquiry(unsigned char adapter, - AdapterInfo* pAdapterInfo); - // Issue a SCSI device inquiry request. - DIError DeviceInquiry(unsigned char adapter, unsigned char target, - unsigned char lun, Inquiry* pInquiry); - // Issue a SCSI test unit ready request. - DIError TestUnitReady(unsigned char adapter, unsigned char target, - unsigned char lun, bool* pReady); - // execute a SCSI command - DIError ExecSCSICommand(SRB_ExecSCSICmd* pSRB); + // Issue an ASPI adapter inquiry request. + DIError HostAdapterInquiry(unsigned char adapter, + AdapterInfo* pAdapterInfo); + // Issue a SCSI device inquiry request. + DIError DeviceInquiry(unsigned char adapter, unsigned char target, + unsigned char lun, Inquiry* pInquiry); + // Issue a SCSI test unit ready request. + DIError TestUnitReady(unsigned char adapter, unsigned char target, + unsigned char lun, bool* pReady); + // execute a SCSI command + DIError ExecSCSICommand(SRB_ExecSCSICmd* pSRB); - enum { - kMaxAdapters = 16, - kMaxTargets = 16, - kMaxLuns = 8, - kTimeout = 30, // timeout, in seconds - kMaxAccessibleDrives = 16, - }; + enum { + kMaxAdapters = 16, + kMaxTargets = 16, + kMaxLuns = 8, + kTimeout = 30, // timeout, in seconds + kMaxAccessibleDrives = 16, + }; - HMODULE fhASPI; - DWORD (*GetASPI32SupportInfo)(void); - DWORD (*SendASPI32Command)(void* lpsrb); - DWORD (*GetASPI32DLLVersion)(void); - DWORD fASPIVersion; - int fHostAdapterCount; + HMODULE fhASPI; + DWORD (*GetASPI32SupportInfo)(void); + DWORD (*SendASPI32Command)(void* lpsrb); + DWORD (*GetASPI32DLLVersion)(void); + DWORD fASPIVersion; + int fHostAdapterCount; }; }; // namespace DiskImgLib diff --git a/diskimg/CFFA.cpp b/diskimg/CFFA.cpp index c0a0c8c..e1123fe 100644 --- a/diskimg/CFFA.cpp +++ b/diskimg/CFFA.cpp @@ -52,304 +52,304 @@ */ /*static*/ DIError DiskFSCFFA::TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder, - DiskImg::FSFormat* pFormatFound) + DiskImg::FSFormat* pFormatFound) { - DIError dierr; - long totalBlocks = pImg->GetNumBlocks(); - long startBlock, maxBlocks, totalBlocksLeft; - long fsNumBlocks; - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; - //bool fiveIs32MB; + DIError dierr; + long totalBlocks = pImg->GetNumBlocks(); + long startBlock, maxBlocks, totalBlocksLeft; + long fsNumBlocks; + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; + //bool fiveIs32MB; - assert(totalBlocks > kEarlyVolExpectedSize); + assert(totalBlocks > kEarlyVolExpectedSize); - // could be "generic" from an earlier override - if (*pFormatFound != DiskImg::kFormatCFFA4 && - *pFormatFound != DiskImg::kFormatCFFA8) - { - *pFormatFound = DiskImg::kFormatUnknown; - } + // could be "generic" from an earlier override + if (*pFormatFound != DiskImg::kFormatCFFA4 && + *pFormatFound != DiskImg::kFormatCFFA8) + { + *pFormatFound = DiskImg::kFormatUnknown; + } - WMSG1("----- BEGIN CFFA SCAN (fmt=%d) -----\n", *pFormatFound); + WMSG1("----- BEGIN CFFA SCAN (fmt=%d) -----\n", *pFormatFound); - startBlock = 0; - totalBlocksLeft = totalBlocks; + startBlock = 0; + totalBlocksLeft = totalBlocks; - /* - * Look for a 32MB ProDOS or HFS volume in the first slot. If we - * don't find this, it's probably not CFFA. It's possible they just - * didn't format the first one, but that seems unlikely, and it's not - * unreasonable to insist that they format the first partition. - */ - maxBlocks = totalBlocksLeft; - if (maxBlocks > kEarlyVolExpectedSize) - maxBlocks = kEarlyVolExpectedSize; + /* + * Look for a 32MB ProDOS or HFS volume in the first slot. If we + * don't find this, it's probably not CFFA. It's possible they just + * didn't format the first one, but that seems unlikely, and it's not + * unreasonable to insist that they format the first partition. + */ + maxBlocks = totalBlocksLeft; + if (maxBlocks > kEarlyVolExpectedSize) + maxBlocks = kEarlyVolExpectedSize; - dierr = OpenSubVolume(pImg, startBlock, maxBlocks, true, - &pNewImg, &pNewFS); - if (dierr != kDIErrNone) { - WMSG0(" CFFA failed opening sub-volume #1\n"); - goto bail; - } - fsNumBlocks = pNewFS->GetFSNumBlocks(); - delete pNewFS; - delete pNewImg; - if (fsNumBlocks != kEarlyVolExpectedSize && - fsNumBlocks != kEarlyVolExpectedSize-1) - { - WMSG1(" CFFA found fsNumBlocks=%ld in slot #1\n", fsNumBlocks); - dierr = kDIErrFilesystemNotFound; - goto bail; - } - WMSG0(" CFFA found good volume in slot #1\n"); + dierr = OpenSubVolume(pImg, startBlock, maxBlocks, true, + &pNewImg, &pNewFS); + if (dierr != kDIErrNone) { + WMSG0(" CFFA failed opening sub-volume #1\n"); + goto bail; + } + fsNumBlocks = pNewFS->GetFSNumBlocks(); + delete pNewFS; + delete pNewImg; + if (fsNumBlocks != kEarlyVolExpectedSize && + fsNumBlocks != kEarlyVolExpectedSize-1) + { + WMSG1(" CFFA found fsNumBlocks=%ld in slot #1\n", fsNumBlocks); + dierr = kDIErrFilesystemNotFound; + goto bail; + } + WMSG0(" CFFA found good volume in slot #1\n"); - startBlock += maxBlocks; - totalBlocksLeft -= maxBlocks; - assert(totalBlocksLeft > 0); + startBlock += maxBlocks; + totalBlocksLeft -= maxBlocks; + assert(totalBlocksLeft > 0); - /* - * Look for a ProDOS or HFS volume <= 32MB in the second slot. If - * we don't find something here, and this is a 64MB card, then there's - * no advantage to using CFFA (in fact, the single-volume handling may - * be more convenient). If there's at least another 32MB, we continue - * looking. - */ - maxBlocks = totalBlocksLeft; - if (maxBlocks > kEarlyVolExpectedSize) - maxBlocks = kEarlyVolExpectedSize; + /* + * Look for a ProDOS or HFS volume <= 32MB in the second slot. If + * we don't find something here, and this is a 64MB card, then there's + * no advantage to using CFFA (in fact, the single-volume handling may + * be more convenient). If there's at least another 32MB, we continue + * looking. + */ + maxBlocks = totalBlocksLeft; + if (maxBlocks > kEarlyVolExpectedSize) + maxBlocks = kEarlyVolExpectedSize; - dierr = OpenSubVolume(pImg, startBlock, maxBlocks, true, - &pNewImg, &pNewFS); - if (dierr != kDIErrNone) { - WMSG0(" CFFA failed opening sub-volume #2\n"); - if (maxBlocks < kEarlyVolExpectedSize) - goto bail; - // otherwise, assume they just didn't format #2, and keep going - } else { - fsNumBlocks = pNewFS->GetFSNumBlocks(); - delete pNewFS; - delete pNewImg; + dierr = OpenSubVolume(pImg, startBlock, maxBlocks, true, + &pNewImg, &pNewFS); + if (dierr != kDIErrNone) { + WMSG0(" CFFA failed opening sub-volume #2\n"); + if (maxBlocks < kEarlyVolExpectedSize) + goto bail; + // otherwise, assume they just didn't format #2, and keep going + } else { + fsNumBlocks = pNewFS->GetFSNumBlocks(); + delete pNewFS; + delete pNewImg; #if 0 - if (fsNumBlocks != kEarlyVolExpectedSize && - fsNumBlocks != kEarlyVolExpectedSize-1) - { - WMSG1(" CFFA found fsNumBlocks=%ld in slot #2\n", fsNumBlocks); - dierr = kDIErrFilesystemNotFound; - goto bail; - } + if (fsNumBlocks != kEarlyVolExpectedSize && + fsNumBlocks != kEarlyVolExpectedSize-1) + { + WMSG1(" CFFA found fsNumBlocks=%ld in slot #2\n", fsNumBlocks); + dierr = kDIErrFilesystemNotFound; + goto bail; + } #endif - WMSG0(" CFFA found good volume in slot #2\n"); - } + WMSG0(" CFFA found good volume in slot #2\n"); + } - startBlock += maxBlocks; - totalBlocksLeft -= maxBlocks; - if (totalBlocksLeft == 0) { - *pFormatFound = DiskImg::kFormatCFFA4; - goto bail; - } + startBlock += maxBlocks; + totalBlocksLeft -= maxBlocks; + if (totalBlocksLeft == 0) { + *pFormatFound = DiskImg::kFormatCFFA4; + goto bail; + } - /* - * Skip #3 and #4. - */ - WMSG0(" CFFA skipping over slot #3\n"); - maxBlocks = kEarlyVolExpectedSize*2; - if (maxBlocks > totalBlocksLeft) - maxBlocks = totalBlocksLeft; - startBlock += maxBlocks; - totalBlocksLeft -= maxBlocks; - if (totalBlocksLeft == 0) { - // no more partitions to find; we're done - *pFormatFound = DiskImg::kFormatCFFA4; - goto bail; - } - WMSG0(" CFFA skipping over slot #4\n"); + /* + * Skip #3 and #4. + */ + WMSG0(" CFFA skipping over slot #3\n"); + maxBlocks = kEarlyVolExpectedSize*2; + if (maxBlocks > totalBlocksLeft) + maxBlocks = totalBlocksLeft; + startBlock += maxBlocks; + totalBlocksLeft -= maxBlocks; + if (totalBlocksLeft == 0) { + // no more partitions to find; we're done + *pFormatFound = DiskImg::kFormatCFFA4; + goto bail; + } + WMSG0(" CFFA skipping over slot #4\n"); - /* - * Partition #5. We know where it starts, but not how large it is. - * Could be 32MB, could be 1GB, could be anything between. - * - * CF cards come in power-of-two sizes -- 128MB, 256MB, etc. -- but - * we don't want to make assumptions here. It's possible we're - * looking at an odd-sized image file that some clever person is - * expecting to access with CiderPress. - */ - maxBlocks = totalBlocksLeft; - if (maxBlocks > kOneGB) - maxBlocks = kOneGB; - if (maxBlocks <= kEarlyVolExpectedSize) { - /* - * Only enough room for one <= 32MB volume. Not expected for a - * real CFFA card, unless they come in 160MB sizes. - * - * Treat it like 4-partition; it'll look like somebody slapped a - * 32MB volume into the first 1GB area. - */ - WMSG0(" CFFA assuming odd-sized slot #5\n"); - *pFormatFound = DiskImg::kFormatCFFA4; - goto bail; - } + /* + * Partition #5. We know where it starts, but not how large it is. + * Could be 32MB, could be 1GB, could be anything between. + * + * CF cards come in power-of-two sizes -- 128MB, 256MB, etc. -- but + * we don't want to make assumptions here. It's possible we're + * looking at an odd-sized image file that some clever person is + * expecting to access with CiderPress. + */ + maxBlocks = totalBlocksLeft; + if (maxBlocks > kOneGB) + maxBlocks = kOneGB; + if (maxBlocks <= kEarlyVolExpectedSize) { + /* + * Only enough room for one <= 32MB volume. Not expected for a + * real CFFA card, unless they come in 160MB sizes. + * + * Treat it like 4-partition; it'll look like somebody slapped a + * 32MB volume into the first 1GB area. + */ + WMSG0(" CFFA assuming odd-sized slot #5\n"); + *pFormatFound = DiskImg::kFormatCFFA4; + goto bail; + } - /* - * We could be looking at a 32MB ProDOS partition, 32MB HFS partition, - * or an up to 1GB HFS partition. We have to specify the size in - * the OpenSubVolume request, which means trying it both ways and - * finding a match from GetFSNumBlocks(). Complicating matters is - * truncation (ProDOS max 65535, not 65536) and round-off (not sure - * how HFS deals with left-over blocks). - * - * Start with <= 1GB. - */ - dierr = OpenSubVolume(pImg, startBlock, maxBlocks, true, - &pNewImg, &pNewFS); - if (dierr != kDIErrNone) { - if (dierr == kDIErrCancelled) - goto bail; - WMSG0(" CFFA failed opening large sub-volume #5\n"); - // if we can't get #5, don't bother looking for #6 - // (we could try anyway, but it's easier to just skip it) - dierr = kDIErrNone; - *pFormatFound = DiskImg::kFormatCFFA4; - goto bail; - } + /* + * We could be looking at a 32MB ProDOS partition, 32MB HFS partition, + * or an up to 1GB HFS partition. We have to specify the size in + * the OpenSubVolume request, which means trying it both ways and + * finding a match from GetFSNumBlocks(). Complicating matters is + * truncation (ProDOS max 65535, not 65536) and round-off (not sure + * how HFS deals with left-over blocks). + * + * Start with <= 1GB. + */ + dierr = OpenSubVolume(pImg, startBlock, maxBlocks, true, + &pNewImg, &pNewFS); + if (dierr != kDIErrNone) { + if (dierr == kDIErrCancelled) + goto bail; + WMSG0(" CFFA failed opening large sub-volume #5\n"); + // if we can't get #5, don't bother looking for #6 + // (we could try anyway, but it's easier to just skip it) + dierr = kDIErrNone; + *pFormatFound = DiskImg::kFormatCFFA4; + goto bail; + } - fsNumBlocks = pNewFS->GetFSNumBlocks(); - delete pNewFS; - delete pNewImg; - if (fsNumBlocks < 2 || fsNumBlocks > maxBlocks) { - WMSG1(" CFFA WARNING: FSNumBlocks #5 reported blocks=%ld\n", - fsNumBlocks); - } - if (fsNumBlocks == kEarlyVolExpectedSize-1 || - fsNumBlocks == kEarlyVolExpectedSize) - { - WMSG0(" CFFA #5 is a 32MB volume\n"); - // tells us nothing -- could still be 4 or 8, so we keep going - maxBlocks = kEarlyVolExpectedSize; - } else if (fsNumBlocks > kEarlyVolExpectedSize) { - // must be a GS/OS 1GB area - WMSG0(" CFFA #5 is larger than 32MB\n"); - *pFormatFound = DiskImg::kFormatCFFA4; - goto bail; - } else { - WMSG1(" CFFA #5 was unexpectedly small (%ld blocks)\n", fsNumBlocks); - // just stop now - *pFormatFound = DiskImg::kFormatCFFA4; - goto bail; - } + fsNumBlocks = pNewFS->GetFSNumBlocks(); + delete pNewFS; + delete pNewImg; + if (fsNumBlocks < 2 || fsNumBlocks > maxBlocks) { + WMSG1(" CFFA WARNING: FSNumBlocks #5 reported blocks=%ld\n", + fsNumBlocks); + } + if (fsNumBlocks == kEarlyVolExpectedSize-1 || + fsNumBlocks == kEarlyVolExpectedSize) + { + WMSG0(" CFFA #5 is a 32MB volume\n"); + // tells us nothing -- could still be 4 or 8, so we keep going + maxBlocks = kEarlyVolExpectedSize; + } else if (fsNumBlocks > kEarlyVolExpectedSize) { + // must be a GS/OS 1GB area + WMSG0(" CFFA #5 is larger than 32MB\n"); + *pFormatFound = DiskImg::kFormatCFFA4; + goto bail; + } else { + WMSG1(" CFFA #5 was unexpectedly small (%ld blocks)\n", fsNumBlocks); + // just stop now + *pFormatFound = DiskImg::kFormatCFFA4; + goto bail; + } - startBlock += maxBlocks; - totalBlocksLeft -= maxBlocks; + startBlock += maxBlocks; + totalBlocksLeft -= maxBlocks; - if (!totalBlocksLeft) { - WMSG0(" CFFA got 5 volumes\n"); - *pFormatFound = DiskImg::kFormatCFFA4; - goto bail; - } + if (!totalBlocksLeft) { + WMSG0(" CFFA got 5 volumes\n"); + *pFormatFound = DiskImg::kFormatCFFA4; + goto bail; + } - /* - * Various possibilities for slots 5 and up: - * A. Card in 4-partition mode. 5th partition isn't formatted. Don't - * bother looking for 6th. [already handled] - * B. Card in 4-partition mode. 5th partition is >32MB HFS. 6th - * partition will be at +1GB. [already handled] - * C. Card in 4-partition mode. 5th partition is 32MB ProDOS. 6th - * partition will be at +1GB. - * D. Card in 8-partition mode. 5th partition is 32MB HFS. 6th - * partition will be at +32MB. - * E. Card in 8-partition mode. 5th partition is 32MB ProDOS. 6th - * partition will be at +32MB. - * - * I'm ignoring D on the off chance somebody could create a 32MB HFS - * partition in the 1GB space. D and E are handled alike. - * - * The difference between C and D/E can *usually* be determined by - * opening up a 6th partition in the two expected locations. - */ - WMSG0(" CFFA probing 6th slot for 4-vs-8\n"); - /* - * Look in two different places. If we find something at the - * +32MB mark, assume it's in "8 mode". If we find something at - * the +1GB mark, assume it's in "4 + GS/OS mode". If both exist - * we have a problem. - */ - bool foundSmall, foundGig; + /* + * Various possibilities for slots 5 and up: + * A. Card in 4-partition mode. 5th partition isn't formatted. Don't + * bother looking for 6th. [already handled] + * B. Card in 4-partition mode. 5th partition is >32MB HFS. 6th + * partition will be at +1GB. [already handled] + * C. Card in 4-partition mode. 5th partition is 32MB ProDOS. 6th + * partition will be at +1GB. + * D. Card in 8-partition mode. 5th partition is 32MB HFS. 6th + * partition will be at +32MB. + * E. Card in 8-partition mode. 5th partition is 32MB ProDOS. 6th + * partition will be at +32MB. + * + * I'm ignoring D on the off chance somebody could create a 32MB HFS + * partition in the 1GB space. D and E are handled alike. + * + * The difference between C and D/E can *usually* be determined by + * opening up a 6th partition in the two expected locations. + */ + WMSG0(" CFFA probing 6th slot for 4-vs-8\n"); + /* + * Look in two different places. If we find something at the + * +32MB mark, assume it's in "8 mode". If we find something at + * the +1GB mark, assume it's in "4 + GS/OS mode". If both exist + * we have a problem. + */ + bool foundSmall, foundGig; - foundSmall = false; - maxBlocks = totalBlocksLeft; - if (maxBlocks > kEarlyVolExpectedSize) - maxBlocks = kEarlyVolExpectedSize; - dierr = OpenSubVolume(pImg, startBlock + kEarlyVolExpectedSize, - maxBlocks, true, &pNewImg, &pNewFS); - if (dierr != kDIErrNone) { - if (dierr == kDIErrCancelled) - goto bail; - WMSG0(" CFFA no vol #6 found at +32MB\n"); - } else { - foundSmall = true; - delete pNewFS; - delete pNewImg; - } + foundSmall = false; + maxBlocks = totalBlocksLeft; + if (maxBlocks > kEarlyVolExpectedSize) + maxBlocks = kEarlyVolExpectedSize; + dierr = OpenSubVolume(pImg, startBlock + kEarlyVolExpectedSize, + maxBlocks, true, &pNewImg, &pNewFS); + if (dierr != kDIErrNone) { + if (dierr == kDIErrCancelled) + goto bail; + WMSG0(" CFFA no vol #6 found at +32MB\n"); + } else { + foundSmall = true; + delete pNewFS; + delete pNewImg; + } - foundGig = false; - // no need to look if we don't have at least 1GB left! - if (totalBlocksLeft >= kOneGB) { - maxBlocks = totalBlocksLeft; - if (maxBlocks > kOneGB) - maxBlocks = kOneGB; - dierr = OpenSubVolume(pImg, startBlock + kOneGB, - maxBlocks, true, &pNewImg, &pNewFS); - if (dierr != kDIErrNone) { - if (dierr == kDIErrCancelled) - goto bail; - WMSG0(" CFFA no vol #6 found at +1GB\n"); - } else { - foundGig = true; - delete pNewFS; - delete pNewImg; - } - } + foundGig = false; + // no need to look if we don't have at least 1GB left! + if (totalBlocksLeft >= kOneGB) { + maxBlocks = totalBlocksLeft; + if (maxBlocks > kOneGB) + maxBlocks = kOneGB; + dierr = OpenSubVolume(pImg, startBlock + kOneGB, + maxBlocks, true, &pNewImg, &pNewFS); + if (dierr != kDIErrNone) { + if (dierr == kDIErrCancelled) + goto bail; + WMSG0(" CFFA no vol #6 found at +1GB\n"); + } else { + foundGig = true; + delete pNewFS; + delete pNewImg; + } + } - dierr = kDIErrNone; + dierr = kDIErrNone; - if (!foundSmall && !foundGig) { - WMSG0(" CFFA no valid filesystem found in 6th position\n"); - *pFormatFound = DiskImg::kFormatCFFA4; - // don't bother looking for 7 and 8 - } else if (foundSmall && foundGig) { - WMSG0(" CFFA WARNING: found valid volumes at +32MB *and* +1GB\n"); - // default to 4-partition mode - if (*pFormatFound == DiskImg::kFormatUnknown) - *pFormatFound = DiskImg::kFormatCFFA4; - } else if (foundGig) { - WMSG0(" CFFA found 6th volume at +1GB, assuming 4-mode w/GSOS\n"); - if (fsNumBlocks < 2 || fsNumBlocks > kOneGB) { - WMSG1(" CFFA WARNING: FSNumBlocks #6 reported as %ld\n", - fsNumBlocks); - } - *pFormatFound = DiskImg::kFormatCFFA4; - } else if (foundSmall) { - WMSG0(" CFFA found 6th volume at +32MB, assuming 8-mode\n"); - if (fsNumBlocks < 2 || fsNumBlocks > kEarlyVolExpectedSize) { - WMSG1(" CFFA WARNING: FSNumBlocks #6 reported as %ld\n", - fsNumBlocks); - } - *pFormatFound = DiskImg::kFormatCFFA8; - } else { - assert(false); // how'd we get here?? - } + if (!foundSmall && !foundGig) { + WMSG0(" CFFA no valid filesystem found in 6th position\n"); + *pFormatFound = DiskImg::kFormatCFFA4; + // don't bother looking for 7 and 8 + } else if (foundSmall && foundGig) { + WMSG0(" CFFA WARNING: found valid volumes at +32MB *and* +1GB\n"); + // default to 4-partition mode + if (*pFormatFound == DiskImg::kFormatUnknown) + *pFormatFound = DiskImg::kFormatCFFA4; + } else if (foundGig) { + WMSG0(" CFFA found 6th volume at +1GB, assuming 4-mode w/GSOS\n"); + if (fsNumBlocks < 2 || fsNumBlocks > kOneGB) { + WMSG1(" CFFA WARNING: FSNumBlocks #6 reported as %ld\n", + fsNumBlocks); + } + *pFormatFound = DiskImg::kFormatCFFA4; + } else if (foundSmall) { + WMSG0(" CFFA found 6th volume at +32MB, assuming 8-mode\n"); + if (fsNumBlocks < 2 || fsNumBlocks > kEarlyVolExpectedSize) { + WMSG1(" CFFA WARNING: FSNumBlocks #6 reported as %ld\n", + fsNumBlocks); + } + *pFormatFound = DiskImg::kFormatCFFA8; + } else { + assert(false); // how'd we get here?? + } - // done! + // done! bail: - WMSG2("----- END CFFA SCAN (err=%d format=%d) -----\n", - dierr, *pFormatFound); - if (dierr == kDIErrNone) { - assert(*pFormatFound != DiskImg::kFormatUnknown); - } else { - *pFormatFound = DiskImg::kFormatUnknown; - } - return dierr; + WMSG2("----- END CFFA SCAN (err=%d format=%d) -----\n", + dierr, *pFormatFound); + if (dierr == kDIErrNone) { + assert(*pFormatFound != DiskImg::kFormatUnknown); + } else { + *pFormatFound = DiskImg::kFormatUnknown; + } + return dierr; } @@ -361,79 +361,79 @@ bail: */ /*static*/ DIError DiskFSCFFA::OpenSubVolume(DiskImg* pImg, long startBlock, long numBlocks, - bool scanOnly, DiskImg** ppNewImg, DiskFS** ppNewFS) + bool scanOnly, DiskImg** ppNewImg, DiskFS** ppNewFS) { - DIError dierr = kDIErrNone; - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; - - pNewImg = new DiskImg; - if (pNewImg == nil) { - dierr = kDIErrMalloc; - goto bail; - } + DIError dierr = kDIErrNone; + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; + + pNewImg = new DiskImg; + if (pNewImg == nil) { + dierr = kDIErrMalloc; + goto bail; + } - dierr = pNewImg->OpenImage(pImg, startBlock, numBlocks); - if (dierr != kDIErrNone) { - WMSG3(" CFFASub: OpenImage(%ld,%ld) failed (err=%d)\n", - startBlock, numBlocks, dierr); - goto bail; - } - //WMSG2(" +++ CFFASub: new image has ro=%d (parent=%d)\n", - // pNewImg->GetReadOnly(), pImg->GetReadOnly()); + dierr = pNewImg->OpenImage(pImg, startBlock, numBlocks); + if (dierr != kDIErrNone) { + WMSG3(" CFFASub: OpenImage(%ld,%ld) failed (err=%d)\n", + startBlock, numBlocks, dierr); + goto bail; + } + //WMSG2(" +++ CFFASub: new image has ro=%d (parent=%d)\n", + // pNewImg->GetReadOnly(), pImg->GetReadOnly()); - dierr = pNewImg->AnalyzeImage(); - if (dierr != kDIErrNone) { - WMSG1(" CFFASub: analysis failed (err=%d)\n", dierr); - goto bail; - } + dierr = pNewImg->AnalyzeImage(); + if (dierr != kDIErrNone) { + WMSG1(" CFFASub: analysis failed (err=%d)\n", dierr); + goto bail; + } - if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || - pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) - { - WMSG1(" CFFASub: unable to identify filesystem at %ld\n", - startBlock); - dierr = kDIErrUnsupportedFSFmt; - goto bail; - } + if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || + pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) + { + WMSG1(" CFFASub: unable to identify filesystem at %ld\n", + startBlock); + dierr = kDIErrUnsupportedFSFmt; + goto bail; + } - /* open a DiskFS for the sub-image */ - WMSG2(" CFFASub (%ld,%ld) analyze succeeded!\n", startBlock, numBlocks); - pNewFS = pNewImg->OpenAppropriateDiskFS(); - if (pNewFS == nil) { - WMSG0(" CFFASub: OpenAppropriateDiskFS failed\n"); - dierr = kDIErrUnsupportedFSFmt; - goto bail; - } + /* open a DiskFS for the sub-image */ + WMSG2(" CFFASub (%ld,%ld) analyze succeeded!\n", startBlock, numBlocks); + pNewFS = pNewImg->OpenAppropriateDiskFS(); + if (pNewFS == nil) { + WMSG0(" CFFASub: OpenAppropriateDiskFS failed\n"); + dierr = kDIErrUnsupportedFSFmt; + goto bail; + } - /* we encapsulate arbitrary stuff, so encourage child to scan */ - pNewFS->SetScanForSubVolumes(kScanSubEnabled); + /* we encapsulate arbitrary stuff, so encourage child to scan */ + pNewFS->SetScanForSubVolumes(kScanSubEnabled); - /* - * Load the files from the sub-image. When doing our initial tests, - * or when loading data for the volume copier, we don't want to dig - * into our sub-volumes, just figure out what they are and where. - */ - InitMode initMode; - if (scanOnly) - initMode = kInitHeaderOnly; - else - initMode = kInitFull; - dierr = pNewFS->Initialize(pNewImg, initMode); - if (dierr != kDIErrNone) { - WMSG1(" CFFASub: error %d reading list of files from disk\n", dierr); - goto bail; - } + /* + * Load the files from the sub-image. When doing our initial tests, + * or when loading data for the volume copier, we don't want to dig + * into our sub-volumes, just figure out what they are and where. + */ + InitMode initMode; + if (scanOnly) + initMode = kInitHeaderOnly; + else + initMode = kInitFull; + dierr = pNewFS->Initialize(pNewImg, initMode); + if (dierr != kDIErrNone) { + WMSG1(" CFFASub: error %d reading list of files from disk\n", dierr); + goto bail; + } bail: - if (dierr != kDIErrNone) { - delete pNewFS; - delete pNewImg; - } else { - *ppNewImg = pNewImg; - *ppNewFS = pNewFS; - } - return dierr; + if (dierr != kDIErrNone) { + delete pNewFS; + delete pNewImg; + } else { + *ppNewImg = pNewImg; + *ppNewFS = pNewFS; + } + return dierr; } /* @@ -441,26 +441,26 @@ bail: */ /*static*/ DIError DiskFSCFFA::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency) + DiskImg::FSFormat* pFormat, FSLeniency leniency) { - if (pImg->GetNumBlocks() < kMinInterestingBlocks) - return kDIErrFilesystemNotFound; - if (pImg->GetIsEmbedded()) // don't look for CFFA inside CFFA! - return kDIErrFilesystemNotFound; + if (pImg->GetNumBlocks() < kMinInterestingBlocks) + return kDIErrFilesystemNotFound; + if (pImg->GetIsEmbedded()) // don't look for CFFA inside CFFA! + return kDIErrFilesystemNotFound; - /* assume ProDOS -- shouldn't matter, since it's embedded */ - if (TestImage(pImg, DiskImg::kSectorOrderProDOS, pFormat) == kDIErrNone) { - assert(*pFormat == DiskImg::kFormatCFFA4 || - *pFormat == DiskImg::kFormatCFFA8); - *pOrder = DiskImg::kSectorOrderProDOS; - return kDIErrNone; - } + /* assume ProDOS -- shouldn't matter, since it's embedded */ + if (TestImage(pImg, DiskImg::kSectorOrderProDOS, pFormat) == kDIErrNone) { + assert(*pFormat == DiskImg::kFormatCFFA4 || + *pFormat == DiskImg::kFormatCFFA8); + *pOrder = DiskImg::kSectorOrderProDOS; + return kDIErrNone; + } - // make sure we didn't tamper with it - assert(*pFormat == DiskImg::kFormatUnknown); + // make sure we didn't tamper with it + assert(*pFormat == DiskImg::kFormatUnknown); - WMSG0(" FS didn't find valid CFFA\n"); - return kDIErrFilesystemNotFound; + WMSG0(" FS didn't find valid CFFA\n"); + return kDIErrFilesystemNotFound; } @@ -470,21 +470,21 @@ DiskFSCFFA::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DIError DiskFSCFFA::Initialize(void) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - WMSG1("CFFA initializing (scanForSub=%d)\n", fScanForSubVolumes); + WMSG1("CFFA initializing (scanForSub=%d)\n", fScanForSubVolumes); - /* seems pointless *not* to, but we just do what we're told */ - if (fScanForSubVolumes != kScanSubDisabled) { - dierr = FindSubVolumes(); - if (dierr != kDIErrNone) - return dierr; - } + /* seems pointless *not* to, but we just do what we're told */ + if (fScanForSubVolumes != kScanSubDisabled) { + dierr = FindSubVolumes(); + if (dierr != kDIErrNone) + return dierr; + } - /* blank out the volume usage map */ - SetVolumeUsageMap(); + /* blank out the volume usage map */ + SetVolumeUsageMap(); - return dierr; + return dierr; } @@ -497,44 +497,44 @@ DiskFSCFFA::Initialize(void) DIError DiskFSCFFA::FindSubVolumes(void) { - DIError dierr; - long startBlock, blocksLeft; + DIError dierr; + long startBlock, blocksLeft; - startBlock = 0; - blocksLeft = fpImg->GetNumBlocks(); + startBlock = 0; + blocksLeft = fpImg->GetNumBlocks(); - if (fpImg->GetFSFormat() == DiskImg::kFormatCFFA4) { - WMSG0(" CFFA opening 4+2 volumes\n"); - dierr = AddVolumeSeries(0, 4, kEarlyVolExpectedSize, /*ref*/startBlock, - /*ref*/blocksLeft); - if (dierr != kDIErrNone) - goto bail; + if (fpImg->GetFSFormat() == DiskImg::kFormatCFFA4) { + WMSG0(" CFFA opening 4+2 volumes\n"); + dierr = AddVolumeSeries(0, 4, kEarlyVolExpectedSize, /*ref*/startBlock, + /*ref*/blocksLeft); + if (dierr != kDIErrNone) + goto bail; - WMSG2(" CFFA after first 4, startBlock=%ld blocksLeft=%ld\n", - startBlock, blocksLeft); - if (blocksLeft > 0) { - dierr = AddVolumeSeries(4, 2, kOneGB, /*ref*/startBlock, - /*ref*/blocksLeft); - if (dierr != kDIErrNone) - goto bail; - } - } else if (fpImg->GetFSFormat() == DiskImg::kFormatCFFA8) { - WMSG0(" CFFA opening 8 volumes\n"); - dierr = AddVolumeSeries(0, 8, kEarlyVolExpectedSize, /*ref*/startBlock, - /*ref*/blocksLeft); - if (dierr != kDIErrNone) - goto bail; - } else { - assert(false); - return kDIErrInternal; - } + WMSG2(" CFFA after first 4, startBlock=%ld blocksLeft=%ld\n", + startBlock, blocksLeft); + if (blocksLeft > 0) { + dierr = AddVolumeSeries(4, 2, kOneGB, /*ref*/startBlock, + /*ref*/blocksLeft); + if (dierr != kDIErrNone) + goto bail; + } + } else if (fpImg->GetFSFormat() == DiskImg::kFormatCFFA8) { + WMSG0(" CFFA opening 8 volumes\n"); + dierr = AddVolumeSeries(0, 8, kEarlyVolExpectedSize, /*ref*/startBlock, + /*ref*/blocksLeft); + if (dierr != kDIErrNone) + goto bail; + } else { + assert(false); + return kDIErrInternal; + } - if (blocksLeft != 0) { - WMSG1(" CFFA ignoring leftover %ld blocks\n", blocksLeft); - } + if (blocksLeft != 0) { + WMSG1(" CFFA ignoring leftover %ld blocks\n", blocksLeft); + } bail: - return dierr; + return dierr; } /* @@ -544,54 +544,54 @@ bail: */ DIError DiskFSCFFA::AddVolumeSeries(int start, int count, long blocksPerVolume, - long& startBlock, long& totalBlocksLeft) + long& startBlock, long& totalBlocksLeft) { - DIError dierr = kDIErrNone; - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; - long maxBlocks, fsNumBlocks; - bool scanOnly = false; + DIError dierr = kDIErrNone; + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; + long maxBlocks, fsNumBlocks; + bool scanOnly = false; - /* used by volume copier, to avoid deep scan */ - if (GetScanForSubVolumes() == kScanSubContainerOnly) - scanOnly = true; + /* used by volume copier, to avoid deep scan */ + if (GetScanForSubVolumes() == kScanSubContainerOnly) + scanOnly = true; - for (int i = start; i < start+count; i++) { - maxBlocks = blocksPerVolume; - if (maxBlocks > totalBlocksLeft) - maxBlocks = totalBlocksLeft; + for (int i = start; i < start+count; i++) { + maxBlocks = blocksPerVolume; + if (maxBlocks > totalBlocksLeft) + maxBlocks = totalBlocksLeft; - dierr = OpenSubVolume(fpImg, startBlock, maxBlocks, scanOnly, - &pNewImg, &pNewFS); - if (dierr != kDIErrNone) { - if (dierr == kDIErrCancelled) - goto bail; - WMSG1(" CFFA failed opening sub-volume %d (not formatted?)\n", i); - /* create a fake one to represent the partition */ - dierr = CreatePlaceholder(startBlock, maxBlocks, NULL, NULL, - &pNewImg, &pNewFS); - if (dierr == kDIErrNone) { - AddSubVolumeToList(pNewImg, pNewFS); - } else { - WMSG3(" CFFA unable to create placeholder (%ld, %ld) (err=%d)\n", - startBlock, maxBlocks, dierr); - goto bail; - } - } else { - fsNumBlocks = pNewFS->GetFSNumBlocks(); - if (fsNumBlocks < 2 || fsNumBlocks > blocksPerVolume) { - WMSG2(" CFFA WARNING: FSNumBlocks #%d reported as %ld\n", - i, fsNumBlocks); - } - AddSubVolumeToList(pNewImg, pNewFS); - } + dierr = OpenSubVolume(fpImg, startBlock, maxBlocks, scanOnly, + &pNewImg, &pNewFS); + if (dierr != kDIErrNone) { + if (dierr == kDIErrCancelled) + goto bail; + WMSG1(" CFFA failed opening sub-volume %d (not formatted?)\n", i); + /* create a fake one to represent the partition */ + dierr = CreatePlaceholder(startBlock, maxBlocks, NULL, NULL, + &pNewImg, &pNewFS); + if (dierr == kDIErrNone) { + AddSubVolumeToList(pNewImg, pNewFS); + } else { + WMSG3(" CFFA unable to create placeholder (%ld, %ld) (err=%d)\n", + startBlock, maxBlocks, dierr); + goto bail; + } + } else { + fsNumBlocks = pNewFS->GetFSNumBlocks(); + if (fsNumBlocks < 2 || fsNumBlocks > blocksPerVolume) { + WMSG2(" CFFA WARNING: FSNumBlocks #%d reported as %ld\n", + i, fsNumBlocks); + } + AddSubVolumeToList(pNewImg, pNewFS); + } - startBlock += maxBlocks; - totalBlocksLeft -= maxBlocks; - if (!totalBlocksLeft) - break; // all done - } + startBlock += maxBlocks; + totalBlocksLeft -= maxBlocks; + if (!totalBlocksLeft) + break; // all done + } bail: - return dierr; + return dierr; } diff --git a/diskimg/CPM.cpp b/diskimg/CPM.cpp index 6f970f9..979d453 100644 --- a/diskimg/CPM.cpp +++ b/diskimg/CPM.cpp @@ -7,11 +7,11 @@ * Apple II CP/M disk format. * * Limitations: - * - Read-only. - * - Does not do much with user numbers. - * - Rumor has it that "sparse" files are possible. Not handled. - * - I'm currently treating the directory as fixed-length. This may - * not be correct. + * - Read-only. + * - Does not do much with user numbers. + * - Rumor has it that "sparse" files are possible. Not handled. + * - I'm currently treating the directory as fixed-length. This may + * not be correct. * - Not handling special entries (volume label, date stamps, * password control). * @@ -24,17 +24,17 @@ /* * =========================================================================== - * DiskFSCPM + * DiskFSCPM * =========================================================================== */ -const int kBlkSize = 512; // really ought to be 1024 -const int kVolDirBlock = 24; // track 3 sector 0 -const int kVolDirCount = 4; // 4 prodos blocks +const int kBlkSize = 512; // really ought to be 1024 +const int kVolDirBlock = 24; // track 3 sector 0 +const int kVolDirCount = 4; // 4 prodos blocks const int kNoDataByte = 0xe5; -const int kMaxUserNumber = 31; // 0-15 on some systems, 0-31 on others -const int kMaxSpecialUserNumber = 0x21; // 0x20 and 0x21 have special meanings -const int kMaxExtent = 31; // extent counter, 0-31 +const int kMaxUserNumber = 31; // 0-15 on some systems, 0-31 on others +const int kMaxSpecialUserNumber = 0x21; // 0x20 and 0x21 have special meanings +const int kMaxExtent = 31; // extent counter, 0-31 /* * See if this looks like a CP/M volume. @@ -44,55 +44,55 @@ const int kMaxExtent = 31; // extent counter, 0-31 static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder) { - DIError dierr = kDIErrNone; - unsigned char dirBuf[kBlkSize * kVolDirCount]; - unsigned char* dptr; - int i; + DIError dierr = kDIErrNone; + unsigned char dirBuf[kBlkSize * kVolDirCount]; + unsigned char* dptr; + int i; - assert(sizeof(dirBuf) == DiskFSCPM::kFullDirSize); + assert(sizeof(dirBuf) == DiskFSCPM::kFullDirSize); - for (i = 0; i < kVolDirCount; i++) { - dierr = pImg->ReadBlockSwapped(kVolDirBlock + i, dirBuf + kBlkSize*i, - imageOrder, DiskImg::kSectorOrderCPM); - if (dierr != kDIErrNone) - goto bail; - } + for (i = 0; i < kVolDirCount; i++) { + dierr = pImg->ReadBlockSwapped(kVolDirBlock + i, dirBuf + kBlkSize*i, + imageOrder, DiskImg::kSectorOrderCPM); + if (dierr != kDIErrNone) + goto bail; + } - dptr = dirBuf; - for (i = 0; i < DiskFSCPM::kFullDirSize/DiskFSCPM::kDirectoryEntryLen; i++) - { - if (*dptr != kNoDataByte) { - /* - * Usually userNumber is 0, but sometimes not. It's expected to - * be < 0x20 for a normal file, may be 0x21 or 0x22 for special - * entries (volume label, date stamps). - */ - if (*dptr > kMaxSpecialUserNumber) { - dierr = kDIErrFilesystemNotFound; - break; - } + dptr = dirBuf; + for (i = 0; i < DiskFSCPM::kFullDirSize/DiskFSCPM::kDirectoryEntryLen; i++) + { + if (*dptr != kNoDataByte) { + /* + * Usually userNumber is 0, but sometimes not. It's expected to + * be < 0x20 for a normal file, may be 0x21 or 0x22 for special + * entries (volume label, date stamps). + */ + if (*dptr > kMaxSpecialUserNumber) { + dierr = kDIErrFilesystemNotFound; + break; + } - /* extent counter, 0-31 */ - if (dptr[12] > kMaxExtent) { - dierr = kDIErrFilesystemNotFound; - break; - } + /* extent counter, 0-31 */ + if (dptr[12] > kMaxExtent) { + dierr = kDIErrFilesystemNotFound; + break; + } - /* check for a valid filename here; high bit may be set on some bytes */ - unsigned char firstLet = *(dptr+1) & 0x7f; - if (firstLet < 0x20) { - dierr = kDIErrFilesystemNotFound; - break; - } - } - dptr += DiskFSCPM::kDirectoryEntryLen; - } - if (dierr == kDIErrNone) { - WMSG1(" CPM found clean directory, imageOrder=%d\n", imageOrder); - } + /* check for a valid filename here; high bit may be set on some bytes */ + unsigned char firstLet = *(dptr+1) & 0x7f; + if (firstLet < 0x20) { + dierr = kDIErrFilesystemNotFound; + break; + } + } + dptr += DiskFSCPM::kDirectoryEntryLen; + } + if (dierr == kDIErrNone) { + WMSG1(" CPM found clean directory, imageOrder=%d\n", imageOrder); + } bail: - return dierr; + return dierr; } /* @@ -114,22 +114,22 @@ DiskFSCPM::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, return kDIErrFilesystemNotFound; } - DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; - - DiskImg::GetSectorOrderArray(ordering, *pOrder); + DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; + + DiskImg::GetSectorOrderArray(ordering, *pOrder); - for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { - if (ordering[i] == DiskImg::kSectorOrderUnknown) - continue; - if (TestImage(pImg, ordering[i]) == kDIErrNone) { - *pOrder = ordering[i]; - *pFormat = DiskImg::kFormatCPM; - return kDIErrNone; - } - } + for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { + if (ordering[i] == DiskImg::kSectorOrderUnknown) + continue; + if (TestImage(pImg, ordering[i]) == kDIErrNone) { + *pOrder = ordering[i]; + *pFormat = DiskImg::kFormatCPM; + return kDIErrNone; + } + } - WMSG0(" CPM didn't find valid FS\n"); - return kDIErrFilesystemNotFound; + WMSG0(" CPM didn't find valid FS\n"); + return kDIErrFilesystemNotFound; } /* @@ -142,33 +142,33 @@ DiskFSCPM::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DIError DiskFSCPM::Initialize(void) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - dierr = ReadCatalog(); - if (dierr != kDIErrNone) - goto bail; + dierr = ReadCatalog(); + if (dierr != kDIErrNone) + goto bail; - fVolumeUsage.Create(fpImg->GetNumBlocks()); - dierr = ScanFileUsage(); - if (dierr != kDIErrNone) { - /* this might not be fatal; just means that *some* files are bad */ - dierr = kDIErrNone; - goto bail; - } + fVolumeUsage.Create(fpImg->GetNumBlocks()); + dierr = ScanFileUsage(); + if (dierr != kDIErrNone) { + /* this might not be fatal; just means that *some* files are bad */ + dierr = kDIErrNone; + goto bail; + } - fDiskIsGood = CheckDiskIsGood(); + fDiskIsGood = CheckDiskIsGood(); - fVolumeUsage.Dump(); + fVolumeUsage.Dump(); - //A2File* pFile; - //pFile = GetNextFile(nil); - //while (pFile != nil) { - // pFile->Dump(); - // pFile = GetNextFile(pFile); - //} + //A2File* pFile; + //pFile = GetNextFile(nil); + //while (pFile != nil) { + // pFile->Dump(); + // pFile = GetNextFile(pFile); + //} bail: - return dierr; + return dierr; } /* @@ -181,82 +181,82 @@ bail: DIError DiskFSCPM::ReadCatalog(void) { - DIError dierr = kDIErrNone; - unsigned char dirBuf[kFullDirSize]; - unsigned char* dptr; - int i; + DIError dierr = kDIErrNone; + unsigned char dirBuf[kFullDirSize]; + unsigned char* dptr; + int i; - for (i = 0; i < kVolDirCount; i++) { - dierr = fpImg->ReadBlock(kVolDirBlock + i, dirBuf + kBlkSize*i); - if (dierr != kDIErrNone) - goto bail; - } + for (i = 0; i < kVolDirCount; i++) { + dierr = fpImg->ReadBlock(kVolDirBlock + i, dirBuf + kBlkSize*i); + if (dierr != kDIErrNone) + goto bail; + } - dptr = dirBuf; - for (i = 0; i < kNumDirEntries; i++) { - fDirEntry[i].userNumber = dptr[0x00]; - /* copy the filename, stripping the high bits off */ - for (int j = 0; j < kDirFileNameLen; j++) - fDirEntry[i].fileName[j] = dptr[0x01 + j] & 0x7f; - fDirEntry[i].fileName[kDirFileNameLen] = '\0'; - fDirEntry[i].extent = dptr[0x0c] + dptr[0x0e] * kExtentsInLowByte; - fDirEntry[i].S1 = dptr[0x0d]; - fDirEntry[i].records = dptr[0x0f]; - memcpy(fDirEntry[i].blocks, &dptr[0x10], kDirEntryBlockCount); - fDirEntry[i].readOnly = (dptr[0x09] & 0x80) != 0; - fDirEntry[i].system = (dptr[0x0a] & 0x80) != 0; - fDirEntry[i].badBlockList = false; // set if block list is bad + dptr = dirBuf; + for (i = 0; i < kNumDirEntries; i++) { + fDirEntry[i].userNumber = dptr[0x00]; + /* copy the filename, stripping the high bits off */ + for (int j = 0; j < kDirFileNameLen; j++) + fDirEntry[i].fileName[j] = dptr[0x01 + j] & 0x7f; + fDirEntry[i].fileName[kDirFileNameLen] = '\0'; + fDirEntry[i].extent = dptr[0x0c] + dptr[0x0e] * kExtentsInLowByte; + fDirEntry[i].S1 = dptr[0x0d]; + fDirEntry[i].records = dptr[0x0f]; + memcpy(fDirEntry[i].blocks, &dptr[0x10], kDirEntryBlockCount); + fDirEntry[i].readOnly = (dptr[0x09] & 0x80) != 0; + fDirEntry[i].system = (dptr[0x0a] & 0x80) != 0; + fDirEntry[i].badBlockList = false; // set if block list is bad - dptr += kDirectoryEntryLen; - } + dptr += kDirectoryEntryLen; + } - /* create an entry for the first extent of each file */ - for (i = 0; i < kNumDirEntries; i++) { - A2FileCPM* pFile; + /* create an entry for the first extent of each file */ + for (i = 0; i < kNumDirEntries; i++) { + A2FileCPM* pFile; - if (fDirEntry[i].userNumber == kNoDataByte || fDirEntry[i].extent != 0) - continue; - if (fDirEntry[i].userNumber > kMaxUserNumber) { - /* skip over volume label, date stamps, etc */ - WMSG1("Skipping entry with userNumber=0x%02x\n", - fDirEntry[i].userNumber); - } + if (fDirEntry[i].userNumber == kNoDataByte || fDirEntry[i].extent != 0) + continue; + if (fDirEntry[i].userNumber > kMaxUserNumber) { + /* skip over volume label, date stamps, etc */ + WMSG1("Skipping entry with userNumber=0x%02x\n", + fDirEntry[i].userNumber); + } - pFile = new A2FileCPM(this, fDirEntry); - FormatName(pFile->fFileName, (char*)fDirEntry[i].fileName); - pFile->fReadOnly = fDirEntry[i].readOnly; - pFile->fDirIdx = i; + pFile = new A2FileCPM(this, fDirEntry); + FormatName(pFile->fFileName, (char*)fDirEntry[i].fileName); + pFile->fReadOnly = fDirEntry[i].readOnly; + pFile->fDirIdx = i; - pFile->fLength = 0; - dierr = ComputeLength(pFile); - if (dierr != kDIErrNone) { - pFile->SetQuality(A2File::kQualityDamaged); - dierr = kDIErrNone; - } - AddFileToList(pFile); - } + pFile->fLength = 0; + dierr = ComputeLength(pFile); + if (dierr != kDIErrNone) { + pFile->SetQuality(A2File::kQualityDamaged); + dierr = kDIErrNone; + } + AddFileToList(pFile); + } - /* - * Validate the list of blocks. - */ - int maxCpmBlock; - maxCpmBlock = (fpImg->GetNumBlocks() - kVolDirBlock) / 2; - for (i = 0; i < kNumDirEntries; i++) { - if (fDirEntry[i].userNumber == kNoDataByte) - continue; - for (int j = 0; j < kDirEntryBlockCount; j++) { - if (fDirEntry[i].blocks[j] >= maxCpmBlock) { - WMSG2(" CPM invalid block %d in file '%s'\n", - fDirEntry[i].blocks[j], fDirEntry[i].fileName); - //pFile->SetQuality(A2File::kQualityDamaged); - fDirEntry[i].badBlockList = true; - break; - } - } - } + /* + * Validate the list of blocks. + */ + int maxCpmBlock; + maxCpmBlock = (fpImg->GetNumBlocks() - kVolDirBlock) / 2; + for (i = 0; i < kNumDirEntries; i++) { + if (fDirEntry[i].userNumber == kNoDataByte) + continue; + for (int j = 0; j < kDirEntryBlockCount; j++) { + if (fDirEntry[i].blocks[j] >= maxCpmBlock) { + WMSG2(" CPM invalid block %d in file '%s'\n", + fDirEntry[i].blocks[j], fDirEntry[i].fileName); + //pFile->SetQuality(A2File::kQualityDamaged); + fDirEntry[i].badBlockList = true; + break; + } + } + } bail: - return dierr; + return dierr; } /* @@ -265,28 +265,28 @@ bail: void DiskFSCPM::FormatName(char* dstBuf, const char* srcBuf) { - char workBuf[kDirFileNameLen+1]; - char* cp; + char workBuf[kDirFileNameLen+1]; + char* cp; - assert(strlen(srcBuf) < sizeof(workBuf)); - strcpy(workBuf, srcBuf); + assert(strlen(srcBuf) < sizeof(workBuf)); + strcpy(workBuf, srcBuf); - cp = workBuf; - while (*cp != '\0') { - //*cp &= 0x7f; // [no longer necessary] - if (*cp == ' ') - *cp = '\0'; - if (*cp == ':') // don't think this is allowed, but check - *cp = 'X'; // for it anyway - cp++; - } + cp = workBuf; + while (*cp != '\0') { + //*cp &= 0x7f; // [no longer necessary] + if (*cp == ' ') + *cp = '\0'; + if (*cp == ':') // don't think this is allowed, but check + *cp = 'X'; // for it anyway + cp++; + } - strcpy(dstBuf, workBuf); - dstBuf[8] = '\0'; // in case filename part is full 8 chars - strcat(dstBuf, "."); - strcat(dstBuf, workBuf+8); + strcpy(dstBuf, workBuf); + dstBuf[8] = '\0'; // in case filename part is full 8 chars + strcat(dstBuf, "."); + strcat(dstBuf, workBuf+8); - assert(strlen(dstBuf) <= A2FileCPM::kMaxFileName); + assert(strlen(dstBuf) <= A2FileCPM::kMaxFileName); } /* @@ -302,37 +302,37 @@ DiskFSCPM::FormatName(char* dstBuf, const char* srcBuf) DIError DiskFSCPM::ComputeLength(A2FileCPM* pFile) { - int i; - int best, maxExtent; + int i; + int best, maxExtent; - best = maxExtent = -1; + best = maxExtent = -1; - for (i = 0; i < DiskFSCPM::kNumDirEntries; i++) { - if (fDirEntry[i].userNumber == kNoDataByte) - continue; + for (i = 0; i < DiskFSCPM::kNumDirEntries; i++) { + if (fDirEntry[i].userNumber == kNoDataByte) + continue; - if (strcmp((const char*)fDirEntry[i].fileName, - (const char*)fDirEntry[pFile->fDirIdx].fileName) == 0 && - fDirEntry[i].userNumber == fDirEntry[pFile->fDirIdx].userNumber) - { - /* this entry is part of the file */ - if (fDirEntry[i].extent > maxExtent) { - best = i; - maxExtent = fDirEntry[i].extent; - } - } - } + if (strcmp((const char*)fDirEntry[i].fileName, + (const char*)fDirEntry[pFile->fDirIdx].fileName) == 0 && + fDirEntry[i].userNumber == fDirEntry[pFile->fDirIdx].userNumber) + { + /* this entry is part of the file */ + if (fDirEntry[i].extent > maxExtent) { + best = i; + maxExtent = fDirEntry[i].extent; + } + } + } - if (maxExtent < 0 || best < 0) { - WMSG1(" CPM couldn't find existing file '%s'!\n", pFile->fFileName); - assert(false); - return kDIErrInternal; - } + if (maxExtent < 0 || best < 0) { + WMSG1(" CPM couldn't find existing file '%s'!\n", pFile->fFileName); + assert(false); + return kDIErrInternal; + } - pFile->fLength = kDirEntryBlockCount * 1024 * maxExtent + - fDirEntry[best].records * 128; + pFile->fLength = kDirEntryBlockCount * 1024 * maxExtent + + fDirEntry[best].records * 128; - return kDIErrNone; + return kDIErrNone; } @@ -345,32 +345,32 @@ DiskFSCPM::ComputeLength(A2FileCPM* pFile) DIError DiskFSCPM::ScanFileUsage(void) { - int cpmBlock; - int i, j; + int cpmBlock; + int i, j; - for (i = 0; i < kVolDirBlock; i++) - SetBlockUsage(i, VolumeUsage::kChunkPurposeSystem); - for (i = kVolDirBlock; i < kVolDirBlock + kVolDirCount; i++) - SetBlockUsage(i, VolumeUsage::kChunkPurposeVolumeDir); + for (i = 0; i < kVolDirBlock; i++) + SetBlockUsage(i, VolumeUsage::kChunkPurposeSystem); + for (i = kVolDirBlock; i < kVolDirBlock + kVolDirCount; i++) + SetBlockUsage(i, VolumeUsage::kChunkPurposeVolumeDir); - for (i = 0; i < kNumDirEntries; i++) { - if (fDirEntry[i].userNumber == kNoDataByte) - continue; - if (fDirEntry[i].badBlockList) - continue; + for (i = 0; i < kNumDirEntries; i++) { + if (fDirEntry[i].userNumber == kNoDataByte) + continue; + if (fDirEntry[i].badBlockList) + continue; - for (j = 0; j < kDirEntryBlockCount; j++) { - cpmBlock = fDirEntry[i].blocks[j]; - if (cpmBlock == 0) - break; - SetBlockUsage(CPMToProDOSBlock(cpmBlock), - VolumeUsage::kChunkPurposeUserData); - SetBlockUsage(CPMToProDOSBlock(cpmBlock)+1, - VolumeUsage::kChunkPurposeUserData); - } - } + for (j = 0; j < kDirEntryBlockCount; j++) { + cpmBlock = fDirEntry[i].blocks[j]; + if (cpmBlock == 0) + break; + SetBlockUsage(CPMToProDOSBlock(cpmBlock), + VolumeUsage::kChunkPurposeUserData); + SetBlockUsage(CPMToProDOSBlock(cpmBlock)+1, + VolumeUsage::kChunkPurposeUserData); + } + } - return kDIErrNone; + return kDIErrNone; } /* @@ -382,22 +382,22 @@ DiskFSCPM::ScanFileUsage(void) void DiskFSCPM::SetBlockUsage(long block, VolumeUsage::ChunkPurpose purpose) { - VolumeUsage::ChunkState cstate; + VolumeUsage::ChunkState cstate; - if (fVolumeUsage.GetChunkState(block, &cstate) != kDIErrNone) { - WMSG1(" CPM ERROR: unable to set state on block %ld\n", block); - return; - } + if (fVolumeUsage.GetChunkState(block, &cstate) != kDIErrNone) { + WMSG1(" CPM ERROR: unable to set state on block %ld\n", block); + return; + } - if (cstate.isUsed) { - cstate.purpose = VolumeUsage::kChunkPurposeConflict; - WMSG1(" CPM conflicting uses for block=%ld\n", block); - } else { - cstate.isUsed = true; - cstate.isMarkedUsed = true; // no volume bitmap - cstate.purpose = purpose; - } - fVolumeUsage.SetChunkState(block, &cstate); + if (cstate.isUsed) { + cstate.purpose = VolumeUsage::kChunkPurposeConflict; + WMSG1(" CPM conflicting uses for block=%ld\n", block); + } else { + cstate.isUsed = true; + cstate.isMarkedUsed = true; // no volume bitmap + cstate.purpose = purpose; + } + fVolumeUsage.SetChunkState(block, &cstate); } @@ -412,39 +412,39 @@ DiskFSCPM::SetBlockUsage(long block, VolumeUsage::ChunkPurpose purpose) bool DiskFSCPM::CheckDiskIsGood(void) { - //DIError dierr; - bool result = true; + //DIError dierr; + bool result = true; - //if (fEarlyDamage) - // result = false; + //if (fEarlyDamage) + // result = false; - /* - * TO DO: look for multiple files occupying the same blocks. - */ + /* + * TO DO: look for multiple files occupying the same blocks. + */ - /* - * Scan for "damaged" or "suspicious" files diagnosed earlier. - */ - bool damaged, suspicious; - ScanForDamagedFiles(&damaged, &suspicious); + /* + * Scan for "damaged" or "suspicious" files diagnosed earlier. + */ + bool damaged, suspicious; + ScanForDamagedFiles(&damaged, &suspicious); - if (damaged) { - fpImg->AddNote(DiskImg::kNoteWarning, - "One or more files are damaged."); - result = false; - } else if (suspicious) { - fpImg->AddNote(DiskImg::kNoteWarning, - "One or more files look suspicious."); - result = false; - } + if (damaged) { + fpImg->AddNote(DiskImg::kNoteWarning, + "One or more files are damaged."); + result = false; + } else if (suspicious) { + fpImg->AddNote(DiskImg::kNoteWarning, + "One or more files look suspicious."); + result = false; + } - return result; + return result; } /* * =========================================================================== - * A2FileCPM + * A2FileCPM * =========================================================================== */ @@ -456,43 +456,43 @@ DiskFSCPM::CheckDiskIsGood(void) */ DIError A2FileCPM::Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork /*=false*/) + bool rsrcFork /*=false*/) { - DIError dierr; - A2FDCPM* pOpenFile = nil; + DIError dierr; + A2FDCPM* pOpenFile = nil; - if (fpOpenFile != nil) - return kDIErrAlreadyOpen; - if (rsrcFork) - return kDIErrForkNotFound; + if (fpOpenFile != nil) + return kDIErrAlreadyOpen; + if (rsrcFork) + return kDIErrForkNotFound; - assert(readOnly); + assert(readOnly); - pOpenFile = new A2FDCPM(this); + pOpenFile = new A2FDCPM(this); - dierr = GetBlockList(&pOpenFile->fBlockCount, nil); - if (dierr != kDIErrNone) - goto bail; + dierr = GetBlockList(&pOpenFile->fBlockCount, nil); + if (dierr != kDIErrNone) + goto bail; - pOpenFile->fBlockList = new unsigned char[pOpenFile->fBlockCount+1]; - pOpenFile->fBlockList[pOpenFile->fBlockCount] = 0xff; + pOpenFile->fBlockList = new unsigned char[pOpenFile->fBlockCount+1]; + pOpenFile->fBlockList[pOpenFile->fBlockCount] = 0xff; - dierr = GetBlockList(&pOpenFile->fBlockCount, pOpenFile->fBlockList); - if (dierr != kDIErrNone) - goto bail; + dierr = GetBlockList(&pOpenFile->fBlockCount, pOpenFile->fBlockList); + if (dierr != kDIErrNone) + goto bail; - assert(pOpenFile->fBlockList[pOpenFile->fBlockCount] == 0xff); + assert(pOpenFile->fBlockList[pOpenFile->fBlockCount] == 0xff); - pOpenFile->fOffset = 0; - //fOpen = true; + pOpenFile->fOffset = 0; + //fOpen = true; - fpOpenFile = pOpenFile; - *ppOpenFile = pOpenFile; - pOpenFile = nil; + fpOpenFile = pOpenFile; + *ppOpenFile = pOpenFile; + pOpenFile = nil; bail: - delete pOpenFile; - return dierr; + delete pOpenFile; + return dierr; } @@ -506,60 +506,60 @@ bail: DIError A2FileCPM::GetBlockList(long* pBlockCount, unsigned char* blockBuf) const { - di_off_t length = fLength; - int blockCount = 0; - int i, j; + di_off_t length = fLength; + int blockCount = 0; + int i, j; - /* - * Run through the entries, pulling blocks out until we account for the - * entire length of the file. - * - * [Should probably pay more attention to extent numbers, making sure - * that they make sense. Not vital until we allow writes.] - */ - for (i = 0; i < DiskFSCPM::kNumDirEntries; i++) { - if (length <= 0) - break; - if (fpDirEntry[i].userNumber == kNoDataByte) - continue; + /* + * Run through the entries, pulling blocks out until we account for the + * entire length of the file. + * + * [Should probably pay more attention to extent numbers, making sure + * that they make sense. Not vital until we allow writes.] + */ + for (i = 0; i < DiskFSCPM::kNumDirEntries; i++) { + if (length <= 0) + break; + if (fpDirEntry[i].userNumber == kNoDataByte) + continue; - if (strcmp((const char*)fpDirEntry[i].fileName, - (const char*)fpDirEntry[fDirIdx].fileName) == 0 && - fpDirEntry[i].userNumber == fpDirEntry[fDirIdx].userNumber) - { - /* this entry is part of the file */ - for (j = 0; j < DiskFSCPM::kDirEntryBlockCount; j++) { - if (fpDirEntry[i].blocks[j] == 0) { - WMSG2(" CPM found sparse block %d/%d\n", i, j); - } - blockCount++; + if (strcmp((const char*)fpDirEntry[i].fileName, + (const char*)fpDirEntry[fDirIdx].fileName) == 0 && + fpDirEntry[i].userNumber == fpDirEntry[fDirIdx].userNumber) + { + /* this entry is part of the file */ + for (j = 0; j < DiskFSCPM::kDirEntryBlockCount; j++) { + if (fpDirEntry[i].blocks[j] == 0) { + WMSG2(" CPM found sparse block %d/%d\n", i, j); + } + blockCount++; - if (blockBuf != nil) { - long listOffset = j + - fpDirEntry[i].extent * DiskFSCPM::kDirEntryBlockCount; - blockBuf[listOffset] = fpDirEntry[i].blocks[j]; - } + if (blockBuf != nil) { + long listOffset = j + + fpDirEntry[i].extent * DiskFSCPM::kDirEntryBlockCount; + blockBuf[listOffset] = fpDirEntry[i].blocks[j]; + } - length -= 1024; - if (length <= 0) - break; - } - } - } + length -= 1024; + if (length <= 0) + break; + } + } + } - if (length > 0) { - WMSG1(" CPM WARNING: can't account for %ld bytes!\n", (long) length); - //assert(false); - } + if (length > 0) { + WMSG1(" CPM WARNING: can't account for %ld bytes!\n", (long) length); + //assert(false); + } - //WMSG2(" Returning blockCount=%d for '%s'\n", blockCount, - // fpDirEntry[fDirIdx].fileName); - if (pBlockCount != nil) { - assert(blockBuf == nil || *pBlockCount == blockCount); - *pBlockCount = blockCount; - } + //WMSG2(" Returning blockCount=%d for '%s'\n", blockCount, + // fpDirEntry[fDirIdx].fileName); + if (pBlockCount != nil) { + assert(blockBuf == nil || *pBlockCount == blockCount); + *pBlockCount = blockCount; + } - return kDIErrNone; + return kDIErrNone; } /* @@ -568,13 +568,13 @@ A2FileCPM::GetBlockList(long* pBlockCount, unsigned char* blockBuf) const void A2FileCPM::Dump(void) const { - WMSG2("A2FileCPM '%s' length=%ld\n", fFileName, (long) fLength); + WMSG2("A2FileCPM '%s' length=%ld\n", fFileName, (long) fLength); } /* * =========================================================================== - * A2FDCPM + * A2FDCPM * =========================================================================== */ @@ -584,86 +584,86 @@ A2FileCPM::Dump(void) const DIError A2FDCPM::Read(void* buf, size_t len, size_t* pActual) { - WMSG3(" CP/M reading %d bytes from '%s' (offset=%ld)\n", - len, fpFile->GetPathName(), (long) fOffset); + WMSG3(" CP/M reading %d bytes from '%s' (offset=%ld)\n", + len, fpFile->GetPathName(), (long) fOffset); - A2FileCPM* pFile = (A2FileCPM*) fpFile; + A2FileCPM* pFile = (A2FileCPM*) fpFile; - /* don't allow them to read past the end of the file */ - if (fOffset + (long)len > pFile->fLength) { - if (pActual == nil) - return kDIErrDataUnderrun; - len = (size_t) (pFile->fLength - fOffset); - } - if (pActual != nil) - *pActual = len; - long incrLen = len; + /* don't allow them to read past the end of the file */ + if (fOffset + (long)len > pFile->fLength) { + if (pActual == nil) + return kDIErrDataUnderrun; + len = (size_t) (pFile->fLength - fOffset); + } + if (pActual != nil) + *pActual = len; + long incrLen = len; - DIError dierr = kDIErrNone; - const int kCPMBlockSize = kBlkSize*2; - assert(kCPMBlockSize == 1024); - unsigned char blkBuf[kCPMBlockSize]; - int blkIndex = (int) (fOffset / kCPMBlockSize); - int bufOffset = (int) (fOffset % kCPMBlockSize); // (& 0x3ff) - size_t thisCount; - long prodosBlock; + DIError dierr = kDIErrNone; + const int kCPMBlockSize = kBlkSize*2; + assert(kCPMBlockSize == 1024); + unsigned char blkBuf[kCPMBlockSize]; + int blkIndex = (int) (fOffset / kCPMBlockSize); + int bufOffset = (int) (fOffset % kCPMBlockSize); // (& 0x3ff) + size_t thisCount; + long prodosBlock; - if (len == 0) - return kDIErrNone; - assert(pFile->fLength != 0); + if (len == 0) + return kDIErrNone; + assert(pFile->fLength != 0); - while (len) { - if (blkIndex >= fBlockCount) { - /* ran out of data */ - return kDIErrDataUnderrun; - } + while (len) { + if (blkIndex >= fBlockCount) { + /* ran out of data */ + return kDIErrDataUnderrun; + } - if (fBlockList[blkIndex] == 0) { - /* - * Sparse block. - */ - memset(blkBuf, kNoDataByte, sizeof(blkBuf)); - } else { - /* - * Read one CP/M block (two ProDOS blocks) and pull out the - * set of data that the user wants. - * - * On some Microsoft Softcard disks, the first three tracks hold - * file data rather than the system image. - */ - prodosBlock = DiskFSCPM::CPMToProDOSBlock(fBlockList[blkIndex]); - if (prodosBlock >= 280) - prodosBlock -= 280; + if (fBlockList[blkIndex] == 0) { + /* + * Sparse block. + */ + memset(blkBuf, kNoDataByte, sizeof(blkBuf)); + } else { + /* + * Read one CP/M block (two ProDOS blocks) and pull out the + * set of data that the user wants. + * + * On some Microsoft Softcard disks, the first three tracks hold + * file data rather than the system image. + */ + prodosBlock = DiskFSCPM::CPMToProDOSBlock(fBlockList[blkIndex]); + if (prodosBlock >= 280) + prodosBlock -= 280; - dierr = fpFile->GetDiskFS()->GetDiskImg()->ReadBlock(prodosBlock, - blkBuf); - if (dierr != kDIErrNone) { - WMSG1(" CP/M error1 reading file '%s'\n", pFile->fFileName); - return dierr; - } - dierr = fpFile->GetDiskFS()->GetDiskImg()->ReadBlock(prodosBlock+1, - blkBuf + kBlkSize); - if (dierr != kDIErrNone) { - WMSG1(" CP/M error2 reading file '%s'\n", pFile->fFileName); - return dierr; - } - } + dierr = fpFile->GetDiskFS()->GetDiskImg()->ReadBlock(prodosBlock, + blkBuf); + if (dierr != kDIErrNone) { + WMSG1(" CP/M error1 reading file '%s'\n", pFile->fFileName); + return dierr; + } + dierr = fpFile->GetDiskFS()->GetDiskImg()->ReadBlock(prodosBlock+1, + blkBuf + kBlkSize); + if (dierr != kDIErrNone) { + WMSG1(" CP/M error2 reading file '%s'\n", pFile->fFileName); + return dierr; + } + } - thisCount = kCPMBlockSize - bufOffset; - if (thisCount > len) - thisCount = len; + thisCount = kCPMBlockSize - bufOffset; + if (thisCount > len) + thisCount = len; - memcpy(buf, blkBuf + bufOffset, thisCount); - len -= thisCount; - buf = (char*)buf + thisCount; + memcpy(buf, blkBuf + bufOffset, thisCount); + len -= thisCount; + buf = (char*)buf + thisCount; - bufOffset = 0; - blkIndex++; - } + bufOffset = 0; + blkIndex++; + } - fOffset += incrLen; + fOffset += incrLen; - return dierr; + return dierr; } /* @@ -672,7 +672,7 @@ A2FDCPM::Read(void* buf, size_t len, size_t* pActual) DIError A2FDCPM::Write(const void* buf, size_t len, size_t* pActual) { - return kDIErrNotSupported; + return kDIErrNotSupported; } /* @@ -681,34 +681,34 @@ A2FDCPM::Write(const void* buf, size_t len, size_t* pActual) DIError A2FDCPM::Seek(di_off_t offset, DIWhence whence) { - di_off_t fileLength = ((A2FileCPM*) fpFile)->fLength; + di_off_t fileLength = ((A2FileCPM*) fpFile)->fLength; - switch (whence) { - case kSeekSet: - if (offset < 0 || offset > fileLength) - return kDIErrInvalidArg; - fOffset = offset; - break; - case kSeekEnd: - if (offset > 0 || offset < -fileLength) - return kDIErrInvalidArg; - fOffset = fileLength + offset; - break; - case kSeekCur: - if (offset < -fOffset || - offset >= (fileLength - fOffset)) - { - return kDIErrInvalidArg; - } - fOffset += offset; - break; - default: - assert(false); - return kDIErrInvalidArg; - } + switch (whence) { + case kSeekSet: + if (offset < 0 || offset > fileLength) + return kDIErrInvalidArg; + fOffset = offset; + break; + case kSeekEnd: + if (offset > 0 || offset < -fileLength) + return kDIErrInvalidArg; + fOffset = fileLength + offset; + break; + case kSeekCur: + if (offset < -fOffset || + offset >= (fileLength - fOffset)) + { + return kDIErrInvalidArg; + } + fOffset += offset; + break; + default: + assert(false); + return kDIErrInvalidArg; + } - assert(fOffset >= 0 && fOffset <= fileLength); - return kDIErrNone; + assert(fOffset >= 0 && fOffset <= fileLength); + return kDIErrNone; } /* @@ -717,7 +717,7 @@ A2FDCPM::Seek(di_off_t offset, DIWhence whence) di_off_t A2FDCPM::Tell(void) { - return fOffset; + return fOffset; } /* @@ -726,8 +726,8 @@ A2FDCPM::Tell(void) DIError A2FDCPM::Close(void) { - fpFile->CloseDescr(this); - return kDIErrNone; + fpFile->CloseDescr(this); + return kDIErrNone; } /* @@ -736,12 +736,12 @@ A2FDCPM::Close(void) long A2FDCPM::GetSectorCount(void) const { - return fBlockCount * 4; + return fBlockCount * 4; } long A2FDCPM::GetBlockCount(void) const { - return fBlockCount * 2; + return fBlockCount * 2; } /* @@ -750,17 +750,17 @@ A2FDCPM::GetBlockCount(void) const DIError A2FDCPM::GetStorage(long sectorIdx, long* pTrack, long* pSector) const { - long cpmIdx = sectorIdx / 4; // 4 256-byte sectors per 1K CP/M block - if (cpmIdx >= fBlockCount) - return kDIErrInvalidIndex; // CP/M files can have *no* storage + long cpmIdx = sectorIdx / 4; // 4 256-byte sectors per 1K CP/M block + if (cpmIdx >= fBlockCount) + return kDIErrInvalidIndex; // CP/M files can have *no* storage - long cpmBlock = fBlockList[cpmIdx]; - long prodosBlock = DiskFSCPM::CPMToProDOSBlock(cpmBlock); - if (sectorIdx & 0x02) - prodosBlock++; + long cpmBlock = fBlockList[cpmIdx]; + long prodosBlock = DiskFSCPM::CPMToProDOSBlock(cpmBlock); + if (sectorIdx & 0x02) + prodosBlock++; - BlockToTrackSector(prodosBlock, (sectorIdx & 0x01) != 0, pTrack, pSector); - return kDIErrNone; + BlockToTrackSector(prodosBlock, (sectorIdx & 0x01) != 0, pTrack, pSector); + return kDIErrNone; } /* * Return the Nth 512-byte block in this file. Since things aren't stored @@ -769,16 +769,16 @@ A2FDCPM::GetStorage(long sectorIdx, long* pTrack, long* pSector) const DIError A2FDCPM::GetStorage(long blockIdx, long* pBlock) const { - long cpmIdx = blockIdx / 2; // 4 256-byte sectors per 1K CP/M block - if (cpmIdx >= fBlockCount) - return kDIErrInvalidIndex; + long cpmIdx = blockIdx / 2; // 4 256-byte sectors per 1K CP/M block + if (cpmIdx >= fBlockCount) + return kDIErrInvalidIndex; - long cpmBlock = fBlockList[cpmIdx]; - long prodosBlock = DiskFSCPM::CPMToProDOSBlock(cpmBlock); - if (blockIdx & 0x01) - prodosBlock++; + long cpmBlock = fBlockList[cpmIdx]; + long prodosBlock = DiskFSCPM::CPMToProDOSBlock(cpmBlock); + if (blockIdx & 0x01) + prodosBlock++; - *pBlock = prodosBlock; - assert(*pBlock < fpFile->GetDiskFS()->GetDiskImg()->GetNumBlocks()); - return kDIErrNone; + *pBlock = prodosBlock; + assert(*pBlock < fpFile->GetDiskFS()->GetDiskImg()->GetNumBlocks()); + return kDIErrNone; } diff --git a/diskimg/CP_ntddscsi.h b/diskimg/CP_ntddscsi.h index ccdda6c..a28db87 100644 --- a/diskimg/CP_ntddscsi.h +++ b/diskimg/CP_ntddscsi.h @@ -115,43 +115,43 @@ typedef struct _SRB_IO_CONTROL { } SRB_IO_CONTROL, *PSRB_IO_CONTROL; typedef struct _SCSI_ADDRESS { - ULONG Length; - UCHAR PortNumber; - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; + ULONG Length; + UCHAR PortNumber; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; } SCSI_ADDRESS, *PSCSI_ADDRESS; typedef struct _SCSI_BUS_DATA { - UCHAR NumberOfLogicalUnits; - UCHAR InitiatorBusId; - ULONG InquiryDataOffset; + UCHAR NumberOfLogicalUnits; + UCHAR InitiatorBusId; + ULONG InquiryDataOffset; }SCSI_BUS_DATA, *PSCSI_BUS_DATA; typedef struct _SCSI_ADAPTER_BUS_INFO { - UCHAR NumberOfBuses; - SCSI_BUS_DATA BusData[1]; + UCHAR NumberOfBuses; + SCSI_BUS_DATA BusData[1]; } SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO; typedef struct _IO_SCSI_CAPABILITIES { - ULONG Length; - ULONG MaximumTransferLength; - ULONG MaximumPhysicalPages; - ULONG SupportedAsynchronousEvents; - ULONG AlignmentMask; - BOOLEAN TaggedQueuing; - BOOLEAN AdapterScansDown; - BOOLEAN AdapterUsesPio; + ULONG Length; + ULONG MaximumTransferLength; + ULONG MaximumPhysicalPages; + ULONG SupportedAsynchronousEvents; + ULONG AlignmentMask; + BOOLEAN TaggedQueuing; + BOOLEAN AdapterScansDown; + BOOLEAN AdapterUsesPio; } IO_SCSI_CAPABILITIES, *PIO_SCSI_CAPABILITIES; typedef struct _SCSI_INQUIRY_DATA { - UCHAR PathId; - UCHAR TargetId; - UCHAR Lun; - BOOLEAN DeviceClaimed; - ULONG InquiryDataLength; - ULONG NextInquiryDataOffset; - UCHAR InquiryData[1]; + UCHAR PathId; + UCHAR TargetId; + UCHAR Lun; + BOOLEAN DeviceClaimed; + ULONG InquiryDataLength; + ULONG NextInquiryDataOffset; + UCHAR InquiryData[1]; } SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA; #define SCSI_IOCTL_DATA_OUT 0 @@ -162,16 +162,16 @@ struct ADAPTER_OBJECT; typedef struct ADAPTER_OBJECT* PADAPTER_OBJECT; typedef struct _DUMP_POINTERS { - PADAPTER_OBJECT AdapterObject; - PVOID MappedRegisterBase; - PVOID DumpData; - PVOID CommonBufferVa; - LARGE_INTEGER CommonBufferPa; - ULONG CommonBufferSize; - BOOLEAN AllocateCommonBuffers; - BOOLEAN UseDiskDump; - UCHAR Spare1[2]; - PVOID DeviceObject; + PADAPTER_OBJECT AdapterObject; + PVOID MappedRegisterBase; + PVOID DumpData; + PVOID CommonBufferVa; + LARGE_INTEGER CommonBufferPa; + ULONG CommonBufferSize; + BOOLEAN AllocateCommonBuffers; + BOOLEAN UseDiskDump; + UCHAR Spare1[2]; + PVOID DeviceObject; } DUMP_POINTERS, *PDUMP_POINTERS; diff --git a/diskimg/Container.cpp b/diskimg/Container.cpp index 016215d..bd6bdbc 100644 --- a/diskimg/Container.cpp +++ b/diskimg/Container.cpp @@ -16,17 +16,17 @@ void DiskFSContainer::SetVolumeUsageMap(void) { - VolumeUsage::ChunkState cstate; - long block; + VolumeUsage::ChunkState cstate; + long block; - fVolumeUsage.Create(fpImg->GetNumBlocks()); + fVolumeUsage.Create(fpImg->GetNumBlocks()); - cstate.isUsed = true; - cstate.isMarkedUsed = true; - cstate.purpose = VolumeUsage::kChunkPurposeEmbedded; + cstate.isUsed = true; + cstate.isMarkedUsed = true; + cstate.purpose = VolumeUsage::kChunkPurposeEmbedded; - for (block = fpImg->GetNumBlocks()-1; block >= 0; block--) - fVolumeUsage.SetChunkState(block, &cstate); + for (block = fpImg->GetNumBlocks()-1; block >= 0; block--) + fVolumeUsage.SetChunkState(block, &cstate); } @@ -36,87 +36,87 @@ DiskFSContainer::SetVolumeUsageMap(void) */ DIError DiskFSContainer::CreatePlaceholder(long startBlock, long numBlocks, - const char* partName, const char* partType, - DiskImg** ppNewImg, DiskFS** ppNewFS) + const char* partName, const char* partType, + DiskImg** ppNewImg, DiskFS** ppNewFS) { - DIError dierr = kDIErrNone; - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; + DIError dierr = kDIErrNone; + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; - WMSG3(" %s/CrPl creating placeholder for %ld +%ld\n", GetDebugName(), - startBlock, numBlocks); + WMSG3(" %s/CrPl creating placeholder for %ld +%ld\n", GetDebugName(), + startBlock, numBlocks); - if (startBlock > fpImg->GetNumBlocks()) { - WMSG3(" %s/CrPl start block out of range (%ld vs %ld)\n", - GetDebugName(), startBlock, fpImg->GetNumBlocks()); - return kDIErrBadPartition; - } + if (startBlock > fpImg->GetNumBlocks()) { + WMSG3(" %s/CrPl start block out of range (%ld vs %ld)\n", + GetDebugName(), startBlock, fpImg->GetNumBlocks()); + return kDIErrBadPartition; + } - pNewImg = new DiskImg; - if (pNewImg == nil) { - dierr = kDIErrMalloc; - goto bail; - } + pNewImg = new DiskImg; + if (pNewImg == nil) { + dierr = kDIErrMalloc; + goto bail; + } - if (partName != nil) { - if (partType != nil) - pNewImg->AddNote(DiskImg::kNoteInfo, - "Partition name='%s' type='%s'.", partName, partType); - else - pNewImg->AddNote(DiskImg::kNoteInfo, - "Partition name='%s'.", partName); - } + if (partName != nil) { + if (partType != nil) + pNewImg->AddNote(DiskImg::kNoteInfo, + "Partition name='%s' type='%s'.", partName, partType); + else + pNewImg->AddNote(DiskImg::kNoteInfo, + "Partition name='%s'.", partName); + } - dierr = pNewImg->OpenImage(fpImg, startBlock, numBlocks); - if (dierr != kDIErrNone) { - WMSG4(" %s/CrPl: OpenImage(%ld,%ld) failed (err=%d)\n", - GetDebugName(), startBlock, numBlocks, dierr); - goto bail; - } + dierr = pNewImg->OpenImage(fpImg, startBlock, numBlocks); + if (dierr != kDIErrNone) { + WMSG4(" %s/CrPl: OpenImage(%ld,%ld) failed (err=%d)\n", + GetDebugName(), startBlock, numBlocks, dierr); + goto bail; + } - /* - * If this slot isn't formatted at all, the call will return with - * "unknown FS". If it's formatted enough to pass the initial test, - * but fails during "Initialize", we'll have a non-unknown value - * for the FS format. We need to stomp that. - */ - dierr = pNewImg->AnalyzeImage(); - if (dierr != kDIErrNone) { - WMSG2(" %s/CrPl: analysis failed (err=%d)\n", GetDebugName(), dierr); - goto bail; - } - if (pNewImg->GetFSFormat() != DiskImg::kFormatUnknown) { - dierr = pNewImg->OverrideFormat(pNewImg->GetPhysicalFormat(), - DiskImg::kFormatUnknown, pNewImg->GetSectorOrder()); - if (dierr != kDIErrNone) { - WMSG1(" %s/CrPl: unable to override to unknown\n", - GetDebugName()); - goto bail; - } - } + /* + * If this slot isn't formatted at all, the call will return with + * "unknown FS". If it's formatted enough to pass the initial test, + * but fails during "Initialize", we'll have a non-unknown value + * for the FS format. We need to stomp that. + */ + dierr = pNewImg->AnalyzeImage(); + if (dierr != kDIErrNone) { + WMSG2(" %s/CrPl: analysis failed (err=%d)\n", GetDebugName(), dierr); + goto bail; + } + if (pNewImg->GetFSFormat() != DiskImg::kFormatUnknown) { + dierr = pNewImg->OverrideFormat(pNewImg->GetPhysicalFormat(), + DiskImg::kFormatUnknown, pNewImg->GetSectorOrder()); + if (dierr != kDIErrNone) { + WMSG1(" %s/CrPl: unable to override to unknown\n", + GetDebugName()); + goto bail; + } + } - /* open a DiskFS for the sub-image, allowing "unknown" */ - pNewFS = pNewImg->OpenAppropriateDiskFS(true); - if (pNewFS == nil) { - WMSG1(" %s/CrPl: OpenAppropriateDiskFS failed\n", GetDebugName()); - dierr = kDIErrUnsupportedFSFmt; - goto bail; - } + /* open a DiskFS for the sub-image, allowing "unknown" */ + pNewFS = pNewImg->OpenAppropriateDiskFS(true); + if (pNewFS == nil) { + WMSG1(" %s/CrPl: OpenAppropriateDiskFS failed\n", GetDebugName()); + dierr = kDIErrUnsupportedFSFmt; + goto bail; + } - /* sets the DiskImg ptr (and very little else) */ - dierr = pNewFS->Initialize(pNewImg, kInitFull); - if (dierr != kDIErrNone) { - WMSG2(" %s/CrPl: init failed (err=%d)\n", GetDebugName(), dierr); - goto bail; - } + /* sets the DiskImg ptr (and very little else) */ + dierr = pNewFS->Initialize(pNewImg, kInitFull); + if (dierr != kDIErrNone) { + WMSG2(" %s/CrPl: init failed (err=%d)\n", GetDebugName(), dierr); + goto bail; + } bail: - if (dierr != kDIErrNone) { - delete pNewFS; - delete pNewImg; - } else { - *ppNewImg = pNewImg; - *ppNewFS = pNewFS; - } - return dierr; + if (dierr != kDIErrNone) { + delete pNewFS; + delete pNewImg; + } else { + *ppNewImg = pNewImg; + *ppNewFS = pNewFS; + } + return dierr; } diff --git a/diskimg/DDD.cpp b/diskimg/DDD.cpp index a8370d5..6359128 100644 --- a/diskimg/DDD.cpp +++ b/diskimg/DDD.cpp @@ -485,7 +485,7 @@ WrapperDDD::UnpackDisk(GenericFD* pGFD, GenericFD* pNewGFD, *pDiskVolNum = bitBuffer.Reverse(val); WMSG1(" DDD found disk volume num = %d\n", *pDiskVolNum); - int track; + int track; for (track = 0; track < kNumTracks; track++) { unsigned char trackBuf[kTrackLen]; @@ -507,29 +507,29 @@ WrapperDDD::UnpackDisk(GenericFD* pGFD, GenericFD* pNewGFD, /* * We should be within a byte or two of the end of the file. Try * to read more and expect it to fail. - * - * Unfortunately, if this was a DOS DDD file, we could be up to 256 - * bytes off (the 1 additional byte it adds plus the remaining 255 - * bytes in the sector). We have to choose between a tight auto-detect - * and the ability to process DOS DDD files. - * - * Fortunately the need to hit track boundaries exactly and the quick test - * for long runs of bytes provides some opportunity for correct - * detection. + * + * Unfortunately, if this was a DOS DDD file, we could be up to 256 + * bytes off (the 1 additional byte it adds plus the remaining 255 + * bytes in the sector). We have to choose between a tight auto-detect + * and the ability to process DOS DDD files. + * + * Fortunately the need to hit track boundaries exactly and the quick test + * for long runs of bytes provides some opportunity for correct + * detection. */ - size_t actual; - char sctBuf[256 + 16]; + size_t actual; + char sctBuf[256 + 16]; dierr = pGFD->Read(&sctBuf, sizeof(sctBuf), &actual); if (dierr == kDIErrNone) { - if (actual > /*kMaxExcessByteCount*/ 256) { - WMSG1(" DDD looks like too much data in input file (%d extra)\n", - actual); - dierr = kDIErrBadCompressedData; - goto bail; - } else { - WMSG1(" DDD excess bytes (%d) within normal parameters\n", actual); - } - } + if (actual > /*kMaxExcessByteCount*/ 256) { + WMSG1(" DDD looks like too much data in input file (%d extra)\n", + actual); + dierr = kDIErrBadCompressedData; + goto bail; + } else { + WMSG1(" DDD excess bytes (%d) within normal parameters\n", actual); + } + } WMSG0(" DDD looks like a DDD archive!\n"); dierr = kDIErrNone; diff --git a/diskimg/DIUtil.cpp b/diskimg/DIUtil.cpp index 911797b..fc0bed3 100644 --- a/diskimg/DIUtil.cpp +++ b/diskimg/DIUtil.cpp @@ -9,7 +9,7 @@ #include "StdAfx.h" #include "DiskImgPriv.h" -#define kFilenameExtDelim '.' /* separates extension from filename */ +#define kFilenameExtDelim '.' /* separates extension from filename */ /* * Get values from a memory buffer. @@ -17,39 +17,39 @@ unsigned short DiskImgLib::GetShortLE(const unsigned char* ptr) { - return *ptr | (unsigned short) *(ptr+1) << 8; + return *ptr | (unsigned short) *(ptr+1) << 8; } unsigned long DiskImgLib::GetLongLE(const unsigned char* ptr) { - return *ptr | - (unsigned long) *(ptr+1) << 8 | - (unsigned long) *(ptr+2) << 16 | - (unsigned long) *(ptr+3) << 24; + return *ptr | + (unsigned long) *(ptr+1) << 8 | + (unsigned long) *(ptr+2) << 16 | + (unsigned long) *(ptr+3) << 24; } unsigned short DiskImgLib::GetShortBE(const unsigned char* ptr) { - return *(ptr+1) | (unsigned short) *ptr << 8; + return *(ptr+1) | (unsigned short) *ptr << 8; } unsigned long DiskImgLib::GetLongBE(const unsigned char* ptr) { - return *(ptr+3) | - (unsigned long) *(ptr+2) << 8 | - (unsigned long) *(ptr+1) << 16 | - (unsigned long) *ptr << 24; + return *(ptr+3) | + (unsigned long) *(ptr+2) << 8 | + (unsigned long) *(ptr+1) << 16 | + (unsigned long) *ptr << 24; } unsigned long DiskImgLib::Get24BE(const unsigned char* ptr) { - return *(ptr+2) | - (unsigned long) *(ptr+1) << 8 | - (unsigned long) *ptr << 16; + return *(ptr+2) | + (unsigned long) *(ptr+1) << 8 | + (unsigned long) *ptr << 16; } void @@ -91,15 +91,15 @@ DiskImgLib::PutLongBE(unsigned char* ptr, unsigned long val) DIError DiskImgLib::ReadShortLE(GenericFD* pGFD, short* pBuf) { - DIError dierr; - unsigned char val[2]; + DIError dierr; + unsigned char val[2]; - dierr = pGFD->Read(&val[0], 1); - if (dierr == kDIErrNone) - dierr = pGFD->Read(&val[1], 1); + dierr = pGFD->Read(&val[0], 1); + if (dierr == kDIErrNone) + dierr = pGFD->Read(&val[1], 1); *pBuf = val[0] | (short) val[1] << 8; - return dierr; + return dierr; } /* @@ -108,19 +108,19 @@ DiskImgLib::ReadShortLE(GenericFD* pGFD, short* pBuf) DIError DiskImgLib::ReadLongLE(GenericFD* pGFD, long* pBuf) { - DIError dierr; - unsigned char val[4]; + DIError dierr; + unsigned char val[4]; - dierr = pGFD->Read(&val[0], 1); - if (dierr == kDIErrNone) - dierr = pGFD->Read(&val[1], 1); - if (dierr == kDIErrNone) - dierr = pGFD->Read(&val[2], 1); - if (dierr == kDIErrNone) - dierr = pGFD->Read(&val[3], 1); + dierr = pGFD->Read(&val[0], 1); + if (dierr == kDIErrNone) + dierr = pGFD->Read(&val[1], 1); + if (dierr == kDIErrNone) + dierr = pGFD->Read(&val[2], 1); + if (dierr == kDIErrNone) + dierr = pGFD->Read(&val[3], 1); *pBuf = val[0] | (long)val[1] << 8 | (long)val[2] << 16 | (long)val[3] << 24; - return dierr; + return dierr; } /* @@ -131,7 +131,7 @@ DiskImgLib::WriteShortLE(FILE* fp, unsigned short val) { putc(val, fp); putc(val >> 8, fp); - return kDIErrNone; + return kDIErrNone; } /* @@ -144,7 +144,7 @@ DiskImgLib::WriteLongLE(FILE* fp, unsigned long val) putc(val >> 8, fp); putc(val >> 16, fp); putc(val >> 24, fp); - return kDIErrNone; + return kDIErrNone; } /* @@ -222,55 +222,55 @@ DiskImgLib::WriteLongBE(GenericFD* pGFD, unsigned long val) const char* DiskImgLib::FilenameOnly(const char* pathname, char fssep) { - const char* retstr; - const char* pSlash; - char* tmpStr = nil; + const char* retstr; + const char* pSlash; + char* tmpStr = nil; - assert(pathname != nil); - if (fssep == '\0') { - retstr = pathname; - goto bail; - } + assert(pathname != nil); + if (fssep == '\0') { + retstr = pathname; + goto bail; + } - pSlash = strrchr(pathname, fssep); - if (pSlash == nil) { - retstr = pathname; /* whole thing is the filename */ - goto bail; - } + pSlash = strrchr(pathname, fssep); + if (pSlash == nil) { + retstr = pathname; /* whole thing is the filename */ + goto bail; + } - pSlash++; - if (*pSlash == '\0') { - if (strlen(pathname) < 2) { - retstr = pathname; /* the pathname is just "/"? Whatever */ - goto bail; - } + pSlash++; + if (*pSlash == '\0') { + if (strlen(pathname) < 2) { + retstr = pathname; /* the pathname is just "/"? Whatever */ + goto bail; + } - /* some bonehead put an fssep on the very end; back up before it */ - /* (not efficient, but this should be rare, and I'm feeling lazy) */ - tmpStr = strdup(pathname); - tmpStr[strlen(pathname)-1] = '\0'; - pSlash = strrchr(tmpStr, fssep); + /* some bonehead put an fssep on the very end; back up before it */ + /* (not efficient, but this should be rare, and I'm feeling lazy) */ + tmpStr = strdup(pathname); + tmpStr[strlen(pathname)-1] = '\0'; + pSlash = strrchr(tmpStr, fssep); - if (pSlash == nil) { - retstr = pathname; /* just a filename with a '/' after it */ - goto bail; - } + if (pSlash == nil) { + retstr = pathname; /* just a filename with a '/' after it */ + goto bail; + } - pSlash++; - if (*pSlash == '\0') { - retstr = pathname; /* I give up! */ - goto bail; - } + pSlash++; + if (*pSlash == '\0') { + retstr = pathname; /* I give up! */ + goto bail; + } - retstr = pathname + (pSlash - tmpStr); + retstr = pathname + (pSlash - tmpStr); - } else { - retstr = pSlash; - } + } else { + retstr = pSlash; + } bail: - free(tmpStr); - return retstr; + free(tmpStr); + return retstr; } /* @@ -287,22 +287,22 @@ bail: const char* DiskImgLib::FindExtension(const char* pathname, char fssep) { - const char* pFilename; - const char* pExt; + const char* pFilename; + const char* pExt; - /* - * We have to isolate the filename so that we don't get excited - * about "/foo.bar/file". - */ - pFilename = FilenameOnly(pathname, fssep); - assert(pFilename != nil); - pExt = strrchr(pFilename, kFilenameExtDelim); + /* + * We have to isolate the filename so that we don't get excited + * about "/foo.bar/file". + */ + pFilename = FilenameOnly(pathname, fssep); + assert(pFilename != nil); + pExt = strrchr(pFilename, kFilenameExtDelim); - /* also check for "/blah/foo.", which doesn't count */ - if (pExt != nil && *(pExt+1) != '\0') - return pExt; + /* also check for "/blah/foo.", which doesn't count */ + if (pExt != nil && *(pExt+1) != '\0') + return pExt; - return nil; + return nil; } /* @@ -313,14 +313,14 @@ DiskImgLib::FindExtension(const char* pathname, char fssep) char* DiskImgLib::StrcpyNew(const char* str) { - char* newStr; + char* newStr; - if (str == nil) - return nil; - newStr = new char[strlen(str)+1]; - if (newStr != nil) - strcpy(newStr, str); - return newStr; + if (str == nil) + return nil; + newStr = new char[strlen(str)+1]; + if (newStr != nil) + strcpy(newStr, str); + return newStr; } @@ -331,30 +331,30 @@ DiskImgLib::StrcpyNew(const char* str) DIError DiskImgLib::LastErrorToDIError(void) { - DWORD lastErr = ::GetLastError(); + DWORD lastErr = ::GetLastError(); - switch (lastErr) { - case ERROR_FILE_NOT_FOUND: return kDIErrFileNotFound; // 2 - case ERROR_ACCESS_DENIED: return kDIErrAccessDenied; // 5 - case ERROR_WRITE_PROTECT: return kDIErrWriteProtected; // 19 - case ERROR_SECTOR_NOT_FOUND: return kDIErrGeneric; // 27 - case ERROR_SHARING_VIOLATION: return kDIErrSharingViolation; // 32 - case ERROR_HANDLE_EOF: return kDIErrEOF; // 38 - case ERROR_INVALID_PARAMETER: return kDIErrInvalidArg; // 87 - case ERROR_SEM_TIMEOUT: return kDIErrGenericIO; // 121 - // ERROR_SEM_TIMEOUT seen read bad blocks from floptical under Win2K + switch (lastErr) { + case ERROR_FILE_NOT_FOUND: return kDIErrFileNotFound; // 2 + case ERROR_ACCESS_DENIED: return kDIErrAccessDenied; // 5 + case ERROR_WRITE_PROTECT: return kDIErrWriteProtected; // 19 + case ERROR_SECTOR_NOT_FOUND: return kDIErrGeneric; // 27 + case ERROR_SHARING_VIOLATION: return kDIErrSharingViolation; // 32 + case ERROR_HANDLE_EOF: return kDIErrEOF; // 38 + case ERROR_INVALID_PARAMETER: return kDIErrInvalidArg; // 87 + case ERROR_SEM_TIMEOUT: return kDIErrGenericIO; // 121 + // ERROR_SEM_TIMEOUT seen read bad blocks from floptical under Win2K - case ERROR_INVALID_HANDLE: // 6 - WMSG0("HEY: got ERROR_INVALID_HANDLE!\n"); - return kDIErrInternal; - case ERROR_NEGATIVE_SEEK: // 131 - WMSG0("HEY: got ERROR_NEGATIVE_SEEK!\n"); - return kDIErrInternal; - default: - WMSG2("LastErrorToDIError: not converting 0x%08lx (%ld)\n", - lastErr, lastErr); - return kDIErrGeneric; - } + case ERROR_INVALID_HANDLE: // 6 + WMSG0("HEY: got ERROR_INVALID_HANDLE!\n"); + return kDIErrInternal; + case ERROR_NEGATIVE_SEEK: // 131 + WMSG0("HEY: got ERROR_NEGATIVE_SEEK!\n"); + return kDIErrInternal; + default: + WMSG2("LastErrorToDIError: not converting 0x%08lx (%ld)\n", + lastErr, lastErr); + return kDIErrGeneric; + } } /* @@ -364,16 +364,16 @@ DiskImgLib::LastErrorToDIError(void) bool DiskImgLib::IsWin9x(void) { - OSVERSIONINFO osvers; - BOOL result; + OSVERSIONINFO osvers; + BOOL result; - osvers.dwOSVersionInfoSize = sizeof(osvers); - result = ::GetVersionEx(&osvers); - assert(result != FALSE); + osvers.dwOSVersionInfoSize = sizeof(osvers); + result = ::GetVersionEx(&osvers); + assert(result != FALSE); - if (osvers.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) - return true; - else - return false; + if (osvers.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + return true; + else + return false; } #endif diff --git a/diskimg/DOS33.cpp b/diskimg/DOS33.cpp index bd5b983..38ec8a0 100644 --- a/diskimg/DOS33.cpp +++ b/diskimg/DOS33.cpp @@ -16,7 +16,7 @@ /* * =========================================================================== - * DiskFSDOS33 + * DiskFSDOS33 * =========================================================================== */ @@ -26,13 +26,13 @@ const int kSctSize = 256; /* do we need a way to override these? */ const int kVTOCTrack = 17; const int kVTOCSector = 0; -const int kCatalogEntryOffset = 0x0b; // first entry in cat sect starts here -const int kCatalogEntrySize = 0x23; // length in bytes of catalog entries -const int kCatalogEntriesPerSect = 7; // #of entries per catalog sector -const int kEntryDeleted = 0xff; // this is used for track# of deleted files -const int kEntryUnused = 0x00; // this is track# in never-used entries -const int kMaxTSPairs = 0x7a; // 122 entries for 256-byte sectors -const int kTSOffset = 0x0c; // first T/S entry in a T/S list +const int kCatalogEntryOffset = 0x0b; // first entry in cat sect starts here +const int kCatalogEntrySize = 0x23; // length in bytes of catalog entries +const int kCatalogEntriesPerSect = 7; // #of entries per catalog sector +const int kEntryDeleted = 0xff; // this is used for track# of deleted files +const int kEntryUnused = 0x00; // this is track# in never-used entries +const int kMaxTSPairs = 0x7a; // 122 entries for 256-byte sectors +const int kTSOffset = 0x0c; // first T/S entry in a T/S list const int kMaxTSIterations = 32; @@ -42,8 +42,8 @@ const int kMaxTSIterations = 32; static inline unsigned char* GetCatalogEntryPtr(unsigned char* basePtr, int entryNum) { - assert(entryNum >= 0 && entryNum < kCatalogEntriesPerSect); - return basePtr + kCatalogEntryOffset + entryNum * kCatalogEntrySize; + assert(entryNum >= 0 && entryNum < kCatalogEntriesPerSect); + return basePtr + kCatalogEntryOffset + entryNum * kCatalogEntrySize; } @@ -73,75 +73,75 @@ GetCatalogEntryPtr(unsigned char* basePtr, int entryNum) static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder, int* pGoodCount) { - DIError dierr = kDIErrNone; - unsigned char sctBuf[kSctSize]; - int numTracks, numSectors; - int catTrack, catSect; - int foundGood = 0; - int iterations = 0; + DIError dierr = kDIErrNone; + unsigned char sctBuf[kSctSize]; + int numTracks, numSectors; + int catTrack, catSect; + int foundGood = 0; + int iterations = 0; - *pGoodCount = 0; + *pGoodCount = 0; - dierr = pImg->ReadTrackSectorSwapped(kVTOCTrack, kVTOCSector, - sctBuf, imageOrder, DiskImg::kSectorOrderDOS); - if (dierr != kDIErrNone) - goto bail; + dierr = pImg->ReadTrackSectorSwapped(kVTOCTrack, kVTOCSector, + sctBuf, imageOrder, DiskImg::kSectorOrderDOS); + if (dierr != kDIErrNone) + goto bail; - catTrack = sctBuf[0x01]; - catSect = sctBuf[0x02]; - numTracks = sctBuf[0x34]; - numSectors = sctBuf[0x35]; + catTrack = sctBuf[0x01]; + catSect = sctBuf[0x02]; + numTracks = sctBuf[0x34]; + numSectors = sctBuf[0x35]; - if (!(sctBuf[0x27] == kMaxTSPairs) || - /*!(sctBuf[0x36] == 0 && sctBuf[0x37] == 1) ||*/ // bytes per sect - !(numTracks <= DiskFSDOS33::kMaxTracks) || - !(numSectors == 13 || numSectors == 16 || numSectors == 32) || - !(catTrack < numTracks && catSect < numSectors) || - 0) - { - WMSG1(" DOS header test failed (order=%d)\n", imageOrder); - dierr = kDIErrFilesystemNotFound; - goto bail; - } + if (!(sctBuf[0x27] == kMaxTSPairs) || + /*!(sctBuf[0x36] == 0 && sctBuf[0x37] == 1) ||*/ // bytes per sect + !(numTracks <= DiskFSDOS33::kMaxTracks) || + !(numSectors == 13 || numSectors == 16 || numSectors == 32) || + !(catTrack < numTracks && catSect < numSectors) || + 0) + { + WMSG1(" DOS header test failed (order=%d)\n", imageOrder); + dierr = kDIErrFilesystemNotFound; + goto bail; + } - foundGood++; // score one for a valid-looking VTOC + foundGood++; // score one for a valid-looking VTOC - /* - * Walk through the catalog track to try to figure out ordering. - */ - while (catTrack != 0 && catSect != 0 && - iterations < DiskFSDOS33::kMaxCatalogSectors) - { - dierr = pImg->ReadTrackSectorSwapped(catTrack, catSect, sctBuf, - imageOrder, DiskImg::kSectorOrderDOS); - if (dierr != kDIErrNone) { - dierr = kDIErrNone; - break; /* allow it if earlier stuff was okay */ - } + /* + * Walk through the catalog track to try to figure out ordering. + */ + while (catTrack != 0 && catSect != 0 && + iterations < DiskFSDOS33::kMaxCatalogSectors) + { + dierr = pImg->ReadTrackSectorSwapped(catTrack, catSect, sctBuf, + imageOrder, DiskImg::kSectorOrderDOS); + if (dierr != kDIErrNone) { + dierr = kDIErrNone; + break; /* allow it if earlier stuff was okay */ + } - if (catTrack == sctBuf[1] && catSect == sctBuf[2] +1) - foundGood++; - else if (catTrack == sctBuf[1] && catSect == sctBuf[2]) { - WMSG2(" DOS detected self-reference on cat (%d,%d)\n", - catTrack, catSect); - break; - } - catTrack = sctBuf[1]; - catSect = sctBuf[2]; - iterations++; // watch for infinite loops - } - if (iterations >= DiskFSDOS33::kMaxCatalogSectors) { - /* possible cause: LF->CR conversion screws up link to sector $0a */ - dierr = kDIErrDirectoryLoop; - WMSG1(" DOS directory links cause a loop (order=%d)\n", imageOrder); - goto bail; - } + if (catTrack == sctBuf[1] && catSect == sctBuf[2] +1) + foundGood++; + else if (catTrack == sctBuf[1] && catSect == sctBuf[2]) { + WMSG2(" DOS detected self-reference on cat (%d,%d)\n", + catTrack, catSect); + break; + } + catTrack = sctBuf[1]; + catSect = sctBuf[2]; + iterations++; // watch for infinite loops + } + if (iterations >= DiskFSDOS33::kMaxCatalogSectors) { + /* possible cause: LF->CR conversion screws up link to sector $0a */ + dierr = kDIErrDirectoryLoop; + WMSG1(" DOS directory links cause a loop (order=%d)\n", imageOrder); + goto bail; + } - WMSG2(" DOS foundGood=%d order=%d\n", foundGood, imageOrder); - *pGoodCount = foundGood; + WMSG2(" DOS foundGood=%d order=%d\n", foundGood, imageOrder); + *pGoodCount = foundGood; bail: - return dierr; + return dierr; } /* @@ -149,45 +149,45 @@ bail: */ /*static*/ DIError DiskFSDOS33::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency) + DiskImg::FSFormat* pFormat, FSLeniency leniency) { - if (pImg->GetNumTracks() > kMaxInterestingTracks) - return kDIErrFilesystemNotFound; + if (pImg->GetNumTracks() > kMaxInterestingTracks) + return kDIErrFilesystemNotFound; - DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; - - DiskImg::GetSectorOrderArray(ordering, *pOrder); + DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; + + DiskImg::GetSectorOrderArray(ordering, *pOrder); - DiskImg::SectorOrder bestOrder = DiskImg::kSectorOrderUnknown; - int bestCount = 0; + DiskImg::SectorOrder bestOrder = DiskImg::kSectorOrderUnknown; + int bestCount = 0; - for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { - int goodCount = 0; + for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { + int goodCount = 0; - if (ordering[i] == DiskImg::kSectorOrderUnknown) - continue; - if (TestImage(pImg, ordering[i], &goodCount) == kDIErrNone) { - if (goodCount > bestCount) { - bestCount = goodCount; - bestOrder = ordering[i]; - } - } - } + if (ordering[i] == DiskImg::kSectorOrderUnknown) + continue; + if (TestImage(pImg, ordering[i], &goodCount) == kDIErrNone) { + if (goodCount > bestCount) { + bestCount = goodCount; + bestOrder = ordering[i]; + } + } + } - if (bestCount >= 4 || - (leniency == kLeniencyVery && bestCount >= 2)) - { - WMSG2(" DOS test: bestCount=%d for order=%d\n", bestCount, bestOrder); - assert(bestOrder != DiskImg::kSectorOrderUnknown); - *pOrder = bestOrder; - *pFormat = DiskImg::kFormatDOS33; - if (pImg->GetNumSectPerTrack() == 13) - *pFormat = DiskImg::kFormatDOS32; - return kDIErrNone; - } + if (bestCount >= 4 || + (leniency == kLeniencyVery && bestCount >= 2)) + { + WMSG2(" DOS test: bestCount=%d for order=%d\n", bestCount, bestOrder); + assert(bestOrder != DiskImg::kSectorOrderUnknown); + *pOrder = bestOrder; + *pFormat = DiskImg::kFormatDOS33; + if (pImg->GetNumSectPerTrack() == 13) + *pFormat = DiskImg::kFormatDOS32; + return kDIErrNone; + } - WMSG0(" DOS33 didn't find valid DOS3.2 or DOS3.3\n"); - return kDIErrFilesystemNotFound; + WMSG0(" DOS33 didn't find valid DOS3.2 or DOS3.3\n"); + return kDIErrFilesystemNotFound; } @@ -201,50 +201,50 @@ DiskFSDOS33::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DIError DiskFSDOS33::Initialize(InitMode initMode) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - fVolumeUsage.Create(fpImg->GetNumTracks(), fpImg->GetNumSectPerTrack()); + fVolumeUsage.Create(fpImg->GetNumTracks(), fpImg->GetNumSectPerTrack()); - dierr = ReadVTOC(); - if (dierr != kDIErrNone) - goto bail; - //DumpVTOC(); + dierr = ReadVTOC(); + if (dierr != kDIErrNone) + goto bail; + //DumpVTOC(); - dierr = ScanVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + dierr = ScanVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - if (initMode == kInitHeaderOnly) { - WMSG0(" DOS - headerOnly set, skipping file load\n"); - goto bail; - } + if (initMode == kInitHeaderOnly) { + WMSG0(" DOS - headerOnly set, skipping file load\n"); + goto bail; + } - /* read the contents of the catalog, creating our A2File list */ - dierr = ReadCatalog(); - if (dierr != kDIErrNone) - goto bail; + /* read the contents of the catalog, creating our A2File list */ + dierr = ReadCatalog(); + if (dierr != kDIErrNone) + goto bail; - /* run through and get file lengths and data offsets */ - dierr = GetFileLengths(); - if (dierr != kDIErrNone) - goto bail; + /* run through and get file lengths and data offsets */ + dierr = GetFileLengths(); + if (dierr != kDIErrNone) + goto bail; - /* mark DOS tracks appropriately */ - FixVolumeUsageMap(); + /* mark DOS tracks appropriately */ + FixVolumeUsageMap(); - fDiskIsGood = CheckDiskIsGood(); + fDiskIsGood = CheckDiskIsGood(); - fVolumeUsage.Dump(); + fVolumeUsage.Dump(); -// A2File* pFile; -// pFile = GetNextFile(nil); -// while (pFile != nil) { -// pFile->Dump(); -// pFile = GetNextFile(pFile); -// } +// A2File* pFile; +// pFile = GetNextFile(nil); +// while (pFile != nil) { +// pFile->Dump(); +// pFile = GetNextFile(pFile); +// } bail: - return dierr; + return dierr; } /* @@ -253,38 +253,38 @@ bail: DIError DiskFSDOS33::ReadVTOC(void) { - DIError dierr; + DIError dierr; - dierr = LoadVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + dierr = LoadVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - fFirstCatTrack = fVTOC[0x01]; - fFirstCatSector = fVTOC[0x02]; - fVTOCVolumeNumber = fVTOC[0x06]; - fVTOCNumTracks = fVTOC[0x34]; - fVTOCNumSectors = fVTOC[0x35]; + fFirstCatTrack = fVTOC[0x01]; + fFirstCatSector = fVTOC[0x02]; + fVTOCVolumeNumber = fVTOC[0x06]; + fVTOCNumTracks = fVTOC[0x34]; + fVTOCNumSectors = fVTOC[0x35]; - if (fFirstCatTrack >= fpImg->GetNumTracks()) - return kDIErrBadDiskImage; - if (fFirstCatSector >= fpImg->GetNumSectPerTrack()) - return kDIErrBadDiskImage; + if (fFirstCatTrack >= fpImg->GetNumTracks()) + return kDIErrBadDiskImage; + if (fFirstCatSector >= fpImg->GetNumSectPerTrack()) + return kDIErrBadDiskImage; - if (fVTOCNumTracks != fpImg->GetNumTracks()) { - WMSG2(" DOS33 warning: VTOC numtracks %d vs %ld\n", - fVTOCNumTracks, fpImg->GetNumTracks()); - } - if (fVTOCNumSectors != fpImg->GetNumSectPerTrack()) { - WMSG2(" DOS33 warning: VTOC numsect %d vs %d\n", - fVTOCNumSectors, fpImg->GetNumSectPerTrack()); - } + if (fVTOCNumTracks != fpImg->GetNumTracks()) { + WMSG2(" DOS33 warning: VTOC numtracks %d vs %ld\n", + fVTOCNumTracks, fpImg->GetNumTracks()); + } + if (fVTOCNumSectors != fpImg->GetNumSectPerTrack()) { + WMSG2(" DOS33 warning: VTOC numsect %d vs %d\n", + fVTOCNumSectors, fpImg->GetNumSectPerTrack()); + } - // call SetDiskVolumeNum with the appropriate thing - UpdateVolumeNum(); + // call SetDiskVolumeNum with the appropriate thing + UpdateVolumeNum(); bail: - FreeVolBitmap(); - return dierr; + FreeVolBitmap(); + return dierr; } /* @@ -294,15 +294,15 @@ bail: void DiskFSDOS33::UpdateVolumeNum(void) { - /* use the sector-embedded volume number, if available */ - if (fpImg->GetDOSVolumeNum() == DiskImg::kVolumeNumNotSet) - SetDiskVolumeNum(fVTOCVolumeNumber); - else - SetDiskVolumeNum(fpImg->GetDOSVolumeNum()); - if (fDiskVolumeNum != fVTOCVolumeNumber) { - WMSG2(" NOTE: ignoring VTOC vol (%d) in favor of embedded (%d)\n", - fVTOCVolumeNumber, fDiskVolumeNum); - } + /* use the sector-embedded volume number, if available */ + if (fpImg->GetDOSVolumeNum() == DiskImg::kVolumeNumNotSet) + SetDiskVolumeNum(fVTOCVolumeNumber); + else + SetDiskVolumeNum(fpImg->GetDOSVolumeNum()); + if (fDiskVolumeNum != fVTOCVolumeNumber) { + WMSG2(" NOTE: ignoring VTOC vol (%d) in favor of embedded (%d)\n", + fVTOCVolumeNumber, fDiskVolumeNum); + } } /* @@ -311,19 +311,19 @@ DiskFSDOS33::UpdateVolumeNum(void) void DiskFSDOS33::SetDiskVolumeNum(int val) { - if (val < 0 || val > 255) { - // Actual valid range should be 1-254, but it's possible for a - // sector edit to put invalid stuff here. It's just one byte - // though, so 0-255 should be guaranteed. - assert(false); - return; - } - fDiskVolumeNum = val; - sprintf(fDiskVolumeName, "DOS%03d", fDiskVolumeNum); - if (fpImg->GetFSFormat() == DiskImg::kFormatDOS32) - sprintf(fDiskVolumeID, "DOS 3.2 Volume %03d", fDiskVolumeNum); - else - sprintf(fDiskVolumeID, "DOS 3.3 Volume %03d", fDiskVolumeNum); + if (val < 0 || val > 255) { + // Actual valid range should be 1-254, but it's possible for a + // sector edit to put invalid stuff here. It's just one byte + // though, so 0-255 should be guaranteed. + assert(false); + return; + } + fDiskVolumeNum = val; + sprintf(fDiskVolumeName, "DOS%03d", fDiskVolumeNum); + if (fpImg->GetFSFormat() == DiskImg::kFormatDOS32) + sprintf(fDiskVolumeID, "DOS 3.2 Volume %03d", fDiskVolumeNum); + else + sprintf(fDiskVolumeID, "DOS 3.3 Volume %03d", fDiskVolumeNum); } @@ -334,10 +334,10 @@ void DiskFSDOS33::DumpVTOC(void) { - WMSG2("VTOC catalog: track=%d sector=%d\n", - fFirstCatTrack, fFirstCatSector); - WMSG3(" volnum=%d numTracks=%d numSects=%d\n", - fVTOCVolumeNumber, fVTOCNumTracks, fVTOCNumSectors); + WMSG2("VTOC catalog: track=%d sector=%d\n", + fFirstCatTrack, fFirstCatSector); + WMSG3(" volnum=%d numTracks=%d numSects=%d\n", + fVTOCVolumeNumber, fVTOCNumTracks, fVTOCNumSectors); } /* @@ -345,21 +345,21 @@ DiskFSDOS33::DumpVTOC(void) */ void DiskFSDOS33::SetSectorUsage(long track, long sector, - VolumeUsage::ChunkPurpose purpose) + VolumeUsage::ChunkPurpose purpose) { - VolumeUsage::ChunkState cstate; + VolumeUsage::ChunkState cstate; - //WMSG3(" DOS setting usage %d,%d to %d\n", track, sector, purpose); + //WMSG3(" DOS setting usage %d,%d to %d\n", track, sector, purpose); - fVolumeUsage.GetChunkState(track, sector, &cstate); - if (cstate.isUsed) { - cstate.purpose = VolumeUsage::kChunkPurposeConflict; -// WMSG2(" DOS conflicting uses for t=%d s=%d\n", track, sector); - } else { - cstate.isUsed = true; - cstate.purpose = purpose; - } - fVolumeUsage.SetChunkState(track, sector, &cstate); + fVolumeUsage.GetChunkState(track, sector, &cstate); + if (cstate.isUsed) { + cstate.purpose = VolumeUsage::kChunkPurposeConflict; +// WMSG2(" DOS conflicting uses for t=%d s=%d\n", track, sector); + } else { + cstate.isUsed = true; + cstate.purpose = purpose; + } + fVolumeUsage.SetChunkState(track, sector, &cstate); } /* @@ -381,52 +381,52 @@ DiskFSDOS33::SetSectorUsage(long track, long sector, DIError DiskFSDOS33::ScanVolBitmap(void) { - DIError dierr; - VolumeUsage::ChunkState cstate; - char freemap[32+1] = "--------------------------------"; + DIError dierr; + VolumeUsage::ChunkState cstate; + char freemap[32+1] = "--------------------------------"; - cstate.isUsed = false; - cstate.isMarkedUsed = true; - cstate.purpose = (VolumeUsage::ChunkPurpose) 0; + cstate.isUsed = false; + cstate.isMarkedUsed = true; + cstate.purpose = (VolumeUsage::ChunkPurpose) 0; - dierr = LoadVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + dierr = LoadVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - WMSG0(" map 0123456789abcdef\n"); + WMSG0(" map 0123456789abcdef\n"); - int i; - for (i = 0; i < kMaxTracks; i++) { - unsigned long val, origVal; - int bit; + int i; + for (i = 0; i < kMaxTracks; i++) { + unsigned long val, origVal; + int bit; - val = (unsigned long) fVTOC[0x38 + i*4] << 24; - val |= (unsigned long) fVTOC[0x39 + i*4] << 16; - val |= (unsigned long) fVTOC[0x3a + i*4] << 8; - val |= (unsigned long) fVTOC[0x3b + i*4]; - origVal = val; + val = (unsigned long) fVTOC[0x38 + i*4] << 24; + val |= (unsigned long) fVTOC[0x39 + i*4] << 16; + val |= (unsigned long) fVTOC[0x3a + i*4] << 8; + val |= (unsigned long) fVTOC[0x3b + i*4]; + origVal = val; - /* init the VolumeUsage stuff */ - for (bit = fpImg->GetNumSectPerTrack()-1; bit >= 0; bit--) { - freemap[bit] = val & 0x80000000 ? '.' : 'X'; + /* init the VolumeUsage stuff */ + for (bit = fpImg->GetNumSectPerTrack()-1; bit >= 0; bit--) { + freemap[bit] = val & 0x80000000 ? '.' : 'X'; - if (i < fpImg->GetNumTracks() && !(val & 0x80000000)) { - /* mark the sector as in-use */ - if (fVolumeUsage.SetChunkState(i, bit, &cstate) != kDIErrNone) { - assert(false); - } - } - val <<= 1; - } - WMSG3(" %2d: %s (0x%08lx)\n", i, freemap, origVal); - } + if (i < fpImg->GetNumTracks() && !(val & 0x80000000)) { + /* mark the sector as in-use */ + if (fVolumeUsage.SetChunkState(i, bit, &cstate) != kDIErrNone) { + assert(false); + } + } + val <<= 1; + } + WMSG3(" %2d: %s (0x%08lx)\n", i, freemap, origVal); + } - /* we know the VTOC is used, so mark it now */ - SetSectorUsage(kVTOCTrack, kVTOCSector, VolumeUsage::kChunkPurposeVolumeDir); + /* we know the VTOC is used, so mark it now */ + SetSectorUsage(kVTOCTrack, kVTOCSector, VolumeUsage::kChunkPurposeVolumeDir); bail: - FreeVolBitmap(); - return dierr; + FreeVolBitmap(); + return dierr; } @@ -436,16 +436,16 @@ bail: DIError DiskFSDOS33::LoadVolBitmap(void) { - DIError dierr; + DIError dierr; - assert(!fVTOCLoaded); + assert(!fVTOCLoaded); - dierr = fpImg->ReadTrackSector(kVTOCTrack, kVTOCSector, fVTOC); - if (dierr != kDIErrNone) - return dierr; + dierr = fpImg->ReadTrackSector(kVTOCTrack, kVTOCSector, fVTOC); + if (dierr != kDIErrNone) + return dierr; - fVTOCLoaded = true; - return kDIErrNone; + fVTOCLoaded = true; + return kDIErrNone; } /* @@ -454,12 +454,12 @@ DiskFSDOS33::LoadVolBitmap(void) DIError DiskFSDOS33::SaveVolBitmap(void) { - if (!fVTOCLoaded) { - assert(false); - return kDIErrNotReady; - } + if (!fVTOCLoaded) { + assert(false); + return kDIErrNotReady; + } - return fpImg->WriteTrackSector(kVTOCTrack, kVTOCSector, fVTOC); + return fpImg->WriteTrackSector(kVTOCTrack, kVTOCSector, fVTOC); } /* @@ -470,10 +470,10 @@ DiskFSDOS33::SaveVolBitmap(void) void DiskFSDOS33::FreeVolBitmap(void) { - fVTOCLoaded = false; + fVTOCLoaded = false; #ifdef _DEBUG - memset(fVTOC, 0x99, sizeof(fVTOC)); + memset(fVTOC, 0x99, sizeof(fVTOC)); #endif } @@ -483,13 +483,13 @@ DiskFSDOS33::FreeVolBitmap(void) inline unsigned long DiskFSDOS33::GetVTOCEntry(const unsigned char* pVTOC, long track) const { - unsigned long val; - val = (unsigned long) pVTOC[0x38 + track*4] << 24; - val |= (unsigned long) pVTOC[0x39 + track*4] << 16; - val |= (unsigned long) pVTOC[0x3a + track*4] << 8; - val |= (unsigned long) pVTOC[0x3b + track*4]; + unsigned long val; + val = (unsigned long) pVTOC[0x38 + track*4] << 24; + val |= (unsigned long) pVTOC[0x39 + track*4] << 16; + val |= (unsigned long) pVTOC[0x3a + track*4] << 8; + val |= (unsigned long) pVTOC[0x3b + track*4]; - return val; + return val; } /* @@ -500,83 +500,83 @@ DiskFSDOS33::GetVTOCEntry(const unsigned char* pVTOC, long track) const DIError DiskFSDOS33::AllocSector(TrackSector* pTS) { - unsigned long val; - unsigned long mask; - long track, numSectPerTrack; + unsigned long val; + unsigned long mask; + long track, numSectPerTrack; - /* we could compute "mask", but it's faster and easier to do this */ - numSectPerTrack = GetDiskImg()->GetNumSectPerTrack(); - if (numSectPerTrack == 13) - mask = 0xfff80000; - else if (numSectPerTrack == 16) - mask = 0xffff0000; - else if (numSectPerTrack == 32) - mask = 0xffffffff; - else { - assert(false); - return kDIErrInternal; - } + /* we could compute "mask", but it's faster and easier to do this */ + numSectPerTrack = GetDiskImg()->GetNumSectPerTrack(); + if (numSectPerTrack == 13) + mask = 0xfff80000; + else if (numSectPerTrack == 16) + mask = 0xffff0000; + else if (numSectPerTrack == 32) + mask = 0xffffffff; + else { + assert(false); + return kDIErrInternal; + } - /* - * Start by finding a track with a free sector. We know it's free - * because the bits aren't all zero. - * - * In theory we don't need "mask", because the DOS format routine is - * good about leaving the unused bits clear, and nobody else disturbs - * them. However, it's best not to rely on it. - */ - for (track = kVTOCTrack; track > 0; track--) { - val = GetVTOCEntry(fVTOC, track); - if ((val & mask) != 0) - break; - } - if (track == 0) { - long numTracks = GetDiskImg()->GetNumTracks(); - for (track = kVTOCTrack; track < numTracks; track++) - { - val = GetVTOCEntry(fVTOC, track); - if ((val & mask) != 0) - break; - } - if (track == numTracks) { - WMSG0("DOS33 AllocSector unable to find empty sector\n"); - return kDIErrDiskFull; - } - } + /* + * Start by finding a track with a free sector. We know it's free + * because the bits aren't all zero. + * + * In theory we don't need "mask", because the DOS format routine is + * good about leaving the unused bits clear, and nobody else disturbs + * them. However, it's best not to rely on it. + */ + for (track = kVTOCTrack; track > 0; track--) { + val = GetVTOCEntry(fVTOC, track); + if ((val & mask) != 0) + break; + } + if (track == 0) { + long numTracks = GetDiskImg()->GetNumTracks(); + for (track = kVTOCTrack; track < numTracks; track++) + { + val = GetVTOCEntry(fVTOC, track); + if ((val & mask) != 0) + break; + } + if (track == numTracks) { + WMSG0("DOS33 AllocSector unable to find empty sector\n"); + return kDIErrDiskFull; + } + } - /* - * We've got the track. Now find the first free sector. - */ - int sector; - sector = numSectPerTrack-1; - while (sector >= 0) { - if (val & 0x80000000) { - //WMSG2("+++ allocating T=%d S=%d\n", track, sector); - SetSectorUseEntry(track, sector, true); - break; - } + /* + * We've got the track. Now find the first free sector. + */ + int sector; + sector = numSectPerTrack-1; + while (sector >= 0) { + if (val & 0x80000000) { + //WMSG2("+++ allocating T=%d S=%d\n", track, sector); + SetSectorUseEntry(track, sector, true); + break; + } - val <<= 1; - sector--; - } - if (sector < 0) { - assert(false); - return kDIErrInternal; // should not have failed - } + val <<= 1; + sector--; + } + if (sector < 0) { + assert(false); + return kDIErrInternal; // should not have failed + } - /* - * Mostly for fun, update the VTOC allocation thingy. - */ - fVTOC[0x30] = (unsigned char) track; // last track where alloc happened - if (track < kVTOCTrack) - fVTOC[0x31] = 0xff; // descending - else - fVTOC[0x31] = 0x01; // ascending + /* + * Mostly for fun, update the VTOC allocation thingy. + */ + fVTOC[0x30] = (unsigned char) track; // last track where alloc happened + if (track < kVTOCTrack) + fVTOC[0x31] = 0xff; // descending + else + fVTOC[0x31] = 0x01; // ascending - pTS->track = (char) track; - pTS->sector = (char) sector; + pTS->track = (char) track; + pTS->sector = (char) sector; - return kDIErrNone; + return kDIErrNone; } /* @@ -587,39 +587,39 @@ DiskFSDOS33::AllocSector(TrackSector* pTS) DIError DiskFSDOS33::CreateEmptyBlockMap(bool withDOS) { - DIError dierr; - long track, sector, maxTrack; + DIError dierr; + long track, sector, maxTrack; - dierr = LoadVolBitmap(); - if (dierr != kDIErrNone) - return dierr; + dierr = LoadVolBitmap(); + if (dierr != kDIErrNone) + return dierr; - if (withDOS) - maxTrack = 3; - else - maxTrack = 1; + if (withDOS) + maxTrack = 3; + else + maxTrack = 1; - /* - * Set each bit individually. Slower, but exercises standard functions. - * - * Clear all "in use" flags, except for track 0, track 17, and (if - * withDOS is set) tracks 1 and 2. - */ - for (track = fpImg->GetNumTracks()-1; track >= 0; track--) { - for (sector = fpImg->GetNumSectPerTrack()-1; sector >= 0; sector--) { - if (track < maxTrack || track == kVTOCTrack) - SetSectorUseEntry(track, sector, true); - else - SetSectorUseEntry(track, sector, false); - } - } + /* + * Set each bit individually. Slower, but exercises standard functions. + * + * Clear all "in use" flags, except for track 0, track 17, and (if + * withDOS is set) tracks 1 and 2. + */ + for (track = fpImg->GetNumTracks()-1; track >= 0; track--) { + for (sector = fpImg->GetNumSectPerTrack()-1; sector >= 0; sector--) { + if (track < maxTrack || track == kVTOCTrack) + SetSectorUseEntry(track, sector, true); + else + SetSectorUseEntry(track, sector, false); + } + } - dierr = SaveVolBitmap(); - FreeVolBitmap(); - if (dierr != kDIErrNone) - return dierr; + dierr = SaveVolBitmap(); + FreeVolBitmap(); + if (dierr != kDIErrNone) + return dierr; - return kDIErrNone; + return kDIErrNone; } /* @@ -630,26 +630,26 @@ DiskFSDOS33::CreateEmptyBlockMap(bool withDOS) bool DiskFSDOS33::GetSectorUseEntry(long track, int sector) const { - assert(fVTOCLoaded); - assert(track >= 0 && track < fpImg->GetNumTracks()); - assert(sector >= 0 && sector < fpImg->GetNumSectPerTrack()); + assert(fVTOCLoaded); + assert(track >= 0 && track < fpImg->GetNumTracks()); + assert(sector >= 0 && sector < fpImg->GetNumSectPerTrack()); - unsigned long val, mask; + unsigned long val, mask; - val = GetVTOCEntry(fVTOC, track); - //val = (unsigned long) fVTOC[0x38 + track*4] << 24; - //val |= (unsigned long) fVTOC[0x39 + track*4] << 16; - //val |= (unsigned long) fVTOC[0x3a + track*4] << 8; - //val |= (unsigned long) fVTOC[0x3b + track*4]; + val = GetVTOCEntry(fVTOC, track); + //val = (unsigned long) fVTOC[0x38 + track*4] << 24; + //val |= (unsigned long) fVTOC[0x39 + track*4] << 16; + //val |= (unsigned long) fVTOC[0x3a + track*4] << 8; + //val |= (unsigned long) fVTOC[0x3b + track*4]; - /* - * The highest-numbered sector is now in the high bit. If this is a - * 16-sector disk, the high bit holds the state of sector 15. - * - * A '1' indicates the sector is free, '0' indicates it's in use. - */ - mask = 1L << (32 - fpImg->GetNumSectPerTrack() + sector); - return (val & mask) == 0; + /* + * The highest-numbered sector is now in the high bit. If this is a + * 16-sector disk, the high bit holds the state of sector 15. + * + * A '1' indicates the sector is free, '0' indicates it's in use. + */ + mask = 1L << (32 - fpImg->GetNumSectPerTrack() + sector); + return (val & mask) == 0; } /* @@ -658,25 +658,25 @@ DiskFSDOS33::GetSectorUseEntry(long track, int sector) const void DiskFSDOS33::SetSectorUseEntry(long track, int sector, bool inUse) { - assert(fVTOCLoaded); - assert(track >= 0 && track < fpImg->GetNumTracks()); - assert(sector >= 0 && sector < fpImg->GetNumSectPerTrack()); + assert(fVTOCLoaded); + assert(track >= 0 && track < fpImg->GetNumTracks()); + assert(sector >= 0 && sector < fpImg->GetNumSectPerTrack()); - unsigned long val, mask; + unsigned long val, mask; - val = GetVTOCEntry(fVTOC, track); + val = GetVTOCEntry(fVTOC, track); - /* highest sector is always in the high bit */ - mask = 1L << (32 - fpImg->GetNumSectPerTrack() + sector); - if (inUse) - val &= ~mask; - else - val |= mask; + /* highest sector is always in the high bit */ + mask = 1L << (32 - fpImg->GetNumSectPerTrack() + sector); + if (inUse) + val &= ~mask; + else + val |= mask; - fVTOC[0x38 + track*4] = (unsigned char) (val >> 24); - fVTOC[0x39 + track*4] = (unsigned char) (val >> 16); - fVTOC[0x3a + track*4] = (unsigned char) (val >> 8); - fVTOC[0x3b + track*4] = (unsigned char) val; + fVTOC[0x38 + track*4] = (unsigned char) (val >> 24); + fVTOC[0x39 + track*4] = (unsigned char) (val >> 16); + fVTOC[0x3a + track*4] = (unsigned char) (val >> 8); + fVTOC[0x3b + track*4] = (unsigned char) val; } @@ -685,30 +685,30 @@ DiskFSDOS33::SetSectorUseEntry(long track, int sector, bool inUse) */ DIError DiskFSDOS33::GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const + int* pUnitSize) const { - DIError dierr; - long track, sector, freeSectors; + DIError dierr; + long track, sector, freeSectors; - dierr = const_cast(this)->LoadVolBitmap(); - if (dierr != kDIErrNone) - return dierr; + dierr = const_cast(this)->LoadVolBitmap(); + if (dierr != kDIErrNone) + return dierr; - freeSectors = 0; - for (track = GetDiskImg()->GetNumTracks()-1; track >= 0; track--) { - for (sector = GetDiskImg()->GetNumSectPerTrack()-1; sector >= 0; sector--) - { - if (!GetSectorUseEntry(track, sector)) - freeSectors++; - } - } + freeSectors = 0; + for (track = GetDiskImg()->GetNumTracks()-1; track >= 0; track--) { + for (sector = GetDiskImg()->GetNumSectPerTrack()-1; sector >= 0; sector--) + { + if (!GetSectorUseEntry(track, sector)) + freeSectors++; + } + } - *pTotalUnits = fpImg->GetNumTracks() * fpImg->GetNumSectPerTrack(); - *pFreeUnits = freeSectors; - *pUnitSize = kSectorSize; + *pTotalUnits = fpImg->GetNumTracks() * fpImg->GetNumSectPerTrack(); + *pFreeUnits = freeSectors; + *pUnitSize = kSectorSize; - const_cast(this)->FreeVolBitmap(); - return kDIErrNone; + const_cast(this)->FreeVolBitmap(); + return kDIErrNone; } @@ -723,19 +723,19 @@ DiskFSDOS33::GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, void DiskFSDOS33::FixVolumeUsageMap(void) { - VolumeUsage::ChunkState cstate; - int track, sector; + VolumeUsage::ChunkState cstate; + int track, sector; - for (track = 0; track < 3; track++) { - for (sector = 0; sector < fpImg->GetNumSectPerTrack(); sector++) { - fVolumeUsage.GetChunkState(track, sector, &cstate); - if (cstate.isMarkedUsed && !cstate.isUsed) { - cstate.isUsed = true; - cstate.purpose = VolumeUsage::kChunkPurposeSystem; - fVolumeUsage.SetChunkState(track, sector, &cstate); - } - } - } + for (track = 0; track < 3; track++) { + for (sector = 0; sector < fpImg->GetNumSectPerTrack(); sector++) { + fVolumeUsage.GetChunkState(track, sector, &cstate); + if (cstate.isMarkedUsed && !cstate.isUsed) { + cstate.isUsed = true; + cstate.purpose = VolumeUsage::kChunkPurposeSystem; + fVolumeUsage.SetChunkState(track, sector, &cstate); + } + } + } } @@ -752,67 +752,67 @@ DiskFSDOS33::FixVolumeUsageMap(void) DIError DiskFSDOS33::ReadCatalog(void) { - DIError dierr = kDIErrNone; - unsigned char sctBuf[kSctSize]; - int catTrack, catSect; - int iterations; + DIError dierr = kDIErrNone; + unsigned char sctBuf[kSctSize]; + int catTrack, catSect; + int iterations; - catTrack = fFirstCatTrack; - catSect = fFirstCatSector; - iterations = 0; + catTrack = fFirstCatTrack; + catSect = fFirstCatSector; + iterations = 0; - memset(fCatalogSectors, 0, sizeof(fCatalogSectors)); + memset(fCatalogSectors, 0, sizeof(fCatalogSectors)); - while (catTrack != 0 && catSect != 0 && iterations < kMaxCatalogSectors) - { - SetSectorUsage(catTrack, catSect, VolumeUsage::kChunkPurposeVolumeDir); + while (catTrack != 0 && catSect != 0 && iterations < kMaxCatalogSectors) + { + SetSectorUsage(catTrack, catSect, VolumeUsage::kChunkPurposeVolumeDir); - WMSG2(" DOS33 reading catalog sector T=%d S=%d\n", catTrack, catSect); - dierr = fpImg->ReadTrackSector(catTrack, catSect, sctBuf); - if (dierr != kDIErrNone) - goto bail; + WMSG2(" DOS33 reading catalog sector T=%d S=%d\n", catTrack, catSect); + dierr = fpImg->ReadTrackSector(catTrack, catSect, sctBuf); + if (dierr != kDIErrNone) + goto bail; - /* - * Watch for flaws that the DOS detector allows. - */ - if (catTrack == sctBuf[0x01] && catSect == sctBuf[0x02]) { - WMSG2(" DOS detected self-reference on cat (%d,%d)\n", - catTrack, catSect); - break; - } + /* + * Watch for flaws that the DOS detector allows. + */ + if (catTrack == sctBuf[0x01] && catSect == sctBuf[0x02]) { + WMSG2(" DOS detected self-reference on cat (%d,%d)\n", + catTrack, catSect); + break; + } - /* - * Check the next track/sector in the chain. If the pointer is - * broken, there's a very good chance that this isn't really a - * catalog sector, so we want to bail out now. - */ - if (sctBuf[0x01] >= fpImg->GetNumTracks() || - sctBuf[0x02] >= fpImg->GetNumSectPerTrack()) - { - WMSG0(" DOS bailing out early on catalog read due to funky T/S\n"); - break; - } + /* + * Check the next track/sector in the chain. If the pointer is + * broken, there's a very good chance that this isn't really a + * catalog sector, so we want to bail out now. + */ + if (sctBuf[0x01] >= fpImg->GetNumTracks() || + sctBuf[0x02] >= fpImg->GetNumSectPerTrack()) + { + WMSG0(" DOS bailing out early on catalog read due to funky T/S\n"); + break; + } - dierr = ProcessCatalogSector(catTrack, catSect, sctBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = ProcessCatalogSector(catTrack, catSect, sctBuf); + if (dierr != kDIErrNone) + goto bail; - fCatalogSectors[iterations].track = catTrack; - fCatalogSectors[iterations].sector = catSect; + fCatalogSectors[iterations].track = catTrack; + fCatalogSectors[iterations].sector = catSect; - catTrack = sctBuf[0x01]; - catSect = sctBuf[0x02]; + catTrack = sctBuf[0x01]; + catSect = sctBuf[0x02]; - iterations++; // watch for infinite loops + iterations++; // watch for infinite loops - } - if (iterations >= kMaxCatalogSectors) { - dierr = kDIErrDirectoryLoop; - goto bail; - } + } + if (iterations >= kMaxCatalogSectors) { + dierr = kDIErrDirectoryLoop; + goto bail; + } bail: - return dierr; + return dierr; } /* @@ -823,63 +823,63 @@ bail: */ DIError DiskFSDOS33::ProcessCatalogSector(int catTrack, int catSect, - const unsigned char* sctBuf) + const unsigned char* sctBuf) { - A2FileDOS* pFile; - const unsigned char* pEntry; - int i; + A2FileDOS* pFile; + const unsigned char* pEntry; + int i; - pEntry = &sctBuf[kCatalogEntryOffset]; + pEntry = &sctBuf[kCatalogEntryOffset]; - for (i = 0; i < kCatalogEntriesPerSect; i++) { - if (pEntry[0x00] != kEntryUnused && pEntry[0x00] != kEntryDeleted) { - pFile = new A2FileDOS(this); + for (i = 0; i < kCatalogEntriesPerSect; i++) { + if (pEntry[0x00] != kEntryUnused && pEntry[0x00] != kEntryDeleted) { + pFile = new A2FileDOS(this); - pFile->SetQuality(A2File::kQualityGood); + pFile->SetQuality(A2File::kQualityGood); - pFile->fTSListTrack = pEntry[0x00]; - pFile->fTSListSector = pEntry[0x01]; - pFile->fLocked = (pEntry[0x02] & 0x80) != 0; - switch (pEntry[0x02] & 0x7f) { - case 0x00: pFile->fFileType = A2FileDOS::kTypeText; break; - case 0x01: pFile->fFileType = A2FileDOS::kTypeInteger; break; - case 0x02: pFile->fFileType = A2FileDOS::kTypeApplesoft; break; - case 0x04: pFile->fFileType = A2FileDOS::kTypeBinary; break; - case 0x08: pFile->fFileType = A2FileDOS::kTypeS; break; - case 0x10: pFile->fFileType = A2FileDOS::kTypeReloc; break; - case 0x20: pFile->fFileType = A2FileDOS::kTypeA; break; - case 0x40: pFile->fFileType = A2FileDOS::kTypeB; break; - default: - /* some odd arrangement of bit flags? */ - WMSG1(" DOS33 peculiar filetype byte 0x%02x\n", pEntry[0x02]); - pFile->fFileType = A2FileDOS::kTypeUnknown; - pFile->SetQuality(A2File::kQualitySuspicious); - break; - } + pFile->fTSListTrack = pEntry[0x00]; + pFile->fTSListSector = pEntry[0x01]; + pFile->fLocked = (pEntry[0x02] & 0x80) != 0; + switch (pEntry[0x02] & 0x7f) { + case 0x00: pFile->fFileType = A2FileDOS::kTypeText; break; + case 0x01: pFile->fFileType = A2FileDOS::kTypeInteger; break; + case 0x02: pFile->fFileType = A2FileDOS::kTypeApplesoft; break; + case 0x04: pFile->fFileType = A2FileDOS::kTypeBinary; break; + case 0x08: pFile->fFileType = A2FileDOS::kTypeS; break; + case 0x10: pFile->fFileType = A2FileDOS::kTypeReloc; break; + case 0x20: pFile->fFileType = A2FileDOS::kTypeA; break; + case 0x40: pFile->fFileType = A2FileDOS::kTypeB; break; + default: + /* some odd arrangement of bit flags? */ + WMSG1(" DOS33 peculiar filetype byte 0x%02x\n", pEntry[0x02]); + pFile->fFileType = A2FileDOS::kTypeUnknown; + pFile->SetQuality(A2File::kQualitySuspicious); + break; + } - memcpy(pFile->fFileName, &pEntry[0x03], A2FileDOS::kMaxFileName); - pFile->fFileName[A2FileDOS::kMaxFileName] = '\0'; - pFile->FixFilename(); + memcpy(pFile->fFileName, &pEntry[0x03], A2FileDOS::kMaxFileName); + pFile->fFileName[A2FileDOS::kMaxFileName] = '\0'; + pFile->FixFilename(); - pFile->fLengthInSectors = pEntry[0x21]; - pFile->fLengthInSectors |= (unsigned short) pEntry[0x22] << 8; + pFile->fLengthInSectors = pEntry[0x21]; + pFile->fLengthInSectors |= (unsigned short) pEntry[0x22] << 8; - pFile->fCatTS.track = catTrack; - pFile->fCatTS.sector = catSect; - pFile->fCatEntryNum = i; + pFile->fCatTS.track = catTrack; + pFile->fCatTS.sector = catSect; + pFile->fCatEntryNum = i; - /* can't do these yet, so just set to defaults */ - pFile->fLength = 0; - pFile->fSparseLength = 0; - pFile->fDataOffset = 0; + /* can't do these yet, so just set to defaults */ + pFile->fLength = 0; + pFile->fSparseLength = 0; + pFile->fDataOffset = 0; - AddFileToList(pFile); - } + AddFileToList(pFile); + } - pEntry += kCatalogEntrySize; - } + pEntry += kCatalogEntrySize; + } - return kDIErrNone; + return kDIErrNone; } @@ -891,102 +891,102 @@ DiskFSDOS33::ProcessCatalogSector(int catTrack, int catSect, bool DiskFSDOS33::CheckDiskIsGood(void) { - DIError dierr; - const DiskImg* pDiskImg = GetDiskImg(); - bool result = true; - int i; + DIError dierr; + const DiskImg* pDiskImg = GetDiskImg(); + bool result = true; + int i; - dierr = LoadVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + dierr = LoadVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - /* - * Make sure the VTOC is marked in use, or things could go badly. - * Ditto for the catalog tracks. - */ - if (!GetSectorUseEntry(kVTOCTrack, kVTOCSector)) { - fpImg->AddNote(DiskImg::kNoteWarning, "VTOC sector marked as free."); - result = false; - } - for (i = 0; i < kMaxCatalogSectors; i++) { - if (!GetSectorUseEntry(fCatalogSectors[i].track, - fCatalogSectors[i].sector)) - { - fpImg->AddNote(DiskImg::kNoteWarning, - "Catalog sector %d,%d is marked as free.", - fCatalogSectors[i].track, fCatalogSectors[i].sector); - result = false; - } - } + /* + * Make sure the VTOC is marked in use, or things could go badly. + * Ditto for the catalog tracks. + */ + if (!GetSectorUseEntry(kVTOCTrack, kVTOCSector)) { + fpImg->AddNote(DiskImg::kNoteWarning, "VTOC sector marked as free."); + result = false; + } + for (i = 0; i < kMaxCatalogSectors; i++) { + if (!GetSectorUseEntry(fCatalogSectors[i].track, + fCatalogSectors[i].sector)) + { + fpImg->AddNote(DiskImg::kNoteWarning, + "Catalog sector %d,%d is marked as free.", + fCatalogSectors[i].track, fCatalogSectors[i].sector); + result = false; + } + } - /* - * Check for used blocks that aren't marked in-use. - * - * This requires that VolumeUsage be accurate. Since this function is - * only run during initial startup, any later deviation between VU and - * the block use map is irrelevant. - */ - VolumeUsage::ChunkState cstate; - long track, sector; - long notMarked, extraUsed, conflicts; - notMarked = extraUsed = conflicts = 0; - for (track = 0; track < pDiskImg->GetNumTracks(); track++) { - for (sector = 0; sector < pDiskImg->GetNumSectPerTrack(); sector++) { - dierr = fVolumeUsage.GetChunkState(track, sector, &cstate); - if (dierr != kDIErrNone) { - fpImg->AddNote(DiskImg::kNoteWarning, - "Internal volume usage error on t=%ld s=%ld.", - track, sector); - result = false; - goto bail; - } + /* + * Check for used blocks that aren't marked in-use. + * + * This requires that VolumeUsage be accurate. Since this function is + * only run during initial startup, any later deviation between VU and + * the block use map is irrelevant. + */ + VolumeUsage::ChunkState cstate; + long track, sector; + long notMarked, extraUsed, conflicts; + notMarked = extraUsed = conflicts = 0; + for (track = 0; track < pDiskImg->GetNumTracks(); track++) { + for (sector = 0; sector < pDiskImg->GetNumSectPerTrack(); sector++) { + dierr = fVolumeUsage.GetChunkState(track, sector, &cstate); + if (dierr != kDIErrNone) { + fpImg->AddNote(DiskImg::kNoteWarning, + "Internal volume usage error on t=%ld s=%ld.", + track, sector); + result = false; + goto bail; + } - if (cstate.isUsed && !cstate.isMarkedUsed) - notMarked++; - if (!cstate.isUsed && cstate.isMarkedUsed) - extraUsed++; - if (cstate.purpose == VolumeUsage::kChunkPurposeConflict) - conflicts++; - } - } - if (extraUsed > 0) { - fpImg->AddNote(DiskImg::kNoteInfo, - "%ld sector%s marked used but not part of any file.", - extraUsed, extraUsed == 1 ? " is" : "s are"); - // not a problem, really - } - if (notMarked > 0) { - fpImg->AddNote(DiskImg::kNoteWarning, - "%ld sector%s used by files but not marked used.", - notMarked, notMarked == 1 ? " is" : "s are"); - result = false; - } - if (conflicts > 0) { - fpImg->AddNote(DiskImg::kNoteWarning, - "%ld sector%s used by more than one file.", - conflicts, conflicts == 1 ? " is" : "s are"); - result = false; - } + if (cstate.isUsed && !cstate.isMarkedUsed) + notMarked++; + if (!cstate.isUsed && cstate.isMarkedUsed) + extraUsed++; + if (cstate.purpose == VolumeUsage::kChunkPurposeConflict) + conflicts++; + } + } + if (extraUsed > 0) { + fpImg->AddNote(DiskImg::kNoteInfo, + "%ld sector%s marked used but not part of any file.", + extraUsed, extraUsed == 1 ? " is" : "s are"); + // not a problem, really + } + if (notMarked > 0) { + fpImg->AddNote(DiskImg::kNoteWarning, + "%ld sector%s used by files but not marked used.", + notMarked, notMarked == 1 ? " is" : "s are"); + result = false; + } + if (conflicts > 0) { + fpImg->AddNote(DiskImg::kNoteWarning, + "%ld sector%s used by more than one file.", + conflicts, conflicts == 1 ? " is" : "s are"); + result = false; + } - /* - * Scan for "damaged" files or "suspicious" files diagnosed earlier. - */ - bool damaged, suspicious; - ScanForDamagedFiles(&damaged, &suspicious); + /* + * Scan for "damaged" files or "suspicious" files diagnosed earlier. + */ + bool damaged, suspicious; + ScanForDamagedFiles(&damaged, &suspicious); - if (damaged) { - fpImg->AddNote(DiskImg::kNoteWarning, - "One or more files are damaged."); - result = false; - } else if (suspicious) { - fpImg->AddNote(DiskImg::kNoteWarning, - "One or more files look suspicious."); - result = false; - } + if (damaged) { + fpImg->AddNote(DiskImg::kNoteWarning, + "One or more files are damaged."); + result = false; + } else if (suspicious) { + fpImg->AddNote(DiskImg::kNoteWarning, + "One or more files look suspicious."); + result = false; + } bail: - FreeVolBitmap(); - return result; + FreeVolBitmap(); + return result; } @@ -997,45 +997,45 @@ bail: DIError DiskFSDOS33::GetFileLengths(void) { - A2FileDOS* pFile; - TrackSector* tsList = nil; - TrackSector* indexList = nil; - int tsCount; - int indexCount; + A2FileDOS* pFile; + TrackSector* tsList = nil; + TrackSector* indexList = nil; + int tsCount; + int indexCount; - pFile = (A2FileDOS*) GetNextFile(nil); - while (pFile != nil) { - DIError dierr; - dierr = pFile->LoadTSList(&tsList, &tsCount, &indexList, &indexCount); - if (dierr != kDIErrNone) { - WMSG1("DOS failed loading TS list for '%s'\n", - pFile->GetPathName()); - pFile->SetQuality(A2File::kQualityDamaged); - } else { - MarkFileUsage(pFile, tsList, tsCount, indexList, indexCount); - dierr = ComputeLength(pFile, tsList, tsCount); - if (dierr != kDIErrNone) { - WMSG1("DOS unable to get length for '%s'\n", - pFile->GetPathName()); - pFile->SetQuality(A2File::kQualityDamaged); - } - } + pFile = (A2FileDOS*) GetNextFile(nil); + while (pFile != nil) { + DIError dierr; + dierr = pFile->LoadTSList(&tsList, &tsCount, &indexList, &indexCount); + if (dierr != kDIErrNone) { + WMSG1("DOS failed loading TS list for '%s'\n", + pFile->GetPathName()); + pFile->SetQuality(A2File::kQualityDamaged); + } else { + MarkFileUsage(pFile, tsList, tsCount, indexList, indexCount); + dierr = ComputeLength(pFile, tsList, tsCount); + if (dierr != kDIErrNone) { + WMSG1("DOS unable to get length for '%s'\n", + pFile->GetPathName()); + pFile->SetQuality(A2File::kQualityDamaged); + } + } - if (pFile->fLengthInSectors != indexCount + tsCount) { - WMSG3("DOS NOTE: file '%s' has len-in-sect=%d but actual=%d\n", - pFile->GetPathName(), pFile->fLengthInSectors, - indexCount + tsCount); - // expected on sparse random-access text files - } + if (pFile->fLengthInSectors != indexCount + tsCount) { + WMSG3("DOS NOTE: file '%s' has len-in-sect=%d but actual=%d\n", + pFile->GetPathName(), pFile->fLengthInSectors, + indexCount + tsCount); + // expected on sparse random-access text files + } - delete[] tsList; - delete[] indexList; - tsList = indexList = nil; + delete[] tsList; + delete[] indexList; + tsList = indexList = nil; - pFile = (A2FileDOS*) GetNextFile(pFile); - } + pFile = (A2FileDOS*) GetNextFile(pFile); + } - return kDIErrNone; + return kDIErrNone; } /* @@ -1072,129 +1072,129 @@ DiskFSDOS33::GetFileLengths(void) * sectors, we'll get the actual file plus at most 256 garbage bytes. * * On success, we set the following: - * pFile->fLength - * pFile->fSparseLength - * pFile->fDataOffset + * pFile->fLength + * pFile->fSparseLength + * pFile->fDataOffset */ DIError DiskFSDOS33::ComputeLength(A2FileDOS* pFile, const TrackSector* tsList, - int tsCount) + int tsCount) { - DIError dierr = kDIErrNone; - unsigned char sctBuf[kSctSize]; + DIError dierr = kDIErrNone; + unsigned char sctBuf[kSctSize]; - assert(pFile != nil); - assert(tsList != nil); - assert(tsCount >= 0); + assert(pFile != nil); + assert(tsList != nil); + assert(tsCount >= 0); - pFile->fDataOffset = 0; + pFile->fDataOffset = 0; - pFile->fAuxType = 0; - if (pFile->fFileType == A2FileDOS::kTypeApplesoft) - pFile->fAuxType = 0x0801; - /* for text files it's default record length; assume zero */ + pFile->fAuxType = 0; + if (pFile->fFileType == A2FileDOS::kTypeApplesoft) + pFile->fAuxType = 0x0801; + /* for text files it's default record length; assume zero */ - if (tsCount == 0) { - /* no data at all */ - pFile->fLength = 0; - } else if (pFile->fFileType == A2FileDOS::kTypeApplesoft || - pFile->fFileType == A2FileDOS::kTypeInteger || - pFile->fFileType == A2FileDOS::kTypeBinary) - { - /* read first sector and analyze it */ - //WMSG0(" DOS reading first file sector\n"); - dierr = fpImg->ReadTrackSector(tsList[0].track, tsList[0].sector, - sctBuf); - if (dierr != kDIErrNone) - goto bail; + if (tsCount == 0) { + /* no data at all */ + pFile->fLength = 0; + } else if (pFile->fFileType == A2FileDOS::kTypeApplesoft || + pFile->fFileType == A2FileDOS::kTypeInteger || + pFile->fFileType == A2FileDOS::kTypeBinary) + { + /* read first sector and analyze it */ + //WMSG0(" DOS reading first file sector\n"); + dierr = fpImg->ReadTrackSector(tsList[0].track, tsList[0].sector, + sctBuf); + if (dierr != kDIErrNone) + goto bail; - if (pFile->fFileType == A2FileDOS::kTypeBinary) { - pFile->fAuxType = - sctBuf[0x00] | (unsigned short) sctBuf[0x01] << 8; - pFile->fLength = - sctBuf[0x02] | (unsigned short) sctBuf[0x03] << 8; - pFile->fDataOffset = 4; // take the above into account - } else { - pFile->fLength = - sctBuf[0x00] | (unsigned short) sctBuf[0x01] << 8; - pFile->fDataOffset = 2; // take the above into account - } + if (pFile->fFileType == A2FileDOS::kTypeBinary) { + pFile->fAuxType = + sctBuf[0x00] | (unsigned short) sctBuf[0x01] << 8; + pFile->fLength = + sctBuf[0x02] | (unsigned short) sctBuf[0x03] << 8; + pFile->fDataOffset = 4; // take the above into account + } else { + pFile->fLength = + sctBuf[0x00] | (unsigned short) sctBuf[0x01] << 8; + pFile->fDataOffset = 2; // take the above into account + } - if (pFile->fFileType == A2FileDOS::kTypeBinary && - pFile->fLength == 0 && pFile->fAuxType == 0 && - tsCount >= 8 && - strchr(pFile->fFileName, '<') != nil && - strchr(pFile->fFileName, '>') != nil) - { - WMSG2(" DOS found probable DDD archive, tweaking '%s' (lis=%u)\n", - pFile->GetPathName(), pFile->fLengthInSectors); - //dierr = TrimLastSectorDown(pFile, tsBuf, WrapperDDD::kMaxDDDZeroCount); - //if (dierr != kDIErrNone) - // goto bail; - //WMSG3(" DOS scanned DDD file '%s' to length %ld (tsCount=%d)\n", - // pFile->fFileName, pFile->fLength, pFile->fTSListCount); - pFile->fLength = tsCount * kSctSize; - pFile->fDataOffset = 0; - } + if (pFile->fFileType == A2FileDOS::kTypeBinary && + pFile->fLength == 0 && pFile->fAuxType == 0 && + tsCount >= 8 && + strchr(pFile->fFileName, '<') != nil && + strchr(pFile->fFileName, '>') != nil) + { + WMSG2(" DOS found probable DDD archive, tweaking '%s' (lis=%u)\n", + pFile->GetPathName(), pFile->fLengthInSectors); + //dierr = TrimLastSectorDown(pFile, tsBuf, WrapperDDD::kMaxDDDZeroCount); + //if (dierr != kDIErrNone) + // goto bail; + //WMSG3(" DOS scanned DDD file '%s' to length %ld (tsCount=%d)\n", + // pFile->fFileName, pFile->fLength, pFile->fTSListCount); + pFile->fLength = tsCount * kSctSize; + pFile->fDataOffset = 0; + } - /* catch bogus lengths in damaged A/I/B files */ - if (pFile->fLength > tsCount * kSctSize) { - WMSG3(" DOS33 capping max len from %ld to %d in '%s'\n", - (long) pFile->fLength, tsCount * kSctSize, - pFile->fFileName); - pFile->fLength = tsCount * kSctSize - pFile->fDataOffset; - if (pFile->fLength < 0) // can't happen here? - pFile->fLength = 0; + /* catch bogus lengths in damaged A/I/B files */ + if (pFile->fLength > tsCount * kSctSize) { + WMSG3(" DOS33 capping max len from %ld to %d in '%s'\n", + (long) pFile->fLength, tsCount * kSctSize, + pFile->fFileName); + pFile->fLength = tsCount * kSctSize - pFile->fDataOffset; + if (pFile->fLength < 0) // can't happen here? + pFile->fLength = 0; - /* - * This could cause a problem, because if the user changes a 'T' - * file to 'B', the bogus file length will mark the file as - * "suspicious" and we won't allow writing to the disk (which - * makes it hard to switch the file type back). We really don't - * want to weaken this test though. - */ - pFile->SetQuality(A2File::kQualitySuspicious); - } + /* + * This could cause a problem, because if the user changes a 'T' + * file to 'B', the bogus file length will mark the file as + * "suspicious" and we won't allow writing to the disk (which + * makes it hard to switch the file type back). We really don't + * want to weaken this test though. + */ + pFile->SetQuality(A2File::kQualitySuspicious); + } - } else if (pFile->fFileType == A2FileDOS::kTypeText) { - /* scan text file */ - pFile->fLength = tsCount * kSctSize; - dierr = TrimLastSectorUp(pFile, tsList[tsCount-1]); - if (dierr != kDIErrNone) - goto bail; + } else if (pFile->fFileType == A2FileDOS::kTypeText) { + /* scan text file */ + pFile->fLength = tsCount * kSctSize; + dierr = TrimLastSectorUp(pFile, tsList[tsCount-1]); + if (dierr != kDIErrNone) + goto bail; - WMSG4(" DOS scanned text file '%s' down to %d+%ld = %ld\n", - pFile->fFileName, - (tsCount-1) * kSctSize, - (long)pFile->fLength - (tsCount-1) * kSctSize, - (long)pFile->fLength); + WMSG4(" DOS scanned text file '%s' down to %d+%ld = %ld\n", + pFile->fFileName, + (tsCount-1) * kSctSize, + (long)pFile->fLength - (tsCount-1) * kSctSize, + (long)pFile->fLength); - /* TO DO: something clever to discern random access record length? */ - } else { - /* S/R/A/B: just use the TS count */ - pFile->fLength = tsCount * kSctSize; - } + /* TO DO: something clever to discern random access record length? */ + } else { + /* S/R/A/B: just use the TS count */ + pFile->fLength = tsCount * kSctSize; + } - /* - * Compute the sparse length for random-access text files. - */ - int i, sparseCount; - sparseCount = 0; - for (i = 0; i < tsCount; i++) { - if (tsList[i].track == 0 && tsList[i].sector == 0) - sparseCount++; - } - pFile->fSparseLength = pFile->fLength - sparseCount * kSctSize; - if (pFile->fSparseLength == -pFile->fDataOffset) { - /* - * This can happen for a completely sparse file. Looks sort of - * stupid to have a length of "-4", so force it to zero. - */ - pFile->fSparseLength = 0; - } + /* + * Compute the sparse length for random-access text files. + */ + int i, sparseCount; + sparseCount = 0; + for (i = 0; i < tsCount; i++) { + if (tsList[i].track == 0 && tsList[i].sector == 0) + sparseCount++; + } + pFile->fSparseLength = pFile->fLength - sparseCount * kSctSize; + if (pFile->fSparseLength == -pFile->fDataOffset) { + /* + * This can happen for a completely sparse file. Looks sort of + * stupid to have a length of "-4", so force it to zero. + */ + pFile->fSparseLength = 0; + } bail: - return dierr; + return dierr; } /* @@ -1211,31 +1211,31 @@ bail: DIError DiskFSDOS33::TrimLastSectorUp(A2FileDOS* pFile, TrackSector lastTS) { - DIError dierr; - unsigned char sctBuf[kSctSize]; + DIError dierr; + unsigned char sctBuf[kSctSize]; int i; - if (lastTS.track == 0) { - /* happens on files with lots of "sparse" space at the end */ - return kDIErrNone; - } + if (lastTS.track == 0) { + /* happens on files with lots of "sparse" space at the end */ + return kDIErrNone; + } - //WMSG0(" DOS reading LAST file sector\n"); - dierr = fpImg->ReadTrackSector(lastTS.track, lastTS.sector, sctBuf); - if (dierr != kDIErrNone) - goto bail; + //WMSG0(" DOS reading LAST file sector\n"); + dierr = fpImg->ReadTrackSector(lastTS.track, lastTS.sector, sctBuf); + if (dierr != kDIErrNone) + goto bail; - /* start with EOF equal to previous sectors */ - pFile->fLength -= kSctSize; - for (i = 0; i < kSctSize; i++) { - if (sctBuf[i] == 0x00) - break; - else - pFile->fLength++; - } + /* start with EOF equal to previous sectors */ + pFile->fLength -= kSctSize; + for (i = 0; i < kSctSize; i++) { + if (sctBuf[i] == 0x00) + break; + else + pFile->fLength++; + } bail: - return dierr; + return dierr; } /* @@ -1244,25 +1244,25 @@ bail: */ void DiskFSDOS33::MarkFileUsage(A2FileDOS* pFile, TrackSector* tsList, int tsCount, - TrackSector* indexList, int indexCount) + TrackSector* indexList, int indexCount) { - int i; + int i; - for (i = 0; i < tsCount; i++) { - /* mark all sectors as in-use by file */ - if (tsList[i].track == 0 && tsList[i].sector == 0) { - /* sparse sector in random-access text file */ - } else { - SetSectorUsage(tsList[i].track, tsList[i].sector, - VolumeUsage::kChunkPurposeUserData); - } - } + for (i = 0; i < tsCount; i++) { + /* mark all sectors as in-use by file */ + if (tsList[i].track == 0 && tsList[i].sector == 0) { + /* sparse sector in random-access text file */ + } else { + SetSectorUsage(tsList[i].track, tsList[i].sector, + VolumeUsage::kChunkPurposeUserData); + } + } - for (i = 0; i < indexCount; i++) { - /* mark the T/S sectors as in-use by file structures */ - SetSectorUsage(indexList[i].track, indexList[i].sector, - VolumeUsage::kChunkPurposeFileStruct); - } + for (i = 0; i < indexCount; i++) { + /* mark the T/S sectors as in-use by file structures */ + SetSectorUsage(indexList[i].track, indexList[i].sector, + VolumeUsage::kChunkPurposeFileStruct); + } } @@ -1284,38 +1284,38 @@ DiskFSDOS33::MarkFileUsage(A2FileDOS* pFile, TrackSector* tsList, int tsCount, */ DIError DiskFSDOS33::TrimLastSectorDown(A2FileDOS* pFile, unsigned short* tsBuf, - int maxZeroCount) + int maxZeroCount) { - DIError dierr; - unsigned char sctBuf[kSctSize]; + DIError dierr; + unsigned char sctBuf[kSctSize]; int i; - //WMSG0(" DOS reading LAST file sector\n"); - dierr = fpImg->ReadTrackSector( - pFile->TSTrack(tsBuf[pFile->fTSListCount-1]), - pFile->TSSector(tsBuf[pFile->fTSListCount-1]), - sctBuf); - if (dierr != kDIErrNone) - goto bail; + //WMSG0(" DOS reading LAST file sector\n"); + dierr = fpImg->ReadTrackSector( + pFile->TSTrack(tsBuf[pFile->fTSListCount-1]), + pFile->TSSector(tsBuf[pFile->fTSListCount-1]), + sctBuf); + if (dierr != kDIErrNone) + goto bail; - /* find the first trailing zero by finding the last non-zero */ - for (i = kSctSize-1; i >= 0; i--) { - if (sctBuf[i] != 0x00) - break; - } - if (i < 0) { - /* sector was nothing but zeroes */ - DebugBreak(); - } else { - /* peg it at 256; if it went over that, DDD would've added a sector */ - i += maxZeroCount; - if (i > kSctSize) - i = kSctSize; - pFile->fLength = (pFile->fTSListCount-1) * kSctSize + i; - } + /* find the first trailing zero by finding the last non-zero */ + for (i = kSctSize-1; i >= 0; i--) { + if (sctBuf[i] != 0x00) + break; + } + if (i < 0) { + /* sector was nothing but zeroes */ + DebugBreak(); + } else { + /* peg it at 256; if it went over that, DDD would've added a sector */ + i += maxZeroCount; + if (i > kSctSize) + i = kSctSize; + pFile->fLength = (pFile->fTSListCount-1) * kSctSize + i; + } bail: - return dierr; + return dierr; } #endif @@ -1331,17 +1331,17 @@ bail: /*static*/ void DiskFSDOS33::LowerASCII(unsigned char* buf, long len) { - while (len--) { - if (*buf & 0x80) { - if (*buf >= 0xa0) - *buf &= 0x7f; - else - *buf = (*buf & 0x7f) + 0x20; - } else - *buf = ((*buf & 0x3f) ^ 0x20) + 0x20; + while (len--) { + if (*buf & 0x80) { + if (*buf >= 0xa0) + *buf &= 0x7f; + else + *buf = (*buf & 0x7f) + 0x20; + } else + *buf = ((*buf & 0x3f) ^ 0x20) + 0x20; buf++; - } + } } @@ -1361,27 +1361,27 @@ DiskFSDOS33::LowerASCII(unsigned char* buf, long len) /*static*/ bool DiskFSDOS33::IsValidFileName(const char* name) { - bool nonSpace = false; - int len = 0; + bool nonSpace = false; + int len = 0; - /* count letters, skipping control chars */ - while (*name != '\0') { - char ch = *name++; + /* count letters, skipping control chars */ + while (*name != '\0') { + char ch = *name++; - if (ch < 0x20 || ch >= 0x7f || ch == ',') - return false; - if (ch != 0x20) - nonSpace = true; - len++; - } - if (len == 0 || len > A2FileDOS::kMaxFileName) - return false; // can't be empty, can't be huge - if (!nonSpace) - return false; // must have one non-ctrl non-space char - if (*(name-1) == ' ') - return false; // no trailing spaces + if (ch < 0x20 || ch >= 0x7f || ch == ',') + return false; + if (ch != 0x20) + nonSpace = true; + len++; + } + if (len == 0 || len > A2FileDOS::kMaxFileName) + return false; // can't be empty, can't be huge + if (!nonSpace) + return false; // must have one non-ctrl non-space char + if (*(name-1) == ' ') + return false; // no trailing spaces - return true; + return true; } /* @@ -1390,14 +1390,14 @@ DiskFSDOS33::IsValidFileName(const char* name) /*static*/ bool DiskFSDOS33::IsValidVolumeName(const char* name) { - long val; - char* endp; + long val; + char* endp; - val = strtol(name, &endp, 10); - if (*endp != '\0' || val < 1 || val > 254) - return false; + val = strtol(name, &endp, 10); + if (*endp != '\0' || val < 1 || val > 254) + return false; - return true; + return true; } @@ -1421,130 +1421,130 @@ DiskFSDOS33::IsValidVolumeName(const char* name) DIError DiskFSDOS33::Format(DiskImg* pDiskImg, const char* volName) { - DIError dierr = kDIErrNone; - unsigned char sctBuf[256]; - bool addDOS = false; + DIError dierr = kDIErrNone; + unsigned char sctBuf[256]; + bool addDOS = false; - if (pDiskImg->GetNumTracks() < kMinTracks || - pDiskImg->GetNumTracks() > kMaxTracks) - { + if (pDiskImg->GetNumTracks() < kMinTracks || + pDiskImg->GetNumTracks() > kMaxTracks) + { WMSG1(" DOS33 can't format numTracks=%ld\n", pDiskImg->GetNumTracks()); - return kDIErrInvalidArg; - } - if (pDiskImg->GetNumSectPerTrack() != 13 && - pDiskImg->GetNumSectPerTrack() != 16 && - pDiskImg->GetNumSectPerTrack() != 32) - { + return kDIErrInvalidArg; + } + if (pDiskImg->GetNumSectPerTrack() != 13 && + pDiskImg->GetNumSectPerTrack() != 16 && + pDiskImg->GetNumSectPerTrack() != 32) + { WMSG1(" DOS33 can't format sectors=%d\n", pDiskImg->GetNumSectPerTrack()); - return kDIErrInvalidArg; - } + return kDIErrInvalidArg; + } - if (volName != nil && strcmp(volName, "DOS") == 0) { - if (pDiskImg->GetNumSectPerTrack() != 16 && - pDiskImg->GetNumSectPerTrack() != 13) - { - WMSG1("NOTE: numSectPerTrack = %d, can't write DOS tracks\n", - pDiskImg->GetNumSectPerTrack()); - return kDIErrInvalidArg; - } - addDOS = true; - } + if (volName != nil && strcmp(volName, "DOS") == 0) { + if (pDiskImg->GetNumSectPerTrack() != 16 && + pDiskImg->GetNumSectPerTrack() != 13) + { + WMSG1("NOTE: numSectPerTrack = %d, can't write DOS tracks\n", + pDiskImg->GetNumSectPerTrack()); + return kDIErrInvalidArg; + } + addDOS = true; + } - /* set fpImg so calls that rely on it will work; we un-set it later */ - assert(fpImg == nil); - SetDiskImg(pDiskImg); + /* set fpImg so calls that rely on it will work; we un-set it later */ + assert(fpImg == nil); + SetDiskImg(pDiskImg); - WMSG1(" DOS33 formatting disk image (sectorOrder=%d)\n", - fpImg->GetSectorOrder()); + WMSG1(" DOS33 formatting disk image (sectorOrder=%d)\n", + fpImg->GetSectorOrder()); - /* write DOS sectors */ - dierr = fpImg->OverrideFormat(fpImg->GetPhysicalFormat(), - DiskImg::kFormatGenericDOSOrd, fpImg->GetSectorOrder()); - if (dierr != kDIErrNone) - goto bail; + /* write DOS sectors */ + dierr = fpImg->OverrideFormat(fpImg->GetPhysicalFormat(), + DiskImg::kFormatGenericDOSOrd, fpImg->GetSectorOrder()); + if (dierr != kDIErrNone) + goto bail; - /* - * We should now zero out the disk blocks, but on a 32MB volume that can - * take a little while. The blocks are zeroed for us when a disk is - * created, so this is really only needed if we're re-formatting an - * existing disk. CiderPress currently doesn't do that, so we're going - * to skip it here. - */ -// dierr = fpImg->ZeroImage(); - WMSG0(" DOS33 (not zeroing blocks)\n"); + /* + * We should now zero out the disk blocks, but on a 32MB volume that can + * take a little while. The blocks are zeroed for us when a disk is + * created, so this is really only needed if we're re-formatting an + * existing disk. CiderPress currently doesn't do that, so we're going + * to skip it here. + */ +// dierr = fpImg->ZeroImage(); + WMSG0(" DOS33 (not zeroing blocks)\n"); - if (addDOS) { - dierr = WriteDOSTracks(pDiskImg->GetNumSectPerTrack()); - if (dierr != kDIErrNone) - goto bail; - } + if (addDOS) { + dierr = WriteDOSTracks(pDiskImg->GetNumSectPerTrack()); + if (dierr != kDIErrNone) + goto bail; + } - /* - * Set up the static fields in the VTOC. - */ - dierr = LoadVolBitmap(); - if (dierr != kDIErrNone) - goto bail; - fVTOC[0x00] = 0x04; // (no reason) - fVTOC[0x01] = kVTOCTrack; // first cat track - fVTOC[0x02] = fpImg->GetNumSectPerTrack()-1; // first cat sector - fVTOC[0x03] = 3; // version - if (fpImg->GetDOSVolumeNum() == DiskImg::kVolumeNumNotSet) - fVTOC[0x06] = kDefaultVolumeNum; // VTOC volume number - else - fVTOC[0x06] = (unsigned char) fpImg->GetDOSVolumeNum(); - fVTOC[0x27] = 122; // max T/S pairs - fVTOC[0x30] = kVTOCTrack+1; // last alloc - fVTOC[0x31] = 1; // ascending - fVTOC[0x34] = (unsigned char)fpImg->GetNumTracks(); // #of tracks - fVTOC[0x35] = fpImg->GetNumSectPerTrack(); // #of sectors - fVTOC[0x36] = 0x00; // bytes/sector (lo) - fVTOC[0x37] = 0x01; // bytes/sector (hi) - if (pDiskImg->GetNumSectPerTrack() == 13) { - // minor changes for DOS 3.2 - fVTOC[0x00] = 0x02; - fVTOC[0x03] = 2; - } + /* + * Set up the static fields in the VTOC. + */ + dierr = LoadVolBitmap(); + if (dierr != kDIErrNone) + goto bail; + fVTOC[0x00] = 0x04; // (no reason) + fVTOC[0x01] = kVTOCTrack; // first cat track + fVTOC[0x02] = fpImg->GetNumSectPerTrack()-1; // first cat sector + fVTOC[0x03] = 3; // version + if (fpImg->GetDOSVolumeNum() == DiskImg::kVolumeNumNotSet) + fVTOC[0x06] = kDefaultVolumeNum; // VTOC volume number + else + fVTOC[0x06] = (unsigned char) fpImg->GetDOSVolumeNum(); + fVTOC[0x27] = 122; // max T/S pairs + fVTOC[0x30] = kVTOCTrack+1; // last alloc + fVTOC[0x31] = 1; // ascending + fVTOC[0x34] = (unsigned char)fpImg->GetNumTracks(); // #of tracks + fVTOC[0x35] = fpImg->GetNumSectPerTrack(); // #of sectors + fVTOC[0x36] = 0x00; // bytes/sector (lo) + fVTOC[0x37] = 0x01; // bytes/sector (hi) + if (pDiskImg->GetNumSectPerTrack() == 13) { + // minor changes for DOS 3.2 + fVTOC[0x00] = 0x02; + fVTOC[0x03] = 2; + } - dierr = SaveVolBitmap(); - FreeVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + dierr = SaveVolBitmap(); + FreeVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - /* - * Fill the sectors in the catalog track. - */ - int sect; - memset(sctBuf, 0, sizeof(sctBuf)); - sctBuf[0x01] = kVTOCTrack; - for (sect = fpImg->GetNumSectPerTrack()-1; sect > 1; sect--) { - sctBuf[0x02] = sect-1; + /* + * Fill the sectors in the catalog track. + */ + int sect; + memset(sctBuf, 0, sizeof(sctBuf)); + sctBuf[0x01] = kVTOCTrack; + for (sect = fpImg->GetNumSectPerTrack()-1; sect > 1; sect--) { + sctBuf[0x02] = sect-1; - dierr = fpImg->WriteTrackSector(kVTOCTrack, sect, sctBuf); - if (dierr != kDIErrNone) - goto bail; - } + dierr = fpImg->WriteTrackSector(kVTOCTrack, sect, sctBuf); + if (dierr != kDIErrNone) + goto bail; + } - /* - * Generate the initial block usage map. The only entries in use are - * right at the start of the disk. - */ - CreateEmptyBlockMap(addDOS); + /* + * Generate the initial block usage map. The only entries in use are + * right at the start of the disk. + */ + CreateEmptyBlockMap(addDOS); - /* check our work, and set some object fields, by reading what we wrote */ - dierr = ReadVTOC(); - if (dierr != kDIErrNone) { - WMSG1(" GLITCH: couldn't read header we just wrote (err=%d)\n", dierr); - goto bail; - } + /* check our work, and set some object fields, by reading what we wrote */ + dierr = ReadVTOC(); + if (dierr != kDIErrNone) { + WMSG1(" GLITCH: couldn't read header we just wrote (err=%d)\n", dierr); + goto bail; + } - /* don't do this -- assume they're going to call Initialize() later */ - //ScanVolBitmap(); + /* don't do this -- assume they're going to call Initialize() later */ + //ScanVolBitmap(); bail: - SetDiskImg(nil); // shouldn't really be set by us - return dierr; + SetDiskImg(nil); // shouldn't really be set by us + return dierr; } /* @@ -1557,44 +1557,44 @@ bail: DIError DiskFSDOS33::WriteDOSTracks(int sectPerTrack) { - DIError dierr = kDIErrNone; - long track, sector; - const unsigned char* buf = gDOS33Tracks; + DIError dierr = kDIErrNone; + long track, sector; + const unsigned char* buf = gDOS33Tracks; - if (sectPerTrack == 13) { - WMSG0(" DOS33 writing DOS 3.3 tracks\n"); - buf = gDOS32Tracks; + if (sectPerTrack == 13) { + WMSG0(" DOS33 writing DOS 3.3 tracks\n"); + buf = gDOS32Tracks; - for (track = 0; track < 3; track++) { - for (sector = 0; sector < 13; sector++) { - dierr = fpImg->WriteTrackSector(track, sector, buf); - if (dierr != kDIErrNone) - goto bail; - buf += kSctSize; - } - } - } else if (sectPerTrack == 16) { - WMSG0(" DOS33 writing DOS 3.3 tracks\n"); - buf = gDOS33Tracks; + for (track = 0; track < 3; track++) { + for (sector = 0; sector < 13; sector++) { + dierr = fpImg->WriteTrackSector(track, sector, buf); + if (dierr != kDIErrNone) + goto bail; + buf += kSctSize; + } + } + } else if (sectPerTrack == 16) { + WMSG0(" DOS33 writing DOS 3.3 tracks\n"); + buf = gDOS33Tracks; - // this should be used for 32-sector disks + // this should be used for 32-sector disks - for (track = 0; track < 3; track++) { - for (sector = 0; sector < 16; sector++) { - dierr = fpImg->WriteTrackSector(track, sector, buf); - if (dierr != kDIErrNone) - goto bail; - buf += kSctSize; - } - } - } else { - WMSG1(" DOS33 *not* writing DOS tracks to %d-sector disk\n", - sectPerTrack); - assert(false); - } + for (track = 0; track < 3; track++) { + for (sector = 0; sector < 16; sector++) { + dierr = fpImg->WriteTrackSector(track, sector, buf); + if (dierr != kDIErrNone) + goto bail; + buf += kSctSize; + } + } + } else { + WMSG1(" DOS33 *not* writing DOS tracks to %d-sector disk\n", + sectPerTrack); + assert(false); + } bail: - return dierr; + return dierr; } /* @@ -1606,22 +1606,22 @@ bail: */ DIError DiskFSDOS33::NormalizePath(const char* path, char fssep, - char* normalizedBuf, int* pNormalizedBufLen) + char* normalizedBuf, int* pNormalizedBufLen) { - DIError dierr = kDIErrNone; - char tmpBuf[A2FileDOS::kMaxFileName+1]; - int len; + DIError dierr = kDIErrNone; + char tmpBuf[A2FileDOS::kMaxFileName+1]; + int len; - DoNormalizePath(path, fssep, tmpBuf); - len = strlen(tmpBuf)+1; + DoNormalizePath(path, fssep, tmpBuf); + len = strlen(tmpBuf)+1; - if (*pNormalizedBufLen < len) - dierr = kDIErrDataOverrun; - else - strcpy(normalizedBuf, tmpBuf); - *pNormalizedBufLen = len; + if (*pNormalizedBufLen < len) + dierr = kDIErrDataOverrun; + else + strcpy(normalizedBuf, tmpBuf); + *pNormalizedBufLen = len; - return dierr; + return dierr; } /* @@ -1633,33 +1633,33 @@ DiskFSDOS33::NormalizePath(const char* path, char fssep, void DiskFSDOS33::DoNormalizePath(const char* name, char fssep, char* outBuf) { - char* outp = outBuf; - char* cp; + char* outp = outBuf; + char* cp; - /* throw out leading pathname, if any */ - if (fssep != '\0') { - cp = strrchr(name, fssep); - if (cp != nil) - name = cp+1; - } + /* throw out leading pathname, if any */ + if (fssep != '\0') { + cp = strrchr(name, fssep); + if (cp != nil) + name = cp+1; + } - while (*name != '\0' && (outp - outBuf) <= A2FileDOS::kMaxFileName) { - if (*name >= 0x20 && *name < 0x7f) { - if (*name == ',') - *outp = '_'; - else - *outp = toupper(*name); + while (*name != '\0' && (outp - outBuf) <= A2FileDOS::kMaxFileName) { + if (*name >= 0x20 && *name < 0x7f) { + if (*name == ',') + *outp = '_'; + else + *outp = toupper(*name); - outp++; - } - name++; - } - *outp = '\0'; + outp++; + } + name++; + } + *outp = '\0'; - if (*outBuf == '\0') { - /* nothing left */ - strcpy(outBuf, "BLANK"); - } + if (*outBuf == '\0') { + /* nothing left */ + strcpy(outBuf, "BLANK"); + } } /* @@ -1685,149 +1685,149 @@ DiskFSDOS33::DoNormalizePath(const char* name, char fssep, char* outBuf) * that the first block is already there. Need to do that someday.) */ DIError -DiskFSDOS33::CreateFile(const CreateParms* pParms, A2File** ppNewFile) +DiskFSDOS33::CreateFile(const CreateParms* pParms, A2File** ppNewFile) { - DIError dierr = kDIErrNone; - const bool createUnique = (GetParameter(kParm_CreateUnique) != 0); - char normalName[A2FileDOS::kMaxFileName+1]; -// char storageName[A2FileDOS::kMaxFileName+1]; - A2FileDOS::FileType fileType; - A2FileDOS* pNewFile = nil; + DIError dierr = kDIErrNone; + const bool createUnique = (GetParameter(kParm_CreateUnique) != 0); + char normalName[A2FileDOS::kMaxFileName+1]; +// char storageName[A2FileDOS::kMaxFileName+1]; + A2FileDOS::FileType fileType; + A2FileDOS* pNewFile = nil; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (!fDiskIsGood) - return kDIErrBadDiskImage; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (!fDiskIsGood) + return kDIErrBadDiskImage; - assert(pParms != nil); - assert(pParms->pathName != nil); - assert(pParms->storageType == A2FileProDOS::kStorageSeedling); - WMSG1(" DOS33 ---v--- CreateFile '%s'\n", pParms->pathName); + assert(pParms != nil); + assert(pParms->pathName != nil); + assert(pParms->storageType == A2FileProDOS::kStorageSeedling); + WMSG1(" DOS33 ---v--- CreateFile '%s'\n", pParms->pathName); - *ppNewFile = nil; + *ppNewFile = nil; - DoNormalizePath(pParms->pathName, pParms->fssep, normalName); + DoNormalizePath(pParms->pathName, pParms->fssep, normalName); - /* - * See if the file already exists. - * - * If "create unique" is set, we append digits until the name doesn't - * match any others. The name will be modified in place. - */ - if (createUnique) { - MakeFileNameUnique(normalName); - } else { - if (GetFileByName(normalName) != nil) { - WMSG1(" DOS33 create: normalized name '%s' already exists\n", - normalName); - dierr = kDIErrFileExists; - goto bail; - } - } + /* + * See if the file already exists. + * + * If "create unique" is set, we append digits until the name doesn't + * match any others. The name will be modified in place. + */ + if (createUnique) { + MakeFileNameUnique(normalName); + } else { + if (GetFileByName(normalName) != nil) { + WMSG1(" DOS33 create: normalized name '%s' already exists\n", + normalName); + dierr = kDIErrFileExists; + goto bail; + } + } - fileType = A2FileDOS::ConvertFileType(pParms->fileType, 0); + fileType = A2FileDOS::ConvertFileType(pParms->fileType, 0); - /* - * Allocate a directory entry and T/S list. - */ - unsigned char sctBuf[kSctSize]; - TrackSector catSect; - TrackSector tsSect; - int catEntry; - A2FileDOS* pPrevEntry; + /* + * Allocate a directory entry and T/S list. + */ + unsigned char sctBuf[kSctSize]; + TrackSector catSect; + TrackSector tsSect; + int catEntry; + A2FileDOS* pPrevEntry; - dierr = LoadVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + dierr = LoadVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - /* allocate a sector for the T/S list, and zero it out */ - dierr = AllocSector(&tsSect); - if (dierr != kDIErrNone) - goto bail; + /* allocate a sector for the T/S list, and zero it out */ + dierr = AllocSector(&tsSect); + if (dierr != kDIErrNone) + goto bail; - memset(sctBuf, 0, kSctSize); - dierr = fpImg->WriteTrackSector(tsSect.track, tsSect.sector, sctBuf); - if (dierr != kDIErrNone) - goto bail; + memset(sctBuf, 0, kSctSize); + dierr = fpImg->WriteTrackSector(tsSect.track, tsSect.sector, sctBuf); + if (dierr != kDIErrNone) + goto bail; - /* - * Find the first free catalog entry. Also returns a pointer to the - * previous entry. - */ - dierr = GetFreeCatalogEntry(&catSect, &catEntry, sctBuf, &pPrevEntry); - if (dierr != kDIErrNone) { - WMSG0("DOS unable to find an empty entry in the catalog\n"); - goto bail; - } - WMSG4(" DOS found free catalog entry T=%d S=%d ent=%d prev=0x%08lx\n", - catSect.track, catSect.sector, catEntry, (long) pPrevEntry); + /* + * Find the first free catalog entry. Also returns a pointer to the + * previous entry. + */ + dierr = GetFreeCatalogEntry(&catSect, &catEntry, sctBuf, &pPrevEntry); + if (dierr != kDIErrNone) { + WMSG0("DOS unable to find an empty entry in the catalog\n"); + goto bail; + } + WMSG4(" DOS found free catalog entry T=%d S=%d ent=%d prev=0x%08lx\n", + catSect.track, catSect.sector, catEntry, (long) pPrevEntry); - /* create the new dir entry at the specified location */ - CreateDirEntry(sctBuf, catEntry, normalName, &tsSect, - (unsigned char) fileType, pParms->access); + /* create the new dir entry at the specified location */ + CreateDirEntry(sctBuf, catEntry, normalName, &tsSect, + (unsigned char) fileType, pParms->access); - /* - * Flush everything to disk. - */ - dierr = fpImg->WriteTrackSector(catSect.track, catSect.sector, sctBuf); - if (dierr != kDIErrNone) - goto bail; + /* + * Flush everything to disk. + */ + dierr = fpImg->WriteTrackSector(catSect.track, catSect.sector, sctBuf); + if (dierr != kDIErrNone) + goto bail; - dierr = SaveVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + dierr = SaveVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - /* - * Create a new entry for our file list. - */ - pNewFile = new A2FileDOS(this); - if (pNewFile == nil) { - dierr = kDIErrMalloc; - goto bail; - } - pNewFile->fTSListTrack = tsSect.track; - pNewFile->fTSListSector = tsSect.sector; - pNewFile->fLengthInSectors = 1; - pNewFile->fLocked = false; - strcpy(pNewFile->fFileName, normalName); - pNewFile->fFileType = fileType; + /* + * Create a new entry for our file list. + */ + pNewFile = new A2FileDOS(this); + if (pNewFile == nil) { + dierr = kDIErrMalloc; + goto bail; + } + pNewFile->fTSListTrack = tsSect.track; + pNewFile->fTSListSector = tsSect.sector; + pNewFile->fLengthInSectors = 1; + pNewFile->fLocked = false; + strcpy(pNewFile->fFileName, normalName); + pNewFile->fFileType = fileType; - pNewFile->fCatTS.track = catSect.track; - pNewFile->fCatTS.sector = catSect.sector; - pNewFile->fCatEntryNum = catEntry; + pNewFile->fCatTS.track = catSect.track; + pNewFile->fCatTS.sector = catSect.sector; + pNewFile->fCatEntryNum = catEntry; - pNewFile->fAuxType = (unsigned short) pParms->auxType; - pNewFile->fDataOffset = 0; - switch (pNewFile->fFileType) { - case A2FileDOS::kTypeInteger: - pNewFile->fDataOffset = 2; - break; - case A2FileDOS::kTypeApplesoft: - pNewFile->fDataOffset = 2; - pNewFile->fAuxType = 0x0801; - break; - case A2FileDOS::kTypeBinary: - pNewFile->fDataOffset = 4; - break; - default: - break; - } - pNewFile->fLength = 0; - pNewFile->fSparseLength = 0; + pNewFile->fAuxType = (unsigned short) pParms->auxType; + pNewFile->fDataOffset = 0; + switch (pNewFile->fFileType) { + case A2FileDOS::kTypeInteger: + pNewFile->fDataOffset = 2; + break; + case A2FileDOS::kTypeApplesoft: + pNewFile->fDataOffset = 2; + pNewFile->fAuxType = 0x0801; + break; + case A2FileDOS::kTypeBinary: + pNewFile->fDataOffset = 4; + break; + default: + break; + } + pNewFile->fLength = 0; + pNewFile->fSparseLength = 0; - /* - * Insert it in the proper place, so that the order of the files matches - * the order of entries in the catalog. - */ - InsertFileInList(pNewFile, pPrevEntry); + /* + * Insert it in the proper place, so that the order of the files matches + * the order of entries in the catalog. + */ + InsertFileInList(pNewFile, pPrevEntry); - *ppNewFile = pNewFile; - pNewFile = nil; + *ppNewFile = pNewFile; + pNewFile = nil; bail: - delete pNewFile; - FreeVolBitmap(); - return dierr; + delete pNewFile; + FreeVolBitmap(); + return dierr; } /* @@ -1846,62 +1846,62 @@ bail: DIError DiskFSDOS33::MakeFileNameUnique(char* fileName) { - assert(fileName != nil); - assert(strlen(fileName) <= A2FileDOS::kMaxFileName); + assert(fileName != nil); + assert(strlen(fileName) <= A2FileDOS::kMaxFileName); - if (GetFileByName(fileName) == nil) - return kDIErrNone; + if (GetFileByName(fileName) == nil) + return kDIErrNone; - WMSG1(" DOS found duplicate of '%s', making unique\n", fileName); + WMSG1(" DOS found duplicate of '%s', making unique\n", fileName); - int nameLen = strlen(fileName); - int dotOffset=0, dotLen=0; - char dotBuf[kMaxExtensionLen+1]; + int nameLen = strlen(fileName); + int dotOffset=0, dotLen=0; + char dotBuf[kMaxExtensionLen+1]; - /* ensure the result will be null-terminated */ - memset(fileName + nameLen, 0, (A2FileDOS::kMaxFileName - nameLen) +1); + /* ensure the result will be null-terminated */ + memset(fileName + nameLen, 0, (A2FileDOS::kMaxFileName - nameLen) +1); - /* - * If this has what looks like a filename extension, grab it. We want - * to preserve ".gif", ".c", etc. - */ - const char* cp = strrchr(fileName, '.'); - if (cp != nil) { - int tmpOffset = cp - fileName; - if (tmpOffset > 0 && nameLen - tmpOffset <= kMaxExtensionLen) { - WMSG1(" DOS (keeping extension '%s')\n", cp); - assert(strlen(cp) <= kMaxExtensionLen); - strcpy(dotBuf, cp); - dotOffset = tmpOffset; - dotLen = nameLen - dotOffset; - } - } + /* + * If this has what looks like a filename extension, grab it. We want + * to preserve ".gif", ".c", etc. + */ + const char* cp = strrchr(fileName, '.'); + if (cp != nil) { + int tmpOffset = cp - fileName; + if (tmpOffset > 0 && nameLen - tmpOffset <= kMaxExtensionLen) { + WMSG1(" DOS (keeping extension '%s')\n", cp); + assert(strlen(cp) <= kMaxExtensionLen); + strcpy(dotBuf, cp); + dotOffset = tmpOffset; + dotLen = nameLen - dotOffset; + } + } - const int kMaxDigits = 999; - int digits = 0; - int digitLen; - int copyOffset; - char digitBuf[4]; - do { - if (digits == kMaxDigits) - return kDIErrFileExists; - digits++; + const int kMaxDigits = 999; + int digits = 0; + int digitLen; + int copyOffset; + char digitBuf[4]; + do { + if (digits == kMaxDigits) + return kDIErrFileExists; + digits++; - /* not the most efficient way to do this, but it'll do */ - sprintf(digitBuf, "%d", digits); - digitLen = strlen(digitBuf); - if (nameLen + digitLen > A2FileDOS::kMaxFileName) - copyOffset = A2FileDOS::kMaxFileName - dotLen - digitLen; - else - copyOffset = nameLen - dotLen; - memcpy(fileName + copyOffset, digitBuf, digitLen); - if (dotLen != 0) - memcpy(fileName + copyOffset + digitLen, dotBuf, dotLen); - } while (GetFileByName(fileName) != nil); + /* not the most efficient way to do this, but it'll do */ + sprintf(digitBuf, "%d", digits); + digitLen = strlen(digitBuf); + if (nameLen + digitLen > A2FileDOS::kMaxFileName) + copyOffset = A2FileDOS::kMaxFileName - dotLen - digitLen; + else + copyOffset = nameLen - dotLen; + memcpy(fileName + copyOffset, digitBuf, digitLen); + if (dotLen != 0) + memcpy(fileName + copyOffset + digitLen, dotBuf, dotLen); + } while (GetFileByName(fileName) != nil); - WMSG1(" DOS converted to unique name: %s\n", fileName); + WMSG1(" DOS converted to unique name: %s\n", fileName); - return kDIErrNone; + return kDIErrNone; } /* @@ -1913,86 +1913,86 @@ DiskFSDOS33::MakeFileNameUnique(char* fileName) */ DIError DiskFSDOS33::GetFreeCatalogEntry(TrackSector* pCatSect, int* pCatEntry, - unsigned char* sctBuf, A2FileDOS** ppPrevEntry) + unsigned char* sctBuf, A2FileDOS** ppPrevEntry) { - DIError dierr = kDIErrNone; - unsigned char* pEntry; - int sct, ent; - bool found = false; + DIError dierr = kDIErrNone; + unsigned char* pEntry; + int sct, ent; + bool found = false; - for (sct = 0; sct < kMaxCatalogSectors; sct++) { - if (fCatalogSectors[sct].track == 0 && - fCatalogSectors[sct].sector == 0) - { - /* end of list reached */ - WMSG0("DOS catalog is full\n"); - dierr = kDIErrVolumeDirFull; - goto bail; - } - dierr = fpImg->ReadTrackSector(fCatalogSectors[sct].track, - fCatalogSectors[sct].sector, sctBuf); - if (dierr != kDIErrNone) - goto bail; + for (sct = 0; sct < kMaxCatalogSectors; sct++) { + if (fCatalogSectors[sct].track == 0 && + fCatalogSectors[sct].sector == 0) + { + /* end of list reached */ + WMSG0("DOS catalog is full\n"); + dierr = kDIErrVolumeDirFull; + goto bail; + } + dierr = fpImg->ReadTrackSector(fCatalogSectors[sct].track, + fCatalogSectors[sct].sector, sctBuf); + if (dierr != kDIErrNone) + goto bail; - pEntry = &sctBuf[kCatalogEntryOffset]; - for (ent = 0; ent < kCatalogEntriesPerSect; ent++) { - if (pEntry[0x00] == 0x00 || pEntry[0x00] == kEntryDeleted) { - /* winner! */ - *pCatSect = fCatalogSectors[sct]; - *pCatEntry = ent; - found = true; - break; - } + pEntry = &sctBuf[kCatalogEntryOffset]; + for (ent = 0; ent < kCatalogEntriesPerSect; ent++) { + if (pEntry[0x00] == 0x00 || pEntry[0x00] == kEntryDeleted) { + /* winner! */ + *pCatSect = fCatalogSectors[sct]; + *pCatEntry = ent; + found = true; + break; + } - pEntry += kCatalogEntrySize; - } + pEntry += kCatalogEntrySize; + } - if (found) - break; - } + if (found) + break; + } - if (sct == kMaxCatalogSectors) { - /* didn't find anything, assume the disk is full */ - dierr = kDIErrVolumeDirFull; - // fall through to "bail" - } else { - /* figure out what the previous entry is */ - TrackSector prevTS; - int prevEntry; + if (sct == kMaxCatalogSectors) { + /* didn't find anything, assume the disk is full */ + dierr = kDIErrVolumeDirFull; + // fall through to "bail" + } else { + /* figure out what the previous entry is */ + TrackSector prevTS; + int prevEntry; - if (*pCatEntry != 0) { - prevTS = *pCatSect; - prevEntry = *pCatEntry -1; - } else if (sct != 0) { - prevTS = fCatalogSectors[sct-1]; - prevEntry = kCatalogEntriesPerSect-1; - } else { - /* disk was empty; there's no previous entry */ - prevTS.track = 0; - prevTS.sector = 0; - prevEntry = -1; - } + if (*pCatEntry != 0) { + prevTS = *pCatSect; + prevEntry = *pCatEntry -1; + } else if (sct != 0) { + prevTS = fCatalogSectors[sct-1]; + prevEntry = kCatalogEntriesPerSect-1; + } else { + /* disk was empty; there's no previous entry */ + prevTS.track = 0; + prevTS.sector = 0; + prevEntry = -1; + } - /* now find it in the linear file list */ - *ppPrevEntry = nil; - if (prevEntry >= 0) { - A2FileDOS* pFile = (A2FileDOS*) GetNextFile(nil); - while (pFile != nil) { - if (pFile->fCatTS.track == prevTS.track && - pFile->fCatTS.sector == prevTS.sector && - pFile->fCatEntryNum == prevEntry) - { - *ppPrevEntry = pFile; - break; - } - pFile = (A2FileDOS*) GetNextFile(pFile); - } - assert(*ppPrevEntry != nil); - } - } + /* now find it in the linear file list */ + *ppPrevEntry = nil; + if (prevEntry >= 0) { + A2FileDOS* pFile = (A2FileDOS*) GetNextFile(nil); + while (pFile != nil) { + if (pFile->fCatTS.track == prevTS.track && + pFile->fCatTS.sector == prevTS.sector && + pFile->fCatEntryNum == prevEntry) + { + *ppPrevEntry = pFile; + break; + } + pFile = (A2FileDOS*) GetNextFile(pFile); + } + assert(*ppPrevEntry != nil); + } + } bail: - return dierr; + return dierr; } /* @@ -2000,28 +2000,28 @@ bail: */ void DiskFSDOS33::CreateDirEntry(unsigned char* sctBuf, int catEntry, - const char* fileName, TrackSector* pTSSect, unsigned char fileType, - int access) + const char* fileName, TrackSector* pTSSect, unsigned char fileType, + int access) { - char highName[A2FileDOS::kMaxFileName+1]; - unsigned char* pEntry; + char highName[A2FileDOS::kMaxFileName+1]; + unsigned char* pEntry; - pEntry = GetCatalogEntryPtr(sctBuf, catEntry); - if (pEntry[0x00] != 0x00 && pEntry[0x00] != kEntryDeleted) { - /* somebody screwed up */ - assert(false); - return; - } + pEntry = GetCatalogEntryPtr(sctBuf, catEntry); + if (pEntry[0x00] != 0x00 && pEntry[0x00] != kEntryDeleted) { + /* somebody screwed up */ + assert(false); + return; + } - A2FileDOS::MakeDOSName(highName, fileName); + A2FileDOS::MakeDOSName(highName, fileName); - pEntry[0x00] = pTSSect->track; - pEntry[0x01] = pTSSect->sector; - pEntry[0x02] = fileType; - if ((access & A2FileProDOS::kAccessWrite) == 0) - pEntry[0x02] |= (unsigned char) A2FileDOS::kTypeLocked; - memcpy(&pEntry[0x03], highName, A2FileDOS::kMaxFileName); - PutShortLE(&pEntry[0x21], 1); // assume file is 1 sector long + pEntry[0x00] = pTSSect->track; + pEntry[0x01] = pTSSect->sector; + pEntry[0x02] = fileType; + if ((access & A2FileProDOS::kAccessWrite) == 0) + pEntry[0x02] |= (unsigned char) A2FileDOS::kTypeLocked; + memcpy(&pEntry[0x03], highName, A2FileDOS::kMaxFileName); + PutShortLE(&pEntry[0x21], 1); // assume file is 1 sector long } /* @@ -2033,78 +2033,78 @@ DiskFSDOS33::CreateDirEntry(unsigned char* sctBuf, int catEntry, DIError DiskFSDOS33::DeleteFile(A2File* pGenericFile) { - DIError dierr = kDIErrNone; - A2FileDOS* pFile = (A2FileDOS*) pGenericFile; - TrackSector* tsList = nil; - TrackSector* indexList = nil; - int tsCount, indexCount; - unsigned char sctBuf[kSctSize]; - unsigned char* pEntry; + DIError dierr = kDIErrNone; + A2FileDOS* pFile = (A2FileDOS*) pGenericFile; + TrackSector* tsList = nil; + TrackSector* indexList = nil; + int tsCount, indexCount; + unsigned char sctBuf[kSctSize]; + unsigned char* pEntry; - if (pGenericFile == nil) { - assert(false); - return kDIErrInvalidArg; - } + if (pGenericFile == nil) { + assert(false); + return kDIErrInvalidArg; + } - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (!fDiskIsGood) - return kDIErrBadDiskImage; - if (pGenericFile->IsFileOpen()) - return kDIErrFileOpen; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (!fDiskIsGood) + return kDIErrBadDiskImage; + if (pGenericFile->IsFileOpen()) + return kDIErrFileOpen; - WMSG1(" Deleting '%s'\n", pFile->GetPathName()); + WMSG1(" Deleting '%s'\n", pFile->GetPathName()); - /* - * Update the block usage map. Nothing is permanent until we flush - * the data to disk. - */ - dierr = LoadVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + /* + * Update the block usage map. Nothing is permanent until we flush + * the data to disk. + */ + dierr = LoadVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - dierr = pFile->LoadTSList(&tsList, &tsCount, &indexList, &indexCount); - if (dierr != kDIErrNone) { - WMSG1("Failed loading TS lists while deleting '%s'\n", - pFile->GetPathName()); - goto bail; - } + dierr = pFile->LoadTSList(&tsList, &tsCount, &indexList, &indexCount); + if (dierr != kDIErrNone) { + WMSG1("Failed loading TS lists while deleting '%s'\n", + pFile->GetPathName()); + goto bail; + } - FreeTrackSectors(tsList, tsCount); - FreeTrackSectors(indexList, indexCount); + FreeTrackSectors(tsList, tsCount); + FreeTrackSectors(indexList, indexCount); - /* - * Mark the entry as deleted. - */ - dierr = fpImg->ReadTrackSector(pFile->fCatTS.track, pFile->fCatTS.sector, - sctBuf); - if (dierr != kDIErrNone) - goto bail; - pEntry = GetCatalogEntryPtr(sctBuf, pFile->fCatEntryNum); - assert(pEntry[0x00] != 0x00 && pEntry[0x00] != kEntryDeleted); - pEntry[0x00] = kEntryDeleted; - dierr = fpImg->WriteTrackSector(pFile->fCatTS.track, pFile->fCatTS.sector, - sctBuf); - if (dierr != kDIErrNone) - goto bail; + /* + * Mark the entry as deleted. + */ + dierr = fpImg->ReadTrackSector(pFile->fCatTS.track, pFile->fCatTS.sector, + sctBuf); + if (dierr != kDIErrNone) + goto bail; + pEntry = GetCatalogEntryPtr(sctBuf, pFile->fCatEntryNum); + assert(pEntry[0x00] != 0x00 && pEntry[0x00] != kEntryDeleted); + pEntry[0x00] = kEntryDeleted; + dierr = fpImg->WriteTrackSector(pFile->fCatTS.track, pFile->fCatTS.sector, + sctBuf); + if (dierr != kDIErrNone) + goto bail; - /* - * Save our updated copy of the volume bitmap to disk. - */ - dierr = SaveVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + /* + * Save our updated copy of the volume bitmap to disk. + */ + dierr = SaveVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - /* - * Remove the A2File* from the list. - */ - DeleteFileFromList(pFile); + /* + * Remove the A2File* from the list. + */ + DeleteFileFromList(pFile); bail: - FreeVolBitmap(); - delete[] tsList; - delete[] indexList; - return dierr; + FreeVolBitmap(); + delete[] tsList; + delete[] indexList; + return dierr; } /* @@ -2113,26 +2113,26 @@ bail: void DiskFSDOS33::FreeTrackSectors(TrackSector* pList, int count) { - VolumeUsage::ChunkState cstate; - int i; + VolumeUsage::ChunkState cstate; + int i; - cstate.isUsed = false; - cstate.isMarkedUsed = false; - cstate.purpose = VolumeUsage::kChunkPurposeUnknown; + cstate.isUsed = false; + cstate.isMarkedUsed = false; + cstate.purpose = VolumeUsage::kChunkPurposeUnknown; - for (i = 0; i < count; i++) { - if (pList[i].track == 0 && pList[i].sector == 0) - continue; // sparse file + for (i = 0; i < count; i++) { + if (pList[i].track == 0 && pList[i].sector == 0) + continue; // sparse file - if (!GetSectorUseEntry(pList[i].track, pList[i].sector)) { - WMSG2("WARNING: freeing unallocated sector T=%d S=%d\n", - pList[i].track, pList[i].sector); - assert(false); // impossible unless disk is "damaged" - } - SetSectorUseEntry(pList[i].track, pList[i].sector, false); + if (!GetSectorUseEntry(pList[i].track, pList[i].sector)) { + WMSG2("WARNING: freeing unallocated sector T=%d S=%d\n", + pList[i].track, pList[i].sector); + assert(false); // impossible unless disk is "damaged" + } + SetSectorUseEntry(pList[i].track, pList[i].sector, false); - fVolumeUsage.SetChunkState(pList[i].track, pList[i].sector, &cstate); - } + fVolumeUsage.SetChunkState(pList[i].track, pList[i].sector, &cstate); + } } /* @@ -2143,55 +2143,55 @@ DiskFSDOS33::FreeTrackSectors(TrackSector* pList, int count) DIError DiskFSDOS33::RenameFile(A2File* pGenericFile, const char* newName) { - DIError dierr = kDIErrNone; - A2FileDOS* pFile = (A2FileDOS*) pGenericFile; - char normalName[A2FileDOS::kMaxFileName+1]; - char dosName[A2FileDOS::kMaxFileName+1]; - unsigned char sctBuf[kSctSize]; - unsigned char* pEntry; + DIError dierr = kDIErrNone; + A2FileDOS* pFile = (A2FileDOS*) pGenericFile; + char normalName[A2FileDOS::kMaxFileName+1]; + char dosName[A2FileDOS::kMaxFileName+1]; + unsigned char sctBuf[kSctSize]; + unsigned char* pEntry; - if (pFile == nil || newName == nil) - return kDIErrInvalidArg; - if (!IsValidFileName(newName)) - return kDIErrInvalidArg; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (!fDiskIsGood) - return kDIErrBadDiskImage; + if (pFile == nil || newName == nil) + return kDIErrInvalidArg; + if (!IsValidFileName(newName)) + return kDIErrInvalidArg; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (!fDiskIsGood) + return kDIErrBadDiskImage; - WMSG2(" DOS renaming '%s' to '%s'\n", pFile->GetPathName(), newName); + WMSG2(" DOS renaming '%s' to '%s'\n", pFile->GetPathName(), newName); - /* - * Update the disk catalog entry. - */ - dierr = fpImg->ReadTrackSector(pFile->fCatTS.track, pFile->fCatTS.sector, - sctBuf); - if (dierr != kDIErrNone) - goto bail; + /* + * Update the disk catalog entry. + */ + dierr = fpImg->ReadTrackSector(pFile->fCatTS.track, pFile->fCatTS.sector, + sctBuf); + if (dierr != kDIErrNone) + goto bail; - pEntry = GetCatalogEntryPtr(sctBuf, pFile->fCatEntryNum); + pEntry = GetCatalogEntryPtr(sctBuf, pFile->fCatEntryNum); - DoNormalizePath(newName, '\0', normalName); - A2FileDOS::MakeDOSName(dosName, normalName); - memcpy(&pEntry[0x03], dosName, A2FileDOS::kMaxFileName); + DoNormalizePath(newName, '\0', normalName); + A2FileDOS::MakeDOSName(dosName, normalName); + memcpy(&pEntry[0x03], dosName, A2FileDOS::kMaxFileName); - dierr = fpImg->WriteTrackSector(pFile->fCatTS.track, pFile->fCatTS.sector, - sctBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpImg->WriteTrackSector(pFile->fCatTS.track, pFile->fCatTS.sector, + sctBuf); + if (dierr != kDIErrNone) + goto bail; - /* - * Update our internal copy. - */ - char storedName[A2FileDOS::kMaxFileName+1]; - strcpy(storedName, dosName); - LowerASCII((unsigned char*)storedName, A2FileDOS::kMaxFileName); - A2FileDOS::TrimTrailingSpaces(storedName); + /* + * Update our internal copy. + */ + char storedName[A2FileDOS::kMaxFileName+1]; + strcpy(storedName, dosName); + LowerASCII((unsigned char*)storedName, A2FileDOS::kMaxFileName); + A2FileDOS::TrimTrailingSpaces(storedName); - strcpy(pFile->fFileName, storedName); + strcpy(pFile->fFileName, storedName); bail: - return dierr; + return dierr; } /* @@ -2207,157 +2207,157 @@ bail: */ DIError DiskFSDOS33::SetFileInfo(A2File* pGenericFile, long fileType, long auxType, - long accessFlags) + long accessFlags) { - DIError dierr = kDIErrNone; - A2FileDOS* pFile = (A2FileDOS*) pGenericFile; - TrackSector* tsList = nil; - int tsCount; - bool nowLocked; - bool typeChanged; + DIError dierr = kDIErrNone; + A2FileDOS* pFile = (A2FileDOS*) pGenericFile; + TrackSector* tsList = nil; + int tsCount; + bool nowLocked; + bool typeChanged; - if (pFile == nil) - return kDIErrInvalidArg; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; + if (pFile == nil) + return kDIErrInvalidArg; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; - WMSG4("DOS SetFileInfo '%s' type=0x%02lx aux=0x%04lx access=0x%02lx\n", - pFile->GetPathName(), fileType, auxType, accessFlags); + WMSG4("DOS SetFileInfo '%s' type=0x%02lx aux=0x%04lx access=0x%02lx\n", + pFile->GetPathName(), fileType, auxType, accessFlags); - /* - * We can ignore the file/aux type, or we can verify that they're not - * trying to change it. The latter is a little more work but makes - * the API a little more communicative. - */ - if (!A2FileDOS::IsValidType(fileType)) { - WMSG0("DOS SetFileInfo invalid file type\n"); - dierr = kDIErrInvalidArg; - goto bail; - } - if (auxType != pFile->GetAuxType() && fileType != 0x06) { - /* this only makes sense for BIN files */ - WMSG0("DOS SetFileInfo aux type mismatch; ignoring\n"); - //dierr = kDIErrNotSupported; - //goto bail; - } + /* + * We can ignore the file/aux type, or we can verify that they're not + * trying to change it. The latter is a little more work but makes + * the API a little more communicative. + */ + if (!A2FileDOS::IsValidType(fileType)) { + WMSG0("DOS SetFileInfo invalid file type\n"); + dierr = kDIErrInvalidArg; + goto bail; + } + if (auxType != pFile->GetAuxType() && fileType != 0x06) { + /* this only makes sense for BIN files */ + WMSG0("DOS SetFileInfo aux type mismatch; ignoring\n"); + //dierr = kDIErrNotSupported; + //goto bail; + } - nowLocked = (accessFlags & A2FileProDOS::kAccessWrite) == 0; - typeChanged = (fileType != pFile->GetFileType()); + nowLocked = (accessFlags & A2FileProDOS::kAccessWrite) == 0; + typeChanged = (fileType != pFile->GetFileType()); - /* - * Update the file type and locked status, if necessary. - */ - if (nowLocked != pFile->fLocked || typeChanged) { - A2FileDOS::FileType newFileType; - unsigned char sctBuf[kSctSize]; - unsigned char* pEntry; + /* + * Update the file type and locked status, if necessary. + */ + if (nowLocked != pFile->fLocked || typeChanged) { + A2FileDOS::FileType newFileType; + unsigned char sctBuf[kSctSize]; + unsigned char* pEntry; - WMSG1("Updating file '%s'\n", pFile->GetPathName()); + WMSG1("Updating file '%s'\n", pFile->GetPathName()); - dierr = fpImg->ReadTrackSector(pFile->fCatTS.track, pFile->fCatTS.sector, - sctBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpImg->ReadTrackSector(pFile->fCatTS.track, pFile->fCatTS.sector, + sctBuf); + if (dierr != kDIErrNone) + goto bail; - pEntry = GetCatalogEntryPtr(sctBuf, pFile->fCatEntryNum); + pEntry = GetCatalogEntryPtr(sctBuf, pFile->fCatEntryNum); - newFileType = A2FileDOS::ConvertFileType(fileType, 0); - pEntry[0x02] = (unsigned char) newFileType; - if (nowLocked) - pEntry[0x02] |= 0x80; + newFileType = A2FileDOS::ConvertFileType(fileType, 0); + pEntry[0x02] = (unsigned char) newFileType; + if (nowLocked) + pEntry[0x02] |= 0x80; - dierr = fpImg->WriteTrackSector(pFile->fCatTS.track, pFile->fCatTS.sector, - sctBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpImg->WriteTrackSector(pFile->fCatTS.track, pFile->fCatTS.sector, + sctBuf); + if (dierr != kDIErrNone) + goto bail; - /* update our local copy */ - pFile->fLocked = nowLocked; - } + /* update our local copy */ + pFile->fLocked = nowLocked; + } - if (!typeChanged && auxType == pFile->GetAuxType()) { - /* only the locked status has changed; skip the rest */ - goto bail; - } + if (!typeChanged && auxType == pFile->GetAuxType()) { + /* only the locked status has changed; skip the rest */ + goto bail; + } - /* - * If the file has type BIN (either because it was before and we left it - * alone, or we changed it to BIN), we need to figure out what the aux - * type should be. There are two situations: - * - * (1) User specified an aux type. If the aux type passed in doesn't match - * what's in the A2FileDOS structure, we assume they meant to change it. - * (2) User didn't specify an aux type change. If the file was BIN before, - * we don't need to do anything, but if it was just changed to BIN then - * we need to extract the aux type from the first sector of the file. - * - * There's also a 3rd situation: they changed the aux type for a non-BIN - * file. This should have been blocked earlier. - * - * On top of all this, if we changed the file type at all then we need to - * re-scan the file length and "data offset" value. - */ - unsigned short newAuxType; - newAuxType = (unsigned short) auxType; + /* + * If the file has type BIN (either because it was before and we left it + * alone, or we changed it to BIN), we need to figure out what the aux + * type should be. There are two situations: + * + * (1) User specified an aux type. If the aux type passed in doesn't match + * what's in the A2FileDOS structure, we assume they meant to change it. + * (2) User didn't specify an aux type change. If the file was BIN before, + * we don't need to do anything, but if it was just changed to BIN then + * we need to extract the aux type from the first sector of the file. + * + * There's also a 3rd situation: they changed the aux type for a non-BIN + * file. This should have been blocked earlier. + * + * On top of all this, if we changed the file type at all then we need to + * re-scan the file length and "data offset" value. + */ + unsigned short newAuxType; + newAuxType = (unsigned short) auxType; - dierr = pFile->LoadTSList(&tsList, &tsCount); - if (dierr != kDIErrNone) { - WMSG1(" DOS SFI: unable to load TS list (err=%d)\n", dierr); - goto bail; - } + dierr = pFile->LoadTSList(&tsList, &tsCount); + if (dierr != kDIErrNone) { + WMSG1(" DOS SFI: unable to load TS list (err=%d)\n", dierr); + goto bail; + } - if (fileType == 0x06 && tsCount > 0) { - unsigned char sctBuf[kSctSize]; + if (fileType == 0x06 && tsCount > 0) { + unsigned char sctBuf[kSctSize]; - dierr = fpImg->ReadTrackSector(tsList[0].track, - tsList[0].sector, sctBuf); - if (dierr != kDIErrNone) { - WMSG0("DOS SFI: unable to get first sector of file\n"); - goto bail; - } + dierr = fpImg->ReadTrackSector(tsList[0].track, + tsList[0].sector, sctBuf); + if (dierr != kDIErrNone) { + WMSG0("DOS SFI: unable to get first sector of file\n"); + goto bail; + } - if (auxType == pFile->GetAuxType()) { - newAuxType = GetShortLE(&sctBuf[0x00]); - WMSG1(" Aux type not changed, extracting from file (0x%04x)\n", - newAuxType); - } else { - WMSG1(" Aux type changed (to 0x%04x), changing file\n", - newAuxType); + if (auxType == pFile->GetAuxType()) { + newAuxType = GetShortLE(&sctBuf[0x00]); + WMSG1(" Aux type not changed, extracting from file (0x%04x)\n", + newAuxType); + } else { + WMSG1(" Aux type changed (to 0x%04x), changing file\n", + newAuxType); - PutShortLE(&sctBuf[0x00], newAuxType); - dierr = fpImg->WriteTrackSector(tsList[0].track, - tsList[0].sector, sctBuf); - if (dierr != kDIErrNone) { - WMSG0("DOS SFI: unable to write first sector of file\n"); - goto bail; - } - } - } else { - /* not BIN or file has no sectors */ - if (pFile->fFileType == A2FileDOS::kTypeApplesoft) - newAuxType = 0x0801; - else - newAuxType = 0x0000; - } + PutShortLE(&sctBuf[0x00], newAuxType); + dierr = fpImg->WriteTrackSector(tsList[0].track, + tsList[0].sector, sctBuf); + if (dierr != kDIErrNone) { + WMSG0("DOS SFI: unable to write first sector of file\n"); + goto bail; + } + } + } else { + /* not BIN or file has no sectors */ + if (pFile->fFileType == A2FileDOS::kTypeApplesoft) + newAuxType = 0x0801; + else + newAuxType = 0x0000; + } - /* update our local copy */ - pFile->fFileType = A2FileDOS::ConvertFileType(fileType, 0); - pFile->fAuxType = newAuxType; + /* update our local copy */ + pFile->fFileType = A2FileDOS::ConvertFileType(fileType, 0); + pFile->fAuxType = newAuxType; - /* - * Recalculate the file's length and "data offset". This may also mark - * the file as "suspicious". We wouldn't be here if the file was - * suspicious when we opened the disk image -- the image would have - * been marked read-only -- so if it's suspicious now, it's probably - * from a previous file type change attempt in the current session. - * Clear the flag so it doesn't "stick". - */ - pFile->ResetQuality(); - (void) ComputeLength(pFile, tsList, tsCount); + /* + * Recalculate the file's length and "data offset". This may also mark + * the file as "suspicious". We wouldn't be here if the file was + * suspicious when we opened the disk image -- the image would have + * been marked read-only -- so if it's suspicious now, it's probably + * from a previous file type change attempt in the current session. + * Clear the flag so it doesn't "stick". + */ + pFile->ResetQuality(); + (void) ComputeLength(pFile, tsList, tsCount); bail: - delete[] tsList; - return dierr; + delete[] tsList; + return dierr; } /* @@ -2369,40 +2369,40 @@ bail: DIError DiskFSDOS33::RenameVolume(const char* newName) { - DIError dierr = kDIErrNone; - unsigned char sctBuf[kSctSize]; - long newNumber; - char* endp; + DIError dierr = kDIErrNone; + unsigned char sctBuf[kSctSize]; + long newNumber; + char* endp; - if (!IsValidVolumeName(newName)) - return kDIErrInvalidArg; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; + if (!IsValidVolumeName(newName)) + return kDIErrInvalidArg; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; - // convert the number; we already ascertained that it's valid - newNumber = strtol(newName, &endp, 10); + // convert the number; we already ascertained that it's valid + newNumber = strtol(newName, &endp, 10); - dierr = fpImg->ReadTrackSector(kVTOCTrack, kVTOCSector, sctBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpImg->ReadTrackSector(kVTOCTrack, kVTOCSector, sctBuf); + if (dierr != kDIErrNone) + goto bail; - sctBuf[0x06] = (unsigned char) newNumber; + sctBuf[0x06] = (unsigned char) newNumber; - dierr = fpImg->WriteTrackSector(kVTOCTrack, kVTOCSector, sctBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpImg->WriteTrackSector(kVTOCTrack, kVTOCSector, sctBuf); + if (dierr != kDIErrNone) + goto bail; - fVTOCVolumeNumber = newNumber; - UpdateVolumeNum(); + fVTOCVolumeNumber = newNumber; + UpdateVolumeNum(); bail: - return dierr; + return dierr; } /* * =========================================================================== - * A2FileDOS + * A2FileDOS * =========================================================================== */ @@ -2411,22 +2411,22 @@ bail: */ A2FileDOS::A2FileDOS(DiskFS* pDiskFS) : A2File(pDiskFS) { - fTSListTrack = -1; - fTSListSector = -1; - fLengthInSectors = 0; - fLocked = false; - fFileName[0] = '\0'; - fFileType = kTypeUnknown; + fTSListTrack = -1; + fTSListSector = -1; + fLengthInSectors = 0; + fLocked = false; + fFileName[0] = '\0'; + fFileType = kTypeUnknown; - fCatTS.track = fCatTS.sector = 0; - fCatEntryNum = -1; + fCatTS.track = fCatTS.sector = 0; + fCatEntryNum = -1; - fAuxType = 0; - fDataOffset = 0; - fLength = -1; - fSparseLength = -1; + fAuxType = 0; + fDataOffset = 0; + fLength = -1; + fSparseLength = -1; - fpOpenFile = nil; + fpOpenFile = nil; } /* @@ -2434,7 +2434,7 @@ A2FileDOS::A2FileDOS(DiskFS* pDiskFS) : A2File(pDiskFS) */ A2FileDOS::~A2FileDOS(void) { - delete fpOpenFile; + delete fpOpenFile; } @@ -2456,24 +2456,24 @@ A2FileDOS::~A2FileDOS(void) long A2FileDOS::GetFileType(void) const { - long retval; + long retval; - switch (fFileType) { - case kTypeText: retval = 0x04; break; // TXT - case kTypeInteger: retval = 0xfa; break; // INT - case kTypeApplesoft: retval = 0xfc; break; // BAS - case kTypeBinary: retval = 0x06; break; // BIN - case kTypeS: retval = 0xf2; break; // $f2 - case kTypeReloc: retval = 0xfe; break; // REL - case kTypeA: retval = 0xf3; break; // $f3 - case kTypeB: retval = 0xf4; break; // $f4 - case kTypeUnknown: - default: - retval = 0x00; // NON - break; - } + switch (fFileType) { + case kTypeText: retval = 0x04; break; // TXT + case kTypeInteger: retval = 0xfa; break; // INT + case kTypeApplesoft: retval = 0xfc; break; // BAS + case kTypeBinary: retval = 0x06; break; // BIN + case kTypeS: retval = 0xf2; break; // $f2 + case kTypeReloc: retval = 0xfe; break; // REL + case kTypeA: retval = 0xf3; break; // $f3 + case kTypeB: retval = 0xf4; break; // $f4 + case kTypeUnknown: + default: + retval = 0x00; // NON + break; + } - return retval; + return retval; } /* @@ -2494,31 +2494,31 @@ A2FileDOS::GetFileType(void) const /*static*/ A2FileDOS::FileType A2FileDOS::ConvertFileType(long prodosType, di_off_t fileLen) { - const long kMaxBinary = 65535; - FileType newType; + const long kMaxBinary = 65535; + FileType newType; - switch (prodosType) { - case 0xb0: newType = kTypeText; break; // SRC - case 0x04: newType = kTypeText; break; // TXT - case 0xfa: newType = kTypeInteger; break; // INT - case 0xfc: newType = kTypeApplesoft; break; // BAS - case 0x06: newType = kTypeBinary; break; // BIN - case 0xf2: newType = kTypeS; break; // $f2 - case 0xfe: newType = kTypeReloc; break; // REL - case 0xf3: newType = kTypeA; break; // $f3 - case 0xf4: newType = kTypeB; break; // $f4 - default: newType = kTypeS; break; - } + switch (prodosType) { + case 0xb0: newType = kTypeText; break; // SRC + case 0x04: newType = kTypeText; break; // TXT + case 0xfa: newType = kTypeInteger; break; // INT + case 0xfc: newType = kTypeApplesoft; break; // BAS + case 0x06: newType = kTypeBinary; break; // BIN + case 0xf2: newType = kTypeS; break; // $f2 + case 0xfe: newType = kTypeReloc; break; // REL + case 0xf3: newType = kTypeA; break; // $f3 + case 0xf4: newType = kTypeB; break; // $f4 + default: newType = kTypeS; break; + } - if (fileLen > kMaxBinary && - (newType == kTypeInteger || newType == kTypeApplesoft || - newType == kTypeBinary)) - { - WMSG0(" DOS setting type for large A/I/B file to S\n"); - newType = kTypeS; - } + if (fileLen > kMaxBinary && + (newType == kTypeInteger || newType == kTypeApplesoft || + newType == kTypeBinary)) + { + WMSG0(" DOS setting type for large A/I/B file to S\n"); + newType = kTypeS; + } - return newType; + return newType; } /* @@ -2527,20 +2527,20 @@ A2FileDOS::ConvertFileType(long prodosType, di_off_t fileLen) /*static*/ bool A2FileDOS::IsValidType(long prodosType) { - switch (prodosType) { - case 0xb0: // SRC - case 0x04: // TXT - case 0xfa: // INT - case 0xfc: // BAS - case 0x06: // BIN - case 0xf2: // $f2 - case 0xfe: // REL - case 0xf3: // $f3 - case 0xf4: // $f4 - return true; - default: - return false; - } + switch (prodosType) { + case 0xb0: // SRC + case 0x04: // TXT + case 0xfa: // INT + case 0xfc: // BAS + case 0x06: // BIN + case 0xf2: // $f2 + case 0xfe: // REL + case 0xf3: // $f3 + case 0xf4: // $f4 + return true; + default: + return false; + } } /* @@ -2549,10 +2549,10 @@ A2FileDOS::IsValidType(long prodosType) long A2FileDOS::GetAccess(void) const { - if (fLocked) - return DiskFS::kFileAccessLocked; // 0x01 read - else - return DiskFS::kFileAccessUnlocked; // 0xc3 read/write/rename/destroy + if (fLocked) + return DiskFS::kFileAccessLocked; // 0x01 read + else + return DiskFS::kFileAccessUnlocked; // 0xc3 read/write/rename/destroy } /* @@ -2562,8 +2562,8 @@ A2FileDOS::GetAccess(void) const void A2FileDOS::FixFilename(void) { - DiskFSDOS33::LowerASCII((unsigned char*)fFileName, kMaxFileName); - TrimTrailingSpaces(fFileName); + DiskFSDOS33::LowerASCII((unsigned char*)fFileName, kMaxFileName); + TrimTrailingSpaces(fFileName); } /* @@ -2574,16 +2574,16 @@ A2FileDOS::FixFilename(void) /*static*/ void A2FileDOS::TrimTrailingSpaces(char* filename) { - char* lastspc = filename + strlen(filename); + char* lastspc = filename + strlen(filename); - assert(*lastspc == '\0'); + assert(*lastspc == '\0'); - while (--lastspc) { - if (*lastspc != ' ') - break; - } + while (--lastspc) { + if (*lastspc != ' ') + break; + } - *(lastspc+1) = '\0'; + *(lastspc+1) = '\0'; } /* @@ -2596,13 +2596,13 @@ A2FileDOS::TrimTrailingSpaces(char* filename) /*static*/ void A2FileDOS::MakeDOSName(char* buf, const char* name) { - for (int i = 0; i < kMaxFileName; i++) { - if (*name == '\0') - *buf++ = (char) 0xa0; - else - *buf++ = toupper(*name++) | 0x80; - } - *buf = '\0'; + for (int i = 0; i < kMaxFileName; i++) { + if (*name == '\0') + *buf++ = (char) 0xa0; + else + *buf++ = toupper(*name++) | 0x80; + } + *buf = '\0'; } @@ -2611,46 +2611,46 @@ A2FileDOS::MakeDOSName(char* buf, const char* name) */ DIError A2FileDOS::Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork /*=false*/) + bool rsrcFork /*=false*/) { - DIError dierr = kDIErrNone; - A2FDDOS* pOpenFile = nil; + DIError dierr = kDIErrNone; + A2FDDOS* pOpenFile = nil; - if (!readOnly) { - if (fpDiskFS->GetDiskImg()->GetReadOnly()) - return kDIErrAccessDenied; - if (fpDiskFS->GetFSDamaged()) - return kDIErrBadDiskImage; - } + if (!readOnly) { + if (fpDiskFS->GetDiskImg()->GetReadOnly()) + return kDIErrAccessDenied; + if (fpDiskFS->GetFSDamaged()) + return kDIErrBadDiskImage; + } - if (fpOpenFile != nil) { - dierr = kDIErrAlreadyOpen; - goto bail; - } + if (fpOpenFile != nil) { + dierr = kDIErrAlreadyOpen; + goto bail; + } - if (rsrcFork) - return kDIErrForkNotFound; + if (rsrcFork) + return kDIErrForkNotFound; - pOpenFile = new A2FDDOS(this); + pOpenFile = new A2FDDOS(this); - dierr = LoadTSList(&pOpenFile->fTSList, &pOpenFile->fTSCount, - &pOpenFile->fIndexList, &pOpenFile->fIndexCount); - if (dierr != kDIErrNone) { - WMSG1("DOS33 unable to load TS for '%s' open\n", GetPathName()); - goto bail; - } + dierr = LoadTSList(&pOpenFile->fTSList, &pOpenFile->fTSCount, + &pOpenFile->fIndexList, &pOpenFile->fIndexCount); + if (dierr != kDIErrNone) { + WMSG1("DOS33 unable to load TS for '%s' open\n", GetPathName()); + goto bail; + } - pOpenFile->fOffset = 0; - pOpenFile->fOpenEOF = fLength; - pOpenFile->fOpenSectorsUsed = fLengthInSectors; + pOpenFile->fOffset = 0; + pOpenFile->fOpenEOF = fLength; + pOpenFile->fOpenSectorsUsed = fLengthInSectors; - fpOpenFile = pOpenFile; // add it to our single-member "open file set" - *ppOpenFile = pOpenFile; - pOpenFile = nil; + fpOpenFile = pOpenFile; // add it to our single-member "open file set" + *ppOpenFile = pOpenFile; + pOpenFile = nil; bail: - delete pOpenFile; - return dierr; + delete pOpenFile; + return dierr; } /* @@ -2659,12 +2659,12 @@ bail: void A2FileDOS::Dump(void) const { - WMSG1("A2FileDOS '%s'\n", fFileName); - WMSG2(" TS T=%-2d S=%-2d\n", fTSListTrack, fTSListSector); - WMSG2(" Cat T=%-2d S=%-2d\n", fCatTS.track, fCatTS.sector); - WMSG3(" type=%d lck=%d slen=%d\n", fFileType, fLocked, fLengthInSectors); - WMSG2(" auxtype=0x%04x length=%ld\n", - fAuxType, (long) fLength); + WMSG1("A2FileDOS '%s'\n", fFileName); + WMSG2(" TS T=%-2d S=%-2d\n", fTSListTrack, fTSListSector); + WMSG2(" Cat T=%-2d S=%-2d\n", fCatTS.track, fCatTS.sector); + WMSG3(" type=%d lck=%d slen=%d\n", fFileType, fLocked, fLengthInSectors); + WMSG2(" auxtype=0x%04x length=%ld\n", + fAuxType, (long) fLength); } @@ -2692,169 +2692,169 @@ A2FileDOS::Dump(void) const */ DIError A2FileDOS::LoadTSList(TrackSector** pTSList, int* pTSCount, - TrackSector** pIndexList, int* pIndexCount) + TrackSector** pIndexList, int* pIndexCount) { - DIError dierr = kDIErrNone; - DiskImg* pDiskImg; - const int kDefaultTSAlloc = 2; - const int kDefaultIndexAlloc = 8; - TrackSector* tsList = nil; - TrackSector* indexList = nil; - int tsCount, tsAlloc; - int indexCount, indexAlloc; - unsigned char sctBuf[kSctSize]; - int track, sector, iterations; + DIError dierr = kDIErrNone; + DiskImg* pDiskImg; + const int kDefaultTSAlloc = 2; + const int kDefaultIndexAlloc = 8; + TrackSector* tsList = nil; + TrackSector* indexList = nil; + int tsCount, tsAlloc; + int indexCount, indexAlloc; + unsigned char sctBuf[kSctSize]; + int track, sector, iterations; - WMSG1("--- DOS loading T/S list for '%s'\n", GetPathName()); + WMSG1("--- DOS loading T/S list for '%s'\n", GetPathName()); - /* over-alloc for small files to reduce reallocs */ - tsAlloc = kMaxTSPairs * kDefaultTSAlloc; - tsList = new TrackSector[tsAlloc]; - tsCount = 0; + /* over-alloc for small files to reduce reallocs */ + tsAlloc = kMaxTSPairs * kDefaultTSAlloc; + tsList = new TrackSector[tsAlloc]; + tsCount = 0; - indexAlloc = kDefaultIndexAlloc; - indexList = new TrackSector[indexAlloc]; - indexCount = 0; + indexAlloc = kDefaultIndexAlloc; + indexList = new TrackSector[indexAlloc]; + indexCount = 0; - if (tsList == nil || indexList == nil) { - dierr = kDIErrMalloc; - goto bail; - } + if (tsList == nil || indexList == nil) { + dierr = kDIErrMalloc; + goto bail; + } - assert(fpDiskFS != nil); - pDiskImg = fpDiskFS->GetDiskImg(); - assert(pDiskImg != nil); + assert(fpDiskFS != nil); + pDiskImg = fpDiskFS->GetDiskImg(); + assert(pDiskImg != nil); - /* get the first T/S sector for this file */ - track = fTSListTrack; - sector = fTSListSector; - if (track >= pDiskImg->GetNumTracks() || - sector >= pDiskImg->GetNumSectPerTrack()) - { - WMSG3(" DOS33 invalid initial T/S %d,%d in '%s'\n", track, sector, - fFileName); - dierr = kDIErrBadFile; - goto bail; - } + /* get the first T/S sector for this file */ + track = fTSListTrack; + sector = fTSListSector; + if (track >= pDiskImg->GetNumTracks() || + sector >= pDiskImg->GetNumSectPerTrack()) + { + WMSG3(" DOS33 invalid initial T/S %d,%d in '%s'\n", track, sector, + fFileName); + dierr = kDIErrBadFile; + goto bail; + } - /* - * Run through the set of t/s pairs. - */ - iterations = 0; - do { - unsigned short sectorOffset; - int lastNonZero; + /* + * Run through the set of t/s pairs. + */ + iterations = 0; + do { + unsigned short sectorOffset; + int lastNonZero; - /* - * Add the current T/S sector to the index list. - */ - if (indexCount == indexAlloc) { - WMSG0("+++ expanding index list\n"); - TrackSector* newList; - indexAlloc += kDefaultIndexAlloc; - newList = new TrackSector[indexAlloc]; - if (newList == nil) { - dierr = kDIErrMalloc; - goto bail; - } - memcpy(newList, indexList, indexCount * sizeof(TrackSector)); - delete[] indexList; - indexList = newList; - } - indexList[indexCount].track = track; - indexList[indexCount].sector = sector; - indexCount++; + /* + * Add the current T/S sector to the index list. + */ + if (indexCount == indexAlloc) { + WMSG0("+++ expanding index list\n"); + TrackSector* newList; + indexAlloc += kDefaultIndexAlloc; + newList = new TrackSector[indexAlloc]; + if (newList == nil) { + dierr = kDIErrMalloc; + goto bail; + } + memcpy(newList, indexList, indexCount * sizeof(TrackSector)); + delete[] indexList; + indexList = newList; + } + indexList[indexCount].track = track; + indexList[indexCount].sector = sector; + indexCount++; - //WMSG2("+++ scanning T/S at T=%d S=%d\n", track, sector); - dierr = pDiskImg->ReadTrackSector(track, sector, sctBuf); - if (dierr != kDIErrNone) - goto bail; + //WMSG2("+++ scanning T/S at T=%d S=%d\n", track, sector); + dierr = pDiskImg->ReadTrackSector(track, sector, sctBuf); + if (dierr != kDIErrNone) + goto bail; - /* grab next track/sector */ - track = sctBuf[0x01]; - sector = sctBuf[0x02]; - sectorOffset = GetShortLE(&sctBuf[0x05]); + /* grab next track/sector */ + track = sctBuf[0x01]; + sector = sctBuf[0x02]; + sectorOffset = GetShortLE(&sctBuf[0x05]); - /* if T/S link is bogus, whole sector is probably bad */ - if (track >= pDiskImg->GetNumTracks() || - sector >= pDiskImg->GetNumSectPerTrack()) - { - // bogus T/S, mark file as damaged and stop - WMSG3(" DOS33 invalid T/S link %d,%d in '%s'\n", track, sector, - GetPathName()); - dierr = kDIErrBadFile; - goto bail; - } - if ((sectorOffset % kMaxTSPairs) != 0) { - WMSG2(" DOS33 invalid T/S header sector offset %u in '%s'\n", - sectorOffset, GetPathName()); - // not fatal, just weird - } + /* if T/S link is bogus, whole sector is probably bad */ + if (track >= pDiskImg->GetNumTracks() || + sector >= pDiskImg->GetNumSectPerTrack()) + { + // bogus T/S, mark file as damaged and stop + WMSG3(" DOS33 invalid T/S link %d,%d in '%s'\n", track, sector, + GetPathName()); + dierr = kDIErrBadFile; + goto bail; + } + if ((sectorOffset % kMaxTSPairs) != 0) { + WMSG2(" DOS33 invalid T/S header sector offset %u in '%s'\n", + sectorOffset, GetPathName()); + // not fatal, just weird + } - /* - * Make sure we have enough room to hold an entire sector full of - * T/S pairs in the list. - */ - if (tsCount + kMaxTSPairs > tsAlloc) { - WMSG0("+++ expanding ts list\n"); - TrackSector* newList; - tsAlloc += kMaxTSPairs * kDefaultTSAlloc; - newList = new TrackSector[tsAlloc]; - if (newList == nil) { - dierr = kDIErrMalloc; - goto bail; - } - memcpy(newList, tsList, tsCount * sizeof(TrackSector)); - delete[] tsList; - tsList = newList; - } + /* + * Make sure we have enough room to hold an entire sector full of + * T/S pairs in the list. + */ + if (tsCount + kMaxTSPairs > tsAlloc) { + WMSG0("+++ expanding ts list\n"); + TrackSector* newList; + tsAlloc += kMaxTSPairs * kDefaultTSAlloc; + newList = new TrackSector[tsAlloc]; + if (newList == nil) { + dierr = kDIErrMalloc; + goto bail; + } + memcpy(newList, tsList, tsCount * sizeof(TrackSector)); + delete[] tsList; + tsList = newList; + } - /* - * Add the entries. If there's another T/S list linked, we just - * grab the entire sector. If not, we grab every entry until the - * last 0,0. (Can't stop at the first (0,0), or we'll drop a - * piece of a random access text file.) - */ - dierr = ExtractTSPairs(sctBuf, &tsList[tsCount], &lastNonZero); - if (dierr != kDIErrNone) - goto bail; + /* + * Add the entries. If there's another T/S list linked, we just + * grab the entire sector. If not, we grab every entry until the + * last 0,0. (Can't stop at the first (0,0), or we'll drop a + * piece of a random access text file.) + */ + dierr = ExtractTSPairs(sctBuf, &tsList[tsCount], &lastNonZero); + if (dierr != kDIErrNone) + goto bail; - if (track != 0 && sector != 0) { - /* more T/S lists to come, so we keep all entries */ - tsCount += kMaxTSPairs; - } else { - /* this was the last one */ - if (lastNonZero == -1) { - /* this is ALWAYS the case for a newly-created file */ - //WMSG1(" DOS33 odd -- last T/S sector of '%s' was empty\n", - // GetPathName()); - } - tsCount += lastNonZero +1; - } + if (track != 0 && sector != 0) { + /* more T/S lists to come, so we keep all entries */ + tsCount += kMaxTSPairs; + } else { + /* this was the last one */ + if (lastNonZero == -1) { + /* this is ALWAYS the case for a newly-created file */ + //WMSG1(" DOS33 odd -- last T/S sector of '%s' was empty\n", + // GetPathName()); + } + tsCount += lastNonZero +1; + } - iterations++; // watch for infinite loops - } while (!(track == 0 && sector == 0) && iterations < kMaxTSIterations); + iterations++; // watch for infinite loops + } while (!(track == 0 && sector == 0) && iterations < kMaxTSIterations); - if (iterations == kMaxTSIterations) { - dierr = kDIErrFileLoop; - goto bail; - } + if (iterations == kMaxTSIterations) { + dierr = kDIErrFileLoop; + goto bail; + } - *pTSList = tsList; - *pTSCount = tsCount; - tsList = nil; + *pTSList = tsList; + *pTSCount = tsCount; + tsList = nil; - if (pIndexList != nil) { - *pIndexList = indexList; - *pIndexCount = indexCount; - indexList = nil; - } + if (pIndexList != nil) { + *pIndexList = indexList; + *pIndexCount = indexCount; + indexList = nil; + } bail: - delete[] tsList; - delete[] indexList; - return dierr; + delete[] tsList; + delete[] indexList; + return dierr; } /* @@ -2877,55 +2877,55 @@ bail: */ DIError A2FileDOS::ExtractTSPairs(const unsigned char* sctBuf, TrackSector* tsList, - int* pLastNonZero) + int* pLastNonZero) { - DIError dierr = kDIErrNone; - const DiskImg* pDiskImg = fpDiskFS->GetDiskImg(); - const unsigned char* ptr; - int i, track, sector; + DIError dierr = kDIErrNone; + const DiskImg* pDiskImg = fpDiskFS->GetDiskImg(); + const unsigned char* ptr; + int i, track, sector; - *pLastNonZero = -1; - memset(tsList, 0, sizeof(TrackSector) * kMaxTSPairs); + *pLastNonZero = -1; + memset(tsList, 0, sizeof(TrackSector) * kMaxTSPairs); - ptr = &sctBuf[kTSOffset]; // offset of first T/S entry (0x0c) + ptr = &sctBuf[kTSOffset]; // offset of first T/S entry (0x0c) - for (i = 0; i < kMaxTSPairs; i++) { - track = *ptr++; - sector = *ptr++; + for (i = 0; i < kMaxTSPairs; i++) { + track = *ptr++; + sector = *ptr++; - if (dierr == kDIErrNone && - (track >= pDiskImg->GetNumTracks() || - sector >= pDiskImg->GetNumSectPerTrack() || - (track == 0 && sector != 0))) - { - WMSG3(" DOS33 invalid T/S %d,%d in '%s'\n", track, sector, - fFileName); + if (dierr == kDIErrNone && + (track >= pDiskImg->GetNumTracks() || + sector >= pDiskImg->GetNumSectPerTrack() || + (track == 0 && sector != 0))) + { + WMSG3(" DOS33 invalid T/S %d,%d in '%s'\n", track, sector, + fFileName); - if (i > 0 && tsList[i-1].track == 0 && tsList[i-1].sector == 0) { - WMSG0(" T/S list looks partially valid\n"); - SetQuality(kQualitySuspicious); - goto bail; // quit immediately - } else { - dierr = kDIErrBadFile; - // keep going, just so caller has the full set to stare at - } - } + if (i > 0 && tsList[i-1].track == 0 && tsList[i-1].sector == 0) { + WMSG0(" T/S list looks partially valid\n"); + SetQuality(kQualitySuspicious); + goto bail; // quit immediately + } else { + dierr = kDIErrBadFile; + // keep going, just so caller has the full set to stare at + } + } - if (track != 0 || sector != 0) - *pLastNonZero = i; + if (track != 0 || sector != 0) + *pLastNonZero = i; - tsList[i].track = track; - tsList[i].sector = sector; - } + tsList[i].track = track; + tsList[i].sector = sector; + } bail: - return dierr; + return dierr; } /* * =========================================================================== - * A2FDDOS + * A2FDDOS * =========================================================================== */ @@ -2938,75 +2938,75 @@ bail: DIError A2FDDOS::Read(void* buf, size_t len, size_t* pActual) { - WMSG3(" DOS reading %d bytes from '%s' (offset=%ld)\n", - len, fpFile->GetPathName(), (long) fOffset); + WMSG3(" DOS reading %d bytes from '%s' (offset=%ld)\n", + len, fpFile->GetPathName(), (long) fOffset); - A2FileDOS* pFile = (A2FileDOS*) fpFile; + A2FileDOS* pFile = (A2FileDOS*) fpFile; - /* - * Don't allow them to read past the end of the file. The length value - * stored in pFile->fLength already has pFile->fDataOffset subtracted - * from the actual data length, so don't factor it in again. - */ - if (fOffset + (long)len > fOpenEOF) { - if (pActual == nil) - return kDIErrDataUnderrun; - len = (size_t) (fOpenEOF - fOffset); - } - if (pActual != nil) - *pActual = len; - long incrLen = len; + /* + * Don't allow them to read past the end of the file. The length value + * stored in pFile->fLength already has pFile->fDataOffset subtracted + * from the actual data length, so don't factor it in again. + */ + if (fOffset + (long)len > fOpenEOF) { + if (pActual == nil) + return kDIErrDataUnderrun; + len = (size_t) (fOpenEOF - fOffset); + } + if (pActual != nil) + *pActual = len; + long incrLen = len; - DIError dierr = kDIErrNone; - unsigned char sctBuf[kSctSize]; - di_off_t actualOffset = fOffset + pFile->fDataOffset; // adjust for embedded len - int tsIndex = (int) (actualOffset / kSctSize); - int bufOffset = (int) (actualOffset % kSctSize); // (& 0xff) - size_t thisCount; + DIError dierr = kDIErrNone; + unsigned char sctBuf[kSctSize]; + di_off_t actualOffset = fOffset + pFile->fDataOffset; // adjust for embedded len + int tsIndex = (int) (actualOffset / kSctSize); + int bufOffset = (int) (actualOffset % kSctSize); // (& 0xff) + size_t thisCount; - if (len == 0) - return kDIErrNone; - assert(fOpenEOF != 0); + if (len == 0) + return kDIErrNone; + assert(fOpenEOF != 0); - assert(tsIndex >= 0 && tsIndex < fTSCount); + assert(tsIndex >= 0 && tsIndex < fTSCount); - /* could be more clever in here and avoid double-buffering */ - while (len) { - if (tsIndex >= fTSCount) { - /* should've caught this earlier */ - assert(false); - WMSG1(" DOS ran off the end (fTSCount=%d)\n", fTSCount); - return kDIErrDataUnderrun; - } + /* could be more clever in here and avoid double-buffering */ + while (len) { + if (tsIndex >= fTSCount) { + /* should've caught this earlier */ + assert(false); + WMSG1(" DOS ran off the end (fTSCount=%d)\n", fTSCount); + return kDIErrDataUnderrun; + } - if (fTSList[tsIndex].track == 0 && fTSList[tsIndex].sector == 0) { - //WMSG2(" DOS sparse sector T=%d S=%d\n", - // TSTrack(fTSList[tsIndex]), TSSector(fTSList[tsIndex])); - memset(sctBuf, 0, sizeof(sctBuf)); - } else { - dierr = pFile->GetDiskFS()->GetDiskImg()->ReadTrackSector( - fTSList[tsIndex].track, - fTSList[tsIndex].sector, - sctBuf); - if (dierr != kDIErrNone) { - WMSG1(" DOS error reading file '%s'\n", pFile->GetPathName()); - return dierr; - } - } - thisCount = kSctSize - bufOffset; - if (thisCount > len) - thisCount = len; - memcpy(buf, sctBuf + bufOffset, thisCount); - len -= thisCount; - buf = (char*)buf + thisCount; + if (fTSList[tsIndex].track == 0 && fTSList[tsIndex].sector == 0) { + //WMSG2(" DOS sparse sector T=%d S=%d\n", + // TSTrack(fTSList[tsIndex]), TSSector(fTSList[tsIndex])); + memset(sctBuf, 0, sizeof(sctBuf)); + } else { + dierr = pFile->GetDiskFS()->GetDiskImg()->ReadTrackSector( + fTSList[tsIndex].track, + fTSList[tsIndex].sector, + sctBuf); + if (dierr != kDIErrNone) { + WMSG1(" DOS error reading file '%s'\n", pFile->GetPathName()); + return dierr; + } + } + thisCount = kSctSize - bufOffset; + if (thisCount > len) + thisCount = len; + memcpy(buf, sctBuf + bufOffset, thisCount); + len -= thisCount; + buf = (char*)buf + thisCount; - bufOffset = 0; - tsIndex++; - } + bufOffset = 0; + tsIndex++; + } - fOffset += incrLen; + fOffset += incrLen; - return dierr; + return dierr; } /* @@ -3026,204 +3026,204 @@ A2FDDOS::Read(void* buf, size_t len, size_t* pActual) DIError A2FDDOS::Write(const void* buf, size_t len, size_t* pActual) { - DIError dierr = kDIErrNone; - A2FileDOS* pFile = (A2FileDOS*) fpFile; - DiskFSDOS33* pDiskFS = (DiskFSDOS33*) fpFile->GetDiskFS(); - unsigned char sctBuf[kSctSize]; + DIError dierr = kDIErrNone; + A2FileDOS* pFile = (A2FileDOS*) fpFile; + DiskFSDOS33* pDiskFS = (DiskFSDOS33*) fpFile->GetDiskFS(); + unsigned char sctBuf[kSctSize]; - WMSG2(" DOS Write len=%u %s\n", len, pFile->GetPathName()); + WMSG2(" DOS Write len=%u %s\n", len, pFile->GetPathName()); - if (len >= 0x01000000) { // 16MB - assert(false); - return kDIErrInvalidArg; - } - assert(fOffset == 0); // big simplifying assumption - assert(fOpenEOF == 0); // another one - assert(fTSCount == 0); // must hold for our newly-created files - assert(fIndexCount == 1); // must hold for our newly-created files - assert(fOpenSectorsUsed == fTSCount + fIndexCount); - assert(buf != nil); + if (len >= 0x01000000) { // 16MB + assert(false); + return kDIErrInvalidArg; + } + assert(fOffset == 0); // big simplifying assumption + assert(fOpenEOF == 0); // another one + assert(fTSCount == 0); // must hold for our newly-created files + assert(fIndexCount == 1); // must hold for our newly-created files + assert(fOpenSectorsUsed == fTSCount + fIndexCount); + assert(buf != nil); - long actualLen = (long) len + pFile->fDataOffset; - long numSectors = (actualLen + kSctSize -1) / kSctSize; - TrackSector firstIndex; - int i; + long actualLen = (long) len + pFile->fDataOffset; + long numSectors = (actualLen + kSctSize -1) / kSctSize; + TrackSector firstIndex; + int i; - /* - * Nothing to do for zero-length write; don't even set fModified. Note, - * however, that a zero-length 'B' file is actually 4 bytes long, and - * must have a data block allocated. - */ - if (actualLen == 0) - goto bail; - assert(numSectors > 0); + /* + * Nothing to do for zero-length write; don't even set fModified. Note, + * however, that a zero-length 'B' file is actually 4 bytes long, and + * must have a data block allocated. + */ + if (actualLen == 0) + goto bail; + assert(numSectors > 0); - dierr = pDiskFS->LoadVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + dierr = pDiskFS->LoadVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - /* - * Start by allocating a full T/S list. The existing T/S list is - * empty, but we do have one T/S index sector to fill before we - * allocate any others. - * - * Since we determined above that there was nothing interesting in - * our T/S list, we just grab the one allocated block, throw out - * the lists, and reallocate them. - */ - firstIndex = fIndexList[0]; - delete[] fTSList; - delete[] fIndexList; - fTSList = fIndexList = nil; + /* + * Start by allocating a full T/S list. The existing T/S list is + * empty, but we do have one T/S index sector to fill before we + * allocate any others. + * + * Since we determined above that there was nothing interesting in + * our T/S list, we just grab the one allocated block, throw out + * the lists, and reallocate them. + */ + firstIndex = fIndexList[0]; + delete[] fTSList; + delete[] fIndexList; + fTSList = fIndexList = nil; - fTSCount = numSectors; - fTSList = new TrackSector[fTSCount]; - fIndexCount = (numSectors + kMaxTSPairs -1) / kMaxTSPairs; - assert(fIndexCount > 0); - fIndexList = new TrackSector[fIndexCount]; - if (fTSList == nil || fIndexList == nil) { - dierr = kDIErrMalloc; - goto bail; - } + fTSCount = numSectors; + fTSList = new TrackSector[fTSCount]; + fIndexCount = (numSectors + kMaxTSPairs -1) / kMaxTSPairs; + assert(fIndexCount > 0); + fIndexList = new TrackSector[fIndexCount]; + if (fTSList == nil || fIndexList == nil) { + dierr = kDIErrMalloc; + goto bail; + } - /* - * Allocate all of the index sectors. In theory we should to this along - * with the file sectors, so that the index and file sectors are - * interspersed with the data, but in practice 99% of the file have - * only one or two index blocks. By grouping them together we improve - * the performance for emulators and CiderPress. - */ - fIndexList[0] = firstIndex; - for (i = 1; i < fIndexCount; i++) { - TrackSector allocTS; + /* + * Allocate all of the index sectors. In theory we should to this along + * with the file sectors, so that the index and file sectors are + * interspersed with the data, but in practice 99% of the file have + * only one or two index blocks. By grouping them together we improve + * the performance for emulators and CiderPress. + */ + fIndexList[0] = firstIndex; + for (i = 1; i < fIndexCount; i++) { + TrackSector allocTS; - dierr = pDiskFS->AllocSector(&allocTS); - if (dierr != kDIErrNone) - goto bail; - fIndexList[i] = allocTS; - } - /* - * Allocate the data sectors. - */ - for (i = 0; i < fTSCount; i++) { - TrackSector allocTS; + dierr = pDiskFS->AllocSector(&allocTS); + if (dierr != kDIErrNone) + goto bail; + fIndexList[i] = allocTS; + } + /* + * Allocate the data sectors. + */ + for (i = 0; i < fTSCount; i++) { + TrackSector allocTS; - dierr = pDiskFS->AllocSector(&allocTS); - if (dierr != kDIErrNone) - goto bail; - fTSList[i] = allocTS; - } + dierr = pDiskFS->AllocSector(&allocTS); + if (dierr != kDIErrNone) + goto bail; + fTSList[i] = allocTS; + } - /* - * Write the sectors into the T/S list. - */ - const unsigned char* curPtr; - int sectorIdx; + /* + * Write the sectors into the T/S list. + */ + const unsigned char* curPtr; + int sectorIdx; - curPtr = (const unsigned char*) buf; - sectorIdx = 0; + curPtr = (const unsigned char*) buf; + sectorIdx = 0; - if (pFile->fDataOffset > 0) { - /* handle first sector specially */ - assert(pFile->fDataOffset < kSctSize); - int dataInFirstSct = kSctSize - pFile->fDataOffset; - if (dataInFirstSct > actualLen - pFile->fDataOffset) - dataInFirstSct = actualLen - pFile->fDataOffset; + if (pFile->fDataOffset > 0) { + /* handle first sector specially */ + assert(pFile->fDataOffset < kSctSize); + int dataInFirstSct = kSctSize - pFile->fDataOffset; + if (dataInFirstSct > actualLen - pFile->fDataOffset) + dataInFirstSct = actualLen - pFile->fDataOffset; - // dataInFirstSct could be zero (== len) - memset(sctBuf, 0, sizeof(sctBuf)); - memcpy(sctBuf + pFile->fDataOffset, curPtr, - dataInFirstSct); - dierr = pDiskFS->GetDiskImg()->WriteTrackSector(fTSList[sectorIdx].track, - fTSList[sectorIdx].sector, sctBuf); - if (dierr != kDIErrNone) - goto bail; + // dataInFirstSct could be zero (== len) + memset(sctBuf, 0, sizeof(sctBuf)); + memcpy(sctBuf + pFile->fDataOffset, curPtr, + dataInFirstSct); + dierr = pDiskFS->GetDiskImg()->WriteTrackSector(fTSList[sectorIdx].track, + fTSList[sectorIdx].sector, sctBuf); + if (dierr != kDIErrNone) + goto bail; - sectorIdx++; - actualLen -= dataInFirstSct + pFile->fDataOffset; - curPtr += dataInFirstSct; - } - while (actualLen > 0) { - if (actualLen >= kSctSize) { - /* write directly from input */ - dierr = pDiskFS->GetDiskImg()->WriteTrackSector(fTSList[sectorIdx].track, - fTSList[sectorIdx].sector, curPtr); - if (dierr != kDIErrNone) - goto bail; - } else { - /* make a copy of the partial buffer */ - memset(sctBuf, 0, sizeof(sctBuf)); - memcpy(sctBuf, curPtr, actualLen); - dierr = pDiskFS->GetDiskImg()->WriteTrackSector(fTSList[sectorIdx].track, - fTSList[sectorIdx].sector, sctBuf); - if (dierr != kDIErrNone) - goto bail; - } + sectorIdx++; + actualLen -= dataInFirstSct + pFile->fDataOffset; + curPtr += dataInFirstSct; + } + while (actualLen > 0) { + if (actualLen >= kSctSize) { + /* write directly from input */ + dierr = pDiskFS->GetDiskImg()->WriteTrackSector(fTSList[sectorIdx].track, + fTSList[sectorIdx].sector, curPtr); + if (dierr != kDIErrNone) + goto bail; + } else { + /* make a copy of the partial buffer */ + memset(sctBuf, 0, sizeof(sctBuf)); + memcpy(sctBuf, curPtr, actualLen); + dierr = pDiskFS->GetDiskImg()->WriteTrackSector(fTSList[sectorIdx].track, + fTSList[sectorIdx].sector, sctBuf); + if (dierr != kDIErrNone) + goto bail; + } - sectorIdx++; - actualLen -= kSctSize; // goes negative; that's fine - curPtr += kSctSize; - } - assert(sectorIdx == fTSCount); + sectorIdx++; + actualLen -= kSctSize; // goes negative; that's fine + curPtr += kSctSize; + } + assert(sectorIdx == fTSCount); - /* - * Fill out the T/S list sectors. Failure here presents a potential - * problem because, once we've written the first T/S entry, the file - * appears to have storage that it actually doesn't. The easiest way - * to handle this safely is to start by writing the last index block - * first. - */ - for (i = fIndexCount-1; i >= 0; i--) { - int tsOffset = i * kMaxTSPairs; - assert(tsOffset < fTSCount); + /* + * Fill out the T/S list sectors. Failure here presents a potential + * problem because, once we've written the first T/S entry, the file + * appears to have storage that it actually doesn't. The easiest way + * to handle this safely is to start by writing the last index block + * first. + */ + for (i = fIndexCount-1; i >= 0; i--) { + int tsOffset = i * kMaxTSPairs; + assert(tsOffset < fTSCount); - memset(sctBuf, 0, kSctSize); - if (i != fIndexCount-1) { - sctBuf[0x01] = fIndexList[i+1].track; - sctBuf[0x02] = fIndexList[i+1].sector; - } - PutShortLE(&sctBuf[0x05], kMaxTSPairs * i); + memset(sctBuf, 0, kSctSize); + if (i != fIndexCount-1) { + sctBuf[0x01] = fIndexList[i+1].track; + sctBuf[0x02] = fIndexList[i+1].sector; + } + PutShortLE(&sctBuf[0x05], kMaxTSPairs * i); - int ent = i * kMaxTSPairs; // start here - for (int j = 0; j < kMaxTSPairs; j++) { - if (ent == fTSCount) - break; - sctBuf[kTSOffset + j*2] = fTSList[ent].track; - sctBuf[kTSOffset + j*2 +1] = fTSList[ent].sector; - ent++; - } + int ent = i * kMaxTSPairs; // start here + for (int j = 0; j < kMaxTSPairs; j++) { + if (ent == fTSCount) + break; + sctBuf[kTSOffset + j*2] = fTSList[ent].track; + sctBuf[kTSOffset + j*2 +1] = fTSList[ent].sector; + ent++; + } - dierr = pDiskFS->GetDiskImg()->WriteTrackSector(fIndexList[i].track, - fIndexList[i].sector, sctBuf); - if (dierr != kDIErrNone) - goto bail; - } + dierr = pDiskFS->GetDiskImg()->WriteTrackSector(fIndexList[i].track, + fIndexList[i].sector, sctBuf); + if (dierr != kDIErrNone) + goto bail; + } - dierr = pDiskFS->SaveVolBitmap(); - if (dierr != kDIErrNone) { - /* - * This is awkward -- we wrote the first T/S list, so the file - * now appears to have content, but the blocks aren't marked used. - * We read the VTOC successfully though, so it's VERY unlikely - * that this will fail. If it does, it's likely that any attempt - * to mitigate the problem will also fail. (Maybe we could force - * the object into read-only mode?) - */ - goto bail; - } + dierr = pDiskFS->SaveVolBitmap(); + if (dierr != kDIErrNone) { + /* + * This is awkward -- we wrote the first T/S list, so the file + * now appears to have content, but the blocks aren't marked used. + * We read the VTOC successfully though, so it's VERY unlikely + * that this will fail. If it does, it's likely that any attempt + * to mitigate the problem will also fail. (Maybe we could force + * the object into read-only mode?) + */ + goto bail; + } - /* finish up */ - fOpenSectorsUsed = fIndexCount + fTSCount; - fOpenEOF = len; - fOffset += len; - fModified = true; + /* finish up */ + fOpenSectorsUsed = fIndexCount + fTSCount; + fOpenEOF = len; + fOffset += len; + fModified = true; - if (!UpdateProgress(fOffset)) - dierr = kDIErrCancelled; + if (!UpdateProgress(fOffset)) + dierr = kDIErrCancelled; bail: - pDiskFS->FreeVolBitmap(); - return dierr; + pDiskFS->FreeVolBitmap(); + return dierr; } /* @@ -3232,34 +3232,34 @@ bail: DIError A2FDDOS::Seek(di_off_t offset, DIWhence whence) { - //di_off_t fileLength = fpFile->GetDataLength(); + //di_off_t fileLength = fpFile->GetDataLength(); - switch (whence) { - case kSeekSet: - if (offset < 0 || offset > fOpenEOF) - return kDIErrInvalidArg; - fOffset = offset; - break; - case kSeekEnd: - if (offset > 0 || offset < -fOpenEOF) - return kDIErrInvalidArg; - fOffset = fOpenEOF + offset; - break; - case kSeekCur: - if (offset < -fOffset || - offset >= (fOpenEOF - fOffset)) - { - return kDIErrInvalidArg; - } - fOffset += offset; - break; - default: - assert(false); - return kDIErrInvalidArg; - } + switch (whence) { + case kSeekSet: + if (offset < 0 || offset > fOpenEOF) + return kDIErrInvalidArg; + fOffset = offset; + break; + case kSeekEnd: + if (offset > 0 || offset < -fOpenEOF) + return kDIErrInvalidArg; + fOffset = fOpenEOF + offset; + break; + case kSeekCur: + if (offset < -fOffset || + offset >= (fOpenEOF - fOffset)) + { + return kDIErrInvalidArg; + } + fOffset += offset; + break; + default: + assert(false); + return kDIErrInvalidArg; + } - assert(fOffset >= 0 && fOffset <= fOpenEOF); - return kDIErrNone; + assert(fOffset >= 0 && fOffset <= fOpenEOF); + return kDIErrNone; } /* @@ -3268,7 +3268,7 @@ A2FDDOS::Seek(di_off_t offset, DIWhence whence) di_off_t A2FDDOS::Tell(void) { - return fOffset; + return fOffset; } /* @@ -3288,96 +3288,96 @@ A2FDDOS::Tell(void) DIError A2FDDOS::Close(void) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - if (fModified) { - DiskFSDOS33* pDiskFS = (DiskFSDOS33*) fpFile->GetDiskFS(); - A2FileDOS* pFile = (A2FileDOS*) fpFile; - unsigned char sctBuf[kSctSize]; - unsigned char* pEntry; + if (fModified) { + DiskFSDOS33* pDiskFS = (DiskFSDOS33*) fpFile->GetDiskFS(); + A2FileDOS* pFile = (A2FileDOS*) fpFile; + unsigned char sctBuf[kSctSize]; + unsigned char* pEntry; - /* - * Fill in the length and address, if needed for this type of file. - */ - if (pFile->fFileType == A2FileDOS::kTypeInteger || - pFile->fFileType == A2FileDOS::kTypeApplesoft || - pFile->fFileType == A2FileDOS::kTypeBinary) - { - assert(fTSCount > 0); - assert(pFile->fDataOffset > 0); - //assert(fOpenEOF < 65536); - if (fOpenEOF > 65535) { - WMSG1("WARNING: DOS Close trimming A/I/B file from %ld to 65535\n", - (long) fOpenEOF); - fOpenEOF = 65535; - } - dierr = pDiskFS->GetDiskImg()->ReadTrackSector(fTSList[0].track, - fTSList[0].sector, sctBuf); - if (dierr != kDIErrNone) { - WMSG0("DOS Close: unable to get first sector of file\n"); - goto bail; - } + /* + * Fill in the length and address, if needed for this type of file. + */ + if (pFile->fFileType == A2FileDOS::kTypeInteger || + pFile->fFileType == A2FileDOS::kTypeApplesoft || + pFile->fFileType == A2FileDOS::kTypeBinary) + { + assert(fTSCount > 0); + assert(pFile->fDataOffset > 0); + //assert(fOpenEOF < 65536); + if (fOpenEOF > 65535) { + WMSG1("WARNING: DOS Close trimming A/I/B file from %ld to 65535\n", + (long) fOpenEOF); + fOpenEOF = 65535; + } + dierr = pDiskFS->GetDiskImg()->ReadTrackSector(fTSList[0].track, + fTSList[0].sector, sctBuf); + if (dierr != kDIErrNone) { + WMSG0("DOS Close: unable to get first sector of file\n"); + goto bail; + } - if (pFile->fFileType == A2FileDOS::kTypeInteger || - pFile->fFileType == A2FileDOS::kTypeApplesoft) - { - PutShortLE(&sctBuf[0x00], (unsigned short) fOpenEOF); - } else { - PutShortLE(&sctBuf[0x00], pFile->fAuxType); - PutShortLE(&sctBuf[0x02], (unsigned short) fOpenEOF); - } + if (pFile->fFileType == A2FileDOS::kTypeInteger || + pFile->fFileType == A2FileDOS::kTypeApplesoft) + { + PutShortLE(&sctBuf[0x00], (unsigned short) fOpenEOF); + } else { + PutShortLE(&sctBuf[0x00], pFile->fAuxType); + PutShortLE(&sctBuf[0x02], (unsigned short) fOpenEOF); + } - dierr = pDiskFS->GetDiskImg()->WriteTrackSector(fTSList[0].track, - fTSList[0].sector, sctBuf); - if (dierr != kDIErrNone) { - WMSG0("DOS Close: unable to write first sector of file\n"); - goto bail; - } - } else if (pFile->fFileType == A2FileDOS::kTypeText) { - /* - * The length of text files can be determined by looking for the - * first $00. A file of exactly 256 bytes occupies only one - * sector though, so running out of sectors also works -- the - * last $00 is not mandatory. - * - * Bottom line is that the value we just wrote for fOpenEOF is - * *probably* recoverable, so we can stuff it into "fLength" - * with some assurance that it will be there when we reopen the - * file. - */ - } else { - /* - * The remaining file types have a length based solely on - * sector count. We need to round off our length value. - */ - fOpenEOF = ((fOpenEOF + kSctSize-1) / kSctSize) * kSctSize; - } + dierr = pDiskFS->GetDiskImg()->WriteTrackSector(fTSList[0].track, + fTSList[0].sector, sctBuf); + if (dierr != kDIErrNone) { + WMSG0("DOS Close: unable to write first sector of file\n"); + goto bail; + } + } else if (pFile->fFileType == A2FileDOS::kTypeText) { + /* + * The length of text files can be determined by looking for the + * first $00. A file of exactly 256 bytes occupies only one + * sector though, so running out of sectors also works -- the + * last $00 is not mandatory. + * + * Bottom line is that the value we just wrote for fOpenEOF is + * *probably* recoverable, so we can stuff it into "fLength" + * with some assurance that it will be there when we reopen the + * file. + */ + } else { + /* + * The remaining file types have a length based solely on + * sector count. We need to round off our length value. + */ + fOpenEOF = ((fOpenEOF + kSctSize-1) / kSctSize) * kSctSize; + } - /* - * Update our internal copies of stuff. - */ - pFile->fLength = fOpenEOF; - pFile->fSparseLength = pFile->fLength; - pFile->fLengthInSectors = (unsigned short) fOpenSectorsUsed; + /* + * Update our internal copies of stuff. + */ + pFile->fLength = fOpenEOF; + pFile->fSparseLength = pFile->fLength; + pFile->fLengthInSectors = (unsigned short) fOpenSectorsUsed; - /* - * Update the sector count in the directory entry. - */ - dierr = pDiskFS->GetDiskImg()->ReadTrackSector(pFile->fCatTS.track, - pFile->fCatTS.sector, sctBuf); - if (dierr != kDIErrNone) - goto bail; + /* + * Update the sector count in the directory entry. + */ + dierr = pDiskFS->GetDiskImg()->ReadTrackSector(pFile->fCatTS.track, + pFile->fCatTS.sector, sctBuf); + if (dierr != kDIErrNone) + goto bail; - pEntry = GetCatalogEntryPtr(sctBuf, pFile->fCatEntryNum); - assert(GetShortLE(&pEntry[0x21]) == 1); // holds for new file - PutShortLE(&pEntry[0x21], pFile->fLengthInSectors); - dierr = pDiskFS->GetDiskImg()->WriteTrackSector(pFile->fCatTS.track, - pFile->fCatTS.sector, sctBuf); - } + pEntry = GetCatalogEntryPtr(sctBuf, pFile->fCatEntryNum); + assert(GetShortLE(&pEntry[0x21]) == 1); // holds for new file + PutShortLE(&pEntry[0x21], pFile->fLengthInSectors); + dierr = pDiskFS->GetDiskImg()->WriteTrackSector(pFile->fCatTS.track, + pFile->fCatTS.sector, sctBuf); + } bail: - fpFile->CloseDescr(this); - return dierr; + fpFile->CloseDescr(this); + return dierr; } @@ -3387,12 +3387,12 @@ bail: long A2FDDOS::GetSectorCount(void) const { - return fTSCount; + return fTSCount; } long A2FDDOS::GetBlockCount(void) const { - return (fTSCount+1)/2; + return (fTSCount+1)/2; } /* @@ -3403,12 +3403,12 @@ A2FDDOS::GetBlockCount(void) const DIError A2FDDOS::GetStorage(long sectorIdx, long* pTrack, long* pSector) const { - if (sectorIdx < 0 || sectorIdx >= fTSCount) - return kDIErrInvalidIndex; + if (sectorIdx < 0 || sectorIdx >= fTSCount) + return kDIErrInvalidIndex; - *pTrack = fTSList[sectorIdx].track; - *pSector = fTSList[sectorIdx].sector; - return kDIErrNone; + *pTrack = fTSList[sectorIdx].track; + *pSector = fTSList[sectorIdx].sector; + return kDIErrNone; } /* * Return the Nth 512-byte block in this file. Since things aren't stored @@ -3418,15 +3418,15 @@ A2FDDOS::GetStorage(long sectorIdx, long* pTrack, long* pSector) const DIError A2FDDOS::GetStorage(long blockIdx, long* pBlock) const { - long sectorIdx = blockIdx * 2; - if (sectorIdx < 0 || sectorIdx >= fTSCount) - return kDIErrInvalidIndex; + long sectorIdx = blockIdx * 2; + if (sectorIdx < 0 || sectorIdx >= fTSCount) + return kDIErrInvalidIndex; - bool dummy; - TrackSectorToBlock(fTSList[sectorIdx].track, - fTSList[sectorIdx].sector, pBlock, &dummy); - assert(*pBlock < fpFile->GetDiskFS()->GetDiskImg()->GetNumBlocks()); - return kDIErrNone; + bool dummy; + TrackSectorToBlock(fTSList[sectorIdx].track, + fTSList[sectorIdx].sector, pBlock, &dummy); + assert(*pBlock < fpFile->GetDiskFS()->GetDiskImg()->GetNumBlocks()); + return kDIErrNone; } @@ -3436,12 +3436,12 @@ A2FDDOS::GetStorage(long blockIdx, long* pBlock) const void A2FDDOS::DumpTSList(void) const { - //A2FileDOS* pFile = (A2FileDOS*) fpFile; - WMSG2(" DOS T/S list for '%s' (count=%d)\n", + //A2FileDOS* pFile = (A2FileDOS*) fpFile; + WMSG2(" DOS T/S list for '%s' (count=%d)\n", ((A2FileDOS*)fpFile)->fFileName, fTSCount); - int i; - for (i = 0; i <= fTSCount; i++) { - WMSG3(" %3d: T=%-2d S=%d\n", i, fTSList[i].track, fTSList[i].sector); - } + int i; + for (i = 0; i <= fTSCount; i++) { + WMSG3(" %3d: T=%-2d S=%d\n", i, fTSList[i].track, fTSList[i].sector); + } } diff --git a/diskimg/DOSImage.cpp b/diskimg/DOSImage.cpp index de5062f..cfb158b 100644 --- a/diskimg/DOSImage.cpp +++ b/diskimg/DOSImage.cpp @@ -19,1589 +19,1589 @@ namespace DiskImgLib { * by "INIT HELLO" after booting the DOS 3.3 system master. */ /*static*/ const unsigned char DiskFSDOS33::gDOS33Tracks[16 * 3 * 256] = { - 0x01, 0xa5, 0x27, 0xc9, 0x09, 0xd0, 0x18, 0xa5, - 0x2b, 0x4a, 0x4a, 0x4a, 0x4a, 0x09, 0xc0, 0x85, - 0x3f, 0xa9, 0x5c, 0x85, 0x3e, 0x18, 0xad, 0xfe, - 0x08, 0x6d, 0xff, 0x08, 0x8d, 0xfe, 0x08, 0xae, - 0xff, 0x08, 0x30, 0x15, 0xbd, 0x4d, 0x08, 0x85, - 0x3d, 0xce, 0xff, 0x08, 0xad, 0xfe, 0x08, 0x85, - 0x27, 0xce, 0xfe, 0x08, 0xa6, 0x2b, 0x6c, 0x3e, - 0x00, 0xee, 0xfe, 0x08, 0xee, 0xfe, 0x08, 0x20, - 0x89, 0xfe, 0x20, 0x93, 0xfe, 0x20, 0x2f, 0xfb, - 0xa6, 0x2b, 0x6c, 0xfd, 0x08, 0x00, 0x0d, 0x0b, - 0x09, 0x07, 0x05, 0x03, 0x01, 0x0e, 0x0c, 0x0a, - 0x08, 0x06, 0x04, 0x02, 0x0f, 0x00, 0x20, 0x64, - 0xa7, 0xb0, 0x08, 0xa9, 0x00, 0xa8, 0x8d, 0x5d, - 0xb6, 0x91, 0x40, 0xad, 0xc5, 0xb5, 0x4c, 0xd2, - 0xa6, 0xad, 0x5d, 0xb6, 0xf0, 0x08, 0xee, 0xbd, - 0xb5, 0xd0, 0x03, 0xee, 0xbe, 0xb5, 0xa9, 0x00, - 0x8d, 0x5d, 0xb6, 0x4c, 0x46, 0xa5, 0x8d, 0xbc, - 0xb5, 0x20, 0xa8, 0xa6, 0x20, 0xea, 0xa2, 0x4c, - 0x7d, 0xa2, 0xa0, 0x13, 0xb1, 0x42, 0xd0, 0x14, - 0xc8, 0xc0, 0x17, 0xd0, 0xf7, 0xa0, 0x19, 0xb1, - 0x42, 0x99, 0xa4, 0xb5, 0xc8, 0xc0, 0x1d, 0xd0, - 0xf6, 0x4c, 0xbc, 0xa6, 0xa2, 0xff, 0x8e, 0x5d, - 0xb6, 0xd0, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x58, 0xfc, 0xa9, 0xc2, 0x20, 0xed, 0xfd, - 0xa9, 0x01, 0x20, 0xda, 0xfd, 0xa9, 0xad, 0x20, - 0xed, 0xfd, 0xa9, 0x00, 0x20, 0xda, 0xfd, 0x60, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x09, + 0x01, 0xa5, 0x27, 0xc9, 0x09, 0xd0, 0x18, 0xa5, + 0x2b, 0x4a, 0x4a, 0x4a, 0x4a, 0x09, 0xc0, 0x85, + 0x3f, 0xa9, 0x5c, 0x85, 0x3e, 0x18, 0xad, 0xfe, + 0x08, 0x6d, 0xff, 0x08, 0x8d, 0xfe, 0x08, 0xae, + 0xff, 0x08, 0x30, 0x15, 0xbd, 0x4d, 0x08, 0x85, + 0x3d, 0xce, 0xff, 0x08, 0xad, 0xfe, 0x08, 0x85, + 0x27, 0xce, 0xfe, 0x08, 0xa6, 0x2b, 0x6c, 0x3e, + 0x00, 0xee, 0xfe, 0x08, 0xee, 0xfe, 0x08, 0x20, + 0x89, 0xfe, 0x20, 0x93, 0xfe, 0x20, 0x2f, 0xfb, + 0xa6, 0x2b, 0x6c, 0xfd, 0x08, 0x00, 0x0d, 0x0b, + 0x09, 0x07, 0x05, 0x03, 0x01, 0x0e, 0x0c, 0x0a, + 0x08, 0x06, 0x04, 0x02, 0x0f, 0x00, 0x20, 0x64, + 0xa7, 0xb0, 0x08, 0xa9, 0x00, 0xa8, 0x8d, 0x5d, + 0xb6, 0x91, 0x40, 0xad, 0xc5, 0xb5, 0x4c, 0xd2, + 0xa6, 0xad, 0x5d, 0xb6, 0xf0, 0x08, 0xee, 0xbd, + 0xb5, 0xd0, 0x03, 0xee, 0xbe, 0xb5, 0xa9, 0x00, + 0x8d, 0x5d, 0xb6, 0x4c, 0x46, 0xa5, 0x8d, 0xbc, + 0xb5, 0x20, 0xa8, 0xa6, 0x20, 0xea, 0xa2, 0x4c, + 0x7d, 0xa2, 0xa0, 0x13, 0xb1, 0x42, 0xd0, 0x14, + 0xc8, 0xc0, 0x17, 0xd0, 0xf7, 0xa0, 0x19, 0xb1, + 0x42, 0x99, 0xa4, 0xb5, 0xc8, 0xc0, 0x1d, 0xd0, + 0xf6, 0x4c, 0xbc, 0xa6, 0xa2, 0xff, 0x8e, 0x5d, + 0xb6, 0xd0, 0xf6, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x58, 0xfc, 0xa9, 0xc2, 0x20, 0xed, 0xfd, + 0xa9, 0x01, 0x20, 0xda, 0xfd, 0xa9, 0xad, 0x20, + 0xed, 0xfd, 0xa9, 0x00, 0x20, 0xda, 0xfd, 0x60, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb6, 0x09, - 0x8e, 0xe9, 0xb7, 0x8e, 0xf7, 0xb7, 0xa9, 0x01, - 0x8d, 0xf8, 0xb7, 0x8d, 0xea, 0xb7, 0xad, 0xe0, - 0xb7, 0x8d, 0xe1, 0xb7, 0xa9, 0x02, 0x8d, 0xec, - 0xb7, 0xa9, 0x04, 0x8d, 0xed, 0xb7, 0xac, 0xe7, - 0xb7, 0x88, 0x8c, 0xf1, 0xb7, 0xa9, 0x01, 0x8d, - 0xf4, 0xb7, 0x8a, 0x4a, 0x4a, 0x4a, 0x4a, 0xaa, - 0xa9, 0x00, 0x9d, 0xf8, 0x04, 0x9d, 0x78, 0x04, - 0x20, 0x93, 0xb7, 0xa2, 0xff, 0x9a, 0x8e, 0xeb, - 0xb7, 0x4c, 0xc8, 0xbf, 0x20, 0x89, 0xfe, 0x4c, - 0x84, 0x9d, 0xad, 0xe7, 0xb7, 0x38, 0xed, 0xf1, - 0xb7, 0x8d, 0xe1, 0xb7, 0xad, 0xe7, 0xb7, 0x8d, - 0xf1, 0xb7, 0xce, 0xf1, 0xb7, 0xa9, 0x02, 0x8d, - 0xec, 0xb7, 0xa9, 0x04, 0x8d, 0xed, 0xb7, 0xa9, - 0x02, 0x8d, 0xf4, 0xb7, 0x20, 0x93, 0xb7, 0xad, - 0xe7, 0xb7, 0x8d, 0xfe, 0xb6, 0x18, 0x69, 0x09, - 0x8d, 0xf1, 0xb7, 0xa9, 0x0a, 0x8d, 0xe1, 0xb7, - 0x38, 0xe9, 0x01, 0x8d, 0xff, 0xb6, 0x8d, 0xed, - 0xb7, 0x20, 0x93, 0xb7, 0x60, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xad, 0xe5, 0xb7, 0xac, 0xe4, - 0xb7, 0x20, 0xb5, 0xb7, 0xac, 0xed, 0xb7, 0x88, - 0x10, 0x07, 0xa0, 0x0f, 0xea, 0xea, 0xce, 0xec, - 0xb7, 0x8c, 0xed, 0xb7, 0xce, 0xf1, 0xb7, 0xce, - 0xe1, 0xb7, 0xd0, 0xdf, 0x60, 0x08, 0x78, 0x20, - 0x00, 0xbd, 0xb0, 0x03, 0x28, 0x18, 0x60, 0x28, - 0x38, 0x60, 0xad, 0xbc, 0xb5, 0x8d, 0xf1, 0xb7, - 0xa9, 0x00, 0x8d, 0xf0, 0xb7, 0xad, 0xf9, 0xb5, - 0x49, 0xff, 0x8d, 0xeb, 0xb7, 0x60, 0xa9, 0x00, - 0xa8, 0x91, 0x42, 0xc8, 0xd0, 0xfb, 0x60, 0x00, - 0x1b, 0x02, 0x0a, 0x1b, 0xe8, 0xb7, 0x00, 0xb6, - 0x01, 0x60, 0x02, 0xfe, 0x00, 0x01, 0xfb, 0xb7, - 0x00, 0xb7, 0x00, 0x00, 0x02, 0xeb, 0xfe, 0x60, - 0x02, 0x00, 0x00, 0x00, 0x01, 0xef, 0xd8, 0x00, + 0x8e, 0xe9, 0xb7, 0x8e, 0xf7, 0xb7, 0xa9, 0x01, + 0x8d, 0xf8, 0xb7, 0x8d, 0xea, 0xb7, 0xad, 0xe0, + 0xb7, 0x8d, 0xe1, 0xb7, 0xa9, 0x02, 0x8d, 0xec, + 0xb7, 0xa9, 0x04, 0x8d, 0xed, 0xb7, 0xac, 0xe7, + 0xb7, 0x88, 0x8c, 0xf1, 0xb7, 0xa9, 0x01, 0x8d, + 0xf4, 0xb7, 0x8a, 0x4a, 0x4a, 0x4a, 0x4a, 0xaa, + 0xa9, 0x00, 0x9d, 0xf8, 0x04, 0x9d, 0x78, 0x04, + 0x20, 0x93, 0xb7, 0xa2, 0xff, 0x9a, 0x8e, 0xeb, + 0xb7, 0x4c, 0xc8, 0xbf, 0x20, 0x89, 0xfe, 0x4c, + 0x84, 0x9d, 0xad, 0xe7, 0xb7, 0x38, 0xed, 0xf1, + 0xb7, 0x8d, 0xe1, 0xb7, 0xad, 0xe7, 0xb7, 0x8d, + 0xf1, 0xb7, 0xce, 0xf1, 0xb7, 0xa9, 0x02, 0x8d, + 0xec, 0xb7, 0xa9, 0x04, 0x8d, 0xed, 0xb7, 0xa9, + 0x02, 0x8d, 0xf4, 0xb7, 0x20, 0x93, 0xb7, 0xad, + 0xe7, 0xb7, 0x8d, 0xfe, 0xb6, 0x18, 0x69, 0x09, + 0x8d, 0xf1, 0xb7, 0xa9, 0x0a, 0x8d, 0xe1, 0xb7, + 0x38, 0xe9, 0x01, 0x8d, 0xff, 0xb6, 0x8d, 0xed, + 0xb7, 0x20, 0x93, 0xb7, 0x60, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xad, 0xe5, 0xb7, 0xac, 0xe4, + 0xb7, 0x20, 0xb5, 0xb7, 0xac, 0xed, 0xb7, 0x88, + 0x10, 0x07, 0xa0, 0x0f, 0xea, 0xea, 0xce, 0xec, + 0xb7, 0x8c, 0xed, 0xb7, 0xce, 0xf1, 0xb7, 0xce, + 0xe1, 0xb7, 0xd0, 0xdf, 0x60, 0x08, 0x78, 0x20, + 0x00, 0xbd, 0xb0, 0x03, 0x28, 0x18, 0x60, 0x28, + 0x38, 0x60, 0xad, 0xbc, 0xb5, 0x8d, 0xf1, 0xb7, + 0xa9, 0x00, 0x8d, 0xf0, 0xb7, 0xad, 0xf9, 0xb5, + 0x49, 0xff, 0x8d, 0xeb, 0xb7, 0x60, 0xa9, 0x00, + 0xa8, 0x91, 0x42, 0xc8, 0xd0, 0xfb, 0x60, 0x00, + 0x1b, 0x02, 0x0a, 0x1b, 0xe8, 0xb7, 0x00, 0xb6, + 0x01, 0x60, 0x02, 0xfe, 0x00, 0x01, 0xfb, 0xb7, + 0x00, 0xb7, 0x00, 0x00, 0x02, 0xeb, 0xfe, 0x60, + 0x02, 0x00, 0x00, 0x00, 0x01, 0xef, 0xd8, 0x00, - 0xa2, 0x00, 0xa0, 0x02, 0x88, 0xb1, 0x3e, 0x4a, - 0x3e, 0x00, 0xbc, 0x4a, 0x3e, 0x00, 0xbc, 0x99, - 0x00, 0xbb, 0xe8, 0xe0, 0x56, 0x90, 0xed, 0xa2, - 0x00, 0x98, 0xd0, 0xe8, 0xa2, 0x55, 0xbd, 0x00, - 0xbc, 0x29, 0x3f, 0x9d, 0x00, 0xbc, 0xca, 0x10, - 0xf5, 0x60, 0x38, 0x86, 0x27, 0x8e, 0x78, 0x06, - 0xbd, 0x8d, 0xc0, 0xbd, 0x8e, 0xc0, 0x30, 0x7c, - 0xad, 0x00, 0xbc, 0x85, 0x26, 0xa9, 0xff, 0x9d, - 0x8f, 0xc0, 0x1d, 0x8c, 0xc0, 0x48, 0x68, 0xea, - 0xa0, 0x04, 0x48, 0x68, 0x20, 0xb9, 0xb8, 0x88, - 0xd0, 0xf8, 0xa9, 0xd5, 0x20, 0xb8, 0xb8, 0xa9, - 0xaa, 0x20, 0xb8, 0xb8, 0xa9, 0xad, 0x20, 0xb8, - 0xb8, 0x98, 0xa0, 0x56, 0xd0, 0x03, 0xb9, 0x00, - 0xbc, 0x59, 0xff, 0xbb, 0xaa, 0xbd, 0x29, 0xba, - 0xa6, 0x27, 0x9d, 0x8d, 0xc0, 0xbd, 0x8c, 0xc0, - 0x88, 0xd0, 0xeb, 0xa5, 0x26, 0xea, 0x59, 0x00, - 0xbb, 0xaa, 0xbd, 0x29, 0xba, 0xae, 0x78, 0x06, - 0x9d, 0x8d, 0xc0, 0xbd, 0x8c, 0xc0, 0xb9, 0x00, - 0xbb, 0xc8, 0xd0, 0xea, 0xaa, 0xbd, 0x29, 0xba, - 0xa6, 0x27, 0x20, 0xbb, 0xb8, 0xa9, 0xde, 0x20, - 0xb8, 0xb8, 0xa9, 0xaa, 0x20, 0xb8, 0xb8, 0xa9, - 0xeb, 0x20, 0xb8, 0xb8, 0xa9, 0xff, 0x20, 0xb8, - 0xb8, 0xbd, 0x8e, 0xc0, 0xbd, 0x8c, 0xc0, 0x60, - 0x18, 0x48, 0x68, 0x9d, 0x8d, 0xc0, 0x1d, 0x8c, - 0xc0, 0x60, 0xa0, 0x00, 0xa2, 0x56, 0xca, 0x30, - 0xfb, 0xb9, 0x00, 0xbb, 0x5e, 0x00, 0xbc, 0x2a, - 0x5e, 0x00, 0xbc, 0x2a, 0x91, 0x3e, 0xc8, 0xc4, - 0x26, 0xd0, 0xeb, 0x60, 0xa0, 0x20, 0x88, 0xf0, - 0x61, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0x49, 0xd5, - 0xd0, 0xf4, 0xea, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, - 0xc9, 0xaa, 0xd0, 0xf2, 0xa0, 0x56, 0xbd, 0x8c, - 0xc0, 0x10, 0xfb, 0xc9, 0xad, 0xd0, 0xe7, 0xa9, + 0xa2, 0x00, 0xa0, 0x02, 0x88, 0xb1, 0x3e, 0x4a, + 0x3e, 0x00, 0xbc, 0x4a, 0x3e, 0x00, 0xbc, 0x99, + 0x00, 0xbb, 0xe8, 0xe0, 0x56, 0x90, 0xed, 0xa2, + 0x00, 0x98, 0xd0, 0xe8, 0xa2, 0x55, 0xbd, 0x00, + 0xbc, 0x29, 0x3f, 0x9d, 0x00, 0xbc, 0xca, 0x10, + 0xf5, 0x60, 0x38, 0x86, 0x27, 0x8e, 0x78, 0x06, + 0xbd, 0x8d, 0xc0, 0xbd, 0x8e, 0xc0, 0x30, 0x7c, + 0xad, 0x00, 0xbc, 0x85, 0x26, 0xa9, 0xff, 0x9d, + 0x8f, 0xc0, 0x1d, 0x8c, 0xc0, 0x48, 0x68, 0xea, + 0xa0, 0x04, 0x48, 0x68, 0x20, 0xb9, 0xb8, 0x88, + 0xd0, 0xf8, 0xa9, 0xd5, 0x20, 0xb8, 0xb8, 0xa9, + 0xaa, 0x20, 0xb8, 0xb8, 0xa9, 0xad, 0x20, 0xb8, + 0xb8, 0x98, 0xa0, 0x56, 0xd0, 0x03, 0xb9, 0x00, + 0xbc, 0x59, 0xff, 0xbb, 0xaa, 0xbd, 0x29, 0xba, + 0xa6, 0x27, 0x9d, 0x8d, 0xc0, 0xbd, 0x8c, 0xc0, + 0x88, 0xd0, 0xeb, 0xa5, 0x26, 0xea, 0x59, 0x00, + 0xbb, 0xaa, 0xbd, 0x29, 0xba, 0xae, 0x78, 0x06, + 0x9d, 0x8d, 0xc0, 0xbd, 0x8c, 0xc0, 0xb9, 0x00, + 0xbb, 0xc8, 0xd0, 0xea, 0xaa, 0xbd, 0x29, 0xba, + 0xa6, 0x27, 0x20, 0xbb, 0xb8, 0xa9, 0xde, 0x20, + 0xb8, 0xb8, 0xa9, 0xaa, 0x20, 0xb8, 0xb8, 0xa9, + 0xeb, 0x20, 0xb8, 0xb8, 0xa9, 0xff, 0x20, 0xb8, + 0xb8, 0xbd, 0x8e, 0xc0, 0xbd, 0x8c, 0xc0, 0x60, + 0x18, 0x48, 0x68, 0x9d, 0x8d, 0xc0, 0x1d, 0x8c, + 0xc0, 0x60, 0xa0, 0x00, 0xa2, 0x56, 0xca, 0x30, + 0xfb, 0xb9, 0x00, 0xbb, 0x5e, 0x00, 0xbc, 0x2a, + 0x5e, 0x00, 0xbc, 0x2a, 0x91, 0x3e, 0xc8, 0xc4, + 0x26, 0xd0, 0xeb, 0x60, 0xa0, 0x20, 0x88, 0xf0, + 0x61, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0x49, 0xd5, + 0xd0, 0xf4, 0xea, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, + 0xc9, 0xaa, 0xd0, 0xf2, 0xa0, 0x56, 0xbd, 0x8c, + 0xc0, 0x10, 0xfb, 0xc9, 0xad, 0xd0, 0xe7, 0xa9, - 0x00, 0x88, 0x84, 0x26, 0xbc, 0x8c, 0xc0, 0x10, - 0xfb, 0x59, 0x00, 0xba, 0xa4, 0x26, 0x99, 0x00, - 0xbc, 0xd0, 0xee, 0x84, 0x26, 0xbc, 0x8c, 0xc0, - 0x10, 0xfb, 0x59, 0x00, 0xba, 0xa4, 0x26, 0x99, - 0x00, 0xbb, 0xc8, 0xd0, 0xee, 0xbc, 0x8c, 0xc0, - 0x10, 0xfb, 0xd9, 0x00, 0xba, 0xd0, 0x13, 0xbd, - 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xde, 0xd0, 0x0a, - 0xea, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xaa, - 0xf0, 0x5c, 0x38, 0x60, 0xa0, 0xfc, 0x84, 0x26, - 0xc8, 0xd0, 0x04, 0xe6, 0x26, 0xf0, 0xf3, 0xbd, - 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xd5, 0xd0, 0xf0, - 0xea, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xaa, - 0xd0, 0xf2, 0xa0, 0x03, 0xbd, 0x8c, 0xc0, 0x10, - 0xfb, 0xc9, 0x96, 0xd0, 0xe7, 0xa9, 0x00, 0x85, - 0x27, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0x2a, 0x85, - 0x26, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0x25, 0x26, - 0x99, 0x2c, 0x00, 0x45, 0x27, 0x88, 0x10, 0xe7, - 0xa8, 0xd0, 0xb7, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, - 0xc9, 0xde, 0xd0, 0xae, 0xea, 0xbd, 0x8c, 0xc0, - 0x10, 0xfb, 0xc9, 0xaa, 0xd0, 0xa4, 0x18, 0x60, - 0x86, 0x2b, 0x85, 0x2a, 0xcd, 0x78, 0x04, 0xf0, - 0x53, 0xa9, 0x00, 0x85, 0x26, 0xad, 0x78, 0x04, - 0x85, 0x27, 0x38, 0xe5, 0x2a, 0xf0, 0x33, 0xb0, - 0x07, 0x49, 0xff, 0xee, 0x78, 0x04, 0x90, 0x05, - 0x69, 0xfe, 0xce, 0x78, 0x04, 0xc5, 0x26, 0x90, - 0x02, 0xa5, 0x26, 0xc9, 0x0c, 0xb0, 0x01, 0xa8, - 0x38, 0x20, 0xee, 0xb9, 0xb9, 0x11, 0xba, 0x20, - 0x00, 0xba, 0xa5, 0x27, 0x18, 0x20, 0xf1, 0xb9, - 0xb9, 0x1d, 0xba, 0x20, 0x00, 0xba, 0xe6, 0x26, - 0xd0, 0xc3, 0x20, 0x00, 0xba, 0x18, 0xad, 0x78, - 0x04, 0x29, 0x03, 0x2a, 0x05, 0x2b, 0xaa, 0xbd, - 0x80, 0xc0, 0xa6, 0x2b, 0x60, 0xaa, 0xa0, 0xa0, + 0x00, 0x88, 0x84, 0x26, 0xbc, 0x8c, 0xc0, 0x10, + 0xfb, 0x59, 0x00, 0xba, 0xa4, 0x26, 0x99, 0x00, + 0xbc, 0xd0, 0xee, 0x84, 0x26, 0xbc, 0x8c, 0xc0, + 0x10, 0xfb, 0x59, 0x00, 0xba, 0xa4, 0x26, 0x99, + 0x00, 0xbb, 0xc8, 0xd0, 0xee, 0xbc, 0x8c, 0xc0, + 0x10, 0xfb, 0xd9, 0x00, 0xba, 0xd0, 0x13, 0xbd, + 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xde, 0xd0, 0x0a, + 0xea, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xaa, + 0xf0, 0x5c, 0x38, 0x60, 0xa0, 0xfc, 0x84, 0x26, + 0xc8, 0xd0, 0x04, 0xe6, 0x26, 0xf0, 0xf3, 0xbd, + 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xd5, 0xd0, 0xf0, + 0xea, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xaa, + 0xd0, 0xf2, 0xa0, 0x03, 0xbd, 0x8c, 0xc0, 0x10, + 0xfb, 0xc9, 0x96, 0xd0, 0xe7, 0xa9, 0x00, 0x85, + 0x27, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0x2a, 0x85, + 0x26, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0x25, 0x26, + 0x99, 0x2c, 0x00, 0x45, 0x27, 0x88, 0x10, 0xe7, + 0xa8, 0xd0, 0xb7, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, + 0xc9, 0xde, 0xd0, 0xae, 0xea, 0xbd, 0x8c, 0xc0, + 0x10, 0xfb, 0xc9, 0xaa, 0xd0, 0xa4, 0x18, 0x60, + 0x86, 0x2b, 0x85, 0x2a, 0xcd, 0x78, 0x04, 0xf0, + 0x53, 0xa9, 0x00, 0x85, 0x26, 0xad, 0x78, 0x04, + 0x85, 0x27, 0x38, 0xe5, 0x2a, 0xf0, 0x33, 0xb0, + 0x07, 0x49, 0xff, 0xee, 0x78, 0x04, 0x90, 0x05, + 0x69, 0xfe, 0xce, 0x78, 0x04, 0xc5, 0x26, 0x90, + 0x02, 0xa5, 0x26, 0xc9, 0x0c, 0xb0, 0x01, 0xa8, + 0x38, 0x20, 0xee, 0xb9, 0xb9, 0x11, 0xba, 0x20, + 0x00, 0xba, 0xa5, 0x27, 0x18, 0x20, 0xf1, 0xb9, + 0xb9, 0x1d, 0xba, 0x20, 0x00, 0xba, 0xe6, 0x26, + 0xd0, 0xc3, 0x20, 0x00, 0xba, 0x18, 0xad, 0x78, + 0x04, 0x29, 0x03, 0x2a, 0x05, 0x2b, 0xaa, 0xbd, + 0x80, 0xc0, 0xa6, 0x2b, 0x60, 0xaa, 0xa0, 0xa0, - 0xa2, 0x11, 0xca, 0xd0, 0xfd, 0xe6, 0x46, 0xd0, - 0x02, 0xe6, 0x47, 0x38, 0xe9, 0x01, 0xd0, 0xf0, - 0x60, 0x01, 0x30, 0x28, 0x24, 0x20, 0x1e, 0x1d, - 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x70, 0x2c, 0x26, - 0x22, 0x1f, 0x1e, 0x1d, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, - 0xa6, 0xa7, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb2, - 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, - 0xbc, 0xbd, 0xbe, 0xbf, 0xcb, 0xcd, 0xce, 0xcf, - 0xd3, 0xd6, 0xd7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, - 0xde, 0xdf, 0xe5, 0xe6, 0xe7, 0xe9, 0xea, 0xeb, - 0xec, 0xed, 0xee, 0xef, 0xf2, 0xf3, 0xf4, 0xf5, - 0xf6, 0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, - 0xff, 0xb3, 0xb3, 0xa0, 0xe0, 0xb3, 0xc3, 0xc5, - 0xb3, 0xa0, 0xe0, 0xb3, 0xc3, 0xc5, 0xb3, 0xa0, - 0xe0, 0xb3, 0xb3, 0xc5, 0xaa, 0xa0, 0x82, 0xb3, - 0xb3, 0xc5, 0xaa, 0xa0, 0x82, 0xc5, 0xb3, 0xb3, - 0xaa, 0x88, 0x82, 0xc5, 0xb3, 0xb3, 0xaa, 0x88, - 0x82, 0xc5, 0xc4, 0xb3, 0xb0, 0x88, 0x00, 0x01, - 0x98, 0x99, 0x02, 0x03, 0x9c, 0x04, 0x05, 0x06, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x07, 0x08, - 0xa8, 0xa9, 0xaa, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, - 0xb0, 0xb1, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, - 0xb8, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0x1b, 0xcc, 0x1c, 0x1d, 0x1e, - 0xd0, 0xd1, 0xd2, 0x1f, 0xd4, 0xd5, 0x20, 0x21, - 0xd8, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x29, 0x2a, 0x2b, - 0xe8, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, - 0xf0, 0xf1, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, - 0xf8, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0xa2, 0x11, 0xca, 0xd0, 0xfd, 0xe6, 0x46, 0xd0, + 0x02, 0xe6, 0x47, 0x38, 0xe9, 0x01, 0xd0, 0xf0, + 0x60, 0x01, 0x30, 0x28, 0x24, 0x20, 0x1e, 0x1d, + 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x70, 0x2c, 0x26, + 0x22, 0x1f, 0x1e, 0x1d, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x96, 0x97, 0x9a, 0x9b, 0x9d, 0x9e, 0x9f, + 0xa6, 0xa7, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb2, + 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb9, 0xba, 0xbb, + 0xbc, 0xbd, 0xbe, 0xbf, 0xcb, 0xcd, 0xce, 0xcf, + 0xd3, 0xd6, 0xd7, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, + 0xde, 0xdf, 0xe5, 0xe6, 0xe7, 0xe9, 0xea, 0xeb, + 0xec, 0xed, 0xee, 0xef, 0xf2, 0xf3, 0xf4, 0xf5, + 0xf6, 0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, + 0xff, 0xb3, 0xb3, 0xa0, 0xe0, 0xb3, 0xc3, 0xc5, + 0xb3, 0xa0, 0xe0, 0xb3, 0xc3, 0xc5, 0xb3, 0xa0, + 0xe0, 0xb3, 0xb3, 0xc5, 0xaa, 0xa0, 0x82, 0xb3, + 0xb3, 0xc5, 0xaa, 0xa0, 0x82, 0xc5, 0xb3, 0xb3, + 0xaa, 0x88, 0x82, 0xc5, 0xb3, 0xb3, 0xaa, 0x88, + 0x82, 0xc5, 0xc4, 0xb3, 0xb0, 0x88, 0x00, 0x01, + 0x98, 0x99, 0x02, 0x03, 0x9c, 0x04, 0x05, 0x06, + 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0x07, 0x08, + 0xa8, 0xa9, 0xaa, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, + 0xb0, 0xb1, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, + 0xb8, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0x1b, 0xcc, 0x1c, 0x1d, 0x1e, + 0xd0, 0xd1, 0xd2, 0x1f, 0xd4, 0xd5, 0x20, 0x21, + 0xd8, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, + 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0x29, 0x2a, 0x2b, + 0xe8, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, + 0xf0, 0xf1, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0xf8, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x01, 0x0a, 0x11, 0x0a, 0x08, 0x20, 0x20, 0x0e, - 0x18, 0x06, 0x02, 0x31, 0x02, 0x09, 0x08, 0x27, - 0x22, 0x00, 0x12, 0x0a, 0x0a, 0x04, 0x00, 0x00, - 0x03, 0x2a, 0x00, 0x04, 0x00, 0x00, 0x22, 0x08, - 0x10, 0x28, 0x12, 0x02, 0x00, 0x02, 0x08, 0x11, - 0x0a, 0x08, 0x02, 0x28, 0x11, 0x01, 0x39, 0x22, - 0x31, 0x01, 0x05, 0x18, 0x20, 0x28, 0x02, 0x10, - 0x06, 0x02, 0x09, 0x02, 0x05, 0x2c, 0x10, 0x00, - 0x08, 0x2e, 0x00, 0x05, 0x02, 0x28, 0x18, 0x02, - 0x30, 0x23, 0x02, 0x20, 0x32, 0x04, 0x11, 0x02, - 0x14, 0x02, 0x08, 0x09, 0x12, 0x20, 0x0e, 0x2f, - 0x23, 0x30, 0x2f, 0x23, 0x30, 0x0c, 0x17, 0x2a, - 0x3f, 0x27, 0x23, 0x30, 0x37, 0x23, 0x30, 0x12, - 0x1a, 0x08, 0x30, 0x2f, 0x08, 0x30, 0x2f, 0x27, - 0x23, 0x30, 0x37, 0x23, 0x30, 0x3a, 0x22, 0x34, - 0x3c, 0x2a, 0x35, 0x08, 0x35, 0x2f, 0x2a, 0x2a, - 0x08, 0x35, 0x2f, 0x2a, 0x25, 0x08, 0x35, 0x2f, - 0x29, 0x10, 0x08, 0x31, 0x2f, 0x29, 0x11, 0x08, - 0x31, 0x2f, 0x29, 0x0f, 0x08, 0x31, 0x2f, 0x29, - 0x10, 0x11, 0x11, 0x11, 0x0f, 0x12, 0x12, 0x01, - 0x0f, 0x27, 0x23, 0x30, 0x2f, 0x23, 0x30, 0x1a, - 0x02, 0x2a, 0x08, 0x35, 0x2f, 0x2a, 0x37, 0x08, - 0x35, 0x2f, 0x2a, 0x2a, 0x08, 0x35, 0x2f, 0x2a, - 0x3a, 0x08, 0x35, 0x2f, 0x06, 0x2f, 0x23, 0x30, - 0x2f, 0x23, 0x30, 0x18, 0x12, 0x12, 0x01, 0x0f, - 0x27, 0x23, 0x30, 0x37, 0x23, 0x30, 0x1a, 0x3a, - 0x3a, 0x3a, 0x02, 0x2a, 0x3a, 0x3a, 0x12, 0x1a, - 0x27, 0x23, 0x30, 0x37, 0x23, 0x30, 0x18, 0x22, - 0x29, 0x3a, 0x24, 0x28, 0x25, 0x22, 0x25, 0x3a, - 0x24, 0x28, 0x25, 0x22, 0x25, 0x24, 0x24, 0x32, - 0x25, 0x34, 0x25, 0x24, 0x24, 0x32, 0x25, 0x34, - 0x25, 0x24, 0x28, 0x32, 0x28, 0x29, 0x21, 0x29, + 0x01, 0x0a, 0x11, 0x0a, 0x08, 0x20, 0x20, 0x0e, + 0x18, 0x06, 0x02, 0x31, 0x02, 0x09, 0x08, 0x27, + 0x22, 0x00, 0x12, 0x0a, 0x0a, 0x04, 0x00, 0x00, + 0x03, 0x2a, 0x00, 0x04, 0x00, 0x00, 0x22, 0x08, + 0x10, 0x28, 0x12, 0x02, 0x00, 0x02, 0x08, 0x11, + 0x0a, 0x08, 0x02, 0x28, 0x11, 0x01, 0x39, 0x22, + 0x31, 0x01, 0x05, 0x18, 0x20, 0x28, 0x02, 0x10, + 0x06, 0x02, 0x09, 0x02, 0x05, 0x2c, 0x10, 0x00, + 0x08, 0x2e, 0x00, 0x05, 0x02, 0x28, 0x18, 0x02, + 0x30, 0x23, 0x02, 0x20, 0x32, 0x04, 0x11, 0x02, + 0x14, 0x02, 0x08, 0x09, 0x12, 0x20, 0x0e, 0x2f, + 0x23, 0x30, 0x2f, 0x23, 0x30, 0x0c, 0x17, 0x2a, + 0x3f, 0x27, 0x23, 0x30, 0x37, 0x23, 0x30, 0x12, + 0x1a, 0x08, 0x30, 0x2f, 0x08, 0x30, 0x2f, 0x27, + 0x23, 0x30, 0x37, 0x23, 0x30, 0x3a, 0x22, 0x34, + 0x3c, 0x2a, 0x35, 0x08, 0x35, 0x2f, 0x2a, 0x2a, + 0x08, 0x35, 0x2f, 0x2a, 0x25, 0x08, 0x35, 0x2f, + 0x29, 0x10, 0x08, 0x31, 0x2f, 0x29, 0x11, 0x08, + 0x31, 0x2f, 0x29, 0x0f, 0x08, 0x31, 0x2f, 0x29, + 0x10, 0x11, 0x11, 0x11, 0x0f, 0x12, 0x12, 0x01, + 0x0f, 0x27, 0x23, 0x30, 0x2f, 0x23, 0x30, 0x1a, + 0x02, 0x2a, 0x08, 0x35, 0x2f, 0x2a, 0x37, 0x08, + 0x35, 0x2f, 0x2a, 0x2a, 0x08, 0x35, 0x2f, 0x2a, + 0x3a, 0x08, 0x35, 0x2f, 0x06, 0x2f, 0x23, 0x30, + 0x2f, 0x23, 0x30, 0x18, 0x12, 0x12, 0x01, 0x0f, + 0x27, 0x23, 0x30, 0x37, 0x23, 0x30, 0x1a, 0x3a, + 0x3a, 0x3a, 0x02, 0x2a, 0x3a, 0x3a, 0x12, 0x1a, + 0x27, 0x23, 0x30, 0x37, 0x23, 0x30, 0x18, 0x22, + 0x29, 0x3a, 0x24, 0x28, 0x25, 0x22, 0x25, 0x3a, + 0x24, 0x28, 0x25, 0x22, 0x25, 0x24, 0x24, 0x32, + 0x25, 0x34, 0x25, 0x24, 0x24, 0x32, 0x25, 0x34, + 0x25, 0x24, 0x28, 0x32, 0x28, 0x29, 0x21, 0x29, - 0x10, 0xa1, 0x45, 0x28, 0x21, 0x82, 0x80, 0x38, - 0x62, 0x19, 0x0b, 0xc5, 0x0b, 0x24, 0x21, 0x9c, - 0x88, 0x00, 0x48, 0x28, 0x2b, 0x10, 0x00, 0x03, - 0x0c, 0xa9, 0x01, 0x10, 0x01, 0x00, 0x88, 0x22, - 0x40, 0xa0, 0x48, 0x09, 0x01, 0x08, 0x21, 0x44, - 0x29, 0x22, 0x08, 0xa0, 0x45, 0x06, 0xe4, 0x8a, - 0xc4, 0x06, 0x16, 0x60, 0x80, 0xa0, 0x09, 0x40, - 0x18, 0x0a, 0x24, 0x0a, 0x16, 0xb0, 0x43, 0x00, - 0x20, 0xbb, 0x00, 0x14, 0x08, 0xa0, 0x60, 0x0a, - 0xc0, 0x8f, 0x0a, 0x83, 0xca, 0x11, 0x44, 0x08, - 0x51, 0x0a, 0x20, 0x26, 0x4a, 0x80, 0x38, 0xbd, - 0x8d, 0xc0, 0xbd, 0x8e, 0xc0, 0x30, 0x5e, 0xa9, - 0xff, 0x9d, 0x8f, 0xc0, 0xdd, 0x8c, 0xc0, 0x48, - 0x68, 0x20, 0xc3, 0xbc, 0x20, 0xc3, 0xbc, 0x9d, - 0x8d, 0xc0, 0xdd, 0x8c, 0xc0, 0xea, 0x88, 0xd0, - 0xf0, 0xa9, 0xd5, 0x20, 0xd5, 0xbc, 0xa9, 0xaa, - 0x20, 0xd5, 0xbc, 0xa9, 0x96, 0x20, 0xd5, 0xbc, - 0xa5, 0x41, 0x20, 0xc4, 0xbc, 0xa5, 0x44, 0x20, - 0xc4, 0xbc, 0xa5, 0x3f, 0x20, 0xc4, 0xbc, 0xa5, - 0x41, 0x45, 0x44, 0x45, 0x3f, 0x48, 0x4a, 0x05, - 0x3e, 0x9d, 0x8d, 0xc0, 0xbd, 0x8c, 0xc0, 0x68, - 0x09, 0xaa, 0x20, 0xd4, 0xbc, 0xa9, 0xde, 0x20, - 0xd5, 0xbc, 0xa9, 0xaa, 0x20, 0xd5, 0xbc, 0xa9, - 0xeb, 0x20, 0xd5, 0xbc, 0x18, 0xbd, 0x8e, 0xc0, - 0xbd, 0x8c, 0xc0, 0x60, 0x48, 0x4a, 0x05, 0x3e, - 0x9d, 0x8d, 0xc0, 0xdd, 0x8c, 0xc0, 0x68, 0xea, - 0xea, 0xea, 0x09, 0xaa, 0xea, 0xea, 0x48, 0x68, - 0x9d, 0x8d, 0xc0, 0xdd, 0x8c, 0xc0, 0x60, 0x88, - 0xa5, 0xe8, 0x91, 0xa0, 0x94, 0x88, 0x96, 0xe8, - 0x91, 0xa0, 0x94, 0x88, 0x96, 0x91, 0x91, 0xc8, - 0x94, 0xd0, 0x96, 0x91, 0x91, 0xc8, 0x94, 0xd0, - 0x96, 0x91, 0xa3, 0xc8, 0xa0, 0xa5, 0x85, 0xa4, + 0x10, 0xa1, 0x45, 0x28, 0x21, 0x82, 0x80, 0x38, + 0x62, 0x19, 0x0b, 0xc5, 0x0b, 0x24, 0x21, 0x9c, + 0x88, 0x00, 0x48, 0x28, 0x2b, 0x10, 0x00, 0x03, + 0x0c, 0xa9, 0x01, 0x10, 0x01, 0x00, 0x88, 0x22, + 0x40, 0xa0, 0x48, 0x09, 0x01, 0x08, 0x21, 0x44, + 0x29, 0x22, 0x08, 0xa0, 0x45, 0x06, 0xe4, 0x8a, + 0xc4, 0x06, 0x16, 0x60, 0x80, 0xa0, 0x09, 0x40, + 0x18, 0x0a, 0x24, 0x0a, 0x16, 0xb0, 0x43, 0x00, + 0x20, 0xbb, 0x00, 0x14, 0x08, 0xa0, 0x60, 0x0a, + 0xc0, 0x8f, 0x0a, 0x83, 0xca, 0x11, 0x44, 0x08, + 0x51, 0x0a, 0x20, 0x26, 0x4a, 0x80, 0x38, 0xbd, + 0x8d, 0xc0, 0xbd, 0x8e, 0xc0, 0x30, 0x5e, 0xa9, + 0xff, 0x9d, 0x8f, 0xc0, 0xdd, 0x8c, 0xc0, 0x48, + 0x68, 0x20, 0xc3, 0xbc, 0x20, 0xc3, 0xbc, 0x9d, + 0x8d, 0xc0, 0xdd, 0x8c, 0xc0, 0xea, 0x88, 0xd0, + 0xf0, 0xa9, 0xd5, 0x20, 0xd5, 0xbc, 0xa9, 0xaa, + 0x20, 0xd5, 0xbc, 0xa9, 0x96, 0x20, 0xd5, 0xbc, + 0xa5, 0x41, 0x20, 0xc4, 0xbc, 0xa5, 0x44, 0x20, + 0xc4, 0xbc, 0xa5, 0x3f, 0x20, 0xc4, 0xbc, 0xa5, + 0x41, 0x45, 0x44, 0x45, 0x3f, 0x48, 0x4a, 0x05, + 0x3e, 0x9d, 0x8d, 0xc0, 0xbd, 0x8c, 0xc0, 0x68, + 0x09, 0xaa, 0x20, 0xd4, 0xbc, 0xa9, 0xde, 0x20, + 0xd5, 0xbc, 0xa9, 0xaa, 0x20, 0xd5, 0xbc, 0xa9, + 0xeb, 0x20, 0xd5, 0xbc, 0x18, 0xbd, 0x8e, 0xc0, + 0xbd, 0x8c, 0xc0, 0x60, 0x48, 0x4a, 0x05, 0x3e, + 0x9d, 0x8d, 0xc0, 0xdd, 0x8c, 0xc0, 0x68, 0xea, + 0xea, 0xea, 0x09, 0xaa, 0xea, 0xea, 0x48, 0x68, + 0x9d, 0x8d, 0xc0, 0xdd, 0x8c, 0xc0, 0x60, 0x88, + 0xa5, 0xe8, 0x91, 0xa0, 0x94, 0x88, 0x96, 0xe8, + 0x91, 0xa0, 0x94, 0x88, 0x96, 0x91, 0x91, 0xc8, + 0x94, 0xd0, 0x96, 0x91, 0x91, 0xc8, 0x94, 0xd0, + 0x96, 0x91, 0xa3, 0xc8, 0xa0, 0xa5, 0x85, 0xa4, - 0x84, 0x48, 0x85, 0x49, 0xa0, 0x02, 0x8c, 0xf8, - 0x06, 0xa0, 0x04, 0x8c, 0xf8, 0x04, 0xa0, 0x01, - 0xb1, 0x48, 0xaa, 0xa0, 0x0f, 0xd1, 0x48, 0xf0, - 0x1b, 0x8a, 0x48, 0xb1, 0x48, 0xaa, 0x68, 0x48, - 0x91, 0x48, 0xbd, 0x8e, 0xc0, 0xa0, 0x08, 0xbd, - 0x8c, 0xc0, 0xdd, 0x8c, 0xc0, 0xd0, 0xf6, 0x88, - 0xd0, 0xf8, 0x68, 0xaa, 0xbd, 0x8e, 0xc0, 0xbd, - 0x8c, 0xc0, 0xa0, 0x08, 0xbd, 0x8c, 0xc0, 0x48, - 0x68, 0x48, 0x68, 0x8e, 0xf8, 0x05, 0xdd, 0x8c, - 0xc0, 0xd0, 0x03, 0x88, 0xd0, 0xee, 0x08, 0xbd, - 0x89, 0xc0, 0xa0, 0x06, 0xb1, 0x48, 0x99, 0x36, - 0x00, 0xc8, 0xc0, 0x0a, 0xd0, 0xf6, 0xa0, 0x03, - 0xb1, 0x3c, 0x85, 0x47, 0xa0, 0x02, 0xb1, 0x48, - 0xa0, 0x10, 0xd1, 0x48, 0xf0, 0x06, 0x91, 0x48, - 0x28, 0xa0, 0x00, 0x08, 0x6a, 0x90, 0x05, 0xbd, - 0x8a, 0xc0, 0xb0, 0x03, 0xbd, 0x8b, 0xc0, 0x66, - 0x35, 0x28, 0x08, 0xd0, 0x0b, 0xa0, 0x07, 0x20, - 0x00, 0xba, 0x88, 0xd0, 0xfa, 0xae, 0xf8, 0x05, - 0xa0, 0x04, 0xb1, 0x48, 0x20, 0x5a, 0xbe, 0x28, - 0xd0, 0x11, 0xa4, 0x47, 0x10, 0x0d, 0xa0, 0x12, - 0x88, 0xd0, 0xfd, 0xe6, 0x46, 0xd0, 0xf7, 0xe6, - 0x47, 0xd0, 0xf3, 0xa0, 0x0c, 0xb1, 0x48, 0xf0, - 0x5a, 0xc9, 0x04, 0xf0, 0x58, 0x6a, 0x08, 0xb0, - 0x03, 0x20, 0x00, 0xb8, 0xa0, 0x30, 0x8c, 0x78, - 0x05, 0xae, 0xf8, 0x05, 0x20, 0x44, 0xb9, 0x90, - 0x24, 0xce, 0x78, 0x05, 0x10, 0xf3, 0xad, 0x78, - 0x04, 0x48, 0xa9, 0x60, 0x20, 0x95, 0xbe, 0xce, - 0xf8, 0x06, 0xf0, 0x28, 0xa9, 0x04, 0x8d, 0xf8, - 0x04, 0xa9, 0x00, 0x20, 0x5a, 0xbe, 0x68, 0x20, - 0x5a, 0xbe, 0x4c, 0xbc, 0xbd, 0xa4, 0x2e, 0xcc, - 0x78, 0x04, 0xf0, 0x1c, 0xad, 0x78, 0x04, 0x48, - 0x98, 0x20, 0x95, 0xbe, 0x68, 0xce, 0xf8, 0x04, + 0x84, 0x48, 0x85, 0x49, 0xa0, 0x02, 0x8c, 0xf8, + 0x06, 0xa0, 0x04, 0x8c, 0xf8, 0x04, 0xa0, 0x01, + 0xb1, 0x48, 0xaa, 0xa0, 0x0f, 0xd1, 0x48, 0xf0, + 0x1b, 0x8a, 0x48, 0xb1, 0x48, 0xaa, 0x68, 0x48, + 0x91, 0x48, 0xbd, 0x8e, 0xc0, 0xa0, 0x08, 0xbd, + 0x8c, 0xc0, 0xdd, 0x8c, 0xc0, 0xd0, 0xf6, 0x88, + 0xd0, 0xf8, 0x68, 0xaa, 0xbd, 0x8e, 0xc0, 0xbd, + 0x8c, 0xc0, 0xa0, 0x08, 0xbd, 0x8c, 0xc0, 0x48, + 0x68, 0x48, 0x68, 0x8e, 0xf8, 0x05, 0xdd, 0x8c, + 0xc0, 0xd0, 0x03, 0x88, 0xd0, 0xee, 0x08, 0xbd, + 0x89, 0xc0, 0xa0, 0x06, 0xb1, 0x48, 0x99, 0x36, + 0x00, 0xc8, 0xc0, 0x0a, 0xd0, 0xf6, 0xa0, 0x03, + 0xb1, 0x3c, 0x85, 0x47, 0xa0, 0x02, 0xb1, 0x48, + 0xa0, 0x10, 0xd1, 0x48, 0xf0, 0x06, 0x91, 0x48, + 0x28, 0xa0, 0x00, 0x08, 0x6a, 0x90, 0x05, 0xbd, + 0x8a, 0xc0, 0xb0, 0x03, 0xbd, 0x8b, 0xc0, 0x66, + 0x35, 0x28, 0x08, 0xd0, 0x0b, 0xa0, 0x07, 0x20, + 0x00, 0xba, 0x88, 0xd0, 0xfa, 0xae, 0xf8, 0x05, + 0xa0, 0x04, 0xb1, 0x48, 0x20, 0x5a, 0xbe, 0x28, + 0xd0, 0x11, 0xa4, 0x47, 0x10, 0x0d, 0xa0, 0x12, + 0x88, 0xd0, 0xfd, 0xe6, 0x46, 0xd0, 0xf7, 0xe6, + 0x47, 0xd0, 0xf3, 0xa0, 0x0c, 0xb1, 0x48, 0xf0, + 0x5a, 0xc9, 0x04, 0xf0, 0x58, 0x6a, 0x08, 0xb0, + 0x03, 0x20, 0x00, 0xb8, 0xa0, 0x30, 0x8c, 0x78, + 0x05, 0xae, 0xf8, 0x05, 0x20, 0x44, 0xb9, 0x90, + 0x24, 0xce, 0x78, 0x05, 0x10, 0xf3, 0xad, 0x78, + 0x04, 0x48, 0xa9, 0x60, 0x20, 0x95, 0xbe, 0xce, + 0xf8, 0x06, 0xf0, 0x28, 0xa9, 0x04, 0x8d, 0xf8, + 0x04, 0xa9, 0x00, 0x20, 0x5a, 0xbe, 0x68, 0x20, + 0x5a, 0xbe, 0x4c, 0xbc, 0xbd, 0xa4, 0x2e, 0xcc, + 0x78, 0x04, 0xf0, 0x1c, 0xad, 0x78, 0x04, 0x48, + 0x98, 0x20, 0x95, 0xbe, 0x68, 0xce, 0xf8, 0x04, - 0xd0, 0xe5, 0xf0, 0xca, 0x68, 0xa9, 0x40, 0x28, - 0x4c, 0x48, 0xbe, 0xf0, 0x39, 0x4c, 0xaf, 0xbe, - 0xa0, 0x03, 0xb1, 0x48, 0x48, 0xa5, 0x2f, 0xa0, - 0x0e, 0x91, 0x48, 0x68, 0xf0, 0x08, 0xc5, 0x2f, - 0xf0, 0x04, 0xa9, 0x20, 0xd0, 0xe1, 0xa0, 0x05, - 0xb1, 0x48, 0xa8, 0xb9, 0xb8, 0xbf, 0xc5, 0x2d, - 0xd0, 0x97, 0x28, 0x90, 0x1c, 0x20, 0xdc, 0xb8, - 0x08, 0xb0, 0x8e, 0x28, 0xa2, 0x00, 0x86, 0x26, - 0x20, 0xc2, 0xb8, 0xae, 0xf8, 0x05, 0x18, 0x24, - 0x38, 0xa0, 0x0d, 0x91, 0x48, 0xbd, 0x88, 0xc0, - 0x60, 0x20, 0x2a, 0xb8, 0x90, 0xf0, 0xa9, 0x10, - 0xb0, 0xee, 0x48, 0xa0, 0x01, 0xb1, 0x3c, 0x6a, - 0x68, 0x90, 0x08, 0x0a, 0x20, 0x6b, 0xbe, 0x4e, - 0x78, 0x04, 0x60, 0x85, 0x2a, 0x20, 0x8e, 0xbe, - 0xb9, 0x78, 0x04, 0x24, 0x35, 0x30, 0x03, 0xb9, - 0xf8, 0x04, 0x8d, 0x78, 0x04, 0xa5, 0x2a, 0x24, - 0x35, 0x30, 0x05, 0x99, 0xf8, 0x04, 0x10, 0x03, - 0x99, 0x78, 0x04, 0x4c, 0xa0, 0xb9, 0x8a, 0x4a, - 0x4a, 0x4a, 0x4a, 0xa8, 0x60, 0x48, 0xa0, 0x02, - 0xb1, 0x48, 0x6a, 0x66, 0x35, 0x20, 0x8e, 0xbe, - 0x68, 0x0a, 0x24, 0x35, 0x30, 0x05, 0x99, 0xf8, - 0x04, 0x10, 0x03, 0x99, 0x78, 0x04, 0x60, 0xa0, - 0x03, 0xb1, 0x48, 0x85, 0x41, 0xa9, 0xaa, 0x85, - 0x3e, 0xa0, 0x56, 0xa9, 0x00, 0x85, 0x44, 0x99, - 0xff, 0xbb, 0x88, 0xd0, 0xfa, 0x99, 0x00, 0xbb, - 0x88, 0xd0, 0xfa, 0xa9, 0x50, 0x20, 0x95, 0xbe, - 0xa9, 0x28, 0x85, 0x45, 0xa5, 0x44, 0x20, 0x5a, - 0xbe, 0x20, 0x0d, 0xbf, 0xa9, 0x08, 0xb0, 0x24, - 0xa9, 0x30, 0x8d, 0x78, 0x05, 0x38, 0xce, 0x78, - 0x05, 0xf0, 0x19, 0x20, 0x44, 0xb9, 0xb0, 0xf5, - 0xa5, 0x2d, 0xd0, 0xf1, 0x20, 0xdc, 0xb8, 0xb0, - 0xec, 0xe6, 0x44, 0xa5, 0x44, 0xc9, 0x23, 0x90, + 0xd0, 0xe5, 0xf0, 0xca, 0x68, 0xa9, 0x40, 0x28, + 0x4c, 0x48, 0xbe, 0xf0, 0x39, 0x4c, 0xaf, 0xbe, + 0xa0, 0x03, 0xb1, 0x48, 0x48, 0xa5, 0x2f, 0xa0, + 0x0e, 0x91, 0x48, 0x68, 0xf0, 0x08, 0xc5, 0x2f, + 0xf0, 0x04, 0xa9, 0x20, 0xd0, 0xe1, 0xa0, 0x05, + 0xb1, 0x48, 0xa8, 0xb9, 0xb8, 0xbf, 0xc5, 0x2d, + 0xd0, 0x97, 0x28, 0x90, 0x1c, 0x20, 0xdc, 0xb8, + 0x08, 0xb0, 0x8e, 0x28, 0xa2, 0x00, 0x86, 0x26, + 0x20, 0xc2, 0xb8, 0xae, 0xf8, 0x05, 0x18, 0x24, + 0x38, 0xa0, 0x0d, 0x91, 0x48, 0xbd, 0x88, 0xc0, + 0x60, 0x20, 0x2a, 0xb8, 0x90, 0xf0, 0xa9, 0x10, + 0xb0, 0xee, 0x48, 0xa0, 0x01, 0xb1, 0x3c, 0x6a, + 0x68, 0x90, 0x08, 0x0a, 0x20, 0x6b, 0xbe, 0x4e, + 0x78, 0x04, 0x60, 0x85, 0x2a, 0x20, 0x8e, 0xbe, + 0xb9, 0x78, 0x04, 0x24, 0x35, 0x30, 0x03, 0xb9, + 0xf8, 0x04, 0x8d, 0x78, 0x04, 0xa5, 0x2a, 0x24, + 0x35, 0x30, 0x05, 0x99, 0xf8, 0x04, 0x10, 0x03, + 0x99, 0x78, 0x04, 0x4c, 0xa0, 0xb9, 0x8a, 0x4a, + 0x4a, 0x4a, 0x4a, 0xa8, 0x60, 0x48, 0xa0, 0x02, + 0xb1, 0x48, 0x6a, 0x66, 0x35, 0x20, 0x8e, 0xbe, + 0x68, 0x0a, 0x24, 0x35, 0x30, 0x05, 0x99, 0xf8, + 0x04, 0x10, 0x03, 0x99, 0x78, 0x04, 0x60, 0xa0, + 0x03, 0xb1, 0x48, 0x85, 0x41, 0xa9, 0xaa, 0x85, + 0x3e, 0xa0, 0x56, 0xa9, 0x00, 0x85, 0x44, 0x99, + 0xff, 0xbb, 0x88, 0xd0, 0xfa, 0x99, 0x00, 0xbb, + 0x88, 0xd0, 0xfa, 0xa9, 0x50, 0x20, 0x95, 0xbe, + 0xa9, 0x28, 0x85, 0x45, 0xa5, 0x44, 0x20, 0x5a, + 0xbe, 0x20, 0x0d, 0xbf, 0xa9, 0x08, 0xb0, 0x24, + 0xa9, 0x30, 0x8d, 0x78, 0x05, 0x38, 0xce, 0x78, + 0x05, 0xf0, 0x19, 0x20, 0x44, 0xb9, 0xb0, 0xf5, + 0xa5, 0x2d, 0xd0, 0xf1, 0x20, 0xdc, 0xb8, 0xb0, + 0xec, 0xe6, 0x44, 0xa5, 0x44, 0xc9, 0x23, 0x90, - 0xd3, 0x18, 0x90, 0x05, 0xa0, 0x0d, 0x91, 0x48, - 0x38, 0xbd, 0x88, 0xc0, 0x60, 0xa9, 0x00, 0x85, - 0x3f, 0xa0, 0x80, 0xd0, 0x02, 0xa4, 0x45, 0x20, - 0x56, 0xbc, 0xb0, 0x6b, 0x20, 0x2a, 0xb8, 0xb0, - 0x66, 0xe6, 0x3f, 0xa5, 0x3f, 0xc9, 0x10, 0x90, - 0xec, 0xa0, 0x0f, 0x84, 0x3f, 0xa9, 0x30, 0x8d, - 0x78, 0x05, 0x99, 0xa8, 0xbf, 0x88, 0x10, 0xfa, - 0xa4, 0x45, 0x20, 0x87, 0xbf, 0x20, 0x87, 0xbf, - 0x20, 0x87, 0xbf, 0x48, 0x68, 0xea, 0x88, 0xd0, - 0xf1, 0x20, 0x44, 0xb9, 0xb0, 0x23, 0xa5, 0x2d, - 0xf0, 0x15, 0xa9, 0x10, 0xc5, 0x45, 0xa5, 0x45, - 0xe9, 0x01, 0x85, 0x45, 0xc9, 0x05, 0xb0, 0x11, - 0x38, 0x60, 0x20, 0x44, 0xb9, 0xb0, 0x05, 0x20, - 0xdc, 0xb8, 0x90, 0x1c, 0xce, 0x78, 0x05, 0xd0, - 0xf1, 0x20, 0x44, 0xb9, 0xb0, 0x0b, 0xa5, 0x2d, - 0xc9, 0x0f, 0xd0, 0x05, 0x20, 0xdc, 0xb8, 0x90, - 0x8c, 0xce, 0x78, 0x05, 0xd0, 0xeb, 0x38, 0x60, - 0xa4, 0x2d, 0xb9, 0xa8, 0xbf, 0x30, 0xdd, 0xa9, - 0xff, 0x99, 0xa8, 0xbf, 0xc6, 0x3f, 0x10, 0xca, - 0xa5, 0x44, 0xd0, 0x0a, 0xa5, 0x45, 0xc9, 0x10, - 0x90, 0xe5, 0xc6, 0x45, 0xc6, 0x45, 0x18, 0x60, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x0d, 0x0b, 0x09, 0x07, 0x05, 0x03, 0x01, - 0x0e, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x0f, - 0x20, 0x93, 0xfe, 0xad, 0x81, 0xc0, 0xad, 0x81, - 0xc0, 0xa9, 0x00, 0x8d, 0x00, 0xe0, 0x4c, 0x44, - 0xb7, 0x00, 0x00, 0x00, 0x8d, 0x63, 0xaa, 0x8d, - 0x70, 0xaa, 0x8d, 0x71, 0xaa, 0x60, 0x20, 0x5b, - 0xa7, 0x8c, 0xb7, 0xaa, 0x60, 0x20, 0x7e, 0xae, - 0xae, 0x9b, 0xb3, 0x9a, 0x20, 0x16, 0xa3, 0xba, - 0x8e, 0x9b, 0xb3, 0xa9, 0x09, 0x4c, 0x85, 0xb3, + 0xd3, 0x18, 0x90, 0x05, 0xa0, 0x0d, 0x91, 0x48, + 0x38, 0xbd, 0x88, 0xc0, 0x60, 0xa9, 0x00, 0x85, + 0x3f, 0xa0, 0x80, 0xd0, 0x02, 0xa4, 0x45, 0x20, + 0x56, 0xbc, 0xb0, 0x6b, 0x20, 0x2a, 0xb8, 0xb0, + 0x66, 0xe6, 0x3f, 0xa5, 0x3f, 0xc9, 0x10, 0x90, + 0xec, 0xa0, 0x0f, 0x84, 0x3f, 0xa9, 0x30, 0x8d, + 0x78, 0x05, 0x99, 0xa8, 0xbf, 0x88, 0x10, 0xfa, + 0xa4, 0x45, 0x20, 0x87, 0xbf, 0x20, 0x87, 0xbf, + 0x20, 0x87, 0xbf, 0x48, 0x68, 0xea, 0x88, 0xd0, + 0xf1, 0x20, 0x44, 0xb9, 0xb0, 0x23, 0xa5, 0x2d, + 0xf0, 0x15, 0xa9, 0x10, 0xc5, 0x45, 0xa5, 0x45, + 0xe9, 0x01, 0x85, 0x45, 0xc9, 0x05, 0xb0, 0x11, + 0x38, 0x60, 0x20, 0x44, 0xb9, 0xb0, 0x05, 0x20, + 0xdc, 0xb8, 0x90, 0x1c, 0xce, 0x78, 0x05, 0xd0, + 0xf1, 0x20, 0x44, 0xb9, 0xb0, 0x0b, 0xa5, 0x2d, + 0xc9, 0x0f, 0xd0, 0x05, 0x20, 0xdc, 0xb8, 0x90, + 0x8c, 0xce, 0x78, 0x05, 0xd0, 0xeb, 0x38, 0x60, + 0xa4, 0x2d, 0xb9, 0xa8, 0xbf, 0x30, 0xdd, 0xa9, + 0xff, 0x99, 0xa8, 0xbf, 0xc6, 0x3f, 0x10, 0xca, + 0xa5, 0x44, 0xd0, 0x0a, 0xa5, 0x45, 0xc9, 0x10, + 0x90, 0xe5, 0xc6, 0x45, 0xc6, 0x45, 0x18, 0x60, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x0d, 0x0b, 0x09, 0x07, 0x05, 0x03, 0x01, + 0x0e, 0x0c, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x0f, + 0x20, 0x93, 0xfe, 0xad, 0x81, 0xc0, 0xad, 0x81, + 0xc0, 0xa9, 0x00, 0x8d, 0x00, 0xe0, 0x4c, 0x44, + 0xb7, 0x00, 0x00, 0x00, 0x8d, 0x63, 0xaa, 0x8d, + 0x70, 0xaa, 0x8d, 0x71, 0xaa, 0x60, 0x20, 0x5b, + 0xa7, 0x8c, 0xb7, 0xaa, 0x60, 0x20, 0x7e, 0xae, + 0xae, 0x9b, 0xb3, 0x9a, 0x20, 0x16, 0xa3, 0xba, + 0x8e, 0x9b, 0xb3, 0xa9, 0x09, 0x4c, 0x85, 0xb3, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xd3, 0x9c, 0x81, 0x9e, 0xbd, 0x9e, 0x75, 0xaa, - 0x93, 0xaa, 0x60, 0xaa, 0x00, 0x9d, 0xbb, 0xb5, - 0xea, 0x9e, 0x11, 0x9f, 0x22, 0x9f, 0x2e, 0x9f, - 0x51, 0x9f, 0x60, 0x9f, 0x70, 0x9f, 0x4e, 0xa5, - 0x12, 0xa4, 0x96, 0xa3, 0xd0, 0xa4, 0xef, 0xa4, - 0x62, 0xa2, 0x70, 0xa2, 0x74, 0xa2, 0xe9, 0xa2, - 0x1a, 0xa5, 0xc5, 0xa5, 0x0f, 0xa5, 0xdc, 0xa5, - 0xa2, 0xa2, 0x97, 0xa2, 0x80, 0xa2, 0x6d, 0xa5, - 0x32, 0xa2, 0x3c, 0xa2, 0x28, 0xa2, 0x2d, 0xa2, - 0x50, 0xa2, 0x79, 0xa5, 0x9d, 0xa5, 0x30, 0xa3, - 0x5c, 0xa3, 0x8d, 0xa3, 0x7c, 0xa2, 0xfc, 0xa4, - 0xfc, 0xa4, 0x65, 0xd8, 0x00, 0xe0, 0x3c, 0xd4, - 0xf2, 0xd4, 0x36, 0xe8, 0xe5, 0xa4, 0xe3, 0xe3, - 0x00, 0xe0, 0x03, 0xe0, 0xfc, 0xa4, 0xfc, 0xa4, - 0x65, 0xd8, 0x00, 0xe0, 0x3c, 0xd4, 0xf2, 0xd4, - 0x06, 0xa5, 0x06, 0xa5, 0x67, 0x10, 0x84, 0x9d, - 0x3c, 0x0c, 0xf2, 0x0c, 0xad, 0xe9, 0xb7, 0x4a, - 0x4a, 0x4a, 0x4a, 0x8d, 0x6a, 0xaa, 0xad, 0xea, - 0xb7, 0x8d, 0x68, 0xaa, 0xad, 0x00, 0xe0, 0x49, - 0x20, 0xd0, 0x11, 0x8d, 0xb6, 0xaa, 0xa2, 0x0a, - 0xbd, 0x61, 0x9d, 0x9d, 0x55, 0x9d, 0xca, 0xd0, - 0xf7, 0x4c, 0xbc, 0x9d, 0xa9, 0x40, 0x8d, 0xb6, - 0xaa, 0xa2, 0x0c, 0xbd, 0x6b, 0x9d, 0x9d, 0x55, - 0x9d, 0xca, 0xd0, 0xf7, 0x38, 0xb0, 0x12, 0xad, - 0xb6, 0xaa, 0xd0, 0x04, 0xa9, 0x20, 0xd0, 0x05, - 0x0a, 0x10, 0x05, 0xa9, 0x4c, 0x20, 0xb2, 0xa5, - 0x18, 0x08, 0x20, 0x51, 0xa8, 0xa9, 0x00, 0x8d, - 0x5e, 0xaa, 0x8d, 0x52, 0xaa, 0x28, 0x6a, 0x8d, - 0x51, 0xaa, 0x30, 0x03, 0x6c, 0x5e, 0x9d, 0x6c, - 0x5c, 0x9d, 0x0a, 0x10, 0x19, 0x8d, 0xb6, 0xaa, - 0xa2, 0x0c, 0xbd, 0x77, 0x9d, 0x9d, 0x55, 0x9d, - 0xca, 0xd0, 0xf7, 0xa2, 0x1d, 0xbd, 0x93, 0xaa, + 0xd3, 0x9c, 0x81, 0x9e, 0xbd, 0x9e, 0x75, 0xaa, + 0x93, 0xaa, 0x60, 0xaa, 0x00, 0x9d, 0xbb, 0xb5, + 0xea, 0x9e, 0x11, 0x9f, 0x22, 0x9f, 0x2e, 0x9f, + 0x51, 0x9f, 0x60, 0x9f, 0x70, 0x9f, 0x4e, 0xa5, + 0x12, 0xa4, 0x96, 0xa3, 0xd0, 0xa4, 0xef, 0xa4, + 0x62, 0xa2, 0x70, 0xa2, 0x74, 0xa2, 0xe9, 0xa2, + 0x1a, 0xa5, 0xc5, 0xa5, 0x0f, 0xa5, 0xdc, 0xa5, + 0xa2, 0xa2, 0x97, 0xa2, 0x80, 0xa2, 0x6d, 0xa5, + 0x32, 0xa2, 0x3c, 0xa2, 0x28, 0xa2, 0x2d, 0xa2, + 0x50, 0xa2, 0x79, 0xa5, 0x9d, 0xa5, 0x30, 0xa3, + 0x5c, 0xa3, 0x8d, 0xa3, 0x7c, 0xa2, 0xfc, 0xa4, + 0xfc, 0xa4, 0x65, 0xd8, 0x00, 0xe0, 0x3c, 0xd4, + 0xf2, 0xd4, 0x36, 0xe8, 0xe5, 0xa4, 0xe3, 0xe3, + 0x00, 0xe0, 0x03, 0xe0, 0xfc, 0xa4, 0xfc, 0xa4, + 0x65, 0xd8, 0x00, 0xe0, 0x3c, 0xd4, 0xf2, 0xd4, + 0x06, 0xa5, 0x06, 0xa5, 0x67, 0x10, 0x84, 0x9d, + 0x3c, 0x0c, 0xf2, 0x0c, 0xad, 0xe9, 0xb7, 0x4a, + 0x4a, 0x4a, 0x4a, 0x8d, 0x6a, 0xaa, 0xad, 0xea, + 0xb7, 0x8d, 0x68, 0xaa, 0xad, 0x00, 0xe0, 0x49, + 0x20, 0xd0, 0x11, 0x8d, 0xb6, 0xaa, 0xa2, 0x0a, + 0xbd, 0x61, 0x9d, 0x9d, 0x55, 0x9d, 0xca, 0xd0, + 0xf7, 0x4c, 0xbc, 0x9d, 0xa9, 0x40, 0x8d, 0xb6, + 0xaa, 0xa2, 0x0c, 0xbd, 0x6b, 0x9d, 0x9d, 0x55, + 0x9d, 0xca, 0xd0, 0xf7, 0x38, 0xb0, 0x12, 0xad, + 0xb6, 0xaa, 0xd0, 0x04, 0xa9, 0x20, 0xd0, 0x05, + 0x0a, 0x10, 0x05, 0xa9, 0x4c, 0x20, 0xb2, 0xa5, + 0x18, 0x08, 0x20, 0x51, 0xa8, 0xa9, 0x00, 0x8d, + 0x5e, 0xaa, 0x8d, 0x52, 0xaa, 0x28, 0x6a, 0x8d, + 0x51, 0xaa, 0x30, 0x03, 0x6c, 0x5e, 0x9d, 0x6c, + 0x5c, 0x9d, 0x0a, 0x10, 0x19, 0x8d, 0xb6, 0xaa, + 0xa2, 0x0c, 0xbd, 0x77, 0x9d, 0x9d, 0x55, 0x9d, + 0xca, 0xd0, 0xf7, 0xa2, 0x1d, 0xbd, 0x93, 0xaa, - 0x9d, 0x75, 0xaa, 0xca, 0x10, 0xf7, 0xad, 0xb1, - 0xaa, 0x8d, 0x57, 0xaa, 0x20, 0xd4, 0xa7, 0xad, - 0xb3, 0xaa, 0xf0, 0x09, 0x48, 0x20, 0x9d, 0xa6, - 0x68, 0xa0, 0x00, 0x91, 0x40, 0x20, 0x5b, 0xa7, - 0xad, 0x5f, 0xaa, 0xd0, 0x20, 0xa2, 0x2f, 0xbd, - 0x51, 0x9e, 0x9d, 0xd0, 0x03, 0xca, 0x10, 0xf7, - 0xad, 0x53, 0x9e, 0x8d, 0xf3, 0x03, 0x49, 0xa5, - 0x8d, 0xf4, 0x03, 0xad, 0x52, 0x9e, 0x8d, 0xf2, - 0x03, 0xa9, 0x06, 0xd0, 0x05, 0xad, 0x62, 0xaa, - 0xf0, 0x06, 0x8d, 0x5f, 0xaa, 0x4c, 0x80, 0xa1, - 0x60, 0x4c, 0xbf, 0x9d, 0x4c, 0x84, 0x9d, 0x4c, - 0xfd, 0xaa, 0x4c, 0xb5, 0xb7, 0xad, 0x0f, 0x9d, - 0xac, 0x0e, 0x9d, 0x60, 0xad, 0xc2, 0xaa, 0xac, - 0xc1, 0xaa, 0x60, 0x4c, 0x51, 0xa8, 0xea, 0xea, - 0x4c, 0x59, 0xfa, 0x4c, 0x65, 0xff, 0x4c, 0x58, - 0xff, 0x4c, 0x65, 0xff, 0x4c, 0x65, 0xff, 0x65, - 0xff, 0x20, 0xd1, 0x9e, 0xad, 0x51, 0xaa, 0xf0, - 0x15, 0x48, 0xad, 0x5c, 0xaa, 0x91, 0x28, 0x68, - 0x30, 0x03, 0x4c, 0x26, 0xa6, 0x20, 0xea, 0x9d, - 0xa4, 0x24, 0xa9, 0x60, 0x91, 0x28, 0xad, 0xb3, - 0xaa, 0xf0, 0x03, 0x20, 0x82, 0xa6, 0xa9, 0x03, - 0x8d, 0x52, 0xaa, 0x20, 0xba, 0x9f, 0x20, 0xba, - 0x9e, 0x8d, 0x5c, 0xaa, 0x8e, 0x5a, 0xaa, 0x4c, - 0xb3, 0x9f, 0x6c, 0x38, 0x00, 0x20, 0xd1, 0x9e, - 0xad, 0x52, 0xaa, 0x0a, 0xaa, 0xbd, 0x11, 0x9d, - 0x48, 0xbd, 0x10, 0x9d, 0x48, 0xad, 0x5c, 0xaa, - 0x60, 0x8d, 0x5c, 0xaa, 0x8e, 0x5a, 0xaa, 0x8c, - 0x5b, 0xaa, 0xba, 0xe8, 0xe8, 0x8e, 0x59, 0xaa, - 0xa2, 0x03, 0xbd, 0x53, 0xaa, 0x95, 0x36, 0xca, - 0x10, 0xf8, 0x60, 0xae, 0xb7, 0xaa, 0xf0, 0x03, - 0x4c, 0x78, 0x9f, 0xae, 0x51, 0xaa, 0xf0, 0x08, - 0xc9, 0xbf, 0xf0, 0x75, 0xc5, 0x33, 0xf0, 0x27, + 0x9d, 0x75, 0xaa, 0xca, 0x10, 0xf7, 0xad, 0xb1, + 0xaa, 0x8d, 0x57, 0xaa, 0x20, 0xd4, 0xa7, 0xad, + 0xb3, 0xaa, 0xf0, 0x09, 0x48, 0x20, 0x9d, 0xa6, + 0x68, 0xa0, 0x00, 0x91, 0x40, 0x20, 0x5b, 0xa7, + 0xad, 0x5f, 0xaa, 0xd0, 0x20, 0xa2, 0x2f, 0xbd, + 0x51, 0x9e, 0x9d, 0xd0, 0x03, 0xca, 0x10, 0xf7, + 0xad, 0x53, 0x9e, 0x8d, 0xf3, 0x03, 0x49, 0xa5, + 0x8d, 0xf4, 0x03, 0xad, 0x52, 0x9e, 0x8d, 0xf2, + 0x03, 0xa9, 0x06, 0xd0, 0x05, 0xad, 0x62, 0xaa, + 0xf0, 0x06, 0x8d, 0x5f, 0xaa, 0x4c, 0x80, 0xa1, + 0x60, 0x4c, 0xbf, 0x9d, 0x4c, 0x84, 0x9d, 0x4c, + 0xfd, 0xaa, 0x4c, 0xb5, 0xb7, 0xad, 0x0f, 0x9d, + 0xac, 0x0e, 0x9d, 0x60, 0xad, 0xc2, 0xaa, 0xac, + 0xc1, 0xaa, 0x60, 0x4c, 0x51, 0xa8, 0xea, 0xea, + 0x4c, 0x59, 0xfa, 0x4c, 0x65, 0xff, 0x4c, 0x58, + 0xff, 0x4c, 0x65, 0xff, 0x4c, 0x65, 0xff, 0x65, + 0xff, 0x20, 0xd1, 0x9e, 0xad, 0x51, 0xaa, 0xf0, + 0x15, 0x48, 0xad, 0x5c, 0xaa, 0x91, 0x28, 0x68, + 0x30, 0x03, 0x4c, 0x26, 0xa6, 0x20, 0xea, 0x9d, + 0xa4, 0x24, 0xa9, 0x60, 0x91, 0x28, 0xad, 0xb3, + 0xaa, 0xf0, 0x03, 0x20, 0x82, 0xa6, 0xa9, 0x03, + 0x8d, 0x52, 0xaa, 0x20, 0xba, 0x9f, 0x20, 0xba, + 0x9e, 0x8d, 0x5c, 0xaa, 0x8e, 0x5a, 0xaa, 0x4c, + 0xb3, 0x9f, 0x6c, 0x38, 0x00, 0x20, 0xd1, 0x9e, + 0xad, 0x52, 0xaa, 0x0a, 0xaa, 0xbd, 0x11, 0x9d, + 0x48, 0xbd, 0x10, 0x9d, 0x48, 0xad, 0x5c, 0xaa, + 0x60, 0x8d, 0x5c, 0xaa, 0x8e, 0x5a, 0xaa, 0x8c, + 0x5b, 0xaa, 0xba, 0xe8, 0xe8, 0x8e, 0x59, 0xaa, + 0xa2, 0x03, 0xbd, 0x53, 0xaa, 0x95, 0x36, 0xca, + 0x10, 0xf8, 0x60, 0xae, 0xb7, 0xaa, 0xf0, 0x03, + 0x4c, 0x78, 0x9f, 0xae, 0x51, 0xaa, 0xf0, 0x08, + 0xc9, 0xbf, 0xf0, 0x75, 0xc5, 0x33, 0xf0, 0x27, - 0xa2, 0x02, 0x8e, 0x52, 0xaa, 0xcd, 0xb2, 0xaa, - 0xd0, 0x19, 0xca, 0x8e, 0x52, 0xaa, 0xca, 0x8e, - 0x5d, 0xaa, 0xae, 0x5d, 0xaa, 0x9d, 0x00, 0x02, - 0xe8, 0x8e, 0x5d, 0xaa, 0xc9, 0x8d, 0xd0, 0x75, - 0x4c, 0xcd, 0x9f, 0xc9, 0x8d, 0xd0, 0x7d, 0xa2, - 0x00, 0x8e, 0x52, 0xaa, 0x4c, 0xa4, 0x9f, 0xa2, - 0x00, 0x8e, 0x52, 0xaa, 0xc9, 0x8d, 0xf0, 0x07, - 0xad, 0xb3, 0xaa, 0xf0, 0x67, 0xd0, 0x5e, 0x48, - 0x38, 0xad, 0xb3, 0xaa, 0xd0, 0x03, 0x20, 0x5e, - 0xa6, 0x68, 0x90, 0xec, 0xae, 0x5a, 0xaa, 0x4c, - 0x15, 0x9f, 0xc9, 0x8d, 0xd0, 0x05, 0xa9, 0x05, - 0x8d, 0x52, 0xaa, 0x20, 0x0e, 0xa6, 0x4c, 0x99, - 0x9f, 0xcd, 0xb2, 0xaa, 0xf0, 0x85, 0xc9, 0x8a, - 0xf0, 0xf1, 0xa2, 0x04, 0x8e, 0x52, 0xaa, 0xd0, - 0xe1, 0xa9, 0x00, 0x8d, 0x52, 0xaa, 0xf0, 0x25, - 0xa9, 0x00, 0x8d, 0xb7, 0xaa, 0x20, 0x51, 0xa8, - 0x4c, 0xdc, 0xa4, 0xad, 0x00, 0x02, 0xcd, 0xb2, - 0xaa, 0xf0, 0x0a, 0xa9, 0x8d, 0x8d, 0x00, 0x02, - 0xa2, 0x00, 0x8e, 0x5a, 0xaa, 0xa9, 0x40, 0xd0, - 0x06, 0xa9, 0x10, 0xd0, 0x02, 0xa9, 0x20, 0x2d, - 0x5e, 0xaa, 0xf0, 0x0f, 0x20, 0xba, 0x9f, 0x20, - 0xc5, 0x9f, 0x8d, 0x5c, 0xaa, 0x8c, 0x5b, 0xaa, - 0x8e, 0x5a, 0xaa, 0x20, 0x51, 0xa8, 0xae, 0x59, - 0xaa, 0x9a, 0xad, 0x5c, 0xaa, 0xac, 0x5b, 0xaa, - 0xae, 0x5a, 0xaa, 0x38, 0x60, 0x6c, 0x36, 0x00, - 0xa9, 0x8d, 0x4c, 0xc5, 0x9f, 0xa0, 0xff, 0x8c, - 0x5f, 0xaa, 0xc8, 0x8c, 0x62, 0xaa, 0xee, 0x5f, - 0xaa, 0xa2, 0x00, 0x08, 0xbd, 0x00, 0x02, 0xcd, - 0xb2, 0xaa, 0xd0, 0x01, 0xe8, 0x8e, 0x5d, 0xaa, - 0x20, 0xa4, 0xa1, 0x29, 0x7f, 0x59, 0x84, 0xa8, - 0xc8, 0x0a, 0xf0, 0x02, 0x68, 0x08, 0x90, 0xf0, - 0x28, 0xf0, 0x20, 0xb9, 0x84, 0xa8, 0xd0, 0xd6, + 0xa2, 0x02, 0x8e, 0x52, 0xaa, 0xcd, 0xb2, 0xaa, + 0xd0, 0x19, 0xca, 0x8e, 0x52, 0xaa, 0xca, 0x8e, + 0x5d, 0xaa, 0xae, 0x5d, 0xaa, 0x9d, 0x00, 0x02, + 0xe8, 0x8e, 0x5d, 0xaa, 0xc9, 0x8d, 0xd0, 0x75, + 0x4c, 0xcd, 0x9f, 0xc9, 0x8d, 0xd0, 0x7d, 0xa2, + 0x00, 0x8e, 0x52, 0xaa, 0x4c, 0xa4, 0x9f, 0xa2, + 0x00, 0x8e, 0x52, 0xaa, 0xc9, 0x8d, 0xf0, 0x07, + 0xad, 0xb3, 0xaa, 0xf0, 0x67, 0xd0, 0x5e, 0x48, + 0x38, 0xad, 0xb3, 0xaa, 0xd0, 0x03, 0x20, 0x5e, + 0xa6, 0x68, 0x90, 0xec, 0xae, 0x5a, 0xaa, 0x4c, + 0x15, 0x9f, 0xc9, 0x8d, 0xd0, 0x05, 0xa9, 0x05, + 0x8d, 0x52, 0xaa, 0x20, 0x0e, 0xa6, 0x4c, 0x99, + 0x9f, 0xcd, 0xb2, 0xaa, 0xf0, 0x85, 0xc9, 0x8a, + 0xf0, 0xf1, 0xa2, 0x04, 0x8e, 0x52, 0xaa, 0xd0, + 0xe1, 0xa9, 0x00, 0x8d, 0x52, 0xaa, 0xf0, 0x25, + 0xa9, 0x00, 0x8d, 0xb7, 0xaa, 0x20, 0x51, 0xa8, + 0x4c, 0xdc, 0xa4, 0xad, 0x00, 0x02, 0xcd, 0xb2, + 0xaa, 0xf0, 0x0a, 0xa9, 0x8d, 0x8d, 0x00, 0x02, + 0xa2, 0x00, 0x8e, 0x5a, 0xaa, 0xa9, 0x40, 0xd0, + 0x06, 0xa9, 0x10, 0xd0, 0x02, 0xa9, 0x20, 0x2d, + 0x5e, 0xaa, 0xf0, 0x0f, 0x20, 0xba, 0x9f, 0x20, + 0xc5, 0x9f, 0x8d, 0x5c, 0xaa, 0x8c, 0x5b, 0xaa, + 0x8e, 0x5a, 0xaa, 0x20, 0x51, 0xa8, 0xae, 0x59, + 0xaa, 0x9a, 0xad, 0x5c, 0xaa, 0xac, 0x5b, 0xaa, + 0xae, 0x5a, 0xaa, 0x38, 0x60, 0x6c, 0x36, 0x00, + 0xa9, 0x8d, 0x4c, 0xc5, 0x9f, 0xa0, 0xff, 0x8c, + 0x5f, 0xaa, 0xc8, 0x8c, 0x62, 0xaa, 0xee, 0x5f, + 0xaa, 0xa2, 0x00, 0x08, 0xbd, 0x00, 0x02, 0xcd, + 0xb2, 0xaa, 0xd0, 0x01, 0xe8, 0x8e, 0x5d, 0xaa, + 0x20, 0xa4, 0xa1, 0x29, 0x7f, 0x59, 0x84, 0xa8, + 0xc8, 0x0a, 0xf0, 0x02, 0x68, 0x08, 0x90, 0xf0, + 0x28, 0xf0, 0x20, 0xb9, 0x84, 0xa8, 0xd0, 0xd6, - 0xad, 0x00, 0x02, 0xcd, 0xb2, 0xaa, 0xf0, 0x03, - 0x4c, 0xa4, 0x9f, 0xad, 0x01, 0x02, 0xc9, 0x8d, - 0xd0, 0x06, 0x20, 0x5b, 0xa7, 0x4c, 0x95, 0x9f, - 0x4c, 0xc4, 0xa6, 0x0e, 0x5f, 0xaa, 0xac, 0x5f, - 0xaa, 0x20, 0x5e, 0xa6, 0x90, 0x0c, 0xa9, 0x02, - 0x39, 0x09, 0xa9, 0xf0, 0x05, 0xa9, 0x0f, 0x4c, - 0xd2, 0xa6, 0xc0, 0x06, 0xd0, 0x02, 0x84, 0x33, - 0xa9, 0x20, 0x39, 0x09, 0xa9, 0xf0, 0x61, 0x20, - 0x95, 0xa0, 0x08, 0x20, 0xa4, 0xa1, 0xf0, 0x1e, - 0x0a, 0x90, 0x05, 0x30, 0x03, 0x4c, 0x00, 0xa0, - 0x6a, 0x4c, 0x59, 0xa0, 0x20, 0x93, 0xa1, 0xf0, - 0x0d, 0x99, 0x75, 0xaa, 0xc8, 0xc0, 0x3c, 0x90, - 0xf3, 0x20, 0x93, 0xa1, 0xd0, 0xfb, 0x28, 0xd0, - 0x0f, 0xac, 0x5f, 0xaa, 0xa9, 0x10, 0x39, 0x09, - 0xa9, 0xf0, 0x0c, 0xa0, 0x1e, 0x08, 0xd0, 0xcb, - 0xad, 0x93, 0xaa, 0xc9, 0xa0, 0xf0, 0x13, 0xad, - 0x75, 0xaa, 0xc9, 0xa0, 0xd0, 0x4b, 0xac, 0x5f, - 0xaa, 0xa9, 0xc0, 0x39, 0x09, 0xa9, 0xf0, 0x02, - 0x10, 0x3f, 0x4c, 0x00, 0xa0, 0xa0, 0x3c, 0xa9, - 0xa0, 0x99, 0x74, 0xaa, 0x88, 0xd0, 0xfa, 0x60, - 0x8d, 0x75, 0xaa, 0xa9, 0x0c, 0x39, 0x09, 0xa9, - 0xf0, 0x27, 0x20, 0xb9, 0xa1, 0xb0, 0x1f, 0xa8, - 0xd0, 0x17, 0xe0, 0x11, 0xb0, 0x13, 0xac, 0x5f, - 0xaa, 0xa9, 0x08, 0x39, 0x09, 0xa9, 0xf0, 0x06, - 0xe0, 0x08, 0xb0, 0xce, 0x90, 0x0b, 0x8a, 0xd0, - 0x08, 0xa9, 0x02, 0x4c, 0xd2, 0xa6, 0x4c, 0xc4, - 0xa6, 0xa9, 0x00, 0x8d, 0x65, 0xaa, 0x8d, 0x74, - 0xaa, 0x8d, 0x66, 0xaa, 0x8d, 0x6c, 0xaa, 0x8d, - 0x6d, 0xaa, 0x20, 0xdc, 0xbf, 0xad, 0x5d, 0xaa, - 0x20, 0xa4, 0xa1, 0xd0, 0x1f, 0xc9, 0x8d, 0xd0, - 0xf7, 0xae, 0x5f, 0xaa, 0xad, 0x65, 0xaa, 0x1d, - 0x0a, 0xa9, 0x5d, 0x0a, 0xa9, 0xd0, 0x93, 0xae, + 0xad, 0x00, 0x02, 0xcd, 0xb2, 0xaa, 0xf0, 0x03, + 0x4c, 0xa4, 0x9f, 0xad, 0x01, 0x02, 0xc9, 0x8d, + 0xd0, 0x06, 0x20, 0x5b, 0xa7, 0x4c, 0x95, 0x9f, + 0x4c, 0xc4, 0xa6, 0x0e, 0x5f, 0xaa, 0xac, 0x5f, + 0xaa, 0x20, 0x5e, 0xa6, 0x90, 0x0c, 0xa9, 0x02, + 0x39, 0x09, 0xa9, 0xf0, 0x05, 0xa9, 0x0f, 0x4c, + 0xd2, 0xa6, 0xc0, 0x06, 0xd0, 0x02, 0x84, 0x33, + 0xa9, 0x20, 0x39, 0x09, 0xa9, 0xf0, 0x61, 0x20, + 0x95, 0xa0, 0x08, 0x20, 0xa4, 0xa1, 0xf0, 0x1e, + 0x0a, 0x90, 0x05, 0x30, 0x03, 0x4c, 0x00, 0xa0, + 0x6a, 0x4c, 0x59, 0xa0, 0x20, 0x93, 0xa1, 0xf0, + 0x0d, 0x99, 0x75, 0xaa, 0xc8, 0xc0, 0x3c, 0x90, + 0xf3, 0x20, 0x93, 0xa1, 0xd0, 0xfb, 0x28, 0xd0, + 0x0f, 0xac, 0x5f, 0xaa, 0xa9, 0x10, 0x39, 0x09, + 0xa9, 0xf0, 0x0c, 0xa0, 0x1e, 0x08, 0xd0, 0xcb, + 0xad, 0x93, 0xaa, 0xc9, 0xa0, 0xf0, 0x13, 0xad, + 0x75, 0xaa, 0xc9, 0xa0, 0xd0, 0x4b, 0xac, 0x5f, + 0xaa, 0xa9, 0xc0, 0x39, 0x09, 0xa9, 0xf0, 0x02, + 0x10, 0x3f, 0x4c, 0x00, 0xa0, 0xa0, 0x3c, 0xa9, + 0xa0, 0x99, 0x74, 0xaa, 0x88, 0xd0, 0xfa, 0x60, + 0x8d, 0x75, 0xaa, 0xa9, 0x0c, 0x39, 0x09, 0xa9, + 0xf0, 0x27, 0x20, 0xb9, 0xa1, 0xb0, 0x1f, 0xa8, + 0xd0, 0x17, 0xe0, 0x11, 0xb0, 0x13, 0xac, 0x5f, + 0xaa, 0xa9, 0x08, 0x39, 0x09, 0xa9, 0xf0, 0x06, + 0xe0, 0x08, 0xb0, 0xce, 0x90, 0x0b, 0x8a, 0xd0, + 0x08, 0xa9, 0x02, 0x4c, 0xd2, 0xa6, 0x4c, 0xc4, + 0xa6, 0xa9, 0x00, 0x8d, 0x65, 0xaa, 0x8d, 0x74, + 0xaa, 0x8d, 0x66, 0xaa, 0x8d, 0x6c, 0xaa, 0x8d, + 0x6d, 0xaa, 0x20, 0xdc, 0xbf, 0xad, 0x5d, 0xaa, + 0x20, 0xa4, 0xa1, 0xd0, 0x1f, 0xc9, 0x8d, 0xd0, + 0xf7, 0xae, 0x5f, 0xaa, 0xad, 0x65, 0xaa, 0x1d, + 0x0a, 0xa9, 0x5d, 0x0a, 0xa9, 0xd0, 0x93, 0xae, - 0x63, 0xaa, 0xf0, 0x76, 0x8d, 0x63, 0xaa, 0x8e, - 0x5d, 0xaa, 0xd0, 0xdc, 0xa2, 0x0a, 0xdd, 0x40, - 0xa9, 0xf0, 0x05, 0xca, 0xd0, 0xf8, 0xf0, 0xb6, - 0xbd, 0x4a, 0xa9, 0x30, 0x47, 0x0d, 0x65, 0xaa, - 0x8d, 0x65, 0xaa, 0xca, 0x8e, 0x64, 0xaa, 0x20, - 0xb9, 0xa1, 0xb0, 0xa2, 0xad, 0x64, 0xaa, 0x0a, - 0x0a, 0xa8, 0xa5, 0x45, 0xd0, 0x09, 0xa5, 0x44, - 0xd9, 0x55, 0xa9, 0x90, 0x8c, 0xa5, 0x45, 0xd9, - 0x58, 0xa9, 0x90, 0x0b, 0xd0, 0x83, 0xa5, 0x44, - 0xd9, 0x57, 0xa9, 0x90, 0x02, 0xd0, 0xf5, 0xad, - 0x63, 0xaa, 0xd0, 0x94, 0x98, 0x4a, 0xa8, 0xa5, - 0x45, 0x99, 0x67, 0xaa, 0xa5, 0x44, 0x99, 0x66, - 0xaa, 0x4c, 0xe8, 0xa0, 0x48, 0xa9, 0x80, 0x0d, - 0x65, 0xaa, 0x8d, 0x65, 0xaa, 0x68, 0x29, 0x7f, - 0x0d, 0x74, 0xaa, 0x8d, 0x74, 0xaa, 0xd0, 0xe9, - 0xf0, 0x9c, 0x20, 0x80, 0xa1, 0x4c, 0x83, 0x9f, - 0x20, 0x5b, 0xa7, 0x20, 0xae, 0xa1, 0xad, 0x5f, - 0xaa, 0xaa, 0xbd, 0x1f, 0x9d, 0x48, 0xbd, 0x1e, - 0x9d, 0x48, 0x60, 0xae, 0x5d, 0xaa, 0xbd, 0x00, - 0x02, 0xc9, 0x8d, 0xf0, 0x06, 0xe8, 0x8e, 0x5d, - 0xaa, 0xc9, 0xac, 0x60, 0x20, 0x93, 0xa1, 0xf0, - 0xfa, 0xc9, 0xa0, 0xf0, 0xf7, 0x60, 0xa9, 0x00, - 0xa0, 0x16, 0x99, 0xba, 0xb5, 0x88, 0xd0, 0xfa, - 0x60, 0xa9, 0x00, 0x85, 0x44, 0x85, 0x45, 0x20, - 0xa4, 0xa1, 0x08, 0xc9, 0xa4, 0xf0, 0x3c, 0x28, - 0x4c, 0xce, 0xa1, 0x20, 0xa4, 0xa1, 0xd0, 0x06, - 0xa6, 0x44, 0xa5, 0x45, 0x18, 0x60, 0x38, 0xe9, - 0xb0, 0x30, 0x21, 0xc9, 0x0a, 0xb0, 0x1d, 0x20, - 0xfe, 0xa1, 0x65, 0x44, 0xaa, 0xa9, 0x00, 0x65, - 0x45, 0xa8, 0x20, 0xfe, 0xa1, 0x20, 0xfe, 0xa1, - 0x8a, 0x65, 0x44, 0x85, 0x44, 0x98, 0x65, 0x45, - 0x85, 0x45, 0x90, 0xcf, 0x38, 0x60, 0x06, 0x44, + 0x63, 0xaa, 0xf0, 0x76, 0x8d, 0x63, 0xaa, 0x8e, + 0x5d, 0xaa, 0xd0, 0xdc, 0xa2, 0x0a, 0xdd, 0x40, + 0xa9, 0xf0, 0x05, 0xca, 0xd0, 0xf8, 0xf0, 0xb6, + 0xbd, 0x4a, 0xa9, 0x30, 0x47, 0x0d, 0x65, 0xaa, + 0x8d, 0x65, 0xaa, 0xca, 0x8e, 0x64, 0xaa, 0x20, + 0xb9, 0xa1, 0xb0, 0xa2, 0xad, 0x64, 0xaa, 0x0a, + 0x0a, 0xa8, 0xa5, 0x45, 0xd0, 0x09, 0xa5, 0x44, + 0xd9, 0x55, 0xa9, 0x90, 0x8c, 0xa5, 0x45, 0xd9, + 0x58, 0xa9, 0x90, 0x0b, 0xd0, 0x83, 0xa5, 0x44, + 0xd9, 0x57, 0xa9, 0x90, 0x02, 0xd0, 0xf5, 0xad, + 0x63, 0xaa, 0xd0, 0x94, 0x98, 0x4a, 0xa8, 0xa5, + 0x45, 0x99, 0x67, 0xaa, 0xa5, 0x44, 0x99, 0x66, + 0xaa, 0x4c, 0xe8, 0xa0, 0x48, 0xa9, 0x80, 0x0d, + 0x65, 0xaa, 0x8d, 0x65, 0xaa, 0x68, 0x29, 0x7f, + 0x0d, 0x74, 0xaa, 0x8d, 0x74, 0xaa, 0xd0, 0xe9, + 0xf0, 0x9c, 0x20, 0x80, 0xa1, 0x4c, 0x83, 0x9f, + 0x20, 0x5b, 0xa7, 0x20, 0xae, 0xa1, 0xad, 0x5f, + 0xaa, 0xaa, 0xbd, 0x1f, 0x9d, 0x48, 0xbd, 0x1e, + 0x9d, 0x48, 0x60, 0xae, 0x5d, 0xaa, 0xbd, 0x00, + 0x02, 0xc9, 0x8d, 0xf0, 0x06, 0xe8, 0x8e, 0x5d, + 0xaa, 0xc9, 0xac, 0x60, 0x20, 0x93, 0xa1, 0xf0, + 0xfa, 0xc9, 0xa0, 0xf0, 0xf7, 0x60, 0xa9, 0x00, + 0xa0, 0x16, 0x99, 0xba, 0xb5, 0x88, 0xd0, 0xfa, + 0x60, 0xa9, 0x00, 0x85, 0x44, 0x85, 0x45, 0x20, + 0xa4, 0xa1, 0x08, 0xc9, 0xa4, 0xf0, 0x3c, 0x28, + 0x4c, 0xce, 0xa1, 0x20, 0xa4, 0xa1, 0xd0, 0x06, + 0xa6, 0x44, 0xa5, 0x45, 0x18, 0x60, 0x38, 0xe9, + 0xb0, 0x30, 0x21, 0xc9, 0x0a, 0xb0, 0x1d, 0x20, + 0xfe, 0xa1, 0x65, 0x44, 0xaa, 0xa9, 0x00, 0x65, + 0x45, 0xa8, 0x20, 0xfe, 0xa1, 0x20, 0xfe, 0xa1, + 0x8a, 0x65, 0x44, 0x85, 0x44, 0x98, 0x65, 0x45, + 0x85, 0x45, 0x90, 0xcf, 0x38, 0x60, 0x06, 0x44, - 0x26, 0x45, 0x60, 0x28, 0x20, 0xa4, 0xa1, 0xf0, - 0xc5, 0x38, 0xe9, 0xb0, 0x30, 0xee, 0xc9, 0x0a, - 0x90, 0x08, 0xe9, 0x07, 0x30, 0xe6, 0xc9, 0x10, - 0xb0, 0xe2, 0xa2, 0x04, 0x20, 0xfe, 0xa1, 0xca, - 0xd0, 0xfa, 0x05, 0x44, 0x85, 0x44, 0x4c, 0x04, - 0xa2, 0xa5, 0x44, 0x4c, 0x95, 0xfe, 0xa5, 0x44, - 0x4c, 0x8b, 0xfe, 0xad, 0x5e, 0xaa, 0x0d, 0x74, - 0xaa, 0x8d, 0x5e, 0xaa, 0x60, 0x2c, 0x74, 0xaa, - 0x50, 0x03, 0x20, 0xc8, 0x9f, 0xa9, 0x70, 0x4d, - 0x74, 0xaa, 0x2d, 0x5e, 0xaa, 0x8d, 0x5e, 0xaa, - 0x60, 0xa9, 0x00, 0x8d, 0xb3, 0xaa, 0xa5, 0x44, - 0x48, 0x20, 0x16, 0xa3, 0x68, 0x8d, 0x57, 0xaa, - 0x4c, 0xd4, 0xa7, 0xa9, 0x05, 0x20, 0xaa, 0xa2, - 0x20, 0x64, 0xa7, 0xa0, 0x00, 0x98, 0x91, 0x40, - 0x60, 0xa9, 0x07, 0xd0, 0x02, 0xa9, 0x08, 0x20, - 0xaa, 0xa2, 0x4c, 0xea, 0xa2, 0xa9, 0x0c, 0xd0, - 0xf6, 0xad, 0x08, 0x9d, 0x8d, 0xbd, 0xb5, 0xad, - 0x09, 0x9d, 0x8d, 0xbe, 0xb5, 0xa9, 0x09, 0x8d, - 0x63, 0xaa, 0x20, 0xc8, 0xa2, 0x4c, 0xea, 0xa2, - 0x20, 0xa3, 0xa2, 0x20, 0x8c, 0xa6, 0xd0, 0xfb, - 0x4c, 0x71, 0xb6, 0xa9, 0x00, 0x4c, 0xd5, 0xa3, - 0xa9, 0x01, 0x8d, 0x63, 0xaa, 0xad, 0x6c, 0xaa, - 0xd0, 0x0a, 0xad, 0x6d, 0xaa, 0xd0, 0x05, 0xa9, - 0x01, 0x8d, 0x6c, 0xaa, 0xad, 0x6c, 0xaa, 0x8d, - 0xbd, 0xb5, 0xad, 0x6d, 0xaa, 0x8d, 0xbe, 0xb5, - 0x20, 0xea, 0xa2, 0xa5, 0x45, 0xd0, 0x03, 0x4c, - 0xc8, 0xa6, 0x85, 0x41, 0xa5, 0x44, 0x85, 0x40, - 0x20, 0x43, 0xa7, 0x20, 0x4e, 0xa7, 0x20, 0x1a, - 0xa7, 0xad, 0x63, 0xaa, 0x8d, 0xbb, 0xb5, 0x4c, - 0xa8, 0xa6, 0xad, 0x75, 0xaa, 0xc9, 0xa0, 0xf0, - 0x25, 0x20, 0x64, 0xa7, 0xb0, 0x3a, 0x20, 0xfc, - 0xa2, 0x4c, 0xea, 0xa2, 0x20, 0xaf, 0xa7, 0xd0, + 0x26, 0x45, 0x60, 0x28, 0x20, 0xa4, 0xa1, 0xf0, + 0xc5, 0x38, 0xe9, 0xb0, 0x30, 0xee, 0xc9, 0x0a, + 0x90, 0x08, 0xe9, 0x07, 0x30, 0xe6, 0xc9, 0x10, + 0xb0, 0xe2, 0xa2, 0x04, 0x20, 0xfe, 0xa1, 0xca, + 0xd0, 0xfa, 0x05, 0x44, 0x85, 0x44, 0x4c, 0x04, + 0xa2, 0xa5, 0x44, 0x4c, 0x95, 0xfe, 0xa5, 0x44, + 0x4c, 0x8b, 0xfe, 0xad, 0x5e, 0xaa, 0x0d, 0x74, + 0xaa, 0x8d, 0x5e, 0xaa, 0x60, 0x2c, 0x74, 0xaa, + 0x50, 0x03, 0x20, 0xc8, 0x9f, 0xa9, 0x70, 0x4d, + 0x74, 0xaa, 0x2d, 0x5e, 0xaa, 0x8d, 0x5e, 0xaa, + 0x60, 0xa9, 0x00, 0x8d, 0xb3, 0xaa, 0xa5, 0x44, + 0x48, 0x20, 0x16, 0xa3, 0x68, 0x8d, 0x57, 0xaa, + 0x4c, 0xd4, 0xa7, 0xa9, 0x05, 0x20, 0xaa, 0xa2, + 0x20, 0x64, 0xa7, 0xa0, 0x00, 0x98, 0x91, 0x40, + 0x60, 0xa9, 0x07, 0xd0, 0x02, 0xa9, 0x08, 0x20, + 0xaa, 0xa2, 0x4c, 0xea, 0xa2, 0xa9, 0x0c, 0xd0, + 0xf6, 0xad, 0x08, 0x9d, 0x8d, 0xbd, 0xb5, 0xad, + 0x09, 0x9d, 0x8d, 0xbe, 0xb5, 0xa9, 0x09, 0x8d, + 0x63, 0xaa, 0x20, 0xc8, 0xa2, 0x4c, 0xea, 0xa2, + 0x20, 0xa3, 0xa2, 0x20, 0x8c, 0xa6, 0xd0, 0xfb, + 0x4c, 0x71, 0xb6, 0xa9, 0x00, 0x4c, 0xd5, 0xa3, + 0xa9, 0x01, 0x8d, 0x63, 0xaa, 0xad, 0x6c, 0xaa, + 0xd0, 0x0a, 0xad, 0x6d, 0xaa, 0xd0, 0x05, 0xa9, + 0x01, 0x8d, 0x6c, 0xaa, 0xad, 0x6c, 0xaa, 0x8d, + 0xbd, 0xb5, 0xad, 0x6d, 0xaa, 0x8d, 0xbe, 0xb5, + 0x20, 0xea, 0xa2, 0xa5, 0x45, 0xd0, 0x03, 0x4c, + 0xc8, 0xa6, 0x85, 0x41, 0xa5, 0x44, 0x85, 0x40, + 0x20, 0x43, 0xa7, 0x20, 0x4e, 0xa7, 0x20, 0x1a, + 0xa7, 0xad, 0x63, 0xaa, 0x8d, 0xbb, 0xb5, 0x4c, + 0xa8, 0xa6, 0xad, 0x75, 0xaa, 0xc9, 0xa0, 0xf0, + 0x25, 0x20, 0x64, 0xa7, 0xb0, 0x3a, 0x20, 0xfc, + 0xa2, 0x4c, 0xea, 0xa2, 0x20, 0xaf, 0xa7, 0xd0, - 0x05, 0xa9, 0x00, 0x8d, 0xb3, 0xaa, 0xa0, 0x00, - 0x98, 0x91, 0x40, 0x20, 0x4e, 0xa7, 0xa9, 0x02, - 0x8d, 0xbb, 0xb5, 0x4c, 0xa8, 0xa6, 0x20, 0x92, - 0xa7, 0xd0, 0x05, 0x20, 0x9a, 0xa7, 0xf0, 0x10, - 0x20, 0xaf, 0xa7, 0xf0, 0xf6, 0x20, 0xaa, 0xa7, - 0xf0, 0xf1, 0x20, 0xfc, 0xa2, 0x4c, 0x16, 0xa3, - 0x60, 0xa9, 0x09, 0x2d, 0x65, 0xaa, 0xc9, 0x09, - 0xf0, 0x03, 0x4c, 0x00, 0xa0, 0xa9, 0x04, 0x20, - 0xd5, 0xa3, 0xad, 0x73, 0xaa, 0xac, 0x72, 0xaa, - 0x20, 0xe0, 0xa3, 0xad, 0x6d, 0xaa, 0xac, 0x6c, - 0xaa, 0x20, 0xe0, 0xa3, 0xad, 0x73, 0xaa, 0xac, - 0x72, 0xaa, 0x4c, 0xff, 0xa3, 0x20, 0xa8, 0xa2, - 0xa9, 0x7f, 0x2d, 0xc2, 0xb5, 0xc9, 0x04, 0xf0, - 0x03, 0x4c, 0xd0, 0xa6, 0xa9, 0x04, 0x20, 0xd5, - 0xa3, 0x20, 0x7a, 0xa4, 0xaa, 0xad, 0x65, 0xaa, - 0x29, 0x01, 0xd0, 0x06, 0x8e, 0x72, 0xaa, 0x8c, - 0x73, 0xaa, 0x20, 0x7a, 0xa4, 0xae, 0x72, 0xaa, - 0xac, 0x73, 0xaa, 0x4c, 0x71, 0xa4, 0x20, 0x5d, - 0xa3, 0x20, 0x51, 0xa8, 0x6c, 0x72, 0xaa, 0xad, - 0xb6, 0xaa, 0xf0, 0x20, 0xa5, 0xd6, 0x10, 0x03, - 0x4c, 0xcc, 0xa6, 0xa9, 0x02, 0x20, 0xd5, 0xa3, - 0x38, 0xa5, 0xaf, 0xe5, 0x67, 0xa8, 0xa5, 0xb0, - 0xe5, 0x68, 0x20, 0xe0, 0xa3, 0xa5, 0x68, 0xa4, - 0x67, 0x4c, 0xff, 0xa3, 0xa9, 0x01, 0x20, 0xd5, - 0xa3, 0x38, 0xa5, 0x4c, 0xe5, 0xca, 0xa8, 0xa5, - 0x4d, 0xe5, 0xcb, 0x20, 0xe0, 0xa3, 0xa5, 0xcb, - 0xa4, 0xca, 0x4c, 0xff, 0xa3, 0x8d, 0xc2, 0xb5, - 0x48, 0x20, 0xa8, 0xa2, 0x68, 0x4c, 0xc4, 0xa7, - 0x8c, 0xc1, 0xb5, 0x8c, 0xc3, 0xb5, 0x8d, 0xc2, - 0xb5, 0xa9, 0x04, 0x8d, 0xbb, 0xb5, 0xa9, 0x01, - 0x8d, 0xbc, 0xb5, 0x20, 0xa8, 0xa6, 0xad, 0xc2, - 0xb5, 0x8d, 0xc3, 0xb5, 0x4c, 0xa8, 0xa6, 0x8c, + 0x05, 0xa9, 0x00, 0x8d, 0xb3, 0xaa, 0xa0, 0x00, + 0x98, 0x91, 0x40, 0x20, 0x4e, 0xa7, 0xa9, 0x02, + 0x8d, 0xbb, 0xb5, 0x4c, 0xa8, 0xa6, 0x20, 0x92, + 0xa7, 0xd0, 0x05, 0x20, 0x9a, 0xa7, 0xf0, 0x10, + 0x20, 0xaf, 0xa7, 0xf0, 0xf6, 0x20, 0xaa, 0xa7, + 0xf0, 0xf1, 0x20, 0xfc, 0xa2, 0x4c, 0x16, 0xa3, + 0x60, 0xa9, 0x09, 0x2d, 0x65, 0xaa, 0xc9, 0x09, + 0xf0, 0x03, 0x4c, 0x00, 0xa0, 0xa9, 0x04, 0x20, + 0xd5, 0xa3, 0xad, 0x73, 0xaa, 0xac, 0x72, 0xaa, + 0x20, 0xe0, 0xa3, 0xad, 0x6d, 0xaa, 0xac, 0x6c, + 0xaa, 0x20, 0xe0, 0xa3, 0xad, 0x73, 0xaa, 0xac, + 0x72, 0xaa, 0x4c, 0xff, 0xa3, 0x20, 0xa8, 0xa2, + 0xa9, 0x7f, 0x2d, 0xc2, 0xb5, 0xc9, 0x04, 0xf0, + 0x03, 0x4c, 0xd0, 0xa6, 0xa9, 0x04, 0x20, 0xd5, + 0xa3, 0x20, 0x7a, 0xa4, 0xaa, 0xad, 0x65, 0xaa, + 0x29, 0x01, 0xd0, 0x06, 0x8e, 0x72, 0xaa, 0x8c, + 0x73, 0xaa, 0x20, 0x7a, 0xa4, 0xae, 0x72, 0xaa, + 0xac, 0x73, 0xaa, 0x4c, 0x71, 0xa4, 0x20, 0x5d, + 0xa3, 0x20, 0x51, 0xa8, 0x6c, 0x72, 0xaa, 0xad, + 0xb6, 0xaa, 0xf0, 0x20, 0xa5, 0xd6, 0x10, 0x03, + 0x4c, 0xcc, 0xa6, 0xa9, 0x02, 0x20, 0xd5, 0xa3, + 0x38, 0xa5, 0xaf, 0xe5, 0x67, 0xa8, 0xa5, 0xb0, + 0xe5, 0x68, 0x20, 0xe0, 0xa3, 0xa5, 0x68, 0xa4, + 0x67, 0x4c, 0xff, 0xa3, 0xa9, 0x01, 0x20, 0xd5, + 0xa3, 0x38, 0xa5, 0x4c, 0xe5, 0xca, 0xa8, 0xa5, + 0x4d, 0xe5, 0xcb, 0x20, 0xe0, 0xa3, 0xa5, 0xcb, + 0xa4, 0xca, 0x4c, 0xff, 0xa3, 0x8d, 0xc2, 0xb5, + 0x48, 0x20, 0xa8, 0xa2, 0x68, 0x4c, 0xc4, 0xa7, + 0x8c, 0xc1, 0xb5, 0x8c, 0xc3, 0xb5, 0x8d, 0xc2, + 0xb5, 0xa9, 0x04, 0x8d, 0xbb, 0xb5, 0xa9, 0x01, + 0x8d, 0xbc, 0xb5, 0x20, 0xa8, 0xa6, 0xad, 0xc2, + 0xb5, 0x8d, 0xc3, 0xb5, 0x4c, 0xa8, 0xa6, 0x8c, - 0xc3, 0xb5, 0x8d, 0xc4, 0xb5, 0xa9, 0x02, 0x4c, - 0x86, 0xb6, 0x20, 0xa8, 0xa6, 0x4c, 0xea, 0xa2, - 0x4c, 0xd0, 0xa6, 0x20, 0x16, 0xa3, 0x20, 0xa8, - 0xa2, 0xa9, 0x23, 0x2d, 0xc2, 0xb5, 0xf0, 0xf0, - 0x8d, 0xc2, 0xb5, 0xad, 0xb6, 0xaa, 0xf0, 0x28, - 0xa9, 0x02, 0x20, 0xb1, 0xa4, 0x20, 0x7a, 0xa4, - 0x18, 0x65, 0x67, 0xaa, 0x98, 0x65, 0x68, 0xc5, - 0x74, 0xb0, 0x70, 0x85, 0xb0, 0x85, 0x6a, 0x86, - 0xaf, 0x86, 0x69, 0xa6, 0x67, 0xa4, 0x68, 0x20, - 0x71, 0xa4, 0x20, 0x51, 0xa8, 0x6c, 0x60, 0x9d, - 0xa9, 0x01, 0x20, 0xb1, 0xa4, 0x20, 0x7a, 0xa4, - 0x38, 0xa5, 0x4c, 0xed, 0x60, 0xaa, 0xaa, 0xa5, - 0x4d, 0xed, 0x61, 0xaa, 0x90, 0x45, 0xa8, 0xc4, - 0x4b, 0x90, 0x40, 0xf0, 0x3e, 0x84, 0xcb, 0x86, - 0xca, 0x8e, 0xc3, 0xb5, 0x8c, 0xc4, 0xb5, 0x4c, - 0x0a, 0xa4, 0xad, 0x0a, 0x9d, 0x8d, 0xc3, 0xb5, - 0xad, 0x0b, 0x9d, 0x8d, 0xc4, 0xb5, 0xa9, 0x00, - 0x8d, 0xc2, 0xb5, 0xa9, 0x02, 0x8d, 0xc1, 0xb5, - 0xa9, 0x03, 0x8d, 0xbb, 0xb5, 0xa9, 0x02, 0x8d, - 0xbc, 0xb5, 0x20, 0xa8, 0xa6, 0xad, 0x61, 0xaa, - 0x8d, 0xc2, 0xb5, 0xa8, 0xad, 0x60, 0xaa, 0x8d, - 0xc1, 0xb5, 0x60, 0x20, 0xea, 0xa2, 0x4c, 0xcc, - 0xa6, 0xcd, 0xc2, 0xb5, 0xf0, 0x1a, 0xae, 0x5f, - 0xaa, 0x8e, 0x62, 0xaa, 0x4a, 0xf0, 0x03, 0x4c, - 0x9e, 0xa5, 0xa2, 0x1d, 0xbd, 0x75, 0xaa, 0x9d, - 0x93, 0xaa, 0xca, 0x10, 0xf7, 0x4c, 0x7a, 0xa5, - 0x60, 0xad, 0xb6, 0xaa, 0xf0, 0x03, 0x8d, 0xb7, - 0xaa, 0x20, 0x13, 0xa4, 0x20, 0xc8, 0x9f, 0x20, - 0x51, 0xa8, 0x6c, 0x58, 0x9d, 0xa5, 0x4a, 0x85, - 0xcc, 0xa5, 0x4b, 0x85, 0xcd, 0x6c, 0x56, 0x9d, - 0x20, 0x16, 0xa4, 0x20, 0xc8, 0x9f, 0x20, 0x51, - 0xa8, 0x6c, 0x56, 0x9d, 0x20, 0x65, 0xd6, 0x85, + 0xc3, 0xb5, 0x8d, 0xc4, 0xb5, 0xa9, 0x02, 0x4c, + 0x86, 0xb6, 0x20, 0xa8, 0xa6, 0x4c, 0xea, 0xa2, + 0x4c, 0xd0, 0xa6, 0x20, 0x16, 0xa3, 0x20, 0xa8, + 0xa2, 0xa9, 0x23, 0x2d, 0xc2, 0xb5, 0xf0, 0xf0, + 0x8d, 0xc2, 0xb5, 0xad, 0xb6, 0xaa, 0xf0, 0x28, + 0xa9, 0x02, 0x20, 0xb1, 0xa4, 0x20, 0x7a, 0xa4, + 0x18, 0x65, 0x67, 0xaa, 0x98, 0x65, 0x68, 0xc5, + 0x74, 0xb0, 0x70, 0x85, 0xb0, 0x85, 0x6a, 0x86, + 0xaf, 0x86, 0x69, 0xa6, 0x67, 0xa4, 0x68, 0x20, + 0x71, 0xa4, 0x20, 0x51, 0xa8, 0x6c, 0x60, 0x9d, + 0xa9, 0x01, 0x20, 0xb1, 0xa4, 0x20, 0x7a, 0xa4, + 0x38, 0xa5, 0x4c, 0xed, 0x60, 0xaa, 0xaa, 0xa5, + 0x4d, 0xed, 0x61, 0xaa, 0x90, 0x45, 0xa8, 0xc4, + 0x4b, 0x90, 0x40, 0xf0, 0x3e, 0x84, 0xcb, 0x86, + 0xca, 0x8e, 0xc3, 0xb5, 0x8c, 0xc4, 0xb5, 0x4c, + 0x0a, 0xa4, 0xad, 0x0a, 0x9d, 0x8d, 0xc3, 0xb5, + 0xad, 0x0b, 0x9d, 0x8d, 0xc4, 0xb5, 0xa9, 0x00, + 0x8d, 0xc2, 0xb5, 0xa9, 0x02, 0x8d, 0xc1, 0xb5, + 0xa9, 0x03, 0x8d, 0xbb, 0xb5, 0xa9, 0x02, 0x8d, + 0xbc, 0xb5, 0x20, 0xa8, 0xa6, 0xad, 0x61, 0xaa, + 0x8d, 0xc2, 0xb5, 0xa8, 0xad, 0x60, 0xaa, 0x8d, + 0xc1, 0xb5, 0x60, 0x20, 0xea, 0xa2, 0x4c, 0xcc, + 0xa6, 0xcd, 0xc2, 0xb5, 0xf0, 0x1a, 0xae, 0x5f, + 0xaa, 0x8e, 0x62, 0xaa, 0x4a, 0xf0, 0x03, 0x4c, + 0x9e, 0xa5, 0xa2, 0x1d, 0xbd, 0x75, 0xaa, 0x9d, + 0x93, 0xaa, 0xca, 0x10, 0xf7, 0x4c, 0x7a, 0xa5, + 0x60, 0xad, 0xb6, 0xaa, 0xf0, 0x03, 0x8d, 0xb7, + 0xaa, 0x20, 0x13, 0xa4, 0x20, 0xc8, 0x9f, 0x20, + 0x51, 0xa8, 0x6c, 0x58, 0x9d, 0xa5, 0x4a, 0x85, + 0xcc, 0xa5, 0x4b, 0x85, 0xcd, 0x6c, 0x56, 0x9d, + 0x20, 0x16, 0xa4, 0x20, 0xc8, 0x9f, 0x20, 0x51, + 0xa8, 0x6c, 0x56, 0x9d, 0x20, 0x65, 0xd6, 0x85, - 0x33, 0x85, 0xd8, 0x4c, 0xd2, 0xd7, 0x20, 0x65, - 0x0e, 0x85, 0x33, 0x85, 0xd8, 0x4c, 0xd4, 0x0f, - 0x20, 0x26, 0xa5, 0xa9, 0x05, 0x8d, 0x52, 0xaa, - 0x4c, 0x83, 0x9f, 0x20, 0x26, 0xa5, 0xa9, 0x01, - 0x8d, 0x51, 0xaa, 0x4c, 0x83, 0x9f, 0x20, 0x64, - 0xa7, 0x90, 0x06, 0x20, 0xa3, 0xa2, 0x4c, 0x34, - 0xa5, 0x20, 0x4e, 0xa7, 0xad, 0x65, 0xaa, 0x29, - 0x06, 0xf0, 0x13, 0xa2, 0x03, 0xbd, 0x6e, 0xaa, - 0x9d, 0xbd, 0xb5, 0xca, 0x10, 0xf7, 0xa9, 0x0a, - 0x8d, 0xbb, 0xb5, 0x20, 0xa8, 0xa6, 0x60, 0xa9, - 0x40, 0x2d, 0x65, 0xaa, 0xf0, 0x05, 0xad, 0x66, - 0xaa, 0xd0, 0x05, 0xa9, 0xfe, 0x8d, 0x66, 0xaa, - 0xad, 0x0d, 0x9d, 0x8d, 0xbc, 0xb5, 0xa9, 0x0b, - 0x20, 0xaa, 0xa2, 0x4c, 0x97, 0xa3, 0xa9, 0x06, - 0x20, 0xaa, 0xa2, 0xad, 0xbf, 0xb5, 0x8d, 0x66, - 0xaa, 0x60, 0xa9, 0x4c, 0x20, 0xb2, 0xa5, 0xf0, - 0x2e, 0xa9, 0x00, 0x8d, 0xb6, 0xaa, 0xa0, 0x1e, - 0x20, 0x97, 0xa0, 0xa2, 0x09, 0xbd, 0xb7, 0xaa, - 0x9d, 0x74, 0xaa, 0xca, 0xd0, 0xf7, 0xa9, 0xc0, - 0x8d, 0x51, 0xaa, 0x4c, 0xd1, 0xa4, 0xa9, 0x20, - 0x20, 0xb2, 0xa5, 0xf0, 0x05, 0xa9, 0x01, 0x4c, - 0xd2, 0xa6, 0xa9, 0x00, 0x8d, 0xb7, 0xaa, 0x4c, - 0x84, 0x9d, 0xcd, 0x00, 0xe0, 0xf0, 0x0e, 0x8d, - 0x80, 0xc0, 0xcd, 0x00, 0xe0, 0xf0, 0x06, 0x8d, - 0x81, 0xc0, 0xcd, 0x00, 0xe0, 0x60, 0x20, 0xa3, - 0xa2, 0xad, 0x4f, 0xaa, 0x8d, 0xb4, 0xaa, 0xad, - 0x50, 0xaa, 0x8d, 0xb5, 0xaa, 0xad, 0x75, 0xaa, - 0x8d, 0xb3, 0xaa, 0xd0, 0x0e, 0x20, 0x64, 0xa7, - 0x90, 0x06, 0x20, 0xa3, 0xa2, 0x4c, 0xeb, 0xa5, - 0x20, 0x4e, 0xa7, 0xad, 0x65, 0xaa, 0x29, 0x04, - 0xf0, 0x1b, 0xad, 0x6e, 0xaa, 0xd0, 0x08, 0xae, - 0x6f, 0xaa, 0xf0, 0x11, 0xce, 0x6f, 0xaa, 0xce, + 0x33, 0x85, 0xd8, 0x4c, 0xd2, 0xd7, 0x20, 0x65, + 0x0e, 0x85, 0x33, 0x85, 0xd8, 0x4c, 0xd4, 0x0f, + 0x20, 0x26, 0xa5, 0xa9, 0x05, 0x8d, 0x52, 0xaa, + 0x4c, 0x83, 0x9f, 0x20, 0x26, 0xa5, 0xa9, 0x01, + 0x8d, 0x51, 0xaa, 0x4c, 0x83, 0x9f, 0x20, 0x64, + 0xa7, 0x90, 0x06, 0x20, 0xa3, 0xa2, 0x4c, 0x34, + 0xa5, 0x20, 0x4e, 0xa7, 0xad, 0x65, 0xaa, 0x29, + 0x06, 0xf0, 0x13, 0xa2, 0x03, 0xbd, 0x6e, 0xaa, + 0x9d, 0xbd, 0xb5, 0xca, 0x10, 0xf7, 0xa9, 0x0a, + 0x8d, 0xbb, 0xb5, 0x20, 0xa8, 0xa6, 0x60, 0xa9, + 0x40, 0x2d, 0x65, 0xaa, 0xf0, 0x05, 0xad, 0x66, + 0xaa, 0xd0, 0x05, 0xa9, 0xfe, 0x8d, 0x66, 0xaa, + 0xad, 0x0d, 0x9d, 0x8d, 0xbc, 0xb5, 0xa9, 0x0b, + 0x20, 0xaa, 0xa2, 0x4c, 0x97, 0xa3, 0xa9, 0x06, + 0x20, 0xaa, 0xa2, 0xad, 0xbf, 0xb5, 0x8d, 0x66, + 0xaa, 0x60, 0xa9, 0x4c, 0x20, 0xb2, 0xa5, 0xf0, + 0x2e, 0xa9, 0x00, 0x8d, 0xb6, 0xaa, 0xa0, 0x1e, + 0x20, 0x97, 0xa0, 0xa2, 0x09, 0xbd, 0xb7, 0xaa, + 0x9d, 0x74, 0xaa, 0xca, 0xd0, 0xf7, 0xa9, 0xc0, + 0x8d, 0x51, 0xaa, 0x4c, 0xd1, 0xa4, 0xa9, 0x20, + 0x20, 0xb2, 0xa5, 0xf0, 0x05, 0xa9, 0x01, 0x4c, + 0xd2, 0xa6, 0xa9, 0x00, 0x8d, 0xb7, 0xaa, 0x4c, + 0x84, 0x9d, 0xcd, 0x00, 0xe0, 0xf0, 0x0e, 0x8d, + 0x80, 0xc0, 0xcd, 0x00, 0xe0, 0xf0, 0x06, 0x8d, + 0x81, 0xc0, 0xcd, 0x00, 0xe0, 0x60, 0x20, 0xa3, + 0xa2, 0xad, 0x4f, 0xaa, 0x8d, 0xb4, 0xaa, 0xad, + 0x50, 0xaa, 0x8d, 0xb5, 0xaa, 0xad, 0x75, 0xaa, + 0x8d, 0xb3, 0xaa, 0xd0, 0x0e, 0x20, 0x64, 0xa7, + 0x90, 0x06, 0x20, 0xa3, 0xa2, 0x4c, 0xeb, 0xa5, + 0x20, 0x4e, 0xa7, 0xad, 0x65, 0xaa, 0x29, 0x04, + 0xf0, 0x1b, 0xad, 0x6e, 0xaa, 0xd0, 0x08, 0xae, + 0x6f, 0xaa, 0xf0, 0x11, 0xce, 0x6f, 0xaa, 0xce, - 0x6e, 0xaa, 0x20, 0x8c, 0xa6, 0xf0, 0x38, 0xc9, - 0x8d, 0xd0, 0xf7, 0xf0, 0xe5, 0x60, 0x20, 0x5e, - 0xa6, 0xb0, 0x66, 0xad, 0x5c, 0xaa, 0x8d, 0xc3, - 0xb5, 0xa9, 0x04, 0x8d, 0xbb, 0xb5, 0xa9, 0x01, - 0x8d, 0xbc, 0xb5, 0x4c, 0xa8, 0xa6, 0x20, 0x5e, - 0xa6, 0xb0, 0x4e, 0xa9, 0x06, 0x8d, 0x52, 0xaa, - 0x20, 0x8c, 0xa6, 0xd0, 0x0f, 0x20, 0xfc, 0xa2, - 0xa9, 0x03, 0xcd, 0x52, 0xaa, 0xf0, 0xce, 0xa9, - 0x05, 0x4c, 0xd2, 0xa6, 0xc9, 0xe0, 0x90, 0x02, - 0x29, 0x7f, 0x8d, 0x5c, 0xaa, 0xae, 0x5a, 0xaa, - 0xf0, 0x09, 0xca, 0xbd, 0x00, 0x02, 0x09, 0x80, - 0x9d, 0x00, 0x02, 0x4c, 0xb3, 0x9f, 0x48, 0xad, - 0xb6, 0xaa, 0xf0, 0x0e, 0xa6, 0x76, 0xe8, 0xf0, - 0x0d, 0xa6, 0x33, 0xe0, 0xdd, 0xf0, 0x07, 0x68, - 0x18, 0x60, 0xa5, 0xd9, 0x30, 0xf9, 0x68, 0x38, - 0x60, 0x20, 0xfc, 0xa2, 0x20, 0x5b, 0xa7, 0x4c, - 0xb3, 0x9f, 0x20, 0x9d, 0xa6, 0x20, 0x4e, 0xa7, - 0xa9, 0x03, 0xd0, 0xa1, 0xa9, 0x03, 0x8d, 0xbb, - 0xb5, 0xa9, 0x01, 0x8d, 0xbc, 0xb5, 0x20, 0xa8, - 0xa6, 0xad, 0xc3, 0xb5, 0x60, 0xad, 0xb5, 0xaa, - 0x85, 0x41, 0xad, 0xb4, 0xaa, 0x85, 0x40, 0x60, - 0x20, 0x06, 0xab, 0x90, 0x16, 0xad, 0xc5, 0xb5, - 0xc9, 0x05, 0xf0, 0x03, 0x4c, 0x5e, 0xb6, 0x4c, - 0x92, 0xb6, 0xea, 0xea, 0xea, 0xea, 0xa2, 0x00, - 0x8e, 0xc3, 0xb5, 0x60, 0xa9, 0x0b, 0xd0, 0x0a, - 0xa9, 0x0c, 0xd0, 0x06, 0xa9, 0x0e, 0xd0, 0x02, - 0xa9, 0x0d, 0x8d, 0x5c, 0xaa, 0x20, 0xe6, 0xbf, - 0xad, 0xb6, 0xaa, 0xf0, 0x04, 0xa5, 0xd8, 0x30, - 0x0e, 0xa2, 0x00, 0x20, 0x02, 0xa7, 0xae, 0x5c, - 0xaa, 0x20, 0x02, 0xa7, 0x20, 0xc8, 0x9f, 0x20, - 0x51, 0xa8, 0x20, 0x5e, 0xa6, 0xae, 0x5c, 0xaa, - 0xa9, 0x03, 0xb0, 0x03, 0x6c, 0x5a, 0x9d, 0x6c, + 0x6e, 0xaa, 0x20, 0x8c, 0xa6, 0xf0, 0x38, 0xc9, + 0x8d, 0xd0, 0xf7, 0xf0, 0xe5, 0x60, 0x20, 0x5e, + 0xa6, 0xb0, 0x66, 0xad, 0x5c, 0xaa, 0x8d, 0xc3, + 0xb5, 0xa9, 0x04, 0x8d, 0xbb, 0xb5, 0xa9, 0x01, + 0x8d, 0xbc, 0xb5, 0x4c, 0xa8, 0xa6, 0x20, 0x5e, + 0xa6, 0xb0, 0x4e, 0xa9, 0x06, 0x8d, 0x52, 0xaa, + 0x20, 0x8c, 0xa6, 0xd0, 0x0f, 0x20, 0xfc, 0xa2, + 0xa9, 0x03, 0xcd, 0x52, 0xaa, 0xf0, 0xce, 0xa9, + 0x05, 0x4c, 0xd2, 0xa6, 0xc9, 0xe0, 0x90, 0x02, + 0x29, 0x7f, 0x8d, 0x5c, 0xaa, 0xae, 0x5a, 0xaa, + 0xf0, 0x09, 0xca, 0xbd, 0x00, 0x02, 0x09, 0x80, + 0x9d, 0x00, 0x02, 0x4c, 0xb3, 0x9f, 0x48, 0xad, + 0xb6, 0xaa, 0xf0, 0x0e, 0xa6, 0x76, 0xe8, 0xf0, + 0x0d, 0xa6, 0x33, 0xe0, 0xdd, 0xf0, 0x07, 0x68, + 0x18, 0x60, 0xa5, 0xd9, 0x30, 0xf9, 0x68, 0x38, + 0x60, 0x20, 0xfc, 0xa2, 0x20, 0x5b, 0xa7, 0x4c, + 0xb3, 0x9f, 0x20, 0x9d, 0xa6, 0x20, 0x4e, 0xa7, + 0xa9, 0x03, 0xd0, 0xa1, 0xa9, 0x03, 0x8d, 0xbb, + 0xb5, 0xa9, 0x01, 0x8d, 0xbc, 0xb5, 0x20, 0xa8, + 0xa6, 0xad, 0xc3, 0xb5, 0x60, 0xad, 0xb5, 0xaa, + 0x85, 0x41, 0xad, 0xb4, 0xaa, 0x85, 0x40, 0x60, + 0x20, 0x06, 0xab, 0x90, 0x16, 0xad, 0xc5, 0xb5, + 0xc9, 0x05, 0xf0, 0x03, 0x4c, 0x5e, 0xb6, 0x4c, + 0x92, 0xb6, 0xea, 0xea, 0xea, 0xea, 0xa2, 0x00, + 0x8e, 0xc3, 0xb5, 0x60, 0xa9, 0x0b, 0xd0, 0x0a, + 0xa9, 0x0c, 0xd0, 0x06, 0xa9, 0x0e, 0xd0, 0x02, + 0xa9, 0x0d, 0x8d, 0x5c, 0xaa, 0x20, 0xe6, 0xbf, + 0xad, 0xb6, 0xaa, 0xf0, 0x04, 0xa5, 0xd8, 0x30, + 0x0e, 0xa2, 0x00, 0x20, 0x02, 0xa7, 0xae, 0x5c, + 0xaa, 0x20, 0x02, 0xa7, 0x20, 0xc8, 0x9f, 0x20, + 0x51, 0xa8, 0x20, 0x5e, 0xa6, 0xae, 0x5c, 0xaa, + 0xa9, 0x03, 0xb0, 0x03, 0x6c, 0x5a, 0x9d, 0x6c, - 0x5e, 0x9d, 0xbd, 0x3f, 0xaa, 0xaa, 0x8e, 0x63, - 0xaa, 0xbd, 0x71, 0xa9, 0x48, 0x09, 0x80, 0x20, - 0xc5, 0x9f, 0xae, 0x63, 0xaa, 0xe8, 0x68, 0x10, - 0xed, 0x60, 0xad, 0x66, 0xaa, 0x8d, 0xbf, 0xb5, - 0xad, 0x68, 0xaa, 0x8d, 0xc0, 0xb5, 0xad, 0x6a, - 0xaa, 0x8d, 0xc1, 0xb5, 0xad, 0x06, 0x9d, 0x8d, - 0xc3, 0xb5, 0xad, 0x07, 0x9d, 0x8d, 0xc4, 0xb5, - 0xa5, 0x40, 0x8d, 0x4f, 0xaa, 0xa5, 0x41, 0x8d, - 0x50, 0xaa, 0x60, 0xa0, 0x1d, 0xb9, 0x75, 0xaa, - 0x91, 0x40, 0x88, 0x10, 0xf8, 0x60, 0xa0, 0x1e, - 0xb1, 0x40, 0x99, 0xa9, 0xb5, 0xc8, 0xc0, 0x26, - 0xd0, 0xf6, 0x60, 0xa0, 0x00, 0x8c, 0x51, 0xaa, - 0x8c, 0x52, 0xaa, 0x60, 0xa9, 0x00, 0x85, 0x45, - 0x20, 0x92, 0xa7, 0x4c, 0x73, 0xa7, 0x20, 0x9a, - 0xa7, 0xf0, 0x1d, 0x20, 0xaa, 0xa7, 0xd0, 0x0a, - 0xa5, 0x40, 0x85, 0x44, 0xa5, 0x41, 0x85, 0x45, - 0xd0, 0xec, 0xa0, 0x1d, 0xb1, 0x40, 0xd9, 0x75, - 0xaa, 0xd0, 0xe3, 0x88, 0x10, 0xf6, 0x18, 0x60, - 0x38, 0x60, 0xad, 0x00, 0x9d, 0xae, 0x01, 0x9d, - 0xd0, 0x0a, 0xa0, 0x25, 0xb1, 0x40, 0xf0, 0x09, - 0xaa, 0x88, 0xb1, 0x40, 0x86, 0x41, 0x85, 0x40, - 0x8a, 0x60, 0xa0, 0x00, 0xb1, 0x40, 0x60, 0xad, - 0xb3, 0xaa, 0xf0, 0x0e, 0xad, 0xb4, 0xaa, 0xc5, - 0x40, 0xd0, 0x08, 0xad, 0xb5, 0xaa, 0xc5, 0x41, - 0xf0, 0x01, 0xca, 0x60, 0x4d, 0xc2, 0xb5, 0xf0, - 0x0a, 0x29, 0x7f, 0xf0, 0x06, 0x20, 0xea, 0xa2, - 0x4c, 0xd0, 0xa6, 0x60, 0x38, 0xad, 0x00, 0x9d, - 0x85, 0x40, 0xad, 0x01, 0x9d, 0x85, 0x41, 0xad, - 0x57, 0xaa, 0x8d, 0x63, 0xaa, 0xa0, 0x00, 0x98, - 0x91, 0x40, 0xa0, 0x1e, 0x38, 0xa5, 0x40, 0xe9, - 0x2d, 0x91, 0x40, 0x48, 0xa5, 0x41, 0xe9, 0x00, - 0xc8, 0x91, 0x40, 0xaa, 0xca, 0x68, 0x48, 0xc8, + 0x5e, 0x9d, 0xbd, 0x3f, 0xaa, 0xaa, 0x8e, 0x63, + 0xaa, 0xbd, 0x71, 0xa9, 0x48, 0x09, 0x80, 0x20, + 0xc5, 0x9f, 0xae, 0x63, 0xaa, 0xe8, 0x68, 0x10, + 0xed, 0x60, 0xad, 0x66, 0xaa, 0x8d, 0xbf, 0xb5, + 0xad, 0x68, 0xaa, 0x8d, 0xc0, 0xb5, 0xad, 0x6a, + 0xaa, 0x8d, 0xc1, 0xb5, 0xad, 0x06, 0x9d, 0x8d, + 0xc3, 0xb5, 0xad, 0x07, 0x9d, 0x8d, 0xc4, 0xb5, + 0xa5, 0x40, 0x8d, 0x4f, 0xaa, 0xa5, 0x41, 0x8d, + 0x50, 0xaa, 0x60, 0xa0, 0x1d, 0xb9, 0x75, 0xaa, + 0x91, 0x40, 0x88, 0x10, 0xf8, 0x60, 0xa0, 0x1e, + 0xb1, 0x40, 0x99, 0xa9, 0xb5, 0xc8, 0xc0, 0x26, + 0xd0, 0xf6, 0x60, 0xa0, 0x00, 0x8c, 0x51, 0xaa, + 0x8c, 0x52, 0xaa, 0x60, 0xa9, 0x00, 0x85, 0x45, + 0x20, 0x92, 0xa7, 0x4c, 0x73, 0xa7, 0x20, 0x9a, + 0xa7, 0xf0, 0x1d, 0x20, 0xaa, 0xa7, 0xd0, 0x0a, + 0xa5, 0x40, 0x85, 0x44, 0xa5, 0x41, 0x85, 0x45, + 0xd0, 0xec, 0xa0, 0x1d, 0xb1, 0x40, 0xd9, 0x75, + 0xaa, 0xd0, 0xe3, 0x88, 0x10, 0xf6, 0x18, 0x60, + 0x38, 0x60, 0xad, 0x00, 0x9d, 0xae, 0x01, 0x9d, + 0xd0, 0x0a, 0xa0, 0x25, 0xb1, 0x40, 0xf0, 0x09, + 0xaa, 0x88, 0xb1, 0x40, 0x86, 0x41, 0x85, 0x40, + 0x8a, 0x60, 0xa0, 0x00, 0xb1, 0x40, 0x60, 0xad, + 0xb3, 0xaa, 0xf0, 0x0e, 0xad, 0xb4, 0xaa, 0xc5, + 0x40, 0xd0, 0x08, 0xad, 0xb5, 0xaa, 0xc5, 0x41, + 0xf0, 0x01, 0xca, 0x60, 0x4d, 0xc2, 0xb5, 0xf0, + 0x0a, 0x29, 0x7f, 0xf0, 0x06, 0x20, 0xea, 0xa2, + 0x4c, 0xd0, 0xa6, 0x60, 0x38, 0xad, 0x00, 0x9d, + 0x85, 0x40, 0xad, 0x01, 0x9d, 0x85, 0x41, 0xad, + 0x57, 0xaa, 0x8d, 0x63, 0xaa, 0xa0, 0x00, 0x98, + 0x91, 0x40, 0xa0, 0x1e, 0x38, 0xa5, 0x40, 0xe9, + 0x2d, 0x91, 0x40, 0x48, 0xa5, 0x41, 0xe9, 0x00, + 0xc8, 0x91, 0x40, 0xaa, 0xca, 0x68, 0x48, 0xc8, - 0x91, 0x40, 0x8a, 0xc8, 0x91, 0x40, 0xaa, 0xca, - 0x68, 0x48, 0xc8, 0x91, 0x40, 0xc8, 0x8a, 0x91, - 0x40, 0xce, 0x63, 0xaa, 0xf0, 0x17, 0xaa, 0x68, - 0x38, 0xe9, 0x26, 0xc8, 0x91, 0x40, 0x48, 0x8a, - 0xe9, 0x00, 0xc8, 0x91, 0x40, 0x85, 0x41, 0x68, - 0x85, 0x40, 0x4c, 0xe5, 0xa7, 0x48, 0xa9, 0x00, - 0xc8, 0x91, 0x40, 0xc8, 0x91, 0x40, 0xad, 0xb6, - 0xaa, 0xf0, 0x0b, 0x68, 0x85, 0x74, 0x85, 0x70, - 0x68, 0x85, 0x73, 0x85, 0x6f, 0x60, 0x68, 0x85, - 0x4d, 0x85, 0xcb, 0x68, 0x85, 0x4c, 0x85, 0xca, - 0x60, 0xa5, 0x39, 0xcd, 0x03, 0x9d, 0xf0, 0x12, - 0x8d, 0x56, 0xaa, 0xa5, 0x38, 0x8d, 0x55, 0xaa, - 0xad, 0x02, 0x9d, 0x85, 0x38, 0xad, 0x03, 0x9d, - 0x85, 0x39, 0xa5, 0x37, 0xcd, 0x05, 0x9d, 0xf0, - 0x12, 0x8d, 0x54, 0xaa, 0xa5, 0x36, 0x8d, 0x53, - 0xaa, 0xad, 0x04, 0x9d, 0x85, 0x36, 0xad, 0x05, - 0x9d, 0x85, 0x37, 0x60, 0x49, 0x4e, 0x49, 0xd4, - 0x4c, 0x4f, 0x41, 0xc4, 0x53, 0x41, 0x56, 0xc5, - 0x52, 0x55, 0xce, 0x43, 0x48, 0x41, 0x49, 0xce, - 0x44, 0x45, 0x4c, 0x45, 0x54, 0xc5, 0x4c, 0x4f, - 0x43, 0xcb, 0x55, 0x4e, 0x4c, 0x4f, 0x43, 0xcb, - 0x43, 0x4c, 0x4f, 0x53, 0xc5, 0x52, 0x45, 0x41, - 0xc4, 0x45, 0x58, 0x45, 0xc3, 0x57, 0x52, 0x49, - 0x54, 0xc5, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, - 0x4f, 0xce, 0x4f, 0x50, 0x45, 0xce, 0x41, 0x50, - 0x50, 0x45, 0x4e, 0xc4, 0x52, 0x45, 0x4e, 0x41, - 0x4d, 0xc5, 0x43, 0x41, 0x54, 0x41, 0x4c, 0x4f, - 0xc7, 0x4d, 0x4f, 0xce, 0x4e, 0x4f, 0x4d, 0x4f, - 0xce, 0x50, 0x52, 0xa3, 0x49, 0x4e, 0xa3, 0x4d, - 0x41, 0x58, 0x46, 0x49, 0x4c, 0x45, 0xd3, 0x46, - 0xd0, 0x49, 0x4e, 0xd4, 0x42, 0x53, 0x41, 0x56, - 0xc5, 0x42, 0x4c, 0x4f, 0x41, 0xc4, 0x42, 0x52, + 0x91, 0x40, 0x8a, 0xc8, 0x91, 0x40, 0xaa, 0xca, + 0x68, 0x48, 0xc8, 0x91, 0x40, 0xc8, 0x8a, 0x91, + 0x40, 0xce, 0x63, 0xaa, 0xf0, 0x17, 0xaa, 0x68, + 0x38, 0xe9, 0x26, 0xc8, 0x91, 0x40, 0x48, 0x8a, + 0xe9, 0x00, 0xc8, 0x91, 0x40, 0x85, 0x41, 0x68, + 0x85, 0x40, 0x4c, 0xe5, 0xa7, 0x48, 0xa9, 0x00, + 0xc8, 0x91, 0x40, 0xc8, 0x91, 0x40, 0xad, 0xb6, + 0xaa, 0xf0, 0x0b, 0x68, 0x85, 0x74, 0x85, 0x70, + 0x68, 0x85, 0x73, 0x85, 0x6f, 0x60, 0x68, 0x85, + 0x4d, 0x85, 0xcb, 0x68, 0x85, 0x4c, 0x85, 0xca, + 0x60, 0xa5, 0x39, 0xcd, 0x03, 0x9d, 0xf0, 0x12, + 0x8d, 0x56, 0xaa, 0xa5, 0x38, 0x8d, 0x55, 0xaa, + 0xad, 0x02, 0x9d, 0x85, 0x38, 0xad, 0x03, 0x9d, + 0x85, 0x39, 0xa5, 0x37, 0xcd, 0x05, 0x9d, 0xf0, + 0x12, 0x8d, 0x54, 0xaa, 0xa5, 0x36, 0x8d, 0x53, + 0xaa, 0xad, 0x04, 0x9d, 0x85, 0x36, 0xad, 0x05, + 0x9d, 0x85, 0x37, 0x60, 0x49, 0x4e, 0x49, 0xd4, + 0x4c, 0x4f, 0x41, 0xc4, 0x53, 0x41, 0x56, 0xc5, + 0x52, 0x55, 0xce, 0x43, 0x48, 0x41, 0x49, 0xce, + 0x44, 0x45, 0x4c, 0x45, 0x54, 0xc5, 0x4c, 0x4f, + 0x43, 0xcb, 0x55, 0x4e, 0x4c, 0x4f, 0x43, 0xcb, + 0x43, 0x4c, 0x4f, 0x53, 0xc5, 0x52, 0x45, 0x41, + 0xc4, 0x45, 0x58, 0x45, 0xc3, 0x57, 0x52, 0x49, + 0x54, 0xc5, 0x50, 0x4f, 0x53, 0x49, 0x54, 0x49, + 0x4f, 0xce, 0x4f, 0x50, 0x45, 0xce, 0x41, 0x50, + 0x50, 0x45, 0x4e, 0xc4, 0x52, 0x45, 0x4e, 0x41, + 0x4d, 0xc5, 0x43, 0x41, 0x54, 0x41, 0x4c, 0x4f, + 0xc7, 0x4d, 0x4f, 0xce, 0x4e, 0x4f, 0x4d, 0x4f, + 0xce, 0x50, 0x52, 0xa3, 0x49, 0x4e, 0xa3, 0x4d, + 0x41, 0x58, 0x46, 0x49, 0x4c, 0x45, 0xd3, 0x46, + 0xd0, 0x49, 0x4e, 0xd4, 0x42, 0x53, 0x41, 0x56, + 0xc5, 0x42, 0x4c, 0x4f, 0x41, 0xc4, 0x42, 0x52, - 0x55, 0xce, 0x56, 0x45, 0x52, 0x49, 0x46, 0xd9, - 0x00, 0x21, 0x70, 0xa0, 0x70, 0xa1, 0x70, 0xa0, - 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, - 0x70, 0x60, 0x00, 0x22, 0x06, 0x20, 0x74, 0x22, - 0x06, 0x22, 0x04, 0x23, 0x78, 0x22, 0x70, 0x30, - 0x70, 0x40, 0x70, 0x40, 0x80, 0x40, 0x80, 0x08, - 0x00, 0x08, 0x00, 0x04, 0x00, 0x40, 0x70, 0x40, - 0x00, 0x21, 0x79, 0x20, 0x71, 0x20, 0x71, 0x20, - 0x70, 0xd6, 0xc4, 0xd3, 0xcc, 0xd2, 0xc2, 0xc1, - 0xc3, 0xc9, 0xcf, 0x40, 0x20, 0x10, 0x08, 0x04, - 0x02, 0x01, 0xc0, 0xa0, 0x90, 0x00, 0x00, 0xfe, - 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x07, - 0x00, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x00, 0xff, - 0x7f, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0xff, - 0xff, 0x0d, 0x07, 0x8d, 0x4c, 0x41, 0x4e, 0x47, - 0x55, 0x41, 0x47, 0x45, 0x20, 0x4e, 0x4f, 0x54, - 0x20, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, - 0x4c, 0xc5, 0x52, 0x41, 0x4e, 0x47, 0x45, 0x20, - 0x45, 0x52, 0x52, 0x4f, 0xd2, 0x57, 0x52, 0x49, - 0x54, 0x45, 0x20, 0x50, 0x52, 0x4f, 0x54, 0x45, - 0x43, 0x54, 0x45, 0xc4, 0x45, 0x4e, 0x44, 0x20, - 0x4f, 0x46, 0x20, 0x44, 0x41, 0x54, 0xc1, 0x46, - 0x49, 0x4c, 0x45, 0x20, 0x4e, 0x4f, 0x54, 0x20, - 0x46, 0x4f, 0x55, 0x4e, 0xc4, 0x56, 0x4f, 0x4c, - 0x55, 0x4d, 0x45, 0x20, 0x4d, 0x49, 0x53, 0x4d, - 0x41, 0x54, 0x43, 0xc8, 0x49, 0x2f, 0x4f, 0x20, - 0x45, 0x52, 0x52, 0x4f, 0xd2, 0x44, 0x49, 0x53, - 0x4b, 0x20, 0x46, 0x55, 0x4c, 0xcc, 0x46, 0x49, - 0x4c, 0x45, 0x20, 0x4c, 0x4f, 0x43, 0x4b, 0x45, - 0xc4, 0x53, 0x59, 0x4e, 0x54, 0x41, 0x58, 0x20, - 0x45, 0x52, 0x52, 0x4f, 0xd2, 0x4e, 0x4f, 0x20, - 0x42, 0x55, 0x46, 0x46, 0x45, 0x52, 0x53, 0x20, + 0x55, 0xce, 0x56, 0x45, 0x52, 0x49, 0x46, 0xd9, + 0x00, 0x21, 0x70, 0xa0, 0x70, 0xa1, 0x70, 0xa0, + 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, 0x70, 0x20, + 0x70, 0x60, 0x00, 0x22, 0x06, 0x20, 0x74, 0x22, + 0x06, 0x22, 0x04, 0x23, 0x78, 0x22, 0x70, 0x30, + 0x70, 0x40, 0x70, 0x40, 0x80, 0x40, 0x80, 0x08, + 0x00, 0x08, 0x00, 0x04, 0x00, 0x40, 0x70, 0x40, + 0x00, 0x21, 0x79, 0x20, 0x71, 0x20, 0x71, 0x20, + 0x70, 0xd6, 0xc4, 0xd3, 0xcc, 0xd2, 0xc2, 0xc1, + 0xc3, 0xc9, 0xcf, 0x40, 0x20, 0x10, 0x08, 0x04, + 0x02, 0x01, 0xc0, 0xa0, 0x90, 0x00, 0x00, 0xfe, + 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x07, + 0x00, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x00, 0xff, + 0x7f, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0xff, + 0xff, 0x0d, 0x07, 0x8d, 0x4c, 0x41, 0x4e, 0x47, + 0x55, 0x41, 0x47, 0x45, 0x20, 0x4e, 0x4f, 0x54, + 0x20, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, + 0x4c, 0xc5, 0x52, 0x41, 0x4e, 0x47, 0x45, 0x20, + 0x45, 0x52, 0x52, 0x4f, 0xd2, 0x57, 0x52, 0x49, + 0x54, 0x45, 0x20, 0x50, 0x52, 0x4f, 0x54, 0x45, + 0x43, 0x54, 0x45, 0xc4, 0x45, 0x4e, 0x44, 0x20, + 0x4f, 0x46, 0x20, 0x44, 0x41, 0x54, 0xc1, 0x46, + 0x49, 0x4c, 0x45, 0x20, 0x4e, 0x4f, 0x54, 0x20, + 0x46, 0x4f, 0x55, 0x4e, 0xc4, 0x56, 0x4f, 0x4c, + 0x55, 0x4d, 0x45, 0x20, 0x4d, 0x49, 0x53, 0x4d, + 0x41, 0x54, 0x43, 0xc8, 0x49, 0x2f, 0x4f, 0x20, + 0x45, 0x52, 0x52, 0x4f, 0xd2, 0x44, 0x49, 0x53, + 0x4b, 0x20, 0x46, 0x55, 0x4c, 0xcc, 0x46, 0x49, + 0x4c, 0x45, 0x20, 0x4c, 0x4f, 0x43, 0x4b, 0x45, + 0xc4, 0x53, 0x59, 0x4e, 0x54, 0x41, 0x58, 0x20, + 0x45, 0x52, 0x52, 0x4f, 0xd2, 0x4e, 0x4f, 0x20, + 0x42, 0x55, 0x46, 0x46, 0x45, 0x52, 0x53, 0x20, - 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, - 0xc5, 0x46, 0x49, 0x4c, 0x45, 0x20, 0x54, 0x59, - 0x50, 0x45, 0x20, 0x4d, 0x49, 0x53, 0x4d, 0x41, - 0x54, 0x43, 0xc8, 0x50, 0x52, 0x4f, 0x47, 0x52, - 0x41, 0x4d, 0x20, 0x54, 0x4f, 0x4f, 0x20, 0x4c, - 0x41, 0x52, 0x47, 0xc5, 0x4e, 0x4f, 0x54, 0x20, - 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x20, 0x43, - 0x4f, 0x4d, 0x4d, 0x41, 0x4e, 0xc4, 0x8d, 0x00, - 0x03, 0x19, 0x19, 0x24, 0x33, 0x3e, 0x4c, 0x5b, - 0x64, 0x6d, 0x78, 0x84, 0x98, 0xaa, 0xbb, 0x2d, - 0x98, 0x00, 0x00, 0xf0, 0xfd, 0x1b, 0xfd, 0x03, - 0x03, 0xf4, 0x0d, 0x28, 0x8d, 0x0d, 0x00, 0x00, - 0x00, 0x30, 0x00, 0x0b, 0x01, 0x20, 0xfe, 0x00, - 0x02, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xd0, 0x00, 0xc8, 0xc5, 0xcc, - 0xcc, 0xcf, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, - 0xa0, 0x03, 0x84, 0x00, 0x00, 0x00, 0x40, 0x00, - 0xc1, 0xd0, 0xd0, 0xcc, 0xc5, 0xd3, 0xcf, 0xc6, - 0xd4, 0xe8, 0xb7, 0xbb, 0xb3, 0xbb, 0xb4, 0x00, - 0xc0, 0x7e, 0xb3, 0x21, 0xab, 0x05, 0xac, 0x57, - 0xac, 0x6f, 0xac, 0x2a, 0xad, 0x97, 0xad, 0xee, - 0xac, 0xf5, 0xac, 0x39, 0xac, 0x11, 0xad, 0x8d, - 0xae, 0x17, 0xad, 0x7e, 0xb3, 0x7e, 0xb3, 0x89, - 0xac, 0x95, 0xac, 0x86, 0xac, 0x92, 0xac, 0x7e, - 0xb3, 0x7e, 0xb3, 0xbd, 0xac, 0xc9, 0xac, 0xba, - 0xac, 0xc6, 0xac, 0x7e, 0xb3, 0xe0, 0x00, 0xf0, + 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, + 0xc5, 0x46, 0x49, 0x4c, 0x45, 0x20, 0x54, 0x59, + 0x50, 0x45, 0x20, 0x4d, 0x49, 0x53, 0x4d, 0x41, + 0x54, 0x43, 0xc8, 0x50, 0x52, 0x4f, 0x47, 0x52, + 0x41, 0x4d, 0x20, 0x54, 0x4f, 0x4f, 0x20, 0x4c, + 0x41, 0x52, 0x47, 0xc5, 0x4e, 0x4f, 0x54, 0x20, + 0x44, 0x49, 0x52, 0x45, 0x43, 0x54, 0x20, 0x43, + 0x4f, 0x4d, 0x4d, 0x41, 0x4e, 0xc4, 0x8d, 0x00, + 0x03, 0x19, 0x19, 0x24, 0x33, 0x3e, 0x4c, 0x5b, + 0x64, 0x6d, 0x78, 0x84, 0x98, 0xaa, 0xbb, 0x2d, + 0x98, 0x00, 0x00, 0xf0, 0xfd, 0x1b, 0xfd, 0x03, + 0x03, 0xf4, 0x0d, 0x28, 0x8d, 0x0d, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x0b, 0x01, 0x20, 0xfe, 0x00, + 0x02, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xd0, 0x00, 0xc8, 0xc5, 0xcc, + 0xcc, 0xcf, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, + 0xa0, 0x03, 0x84, 0x00, 0x00, 0x00, 0x40, 0x00, + 0xc1, 0xd0, 0xd0, 0xcc, 0xc5, 0xd3, 0xcf, 0xc6, + 0xd4, 0xe8, 0xb7, 0xbb, 0xb3, 0xbb, 0xb4, 0x00, + 0xc0, 0x7e, 0xb3, 0x21, 0xab, 0x05, 0xac, 0x57, + 0xac, 0x6f, 0xac, 0x2a, 0xad, 0x97, 0xad, 0xee, + 0xac, 0xf5, 0xac, 0x39, 0xac, 0x11, 0xad, 0x8d, + 0xae, 0x17, 0xad, 0x7e, 0xb3, 0x7e, 0xb3, 0x89, + 0xac, 0x95, 0xac, 0x86, 0xac, 0x92, 0xac, 0x7e, + 0xb3, 0x7e, 0xb3, 0xbd, 0xac, 0xc9, 0xac, 0xba, + 0xac, 0xc6, 0xac, 0x7e, 0xb3, 0xe0, 0x00, 0xf0, - 0x02, 0xa2, 0x02, 0x8e, 0x5f, 0xaa, 0xba, 0x8e, - 0x9b, 0xb3, 0x20, 0x6a, 0xae, 0xad, 0xbb, 0xb5, - 0xc9, 0x0d, 0xb0, 0x0b, 0x0a, 0xaa, 0xbd, 0xca, - 0xaa, 0x48, 0xbd, 0xc9, 0xaa, 0x48, 0x60, 0x4c, - 0x63, 0xb3, 0x20, 0x28, 0xab, 0x4c, 0x7f, 0xb3, - 0x20, 0xdc, 0xab, 0xa9, 0x01, 0x8d, 0xe3, 0xb5, - 0xae, 0xbe, 0xb5, 0xad, 0xbd, 0xb5, 0xd0, 0x05, - 0xe0, 0x00, 0xd0, 0x01, 0xe8, 0x8d, 0xe8, 0xb5, - 0x8e, 0xe9, 0xb5, 0x20, 0xc9, 0xb1, 0x90, 0x5e, - 0x8e, 0x9c, 0xb3, 0xae, 0x5f, 0xaa, 0xbd, 0x09, - 0xa9, 0xae, 0x9c, 0xb3, 0x4a, 0xb0, 0x0d, 0xad, - 0x51, 0xaa, 0xc9, 0xc0, 0xd0, 0x03, 0x4c, 0x5f, - 0xb3, 0x4c, 0x73, 0xb3, 0xa9, 0x00, 0x9d, 0xe8, - 0xb4, 0xa9, 0x01, 0x9d, 0xe7, 0xb4, 0x8e, 0x9c, - 0xb3, 0x20, 0x44, 0xb2, 0xae, 0x9c, 0xb3, 0x9d, - 0xc7, 0xb4, 0x8d, 0xd2, 0xb5, 0x8d, 0xd4, 0xb5, - 0xad, 0xf1, 0xb5, 0x9d, 0xc6, 0xb4, 0x8d, 0xd1, - 0xb5, 0x8d, 0xd3, 0xb5, 0xad, 0xc2, 0xb5, 0x9d, - 0xc8, 0xb4, 0x20, 0x37, 0xb0, 0x20, 0x0c, 0xaf, - 0x20, 0xd6, 0xb7, 0x20, 0x3a, 0xaf, 0xae, 0x9c, - 0xb3, 0xa9, 0x06, 0x8d, 0xc5, 0xb5, 0xbd, 0xc6, - 0xb4, 0x8d, 0xd1, 0xb5, 0xbd, 0xc7, 0xb4, 0x8d, - 0xd2, 0xb5, 0xbd, 0xc8, 0xb4, 0x8d, 0xc2, 0xb5, - 0x8d, 0xf6, 0xb5, 0xbd, 0xe7, 0xb4, 0x8d, 0xee, - 0xb5, 0xbd, 0xe8, 0xb4, 0x8d, 0xef, 0xb5, 0x8e, - 0xd9, 0xb5, 0xa9, 0xff, 0x8d, 0xe0, 0xb5, 0x8d, - 0xe1, 0xb5, 0xad, 0xe2, 0xb3, 0x8d, 0xda, 0xb5, - 0x18, 0x4c, 0x5e, 0xaf, 0xa9, 0x00, 0xaa, 0x9d, - 0xd1, 0xb5, 0xe8, 0xe0, 0x2d, 0xd0, 0xf8, 0xad, - 0xbf, 0xb5, 0x49, 0xff, 0x8d, 0xf9, 0xb5, 0xad, - 0xc0, 0xb5, 0x8d, 0xf8, 0xb5, 0xad, 0xc1, 0xb5, - 0x0a, 0x0a, 0x0a, 0x0a, 0xaa, 0x8e, 0xf7, 0xb5, + 0x02, 0xa2, 0x02, 0x8e, 0x5f, 0xaa, 0xba, 0x8e, + 0x9b, 0xb3, 0x20, 0x6a, 0xae, 0xad, 0xbb, 0xb5, + 0xc9, 0x0d, 0xb0, 0x0b, 0x0a, 0xaa, 0xbd, 0xca, + 0xaa, 0x48, 0xbd, 0xc9, 0xaa, 0x48, 0x60, 0x4c, + 0x63, 0xb3, 0x20, 0x28, 0xab, 0x4c, 0x7f, 0xb3, + 0x20, 0xdc, 0xab, 0xa9, 0x01, 0x8d, 0xe3, 0xb5, + 0xae, 0xbe, 0xb5, 0xad, 0xbd, 0xb5, 0xd0, 0x05, + 0xe0, 0x00, 0xd0, 0x01, 0xe8, 0x8d, 0xe8, 0xb5, + 0x8e, 0xe9, 0xb5, 0x20, 0xc9, 0xb1, 0x90, 0x5e, + 0x8e, 0x9c, 0xb3, 0xae, 0x5f, 0xaa, 0xbd, 0x09, + 0xa9, 0xae, 0x9c, 0xb3, 0x4a, 0xb0, 0x0d, 0xad, + 0x51, 0xaa, 0xc9, 0xc0, 0xd0, 0x03, 0x4c, 0x5f, + 0xb3, 0x4c, 0x73, 0xb3, 0xa9, 0x00, 0x9d, 0xe8, + 0xb4, 0xa9, 0x01, 0x9d, 0xe7, 0xb4, 0x8e, 0x9c, + 0xb3, 0x20, 0x44, 0xb2, 0xae, 0x9c, 0xb3, 0x9d, + 0xc7, 0xb4, 0x8d, 0xd2, 0xb5, 0x8d, 0xd4, 0xb5, + 0xad, 0xf1, 0xb5, 0x9d, 0xc6, 0xb4, 0x8d, 0xd1, + 0xb5, 0x8d, 0xd3, 0xb5, 0xad, 0xc2, 0xb5, 0x9d, + 0xc8, 0xb4, 0x20, 0x37, 0xb0, 0x20, 0x0c, 0xaf, + 0x20, 0xd6, 0xb7, 0x20, 0x3a, 0xaf, 0xae, 0x9c, + 0xb3, 0xa9, 0x06, 0x8d, 0xc5, 0xb5, 0xbd, 0xc6, + 0xb4, 0x8d, 0xd1, 0xb5, 0xbd, 0xc7, 0xb4, 0x8d, + 0xd2, 0xb5, 0xbd, 0xc8, 0xb4, 0x8d, 0xc2, 0xb5, + 0x8d, 0xf6, 0xb5, 0xbd, 0xe7, 0xb4, 0x8d, 0xee, + 0xb5, 0xbd, 0xe8, 0xb4, 0x8d, 0xef, 0xb5, 0x8e, + 0xd9, 0xb5, 0xa9, 0xff, 0x8d, 0xe0, 0xb5, 0x8d, + 0xe1, 0xb5, 0xad, 0xe2, 0xb3, 0x8d, 0xda, 0xb5, + 0x18, 0x4c, 0x5e, 0xaf, 0xa9, 0x00, 0xaa, 0x9d, + 0xd1, 0xb5, 0xe8, 0xe0, 0x2d, 0xd0, 0xf8, 0xad, + 0xbf, 0xb5, 0x49, 0xff, 0x8d, 0xf9, 0xb5, 0xad, + 0xc0, 0xb5, 0x8d, 0xf8, 0xb5, 0xad, 0xc1, 0xb5, + 0x0a, 0x0a, 0x0a, 0x0a, 0xaa, 0x8e, 0xf7, 0xb5, - 0xa9, 0x11, 0x8d, 0xfa, 0xb5, 0x60, 0x20, 0x1d, - 0xaf, 0x20, 0x34, 0xaf, 0x20, 0xc3, 0xb2, 0xa9, - 0x02, 0x2d, 0xd5, 0xb5, 0xf0, 0x21, 0x20, 0xf7, - 0xaf, 0xa9, 0x00, 0x18, 0x20, 0x11, 0xb0, 0x38, - 0xce, 0xd8, 0xb5, 0xd0, 0xf7, 0xae, 0xd9, 0xb5, - 0xad, 0xee, 0xb5, 0x9d, 0xe7, 0xb4, 0xad, 0xef, - 0xb5, 0x9d, 0xe8, 0xb4, 0x20, 0x37, 0xb0, 0x4c, - 0x7f, 0xb3, 0x20, 0x28, 0xab, 0xad, 0xf6, 0xb5, - 0x30, 0x2b, 0xad, 0xbd, 0xb5, 0x85, 0x42, 0xad, - 0xbe, 0xb5, 0x85, 0x43, 0xae, 0x9c, 0xb3, 0x20, - 0x1c, 0xb2, 0x20, 0x37, 0xb0, 0x4c, 0x7f, 0xb3, - 0xad, 0xbc, 0xb5, 0xc9, 0x05, 0xb0, 0x0b, 0x0a, - 0xaa, 0xbd, 0xe6, 0xaa, 0x48, 0xbd, 0xe5, 0xaa, - 0x48, 0x60, 0x4c, 0x67, 0xb3, 0x4c, 0x7b, 0xb3, - 0xad, 0xf6, 0xb5, 0x30, 0xf8, 0xad, 0xbc, 0xb5, - 0xc9, 0x05, 0xb0, 0xee, 0x0a, 0xaa, 0xbd, 0xf2, - 0xaa, 0x48, 0xbd, 0xf1, 0xaa, 0x48, 0x60, 0x20, - 0x00, 0xb3, 0x20, 0xa8, 0xac, 0x8d, 0xc3, 0xb5, - 0x4c, 0x7f, 0xb3, 0x20, 0x00, 0xb3, 0x20, 0xb5, - 0xb1, 0x20, 0xa8, 0xac, 0x48, 0x20, 0xa2, 0xb1, - 0xa0, 0x00, 0x68, 0x91, 0x42, 0x4c, 0x96, 0xac, - 0x20, 0xb6, 0xb0, 0xb0, 0x0b, 0xb1, 0x42, 0x48, - 0x20, 0x5b, 0xb1, 0x20, 0x94, 0xb1, 0x68, 0x60, - 0x4c, 0x6f, 0xb3, 0x20, 0x00, 0xb3, 0xad, 0xc3, - 0xb5, 0x20, 0xda, 0xac, 0x4c, 0x7f, 0xb3, 0x20, - 0x00, 0xb3, 0x20, 0xa2, 0xb1, 0xa0, 0x00, 0xb1, - 0x42, 0x20, 0xda, 0xac, 0x20, 0xb5, 0xb1, 0x4c, - 0xca, 0xac, 0x48, 0x20, 0xb6, 0xb0, 0x68, 0x91, - 0x42, 0xa9, 0x40, 0x0d, 0xd5, 0xb5, 0x8d, 0xd5, - 0xb5, 0x20, 0x5b, 0xb1, 0x4c, 0x94, 0xb1, 0xa9, - 0x80, 0x8d, 0x9e, 0xb3, 0xd0, 0x05, 0xa9, 0x00, - 0x8d, 0x9e, 0xb3, 0x20, 0x28, 0xab, 0xae, 0x9c, + 0xa9, 0x11, 0x8d, 0xfa, 0xb5, 0x60, 0x20, 0x1d, + 0xaf, 0x20, 0x34, 0xaf, 0x20, 0xc3, 0xb2, 0xa9, + 0x02, 0x2d, 0xd5, 0xb5, 0xf0, 0x21, 0x20, 0xf7, + 0xaf, 0xa9, 0x00, 0x18, 0x20, 0x11, 0xb0, 0x38, + 0xce, 0xd8, 0xb5, 0xd0, 0xf7, 0xae, 0xd9, 0xb5, + 0xad, 0xee, 0xb5, 0x9d, 0xe7, 0xb4, 0xad, 0xef, + 0xb5, 0x9d, 0xe8, 0xb4, 0x20, 0x37, 0xb0, 0x4c, + 0x7f, 0xb3, 0x20, 0x28, 0xab, 0xad, 0xf6, 0xb5, + 0x30, 0x2b, 0xad, 0xbd, 0xb5, 0x85, 0x42, 0xad, + 0xbe, 0xb5, 0x85, 0x43, 0xae, 0x9c, 0xb3, 0x20, + 0x1c, 0xb2, 0x20, 0x37, 0xb0, 0x4c, 0x7f, 0xb3, + 0xad, 0xbc, 0xb5, 0xc9, 0x05, 0xb0, 0x0b, 0x0a, + 0xaa, 0xbd, 0xe6, 0xaa, 0x48, 0xbd, 0xe5, 0xaa, + 0x48, 0x60, 0x4c, 0x67, 0xb3, 0x4c, 0x7b, 0xb3, + 0xad, 0xf6, 0xb5, 0x30, 0xf8, 0xad, 0xbc, 0xb5, + 0xc9, 0x05, 0xb0, 0xee, 0x0a, 0xaa, 0xbd, 0xf2, + 0xaa, 0x48, 0xbd, 0xf1, 0xaa, 0x48, 0x60, 0x20, + 0x00, 0xb3, 0x20, 0xa8, 0xac, 0x8d, 0xc3, 0xb5, + 0x4c, 0x7f, 0xb3, 0x20, 0x00, 0xb3, 0x20, 0xb5, + 0xb1, 0x20, 0xa8, 0xac, 0x48, 0x20, 0xa2, 0xb1, + 0xa0, 0x00, 0x68, 0x91, 0x42, 0x4c, 0x96, 0xac, + 0x20, 0xb6, 0xb0, 0xb0, 0x0b, 0xb1, 0x42, 0x48, + 0x20, 0x5b, 0xb1, 0x20, 0x94, 0xb1, 0x68, 0x60, + 0x4c, 0x6f, 0xb3, 0x20, 0x00, 0xb3, 0xad, 0xc3, + 0xb5, 0x20, 0xda, 0xac, 0x4c, 0x7f, 0xb3, 0x20, + 0x00, 0xb3, 0x20, 0xa2, 0xb1, 0xa0, 0x00, 0xb1, + 0x42, 0x20, 0xda, 0xac, 0x20, 0xb5, 0xb1, 0x4c, + 0xca, 0xac, 0x48, 0x20, 0xb6, 0xb0, 0x68, 0x91, + 0x42, 0xa9, 0x40, 0x0d, 0xd5, 0xb5, 0x8d, 0xd5, + 0xb5, 0x20, 0x5b, 0xb1, 0x4c, 0x94, 0xb1, 0xa9, + 0x80, 0x8d, 0x9e, 0xb3, 0xd0, 0x05, 0xa9, 0x00, + 0x8d, 0x9e, 0xb3, 0x20, 0x28, 0xab, 0xae, 0x9c, - 0xb3, 0xbd, 0xc8, 0xb4, 0x29, 0x7f, 0x0d, 0x9e, - 0xb3, 0x9d, 0xc8, 0xb4, 0x20, 0x37, 0xb0, 0x4c, - 0x7f, 0xb3, 0x20, 0x00, 0xb3, 0x4c, 0x7f, 0xb3, - 0x20, 0x28, 0xab, 0x20, 0xb6, 0xb0, 0xb0, 0xef, - 0xee, 0xe4, 0xb5, 0xd0, 0xf6, 0xee, 0xe5, 0xb5, - 0x4c, 0x1b, 0xad, 0x20, 0x28, 0xab, 0xae, 0x9c, - 0xb3, 0xbd, 0xc8, 0xb4, 0x10, 0x03, 0x4c, 0x7b, - 0xb3, 0xae, 0x9c, 0xb3, 0xbd, 0xc6, 0xb4, 0x8d, - 0xd1, 0xb5, 0x9d, 0xe6, 0xb4, 0xa9, 0xff, 0x9d, - 0xc6, 0xb4, 0xbc, 0xc7, 0xb4, 0x8c, 0xd2, 0xb5, - 0x20, 0x37, 0xb0, 0x18, 0x20, 0x5e, 0xaf, 0xb0, - 0x2a, 0x20, 0x0c, 0xaf, 0xa0, 0x0c, 0x8c, 0x9c, - 0xb3, 0xb1, 0x42, 0x30, 0x0b, 0xf0, 0x09, 0x48, - 0xc8, 0xb1, 0x42, 0xa8, 0x68, 0x20, 0x89, 0xad, - 0xac, 0x9c, 0xb3, 0xc8, 0xc8, 0xd0, 0xe7, 0xad, - 0xd3, 0xb5, 0xac, 0xd4, 0xb5, 0x20, 0x89, 0xad, - 0x38, 0xb0, 0xd1, 0x20, 0xfb, 0xaf, 0x4c, 0x7f, - 0xb3, 0x38, 0x20, 0xdd, 0xb2, 0xa9, 0x00, 0xa2, - 0x05, 0x9d, 0xf0, 0xb5, 0xca, 0x10, 0xfa, 0x60, - 0x20, 0xdc, 0xab, 0xa9, 0xff, 0x8d, 0xf9, 0xb5, - 0x20, 0xf7, 0xaf, 0xa9, 0x16, 0x8d, 0x9d, 0xb3, - 0x20, 0x2f, 0xae, 0x20, 0x2f, 0xae, 0xa2, 0x0b, - 0xbd, 0xaf, 0xb3, 0x20, 0xed, 0xfd, 0xca, 0x10, - 0xf7, 0x86, 0x45, 0xad, 0xf6, 0xb7, 0x85, 0x44, - 0x20, 0x42, 0xae, 0x20, 0x2f, 0xae, 0x20, 0x2f, - 0xae, 0x18, 0x20, 0x11, 0xb0, 0xb0, 0x5d, 0xa2, - 0x00, 0x8e, 0x9c, 0xb3, 0xbd, 0xc6, 0xb4, 0xf0, - 0x53, 0x30, 0x4a, 0xa0, 0xa0, 0xbd, 0xc8, 0xb4, - 0x10, 0x02, 0xa0, 0xaa, 0x98, 0x20, 0xed, 0xfd, - 0xbd, 0xc8, 0xb4, 0x29, 0x7f, 0xa0, 0x07, 0x0a, - 0x0a, 0xb0, 0x03, 0x88, 0xd0, 0xfa, 0xb9, 0xa7, - 0xb3, 0x20, 0xed, 0xfd, 0xa9, 0xa0, 0x20, 0xed, + 0xb3, 0xbd, 0xc8, 0xb4, 0x29, 0x7f, 0x0d, 0x9e, + 0xb3, 0x9d, 0xc8, 0xb4, 0x20, 0x37, 0xb0, 0x4c, + 0x7f, 0xb3, 0x20, 0x00, 0xb3, 0x4c, 0x7f, 0xb3, + 0x20, 0x28, 0xab, 0x20, 0xb6, 0xb0, 0xb0, 0xef, + 0xee, 0xe4, 0xb5, 0xd0, 0xf6, 0xee, 0xe5, 0xb5, + 0x4c, 0x1b, 0xad, 0x20, 0x28, 0xab, 0xae, 0x9c, + 0xb3, 0xbd, 0xc8, 0xb4, 0x10, 0x03, 0x4c, 0x7b, + 0xb3, 0xae, 0x9c, 0xb3, 0xbd, 0xc6, 0xb4, 0x8d, + 0xd1, 0xb5, 0x9d, 0xe6, 0xb4, 0xa9, 0xff, 0x9d, + 0xc6, 0xb4, 0xbc, 0xc7, 0xb4, 0x8c, 0xd2, 0xb5, + 0x20, 0x37, 0xb0, 0x18, 0x20, 0x5e, 0xaf, 0xb0, + 0x2a, 0x20, 0x0c, 0xaf, 0xa0, 0x0c, 0x8c, 0x9c, + 0xb3, 0xb1, 0x42, 0x30, 0x0b, 0xf0, 0x09, 0x48, + 0xc8, 0xb1, 0x42, 0xa8, 0x68, 0x20, 0x89, 0xad, + 0xac, 0x9c, 0xb3, 0xc8, 0xc8, 0xd0, 0xe7, 0xad, + 0xd3, 0xb5, 0xac, 0xd4, 0xb5, 0x20, 0x89, 0xad, + 0x38, 0xb0, 0xd1, 0x20, 0xfb, 0xaf, 0x4c, 0x7f, + 0xb3, 0x38, 0x20, 0xdd, 0xb2, 0xa9, 0x00, 0xa2, + 0x05, 0x9d, 0xf0, 0xb5, 0xca, 0x10, 0xfa, 0x60, + 0x20, 0xdc, 0xab, 0xa9, 0xff, 0x8d, 0xf9, 0xb5, + 0x20, 0xf7, 0xaf, 0xa9, 0x16, 0x8d, 0x9d, 0xb3, + 0x20, 0x2f, 0xae, 0x20, 0x2f, 0xae, 0xa2, 0x0b, + 0xbd, 0xaf, 0xb3, 0x20, 0xed, 0xfd, 0xca, 0x10, + 0xf7, 0x86, 0x45, 0xad, 0xf6, 0xb7, 0x85, 0x44, + 0x20, 0x42, 0xae, 0x20, 0x2f, 0xae, 0x20, 0x2f, + 0xae, 0x18, 0x20, 0x11, 0xb0, 0xb0, 0x5d, 0xa2, + 0x00, 0x8e, 0x9c, 0xb3, 0xbd, 0xc6, 0xb4, 0xf0, + 0x53, 0x30, 0x4a, 0xa0, 0xa0, 0xbd, 0xc8, 0xb4, + 0x10, 0x02, 0xa0, 0xaa, 0x98, 0x20, 0xed, 0xfd, + 0xbd, 0xc8, 0xb4, 0x29, 0x7f, 0xa0, 0x07, 0x0a, + 0x0a, 0xb0, 0x03, 0x88, 0xd0, 0xfa, 0xb9, 0xa7, + 0xb3, 0x20, 0xed, 0xfd, 0xa9, 0xa0, 0x20, 0xed, - 0xfd, 0xbd, 0xe7, 0xb4, 0x85, 0x44, 0xbd, 0xe8, - 0xb4, 0x85, 0x45, 0x20, 0x42, 0xae, 0xa9, 0xa0, - 0x20, 0xed, 0xfd, 0xe8, 0xe8, 0xe8, 0xa0, 0x1d, - 0xbd, 0xc6, 0xb4, 0x20, 0xed, 0xfd, 0xe8, 0x88, - 0x10, 0xf6, 0x20, 0x2f, 0xae, 0x20, 0x30, 0xb2, - 0x90, 0xa7, 0xb0, 0x9e, 0x4c, 0x7f, 0xb3, 0xa9, - 0x8d, 0x20, 0xed, 0xfd, 0xce, 0x9d, 0xb3, 0xd0, - 0x08, 0x20, 0x0c, 0xfd, 0xa9, 0x15, 0x8d, 0x9d, - 0xb3, 0x60, 0xa0, 0x02, 0xa9, 0x00, 0x48, 0xa5, - 0x44, 0xd9, 0xa4, 0xb3, 0x90, 0x12, 0xf9, 0xa4, - 0xb3, 0x85, 0x44, 0xa5, 0x45, 0xe9, 0x00, 0x85, - 0x45, 0x68, 0x69, 0x00, 0x48, 0x4c, 0x47, 0xae, - 0x68, 0x09, 0xb0, 0x20, 0xed, 0xfd, 0x88, 0x10, - 0xdb, 0x60, 0x20, 0x08, 0xaf, 0xa0, 0x00, 0x8c, - 0xc5, 0xb5, 0xb1, 0x42, 0x99, 0xd1, 0xb5, 0xc8, - 0xc0, 0x2d, 0xd0, 0xf6, 0x18, 0x60, 0x20, 0x08, - 0xaf, 0xa0, 0x00, 0xb9, 0xd1, 0xb5, 0x91, 0x42, - 0xc8, 0xc0, 0x2d, 0xd0, 0xf6, 0x60, 0x20, 0xdc, - 0xab, 0xa9, 0x04, 0x20, 0x58, 0xb0, 0xad, 0xf9, - 0xb5, 0x49, 0xff, 0x8d, 0xc1, 0xb3, 0xa9, 0x11, - 0x8d, 0xeb, 0xb3, 0xa9, 0x01, 0x8d, 0xec, 0xb3, - 0xa2, 0x38, 0xa9, 0x00, 0x9d, 0xbb, 0xb3, 0xe8, - 0xd0, 0xfa, 0xa2, 0x0c, 0xe0, 0x8c, 0xf0, 0x14, - 0xa0, 0x03, 0xb9, 0xa0, 0xb3, 0x9d, 0xf3, 0xb3, - 0xe8, 0x88, 0x10, 0xf6, 0xe0, 0x44, 0xd0, 0xec, - 0xa2, 0x48, 0xd0, 0xe8, 0x20, 0xfb, 0xaf, 0xa2, - 0x00, 0x8a, 0x9d, 0xbb, 0xb4, 0xe8, 0xd0, 0xfa, - 0x20, 0x45, 0xb0, 0xa9, 0x11, 0xac, 0xf0, 0xb3, - 0x88, 0x88, 0x8d, 0xec, 0xb7, 0x8d, 0xbc, 0xb4, - 0x8c, 0xbd, 0xb4, 0xc8, 0x8c, 0xed, 0xb7, 0xa9, - 0x02, 0x20, 0x58, 0xb0, 0xac, 0xbd, 0xb4, 0x88, - 0x30, 0x05, 0xd0, 0xec, 0x98, 0xf0, 0xe6, 0x20, + 0xfd, 0xbd, 0xe7, 0xb4, 0x85, 0x44, 0xbd, 0xe8, + 0xb4, 0x85, 0x45, 0x20, 0x42, 0xae, 0xa9, 0xa0, + 0x20, 0xed, 0xfd, 0xe8, 0xe8, 0xe8, 0xa0, 0x1d, + 0xbd, 0xc6, 0xb4, 0x20, 0xed, 0xfd, 0xe8, 0x88, + 0x10, 0xf6, 0x20, 0x2f, 0xae, 0x20, 0x30, 0xb2, + 0x90, 0xa7, 0xb0, 0x9e, 0x4c, 0x7f, 0xb3, 0xa9, + 0x8d, 0x20, 0xed, 0xfd, 0xce, 0x9d, 0xb3, 0xd0, + 0x08, 0x20, 0x0c, 0xfd, 0xa9, 0x15, 0x8d, 0x9d, + 0xb3, 0x60, 0xa0, 0x02, 0xa9, 0x00, 0x48, 0xa5, + 0x44, 0xd9, 0xa4, 0xb3, 0x90, 0x12, 0xf9, 0xa4, + 0xb3, 0x85, 0x44, 0xa5, 0x45, 0xe9, 0x00, 0x85, + 0x45, 0x68, 0x69, 0x00, 0x48, 0x4c, 0x47, 0xae, + 0x68, 0x09, 0xb0, 0x20, 0xed, 0xfd, 0x88, 0x10, + 0xdb, 0x60, 0x20, 0x08, 0xaf, 0xa0, 0x00, 0x8c, + 0xc5, 0xb5, 0xb1, 0x42, 0x99, 0xd1, 0xb5, 0xc8, + 0xc0, 0x2d, 0xd0, 0xf6, 0x18, 0x60, 0x20, 0x08, + 0xaf, 0xa0, 0x00, 0xb9, 0xd1, 0xb5, 0x91, 0x42, + 0xc8, 0xc0, 0x2d, 0xd0, 0xf6, 0x60, 0x20, 0xdc, + 0xab, 0xa9, 0x04, 0x20, 0x58, 0xb0, 0xad, 0xf9, + 0xb5, 0x49, 0xff, 0x8d, 0xc1, 0xb3, 0xa9, 0x11, + 0x8d, 0xeb, 0xb3, 0xa9, 0x01, 0x8d, 0xec, 0xb3, + 0xa2, 0x38, 0xa9, 0x00, 0x9d, 0xbb, 0xb3, 0xe8, + 0xd0, 0xfa, 0xa2, 0x0c, 0xe0, 0x8c, 0xf0, 0x14, + 0xa0, 0x03, 0xb9, 0xa0, 0xb3, 0x9d, 0xf3, 0xb3, + 0xe8, 0x88, 0x10, 0xf6, 0xe0, 0x44, 0xd0, 0xec, + 0xa2, 0x48, 0xd0, 0xe8, 0x20, 0xfb, 0xaf, 0xa2, + 0x00, 0x8a, 0x9d, 0xbb, 0xb4, 0xe8, 0xd0, 0xfa, + 0x20, 0x45, 0xb0, 0xa9, 0x11, 0xac, 0xf0, 0xb3, + 0x88, 0x88, 0x8d, 0xec, 0xb7, 0x8d, 0xbc, 0xb4, + 0x8c, 0xbd, 0xb4, 0xc8, 0x8c, 0xed, 0xb7, 0xa9, + 0x02, 0x20, 0x58, 0xb0, 0xac, 0xbd, 0xb4, 0x88, + 0x30, 0x05, 0xd0, 0xec, 0x98, 0xf0, 0xe6, 0x20, - 0xc2, 0xb7, 0x20, 0x4a, 0xb7, 0x4c, 0x7f, 0xb3, - 0xa2, 0x00, 0xf0, 0x06, 0xa2, 0x02, 0xd0, 0x02, - 0xa2, 0x04, 0xbd, 0xc7, 0xb5, 0x85, 0x42, 0xbd, - 0xc8, 0xb5, 0x85, 0x43, 0x60, 0x2c, 0xd5, 0xb5, - 0x70, 0x01, 0x60, 0x20, 0xe4, 0xaf, 0xa9, 0x02, - 0x20, 0x52, 0xb0, 0xa9, 0xbf, 0x2d, 0xd5, 0xb5, - 0x8d, 0xd5, 0xb5, 0x60, 0xad, 0xd5, 0xb5, 0x30, - 0x01, 0x60, 0x20, 0x4b, 0xaf, 0xa9, 0x02, 0x20, - 0x52, 0xb0, 0xa9, 0x7f, 0x2d, 0xd5, 0xb5, 0x8d, - 0xd5, 0xb5, 0x60, 0xad, 0xc9, 0xb5, 0x8d, 0xf0, - 0xb7, 0xad, 0xca, 0xb5, 0x8d, 0xf1, 0xb7, 0xae, - 0xd3, 0xb5, 0xac, 0xd4, 0xb5, 0x60, 0x08, 0x20, - 0x34, 0xaf, 0x20, 0x4b, 0xaf, 0x20, 0x0c, 0xaf, - 0x28, 0xb0, 0x09, 0xae, 0xd1, 0xb5, 0xac, 0xd2, - 0xb5, 0x4c, 0xb5, 0xaf, 0xa0, 0x01, 0xb1, 0x42, - 0xf0, 0x08, 0xaa, 0xc8, 0xb1, 0x42, 0xa8, 0x4c, - 0xb5, 0xaf, 0xad, 0xbb, 0xb5, 0xc9, 0x04, 0xf0, - 0x02, 0x38, 0x60, 0x20, 0x44, 0xb2, 0xa0, 0x02, - 0x91, 0x42, 0x48, 0x88, 0xad, 0xf1, 0xb5, 0x91, - 0x42, 0x48, 0x20, 0x3a, 0xaf, 0x20, 0xd6, 0xb7, - 0xa0, 0x05, 0xad, 0xde, 0xb5, 0x91, 0x42, 0xc8, - 0xad, 0xdf, 0xb5, 0x91, 0x42, 0x68, 0xaa, 0x68, - 0xa8, 0xa9, 0x02, 0xd0, 0x02, 0xa9, 0x01, 0x8e, - 0xd3, 0xb5, 0x8c, 0xd4, 0xb5, 0x20, 0x52, 0xb0, - 0xa0, 0x05, 0xb1, 0x42, 0x8d, 0xdc, 0xb5, 0x18, - 0x6d, 0xda, 0xb5, 0x8d, 0xde, 0xb5, 0xc8, 0xb1, - 0x42, 0x8d, 0xdd, 0xb5, 0x6d, 0xdb, 0xb5, 0x8d, - 0xdf, 0xb5, 0x18, 0x60, 0x20, 0xe4, 0xaf, 0xa9, - 0x01, 0x4c, 0x52, 0xb0, 0xac, 0xcb, 0xb5, 0xad, - 0xcc, 0xb5, 0x8c, 0xf0, 0xb7, 0x8d, 0xf1, 0xb7, - 0xae, 0xd6, 0xb5, 0xac, 0xd7, 0xb5, 0x60, 0xa9, - 0x01, 0xd0, 0x02, 0xa9, 0x02, 0xac, 0xc3, 0xaa, + 0xc2, 0xb7, 0x20, 0x4a, 0xb7, 0x4c, 0x7f, 0xb3, + 0xa2, 0x00, 0xf0, 0x06, 0xa2, 0x02, 0xd0, 0x02, + 0xa2, 0x04, 0xbd, 0xc7, 0xb5, 0x85, 0x42, 0xbd, + 0xc8, 0xb5, 0x85, 0x43, 0x60, 0x2c, 0xd5, 0xb5, + 0x70, 0x01, 0x60, 0x20, 0xe4, 0xaf, 0xa9, 0x02, + 0x20, 0x52, 0xb0, 0xa9, 0xbf, 0x2d, 0xd5, 0xb5, + 0x8d, 0xd5, 0xb5, 0x60, 0xad, 0xd5, 0xb5, 0x30, + 0x01, 0x60, 0x20, 0x4b, 0xaf, 0xa9, 0x02, 0x20, + 0x52, 0xb0, 0xa9, 0x7f, 0x2d, 0xd5, 0xb5, 0x8d, + 0xd5, 0xb5, 0x60, 0xad, 0xc9, 0xb5, 0x8d, 0xf0, + 0xb7, 0xad, 0xca, 0xb5, 0x8d, 0xf1, 0xb7, 0xae, + 0xd3, 0xb5, 0xac, 0xd4, 0xb5, 0x60, 0x08, 0x20, + 0x34, 0xaf, 0x20, 0x4b, 0xaf, 0x20, 0x0c, 0xaf, + 0x28, 0xb0, 0x09, 0xae, 0xd1, 0xb5, 0xac, 0xd2, + 0xb5, 0x4c, 0xb5, 0xaf, 0xa0, 0x01, 0xb1, 0x42, + 0xf0, 0x08, 0xaa, 0xc8, 0xb1, 0x42, 0xa8, 0x4c, + 0xb5, 0xaf, 0xad, 0xbb, 0xb5, 0xc9, 0x04, 0xf0, + 0x02, 0x38, 0x60, 0x20, 0x44, 0xb2, 0xa0, 0x02, + 0x91, 0x42, 0x48, 0x88, 0xad, 0xf1, 0xb5, 0x91, + 0x42, 0x48, 0x20, 0x3a, 0xaf, 0x20, 0xd6, 0xb7, + 0xa0, 0x05, 0xad, 0xde, 0xb5, 0x91, 0x42, 0xc8, + 0xad, 0xdf, 0xb5, 0x91, 0x42, 0x68, 0xaa, 0x68, + 0xa8, 0xa9, 0x02, 0xd0, 0x02, 0xa9, 0x01, 0x8e, + 0xd3, 0xb5, 0x8c, 0xd4, 0xb5, 0x20, 0x52, 0xb0, + 0xa0, 0x05, 0xb1, 0x42, 0x8d, 0xdc, 0xb5, 0x18, + 0x6d, 0xda, 0xb5, 0x8d, 0xde, 0xb5, 0xc8, 0xb1, + 0x42, 0x8d, 0xdd, 0xb5, 0x6d, 0xdb, 0xb5, 0x8d, + 0xdf, 0xb5, 0x18, 0x60, 0x20, 0xe4, 0xaf, 0xa9, + 0x01, 0x4c, 0x52, 0xb0, 0xac, 0xcb, 0xb5, 0xad, + 0xcc, 0xb5, 0x8c, 0xf0, 0xb7, 0x8d, 0xf1, 0xb7, + 0xae, 0xd6, 0xb5, 0xac, 0xd7, 0xb5, 0x60, 0xa9, + 0x01, 0xd0, 0x02, 0xa9, 0x02, 0xac, 0xc3, 0xaa, - 0x8c, 0xf0, 0xb7, 0xac, 0xc4, 0xaa, 0x8c, 0xf1, - 0xb7, 0xae, 0xfa, 0xb5, 0xa0, 0x00, 0x4c, 0x52, - 0xb0, 0x08, 0x20, 0x45, 0xb0, 0x28, 0xb0, 0x08, - 0xac, 0xbd, 0xb3, 0xae, 0xbc, 0xb3, 0xd0, 0x0a, - 0xae, 0xbc, 0xb4, 0xd0, 0x02, 0x38, 0x60, 0xac, - 0xbd, 0xb4, 0x8e, 0x97, 0xb3, 0x8c, 0x98, 0xb3, - 0xa9, 0x01, 0x20, 0x52, 0xb0, 0x18, 0x60, 0x20, - 0x45, 0xb0, 0xae, 0x97, 0xb3, 0xac, 0x98, 0xb3, - 0xa9, 0x02, 0x4c, 0x52, 0xb0, 0xad, 0xc5, 0xaa, - 0x8d, 0xf0, 0xb7, 0xad, 0xc6, 0xaa, 0x8d, 0xf1, - 0xb7, 0x60, 0x8e, 0xec, 0xb7, 0x8c, 0xed, 0xb7, - 0x8d, 0xf4, 0xb7, 0xc9, 0x02, 0xd0, 0x06, 0x0d, - 0xd5, 0xb5, 0x8d, 0xd5, 0xb5, 0xad, 0xf9, 0xb5, - 0x49, 0xff, 0x8d, 0xeb, 0xb7, 0xad, 0xf7, 0xb5, - 0x8d, 0xe9, 0xb7, 0xad, 0xf8, 0xb5, 0x8d, 0xea, - 0xb7, 0xad, 0xe2, 0xb5, 0x8d, 0xf2, 0xb7, 0xad, - 0xe3, 0xb5, 0x8d, 0xf3, 0xb7, 0xa9, 0x01, 0x8d, - 0xe8, 0xb7, 0xac, 0xc1, 0xaa, 0xad, 0xc2, 0xaa, - 0x20, 0xb5, 0xb7, 0xad, 0xf6, 0xb7, 0x8d, 0xbf, - 0xb5, 0xa9, 0xff, 0x8d, 0xeb, 0xb7, 0xb0, 0x01, - 0x60, 0xad, 0xf5, 0xb7, 0xa0, 0x07, 0xc9, 0x20, - 0xf0, 0x08, 0xa0, 0x04, 0xc9, 0x10, 0xf0, 0x02, - 0xa0, 0x08, 0x98, 0x4c, 0x85, 0xb3, 0xad, 0xe4, - 0xb5, 0xcd, 0xe0, 0xb5, 0xd0, 0x08, 0xad, 0xe5, - 0xb5, 0xcd, 0xe1, 0xb5, 0xf0, 0x66, 0x20, 0x1d, - 0xaf, 0xad, 0xe5, 0xb5, 0xcd, 0xdd, 0xb5, 0x90, - 0x1c, 0xd0, 0x08, 0xad, 0xe4, 0xb5, 0xcd, 0xdc, - 0xb5, 0x90, 0x12, 0xad, 0xe5, 0xb5, 0xcd, 0xdf, - 0xb5, 0x90, 0x10, 0xd0, 0x08, 0xad, 0xe4, 0xb5, - 0xcd, 0xde, 0xb5, 0x90, 0x06, 0x20, 0x5e, 0xaf, - 0x90, 0xd7, 0x60, 0x38, 0xad, 0xe4, 0xb5, 0xed, - 0xdc, 0xb5, 0x0a, 0x69, 0x0c, 0xa8, 0x20, 0x0c, + 0x8c, 0xf0, 0xb7, 0xac, 0xc4, 0xaa, 0x8c, 0xf1, + 0xb7, 0xae, 0xfa, 0xb5, 0xa0, 0x00, 0x4c, 0x52, + 0xb0, 0x08, 0x20, 0x45, 0xb0, 0x28, 0xb0, 0x08, + 0xac, 0xbd, 0xb3, 0xae, 0xbc, 0xb3, 0xd0, 0x0a, + 0xae, 0xbc, 0xb4, 0xd0, 0x02, 0x38, 0x60, 0xac, + 0xbd, 0xb4, 0x8e, 0x97, 0xb3, 0x8c, 0x98, 0xb3, + 0xa9, 0x01, 0x20, 0x52, 0xb0, 0x18, 0x60, 0x20, + 0x45, 0xb0, 0xae, 0x97, 0xb3, 0xac, 0x98, 0xb3, + 0xa9, 0x02, 0x4c, 0x52, 0xb0, 0xad, 0xc5, 0xaa, + 0x8d, 0xf0, 0xb7, 0xad, 0xc6, 0xaa, 0x8d, 0xf1, + 0xb7, 0x60, 0x8e, 0xec, 0xb7, 0x8c, 0xed, 0xb7, + 0x8d, 0xf4, 0xb7, 0xc9, 0x02, 0xd0, 0x06, 0x0d, + 0xd5, 0xb5, 0x8d, 0xd5, 0xb5, 0xad, 0xf9, 0xb5, + 0x49, 0xff, 0x8d, 0xeb, 0xb7, 0xad, 0xf7, 0xb5, + 0x8d, 0xe9, 0xb7, 0xad, 0xf8, 0xb5, 0x8d, 0xea, + 0xb7, 0xad, 0xe2, 0xb5, 0x8d, 0xf2, 0xb7, 0xad, + 0xe3, 0xb5, 0x8d, 0xf3, 0xb7, 0xa9, 0x01, 0x8d, + 0xe8, 0xb7, 0xac, 0xc1, 0xaa, 0xad, 0xc2, 0xaa, + 0x20, 0xb5, 0xb7, 0xad, 0xf6, 0xb7, 0x8d, 0xbf, + 0xb5, 0xa9, 0xff, 0x8d, 0xeb, 0xb7, 0xb0, 0x01, + 0x60, 0xad, 0xf5, 0xb7, 0xa0, 0x07, 0xc9, 0x20, + 0xf0, 0x08, 0xa0, 0x04, 0xc9, 0x10, 0xf0, 0x02, + 0xa0, 0x08, 0x98, 0x4c, 0x85, 0xb3, 0xad, 0xe4, + 0xb5, 0xcd, 0xe0, 0xb5, 0xd0, 0x08, 0xad, 0xe5, + 0xb5, 0xcd, 0xe1, 0xb5, 0xf0, 0x66, 0x20, 0x1d, + 0xaf, 0xad, 0xe5, 0xb5, 0xcd, 0xdd, 0xb5, 0x90, + 0x1c, 0xd0, 0x08, 0xad, 0xe4, 0xb5, 0xcd, 0xdc, + 0xb5, 0x90, 0x12, 0xad, 0xe5, 0xb5, 0xcd, 0xdf, + 0xb5, 0x90, 0x10, 0xd0, 0x08, 0xad, 0xe4, 0xb5, + 0xcd, 0xde, 0xb5, 0x90, 0x06, 0x20, 0x5e, 0xaf, + 0x90, 0xd7, 0x60, 0x38, 0xad, 0xe4, 0xb5, 0xed, + 0xdc, 0xb5, 0x0a, 0x69, 0x0c, 0xa8, 0x20, 0x0c, - 0xaf, 0xb1, 0x42, 0xd0, 0x0f, 0xad, 0xbb, 0xb5, - 0xc9, 0x04, 0xf0, 0x02, 0x38, 0x60, 0x20, 0x34, - 0xb1, 0x4c, 0x20, 0xb1, 0x8d, 0xd6, 0xb5, 0xc8, - 0xb1, 0x42, 0x8d, 0xd7, 0xb5, 0x20, 0xdc, 0xaf, - 0xad, 0xe4, 0xb5, 0x8d, 0xe0, 0xb5, 0xad, 0xe5, - 0xb5, 0x8d, 0xe1, 0xb5, 0x20, 0x10, 0xaf, 0xac, - 0xe6, 0xb5, 0x18, 0x60, 0x8c, 0x9d, 0xb3, 0x20, - 0x44, 0xb2, 0xac, 0x9d, 0xb3, 0xc8, 0x91, 0x42, - 0x8d, 0xd7, 0xb5, 0x88, 0xad, 0xf1, 0xb5, 0x91, - 0x42, 0x8d, 0xd6, 0xb5, 0x20, 0x10, 0xaf, 0x20, - 0xd6, 0xb7, 0xa9, 0xc0, 0x0d, 0xd5, 0xb5, 0x8d, - 0xd5, 0xb5, 0x60, 0xae, 0xea, 0xb5, 0x8e, 0xbd, - 0xb5, 0xae, 0xeb, 0xb5, 0x8e, 0xbe, 0xb5, 0xae, - 0xec, 0xb5, 0xac, 0xed, 0xb5, 0x8e, 0xbf, 0xb5, - 0x8c, 0xc0, 0xb5, 0xe8, 0xd0, 0x01, 0xc8, 0xcc, - 0xe9, 0xb5, 0xd0, 0x11, 0xec, 0xe8, 0xb5, 0xd0, - 0x0c, 0xa2, 0x00, 0xa0, 0x00, 0xee, 0xea, 0xb5, - 0xd0, 0x03, 0xee, 0xeb, 0xb5, 0x8e, 0xec, 0xb5, - 0x8c, 0xed, 0xb5, 0x60, 0xee, 0xe6, 0xb5, 0xd0, - 0x08, 0xee, 0xe4, 0xb5, 0xd0, 0x03, 0xee, 0xe5, - 0xb5, 0x60, 0xac, 0xc3, 0xb5, 0xae, 0xc4, 0xb5, - 0x84, 0x42, 0x86, 0x43, 0xee, 0xc3, 0xb5, 0xd0, - 0x03, 0xee, 0xc4, 0xb5, 0x60, 0xac, 0xc1, 0xb5, - 0xd0, 0x08, 0xae, 0xc2, 0xb5, 0xf0, 0x07, 0xce, - 0xc2, 0xb5, 0xce, 0xc1, 0xb5, 0x60, 0x4c, 0x7f, - 0xb3, 0x20, 0xf7, 0xaf, 0xad, 0xc3, 0xb5, 0x85, - 0x42, 0xad, 0xc4, 0xb5, 0x85, 0x43, 0xa9, 0x01, - 0x8d, 0x9d, 0xb3, 0xa9, 0x00, 0x8d, 0xd8, 0xb5, - 0x18, 0xee, 0xd8, 0xb5, 0x20, 0x11, 0xb0, 0xb0, - 0x51, 0xa2, 0x00, 0x8e, 0x9c, 0xb3, 0xbd, 0xc6, - 0xb4, 0xf0, 0x1f, 0x30, 0x22, 0xa0, 0x00, 0xe8, - 0xe8, 0xe8, 0xb1, 0x42, 0xdd, 0xc6, 0xb4, 0xd0, + 0xaf, 0xb1, 0x42, 0xd0, 0x0f, 0xad, 0xbb, 0xb5, + 0xc9, 0x04, 0xf0, 0x02, 0x38, 0x60, 0x20, 0x34, + 0xb1, 0x4c, 0x20, 0xb1, 0x8d, 0xd6, 0xb5, 0xc8, + 0xb1, 0x42, 0x8d, 0xd7, 0xb5, 0x20, 0xdc, 0xaf, + 0xad, 0xe4, 0xb5, 0x8d, 0xe0, 0xb5, 0xad, 0xe5, + 0xb5, 0x8d, 0xe1, 0xb5, 0x20, 0x10, 0xaf, 0xac, + 0xe6, 0xb5, 0x18, 0x60, 0x8c, 0x9d, 0xb3, 0x20, + 0x44, 0xb2, 0xac, 0x9d, 0xb3, 0xc8, 0x91, 0x42, + 0x8d, 0xd7, 0xb5, 0x88, 0xad, 0xf1, 0xb5, 0x91, + 0x42, 0x8d, 0xd6, 0xb5, 0x20, 0x10, 0xaf, 0x20, + 0xd6, 0xb7, 0xa9, 0xc0, 0x0d, 0xd5, 0xb5, 0x8d, + 0xd5, 0xb5, 0x60, 0xae, 0xea, 0xb5, 0x8e, 0xbd, + 0xb5, 0xae, 0xeb, 0xb5, 0x8e, 0xbe, 0xb5, 0xae, + 0xec, 0xb5, 0xac, 0xed, 0xb5, 0x8e, 0xbf, 0xb5, + 0x8c, 0xc0, 0xb5, 0xe8, 0xd0, 0x01, 0xc8, 0xcc, + 0xe9, 0xb5, 0xd0, 0x11, 0xec, 0xe8, 0xb5, 0xd0, + 0x0c, 0xa2, 0x00, 0xa0, 0x00, 0xee, 0xea, 0xb5, + 0xd0, 0x03, 0xee, 0xeb, 0xb5, 0x8e, 0xec, 0xb5, + 0x8c, 0xed, 0xb5, 0x60, 0xee, 0xe6, 0xb5, 0xd0, + 0x08, 0xee, 0xe4, 0xb5, 0xd0, 0x03, 0xee, 0xe5, + 0xb5, 0x60, 0xac, 0xc3, 0xb5, 0xae, 0xc4, 0xb5, + 0x84, 0x42, 0x86, 0x43, 0xee, 0xc3, 0xb5, 0xd0, + 0x03, 0xee, 0xc4, 0xb5, 0x60, 0xac, 0xc1, 0xb5, + 0xd0, 0x08, 0xae, 0xc2, 0xb5, 0xf0, 0x07, 0xce, + 0xc2, 0xb5, 0xce, 0xc1, 0xb5, 0x60, 0x4c, 0x7f, + 0xb3, 0x20, 0xf7, 0xaf, 0xad, 0xc3, 0xb5, 0x85, + 0x42, 0xad, 0xc4, 0xb5, 0x85, 0x43, 0xa9, 0x01, + 0x8d, 0x9d, 0xb3, 0xa9, 0x00, 0x8d, 0xd8, 0xb5, + 0x18, 0xee, 0xd8, 0xb5, 0x20, 0x11, 0xb0, 0xb0, + 0x51, 0xa2, 0x00, 0x8e, 0x9c, 0xb3, 0xbd, 0xc6, + 0xb4, 0xf0, 0x1f, 0x30, 0x22, 0xa0, 0x00, 0xe8, + 0xe8, 0xe8, 0xb1, 0x42, 0xdd, 0xc6, 0xb4, 0xd0, - 0x0a, 0xc8, 0xc0, 0x1e, 0xd0, 0xf3, 0xae, 0x9c, - 0xb3, 0x18, 0x60, 0x20, 0x30, 0xb2, 0x90, 0xdb, - 0xb0, 0xcf, 0xac, 0x9d, 0xb3, 0xd0, 0xc1, 0xac, - 0x9d, 0xb3, 0xd0, 0xef, 0xa0, 0x00, 0xe8, 0xe8, - 0xe8, 0xb1, 0x42, 0x9d, 0xc6, 0xb4, 0xc8, 0xc0, - 0x1e, 0xd0, 0xf5, 0xae, 0x9c, 0xb3, 0x38, 0x60, - 0x18, 0xad, 0x9c, 0xb3, 0x69, 0x23, 0xaa, 0xe0, - 0xf5, 0x60, 0xa9, 0x00, 0xac, 0x9d, 0xb3, 0xd0, - 0x97, 0x4c, 0x77, 0xb3, 0xad, 0xf1, 0xb5, 0xf0, - 0x21, 0xce, 0xf0, 0xb5, 0x30, 0x17, 0x18, 0xa2, - 0x04, 0x3e, 0xf1, 0xb5, 0xca, 0xd0, 0xfa, 0x90, - 0xf0, 0xee, 0xee, 0xb5, 0xd0, 0x03, 0xee, 0xef, - 0xb5, 0xad, 0xf0, 0xb5, 0x60, 0xa9, 0x00, 0x8d, - 0xf1, 0xb5, 0xa9, 0x00, 0x8d, 0x9e, 0xb3, 0x20, - 0xf7, 0xaf, 0x18, 0xad, 0xeb, 0xb3, 0x6d, 0xec, - 0xb3, 0xf0, 0x09, 0xcd, 0xef, 0xb3, 0x90, 0x14, - 0xa9, 0xff, 0xd0, 0x0a, 0xad, 0x9e, 0xb3, 0xd0, - 0x37, 0xa9, 0x01, 0x8d, 0x9e, 0xb3, 0x8d, 0xec, - 0xb3, 0x18, 0x69, 0x11, 0x8d, 0xeb, 0xb3, 0x8d, - 0xf1, 0xb5, 0xa8, 0x0a, 0x0a, 0xa8, 0xa2, 0x04, - 0x18, 0xb9, 0xf6, 0xb3, 0x9d, 0xf1, 0xb5, 0xf0, - 0x06, 0x38, 0xa9, 0x00, 0x99, 0xf6, 0xb3, 0x88, - 0xca, 0xd0, 0xee, 0x90, 0xbd, 0x20, 0xfb, 0xaf, - 0xad, 0xf0, 0xb3, 0x8d, 0xf0, 0xb5, 0xd0, 0x89, - 0x4c, 0x77, 0xb3, 0xad, 0xf1, 0xb5, 0xd0, 0x01, - 0x60, 0x48, 0x20, 0xf7, 0xaf, 0xac, 0xf0, 0xb5, - 0x68, 0x18, 0x20, 0xdd, 0xb2, 0xa9, 0x00, 0x8d, - 0xf1, 0xb5, 0x4c, 0xfb, 0xaf, 0xa2, 0xfc, 0x7e, - 0xf6, 0xb4, 0xe8, 0xd0, 0xfa, 0xc8, 0xcc, 0xf0, - 0xb3, 0xd0, 0xf2, 0x0a, 0x0a, 0xa8, 0xf0, 0x0f, - 0xa2, 0x04, 0xbd, 0xf1, 0xb5, 0x19, 0xf6, 0xb3, - 0x99, 0xf6, 0xb3, 0x88, 0xca, 0xd0, 0xf3, 0x60, + 0x0a, 0xc8, 0xc0, 0x1e, 0xd0, 0xf3, 0xae, 0x9c, + 0xb3, 0x18, 0x60, 0x20, 0x30, 0xb2, 0x90, 0xdb, + 0xb0, 0xcf, 0xac, 0x9d, 0xb3, 0xd0, 0xc1, 0xac, + 0x9d, 0xb3, 0xd0, 0xef, 0xa0, 0x00, 0xe8, 0xe8, + 0xe8, 0xb1, 0x42, 0x9d, 0xc6, 0xb4, 0xc8, 0xc0, + 0x1e, 0xd0, 0xf5, 0xae, 0x9c, 0xb3, 0x38, 0x60, + 0x18, 0xad, 0x9c, 0xb3, 0x69, 0x23, 0xaa, 0xe0, + 0xf5, 0x60, 0xa9, 0x00, 0xac, 0x9d, 0xb3, 0xd0, + 0x97, 0x4c, 0x77, 0xb3, 0xad, 0xf1, 0xb5, 0xf0, + 0x21, 0xce, 0xf0, 0xb5, 0x30, 0x17, 0x18, 0xa2, + 0x04, 0x3e, 0xf1, 0xb5, 0xca, 0xd0, 0xfa, 0x90, + 0xf0, 0xee, 0xee, 0xb5, 0xd0, 0x03, 0xee, 0xef, + 0xb5, 0xad, 0xf0, 0xb5, 0x60, 0xa9, 0x00, 0x8d, + 0xf1, 0xb5, 0xa9, 0x00, 0x8d, 0x9e, 0xb3, 0x20, + 0xf7, 0xaf, 0x18, 0xad, 0xeb, 0xb3, 0x6d, 0xec, + 0xb3, 0xf0, 0x09, 0xcd, 0xef, 0xb3, 0x90, 0x14, + 0xa9, 0xff, 0xd0, 0x0a, 0xad, 0x9e, 0xb3, 0xd0, + 0x37, 0xa9, 0x01, 0x8d, 0x9e, 0xb3, 0x8d, 0xec, + 0xb3, 0x18, 0x69, 0x11, 0x8d, 0xeb, 0xb3, 0x8d, + 0xf1, 0xb5, 0xa8, 0x0a, 0x0a, 0xa8, 0xa2, 0x04, + 0x18, 0xb9, 0xf6, 0xb3, 0x9d, 0xf1, 0xb5, 0xf0, + 0x06, 0x38, 0xa9, 0x00, 0x99, 0xf6, 0xb3, 0x88, + 0xca, 0xd0, 0xee, 0x90, 0xbd, 0x20, 0xfb, 0xaf, + 0xad, 0xf0, 0xb3, 0x8d, 0xf0, 0xb5, 0xd0, 0x89, + 0x4c, 0x77, 0xb3, 0xad, 0xf1, 0xb5, 0xd0, 0x01, + 0x60, 0x48, 0x20, 0xf7, 0xaf, 0xac, 0xf0, 0xb5, + 0x68, 0x18, 0x20, 0xdd, 0xb2, 0xa9, 0x00, 0x8d, + 0xf1, 0xb5, 0x4c, 0xfb, 0xaf, 0xa2, 0xfc, 0x7e, + 0xf6, 0xb4, 0xe8, 0xd0, 0xfa, 0xc8, 0xcc, 0xf0, + 0xb3, 0xd0, 0xf2, 0x0a, 0x0a, 0xa8, 0xf0, 0x0f, + 0xa2, 0x04, 0xbd, 0xf1, 0xb5, 0x19, 0xf6, 0xb3, + 0x99, 0xf6, 0xb3, 0x88, 0xca, 0xd0, 0xf3, 0x60, - 0xad, 0xbd, 0xb5, 0x8d, 0xe6, 0xb5, 0x8d, 0xea, - 0xb5, 0xad, 0xbe, 0xb5, 0x8d, 0xe4, 0xb5, 0x8d, - 0xeb, 0xb5, 0xa9, 0x00, 0x8d, 0xe5, 0xb5, 0xa0, - 0x10, 0xaa, 0xad, 0xe6, 0xb5, 0x4a, 0xb0, 0x03, - 0x8a, 0x90, 0x0e, 0x18, 0xad, 0xe5, 0xb5, 0x6d, - 0xe8, 0xb5, 0x8d, 0xe5, 0xb5, 0x8a, 0x6d, 0xe9, - 0xb5, 0x6a, 0x6e, 0xe5, 0xb5, 0x6e, 0xe4, 0xb5, - 0x6e, 0xe6, 0xb5, 0x88, 0xd0, 0xdb, 0xad, 0xbf, - 0xb5, 0x8d, 0xec, 0xb5, 0x6d, 0xe6, 0xb5, 0x8d, - 0xe6, 0xb5, 0xad, 0xc0, 0xb5, 0x8d, 0xed, 0xb5, - 0x6d, 0xe4, 0xb5, 0x8d, 0xe4, 0xb5, 0xa9, 0x00, - 0x6d, 0xe5, 0xb5, 0x8d, 0xe5, 0xb5, 0x60, 0xa9, - 0x01, 0xd0, 0x22, 0xa9, 0x02, 0xd0, 0x1e, 0xa9, - 0x03, 0xd0, 0x1a, 0xa9, 0x04, 0xd0, 0x16, 0xa9, - 0x05, 0xd0, 0x12, 0xa9, 0x06, 0xd0, 0x0e, 0x4c, - 0xed, 0xbf, 0xea, 0xa9, 0x0a, 0xd0, 0x06, 0xad, - 0xc5, 0xb5, 0x18, 0x90, 0x01, 0x38, 0x08, 0x8d, - 0xc5, 0xb5, 0xa9, 0x00, 0x85, 0x48, 0x20, 0x7e, - 0xae, 0x28, 0xae, 0x9b, 0xb3, 0x9a, 0x60, 0x11, - 0x0d, 0x00, 0x00, 0xee, 0x69, 0x01, 0x00, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x01, 0x0a, 0x64, 0xd4, - 0xc9, 0xc1, 0xc2, 0xd3, 0xd2, 0xc1, 0xc2, 0xa0, - 0xc5, 0xcd, 0xd5, 0xcc, 0xcf, 0xd6, 0xa0, 0xcb, - 0xd3, 0xc9, 0xc4, 0x04, 0x11, 0x0f, 0x03, 0x00, - 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x23, - 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xad, 0xbd, 0xb5, 0x8d, 0xe6, 0xb5, 0x8d, 0xea, + 0xb5, 0xad, 0xbe, 0xb5, 0x8d, 0xe4, 0xb5, 0x8d, + 0xeb, 0xb5, 0xa9, 0x00, 0x8d, 0xe5, 0xb5, 0xa0, + 0x10, 0xaa, 0xad, 0xe6, 0xb5, 0x4a, 0xb0, 0x03, + 0x8a, 0x90, 0x0e, 0x18, 0xad, 0xe5, 0xb5, 0x6d, + 0xe8, 0xb5, 0x8d, 0xe5, 0xb5, 0x8a, 0x6d, 0xe9, + 0xb5, 0x6a, 0x6e, 0xe5, 0xb5, 0x6e, 0xe4, 0xb5, + 0x6e, 0xe6, 0xb5, 0x88, 0xd0, 0xdb, 0xad, 0xbf, + 0xb5, 0x8d, 0xec, 0xb5, 0x6d, 0xe6, 0xb5, 0x8d, + 0xe6, 0xb5, 0xad, 0xc0, 0xb5, 0x8d, 0xed, 0xb5, + 0x6d, 0xe4, 0xb5, 0x8d, 0xe4, 0xb5, 0xa9, 0x00, + 0x6d, 0xe5, 0xb5, 0x8d, 0xe5, 0xb5, 0x60, 0xa9, + 0x01, 0xd0, 0x22, 0xa9, 0x02, 0xd0, 0x1e, 0xa9, + 0x03, 0xd0, 0x1a, 0xa9, 0x04, 0xd0, 0x16, 0xa9, + 0x05, 0xd0, 0x12, 0xa9, 0x06, 0xd0, 0x0e, 0x4c, + 0xed, 0xbf, 0xea, 0xa9, 0x0a, 0xd0, 0x06, 0xad, + 0xc5, 0xb5, 0x18, 0x90, 0x01, 0x38, 0x08, 0x8d, + 0xc5, 0xb5, 0xa9, 0x00, 0x85, 0x48, 0x20, 0x7e, + 0xae, 0x28, 0xae, 0x9b, 0xb3, 0x9a, 0x60, 0x11, + 0x0d, 0x00, 0x00, 0xee, 0x69, 0x01, 0x00, 0x00, + 0x00, 0x00, 0xff, 0xff, 0x01, 0x0a, 0x64, 0xd4, + 0xc9, 0xc1, 0xc2, 0xd3, 0xd2, 0xc1, 0xc2, 0xa0, + 0xc5, 0xcd, 0xd5, 0xcc, 0xcf, 0xd6, 0xa0, 0xcb, + 0xd3, 0xc9, 0xc4, 0x04, 0x11, 0x0f, 0x03, 0x00, + 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x11, 0x01, 0x00, 0x00, 0x23, + 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, + 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0b, 0x9d, 0x01, 0x00, 0xfe, - 0x02, 0x06, 0x00, 0x75, 0xaa, 0x00, 0x00, 0x00, - 0x98, 0x00, 0x97, 0x00, 0x96, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, - 0x02, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0b, 0x9d, 0x01, 0x00, 0xfe, + 0x02, 0x06, 0x00, 0x75, 0xaa, 0x00, 0x00, 0x00, + 0x98, 0x00, 0x97, 0x00, 0x96, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, + 0x02, 0x01, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -2902,4 +2902,4 @@ namespace DiskImgLib { }; -}; // namespace DiskImgLib +}; // namespace DiskImgLib diff --git a/diskimg/DiskFS.cpp b/diskimg/DiskFS.cpp index 201429c..d687055 100644 --- a/diskimg/DiskFS.cpp +++ b/diskimg/DiskFS.cpp @@ -12,7 +12,7 @@ /* * =========================================================================== - * A2File + * A2File * =========================================================================== */ @@ -24,18 +24,18 @@ void A2File::SetQuality(FileQuality quality) { - if (quality == kQualityGood && - (fFileQuality == kQualitySuspicious || fFileQuality == kQualityDamaged)) - { - assert(false); - return; - } - if (quality == kQualitySuspicious && fFileQuality == kQualityDamaged) { - //assert(false); - return; - } + if (quality == kQualityGood && + (fFileQuality == kQualitySuspicious || fFileQuality == kQualityDamaged)) + { + assert(false); + return; + } + if (quality == kQualitySuspicious && fFileQuality == kQualityDamaged) { + //assert(false); + return; + } - fFileQuality = quality; + fFileQuality = quality; } /* @@ -44,13 +44,13 @@ A2File::SetQuality(FileQuality quality) void A2File::ResetQuality(void) { - fFileQuality = kQualityGood; + fFileQuality = kQualityGood; } /* * =========================================================================== - * DiskFS + * DiskFS * =========================================================================== */ @@ -62,19 +62,19 @@ A2File::ResetQuality(void) void DiskFS::SetDiskImg(DiskImg* pImg) { - if (pImg == nil && fpImg == nil) { - WMSG0("SetDiskImg: no-op (both nil)\n"); - return; - } else if (fpImg == pImg) { - WMSG0("SetDiskImg: no-op (old == new)\n"); - return; - } + if (pImg == nil && fpImg == nil) { + WMSG0("SetDiskImg: no-op (both nil)\n"); + return; + } else if (fpImg == pImg) { + WMSG0("SetDiskImg: no-op (old == new)\n"); + return; + } - if (fpImg != nil) - fpImg->RemoveDiskFS(this); - if (pImg != nil) - pImg->AddDiskFS(this); - fpImg = pImg; + if (fpImg != nil) + fpImg->RemoveDiskFS(this); + if (pImg != nil) + pImg->AddDiskFS(this); + fpImg = pImg; } /* @@ -83,24 +83,24 @@ DiskFS::SetDiskImg(DiskImg* pImg) DIError DiskFS::Flush(DiskImg::FlushMode mode) { - SubVolume* pSubVol = GetNextSubVolume(nil); - DIError dierr; + SubVolume* pSubVol = GetNextSubVolume(nil); + DIError dierr; - while (pSubVol != nil) { + while (pSubVol != nil) { - // quick sanity check - assert(pSubVol->GetDiskFS()->GetDiskImg() == pSubVol->GetDiskImg()); + // quick sanity check + assert(pSubVol->GetDiskFS()->GetDiskImg() == pSubVol->GetDiskImg()); - dierr = pSubVol->GetDiskFS()->Flush(mode); // recurse - if (dierr != kDIErrNone) - return dierr; + dierr = pSubVol->GetDiskFS()->Flush(mode); // recurse + if (dierr != kDIErrNone) + return dierr; - pSubVol = GetNextSubVolume(pSubVol); - } + pSubVol = GetNextSubVolume(pSubVol); + } - assert(fpImg != nil); + assert(fpImg != nil); - return fpImg->FlushImage(mode); + return fpImg->FlushImage(mode); } /* @@ -109,22 +109,22 @@ DiskFS::Flush(DiskImg::FlushMode mode) void DiskFS::SetAllReadOnly(bool val) { - SubVolume* pSubVol = GetNextSubVolume(nil); + SubVolume* pSubVol = GetNextSubVolume(nil); - /* put current volume in read-only mode */ - if (fpImg != nil) - fpImg->SetReadOnly(val); + /* put current volume in read-only mode */ + if (fpImg != nil) + fpImg->SetReadOnly(val); - /* handle our kids */ - while (pSubVol != nil) { - // quick sanity check - assert(pSubVol->GetDiskFS()->GetDiskImg() == pSubVol->GetDiskImg()); + /* handle our kids */ + while (pSubVol != nil) { + // quick sanity check + assert(pSubVol->GetDiskFS()->GetDiskImg() == pSubVol->GetDiskImg()); - //pSubVol->GetDiskImg()->SetReadOnly(val); - pSubVol->GetDiskFS()->SetAllReadOnly(val); // recurse + //pSubVol->GetDiskImg()->SetReadOnly(val); + pSubVol->GetDiskFS()->SetAllReadOnly(val); // recurse - pSubVol = GetNextSubVolume(pSubVol); - } + pSubVol = GetNextSubVolume(pSubVol); + } } @@ -164,16 +164,16 @@ DiskFS::SetAllReadOnly(bool val) void DiskFS::AddFileToList(A2File* pFile) { - assert(pFile->GetNext() == nil); + assert(pFile->GetNext() == nil); - if (fpA2Head == nil) { - assert(fpA2Tail == nil); - fpA2Head = fpA2Tail = pFile; - } else { - pFile->SetPrev(fpA2Tail); - fpA2Tail->SetNext(pFile); - fpA2Tail = pFile; - } + if (fpA2Head == nil) { + assert(fpA2Tail == nil); + fpA2Head = fpA2Tail = pFile; + } else { + pFile->SetPrev(fpA2Tail); + fpA2Tail->SetNext(pFile); + fpA2Tail = pFile; + } } /* @@ -196,31 +196,31 @@ DiskFS::AddFileToList(A2File* pFile) void DiskFS::InsertFileInList(A2File* pFile, A2File* pPrev) { - assert(pFile->GetNext() == nil); + assert(pFile->GetNext() == nil); - if (fpA2Head == nil) { - assert(pPrev == nil); - fpA2Head = fpA2Tail = pFile; - return; - } else if (pPrev == nil) { - // create two entries on DOS disk, delete first, add new file - pFile->SetNext(fpA2Head); - fpA2Head = pFile; - return; - } + if (fpA2Head == nil) { + assert(pPrev == nil); + fpA2Head = fpA2Tail = pFile; + return; + } else if (pPrev == nil) { + // create two entries on DOS disk, delete first, add new file + pFile->SetNext(fpA2Head); + fpA2Head = pFile; + return; + } - /* - * If we're inserting after the parent (i.e. we're the very first thing - * in a subdir) or after a plain file, just drop it in. - * - * If we're inserting after a subdir, go fish. - */ - if (pPrev->IsDirectory() && pFile->GetParent() != pPrev) { - pPrev = SkipSubdir(pPrev); - } + /* + * If we're inserting after the parent (i.e. we're the very first thing + * in a subdir) or after a plain file, just drop it in. + * + * If we're inserting after a subdir, go fish. + */ + if (pPrev->IsDirectory() && pFile->GetParent() != pPrev) { + pPrev = SkipSubdir(pPrev); + } - pFile->SetNext(pPrev->GetNext()); - pPrev->SetNext(pFile); + pFile->SetNext(pPrev->GetNext()); + pPrev->SetNext(pFile); } /* @@ -231,30 +231,30 @@ DiskFS::InsertFileInList(A2File* pFile, A2File* pPrev) A2File* DiskFS::SkipSubdir(A2File* pSubdir) { - if (pSubdir->GetNext() == nil) - return pSubdir; // end of list reached -- subdir is empty + if (pSubdir->GetNext() == nil) + return pSubdir; // end of list reached -- subdir is empty - A2File* pCur = pSubdir; - A2File* pNext = nil; + A2File* pCur = pSubdir; + A2File* pNext = nil; - assert(pCur != nil); // at least one time through the loop + assert(pCur != nil); // at least one time through the loop - while (pCur != nil) { - pNext = pCur->GetNext(); - if (pNext == nil) // end of list reached - return pCur; + while (pCur != nil) { + pNext = pCur->GetNext(); + if (pNext == nil) // end of list reached + return pCur; - if (pNext->GetParent() != pSubdir) // end of dir reached - return pCur; - if (pNext->IsDirectory()) - pCur = SkipSubdir(pNext); // get last entry in dir - else - pCur = pNext; // advance forward one - } + if (pNext->GetParent() != pSubdir) // end of dir reached + return pCur; + if (pNext->IsDirectory()) + pCur = SkipSubdir(pNext); // get last entry in dir + else + pCur = pNext; // advance forward one + } - /* should never get here */ - assert(false); - return pNext; + /* should never get here */ + assert(false); + return pNext; } /* @@ -265,28 +265,28 @@ DiskFS::SkipSubdir(A2File* pSubdir) void DiskFS::DeleteFileFromList(A2File* pFile) { - if (fpA2Head == pFile) { - /* delete the head of the list */ - fpA2Head = fpA2Head->GetNext(); - delete pFile; - } else { - A2File* pCur = fpA2Head; - while (pCur != nil) { - if (pCur->GetNext() == pFile) { - /* found it */ - A2File* pNextNext = pCur->GetNext()->GetNext(); - delete pCur->GetNext(); - pCur->SetNext(pNextNext); - break; - } - pCur = pCur->GetNext(); - } + if (fpA2Head == pFile) { + /* delete the head of the list */ + fpA2Head = fpA2Head->GetNext(); + delete pFile; + } else { + A2File* pCur = fpA2Head; + while (pCur != nil) { + if (pCur->GetNext() == pFile) { + /* found it */ + A2File* pNextNext = pCur->GetNext()->GetNext(); + delete pCur->GetNext(); + pCur->SetNext(pNextNext); + break; + } + pCur = pCur->GetNext(); + } - if (pCur == nil) { - WMSG0("GLITCH: couldn't find element to delete!\n"); - assert(false); - } - } + if (pCur == nil) { + WMSG0("GLITCH: couldn't find element to delete!\n"); + assert(false); + } + } } @@ -299,10 +299,10 @@ DiskFS::DeleteFileFromList(A2File* pFile) A2File* DiskFS::GetNextFile(A2File* pFile) const { - if (pFile == NULL) - return fpA2Head; - else - return pFile->GetNext(); + if (pFile == NULL) + return fpA2Head; + else + return pFile->GetNext(); } /* @@ -314,15 +314,15 @@ DiskFS::GetNextFile(A2File* pFile) const long DiskFS::GetFileCount(void) const { - long count = 0; + long count = 0; - A2File* pFile = fpA2Head; - while (pFile != nil) { - count++; - pFile = pFile->GetNext(); - } + A2File* pFile = fpA2Head; + while (pFile != nil) { + count++; + pFile = pFile->GetNext(); + } - return count; + return count; } /* @@ -331,15 +331,15 @@ DiskFS::GetFileCount(void) const void DiskFS::DeleteFileList(void) { - A2File* pFile; - A2File* pNext; + A2File* pFile; + A2File* pNext; - pFile = fpA2Head; - while (pFile != nil) { - pNext = pFile->GetNext(); - delete pFile; - pFile = pNext; - } + pFile = fpA2Head; + while (pFile != nil) { + pNext = pFile->GetNext(); + delete pFile; + pFile = pNext; + } } /* @@ -348,15 +348,15 @@ DiskFS::DeleteFileList(void) void DiskFS::DumpFileList(void) { - A2File* pFile; + A2File* pFile; - WMSG0("DiskFS file list contents:\n"); + WMSG0("DiskFS file list contents:\n"); - pFile = GetNextFile(nil); - while (pFile != nil) { - WMSG1(" %s\n", pFile->GetPathName()); - pFile = GetNextFile(pFile); - } + pFile = GetNextFile(nil); + while (pFile != nil) { + WMSG1(" %s\n", pFile->GetPathName()); + pFile = GetNextFile(pFile); + } } /* @@ -370,20 +370,20 @@ DiskFS::DumpFileList(void) A2File* DiskFS::GetFileByName(const char* fileName, StringCompareFunc func) { - A2File* pFile; + A2File* pFile; - if (func == nil) - func = ::strcasecmp; + if (func == nil) + func = ::strcasecmp; - pFile = GetNextFile(nil); - while (pFile != nil) { - if ((*func)(pFile->GetPathName(), fileName) == 0) - return pFile; + pFile = GetNextFile(nil); + while (pFile != nil) { + if ((*func)(pFile->GetPathName(), fileName) == 0) + return pFile; - pFile = GetNextFile(pFile); - } + pFile = GetNextFile(pFile); + } - return nil; + return nil; } @@ -398,61 +398,61 @@ DiskFS::GetFileByName(const char* fileName, StringCompareFunc func) void DiskFS::AddSubVolumeToList(DiskImg* pDiskImg, DiskFS* pDiskFS) { - SubVolume* pSubVol; + SubVolume* pSubVol; - /* - * Check the arguments. - */ - if (pDiskImg == nil || pDiskFS == nil) { - WMSG2(" DiskFS bogus sub volume ptrs %08lx %08lx\n", - (long) pDiskImg, (long) pDiskFS); - assert(false); - return; - } - if (pDiskImg == fpImg || pDiskFS == this) { - WMSG0(" DiskFS attempt to add self to sub-vol list\n"); - assert(false); - return; - } - if (pDiskFS->GetDiskImg() == nil) { - WMSG0(" DiskFS lacks a DiskImg pointer\n"); - assert(false); - return; - } - pSubVol = fpSubVolumeHead; - while (pSubVol != nil) { - if (pSubVol->GetDiskImg() == pDiskImg || - pSubVol->GetDiskFS() == pDiskFS) - { - WMSG0(" DiskFS multiple adds on diskimg or diskfs\n"); - assert(false); - return; - } - pSubVol = pSubVol->GetNext(); - } + /* + * Check the arguments. + */ + if (pDiskImg == nil || pDiskFS == nil) { + WMSG2(" DiskFS bogus sub volume ptrs %08lx %08lx\n", + (long) pDiskImg, (long) pDiskFS); + assert(false); + return; + } + if (pDiskImg == fpImg || pDiskFS == this) { + WMSG0(" DiskFS attempt to add self to sub-vol list\n"); + assert(false); + return; + } + if (pDiskFS->GetDiskImg() == nil) { + WMSG0(" DiskFS lacks a DiskImg pointer\n"); + assert(false); + return; + } + pSubVol = fpSubVolumeHead; + while (pSubVol != nil) { + if (pSubVol->GetDiskImg() == pDiskImg || + pSubVol->GetDiskFS() == pDiskFS) + { + WMSG0(" DiskFS multiple adds on diskimg or diskfs\n"); + assert(false); + return; + } + pSubVol = pSubVol->GetNext(); + } - assert(pDiskFS->GetDiskImg() == pDiskImg); + assert(pDiskFS->GetDiskImg() == pDiskImg); - /* - * Looks good. Add it. - */ - pSubVol = new SubVolume; - if (pSubVol == nil) - return; + /* + * Looks good. Add it. + */ + pSubVol = new SubVolume; + if (pSubVol == nil) + return; - pSubVol->Create(pDiskImg, pDiskFS); + pSubVol->Create(pDiskImg, pDiskFS); - if (fpSubVolumeHead == nil) { - assert(fpSubVolumeTail == nil); - fpSubVolumeHead = fpSubVolumeTail = pSubVol; - } else { - pSubVol->SetPrev(fpSubVolumeTail); - fpSubVolumeTail->SetNext(pSubVol); - fpSubVolumeTail = pSubVol; - } + if (fpSubVolumeHead == nil) { + assert(fpSubVolumeTail == nil); + fpSubVolumeHead = fpSubVolumeTail = pSubVol; + } else { + pSubVol->SetPrev(fpSubVolumeTail); + fpSubVolumeTail->SetNext(pSubVol); + fpSubVolumeTail = pSubVol; + } - /* make sure inheritable stuff gets copied */ - CopyInheritables(pDiskFS); + /* make sure inheritable stuff gets copied */ + CopyInheritables(pDiskFS); } /* @@ -461,17 +461,17 @@ DiskFS::AddSubVolumeToList(DiskImg* pDiskImg, DiskFS* pDiskFS) void DiskFS::CopyInheritables(DiskFS* pNewFS) { - for (int i = 0; i < (int) NELEM(fParmTable); i++) - pNewFS->fParmTable[i] = fParmTable[i]; + for (int i = 0; i < (int) NELEM(fParmTable); i++) + pNewFS->fParmTable[i] = fParmTable[i]; - pNewFS->fScanForSubVolumes = fScanForSubVolumes; + pNewFS->fScanForSubVolumes = fScanForSubVolumes; #if 0 - /* copy scan progress update stuff */ - pNewFS->fpScanProgressCallback = fpScanProgressCallback; - pNewFS->fpScanProgressCookie = fpScanProgressCookie; - pNewFS->fpScanCount = -1; - strcpy(pNewFS->fpScanMsg, "HEY"); + /* copy scan progress update stuff */ + pNewFS->fpScanProgressCallback = fpScanProgressCallback; + pNewFS->fpScanProgressCookie = fpScanProgressCookie; + pNewFS->fpScanCount = -1; + strcpy(pNewFS->fpScanMsg, "HEY"); #endif } @@ -484,10 +484,10 @@ DiskFS::CopyInheritables(DiskFS* pNewFS) DiskFS::SubVolume* DiskFS::GetNextSubVolume(const SubVolume* pSubVol) const { - if (pSubVol == NULL) - return fpSubVolumeHead; - else - return pSubVol->GetNext(); + if (pSubVol == NULL) + return fpSubVolumeHead; + else + return pSubVol->GetNext(); } /* @@ -496,15 +496,15 @@ DiskFS::GetNextSubVolume(const SubVolume* pSubVol) const void DiskFS::DeleteSubVolumeList(void) { - SubVolume* pSubVol; - SubVolume* pNext; + SubVolume* pSubVol; + SubVolume* pNext; - pSubVol = fpSubVolumeHead; - while (pSubVol != nil) { - pNext = pSubVol->GetNext(); - delete pSubVol; - pSubVol = pNext; - } + pSubVol = fpSubVolumeHead; + while (pSubVol != nil) { + pNext = pSubVol->GetNext(); + delete pSubVol; + pSubVol = pNext; + } } @@ -514,8 +514,8 @@ DiskFS::DeleteSubVolumeList(void) long DiskFS::GetParameter(DiskFSParameter parm) { - assert(parm > kParmUnknown && parm < kParmMax); - return fParmTable[parm]; + assert(parm > kParmUnknown && parm < kParmMax); + return fParmTable[parm]; } /* @@ -526,14 +526,14 @@ DiskFS::GetParameter(DiskFSParameter parm) void DiskFS::SetParameter(DiskFSParameter parm, long val) { - assert(parm > kParmUnknown && parm < kParmMax); - fParmTable[parm] = val; + assert(parm > kParmUnknown && parm < kParmMax); + fParmTable[parm] = val; - SubVolume* pSubVol = GetNextSubVolume(nil); - while (pSubVol != nil) { - pSubVol->GetDiskFS()->SetParameter(parm, val); - pSubVol = GetNextSubVolume(pSubVol); - } + SubVolume* pSubVol = GetNextSubVolume(nil); + while (pSubVol != nil) { + pSubVol->GetDiskFS()->SetParameter(parm, val); + pSubVol = GetNextSubVolume(pSubVol); + } } @@ -543,16 +543,16 @@ DiskFS::SetParameter(DiskFSParameter parm, long val) void DiskFS::ScanForDamagedFiles(bool* pDamaged, bool* pSuspicious) { - A2File* pFile; + A2File* pFile; - *pDamaged = *pSuspicious = false; + *pDamaged = *pSuspicious = false; - pFile = GetNextFile(nil); - while (pFile != nil) { - if (pFile->GetQuality() == A2File::kQualityDamaged) - *pDamaged = true; - if (pFile->GetQuality() != A2File::kQualityGood) - *pSuspicious = true; - pFile = GetNextFile(pFile); - } + pFile = GetNextFile(nil); + while (pFile != nil) { + if (pFile->GetQuality() == A2File::kQualityDamaged) + *pDamaged = true; + if (pFile->GetQuality() != A2File::kQualityGood) + *pSuspicious = true; + pFile = GetNextFile(pFile); + } } diff --git a/diskimg/DiskImg.cpp b/diskimg/DiskImg.cpp index 17d7931..a66a9cd 100644 --- a/diskimg/DiskImg.cpp +++ b/diskimg/DiskImg.cpp @@ -1,3525 +1,3525 @@ -/* - * CiderPress - * Copyright (C) 2009 by CiderPress authors. All Rights Reserved. - * Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved. - * See the file LICENSE for distribution terms. - */ -/* - * Implementation of the DiskImg class. - */ -#include "StdAfx.h" -#include "DiskImgPriv.h" -#include "TwoImg.h" - - -/* - * =========================================================================== - * DiskImg - * =========================================================================== - */ - -/* - * Standard NibbleDescr profiles. - * - * These will be tried in the order in which they appear here. - * - * IMPORTANT: if you add or remove an entry, update the StdNibbleDescr enum - * in DiskImg.h. - * - * Formats that allow the data checksum to be ignored should NOT be written. - * It's possible that the DOS on the disk is ignoring the checksums, but - * it's more likely that they're using a non-standard seed, and the newly- - * written sectors will have the wrong checksum value. - * - * Non-standard headers are usually okay, because we don't rewrite the - * headers, just the sector contents. - */ -/*static*/ const DiskImg::NibbleDescr DiskImg::kStdNibbleDescrs[] = { - { - "DOS 3.3 Standard", - 16, - { 0xd5, 0xaa, 0x96 }, { 0xde, 0xaa, 0xeb }, - 0x00, // checksum seed - true, // verify checksum - true, // verify track - 2, // epilog verify count - { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, - 0x00, // checksum seed - true, // verify checksum - 2, // epilog verify count - kNibbleEnc62, - kNibbleSpecialNone, - }, - { - "DOS 3.3 Patched", - 16, - { 0xd5, 0xaa, 0x96 }, { 0xde, 0xaa, 0xeb }, - 0x00, // checksum seed - false, // verify checksum - false, // verify track - 0, // epilog verify count - { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, - 0x00, // checksum seed - true, // verify checksum - 0, // epilog verify count - kNibbleEnc62, - kNibbleSpecialNone, - }, - { - "DOS 3.3 Ignore Checksum", - 16, - { 0xd5, 0xaa, 0x96 }, { 0xde, 0xaa, 0xeb }, - 0x00, // checksum seed - false, // verify checksum - false, // verify track - 0, // epilog verify count - { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, - 0x00, // checksum seed - false, // verify checksum - 0, // epilog verify count - kNibbleEnc62, - kNibbleSpecialNone, - }, - { - "DOS 3.2 Standard", - 13, - { 0xd5, 0xaa, 0xb5 }, { 0xde, 0xaa, 0xeb }, - 0x00, - true, - true, - 2, - { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, - 0x00, - true, - 2, - kNibbleEnc53, - kNibbleSpecialNone, - }, - { - "DOS 3.2 Patched", - 13, - { 0xd5, 0xaa, 0xb5 }, { 0xde, 0xaa, 0xeb }, - 0x00, - false, - false, - 0, - { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, - 0x00, - true, - 0, - kNibbleEnc53, - kNibbleSpecialNone, - }, - { - "Muse DOS 3.2", // standard DOS 3.2 with doubled sectors - 13, - { 0xd5, 0xaa, 0xb5 }, { 0xde, 0xaa, 0xeb }, - 0x00, - true, - true, - 2, - { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, - 0x00, - true, - 2, - kNibbleEnc53, - kNibbleSpecialMuse, - }, - { - "RDOS 3.3", // SSI 16-sector RDOS, with altered headers - 16, - { 0xd4, 0xaa, 0x96 }, { 0xde, 0xaa, 0xeb }, - 0x00, - true, - true, - 0, // epilog verify count - { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, - 0x00, - true, - 2, - kNibbleEnc62, - kNibbleSpecialSkipFirstAddrByte, - /* odd tracks use d4aa96, even tracks use d5aa96 */ - }, - { - "RDOS 3.2", // SSI 13-sector RDOS, with altered headers - 13, - { 0xd4, 0xaa, 0xb7 }, { 0xde, 0xaa, 0xeb }, - 0x00, - true, - true, - 2, - { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, - 0x00, - true, - 2, - kNibbleEnc53, - kNibbleSpecialNone, - }, - { - "Custom", // reserve space for empty slot - 0, - }, -}; -/*static*/ const DiskImg::NibbleDescr* -DiskImg::GetStdNibbleDescr(StdNibbleDescr idx) -{ - if ((int)idx < 0 || (int)idx >= (int) NELEM(kStdNibbleDescrs)) - return nil; - return &kStdNibbleDescrs[(int)idx]; -} - - -/* - * Initialize the members during construction. - */ -DiskImg::DiskImg(void) -{ - assert(Global::GetAppInitCalled()); - - fOuterFormat = kOuterFormatUnknown; - fFileFormat = kFileFormatUnknown; - fPhysical = kPhysicalFormatUnknown; - fpNibbleDescr = nil; - fOrder = kSectorOrderUnknown; - fFormat = kFormatUnknown; - - fFileSysOrder = kSectorOrderUnknown; - fSectorPairing = false; - fSectorPairOffset = -1; - - fpOuterGFD = nil; - fpWrapperGFD = nil; - fpDataGFD = nil; - fpOuterWrapper = nil; - fpImageWrapper = nil; - fpParentImg = nil; - fDOSVolumeNum = kVolumeNumNotSet; - fOuterLength = -1; - fWrappedLength = -1; - fLength = -1; - fExpandable = false; - fReadOnly = true; - fDirty = false; - - fHasSectors = false; - fHasBlocks = false; - fHasNibbles = false; - - fNumTracks = -1; - fNumSectPerTrack = -1; - fNumBlocks = -1; - - fpScanProgressCallback = NULL; - - /* - * Create a working copy of the nibble descr table. We want to leave - * open the possibility of applications editing or discarding entries, - * so we work off of a copy. - * - * Ideally we'd allow these to be set per-track, so that certain odd - * formats could be handled transparently (e.g. Muse tweaked DOS 3.2) - * for formatting as well as reading. - */ - assert(kStdNibbleDescrs[kNibbleDescrCustom].numSectors == 0); - assert(kNibbleDescrCustom == NELEM(kStdNibbleDescrs)-1); - fpNibbleDescrTable = new NibbleDescr[NELEM(kStdNibbleDescrs)]; - fNumNibbleDescrEntries = NELEM(kStdNibbleDescrs); - memcpy(fpNibbleDescrTable, kStdNibbleDescrs, sizeof(kStdNibbleDescrs)); - - fNibbleTrackBuf = nil; - fNibbleTrackLoaded = -1; - - fNuFXCompressType = kNuThreadFormatLZW2; - - fNotes = nil; - fpBadBlockMap = nil; - fDiskFSRefCnt = 0; -} - -/* - * Throw away local storage. - */ -DiskImg::~DiskImg(void) -{ - if (fpDataGFD != nil) { - WMSG0("~DiskImg closing GenericFD(s)\n"); - } - (void) CloseImage(); - delete[] fpNibbleDescrTable; - delete[] fNibbleTrackBuf; - delete[] fNotes; - delete fpBadBlockMap; - - /* normally these will be closed, but perhaps not if something failed */ - if (fpOuterGFD != nil) - delete fpOuterGFD; - if (fpWrapperGFD != nil) - delete fpWrapperGFD; - if (fpDataGFD != nil) - delete fpDataGFD; - if (fpOuterWrapper != nil) - delete fpOuterWrapper; - if (fpImageWrapper != nil) - delete fpImageWrapper; - - fDiskFSRefCnt = 100; // flag as freed -} - - -/* - * Set the nibble descr pointer. - */ -void -DiskImg::SetNibbleDescr(int idx) -{ - assert(idx >= 0 && idx < kNibbleDescrMAX); - fpNibbleDescr = &fpNibbleDescrTable[idx]; -} - -/* - * Set up a custom nibble descriptor. - */ -void -DiskImg::SetCustomNibbleDescr(const NibbleDescr* pDescr) -{ - if (pDescr == NULL) { - fpNibbleDescr = NULL; - } else { - assert(fpNibbleDescrTable != NULL); - //WMSG2("Overwriting entry %d with new value (special=%d)\n", - // kNibbleDescrCustom, pDescr->special); - fpNibbleDescrTable[kNibbleDescrCustom] = *pDescr; - fpNibbleDescr = &fpNibbleDescrTable[kNibbleDescrCustom]; - } -} - - -/* - * Open a volume or a file on disk. - * - * For Windows, we need to handle logical/physical volumes specially. If - * the filename matches the appropriate pattern, use a different GFD. - */ -DIError -DiskImg::OpenImage(const char* pathName, char fssep, bool readOnly) -{ - DIError dierr = kDIErrNone; - bool isWinDevice = false; - - if (fpDataGFD != nil) { - WMSG0(" DI already open!\n"); - return kDIErrAlreadyOpen; - } - WMSG3(" DI OpenImage '%s' '%.1s' ro=%d\n", pathName, &fssep, readOnly); - - fReadOnly = readOnly; - -#ifdef _WIN32 - if ((fssep == '\0' || fssep == '\\') && - pathName[0] >= 'A' && pathName[0] <= 'Z' && - pathName[1] == ':' && pathName[2] == '\\' && - pathName[3] == '\0') - { - isWinDevice = true; // logical volume ("A:\") - } - if ((fssep == '\0' || fssep == '\\') && - isdigit(pathName[0]) && isdigit(pathName[1]) && - pathName[2] == ':' && pathName[3] == '\\' && - pathName[4] == '\0') - { - isWinDevice = true; // physical volume ("80:\") - } - if ((fssep == '\0' || fssep == '\\') && - strncmp(pathName, kASPIDev, strlen(kASPIDev)) == 0 && - pathName[strlen(pathName)-1] == '\\') - { - isWinDevice = true; // ASPI volume ("ASPI:x:y:z\") - } -#endif - - if (isWinDevice) { -#ifdef _WIN32 - GFDWinVolume* pGFDWinVolume = new GFDWinVolume; - - dierr = pGFDWinVolume->Open(pathName, fReadOnly); - if (dierr != kDIErrNone) { - delete pGFDWinVolume; - goto bail; - } - - fpWrapperGFD = pGFDWinVolume; - // Use a unique extension to skip some of the probing. - dierr = AnalyzeImageFile("CPDevice.cp-win-vol", '\0'); - if (dierr != kDIErrNone) - goto bail; -#endif - } else { - GFDFile* pGFDFile = new GFDFile; - - dierr = pGFDFile->Open(pathName, fReadOnly); - if (dierr != kDIErrNone) { - delete pGFDFile; - goto bail; - } - - //fImageFileName = new char[strlen(pathName) + 1]; - //strcpy(fImageFileName, pathName); - - fpWrapperGFD = pGFDFile; - pGFDFile = nil; - - dierr = AnalyzeImageFile(pathName, fssep); - if (dierr != kDIErrNone) - goto bail; - } - - - assert(fpDataGFD != nil); - -bail: - return dierr; -} - -/* - * Open from a buffer, which could point to unadorned ready-to-go content - * or to a preloaded image file. - */ -DIError -DiskImg::OpenImage(const void* buffer, long length, bool readOnly) -{ - if (fpDataGFD != nil) { - WMSG0(" DI already open!\n"); - return kDIErrAlreadyOpen; - } - WMSG3(" DI OpenImage %08lx %ld ro=%d\n", (long) buffer, length, readOnly); - - DIError dierr; - GFDBuffer* pGFDBuffer; - - fReadOnly = readOnly; - pGFDBuffer = new GFDBuffer; - - dierr = pGFDBuffer->Open(const_cast(buffer), length, false, false, - readOnly); - if (dierr != kDIErrNone) { - delete pGFDBuffer; - return dierr; - } - - fpWrapperGFD = pGFDBuffer; - pGFDBuffer = nil; - - dierr = AnalyzeImageFile("", '\0'); - if (dierr != kDIErrNone) - return dierr; - - assert(fpDataGFD != nil); - return kDIErrNone; -} - -/* - * Open a range of blocks from an already-open disk image. This is only - * useful for things like UNIDOS volumes, which don't have an associated - * file in the image and are linear. - * - * The "read only" flag is inherited from the parent. - * - * For embedded images with visible file structure, we should be using - * an EmbeddedFD instead. [Note these were never implemented.] - * - * NOTE: there is an implicit ProDOS block ordering imposed on the parent - * image. It turns out that all of our current embedded parents use - * ProDOS-ordered blocks, so it works out okay, but the "linear" requirement - * above goes beyond just having contiguous blocks. - */ -DIError -DiskImg::OpenImage(DiskImg* pParent, long firstBlock, long numBlocks) -{ - WMSG3(" DI OpenImage parent=0x%08lx %ld %ld\n", (long) pParent, firstBlock, - numBlocks); - if (fpDataGFD != nil) { - WMSG0(" DI already open!\n"); - return kDIErrAlreadyOpen; - } - - if (pParent == nil || firstBlock < 0 || numBlocks <= 0 || - firstBlock + numBlocks > pParent->GetNumBlocks()) - { - assert(false); - return kDIErrInvalidArg; - } - - fReadOnly = pParent->GetReadOnly(); // very important - - DIError dierr; - GFDGFD* pGFDGFD; - - pGFDGFD = new GFDGFD; - dierr = pGFDGFD->Open(pParent->fpDataGFD, firstBlock * kBlockSize, fReadOnly); - if (dierr != kDIErrNone) { - delete pGFDGFD; - return dierr; - } - - fpDataGFD = pGFDGFD; - assert(fpWrapperGFD == nil); - - /* - * This replaces the call to "analyze image file" because we know we - * already have an open file with specific characteristics. - */ - //fOffset = pParent->fOffset + kBlockSize * firstBlock; - fLength = numBlocks * kBlockSize; - fOuterLength = fWrappedLength = fLength; - fFileFormat = kFileFormatUnadorned; - fPhysical = pParent->fPhysical; - fOrder = pParent->fOrder; - - fpParentImg = pParent; - - return dierr; -} -DIError -DiskImg::OpenImage(DiskImg* pParent, long firstTrack, long firstSector, - long numSectors) -{ - WMSG4(" DI OpenImage parent=0x%08lx %ld %ld %ld\n", (long) pParent, - firstTrack, firstSector, numSectors); - if (fpDataGFD != nil) { - WMSG0(" DI already open!\n"); - return kDIErrAlreadyOpen; - } - - if (pParent == nil) - return kDIErrInvalidArg; - - int prntSectPerTrack = pParent->GetNumSectPerTrack(); - int lastTrack = firstTrack + - (numSectors + prntSectPerTrack-1) / prntSectPerTrack; - if (firstTrack < 0 || numSectors <= 0 || - lastTrack > pParent->GetNumTracks()) - { - return kDIErrInvalidArg; - } - - fReadOnly = pParent->GetReadOnly(); // very important - - DIError dierr; - GFDGFD* pGFDGFD; - - pGFDGFD = new GFDGFD; - dierr = pGFDGFD->Open(pParent->fpDataGFD, - kSectorSize * firstTrack * prntSectPerTrack, fReadOnly); - if (dierr != kDIErrNone) { - delete pGFDGFD; - return dierr; - } - - fpDataGFD = pGFDGFD; - assert(fpWrapperGFD == nil); - - /* - * This replaces the call to "analyze image file" because we know we - * already have an open file with specific characteristics. - */ - assert(firstSector == 0); // else fOffset calculation breaks - //fOffset = pParent->fOffset + kSectorSize * firstTrack * prntSectPerTrack; - fLength = numSectors * kSectorSize; - fOuterLength = fWrappedLength = fLength; - fFileFormat = kFileFormatUnadorned; - fPhysical = pParent->fPhysical; - fOrder = pParent->fOrder; - - fpParentImg = pParent; - - return dierr; -} - - -/* - * Enable sector pairing. Useful for OzDOS. - */ -void -DiskImg::SetPairedSectors(bool enable, int idx) -{ - fSectorPairing = enable; - fSectorPairOffset = idx; - - if (enable) { - assert(idx == 0 || idx == 1); - } -} - -/* - * Close the image, freeing resources. - * - * If we write to a child DiskImg, it's responsible for setting the "dirty" - * flag in its parent (and so on up the chain). That's necessary so that, - * when we close the file, changes made to a child DiskImg cause the parent - * to do any necessary recompression. - * - * [ This is getting called even when image creation failed with an error. - * This is probably the correct behavior, but we may want to be aborting the - * image creation instead of completing it. That's a higher-level decision - * though. ++ATM 20040506 ] - */ -DIError -DiskImg::CloseImage(void) -{ - DIError dierr; - - WMSG1("CloseImage %p\n", this); - - /* check for DiskFS objects that still point to us */ - if (fDiskFSRefCnt != 0) { - WMSG1("ERROR: CloseImage: fDiskFSRefCnt=%d\n", fDiskFSRefCnt); - assert(false); //DebugBreak(); - } - - /* - * Flush any changes. - */ - dierr = FlushImage(kFlushAll); - if (dierr != kDIErrNone) - return dierr; - - /* - * Clean up. Close GFD, OrigGFD, and OuterGFD. Delete ImageWrapper - * and OuterWrapper. - * - * In some cases we will have the file open more than once (e.g. a - * NuFX archive, which must be opened on disk). - */ - if (fpDataGFD != nil) { - fpDataGFD->Close(); - delete fpDataGFD; - fpDataGFD = nil; - } - if (fpWrapperGFD != nil) { - fpWrapperGFD->Close(); - delete fpWrapperGFD; - fpWrapperGFD = nil; - } - if (fpOuterGFD != nil) { - fpOuterGFD->Close(); - delete fpOuterGFD; - fpOuterGFD = nil; - } - delete fpImageWrapper; - fpImageWrapper = nil; - delete fpOuterWrapper; - fpOuterWrapper = nil; - - return dierr; -} - - -/* - * Flush data to disk. - * - * The only time this really needs to do anything on a disk image file is - * when we have compressed data (NuFX, DDD, .gz, .zip). The uncompressed - * wrappers either don't do anything ("unadorned") or just update some - * header fields (DiskCopy42). - * - * If "mode" is kFlushFastOnly, we only flush the formats that don't really - * need flushing. This is part of a scheme to keep the disk contents in a - * reasonable state on the off chance we crash with a modified file open. - * It also helps the user understand when changes are being made immediately - * vs. when they're written to memory and compressed later. We could just - * refuse to raise the "dirty" flag when modifying "simple" file formats, - * but that would change the meaning of the flag from "something has been - * changed" to "what's in the file and what's in memory differ". I want it - * to be a "dirty" flag. - */ -DIError -DiskImg::FlushImage(FlushMode mode) -{ - DIError dierr = kDIErrNone; - - WMSG2(" DI FlushImage (dirty=%d mode=%d)\n", fDirty, mode); - if (!fDirty) - return kDIErrNone; - if (fpDataGFD == nil) { - /* - * This can happen if we tried to create a disk image but failed, e.g. - * couldn't create the output file because of access denied on the - * directory. There's no data, therefore nothing to flush, but the - * "dirty" flag is set because CreateImageCommon sets it almost - * immediately. - */ - WMSG0(" (disk must've failed during creation)\n"); - fDirty = false; - return kDIErrNone; - } - - if (mode == kFlushFastOnly && - ((fpImageWrapper != nil && !fpImageWrapper->HasFastFlush()) || - (fpOuterWrapper != nil && !fpOuterWrapper->HasFastFlush()) )) - { - WMSG0("DI fast flush requested, but one or both wrappers are slow\n"); - return kDIErrNone; - } - - /* - * Step 1: make sure any local caches have been flushed. - */ - /* (none) */ - - /* - * Step 2: push changes from fpDataGFD to fpWrapperGFD. This will - * cause ImageWrapper to rebuild itself (SHK, DDD, whatever). In - * some cases this amounts to copying the data on top of itself, - * which we can avoid easily. - * - * Embedded volumes don't have wrappers; when you write to an - * embedded volume, it passes straight through to the parent. - * - * (Note to self: formats like NuFX that write to a temp file and then - * rename over the old will close fpWrapperGFD and just access it - * directly. This is bad, because it doesn't allow them to have an - * "outer" format, but it's the way life is. The point is that it's - * okay for fpWrapperGFD to be non-nil but represent a closed file, - * so long as the "Flush" function has it figured out.) - */ - if (fpWrapperGFD != nil) { - WMSG2(" DI flushing data changes to wrapper (fLen=%ld fWrapLen=%ld)\n", - (long) fLength, (long) fWrappedLength); - dierr = fpImageWrapper->Flush(fpWrapperGFD, fpDataGFD, fLength, - &fWrappedLength); - if (dierr != kDIErrNone) { - WMSG1(" ERROR: wrapper flush failed (err=%d)\n", dierr); - return dierr; - } - /* flush the GFD in case it's a Win32 volume with block caching */ - dierr = fpWrapperGFD->Flush(); - } else { - assert(fpParentImg != nil); - } - - /* - * Step 3: if we have an fpOuterGFD, rebuild the file with the data - * in fpWrapperGFD. - */ - if (fpOuterWrapper != nil) { - WMSG1(" DI saving wrapper to outer, fWrapLen=%ld\n", - (long) fWrappedLength); - assert(fpOuterGFD != nil); - dierr = fpOuterWrapper->Save(fpOuterGFD, fpWrapperGFD, - fWrappedLength); - if (dierr != kDIErrNone) { - WMSG1(" ERROR: outer save failed (err=%d)\n", dierr); - return dierr; - } - } - - fDirty = false; - return kDIErrNone; -} - - - -/* - * Given the filename extension and a GFD, figure out what's inside. - * - * The filename extension should give us some idea what to expect: - * SHK, SDK, BXY - ShrinkIt compressed disk image - * GZ - gzip-compressed file (with something else inside) - * ZIP - ZIP archive with a single disk image inside - * DDD - DDD, DDD Pro, or DDD5.0 compressed image - * DSK - DiskCopy 4.2 or DO/PO - * DC - DiskCopy 4.2 (or 6?) - * DC6 - DiskCopy 6 (usually just raw sectors) - * DO, PO, D13, RAW? - DOS-order or ProDOS-order uncompressed - * IMG - Copy ][+ image (unadorned, physical sector order) - * HDV - virtual hard drive image - * NIB, RAW? - nibblized image - * (no extension) uncompressed - * cp-win-vol - our "magic" extension to indicate a Windows logical volume - * - * We can also examine the file length to see if it's a standard size - * (140K, 800K) and look for magic values in the header. - * - * If we can access the contents directly from disk, we do so. It's - * possibly more efficient to load the whole thing into memory, but if - * we have that much memory then the OS should cache it for us. (I have - * some 20MB disk images from my hard drive that shouldn't be loaded - * in their entirety. Certainly don't want to load a 512MB CFFA image.) - * - * On input, the following fields must be set: - * fpWrapperGFD - GenericFD for the file pointed to by "pathname" (or for a - * memory buffer if this is a sub-volume) - * - * On success, the following fields will be set: - * fWrappedLength, fOuterLength - set appropriately - * fpDataGFD - GFD for the raw data, possibly just a GFDGFD with an offset - * fLength - length of unadorned data in the file, or the length of - * data stored in fBuffer (test for fBuffer!=nil) - * fFileFormat - set to the overall file format, mostly interesting - * for identification of the file "wrapper" - * fPhysicalFormat - set to the type of data this holds - * (maybe) fOrder - set when the file format or extension dictates, e.g. - * 2MG or *.po; not always reliable - * (maybe) fDOSVolumeNum - set to DOS volume number from wrapper - * - * This may set fReadOnly if one of the wrappers looks okay but is reporting - * a bad checksum. - */ -DIError -DiskImg::AnalyzeImageFile(const char* pathName, char fssep) -{ - DIError dierr = kDIErrNone; - FileFormat probableFormat; - bool reliableExt; - const char* ext = FindExtension(pathName, fssep); - char* extBuf = nil; // uses malloc/free - bool needExtFromOuter = false; - - if (ext != nil) { - assert(*ext == '.'); - ext++; - } else - ext = ""; - - WMSG1(" DI AnalyzeImageFile ext='%s'\n", ext); - - /* sanity check: nobody should have configured these yet */ - assert(fOuterFormat == kOuterFormatUnknown); - assert(fFileFormat == kFileFormatUnknown); - assert(fOrder == kSectorOrderUnknown); - assert(fFormat == kFormatUnknown); - fLength = -1; - dierr = fpWrapperGFD->Seek(0, kSeekEnd); - if (dierr != kDIErrNone) { - WMSG0(" DI Couldn't seek to end of wrapperGFD\n"); - goto bail; - } - fWrappedLength = fOuterLength = fpWrapperGFD->Tell(); - - /* quick test for zero-length files */ - if (fWrappedLength == 0) - return kDIErrUnrecognizedFileFmt; - - /* - * Start by checking for a zip/gzip "wrapper wrapper". We want to strip - * that away before we do anything else. Because web sites tend to - * gzip everything in sight whether it needs it or not, we treat this - * as a special case and assume that anything could be inside. - * - * Some cases are difficult to handle, e.g. ".SDK", since NufxLib - * doesn't let us open an archive that is sitting in memory. - * - * We could also handle disk images stored as ordinary files stored - * inside SHK. Not much point in handling multiple files down at - * this level though. - */ - if (strcasecmp(ext, "gz") == 0 && - OuterGzip::Test(fpWrapperGFD, fOuterLength) == kDIErrNone) - { - WMSG0(" DI found gz outer wrapper\n"); - - fpOuterWrapper = new OuterGzip(); - if (fpOuterWrapper == nil) { - dierr = kDIErrMalloc; - goto bail; - } - fOuterFormat = kOuterFormatGzip; - - /* drop the ".gz" and get down to the next extension */ - ext = ""; - extBuf = strdup(pathName); - if (extBuf != nil) { - char* localExt; - - localExt = (char*) FindExtension(extBuf, fssep); - if (localExt != nil) - *localExt = '\0'; - localExt = (char*) FindExtension(extBuf, fssep); - if (localExt != nil) { - ext = localExt; - assert(*ext == '.'); - ext++; - } - } - WMSG1(" DI after gz, ext='%s'\n", ext == nil ? "(nil)" : ext); - - } else if (strcasecmp(ext, "zip") == 0) { - dierr = OuterZip::Test(fpWrapperGFD, fOuterLength); - if (dierr != kDIErrNone) - goto bail; - - WMSG0(" DI found ZIP outer wrapper\n"); - - fpOuterWrapper = new OuterZip(); - if (fpOuterWrapper == nil) { - dierr = kDIErrMalloc; - goto bail; - } - fOuterFormat = kOuterFormatZip; - - needExtFromOuter = true; - - } else { - fOuterFormat = kOuterFormatNone; - } - - /* finish up outer wrapper stuff */ - if (fOuterFormat != kOuterFormatNone) { - GenericFD* pNewGFD = nil; - dierr = fpOuterWrapper->Load(fpWrapperGFD, fOuterLength, fReadOnly, - &fWrappedLength, &pNewGFD); - if (dierr != kDIErrNone) { - WMSG0(" DI outer prep failed\n"); - /* extensions are "reliable", so failure is unavoidable */ - goto bail; - } - - /* Load() sets this */ - if (fpOuterWrapper->IsDamaged()) { - AddNote(kNoteWarning, "The zip/gzip wrapper appears to be damaged."); - fReadOnly = true; - } - - /* shift GFDs */ - fpOuterGFD = fpWrapperGFD; - fpWrapperGFD = pNewGFD; - - if (needExtFromOuter) { - ext = fpOuterWrapper->GetExtension(); - if (ext == nil) - ext = ""; - } - } - - /* - * Try to figure out what format the file is in. - * - * First pass, try only what the filename says it is. This way, if - * two file formats look alike, we have a good chance of getting it - * right. - * - * The "Test" functions have the complete file at their disposal. The - * file's length is stored in "fWrappedLength" for convenience. - */ - reliableExt = false; - probableFormat = kFileFormatUnknown; - if (strcasecmp(ext, "2mg") == 0 || strcasecmp(ext, "2img") == 0) { - reliableExt = true; - if (Wrapper2MG::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) - probableFormat = kFileFormat2MG; - } else if (strcasecmp(ext, "shk") == 0 || strcasecmp(ext, "sdk") == 0 || - strcasecmp(ext, "bxy") == 0) - { - DIError dierr2; - reliableExt = true; - dierr2 = WrapperNuFX::Test(fpWrapperGFD, fWrappedLength); - if (dierr2 == kDIErrNone) - probableFormat = kFileFormatNuFX; - else if (dierr2 == kDIErrFileArchive) { - WMSG0(" AnalyzeImageFile thinks it found a NuFX file archive\n"); - dierr = dierr2; - goto bail; - } - } else if (strcasecmp(ext, "hdv") == 0) { - /* usually just a "raw" disk, but check for Sim //e */ - if (WrapperSim2eHDV::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) - probableFormat = kFileFormatSim2eHDV; - - /* ProDOS .hdv volumes can expand */ - fExpandable = true; - } else if (strcasecmp(ext, "dsk") == 0 || strcasecmp(ext, "dc") == 0) { - /* might be DiskCopy */ - if (WrapperDiskCopy42::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) - probableFormat = kFileFormatDiskCopy42; - } else if (strcasecmp(ext, "ddd") == 0) { - /* do this after compressed formats but before unadorned */ - reliableExt = true; - if (WrapperDDD::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) - probableFormat = kFileFormatDDD; - } else if (strcasecmp(ext, "app") == 0) { - reliableExt = true; - if (WrapperTrackStar::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) - probableFormat = kFileFormatTrackStar; - } else if (strcasecmp(ext, "fdi") == 0) { - reliableExt = true; - if (WrapperFDI::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) - probableFormat = kFileFormatFDI; - } else if (strcasecmp(ext, "img") == 0) { - if (WrapperUnadornedSector::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) - { - probableFormat = kFileFormatUnadorned; - fPhysical = kPhysicalFormatSectors; - fOrder = kSectorOrderPhysical; - } - } else if (strcasecmp(ext, "nib") == 0 || strcasecmp(ext, "raw") == 0) { - if (WrapperUnadornedNibble::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) - { - probableFormat = kFileFormatUnadorned; - fPhysical = kPhysicalFormatNib525_6656; - /* figure out NibbleFormat later */ - } - } else if (strcasecmp(ext, "do") == 0 || strcasecmp(ext, "po") == 0 || - strcasecmp(ext, "d13") == 0 || strcasecmp(ext, "dc6") == 0) - { - if (WrapperUnadornedSector::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) - { - probableFormat = kFileFormatUnadorned; - fPhysical = kPhysicalFormatSectors; - if (strcasecmp(ext, "do") == 0 || strcasecmp(ext, "d13") == 0) - fOrder = kSectorOrderDOS; - else - fOrder = kSectorOrderProDOS; // po, dc6 - WMSG1(" DI guessing order is %d by extension\n", fOrder); - } - } else if (strcasecmp(ext, "cp-win-vol") == 0) { - /* this is a Windows logical volume */ - reliableExt = true; - probableFormat = kFileFormatUnadorned; - fPhysical = kPhysicalFormatSectors; - fOrder = kSectorOrderProDOS; - } else { - /* no match on the filename extension; start guessing */ - } - - if (probableFormat != kFileFormatUnknown) { - /* - * Found a match. Use "probableFormat" to open the file. - */ - WMSG1(" DI scored hit on extension '%s'\n", ext); - } else { - /* - * Didn't work. If the file extension was marked "reliable", then - * either we have the wrong extension on the file, or the contents - * are damaged. - * - * If the extension isn't reliable, or simply absent, then we have - * to probe through the formats we know and just hope for the best. - * - * If the "test" function returns with a checksum failure, we take - * it to mean that the format was positively identified, but the - * data inside is corrupted. This results in an immediate return - * with the checksum failure noted. Only a few wrapper formats - * have checksums embedded. (The "test" functions should only - * be looking at header checksums.) - */ - if (reliableExt) { - WMSG1(" DI file extension '%s' did not match contents\n", ext); - dierr = kDIErrBadFileFormat; - goto bail; - } else { - WMSG1(" DI extension '%s' not useful, probing formats\n", ext); - dierr = WrapperNuFX::Test(fpWrapperGFD, fWrappedLength); - if (dierr == kDIErrNone) { - probableFormat = kFileFormatNuFX; - goto gotit; - } else if (dierr == kDIErrFileArchive) - goto bail; // we know it's NuFX, we know we can't use it - else if (dierr == kDIErrBadChecksum) - goto bail; // right file type, bad data - - dierr = WrapperDiskCopy42::Test(fpWrapperGFD, fWrappedLength); - if (dierr == kDIErrNone) { - probableFormat = kFileFormatDiskCopy42; - goto gotit; - } else if (dierr == kDIErrBadChecksum) - goto bail; // right file type, bad data - - if (Wrapper2MG::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) { - probableFormat = kFileFormat2MG; - } else if (WrapperDDD::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) { - probableFormat = kFileFormatDDD; - } else if (WrapperSim2eHDV::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) - { - probableFormat = kFileFormatSim2eHDV; - } else if (WrapperTrackStar::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) - { - probableFormat = kFileFormatTrackStar; - } else if (WrapperFDI::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) - { - probableFormat = kFileFormatFDI; - } else if (WrapperUnadornedNibble::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) { - probableFormat = kFileFormatUnadorned; - fPhysical = kPhysicalFormatNib525_6656; // placeholder - } else if (WrapperUnadornedSector::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) { - probableFormat = kFileFormatUnadorned; - fPhysical = kPhysicalFormatSectors; - } -gotit: ; - } - } - - /* - * Either we recognize it or we don't. Finish opening the file by - * setting up "fLength" and "fPhysical" values, extracting data - * into a memory buffer if necessary. fpDataGFD is set up by the - * "prep" function. - * - * If we're lucky, this will also configure "fOrder" for us, which is - * important when we can't recognize the filesystem format (for correct - * operation of disk tools). - */ - switch (probableFormat) { - case kFileFormat2MG: - fpImageWrapper = new Wrapper2MG(); - break; - case kFileFormatDiskCopy42: - fpImageWrapper = new WrapperDiskCopy42(); - break; - case kFileFormatSim2eHDV: - fpImageWrapper = new WrapperSim2eHDV(); - break; - case kFileFormatTrackStar: - fpImageWrapper = new WrapperTrackStar(); - break; - case kFileFormatFDI: - fpImageWrapper = new WrapperFDI(); - fReadOnly = true; // writing to FDI not yet supported - break; - case kFileFormatNuFX: - fpImageWrapper = new WrapperNuFX(); - ((WrapperNuFX*)fpImageWrapper)->SetCompressType( - (NuThreadFormat) fNuFXCompressType); - break; - case kFileFormatDDD: - fpImageWrapper = new WrapperDDD(); - break; - case kFileFormatUnadorned: - if (IsSectorFormat(fPhysical)) - fpImageWrapper = new WrapperUnadornedSector(); - else if (IsNibbleFormat(fPhysical)) - fpImageWrapper = new WrapperUnadornedNibble(); - else { - assert(false); - } - break; - default: - WMSG0(" DI couldn't figure out the file format\n"); - dierr = kDIErrUnrecognizedFileFmt; - break; - } - if (fpImageWrapper != nil) { - assert(fpDataGFD == nil); - dierr = fpImageWrapper->Prep(fpWrapperGFD, fWrappedLength, fReadOnly, - &fLength, &fPhysical, &fOrder, &fDOSVolumeNum, - &fpBadBlockMap, &fpDataGFD); - } else { - /* could be a mem alloc failure that didn't set dierr */ - if (dierr == kDIErrNone) - dierr = kDIErrGeneric; - } - - if (dierr != kDIErrNone) { - WMSG1(" DI wrapper prep failed (err=%d)\n", dierr); - goto bail; - } - - /* check for non-fatal checksum failures, e.g. DiskCopy42 */ - if (fpImageWrapper->IsDamaged()) { - AddNote(kNoteWarning, "File checksum didn't match."); - fReadOnly = true; - } - - fFileFormat = probableFormat; - - assert(fLength >= 0); - assert(fpDataGFD != nil); - assert(fOuterFormat != kOuterFormatUnknown); - assert(fFileFormat != kFileFormatUnknown); - assert(fPhysical != kPhysicalFormatUnknown); - -bail: - free(extBuf); - return dierr; -} - - -/* - * Try to figure out what we're looking at. - * - * Returns an error if we don't think this is even a disk image. If we - * just can't figure it out, we return success but with the format value - * set to "unknown". This gives the caller a chance to use "override" - * to help us find our way. - * - * On entry: - * fpDataGFD, fLength, and fFileFormat are defined - * fSectorPairing is specified - * fOrder has a semi-reliable guess at sector ordering - * On exit: - * fOrder and fFormat are set to the best of our ability - * fNumTracks, fNumSectPerTrack, and fNumBlocks are set - * fHasSectors, fHasTracks, and fHasNibbles are set - * fFileSysOrder is set - * fpNibbleDescr will be set for nibble images - */ -DIError -DiskImg::AnalyzeImage(void) -{ - assert(fLength >= 0); - assert(fpDataGFD != nil); - assert(fFileFormat != kFileFormatUnknown); - assert(fPhysical != kPhysicalFormatUnknown); - assert(fFormat == kFormatUnknown); - assert(fFileSysOrder == kSectorOrderUnknown); - assert(fNumTracks == -1); - assert(fNumSectPerTrack == -1); - assert(fNumBlocks == -1); - if (fpDataGFD == nil) - return kDIErrInternal; - - /* - * Figure out how many tracks and sectors the image has. - * - * For an odd-sized ProDOS image, there will be no tracks and sectors. - */ - if (IsSectorFormat(fPhysical)) { - if (!fLength) { - WMSG0(" DI zero-length disk images not allowed\n"); - return kDIErrOddLength; - } - - if (fLength == kD13Length) { - /* 13-sector .d13 image */ - fHasSectors = true; - fNumSectPerTrack = 13; - fNumTracks = kTrackCount525; - assert(!fHasBlocks); - } else if (fLength % (16 * kSectorSize) == 0) { - /* looks like a collection of 16-sector tracks */ - fHasSectors = true; - - fNumSectPerTrack = 16; - fNumTracks = (int) (fLength / (fNumSectPerTrack * kSectorSize)); - - /* sector pairing effectively cuts #of tracks in half */ - if (fSectorPairing) { - if ((fNumTracks & 0x01) != 0) { - WMSG0(" DI error: bad attempt at sector pairing\n"); - assert(false); - fSectorPairing = false; - } - } - - if (fSectorPairing) - fNumTracks /= 2; - } else { - if (fSectorPairing) { - WMSG1("GLITCH: sector pairing enabled, but fLength=%ld\n", - (long) fLength); - return kDIErrOddLength; - } - - assert(fNumTracks == -1); - assert(fNumSectPerTrack == -1); - assert((fLength % kBlockSize) == 0); - - fHasBlocks = true; - fNumBlocks = (long) (fLength / kBlockSize); - } - } else if (IsNibbleFormat(fPhysical)) { - fHasNibbles = fHasSectors = true; - - /* - * Figure out if it's 13-sector or 16-sector (or garbage). We - * have to make an assessment of the entire disk so we can declare - * it to be 13-sector or 16-sector, which is useful for DiskFS - * which will want to scan for DOS VTOCs and other goodies. We - * also want to provide a default NibbleDescr. - * - * Failing that, we still allow it to be opened for raw track access. - * - * This also sets fNumTracks, which could be more than 35 if we're - * working with a TrackStar or FDI image. - */ - DIError dierr; - dierr = AnalyzeNibbleData(); // sets nibbleDescr and DOS vol num - if (dierr == kDIErrNone) { - assert(fpNibbleDescr != nil); - fNumSectPerTrack = fpNibbleDescr->numSectors; - fOrder = kSectorOrderPhysical; - - if (!fReadOnly && !fpNibbleDescr->dataVerifyChecksum) { - WMSG0("DI nibbleDescr does not verify data checksum, disabling writes\n"); - AddNote(kNoteInfo, - "Sectors use non-standard data checksums; writing disabled."); - fReadOnly = true; - } - } else { - //assert(fpNibbleDescr == nil); - fNumSectPerTrack = -1; - fOrder = kSectorOrderPhysical; - fHasSectors = false; - } - } else { - WMSG1("Unsupported physical %d\n", fPhysical); - assert(false); - return kDIErrGeneric; - } - - /* - * Compute the number of blocks. For a 13-sector disk, block access - * is not possible. - * - * For nibble formats, we have to base the block count on the number - * of sectors rather than the file length. - */ - if (fHasSectors) { - assert(fNumSectPerTrack > 0); - if ((fNumSectPerTrack & 0x01) == 0) { - /* not a 13-sector disk, so define blocks in terms of sectors */ - /* (effects of sector pairing are already taken into account) */ - fHasBlocks = true; - fNumBlocks = (fNumTracks * fNumSectPerTrack) / 2; - } - } else if (fHasBlocks) { - if ((fLength % kBlockSize) == 0) { - /* not sector-oriented, so define blocks based on length */ - fHasBlocks = true; - fNumBlocks = (long) (fLength / kBlockSize); - - if (fSectorPairing) { - if ((fNumBlocks & 0x01) != 0) { - WMSG0(" DI error: bad attempt at sector pairing (blk)\n"); - assert(false); - fSectorPairing = false; - } else - fNumBlocks /= 2; - } - - } else { - assert(false); - return kDIErrGeneric; - } - } else if (fHasNibbles) { - assert(fNumBlocks == -1); - } else { - WMSG0(" DI none of fHasSectors/fHasBlocks/fHasNibbles are set\n"); - assert(false); - return kDIErrInternal; - } - - /* - * We've got the track/sector/block layout sorted out; now figure out - * what kind of filesystem we're dealing with. - */ - AnalyzeImageFS(); - - WMSG4(" DI AnalyzeImage tracks=%ld sectors=%d blocks=%ld fileSysOrder=%d\n", - fNumTracks, fNumSectPerTrack, fNumBlocks, fFileSysOrder); - WMSG3(" hasBlocks=%d hasSectors=%d hasNibbles=%d\n", - fHasBlocks, fHasSectors, fHasNibbles); - - return kDIErrNone; -} - -/* - * Try to figure out what filesystem exists on this disk image. - * - * We want to test for DOS before ProDOS, because sometimes they overlap (e.g. - * 800K ProDOS disk with five 160K DOS volumes on it). - * - * Sets fFormat, fOrder, and fFileSysOrder. - */ -void -DiskImg::AnalyzeImageFS(void) -{ - /* - * In some circumstances it would be useful to have a set describing - * what filesystems we might expect to find, e.g. we're not likely to - * encounter RDOS embedded in a CF card. - */ - if (DiskFSMacPart::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - assert(fFormat == kFormatMacPart); - WMSG1(" DI found MacPart, order=%d\n", fOrder); - } else if (DiskFSMicroDrive::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - assert(fFormat == kFormatMicroDrive); - WMSG1(" DI found MicroDrive, order=%d\n", fOrder); - } else if (DiskFSFocusDrive::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - assert(fFormat == kFormatFocusDrive); - WMSG1(" DI found FocusDrive, order=%d\n", fOrder); - } else if (DiskFSCFFA::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - // The CFFA format doesn't have a partition map, but we do insist - // on finding multiple volumes. It needs to come after MicroDrive, - // because a disk formatted for CFFA then subsequently partitioned - // for MicroDrive will still look like valid CFFA unless you zero - // out the blocks. - assert(fFormat == kFormatCFFA4 || fFormat == kFormatCFFA8); - WMSG1(" DI found CFFA, order=%d\n", fOrder); - } else if (DiskFSFAT::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - // This is really just a trap to catch CFFA cards that were formatted - // for ProDOS and then re-formatted for MSDOS. As such it needs to - // come before the ProDOS test. It only works on larger volumes, - // and can be overridden, so it's pretty safe. - assert(fFormat == kFormatMSDOS); - WMSG1(" DI found MSDOS, order=%d\n", fOrder); - } else if (DiskFSDOS33::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - assert(fFormat == kFormatDOS32 || fFormat == kFormatDOS33); - WMSG1(" DI found DOS3.x, order=%d\n", fOrder); - if (fNumSectPerTrack == 13) - fFormat = kFormatDOS32; - } else if (DiskFSUNIDOS::TestWideFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - // Should only succeed on 400K embedded chunks. - assert(fFormat == kFormatDOS33); - fNumSectPerTrack = 32; - fNumTracks /= 2; - WMSG1(" DI found 'wide' DOS3.3, order=%d\n", fOrder); - } else if (DiskFSUNIDOS::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - assert(fFormat == kFormatUNIDOS); - fNumSectPerTrack = 32; - fNumTracks /= 2; - WMSG1(" DI found UNIDOS, order=%d\n", fOrder); - } else if (DiskFSOzDOS::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - assert(fFormat == kFormatOzDOS); - fNumSectPerTrack = 32; - fNumTracks /= 2; - WMSG1(" DI found OzDOS, order=%d\n", fOrder); - } else if (DiskFSProDOS::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - assert(fFormat == kFormatProDOS); - WMSG1(" DI found ProDOS, order=%d\n", fOrder); - } else if (DiskFSPascal::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - assert(fFormat == kFormatPascal); - WMSG1(" DI found Pascal, order=%d\n", fOrder); - } else if (DiskFSCPM::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - assert(fFormat == kFormatCPM); - WMSG1(" DI found CP/M, order=%d\n", fOrder); - } else if (DiskFSRDOS::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - assert(fFormat == kFormatRDOS33 || - fFormat == kFormatRDOS32 || - fFormat == kFormatRDOS3); - WMSG1(" DI found RDOS 3.3, order=%d\n", fOrder); - } else if (DiskFSHFS::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - assert(fFormat == kFormatMacHFS); - WMSG1(" DI found HFS, order=%d\n", fOrder); - } else if (DiskFSGutenberg::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) - { - assert(fFormat == kFormatGutenberg); - WMSG1(" DI found Gutenberg, order=%d\n", fOrder); - } else { - fFormat = kFormatUnknown; - WMSG1(" DI no recognizeable filesystem found (fOrder=%d)\n", - fOrder); - } - - fFileSysOrder = CalcFSSectorOrder(); -} - - -/* - * Override the format determined by the analyzer. - * - * If they insist on the presence of a valid filesystem, check to make sure - * that filesystem actually exists. - * - * Note that this does not allow overriding the file structure, which must - * be clearly identifiable to be at all useful. If the file has no "wrapper" - * structure, the "unadorned" format should be specified, and the contents - * identified by the PhysicalFormat. - */ -DIError -DiskImg::OverrideFormat(PhysicalFormat physical, FSFormat format, - SectorOrder order) -{ - DIError dierr = kDIErrNone; - SectorOrder newOrder; - FSFormat newFormat; - - WMSG3(" DI override: physical=%d format=%d order=%d\n", - physical, format, order); - - if (!IsSectorFormat(physical) && !IsNibbleFormat(physical)) - return kDIErrUnsupportedPhysicalFmt; - - /* don't allow forcing physical format change */ - if (physical != fPhysical) - return kDIErrInvalidArg; - - /* optimization */ - if (physical == fPhysical && format == fFormat && order == fOrder) { - WMSG0(" DI override matches existing, ignoring\n"); - return kDIErrNone; - } - - newOrder = order; - newFormat = format; - - switch (format) { - case kFormatDOS33: - case kFormatDOS32: - dierr = DiskFSDOS33::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); - // Go ahead and allow the override even if the DOS version is wrong. - // So long as the sector count is correct, it's okay. - break; - case kFormatProDOS: - dierr = DiskFSProDOS::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); - break; - case kFormatPascal: - dierr = DiskFSPascal::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); - break; - case kFormatMacHFS: - dierr = DiskFSHFS::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); - break; - case kFormatUNIDOS: - dierr = DiskFSUNIDOS::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); - break; - case kFormatOzDOS: - dierr = DiskFSOzDOS::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); - break; - case kFormatCFFA4: - case kFormatCFFA8: - dierr = DiskFSCFFA::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); - // So long as it's CFFA, we allow the user to force it to be 4-mode - // or 8-mode. Don't require newFormat==format. - break; - case kFormatMacPart: - dierr = DiskFSMacPart::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); - break; - case kFormatMicroDrive: - dierr = DiskFSMicroDrive::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); - break; - case kFormatFocusDrive: - dierr = DiskFSFocusDrive::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); - break; - case kFormatCPM: - dierr = DiskFSCPM::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); - break; - case kFormatMSDOS: - dierr = DiskFSFAT::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); - break; - case kFormatRDOS33: - case kFormatRDOS32: - case kFormatRDOS3: - dierr = DiskFSRDOS::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); - if (newFormat != format) - dierr = kDIErrFilesystemNotFound; // found RDOS, but wrong flavor - break; - case kFormatGenericPhysicalOrd: - case kFormatGenericProDOSOrd: - case kFormatGenericDOSOrd: - case kFormatGenericCPMOrd: - /* no discussion possible, since there's no FS to validate */ - newFormat = format; - newOrder = order; - break; - case kFormatUnknown: - /* only valid in rare situations, e.g. CFFA CreatePlaceholder */ - newFormat = format; - newOrder = order; - break; - default: - dierr = kDIErrUnsupportedFSFmt; - break; - } - - if (dierr != kDIErrNone) { - WMSG0(" DI override failed\n"); - goto bail; - } - - /* - * We passed in "order" to TestFS. If it came back with something - * different, it means that it didn't like the new order value even - * when "leniency" was granted. - */ - if (newOrder != order) { - dierr = kDIErrBadOrdering; - goto bail; - } - - fFormat = format; - fOrder = newOrder; - fFileSysOrder = CalcFSSectorOrder(); - - WMSG0(" DI override accepted\n"); - -bail: - return dierr; -} - -/* - * Figure out the sector ordering for this filesystem, so we can decide - * how the sectors need to be re-arranged when we're reading them. - * - * If the value returned by this function matches fOrder, then no swapping - * will be done. - * - * NOTE: this table is redundant with some knowledge embedded in the - * individual "TestFS" functions. - */ -DiskImg::SectorOrder -DiskImg::CalcFSSectorOrder(void) const -{ - /* in the absence of information, just leave it alone */ - if (fFormat == kFormatUnknown || fOrder == kSectorOrderUnknown) { - WMSG0(" DI WARNING: FindSectorOrder but format not known\n"); - return fOrder; - } - - assert(fOrder == kSectorOrderPhysical || fOrder == kSectorOrderCPM || - fOrder == kSectorOrderProDOS || fOrder == kSectorOrderDOS); - - switch (fFormat) { - case kFormatGenericPhysicalOrd: - case kFormatRDOS32: - case kFormatRDOS3: - return kSectorOrderPhysical; - - case kFormatGenericDOSOrd: - case kFormatDOS33: - case kFormatDOS32: - case kFormatUNIDOS: - case kFormatOzDOS: - case kFormatGutenberg: - return kSectorOrderDOS; - - case kFormatGenericCPMOrd: - case kFormatCPM: - return kSectorOrderCPM; - - case kFormatGenericProDOSOrd: - case kFormatProDOS: - case kFormatRDOS33: - case kFormatPascal: - case kFormatMacHFS: - case kFormatMacMFS: - case kFormatLisa: - case kFormatMSDOS: - case kFormatISO9660: - case kFormatCFFA4: - case kFormatCFFA8: - case kFormatMacPart: - case kFormatMicroDrive: - case kFormatFocusDrive: - return kSectorOrderProDOS; - - default: - assert(false); - return fOrder; - } -} - -/* - * Based on the disk format, figure out if we should prefer blocks or - * sectors when examining disk contents. - */ -bool -DiskImg::ShowAsBlocks(void) const -{ - if (!fHasBlocks) - return false; - - /* in the absence of information, assume sectors */ - if (fFormat == kFormatUnknown) { - if (fOrder == kSectorOrderProDOS) - return true; - else - return false; - } - - switch (fFormat) { - case kFormatGenericPhysicalOrd: - case kFormatGenericDOSOrd: - case kFormatDOS33: - case kFormatDOS32: - case kFormatRDOS3: - case kFormatRDOS33: - case kFormatUNIDOS: - case kFormatOzDOS: - case kFormatGutenberg: - return false; - - case kFormatGenericProDOSOrd: - case kFormatGenericCPMOrd: - case kFormatProDOS: - case kFormatPascal: - case kFormatMacHFS: - case kFormatMacMFS: - case kFormatLisa: - case kFormatCPM: - case kFormatMSDOS: - case kFormatISO9660: - case kFormatCFFA4: - case kFormatCFFA8: - case kFormatMacPart: - case kFormatMicroDrive: - case kFormatFocusDrive: - return true; - - default: - assert(false); - return false; - } -} - - -/* - * Format an image with the requested fileystem format. This only works if - * the matching DiskFS supports formatting of disks. - */ -DIError -DiskImg::FormatImage(FSFormat format, const char* volName) -{ - DIError dierr = kDIErrNone; - DiskFS* pDiskFS = nil; - FSFormat savedFormat; - - WMSG1(" DI FormatImage '%s'\n", volName); - - /* - * Open a temporary DiskFS for the requested format. We do this via the - * standard OpenAppropriate call, so we temporarily switch our format - * out. (We will eventually replace it, but we want to make sure that - * local error handling works correctly, so we restore it for now.) - */ - savedFormat = fFormat; - fFormat = format; - pDiskFS = OpenAppropriateDiskFS(false); - fFormat = savedFormat; - - if (pDiskFS == nil) { - dierr = kDIErrUnsupportedFSFmt; - goto bail; - } - - dierr = pDiskFS->Format(this, volName); - if (dierr != kDIErrNone) - goto bail; - - WMSG0("DI format successful\n"); - fFormat = format; - -bail: - delete pDiskFS; - return dierr; -} - -/* - * Clear an image to zeros, usually done as a prelude to a higher-level format. - * - * BUG: this should also handle the track/sector case. - * - * HEY: this is awfully slow on large disks... should have some sort of - * optimized path that just writes to the GFD or something. Maybe even just - * a "ZeroBlock" instead of "WriteBlock" so we can memset instead of memcpy? - */ -DIError -DiskImg::ZeroImage(void) -{ - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlockSize]; - long block; - - WMSG1(" DI ZeroImage (%ld blocks)\n", GetNumBlocks()); - memset(blkBuf, 0, sizeof(blkBuf)); - - for (block = 0; block < GetNumBlocks(); block++) { - dierr = WriteBlock(block, blkBuf); - if (dierr != kDIErrNone) - break; - } - - return dierr; -} - - -/* - * Set the "scan progress" function. - * - * We want to use the same function for our sub-volumes too. - */ -void -DiskImg::SetScanProgressCallback(ScanProgressCallback func, void* cookie) -{ - if (fpParentImg != nil) { - /* unexpected, but perfectly okay */ - DebugBreak(); - } - - fpScanProgressCallback = func; - fScanProgressCookie = cookie; - fScanCount = 0; - fScanMsg[0] = '\0'; - fScanLastMsgWhen = time(nil); -} - -/* - * Update the progress. Call with a string at the start of a volume, then - * call with a NULL pointer every time we add a file. - */ -bool -DiskImg::UpdateScanProgress(const char* newStr) -{ - ScanProgressCallback func = fpScanProgressCallback; - DiskImg* pImg = this; - bool result = true; - - /* search up the tree to find a progress updater */ - while (func == nil) { - pImg = pImg->fpParentImg; - if (pImg == nil) - return result; // none defined, bail out - func = pImg->fpScanProgressCallback; - } - - time_t now = time(nil); - - if (newStr == NULL) { - fScanCount++; - //if ((fScanCount % 100) == 0) - if (fScanLastMsgWhen != now) { - result = (*func)(fScanProgressCookie, - fScanMsg, fScanCount); - fScanLastMsgWhen = now; - } - } else { - fScanCount = 0; - strncpy(fScanMsg, newStr, sizeof(fScanMsg)); - fScanMsg[sizeof(fScanMsg)-1] = '\0'; - result = (*func)(fScanProgressCookie, fScanMsg, - fScanCount); - fScanLastMsgWhen = now; - } - - return result; -} - - -/* - * ========================================================================== - * Block/track/sector I/O - * ========================================================================== - */ - -/* - * Handle sector order conversions. - */ -DIError -DiskImg::CalcSectorAndOffset(long track, int sector, SectorOrder imageOrder, - SectorOrder fsOrder, di_off_t* pOffset, int* pNewSector) -{ - if (!fHasSectors) - return kDIErrUnsupportedAccess; - - /* - * Sector order conversions. No table is needed for Copy ][+ format, - * which is equivalent to "physical". - */ - static const int raw2dos[16] = { - 0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15 - }; - static const int dos2raw[16] = { - 0, 13, 11, 9, 7, 5, 3, 1, 14, 12, 10, 8, 6, 4, 2, 15 - }; - static const int raw2prodos[16] = { - 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 - }; - static const int prodos2raw[16] = { - 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 - }; - static const int raw2cpm[16] = { - 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5 - }; - static const int cpm2raw[16] = { - 0, 3, 6, 9, 12, 15, 2, 5, 8, 11, 14, 1, 4, 7, 10, 13 - }; - - if (track < 0 || track >= fNumTracks) { - WMSG1(" DI read invalid track %ld\n", track); - return kDIErrInvalidTrack; - } - if (sector < 0 || sector >= fNumSectPerTrack) { - WMSG1(" DI read invalid sector %d\n", sector); - return kDIErrInvalidSector; - } - - di_off_t offset; - int newSector = -1; - - /* - * 16-sector disks write sectors in ascending order and then remap - * them with a translation table. - */ - if (fNumSectPerTrack == 16 || fNumSectPerTrack == 32) { - if (fSectorPairing) { - assert(fSectorPairOffset == 0 || fSectorPairOffset == 1); - // this pushes "track" beyond fNumTracks - track *= 2; - if (sector >= 16) { - track++; - sector -= 16; - } - offset = track * fNumSectPerTrack * kSectorSize; - - sector = sector * 2 + fSectorPairOffset; - if (sector >= 16) { - offset += 16*kSectorSize; - sector -= 16; - } - } else { - offset = track * fNumSectPerTrack * kSectorSize; - if (sector >= 16) { - offset += 16*kSectorSize; - sector -= 16; - } - } - assert(sector >= 0 && sector < 16); - - /* convert request to "raw" sector number */ - switch (fsOrder) { - case kSectorOrderProDOS: - newSector = prodos2raw[sector]; - break; - case kSectorOrderDOS: - newSector = dos2raw[sector]; - break; - case kSectorOrderCPM: - newSector = cpm2raw[sector]; - break; - case kSectorOrderPhysical: // used for Copy ][+ - newSector = sector; - break; - case kSectorOrderUnknown: - // should never happen; fall through to "default" - default: - assert(false); - newSector = sector; - break; - } - - /* convert "raw" request to the image's ordering */ - switch (imageOrder) { - case kSectorOrderProDOS: - newSector = raw2prodos[newSector]; - break; - case kSectorOrderDOS: - newSector = raw2dos[newSector]; - break; - case kSectorOrderCPM: - newSector = raw2cpm[newSector]; - break; - case kSectorOrderPhysical: - //newSector = newSector; - break; - case kSectorOrderUnknown: - // should never happen; fall through to "default" - default: - assert(false); - //newSector = newSector; - break; - } - - if (imageOrder == fsOrder) { - assert(sector == newSector); - } - - offset += newSector * kSectorSize; - } else if (fNumSectPerTrack == 13) { - /* sector skew has no meaning, so assume no translation */ - offset = track * fNumSectPerTrack * kSectorSize; - newSector = sector; - offset += newSector * kSectorSize; - if (imageOrder != fsOrder) { - /* translation expected */ - WMSG2("NOTE: CalcSectorAndOffset for nspt=13 with img=%d fs=%d\n", - imageOrder, fsOrder); - } - } else { - assert(false); // should not be here - - /* try to do something reasonable */ - assert(imageOrder == fsOrder); - offset = (di_off_t)track * fNumSectPerTrack * kSectorSize; - offset += sector * kSectorSize; - } - - *pOffset = offset; - *pNewSector = newSector; - return kDIErrNone; -} - -/* - * Determine whether an image uses a linear mapping. This allows us to - * optimize block reads & writes, very useful when dealing with logical - * volumes under Windows (which also use 512-byte blocks). - * - * The "imageOrder" argument usually comes from fOrder, and "fsOrder" - * comes from "fFileSysOrder". - */ -inline bool -DiskImg::IsLinearBlocks(SectorOrder imageOrder, SectorOrder fsOrder) -{ - /* - * Any time fOrder==fFileSysOrder, we know that we have a linear - * mapping. This holds true for reading ProDOS blocks from a ".po" - * file or reading DOS sectors from a ".do" file. - */ - return (IsSectorFormat(fPhysical) && fHasBlocks && - imageOrder == fsOrder); -} - -/* - * Read the specified track and sector, adjusting for sector ordering as - * appropriate. - * - * Copies 256 bytes into "*buf". - * - * Returns 0 on success, nonzero on failure. - */ -DIError -DiskImg::ReadTrackSectorSwapped(long track, int sector, void* buf, - SectorOrder imageOrder, SectorOrder fsOrder) -{ - DIError dierr; - di_off_t offset; - int newSector = -1; - - if (buf == nil) - return kDIErrInvalidArg; - -#if 0 // Pre-d13 - if (fNumSectPerTrack == 13) { - /* no sector skewing possible for 13-sector disks */ - assert(fHasNibbles); - - return ReadNibbleSector(track, sector, buf, fpNibbleDescr); - } -#endif - - dierr = CalcSectorAndOffset(track, sector, imageOrder, fsOrder, - &offset, &newSector); - if (dierr != kDIErrNone) - return dierr; - - if (IsSectorFormat(fPhysical)) { - assert(offset+kSectorSize <= fLength); - - //WMSG2(" DI t=%d s=%d\n", track, - // (offset - track * fNumSectPerTrack * kSectorSize) / kSectorSize); - - dierr = CopyBytesOut(buf, offset, kSectorSize); - } else if (IsNibbleFormat(fPhysical)) { - if (imageOrder != kSectorOrderPhysical) { - WMSG2(" NOTE: nibble imageOrder is %d (expected %d)\n", - imageOrder, kSectorOrderPhysical); - } - dierr = ReadNibbleSector(track, newSector, buf, fpNibbleDescr); - } else { - assert(false); - dierr = kDIErrInternal; - } - - return dierr; -} - -/* - * Write the specified track and sector, adjusting for sector ordering as - * appropriate. - * - * Copies 256 bytes out of "buf". - * - * Returns 0 on success, nonzero on failure. - */ -DIError -DiskImg::WriteTrackSector(long track, int sector, const void* buf) -{ - DIError dierr; - di_off_t offset; - int newSector = -1; - - if (buf == nil) - return kDIErrInvalidArg; - if (fReadOnly) - return kDIErrAccessDenied; - -#if 0 // Pre-d13 - if (fNumSectPerTrack == 13) { - /* no sector skewing possible for 13-sector disks */ - assert(fHasNibbles); - - return WriteNibbleSector(track, sector, buf, fpNibbleDescr); - } -#endif - - dierr = CalcSectorAndOffset(track, sector, fOrder, fFileSysOrder, - &offset, &newSector); - if (dierr != kDIErrNone) - return dierr; - - if (IsSectorFormat(fPhysical)) { - assert(offset+kSectorSize <= fLength); - - //WMSG2(" DI t=%d s=%d\n", track, - // (offset - track * fNumSectPerTrack * kSectorSize) / kSectorSize); - - dierr = CopyBytesIn(buf, offset, kSectorSize); - } else if (IsNibbleFormat(fPhysical)) { - if (fOrder != kSectorOrderPhysical) { - WMSG2(" NOTE: nibble fOrder is %d (expected %d)\n", - fOrder, kSectorOrderPhysical); - } - dierr = WriteNibbleSector(track, newSector, buf, fpNibbleDescr); - } else { - assert(false); - dierr = kDIErrInternal; - } - - return dierr; -} - -/* - * Read a 512-byte block. - * - * Copies 512 bytes into "*buf". - */ -DIError -DiskImg::ReadBlockSwapped(long block, void* buf, SectorOrder imageOrder, - SectorOrder fsOrder) -{ - if (!fHasBlocks) - return kDIErrUnsupportedAccess; - if (block < 0 || block >= fNumBlocks) - return kDIErrInvalidBlock; - if (buf == nil) - return kDIErrInvalidArg; - - DIError dierr; - long track, blkInTrk; - - /* if we have a bad block map, check it */ - if (CheckForBadBlocks(block, 1)) { - dierr = kDIErrReadFailed; - goto bail; - } - - if (fHasSectors && !IsLinearBlocks(imageOrder, fsOrder)) { - /* run it through the t/s call so we handle DOS ordering */ - track = block / (fNumSectPerTrack/2); - blkInTrk = block - (track * (fNumSectPerTrack/2)); - dierr = ReadTrackSectorSwapped(track, blkInTrk*2, buf, - imageOrder, fsOrder); - if (dierr != kDIErrNone) - return dierr; - dierr = ReadTrackSectorSwapped(track, blkInTrk*2+1, - (char*)buf+kSectorSize, imageOrder, fsOrder); - } else if (fHasBlocks) { - /* no sectors, so no swapping; must be linear blocks */ - if (imageOrder != fsOrder) { - WMSG2(" DI NOTE: ReadBlockSwapped on non-sector (%d/%d)\n", - imageOrder, fsOrder); - } - dierr = CopyBytesOut(buf, (di_off_t) block * kBlockSize, kBlockSize); - } else { - assert(false); - dierr = kDIErrInternal; - } - -bail: - return dierr; -} - -/* - * Read multiple blocks. - * - * IMPORTANT: this returns immediately when a read fails. The buffer will - * probably not contain data from all readable sectors. The application is - * expected to retry the blocks individually. - */ -DIError -DiskImg::ReadBlocks(long startBlock, int numBlocks, void* buf) -{ - DIError dierr = kDIErrNone; - - assert(fHasBlocks); - assert(startBlock >= 0); - assert(numBlocks > 0); - assert(buf != nil); - - if (startBlock < 0 || numBlocks + startBlock > GetNumBlocks()) { - assert(false); - return kDIErrInvalidArg; - } - - /* if we have a bad block map, check it */ - if (CheckForBadBlocks(startBlock, numBlocks)) { - dierr = kDIErrReadFailed; - goto bail; - } - - if (!IsLinearBlocks(fOrder, fFileSysOrder)) { - /* - * This isn't a collection of linear blocks, so we need to read it one - * block at a time with sector swapping. This almost certainly means - * that we're not reading from physical media, so performance shouldn't - * be an issue. - */ - if (startBlock == 0) { - WMSG0(" ReadBlocks: nonlinear, not trying\n"); - } - while (numBlocks--) { - dierr = ReadBlock(startBlock, buf); - if (dierr != kDIErrNone) - goto bail; - startBlock++; - buf = (unsigned char*)buf + kBlockSize; - } - } else { - if (startBlock == 0) { - WMSG0(" ReadBlocks: doing big linear reads\n"); - } - dierr = CopyBytesOut(buf, - (di_off_t) startBlock * kBlockSize, numBlocks * kBlockSize); - } - -bail: - return dierr; -} - -/* - * Check to see if any blocks in a range of blocks show up in the bad - * block map. This is primarily useful for 3.5" disk images converted - * from nibble images, because we convert them directly to "cooked" - * 512-byte blocks. - * - * Returns "true" if we found bad blocks, "false" if not. - */ -bool -DiskImg::CheckForBadBlocks(long startBlock, int numBlocks) -{ - int i; - - if (fpBadBlockMap == nil) - return false; - - for (i = startBlock; i < startBlock+numBlocks; i++) { - if (fpBadBlockMap->IsSet(i)) - return true; - } - return false; -} - -/* - * Write a block of data to a DiskImg. - * - * Returns immediately when a block write fails. Does not try to write all - * blocks before returning failure. - */ -DIError -DiskImg::WriteBlock(long block, const void* buf) -{ - if (!fHasBlocks) - return kDIErrUnsupportedAccess; - if (block < 0 || block >= fNumBlocks) - return kDIErrInvalidBlock; - if (buf == nil) - return kDIErrInvalidArg; - if (fReadOnly) - return kDIErrAccessDenied; - - DIError dierr; - long track, blkInTrk; - - if (fHasSectors && !IsLinearBlocks(fOrder, fFileSysOrder)) { - /* run it through the t/s call so we handle DOS ordering */ - track = block / (fNumSectPerTrack/2); - blkInTrk = block - (track * (fNumSectPerTrack/2)); - dierr = WriteTrackSector(track, blkInTrk*2, buf); - if (dierr != kDIErrNone) - return dierr; - dierr = WriteTrackSector(track, blkInTrk*2+1, (char*)buf+kSectorSize); - } else if (fHasBlocks) { - /* no sectors, so no swapping; must be linear blocks */ - if (fOrder != fFileSysOrder) { - WMSG2(" DI NOTE: WriteBlock on non-sector (%d/%d)\n", - fOrder, fFileSysOrder); - } - dierr = CopyBytesIn(buf, (di_off_t)block * kBlockSize, kBlockSize); - } else { - assert(false); - dierr = kDIErrInternal; - } - return dierr; -} - -/* - * Write multiple blocks. - */ -DIError -DiskImg::WriteBlocks(long startBlock, int numBlocks, const void* buf) -{ - DIError dierr = kDIErrNone; - - assert(fHasBlocks); - assert(startBlock >= 0); - assert(numBlocks > 0); - assert(buf != nil); - - if (startBlock < 0 || numBlocks + startBlock > GetNumBlocks()) { - assert(false); - return kDIErrInvalidArg; - } - - if (!IsLinearBlocks(fOrder, fFileSysOrder)) { - /* - * This isn't a collection of linear blocks, so we need to write it - * one block at a time with sector swapping. This almost certainly - * means that we're not reading from physical media, so performance - * shouldn't be an issue. - */ - if (startBlock == 0) { - WMSG0(" WriteBlocks: nonlinear, not trying\n"); - } - while (numBlocks--) { - dierr = WriteBlock(startBlock, buf); - if (dierr != kDIErrNone) - goto bail; - startBlock++; - buf = (unsigned char*)buf + kBlockSize; - } - } else { - if (startBlock == 0) { - WMSG0(" WriteBlocks: doing big linear writes\n"); - } - dierr = CopyBytesIn(buf, - (di_off_t) startBlock * kBlockSize, numBlocks * kBlockSize); - } - -bail: - return dierr; -} - - -/* - * Copy a chunk of bytes out of the disk image. - * - * (This is the lowest-level read routine in this class.) - */ -DIError -DiskImg::CopyBytesOut(void* buf, di_off_t offset, int size) const -{ - DIError dierr; - - dierr = fpDataGFD->Seek(offset, kSeekSet); - if (dierr != kDIErrNone) { - WMSG2(" DI seek off=%ld failed (err=%d)\n", (long) offset, dierr); - return dierr; - } - - dierr = fpDataGFD->Read(buf, size); - if (dierr != kDIErrNone) { - WMSG3(" DI read off=%ld size=%d failed (err=%d)\n", - (long) offset, size, dierr); - return dierr; - } - - return kDIErrNone; -} - -/* - * Copy a chunk of bytes into the disk image. - * - * Sets the "dirty" flag. - * - * (This is the lowest-level write routine in DiskImg.) - */ -DIError -DiskImg::CopyBytesIn(const void* buf, di_off_t offset, int size) -{ - DIError dierr; - - if (fReadOnly) { - DebugBreak(); - return kDIErrAccessDenied; - } - assert(fpDataGFD != nil); // somebody closed the image? - - dierr = fpDataGFD->Seek(offset, kSeekSet); - if (dierr != kDIErrNone) { - WMSG2(" DI seek off=%ld failed (err=%d)\n", (long) offset, dierr); - return dierr; - } - - dierr = fpDataGFD->Write(buf, size); - if (dierr != kDIErrNone) { - WMSG3(" DI write off=%ld size=%d failed (err=%d)\n", - (long) offset, size, dierr); - return dierr; - } - - /* set the dirty flag here and everywhere above */ - DiskImg* pImg = this; - while (pImg != nil) { - pImg->fDirty = true; - pImg = pImg->fpParentImg; - } - - return kDIErrNone; -} - - -/* - * =========================================================================== - * Image creation - * =========================================================================== - */ - -/* - * Create a disk image with the specified parameters. - * - * "storageName" and "pNibbleDescr" may be nil. - */ -DIError -DiskImg::CreateImage(const char* pathName, const char* storageName, - OuterFormat outerFormat, FileFormat fileFormat, PhysicalFormat physical, - const NibbleDescr* pNibbleDescr, SectorOrder order, - FSFormat format, long numBlocks, bool skipFormat) -{ - assert(fpDataGFD == nil); // should not be open already! - - if (numBlocks <= 0) { - WMSG1("ERROR: bad numBlocks %ld\n", numBlocks); - assert(false); - return kDIErrInvalidCreateReq; - } - - fOuterFormat = outerFormat; - fFileFormat = fileFormat; - fPhysical = physical; - SetCustomNibbleDescr(pNibbleDescr); - fOrder = order; - fFormat = format; - - fNumBlocks = numBlocks; - fHasBlocks = true; - - return CreateImageCommon(pathName, storageName, skipFormat); -} -DIError -DiskImg::CreateImage(const char* pathName, const char* storageName, - OuterFormat outerFormat, FileFormat fileFormat, PhysicalFormat physical, - const NibbleDescr* pNibbleDescr, SectorOrder order, - FSFormat format, long numTracks, long numSectPerTrack, bool skipFormat) -{ - assert(fpDataGFD == nil); // should not be open already! - - if (numTracks <= 0 || numSectPerTrack == 0) { - WMSG2("ERROR: bad tracks/sectors %ld/%ld\n", numTracks, numSectPerTrack); - assert(false); - return kDIErrInvalidCreateReq; - } - - fOuterFormat = outerFormat; - fFileFormat = fileFormat; - fPhysical = physical; - SetCustomNibbleDescr(pNibbleDescr); - fOrder = order; - fFormat = format; - - fNumTracks = numTracks; - fNumSectPerTrack = numSectPerTrack; - fHasSectors = true; - if (numSectPerTrack < 0) { - /* nibble image with non-standard formatting */ - if (!IsNibbleFormat(fPhysical)) { - WMSG0("Whoa: expected nibble format here\n"); - assert(false); - return kDIErrInvalidCreateReq; - } - WMSG0("Sector image w/o sectors, switching to nibble mode\n"); - fHasNibbles = true; - fHasSectors = false; - fpNibbleDescr = nil; - } - - return CreateImageCommon(pathName, storageName, skipFormat); -} - -/* - * Do the actual disk image creation. - */ -DIError -DiskImg::CreateImageCommon(const char* pathName, const char* storageName, - bool skipFormat) -{ - DIError dierr; - - /* - * Step 1: figure out fHasBlocks/fHasSectors/fHasNibbles and any - * other misc fields. - * - * If the disk is a nibble image expected to have a particular - * volume number, it should have already been set by the application. - */ - if (fHasBlocks) { - if ((fNumBlocks % 8) == 0) { - fHasSectors = true; - fNumSectPerTrack = 16; - fNumTracks = fNumBlocks / 8; - } else { - WMSG0("NOTE: sector access to new image not possible\n"); - } - } else if (fHasSectors) { - if ((fNumSectPerTrack & 0x01) == 0) { - fHasBlocks = true; - fNumBlocks = (fNumTracks * fNumSectPerTrack) / 2; - } else { - WMSG0("NOTE: block access to new image not possible\n"); - } - } - if (fHasSectors && fPhysical != kPhysicalFormatSectors) - fHasNibbles = true; - assert(fHasBlocks || fHasSectors || fHasNibbles); - - fFileSysOrder = CalcFSSectorOrder(); - fReadOnly = false; - fDirty = true; - - /* - * Step 2: check for invalid arguments and bad combinations. - */ - dierr = ValidateCreateFormat(); - if (dierr != kDIErrNone) { - WMSG0("ERROR: CIC arg validation failed, bailing\n"); - goto bail; - } - - /* - * Step 3: create the destination file. Put this into fpWrapperGFD - * or fpOuterGFD. - * - * The file must not already exist. - * - * THOUGHT: should allow creation of an in-memory disk image. This won't - * work for NuFX, but will work for pretty much everything else. - */ - WMSG1(" CIC: creating '%s'\n", pathName); - int fd; - fd = open(pathName, O_CREAT | O_EXCL, 0644); - if (fd < 0) { - dierr = (DIError) errno; - WMSG2("ERROR: unable to create file '%s' (errno=%d)\n", - pathName, dierr); - goto bail; - } - close(fd); - - GFDFile* pGFDFile; - pGFDFile = new GFDFile; - - dierr = pGFDFile->Open(pathName, false); - if (dierr != kDIErrNone) { - delete pGFDFile; - goto bail; - } - - if (fOuterFormat == kOuterFormatNone) - fpWrapperGFD = pGFDFile; - else - fpOuterGFD = pGFDFile; - pGFDFile = nil; - - /* - * Step 4: if we have an outer GFD and therefore don't currently have - * an fpWrapperGFD, create an expandable memory buffer to use. - * - * We want to take a guess at how big the image will be, so compute - * fLength now. - * - * Create an OuterWrapper as needed. - */ - if (IsSectorFormat(fPhysical)) { - if (fHasBlocks) - fLength = (di_off_t) GetNumBlocks() * kBlockSize; - else - fLength = (di_off_t) GetNumTracks() * GetNumSectPerTrack() * kSectorSize; - } else { - assert(IsNibbleFormat(fPhysical)); - fLength = GetNumTracks() * GetNibbleTrackAllocLength(); - } - assert(fLength > 0); - - if (fpWrapperGFD == nil) { - /* shift GFDs and create a new memory GFD, pre-sized */ - GFDBuffer* pGFDBuffer = new GFDBuffer; - - /* use fLength as a starting point for buffer size; this may expand */ - dierr = pGFDBuffer->Open(nil, fLength, true, true, false); - if (dierr != kDIErrNone) { - delete pGFDBuffer; - goto bail; - } - - fpWrapperGFD = pGFDBuffer; - pGFDBuffer = nil; - } - - /* create an fpOuterWrapper struct */ - switch (fOuterFormat) { - case kOuterFormatNone: - break; - case kOuterFormatGzip: - fpOuterWrapper = new OuterGzip; - if (fpOuterWrapper == nil) { - dierr = kDIErrMalloc; - goto bail; - } - break; - case kOuterFormatZip: - fpOuterWrapper = new OuterZip; - if (fpOuterWrapper == nil) { - dierr = kDIErrMalloc; - goto bail; - } - break; - default: - assert(false); - dierr = kDIErrInternal; - goto bail; - } - - /* - * Step 5: tell the ImageWrapper to write itself into the GFD, passing - * in the blank memory buffer. - * - * - Unadorned formats copy from memory buffer to fpWrapperGFD on disk. - * (With gz, fpWrapperGFD is actually a memory buffer.) fpDataGFD - * becomes an offset into the file. - * - 2MG writes header into GFD and follows it with all data; DC42 - * and Sim2e do similar things. - * - NuFX reopens pathName as SHK file (fpWrapperGFD must point to a - * file) and accesses the archive through an fpArchive. fpDataGFD - * is created as a memory buffer and the blank image is copied in. - * - DDD leaves fpWrapperGFD alone and copies the blank image into a - * new buffer for fpDataGFD. - * - * Sets fWrappedLength when possible, determined from fPhysical and - * either fNumBlocks or fNumTracks. Creates fpDataGFD, often as a - * GFDGFD offset into fpWrapperGFD. - */ - switch (fFileFormat) { - case kFileFormat2MG: - fpImageWrapper = new Wrapper2MG(); - break; - case kFileFormatDiskCopy42: - fpImageWrapper = new WrapperDiskCopy42(); - fpImageWrapper->SetStorageName(storageName); - break; - case kFileFormatSim2eHDV: - fpImageWrapper = new WrapperSim2eHDV(); - break; - case kFileFormatTrackStar: - fpImageWrapper = new WrapperTrackStar(); - fpImageWrapper->SetStorageName(storageName); - break; - case kFileFormatFDI: - fpImageWrapper = new WrapperFDI(); - break; - case kFileFormatNuFX: - fpImageWrapper = new WrapperNuFX(); - fpImageWrapper->SetStorageName(storageName); - ((WrapperNuFX*)fpImageWrapper)->SetCompressType( - (NuThreadFormat) fNuFXCompressType); - break; - case kFileFormatDDD: - fpImageWrapper = new WrapperDDD(); - break; - case kFileFormatUnadorned: - if (IsSectorFormat(fPhysical)) - fpImageWrapper = new WrapperUnadornedSector(); - else if (IsNibbleFormat(fPhysical)) - fpImageWrapper = new WrapperUnadornedNibble(); - else { - assert(false); - } - break; - default: - assert(fpImageWrapper == nil); - break; - } - - if (fpImageWrapper == nil) { - WMSG0(" DI couldn't figure out the file format\n"); - dierr = kDIErrUnrecognizedFileFmt; - goto bail; - } - - /* create the wrapper, write the header, and create fpDataGFD */ - assert(fpDataGFD == nil); - dierr = fpImageWrapper->Create(fLength, fPhysical, fOrder, - fDOSVolumeNum, fpWrapperGFD, &fWrappedLength, &fpDataGFD); - if (dierr != kDIErrNone) { - WMSG1("ImageWrapper Create failed, err=%d\n", dierr); - goto bail; - } - assert(fpDataGFD != nil); - - /* - * Step 6: "format" fpDataGFD. - * - * Note we don't specify an ordering to the "create blank" functions. - * Either it's sectors, in which case it's all zeroes, or it's nibbles, - * in which case it's always in physical order. - * - * If we're formatting for nibbles, and the application hasn't specified - * a disk volume number, use the default (254). - */ - if (fPhysical == kPhysicalFormatSectors) - dierr = FormatSectors(fpDataGFD, skipFormat); // zero out the image - else { - assert(!skipFormat); // don't skip low-level nibble formatting! - if (fDOSVolumeNum == kVolumeNumNotSet) { - fDOSVolumeNum = kDefaultNibbleVolumeNum; - WMSG0(" Using default nibble volume num\n"); - } - - dierr = FormatNibbles(fpDataGFD); // write basic nibble stuff - } - - - /* - * We're done! - * - * Quick sanity check... - */ - if (fOuterFormat != kOuterFormatNone) { - assert(fpOuterGFD != nil); - assert(fpWrapperGFD != nil); - assert(fpDataGFD != nil); - } - -bail: - return dierr; -} - -/* - * Check that the requested format is one we can create. - * - * We don't allow .SDK.GZ or 6384-byte nibble 2MG. 2MG sector images - * must be in DOS or ProDOS order. - * - * Only "generic" FS formats may be used. The application may choose - * to call AnalyzeImage later on to set the actual FS once data has - * been written. - */ -DIError -DiskImg::ValidateCreateFormat(void) const -{ - /* - * Check for invalid arguments. - */ - if (fHasBlocks && fNumBlocks >= 4194304) { // 2GB or larger? - if (fFileFormat != kFileFormatUnadorned) { - WMSG0("CreateImage: images >= 2GB can only be unadorned\n"); - return kDIErrInvalidCreateReq; - } - } - if (fOuterFormat == kOuterFormatUnknown || - fFileFormat == kFileFormatUnknown || - fPhysical == kPhysicalFormatUnknown || - fOrder == kSectorOrderUnknown || - fFormat == kFormatUnknown) - { - WMSG0("CreateImage: ambiguous format\n"); - return kDIErrInvalidCreateReq; - } - if (fOuterFormat != kOuterFormatNone && - fOuterFormat != kOuterFormatGzip && - fOuterFormat != kOuterFormatZip) - { - WMSG1("CreateImage: unsupported outer format %d\n", fOuterFormat); - return kDIErrInvalidCreateReq; - } - if (fFileFormat != kFileFormatUnadorned && - fFileFormat != kFileFormat2MG && - fFileFormat != kFileFormatDiskCopy42 && - fFileFormat != kFileFormatSim2eHDV && - fFileFormat != kFileFormatTrackStar && - fFileFormat != kFileFormatFDI && - fFileFormat != kFileFormatNuFX && - fFileFormat != kFileFormatDDD) - { - WMSG1("CreateImage: unsupported file format %d\n", fFileFormat); - return kDIErrInvalidCreateReq; - } - if (fFormat != kFormatGenericPhysicalOrd && - fFormat != kFormatGenericProDOSOrd && - fFormat != kFormatGenericDOSOrd && - fFormat != kFormatGenericCPMOrd) - { - WMSG0("CreateImage: may only use 'generic' formats\n"); - return kDIErrInvalidCreateReq; - } - - /* - * Check for invalid combinations. - */ - if (fPhysical != kPhysicalFormatSectors) { - if (fOrder != kSectorOrderPhysical) { - WMSG0("CreateImage: nibble images are always 'physical' order\n"); - return kDIErrInvalidCreateReq; - } - - if (GetHasSectors() == false && GetHasNibbles() == false) { - WMSG2("CreateImage: must set hasSectors(%d) or hasNibbles(%d)\n", - GetHasSectors(), GetHasNibbles()); - return kDIErrInvalidCreateReq; - } - - if (fpNibbleDescr == nil && GetNumSectPerTrack() > 0) { - WMSG0("CreateImage: must provide NibbleDescr for non-sector\n"); - return kDIErrInvalidCreateReq; - } - - if (fpNibbleDescr != nil && - fpNibbleDescr->numSectors != GetNumSectPerTrack()) - { - WMSG2("CreateImage: ?? nd->numSectors=%d, GetNumSectPerTrack=%d\n", - fpNibbleDescr->numSectors, GetNumSectPerTrack()); - return kDIErrInvalidCreateReq; - } - - if (fpNibbleDescr != nil && ( - (fpNibbleDescr->numSectors == 13 && - fpNibbleDescr->encoding != kNibbleEnc53) || - (fpNibbleDescr->numSectors == 16 && - fpNibbleDescr->encoding != kNibbleEnc62)) - ) - { - WMSG0("CreateImage: sector count/encoding mismatch\n"); - return kDIErrInvalidCreateReq; - } - - if (GetNumTracks() != kTrackCount525 && - !(GetNumTracks() == 40 && fFileFormat == kFileFormatTrackStar)) - { - WMSG1("CreateImage: unexpected track count %ld\n", GetNumTracks()); - return kDIErrInvalidCreateReq; - } - } - if (fFileFormat == kFileFormat2MG) { - if (fPhysical != kPhysicalFormatSectors && - fPhysical != kPhysicalFormatNib525_6656) - { - WMSG1("CreateImage: 2MG can't handle physical %d\n", fPhysical); - return kDIErrInvalidCreateReq; - } - - if (fPhysical == kPhysicalFormatSectors && - (fOrder != kSectorOrderProDOS && - fOrder != kSectorOrderDOS)) - { - WMSG0("CreateImage: 2MG requires DOS or ProDOS ordering\n"); - return kDIErrInvalidCreateReq; - } - } - if (fFileFormat == kFileFormatNuFX) { - if (fOuterFormat != kOuterFormatNone) { - WMSG0("CreateImage: can't mix NuFX and outer wrapper\n"); - return kDIErrInvalidCreateReq; - } - if (fPhysical != kPhysicalFormatSectors) { - WMSG0("CreateImage: NuFX physical must be sectors\n"); - return kDIErrInvalidCreateReq; - } - if (fOrder != kSectorOrderProDOS) { - WMSG0("CreateImage: NuFX is always ProDOS-order\n"); - return kDIErrInvalidCreateReq; - } - } - if (fFileFormat == kFileFormatDiskCopy42) { - if (fPhysical != kPhysicalFormatSectors) { - WMSG0("CreateImage: DC42 physical must be sectors\n"); - return kDIErrInvalidCreateReq; - } - if ((GetHasBlocks() && GetNumBlocks() != 1600) || - GetHasSectors() && - (GetNumTracks() != 200 || GetNumSectPerTrack() != 16)) - { - WMSG0("CreateImage: DC42 only for 800K disks\n"); - return kDIErrInvalidCreateReq; - } - if (fOrder != kSectorOrderProDOS && - fOrder != kSectorOrderDOS) // used for UNIDOS disks?? - { - WMSG0("CreateImage: DC42 is always ProDOS or DOS\n"); - return kDIErrInvalidCreateReq; - } - } - if (fFileFormat == kFileFormatSim2eHDV) { - if (fPhysical != kPhysicalFormatSectors) { - WMSG0("CreateImage: Sim2eHDV physical must be sectors\n"); - return kDIErrInvalidCreateReq; - } - if (fOrder != kSectorOrderProDOS) { - WMSG0("CreateImage: Sim2eHDV is always ProDOS-order\n"); - return kDIErrInvalidCreateReq; - } - } - if (fFileFormat == kFileFormatTrackStar) { - if (fPhysical != kPhysicalFormatNib525_Var) { - WMSG0("CreateImage: TrackStar physical must be var-nibbles\n"); - return kDIErrInvalidCreateReq; - } - } - if (fFileFormat == kFileFormatFDI) { - if (fPhysical != kPhysicalFormatNib525_Var) { - WMSG0("CreateImage: FDI physical must be var-nibbles\n"); - return kDIErrInvalidCreateReq; - } - } - if (fFileFormat == kFileFormatDDD) { - if (fPhysical != kPhysicalFormatSectors) { - WMSG0("CreateImage: DDD physical must be sectors\n"); - return kDIErrInvalidCreateReq; - } - if (fOrder != kSectorOrderDOS) { - WMSG0("CreateImage: DDD is always DOS-order\n"); - return kDIErrInvalidCreateReq; - } - if (!GetHasSectors() || GetNumTracks() != 35 || - GetNumSectPerTrack() != 16) - { - WMSG0("CreateImage: DDD is only for 16-sector 35-track disks\n"); - return kDIErrInvalidCreateReq; - } - } - - return kDIErrNone; -} - -/* - * Create a blank image for physical=="sectors". - * - * fLength must be a multiple of 256. - * - * If "quickFormat" is set, only the very last sector is written (to set - * the EOF on the file). - */ -DIError -DiskImg::FormatSectors(GenericFD* pGFD, bool quickFormat) const -{ - DIError dierr = kDIErrNone; - char sctBuf[kSectorSize]; - di_off_t length; - - assert(fLength > 0 && (fLength & 0xff) == 0); - - //if (!(fLength & 0x01)) - // return FormatBlocks(pGFD); - - memset(sctBuf, 0, sizeof(sctBuf)); - pGFD->Rewind(); - - if (quickFormat) { - dierr = pGFD->Seek(fLength - sizeof(sctBuf), kSeekSet); - if (dierr != kDIErrNone) { - WMSG2(" FormatSectors: GFD seek %ld failed (err=%d)\n", - (long) fLength - sizeof(sctBuf), dierr); - goto bail; - } - dierr = pGFD->Write(sctBuf, sizeof(sctBuf), nil); - if (dierr != kDIErrNone) { - WMSG1(" FormatSectors: GFD quick write failed (err=%d)\n", dierr); - goto bail; - } - } else { - for (length = fLength ; length > 0; length -= sizeof(sctBuf)) { - dierr = pGFD->Write(sctBuf, sizeof(sctBuf), nil); - if (dierr != kDIErrNone) { - WMSG1(" FormatSectors: GFD write failed (err=%d)\n", dierr); - goto bail; - } - } - assert(length == 0); - } - - -bail: - return dierr; -} - -#if 0 // didn't help -/* - * Create a blank image for physical=="sectors". This is called from - * FormatSectors when it looks like we're formatting entire blocks. - */ -DIError -DiskImg::FormatBlocks(GenericFD* pGFD) const -{ - DIError dierr; - char blkBuf[kBlockSize]; - long length; - time_t start, end; - - assert(fLength > 0 && (fLength & 0x1ff) == 0); - - start = time(nil); - - memset(blkBuf, 0, sizeof(blkBuf)); - pGFD->Rewind(); - - for (length = fLength ; length > 0; length -= sizeof(blkBuf)) { - dierr = pGFD->Write(blkBuf, sizeof(blkBuf), nil); - if (dierr != kDIErrNone) { - WMSG1(" FormatBlocks: GFD write failed (err=%d)\n", dierr); - return dierr; - } - } - assert(length == 0); - - end = time(nil); - WMSG1("FormatBlocks complete, time=%ld\n", end - start); - - return kDIErrNone; -} -#endif - - -/* - * =========================================================================== - * Utility functions - * =========================================================================== - */ - -/* - * Add a note to this disk image. - * - * This is how we communicate cautions and warnings to the user. Use - * linefeeds ('\n') to indicate line breaks. - * - * The maximum length of a single note is set by the size of "buf". - */ -void -DiskImg::AddNote(NoteType type, const char* fmt, ...) -{ - char buf[512]; - char* cp = buf; - int maxLen = sizeof(buf); - va_list args; - int len; - - /* - * Prepend a string that highlights the note. - */ - switch (type) { - case kNoteWarning: - strcpy(cp, "- WARNING: "); - break; - default: - strcpy(cp, "- "); - break; - } - len = strlen(cp); - cp += len; - maxLen -= len; - - /* - * Add the note. - */ - va_start(args, fmt); -#if defined(HAVE_VSNPRINTF) - (void) vsnprintf(cp, maxLen, fmt, args); -#elif defined(HAVE__VSNPRINTF) - (void) _vsnprintf(cp, maxLen, fmt, args); -#else -# error "hosed" -#endif - va_end(args); - - buf[sizeof(buf)-2] = '\0'; // leave room for additional '\n' - len = strlen(buf); - if (len > 0 && buf[len-1] != '\n') { - buf[len] = '\n'; - buf[len+1] = '\0'; - len++; - } - - WMSG1("+++ adding note '%s'\n", buf); - - if (fNotes == nil) { - fNotes = new char[len +1]; - if (fNotes == nil) { - WMSG1("Unable to create notes[%d]\n", len+1); - assert(false); - return; - } - strcpy(fNotes, buf); - } else { - int existingLen = strlen(fNotes); - char* newNotes = new char[existingLen + len +1]; - if (newNotes == nil) { - WMSG1("Unable to create newNotes[%d]\n", existingLen+len+1); - assert(false); - return; - } - strcpy(newNotes, fNotes); - strcpy(newNotes + existingLen, buf); - delete[] fNotes; - fNotes = newNotes; - } -} - -/* - * Return a string with the notes in it. - */ -const char* -DiskImg::GetNotes(void) const -{ - if (fNotes == nil) - return ""; - else - return fNotes; -} - - -/* - * Get length and offset of tracks in a nibble image. This is necessary - * because of formats with variable-length tracks (e.g. TrackStar). - */ -int -DiskImg::GetNibbleTrackLength(long track) const -{ - assert(fpImageWrapper != NULL); - return fpImageWrapper->GetNibbleTrackLength(fPhysical, track); -} -int -DiskImg::GetNibbleTrackOffset(long track) const -{ - assert(fpImageWrapper != NULL); - return fpImageWrapper->GetNibbleTrackOffset(fPhysical, track); -} - - -/* - * Return a new object with the appropriate DiskFS sub-class. - * - * If the image hasn't been analyzed, or was analyzed to no avail, "nil" - * is returned unless "allowUnknown" is set to "true". In that case, a - * DiskFSUnknown is returned. - * - * This doesn't inspire the DiskFS to do any processing, just creates the - * new object. - */ -DiskFS* -DiskImg::OpenAppropriateDiskFS(bool allowUnknown) -{ - DiskFS* pDiskFS = nil; - - /* - * Create an appropriate DiskFS object. - */ - switch (GetFSFormat()) { - case DiskImg::kFormatDOS33: - case DiskImg::kFormatDOS32: - pDiskFS = new DiskFSDOS33(); - break; - case DiskImg::kFormatProDOS: - pDiskFS = new DiskFSProDOS(); - break; - case DiskImg::kFormatPascal: - pDiskFS = new DiskFSPascal(); - break; - case DiskImg::kFormatMacHFS: - pDiskFS = new DiskFSHFS(); - break; - case DiskImg::kFormatUNIDOS: - pDiskFS = new DiskFSUNIDOS(); - break; - case DiskImg::kFormatOzDOS: - pDiskFS = new DiskFSOzDOS(); - break; - case DiskImg::kFormatCFFA4: - case DiskImg::kFormatCFFA8: - pDiskFS = new DiskFSCFFA(); - break; - case DiskImg::kFormatMacPart: - pDiskFS = new DiskFSMacPart(); - break; - case DiskImg::kFormatMicroDrive: - pDiskFS = new DiskFSMicroDrive(); - break; - case DiskImg::kFormatFocusDrive: - pDiskFS = new DiskFSFocusDrive(); - break; - case DiskImg::kFormatCPM: - pDiskFS = new DiskFSCPM(); - break; - case DiskImg::kFormatMSDOS: - pDiskFS = new DiskFSFAT(); - break; - case DiskImg::kFormatRDOS33: - case DiskImg::kFormatRDOS32: - case DiskImg::kFormatRDOS3: - pDiskFS = new DiskFSRDOS(); - break; - case DiskImg::kFormatGutenberg: - pDiskFS = new DiskFSGutenberg(); - break; - - default: - WMSG1("WARNING: unhandled DiskFS case %d\n", GetFSFormat()); - assert(false); - /* fall through */ - case DiskImg::kFormatGenericPhysicalOrd: - case DiskImg::kFormatGenericProDOSOrd: - case DiskImg::kFormatGenericDOSOrd: - case DiskImg::kFormatGenericCPMOrd: - case DiskImg::kFormatUnknown: - if (allowUnknown) { - pDiskFS = new DiskFSUnknown(); - break; - } - } - - return pDiskFS; -} - - -/* - * Fill an array with SectorOrder values. The ordering specified by "first" - * will come first. Unused entries will be set to "unknown" and should be - * ignored. - * - * "orderArray" must have kSectorOrderMax elements. - */ -/*static*/ void -DiskImg::GetSectorOrderArray(SectorOrder* orderArray, SectorOrder first) -{ - // init array - for (int i = 0; i < kSectorOrderMax; i++) - orderArray[i] = (SectorOrder) i; - - // pull the best-guess ordering to the front - assert(orderArray[0] == kSectorOrderUnknown); - - orderArray[0] = first; - orderArray[(int) first] = kSectorOrderUnknown; - - // don't bother checking CP/M sector order - orderArray[kSectorOrderCPM] = kSectorOrderUnknown; -} - - -/* - * Return a short string describing "format". - * - * These are semi-duplicated in ImageFormatDialog.cpp in CiderPress. - */ -/*static*/ const char* -DiskImg::ToStringCommon(int format, const ToStringLookup* pTable, - int tableSize) -{ - for (int i = 0; i < tableSize; i++) { - if (pTable[i].format == format) - return pTable[i].str; - } - - assert(false); - return "(unknown)"; -} - -/*static*/ const char* -DiskImg::ToString(OuterFormat format) -{ - static const ToStringLookup kOuterFormats[] = { - { DiskImg::kOuterFormatUnknown, "Unknown format" }, - { DiskImg::kOuterFormatNone, "(none)" }, - { DiskImg::kOuterFormatCompress, "UNIX compress" }, - { DiskImg::kOuterFormatGzip, "gzip" }, - { DiskImg::kOuterFormatBzip2, "bzip2" }, - { DiskImg::kOuterFormatZip, "Zip archive" }, - }; - - return ToStringCommon(format, kOuterFormats, NELEM(kOuterFormats)); -} -/*static*/ const char* -DiskImg::ToString(FileFormat format) -{ - static const ToStringLookup kFileFormats[] = { - { DiskImg::kFileFormatUnknown, "Unknown format" }, - { DiskImg::kFileFormatUnadorned, "Unadorned raw data" }, - { DiskImg::kFileFormat2MG, "2MG" }, - { DiskImg::kFileFormatNuFX, "NuFX (ShrinkIt)" }, - { DiskImg::kFileFormatDiskCopy42, "DiskCopy 4.2" }, - { DiskImg::kFileFormatDiskCopy60, "DiskCopy 6.0" }, - { DiskImg::kFileFormatDavex, "Davex volume image" }, - { DiskImg::kFileFormatSim2eHDV, "Sim //e HDV" }, - { DiskImg::kFileFormatTrackStar, "TrackStar image" }, - { DiskImg::kFileFormatFDI, "FDI image" }, - { DiskImg::kFileFormatDDD, "DDD" }, - { DiskImg::kFileFormatDDDDeluxe, "DDDDeluxe" }, - }; - - return ToStringCommon(format, kFileFormats, NELEM(kFileFormats)); -}; -/*static*/ const char* -DiskImg::ToString(PhysicalFormat format) -{ - static const ToStringLookup kPhysicalFormats[] = { - { DiskImg::kPhysicalFormatUnknown, "Unknown format" }, - { DiskImg::kPhysicalFormatSectors, "Sectors" }, - { DiskImg::kPhysicalFormatNib525_6656, "Raw nibbles (6656-byte)" }, - { DiskImg::kPhysicalFormatNib525_6384, "Raw nibbles (6384-byte)" }, - { DiskImg::kPhysicalFormatNib525_Var, "Raw nibbles (variable len)" }, - }; - - return ToStringCommon(format, kPhysicalFormats, NELEM(kPhysicalFormats)); -}; -/*static*/ const char* -DiskImg::ToString(SectorOrder format) -{ - static const ToStringLookup kSectorOrders[] = { - { DiskImg::kSectorOrderUnknown, "Unknown ordering" }, - { DiskImg::kSectorOrderProDOS, "ProDOS block ordering" }, - { DiskImg::kSectorOrderDOS, "DOS sector ordering" }, - { DiskImg::kSectorOrderCPM, "CP/M block ordering" }, - { DiskImg::kSectorOrderPhysical, "Physical sector ordering" }, - }; - - return ToStringCommon(format, kSectorOrders, NELEM(kSectorOrders)); -}; -/*static*/ const char* -DiskImg::ToString(FSFormat format) -{ - static const ToStringLookup kFSFormats[] = { - { DiskImg::kFormatUnknown, "Unknown" }, - { DiskImg::kFormatProDOS, "ProDOS" }, - { DiskImg::kFormatDOS33, "DOS 3.3" }, - { DiskImg::kFormatDOS32, "DOS 3.2" }, - { DiskImg::kFormatPascal, "Pascal" }, - { DiskImg::kFormatMacHFS, "HFS" }, - { DiskImg::kFormatMacMFS, "MFS" }, - { DiskImg::kFormatLisa, "Lisa" }, - { DiskImg::kFormatCPM, "CP/M" }, - { DiskImg::kFormatMSDOS, "MS-DOS FAT" }, - { DiskImg::kFormatISO9660, "ISO-9660" }, - { DiskImg::kFormatRDOS33, "RDOS 3.3 (16-sector)" }, - { DiskImg::kFormatRDOS32, "RDOS 3.2 (13-sector)" }, - { DiskImg::kFormatRDOS3, "RDOS 3 (cracked 13-sector)" }, - { DiskImg::kFormatGenericDOSOrd, "Generic DOS sectors" }, - { DiskImg::kFormatGenericProDOSOrd, "Generic ProDOS blocks" }, - { DiskImg::kFormatGenericPhysicalOrd, "Generic raw sectors" }, - { DiskImg::kFormatGenericCPMOrd, "Generic CP/M blocks" }, - { DiskImg::kFormatUNIDOS, "UNIDOS (400K DOS x2)" }, - { DiskImg::kFormatOzDOS, "OzDOS (400K DOS x2)" }, - { DiskImg::kFormatCFFA4, "CFFA (4 or 6 partitions)" }, - { DiskImg::kFormatCFFA8, "CFFA (8 partitions)" }, - { DiskImg::kFormatMacPart, "Macintosh partitioned disk" }, - { DiskImg::kFormatMicroDrive, "MicroDrive partitioned disk" }, - { DiskImg::kFormatFocusDrive, "FocusDrive partitioned disk" }, - }; - - return ToStringCommon(format, kFSFormats, NELEM(kFSFormats)); -}; - - -/* - * strerror() equivalent for DiskImg errors. - */ -const char* -DiskImgLib::DIStrError(DIError dierr) -{ - if (dierr > 0) { - const char* msg; - msg = strerror(dierr); - if (msg != nil) - return msg; - } - - /* - * BUG: this should be set up as per-thread storage in an MT environment. - * I would be more inclined to worry about this if I was expecting - * to hit "default:". So long as valid values are passed in, and the - * switch statement is kept up to date, we should never have cause - * to return this. - * - * An easier solution, should this present a problem for someone, would - * be to have the function return nil or "unknown error" when the - * error value isn't recognized. I'd recommend leaving it as-is for - * debug builds, though, as it's helpful to know *which* error is not - * recognized. - */ - static char defaultMsg[32]; - - switch (dierr) { - case kDIErrNone: - return "(no error)"; - - case kDIErrAccessDenied: - return "access denied"; - case kDIErrVWAccessForbidden: - return "for safety, write access to this volume is forbidden"; - case kDIErrSharingViolation: - return "file is already open and cannot be shared"; - case kDIErrNoExclusiveAccess: - return "couldn't get exclusive access"; - case kDIErrWriteProtected: - return "write protected"; - case kDIErrCDROMNotSupported: - return "access to CD-ROM drives is not supported"; - case kDIErrASPIFailure: - return "an ASPI request failed"; - case kDIErrSPTIFailure: - return "an SPTI request failed"; - case kDIErrSCSIFailure: - return "a SCSI request failed"; - case kDIErrDeviceNotReady: - return "device not ready"; - - case kDIErrFileNotFound: - return "file not found"; - case kDIErrForkNotFound: - return "fork not found"; - case kDIErrAlreadyOpen: - return "an image is already open"; - case kDIErrFileOpen: - return "file is open"; - case kDIErrNotReady: - return "object not ready"; - case kDIErrFileExists: - return "file already exists"; - case kDIErrDirectoryExists: - return "directory already exists"; - - case kDIErrEOF: - return "end of file reached"; - case kDIErrReadFailed: - return "read failed"; - case kDIErrWriteFailed: - return "write failed"; - case kDIErrDataUnderrun: - return "tried to read past end of file"; - case kDIErrDataOverrun: - return "tried to write past end of file"; - case kDIErrGenericIO: - return "I/O error"; - - case kDIErrOddLength: - return "image size is wrong"; - case kDIErrUnrecognizedFileFmt: - return "not a recognized disk image format"; - case kDIErrBadFileFormat: - return "image file contents aren't in expected format"; - case kDIErrUnsupportedFileFmt: - return "file format not supported"; - case kDIErrUnsupportedPhysicalFmt: - return "physical format not supported"; - case kDIErrUnsupportedFSFmt: - return "filesystem type not supported"; - case kDIErrBadOrdering: - return "bad sector ordering"; - case kDIErrFilesystemNotFound: - return "specified filesystem not found"; - case kDIErrUnsupportedAccess: - return "the method of access used isn't supported for this image"; - case kDIErrUnsupportedImageFeature: - return "image file uses features that CiderPress doesn't support"; - - case kDIErrInvalidTrack: - return "invalid track number"; - case kDIErrInvalidSector: - return "invalid sector number"; - case kDIErrInvalidBlock: - return "invalid block number"; - case kDIErrInvalidIndex: - return "invalid index number"; - - case kDIErrDirectoryLoop: - return "disk directory structure has an infinite loop"; - case kDIErrFileLoop: - return "file structure has an infinite loop"; - case kDIErrBadDiskImage: - return "the filesystem on this image appears damaged"; - case kDIErrBadFile: - return "file structure appears damaged"; - case kDIErrBadDirectory: - return "a directory appears damaged"; - case kDIErrBadPartition: - return "bad partition"; - - case kDIErrFileArchive: - return "this looks like a file archive, not a disk archive"; - case kDIErrUnsupportedCompression: - return "compression method not supported"; - case kDIErrBadChecksum: - return "checksum doesn't match, data may be corrupted"; - case kDIErrBadCompressedData: - return "the compressed data is corrupted"; - case kDIErrBadArchiveStruct: - return "archive may be damaged"; - - case kDIErrBadNibbleSectors: - return "couldn't read sectors from this image"; - case kDIErrSectorUnreadable: - return "sector not readable"; - case kDIErrInvalidDiskByte: - return "found invalid nibble image disk byte"; - case kDIErrBadRawData: - return "couldn't convert raw data to nibble data"; - - case kDIErrInvalidFileName: - return "invalid file name"; - case kDIErrDiskFull: - return "disk full"; - case kDIErrVolumeDirFull: - return "volume directory is full"; - case kDIErrInvalidCreateReq: - return "invalid disk image create request"; - case kDIErrTooBig: - return "size is larger than we can handle"; - - case kDIErrGeneric: - return "DiskImg generic error"; - case kDIErrInternal: - return "DiskImg internal error"; - case kDIErrMalloc: - return "memory allocation failure"; - case kDIErrInvalidArg: - return "invalid argument"; - case kDIErrNotSupported: - return "feature not supported"; - case kDIErrCancelled: - return "cancelled by user"; - - case kDIErrNufxLibInitFailed: - return "NufxLib initialization failed"; - - default: - sprintf(defaultMsg, "(error=%d)", dierr); - return defaultMsg; - } -} - -/* - * High ASCII conversion table, from Technical Note PT515, - * "Apple File Exchange Q&As". The table is available in a hopelessly - * blurry PDF or a pair of GIFs created with small fonts, but I think I - * have mostly captured it. - */ -/*static*/ const unsigned char DiskImg::kMacHighASCII[128+1] = - "AACENOUaaaaaaceeeeiiiinooooouuuu" // 0x80 - 0x9f - "tocL$oPBrct'.=AO%+<>YudsPpSaoOao" // 0xa0 - 0xbf - "?!-vf=d<>. AAOOo--\"\"''/oyY/o<> f" // 0xc0 - 0xdf - "|*,,%AEAEEIIIIOOaOUUUi^~-,**,\"? "; // 0xe0 - 0xff - - -/* - * Hack for Win32 systems. See Win32BlockIO.cpp for commentary. - */ -bool DiskImgLib::gAllowWritePhys0 = false; -/*static*/ void DiskImg::SetAllowWritePhys0(bool val) { - DiskImgLib::gAllowWritePhys0 = val; -} +/* + * CiderPress + * Copyright (C) 2009 by CiderPress authors. All Rights Reserved. + * Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved. + * See the file LICENSE for distribution terms. + */ +/* + * Implementation of the DiskImg class. + */ +#include "StdAfx.h" +#include "DiskImgPriv.h" +#include "TwoImg.h" + + +/* + * =========================================================================== + * DiskImg + * =========================================================================== + */ + +/* + * Standard NibbleDescr profiles. + * + * These will be tried in the order in which they appear here. + * + * IMPORTANT: if you add or remove an entry, update the StdNibbleDescr enum + * in DiskImg.h. + * + * Formats that allow the data checksum to be ignored should NOT be written. + * It's possible that the DOS on the disk is ignoring the checksums, but + * it's more likely that they're using a non-standard seed, and the newly- + * written sectors will have the wrong checksum value. + * + * Non-standard headers are usually okay, because we don't rewrite the + * headers, just the sector contents. + */ +/*static*/ const DiskImg::NibbleDescr DiskImg::kStdNibbleDescrs[] = { + { + "DOS 3.3 Standard", + 16, + { 0xd5, 0xaa, 0x96 }, { 0xde, 0xaa, 0xeb }, + 0x00, // checksum seed + true, // verify checksum + true, // verify track + 2, // epilog verify count + { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, + 0x00, // checksum seed + true, // verify checksum + 2, // epilog verify count + kNibbleEnc62, + kNibbleSpecialNone, + }, + { + "DOS 3.3 Patched", + 16, + { 0xd5, 0xaa, 0x96 }, { 0xde, 0xaa, 0xeb }, + 0x00, // checksum seed + false, // verify checksum + false, // verify track + 0, // epilog verify count + { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, + 0x00, // checksum seed + true, // verify checksum + 0, // epilog verify count + kNibbleEnc62, + kNibbleSpecialNone, + }, + { + "DOS 3.3 Ignore Checksum", + 16, + { 0xd5, 0xaa, 0x96 }, { 0xde, 0xaa, 0xeb }, + 0x00, // checksum seed + false, // verify checksum + false, // verify track + 0, // epilog verify count + { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, + 0x00, // checksum seed + false, // verify checksum + 0, // epilog verify count + kNibbleEnc62, + kNibbleSpecialNone, + }, + { + "DOS 3.2 Standard", + 13, + { 0xd5, 0xaa, 0xb5 }, { 0xde, 0xaa, 0xeb }, + 0x00, + true, + true, + 2, + { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, + 0x00, + true, + 2, + kNibbleEnc53, + kNibbleSpecialNone, + }, + { + "DOS 3.2 Patched", + 13, + { 0xd5, 0xaa, 0xb5 }, { 0xde, 0xaa, 0xeb }, + 0x00, + false, + false, + 0, + { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, + 0x00, + true, + 0, + kNibbleEnc53, + kNibbleSpecialNone, + }, + { + "Muse DOS 3.2", // standard DOS 3.2 with doubled sectors + 13, + { 0xd5, 0xaa, 0xb5 }, { 0xde, 0xaa, 0xeb }, + 0x00, + true, + true, + 2, + { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, + 0x00, + true, + 2, + kNibbleEnc53, + kNibbleSpecialMuse, + }, + { + "RDOS 3.3", // SSI 16-sector RDOS, with altered headers + 16, + { 0xd4, 0xaa, 0x96 }, { 0xde, 0xaa, 0xeb }, + 0x00, + true, + true, + 0, // epilog verify count + { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, + 0x00, + true, + 2, + kNibbleEnc62, + kNibbleSpecialSkipFirstAddrByte, + /* odd tracks use d4aa96, even tracks use d5aa96 */ + }, + { + "RDOS 3.2", // SSI 13-sector RDOS, with altered headers + 13, + { 0xd4, 0xaa, 0xb7 }, { 0xde, 0xaa, 0xeb }, + 0x00, + true, + true, + 2, + { 0xd5, 0xaa, 0xad }, { 0xde, 0xaa, 0xeb }, + 0x00, + true, + 2, + kNibbleEnc53, + kNibbleSpecialNone, + }, + { + "Custom", // reserve space for empty slot + 0, + }, +}; +/*static*/ const DiskImg::NibbleDescr* +DiskImg::GetStdNibbleDescr(StdNibbleDescr idx) +{ + if ((int)idx < 0 || (int)idx >= (int) NELEM(kStdNibbleDescrs)) + return nil; + return &kStdNibbleDescrs[(int)idx]; +} + + +/* + * Initialize the members during construction. + */ +DiskImg::DiskImg(void) +{ + assert(Global::GetAppInitCalled()); + + fOuterFormat = kOuterFormatUnknown; + fFileFormat = kFileFormatUnknown; + fPhysical = kPhysicalFormatUnknown; + fpNibbleDescr = nil; + fOrder = kSectorOrderUnknown; + fFormat = kFormatUnknown; + + fFileSysOrder = kSectorOrderUnknown; + fSectorPairing = false; + fSectorPairOffset = -1; + + fpOuterGFD = nil; + fpWrapperGFD = nil; + fpDataGFD = nil; + fpOuterWrapper = nil; + fpImageWrapper = nil; + fpParentImg = nil; + fDOSVolumeNum = kVolumeNumNotSet; + fOuterLength = -1; + fWrappedLength = -1; + fLength = -1; + fExpandable = false; + fReadOnly = true; + fDirty = false; + + fHasSectors = false; + fHasBlocks = false; + fHasNibbles = false; + + fNumTracks = -1; + fNumSectPerTrack = -1; + fNumBlocks = -1; + + fpScanProgressCallback = NULL; + + /* + * Create a working copy of the nibble descr table. We want to leave + * open the possibility of applications editing or discarding entries, + * so we work off of a copy. + * + * Ideally we'd allow these to be set per-track, so that certain odd + * formats could be handled transparently (e.g. Muse tweaked DOS 3.2) + * for formatting as well as reading. + */ + assert(kStdNibbleDescrs[kNibbleDescrCustom].numSectors == 0); + assert(kNibbleDescrCustom == NELEM(kStdNibbleDescrs)-1); + fpNibbleDescrTable = new NibbleDescr[NELEM(kStdNibbleDescrs)]; + fNumNibbleDescrEntries = NELEM(kStdNibbleDescrs); + memcpy(fpNibbleDescrTable, kStdNibbleDescrs, sizeof(kStdNibbleDescrs)); + + fNibbleTrackBuf = nil; + fNibbleTrackLoaded = -1; + + fNuFXCompressType = kNuThreadFormatLZW2; + + fNotes = nil; + fpBadBlockMap = nil; + fDiskFSRefCnt = 0; +} + +/* + * Throw away local storage. + */ +DiskImg::~DiskImg(void) +{ + if (fpDataGFD != nil) { + WMSG0("~DiskImg closing GenericFD(s)\n"); + } + (void) CloseImage(); + delete[] fpNibbleDescrTable; + delete[] fNibbleTrackBuf; + delete[] fNotes; + delete fpBadBlockMap; + + /* normally these will be closed, but perhaps not if something failed */ + if (fpOuterGFD != nil) + delete fpOuterGFD; + if (fpWrapperGFD != nil) + delete fpWrapperGFD; + if (fpDataGFD != nil) + delete fpDataGFD; + if (fpOuterWrapper != nil) + delete fpOuterWrapper; + if (fpImageWrapper != nil) + delete fpImageWrapper; + + fDiskFSRefCnt = 100; // flag as freed +} + + +/* + * Set the nibble descr pointer. + */ +void +DiskImg::SetNibbleDescr(int idx) +{ + assert(idx >= 0 && idx < kNibbleDescrMAX); + fpNibbleDescr = &fpNibbleDescrTable[idx]; +} + +/* + * Set up a custom nibble descriptor. + */ +void +DiskImg::SetCustomNibbleDescr(const NibbleDescr* pDescr) +{ + if (pDescr == NULL) { + fpNibbleDescr = NULL; + } else { + assert(fpNibbleDescrTable != NULL); + //WMSG2("Overwriting entry %d with new value (special=%d)\n", + // kNibbleDescrCustom, pDescr->special); + fpNibbleDescrTable[kNibbleDescrCustom] = *pDescr; + fpNibbleDescr = &fpNibbleDescrTable[kNibbleDescrCustom]; + } +} + + +/* + * Open a volume or a file on disk. + * + * For Windows, we need to handle logical/physical volumes specially. If + * the filename matches the appropriate pattern, use a different GFD. + */ +DIError +DiskImg::OpenImage(const char* pathName, char fssep, bool readOnly) +{ + DIError dierr = kDIErrNone; + bool isWinDevice = false; + + if (fpDataGFD != nil) { + WMSG0(" DI already open!\n"); + return kDIErrAlreadyOpen; + } + WMSG3(" DI OpenImage '%s' '%.1s' ro=%d\n", pathName, &fssep, readOnly); + + fReadOnly = readOnly; + +#ifdef _WIN32 + if ((fssep == '\0' || fssep == '\\') && + pathName[0] >= 'A' && pathName[0] <= 'Z' && + pathName[1] == ':' && pathName[2] == '\\' && + pathName[3] == '\0') + { + isWinDevice = true; // logical volume ("A:\") + } + if ((fssep == '\0' || fssep == '\\') && + isdigit(pathName[0]) && isdigit(pathName[1]) && + pathName[2] == ':' && pathName[3] == '\\' && + pathName[4] == '\0') + { + isWinDevice = true; // physical volume ("80:\") + } + if ((fssep == '\0' || fssep == '\\') && + strncmp(pathName, kASPIDev, strlen(kASPIDev)) == 0 && + pathName[strlen(pathName)-1] == '\\') + { + isWinDevice = true; // ASPI volume ("ASPI:x:y:z\") + } +#endif + + if (isWinDevice) { +#ifdef _WIN32 + GFDWinVolume* pGFDWinVolume = new GFDWinVolume; + + dierr = pGFDWinVolume->Open(pathName, fReadOnly); + if (dierr != kDIErrNone) { + delete pGFDWinVolume; + goto bail; + } + + fpWrapperGFD = pGFDWinVolume; + // Use a unique extension to skip some of the probing. + dierr = AnalyzeImageFile("CPDevice.cp-win-vol", '\0'); + if (dierr != kDIErrNone) + goto bail; +#endif + } else { + GFDFile* pGFDFile = new GFDFile; + + dierr = pGFDFile->Open(pathName, fReadOnly); + if (dierr != kDIErrNone) { + delete pGFDFile; + goto bail; + } + + //fImageFileName = new char[strlen(pathName) + 1]; + //strcpy(fImageFileName, pathName); + + fpWrapperGFD = pGFDFile; + pGFDFile = nil; + + dierr = AnalyzeImageFile(pathName, fssep); + if (dierr != kDIErrNone) + goto bail; + } + + + assert(fpDataGFD != nil); + +bail: + return dierr; +} + +/* + * Open from a buffer, which could point to unadorned ready-to-go content + * or to a preloaded image file. + */ +DIError +DiskImg::OpenImage(const void* buffer, long length, bool readOnly) +{ + if (fpDataGFD != nil) { + WMSG0(" DI already open!\n"); + return kDIErrAlreadyOpen; + } + WMSG3(" DI OpenImage %08lx %ld ro=%d\n", (long) buffer, length, readOnly); + + DIError dierr; + GFDBuffer* pGFDBuffer; + + fReadOnly = readOnly; + pGFDBuffer = new GFDBuffer; + + dierr = pGFDBuffer->Open(const_cast(buffer), length, false, false, + readOnly); + if (dierr != kDIErrNone) { + delete pGFDBuffer; + return dierr; + } + + fpWrapperGFD = pGFDBuffer; + pGFDBuffer = nil; + + dierr = AnalyzeImageFile("", '\0'); + if (dierr != kDIErrNone) + return dierr; + + assert(fpDataGFD != nil); + return kDIErrNone; +} + +/* + * Open a range of blocks from an already-open disk image. This is only + * useful for things like UNIDOS volumes, which don't have an associated + * file in the image and are linear. + * + * The "read only" flag is inherited from the parent. + * + * For embedded images with visible file structure, we should be using + * an EmbeddedFD instead. [Note these were never implemented.] + * + * NOTE: there is an implicit ProDOS block ordering imposed on the parent + * image. It turns out that all of our current embedded parents use + * ProDOS-ordered blocks, so it works out okay, but the "linear" requirement + * above goes beyond just having contiguous blocks. + */ +DIError +DiskImg::OpenImage(DiskImg* pParent, long firstBlock, long numBlocks) +{ + WMSG3(" DI OpenImage parent=0x%08lx %ld %ld\n", (long) pParent, firstBlock, + numBlocks); + if (fpDataGFD != nil) { + WMSG0(" DI already open!\n"); + return kDIErrAlreadyOpen; + } + + if (pParent == nil || firstBlock < 0 || numBlocks <= 0 || + firstBlock + numBlocks > pParent->GetNumBlocks()) + { + assert(false); + return kDIErrInvalidArg; + } + + fReadOnly = pParent->GetReadOnly(); // very important + + DIError dierr; + GFDGFD* pGFDGFD; + + pGFDGFD = new GFDGFD; + dierr = pGFDGFD->Open(pParent->fpDataGFD, firstBlock * kBlockSize, fReadOnly); + if (dierr != kDIErrNone) { + delete pGFDGFD; + return dierr; + } + + fpDataGFD = pGFDGFD; + assert(fpWrapperGFD == nil); + + /* + * This replaces the call to "analyze image file" because we know we + * already have an open file with specific characteristics. + */ + //fOffset = pParent->fOffset + kBlockSize * firstBlock; + fLength = numBlocks * kBlockSize; + fOuterLength = fWrappedLength = fLength; + fFileFormat = kFileFormatUnadorned; + fPhysical = pParent->fPhysical; + fOrder = pParent->fOrder; + + fpParentImg = pParent; + + return dierr; +} +DIError +DiskImg::OpenImage(DiskImg* pParent, long firstTrack, long firstSector, + long numSectors) +{ + WMSG4(" DI OpenImage parent=0x%08lx %ld %ld %ld\n", (long) pParent, + firstTrack, firstSector, numSectors); + if (fpDataGFD != nil) { + WMSG0(" DI already open!\n"); + return kDIErrAlreadyOpen; + } + + if (pParent == nil) + return kDIErrInvalidArg; + + int prntSectPerTrack = pParent->GetNumSectPerTrack(); + int lastTrack = firstTrack + + (numSectors + prntSectPerTrack-1) / prntSectPerTrack; + if (firstTrack < 0 || numSectors <= 0 || + lastTrack > pParent->GetNumTracks()) + { + return kDIErrInvalidArg; + } + + fReadOnly = pParent->GetReadOnly(); // very important + + DIError dierr; + GFDGFD* pGFDGFD; + + pGFDGFD = new GFDGFD; + dierr = pGFDGFD->Open(pParent->fpDataGFD, + kSectorSize * firstTrack * prntSectPerTrack, fReadOnly); + if (dierr != kDIErrNone) { + delete pGFDGFD; + return dierr; + } + + fpDataGFD = pGFDGFD; + assert(fpWrapperGFD == nil); + + /* + * This replaces the call to "analyze image file" because we know we + * already have an open file with specific characteristics. + */ + assert(firstSector == 0); // else fOffset calculation breaks + //fOffset = pParent->fOffset + kSectorSize * firstTrack * prntSectPerTrack; + fLength = numSectors * kSectorSize; + fOuterLength = fWrappedLength = fLength; + fFileFormat = kFileFormatUnadorned; + fPhysical = pParent->fPhysical; + fOrder = pParent->fOrder; + + fpParentImg = pParent; + + return dierr; +} + + +/* + * Enable sector pairing. Useful for OzDOS. + */ +void +DiskImg::SetPairedSectors(bool enable, int idx) +{ + fSectorPairing = enable; + fSectorPairOffset = idx; + + if (enable) { + assert(idx == 0 || idx == 1); + } +} + +/* + * Close the image, freeing resources. + * + * If we write to a child DiskImg, it's responsible for setting the "dirty" + * flag in its parent (and so on up the chain). That's necessary so that, + * when we close the file, changes made to a child DiskImg cause the parent + * to do any necessary recompression. + * + * [ This is getting called even when image creation failed with an error. + * This is probably the correct behavior, but we may want to be aborting the + * image creation instead of completing it. That's a higher-level decision + * though. ++ATM 20040506 ] + */ +DIError +DiskImg::CloseImage(void) +{ + DIError dierr; + + WMSG1("CloseImage %p\n", this); + + /* check for DiskFS objects that still point to us */ + if (fDiskFSRefCnt != 0) { + WMSG1("ERROR: CloseImage: fDiskFSRefCnt=%d\n", fDiskFSRefCnt); + assert(false); //DebugBreak(); + } + + /* + * Flush any changes. + */ + dierr = FlushImage(kFlushAll); + if (dierr != kDIErrNone) + return dierr; + + /* + * Clean up. Close GFD, OrigGFD, and OuterGFD. Delete ImageWrapper + * and OuterWrapper. + * + * In some cases we will have the file open more than once (e.g. a + * NuFX archive, which must be opened on disk). + */ + if (fpDataGFD != nil) { + fpDataGFD->Close(); + delete fpDataGFD; + fpDataGFD = nil; + } + if (fpWrapperGFD != nil) { + fpWrapperGFD->Close(); + delete fpWrapperGFD; + fpWrapperGFD = nil; + } + if (fpOuterGFD != nil) { + fpOuterGFD->Close(); + delete fpOuterGFD; + fpOuterGFD = nil; + } + delete fpImageWrapper; + fpImageWrapper = nil; + delete fpOuterWrapper; + fpOuterWrapper = nil; + + return dierr; +} + + +/* + * Flush data to disk. + * + * The only time this really needs to do anything on a disk image file is + * when we have compressed data (NuFX, DDD, .gz, .zip). The uncompressed + * wrappers either don't do anything ("unadorned") or just update some + * header fields (DiskCopy42). + * + * If "mode" is kFlushFastOnly, we only flush the formats that don't really + * need flushing. This is part of a scheme to keep the disk contents in a + * reasonable state on the off chance we crash with a modified file open. + * It also helps the user understand when changes are being made immediately + * vs. when they're written to memory and compressed later. We could just + * refuse to raise the "dirty" flag when modifying "simple" file formats, + * but that would change the meaning of the flag from "something has been + * changed" to "what's in the file and what's in memory differ". I want it + * to be a "dirty" flag. + */ +DIError +DiskImg::FlushImage(FlushMode mode) +{ + DIError dierr = kDIErrNone; + + WMSG2(" DI FlushImage (dirty=%d mode=%d)\n", fDirty, mode); + if (!fDirty) + return kDIErrNone; + if (fpDataGFD == nil) { + /* + * This can happen if we tried to create a disk image but failed, e.g. + * couldn't create the output file because of access denied on the + * directory. There's no data, therefore nothing to flush, but the + * "dirty" flag is set because CreateImageCommon sets it almost + * immediately. + */ + WMSG0(" (disk must've failed during creation)\n"); + fDirty = false; + return kDIErrNone; + } + + if (mode == kFlushFastOnly && + ((fpImageWrapper != nil && !fpImageWrapper->HasFastFlush()) || + (fpOuterWrapper != nil && !fpOuterWrapper->HasFastFlush()) )) + { + WMSG0("DI fast flush requested, but one or both wrappers are slow\n"); + return kDIErrNone; + } + + /* + * Step 1: make sure any local caches have been flushed. + */ + /* (none) */ + + /* + * Step 2: push changes from fpDataGFD to fpWrapperGFD. This will + * cause ImageWrapper to rebuild itself (SHK, DDD, whatever). In + * some cases this amounts to copying the data on top of itself, + * which we can avoid easily. + * + * Embedded volumes don't have wrappers; when you write to an + * embedded volume, it passes straight through to the parent. + * + * (Note to self: formats like NuFX that write to a temp file and then + * rename over the old will close fpWrapperGFD and just access it + * directly. This is bad, because it doesn't allow them to have an + * "outer" format, but it's the way life is. The point is that it's + * okay for fpWrapperGFD to be non-nil but represent a closed file, + * so long as the "Flush" function has it figured out.) + */ + if (fpWrapperGFD != nil) { + WMSG2(" DI flushing data changes to wrapper (fLen=%ld fWrapLen=%ld)\n", + (long) fLength, (long) fWrappedLength); + dierr = fpImageWrapper->Flush(fpWrapperGFD, fpDataGFD, fLength, + &fWrappedLength); + if (dierr != kDIErrNone) { + WMSG1(" ERROR: wrapper flush failed (err=%d)\n", dierr); + return dierr; + } + /* flush the GFD in case it's a Win32 volume with block caching */ + dierr = fpWrapperGFD->Flush(); + } else { + assert(fpParentImg != nil); + } + + /* + * Step 3: if we have an fpOuterGFD, rebuild the file with the data + * in fpWrapperGFD. + */ + if (fpOuterWrapper != nil) { + WMSG1(" DI saving wrapper to outer, fWrapLen=%ld\n", + (long) fWrappedLength); + assert(fpOuterGFD != nil); + dierr = fpOuterWrapper->Save(fpOuterGFD, fpWrapperGFD, + fWrappedLength); + if (dierr != kDIErrNone) { + WMSG1(" ERROR: outer save failed (err=%d)\n", dierr); + return dierr; + } + } + + fDirty = false; + return kDIErrNone; +} + + + +/* + * Given the filename extension and a GFD, figure out what's inside. + * + * The filename extension should give us some idea what to expect: + * SHK, SDK, BXY - ShrinkIt compressed disk image + * GZ - gzip-compressed file (with something else inside) + * ZIP - ZIP archive with a single disk image inside + * DDD - DDD, DDD Pro, or DDD5.0 compressed image + * DSK - DiskCopy 4.2 or DO/PO + * DC - DiskCopy 4.2 (or 6?) + * DC6 - DiskCopy 6 (usually just raw sectors) + * DO, PO, D13, RAW? - DOS-order or ProDOS-order uncompressed + * IMG - Copy ][+ image (unadorned, physical sector order) + * HDV - virtual hard drive image + * NIB, RAW? - nibblized image + * (no extension) uncompressed + * cp-win-vol - our "magic" extension to indicate a Windows logical volume + * + * We can also examine the file length to see if it's a standard size + * (140K, 800K) and look for magic values in the header. + * + * If we can access the contents directly from disk, we do so. It's + * possibly more efficient to load the whole thing into memory, but if + * we have that much memory then the OS should cache it for us. (I have + * some 20MB disk images from my hard drive that shouldn't be loaded + * in their entirety. Certainly don't want to load a 512MB CFFA image.) + * + * On input, the following fields must be set: + * fpWrapperGFD - GenericFD for the file pointed to by "pathname" (or for a + * memory buffer if this is a sub-volume) + * + * On success, the following fields will be set: + * fWrappedLength, fOuterLength - set appropriately + * fpDataGFD - GFD for the raw data, possibly just a GFDGFD with an offset + * fLength - length of unadorned data in the file, or the length of + * data stored in fBuffer (test for fBuffer!=nil) + * fFileFormat - set to the overall file format, mostly interesting + * for identification of the file "wrapper" + * fPhysicalFormat - set to the type of data this holds + * (maybe) fOrder - set when the file format or extension dictates, e.g. + * 2MG or *.po; not always reliable + * (maybe) fDOSVolumeNum - set to DOS volume number from wrapper + * + * This may set fReadOnly if one of the wrappers looks okay but is reporting + * a bad checksum. + */ +DIError +DiskImg::AnalyzeImageFile(const char* pathName, char fssep) +{ + DIError dierr = kDIErrNone; + FileFormat probableFormat; + bool reliableExt; + const char* ext = FindExtension(pathName, fssep); + char* extBuf = nil; // uses malloc/free + bool needExtFromOuter = false; + + if (ext != nil) { + assert(*ext == '.'); + ext++; + } else + ext = ""; + + WMSG1(" DI AnalyzeImageFile ext='%s'\n", ext); + + /* sanity check: nobody should have configured these yet */ + assert(fOuterFormat == kOuterFormatUnknown); + assert(fFileFormat == kFileFormatUnknown); + assert(fOrder == kSectorOrderUnknown); + assert(fFormat == kFormatUnknown); + fLength = -1; + dierr = fpWrapperGFD->Seek(0, kSeekEnd); + if (dierr != kDIErrNone) { + WMSG0(" DI Couldn't seek to end of wrapperGFD\n"); + goto bail; + } + fWrappedLength = fOuterLength = fpWrapperGFD->Tell(); + + /* quick test for zero-length files */ + if (fWrappedLength == 0) + return kDIErrUnrecognizedFileFmt; + + /* + * Start by checking for a zip/gzip "wrapper wrapper". We want to strip + * that away before we do anything else. Because web sites tend to + * gzip everything in sight whether it needs it or not, we treat this + * as a special case and assume that anything could be inside. + * + * Some cases are difficult to handle, e.g. ".SDK", since NufxLib + * doesn't let us open an archive that is sitting in memory. + * + * We could also handle disk images stored as ordinary files stored + * inside SHK. Not much point in handling multiple files down at + * this level though. + */ + if (strcasecmp(ext, "gz") == 0 && + OuterGzip::Test(fpWrapperGFD, fOuterLength) == kDIErrNone) + { + WMSG0(" DI found gz outer wrapper\n"); + + fpOuterWrapper = new OuterGzip(); + if (fpOuterWrapper == nil) { + dierr = kDIErrMalloc; + goto bail; + } + fOuterFormat = kOuterFormatGzip; + + /* drop the ".gz" and get down to the next extension */ + ext = ""; + extBuf = strdup(pathName); + if (extBuf != nil) { + char* localExt; + + localExt = (char*) FindExtension(extBuf, fssep); + if (localExt != nil) + *localExt = '\0'; + localExt = (char*) FindExtension(extBuf, fssep); + if (localExt != nil) { + ext = localExt; + assert(*ext == '.'); + ext++; + } + } + WMSG1(" DI after gz, ext='%s'\n", ext == nil ? "(nil)" : ext); + + } else if (strcasecmp(ext, "zip") == 0) { + dierr = OuterZip::Test(fpWrapperGFD, fOuterLength); + if (dierr != kDIErrNone) + goto bail; + + WMSG0(" DI found ZIP outer wrapper\n"); + + fpOuterWrapper = new OuterZip(); + if (fpOuterWrapper == nil) { + dierr = kDIErrMalloc; + goto bail; + } + fOuterFormat = kOuterFormatZip; + + needExtFromOuter = true; + + } else { + fOuterFormat = kOuterFormatNone; + } + + /* finish up outer wrapper stuff */ + if (fOuterFormat != kOuterFormatNone) { + GenericFD* pNewGFD = nil; + dierr = fpOuterWrapper->Load(fpWrapperGFD, fOuterLength, fReadOnly, + &fWrappedLength, &pNewGFD); + if (dierr != kDIErrNone) { + WMSG0(" DI outer prep failed\n"); + /* extensions are "reliable", so failure is unavoidable */ + goto bail; + } + + /* Load() sets this */ + if (fpOuterWrapper->IsDamaged()) { + AddNote(kNoteWarning, "The zip/gzip wrapper appears to be damaged."); + fReadOnly = true; + } + + /* shift GFDs */ + fpOuterGFD = fpWrapperGFD; + fpWrapperGFD = pNewGFD; + + if (needExtFromOuter) { + ext = fpOuterWrapper->GetExtension(); + if (ext == nil) + ext = ""; + } + } + + /* + * Try to figure out what format the file is in. + * + * First pass, try only what the filename says it is. This way, if + * two file formats look alike, we have a good chance of getting it + * right. + * + * The "Test" functions have the complete file at their disposal. The + * file's length is stored in "fWrappedLength" for convenience. + */ + reliableExt = false; + probableFormat = kFileFormatUnknown; + if (strcasecmp(ext, "2mg") == 0 || strcasecmp(ext, "2img") == 0) { + reliableExt = true; + if (Wrapper2MG::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) + probableFormat = kFileFormat2MG; + } else if (strcasecmp(ext, "shk") == 0 || strcasecmp(ext, "sdk") == 0 || + strcasecmp(ext, "bxy") == 0) + { + DIError dierr2; + reliableExt = true; + dierr2 = WrapperNuFX::Test(fpWrapperGFD, fWrappedLength); + if (dierr2 == kDIErrNone) + probableFormat = kFileFormatNuFX; + else if (dierr2 == kDIErrFileArchive) { + WMSG0(" AnalyzeImageFile thinks it found a NuFX file archive\n"); + dierr = dierr2; + goto bail; + } + } else if (strcasecmp(ext, "hdv") == 0) { + /* usually just a "raw" disk, but check for Sim //e */ + if (WrapperSim2eHDV::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) + probableFormat = kFileFormatSim2eHDV; + + /* ProDOS .hdv volumes can expand */ + fExpandable = true; + } else if (strcasecmp(ext, "dsk") == 0 || strcasecmp(ext, "dc") == 0) { + /* might be DiskCopy */ + if (WrapperDiskCopy42::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) + probableFormat = kFileFormatDiskCopy42; + } else if (strcasecmp(ext, "ddd") == 0) { + /* do this after compressed formats but before unadorned */ + reliableExt = true; + if (WrapperDDD::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) + probableFormat = kFileFormatDDD; + } else if (strcasecmp(ext, "app") == 0) { + reliableExt = true; + if (WrapperTrackStar::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) + probableFormat = kFileFormatTrackStar; + } else if (strcasecmp(ext, "fdi") == 0) { + reliableExt = true; + if (WrapperFDI::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) + probableFormat = kFileFormatFDI; + } else if (strcasecmp(ext, "img") == 0) { + if (WrapperUnadornedSector::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) + { + probableFormat = kFileFormatUnadorned; + fPhysical = kPhysicalFormatSectors; + fOrder = kSectorOrderPhysical; + } + } else if (strcasecmp(ext, "nib") == 0 || strcasecmp(ext, "raw") == 0) { + if (WrapperUnadornedNibble::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) + { + probableFormat = kFileFormatUnadorned; + fPhysical = kPhysicalFormatNib525_6656; + /* figure out NibbleFormat later */ + } + } else if (strcasecmp(ext, "do") == 0 || strcasecmp(ext, "po") == 0 || + strcasecmp(ext, "d13") == 0 || strcasecmp(ext, "dc6") == 0) + { + if (WrapperUnadornedSector::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) + { + probableFormat = kFileFormatUnadorned; + fPhysical = kPhysicalFormatSectors; + if (strcasecmp(ext, "do") == 0 || strcasecmp(ext, "d13") == 0) + fOrder = kSectorOrderDOS; + else + fOrder = kSectorOrderProDOS; // po, dc6 + WMSG1(" DI guessing order is %d by extension\n", fOrder); + } + } else if (strcasecmp(ext, "cp-win-vol") == 0) { + /* this is a Windows logical volume */ + reliableExt = true; + probableFormat = kFileFormatUnadorned; + fPhysical = kPhysicalFormatSectors; + fOrder = kSectorOrderProDOS; + } else { + /* no match on the filename extension; start guessing */ + } + + if (probableFormat != kFileFormatUnknown) { + /* + * Found a match. Use "probableFormat" to open the file. + */ + WMSG1(" DI scored hit on extension '%s'\n", ext); + } else { + /* + * Didn't work. If the file extension was marked "reliable", then + * either we have the wrong extension on the file, or the contents + * are damaged. + * + * If the extension isn't reliable, or simply absent, then we have + * to probe through the formats we know and just hope for the best. + * + * If the "test" function returns with a checksum failure, we take + * it to mean that the format was positively identified, but the + * data inside is corrupted. This results in an immediate return + * with the checksum failure noted. Only a few wrapper formats + * have checksums embedded. (The "test" functions should only + * be looking at header checksums.) + */ + if (reliableExt) { + WMSG1(" DI file extension '%s' did not match contents\n", ext); + dierr = kDIErrBadFileFormat; + goto bail; + } else { + WMSG1(" DI extension '%s' not useful, probing formats\n", ext); + dierr = WrapperNuFX::Test(fpWrapperGFD, fWrappedLength); + if (dierr == kDIErrNone) { + probableFormat = kFileFormatNuFX; + goto gotit; + } else if (dierr == kDIErrFileArchive) + goto bail; // we know it's NuFX, we know we can't use it + else if (dierr == kDIErrBadChecksum) + goto bail; // right file type, bad data + + dierr = WrapperDiskCopy42::Test(fpWrapperGFD, fWrappedLength); + if (dierr == kDIErrNone) { + probableFormat = kFileFormatDiskCopy42; + goto gotit; + } else if (dierr == kDIErrBadChecksum) + goto bail; // right file type, bad data + + if (Wrapper2MG::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) { + probableFormat = kFileFormat2MG; + } else if (WrapperDDD::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) { + probableFormat = kFileFormatDDD; + } else if (WrapperSim2eHDV::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) + { + probableFormat = kFileFormatSim2eHDV; + } else if (WrapperTrackStar::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) + { + probableFormat = kFileFormatTrackStar; + } else if (WrapperFDI::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) + { + probableFormat = kFileFormatFDI; + } else if (WrapperUnadornedNibble::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) { + probableFormat = kFileFormatUnadorned; + fPhysical = kPhysicalFormatNib525_6656; // placeholder + } else if (WrapperUnadornedSector::Test(fpWrapperGFD, fWrappedLength) == kDIErrNone) { + probableFormat = kFileFormatUnadorned; + fPhysical = kPhysicalFormatSectors; + } +gotit: ; + } + } + + /* + * Either we recognize it or we don't. Finish opening the file by + * setting up "fLength" and "fPhysical" values, extracting data + * into a memory buffer if necessary. fpDataGFD is set up by the + * "prep" function. + * + * If we're lucky, this will also configure "fOrder" for us, which is + * important when we can't recognize the filesystem format (for correct + * operation of disk tools). + */ + switch (probableFormat) { + case kFileFormat2MG: + fpImageWrapper = new Wrapper2MG(); + break; + case kFileFormatDiskCopy42: + fpImageWrapper = new WrapperDiskCopy42(); + break; + case kFileFormatSim2eHDV: + fpImageWrapper = new WrapperSim2eHDV(); + break; + case kFileFormatTrackStar: + fpImageWrapper = new WrapperTrackStar(); + break; + case kFileFormatFDI: + fpImageWrapper = new WrapperFDI(); + fReadOnly = true; // writing to FDI not yet supported + break; + case kFileFormatNuFX: + fpImageWrapper = new WrapperNuFX(); + ((WrapperNuFX*)fpImageWrapper)->SetCompressType( + (NuThreadFormat) fNuFXCompressType); + break; + case kFileFormatDDD: + fpImageWrapper = new WrapperDDD(); + break; + case kFileFormatUnadorned: + if (IsSectorFormat(fPhysical)) + fpImageWrapper = new WrapperUnadornedSector(); + else if (IsNibbleFormat(fPhysical)) + fpImageWrapper = new WrapperUnadornedNibble(); + else { + assert(false); + } + break; + default: + WMSG0(" DI couldn't figure out the file format\n"); + dierr = kDIErrUnrecognizedFileFmt; + break; + } + if (fpImageWrapper != nil) { + assert(fpDataGFD == nil); + dierr = fpImageWrapper->Prep(fpWrapperGFD, fWrappedLength, fReadOnly, + &fLength, &fPhysical, &fOrder, &fDOSVolumeNum, + &fpBadBlockMap, &fpDataGFD); + } else { + /* could be a mem alloc failure that didn't set dierr */ + if (dierr == kDIErrNone) + dierr = kDIErrGeneric; + } + + if (dierr != kDIErrNone) { + WMSG1(" DI wrapper prep failed (err=%d)\n", dierr); + goto bail; + } + + /* check for non-fatal checksum failures, e.g. DiskCopy42 */ + if (fpImageWrapper->IsDamaged()) { + AddNote(kNoteWarning, "File checksum didn't match."); + fReadOnly = true; + } + + fFileFormat = probableFormat; + + assert(fLength >= 0); + assert(fpDataGFD != nil); + assert(fOuterFormat != kOuterFormatUnknown); + assert(fFileFormat != kFileFormatUnknown); + assert(fPhysical != kPhysicalFormatUnknown); + +bail: + free(extBuf); + return dierr; +} + + +/* + * Try to figure out what we're looking at. + * + * Returns an error if we don't think this is even a disk image. If we + * just can't figure it out, we return success but with the format value + * set to "unknown". This gives the caller a chance to use "override" + * to help us find our way. + * + * On entry: + * fpDataGFD, fLength, and fFileFormat are defined + * fSectorPairing is specified + * fOrder has a semi-reliable guess at sector ordering + * On exit: + * fOrder and fFormat are set to the best of our ability + * fNumTracks, fNumSectPerTrack, and fNumBlocks are set + * fHasSectors, fHasTracks, and fHasNibbles are set + * fFileSysOrder is set + * fpNibbleDescr will be set for nibble images + */ +DIError +DiskImg::AnalyzeImage(void) +{ + assert(fLength >= 0); + assert(fpDataGFD != nil); + assert(fFileFormat != kFileFormatUnknown); + assert(fPhysical != kPhysicalFormatUnknown); + assert(fFormat == kFormatUnknown); + assert(fFileSysOrder == kSectorOrderUnknown); + assert(fNumTracks == -1); + assert(fNumSectPerTrack == -1); + assert(fNumBlocks == -1); + if (fpDataGFD == nil) + return kDIErrInternal; + + /* + * Figure out how many tracks and sectors the image has. + * + * For an odd-sized ProDOS image, there will be no tracks and sectors. + */ + if (IsSectorFormat(fPhysical)) { + if (!fLength) { + WMSG0(" DI zero-length disk images not allowed\n"); + return kDIErrOddLength; + } + + if (fLength == kD13Length) { + /* 13-sector .d13 image */ + fHasSectors = true; + fNumSectPerTrack = 13; + fNumTracks = kTrackCount525; + assert(!fHasBlocks); + } else if (fLength % (16 * kSectorSize) == 0) { + /* looks like a collection of 16-sector tracks */ + fHasSectors = true; + + fNumSectPerTrack = 16; + fNumTracks = (int) (fLength / (fNumSectPerTrack * kSectorSize)); + + /* sector pairing effectively cuts #of tracks in half */ + if (fSectorPairing) { + if ((fNumTracks & 0x01) != 0) { + WMSG0(" DI error: bad attempt at sector pairing\n"); + assert(false); + fSectorPairing = false; + } + } + + if (fSectorPairing) + fNumTracks /= 2; + } else { + if (fSectorPairing) { + WMSG1("GLITCH: sector pairing enabled, but fLength=%ld\n", + (long) fLength); + return kDIErrOddLength; + } + + assert(fNumTracks == -1); + assert(fNumSectPerTrack == -1); + assert((fLength % kBlockSize) == 0); + + fHasBlocks = true; + fNumBlocks = (long) (fLength / kBlockSize); + } + } else if (IsNibbleFormat(fPhysical)) { + fHasNibbles = fHasSectors = true; + + /* + * Figure out if it's 13-sector or 16-sector (or garbage). We + * have to make an assessment of the entire disk so we can declare + * it to be 13-sector or 16-sector, which is useful for DiskFS + * which will want to scan for DOS VTOCs and other goodies. We + * also want to provide a default NibbleDescr. + * + * Failing that, we still allow it to be opened for raw track access. + * + * This also sets fNumTracks, which could be more than 35 if we're + * working with a TrackStar or FDI image. + */ + DIError dierr; + dierr = AnalyzeNibbleData(); // sets nibbleDescr and DOS vol num + if (dierr == kDIErrNone) { + assert(fpNibbleDescr != nil); + fNumSectPerTrack = fpNibbleDescr->numSectors; + fOrder = kSectorOrderPhysical; + + if (!fReadOnly && !fpNibbleDescr->dataVerifyChecksum) { + WMSG0("DI nibbleDescr does not verify data checksum, disabling writes\n"); + AddNote(kNoteInfo, + "Sectors use non-standard data checksums; writing disabled."); + fReadOnly = true; + } + } else { + //assert(fpNibbleDescr == nil); + fNumSectPerTrack = -1; + fOrder = kSectorOrderPhysical; + fHasSectors = false; + } + } else { + WMSG1("Unsupported physical %d\n", fPhysical); + assert(false); + return kDIErrGeneric; + } + + /* + * Compute the number of blocks. For a 13-sector disk, block access + * is not possible. + * + * For nibble formats, we have to base the block count on the number + * of sectors rather than the file length. + */ + if (fHasSectors) { + assert(fNumSectPerTrack > 0); + if ((fNumSectPerTrack & 0x01) == 0) { + /* not a 13-sector disk, so define blocks in terms of sectors */ + /* (effects of sector pairing are already taken into account) */ + fHasBlocks = true; + fNumBlocks = (fNumTracks * fNumSectPerTrack) / 2; + } + } else if (fHasBlocks) { + if ((fLength % kBlockSize) == 0) { + /* not sector-oriented, so define blocks based on length */ + fHasBlocks = true; + fNumBlocks = (long) (fLength / kBlockSize); + + if (fSectorPairing) { + if ((fNumBlocks & 0x01) != 0) { + WMSG0(" DI error: bad attempt at sector pairing (blk)\n"); + assert(false); + fSectorPairing = false; + } else + fNumBlocks /= 2; + } + + } else { + assert(false); + return kDIErrGeneric; + } + } else if (fHasNibbles) { + assert(fNumBlocks == -1); + } else { + WMSG0(" DI none of fHasSectors/fHasBlocks/fHasNibbles are set\n"); + assert(false); + return kDIErrInternal; + } + + /* + * We've got the track/sector/block layout sorted out; now figure out + * what kind of filesystem we're dealing with. + */ + AnalyzeImageFS(); + + WMSG4(" DI AnalyzeImage tracks=%ld sectors=%d blocks=%ld fileSysOrder=%d\n", + fNumTracks, fNumSectPerTrack, fNumBlocks, fFileSysOrder); + WMSG3(" hasBlocks=%d hasSectors=%d hasNibbles=%d\n", + fHasBlocks, fHasSectors, fHasNibbles); + + return kDIErrNone; +} + +/* + * Try to figure out what filesystem exists on this disk image. + * + * We want to test for DOS before ProDOS, because sometimes they overlap (e.g. + * 800K ProDOS disk with five 160K DOS volumes on it). + * + * Sets fFormat, fOrder, and fFileSysOrder. + */ +void +DiskImg::AnalyzeImageFS(void) +{ + /* + * In some circumstances it would be useful to have a set describing + * what filesystems we might expect to find, e.g. we're not likely to + * encounter RDOS embedded in a CF card. + */ + if (DiskFSMacPart::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + assert(fFormat == kFormatMacPart); + WMSG1(" DI found MacPart, order=%d\n", fOrder); + } else if (DiskFSMicroDrive::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + assert(fFormat == kFormatMicroDrive); + WMSG1(" DI found MicroDrive, order=%d\n", fOrder); + } else if (DiskFSFocusDrive::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + assert(fFormat == kFormatFocusDrive); + WMSG1(" DI found FocusDrive, order=%d\n", fOrder); + } else if (DiskFSCFFA::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + // The CFFA format doesn't have a partition map, but we do insist + // on finding multiple volumes. It needs to come after MicroDrive, + // because a disk formatted for CFFA then subsequently partitioned + // for MicroDrive will still look like valid CFFA unless you zero + // out the blocks. + assert(fFormat == kFormatCFFA4 || fFormat == kFormatCFFA8); + WMSG1(" DI found CFFA, order=%d\n", fOrder); + } else if (DiskFSFAT::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + // This is really just a trap to catch CFFA cards that were formatted + // for ProDOS and then re-formatted for MSDOS. As such it needs to + // come before the ProDOS test. It only works on larger volumes, + // and can be overridden, so it's pretty safe. + assert(fFormat == kFormatMSDOS); + WMSG1(" DI found MSDOS, order=%d\n", fOrder); + } else if (DiskFSDOS33::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + assert(fFormat == kFormatDOS32 || fFormat == kFormatDOS33); + WMSG1(" DI found DOS3.x, order=%d\n", fOrder); + if (fNumSectPerTrack == 13) + fFormat = kFormatDOS32; + } else if (DiskFSUNIDOS::TestWideFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + // Should only succeed on 400K embedded chunks. + assert(fFormat == kFormatDOS33); + fNumSectPerTrack = 32; + fNumTracks /= 2; + WMSG1(" DI found 'wide' DOS3.3, order=%d\n", fOrder); + } else if (DiskFSUNIDOS::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + assert(fFormat == kFormatUNIDOS); + fNumSectPerTrack = 32; + fNumTracks /= 2; + WMSG1(" DI found UNIDOS, order=%d\n", fOrder); + } else if (DiskFSOzDOS::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + assert(fFormat == kFormatOzDOS); + fNumSectPerTrack = 32; + fNumTracks /= 2; + WMSG1(" DI found OzDOS, order=%d\n", fOrder); + } else if (DiskFSProDOS::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + assert(fFormat == kFormatProDOS); + WMSG1(" DI found ProDOS, order=%d\n", fOrder); + } else if (DiskFSPascal::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + assert(fFormat == kFormatPascal); + WMSG1(" DI found Pascal, order=%d\n", fOrder); + } else if (DiskFSCPM::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + assert(fFormat == kFormatCPM); + WMSG1(" DI found CP/M, order=%d\n", fOrder); + } else if (DiskFSRDOS::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + assert(fFormat == kFormatRDOS33 || + fFormat == kFormatRDOS32 || + fFormat == kFormatRDOS3); + WMSG1(" DI found RDOS 3.3, order=%d\n", fOrder); + } else if (DiskFSHFS::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + assert(fFormat == kFormatMacHFS); + WMSG1(" DI found HFS, order=%d\n", fOrder); + } else if (DiskFSGutenberg::TestFS(this, &fOrder, &fFormat, DiskFS::kLeniencyNot) == kDIErrNone) + { + assert(fFormat == kFormatGutenberg); + WMSG1(" DI found Gutenberg, order=%d\n", fOrder); + } else { + fFormat = kFormatUnknown; + WMSG1(" DI no recognizeable filesystem found (fOrder=%d)\n", + fOrder); + } + + fFileSysOrder = CalcFSSectorOrder(); +} + + +/* + * Override the format determined by the analyzer. + * + * If they insist on the presence of a valid filesystem, check to make sure + * that filesystem actually exists. + * + * Note that this does not allow overriding the file structure, which must + * be clearly identifiable to be at all useful. If the file has no "wrapper" + * structure, the "unadorned" format should be specified, and the contents + * identified by the PhysicalFormat. + */ +DIError +DiskImg::OverrideFormat(PhysicalFormat physical, FSFormat format, + SectorOrder order) +{ + DIError dierr = kDIErrNone; + SectorOrder newOrder; + FSFormat newFormat; + + WMSG3(" DI override: physical=%d format=%d order=%d\n", + physical, format, order); + + if (!IsSectorFormat(physical) && !IsNibbleFormat(physical)) + return kDIErrUnsupportedPhysicalFmt; + + /* don't allow forcing physical format change */ + if (physical != fPhysical) + return kDIErrInvalidArg; + + /* optimization */ + if (physical == fPhysical && format == fFormat && order == fOrder) { + WMSG0(" DI override matches existing, ignoring\n"); + return kDIErrNone; + } + + newOrder = order; + newFormat = format; + + switch (format) { + case kFormatDOS33: + case kFormatDOS32: + dierr = DiskFSDOS33::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); + // Go ahead and allow the override even if the DOS version is wrong. + // So long as the sector count is correct, it's okay. + break; + case kFormatProDOS: + dierr = DiskFSProDOS::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); + break; + case kFormatPascal: + dierr = DiskFSPascal::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); + break; + case kFormatMacHFS: + dierr = DiskFSHFS::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); + break; + case kFormatUNIDOS: + dierr = DiskFSUNIDOS::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); + break; + case kFormatOzDOS: + dierr = DiskFSOzDOS::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); + break; + case kFormatCFFA4: + case kFormatCFFA8: + dierr = DiskFSCFFA::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); + // So long as it's CFFA, we allow the user to force it to be 4-mode + // or 8-mode. Don't require newFormat==format. + break; + case kFormatMacPart: + dierr = DiskFSMacPart::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); + break; + case kFormatMicroDrive: + dierr = DiskFSMicroDrive::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); + break; + case kFormatFocusDrive: + dierr = DiskFSFocusDrive::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); + break; + case kFormatCPM: + dierr = DiskFSCPM::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); + break; + case kFormatMSDOS: + dierr = DiskFSFAT::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); + break; + case kFormatRDOS33: + case kFormatRDOS32: + case kFormatRDOS3: + dierr = DiskFSRDOS::TestFS(this, &newOrder, &newFormat, DiskFS::kLeniencyVery); + if (newFormat != format) + dierr = kDIErrFilesystemNotFound; // found RDOS, but wrong flavor + break; + case kFormatGenericPhysicalOrd: + case kFormatGenericProDOSOrd: + case kFormatGenericDOSOrd: + case kFormatGenericCPMOrd: + /* no discussion possible, since there's no FS to validate */ + newFormat = format; + newOrder = order; + break; + case kFormatUnknown: + /* only valid in rare situations, e.g. CFFA CreatePlaceholder */ + newFormat = format; + newOrder = order; + break; + default: + dierr = kDIErrUnsupportedFSFmt; + break; + } + + if (dierr != kDIErrNone) { + WMSG0(" DI override failed\n"); + goto bail; + } + + /* + * We passed in "order" to TestFS. If it came back with something + * different, it means that it didn't like the new order value even + * when "leniency" was granted. + */ + if (newOrder != order) { + dierr = kDIErrBadOrdering; + goto bail; + } + + fFormat = format; + fOrder = newOrder; + fFileSysOrder = CalcFSSectorOrder(); + + WMSG0(" DI override accepted\n"); + +bail: + return dierr; +} + +/* + * Figure out the sector ordering for this filesystem, so we can decide + * how the sectors need to be re-arranged when we're reading them. + * + * If the value returned by this function matches fOrder, then no swapping + * will be done. + * + * NOTE: this table is redundant with some knowledge embedded in the + * individual "TestFS" functions. + */ +DiskImg::SectorOrder +DiskImg::CalcFSSectorOrder(void) const +{ + /* in the absence of information, just leave it alone */ + if (fFormat == kFormatUnknown || fOrder == kSectorOrderUnknown) { + WMSG0(" DI WARNING: FindSectorOrder but format not known\n"); + return fOrder; + } + + assert(fOrder == kSectorOrderPhysical || fOrder == kSectorOrderCPM || + fOrder == kSectorOrderProDOS || fOrder == kSectorOrderDOS); + + switch (fFormat) { + case kFormatGenericPhysicalOrd: + case kFormatRDOS32: + case kFormatRDOS3: + return kSectorOrderPhysical; + + case kFormatGenericDOSOrd: + case kFormatDOS33: + case kFormatDOS32: + case kFormatUNIDOS: + case kFormatOzDOS: + case kFormatGutenberg: + return kSectorOrderDOS; + + case kFormatGenericCPMOrd: + case kFormatCPM: + return kSectorOrderCPM; + + case kFormatGenericProDOSOrd: + case kFormatProDOS: + case kFormatRDOS33: + case kFormatPascal: + case kFormatMacHFS: + case kFormatMacMFS: + case kFormatLisa: + case kFormatMSDOS: + case kFormatISO9660: + case kFormatCFFA4: + case kFormatCFFA8: + case kFormatMacPart: + case kFormatMicroDrive: + case kFormatFocusDrive: + return kSectorOrderProDOS; + + default: + assert(false); + return fOrder; + } +} + +/* + * Based on the disk format, figure out if we should prefer blocks or + * sectors when examining disk contents. + */ +bool +DiskImg::ShowAsBlocks(void) const +{ + if (!fHasBlocks) + return false; + + /* in the absence of information, assume sectors */ + if (fFormat == kFormatUnknown) { + if (fOrder == kSectorOrderProDOS) + return true; + else + return false; + } + + switch (fFormat) { + case kFormatGenericPhysicalOrd: + case kFormatGenericDOSOrd: + case kFormatDOS33: + case kFormatDOS32: + case kFormatRDOS3: + case kFormatRDOS33: + case kFormatUNIDOS: + case kFormatOzDOS: + case kFormatGutenberg: + return false; + + case kFormatGenericProDOSOrd: + case kFormatGenericCPMOrd: + case kFormatProDOS: + case kFormatPascal: + case kFormatMacHFS: + case kFormatMacMFS: + case kFormatLisa: + case kFormatCPM: + case kFormatMSDOS: + case kFormatISO9660: + case kFormatCFFA4: + case kFormatCFFA8: + case kFormatMacPart: + case kFormatMicroDrive: + case kFormatFocusDrive: + return true; + + default: + assert(false); + return false; + } +} + + +/* + * Format an image with the requested fileystem format. This only works if + * the matching DiskFS supports formatting of disks. + */ +DIError +DiskImg::FormatImage(FSFormat format, const char* volName) +{ + DIError dierr = kDIErrNone; + DiskFS* pDiskFS = nil; + FSFormat savedFormat; + + WMSG1(" DI FormatImage '%s'\n", volName); + + /* + * Open a temporary DiskFS for the requested format. We do this via the + * standard OpenAppropriate call, so we temporarily switch our format + * out. (We will eventually replace it, but we want to make sure that + * local error handling works correctly, so we restore it for now.) + */ + savedFormat = fFormat; + fFormat = format; + pDiskFS = OpenAppropriateDiskFS(false); + fFormat = savedFormat; + + if (pDiskFS == nil) { + dierr = kDIErrUnsupportedFSFmt; + goto bail; + } + + dierr = pDiskFS->Format(this, volName); + if (dierr != kDIErrNone) + goto bail; + + WMSG0("DI format successful\n"); + fFormat = format; + +bail: + delete pDiskFS; + return dierr; +} + +/* + * Clear an image to zeros, usually done as a prelude to a higher-level format. + * + * BUG: this should also handle the track/sector case. + * + * HEY: this is awfully slow on large disks... should have some sort of + * optimized path that just writes to the GFD or something. Maybe even just + * a "ZeroBlock" instead of "WriteBlock" so we can memset instead of memcpy? + */ +DIError +DiskImg::ZeroImage(void) +{ + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlockSize]; + long block; + + WMSG1(" DI ZeroImage (%ld blocks)\n", GetNumBlocks()); + memset(blkBuf, 0, sizeof(blkBuf)); + + for (block = 0; block < GetNumBlocks(); block++) { + dierr = WriteBlock(block, blkBuf); + if (dierr != kDIErrNone) + break; + } + + return dierr; +} + + +/* + * Set the "scan progress" function. + * + * We want to use the same function for our sub-volumes too. + */ +void +DiskImg::SetScanProgressCallback(ScanProgressCallback func, void* cookie) +{ + if (fpParentImg != nil) { + /* unexpected, but perfectly okay */ + DebugBreak(); + } + + fpScanProgressCallback = func; + fScanProgressCookie = cookie; + fScanCount = 0; + fScanMsg[0] = '\0'; + fScanLastMsgWhen = time(nil); +} + +/* + * Update the progress. Call with a string at the start of a volume, then + * call with a NULL pointer every time we add a file. + */ +bool +DiskImg::UpdateScanProgress(const char* newStr) +{ + ScanProgressCallback func = fpScanProgressCallback; + DiskImg* pImg = this; + bool result = true; + + /* search up the tree to find a progress updater */ + while (func == nil) { + pImg = pImg->fpParentImg; + if (pImg == nil) + return result; // none defined, bail out + func = pImg->fpScanProgressCallback; + } + + time_t now = time(nil); + + if (newStr == NULL) { + fScanCount++; + //if ((fScanCount % 100) == 0) + if (fScanLastMsgWhen != now) { + result = (*func)(fScanProgressCookie, + fScanMsg, fScanCount); + fScanLastMsgWhen = now; + } + } else { + fScanCount = 0; + strncpy(fScanMsg, newStr, sizeof(fScanMsg)); + fScanMsg[sizeof(fScanMsg)-1] = '\0'; + result = (*func)(fScanProgressCookie, fScanMsg, + fScanCount); + fScanLastMsgWhen = now; + } + + return result; +} + + +/* + * ========================================================================== + * Block/track/sector I/O + * ========================================================================== + */ + +/* + * Handle sector order conversions. + */ +DIError +DiskImg::CalcSectorAndOffset(long track, int sector, SectorOrder imageOrder, + SectorOrder fsOrder, di_off_t* pOffset, int* pNewSector) +{ + if (!fHasSectors) + return kDIErrUnsupportedAccess; + + /* + * Sector order conversions. No table is needed for Copy ][+ format, + * which is equivalent to "physical". + */ + static const int raw2dos[16] = { + 0, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 15 + }; + static const int dos2raw[16] = { + 0, 13, 11, 9, 7, 5, 3, 1, 14, 12, 10, 8, 6, 4, 2, 15 + }; + static const int raw2prodos[16] = { + 0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15 + }; + static const int prodos2raw[16] = { + 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 + }; + static const int raw2cpm[16] = { + 0, 11, 6, 1, 12, 7, 2, 13, 8, 3, 14, 9, 4, 15, 10, 5 + }; + static const int cpm2raw[16] = { + 0, 3, 6, 9, 12, 15, 2, 5, 8, 11, 14, 1, 4, 7, 10, 13 + }; + + if (track < 0 || track >= fNumTracks) { + WMSG1(" DI read invalid track %ld\n", track); + return kDIErrInvalidTrack; + } + if (sector < 0 || sector >= fNumSectPerTrack) { + WMSG1(" DI read invalid sector %d\n", sector); + return kDIErrInvalidSector; + } + + di_off_t offset; + int newSector = -1; + + /* + * 16-sector disks write sectors in ascending order and then remap + * them with a translation table. + */ + if (fNumSectPerTrack == 16 || fNumSectPerTrack == 32) { + if (fSectorPairing) { + assert(fSectorPairOffset == 0 || fSectorPairOffset == 1); + // this pushes "track" beyond fNumTracks + track *= 2; + if (sector >= 16) { + track++; + sector -= 16; + } + offset = track * fNumSectPerTrack * kSectorSize; + + sector = sector * 2 + fSectorPairOffset; + if (sector >= 16) { + offset += 16*kSectorSize; + sector -= 16; + } + } else { + offset = track * fNumSectPerTrack * kSectorSize; + if (sector >= 16) { + offset += 16*kSectorSize; + sector -= 16; + } + } + assert(sector >= 0 && sector < 16); + + /* convert request to "raw" sector number */ + switch (fsOrder) { + case kSectorOrderProDOS: + newSector = prodos2raw[sector]; + break; + case kSectorOrderDOS: + newSector = dos2raw[sector]; + break; + case kSectorOrderCPM: + newSector = cpm2raw[sector]; + break; + case kSectorOrderPhysical: // used for Copy ][+ + newSector = sector; + break; + case kSectorOrderUnknown: + // should never happen; fall through to "default" + default: + assert(false); + newSector = sector; + break; + } + + /* convert "raw" request to the image's ordering */ + switch (imageOrder) { + case kSectorOrderProDOS: + newSector = raw2prodos[newSector]; + break; + case kSectorOrderDOS: + newSector = raw2dos[newSector]; + break; + case kSectorOrderCPM: + newSector = raw2cpm[newSector]; + break; + case kSectorOrderPhysical: + //newSector = newSector; + break; + case kSectorOrderUnknown: + // should never happen; fall through to "default" + default: + assert(false); + //newSector = newSector; + break; + } + + if (imageOrder == fsOrder) { + assert(sector == newSector); + } + + offset += newSector * kSectorSize; + } else if (fNumSectPerTrack == 13) { + /* sector skew has no meaning, so assume no translation */ + offset = track * fNumSectPerTrack * kSectorSize; + newSector = sector; + offset += newSector * kSectorSize; + if (imageOrder != fsOrder) { + /* translation expected */ + WMSG2("NOTE: CalcSectorAndOffset for nspt=13 with img=%d fs=%d\n", + imageOrder, fsOrder); + } + } else { + assert(false); // should not be here + + /* try to do something reasonable */ + assert(imageOrder == fsOrder); + offset = (di_off_t)track * fNumSectPerTrack * kSectorSize; + offset += sector * kSectorSize; + } + + *pOffset = offset; + *pNewSector = newSector; + return kDIErrNone; +} + +/* + * Determine whether an image uses a linear mapping. This allows us to + * optimize block reads & writes, very useful when dealing with logical + * volumes under Windows (which also use 512-byte blocks). + * + * The "imageOrder" argument usually comes from fOrder, and "fsOrder" + * comes from "fFileSysOrder". + */ +inline bool +DiskImg::IsLinearBlocks(SectorOrder imageOrder, SectorOrder fsOrder) +{ + /* + * Any time fOrder==fFileSysOrder, we know that we have a linear + * mapping. This holds true for reading ProDOS blocks from a ".po" + * file or reading DOS sectors from a ".do" file. + */ + return (IsSectorFormat(fPhysical) && fHasBlocks && + imageOrder == fsOrder); +} + +/* + * Read the specified track and sector, adjusting for sector ordering as + * appropriate. + * + * Copies 256 bytes into "*buf". + * + * Returns 0 on success, nonzero on failure. + */ +DIError +DiskImg::ReadTrackSectorSwapped(long track, int sector, void* buf, + SectorOrder imageOrder, SectorOrder fsOrder) +{ + DIError dierr; + di_off_t offset; + int newSector = -1; + + if (buf == nil) + return kDIErrInvalidArg; + +#if 0 // Pre-d13 + if (fNumSectPerTrack == 13) { + /* no sector skewing possible for 13-sector disks */ + assert(fHasNibbles); + + return ReadNibbleSector(track, sector, buf, fpNibbleDescr); + } +#endif + + dierr = CalcSectorAndOffset(track, sector, imageOrder, fsOrder, + &offset, &newSector); + if (dierr != kDIErrNone) + return dierr; + + if (IsSectorFormat(fPhysical)) { + assert(offset+kSectorSize <= fLength); + + //WMSG2(" DI t=%d s=%d\n", track, + // (offset - track * fNumSectPerTrack * kSectorSize) / kSectorSize); + + dierr = CopyBytesOut(buf, offset, kSectorSize); + } else if (IsNibbleFormat(fPhysical)) { + if (imageOrder != kSectorOrderPhysical) { + WMSG2(" NOTE: nibble imageOrder is %d (expected %d)\n", + imageOrder, kSectorOrderPhysical); + } + dierr = ReadNibbleSector(track, newSector, buf, fpNibbleDescr); + } else { + assert(false); + dierr = kDIErrInternal; + } + + return dierr; +} + +/* + * Write the specified track and sector, adjusting for sector ordering as + * appropriate. + * + * Copies 256 bytes out of "buf". + * + * Returns 0 on success, nonzero on failure. + */ +DIError +DiskImg::WriteTrackSector(long track, int sector, const void* buf) +{ + DIError dierr; + di_off_t offset; + int newSector = -1; + + if (buf == nil) + return kDIErrInvalidArg; + if (fReadOnly) + return kDIErrAccessDenied; + +#if 0 // Pre-d13 + if (fNumSectPerTrack == 13) { + /* no sector skewing possible for 13-sector disks */ + assert(fHasNibbles); + + return WriteNibbleSector(track, sector, buf, fpNibbleDescr); + } +#endif + + dierr = CalcSectorAndOffset(track, sector, fOrder, fFileSysOrder, + &offset, &newSector); + if (dierr != kDIErrNone) + return dierr; + + if (IsSectorFormat(fPhysical)) { + assert(offset+kSectorSize <= fLength); + + //WMSG2(" DI t=%d s=%d\n", track, + // (offset - track * fNumSectPerTrack * kSectorSize) / kSectorSize); + + dierr = CopyBytesIn(buf, offset, kSectorSize); + } else if (IsNibbleFormat(fPhysical)) { + if (fOrder != kSectorOrderPhysical) { + WMSG2(" NOTE: nibble fOrder is %d (expected %d)\n", + fOrder, kSectorOrderPhysical); + } + dierr = WriteNibbleSector(track, newSector, buf, fpNibbleDescr); + } else { + assert(false); + dierr = kDIErrInternal; + } + + return dierr; +} + +/* + * Read a 512-byte block. + * + * Copies 512 bytes into "*buf". + */ +DIError +DiskImg::ReadBlockSwapped(long block, void* buf, SectorOrder imageOrder, + SectorOrder fsOrder) +{ + if (!fHasBlocks) + return kDIErrUnsupportedAccess; + if (block < 0 || block >= fNumBlocks) + return kDIErrInvalidBlock; + if (buf == nil) + return kDIErrInvalidArg; + + DIError dierr; + long track, blkInTrk; + + /* if we have a bad block map, check it */ + if (CheckForBadBlocks(block, 1)) { + dierr = kDIErrReadFailed; + goto bail; + } + + if (fHasSectors && !IsLinearBlocks(imageOrder, fsOrder)) { + /* run it through the t/s call so we handle DOS ordering */ + track = block / (fNumSectPerTrack/2); + blkInTrk = block - (track * (fNumSectPerTrack/2)); + dierr = ReadTrackSectorSwapped(track, blkInTrk*2, buf, + imageOrder, fsOrder); + if (dierr != kDIErrNone) + return dierr; + dierr = ReadTrackSectorSwapped(track, blkInTrk*2+1, + (char*)buf+kSectorSize, imageOrder, fsOrder); + } else if (fHasBlocks) { + /* no sectors, so no swapping; must be linear blocks */ + if (imageOrder != fsOrder) { + WMSG2(" DI NOTE: ReadBlockSwapped on non-sector (%d/%d)\n", + imageOrder, fsOrder); + } + dierr = CopyBytesOut(buf, (di_off_t) block * kBlockSize, kBlockSize); + } else { + assert(false); + dierr = kDIErrInternal; + } + +bail: + return dierr; +} + +/* + * Read multiple blocks. + * + * IMPORTANT: this returns immediately when a read fails. The buffer will + * probably not contain data from all readable sectors. The application is + * expected to retry the blocks individually. + */ +DIError +DiskImg::ReadBlocks(long startBlock, int numBlocks, void* buf) +{ + DIError dierr = kDIErrNone; + + assert(fHasBlocks); + assert(startBlock >= 0); + assert(numBlocks > 0); + assert(buf != nil); + + if (startBlock < 0 || numBlocks + startBlock > GetNumBlocks()) { + assert(false); + return kDIErrInvalidArg; + } + + /* if we have a bad block map, check it */ + if (CheckForBadBlocks(startBlock, numBlocks)) { + dierr = kDIErrReadFailed; + goto bail; + } + + if (!IsLinearBlocks(fOrder, fFileSysOrder)) { + /* + * This isn't a collection of linear blocks, so we need to read it one + * block at a time with sector swapping. This almost certainly means + * that we're not reading from physical media, so performance shouldn't + * be an issue. + */ + if (startBlock == 0) { + WMSG0(" ReadBlocks: nonlinear, not trying\n"); + } + while (numBlocks--) { + dierr = ReadBlock(startBlock, buf); + if (dierr != kDIErrNone) + goto bail; + startBlock++; + buf = (unsigned char*)buf + kBlockSize; + } + } else { + if (startBlock == 0) { + WMSG0(" ReadBlocks: doing big linear reads\n"); + } + dierr = CopyBytesOut(buf, + (di_off_t) startBlock * kBlockSize, numBlocks * kBlockSize); + } + +bail: + return dierr; +} + +/* + * Check to see if any blocks in a range of blocks show up in the bad + * block map. This is primarily useful for 3.5" disk images converted + * from nibble images, because we convert them directly to "cooked" + * 512-byte blocks. + * + * Returns "true" if we found bad blocks, "false" if not. + */ +bool +DiskImg::CheckForBadBlocks(long startBlock, int numBlocks) +{ + int i; + + if (fpBadBlockMap == nil) + return false; + + for (i = startBlock; i < startBlock+numBlocks; i++) { + if (fpBadBlockMap->IsSet(i)) + return true; + } + return false; +} + +/* + * Write a block of data to a DiskImg. + * + * Returns immediately when a block write fails. Does not try to write all + * blocks before returning failure. + */ +DIError +DiskImg::WriteBlock(long block, const void* buf) +{ + if (!fHasBlocks) + return kDIErrUnsupportedAccess; + if (block < 0 || block >= fNumBlocks) + return kDIErrInvalidBlock; + if (buf == nil) + return kDIErrInvalidArg; + if (fReadOnly) + return kDIErrAccessDenied; + + DIError dierr; + long track, blkInTrk; + + if (fHasSectors && !IsLinearBlocks(fOrder, fFileSysOrder)) { + /* run it through the t/s call so we handle DOS ordering */ + track = block / (fNumSectPerTrack/2); + blkInTrk = block - (track * (fNumSectPerTrack/2)); + dierr = WriteTrackSector(track, blkInTrk*2, buf); + if (dierr != kDIErrNone) + return dierr; + dierr = WriteTrackSector(track, blkInTrk*2+1, (char*)buf+kSectorSize); + } else if (fHasBlocks) { + /* no sectors, so no swapping; must be linear blocks */ + if (fOrder != fFileSysOrder) { + WMSG2(" DI NOTE: WriteBlock on non-sector (%d/%d)\n", + fOrder, fFileSysOrder); + } + dierr = CopyBytesIn(buf, (di_off_t)block * kBlockSize, kBlockSize); + } else { + assert(false); + dierr = kDIErrInternal; + } + return dierr; +} + +/* + * Write multiple blocks. + */ +DIError +DiskImg::WriteBlocks(long startBlock, int numBlocks, const void* buf) +{ + DIError dierr = kDIErrNone; + + assert(fHasBlocks); + assert(startBlock >= 0); + assert(numBlocks > 0); + assert(buf != nil); + + if (startBlock < 0 || numBlocks + startBlock > GetNumBlocks()) { + assert(false); + return kDIErrInvalidArg; + } + + if (!IsLinearBlocks(fOrder, fFileSysOrder)) { + /* + * This isn't a collection of linear blocks, so we need to write it + * one block at a time with sector swapping. This almost certainly + * means that we're not reading from physical media, so performance + * shouldn't be an issue. + */ + if (startBlock == 0) { + WMSG0(" WriteBlocks: nonlinear, not trying\n"); + } + while (numBlocks--) { + dierr = WriteBlock(startBlock, buf); + if (dierr != kDIErrNone) + goto bail; + startBlock++; + buf = (unsigned char*)buf + kBlockSize; + } + } else { + if (startBlock == 0) { + WMSG0(" WriteBlocks: doing big linear writes\n"); + } + dierr = CopyBytesIn(buf, + (di_off_t) startBlock * kBlockSize, numBlocks * kBlockSize); + } + +bail: + return dierr; +} + + +/* + * Copy a chunk of bytes out of the disk image. + * + * (This is the lowest-level read routine in this class.) + */ +DIError +DiskImg::CopyBytesOut(void* buf, di_off_t offset, int size) const +{ + DIError dierr; + + dierr = fpDataGFD->Seek(offset, kSeekSet); + if (dierr != kDIErrNone) { + WMSG2(" DI seek off=%ld failed (err=%d)\n", (long) offset, dierr); + return dierr; + } + + dierr = fpDataGFD->Read(buf, size); + if (dierr != kDIErrNone) { + WMSG3(" DI read off=%ld size=%d failed (err=%d)\n", + (long) offset, size, dierr); + return dierr; + } + + return kDIErrNone; +} + +/* + * Copy a chunk of bytes into the disk image. + * + * Sets the "dirty" flag. + * + * (This is the lowest-level write routine in DiskImg.) + */ +DIError +DiskImg::CopyBytesIn(const void* buf, di_off_t offset, int size) +{ + DIError dierr; + + if (fReadOnly) { + DebugBreak(); + return kDIErrAccessDenied; + } + assert(fpDataGFD != nil); // somebody closed the image? + + dierr = fpDataGFD->Seek(offset, kSeekSet); + if (dierr != kDIErrNone) { + WMSG2(" DI seek off=%ld failed (err=%d)\n", (long) offset, dierr); + return dierr; + } + + dierr = fpDataGFD->Write(buf, size); + if (dierr != kDIErrNone) { + WMSG3(" DI write off=%ld size=%d failed (err=%d)\n", + (long) offset, size, dierr); + return dierr; + } + + /* set the dirty flag here and everywhere above */ + DiskImg* pImg = this; + while (pImg != nil) { + pImg->fDirty = true; + pImg = pImg->fpParentImg; + } + + return kDIErrNone; +} + + +/* + * =========================================================================== + * Image creation + * =========================================================================== + */ + +/* + * Create a disk image with the specified parameters. + * + * "storageName" and "pNibbleDescr" may be nil. + */ +DIError +DiskImg::CreateImage(const char* pathName, const char* storageName, + OuterFormat outerFormat, FileFormat fileFormat, PhysicalFormat physical, + const NibbleDescr* pNibbleDescr, SectorOrder order, + FSFormat format, long numBlocks, bool skipFormat) +{ + assert(fpDataGFD == nil); // should not be open already! + + if (numBlocks <= 0) { + WMSG1("ERROR: bad numBlocks %ld\n", numBlocks); + assert(false); + return kDIErrInvalidCreateReq; + } + + fOuterFormat = outerFormat; + fFileFormat = fileFormat; + fPhysical = physical; + SetCustomNibbleDescr(pNibbleDescr); + fOrder = order; + fFormat = format; + + fNumBlocks = numBlocks; + fHasBlocks = true; + + return CreateImageCommon(pathName, storageName, skipFormat); +} +DIError +DiskImg::CreateImage(const char* pathName, const char* storageName, + OuterFormat outerFormat, FileFormat fileFormat, PhysicalFormat physical, + const NibbleDescr* pNibbleDescr, SectorOrder order, + FSFormat format, long numTracks, long numSectPerTrack, bool skipFormat) +{ + assert(fpDataGFD == nil); // should not be open already! + + if (numTracks <= 0 || numSectPerTrack == 0) { + WMSG2("ERROR: bad tracks/sectors %ld/%ld\n", numTracks, numSectPerTrack); + assert(false); + return kDIErrInvalidCreateReq; + } + + fOuterFormat = outerFormat; + fFileFormat = fileFormat; + fPhysical = physical; + SetCustomNibbleDescr(pNibbleDescr); + fOrder = order; + fFormat = format; + + fNumTracks = numTracks; + fNumSectPerTrack = numSectPerTrack; + fHasSectors = true; + if (numSectPerTrack < 0) { + /* nibble image with non-standard formatting */ + if (!IsNibbleFormat(fPhysical)) { + WMSG0("Whoa: expected nibble format here\n"); + assert(false); + return kDIErrInvalidCreateReq; + } + WMSG0("Sector image w/o sectors, switching to nibble mode\n"); + fHasNibbles = true; + fHasSectors = false; + fpNibbleDescr = nil; + } + + return CreateImageCommon(pathName, storageName, skipFormat); +} + +/* + * Do the actual disk image creation. + */ +DIError +DiskImg::CreateImageCommon(const char* pathName, const char* storageName, + bool skipFormat) +{ + DIError dierr; + + /* + * Step 1: figure out fHasBlocks/fHasSectors/fHasNibbles and any + * other misc fields. + * + * If the disk is a nibble image expected to have a particular + * volume number, it should have already been set by the application. + */ + if (fHasBlocks) { + if ((fNumBlocks % 8) == 0) { + fHasSectors = true; + fNumSectPerTrack = 16; + fNumTracks = fNumBlocks / 8; + } else { + WMSG0("NOTE: sector access to new image not possible\n"); + } + } else if (fHasSectors) { + if ((fNumSectPerTrack & 0x01) == 0) { + fHasBlocks = true; + fNumBlocks = (fNumTracks * fNumSectPerTrack) / 2; + } else { + WMSG0("NOTE: block access to new image not possible\n"); + } + } + if (fHasSectors && fPhysical != kPhysicalFormatSectors) + fHasNibbles = true; + assert(fHasBlocks || fHasSectors || fHasNibbles); + + fFileSysOrder = CalcFSSectorOrder(); + fReadOnly = false; + fDirty = true; + + /* + * Step 2: check for invalid arguments and bad combinations. + */ + dierr = ValidateCreateFormat(); + if (dierr != kDIErrNone) { + WMSG0("ERROR: CIC arg validation failed, bailing\n"); + goto bail; + } + + /* + * Step 3: create the destination file. Put this into fpWrapperGFD + * or fpOuterGFD. + * + * The file must not already exist. + * + * THOUGHT: should allow creation of an in-memory disk image. This won't + * work for NuFX, but will work for pretty much everything else. + */ + WMSG1(" CIC: creating '%s'\n", pathName); + int fd; + fd = open(pathName, O_CREAT | O_EXCL, 0644); + if (fd < 0) { + dierr = (DIError) errno; + WMSG2("ERROR: unable to create file '%s' (errno=%d)\n", + pathName, dierr); + goto bail; + } + close(fd); + + GFDFile* pGFDFile; + pGFDFile = new GFDFile; + + dierr = pGFDFile->Open(pathName, false); + if (dierr != kDIErrNone) { + delete pGFDFile; + goto bail; + } + + if (fOuterFormat == kOuterFormatNone) + fpWrapperGFD = pGFDFile; + else + fpOuterGFD = pGFDFile; + pGFDFile = nil; + + /* + * Step 4: if we have an outer GFD and therefore don't currently have + * an fpWrapperGFD, create an expandable memory buffer to use. + * + * We want to take a guess at how big the image will be, so compute + * fLength now. + * + * Create an OuterWrapper as needed. + */ + if (IsSectorFormat(fPhysical)) { + if (fHasBlocks) + fLength = (di_off_t) GetNumBlocks() * kBlockSize; + else + fLength = (di_off_t) GetNumTracks() * GetNumSectPerTrack() * kSectorSize; + } else { + assert(IsNibbleFormat(fPhysical)); + fLength = GetNumTracks() * GetNibbleTrackAllocLength(); + } + assert(fLength > 0); + + if (fpWrapperGFD == nil) { + /* shift GFDs and create a new memory GFD, pre-sized */ + GFDBuffer* pGFDBuffer = new GFDBuffer; + + /* use fLength as a starting point for buffer size; this may expand */ + dierr = pGFDBuffer->Open(nil, fLength, true, true, false); + if (dierr != kDIErrNone) { + delete pGFDBuffer; + goto bail; + } + + fpWrapperGFD = pGFDBuffer; + pGFDBuffer = nil; + } + + /* create an fpOuterWrapper struct */ + switch (fOuterFormat) { + case kOuterFormatNone: + break; + case kOuterFormatGzip: + fpOuterWrapper = new OuterGzip; + if (fpOuterWrapper == nil) { + dierr = kDIErrMalloc; + goto bail; + } + break; + case kOuterFormatZip: + fpOuterWrapper = new OuterZip; + if (fpOuterWrapper == nil) { + dierr = kDIErrMalloc; + goto bail; + } + break; + default: + assert(false); + dierr = kDIErrInternal; + goto bail; + } + + /* + * Step 5: tell the ImageWrapper to write itself into the GFD, passing + * in the blank memory buffer. + * + * - Unadorned formats copy from memory buffer to fpWrapperGFD on disk. + * (With gz, fpWrapperGFD is actually a memory buffer.) fpDataGFD + * becomes an offset into the file. + * - 2MG writes header into GFD and follows it with all data; DC42 + * and Sim2e do similar things. + * - NuFX reopens pathName as SHK file (fpWrapperGFD must point to a + * file) and accesses the archive through an fpArchive. fpDataGFD + * is created as a memory buffer and the blank image is copied in. + * - DDD leaves fpWrapperGFD alone and copies the blank image into a + * new buffer for fpDataGFD. + * + * Sets fWrappedLength when possible, determined from fPhysical and + * either fNumBlocks or fNumTracks. Creates fpDataGFD, often as a + * GFDGFD offset into fpWrapperGFD. + */ + switch (fFileFormat) { + case kFileFormat2MG: + fpImageWrapper = new Wrapper2MG(); + break; + case kFileFormatDiskCopy42: + fpImageWrapper = new WrapperDiskCopy42(); + fpImageWrapper->SetStorageName(storageName); + break; + case kFileFormatSim2eHDV: + fpImageWrapper = new WrapperSim2eHDV(); + break; + case kFileFormatTrackStar: + fpImageWrapper = new WrapperTrackStar(); + fpImageWrapper->SetStorageName(storageName); + break; + case kFileFormatFDI: + fpImageWrapper = new WrapperFDI(); + break; + case kFileFormatNuFX: + fpImageWrapper = new WrapperNuFX(); + fpImageWrapper->SetStorageName(storageName); + ((WrapperNuFX*)fpImageWrapper)->SetCompressType( + (NuThreadFormat) fNuFXCompressType); + break; + case kFileFormatDDD: + fpImageWrapper = new WrapperDDD(); + break; + case kFileFormatUnadorned: + if (IsSectorFormat(fPhysical)) + fpImageWrapper = new WrapperUnadornedSector(); + else if (IsNibbleFormat(fPhysical)) + fpImageWrapper = new WrapperUnadornedNibble(); + else { + assert(false); + } + break; + default: + assert(fpImageWrapper == nil); + break; + } + + if (fpImageWrapper == nil) { + WMSG0(" DI couldn't figure out the file format\n"); + dierr = kDIErrUnrecognizedFileFmt; + goto bail; + } + + /* create the wrapper, write the header, and create fpDataGFD */ + assert(fpDataGFD == nil); + dierr = fpImageWrapper->Create(fLength, fPhysical, fOrder, + fDOSVolumeNum, fpWrapperGFD, &fWrappedLength, &fpDataGFD); + if (dierr != kDIErrNone) { + WMSG1("ImageWrapper Create failed, err=%d\n", dierr); + goto bail; + } + assert(fpDataGFD != nil); + + /* + * Step 6: "format" fpDataGFD. + * + * Note we don't specify an ordering to the "create blank" functions. + * Either it's sectors, in which case it's all zeroes, or it's nibbles, + * in which case it's always in physical order. + * + * If we're formatting for nibbles, and the application hasn't specified + * a disk volume number, use the default (254). + */ + if (fPhysical == kPhysicalFormatSectors) + dierr = FormatSectors(fpDataGFD, skipFormat); // zero out the image + else { + assert(!skipFormat); // don't skip low-level nibble formatting! + if (fDOSVolumeNum == kVolumeNumNotSet) { + fDOSVolumeNum = kDefaultNibbleVolumeNum; + WMSG0(" Using default nibble volume num\n"); + } + + dierr = FormatNibbles(fpDataGFD); // write basic nibble stuff + } + + + /* + * We're done! + * + * Quick sanity check... + */ + if (fOuterFormat != kOuterFormatNone) { + assert(fpOuterGFD != nil); + assert(fpWrapperGFD != nil); + assert(fpDataGFD != nil); + } + +bail: + return dierr; +} + +/* + * Check that the requested format is one we can create. + * + * We don't allow .SDK.GZ or 6384-byte nibble 2MG. 2MG sector images + * must be in DOS or ProDOS order. + * + * Only "generic" FS formats may be used. The application may choose + * to call AnalyzeImage later on to set the actual FS once data has + * been written. + */ +DIError +DiskImg::ValidateCreateFormat(void) const +{ + /* + * Check for invalid arguments. + */ + if (fHasBlocks && fNumBlocks >= 4194304) { // 2GB or larger? + if (fFileFormat != kFileFormatUnadorned) { + WMSG0("CreateImage: images >= 2GB can only be unadorned\n"); + return kDIErrInvalidCreateReq; + } + } + if (fOuterFormat == kOuterFormatUnknown || + fFileFormat == kFileFormatUnknown || + fPhysical == kPhysicalFormatUnknown || + fOrder == kSectorOrderUnknown || + fFormat == kFormatUnknown) + { + WMSG0("CreateImage: ambiguous format\n"); + return kDIErrInvalidCreateReq; + } + if (fOuterFormat != kOuterFormatNone && + fOuterFormat != kOuterFormatGzip && + fOuterFormat != kOuterFormatZip) + { + WMSG1("CreateImage: unsupported outer format %d\n", fOuterFormat); + return kDIErrInvalidCreateReq; + } + if (fFileFormat != kFileFormatUnadorned && + fFileFormat != kFileFormat2MG && + fFileFormat != kFileFormatDiskCopy42 && + fFileFormat != kFileFormatSim2eHDV && + fFileFormat != kFileFormatTrackStar && + fFileFormat != kFileFormatFDI && + fFileFormat != kFileFormatNuFX && + fFileFormat != kFileFormatDDD) + { + WMSG1("CreateImage: unsupported file format %d\n", fFileFormat); + return kDIErrInvalidCreateReq; + } + if (fFormat != kFormatGenericPhysicalOrd && + fFormat != kFormatGenericProDOSOrd && + fFormat != kFormatGenericDOSOrd && + fFormat != kFormatGenericCPMOrd) + { + WMSG0("CreateImage: may only use 'generic' formats\n"); + return kDIErrInvalidCreateReq; + } + + /* + * Check for invalid combinations. + */ + if (fPhysical != kPhysicalFormatSectors) { + if (fOrder != kSectorOrderPhysical) { + WMSG0("CreateImage: nibble images are always 'physical' order\n"); + return kDIErrInvalidCreateReq; + } + + if (GetHasSectors() == false && GetHasNibbles() == false) { + WMSG2("CreateImage: must set hasSectors(%d) or hasNibbles(%d)\n", + GetHasSectors(), GetHasNibbles()); + return kDIErrInvalidCreateReq; + } + + if (fpNibbleDescr == nil && GetNumSectPerTrack() > 0) { + WMSG0("CreateImage: must provide NibbleDescr for non-sector\n"); + return kDIErrInvalidCreateReq; + } + + if (fpNibbleDescr != nil && + fpNibbleDescr->numSectors != GetNumSectPerTrack()) + { + WMSG2("CreateImage: ?? nd->numSectors=%d, GetNumSectPerTrack=%d\n", + fpNibbleDescr->numSectors, GetNumSectPerTrack()); + return kDIErrInvalidCreateReq; + } + + if (fpNibbleDescr != nil && ( + (fpNibbleDescr->numSectors == 13 && + fpNibbleDescr->encoding != kNibbleEnc53) || + (fpNibbleDescr->numSectors == 16 && + fpNibbleDescr->encoding != kNibbleEnc62)) + ) + { + WMSG0("CreateImage: sector count/encoding mismatch\n"); + return kDIErrInvalidCreateReq; + } + + if (GetNumTracks() != kTrackCount525 && + !(GetNumTracks() == 40 && fFileFormat == kFileFormatTrackStar)) + { + WMSG1("CreateImage: unexpected track count %ld\n", GetNumTracks()); + return kDIErrInvalidCreateReq; + } + } + if (fFileFormat == kFileFormat2MG) { + if (fPhysical != kPhysicalFormatSectors && + fPhysical != kPhysicalFormatNib525_6656) + { + WMSG1("CreateImage: 2MG can't handle physical %d\n", fPhysical); + return kDIErrInvalidCreateReq; + } + + if (fPhysical == kPhysicalFormatSectors && + (fOrder != kSectorOrderProDOS && + fOrder != kSectorOrderDOS)) + { + WMSG0("CreateImage: 2MG requires DOS or ProDOS ordering\n"); + return kDIErrInvalidCreateReq; + } + } + if (fFileFormat == kFileFormatNuFX) { + if (fOuterFormat != kOuterFormatNone) { + WMSG0("CreateImage: can't mix NuFX and outer wrapper\n"); + return kDIErrInvalidCreateReq; + } + if (fPhysical != kPhysicalFormatSectors) { + WMSG0("CreateImage: NuFX physical must be sectors\n"); + return kDIErrInvalidCreateReq; + } + if (fOrder != kSectorOrderProDOS) { + WMSG0("CreateImage: NuFX is always ProDOS-order\n"); + return kDIErrInvalidCreateReq; + } + } + if (fFileFormat == kFileFormatDiskCopy42) { + if (fPhysical != kPhysicalFormatSectors) { + WMSG0("CreateImage: DC42 physical must be sectors\n"); + return kDIErrInvalidCreateReq; + } + if ((GetHasBlocks() && GetNumBlocks() != 1600) || + GetHasSectors() && + (GetNumTracks() != 200 || GetNumSectPerTrack() != 16)) + { + WMSG0("CreateImage: DC42 only for 800K disks\n"); + return kDIErrInvalidCreateReq; + } + if (fOrder != kSectorOrderProDOS && + fOrder != kSectorOrderDOS) // used for UNIDOS disks?? + { + WMSG0("CreateImage: DC42 is always ProDOS or DOS\n"); + return kDIErrInvalidCreateReq; + } + } + if (fFileFormat == kFileFormatSim2eHDV) { + if (fPhysical != kPhysicalFormatSectors) { + WMSG0("CreateImage: Sim2eHDV physical must be sectors\n"); + return kDIErrInvalidCreateReq; + } + if (fOrder != kSectorOrderProDOS) { + WMSG0("CreateImage: Sim2eHDV is always ProDOS-order\n"); + return kDIErrInvalidCreateReq; + } + } + if (fFileFormat == kFileFormatTrackStar) { + if (fPhysical != kPhysicalFormatNib525_Var) { + WMSG0("CreateImage: TrackStar physical must be var-nibbles\n"); + return kDIErrInvalidCreateReq; + } + } + if (fFileFormat == kFileFormatFDI) { + if (fPhysical != kPhysicalFormatNib525_Var) { + WMSG0("CreateImage: FDI physical must be var-nibbles\n"); + return kDIErrInvalidCreateReq; + } + } + if (fFileFormat == kFileFormatDDD) { + if (fPhysical != kPhysicalFormatSectors) { + WMSG0("CreateImage: DDD physical must be sectors\n"); + return kDIErrInvalidCreateReq; + } + if (fOrder != kSectorOrderDOS) { + WMSG0("CreateImage: DDD is always DOS-order\n"); + return kDIErrInvalidCreateReq; + } + if (!GetHasSectors() || GetNumTracks() != 35 || + GetNumSectPerTrack() != 16) + { + WMSG0("CreateImage: DDD is only for 16-sector 35-track disks\n"); + return kDIErrInvalidCreateReq; + } + } + + return kDIErrNone; +} + +/* + * Create a blank image for physical=="sectors". + * + * fLength must be a multiple of 256. + * + * If "quickFormat" is set, only the very last sector is written (to set + * the EOF on the file). + */ +DIError +DiskImg::FormatSectors(GenericFD* pGFD, bool quickFormat) const +{ + DIError dierr = kDIErrNone; + char sctBuf[kSectorSize]; + di_off_t length; + + assert(fLength > 0 && (fLength & 0xff) == 0); + + //if (!(fLength & 0x01)) + // return FormatBlocks(pGFD); + + memset(sctBuf, 0, sizeof(sctBuf)); + pGFD->Rewind(); + + if (quickFormat) { + dierr = pGFD->Seek(fLength - sizeof(sctBuf), kSeekSet); + if (dierr != kDIErrNone) { + WMSG2(" FormatSectors: GFD seek %ld failed (err=%d)\n", + (long) fLength - sizeof(sctBuf), dierr); + goto bail; + } + dierr = pGFD->Write(sctBuf, sizeof(sctBuf), nil); + if (dierr != kDIErrNone) { + WMSG1(" FormatSectors: GFD quick write failed (err=%d)\n", dierr); + goto bail; + } + } else { + for (length = fLength ; length > 0; length -= sizeof(sctBuf)) { + dierr = pGFD->Write(sctBuf, sizeof(sctBuf), nil); + if (dierr != kDIErrNone) { + WMSG1(" FormatSectors: GFD write failed (err=%d)\n", dierr); + goto bail; + } + } + assert(length == 0); + } + + +bail: + return dierr; +} + +#if 0 // didn't help +/* + * Create a blank image for physical=="sectors". This is called from + * FormatSectors when it looks like we're formatting entire blocks. + */ +DIError +DiskImg::FormatBlocks(GenericFD* pGFD) const +{ + DIError dierr; + char blkBuf[kBlockSize]; + long length; + time_t start, end; + + assert(fLength > 0 && (fLength & 0x1ff) == 0); + + start = time(nil); + + memset(blkBuf, 0, sizeof(blkBuf)); + pGFD->Rewind(); + + for (length = fLength ; length > 0; length -= sizeof(blkBuf)) { + dierr = pGFD->Write(blkBuf, sizeof(blkBuf), nil); + if (dierr != kDIErrNone) { + WMSG1(" FormatBlocks: GFD write failed (err=%d)\n", dierr); + return dierr; + } + } + assert(length == 0); + + end = time(nil); + WMSG1("FormatBlocks complete, time=%ld\n", end - start); + + return kDIErrNone; +} +#endif + + +/* + * =========================================================================== + * Utility functions + * =========================================================================== + */ + +/* + * Add a note to this disk image. + * + * This is how we communicate cautions and warnings to the user. Use + * linefeeds ('\n') to indicate line breaks. + * + * The maximum length of a single note is set by the size of "buf". + */ +void +DiskImg::AddNote(NoteType type, const char* fmt, ...) +{ + char buf[512]; + char* cp = buf; + int maxLen = sizeof(buf); + va_list args; + int len; + + /* + * Prepend a string that highlights the note. + */ + switch (type) { + case kNoteWarning: + strcpy(cp, "- WARNING: "); + break; + default: + strcpy(cp, "- "); + break; + } + len = strlen(cp); + cp += len; + maxLen -= len; + + /* + * Add the note. + */ + va_start(args, fmt); +#if defined(HAVE_VSNPRINTF) + (void) vsnprintf(cp, maxLen, fmt, args); +#elif defined(HAVE__VSNPRINTF) + (void) _vsnprintf(cp, maxLen, fmt, args); +#else +# error "hosed" +#endif + va_end(args); + + buf[sizeof(buf)-2] = '\0'; // leave room for additional '\n' + len = strlen(buf); + if (len > 0 && buf[len-1] != '\n') { + buf[len] = '\n'; + buf[len+1] = '\0'; + len++; + } + + WMSG1("+++ adding note '%s'\n", buf); + + if (fNotes == nil) { + fNotes = new char[len +1]; + if (fNotes == nil) { + WMSG1("Unable to create notes[%d]\n", len+1); + assert(false); + return; + } + strcpy(fNotes, buf); + } else { + int existingLen = strlen(fNotes); + char* newNotes = new char[existingLen + len +1]; + if (newNotes == nil) { + WMSG1("Unable to create newNotes[%d]\n", existingLen+len+1); + assert(false); + return; + } + strcpy(newNotes, fNotes); + strcpy(newNotes + existingLen, buf); + delete[] fNotes; + fNotes = newNotes; + } +} + +/* + * Return a string with the notes in it. + */ +const char* +DiskImg::GetNotes(void) const +{ + if (fNotes == nil) + return ""; + else + return fNotes; +} + + +/* + * Get length and offset of tracks in a nibble image. This is necessary + * because of formats with variable-length tracks (e.g. TrackStar). + */ +int +DiskImg::GetNibbleTrackLength(long track) const +{ + assert(fpImageWrapper != NULL); + return fpImageWrapper->GetNibbleTrackLength(fPhysical, track); +} +int +DiskImg::GetNibbleTrackOffset(long track) const +{ + assert(fpImageWrapper != NULL); + return fpImageWrapper->GetNibbleTrackOffset(fPhysical, track); +} + + +/* + * Return a new object with the appropriate DiskFS sub-class. + * + * If the image hasn't been analyzed, or was analyzed to no avail, "nil" + * is returned unless "allowUnknown" is set to "true". In that case, a + * DiskFSUnknown is returned. + * + * This doesn't inspire the DiskFS to do any processing, just creates the + * new object. + */ +DiskFS* +DiskImg::OpenAppropriateDiskFS(bool allowUnknown) +{ + DiskFS* pDiskFS = nil; + + /* + * Create an appropriate DiskFS object. + */ + switch (GetFSFormat()) { + case DiskImg::kFormatDOS33: + case DiskImg::kFormatDOS32: + pDiskFS = new DiskFSDOS33(); + break; + case DiskImg::kFormatProDOS: + pDiskFS = new DiskFSProDOS(); + break; + case DiskImg::kFormatPascal: + pDiskFS = new DiskFSPascal(); + break; + case DiskImg::kFormatMacHFS: + pDiskFS = new DiskFSHFS(); + break; + case DiskImg::kFormatUNIDOS: + pDiskFS = new DiskFSUNIDOS(); + break; + case DiskImg::kFormatOzDOS: + pDiskFS = new DiskFSOzDOS(); + break; + case DiskImg::kFormatCFFA4: + case DiskImg::kFormatCFFA8: + pDiskFS = new DiskFSCFFA(); + break; + case DiskImg::kFormatMacPart: + pDiskFS = new DiskFSMacPart(); + break; + case DiskImg::kFormatMicroDrive: + pDiskFS = new DiskFSMicroDrive(); + break; + case DiskImg::kFormatFocusDrive: + pDiskFS = new DiskFSFocusDrive(); + break; + case DiskImg::kFormatCPM: + pDiskFS = new DiskFSCPM(); + break; + case DiskImg::kFormatMSDOS: + pDiskFS = new DiskFSFAT(); + break; + case DiskImg::kFormatRDOS33: + case DiskImg::kFormatRDOS32: + case DiskImg::kFormatRDOS3: + pDiskFS = new DiskFSRDOS(); + break; + case DiskImg::kFormatGutenberg: + pDiskFS = new DiskFSGutenberg(); + break; + + default: + WMSG1("WARNING: unhandled DiskFS case %d\n", GetFSFormat()); + assert(false); + /* fall through */ + case DiskImg::kFormatGenericPhysicalOrd: + case DiskImg::kFormatGenericProDOSOrd: + case DiskImg::kFormatGenericDOSOrd: + case DiskImg::kFormatGenericCPMOrd: + case DiskImg::kFormatUnknown: + if (allowUnknown) { + pDiskFS = new DiskFSUnknown(); + break; + } + } + + return pDiskFS; +} + + +/* + * Fill an array with SectorOrder values. The ordering specified by "first" + * will come first. Unused entries will be set to "unknown" and should be + * ignored. + * + * "orderArray" must have kSectorOrderMax elements. + */ +/*static*/ void +DiskImg::GetSectorOrderArray(SectorOrder* orderArray, SectorOrder first) +{ + // init array + for (int i = 0; i < kSectorOrderMax; i++) + orderArray[i] = (SectorOrder) i; + + // pull the best-guess ordering to the front + assert(orderArray[0] == kSectorOrderUnknown); + + orderArray[0] = first; + orderArray[(int) first] = kSectorOrderUnknown; + + // don't bother checking CP/M sector order + orderArray[kSectorOrderCPM] = kSectorOrderUnknown; +} + + +/* + * Return a short string describing "format". + * + * These are semi-duplicated in ImageFormatDialog.cpp in CiderPress. + */ +/*static*/ const char* +DiskImg::ToStringCommon(int format, const ToStringLookup* pTable, + int tableSize) +{ + for (int i = 0; i < tableSize; i++) { + if (pTable[i].format == format) + return pTable[i].str; + } + + assert(false); + return "(unknown)"; +} + +/*static*/ const char* +DiskImg::ToString(OuterFormat format) +{ + static const ToStringLookup kOuterFormats[] = { + { DiskImg::kOuterFormatUnknown, "Unknown format" }, + { DiskImg::kOuterFormatNone, "(none)" }, + { DiskImg::kOuterFormatCompress, "UNIX compress" }, + { DiskImg::kOuterFormatGzip, "gzip" }, + { DiskImg::kOuterFormatBzip2, "bzip2" }, + { DiskImg::kOuterFormatZip, "Zip archive" }, + }; + + return ToStringCommon(format, kOuterFormats, NELEM(kOuterFormats)); +} +/*static*/ const char* +DiskImg::ToString(FileFormat format) +{ + static const ToStringLookup kFileFormats[] = { + { DiskImg::kFileFormatUnknown, "Unknown format" }, + { DiskImg::kFileFormatUnadorned, "Unadorned raw data" }, + { DiskImg::kFileFormat2MG, "2MG" }, + { DiskImg::kFileFormatNuFX, "NuFX (ShrinkIt)" }, + { DiskImg::kFileFormatDiskCopy42, "DiskCopy 4.2" }, + { DiskImg::kFileFormatDiskCopy60, "DiskCopy 6.0" }, + { DiskImg::kFileFormatDavex, "Davex volume image" }, + { DiskImg::kFileFormatSim2eHDV, "Sim //e HDV" }, + { DiskImg::kFileFormatTrackStar, "TrackStar image" }, + { DiskImg::kFileFormatFDI, "FDI image" }, + { DiskImg::kFileFormatDDD, "DDD" }, + { DiskImg::kFileFormatDDDDeluxe, "DDDDeluxe" }, + }; + + return ToStringCommon(format, kFileFormats, NELEM(kFileFormats)); +}; +/*static*/ const char* +DiskImg::ToString(PhysicalFormat format) +{ + static const ToStringLookup kPhysicalFormats[] = { + { DiskImg::kPhysicalFormatUnknown, "Unknown format" }, + { DiskImg::kPhysicalFormatSectors, "Sectors" }, + { DiskImg::kPhysicalFormatNib525_6656, "Raw nibbles (6656-byte)" }, + { DiskImg::kPhysicalFormatNib525_6384, "Raw nibbles (6384-byte)" }, + { DiskImg::kPhysicalFormatNib525_Var, "Raw nibbles (variable len)" }, + }; + + return ToStringCommon(format, kPhysicalFormats, NELEM(kPhysicalFormats)); +}; +/*static*/ const char* +DiskImg::ToString(SectorOrder format) +{ + static const ToStringLookup kSectorOrders[] = { + { DiskImg::kSectorOrderUnknown, "Unknown ordering" }, + { DiskImg::kSectorOrderProDOS, "ProDOS block ordering" }, + { DiskImg::kSectorOrderDOS, "DOS sector ordering" }, + { DiskImg::kSectorOrderCPM, "CP/M block ordering" }, + { DiskImg::kSectorOrderPhysical, "Physical sector ordering" }, + }; + + return ToStringCommon(format, kSectorOrders, NELEM(kSectorOrders)); +}; +/*static*/ const char* +DiskImg::ToString(FSFormat format) +{ + static const ToStringLookup kFSFormats[] = { + { DiskImg::kFormatUnknown, "Unknown" }, + { DiskImg::kFormatProDOS, "ProDOS" }, + { DiskImg::kFormatDOS33, "DOS 3.3" }, + { DiskImg::kFormatDOS32, "DOS 3.2" }, + { DiskImg::kFormatPascal, "Pascal" }, + { DiskImg::kFormatMacHFS, "HFS" }, + { DiskImg::kFormatMacMFS, "MFS" }, + { DiskImg::kFormatLisa, "Lisa" }, + { DiskImg::kFormatCPM, "CP/M" }, + { DiskImg::kFormatMSDOS, "MS-DOS FAT" }, + { DiskImg::kFormatISO9660, "ISO-9660" }, + { DiskImg::kFormatRDOS33, "RDOS 3.3 (16-sector)" }, + { DiskImg::kFormatRDOS32, "RDOS 3.2 (13-sector)" }, + { DiskImg::kFormatRDOS3, "RDOS 3 (cracked 13-sector)" }, + { DiskImg::kFormatGenericDOSOrd, "Generic DOS sectors" }, + { DiskImg::kFormatGenericProDOSOrd, "Generic ProDOS blocks" }, + { DiskImg::kFormatGenericPhysicalOrd, "Generic raw sectors" }, + { DiskImg::kFormatGenericCPMOrd, "Generic CP/M blocks" }, + { DiskImg::kFormatUNIDOS, "UNIDOS (400K DOS x2)" }, + { DiskImg::kFormatOzDOS, "OzDOS (400K DOS x2)" }, + { DiskImg::kFormatCFFA4, "CFFA (4 or 6 partitions)" }, + { DiskImg::kFormatCFFA8, "CFFA (8 partitions)" }, + { DiskImg::kFormatMacPart, "Macintosh partitioned disk" }, + { DiskImg::kFormatMicroDrive, "MicroDrive partitioned disk" }, + { DiskImg::kFormatFocusDrive, "FocusDrive partitioned disk" }, + }; + + return ToStringCommon(format, kFSFormats, NELEM(kFSFormats)); +}; + + +/* + * strerror() equivalent for DiskImg errors. + */ +const char* +DiskImgLib::DIStrError(DIError dierr) +{ + if (dierr > 0) { + const char* msg; + msg = strerror(dierr); + if (msg != nil) + return msg; + } + + /* + * BUG: this should be set up as per-thread storage in an MT environment. + * I would be more inclined to worry about this if I was expecting + * to hit "default:". So long as valid values are passed in, and the + * switch statement is kept up to date, we should never have cause + * to return this. + * + * An easier solution, should this present a problem for someone, would + * be to have the function return nil or "unknown error" when the + * error value isn't recognized. I'd recommend leaving it as-is for + * debug builds, though, as it's helpful to know *which* error is not + * recognized. + */ + static char defaultMsg[32]; + + switch (dierr) { + case kDIErrNone: + return "(no error)"; + + case kDIErrAccessDenied: + return "access denied"; + case kDIErrVWAccessForbidden: + return "for safety, write access to this volume is forbidden"; + case kDIErrSharingViolation: + return "file is already open and cannot be shared"; + case kDIErrNoExclusiveAccess: + return "couldn't get exclusive access"; + case kDIErrWriteProtected: + return "write protected"; + case kDIErrCDROMNotSupported: + return "access to CD-ROM drives is not supported"; + case kDIErrASPIFailure: + return "an ASPI request failed"; + case kDIErrSPTIFailure: + return "an SPTI request failed"; + case kDIErrSCSIFailure: + return "a SCSI request failed"; + case kDIErrDeviceNotReady: + return "device not ready"; + + case kDIErrFileNotFound: + return "file not found"; + case kDIErrForkNotFound: + return "fork not found"; + case kDIErrAlreadyOpen: + return "an image is already open"; + case kDIErrFileOpen: + return "file is open"; + case kDIErrNotReady: + return "object not ready"; + case kDIErrFileExists: + return "file already exists"; + case kDIErrDirectoryExists: + return "directory already exists"; + + case kDIErrEOF: + return "end of file reached"; + case kDIErrReadFailed: + return "read failed"; + case kDIErrWriteFailed: + return "write failed"; + case kDIErrDataUnderrun: + return "tried to read past end of file"; + case kDIErrDataOverrun: + return "tried to write past end of file"; + case kDIErrGenericIO: + return "I/O error"; + + case kDIErrOddLength: + return "image size is wrong"; + case kDIErrUnrecognizedFileFmt: + return "not a recognized disk image format"; + case kDIErrBadFileFormat: + return "image file contents aren't in expected format"; + case kDIErrUnsupportedFileFmt: + return "file format not supported"; + case kDIErrUnsupportedPhysicalFmt: + return "physical format not supported"; + case kDIErrUnsupportedFSFmt: + return "filesystem type not supported"; + case kDIErrBadOrdering: + return "bad sector ordering"; + case kDIErrFilesystemNotFound: + return "specified filesystem not found"; + case kDIErrUnsupportedAccess: + return "the method of access used isn't supported for this image"; + case kDIErrUnsupportedImageFeature: + return "image file uses features that CiderPress doesn't support"; + + case kDIErrInvalidTrack: + return "invalid track number"; + case kDIErrInvalidSector: + return "invalid sector number"; + case kDIErrInvalidBlock: + return "invalid block number"; + case kDIErrInvalidIndex: + return "invalid index number"; + + case kDIErrDirectoryLoop: + return "disk directory structure has an infinite loop"; + case kDIErrFileLoop: + return "file structure has an infinite loop"; + case kDIErrBadDiskImage: + return "the filesystem on this image appears damaged"; + case kDIErrBadFile: + return "file structure appears damaged"; + case kDIErrBadDirectory: + return "a directory appears damaged"; + case kDIErrBadPartition: + return "bad partition"; + + case kDIErrFileArchive: + return "this looks like a file archive, not a disk archive"; + case kDIErrUnsupportedCompression: + return "compression method not supported"; + case kDIErrBadChecksum: + return "checksum doesn't match, data may be corrupted"; + case kDIErrBadCompressedData: + return "the compressed data is corrupted"; + case kDIErrBadArchiveStruct: + return "archive may be damaged"; + + case kDIErrBadNibbleSectors: + return "couldn't read sectors from this image"; + case kDIErrSectorUnreadable: + return "sector not readable"; + case kDIErrInvalidDiskByte: + return "found invalid nibble image disk byte"; + case kDIErrBadRawData: + return "couldn't convert raw data to nibble data"; + + case kDIErrInvalidFileName: + return "invalid file name"; + case kDIErrDiskFull: + return "disk full"; + case kDIErrVolumeDirFull: + return "volume directory is full"; + case kDIErrInvalidCreateReq: + return "invalid disk image create request"; + case kDIErrTooBig: + return "size is larger than we can handle"; + + case kDIErrGeneric: + return "DiskImg generic error"; + case kDIErrInternal: + return "DiskImg internal error"; + case kDIErrMalloc: + return "memory allocation failure"; + case kDIErrInvalidArg: + return "invalid argument"; + case kDIErrNotSupported: + return "feature not supported"; + case kDIErrCancelled: + return "cancelled by user"; + + case kDIErrNufxLibInitFailed: + return "NufxLib initialization failed"; + + default: + sprintf(defaultMsg, "(error=%d)", dierr); + return defaultMsg; + } +} + +/* + * High ASCII conversion table, from Technical Note PT515, + * "Apple File Exchange Q&As". The table is available in a hopelessly + * blurry PDF or a pair of GIFs created with small fonts, but I think I + * have mostly captured it. + */ +/*static*/ const unsigned char DiskImg::kMacHighASCII[128+1] = + "AACENOUaaaaaaceeeeiiiinooooouuuu" // 0x80 - 0x9f + "tocL$oPBrct'.=AO%+<>YudsPpSaoOao" // 0xa0 - 0xbf + "?!-vf=d<>. AAOOo--\"\"''/oyY/o<> f" // 0xc0 - 0xdf + "|*,,%AEAEEIIIIOOaOUUUi^~-,**,\"? "; // 0xe0 - 0xff + + +/* + * Hack for Win32 systems. See Win32BlockIO.cpp for commentary. + */ +bool DiskImgLib::gAllowWritePhys0 = false; +/*static*/ void DiskImg::SetAllowWritePhys0(bool val) { + DiskImgLib::gAllowWritePhys0 = val; +} diff --git a/diskimg/DiskImg.h b/diskimg/DiskImg.h index 9b900d1..ff1450d 100644 --- a/diskimg/DiskImg.h +++ b/diskimg/DiskImg.h @@ -1,1662 +1,1662 @@ -/* - * CiderPress - * Copyright (C) 2009 by CiderPress authors. All Rights Reserved. - * Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved. - * See the file LICENSE for distribution terms. - */ -/* - * Public declarations for the DiskImg library. - * - * Everything is wrapped in the "DiskImgLib" namespace. Either prefix - * all references with "DiskImgLib::", or add "using namespace DiskImgLib" - * to all C++ source files that make use of it. - * - * Under Linux, this should be compiled with -D_FILE_OFFSET_BITS=64. - * - * These classes are not thread-safe with respect to access to a single - * disk image. Writing to the same disk image from multiple threads - * simultaneously is bound to end in disaster. Simultaneous access to - * different objects will work, though modifying the same disk image - * file from multiple objects will lead to unpredictable results. - */ -#ifndef __DISK_IMG__ -#define __DISK_IMG__ - -#include -#include -#include - -//#define EXCISE_GPL_CODE - -/* Windows DLL stuff */ -#ifdef _WIN32 -# ifdef DISKIMG_EXPORTS -# define DISKIMG_API __declspec(dllexport) -# else -# define DISKIMG_API __declspec(dllimport) -# endif -#else -# define DISKIMG_API -#endif - -namespace DiskImgLib { - -/* compiled-against versions; call DiskImg::GetVersion for linked-against */ -#define kDiskImgVersionMajor 4 -#define kDiskImgVersionMinor 6 -#define kDiskImgVersionBug 0 - - -/* - * Errors from the various disk image classes. - */ -typedef enum DIError { - kDIErrNone = 0, - - /* I/O request errors (should renumber/rename to match GS/OS errors?) */ - kDIErrAccessDenied = -10, - kDIErrVWAccessForbidden = -11, // write access to volume forbidden - kDIErrSharingViolation = -12, // file is in use and not shareable - kDIErrNoExclusiveAccess = -13, // couldn't get exclusive access - kDIErrWriteProtected = -14, // disk is write protected - kDIErrCDROMNotSupported = -15, // access to CD-ROM drives not supptd - kDIErrASPIFailure = -16, // generic ASPI failure result - kDIErrSPTIFailure = -17, // generic SPTI failure result - kDIErrSCSIFailure = -18, // generic SCSI failure result - kDIErrDeviceNotReady = -19, // floppy or CD-ROM drive has no media - - kDIErrFileNotFound = -20, - kDIErrForkNotFound = -21, // requested fork does not exist - kDIErrAlreadyOpen = -22, // already open, can't open a 2nd time - kDIErrFileOpen = -23, // file is open, can't delete it - kDIErrNotReady = -24, - kDIErrFileExists = -25, // file already exists - kDIErrDirectoryExists = -26, // directory already exists - - kDIErrEOF = -30, // end-of-file reached - kDIErrReadFailed = -31, - kDIErrWriteFailed = -32, - kDIErrDataUnderrun = -33, // tried to read off end of the image - kDIErrDataOverrun = -34, // tried to write off end of the image - kDIErrGenericIO = -35, // generic I/O error - - kDIErrOddLength = -40, // image size not multiple of sectors - kDIErrUnrecognizedFileFmt = -41, // file format just not recognized - kDIErrBadFileFormat = -42, // filename ext doesn't match contents - kDIErrUnsupportedFileFmt = -43, // recognized but not supported - kDIErrUnsupportedPhysicalFmt = -44, // (same) - kDIErrUnsupportedFSFmt = -45, // (and again) - kDIErrBadOrdering = -46, // requested sector ordering no good - kDIErrFilesystemNotFound = -47, // requested filesystem isn't there - kDIErrUnsupportedAccess = -48, // e.g. read sectors from blocks-only - kDIErrUnsupportedImageFeature = -49, // e.g. FDI image w/Amiga sectors - - kDIErrInvalidTrack = -50, // request for invalid track number - kDIErrInvalidSector = -51, // request for invalid sector number - kDIErrInvalidBlock = -52, // request for invalid block number - kDIErrInvalidIndex = -53, // request with an invalid index - - kDIErrDirectoryLoop = -60, // directory chain points into itself - kDIErrFileLoop = -61, // file sector or block alloc loops - kDIErrBadDiskImage = -62, // the FS on the disk image is damaged - kDIErrBadFile = -63, // bad file on disk image - kDIErrBadDirectory = -64, // bad dir on disk image - kDIErrBadPartition = -65, // bad partition on multi-part format - - kDIErrFileArchive = -70, // file archive, not disk archive - kDIErrUnsupportedCompression = -71, // compression method is not supported - kDIErrBadChecksum = -72, // image file's checksum is bad - kDIErrBadCompressedData = -73, // data can't even be unpacked - kDIErrBadArchiveStruct = -74, // bad archive structure - - kDIErrBadNibbleSectors = -80, // can't read sectors from this image - kDIErrSectorUnreadable = -81, // requested sector not readable - kDIErrInvalidDiskByte = -82, // invalid byte for encoding type - kDIErrBadRawData = -83, // couldn't get correct nibbles - - kDIErrInvalidFileName = -90, // tried to create file with bad name - kDIErrDiskFull = -91, // no space left on disk - kDIErrVolumeDirFull = -92, // no more entries in volume dir - kDIErrInvalidCreateReq = -93, // CreateImage request was flawed - kDIErrTooBig = -94, // larger than we want to handle - - /* higher-level errors */ - kDIErrGeneric = -101, - kDIErrInternal = -102, - kDIErrMalloc = -103, - kDIErrInvalidArg = -104, - kDIErrNotSupported = -105, // feature not currently supported - kDIErrCancelled = -106, // an operation was cancelled by user - - kDIErrNufxLibInitFailed = -110, -} DIError; - -/* return a string describing the error */ -DISKIMG_API const char* DIStrError(DIError dierr); - - -/* exact definition of off_t varies, so just define our own */ -#ifdef _ULONGLONG_ - typedef LONGLONG di_off_t; -#else - typedef off_t di_off_t; -#endif - -/* common definition of "whence" for seeks */ -typedef enum DIWhence { - kSeekSet = SEEK_SET, - kSeekCur = SEEK_CUR, - kSeekEnd = SEEK_END -}; - -/* try to load ASPI under Win2K; if successful, SPTI should be disabled */ -const bool kAlwaysTryASPI = false; -/* ASPI device "filenames" look like "ASPI:x:y:z\" */ -DISKIMG_API extern const char* kASPIDev; - -/* some nibble-encoding constants */ -const int kTrackLenNib525 = 6656; -const int kTrackLenNb2525 = 6384; -const int kTrackLenTrackStar525 = 6525; // max len of data in TS image -const int kTrackAllocSize = 6656; // max 5.25 nibble track len; for buffers -const int kTrackCount525 = 35; // expected #of tracks on 5.25 img -const int kMaxNibbleTracks525 = 40; // max #of tracks on 5.25 nibble img -const int kDefaultNibbleVolumeNum = 254; -const int kBlockSize = 512; // block size for DiskImg interfaces -const int kSectorSize = 256; // sector size (1/2 block) -const int kD13Length = 256 * 13 * 35; // length of a .d13 image - -/* largest expanse we allow access to on a volume (8GB in 512-byte blocks) */ -const long kVolumeMaxBlocks = 8*1024*(1024*1024 / kBlockSize); - -/* largest .gz file we'll open (uncompressed size) */ -const long kGzipMax = 32*1024*1024; - -/* forward and external class definitions */ -class DiskFS; -class A2File; -class A2FileDescr; -class GenericFD; -class OuterWrapper; -class ImageWrapper; -class CircularBufferAccess; -class ASPI; -class LinearBitmap; - - -/* - * Library-global data functions. - * - * This class is just a namespace clumper. Do not instantiate. - */ -class DISKIMG_API Global { -public: - // one-time DLL initialization; use SetDebugMsgHandler first - static DIError AppInit(void); - // one-time DLL cleanup - static DIError AppCleanup(void); - - // return the DiskImg version number - static void GetVersion(long* pMajor, long* pMinor, long* pBug); - - static bool GetAppInitCalled(void) { return fAppInitCalled; } - static bool GetHasSPTI(void); - static bool GetHasASPI(void); - - // return a pointer to our global ASPI instance - static ASPI* GetASPI(void) { return fpASPI; } - // shortcut for fpASPI->GetVersion() - static unsigned long GetASPIVersion(void); - - // pointer to the debug message handler - typedef void (*DebugMsgHandler)(const char* file, int line, const char* msg); - static DebugMsgHandler gDebugMsgHandler; - - static DebugMsgHandler SetDebugMsgHandler(DebugMsgHandler handler); - static void PrintDebugMsg(const char* file, int line, const char* fmt, ...) - #if defined(__GNUC__) - __attribute__ ((format(printf, 3, 4))) - #endif - ; - -private: - // no instantiation allowed - Global(void) {} - ~Global(void) {} - - // make sure app calls AppInit - static bool fAppInitCalled; - - static ASPI* fpASPI; -}; - -extern bool gAllowWritePhys0; // ugh -- see Win32BlockIO.cpp - - -/* - * Disk I/O class, roughly equivalent to a GS/OS disk device driver. - * - * Abstracts away the file's source (file on disk, file in memory) and - * storage format (DOS order, ProDOS order, nibble). Will also cope - * with common disk compression and wrapper formats (Mac DiskCopy, 2MG, - * ShrinkIt, etc) if handed a file on disk. - * - * Images may be embedded within other images, e.g. UNIDOS and storage - * type $04 pascal volumes. - * - * THOUGHT: we need a list(?) of pointers from here back to the DiskFS - * so that any modifications here will "wake" the DiskFS and sub-volumes. - * We also need a "dirty" flag so things like CloseNufx can know not to - * re-do work when Closing after a Flush. Also DiskFS can alert us to - * any locally cached stuff, and we can tell them to flush everything. - * (Possibly useful when doing disk updates, so stuff can be trivially - * un-done. Currently CiderPress checks the filename manually after - * each write, but that's generally less reliable than having the knowledge - * contained in the DiskImg.) - * - * THOUGHT: need a ReadRawTrack that gets raw nibblized data. For a - * nibblized image it returns the data, for a sector image it generates - * the raw data. - * - * THOUGHT: we could reduce the risk of problems and increase performance - * for physical media with a "copy on write" scheme. We'd create a shadow - * array of modified blocks, and write them at Flush time. This would - * provide an instantaneous "revert" feature, and prevent formats like - * DiskCopy42 (which has a CRC in its header) from being inconsistent for - * long stretches. - */ -class DISKIMG_API DiskImg { -public: - // create DiskImg object - DiskImg(void); - virtual ~DiskImg(void); - - /* - * Types describing an image file. - * - * The file itself is described by an external parameter ("file source") - * that is either the name of the file, a memory buffer, or an EFD - * (EmbeddedFileDescriptor). - */ - typedef enum { // format of the "wrapper wrapper" - kOuterFormatUnknown = 0, - kOuterFormatNone = 1, // (plain) - kOuterFormatCompress = 2, // .xx.Z - kOuterFormatGzip = 3, // .xx.gz - kOuterFormatBzip2 = 4, // .xx.bz2 - kOuterFormatZip = 10, // .zip - } OuterFormat; - typedef enum { // format of the image "wrapper" - kFileFormatUnknown = 0, - kFileFormatUnadorned = 1, // .po, .do, ,nib, .raw, .d13 - kFileFormat2MG = 2, // .2mg, .2img, $e0/0130 - kFileFormatDiskCopy42 = 3, // .dsk/.disk, maybe .dc - kFileFormatDiskCopy60 = 4, // .dc6 (often just raw format) - kFileFormatDavex = 5, // $e0/8004 - kFileFormatSim2eHDV = 6, // .hdv - kFileFormatTrackStar = 7, // .app (40-track or 80-track) - kFileFormatFDI = 8, // .fdi (5.25" or 3.5") - kFileFormatNuFX = 20, // .shk, .sdk, .bxy - kFileFormatDDD = 21, // .ddd - kFileFormatDDDDeluxe = 22, // $DD, .ddd - } FileFormat; - typedef enum { // format of the image data stream - kPhysicalFormatUnknown = 0, - kPhysicalFormatSectors = 1, // sequential 256-byte sectors (13/16/32) - kPhysicalFormatNib525_6656 = 2, // 5.25" disk ".nib" (6656 bytes/track) - kPhysicalFormatNib525_6384 = 3, // 5.25" disk ".nb2" (6384 bytes/track) - kPhysicalFormatNib525_Var = 4, // 5.25" disk (variable len, e.g. ".app") - } PhysicalFormat; - typedef enum { // sector ordering for "sector" format images - kSectorOrderUnknown = 0, - kSectorOrderProDOS = 1, // written as series of ProDOS blocks - kSectorOrderDOS = 2, // written as series of DOS sectors - kSectorOrderCPM = 3, // written as series of 1K CP/M blocks - kSectorOrderPhysical = 4, // written as un-interleaved sectors - kSectorOrderMax, // (used for array sizing) - } SectorOrder; - typedef enum { // main filesystem format (based on NuFX enum) - kFormatUnknown = 0, - kFormatProDOS = 1, - kFormatDOS33 = 2, - kFormatDOS32 = 3, - kFormatPascal = 4, - kFormatMacHFS = 5, - kFormatMacMFS = 6, - kFormatLisa = 7, - kFormatCPM = 8, - //kFormatCharFST - kFormatMSDOS = 10, // any FAT filesystem - //kFormatHighSierra - kFormatISO9660 = 12, - //kFormatAppleShare - kFormatRDOS33 = 20, // 16-sector RDOS disk - kFormatRDOS32 = 21, // 13-sector RDOS disk - kFormatRDOS3 = 22, // 13-sector RDOS disk converted to 16 - // "generic" formats *must* be in their own "decade" - kFormatGenericPhysicalOrd = 30, // unknown, but physical-sector-ordered - kFormatGenericProDOSOrd = 31, // unknown, but ProDOS-block-ordered - kFormatGenericDOSOrd = 32, // unknown, but DOS-sector-ordered - kFormatGenericCPMOrd = 33, // unknown, but CP/M-block-ordered - kFormatUNIDOS = 40, // two 400K DOS 3.3 volumes - kFormatOzDOS = 41, // two 400K DOS 3.3 volumes, weird order - kFormatCFFA4 = 42, // CFFA image with 4 or 6 partitions - kFormatCFFA8 = 43, // CFFA image with 8 partitions - kFormatMacPart = 44, // Macintosh-style partitioned disk - kFormatMicroDrive = 45, // ///SHH Systeme's MicroDrive format - kFormatFocusDrive = 46, // Parsons Engineering FocusDrive format - kFormatGutenberg = 47, // Gutenberg word processor format - - // try to keep this in an unsigned char, e.g. for CP clipboard - } FSFormat; - - /* - * Nibble encode/decode description. Use no pointers here, so we - * store as an array and resize at will. - * - * Should we define an enum to describe whether address and data - * headers are standard or some wacky variant? - */ - typedef enum { - kNibbleAddrPrologLen = 3, // d5 aa 96 - kNibbleAddrEpilogLen = 3, // de aa eb - kNibbleDataPrologLen = 3, // d5 aa ad - kNibbleDataEpilogLen = 3, // de aa eb - }; - typedef enum { - kNibbleEncUnknown = 0, - kNibbleEnc44, - kNibbleEnc53, - kNibbleEnc62, - } NibbleEnc; - typedef enum { - kNibbleSpecialNone = 0, - kNibbleSpecialMuse, // doubled sector numbers on tracks > 2 - kNibbleSpecialSkipFirstAddrByte, - } NibbleSpecial; - typedef struct { - char description[32]; - short numSectors; // 13 or 16 (or 18?) - - unsigned char addrProlog[kNibbleAddrPrologLen]; - unsigned char addrEpilog[kNibbleAddrEpilogLen]; - unsigned char addrChecksumSeed; - bool addrVerifyChecksum; - bool addrVerifyTrack; - int addrEpilogVerifyCount; - - unsigned char dataProlog[kNibbleDataPrologLen]; - unsigned char dataEpilog[kNibbleDataEpilogLen]; - unsigned char dataChecksumSeed; - bool dataVerifyChecksum; - int dataEpilogVerifyCount; - - NibbleEnc encoding; - NibbleSpecial special; - } NibbleDescr; - - - static inline bool IsSectorFormat(PhysicalFormat fmt) { - return (fmt == kPhysicalFormatSectors); - } - static inline bool IsNibbleFormat(PhysicalFormat fmt) { - return (fmt == kPhysicalFormatNib525_6656 || - fmt == kPhysicalFormatNib525_6384 || - fmt == kPhysicalFormatNib525_Var); - } - - // file is on disk; stuff like 2MG headers will be identified and stripped - DIError OpenImage(const char* filename, char fssep, bool readOnly); - // file is in memory; provide a pointer to the data start and buffer size - DIError OpenImage(const void* buffer, long length, bool readOnly); - // file is a range of blocks on an open block-oriented disk image - DIError OpenImage(DiskImg* pParent, long firstBlock, long numBlocks); - // file is a range of tracks/sectors on an open sector-oriented disk image - DIError OpenImage(DiskImg* pParent, long firstTrack, long firstSector, - long numSectors); - - // create a new, blank image file - DIError CreateImage(const char* pathName, const char* storageName, - OuterFormat outerFormat, FileFormat fileFormat, - PhysicalFormat physical, const NibbleDescr* pNibbleDescr, - SectorOrder order, FSFormat format, - long numBlocks, bool skipFormat); - DIError CreateImage(const char* pathName, const char* storageName, - OuterFormat outerFormat, FileFormat fileFormat, - PhysicalFormat physical, const NibbleDescr* pNibbleDescr, - SectorOrder order, FSFormat format, - long numTracks, long numSectPerTrack, bool skipFormat); - - // flush any changes to disk; slow recompress only for "kFlushAll" - typedef enum { kFlushUnknown=0, kFlushFastOnly=1, kFlushAll=2 } FlushMode; - DIError FlushImage(FlushMode mode); - // close the image, freeing up any resources in use - DIError CloseImage(void); - // raise/lower refCnt (may want to track pointers someday) - void AddDiskFS(DiskFS* pDiskFS) { fDiskFSRefCnt++; } - void RemoveDiskFS(DiskFS* pDiskFS) { - assert(fDiskFSRefCnt > 0); - fDiskFSRefCnt--; - } - - // (re-)format this image in the specified FS format - DIError FormatImage(FSFormat format, const char* volName); - // reset all blocks/sectors to zeroes - DIError ZeroImage(void); - - // configure for paired sectors (OzDOS) - void SetPairedSectors(bool enable, int idx); - - // identify sector ordering and disk format - // (may want a version that takes "hints" for special disks?) - DIError AnalyzeImage(void); - // figure out what FS and sector ordering is on the disk image - void AnalyzeImageFS(void); - bool ShowAsBlocks(void) const; - // overrule the analyzer (generally not recommended) -- does not - // override FileFormat, which is very reliable - DIError OverrideFormat(PhysicalFormat physical, FSFormat format, - SectorOrder order); - - // Create a DiskFS that matches this DiskImg. Must be called after - // AnalayzeImage, or you will always get a DiskFSUnknown. The DiskFS - // must be freed with "delete" when no longer needed. - DiskFS* OpenAppropriateDiskFS(bool allowUnknown = false); - - // Add information or a warning to the list of notes. Use linefeeds to - // indicate line breaks. This is currently append-only. - typedef enum { kNoteInfo, kNoteWarning } NoteType; - void AddNote(NoteType type, const char* fmt, ...) - #if defined(__GNUC__) - __attribute__ ((format(printf, 3, 4))) - #endif - ; - const char* GetNotes(void) const; - - // simple accessors - OuterFormat GetOuterFormat(void) const { return fOuterFormat; } - FileFormat GetFileFormat(void) const { return fFileFormat; } - PhysicalFormat GetPhysicalFormat(void) const { return fPhysical; } - SectorOrder GetSectorOrder(void) const { return fOrder; } - FSFormat GetFSFormat(void) const { return fFormat; } - long GetNumTracks(void) const { return fNumTracks; } - int GetNumSectPerTrack(void) const { return fNumSectPerTrack; } - long GetNumBlocks(void) const { return fNumBlocks; } - bool GetReadOnly(void) const { return fReadOnly; } - bool GetDirtyFlag(void) const { return fDirty; } - - // set read-only flag; don't use this (open with correct setting; - // this was added as safety hack for the volume copier) - void SetReadOnly(bool val) { fReadOnly = val; } - - // read a 256-byte sector - // NOTE to self: this function should not be available for odd-sized - // volumes, e.g. a ProDOS /RAM or /RAM5 stored with Davex. Need some way - // to communicate that to disk editor so it knows to grey-out the - // selection checkbox and/or not use "show as sectors" as default. - virtual DIError ReadTrackSector(long track, int sector, void* buf) { - return ReadTrackSectorSwapped(track, sector, buf, fOrder, - fFileSysOrder); - } - DIError ReadTrackSectorSwapped(long track, int sector, - void* buf, SectorOrder imageOrder, SectorOrder fsOrder); - // write a 256-byte sector - virtual DIError WriteTrackSector(long track, int sector, const void* buf); - - // read a 512-byte block - virtual DIError ReadBlock(long block, void* buf) { - return ReadBlockSwapped(block, buf, fOrder, fFileSysOrder); - } - DIError ReadBlockSwapped(long block, void* buf, SectorOrder imageOrder, - SectorOrder fsOrder); - // read multiple blocks - virtual DIError ReadBlocks(long startBlock, int numBlocks, void* buf); - // check our virtual bad block map - bool CheckForBadBlocks(long startBlock, int numBlocks); - // write a 512-byte block - virtual DIError WriteBlock(long block, const void* buf); - // write multiple blocks - virtual DIError WriteBlocks(long startBlock, int numBlocks, const void* buf); - - // read an entire nibblized track - virtual DIError ReadNibbleTrack(long track, unsigned char* buf, - long* pTrackLen); - // write a track; trackLen must be <= those in image - virtual DIError WriteNibbleTrack(long track, const unsigned char* buf, - long trackLen); - - // save the current image as a 2MG file - //DIError Write2MG(const char* filename); - - // need to treat the DOS volume number as meta-data for some disks - short GetDOSVolumeNum(void) const { return fDOSVolumeNum; } - void SetDOSVolumeNum(short val) { fDOSVolumeNum = val; } - enum { kVolumeNumNotSet = -1 }; - - // some simple getters - bool GetHasSectors(void) const { return fHasSectors; } - bool GetHasBlocks(void) const { return fHasBlocks; } - bool GetHasNibbles(void) const { return fHasNibbles; } - bool GetIsEmbedded(void) const { return fpParentImg != NULL; } - - // return the current NibbleDescr - const NibbleDescr* GetNibbleDescr(void) const { return fpNibbleDescr; } - // set the NibbleDescr; we do this by copying the entry into our table - // (could improve by doing memcmp on available entries?) - void SetNibbleDescr(int idx); - void SetCustomNibbleDescr(const NibbleDescr* pDescr); - const NibbleDescr* GetNibbleDescrTable(int* pCount) const { - *pCount = fNumNibbleDescrEntries; - return fpNibbleDescrTable; - } - - // set the NuFX compression type, used when compressing or re-compressing; - // must be set before image is opened or created - void SetNuFXCompressionType(int val) { fNuFXCompressType = val; } - - /* - * Set up a progress callback to use when scanning a disk volume. Pass - * nil for "func" to disable. - * - * The callback function is expected to return "true" if all is well. - * If it returns false, kDIErrCancelled will eventually come back. - */ - typedef bool (*ScanProgressCallback)(void* cookie, const char* str, - int count); - void SetScanProgressCallback(ScanProgressCallback func, void* cookie); - /* update status dialog during disk scan; called from DiskFS code */ - bool UpdateScanProgress(const char* newStr); - - /* - * Static utility functions. - */ - // returns "true" if the files on this image have DOS structure, i.e. - // simple file types and high-ASCII text files - static bool UsesDOSFileStructure(FSFormat format) { - return (format == kFormatDOS33 || - format == kFormatDOS32 || - format == kFormatGutenberg || - format == kFormatUNIDOS || - format == kFormatOzDOS || - format == kFormatRDOS33 || - format == kFormatRDOS32 || - format == kFormatRDOS3); - } - // returns "true" if we can open files on the specified filesystem - static bool CanOpenFiles(FSFormat format) { - return (format == kFormatProDOS || - format == kFormatDOS33 || - format == kFormatDOS32 || - format == kFormatPascal || - format == kFormatCPM || - format == kFormatRDOS33 || - format == kFormatRDOS32 || - format == kFormatRDOS3); - } - // returns "true" if we can create subdirectories on this filesystem - static bool IsHierarchical(FSFormat format) { - return (format == kFormatProDOS || - format == kFormatMacHFS || - format == kFormatMSDOS); - } - // returns "true" if we can create resource forks on this filesystem - static bool HasResourceForks(FSFormat format) { - return (format == kFormatProDOS || - format == kFormatMacHFS); - } - // returns "true" if the format is one of the "generics" - static bool IsGenericFormat(FSFormat format) { - return (format / 10 == DiskImg::kFormatGenericDOSOrd / 10); - } - - /* this must match DiskImg::kStdNibbleDescrs table */ - typedef enum StdNibbleDescr { - kNibbleDescrDOS33Std = 0, - kNibbleDescrDOS33Patched, - kNibbleDescrDOS33IgnoreChecksum, - kNibbleDescrDOS32Std, - kNibbleDescrDOS32Patched, - kNibbleDescrMuse32, - kNibbleDescrRDOS33, - kNibbleDescrRDOS32, - kNibbleDescrCustom, // slot for custom entry - - kNibbleDescrMAX // must be last - }; - static const NibbleDescr* GetStdNibbleDescr(StdNibbleDescr idx); - // call this once, at DLL initialization time - static void CalcNibbleInvTables(void); - // calculate block number from cyl/head/sect on 3.5" disk - static int CylHeadSect35ToBlock(int cyl, int head, int sect); - // unpack nibble data from a 3.5" disk track - static DIError UnpackNibbleTrack35(const unsigned char* nibbleBuf, - long nibbleLen, unsigned char* outputBuf, int cyl, int head, - LinearBitmap* pBadBlockMap); - // compute the #of sectors per track for cylinder N (0-79) - static int SectorsPerTrack35(int cylinder); - - // get the order in which we test for sector ordering - static void GetSectorOrderArray(SectorOrder* orderArray, SectorOrder first); - - // utility function used by HFS filename normalizer; available to apps - static inline unsigned char MacToASCII(unsigned char uch) { - if (uch < 0x20) - return '?'; - else if (uch < 0x80) - return uch; - else - return kMacHighASCII[uch - 0x80]; - } - - // Allow write access to physical disk 0. This is usually the boot disk, - // but with some BIOS the first IDE drive is always physical 0 even if - // you're booting from SATA. This only has meaning under Win32. - static void SetAllowWritePhys0(bool val); - - /* - * Get string constants for enumerated values. - */ - typedef struct { int format; const char* str; } ToStringLookup; - static const char* ToStringCommon(int format, const ToStringLookup* pTable, - int tableSize); - static const char* ToString(OuterFormat format); - static const char* ToString(FileFormat format); - static const char* ToString(PhysicalFormat format); - static const char* ToString(SectorOrder format); - static const char* ToString(FSFormat format); - -private: - /* - * Fundamental disk image identification. - */ - OuterFormat fOuterFormat; // e.g. gzip - FileFormat fFileFormat; - PhysicalFormat fPhysical; - const NibbleDescr* fpNibbleDescr; // only used for "nibble" images - SectorOrder fOrder; // only used for "sector" images - FSFormat fFormat; - - /* - * This affects how the DiskImg responds to requests for reading - * a track or sector. - * - * "fFileSysOrder", together with with "fOrder", determines how - * sector numbers are translated. It describes the order that the - * DiskFS filesystem expects things to be in. If the image isn't - * sector-addressable, then it is assumed to be in linear block order. - * - * If "fSectorPairing" is set, the DiskImg treats the disk as if - * it were in OzDOS format, with one sector from two different - * volumes in a single 512-byte block. - */ - SectorOrder fFileSysOrder; - bool fSectorPairing; - int fSectorPairOffset; // which image (should be 0 or 1) - - /* - * Internal state. - */ - GenericFD* fpOuterGFD; // outer wrapper, if any (.gz only) - GenericFD* fpWrapperGFD; // Apple II image file - GenericFD* fpDataGFD; // raw Apple II data - OuterWrapper* fpOuterWrapper; // needed for outer .gz wrapper - ImageWrapper* fpImageWrapper; // disk image wrapper (2MG, SHK, etc) - DiskImg* fpParentImg; // set for embedded volumes - short fDOSVolumeNum; // specified by some wrapper formats - di_off_t fOuterLength; // total len of file - di_off_t fWrappedLength; // len of file after Outer wrapper removed - di_off_t fLength; // len of disk image (w/o wrappers) - bool fExpandable; // ProDOS .hdv can expand - bool fReadOnly; // allow writes to this image? - bool fDirty; // have we modified this image? - //bool fIsEmbedded; // is this image embedded in another? - - bool fHasSectors; // image is sector-addressable - bool fHasBlocks; // image is block-addressable - bool fHasNibbles; // image is nibble-addressable - - long fNumTracks; // for sector-addressable images - int fNumSectPerTrack; // (ditto) - long fNumBlocks; // for 512-byte block-addressable images - - unsigned char* fNibbleTrackBuf; // allocated on heap - int fNibbleTrackLoaded; // track currently in buffer - - int fNuFXCompressType; // used when compressing a NuFX image - - char* fNotes; // warnings and FYIs about DiskImg/DiskFS - - LinearBitmap* fpBadBlockMap; // used for 3.5" nibble images - - int fDiskFSRefCnt; // #of DiskFS objects pointing at us - - /* - * NibbleDescr entries. There are several standard ones, and we want - * to allow applications to define additional ones. - */ - NibbleDescr* fpNibbleDescrTable; - int fNumNibbleDescrEntries; - - /* static table of default values */ - static const NibbleDescr kStdNibbleDescrs[]; - - DIError CreateImageCommon(const char* pathName, const char* storageName, - bool skipFormat); - DIError ValidateCreateFormat(void) const; - DIError FormatSectors(GenericFD* pGFD, bool quickFormat) const; - //DIError FormatBlocks(GenericFD* pGFD) const; - - DIError CopyBytesOut(void* buf, di_off_t offset, int size) const; - DIError CopyBytesIn(const void* buf, di_off_t offset, int size); - DIError AnalyzeImageFile(const char* pathName, char fssep); - // Figure out the sector ordering for this filesystem, so we can decide - // how the sectors need to be re-arranged when we're reading them. - SectorOrder CalcFSSectorOrder(void) const; - // Handle sector order calculations. - DIError CalcSectorAndOffset(long track, int sector, SectorOrder ImageOrder, - SectorOrder fsOrder, di_off_t* pOffset, int* pNewSector); - inline bool IsLinearBlocks(SectorOrder imageOrder, SectorOrder fsOrder); - - /* - * Progress update during the filesystem scan. This only exists in the - * topmost DiskImg. (This is arguably more appropriate in DiskFS, but - * DiskFS objects don't have a notion of "parent" and are somewhat more - * ephemeral.) - */ - ScanProgressCallback fpScanProgressCallback; - void* fScanProgressCookie; - int fScanCount; - char fScanMsg[128]; - time_t fScanLastMsgWhen; - - /* - * 5.25" nibble image access. - */ - enum { - kDataSize62 = 343, // 342 bytes + checksum byte - kChunkSize62 = 86, // (0x56) - - kDataSize53 = 411, // 410 bytes + checksum byte - kChunkSize53 = 51, // (0x33) - kThreeSize = (kChunkSize53 * 3) + 1, // same as 410 - 256 - }; - DIError ReadNibbleSector(long track, int sector, void* buf, - const NibbleDescr* pNibbleDescr); - DIError WriteNibbleSector(long track, int sector, const void* buf, - const NibbleDescr* pNibbleDescr); - void DumpNibbleDescr(const NibbleDescr* pNibDescr) const; - int GetNibbleTrackLength(long track) const; - int GetNibbleTrackOffset(long track) const; - int GetNibbleTrackFormatLength(void) const { - /* return length to use when formatting for 16 sectors */ - if (fPhysical == kPhysicalFormatNib525_6656) - return kTrackLenNib525; - else if (fPhysical == kPhysicalFormatNib525_6384) - return kTrackLenNb2525; - else if (fPhysical == kPhysicalFormatNib525_Var) { - if (fFileFormat == kFileFormatTrackStar || - fFileFormat == kFileFormatFDI) - { - return kTrackLenNb2525; // use minimum possible - } - } - assert(false); - return -1; - } - int GetNibbleTrackAllocLength(void) const { - /* return length to allocate when creating an image */ - if (fPhysical == kPhysicalFormatNib525_Var && - (fFileFormat == kFileFormatTrackStar || - fFileFormat == kFileFormatFDI)) - { - // use maximum possible - return kTrackLenTrackStar525; - } - return GetNibbleTrackFormatLength(); - } - DIError LoadNibbleTrack(long track, long* pTrackLen); - DIError SaveNibbleTrack(void); - int FindNibbleSectorStart(const CircularBufferAccess& buffer, - int track, int sector, const NibbleDescr* pNibbleDescr, int* pVol); - void DecodeAddr(const CircularBufferAccess& buffer, int offset, - short* pVol, short* pTrack, short* pSector, short* pChksum); - inline unsigned int ConvFrom44(unsigned char val1, unsigned char val2) { - return ((val1 << 1) | 0x01) & val2; - } - DIError DecodeNibbleData(const CircularBufferAccess& buffer, int idx, - unsigned char* sctBuf, const NibbleDescr* pNibbleDescr); - void EncodeNibbleData(const CircularBufferAccess& buffer, int idx, - const unsigned char* sctBuf, const NibbleDescr* pNibbleDescr) const; - DIError DecodeNibble62(const CircularBufferAccess& buffer, int idx, - unsigned char* sctBuf, const NibbleDescr* pNibbleDescr); - void EncodeNibble62(const CircularBufferAccess& buffer, int idx, - const unsigned char* sctBuf, const NibbleDescr* pNibbleDescr) const; - DIError DecodeNibble53(const CircularBufferAccess& buffer, int idx, - unsigned char* sctBuf, const NibbleDescr* pNibbleDescr); - void EncodeNibble53(const CircularBufferAccess& buffer, int idx, - const unsigned char* sctBuf, const NibbleDescr* pNibbleDescr) const; - int TestNibbleTrack(int track, const NibbleDescr* pNibbleDescr, int* pVol); - DIError AnalyzeNibbleData(void); - inline unsigned char Conv44(unsigned short val, bool first) const { - if (first) - return (val >> 1) | 0xaa; - else - return val | 0xaa; - } - DIError FormatNibbles(GenericFD* pGFD) const; - - static const unsigned char kMacHighASCII[]; - - /* - * 3.5" nibble access - */ - static int FindNextSector35(const CircularBufferAccess& buffer, int start, - int cyl, int head, int* pSector); - static bool DecodeNibbleSector35(const CircularBufferAccess& buffer, - int start, unsigned char* sectorBuf, unsigned char* readChecksum, - unsigned char* calcChecksum); - static bool UnpackChecksum35(const CircularBufferAccess& buffer, - int offset, unsigned char* checksumBuf); - static void EncodeNibbleSector35(const unsigned char* sectorData, - unsigned char* outBuf); - - /* static data tables */ - static unsigned char kDiskBytes53[32]; - static unsigned char kDiskBytes62[64]; - static unsigned char kInvDiskBytes53[256]; - static unsigned char kInvDiskBytes62[256]; - enum { kInvInvalidValue = 0xff }; - -private: // some C++ stuff to block behavior we don't support - DiskImg& operator=(const DiskImg&); - DiskImg(const DiskImg&); -}; - - - -/* - * Disk filesystem class, roughly equivalent to a GS/OS FST. This is an - * abstract base class. - * - * Static functions know how to access a DiskImg and figure out what kind - * of image we have. Once known, the appropriate sub-class can be - * instantiated. - * - * We maintain a linear list of files to make it easy for applications to - * traverse the full set of files. Sometimes this makes it hard for us to - * update internally (especially HFS). With some minor cleverness it - * should be possible to switch to a tree structure while retaining the - * linear "get next" API. This would be a big help for ProDOS and HFS. - * - * NEED: some notification mechanism for changes to files and/or block - * editing of the disk (especially with regard to open sub-volumes). If - * a disk volume open for file-by-file viewing is modified with the disk - * editor, we should close the file when the disk editor exits. - * - * NEED? disk utilities, such as "disk crunch", for Pascal volumes. Could - * be written externally, but might as well keep fs knowledge embedded. - * - * MISSING: there is no way to override the image analyzer when working - * with sub-volumes. Actually, there is; it just has to happen *after* - * the DiskFS has been created. We should provide an approach that either - * stifles the DiskFS creation, or allows us to override and replace the - * internal DiskFS so we can pop up a sub-volume list, show what we *think* - * is there, and then let the user pick a volume and pick overrides (mainly - * for use in the disk editor). Not sure if we want the changes to "stick"; - * we probably do. Q: does the "scan for sub-volumes" attribute propagate - * recursively to each sub-sub-volume? Probably. - * - * NOTE to self: should make "test" functions more lax when called - * from here, on the assumption that the caller is knowledgeable. Perhaps - * an independent "strictness" variable that can be cranked down through - * multiple calls to AnalyzeImage?? - */ -class DISKIMG_API DiskFS { -public: - /* - * Information about volume usage. - * - * Each "chunk" is a track/sector on a DOS disk or a block on a ProDOS - * or Pascal disk. CP/M really ought to use 1K blocks, but for - * convenience we're just using 512-byte blocks (it's up to the CP/M - * code to set two "chunks" per block). - * - * NOTE: the current DOS/ProDOS/Pascal code is sloppy when it comes to - * keeping this structure up to date. HFS doesn't use it at all. This - * has always been a low-priority feature. - */ - class DISKIMG_API VolumeUsage { - public: - VolumeUsage(void) { - fByBlocks = false; - fTotalChunks = -1; - fNumSectors = -1; - //fFreeChunks = -1; - fList = NULL; - fListSize = -1; - } - ~VolumeUsage(void) { - delete[] fList; - } - - /* - * These values MUST fit in five bits. - * - * Suggested disk map colors: - * 0 = unknown (color-key pink) - * 1 = conflict (medium-red) - * 2 = boot loader (dark-blue) - * 3 = volume dir (light-blue) - * 4 = subdir (medium-blue) - * 5 = user data (medium-green) - * 6 = user index blocks (light-green) - * 7 = embedded filesys (yellow) - * - * THOUGHT: Add flag for I/O error (nibble images) -- requires - * automatic disk verify pass. (Or maybe could be done manually - * on request?) - * - * unused --> black - * marked-used-but-not-used --> dark-red - * used-but-not-marked-used --> orange - */ - typedef enum { - kChunkPurposeUnknown = 0, - kChunkPurposeConflict = 1, // two or more different things - kChunkPurposeSystem = 2, // boot blocks, volume bitmap - kChunkPurposeVolumeDir = 3, // volume dir (or only dir) - kChunkPurposeSubdir = 4, // ProDOS sub-directory - kChunkPurposeUserData = 5, // file on this filesystem - kChunkPurposeFileStruct = 6, // index blocks, T/S lists - kChunkPurposeEmbedded = 7, // embedded filesystem - // how about: outside range claimed by disk, e.g. fTotalBlocks on - // 800K ProDOS disk in a 32MB CFFA volume? - } ChunkPurpose; - - typedef struct ChunkState { - bool isUsed; - bool isMarkedUsed; - ChunkPurpose purpose; // only valid if isUsed is set - } ChunkState; - - // initialize, configuring for either blocks or sectors - DIError Create(long numBlocks); - DIError Create(long numTracks, long numSectors); - bool GetInitialized(void) const { return (fList != NULL); } - - // return the number of chunks on this disk - long GetNumChunks(void) const { return fTotalChunks; } - - // return the number of unallocated chunks, taking into account - // both the free-chunk bitmap (if any) and the actual usage - long GetActualFreeChunks(void) const; - - // return the state of the specified chunk - DIError GetChunkState(long block, ChunkState* pState) const; - DIError GetChunkState(long track, long sector, - ChunkState* pState) const; - - // set the state of a particular chunk (should only be done by - // the DiskFS sub-classes) - DIError SetChunkState(long block, const ChunkState* pState); - DIError SetChunkState(long track, long sector, - const ChunkState* pState); - - void Dump(void) const; // debugging - - private: - DIError GetChunkStateIdx(int idx, ChunkState* pState) const; - DIError SetChunkStateIdx(int idx, const ChunkState* pState); - inline char StateToChar(ChunkState* pState) const; - - /* - * Chunk state is stored as a set of bits in one byte: - * - * 0-4: how is block used (only has meaning if bit 6 is set) - * 5: for nibble images, indicates the block or sector is unreadable - * 6: is block used by something (0=no, 1=yes) - * 7: is block marked "in use" by system map (0=no, 1=yes) - * - * [ Consider reducing "purpose" to 0-3 and adding bad block bit for - * nibble images and physical media.] - */ - enum { - kChunkPurposeMask = 0x1f, // ChunkPurpose enum - kChunkDamagedFlag = 0x20, - kChunkUsedFlag = 0x40, - kChunkMarkedUsedFlag = 0x80, - }; - - bool fByBlocks; - long fTotalChunks; - long fNumSectors; // only valid if !fByBlocks - //long fFreeChunks; - unsigned char* fList; - int fListSize; - }; // end of VolumeUsage class - - /* - * List of sub-volumes. The SubVolume owns the DiskImg and DiskFS - * that are handed to it, so they can be deleted when the SubVolume - * is deleted as part of destroying the parent. - */ - class SubVolume { - public: - SubVolume(void) : fpDiskImg(NULL), fpDiskFS(NULL), - fpPrev(NULL), fpNext(NULL) {} - ~SubVolume(void) { - delete fpDiskFS; // must close first; may need flush to DiskImg - delete fpDiskImg; - } - - void Create(DiskImg* pDiskImg, DiskFS* pDiskFS) { - assert(pDiskImg != NULL); - assert(pDiskFS != NULL); - fpDiskImg = pDiskImg; - fpDiskFS = pDiskFS; - } - - DiskImg* GetDiskImg(void) const { return fpDiskImg; } - DiskFS* GetDiskFS(void) const { return fpDiskFS; } - - SubVolume* GetPrev(void) const { return fpPrev; } - void SetPrev(SubVolume* pSubVol) { fpPrev = pSubVol; } - SubVolume* GetNext(void) const { return fpNext; } - void SetNext(SubVolume* pSubVol) { fpNext = pSubVol; } - - private: - DiskImg* fpDiskImg; - DiskFS* fpDiskFS; - - SubVolume* fpPrev; - SubVolume* fpNext; - }; // end of SubVolume class - - - - /* - * Start of DiskFS declarations. - */ -public: - typedef enum SubScanMode { - kScanSubUnknown = 0, - kScanSubDisabled, - kScanSubEnabled, - kScanSubContainerOnly, - } SubScanMode; - - - DiskFS(void) { - fpA2Head = fpA2Tail = NULL; - fpSubVolumeHead = fpSubVolumeTail = NULL; - fpImg = NULL; - fScanForSubVolumes = kScanSubDisabled; - - fParmTable[kParm_CreateUnique] = 0; - fParmTable[kParmProDOS_AllowLowerCase] = 1; - fParmTable[kParmProDOS_AllocSparse] = 1; - } - virtual ~DiskFS(void) { - DeleteSubVolumeList(); - DeleteFileList(); - SetDiskImg(NULL); - } - - /* - * Static FSFormat-analysis functions, called by the DiskImg AnalyzeImage - * function. Capable of determining with a high degree of accuracy - * what format the disk is in, yet remaining flexible enough to - * function correctly with variations (like DOS3.3 disks with - * truncated TOCs and ProDOS images from hard drives). - * - * The "pOrder" and "pFormat" arguments are in/out. Set them to the - * appropriate "unknown" enum value on entry. If something is known - * of the order or format, put that in instead; in some cases this will - * bias the proceedings, which is useful for efficiency and for making - * overrides work correctly. - * - * On success, these return kDIErrNone and set "*pOrder". On failure, - * they return nonzero and leave "*pOrder" unmodified. - * - * Each DiskFS sub-class should declare a TestFS function. It's not - * virtual void here because, since it's called before the DiskFS is - * created, it must be static. - */ - typedef enum FSLeniency { kLeniencyNot, kLeniencyVery } FSLeniency; - //static DIError TestFS(const DiskImg* pImg, DiskImg::SectorOrder* pOrder, - // DiskImg::FSFormat* pFormat, FSLeniency leniency); - - /* - * Load the disk contents and (if enabled) scan for sub-volumes. - * - * If "headerOnly" is set, we just do a quick scan of the volume header - * to get basic information. The deep file scan is skipped (but can - * be done later). (Sub-classes can choose to ignore the flag and - * always do the full scan; this is an optimization.) Guaranteed to - * set the volume name and volume block/sector count. - * - * If a progress callback is set up, this can return with a "cancelled" - * result, which should not be treated as a failure. - */ - typedef enum { kInitUnknown = 0, kInitHeaderOnly, kInitFull } InitMode; - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) = 0; - - /* - * Format the disk with the appropriate filesystem, creating all filesystem - * structures and (when appropriate) boot blocks. - */ - virtual DIError Format(DiskImg* pDiskImg, const char* volName) - { return kDIErrNotSupported; } - - /* - * Pass in a full path to normalize, and a buffer to copy the output - * into. On entry "pNormalizedBufLen" holds the length of the buffer. - * On exit, it holds the size of the buffer required to hold the - * normalized string. If the buffer is nil or isn't big enough, no part - * of the normalized path will be copied into the buffer, and a specific - * error (kDIErrDataOverrun) will be returned. - */ - virtual DIError NormalizePath(const char* path, char fssep, - char* normalizedBuf, int* pNormalizedBufLen) - { return kDIErrNotSupported; } - - - /* - * Create a file. The CreateParms struct specifies the full set of file - * details. To remain FS-agnostic, use the NufxLib constants - * (kNuStorageDirectory, kNuAccessUnlocked, etc). They match up with - * their ProDOS equivalents, and I promise to make them work right. - * - * On success, the file exists as a fully-formed, zero-length file. A - * pointer to the relevant A2File structure is returned. - */ - enum { - /* valid values for CreateParms; must match ProDOS enum */ - kStorageSeedling = 1, - kStorageExtended = 5, - kStorageDirectory = 13, - }; - typedef struct CreateParms { - const char* pathName; // full pathname - char fssep; - int storageType; // determines normal, subdir, or forked - long fileType; - long auxType; - int access; - time_t createWhen; - time_t modWhen; - } CreateParms; - virtual DIError CreateFile(const CreateParms* pParms, A2File** ppNewFile) - { return kDIErrNotSupported; } - - /* - * Delete a file from the disk. - */ - virtual DIError DeleteFile(A2File* pFile) - { return kDIErrNotSupported; } - - /* - * Rename a file. - */ - virtual DIError RenameFile(A2File* pFile, const char* newName) - { return kDIErrNotSupported; } - - /* - * Alter file attributes. - */ - virtual DIError SetFileInfo(A2File* pFile, long fileType, long auxType, - long accessFlags) - { return kDIErrNotSupported; } - - /* - * Rename a volume. Also works for changing the disk volume number. - */ - virtual DIError RenameVolume(const char* newName) - { return kDIErrNotSupported; } - - - // Accessor - DiskImg* GetDiskImg(void) const { return fpImg; } - - // Test file and volume names (and volume numbers) - // [these need to be static functions for some things... hmm] - //virtual bool IsValidFileName(const char* name) const { return false; } - //virtual bool IsValidVolumeName(const char* name) const { return false; } - - // Return the disk volume name, or NULL if there isn't one. - virtual const char* GetVolumeName(void) const = 0; - - // Return a printable string identifying the FS type and volume - virtual const char* GetVolumeID(void) const = 0; - - // Return the "bare" volume name. For formats where the volume name - // is actually a number (e.g. DOS 3.3), this returns just the number. - // For formats without a volume name or number (e.g. CP/M), this returns - // nil, indicating that any attempt to change the volume name will fail. - virtual const char* GetBareVolumeName(void) const = 0; - - // Returns "false" if we only support read-only access to this FS type - virtual bool GetReadWriteSupported(void) const = 0; - - // Returns "true" if the filesystem shows evidence of damage. - virtual bool GetFSDamaged(void) const = 0; - - // Returns number of blocks recognized by the filesystem, or -1 if the - // FS isn't block-oriented (e.g. DOS 3.2/3.3) - virtual long GetFSNumBlocks(void) const { return -1; } - - // Get the next file in the list. Start by passing in NULL to get the - // head of the list. Returns NULL when the end of the list is reached. - A2File* GetNextFile(A2File* pCurrent) const; - - // Get a count of the files and directories on this disk. - long GetFileCount(void) const; - - /* - * Find a file by case-insensitive pathname. Assumes fssep=':'. The - * compare function can be overridden for systems like HFS, where "case - * insensitive" has a different meaning because of the native - * character set. - * - * The A2File* returned should not be deleted. - */ - typedef int (*StringCompareFunc)(const char* str1, const char* str2); - A2File* GetFileByName(const char* pathName, StringCompareFunc func = NULL); - - // This controls scanning for sub-volumes; must be set before Initialize(). - SubScanMode GetScanForSubVolumes(void) const { return fScanForSubVolumes; } - void SetScanForSubVolumes(SubScanMode val) { fScanForSubVolumes = val; } - - // some constants for non-ProDOS filesystems to use - enum { kFileAccessLocked = 0x01, kFileAccessUnlocked = 0xc3 }; - - - /* - * We use this as a filename separator character (i.e. between pathname - * components) in all filenames. It's useful to standardize on this - * so that behavior is consistent across all disk and archive formats. - * - * The choice of ':' is good because it's invalid in filenames on - * Windows, Mac OS, GS/OS, and pretty much anywhere else we could be - * running except for UNIX. It's valid under DOS 3.3, but since you - * can't have subdirectories under DOS there's no risk of confusion. - */ - enum { kDIFssep = ':' }; - - - /* - * Return the volume use map. This is a non-const function because - * it might need to do a "just-in-time" usage map update. It returns - * const to keep non-DiskFS classes from altering the map. - */ - const VolumeUsage* GetVolumeUsageMap(void) { - if (fVolumeUsage.GetInitialized()) - return &fVolumeUsage; - else - return NULL; - } - - /* - * Return the total space and free space, in either blocks or sectors - * as appropriate. "*pUnitSize" will be kBlockSize or kSectorSize. - */ - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const = 0; - - - /* - * Get the next volume in the list. Start by passing in NULL to get the - * head of the list. Returns NULL when the end of the list is reached. - */ - SubVolume* GetNextSubVolume(const SubVolume* pCurrent) const; - - /* - * Set some parameters to tell the DiskFS how to operate. Some of - * these are FS-specific, some may be general. - * - * Parameters are set in the current object and all sub-volume objects. - * - * The enum is part of the interface and must be rigidly defined, but - * it is also used to size an array so it can't be too sparse. - */ - typedef enum DiskFSParameter { - kParmUnknown = 0, - - kParm_CreateUnique = 1, // make new filenames unique - - kParmProDOS_AllowLowerCase = 10, // allow lower case and spaces - kParmProDOS_AllocSparse = 11, // don't store empty blocks - - kParmMax // must be last entry - } DiskFSParameter; - long GetParameter(DiskFSParameter parm); - void SetParameter(DiskFSParameter parm, long val); - - /* - * Flush changed data. - * - * The individual filesystems shouldn't generally do any caching; if - * they do, we would want a virtual "FlushFS()" that gets called by - * Flush. The better answer is to cache in DiskImg, which works for - * everything, and knows if the underlying storage is already in RAM. - * - * For the most part this just needs to recursively flush the DiskImg - * objects in all of the sub-volumes and then the current volume. This - * is a no-op in most cases, but if the archive is compressed this will - * cause a new, compressed archive to be created. - * - * The "mode" value determines whether or not we do "heavy" flushes. It's - * very handy to be able to do "slow" flushes for anything that is being - * written directly to disk (as opposed to being run through Deflate), - * so that the UI doesn't indicate that they're partially written when - * in fact they're fully written. - */ - DIError Flush(DiskImg::FlushMode mode); - - /* - * Set the read-only flag on our DiskImg and those of our subvolumes. - * Used to ensure that a DiskFS with un-flushed data can be deleted - * without corrupting the volume. - */ - void SetAllReadOnly(bool val); - - // debug dump - void DumpFileList(void); - -protected: - /* - * Set the DiskImg pointer. Updates the reference count in DiskImg. - */ - void SetDiskImg(DiskImg* pImg); - - // once added, we own the pDiskImg and the pDiskFS (DO NOT pass the - // same DiskImg or DiskFS in more than once!). Note this copies the - // fParmTable and other stuff (fScanForSubVolumes) from parent to child. - void AddSubVolumeToList(DiskImg* pDiskImg, DiskFS* pDiskFS); - // add files to fpA2Head/fpA2Tail - void AddFileToList(A2File* pFile); - // only need for hierarchical filesystems; insert file after pPrev - void InsertFileInList(A2File* pFile, A2File* pPrev); - // delete an entry - void DeleteFileFromList(A2File* pFile); - - // scan for damaged or suspicious files - void ScanForDamagedFiles(bool* pDamaged, bool* pSuspicious); - - // pointer to the DiskImg structure underlying this filesystem - DiskImg* fpImg; - - VolumeUsage fVolumeUsage; - SubScanMode fScanForSubVolumes; - - -private: - A2File* SkipSubdir(A2File* pSubdir); - void CopyInheritables(DiskFS* pNewFS); - void DeleteFileList(void); - void DeleteSubVolumeList(void); - - long fParmTable[kParmMax]; // for DiskFSParameter - - A2File* fpA2Head; - A2File* fpA2Tail; - SubVolume* fpSubVolumeHead; - SubVolume* fpSubVolumeTail; - -private: - DiskFS& operator=(const DiskFS&); - DiskFS(const DiskFS&); -}; - - -/* - * Apple II file class, representing a file on an Apple II volume. This is an - * abstract base class. - * - * There is a different sub-class for each filesystem type. The A2File object - * encapsulates all of the knowledge required to read a file from a disk - * image. - * - * The prev/next pointers, used to maintain a linked list of files, are only - * accessible from DiskFS functions. At some point we may want to rearrange - * the way this is handled, e.g. by not maintaining a list at all, so it's - * important that everything go through DiskFS requests. - * - * The FSFormat is made an explicit member, because sub-classes may not - * understand exactly where the file came from (e.g. was it DOS3.2 or - * DOS 3.3). Somebody might care. - * - * - * NOTE TO SELF: open files need to be generalized. Right now the internal - * implementations only allow a single open, which is okay for our purposes - * but bad for a general FS implementation. As it stands, you can't even - * open both forks at the same time on ProDOS/HFS. - * - * UMMM: The handling of "damaged" files could be more consistent. - */ -class DISKIMG_API A2File { -public: - friend class DiskFS; - - A2File(DiskFS* pDiskFS) : fpDiskFS(pDiskFS) { - fpPrev = fpNext = NULL; - fFileQuality = kQualityGood; - } - virtual ~A2File(void) {} - - /* - * All Apple II files have certain characteristics, of which ProDOS - * is roughly a superset. (Yes, you can have HFS on a IIgs, but - * all that fancy creator type stuff is decidedly Mac-centric. Still, - * we want to assume 4-byte file and aux types.) - * - * NEED: something distinguishing between files and disk images? - * - * NOTE: there is no guarantee that GetPathName will return unique values - * (duplicates are possible). We don't guarantee that you won't get an - * empty string back (it's valid to have an empty filename in the dir in - * DOS 3.3, and it's possible for other filesystems to be damaged). The - * pathname may receive some minor sanitizing, e.g. removal or conversion - * of high ASCII and control characters, but some filesystems (like HFS) - * make use of them. - * - * We do guarantee that the contents of subdirectories are grouped - * together. This makes it much easier to construct a hierarchy out of - * the linear list. This becomes important when dynamically adding - * files to a disk. - */ - virtual const char* GetFileName(void) const = 0; // name of this file - virtual const char* GetPathName(void) const = 0; // full path - virtual char GetFssep(void) const = 0; // '\0' if none - virtual long GetFileType(void) const = 0; - virtual long GetAuxType(void) const = 0; - virtual long GetAccess(void) const = 0; // ProDOS-style perms - virtual time_t GetCreateWhen(void) const = 0; - virtual time_t GetModWhen(void) const = 0; - virtual di_off_t GetDataLength(void) const = 0; // len of data fork - virtual di_off_t GetDataSparseLength(void) const = 0; // len w/o sparse areas - virtual di_off_t GetRsrcLength(void) const = 0; // len or -1 if no rsrc - virtual di_off_t GetRsrcSparseLength(void) const = 0; // len or -1 if no rsrc - virtual DiskImg::FSFormat GetFSFormat(void) const { - return fpDiskFS->GetDiskImg()->GetFSFormat(); - } - virtual bool IsDirectory(void) const { return false; } - virtual bool IsVolumeDirectory(void) const { return false; } - - /* - * Open a file. Treat the A2FileDescr like an fd. - */ - virtual DIError Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork = false) = 0; - - /* - * This is called by the A2FileDescr object when somebody invokes Close(). - * The A2File object should remove the A2FileDescr from its list of open - * files and delete the storage. The implementation must not call the - * A2FileDescr's Close function, since that would cause a recursive loop. - * - * This should not be called by an application. - */ - virtual void CloseDescr(A2FileDescr* pOpenFile) = 0; - - /* - * This is only useful for hierarchical filesystems like ProDOS, - * where the order of items in the linear list is significant. It - * allows an unambiguous determination of which subdir a file resides - * in, even if somebody has sector-edited the filesystem so that two - * subdirs have the same name. (It's also a bit speedier to compare - * than pathname substrings would be.) - */ - virtual A2File* GetParent(void) const { return NULL; } - - /* - * Returns "true" if either fork of the file is open, "false" if not. - */ - virtual bool IsFileOpen(void) const = 0; - - virtual void Dump(void) const = 0; // debugging - - typedef enum FileQuality { - kQualityUnknown = 0, - kQualityGood, - kQualitySuspicious, - kQualityDamaged, - } FileQuality; - virtual FileQuality GetQuality(void) const { return fFileQuality; } - virtual void SetQuality(FileQuality quality); - virtual void ResetQuality(void); - - DiskFS* GetDiskFS(void) const { return fpDiskFS; } - -protected: - DiskFS* fpDiskFS; - virtual void SetParent(A2File* pParent) { /* do nothing */ } - -private: - A2File* GetPrev(void) const { return fpPrev; } - void SetPrev(A2File* pFile) { fpPrev = pFile; } - A2File* GetNext(void) const { return fpNext; } - void SetNext(A2File* pFile) { fpNext = pFile; } - - // Set when file structure is damaged and application should not try - // to open the file. - FileQuality fFileQuality; - - A2File* fpPrev; - A2File* fpNext; - - -private: - A2File& operator=(const A2File&); - A2File(const A2File&); -}; - - -/* - * Abstract representation of an open file. This contains all active state - * and all information required to read and write a file. - * - * Do not delete these objects; instead, invoke the Close method, so that they - * can be removed from the parents' list of open files. - * TODO: consider making the destructor "protected" - */ -class DISKIMG_API A2FileDescr { -public: - A2FileDescr(A2File* pFile) : fpFile(pFile), fProgressUpdateFunc(NULL) {} - virtual ~A2FileDescr(void) { fpFile = NULL; /*paranoia*/ } - - virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL) = 0; - virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL) = 0; - virtual DIError Seek(di_off_t offset, DIWhence whence) = 0; - virtual di_off_t Tell(void) = 0; - virtual DIError Close(void) = 0; - - virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) - const = 0; - virtual DIError GetStorage(long blockIdx, long* pBlock) - const = 0; - virtual long GetSectorCount(void) const = 0; - virtual long GetBlockCount(void) const = 0; - - virtual DIError Rewind(void) { return Seek(0, kSeekSet); } - - A2File* GetFile(void) const { return fpFile; } - - /* - * Progress update callback mechanism. Pass in the length or (for writes) - * expected length of the file. This invokes the callback with the - * lengths and some pointers. - * - * If the progress callback returns "true", progress continues. If it - * returns "false", the read or write function will return with - * kDIErrCancelled. - */ - typedef bool (*ProgressUpdater)(A2FileDescr* pFile, di_off_t max, - di_off_t current, void* vState); - void SetProgressUpdater(ProgressUpdater func, di_off_t max, void* state) { - fProgressUpdateFunc = func; - fProgressUpdateMax = max; - fProgressUpdateState = state; - } - void ClearProgressUpdater(void) { - fProgressUpdateFunc = NULL; - } - -protected: - A2File* fpFile; - - /* - * Internal utility functions for mapping blocks to sectors and vice-versa. - */ - virtual void TrackSectorToBlock(long track, long sector, long* pBlock, - bool* pSecondHalf) const - { - int numSectPerTrack = fpFile->GetDiskFS()->GetDiskImg()->GetNumSectPerTrack(); - assert(track < fpFile->GetDiskFS()->GetDiskImg()->GetNumTracks()); - assert(sector < numSectPerTrack); - long dblBlock = track * numSectPerTrack + sector; - *pBlock = dblBlock / 2; - *pSecondHalf = (dblBlock & 0x01) != 0; - } - virtual void BlockToTrackSector(long block, bool secondHalf, long* pTrack, - long* pSector) const - { - assert(block < fpFile->GetDiskFS()->GetDiskImg()->GetNumBlocks()); - int numSectPerTrack = fpFile->GetDiskFS()->GetDiskImg()->GetNumSectPerTrack(); - int dblBlock = block * 2; - if (secondHalf) - dblBlock++; - *pTrack = dblBlock / numSectPerTrack; - *pSector = dblBlock % numSectPerTrack; - } - - /* - * Call this from FS-specific read/write functions on successful - * completion (and perhaps more often for filesystems with potentially - * large files, e.g. ProDOS/HFS). - * - * Test the return value; if "false", user wishes to cancel the op, and - * long read or write calls should return immediately. - */ - inline bool UpdateProgress(di_off_t current) { - if (fProgressUpdateFunc != NULL) { - return (*fProgressUpdateFunc)(this, fProgressUpdateMax, current, - fProgressUpdateState); - } else { - return true; - } - } - -private: - A2FileDescr& operator=(const A2FileDescr&); - A2FileDescr(const A2FileDescr&); - - /* storage for progress update goodies */ - ProgressUpdater fProgressUpdateFunc; - di_off_t fProgressUpdateMax; - void* fProgressUpdateState; -}; - -}; // namespace DiskImgLib - -#endif /*__DISK_IMG__*/ +/* + * CiderPress + * Copyright (C) 2009 by CiderPress authors. All Rights Reserved. + * Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved. + * See the file LICENSE for distribution terms. + */ +/* + * Public declarations for the DiskImg library. + * + * Everything is wrapped in the "DiskImgLib" namespace. Either prefix + * all references with "DiskImgLib::", or add "using namespace DiskImgLib" + * to all C++ source files that make use of it. + * + * Under Linux, this should be compiled with -D_FILE_OFFSET_BITS=64. + * + * These classes are not thread-safe with respect to access to a single + * disk image. Writing to the same disk image from multiple threads + * simultaneously is bound to end in disaster. Simultaneous access to + * different objects will work, though modifying the same disk image + * file from multiple objects will lead to unpredictable results. + */ +#ifndef __DISK_IMG__ +#define __DISK_IMG__ + +#include +#include +#include + +//#define EXCISE_GPL_CODE + +/* Windows DLL stuff */ +#ifdef _WIN32 +# ifdef DISKIMG_EXPORTS +# define DISKIMG_API __declspec(dllexport) +# else +# define DISKIMG_API __declspec(dllimport) +# endif +#else +# define DISKIMG_API +#endif + +namespace DiskImgLib { + +/* compiled-against versions; call DiskImg::GetVersion for linked-against */ +#define kDiskImgVersionMajor 4 +#define kDiskImgVersionMinor 6 +#define kDiskImgVersionBug 0 + + +/* + * Errors from the various disk image classes. + */ +typedef enum DIError { + kDIErrNone = 0, + + /* I/O request errors (should renumber/rename to match GS/OS errors?) */ + kDIErrAccessDenied = -10, + kDIErrVWAccessForbidden = -11, // write access to volume forbidden + kDIErrSharingViolation = -12, // file is in use and not shareable + kDIErrNoExclusiveAccess = -13, // couldn't get exclusive access + kDIErrWriteProtected = -14, // disk is write protected + kDIErrCDROMNotSupported = -15, // access to CD-ROM drives not supptd + kDIErrASPIFailure = -16, // generic ASPI failure result + kDIErrSPTIFailure = -17, // generic SPTI failure result + kDIErrSCSIFailure = -18, // generic SCSI failure result + kDIErrDeviceNotReady = -19, // floppy or CD-ROM drive has no media + + kDIErrFileNotFound = -20, + kDIErrForkNotFound = -21, // requested fork does not exist + kDIErrAlreadyOpen = -22, // already open, can't open a 2nd time + kDIErrFileOpen = -23, // file is open, can't delete it + kDIErrNotReady = -24, + kDIErrFileExists = -25, // file already exists + kDIErrDirectoryExists = -26, // directory already exists + + kDIErrEOF = -30, // end-of-file reached + kDIErrReadFailed = -31, + kDIErrWriteFailed = -32, + kDIErrDataUnderrun = -33, // tried to read off end of the image + kDIErrDataOverrun = -34, // tried to write off end of the image + kDIErrGenericIO = -35, // generic I/O error + + kDIErrOddLength = -40, // image size not multiple of sectors + kDIErrUnrecognizedFileFmt = -41, // file format just not recognized + kDIErrBadFileFormat = -42, // filename ext doesn't match contents + kDIErrUnsupportedFileFmt = -43, // recognized but not supported + kDIErrUnsupportedPhysicalFmt = -44, // (same) + kDIErrUnsupportedFSFmt = -45, // (and again) + kDIErrBadOrdering = -46, // requested sector ordering no good + kDIErrFilesystemNotFound = -47, // requested filesystem isn't there + kDIErrUnsupportedAccess = -48, // e.g. read sectors from blocks-only + kDIErrUnsupportedImageFeature = -49, // e.g. FDI image w/Amiga sectors + + kDIErrInvalidTrack = -50, // request for invalid track number + kDIErrInvalidSector = -51, // request for invalid sector number + kDIErrInvalidBlock = -52, // request for invalid block number + kDIErrInvalidIndex = -53, // request with an invalid index + + kDIErrDirectoryLoop = -60, // directory chain points into itself + kDIErrFileLoop = -61, // file sector or block alloc loops + kDIErrBadDiskImage = -62, // the FS on the disk image is damaged + kDIErrBadFile = -63, // bad file on disk image + kDIErrBadDirectory = -64, // bad dir on disk image + kDIErrBadPartition = -65, // bad partition on multi-part format + + kDIErrFileArchive = -70, // file archive, not disk archive + kDIErrUnsupportedCompression = -71, // compression method is not supported + kDIErrBadChecksum = -72, // image file's checksum is bad + kDIErrBadCompressedData = -73, // data can't even be unpacked + kDIErrBadArchiveStruct = -74, // bad archive structure + + kDIErrBadNibbleSectors = -80, // can't read sectors from this image + kDIErrSectorUnreadable = -81, // requested sector not readable + kDIErrInvalidDiskByte = -82, // invalid byte for encoding type + kDIErrBadRawData = -83, // couldn't get correct nibbles + + kDIErrInvalidFileName = -90, // tried to create file with bad name + kDIErrDiskFull = -91, // no space left on disk + kDIErrVolumeDirFull = -92, // no more entries in volume dir + kDIErrInvalidCreateReq = -93, // CreateImage request was flawed + kDIErrTooBig = -94, // larger than we want to handle + + /* higher-level errors */ + kDIErrGeneric = -101, + kDIErrInternal = -102, + kDIErrMalloc = -103, + kDIErrInvalidArg = -104, + kDIErrNotSupported = -105, // feature not currently supported + kDIErrCancelled = -106, // an operation was cancelled by user + + kDIErrNufxLibInitFailed = -110, +} DIError; + +/* return a string describing the error */ +DISKIMG_API const char* DIStrError(DIError dierr); + + +/* exact definition of off_t varies, so just define our own */ +#ifdef _ULONGLONG_ + typedef LONGLONG di_off_t; +#else + typedef off_t di_off_t; +#endif + +/* common definition of "whence" for seeks */ +typedef enum DIWhence { + kSeekSet = SEEK_SET, + kSeekCur = SEEK_CUR, + kSeekEnd = SEEK_END +}; + +/* try to load ASPI under Win2K; if successful, SPTI should be disabled */ +const bool kAlwaysTryASPI = false; +/* ASPI device "filenames" look like "ASPI:x:y:z\" */ +DISKIMG_API extern const char* kASPIDev; + +/* some nibble-encoding constants */ +const int kTrackLenNib525 = 6656; +const int kTrackLenNb2525 = 6384; +const int kTrackLenTrackStar525 = 6525; // max len of data in TS image +const int kTrackAllocSize = 6656; // max 5.25 nibble track len; for buffers +const int kTrackCount525 = 35; // expected #of tracks on 5.25 img +const int kMaxNibbleTracks525 = 40; // max #of tracks on 5.25 nibble img +const int kDefaultNibbleVolumeNum = 254; +const int kBlockSize = 512; // block size for DiskImg interfaces +const int kSectorSize = 256; // sector size (1/2 block) +const int kD13Length = 256 * 13 * 35; // length of a .d13 image + +/* largest expanse we allow access to on a volume (8GB in 512-byte blocks) */ +const long kVolumeMaxBlocks = 8*1024*(1024*1024 / kBlockSize); + +/* largest .gz file we'll open (uncompressed size) */ +const long kGzipMax = 32*1024*1024; + +/* forward and external class definitions */ +class DiskFS; +class A2File; +class A2FileDescr; +class GenericFD; +class OuterWrapper; +class ImageWrapper; +class CircularBufferAccess; +class ASPI; +class LinearBitmap; + + +/* + * Library-global data functions. + * + * This class is just a namespace clumper. Do not instantiate. + */ +class DISKIMG_API Global { +public: + // one-time DLL initialization; use SetDebugMsgHandler first + static DIError AppInit(void); + // one-time DLL cleanup + static DIError AppCleanup(void); + + // return the DiskImg version number + static void GetVersion(long* pMajor, long* pMinor, long* pBug); + + static bool GetAppInitCalled(void) { return fAppInitCalled; } + static bool GetHasSPTI(void); + static bool GetHasASPI(void); + + // return a pointer to our global ASPI instance + static ASPI* GetASPI(void) { return fpASPI; } + // shortcut for fpASPI->GetVersion() + static unsigned long GetASPIVersion(void); + + // pointer to the debug message handler + typedef void (*DebugMsgHandler)(const char* file, int line, const char* msg); + static DebugMsgHandler gDebugMsgHandler; + + static DebugMsgHandler SetDebugMsgHandler(DebugMsgHandler handler); + static void PrintDebugMsg(const char* file, int line, const char* fmt, ...) + #if defined(__GNUC__) + __attribute__ ((format(printf, 3, 4))) + #endif + ; + +private: + // no instantiation allowed + Global(void) {} + ~Global(void) {} + + // make sure app calls AppInit + static bool fAppInitCalled; + + static ASPI* fpASPI; +}; + +extern bool gAllowWritePhys0; // ugh -- see Win32BlockIO.cpp + + +/* + * Disk I/O class, roughly equivalent to a GS/OS disk device driver. + * + * Abstracts away the file's source (file on disk, file in memory) and + * storage format (DOS order, ProDOS order, nibble). Will also cope + * with common disk compression and wrapper formats (Mac DiskCopy, 2MG, + * ShrinkIt, etc) if handed a file on disk. + * + * Images may be embedded within other images, e.g. UNIDOS and storage + * type $04 pascal volumes. + * + * THOUGHT: we need a list(?) of pointers from here back to the DiskFS + * so that any modifications here will "wake" the DiskFS and sub-volumes. + * We also need a "dirty" flag so things like CloseNufx can know not to + * re-do work when Closing after a Flush. Also DiskFS can alert us to + * any locally cached stuff, and we can tell them to flush everything. + * (Possibly useful when doing disk updates, so stuff can be trivially + * un-done. Currently CiderPress checks the filename manually after + * each write, but that's generally less reliable than having the knowledge + * contained in the DiskImg.) + * + * THOUGHT: need a ReadRawTrack that gets raw nibblized data. For a + * nibblized image it returns the data, for a sector image it generates + * the raw data. + * + * THOUGHT: we could reduce the risk of problems and increase performance + * for physical media with a "copy on write" scheme. We'd create a shadow + * array of modified blocks, and write them at Flush time. This would + * provide an instantaneous "revert" feature, and prevent formats like + * DiskCopy42 (which has a CRC in its header) from being inconsistent for + * long stretches. + */ +class DISKIMG_API DiskImg { +public: + // create DiskImg object + DiskImg(void); + virtual ~DiskImg(void); + + /* + * Types describing an image file. + * + * The file itself is described by an external parameter ("file source") + * that is either the name of the file, a memory buffer, or an EFD + * (EmbeddedFileDescriptor). + */ + typedef enum { // format of the "wrapper wrapper" + kOuterFormatUnknown = 0, + kOuterFormatNone = 1, // (plain) + kOuterFormatCompress = 2, // .xx.Z + kOuterFormatGzip = 3, // .xx.gz + kOuterFormatBzip2 = 4, // .xx.bz2 + kOuterFormatZip = 10, // .zip + } OuterFormat; + typedef enum { // format of the image "wrapper" + kFileFormatUnknown = 0, + kFileFormatUnadorned = 1, // .po, .do, ,nib, .raw, .d13 + kFileFormat2MG = 2, // .2mg, .2img, $e0/0130 + kFileFormatDiskCopy42 = 3, // .dsk/.disk, maybe .dc + kFileFormatDiskCopy60 = 4, // .dc6 (often just raw format) + kFileFormatDavex = 5, // $e0/8004 + kFileFormatSim2eHDV = 6, // .hdv + kFileFormatTrackStar = 7, // .app (40-track or 80-track) + kFileFormatFDI = 8, // .fdi (5.25" or 3.5") + kFileFormatNuFX = 20, // .shk, .sdk, .bxy + kFileFormatDDD = 21, // .ddd + kFileFormatDDDDeluxe = 22, // $DD, .ddd + } FileFormat; + typedef enum { // format of the image data stream + kPhysicalFormatUnknown = 0, + kPhysicalFormatSectors = 1, // sequential 256-byte sectors (13/16/32) + kPhysicalFormatNib525_6656 = 2, // 5.25" disk ".nib" (6656 bytes/track) + kPhysicalFormatNib525_6384 = 3, // 5.25" disk ".nb2" (6384 bytes/track) + kPhysicalFormatNib525_Var = 4, // 5.25" disk (variable len, e.g. ".app") + } PhysicalFormat; + typedef enum { // sector ordering for "sector" format images + kSectorOrderUnknown = 0, + kSectorOrderProDOS = 1, // written as series of ProDOS blocks + kSectorOrderDOS = 2, // written as series of DOS sectors + kSectorOrderCPM = 3, // written as series of 1K CP/M blocks + kSectorOrderPhysical = 4, // written as un-interleaved sectors + kSectorOrderMax, // (used for array sizing) + } SectorOrder; + typedef enum { // main filesystem format (based on NuFX enum) + kFormatUnknown = 0, + kFormatProDOS = 1, + kFormatDOS33 = 2, + kFormatDOS32 = 3, + kFormatPascal = 4, + kFormatMacHFS = 5, + kFormatMacMFS = 6, + kFormatLisa = 7, + kFormatCPM = 8, + //kFormatCharFST + kFormatMSDOS = 10, // any FAT filesystem + //kFormatHighSierra + kFormatISO9660 = 12, + //kFormatAppleShare + kFormatRDOS33 = 20, // 16-sector RDOS disk + kFormatRDOS32 = 21, // 13-sector RDOS disk + kFormatRDOS3 = 22, // 13-sector RDOS disk converted to 16 + // "generic" formats *must* be in their own "decade" + kFormatGenericPhysicalOrd = 30, // unknown, but physical-sector-ordered + kFormatGenericProDOSOrd = 31, // unknown, but ProDOS-block-ordered + kFormatGenericDOSOrd = 32, // unknown, but DOS-sector-ordered + kFormatGenericCPMOrd = 33, // unknown, but CP/M-block-ordered + kFormatUNIDOS = 40, // two 400K DOS 3.3 volumes + kFormatOzDOS = 41, // two 400K DOS 3.3 volumes, weird order + kFormatCFFA4 = 42, // CFFA image with 4 or 6 partitions + kFormatCFFA8 = 43, // CFFA image with 8 partitions + kFormatMacPart = 44, // Macintosh-style partitioned disk + kFormatMicroDrive = 45, // ///SHH Systeme's MicroDrive format + kFormatFocusDrive = 46, // Parsons Engineering FocusDrive format + kFormatGutenberg = 47, // Gutenberg word processor format + + // try to keep this in an unsigned char, e.g. for CP clipboard + } FSFormat; + + /* + * Nibble encode/decode description. Use no pointers here, so we + * store as an array and resize at will. + * + * Should we define an enum to describe whether address and data + * headers are standard or some wacky variant? + */ + typedef enum { + kNibbleAddrPrologLen = 3, // d5 aa 96 + kNibbleAddrEpilogLen = 3, // de aa eb + kNibbleDataPrologLen = 3, // d5 aa ad + kNibbleDataEpilogLen = 3, // de aa eb + }; + typedef enum { + kNibbleEncUnknown = 0, + kNibbleEnc44, + kNibbleEnc53, + kNibbleEnc62, + } NibbleEnc; + typedef enum { + kNibbleSpecialNone = 0, + kNibbleSpecialMuse, // doubled sector numbers on tracks > 2 + kNibbleSpecialSkipFirstAddrByte, + } NibbleSpecial; + typedef struct { + char description[32]; + short numSectors; // 13 or 16 (or 18?) + + unsigned char addrProlog[kNibbleAddrPrologLen]; + unsigned char addrEpilog[kNibbleAddrEpilogLen]; + unsigned char addrChecksumSeed; + bool addrVerifyChecksum; + bool addrVerifyTrack; + int addrEpilogVerifyCount; + + unsigned char dataProlog[kNibbleDataPrologLen]; + unsigned char dataEpilog[kNibbleDataEpilogLen]; + unsigned char dataChecksumSeed; + bool dataVerifyChecksum; + int dataEpilogVerifyCount; + + NibbleEnc encoding; + NibbleSpecial special; + } NibbleDescr; + + + static inline bool IsSectorFormat(PhysicalFormat fmt) { + return (fmt == kPhysicalFormatSectors); + } + static inline bool IsNibbleFormat(PhysicalFormat fmt) { + return (fmt == kPhysicalFormatNib525_6656 || + fmt == kPhysicalFormatNib525_6384 || + fmt == kPhysicalFormatNib525_Var); + } + + // file is on disk; stuff like 2MG headers will be identified and stripped + DIError OpenImage(const char* filename, char fssep, bool readOnly); + // file is in memory; provide a pointer to the data start and buffer size + DIError OpenImage(const void* buffer, long length, bool readOnly); + // file is a range of blocks on an open block-oriented disk image + DIError OpenImage(DiskImg* pParent, long firstBlock, long numBlocks); + // file is a range of tracks/sectors on an open sector-oriented disk image + DIError OpenImage(DiskImg* pParent, long firstTrack, long firstSector, + long numSectors); + + // create a new, blank image file + DIError CreateImage(const char* pathName, const char* storageName, + OuterFormat outerFormat, FileFormat fileFormat, + PhysicalFormat physical, const NibbleDescr* pNibbleDescr, + SectorOrder order, FSFormat format, + long numBlocks, bool skipFormat); + DIError CreateImage(const char* pathName, const char* storageName, + OuterFormat outerFormat, FileFormat fileFormat, + PhysicalFormat physical, const NibbleDescr* pNibbleDescr, + SectorOrder order, FSFormat format, + long numTracks, long numSectPerTrack, bool skipFormat); + + // flush any changes to disk; slow recompress only for "kFlushAll" + typedef enum { kFlushUnknown=0, kFlushFastOnly=1, kFlushAll=2 } FlushMode; + DIError FlushImage(FlushMode mode); + // close the image, freeing up any resources in use + DIError CloseImage(void); + // raise/lower refCnt (may want to track pointers someday) + void AddDiskFS(DiskFS* pDiskFS) { fDiskFSRefCnt++; } + void RemoveDiskFS(DiskFS* pDiskFS) { + assert(fDiskFSRefCnt > 0); + fDiskFSRefCnt--; + } + + // (re-)format this image in the specified FS format + DIError FormatImage(FSFormat format, const char* volName); + // reset all blocks/sectors to zeroes + DIError ZeroImage(void); + + // configure for paired sectors (OzDOS) + void SetPairedSectors(bool enable, int idx); + + // identify sector ordering and disk format + // (may want a version that takes "hints" for special disks?) + DIError AnalyzeImage(void); + // figure out what FS and sector ordering is on the disk image + void AnalyzeImageFS(void); + bool ShowAsBlocks(void) const; + // overrule the analyzer (generally not recommended) -- does not + // override FileFormat, which is very reliable + DIError OverrideFormat(PhysicalFormat physical, FSFormat format, + SectorOrder order); + + // Create a DiskFS that matches this DiskImg. Must be called after + // AnalayzeImage, or you will always get a DiskFSUnknown. The DiskFS + // must be freed with "delete" when no longer needed. + DiskFS* OpenAppropriateDiskFS(bool allowUnknown = false); + + // Add information or a warning to the list of notes. Use linefeeds to + // indicate line breaks. This is currently append-only. + typedef enum { kNoteInfo, kNoteWarning } NoteType; + void AddNote(NoteType type, const char* fmt, ...) + #if defined(__GNUC__) + __attribute__ ((format(printf, 3, 4))) + #endif + ; + const char* GetNotes(void) const; + + // simple accessors + OuterFormat GetOuterFormat(void) const { return fOuterFormat; } + FileFormat GetFileFormat(void) const { return fFileFormat; } + PhysicalFormat GetPhysicalFormat(void) const { return fPhysical; } + SectorOrder GetSectorOrder(void) const { return fOrder; } + FSFormat GetFSFormat(void) const { return fFormat; } + long GetNumTracks(void) const { return fNumTracks; } + int GetNumSectPerTrack(void) const { return fNumSectPerTrack; } + long GetNumBlocks(void) const { return fNumBlocks; } + bool GetReadOnly(void) const { return fReadOnly; } + bool GetDirtyFlag(void) const { return fDirty; } + + // set read-only flag; don't use this (open with correct setting; + // this was added as safety hack for the volume copier) + void SetReadOnly(bool val) { fReadOnly = val; } + + // read a 256-byte sector + // NOTE to self: this function should not be available for odd-sized + // volumes, e.g. a ProDOS /RAM or /RAM5 stored with Davex. Need some way + // to communicate that to disk editor so it knows to grey-out the + // selection checkbox and/or not use "show as sectors" as default. + virtual DIError ReadTrackSector(long track, int sector, void* buf) { + return ReadTrackSectorSwapped(track, sector, buf, fOrder, + fFileSysOrder); + } + DIError ReadTrackSectorSwapped(long track, int sector, + void* buf, SectorOrder imageOrder, SectorOrder fsOrder); + // write a 256-byte sector + virtual DIError WriteTrackSector(long track, int sector, const void* buf); + + // read a 512-byte block + virtual DIError ReadBlock(long block, void* buf) { + return ReadBlockSwapped(block, buf, fOrder, fFileSysOrder); + } + DIError ReadBlockSwapped(long block, void* buf, SectorOrder imageOrder, + SectorOrder fsOrder); + // read multiple blocks + virtual DIError ReadBlocks(long startBlock, int numBlocks, void* buf); + // check our virtual bad block map + bool CheckForBadBlocks(long startBlock, int numBlocks); + // write a 512-byte block + virtual DIError WriteBlock(long block, const void* buf); + // write multiple blocks + virtual DIError WriteBlocks(long startBlock, int numBlocks, const void* buf); + + // read an entire nibblized track + virtual DIError ReadNibbleTrack(long track, unsigned char* buf, + long* pTrackLen); + // write a track; trackLen must be <= those in image + virtual DIError WriteNibbleTrack(long track, const unsigned char* buf, + long trackLen); + + // save the current image as a 2MG file + //DIError Write2MG(const char* filename); + + // need to treat the DOS volume number as meta-data for some disks + short GetDOSVolumeNum(void) const { return fDOSVolumeNum; } + void SetDOSVolumeNum(short val) { fDOSVolumeNum = val; } + enum { kVolumeNumNotSet = -1 }; + + // some simple getters + bool GetHasSectors(void) const { return fHasSectors; } + bool GetHasBlocks(void) const { return fHasBlocks; } + bool GetHasNibbles(void) const { return fHasNibbles; } + bool GetIsEmbedded(void) const { return fpParentImg != NULL; } + + // return the current NibbleDescr + const NibbleDescr* GetNibbleDescr(void) const { return fpNibbleDescr; } + // set the NibbleDescr; we do this by copying the entry into our table + // (could improve by doing memcmp on available entries?) + void SetNibbleDescr(int idx); + void SetCustomNibbleDescr(const NibbleDescr* pDescr); + const NibbleDescr* GetNibbleDescrTable(int* pCount) const { + *pCount = fNumNibbleDescrEntries; + return fpNibbleDescrTable; + } + + // set the NuFX compression type, used when compressing or re-compressing; + // must be set before image is opened or created + void SetNuFXCompressionType(int val) { fNuFXCompressType = val; } + + /* + * Set up a progress callback to use when scanning a disk volume. Pass + * nil for "func" to disable. + * + * The callback function is expected to return "true" if all is well. + * If it returns false, kDIErrCancelled will eventually come back. + */ + typedef bool (*ScanProgressCallback)(void* cookie, const char* str, + int count); + void SetScanProgressCallback(ScanProgressCallback func, void* cookie); + /* update status dialog during disk scan; called from DiskFS code */ + bool UpdateScanProgress(const char* newStr); + + /* + * Static utility functions. + */ + // returns "true" if the files on this image have DOS structure, i.e. + // simple file types and high-ASCII text files + static bool UsesDOSFileStructure(FSFormat format) { + return (format == kFormatDOS33 || + format == kFormatDOS32 || + format == kFormatGutenberg || + format == kFormatUNIDOS || + format == kFormatOzDOS || + format == kFormatRDOS33 || + format == kFormatRDOS32 || + format == kFormatRDOS3); + } + // returns "true" if we can open files on the specified filesystem + static bool CanOpenFiles(FSFormat format) { + return (format == kFormatProDOS || + format == kFormatDOS33 || + format == kFormatDOS32 || + format == kFormatPascal || + format == kFormatCPM || + format == kFormatRDOS33 || + format == kFormatRDOS32 || + format == kFormatRDOS3); + } + // returns "true" if we can create subdirectories on this filesystem + static bool IsHierarchical(FSFormat format) { + return (format == kFormatProDOS || + format == kFormatMacHFS || + format == kFormatMSDOS); + } + // returns "true" if we can create resource forks on this filesystem + static bool HasResourceForks(FSFormat format) { + return (format == kFormatProDOS || + format == kFormatMacHFS); + } + // returns "true" if the format is one of the "generics" + static bool IsGenericFormat(FSFormat format) { + return (format / 10 == DiskImg::kFormatGenericDOSOrd / 10); + } + + /* this must match DiskImg::kStdNibbleDescrs table */ + typedef enum StdNibbleDescr { + kNibbleDescrDOS33Std = 0, + kNibbleDescrDOS33Patched, + kNibbleDescrDOS33IgnoreChecksum, + kNibbleDescrDOS32Std, + kNibbleDescrDOS32Patched, + kNibbleDescrMuse32, + kNibbleDescrRDOS33, + kNibbleDescrRDOS32, + kNibbleDescrCustom, // slot for custom entry + + kNibbleDescrMAX // must be last + }; + static const NibbleDescr* GetStdNibbleDescr(StdNibbleDescr idx); + // call this once, at DLL initialization time + static void CalcNibbleInvTables(void); + // calculate block number from cyl/head/sect on 3.5" disk + static int CylHeadSect35ToBlock(int cyl, int head, int sect); + // unpack nibble data from a 3.5" disk track + static DIError UnpackNibbleTrack35(const unsigned char* nibbleBuf, + long nibbleLen, unsigned char* outputBuf, int cyl, int head, + LinearBitmap* pBadBlockMap); + // compute the #of sectors per track for cylinder N (0-79) + static int SectorsPerTrack35(int cylinder); + + // get the order in which we test for sector ordering + static void GetSectorOrderArray(SectorOrder* orderArray, SectorOrder first); + + // utility function used by HFS filename normalizer; available to apps + static inline unsigned char MacToASCII(unsigned char uch) { + if (uch < 0x20) + return '?'; + else if (uch < 0x80) + return uch; + else + return kMacHighASCII[uch - 0x80]; + } + + // Allow write access to physical disk 0. This is usually the boot disk, + // but with some BIOS the first IDE drive is always physical 0 even if + // you're booting from SATA. This only has meaning under Win32. + static void SetAllowWritePhys0(bool val); + + /* + * Get string constants for enumerated values. + */ + typedef struct { int format; const char* str; } ToStringLookup; + static const char* ToStringCommon(int format, const ToStringLookup* pTable, + int tableSize); + static const char* ToString(OuterFormat format); + static const char* ToString(FileFormat format); + static const char* ToString(PhysicalFormat format); + static const char* ToString(SectorOrder format); + static const char* ToString(FSFormat format); + +private: + /* + * Fundamental disk image identification. + */ + OuterFormat fOuterFormat; // e.g. gzip + FileFormat fFileFormat; + PhysicalFormat fPhysical; + const NibbleDescr* fpNibbleDescr; // only used for "nibble" images + SectorOrder fOrder; // only used for "sector" images + FSFormat fFormat; + + /* + * This affects how the DiskImg responds to requests for reading + * a track or sector. + * + * "fFileSysOrder", together with with "fOrder", determines how + * sector numbers are translated. It describes the order that the + * DiskFS filesystem expects things to be in. If the image isn't + * sector-addressable, then it is assumed to be in linear block order. + * + * If "fSectorPairing" is set, the DiskImg treats the disk as if + * it were in OzDOS format, with one sector from two different + * volumes in a single 512-byte block. + */ + SectorOrder fFileSysOrder; + bool fSectorPairing; + int fSectorPairOffset; // which image (should be 0 or 1) + + /* + * Internal state. + */ + GenericFD* fpOuterGFD; // outer wrapper, if any (.gz only) + GenericFD* fpWrapperGFD; // Apple II image file + GenericFD* fpDataGFD; // raw Apple II data + OuterWrapper* fpOuterWrapper; // needed for outer .gz wrapper + ImageWrapper* fpImageWrapper; // disk image wrapper (2MG, SHK, etc) + DiskImg* fpParentImg; // set for embedded volumes + short fDOSVolumeNum; // specified by some wrapper formats + di_off_t fOuterLength; // total len of file + di_off_t fWrappedLength; // len of file after Outer wrapper removed + di_off_t fLength; // len of disk image (w/o wrappers) + bool fExpandable; // ProDOS .hdv can expand + bool fReadOnly; // allow writes to this image? + bool fDirty; // have we modified this image? + //bool fIsEmbedded; // is this image embedded in another? + + bool fHasSectors; // image is sector-addressable + bool fHasBlocks; // image is block-addressable + bool fHasNibbles; // image is nibble-addressable + + long fNumTracks; // for sector-addressable images + int fNumSectPerTrack; // (ditto) + long fNumBlocks; // for 512-byte block-addressable images + + unsigned char* fNibbleTrackBuf; // allocated on heap + int fNibbleTrackLoaded; // track currently in buffer + + int fNuFXCompressType; // used when compressing a NuFX image + + char* fNotes; // warnings and FYIs about DiskImg/DiskFS + + LinearBitmap* fpBadBlockMap; // used for 3.5" nibble images + + int fDiskFSRefCnt; // #of DiskFS objects pointing at us + + /* + * NibbleDescr entries. There are several standard ones, and we want + * to allow applications to define additional ones. + */ + NibbleDescr* fpNibbleDescrTable; + int fNumNibbleDescrEntries; + + /* static table of default values */ + static const NibbleDescr kStdNibbleDescrs[]; + + DIError CreateImageCommon(const char* pathName, const char* storageName, + bool skipFormat); + DIError ValidateCreateFormat(void) const; + DIError FormatSectors(GenericFD* pGFD, bool quickFormat) const; + //DIError FormatBlocks(GenericFD* pGFD) const; + + DIError CopyBytesOut(void* buf, di_off_t offset, int size) const; + DIError CopyBytesIn(const void* buf, di_off_t offset, int size); + DIError AnalyzeImageFile(const char* pathName, char fssep); + // Figure out the sector ordering for this filesystem, so we can decide + // how the sectors need to be re-arranged when we're reading them. + SectorOrder CalcFSSectorOrder(void) const; + // Handle sector order calculations. + DIError CalcSectorAndOffset(long track, int sector, SectorOrder ImageOrder, + SectorOrder fsOrder, di_off_t* pOffset, int* pNewSector); + inline bool IsLinearBlocks(SectorOrder imageOrder, SectorOrder fsOrder); + + /* + * Progress update during the filesystem scan. This only exists in the + * topmost DiskImg. (This is arguably more appropriate in DiskFS, but + * DiskFS objects don't have a notion of "parent" and are somewhat more + * ephemeral.) + */ + ScanProgressCallback fpScanProgressCallback; + void* fScanProgressCookie; + int fScanCount; + char fScanMsg[128]; + time_t fScanLastMsgWhen; + + /* + * 5.25" nibble image access. + */ + enum { + kDataSize62 = 343, // 342 bytes + checksum byte + kChunkSize62 = 86, // (0x56) + + kDataSize53 = 411, // 410 bytes + checksum byte + kChunkSize53 = 51, // (0x33) + kThreeSize = (kChunkSize53 * 3) + 1, // same as 410 - 256 + }; + DIError ReadNibbleSector(long track, int sector, void* buf, + const NibbleDescr* pNibbleDescr); + DIError WriteNibbleSector(long track, int sector, const void* buf, + const NibbleDescr* pNibbleDescr); + void DumpNibbleDescr(const NibbleDescr* pNibDescr) const; + int GetNibbleTrackLength(long track) const; + int GetNibbleTrackOffset(long track) const; + int GetNibbleTrackFormatLength(void) const { + /* return length to use when formatting for 16 sectors */ + if (fPhysical == kPhysicalFormatNib525_6656) + return kTrackLenNib525; + else if (fPhysical == kPhysicalFormatNib525_6384) + return kTrackLenNb2525; + else if (fPhysical == kPhysicalFormatNib525_Var) { + if (fFileFormat == kFileFormatTrackStar || + fFileFormat == kFileFormatFDI) + { + return kTrackLenNb2525; // use minimum possible + } + } + assert(false); + return -1; + } + int GetNibbleTrackAllocLength(void) const { + /* return length to allocate when creating an image */ + if (fPhysical == kPhysicalFormatNib525_Var && + (fFileFormat == kFileFormatTrackStar || + fFileFormat == kFileFormatFDI)) + { + // use maximum possible + return kTrackLenTrackStar525; + } + return GetNibbleTrackFormatLength(); + } + DIError LoadNibbleTrack(long track, long* pTrackLen); + DIError SaveNibbleTrack(void); + int FindNibbleSectorStart(const CircularBufferAccess& buffer, + int track, int sector, const NibbleDescr* pNibbleDescr, int* pVol); + void DecodeAddr(const CircularBufferAccess& buffer, int offset, + short* pVol, short* pTrack, short* pSector, short* pChksum); + inline unsigned int ConvFrom44(unsigned char val1, unsigned char val2) { + return ((val1 << 1) | 0x01) & val2; + } + DIError DecodeNibbleData(const CircularBufferAccess& buffer, int idx, + unsigned char* sctBuf, const NibbleDescr* pNibbleDescr); + void EncodeNibbleData(const CircularBufferAccess& buffer, int idx, + const unsigned char* sctBuf, const NibbleDescr* pNibbleDescr) const; + DIError DecodeNibble62(const CircularBufferAccess& buffer, int idx, + unsigned char* sctBuf, const NibbleDescr* pNibbleDescr); + void EncodeNibble62(const CircularBufferAccess& buffer, int idx, + const unsigned char* sctBuf, const NibbleDescr* pNibbleDescr) const; + DIError DecodeNibble53(const CircularBufferAccess& buffer, int idx, + unsigned char* sctBuf, const NibbleDescr* pNibbleDescr); + void EncodeNibble53(const CircularBufferAccess& buffer, int idx, + const unsigned char* sctBuf, const NibbleDescr* pNibbleDescr) const; + int TestNibbleTrack(int track, const NibbleDescr* pNibbleDescr, int* pVol); + DIError AnalyzeNibbleData(void); + inline unsigned char Conv44(unsigned short val, bool first) const { + if (first) + return (val >> 1) | 0xaa; + else + return val | 0xaa; + } + DIError FormatNibbles(GenericFD* pGFD) const; + + static const unsigned char kMacHighASCII[]; + + /* + * 3.5" nibble access + */ + static int FindNextSector35(const CircularBufferAccess& buffer, int start, + int cyl, int head, int* pSector); + static bool DecodeNibbleSector35(const CircularBufferAccess& buffer, + int start, unsigned char* sectorBuf, unsigned char* readChecksum, + unsigned char* calcChecksum); + static bool UnpackChecksum35(const CircularBufferAccess& buffer, + int offset, unsigned char* checksumBuf); + static void EncodeNibbleSector35(const unsigned char* sectorData, + unsigned char* outBuf); + + /* static data tables */ + static unsigned char kDiskBytes53[32]; + static unsigned char kDiskBytes62[64]; + static unsigned char kInvDiskBytes53[256]; + static unsigned char kInvDiskBytes62[256]; + enum { kInvInvalidValue = 0xff }; + +private: // some C++ stuff to block behavior we don't support + DiskImg& operator=(const DiskImg&); + DiskImg(const DiskImg&); +}; + + + +/* + * Disk filesystem class, roughly equivalent to a GS/OS FST. This is an + * abstract base class. + * + * Static functions know how to access a DiskImg and figure out what kind + * of image we have. Once known, the appropriate sub-class can be + * instantiated. + * + * We maintain a linear list of files to make it easy for applications to + * traverse the full set of files. Sometimes this makes it hard for us to + * update internally (especially HFS). With some minor cleverness it + * should be possible to switch to a tree structure while retaining the + * linear "get next" API. This would be a big help for ProDOS and HFS. + * + * NEED: some notification mechanism for changes to files and/or block + * editing of the disk (especially with regard to open sub-volumes). If + * a disk volume open for file-by-file viewing is modified with the disk + * editor, we should close the file when the disk editor exits. + * + * NEED? disk utilities, such as "disk crunch", for Pascal volumes. Could + * be written externally, but might as well keep fs knowledge embedded. + * + * MISSING: there is no way to override the image analyzer when working + * with sub-volumes. Actually, there is; it just has to happen *after* + * the DiskFS has been created. We should provide an approach that either + * stifles the DiskFS creation, or allows us to override and replace the + * internal DiskFS so we can pop up a sub-volume list, show what we *think* + * is there, and then let the user pick a volume and pick overrides (mainly + * for use in the disk editor). Not sure if we want the changes to "stick"; + * we probably do. Q: does the "scan for sub-volumes" attribute propagate + * recursively to each sub-sub-volume? Probably. + * + * NOTE to self: should make "test" functions more lax when called + * from here, on the assumption that the caller is knowledgeable. Perhaps + * an independent "strictness" variable that can be cranked down through + * multiple calls to AnalyzeImage?? + */ +class DISKIMG_API DiskFS { +public: + /* + * Information about volume usage. + * + * Each "chunk" is a track/sector on a DOS disk or a block on a ProDOS + * or Pascal disk. CP/M really ought to use 1K blocks, but for + * convenience we're just using 512-byte blocks (it's up to the CP/M + * code to set two "chunks" per block). + * + * NOTE: the current DOS/ProDOS/Pascal code is sloppy when it comes to + * keeping this structure up to date. HFS doesn't use it at all. This + * has always been a low-priority feature. + */ + class DISKIMG_API VolumeUsage { + public: + VolumeUsage(void) { + fByBlocks = false; + fTotalChunks = -1; + fNumSectors = -1; + //fFreeChunks = -1; + fList = NULL; + fListSize = -1; + } + ~VolumeUsage(void) { + delete[] fList; + } + + /* + * These values MUST fit in five bits. + * + * Suggested disk map colors: + * 0 = unknown (color-key pink) + * 1 = conflict (medium-red) + * 2 = boot loader (dark-blue) + * 3 = volume dir (light-blue) + * 4 = subdir (medium-blue) + * 5 = user data (medium-green) + * 6 = user index blocks (light-green) + * 7 = embedded filesys (yellow) + * + * THOUGHT: Add flag for I/O error (nibble images) -- requires + * automatic disk verify pass. (Or maybe could be done manually + * on request?) + * + * unused --> black + * marked-used-but-not-used --> dark-red + * used-but-not-marked-used --> orange + */ + typedef enum { + kChunkPurposeUnknown = 0, + kChunkPurposeConflict = 1, // two or more different things + kChunkPurposeSystem = 2, // boot blocks, volume bitmap + kChunkPurposeVolumeDir = 3, // volume dir (or only dir) + kChunkPurposeSubdir = 4, // ProDOS sub-directory + kChunkPurposeUserData = 5, // file on this filesystem + kChunkPurposeFileStruct = 6, // index blocks, T/S lists + kChunkPurposeEmbedded = 7, // embedded filesystem + // how about: outside range claimed by disk, e.g. fTotalBlocks on + // 800K ProDOS disk in a 32MB CFFA volume? + } ChunkPurpose; + + typedef struct ChunkState { + bool isUsed; + bool isMarkedUsed; + ChunkPurpose purpose; // only valid if isUsed is set + } ChunkState; + + // initialize, configuring for either blocks or sectors + DIError Create(long numBlocks); + DIError Create(long numTracks, long numSectors); + bool GetInitialized(void) const { return (fList != NULL); } + + // return the number of chunks on this disk + long GetNumChunks(void) const { return fTotalChunks; } + + // return the number of unallocated chunks, taking into account + // both the free-chunk bitmap (if any) and the actual usage + long GetActualFreeChunks(void) const; + + // return the state of the specified chunk + DIError GetChunkState(long block, ChunkState* pState) const; + DIError GetChunkState(long track, long sector, + ChunkState* pState) const; + + // set the state of a particular chunk (should only be done by + // the DiskFS sub-classes) + DIError SetChunkState(long block, const ChunkState* pState); + DIError SetChunkState(long track, long sector, + const ChunkState* pState); + + void Dump(void) const; // debugging + + private: + DIError GetChunkStateIdx(int idx, ChunkState* pState) const; + DIError SetChunkStateIdx(int idx, const ChunkState* pState); + inline char StateToChar(ChunkState* pState) const; + + /* + * Chunk state is stored as a set of bits in one byte: + * + * 0-4: how is block used (only has meaning if bit 6 is set) + * 5: for nibble images, indicates the block or sector is unreadable + * 6: is block used by something (0=no, 1=yes) + * 7: is block marked "in use" by system map (0=no, 1=yes) + * + * [ Consider reducing "purpose" to 0-3 and adding bad block bit for + * nibble images and physical media.] + */ + enum { + kChunkPurposeMask = 0x1f, // ChunkPurpose enum + kChunkDamagedFlag = 0x20, + kChunkUsedFlag = 0x40, + kChunkMarkedUsedFlag = 0x80, + }; + + bool fByBlocks; + long fTotalChunks; + long fNumSectors; // only valid if !fByBlocks + //long fFreeChunks; + unsigned char* fList; + int fListSize; + }; // end of VolumeUsage class + + /* + * List of sub-volumes. The SubVolume owns the DiskImg and DiskFS + * that are handed to it, so they can be deleted when the SubVolume + * is deleted as part of destroying the parent. + */ + class SubVolume { + public: + SubVolume(void) : fpDiskImg(NULL), fpDiskFS(NULL), + fpPrev(NULL), fpNext(NULL) {} + ~SubVolume(void) { + delete fpDiskFS; // must close first; may need flush to DiskImg + delete fpDiskImg; + } + + void Create(DiskImg* pDiskImg, DiskFS* pDiskFS) { + assert(pDiskImg != NULL); + assert(pDiskFS != NULL); + fpDiskImg = pDiskImg; + fpDiskFS = pDiskFS; + } + + DiskImg* GetDiskImg(void) const { return fpDiskImg; } + DiskFS* GetDiskFS(void) const { return fpDiskFS; } + + SubVolume* GetPrev(void) const { return fpPrev; } + void SetPrev(SubVolume* pSubVol) { fpPrev = pSubVol; } + SubVolume* GetNext(void) const { return fpNext; } + void SetNext(SubVolume* pSubVol) { fpNext = pSubVol; } + + private: + DiskImg* fpDiskImg; + DiskFS* fpDiskFS; + + SubVolume* fpPrev; + SubVolume* fpNext; + }; // end of SubVolume class + + + + /* + * Start of DiskFS declarations. + */ +public: + typedef enum SubScanMode { + kScanSubUnknown = 0, + kScanSubDisabled, + kScanSubEnabled, + kScanSubContainerOnly, + } SubScanMode; + + + DiskFS(void) { + fpA2Head = fpA2Tail = NULL; + fpSubVolumeHead = fpSubVolumeTail = NULL; + fpImg = NULL; + fScanForSubVolumes = kScanSubDisabled; + + fParmTable[kParm_CreateUnique] = 0; + fParmTable[kParmProDOS_AllowLowerCase] = 1; + fParmTable[kParmProDOS_AllocSparse] = 1; + } + virtual ~DiskFS(void) { + DeleteSubVolumeList(); + DeleteFileList(); + SetDiskImg(NULL); + } + + /* + * Static FSFormat-analysis functions, called by the DiskImg AnalyzeImage + * function. Capable of determining with a high degree of accuracy + * what format the disk is in, yet remaining flexible enough to + * function correctly with variations (like DOS3.3 disks with + * truncated TOCs and ProDOS images from hard drives). + * + * The "pOrder" and "pFormat" arguments are in/out. Set them to the + * appropriate "unknown" enum value on entry. If something is known + * of the order or format, put that in instead; in some cases this will + * bias the proceedings, which is useful for efficiency and for making + * overrides work correctly. + * + * On success, these return kDIErrNone and set "*pOrder". On failure, + * they return nonzero and leave "*pOrder" unmodified. + * + * Each DiskFS sub-class should declare a TestFS function. It's not + * virtual void here because, since it's called before the DiskFS is + * created, it must be static. + */ + typedef enum FSLeniency { kLeniencyNot, kLeniencyVery } FSLeniency; + //static DIError TestFS(const DiskImg* pImg, DiskImg::SectorOrder* pOrder, + // DiskImg::FSFormat* pFormat, FSLeniency leniency); + + /* + * Load the disk contents and (if enabled) scan for sub-volumes. + * + * If "headerOnly" is set, we just do a quick scan of the volume header + * to get basic information. The deep file scan is skipped (but can + * be done later). (Sub-classes can choose to ignore the flag and + * always do the full scan; this is an optimization.) Guaranteed to + * set the volume name and volume block/sector count. + * + * If a progress callback is set up, this can return with a "cancelled" + * result, which should not be treated as a failure. + */ + typedef enum { kInitUnknown = 0, kInitHeaderOnly, kInitFull } InitMode; + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) = 0; + + /* + * Format the disk with the appropriate filesystem, creating all filesystem + * structures and (when appropriate) boot blocks. + */ + virtual DIError Format(DiskImg* pDiskImg, const char* volName) + { return kDIErrNotSupported; } + + /* + * Pass in a full path to normalize, and a buffer to copy the output + * into. On entry "pNormalizedBufLen" holds the length of the buffer. + * On exit, it holds the size of the buffer required to hold the + * normalized string. If the buffer is nil or isn't big enough, no part + * of the normalized path will be copied into the buffer, and a specific + * error (kDIErrDataOverrun) will be returned. + */ + virtual DIError NormalizePath(const char* path, char fssep, + char* normalizedBuf, int* pNormalizedBufLen) + { return kDIErrNotSupported; } + + + /* + * Create a file. The CreateParms struct specifies the full set of file + * details. To remain FS-agnostic, use the NufxLib constants + * (kNuStorageDirectory, kNuAccessUnlocked, etc). They match up with + * their ProDOS equivalents, and I promise to make them work right. + * + * On success, the file exists as a fully-formed, zero-length file. A + * pointer to the relevant A2File structure is returned. + */ + enum { + /* valid values for CreateParms; must match ProDOS enum */ + kStorageSeedling = 1, + kStorageExtended = 5, + kStorageDirectory = 13, + }; + typedef struct CreateParms { + const char* pathName; // full pathname + char fssep; + int storageType; // determines normal, subdir, or forked + long fileType; + long auxType; + int access; + time_t createWhen; + time_t modWhen; + } CreateParms; + virtual DIError CreateFile(const CreateParms* pParms, A2File** ppNewFile) + { return kDIErrNotSupported; } + + /* + * Delete a file from the disk. + */ + virtual DIError DeleteFile(A2File* pFile) + { return kDIErrNotSupported; } + + /* + * Rename a file. + */ + virtual DIError RenameFile(A2File* pFile, const char* newName) + { return kDIErrNotSupported; } + + /* + * Alter file attributes. + */ + virtual DIError SetFileInfo(A2File* pFile, long fileType, long auxType, + long accessFlags) + { return kDIErrNotSupported; } + + /* + * Rename a volume. Also works for changing the disk volume number. + */ + virtual DIError RenameVolume(const char* newName) + { return kDIErrNotSupported; } + + + // Accessor + DiskImg* GetDiskImg(void) const { return fpImg; } + + // Test file and volume names (and volume numbers) + // [these need to be static functions for some things... hmm] + //virtual bool IsValidFileName(const char* name) const { return false; } + //virtual bool IsValidVolumeName(const char* name) const { return false; } + + // Return the disk volume name, or NULL if there isn't one. + virtual const char* GetVolumeName(void) const = 0; + + // Return a printable string identifying the FS type and volume + virtual const char* GetVolumeID(void) const = 0; + + // Return the "bare" volume name. For formats where the volume name + // is actually a number (e.g. DOS 3.3), this returns just the number. + // For formats without a volume name or number (e.g. CP/M), this returns + // nil, indicating that any attempt to change the volume name will fail. + virtual const char* GetBareVolumeName(void) const = 0; + + // Returns "false" if we only support read-only access to this FS type + virtual bool GetReadWriteSupported(void) const = 0; + + // Returns "true" if the filesystem shows evidence of damage. + virtual bool GetFSDamaged(void) const = 0; + + // Returns number of blocks recognized by the filesystem, or -1 if the + // FS isn't block-oriented (e.g. DOS 3.2/3.3) + virtual long GetFSNumBlocks(void) const { return -1; } + + // Get the next file in the list. Start by passing in NULL to get the + // head of the list. Returns NULL when the end of the list is reached. + A2File* GetNextFile(A2File* pCurrent) const; + + // Get a count of the files and directories on this disk. + long GetFileCount(void) const; + + /* + * Find a file by case-insensitive pathname. Assumes fssep=':'. The + * compare function can be overridden for systems like HFS, where "case + * insensitive" has a different meaning because of the native + * character set. + * + * The A2File* returned should not be deleted. + */ + typedef int (*StringCompareFunc)(const char* str1, const char* str2); + A2File* GetFileByName(const char* pathName, StringCompareFunc func = NULL); + + // This controls scanning for sub-volumes; must be set before Initialize(). + SubScanMode GetScanForSubVolumes(void) const { return fScanForSubVolumes; } + void SetScanForSubVolumes(SubScanMode val) { fScanForSubVolumes = val; } + + // some constants for non-ProDOS filesystems to use + enum { kFileAccessLocked = 0x01, kFileAccessUnlocked = 0xc3 }; + + + /* + * We use this as a filename separator character (i.e. between pathname + * components) in all filenames. It's useful to standardize on this + * so that behavior is consistent across all disk and archive formats. + * + * The choice of ':' is good because it's invalid in filenames on + * Windows, Mac OS, GS/OS, and pretty much anywhere else we could be + * running except for UNIX. It's valid under DOS 3.3, but since you + * can't have subdirectories under DOS there's no risk of confusion. + */ + enum { kDIFssep = ':' }; + + + /* + * Return the volume use map. This is a non-const function because + * it might need to do a "just-in-time" usage map update. It returns + * const to keep non-DiskFS classes from altering the map. + */ + const VolumeUsage* GetVolumeUsageMap(void) { + if (fVolumeUsage.GetInitialized()) + return &fVolumeUsage; + else + return NULL; + } + + /* + * Return the total space and free space, in either blocks or sectors + * as appropriate. "*pUnitSize" will be kBlockSize or kSectorSize. + */ + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const = 0; + + + /* + * Get the next volume in the list. Start by passing in NULL to get the + * head of the list. Returns NULL when the end of the list is reached. + */ + SubVolume* GetNextSubVolume(const SubVolume* pCurrent) const; + + /* + * Set some parameters to tell the DiskFS how to operate. Some of + * these are FS-specific, some may be general. + * + * Parameters are set in the current object and all sub-volume objects. + * + * The enum is part of the interface and must be rigidly defined, but + * it is also used to size an array so it can't be too sparse. + */ + typedef enum DiskFSParameter { + kParmUnknown = 0, + + kParm_CreateUnique = 1, // make new filenames unique + + kParmProDOS_AllowLowerCase = 10, // allow lower case and spaces + kParmProDOS_AllocSparse = 11, // don't store empty blocks + + kParmMax // must be last entry + } DiskFSParameter; + long GetParameter(DiskFSParameter parm); + void SetParameter(DiskFSParameter parm, long val); + + /* + * Flush changed data. + * + * The individual filesystems shouldn't generally do any caching; if + * they do, we would want a virtual "FlushFS()" that gets called by + * Flush. The better answer is to cache in DiskImg, which works for + * everything, and knows if the underlying storage is already in RAM. + * + * For the most part this just needs to recursively flush the DiskImg + * objects in all of the sub-volumes and then the current volume. This + * is a no-op in most cases, but if the archive is compressed this will + * cause a new, compressed archive to be created. + * + * The "mode" value determines whether or not we do "heavy" flushes. It's + * very handy to be able to do "slow" flushes for anything that is being + * written directly to disk (as opposed to being run through Deflate), + * so that the UI doesn't indicate that they're partially written when + * in fact they're fully written. + */ + DIError Flush(DiskImg::FlushMode mode); + + /* + * Set the read-only flag on our DiskImg and those of our subvolumes. + * Used to ensure that a DiskFS with un-flushed data can be deleted + * without corrupting the volume. + */ + void SetAllReadOnly(bool val); + + // debug dump + void DumpFileList(void); + +protected: + /* + * Set the DiskImg pointer. Updates the reference count in DiskImg. + */ + void SetDiskImg(DiskImg* pImg); + + // once added, we own the pDiskImg and the pDiskFS (DO NOT pass the + // same DiskImg or DiskFS in more than once!). Note this copies the + // fParmTable and other stuff (fScanForSubVolumes) from parent to child. + void AddSubVolumeToList(DiskImg* pDiskImg, DiskFS* pDiskFS); + // add files to fpA2Head/fpA2Tail + void AddFileToList(A2File* pFile); + // only need for hierarchical filesystems; insert file after pPrev + void InsertFileInList(A2File* pFile, A2File* pPrev); + // delete an entry + void DeleteFileFromList(A2File* pFile); + + // scan for damaged or suspicious files + void ScanForDamagedFiles(bool* pDamaged, bool* pSuspicious); + + // pointer to the DiskImg structure underlying this filesystem + DiskImg* fpImg; + + VolumeUsage fVolumeUsage; + SubScanMode fScanForSubVolumes; + + +private: + A2File* SkipSubdir(A2File* pSubdir); + void CopyInheritables(DiskFS* pNewFS); + void DeleteFileList(void); + void DeleteSubVolumeList(void); + + long fParmTable[kParmMax]; // for DiskFSParameter + + A2File* fpA2Head; + A2File* fpA2Tail; + SubVolume* fpSubVolumeHead; + SubVolume* fpSubVolumeTail; + +private: + DiskFS& operator=(const DiskFS&); + DiskFS(const DiskFS&); +}; + + +/* + * Apple II file class, representing a file on an Apple II volume. This is an + * abstract base class. + * + * There is a different sub-class for each filesystem type. The A2File object + * encapsulates all of the knowledge required to read a file from a disk + * image. + * + * The prev/next pointers, used to maintain a linked list of files, are only + * accessible from DiskFS functions. At some point we may want to rearrange + * the way this is handled, e.g. by not maintaining a list at all, so it's + * important that everything go through DiskFS requests. + * + * The FSFormat is made an explicit member, because sub-classes may not + * understand exactly where the file came from (e.g. was it DOS3.2 or + * DOS 3.3). Somebody might care. + * + * + * NOTE TO SELF: open files need to be generalized. Right now the internal + * implementations only allow a single open, which is okay for our purposes + * but bad for a general FS implementation. As it stands, you can't even + * open both forks at the same time on ProDOS/HFS. + * + * UMMM: The handling of "damaged" files could be more consistent. + */ +class DISKIMG_API A2File { +public: + friend class DiskFS; + + A2File(DiskFS* pDiskFS) : fpDiskFS(pDiskFS) { + fpPrev = fpNext = NULL; + fFileQuality = kQualityGood; + } + virtual ~A2File(void) {} + + /* + * All Apple II files have certain characteristics, of which ProDOS + * is roughly a superset. (Yes, you can have HFS on a IIgs, but + * all that fancy creator type stuff is decidedly Mac-centric. Still, + * we want to assume 4-byte file and aux types.) + * + * NEED: something distinguishing between files and disk images? + * + * NOTE: there is no guarantee that GetPathName will return unique values + * (duplicates are possible). We don't guarantee that you won't get an + * empty string back (it's valid to have an empty filename in the dir in + * DOS 3.3, and it's possible for other filesystems to be damaged). The + * pathname may receive some minor sanitizing, e.g. removal or conversion + * of high ASCII and control characters, but some filesystems (like HFS) + * make use of them. + * + * We do guarantee that the contents of subdirectories are grouped + * together. This makes it much easier to construct a hierarchy out of + * the linear list. This becomes important when dynamically adding + * files to a disk. + */ + virtual const char* GetFileName(void) const = 0; // name of this file + virtual const char* GetPathName(void) const = 0; // full path + virtual char GetFssep(void) const = 0; // '\0' if none + virtual long GetFileType(void) const = 0; + virtual long GetAuxType(void) const = 0; + virtual long GetAccess(void) const = 0; // ProDOS-style perms + virtual time_t GetCreateWhen(void) const = 0; + virtual time_t GetModWhen(void) const = 0; + virtual di_off_t GetDataLength(void) const = 0; // len of data fork + virtual di_off_t GetDataSparseLength(void) const = 0; // len w/o sparse areas + virtual di_off_t GetRsrcLength(void) const = 0; // len or -1 if no rsrc + virtual di_off_t GetRsrcSparseLength(void) const = 0; // len or -1 if no rsrc + virtual DiskImg::FSFormat GetFSFormat(void) const { + return fpDiskFS->GetDiskImg()->GetFSFormat(); + } + virtual bool IsDirectory(void) const { return false; } + virtual bool IsVolumeDirectory(void) const { return false; } + + /* + * Open a file. Treat the A2FileDescr like an fd. + */ + virtual DIError Open(A2FileDescr** ppOpenFile, bool readOnly, + bool rsrcFork = false) = 0; + + /* + * This is called by the A2FileDescr object when somebody invokes Close(). + * The A2File object should remove the A2FileDescr from its list of open + * files and delete the storage. The implementation must not call the + * A2FileDescr's Close function, since that would cause a recursive loop. + * + * This should not be called by an application. + */ + virtual void CloseDescr(A2FileDescr* pOpenFile) = 0; + + /* + * This is only useful for hierarchical filesystems like ProDOS, + * where the order of items in the linear list is significant. It + * allows an unambiguous determination of which subdir a file resides + * in, even if somebody has sector-edited the filesystem so that two + * subdirs have the same name. (It's also a bit speedier to compare + * than pathname substrings would be.) + */ + virtual A2File* GetParent(void) const { return NULL; } + + /* + * Returns "true" if either fork of the file is open, "false" if not. + */ + virtual bool IsFileOpen(void) const = 0; + + virtual void Dump(void) const = 0; // debugging + + typedef enum FileQuality { + kQualityUnknown = 0, + kQualityGood, + kQualitySuspicious, + kQualityDamaged, + } FileQuality; + virtual FileQuality GetQuality(void) const { return fFileQuality; } + virtual void SetQuality(FileQuality quality); + virtual void ResetQuality(void); + + DiskFS* GetDiskFS(void) const { return fpDiskFS; } + +protected: + DiskFS* fpDiskFS; + virtual void SetParent(A2File* pParent) { /* do nothing */ } + +private: + A2File* GetPrev(void) const { return fpPrev; } + void SetPrev(A2File* pFile) { fpPrev = pFile; } + A2File* GetNext(void) const { return fpNext; } + void SetNext(A2File* pFile) { fpNext = pFile; } + + // Set when file structure is damaged and application should not try + // to open the file. + FileQuality fFileQuality; + + A2File* fpPrev; + A2File* fpNext; + + +private: + A2File& operator=(const A2File&); + A2File(const A2File&); +}; + + +/* + * Abstract representation of an open file. This contains all active state + * and all information required to read and write a file. + * + * Do not delete these objects; instead, invoke the Close method, so that they + * can be removed from the parents' list of open files. + * TODO: consider making the destructor "protected" + */ +class DISKIMG_API A2FileDescr { +public: + A2FileDescr(A2File* pFile) : fpFile(pFile), fProgressUpdateFunc(NULL) {} + virtual ~A2FileDescr(void) { fpFile = NULL; /*paranoia*/ } + + virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL) = 0; + virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL) = 0; + virtual DIError Seek(di_off_t offset, DIWhence whence) = 0; + virtual di_off_t Tell(void) = 0; + virtual DIError Close(void) = 0; + + virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) + const = 0; + virtual DIError GetStorage(long blockIdx, long* pBlock) + const = 0; + virtual long GetSectorCount(void) const = 0; + virtual long GetBlockCount(void) const = 0; + + virtual DIError Rewind(void) { return Seek(0, kSeekSet); } + + A2File* GetFile(void) const { return fpFile; } + + /* + * Progress update callback mechanism. Pass in the length or (for writes) + * expected length of the file. This invokes the callback with the + * lengths and some pointers. + * + * If the progress callback returns "true", progress continues. If it + * returns "false", the read or write function will return with + * kDIErrCancelled. + */ + typedef bool (*ProgressUpdater)(A2FileDescr* pFile, di_off_t max, + di_off_t current, void* vState); + void SetProgressUpdater(ProgressUpdater func, di_off_t max, void* state) { + fProgressUpdateFunc = func; + fProgressUpdateMax = max; + fProgressUpdateState = state; + } + void ClearProgressUpdater(void) { + fProgressUpdateFunc = NULL; + } + +protected: + A2File* fpFile; + + /* + * Internal utility functions for mapping blocks to sectors and vice-versa. + */ + virtual void TrackSectorToBlock(long track, long sector, long* pBlock, + bool* pSecondHalf) const + { + int numSectPerTrack = fpFile->GetDiskFS()->GetDiskImg()->GetNumSectPerTrack(); + assert(track < fpFile->GetDiskFS()->GetDiskImg()->GetNumTracks()); + assert(sector < numSectPerTrack); + long dblBlock = track * numSectPerTrack + sector; + *pBlock = dblBlock / 2; + *pSecondHalf = (dblBlock & 0x01) != 0; + } + virtual void BlockToTrackSector(long block, bool secondHalf, long* pTrack, + long* pSector) const + { + assert(block < fpFile->GetDiskFS()->GetDiskImg()->GetNumBlocks()); + int numSectPerTrack = fpFile->GetDiskFS()->GetDiskImg()->GetNumSectPerTrack(); + int dblBlock = block * 2; + if (secondHalf) + dblBlock++; + *pTrack = dblBlock / numSectPerTrack; + *pSector = dblBlock % numSectPerTrack; + } + + /* + * Call this from FS-specific read/write functions on successful + * completion (and perhaps more often for filesystems with potentially + * large files, e.g. ProDOS/HFS). + * + * Test the return value; if "false", user wishes to cancel the op, and + * long read or write calls should return immediately. + */ + inline bool UpdateProgress(di_off_t current) { + if (fProgressUpdateFunc != NULL) { + return (*fProgressUpdateFunc)(this, fProgressUpdateMax, current, + fProgressUpdateState); + } else { + return true; + } + } + +private: + A2FileDescr& operator=(const A2FileDescr&); + A2FileDescr(const A2FileDescr&); + + /* storage for progress update goodies */ + ProgressUpdater fProgressUpdateFunc; + di_off_t fProgressUpdateMax; + void* fProgressUpdateState; +}; + +}; // namespace DiskImgLib + +#endif /*__DISK_IMG__*/ diff --git a/diskimg/DiskImgDetail.h b/diskimg/DiskImgDetail.h index c295abc..99d5a1c 100644 --- a/diskimg/DiskImgDetail.h +++ b/diskimg/DiskImgDetail.h @@ -1,3220 +1,3220 @@ -/* - * CiderPress - * Copyright (C) 2009 by CiderPress authors. All Rights Reserved. - * Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved. - * See the file LICENSE for distribution terms. - */ -/* - * Sub-classes of the base classes defined in DiskImg.h. - * - * Most applications will not need to include this file, because the - * polymorphic interfaces do everything they need. If something needs to - * examine the actual directory structure of a file, it can do so through - * these declarations. - */ -#ifndef __DISKIMGDETAIL__ -#define __DISKIMGDETAIL__ - -#include "../prebuilt/NufxLib.h" -#define ZLIB_DLL -#include "../prebuilt/zlib.h" - -#include "DiskImg.h" - -#ifndef EXCISE_GPL_CODE -# include "libhfs/hfs.h" -#endif - -namespace DiskImgLib { - -/* - * =========================================================================== - * Outer wrappers - * =========================================================================== - */ - -/* - * Outer wrapper class, representing a compression utility or archive - * format that must be stripped away so we can get to the Apple II stuff. - * - * Outer wrappers usually have a filename embedded in them, representing - * the original name of the file. We want to use the extension from this - * name when evaluating the file contents. Usually. - */ -class OuterWrapper { -public: - OuterWrapper(void) {} - virtual ~OuterWrapper(void) {} - - // all sub-classes should have one of these - //static DIError Test(GenericFD* pGFD, long outerLength); - - // open the file and prepare to access it; fills out return values - // NOTE: pGFD must be a GFDFile. - virtual DIError Load(GenericFD* pOuterGFD, di_off_t outerLength, bool readOnly, - di_off_t* pWrapperLength, GenericFD** ppWrapperGFD) = 0; - - virtual DIError Save(GenericFD* pOuterGFD, GenericFD* pWrapperGFD, - di_off_t wrapperLength) = 0; - - // set on recoverable errors, like a CRC failure - virtual bool IsDamaged(void) const = 0; - - // indicate that we don't have a "fast" flush - virtual bool HasFastFlush(void) const { return false; } - - virtual const char* GetExtension(void) const = 0; - -private: - OuterWrapper& operator=(const OuterWrapper&); - OuterWrapper(const OuterWrapper&); -}; - -class OuterGzip : public OuterWrapper { -public: - OuterGzip(void) { fWrapperDamaged = false; } - virtual ~OuterGzip(void) {} - - static DIError Test(GenericFD* pGFD, di_off_t outerLength); - virtual DIError Load(GenericFD* pGFD, di_off_t outerLength, bool readOnly, - di_off_t* pTotalLength, GenericFD** ppNewGFD); - virtual DIError Save(GenericFD* pOuterGFD, GenericFD* pWrapperGFD, - di_off_t wrapperLength); - - virtual bool IsDamaged(void) const { return fWrapperDamaged; } - - virtual const char* GetExtension(void) const { return NULL; } - -private: - DIError ExtractGzipImage(gzFile gzfp, char** pBuf, di_off_t* pLength); - DIError CloseGzip(void); - - // Largest possible ProDOS volume; quite a bit to hold in RAM. Add a - // little extra for .hdv format. - enum { kMaxUncompressedSize = kGzipMax +256 }; - - bool fWrapperDamaged; -}; - -class OuterZip : public OuterWrapper { -public: - OuterZip(void) : fStoredFileName(NULL), fExtension(NULL) {} - virtual ~OuterZip(void) { - delete[] fStoredFileName; - delete[] fExtension; - } - - static DIError Test(GenericFD* pGFD, di_off_t outerLength); - virtual DIError Load(GenericFD* pGFD, di_off_t outerLength, bool readOnly, - di_off_t* pTotalLength, GenericFD** ppNewGFD); - virtual DIError Save(GenericFD* pOuterGFD, GenericFD* pWrapperGFD, - di_off_t wrapperLength); - - virtual bool IsDamaged(void) const { return false; } - - virtual const char* GetExtension(void) const { return fExtension; } - -private: - class LocalFileHeader { - public: - LocalFileHeader(void) : - fVersionToExtract(0), - fGPBitFlag(0), - fCompressionMethod(0), - fLastModFileTime(0), - fLastModFileDate(0), - fCRC32(0), - fCompressedSize(0), - fUncompressedSize(0), - fFileNameLength(0), - fExtraFieldLength(0), - fFileName(NULL) - {} - virtual ~LocalFileHeader(void) { delete[] fFileName; } - - DIError Read(GenericFD* pGFD); - DIError Write(GenericFD* pGFD); - void SetFileName(const char* name); - - // unsigned long fSignature; - unsigned short fVersionToExtract; - unsigned short fGPBitFlag; - unsigned short fCompressionMethod; - unsigned short fLastModFileTime; - unsigned short fLastModFileDate; - unsigned long fCRC32; - unsigned long fCompressedSize; - unsigned long fUncompressedSize; - unsigned short fFileNameLength; - unsigned short fExtraFieldLength; - unsigned char* fFileName; - // extra field - - enum { - kSignature = 0x04034b50, - kLFHLen = 30, // LocalFileHdr len, excl. var fields - }; - - void Dump(void) const; - }; - - class CentralDirEntry { - public: - CentralDirEntry(void) : - fVersionMadeBy(0), - fVersionToExtract(0), - fGPBitFlag(0), - fCompressionMethod(0), - fLastModFileTime(0), - fLastModFileDate(0), - fCRC32(0), - fCompressedSize(0), - fUncompressedSize(0), - fFileNameLength(0), - fExtraFieldLength(0), - fFileCommentLength(0), - fDiskNumberStart(0), - fInternalAttrs(0), - fExternalAttrs(0), - fLocalHeaderRelOffset(0), - fFileName(NULL), - fFileComment(NULL) - {} - virtual ~CentralDirEntry(void) { - delete[] fFileName; - delete[] fFileComment; - } - - DIError Read(GenericFD* pGFD); - DIError Write(GenericFD* pGFD); - void SetFileName(const char* name); - - // unsigned long fSignature; - unsigned short fVersionMadeBy; - unsigned short fVersionToExtract; - unsigned short fGPBitFlag; - unsigned short fCompressionMethod; - unsigned short fLastModFileTime; - unsigned short fLastModFileDate; - unsigned long fCRC32; - unsigned long fCompressedSize; - unsigned long fUncompressedSize; - unsigned short fFileNameLength; - unsigned short fExtraFieldLength; - unsigned short fFileCommentLength; - unsigned short fDiskNumberStart; - unsigned short fInternalAttrs; - unsigned long fExternalAttrs; - unsigned long fLocalHeaderRelOffset; - unsigned char* fFileName; - // extra field - unsigned char* fFileComment; // alloc with new[] - - void Dump(void) const; - - enum { - kSignature = 0x02014b50, - kCDELen = 46, // CentralDirEnt len, excl. var fields - }; - }; - - class EndOfCentralDir { - public: - EndOfCentralDir(void) : - fDiskNumber(0), - fDiskWithCentralDir(0), - fNumEntries(0), - fTotalNumEntries(0), - fCentralDirSize(0), - fCentralDirOffset(0), - fCommentLen(0) - {} - virtual ~EndOfCentralDir(void) {} - - DIError ReadBuf(const unsigned char* buf, int len); - DIError Write(GenericFD* pGFD); - - // unsigned long fSignature; - unsigned short fDiskNumber; - unsigned short fDiskWithCentralDir; - unsigned short fNumEntries; - unsigned short fTotalNumEntries; - unsigned long fCentralDirSize; - unsigned long fCentralDirOffset; // offset from first disk - unsigned short fCommentLen; - // archive comment - - enum { - kSignature = 0x06054b50, - kEOCDLen = 22, // EndOfCentralDir len, excl. comment - }; - - void Dump(void) const; - }; - - enum { - kDataDescriptorSignature = 0x08074b50, - - kMaxCommentLen = 65535, // longest possible in ushort - kMaxEOCDSearch = kMaxCommentLen + EndOfCentralDir::kEOCDLen, - - kZipFssep = '/', - kDefaultVersion = 20, - kMaxUncompressedSize = kGzipMax +256, - }; - enum { - kCompressStored = 0, // no compression - //kCompressShrunk = 1, - //kCompressImploded = 6, - kCompressDeflated = 8, // standard deflate - }; - - static DIError ReadCentralDir(GenericFD* pGFD, di_off_t outerLength, - CentralDirEntry* pDirEntry); - DIError ExtractZipEntry(GenericFD* pOuterGFD, CentralDirEntry* pCDE, - unsigned char** pBuf, di_off_t* pLength); - DIError InflateGFDToBuffer(GenericFD* pGFD, unsigned long compSize, - unsigned long uncompSize, unsigned char* buf); - DIError DeflateGFDToGFD(GenericFD* pDst, GenericFD* pSrc, di_off_t length, - di_off_t* pCompLength, unsigned long* pCRC); - -private: - void SetExtension(const char* ext); - void SetStoredFileName(const char* name); - void GetMSDOSTime(unsigned short* pDate, unsigned short* pTime); - void DOSTime(time_t when, unsigned short* pDate, unsigned short* pTime); - - char* fStoredFileName; - char* fExtension; -}; - - -/* - * =========================================================================== - * Image wrappers - * =========================================================================== - */ - -/* - * Image wrapper class, representing the format of the Windows files. - * Might be "raw" data, might be data with a header, might be a complex - * or compressed format that must be extracted to a buffer. - */ -class ImageWrapper { -public: - ImageWrapper(void) {} - virtual ~ImageWrapper(void) {} - - // all sub-classes should have one of these - // static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); - - // open the file and prepare to access it; fills out return values - virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, - di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) = 0; - - // fill out the wrapper, using the specified parameters - virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, - DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, - di_off_t* pWrappedLength, GenericFD** pDataFD) = 0; - - // push altered data to the wrapper GFD - virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, - di_off_t dataLen, di_off_t* pWrappedLen) = 0; - - // set the storage name (used by some formats) - virtual void SetStorageName(const char* name) { - // default implementation - assert(false); - } - - // indicate that we have a "fast" flush - virtual bool HasFastFlush(void) const = 0; - - // set by "Prep" on recoverable errors, like a CRC failure, for some fmts - virtual bool IsDamaged(void) const { return false; } - - // if this wrapper format includes a file comment, return it - //virtual const char* GetComment(void) const { return NULL; } - - /* - * Some additional goodies required for accessing variable-length nibble - * tracks in TrackStar images. A default implementation is provided and - * used for everything but TrackStar. - */ - virtual int GetNibbleTrackLength(DiskImg::PhysicalFormat physical, int track) const - { - if (physical == DiskImg::kPhysicalFormatNib525_6656) - return kTrackLenNib525; - else if (physical == DiskImg::kPhysicalFormatNib525_6384) - return kTrackLenNb2525; - else { - assert(false); - return -1; - } - } - virtual void SetNibbleTrackLength(int track, int length) { /*do nothing*/ } - virtual int GetNibbleTrackOffset(DiskImg::PhysicalFormat physical, int track) const - { - if (physical == DiskImg::kPhysicalFormatNib525_6656 || - physical == DiskImg::kPhysicalFormatNib525_6384) - { - /* fixed-length tracks */ - return GetNibbleTrackLength(physical, 0) * track; - } else { - assert(false); - return -1; - } - } - // TrackStar images can have more, but otherwise all nibble images have 35 - virtual int GetNibbleNumTracks(void) const - { - return kTrackCount525; - } - -private: - ImageWrapper& operator=(const ImageWrapper&); - ImageWrapper(const ImageWrapper&); -}; - - -class Wrapper2MG : public ImageWrapper { -public: - static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); - virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, - di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); - virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, - DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, - di_off_t* pWrappedLength, GenericFD** pDataFD); - virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, - di_off_t dataLen, di_off_t* pWrappedLen); - virtual bool HasFastFlush(void) const { return true; } - //virtual const char* GetComment(void) const { return NULL; } - // (need to hold TwoImgHeader in the struct, rather than as temp, or - // need to copy the comment out into Wrapper2MG storage e.g. StorageName) -}; - -class WrapperNuFX : public ImageWrapper { -public: - WrapperNuFX(void) : fpArchive(NULL), fThreadIdx(0), fStorageName(NULL), - fCompressType(kNuThreadFormatLZW2) - {} - virtual ~WrapperNuFX(void) { CloseNuFX(); delete[] fStorageName; } - - static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); - virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, - di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); - virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, - DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, - di_off_t* pWrappedLength, GenericFD** pDataFD); - virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, - di_off_t dataLen, di_off_t* pWrappedLen); - virtual bool HasFastFlush(void) const { return false; } - - void SetStorageName(const char* name) { - delete[] fStorageName; - if (name != NULL) { - fStorageName = new char[strlen(name)+1]; - strcpy(fStorageName, name); - } else - fStorageName = NULL; - } - void SetCompressType(NuThreadFormat format) { fCompressType = format; } - -private: - enum { kDefaultStorageFssep = ':' }; - static NuResult ErrMsgHandler(NuArchive* pArchive, void* vErrorMessage); - static DIError OpenNuFX(const char* pathName, NuArchive** ppArchive, - NuThreadIdx* pThreadIdx, long* pLength, bool readOnly); - DIError GetNuFXDiskImage(NuArchive* pArchive, NuThreadIdx threadIdx, - long length, char** ppData); - static char* GenTempPath(const char* path); - DIError CloseNuFX(void); - void UNIXTimeToDateTime(const time_t* pWhen, NuDateTime *pDateTime); - - NuArchive* fpArchive; - NuThreadIdx fThreadIdx; - char* fStorageName; - NuThreadFormat fCompressType; -}; - -class WrapperDiskCopy42 : public ImageWrapper { -public: - WrapperDiskCopy42(void) : fStorageName(NULL), fBadChecksum(false) - {} - virtual ~WrapperDiskCopy42(void) { delete[] fStorageName; } - - static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); - virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, - di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); - virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, - DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, - di_off_t* pWrappedLength, GenericFD** pDataFD); - virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, - di_off_t dataLen, di_off_t* pWrappedLen); - void SetStorageName(const char* name) { - delete[] fStorageName; - if (name != NULL) { - fStorageName = new char[strlen(name)+1]; - strcpy(fStorageName, name); - } else - fStorageName = NULL; - } - - virtual bool HasFastFlush(void) const { return false; } - virtual bool IsDamaged(void) const { return fBadChecksum; } - -private: - typedef struct DC42Header DC42Header; - static void DumpHeader(const DC42Header* pHeader); - void InitHeader(DC42Header* pHeader); - static int ReadHeader(GenericFD* pGFD, DC42Header* pHeader); - DIError WriteHeader(GenericFD* pGFD, const DC42Header* pHeader); - static DIError ComputeChecksum(GenericFD* pGFD, - unsigned long* pChecksum); - - char* fStorageName; - bool fBadChecksum; -}; - -class WrapperDDD : public ImageWrapper { -public: - static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); - virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, - di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); - virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, - DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, - di_off_t* pWrappedLength, GenericFD** pDataFD); - virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, - di_off_t dataLen, di_off_t* pWrappedLen); - virtual bool HasFastFlush(void) const { return false; } - - enum { - kMaxDDDZeroCount = 4, // 3 observed, 4 suspected - }; - -private: - class BitBuffer; - enum { - kNumTracks = 35, - kNumSectors = 16, - kSectorSize = 256, - kTrackLen = kNumSectors * kSectorSize, - }; - - static DIError CheckForRuns(GenericFD* pGFD); - static DIError Unpack(GenericFD* pGFD, GenericFD** ppNewGFD, - short* pDiskVolNum); - - static DIError UnpackDisk(GenericFD* pGFD, GenericFD* pNewGFD, - short* pDiskVolNum); - static bool UnpackTrack(BitBuffer* pBitBuffer, unsigned char* trackBuf); - static DIError PackDisk(GenericFD* pSrcGFD, GenericFD* pWrapperGFD, - short diskVolNum); - static void PackTrack(const unsigned char* trackBuf, BitBuffer* pBitBuf); - static void ComputeFreqCounts(const unsigned char* trackBuf, - unsigned short* freqCounts); - static void ComputeFavorites(unsigned short* freqCounts, - unsigned char* favorites); - - short fDiskVolumeNum; -}; - -class WrapperSim2eHDV : public ImageWrapper { -public: - static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); - virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, - di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); - virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, - DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, - di_off_t* pWrappedLength, GenericFD** pDataFD); - virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, - di_off_t dataLen, di_off_t* pWrappedLen); - virtual bool HasFastFlush(void) const { return true; } -}; - -class WrapperTrackStar : public ImageWrapper { -public: - enum { - kTrackStarNumTracks = 40, - kFileTrackStorageLen = 6656, - kMaxTrackLen = kFileTrackStorageLen - (128+1+2), // header + footer - kCommentFieldLen = 0x2e, - }; - - WrapperTrackStar(void) : fStorageName(NULL) { - memset(&fNibbleTrackInfo, 0, sizeof(fNibbleTrackInfo)); - fNibbleTrackInfo.numTracks = -1; - } - virtual ~WrapperTrackStar(void) { delete[] fStorageName; } - - static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); - virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, - di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); - virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, - DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, - di_off_t* pWrappedLength, GenericFD** pDataFD); - virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, - di_off_t dataLen, di_off_t* pWrappedLen); - virtual bool HasFastFlush(void) const { return false; } - - virtual void SetStorageName(const char* name) - { - delete[] fStorageName; - if (name != NULL) { - fStorageName = new char[strlen(name)+1]; - strcpy(fStorageName, name); - } else - fStorageName = NULL; - } - -private: - static DIError VerifyTrack(int track, const unsigned char* trackBuf); - DIError Unpack(GenericFD* pGFD, GenericFD** ppNewGFD); - DIError UnpackDisk(GenericFD* pGFD, GenericFD* pNewGFD); - - int fImageTracks; - char* fStorageName; - - /* - * Data structure for managing nibble images with variable-length tracks. - */ - typedef struct { - int numTracks; // should be 35 or 40 - int length[kMaxNibbleTracks525]; - int offset[kMaxNibbleTracks525]; - } NibbleTrackInfo; - NibbleTrackInfo fNibbleTrackInfo; // count and lengths for variable formats - - // nibble images can have variable-length data fields - virtual int GetNibbleTrackLength(DiskImg::PhysicalFormat physical, int track) const - { - assert(physical == DiskImg::kPhysicalFormatNib525_Var); - assert(fNibbleTrackInfo.numTracks > 0); - - return fNibbleTrackInfo.length[track]; - } - virtual void SetNibbleTrackLength(int track, int length); -#if 0 - { - assert(track >= 0); - assert(length > 0 && length <= kMaxTrackLen); - assert(track < fNibbleTrackInfo.numTracks); - - fNibbleTrackInfo.length[track] = length; - } -#endif - virtual int GetNibbleTrackOffset(DiskImg::PhysicalFormat physical, int track) const - { - assert(physical == DiskImg::kPhysicalFormatNib525_Var); - assert(fNibbleTrackInfo.numTracks > 0); - - return fNibbleTrackInfo.offset[track]; - } - virtual int GetNibbleNumTracks(void) const - { - return kTrackStarNumTracks; - } -}; - -class WrapperFDI : public ImageWrapper { -public: - WrapperFDI(void) {} - virtual ~WrapperFDI(void) {} - - static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); - virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, - di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); - virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, - DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, - di_off_t* pWrappedLength, GenericFD** pDataFD); - virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, - di_off_t dataLen, di_off_t* pWrappedLen); - virtual bool HasFastFlush(void) const { return false; } - - enum { - kSignatureLen = 27, - kCreatorLen = 30, - kCommentLen = 80, - }; - -private: - static const char* kFDIMagic; - - /* what type of disk is this? */ - typedef enum DiskType { - kDiskType8 = 0, - kDiskType525 = 1, - kDiskType35 = 2, - kDiskType3 = 3 - } DiskType; - - /* - * Contents of FDI header. - */ - typedef struct FDIHeader { - char signature[kSignatureLen+1]; - char creator[kCreatorLen+1]; - // CR + LF - char comment[kCommentLen+1]; - // MS-DOS EOF - unsigned short version; - unsigned short lastTrack; - unsigned char lastHead; - unsigned char type; // DiskType enum - unsigned char rotSpeed; - unsigned char flags; - unsigned char tpi; - unsigned char headWidth; - unsigned short reserved; - // track descriptors follow, at byte 152 - } FDIHeader; - - /* - * Header for pulse-index streams track. - */ - typedef struct PulseIndexHeader { - long numPulses; - long avgStreamLen; - int avgStreamCompression; - long minStreamLen; - int minStreamCompression; - long maxStreamLen; - int maxStreamCompression; - long idxStreamLen; - int idxStreamCompression; - - unsigned long* avgStream; // 4 bytes/pulse - unsigned long* minStream; // 4 bytes/pulse; optional - unsigned long* maxStream; // 4 bytes/pulse; optional - unsigned long* idxStream; // 2 bytes/pulse; optional? - } PulseIndexHeader; - - enum { - kTrackDescrOffset = 152, - kMaxHeads = 2, - kMaxHeaderBlockTracks = 180, // max 90 double-sided cylinders - kMinHeaderLen = 512, - kMinVersion = 0x0200, // v2.0 - - kMaxNibbleTracks35 = 80, // 80 double-sided tracks - kNibbleBufLen = 10240, // max seems to be a little under 10K - kBitBufferSize = kNibbleBufLen + (kNibbleBufLen / 4), - - kMaxSectors35 = 12, // max #of sectors per track - //kBytesPerSector35 = 512, // bytes per sector on 3.5" disk - - kPulseStreamDataOffset = 16, // start of header to avg stream - - kBitRate525 = 250000, // 250Kbits/sec - }; - - /* meaning of the two-bit compression format value */ - typedef enum CompressedFormat { - kCompUncompressed = 0, - kCompHuffman = 1, - } CompressedFormat; - - /* node in the Huffman tree */ - typedef struct HuffNode { - unsigned short val; - struct HuffNode* left; - struct HuffNode* right; - } HuffNode; - - /* - * Keep a copy of the header around while we work. None of the formats - * we're interested in have more than kMaxHeaderBlockTracks tracks in - * them, so we don't need anything beyond the initial 512-byte header. - */ - unsigned char fHeaderBuf[kMinHeaderLen]; - - static void UnpackHeader(const unsigned char* headerBuf, FDIHeader* hdr); - static void DumpHeader(const FDIHeader* pHdr); - - DIError Unpack525(GenericFD* pGFD, GenericFD** ppNewGFD, int numCyls, - int numHeads); - DIError Unpack35(GenericFD* pGFD, GenericFD** ppNewGFD, int numCyls, - int numHeads, LinearBitmap** ppBadBlockMap); - DIError PackDisk(GenericFD* pSrcGFD, GenericFD* pWrapperGFD); - - DIError UnpackDisk525(GenericFD* pGFD, GenericFD* pNewGFD, int numCyls, - int numHeads); - DIError UnpackDisk35(GenericFD* pGFD, GenericFD* pNewGFD, int numCyls, - int numHeads, LinearBitmap* pBadBlockMap); - void GetTrackInfo(int trk, int* pType, int* pLength256); - - int BitRate35(int trk); - void FixBadNibbles(unsigned char* nibbleBuf, long nibbleLen); - bool DecodePulseTrack(const unsigned char* inputBuf, long inputLen, - int bitRate, unsigned char* nibbleBuf, long* pNibbleLen); - bool UncompressPulseStream(const unsigned char* inputBuf, long inputLen, - unsigned long* outputBuf, long numPulses, int format, int bytesPerPulse); - bool ExpandHuffman(const unsigned char* inputBuf, long inputLen, - unsigned long* outputBuf, long numPulses); - const unsigned char* HuffExtractTree(const unsigned char* inputBuf, - HuffNode* pNode, unsigned char* pBits, unsigned char* pBitMask); - const unsigned char* HuffExtractValues16(const unsigned char* inputBuf, - HuffNode* pNode); - const unsigned char* HuffExtractValues8(const unsigned char* inputBuf, - HuffNode* pNode); - void HuffFreeNodes(HuffNode* pNode); - unsigned long HuffSignExtend16(unsigned long val); - unsigned long HuffSignExtend8(unsigned long val); - bool ConvertPulseStreamsToNibbles(PulseIndexHeader* pHdr, int bitRate, - unsigned char* nibbleBuf, long* pNibbleLen); - bool ConvertPulsesToBits(const unsigned long* avgStream, - const unsigned long* minStream, const unsigned long* maxStream, - const unsigned long* idxStream, int numPulses, int maxIndex, - int indexOffset, unsigned long totalAvg, int bitRate, - unsigned char* outputBuf, int* pOutputLen); - int MyRand(void); - bool ConvertBitsToNibbles(const unsigned char* bitBuffer, int bitCount, - unsigned char* nibbleBuf, long* pNibbleLen); - - - int fImageTracks; - char* fStorageName; - - - /* - * Data structure for managing nibble images with variable-length tracks. - */ - typedef struct { - int numTracks; // expect 35 or 40 for 5.25" - int length[kMaxNibbleTracks525]; - int offset[kMaxNibbleTracks525]; - } NibbleTrackInfo; - NibbleTrackInfo fNibbleTrackInfo; // count and lengths for variable formats - - // nibble images can have variable-length data fields - virtual int GetNibbleTrackLength(DiskImg::PhysicalFormat physical, int track) const - { - assert(physical == DiskImg::kPhysicalFormatNib525_Var); - assert(fNibbleTrackInfo.numTracks > 0); - - return fNibbleTrackInfo.length[track]; - } - virtual void SetNibbleTrackLength(int track, int length); - virtual int GetNibbleTrackOffset(DiskImg::PhysicalFormat physical, int track) const - { - assert(physical == DiskImg::kPhysicalFormatNib525_Var); - assert(fNibbleTrackInfo.numTracks > 0); - - return fNibbleTrackInfo.offset[track]; - } - virtual int GetNibbleNumTracks(void) const - { - return fNibbleTrackInfo.numTracks; - } -}; - - -class WrapperUnadornedNibble : public ImageWrapper { -public: - static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); - virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, - di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); - virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, - DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, - di_off_t* pWrappedLength, GenericFD** pDataFD); - virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, - di_off_t dataLen, di_off_t* pWrappedLen); - virtual bool HasFastFlush(void) const { return true; } -}; - -class WrapperUnadornedSector : public ImageWrapper { -public: - static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); - virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, - di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); - virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, - DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, - di_off_t* pWrappedLength, GenericFD** pDataFD); - virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, - di_off_t dataLen, di_off_t* pWrappedLen); - virtual bool HasFastFlush(void) const { return true; } -}; - - -/* - * =========================================================================== - * Non-FS DiskFSs - * =========================================================================== - */ - -/* - * A "raw" disk, i.e. no filesystem is known. Useful as a placeholder - * for applications that demand a DiskFS object even when the filesystem - * isn't known. - */ -class DISKIMG_API DiskFSUnknown : public DiskFS { -public: - DiskFSUnknown(void) : DiskFS() { - strcpy(fDiskVolumeName, "[Unknown]"); - strcpy(fDiskVolumeID, "Unknown FS"); - } - virtual ~DiskFSUnknown(void) {} - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return kDIErrNone; - } - - virtual const char* GetVolumeName(void) const { return fDiskVolumeName; } - virtual const char* GetVolumeID(void) const { return fDiskVolumeID; } - virtual const char* GetBareVolumeName(void) const { return NULL; } - virtual bool GetReadWriteSupported(void) const { return false; } - virtual bool GetFSDamaged(void) const { return false; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const - { return kDIErrNotSupported; } - - // Use this if *something* is known about the filesystem, e.g. the - // partition type on a MacPart disk. - void SetVolumeInfo(const char* descr) { - if (strlen(descr) > kMaxVolumeName) - return; - - fDiskVolumeName[0] = '['; - strcpy(fDiskVolumeName+1, descr); - strcat(fDiskVolumeName, "]"); - strcpy(fDiskVolumeID, "Unknown FS - "); - strcat(fDiskVolumeID, descr); - } - -private: - enum { kMaxVolumeName = 64 }; - - char fDiskVolumeName[kMaxVolumeName+3]; - char fDiskVolumeID[kMaxVolumeName + 20]; -}; - - -/* - * Generic "container" DiskFS class. Contains some common functions shared - * among classes that are just containers for other filesystems. This class - * is not expected to be instantiated. - * - * TODO: create a common OpenSubVolume() function. - */ -class DISKIMG_API DiskFSContainer : public DiskFS { -public: - DiskFSContainer(void) : DiskFS() {} - virtual ~DiskFSContainer(void) {} - -protected: - virtual const char* GetDebugName(void) = 0; - virtual DIError CreatePlaceholder(long startBlock, long numBlocks, - const char* partName, const char* partType, - DiskImg** ppNewImg, DiskFS** ppNewFS); - virtual void SetVolumeUsageMap(void); -}; - -/* - * UNIDOS disk, an 800K floppy with two 400K DOS 3.3 volumes on it. - * - * The disk itself has no files; instead, it has two embedded sub-volumes. - */ -class DISKIMG_API DiskFSUNIDOS : public DiskFSContainer { -public: - DiskFSUNIDOS(void) : DiskFSContainer() {} - virtual ~DiskFSUNIDOS(void) {} - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - static DIError TestWideFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(); - } - - virtual const char* GetVolumeName(void) const { return "[UNIDOS]"; } - virtual const char* GetVolumeID(void) const { return "[UNIDOS]"; } - virtual const char* GetBareVolumeName(void) const { return NULL; } - virtual bool GetReadWriteSupported(void) const { return false; } - virtual bool GetFSDamaged(void) const { return false; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const - { return kDIErrNotSupported; } - -private: - virtual const char* GetDebugName(void) { return "UNIDOS"; } - DIError Initialize(void); - DIError OpenSubVolume(int idx); -}; - -/* - * OzDOS disk, an 800K floppy with two 400K DOS 3.3 volumes on it. They - * put the files for disk 1 in the odd sectors and the files for disk 2 - * in the even sectors (the top and bottom halves of a 512-byte block). - * - * The disk itself has no files; instead, it has two embedded sub-volumes. - * Because of the funky layout, we have to use the "sector pairing" feature - * of DiskImg to treat this like a DOS 3.3 disk. - */ -class DISKIMG_API DiskFSOzDOS : public DiskFSContainer { -public: - DiskFSOzDOS(void) : DiskFSContainer() {} - virtual ~DiskFSOzDOS(void) {} - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(); - } - - virtual const char* GetVolumeName(void) const { return "[OzDOS]"; } - virtual const char* GetVolumeID(void) const { return "[OzDOS]"; } - virtual const char* GetBareVolumeName(void) const { return NULL; } - virtual bool GetReadWriteSupported(void) const { return false; } - virtual bool GetFSDamaged(void) const { return false; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const - { return kDIErrNotSupported; } - -private: - virtual const char* GetDebugName(void) { return "OzDOS"; } - DIError Initialize(void); - DIError OpenSubVolume(int idx); -}; - -/* - * CFFA volume. A potentially very large volume with multiple partitions. - * - * This DiskFS is just a container that describes the position and sizes - * of the sub-volumes. - */ -class DISKIMG_API DiskFSCFFA : public DiskFSContainer { -public: - DiskFSCFFA(void) : DiskFSContainer() {} - virtual ~DiskFSCFFA(void) {} - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(); - } - - virtual const char* GetVolumeName(void) const { return "[CFFA]"; } - virtual const char* GetVolumeID(void) const { return "[CFFA]"; } - virtual const char* GetBareVolumeName(void) const { return NULL; } - virtual bool GetReadWriteSupported(void) const { return false; } - virtual bool GetFSDamaged(void) const { return false; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const - { return kDIErrNotSupported; } - -private: - virtual const char* GetDebugName(void) { return "CFFA"; } - - static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder, - DiskImg::FSFormat* pFormatFound); - static DIError OpenSubVolume(DiskImg* pImg, long startBlock, - long numBlocks, bool scanOnly, DiskImg** ppNewImg, DiskFS** ppNewFS); - DIError Initialize(void); - DIError FindSubVolumes(void); - DIError AddVolumeSeries(int start, int count, long blocksPerVolume, - long& startBlock, long& totalBlocksLeft); - - enum { - kMinInterestingBlocks = 65536 + 1024, // less than this, ignore - kEarlyVolExpectedSize = 65536, // 32MB in 512-byte blocks - kOneGB = 1024*1024*(1024/512), // 1GB in 512-byte blocks - }; -}; - - -/* - * Macintosh-style partitioned disk image. - * - * This DiskFS is just a container that describes the position and sizes - * of the sub-volumes. - */ -class DISKIMG_API DiskFSMacPart : public DiskFSContainer { -public: - DiskFSMacPart(void) : DiskFSContainer() {} - virtual ~DiskFSMacPart(void) {} - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(); - } - - virtual const char* GetVolumeName(void) const { return "[MacPartition]"; } - virtual const char* GetVolumeID(void) const { return "[MacPartition]"; } - virtual const char* GetBareVolumeName(void) const { return NULL; } - virtual bool GetReadWriteSupported(void) const { return false; } - virtual bool GetFSDamaged(void) const { return false; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const - { return kDIErrNotSupported; } - -private: - virtual const char* GetDebugName(void) { return "MacPart"; } - - struct PartitionMap; // fwd - struct DriverDescriptorRecord; // fwd - static void UnpackDDR(const unsigned char* buf, - DriverDescriptorRecord* pDDR); - static void DumpDDR(const DriverDescriptorRecord* pDDR); - static void UnpackPartitionMap(const unsigned char* buf, - PartitionMap* pMap); - static void DumpPartitionMap(long block, const PartitionMap* pMap); - - static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder); - DIError OpenSubVolume(const PartitionMap* pMap); - DIError Initialize(void); - DIError FindSubVolumes(void); - - enum { - kMinInterestingBlocks = 2048, // less than this, ignore - kDDRSignature = 0x4552, // 'ER' - kPartitionSignature = 0x504d, // 'PM' - }; -}; - - -/* - * Partitioning for Joachim Lange's MicroDrive card. - * - * This DiskFS is just a container that describes the position and sizes - * of the sub-volumes. - */ -class DISKIMG_API DiskFSMicroDrive : public DiskFSContainer { -public: - DiskFSMicroDrive(void) : DiskFSContainer() {} - virtual ~DiskFSMicroDrive(void) {} - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(); - } - - virtual const char* GetVolumeName(void) const { return "[MicroDrive]"; } - virtual const char* GetVolumeID(void) const { return "[MicroDrive]"; } - virtual const char* GetBareVolumeName(void) const { return NULL; } - virtual bool GetReadWriteSupported(void) const { return false; } - virtual bool GetFSDamaged(void) const { return false; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const - { return kDIErrNotSupported; } - -private: - virtual const char* GetDebugName(void) { return "MicroDrive"; } - - struct PartitionMap; // fwd - static void UnpackPartitionMap(const unsigned char* buf, - PartitionMap* pMap); - static void DumpPartitionMap(const PartitionMap* pMap); - - static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder); - DIError OpenSubVolume(long startBlock, long numBlocks); - DIError OpenVol(int idx, long startBlock, long numBlocks); - DIError Initialize(void); - DIError FindSubVolumes(void); - - enum { - kMinInterestingBlocks = 2048, // less than this, ignore - kPartitionSignature = 0xccca, // 'JL' in little-endian high-ASCII - }; -}; - - -/* - * Partitioning for Parsons Engineering FocusDrive card. - * - * This DiskFS is just a container that describes the position and sizes - * of the sub-volumes. - */ -class DISKIMG_API DiskFSFocusDrive : public DiskFSContainer { -public: - DiskFSFocusDrive(void) : DiskFSContainer() {} - virtual ~DiskFSFocusDrive(void) {} - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(); - } - - virtual const char* GetVolumeName(void) const { return "[FocusDrive]"; } - virtual const char* GetVolumeID(void) const { return "[FocusDrive]"; } - virtual const char* GetBareVolumeName(void) const { return NULL; } - virtual bool GetReadWriteSupported(void) const { return false; } - virtual bool GetFSDamaged(void) const { return false; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const - { return kDIErrNotSupported; } - -private: - virtual const char* GetDebugName(void) { return "FocusDrive"; } - - struct PartitionMap; // fwd - static void UnpackPartitionMap(const unsigned char* buf, - const unsigned char* nameBuf, PartitionMap* pMap); - static void DumpPartitionMap(const PartitionMap* pMap); - - static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder); - DIError OpenSubVolume(long startBlock, long numBlocks, - const char* name); - DIError OpenVol(int idx, long startBlock, long numBlocks, - const char* name); - DIError Initialize(void); - DIError FindSubVolumes(void); - - enum { - kMinInterestingBlocks = 2048, // less than this, ignore - }; -}; - - -/* - * =========================================================================== - * DOS 3.2/3.3 - * =========================================================================== - */ - -class A2FileDOS; - -/* - * DOS 3.2/3.3 disk. - */ -class DISKIMG_API DiskFSDOS33 : public DiskFS { -public: - DiskFSDOS33(void) : DiskFS() { - fVTOCLoaded = false; - fDiskIsGood = false; - } - virtual ~DiskFSDOS33(void) {} - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(initMode); - } - virtual DIError Format(DiskImg* pDiskImg, const char* volName); - - virtual const char* GetVolumeName(void) const { return fDiskVolumeName; } - virtual const char* GetVolumeID(void) const { return fDiskVolumeID; } - virtual const char* GetBareVolumeName(void) const { - // this is fragile -- skip over the "DOS" part, return 3 digits - assert(strlen(fDiskVolumeName) > 3); - return fDiskVolumeName+3; - } - virtual bool GetReadWriteSupported(void) const { return true; } - virtual bool GetFSDamaged(void) const { return !fDiskIsGood; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const; - virtual DIError NormalizePath(const char* path, char fssep, - char* normalizedBuf, int* pNormalizedBufLen); - virtual DIError CreateFile(const CreateParms* pParms, A2File** ppNewFile); - virtual DIError DeleteFile(A2File* pFile); - virtual DIError RenameFile(A2File* pFile, const char* newName); - virtual DIError SetFileInfo(A2File* pFile, long fileType, long auxType, - long accessFlags); - virtual DIError RenameVolume(const char* newName); - - /* - * Unique to DOS 3.3 disks. - */ - int GetDiskVolumeNum(void) const { return fDiskVolumeNum; } - void SetDiskVolumeNum(int val); - - static bool IsValidFileName(const char* name); - static bool IsValidVolumeName(const char* name); - - // utility function - static void LowerASCII(unsigned char* buf, long len); - static void ReplaceFssep(char* str, char replacement); - - enum { - kMinTracks = 17, // need to put the catalog track here - kMaxTracks = 50, - kMaxCatalogSectors = 64, // two tracks on a 32-sector disk - }; - - /* a T/S pair */ - typedef struct TrackSector { - char track; - char sector; - } TrackSector; - - friend class A2FDDOS; // for Write - -private: - DIError Initialize(InitMode initMode); - DIError ReadVTOC(void); - void UpdateVolumeNum(void); - void DumpVTOC(void); - void SetSectorUsage(long track, long sector, - VolumeUsage::ChunkPurpose purpose); - void FixVolumeUsageMap(void); - DIError ReadCatalog(void); - DIError ProcessCatalogSector(int catTrack, int catSect, - const unsigned char* sctBuf); - DIError GetFileLengths(void); - DIError ComputeLength(A2FileDOS* pFile, const TrackSector* tsList, - int tsCount); - DIError TrimLastSectorUp(A2FileDOS* pFile, TrackSector lastTS); - void MarkFileUsage(A2FileDOS* pFile, TrackSector* tsList, int tsCount, - TrackSector* indexList, int indexCount); - //DIError TrimLastSectorDown(A2FileDOS* pFile, unsigned short* tsBuf, - // int maxZeroCount); - void DoNormalizePath(const char* name, char fssep, char* outBuf); - DIError MakeFileNameUnique(char* fileName); - DIError GetFreeCatalogEntry(TrackSector* pCatSect, int* pCatEntry, - unsigned char* sctBuf, A2FileDOS** ppPrevEntry); - void CreateDirEntry(unsigned char* sctBuf, int catEntry, - const char* fileName, TrackSector* pTSSect, unsigned char fileType, - int access); - void FreeTrackSectors(TrackSector* pList, int count); - - bool CheckDiskIsGood(void); - - DIError WriteDOSTracks(int sectPerTrack); - - DIError ScanVolBitmap(void); - DIError LoadVolBitmap(void); - DIError SaveVolBitmap(void); - void FreeVolBitmap(void); - DIError AllocSector(TrackSector* pTS); - DIError CreateEmptyBlockMap(bool withDOS); - bool GetSectorUseEntry(long track, int sector) const; - void SetSectorUseEntry(long track, int sector, bool inUse); - inline unsigned long GetVTOCEntry(const unsigned char* pVTOC, - long track) const; - - // Largest interesting volume is 400K (50 tracks, 32 sectors), but - // we may be looking at it in 16-sector mode, so max tracks is 100. - enum { - kMaxInterestingTracks = 100, - kSectorSize = 256, - kDefaultVolumeNum = 254, - kMaxExtensionLen = 4, // used when normalizing; ".gif" is 4 - }; - - // DOS track images, for initializing disk images - static const unsigned char gDOS33Tracks[]; - static const unsigned char gDOS32Tracks[]; - - /* some fields from the VTOC */ - int fFirstCatTrack; - int fFirstCatSector; - int fVTOCVolumeNumber; - int fVTOCNumTracks; - int fVTOCNumSectors; - - /* private data */ - int fDiskVolumeNum; // usually 254 - char fDiskVolumeName[7]; // "DOS" + num, e.g. "DOS001", "DOS254" - char fDiskVolumeID[32]; // sizeof "DOS 3.3 Volume " +3 +1 - unsigned char fVTOC[kSectorSize]; - bool fVTOCLoaded; - - /* - * There are some things we need to be careful of when reading the - * catalog track, like bad links and infinite loops. By storing a list - * of known good catalog sectors, we only have to handle that stuff once. - * The catalog doesn't grow or shrink, so this never needs to be updated. - */ - TrackSector fCatalogSectors[kMaxCatalogSectors]; - - bool fDiskIsGood; -}; - -/* - * File descriptor for an open DOS file. - */ -class DISKIMG_API A2FDDOS : public A2FileDescr { -public: - A2FDDOS(A2File* pFile) : A2FileDescr(pFile) { - fTSList = NULL; - fIndexList = NULL; - fOffset = 0; - fModified = false; - } - virtual ~A2FDDOS(void) { - delete[] fTSList; - delete[] fIndexList; - //fTSList = fIndexList = NULL; - } - - //typedef DiskFSDOS33::TrackSector TrackSector; - - friend class A2FileDOS; - - virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Seek(di_off_t offset, DIWhence whence); - virtual di_off_t Tell(void); - virtual DIError Close(void); - - virtual long GetSectorCount(void) const; - virtual long GetBlockCount(void) const; - virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; - virtual DIError GetStorage(long blockIdx, long* pBlock) const; - -private: - typedef DiskFSDOS33::TrackSector TrackSector; - - TrackSector* fTSList; // T/S entries for data sectors - int fTSCount; - TrackSector* fIndexList; // T/S entries for T/S list sectors - int fIndexCount; - di_off_t fOffset; // current position in file - - di_off_t fOpenEOF; // how big the file currently is - long fOpenSectorsUsed; // how many sectors it occupies - bool fModified; // if modified, update stuff on Close - - void DumpTSList(void) const; -}; - -/* - * Holds DOS files. Works for DOS33, DOS32, and "wide" DOS implementations. - * - * Catalog contents are public so anyone who wants gory details of DOS 3.3 - * stuff can poke at whatever they want. Anybody else can use the virtual - * interfaces to get standardized answers for things like file type. - * - * The embedded address and length fields found in Applesoft, Integer, and - * Binary files are quietly skipped over with the fDataOffset field when - * files are read. - * - * THOUGHT: have "get filename" and "get raw filename" interfaces? There - * are no directories, so maybe we don't care about "raw pathname"?? Might - * be better to always return the "raw" value and let the caller deal with - * things like high ASCII. - */ -class DISKIMG_API A2FileDOS : public A2File { -public: - A2FileDOS(DiskFS* pDiskFS); - virtual ~A2FileDOS(void); - - // assorted constants - enum { - kMaxFileName = 30, - }; - typedef enum { - kTypeUnknown = -1, - kTypeText = 0x00, // 'T' - kTypeInteger = 0x01, // 'I' - kTypeApplesoft = 0x02, // 'A' - kTypeBinary = 0x04, // 'B' - kTypeS = 0x08, // 'S' - kTypeReloc = 0x10, // 'R' - kTypeA = 0x20, // 'A' - kTypeB = 0x40, // 'B' - - kTypeLocked = 0x80 // bitwise OR with previous values - } FileType; - - /* - * Implementations of standard interfaces. - */ - virtual const char* GetFileName(void) const { return fFileName; } - virtual const char* GetPathName(void) const { return fFileName; } - virtual char GetFssep(void) const { return '\0'; } - virtual long GetFileType(void) const; - virtual long GetAuxType(void) const { return fAuxType; } - virtual long GetAccess(void) const; - virtual time_t GetCreateWhen(void) const { return 0; } - virtual time_t GetModWhen(void) const { return 0; } - virtual di_off_t GetDataLength(void) const { return fLength; } - virtual di_off_t GetDataSparseLength(void) const { return fSparseLength; } - virtual di_off_t GetRsrcLength(void) const { return -1; } - virtual di_off_t GetRsrcSparseLength(void) const { return -1; } - - virtual DIError Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork = false); - virtual void CloseDescr(A2FileDescr* pOpenFile) { - assert(pOpenFile == fpOpenFile); - delete fpOpenFile; - fpOpenFile = NULL; - } - virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } - - void Dump(void) const; - - typedef DiskFSDOS33::TrackSector TrackSector; - - /* - * Contents of directory entry. - * - * We don't hold deleted or unused entries, so fTSListTrack is always - * valid. - */ - short fTSListTrack; // (could use TrackSector here) - short fTSListSector; - unsigned short fLengthInSectors; - bool fLocked; - char fFileName[kMaxFileName+1]; // "fixed" version - FileType fFileType; - - TrackSector fCatTS; // track/sector for our catalog entry - int fCatEntryNum; // entry number within cat sector - - // these are computed or determined from the file contents - unsigned short fAuxType; // addr for bin, etc. - short fDataOffset; // for 'A'/'B'/'I' with embedded len - di_off_t fLength; // file length, in bytes - di_off_t fSparseLength; // file length, factoring sparse out - - void FixFilename(void); - - DIError LoadTSList(TrackSector** pTSList, int* pTSCount, - TrackSector** pIndexList = NULL, int* pIndexCount = NULL); - static FileType ConvertFileType(long prodosType, di_off_t fileLen); - static bool IsValidType(long prodosType); - static void MakeDOSName(char* buf, const char* name); - static void TrimTrailingSpaces(char* filename); - -private: - DIError ExtractTSPairs(const unsigned char* sctBuf, TrackSector* tsList, - int* pLastNonZero); - - A2FDDOS* fpOpenFile; -}; - - -/* - * =========================================================================== - * ProDOS - * =========================================================================== - */ - -class A2FileProDOS; - -/* - * ProDOS disk. - * - * THOUGHT: it would be undesirable for the CiderPress UI, but it would - * make things somewhat easier internally if we treated the volume dir - * like a subdirectory under which everything else sits, instead of special- - * casing it like we do. This is awkward because volume dirs have names - * under ProDOS, giving every pathname an extra component that they don't - * really need. We can never treat the volume dir purely as a subdir, - * because it can't expand beyond 51 files, but the storage_type in the - * header is sufficient to identify it as such (assuming the disk isn't - * broken). Certain operations, such as changing the file type or aux type, - * simply aren't possible on a volume dir, and deleting a volume dir doesn't - * make sense. So in some respects we simply trade one kind of special-case - * behavior for another. - */ -class DISKIMG_API DiskFSProDOS : public DiskFS { -public: - DiskFSProDOS(void) : fBitMapPointer(0), fTotalBlocks(0), fBlockUseMap(NULL) - {} - virtual ~DiskFSProDOS(void) { - if (fBlockUseMap != NULL) { - assert(false); // unexpected - delete[] fBlockUseMap; - } - } - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(initMode); - } - virtual DIError Format(DiskImg* pDiskImg, const char* volName); - virtual DIError NormalizePath(const char* path, char fssep, - char* normalizedBuf, int* pNormalizedBufLen); - virtual DIError CreateFile(const CreateParms* pParms, A2File** ppNewFile); - virtual DIError DeleteFile(A2File* pFile); - virtual DIError RenameFile(A2File* pFile, const char* newName); - virtual DIError SetFileInfo(A2File* pFile, long fileType, long auxType, - long accessFlags); - virtual DIError RenameVolume(const char* newName); - - // assorted constants - enum { - kMaxVolumeName = 15, - }; - typedef unsigned long ProDate; - - virtual const char* GetVolumeName(void) const { return fVolumeName; } - virtual const char* GetVolumeID(void) const { return fVolumeID; } - virtual const char* GetBareVolumeName(void) const { return fVolumeName; } - virtual bool GetReadWriteSupported(void) const { return true; } - virtual bool GetFSDamaged(void) const { return !fDiskIsGood; } - virtual long GetFSNumBlocks(void) const { return fTotalBlocks; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const; - - //A2FileProDOS* GetVolDir(void) const { return fpVolDir; } - - static bool IsValidFileName(const char* name); - static bool IsValidVolumeName(const char* name); - static unsigned short GenerateLowerCaseBits(const char* upperName, - const char* lowerName, bool forAppleWorks); - static void GenerateLowerCaseName(const char* upperName, - char* lowerNameNoTerm, unsigned short lcFlags, bool fromAppleWorks); - - friend class A2FDProDOS; - -private: - struct DirHeader; - - enum { kMaxExtensionLen = 4 }; // used when normalizing; ".gif" is 4 - - DIError Initialize(InitMode initMode); - DIError LoadVolHeader(void); - void SetVolumeID(void); - void DumpVolHeader(void); - DIError ScanVolBitmap(void); - DIError LoadVolBitmap(void); - DIError SaveVolBitmap(void); - void FreeVolBitmap(void); - long AllocBlock(void); - int GetNumBitmapBlocks(void) const { - /* use fTotalBlocks rather than GetNumBlocks() */ - assert(fTotalBlocks > 0); - const int kBitsPerBlock = 512 * 8; - int numBlocks = (fTotalBlocks + kBitsPerBlock-1) / kBitsPerBlock; - return numBlocks; - } - DIError CreateEmptyBlockMap(void); - bool GetBlockUseEntry(long block) const; - void SetBlockUseEntry(long block, bool inUse); - bool ScanForExtraEntries(void) const; - - void SetBlockUsage(long block, VolumeUsage::ChunkPurpose purpose); - DIError GetDirHeader(const unsigned char* blkBuf, DirHeader* pHeader); - DIError RecursiveDirAdd(A2File* pParent, unsigned short dirBlock, - const char* basePath, int depth); - DIError SlurpEntries(A2File* pParent, const DirHeader* pHeader, - const unsigned char* blkBuf, bool skipFirst, int* pCount, - const char* basePath, unsigned short thisBlock, int depth); - DIError ReadExtendedInfo(A2FileProDOS* pFile); - DIError ScanFileUsage(void); - void ScanBlockList(long blockCount, unsigned short* blockList, - long indexCount, unsigned short* indexList, long* pSparseCount); - DIError ScanForSubVolumes(void); - DIError FindSubVolume(long blockStart, long blockCount, - DiskImg** ppDiskImg, DiskFS** ppDiskFS); - void MarkSubVolumeBlocks(long block, long count); - - A2File* FindFileByKeyBlock(A2File* pStart, unsigned short keyBlock); - DIError AllocInitialFileStorage(const CreateParms* pParms, - const char* upperName, unsigned short dirBlock, int dirEntrySlot, - long* pKeyBlock, int* pBlocksUsed, int* pNewEOF); - DIError WriteBootBlocks(void); - DIError DoNormalizePath(const char* path, char fssep, - char** pNormalizedPath); - void UpperCaseName(char* upperName, const char* name); - bool CheckDiskIsGood(void); - DIError AllocDirEntry(A2FileDescr* pOpenSubdir, unsigned char** ppDir, - long* pDirLen, unsigned char** ppDirEntry, unsigned short* pDirKeyBlock, - int* pDirEntrySlot, unsigned short* pDirBlock); - unsigned char* GetPrevDirEntry(unsigned char* buf, unsigned char* ptr); - DIError MakeFileNameUnique(const unsigned char* dirBuf, long dirLen, - char* fileName); - bool NameExistsInDir(const unsigned char* dirBuf, long dirLen, - const char* fileName); - - DIError FreeBlocks(long blockCount, unsigned short* blockList); - DIError RegeneratePathName(A2FileProDOS* pFile); - - /* some items from the volume header */ - char fVolumeName[kMaxVolumeName+1]; - char fVolumeID[kMaxVolumeName + 16]; // add "ProDOS /" - unsigned char fAccess; - ProDate fCreateWhen; - ProDate fModWhen; - unsigned short fBitMapPointer; - unsigned short fTotalBlocks; - //unsigned short fPrevBlock; - //unsigned short fNextBlock; - //unsigned char fVersion; - //unsigned char fMinVersion; - //unsigned char fEntryLength; - //unsigned char fEntriesPerBlock; - unsigned short fVolDirFileCount; - -// A2FileProDOS* fpVolDir; // a "fake" file entry for the volume dir - - /* - * This is a working copy of the block use map from blocks 6+. It should - * be loaded when we're about to modify files on the disk and freed - * immediately afterward. The goal is to facilitate speedy updates to the - * bitmap without creating problems if the application decides to modify - * one of the bitmap blocks directly (e.g. with the disk sector editor). - * It should never be held across calls. - */ - unsigned char* fBlockUseMap; - - /* - * Set this if the disk is "perfect". If it's not, we disallow write - * access for safety reasons. - */ - bool fDiskIsGood; - - /* set if something fixes damage so CheckDiskIsGood can't see it */ - bool fEarlyDamage; -}; - -/* - * File descriptor for an open ProDOS file. - * - * This only represents one fork. - */ -class DISKIMG_API A2FDProDOS : public A2FileDescr { -public: - A2FDProDOS(A2File* pFile) : A2FileDescr(pFile), fModified(false), - fBlockList(NULL), fOffset(0) - {} - virtual ~A2FDProDOS(void) { - delete[] fBlockList; - fBlockList = NULL; - } - - friend class A2FileProDOS; - - virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Seek(di_off_t offset, DIWhence whence); - virtual di_off_t Tell(void); - virtual DIError Close(void); - - virtual long GetSectorCount(void) const; - virtual long GetBlockCount(void) const; - virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; - virtual DIError GetStorage(long blockIdx, long* pBlock) const; - - void DumpBlockList(void) const; - -private: - bool IsEmptyBlock(const unsigned char* blk); - DIError WriteDirectory(const void* buf, size_t len, size_t* pActual); - - /* state for open files */ - bool fModified; - long fBlockCount; - unsigned short* fBlockList; - di_off_t fOpenEOF; // current EOF - unsigned short fOpenBlocksUsed; // #of block used by open piece - int fOpenStorageType; - bool fOpenRsrcFork; // is this the resource fork? - di_off_t fOffset; // current file offset -}; - -/* - * Holds a ProDOS file. - */ -class DISKIMG_API A2FileProDOS : public A2File { -public: - A2FileProDOS(DiskFS* pDiskFS) : A2File(pDiskFS) { - fPathName = NULL; - fSparseDataEof = fSparseRsrcEof = -1; - fpOpenFile = NULL; - fParentDirBlock = 0; - fParentDirIdx = -1; - fpParent = NULL; - } - virtual ~A2FileProDOS(void) { - delete fpOpenFile; - delete[] fPathName; - } - - typedef DiskFSProDOS::ProDate ProDate; - - /* assorted constants */ - enum { - kMaxFileName = 15, - kFssep = ':', - kInvalidBlockNum = 1, // boot block, can't be in file - kMaxBlocksPerIndex = 256, - }; - /* ProDOS access permissions */ - enum { - kAccessRead = 0x01, - kAccessWrite = 0x02, - kAccessInvisible = 0x04, - kAccessBackup = 0x20, - kAccessRename = 0x40, - kAccessDelete = 0x80 - }; - /* contents of a directory entry */ - typedef struct DirEntry { - int storageType; - char fileName[kMaxFileName+1]; // shows lower case - unsigned char fileType; - unsigned short keyPointer; - unsigned short blocksUsed; - unsigned long eof; - ProDate createWhen; - unsigned char version; - unsigned char minVersion; - unsigned char access; - unsigned short auxType; - ProDate modWhen; - unsigned short headerPointer; - } DirEntry; - typedef struct ExtendedInfo { - unsigned char storageType; - unsigned short keyBlock; - unsigned short blocksUsed; - unsigned long eof; - } ExtendedInfo; - typedef enum StorageType { - kStorageDeleted = 0, /* indicates deleted file */ - kStorageSeedling = 1, /* <= 512 bytes */ - kStorageSapling = 2, /* < 128KB */ - kStorageTree = 3, /* < 16MB */ - kStoragePascalVolume = 4, /* see ProDOS technote 25 */ - kStorageExtended = 5, /* forked */ - kStorageDirectory = 13, - kStorageSubdirHeader = 14, - kStorageVolumeDirHeader = 15, - } StorageType; - - static bool IsRegularFile(int type) { - return (type == kStorageSeedling || type == kStorageSapling || - type == kStorageTree); - } - - /* - * Implementations of standard interfaces. - */ - virtual const char* GetFileName(void) const { return fDirEntry.fileName; } - virtual const char* GetPathName(void) const { return fPathName; } - virtual char GetFssep(void) const { return kFssep; } - virtual long GetFileType(void) const { return fDirEntry.fileType; } - virtual long GetAuxType(void) const { return fDirEntry.auxType; } - virtual long GetAccess(void) const { return fDirEntry.access; } - virtual time_t GetCreateWhen(void) const; - virtual time_t GetModWhen(void) const; - virtual di_off_t GetDataLength(void) const { - if (GetQuality() == kQualityDamaged) - return 0; - if (fDirEntry.storageType == kStorageExtended) - return fExtData.eof; - else - return fDirEntry.eof; - } - virtual di_off_t GetRsrcLength(void) const { - if (fDirEntry.storageType == kStorageExtended) { - if (GetQuality() == kQualityDamaged) - return 0; - else - return fExtRsrc.eof; - } else - return -1; - } - virtual di_off_t GetDataSparseLength(void) const { - if (GetQuality() == kQualityDamaged) - return 0; - else - return fSparseDataEof; - } - virtual di_off_t GetRsrcSparseLength(void) const { - if (GetQuality() == kQualityDamaged) - return 0; - else - return fSparseRsrcEof; - } - virtual bool IsDirectory(void) const { - return (fDirEntry.storageType == kStorageDirectory || - fDirEntry.storageType == kStorageVolumeDirHeader); - } - virtual bool IsVolumeDirectory(void) const { - return (fDirEntry.storageType == kStorageVolumeDirHeader); - } - - virtual DIError Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork = false); - virtual void CloseDescr(A2FileDescr* pOpenFile) { - assert(pOpenFile == fpOpenFile); - delete fpOpenFile; - fpOpenFile = NULL; - } - virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } - - virtual void SetParent(A2File* pParent) { fpParent = pParent; } - virtual A2File* GetParent(void) const { return fpParent; } - - static char NameToLower(char ch); - static void InitDirEntry(DirEntry* pEntry, - const unsigned char* entryBuf); - - virtual void Dump(void) const; - - /* directory entry contents for this file */ - DirEntry fDirEntry; - - /* pointer to directory entry (update dir if file size or dates change) */ - unsigned short fParentDirBlock; // directory block - int fParentDirIdx; // index in dir block - - /* these are only valid if storageType == kStorageExtended */ - ExtendedInfo fExtData; - ExtendedInfo fExtRsrc; - - void SetPathName(const char* basePath, const char* fileName); - static time_t ConvertProDate(ProDate proDate); - static ProDate ConvertProDate(time_t unixDate); - - /* returns "true" if AppleWorks aux type is used for lower-case name */ - static bool UsesAppleWorksAuxType(unsigned char fileType) { - return (fileType >= 0x19 && fileType <= 0x1b); - } - -#if 0 - /* change fPathName; should only be used by DiskFS rename */ - void SetPathName(const char* name) { - delete[] fPathName; - if (name == NULL) { - fPathName = NULL; - } else { - fPathName = new char[strlen(name)+1]; - if (fPathName != NULL) - strcpy(fPathName, name); - } - } -#endif - - DIError LoadBlockList(int storageType, unsigned short keyBlock, - long eof, long* pBlockCount, unsigned short** pBlockList, - long* pIndexBlockCount=NULL, unsigned short** pIndexBlockList=NULL); - DIError LoadDirectoryBlockList(unsigned short keyBlock, - long eof, long* pBlockCount, unsigned short** pBlockList); - - /* fork lengths without sparseness */ - di_off_t fSparseDataEof; - di_off_t fSparseRsrcEof; - -private: - DIError LoadIndexBlock(unsigned short block, unsigned short* list, - int maxCount); - DIError ValidateBlockList(const unsigned short* list, long count); - - char* fPathName; // full pathname to file on this volume - - A2FDProDOS* fpOpenFile; // only one fork can be open at a time - A2File* fpParent; -}; - - -/* - * =========================================================================== - * Pascal - * =========================================================================== - */ - -/* - * Pascal disk. - * - * There is no allocation map or file index blocks, just a linear collection - * of files with contiguous blocks. - */ -class A2FilePascal; - -class DISKIMG_API DiskFSPascal : public DiskFS { -public: - DiskFSPascal(void) : fDirectory(NULL) {} - virtual ~DiskFSPascal(void) { - if (fDirectory != NULL) { - assert(false); // unexpected - delete[] fDirectory; - } - } - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(); - } - virtual DIError Format(DiskImg* pDiskImg, const char* volName); - - // assorted constants - enum { - kMaxVolumeName = 7, - kDirectoryEntryLen = 26, - }; - typedef unsigned short PascalDate; - - virtual const char* GetVolumeName(void) const { return fVolumeName; } - virtual const char* GetVolumeID(void) const { return fVolumeID; } - virtual const char* GetBareVolumeName(void) const { return fVolumeName; } - virtual bool GetReadWriteSupported(void) const { return true; } - virtual bool GetFSDamaged(void) const { return !fDiskIsGood; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const; - virtual DIError NormalizePath(const char* path, char fssep, - char* normalizedBuf, int* pNormalizedBufLen); - virtual DIError CreateFile(const CreateParms* pParms, A2File** ppNewFile); - virtual DIError DeleteFile(A2File* pFile); - virtual DIError RenameFile(A2File* pFile, const char* newName); - virtual DIError SetFileInfo(A2File* pFile, long fileType, long auxType, - long accessFlags); - virtual DIError RenameVolume(const char* newName); - - static bool IsValidVolumeName(const char* name); - static bool IsValidFileName(const char* name); - - unsigned short GetTotalBlocks(void) const { return fTotalBlocks; } - - friend class A2FDPascal; - -private: - DIError Initialize(void); - DIError LoadVolHeader(void); - void SetVolumeID(void); - void DumpVolHeader(void); - DIError LoadCatalog(void); - DIError SaveCatalog(void); - void FreeCatalog(void); - DIError ProcessCatalog(void); - DIError ScanFileUsage(void); - void SetBlockUsage(long block, VolumeUsage::ChunkPurpose purpose); - DIError WriteBootBlocks(void); - bool CheckDiskIsGood(void); - void DoNormalizePath(const char* name, char fssep, char* outBuf); - DIError MakeFileNameUnique(char* fileName); - DIError FindLargestFreeArea(int *pPrevIdx, A2FilePascal** ppPrevFile); - unsigned char* FindDirEntry(A2FilePascal* pFile); - - enum { kMaxExtensionLen = 5 }; // used when normalizing; ".code" is 4 - - /* some items from the volume header */ - unsigned short fStartBlock; // first block of dir hdr; always 2 - unsigned short fNextBlock; // i.e. first block with data - char fVolumeName[kMaxVolumeName+1]; - char fVolumeID[kMaxVolumeName + 16]; // add "Pascal ___:" - unsigned short fTotalBlocks; - unsigned short fNumFiles; - PascalDate fAccessWhen; // PascalDate last access - PascalDate fDateSetWhen; // PascalDate last date setting - unsigned short fStuff1; // - unsigned short fStuff2; // - - /* other goodies */ - bool fDiskIsGood; - bool fEarlyDamage; - - /* - * Pascal disks have one fixed-size directory. The contents aren't - * divided into blocks, which means you can't always edit an entry - * by loading a single block from disk and writing it back. Also, - * deleted entries are squeezed out, so if we delete an entry we - * have to reshuffle the entries below it. - * - * We want to keep the copy on disk synced up, so we don't hold on - * to this longer than necessary. Possibly less efficient that way; - * if it becomes a problem it's easy enough to change the behavior. - */ - unsigned char* fDirectory; -}; - -/* - * File descriptor for an open Pascal file. - */ -class DISKIMG_API A2FDPascal : public A2FileDescr { -public: - A2FDPascal(A2File* pFile) : A2FileDescr(pFile) { - fOffset = 0; - } - virtual ~A2FDPascal(void) { - /* nothing to clean up */ - } - - friend class A2FilePascal; - - virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Seek(di_off_t offset, DIWhence whence); - virtual di_off_t Tell(void); - virtual DIError Close(void); - - virtual long GetSectorCount(void) const; - virtual long GetBlockCount(void) const; - virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; - virtual DIError GetStorage(long blockIdx, long* pBlock) const; - -private: - di_off_t fOffset; // where we are - di_off_t fOpenEOF; // how big the file currently is - long fOpenBlocksUsed; // how many blocks it occupies - bool fModified; // if modified, update dir on Close -}; - -/* - * File on a Pascal disk. - */ -class DISKIMG_API A2FilePascal : public A2File { -public: - A2FilePascal(DiskFS* pDiskFS) : A2File(pDiskFS) { - fpOpenFile = NULL; - } - virtual ~A2FilePascal(void) { - /* this comes back and calls CloseDescr */ - if (fpOpenFile != NULL) - fpOpenFile->Close(); - } - - typedef DiskFSPascal::PascalDate PascalDate; - - // assorted constants - enum { - kMaxFileName = 15, - }; - typedef enum FileType { - kTypeUntyped = 0, // NON - kTypeXdsk = 1, // BAD (bad blocks) - kTypeCode = 2, // PCD - kTypeText = 3, // PTX - kTypeInfo = 4, // ? - kTypeData = 5, // PDA - kTypeGraf = 6, // ? - kTypeFoto = 7, // FOT? (hires image) - kTypeSecurdir = 8 // ?? - } FileType; - - /* - * Implementations of standard interfaces. - */ - virtual const char* GetFileName(void) const { return fFileName; } - virtual const char* GetPathName(void) const { return fFileName; } - virtual char GetFssep(void) const { return '\0'; } - virtual long GetFileType(void) const; - virtual long GetAuxType(void) const { return 0; } - virtual long GetAccess(void) const { return DiskFS::kFileAccessUnlocked; } - virtual time_t GetCreateWhen(void) const { return 0; } - virtual time_t GetModWhen(void) const; - virtual di_off_t GetDataLength(void) const { return fLength; } - virtual di_off_t GetDataSparseLength(void) const { return fLength; } - virtual di_off_t GetRsrcLength(void) const { return -1; } - virtual di_off_t GetRsrcSparseLength(void) const { return -1; } - - virtual DIError Open(A2FileDescr** pOpenFile, bool readOnly, - bool rsrcFork = false); - virtual void CloseDescr(A2FileDescr* pOpenFile) { - assert(pOpenFile == fpOpenFile); - delete fpOpenFile; - fpOpenFile = NULL; - } - virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } - - - virtual void Dump(void) const; - - static time_t ConvertPascalDate(PascalDate pascalDate); - static A2FilePascal::PascalDate ConvertPascalDate(time_t unixDate); - static A2FilePascal::FileType ConvertFileType(long prodosType); - - /* fields pulled out of directory block */ - unsigned short fStartBlock; - unsigned short fNextBlock; - FileType fFileType; - char fFileName[kMaxFileName+1]; - unsigned short fBytesRemaining; - PascalDate fModWhen; - - /* derived fields */ - di_off_t fLength; - - /* note to self: don't try to store a directory offset here; they shift - every time you add or delete a file */ - -private: - A2FileDescr* fpOpenFile; -}; - - -/* - * =========================================================================== - * CP/M - * =========================================================================== - */ - -/* - * CP/M disk. - * - * We really ought to be using 1K blocks here, since that's the native - * CP/M format, but there's little value in making an exception for such - * a rarely used Apple II format. - * - * There is no allocation map or file index blocks, just a single 2K - * directory filled with files that have up to 16 1K blocks each. If - * a file is longer than 16K, a second entry with the identical name - * and user number is made. These "extents" may be sparse, so it's - * necessary to use the "records" field to determine the actual file length. - */ -class A2FileCPM; -class DISKIMG_API DiskFSCPM : public DiskFS { -public: - DiskFSCPM(void) : fDiskIsGood(false) {} - virtual ~DiskFSCPM(void) {} - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(); - } - - virtual const char* GetVolumeName(void) const { return "CP/M"; } - virtual const char* GetVolumeID(void) const { return "CP/M"; } - virtual const char* GetBareVolumeName(void) const { return NULL; } - virtual bool GetReadWriteSupported(void) const { return false; } - virtual bool GetFSDamaged(void) const { return !fDiskIsGood; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const - { return kDIErrNotSupported; } - - // assorted constants - enum { - kDirectoryEntryLen = 32, - kVolDirBlock = 24, // ProDOS block where volume dir starts - kDirFileNameLen = 11, // 8+3 without the '.' - kFullDirSize = 2048, // blocks 0 and 1 - kDirEntryBlockCount = 16, // #of blocks held in dir slot - kNumDirEntries = kFullDirSize/kDirectoryEntryLen, - kExtentsInLowByte = 32, - - kDirEntryFlagContinued = 0x8000, // "flags" word - }; - // Contents of the raw 32-byte directory entry. - // - // From http://www.seasip.demon.co.uk/Cpm/format31.html - // - // UU F1 F2 F3 F4 F5 F6 F7 F8 T1 T2 T3 EX S1 S2 RC .FILENAMETYP.... - // AL AL AL AL AL AL AL AL AL AL AL AL AL AL AL AL ................ - // - // If the high bit of T1 is set, the file is read-only. If the high - // bit of T2 is set, the file is a "system" file. - // - // An entry with UU=0x20 indicates a CP/M 3.1 disk label entry. - // An entry with UU=0x21 indicates a time stamp entry (2.x or 3.x). - // - // Files larger than (1024 * 16) have multiple "extent" entries, i.e. - // entries with the same user number and file name. - typedef struct DirEntry { - unsigned char userNumber; // 0-15 or 0-31 (usually 0), e5=unused - unsigned char fileName[kDirFileNameLen+1]; - unsigned short extent; // extent (EX + S2 * 32) - unsigned char S1; // Last Record Byte Count (app-specific) - unsigned char records; // #of 128-byte records in this extent - unsigned char blocks[kDirEntryBlockCount]; - bool readOnly; - bool system; - bool badBlockList; // set if block list is damaged - } DirEntry; - - static long CPMToProDOSBlock(long cpmBlock) { - return kVolDirBlock + (cpmBlock*2); - } - -private: - DIError Initialize(void); - DIError ReadCatalog(void); - DIError ScanFileUsage(void); - void SetBlockUsage(long block, VolumeUsage::ChunkPurpose purpose); - void FormatName(char* dstBuf, const char* srcBuf); - DIError ComputeLength(A2FileCPM* pFile); - bool CheckDiskIsGood(void); - - // the full set of raw dir entries - DirEntry fDirEntry[kNumDirEntries]; - - bool fDiskIsGood; -}; - -/* - * File descriptor for an open CP/M file. - */ -class DISKIMG_API A2FDCPM : public A2FileDescr { -public: - A2FDCPM(A2File* pFile) : A2FileDescr(pFile) { - //fOpen = false; - fBlockList = NULL; - } - virtual ~A2FDCPM(void) { - delete fBlockList; - fBlockList = NULL; - } - - friend class A2FileCPM; - - virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Seek(di_off_t offset, DIWhence whence); - virtual di_off_t Tell(void); - virtual DIError Close(void); - - virtual long GetSectorCount(void) const; - virtual long GetBlockCount(void) const; - virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; - virtual DIError GetStorage(long blockIdx, long* pBlock) const; - -private: - //bool fOpen; - di_off_t fOffset; - long fBlockCount; - unsigned char* fBlockList; -}; - -/* - * File on a CP/M disk. - */ -class DISKIMG_API A2FileCPM : public A2File { -public: - typedef DiskFSCPM::DirEntry DirEntry; - - A2FileCPM(DiskFS* pDiskFS, DirEntry* pDirEntry) : - A2File(pDiskFS), fpDirEntry(pDirEntry) - { - fDirIdx = -1; - fpOpenFile = NULL; - } - virtual ~A2FileCPM(void) { - delete fpOpenFile; - } - - // assorted constants - enum { - kMaxFileName = 12, // 8+3 including '.' - }; - - /* - * Implementations of standard interfaces. - */ - virtual const char* GetFileName(void) const { return fFileName; } - virtual const char* GetPathName(void) const { return fFileName; } - virtual char GetFssep(void) const { return '\0'; } - virtual long GetFileType(void) const { return 0; } - virtual long GetAuxType(void) const { return 0; } - virtual long GetAccess(void) const { - if (fReadOnly) - return DiskFS::kFileAccessLocked; - else - return DiskFS::kFileAccessUnlocked; - } - virtual time_t GetCreateWhen(void) const { return 0; } - virtual time_t GetModWhen(void) const { return 0; } - virtual di_off_t GetDataLength(void) const { return fLength; } - virtual di_off_t GetDataSparseLength(void) const { return fLength; } - virtual di_off_t GetRsrcLength(void) const { return -1; } - virtual di_off_t GetRsrcSparseLength(void) const { return -1; } - - virtual DIError Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork = false); - virtual void CloseDescr(A2FileDescr* pOpenFile) { - assert(pOpenFile == fpOpenFile); - delete fpOpenFile; - fpOpenFile = NULL; - } - virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } - - virtual void Dump(void) const; - - /* fields pulled out of directory block */ - char fFileName[kMaxFileName+1]; - bool fReadOnly; - - /* derived fields */ - di_off_t fLength; - int fDirIdx; // index into fDirEntry for part #1 - - DIError GetBlockList(long* pBlockCount, unsigned char* blockBuf) const; - -private: - const DirEntry* fpDirEntry; - A2FileDescr* fpOpenFile; -}; - - -/* - * =========================================================================== - * RDOS - * =========================================================================== - */ - -/* - * RDOS disk. - * - * There is no allocation map or file index blocks, just a linear collection - * of files with contiguous sectors. Very similar to Pascal. - * - * The one interesting quirk is the "converted 13-sector disk" format, where - * only 13 of 16 sectors are actually used. The linear sector addressing - * must take that into account. - */ -class A2FileRDOS; -class DISKIMG_API DiskFSRDOS : public DiskFS { -public: - DiskFSRDOS(void) {} - virtual ~DiskFSRDOS(void) {} - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(); - } - - virtual const char* GetVolumeName(void) const { return fVolumeName; } - virtual const char* GetVolumeID(void) const { return fVolumeName; } - virtual const char* GetBareVolumeName(void) const { return NULL; } - virtual bool GetReadWriteSupported(void) const { return false; } - virtual bool GetFSDamaged(void) const { return false; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const - { return kDIErrNotSupported; } - - int GetOurSectPerTrack(void) const { return fOurSectPerTrack; } - -private: - static DIError TestCommon(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - FSLeniency leniency, DiskImg::FSFormat* pFormatFound); - - DIError Initialize(void); - DIError ReadCatalog(void); - DIError ScanFileUsage(void); - void SetSectorUsage(long track, long sector, - VolumeUsage::ChunkPurpose purpose); - - char fVolumeName[10]; // e.g. "RDOS 3.3" - int fOurSectPerTrack; -}; - -/* - * File descriptor for an open RDOS file. - */ -class DISKIMG_API A2FDRDOS : public A2FileDescr { -public: - A2FDRDOS(A2File* pFile) : A2FileDescr(pFile) { - fOffset = 0; - } - virtual ~A2FDRDOS(void) { - /* nothing to clean up */ - } - - friend class A2FileRDOS; - - virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Seek(di_off_t offset, DIWhence whence); - virtual di_off_t Tell(void); - virtual DIError Close(void); - - virtual long GetSectorCount(void) const; - virtual long GetBlockCount(void) const; - virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; - virtual DIError GetStorage(long blockIdx, long* pBlock) const; - -private: - /* RDOS is unique in that it can put 13-sector disks on 16-sector tracks */ - inline int GetOurSectPerTrack(void) const { - DiskFSRDOS* pDiskFS = (DiskFSRDOS*) fpFile->GetDiskFS(); - return pDiskFS->GetOurSectPerTrack(); - } - - //bool fOpen; - di_off_t fOffset; -}; - -/* - * File on an RDOS disk. - */ -class DISKIMG_API A2FileRDOS : public A2File { -public: - A2FileRDOS(DiskFS* pDiskFS) : A2File(pDiskFS) { - //fOpen = false; - fpOpenFile = NULL; - } - virtual ~A2FileRDOS(void) { - delete fpOpenFile; - } - - // assorted constants - enum { - kMaxFileName = 24, - }; - typedef enum FileType { - kTypeUnknown = 0, - kTypeApplesoft, // 'A' - kTypeBinary, // 'B' - kTypeText, // 'T' - } FileType; - - /* - * Implementations of standard interfaces. - */ - virtual const char* GetFileName(void) const { return fFileName; } - virtual const char* GetPathName(void) const { return fFileName; } - virtual char GetFssep(void) const { return '\0'; } - virtual long GetFileType(void) const; - virtual long GetAuxType(void) const { return fLoadAddr; } - virtual long GetAccess(void) const { return DiskFS::kFileAccessUnlocked; } - virtual time_t GetCreateWhen(void) const { return 0; } - virtual time_t GetModWhen(void) const { return 0; }; - virtual di_off_t GetDataLength(void) const { return fLength; } - virtual di_off_t GetDataSparseLength(void) const { return fLength; } - virtual di_off_t GetRsrcLength(void) const { return -1; } - virtual di_off_t GetRsrcSparseLength(void) const { return -1; } - - virtual DIError Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork = false); - virtual void CloseDescr(A2FileDescr* pOpenFile) { - assert(pOpenFile == fpOpenFile); - delete fpOpenFile; - fpOpenFile = NULL; - } - virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } - - void FixFilename(void); - virtual void Dump(void) const; - - /* fields pulled out of directory block */ - char fFileName[kMaxFileName+1]; - FileType fFileType; - unsigned short fNumSectors; - unsigned short fLoadAddr; - unsigned short fLength; - unsigned short fStartSector; - -private: - void TrimTrailingSpaces(char* filename); - - A2FileDescr* fpOpenFile; -}; - - -/* - * =========================================================================== - * HFS - * =========================================================================== - */ - -/* - * HFS disk. - */ -class A2FileHFS; -class DISKIMG_API DiskFSHFS : public DiskFS { -public: - DiskFSHFS(void) { - fLocalTimeOffset = -1; - fDiskIsGood = true; -#ifndef EXCISE_GPL_CODE - fHfsVol = NULL; -#endif - } - virtual ~DiskFSHFS(void) { -#ifndef EXCISE_GPL_CODE - hfs_callback_close(fHfsVol); - fHfsVol = (hfsvol*) 0xcdaaaacd; -#endif - } - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(initMode); - } - -#ifndef EXCISE_GPL_CODE - /* these are optional, defined as no-ops in the parent class */ - virtual DIError Format(DiskImg* pDiskImg, const char* volName); - virtual DIError NormalizePath(const char* path, char fssep, - char* normalizedBuf, int* pNormalizedBufLen); - virtual DIError CreateFile(const CreateParms* pParms, A2File** ppNewFile); - virtual DIError DeleteFile(A2File* pFile); - virtual DIError RenameFile(A2File* pFile, const char* newName); - virtual DIError SetFileInfo(A2File* pFile, long fileType, long auxType, - long accessFlags); - virtual DIError RenameVolume(const char* newName); -#endif - - // assorted constants - enum { - kMaxVolumeName = 27, - kMaxExtensionLen = 4, // used when normalizing; ".gif" is 4 - }; - - /* mandatory functions */ - virtual const char* GetVolumeName(void) const { return fVolumeName; } - virtual const char* GetVolumeID(void) const { return fVolumeID; } - virtual const char* GetBareVolumeName(void) const { return fVolumeName; } - virtual bool GetReadWriteSupported(void) const { return true; } - virtual bool GetFSDamaged(void) const { return false; } - virtual long GetFSNumBlocks(void) const { return fTotalBlocks; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const; - -#ifndef EXCISE_GPL_CODE - hfsvol* GetHfsVol(void) const { return fHfsVol; } -#endif - - // utility function, used by app - static bool IsValidVolumeName(const char* name); - static bool IsValidFileName(const char* name); - -private: - enum { - // Macintosh 32-bit dates start in 1904, everybody else starts in - // 1970. Take the Mac date and adjust it 66 years plus 17 leap days. - // The annoying part is that HFS stores dates in local time, which - // means it's impossible to know absolutely when a file was modified. - // libhfs converts timestamps to the current time zone, so that a - // file written January 1st 2006 at 6pm in London will appear to have - // been written January 1st 2006 at 6pm in San Francisco if you - // happen to be sitting in California. - // - // This was fixed in HFS+, but we have to deal with it for now. The - // value below converts the date to local time in Greenwich; the - // current GMT offset and daylight saving time must be added to it. - // - // Curiously, the volume dates shown by Cmd-I on the volume on my - // Quadra are off by an hour, even though the file dates match. - kDateTimeOffset = (1970 - 1904) * 60 * 60 * 24 * 365 + - (60 * 60 * 24 * 17), - - kExpectedMinBlocks = 1440, // ignore volumes under 720K - }; - - struct MasterDirBlock; // fwd - static void UnpackMDB(const unsigned char* buf, MasterDirBlock* pMDB); - static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder); - - DIError Initialize(InitMode initMode); - DIError LoadVolHeader(void); - void SetVolumeID(void); - void DumpVolHeader(void); - void SetVolumeUsageMap(void); - -#ifdef EXCISE_GPL_CODE - void CreateFakeFile(void); -#else - DIError RecursiveDirAdd(A2File* pParent, const char* basePath, int depth); - //void Sanitize(unsigned char* str); - DIError DoNormalizePath(const char* path, char fssep, - char** pNormalizedPath); - static int CompareMacFileNames(const char* str1, const char* str2); - DIError RegeneratePathName(A2FileHFS* pFile); - DIError MakeFileNameUnique(const char* pathName, char** pUniqueName); - - /* libhfs stuff */ - static unsigned long LibHFSCB(void* vThis, int op, unsigned long arg1, - void* arg2); - hfsvol* fHfsVol; -#endif - - - /* some items from the volume header */ - char fVolumeName[kMaxVolumeName+1]; - char fVolumeID[kMaxVolumeName + 8]; // add "HFS :" - unsigned long fTotalBlocks; - unsigned long fAllocationBlockSize; - unsigned long fNumAllocationBlocks; - unsigned long fCreatedDateTime; - unsigned long fModifiedDateTime; - unsigned long fNumFiles; - unsigned long fNumDirectories; - - long fLocalTimeOffset; - bool fDiskIsGood; -}; - -/* - * File descriptor for an open HFS file. - */ -class DISKIMG_API A2FDHFS : public A2FileDescr { -public: -#ifdef EXCISE_GPL_CODE - A2FDHFS(A2File* pFile, void* unused) - : A2FileDescr(pFile), fOffset(0) - {} -#else - A2FDHFS(A2File* pFile, hfsfile* pHfsFile) - : A2FileDescr(pFile), fHfsFile(pHfsFile), fModified(false) - {} -#endif - virtual ~A2FDHFS(void) { -#ifndef EXCISE_GPL_CODE - if (fHfsFile != NULL) - hfs_close(fHfsFile); -#endif - } - - friend class A2FileHFS; - - virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Seek(di_off_t offset, DIWhence whence); - virtual di_off_t Tell(void); - virtual DIError Close(void); - - virtual long GetSectorCount(void) const; - virtual long GetBlockCount(void) const; - virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; - virtual DIError GetStorage(long blockIdx, long* pBlock) const; - -private: -#ifdef EXCISE_GPL_CODE - di_off_t fOffset; -#else - hfsfile* fHfsFile; - bool fModified; -#endif -}; - -/* - * File on an HFS disk. - */ -class DISKIMG_API A2FileHFS : public A2File { -public: - A2FileHFS(DiskFS* pDiskFS) : A2File(pDiskFS) { - fPathName = NULL; - fpOpenFile = NULL; -#ifdef EXCISE_GPL_CODE - fFakeFileBuf = NULL; -#else - //fOrigPathName = NULL; -#endif - } - virtual ~A2FileHFS(void) { - delete fpOpenFile; - delete[] fPathName; -#ifdef EXCISE_GPL_CODE - delete[] fFakeFileBuf; -#else - //delete[] fOrigPathName; -#endif - } - - /* - * Implementations of standard interfaces. - */ - virtual const char* GetFileName(void) const { return fFileName; } - virtual const char* GetPathName(void) const { return fPathName; } - virtual char GetFssep(void) const { return kFssep; } - virtual long GetFileType(void) const; - virtual long GetAuxType(void) const; - virtual long GetAccess(void) const { return fAccess; } - virtual time_t GetCreateWhen(void) const { return fCreateWhen; } - virtual time_t GetModWhen(void) const { return fModWhen; } - virtual di_off_t GetDataLength(void) const { return fDataLength; } - virtual di_off_t GetDataSparseLength(void) const { return fDataLength; } - virtual di_off_t GetRsrcLength(void) const { return fRsrcLength; } - virtual di_off_t GetRsrcSparseLength(void) const { return fRsrcLength; } - virtual bool IsDirectory(void) const { return fIsDir; } - virtual bool IsVolumeDirectory(void) const { return fIsVolumeDir; } - - virtual DIError Open(A2FileDescr** pOpenFile, bool readOnly, - bool rsrcFork = false); - virtual void CloseDescr(A2FileDescr* pOpenFile) { - assert(pOpenFile == fpOpenFile); - delete fpOpenFile; - fpOpenFile = NULL; - } - virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } - - enum { - kMaxFileName = 31, - kFssep = ':', - kPdosType = 0x70646f73, // 'pdos' - }; - - void SetPathName(const char* basePath, const char* fileName); - virtual void Dump(void) const; - -#ifdef EXCISE_GPL_CODE - void SetFakeFile(void* buf, long len) { - assert(len > 0); - if (fFakeFileBuf != NULL) - delete[] fFakeFileBuf; - fFakeFileBuf = new char[len]; - memcpy(fFakeFileBuf, buf, len); - fDataLength = len; - } - const void* GetFakeFileBuf(void) const { return fFakeFileBuf; } -#else - void InitEntry(const hfsdirent* dirEntry); - void SetOrigPathName(const char* pathName); - virtual void SetParent(A2File* pParent) { fpParent = pParent; } - virtual A2File* GetParent(void) const { return fpParent; } - char* GetLibHFSPathName(void) const; - static void ConvertTypeToHFS(long fileType, long auxType, - char* pType, char* pCreator); -#endif - - bool fIsDir; - bool fIsVolumeDir; - long fType; - long fCreator; - char fFileName[kMaxFileName+1]; - char* fPathName; - di_off_t fDataLength; - di_off_t fRsrcLength; - time_t fCreateWhen; - time_t fModWhen; - long fAccess; - -private: -#ifdef EXCISE_GPL_CODE - char* fFakeFileBuf; -#else - //char* fOrigPathName; - A2File* fpParent; -#endif - A2FileDescr* fpOpenFile; // only one fork can be open at a time -}; - - -/* - * =========================================================================== - * Gutenberg - * =========================================================================== - */ - -class A2FileGutenberg; - -/* - * Gutenberg disk. - */ -class DISKIMG_API DiskFSGutenberg : public DiskFS { -public: - DiskFSGutenberg(void) : DiskFS() { - fVTOCLoaded = false; - fDiskIsGood = false; - } - virtual ~DiskFSGutenberg(void) {} - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(initMode); - } - - virtual const char* GetVolumeName(void) const { return fDiskVolumeName; } - virtual const char* GetVolumeID(void) const { return fDiskVolumeID; } - virtual const char* GetBareVolumeName(void) const { - return fDiskVolumeName; - } - virtual bool GetReadWriteSupported(void) const { return true; } - virtual bool GetFSDamaged(void) const { return !fDiskIsGood; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const; - - static bool IsValidFileName(const char* name); - static bool IsValidVolumeName(const char* name); - - // utility function - static void LowerASCII(unsigned char* buf, long len); - static void ReplaceFssep(char* str, char replacement); - - enum { - kMinTracks = 17, // need to put the catalog track here - kMaxTracks = 50, - kMaxCatalogSectors = 64, // two tracks on a 32-sector disk - }; - - /* a T/S pair */ - typedef struct TrackSector { - char track; - char sector; - } TrackSector; - - friend class A2FDGutenberg; // for Write - -private: - DIError Initialize(InitMode initMode); - DIError ReadVTOC(void); - void UpdateVolumeNum(void); - void DumpVTOC(void); - void SetSectorUsage(long track, long sector, - VolumeUsage::ChunkPurpose purpose); - void FixVolumeUsageMap(void); - DIError ReadCatalog(void); - DIError ProcessCatalogSector(int catTrack, int catSect, - const unsigned char* sctBuf); - DIError GetFileLengths(void); - DIError ComputeLength(A2FileGutenberg* pFile, const TrackSector* tsList, - int tsCount); - DIError TrimLastSectorUp(A2FileGutenberg* pFile, TrackSector lastTS); - void MarkFileUsage(A2FileGutenberg* pFile, TrackSector* tsList, int tsCount, - TrackSector* indexList, int indexCount); - DIError MakeFileNameUnique(char* fileName); - DIError GetFreeCatalogEntry(TrackSector* pCatSect, int* pCatEntry, - unsigned char* sctBuf, A2FileGutenberg** ppPrevEntry); - void CreateDirEntry(unsigned char* sctBuf, int catEntry, - const char* fileName, TrackSector* pTSSect, unsigned char fileType, - int access); - void FreeTrackSectors(TrackSector* pList, int count); - - bool CheckDiskIsGood(void); - - DIError WriteDOSTracks(int sectPerTrack); - - DIError ScanVolBitmap(void); - DIError LoadVolBitmap(void); - DIError SaveVolBitmap(void); - void FreeVolBitmap(void); - DIError AllocSector(TrackSector* pTS); - DIError CreateEmptyBlockMap(bool withDOS); - bool GetSectorUseEntry(long track, int sector) const; - void SetSectorUseEntry(long track, int sector, bool inUse); - inline unsigned long GetVTOCEntry(const unsigned char* pVTOC, - long track) const; - - // Largest interesting volume is 400K (50 tracks, 32 sectors), but - // we may be looking at it in 16-sector mode, so max tracks is 100. - enum { - kMaxInterestingTracks = 100, - kSectorSize = 256, - kDefaultVolumeNum = 254, - kMaxExtensionLen = 4, // used when normalizing; ".gif" is 4 - }; - - /* some fields from the VTOC */ - int fFirstCatTrack; - int fFirstCatSector; - int fVTOCVolumeNumber; - int fVTOCNumTracks; - int fVTOCNumSectors; - - /* private data */ - char fDiskVolumeName[10]; // - char fDiskVolumeID[11+12+1]; // sizeof "Gutenberg: " + 12 + null - unsigned char fVTOC[kSectorSize]; - bool fVTOCLoaded; - - /* - * There are some things we need to be careful of when reading the - * catalog track, like bad links and infinite loops. By storing a list - * of known good catalog sectors, we only have to handle that stuff once. - * The catalog doesn't grow or shrink, so this never needs to be updated. - */ - TrackSector fCatalogSectors[kMaxCatalogSectors]; - - bool fDiskIsGood; -}; - -/* - * File descriptor for an open Gutenberg file. - */ -class DISKIMG_API A2FDGutenberg : public A2FileDescr { -public: - A2FDGutenberg(A2File* pFile) : A2FileDescr(pFile) { - fOffset = 0; - fModified = false; - } - virtual ~A2FDGutenberg(void) { - } - - friend class A2FileGutenberg; - - virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Seek(di_off_t offset, DIWhence whence); - virtual di_off_t Tell(void); - virtual DIError Close(void); - - virtual long GetSectorCount(void) const; - virtual long GetBlockCount(void) const; - virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; - virtual DIError GetStorage(long blockIdx, long* pBlock) const; - -private: - typedef DiskFSGutenberg::TrackSector TrackSector; - - int fTSCount; - di_off_t fOffset; // current position in file - - di_off_t fOpenEOF; // how big the file currently is - long fOpenSectorsUsed; // how many sectors it occupies - bool fModified; // if modified, update stuff on Close - - void DumpTSList(void) const; -}; - -/* - * Holds Gutenberg files. - * - */ -class DISKIMG_API A2FileGutenberg : public A2File { -public: - A2FileGutenberg(DiskFS* pDiskFS); - virtual ~A2FileGutenberg(void); - - // assorted constants - enum { - kMaxFileName = 12, - }; - typedef enum { - kTypeText = 0x00, // 'T' - } FileType; - - /* - * Implementations of standard interfaces. - */ - virtual const char* GetFileName(void) const { return fFileName; } - virtual const char* GetPathName(void) const { return fFileName; } - virtual char GetFssep(void) const { return '\0'; } - virtual long GetFileType(void) const; - virtual long GetAuxType(void) const { return fAuxType; } - virtual long GetAccess(void) const { return DiskFS::kFileAccessUnlocked; } - virtual time_t GetCreateWhen(void) const { return 0; } - virtual time_t GetModWhen(void) const { return 0; } - virtual di_off_t GetDataLength(void) const { return fLength; } - virtual di_off_t GetDataSparseLength(void) const { return fSparseLength; } - virtual di_off_t GetRsrcLength(void) const { return -1; } - virtual di_off_t GetRsrcSparseLength(void) const { return -1; } - - virtual DIError Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork = false); - virtual void CloseDescr(A2FileDescr* pOpenFile) { - assert(pOpenFile == fpOpenFile); - delete fpOpenFile; - fpOpenFile = NULL; - } - virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } - - void Dump(void) const; - - typedef DiskFSGutenberg::TrackSector TrackSector; - - /* - * Contents of directory entry. - * - * We don't hold deleted or unused entries, so fTSListTrack is always - * valid. - */ - short fTrack; // (could use TrackSector here) - short fSector; - unsigned short fLengthInSectors; - bool fLocked; - char fFileName[kMaxFileName+1]; // "fixed" version - FileType fFileType; - - TrackSector fCatTS; // track/sector for our catalog entry - int fCatEntryNum; // entry number within cat sector - - // these are computed or determined from the file contents - unsigned short fAuxType; // addr for bin, etc. - short fDataOffset; // for 'A'/'B'/'I' with embedded len - di_off_t fLength; // file length, in bytes - di_off_t fSparseLength; // file length, factoring sparse out - - void FixFilename(void); - - static FileType ConvertFileType(long prodosType, di_off_t fileLen); - static bool IsValidType(long prodosType); - static void MakeDOSName(char* buf, const char* name); - static void TrimTrailingSpaces(char* filename); - -private: - DIError ExtractTSPairs(const unsigned char* sctBuf, TrackSector* tsList, - int* pLastNonZero); - - A2FDGutenberg* fpOpenFile; -}; - - -/* - * =========================================================================== - * FAT (including FAT12, FAT16, and FAT32) - * =========================================================================== - */ - -/* - * MS-DOS FAT disk. - * - * This is currently just the minimum necessary to properly recognize - * the disk. - */ -class A2FileFAT; -class DISKIMG_API DiskFSFAT : public DiskFS { -public: - DiskFSFAT(void) {} - virtual ~DiskFSFAT(void) {} - - static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency); - - virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { - SetDiskImg(pImg); - return Initialize(); - } - - // assorted constants - enum { - kMaxVolumeName = 11, - }; - - virtual const char* GetVolumeName(void) const { return fVolumeName; } - virtual const char* GetVolumeID(void) const { return fVolumeID; } - virtual const char* GetBareVolumeName(void) const { return fVolumeName; } - virtual bool GetReadWriteSupported(void) const { return false; } - virtual bool GetFSDamaged(void) const { return false; } - virtual long GetFSNumBlocks(void) const { return fTotalBlocks; } - virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const - { return kDIErrNotSupported; } - -private: - enum { - kExpectedMinBlocks = 720, // ignore volumes under 360K - }; - - struct MasterBootRecord; // fwd - struct BootSector; - static bool UnpackMBR(const unsigned char* buf, MasterBootRecord* pOut); - static bool UnpackBootSector(const unsigned char* buf, BootSector* pOut); - static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder); - - DIError Initialize(void); - DIError LoadVolHeader(void); - void DumpVolHeader(void); - void SetVolumeUsageMap(void); - void CreateFakeFile(void); - - /* some items from the volume header */ - char fVolumeName[kMaxVolumeName+1]; - char fVolumeID[kMaxVolumeName + 8]; // add "FAT %s:" - unsigned long fTotalBlocks; -}; - -/* - * File descriptor for an open FAT file. - */ -class DISKIMG_API A2FDFAT : public A2FileDescr { -public: - A2FDFAT(A2File* pFile) : A2FileDescr(pFile) { - fOffset = 0; - } - virtual ~A2FDFAT(void) { - /* nothing to clean up */ - } - - friend class A2FileFAT; - - virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); - virtual DIError Seek(di_off_t offset, DIWhence whence); - virtual di_off_t Tell(void); - virtual DIError Close(void); - - virtual long GetSectorCount(void) const; - virtual long GetBlockCount(void) const; - virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; - virtual DIError GetStorage(long blockIdx, long* pBlock) const; - -private: - di_off_t fOffset; -}; - -/* - * File on a FAT disk. - */ -class DISKIMG_API A2FileFAT : public A2File { -public: - A2FileFAT(DiskFS* pDiskFS) : A2File(pDiskFS) { - fFakeFileBuf = NULL; - //fFakeFileLen = -1; - fpOpenFile = NULL; - } - virtual ~A2FileFAT(void) { - delete fpOpenFile; - delete[] fFakeFileBuf; - } - - /* - * Implementations of standard interfaces. - */ - virtual const char* GetFileName(void) const { return fFileName; } - virtual const char* GetPathName(void) const { return fFileName; } - virtual char GetFssep(void) const { return '\0'; } - virtual long GetFileType(void) const { return 0; }; - virtual long GetAuxType(void) const { return 0; } - virtual long GetAccess(void) const { return DiskFS::kFileAccessUnlocked; } - virtual time_t GetCreateWhen(void) const { return 0; } - virtual time_t GetModWhen(void) const { return 0; } - virtual di_off_t GetDataLength(void) const { return fLength; } - virtual di_off_t GetDataSparseLength(void) const { return fLength; } - virtual di_off_t GetRsrcLength(void) const { return -1; } - virtual di_off_t GetRsrcSparseLength(void) const { return -1; } - - virtual DIError Open(A2FileDescr** pOpenFile, bool readOnly, - bool rsrcFork = false); - virtual void CloseDescr(A2FileDescr* pOpenFile) { - assert(pOpenFile == fpOpenFile); - delete fpOpenFile; - fpOpenFile = NULL; - } - virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } - - enum { kMaxFileName = 31 }; - - virtual void Dump(void) const; - - void SetFakeFile(void* buf, long len) { - assert(len > 0); - if (fFakeFileBuf != NULL) - delete[] fFakeFileBuf; - fFakeFileBuf = new char[len]; - memcpy(fFakeFileBuf, buf, len); - fLength = len; - } - const void* GetFakeFileBuf(void) const { return fFakeFileBuf; } - - char fFileName[kMaxFileName+1]; - di_off_t fLength; - -private: - char* fFakeFileBuf; - //long fFakeFileLen; - A2FileDescr* fpOpenFile; -}; - -}; // namespace DiskImgLib - -#endif /*__DISKIMGDETAIL__*/ +/* + * CiderPress + * Copyright (C) 2009 by CiderPress authors. All Rights Reserved. + * Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved. + * See the file LICENSE for distribution terms. + */ +/* + * Sub-classes of the base classes defined in DiskImg.h. + * + * Most applications will not need to include this file, because the + * polymorphic interfaces do everything they need. If something needs to + * examine the actual directory structure of a file, it can do so through + * these declarations. + */ +#ifndef __DISKIMGDETAIL__ +#define __DISKIMGDETAIL__ + +#include "../prebuilt/NufxLib.h" +#define ZLIB_DLL +#include "../prebuilt/zlib.h" + +#include "DiskImg.h" + +#ifndef EXCISE_GPL_CODE +# include "libhfs/hfs.h" +#endif + +namespace DiskImgLib { + +/* + * =========================================================================== + * Outer wrappers + * =========================================================================== + */ + +/* + * Outer wrapper class, representing a compression utility or archive + * format that must be stripped away so we can get to the Apple II stuff. + * + * Outer wrappers usually have a filename embedded in them, representing + * the original name of the file. We want to use the extension from this + * name when evaluating the file contents. Usually. + */ +class OuterWrapper { +public: + OuterWrapper(void) {} + virtual ~OuterWrapper(void) {} + + // all sub-classes should have one of these + //static DIError Test(GenericFD* pGFD, long outerLength); + + // open the file and prepare to access it; fills out return values + // NOTE: pGFD must be a GFDFile. + virtual DIError Load(GenericFD* pOuterGFD, di_off_t outerLength, bool readOnly, + di_off_t* pWrapperLength, GenericFD** ppWrapperGFD) = 0; + + virtual DIError Save(GenericFD* pOuterGFD, GenericFD* pWrapperGFD, + di_off_t wrapperLength) = 0; + + // set on recoverable errors, like a CRC failure + virtual bool IsDamaged(void) const = 0; + + // indicate that we don't have a "fast" flush + virtual bool HasFastFlush(void) const { return false; } + + virtual const char* GetExtension(void) const = 0; + +private: + OuterWrapper& operator=(const OuterWrapper&); + OuterWrapper(const OuterWrapper&); +}; + +class OuterGzip : public OuterWrapper { +public: + OuterGzip(void) { fWrapperDamaged = false; } + virtual ~OuterGzip(void) {} + + static DIError Test(GenericFD* pGFD, di_off_t outerLength); + virtual DIError Load(GenericFD* pGFD, di_off_t outerLength, bool readOnly, + di_off_t* pTotalLength, GenericFD** ppNewGFD); + virtual DIError Save(GenericFD* pOuterGFD, GenericFD* pWrapperGFD, + di_off_t wrapperLength); + + virtual bool IsDamaged(void) const { return fWrapperDamaged; } + + virtual const char* GetExtension(void) const { return NULL; } + +private: + DIError ExtractGzipImage(gzFile gzfp, char** pBuf, di_off_t* pLength); + DIError CloseGzip(void); + + // Largest possible ProDOS volume; quite a bit to hold in RAM. Add a + // little extra for .hdv format. + enum { kMaxUncompressedSize = kGzipMax +256 }; + + bool fWrapperDamaged; +}; + +class OuterZip : public OuterWrapper { +public: + OuterZip(void) : fStoredFileName(NULL), fExtension(NULL) {} + virtual ~OuterZip(void) { + delete[] fStoredFileName; + delete[] fExtension; + } + + static DIError Test(GenericFD* pGFD, di_off_t outerLength); + virtual DIError Load(GenericFD* pGFD, di_off_t outerLength, bool readOnly, + di_off_t* pTotalLength, GenericFD** ppNewGFD); + virtual DIError Save(GenericFD* pOuterGFD, GenericFD* pWrapperGFD, + di_off_t wrapperLength); + + virtual bool IsDamaged(void) const { return false; } + + virtual const char* GetExtension(void) const { return fExtension; } + +private: + class LocalFileHeader { + public: + LocalFileHeader(void) : + fVersionToExtract(0), + fGPBitFlag(0), + fCompressionMethod(0), + fLastModFileTime(0), + fLastModFileDate(0), + fCRC32(0), + fCompressedSize(0), + fUncompressedSize(0), + fFileNameLength(0), + fExtraFieldLength(0), + fFileName(NULL) + {} + virtual ~LocalFileHeader(void) { delete[] fFileName; } + + DIError Read(GenericFD* pGFD); + DIError Write(GenericFD* pGFD); + void SetFileName(const char* name); + + // unsigned long fSignature; + unsigned short fVersionToExtract; + unsigned short fGPBitFlag; + unsigned short fCompressionMethod; + unsigned short fLastModFileTime; + unsigned short fLastModFileDate; + unsigned long fCRC32; + unsigned long fCompressedSize; + unsigned long fUncompressedSize; + unsigned short fFileNameLength; + unsigned short fExtraFieldLength; + unsigned char* fFileName; + // extra field + + enum { + kSignature = 0x04034b50, + kLFHLen = 30, // LocalFileHdr len, excl. var fields + }; + + void Dump(void) const; + }; + + class CentralDirEntry { + public: + CentralDirEntry(void) : + fVersionMadeBy(0), + fVersionToExtract(0), + fGPBitFlag(0), + fCompressionMethod(0), + fLastModFileTime(0), + fLastModFileDate(0), + fCRC32(0), + fCompressedSize(0), + fUncompressedSize(0), + fFileNameLength(0), + fExtraFieldLength(0), + fFileCommentLength(0), + fDiskNumberStart(0), + fInternalAttrs(0), + fExternalAttrs(0), + fLocalHeaderRelOffset(0), + fFileName(NULL), + fFileComment(NULL) + {} + virtual ~CentralDirEntry(void) { + delete[] fFileName; + delete[] fFileComment; + } + + DIError Read(GenericFD* pGFD); + DIError Write(GenericFD* pGFD); + void SetFileName(const char* name); + + // unsigned long fSignature; + unsigned short fVersionMadeBy; + unsigned short fVersionToExtract; + unsigned short fGPBitFlag; + unsigned short fCompressionMethod; + unsigned short fLastModFileTime; + unsigned short fLastModFileDate; + unsigned long fCRC32; + unsigned long fCompressedSize; + unsigned long fUncompressedSize; + unsigned short fFileNameLength; + unsigned short fExtraFieldLength; + unsigned short fFileCommentLength; + unsigned short fDiskNumberStart; + unsigned short fInternalAttrs; + unsigned long fExternalAttrs; + unsigned long fLocalHeaderRelOffset; + unsigned char* fFileName; + // extra field + unsigned char* fFileComment; // alloc with new[] + + void Dump(void) const; + + enum { + kSignature = 0x02014b50, + kCDELen = 46, // CentralDirEnt len, excl. var fields + }; + }; + + class EndOfCentralDir { + public: + EndOfCentralDir(void) : + fDiskNumber(0), + fDiskWithCentralDir(0), + fNumEntries(0), + fTotalNumEntries(0), + fCentralDirSize(0), + fCentralDirOffset(0), + fCommentLen(0) + {} + virtual ~EndOfCentralDir(void) {} + + DIError ReadBuf(const unsigned char* buf, int len); + DIError Write(GenericFD* pGFD); + + // unsigned long fSignature; + unsigned short fDiskNumber; + unsigned short fDiskWithCentralDir; + unsigned short fNumEntries; + unsigned short fTotalNumEntries; + unsigned long fCentralDirSize; + unsigned long fCentralDirOffset; // offset from first disk + unsigned short fCommentLen; + // archive comment + + enum { + kSignature = 0x06054b50, + kEOCDLen = 22, // EndOfCentralDir len, excl. comment + }; + + void Dump(void) const; + }; + + enum { + kDataDescriptorSignature = 0x08074b50, + + kMaxCommentLen = 65535, // longest possible in ushort + kMaxEOCDSearch = kMaxCommentLen + EndOfCentralDir::kEOCDLen, + + kZipFssep = '/', + kDefaultVersion = 20, + kMaxUncompressedSize = kGzipMax +256, + }; + enum { + kCompressStored = 0, // no compression + //kCompressShrunk = 1, + //kCompressImploded = 6, + kCompressDeflated = 8, // standard deflate + }; + + static DIError ReadCentralDir(GenericFD* pGFD, di_off_t outerLength, + CentralDirEntry* pDirEntry); + DIError ExtractZipEntry(GenericFD* pOuterGFD, CentralDirEntry* pCDE, + unsigned char** pBuf, di_off_t* pLength); + DIError InflateGFDToBuffer(GenericFD* pGFD, unsigned long compSize, + unsigned long uncompSize, unsigned char* buf); + DIError DeflateGFDToGFD(GenericFD* pDst, GenericFD* pSrc, di_off_t length, + di_off_t* pCompLength, unsigned long* pCRC); + +private: + void SetExtension(const char* ext); + void SetStoredFileName(const char* name); + void GetMSDOSTime(unsigned short* pDate, unsigned short* pTime); + void DOSTime(time_t when, unsigned short* pDate, unsigned short* pTime); + + char* fStoredFileName; + char* fExtension; +}; + + +/* + * =========================================================================== + * Image wrappers + * =========================================================================== + */ + +/* + * Image wrapper class, representing the format of the Windows files. + * Might be "raw" data, might be data with a header, might be a complex + * or compressed format that must be extracted to a buffer. + */ +class ImageWrapper { +public: + ImageWrapper(void) {} + virtual ~ImageWrapper(void) {} + + // all sub-classes should have one of these + // static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); + + // open the file and prepare to access it; fills out return values + virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, + di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) = 0; + + // fill out the wrapper, using the specified parameters + virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, + DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, + di_off_t* pWrappedLength, GenericFD** pDataFD) = 0; + + // push altered data to the wrapper GFD + virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, + di_off_t dataLen, di_off_t* pWrappedLen) = 0; + + // set the storage name (used by some formats) + virtual void SetStorageName(const char* name) { + // default implementation + assert(false); + } + + // indicate that we have a "fast" flush + virtual bool HasFastFlush(void) const = 0; + + // set by "Prep" on recoverable errors, like a CRC failure, for some fmts + virtual bool IsDamaged(void) const { return false; } + + // if this wrapper format includes a file comment, return it + //virtual const char* GetComment(void) const { return NULL; } + + /* + * Some additional goodies required for accessing variable-length nibble + * tracks in TrackStar images. A default implementation is provided and + * used for everything but TrackStar. + */ + virtual int GetNibbleTrackLength(DiskImg::PhysicalFormat physical, int track) const + { + if (physical == DiskImg::kPhysicalFormatNib525_6656) + return kTrackLenNib525; + else if (physical == DiskImg::kPhysicalFormatNib525_6384) + return kTrackLenNb2525; + else { + assert(false); + return -1; + } + } + virtual void SetNibbleTrackLength(int track, int length) { /*do nothing*/ } + virtual int GetNibbleTrackOffset(DiskImg::PhysicalFormat physical, int track) const + { + if (physical == DiskImg::kPhysicalFormatNib525_6656 || + physical == DiskImg::kPhysicalFormatNib525_6384) + { + /* fixed-length tracks */ + return GetNibbleTrackLength(physical, 0) * track; + } else { + assert(false); + return -1; + } + } + // TrackStar images can have more, but otherwise all nibble images have 35 + virtual int GetNibbleNumTracks(void) const + { + return kTrackCount525; + } + +private: + ImageWrapper& operator=(const ImageWrapper&); + ImageWrapper(const ImageWrapper&); +}; + + +class Wrapper2MG : public ImageWrapper { +public: + static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); + virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, + di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); + virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, + DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, + di_off_t* pWrappedLength, GenericFD** pDataFD); + virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, + di_off_t dataLen, di_off_t* pWrappedLen); + virtual bool HasFastFlush(void) const { return true; } + //virtual const char* GetComment(void) const { return NULL; } + // (need to hold TwoImgHeader in the struct, rather than as temp, or + // need to copy the comment out into Wrapper2MG storage e.g. StorageName) +}; + +class WrapperNuFX : public ImageWrapper { +public: + WrapperNuFX(void) : fpArchive(NULL), fThreadIdx(0), fStorageName(NULL), + fCompressType(kNuThreadFormatLZW2) + {} + virtual ~WrapperNuFX(void) { CloseNuFX(); delete[] fStorageName; } + + static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); + virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, + di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); + virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, + DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, + di_off_t* pWrappedLength, GenericFD** pDataFD); + virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, + di_off_t dataLen, di_off_t* pWrappedLen); + virtual bool HasFastFlush(void) const { return false; } + + void SetStorageName(const char* name) { + delete[] fStorageName; + if (name != NULL) { + fStorageName = new char[strlen(name)+1]; + strcpy(fStorageName, name); + } else + fStorageName = NULL; + } + void SetCompressType(NuThreadFormat format) { fCompressType = format; } + +private: + enum { kDefaultStorageFssep = ':' }; + static NuResult ErrMsgHandler(NuArchive* pArchive, void* vErrorMessage); + static DIError OpenNuFX(const char* pathName, NuArchive** ppArchive, + NuThreadIdx* pThreadIdx, long* pLength, bool readOnly); + DIError GetNuFXDiskImage(NuArchive* pArchive, NuThreadIdx threadIdx, + long length, char** ppData); + static char* GenTempPath(const char* path); + DIError CloseNuFX(void); + void UNIXTimeToDateTime(const time_t* pWhen, NuDateTime *pDateTime); + + NuArchive* fpArchive; + NuThreadIdx fThreadIdx; + char* fStorageName; + NuThreadFormat fCompressType; +}; + +class WrapperDiskCopy42 : public ImageWrapper { +public: + WrapperDiskCopy42(void) : fStorageName(NULL), fBadChecksum(false) + {} + virtual ~WrapperDiskCopy42(void) { delete[] fStorageName; } + + static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); + virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, + di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); + virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, + DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, + di_off_t* pWrappedLength, GenericFD** pDataFD); + virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, + di_off_t dataLen, di_off_t* pWrappedLen); + void SetStorageName(const char* name) { + delete[] fStorageName; + if (name != NULL) { + fStorageName = new char[strlen(name)+1]; + strcpy(fStorageName, name); + } else + fStorageName = NULL; + } + + virtual bool HasFastFlush(void) const { return false; } + virtual bool IsDamaged(void) const { return fBadChecksum; } + +private: + typedef struct DC42Header DC42Header; + static void DumpHeader(const DC42Header* pHeader); + void InitHeader(DC42Header* pHeader); + static int ReadHeader(GenericFD* pGFD, DC42Header* pHeader); + DIError WriteHeader(GenericFD* pGFD, const DC42Header* pHeader); + static DIError ComputeChecksum(GenericFD* pGFD, + unsigned long* pChecksum); + + char* fStorageName; + bool fBadChecksum; +}; + +class WrapperDDD : public ImageWrapper { +public: + static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); + virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, + di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); + virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, + DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, + di_off_t* pWrappedLength, GenericFD** pDataFD); + virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, + di_off_t dataLen, di_off_t* pWrappedLen); + virtual bool HasFastFlush(void) const { return false; } + + enum { + kMaxDDDZeroCount = 4, // 3 observed, 4 suspected + }; + +private: + class BitBuffer; + enum { + kNumTracks = 35, + kNumSectors = 16, + kSectorSize = 256, + kTrackLen = kNumSectors * kSectorSize, + }; + + static DIError CheckForRuns(GenericFD* pGFD); + static DIError Unpack(GenericFD* pGFD, GenericFD** ppNewGFD, + short* pDiskVolNum); + + static DIError UnpackDisk(GenericFD* pGFD, GenericFD* pNewGFD, + short* pDiskVolNum); + static bool UnpackTrack(BitBuffer* pBitBuffer, unsigned char* trackBuf); + static DIError PackDisk(GenericFD* pSrcGFD, GenericFD* pWrapperGFD, + short diskVolNum); + static void PackTrack(const unsigned char* trackBuf, BitBuffer* pBitBuf); + static void ComputeFreqCounts(const unsigned char* trackBuf, + unsigned short* freqCounts); + static void ComputeFavorites(unsigned short* freqCounts, + unsigned char* favorites); + + short fDiskVolumeNum; +}; + +class WrapperSim2eHDV : public ImageWrapper { +public: + static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); + virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, + di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); + virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, + DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, + di_off_t* pWrappedLength, GenericFD** pDataFD); + virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, + di_off_t dataLen, di_off_t* pWrappedLen); + virtual bool HasFastFlush(void) const { return true; } +}; + +class WrapperTrackStar : public ImageWrapper { +public: + enum { + kTrackStarNumTracks = 40, + kFileTrackStorageLen = 6656, + kMaxTrackLen = kFileTrackStorageLen - (128+1+2), // header + footer + kCommentFieldLen = 0x2e, + }; + + WrapperTrackStar(void) : fStorageName(NULL) { + memset(&fNibbleTrackInfo, 0, sizeof(fNibbleTrackInfo)); + fNibbleTrackInfo.numTracks = -1; + } + virtual ~WrapperTrackStar(void) { delete[] fStorageName; } + + static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); + virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, + di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); + virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, + DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, + di_off_t* pWrappedLength, GenericFD** pDataFD); + virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, + di_off_t dataLen, di_off_t* pWrappedLen); + virtual bool HasFastFlush(void) const { return false; } + + virtual void SetStorageName(const char* name) + { + delete[] fStorageName; + if (name != NULL) { + fStorageName = new char[strlen(name)+1]; + strcpy(fStorageName, name); + } else + fStorageName = NULL; + } + +private: + static DIError VerifyTrack(int track, const unsigned char* trackBuf); + DIError Unpack(GenericFD* pGFD, GenericFD** ppNewGFD); + DIError UnpackDisk(GenericFD* pGFD, GenericFD* pNewGFD); + + int fImageTracks; + char* fStorageName; + + /* + * Data structure for managing nibble images with variable-length tracks. + */ + typedef struct { + int numTracks; // should be 35 or 40 + int length[kMaxNibbleTracks525]; + int offset[kMaxNibbleTracks525]; + } NibbleTrackInfo; + NibbleTrackInfo fNibbleTrackInfo; // count and lengths for variable formats + + // nibble images can have variable-length data fields + virtual int GetNibbleTrackLength(DiskImg::PhysicalFormat physical, int track) const + { + assert(physical == DiskImg::kPhysicalFormatNib525_Var); + assert(fNibbleTrackInfo.numTracks > 0); + + return fNibbleTrackInfo.length[track]; + } + virtual void SetNibbleTrackLength(int track, int length); +#if 0 + { + assert(track >= 0); + assert(length > 0 && length <= kMaxTrackLen); + assert(track < fNibbleTrackInfo.numTracks); + + fNibbleTrackInfo.length[track] = length; + } +#endif + virtual int GetNibbleTrackOffset(DiskImg::PhysicalFormat physical, int track) const + { + assert(physical == DiskImg::kPhysicalFormatNib525_Var); + assert(fNibbleTrackInfo.numTracks > 0); + + return fNibbleTrackInfo.offset[track]; + } + virtual int GetNibbleNumTracks(void) const + { + return kTrackStarNumTracks; + } +}; + +class WrapperFDI : public ImageWrapper { +public: + WrapperFDI(void) {} + virtual ~WrapperFDI(void) {} + + static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); + virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, + di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); + virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, + DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, + di_off_t* pWrappedLength, GenericFD** pDataFD); + virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, + di_off_t dataLen, di_off_t* pWrappedLen); + virtual bool HasFastFlush(void) const { return false; } + + enum { + kSignatureLen = 27, + kCreatorLen = 30, + kCommentLen = 80, + }; + +private: + static const char* kFDIMagic; + + /* what type of disk is this? */ + typedef enum DiskType { + kDiskType8 = 0, + kDiskType525 = 1, + kDiskType35 = 2, + kDiskType3 = 3 + } DiskType; + + /* + * Contents of FDI header. + */ + typedef struct FDIHeader { + char signature[kSignatureLen+1]; + char creator[kCreatorLen+1]; + // CR + LF + char comment[kCommentLen+1]; + // MS-DOS EOF + unsigned short version; + unsigned short lastTrack; + unsigned char lastHead; + unsigned char type; // DiskType enum + unsigned char rotSpeed; + unsigned char flags; + unsigned char tpi; + unsigned char headWidth; + unsigned short reserved; + // track descriptors follow, at byte 152 + } FDIHeader; + + /* + * Header for pulse-index streams track. + */ + typedef struct PulseIndexHeader { + long numPulses; + long avgStreamLen; + int avgStreamCompression; + long minStreamLen; + int minStreamCompression; + long maxStreamLen; + int maxStreamCompression; + long idxStreamLen; + int idxStreamCompression; + + unsigned long* avgStream; // 4 bytes/pulse + unsigned long* minStream; // 4 bytes/pulse; optional + unsigned long* maxStream; // 4 bytes/pulse; optional + unsigned long* idxStream; // 2 bytes/pulse; optional? + } PulseIndexHeader; + + enum { + kTrackDescrOffset = 152, + kMaxHeads = 2, + kMaxHeaderBlockTracks = 180, // max 90 double-sided cylinders + kMinHeaderLen = 512, + kMinVersion = 0x0200, // v2.0 + + kMaxNibbleTracks35 = 80, // 80 double-sided tracks + kNibbleBufLen = 10240, // max seems to be a little under 10K + kBitBufferSize = kNibbleBufLen + (kNibbleBufLen / 4), + + kMaxSectors35 = 12, // max #of sectors per track + //kBytesPerSector35 = 512, // bytes per sector on 3.5" disk + + kPulseStreamDataOffset = 16, // start of header to avg stream + + kBitRate525 = 250000, // 250Kbits/sec + }; + + /* meaning of the two-bit compression format value */ + typedef enum CompressedFormat { + kCompUncompressed = 0, + kCompHuffman = 1, + } CompressedFormat; + + /* node in the Huffman tree */ + typedef struct HuffNode { + unsigned short val; + struct HuffNode* left; + struct HuffNode* right; + } HuffNode; + + /* + * Keep a copy of the header around while we work. None of the formats + * we're interested in have more than kMaxHeaderBlockTracks tracks in + * them, so we don't need anything beyond the initial 512-byte header. + */ + unsigned char fHeaderBuf[kMinHeaderLen]; + + static void UnpackHeader(const unsigned char* headerBuf, FDIHeader* hdr); + static void DumpHeader(const FDIHeader* pHdr); + + DIError Unpack525(GenericFD* pGFD, GenericFD** ppNewGFD, int numCyls, + int numHeads); + DIError Unpack35(GenericFD* pGFD, GenericFD** ppNewGFD, int numCyls, + int numHeads, LinearBitmap** ppBadBlockMap); + DIError PackDisk(GenericFD* pSrcGFD, GenericFD* pWrapperGFD); + + DIError UnpackDisk525(GenericFD* pGFD, GenericFD* pNewGFD, int numCyls, + int numHeads); + DIError UnpackDisk35(GenericFD* pGFD, GenericFD* pNewGFD, int numCyls, + int numHeads, LinearBitmap* pBadBlockMap); + void GetTrackInfo(int trk, int* pType, int* pLength256); + + int BitRate35(int trk); + void FixBadNibbles(unsigned char* nibbleBuf, long nibbleLen); + bool DecodePulseTrack(const unsigned char* inputBuf, long inputLen, + int bitRate, unsigned char* nibbleBuf, long* pNibbleLen); + bool UncompressPulseStream(const unsigned char* inputBuf, long inputLen, + unsigned long* outputBuf, long numPulses, int format, int bytesPerPulse); + bool ExpandHuffman(const unsigned char* inputBuf, long inputLen, + unsigned long* outputBuf, long numPulses); + const unsigned char* HuffExtractTree(const unsigned char* inputBuf, + HuffNode* pNode, unsigned char* pBits, unsigned char* pBitMask); + const unsigned char* HuffExtractValues16(const unsigned char* inputBuf, + HuffNode* pNode); + const unsigned char* HuffExtractValues8(const unsigned char* inputBuf, + HuffNode* pNode); + void HuffFreeNodes(HuffNode* pNode); + unsigned long HuffSignExtend16(unsigned long val); + unsigned long HuffSignExtend8(unsigned long val); + bool ConvertPulseStreamsToNibbles(PulseIndexHeader* pHdr, int bitRate, + unsigned char* nibbleBuf, long* pNibbleLen); + bool ConvertPulsesToBits(const unsigned long* avgStream, + const unsigned long* minStream, const unsigned long* maxStream, + const unsigned long* idxStream, int numPulses, int maxIndex, + int indexOffset, unsigned long totalAvg, int bitRate, + unsigned char* outputBuf, int* pOutputLen); + int MyRand(void); + bool ConvertBitsToNibbles(const unsigned char* bitBuffer, int bitCount, + unsigned char* nibbleBuf, long* pNibbleLen); + + + int fImageTracks; + char* fStorageName; + + + /* + * Data structure for managing nibble images with variable-length tracks. + */ + typedef struct { + int numTracks; // expect 35 or 40 for 5.25" + int length[kMaxNibbleTracks525]; + int offset[kMaxNibbleTracks525]; + } NibbleTrackInfo; + NibbleTrackInfo fNibbleTrackInfo; // count and lengths for variable formats + + // nibble images can have variable-length data fields + virtual int GetNibbleTrackLength(DiskImg::PhysicalFormat physical, int track) const + { + assert(physical == DiskImg::kPhysicalFormatNib525_Var); + assert(fNibbleTrackInfo.numTracks > 0); + + return fNibbleTrackInfo.length[track]; + } + virtual void SetNibbleTrackLength(int track, int length); + virtual int GetNibbleTrackOffset(DiskImg::PhysicalFormat physical, int track) const + { + assert(physical == DiskImg::kPhysicalFormatNib525_Var); + assert(fNibbleTrackInfo.numTracks > 0); + + return fNibbleTrackInfo.offset[track]; + } + virtual int GetNibbleNumTracks(void) const + { + return fNibbleTrackInfo.numTracks; + } +}; + + +class WrapperUnadornedNibble : public ImageWrapper { +public: + static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); + virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, + di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); + virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, + DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, + di_off_t* pWrappedLength, GenericFD** pDataFD); + virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, + di_off_t dataLen, di_off_t* pWrappedLen); + virtual bool HasFastFlush(void) const { return true; } +}; + +class WrapperUnadornedSector : public ImageWrapper { +public: + static DIError Test(GenericFD* pGFD, di_off_t wrappedLength); + virtual DIError Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, + di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD); + virtual DIError Create(di_off_t length, DiskImg::PhysicalFormat physical, + DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, + di_off_t* pWrappedLength, GenericFD** pDataFD); + virtual DIError Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, + di_off_t dataLen, di_off_t* pWrappedLen); + virtual bool HasFastFlush(void) const { return true; } +}; + + +/* + * =========================================================================== + * Non-FS DiskFSs + * =========================================================================== + */ + +/* + * A "raw" disk, i.e. no filesystem is known. Useful as a placeholder + * for applications that demand a DiskFS object even when the filesystem + * isn't known. + */ +class DISKIMG_API DiskFSUnknown : public DiskFS { +public: + DiskFSUnknown(void) : DiskFS() { + strcpy(fDiskVolumeName, "[Unknown]"); + strcpy(fDiskVolumeID, "Unknown FS"); + } + virtual ~DiskFSUnknown(void) {} + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return kDIErrNone; + } + + virtual const char* GetVolumeName(void) const { return fDiskVolumeName; } + virtual const char* GetVolumeID(void) const { return fDiskVolumeID; } + virtual const char* GetBareVolumeName(void) const { return NULL; } + virtual bool GetReadWriteSupported(void) const { return false; } + virtual bool GetFSDamaged(void) const { return false; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const + { return kDIErrNotSupported; } + + // Use this if *something* is known about the filesystem, e.g. the + // partition type on a MacPart disk. + void SetVolumeInfo(const char* descr) { + if (strlen(descr) > kMaxVolumeName) + return; + + fDiskVolumeName[0] = '['; + strcpy(fDiskVolumeName+1, descr); + strcat(fDiskVolumeName, "]"); + strcpy(fDiskVolumeID, "Unknown FS - "); + strcat(fDiskVolumeID, descr); + } + +private: + enum { kMaxVolumeName = 64 }; + + char fDiskVolumeName[kMaxVolumeName+3]; + char fDiskVolumeID[kMaxVolumeName + 20]; +}; + + +/* + * Generic "container" DiskFS class. Contains some common functions shared + * among classes that are just containers for other filesystems. This class + * is not expected to be instantiated. + * + * TODO: create a common OpenSubVolume() function. + */ +class DISKIMG_API DiskFSContainer : public DiskFS { +public: + DiskFSContainer(void) : DiskFS() {} + virtual ~DiskFSContainer(void) {} + +protected: + virtual const char* GetDebugName(void) = 0; + virtual DIError CreatePlaceholder(long startBlock, long numBlocks, + const char* partName, const char* partType, + DiskImg** ppNewImg, DiskFS** ppNewFS); + virtual void SetVolumeUsageMap(void); +}; + +/* + * UNIDOS disk, an 800K floppy with two 400K DOS 3.3 volumes on it. + * + * The disk itself has no files; instead, it has two embedded sub-volumes. + */ +class DISKIMG_API DiskFSUNIDOS : public DiskFSContainer { +public: + DiskFSUNIDOS(void) : DiskFSContainer() {} + virtual ~DiskFSUNIDOS(void) {} + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + static DIError TestWideFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(); + } + + virtual const char* GetVolumeName(void) const { return "[UNIDOS]"; } + virtual const char* GetVolumeID(void) const { return "[UNIDOS]"; } + virtual const char* GetBareVolumeName(void) const { return NULL; } + virtual bool GetReadWriteSupported(void) const { return false; } + virtual bool GetFSDamaged(void) const { return false; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const + { return kDIErrNotSupported; } + +private: + virtual const char* GetDebugName(void) { return "UNIDOS"; } + DIError Initialize(void); + DIError OpenSubVolume(int idx); +}; + +/* + * OzDOS disk, an 800K floppy with two 400K DOS 3.3 volumes on it. They + * put the files for disk 1 in the odd sectors and the files for disk 2 + * in the even sectors (the top and bottom halves of a 512-byte block). + * + * The disk itself has no files; instead, it has two embedded sub-volumes. + * Because of the funky layout, we have to use the "sector pairing" feature + * of DiskImg to treat this like a DOS 3.3 disk. + */ +class DISKIMG_API DiskFSOzDOS : public DiskFSContainer { +public: + DiskFSOzDOS(void) : DiskFSContainer() {} + virtual ~DiskFSOzDOS(void) {} + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(); + } + + virtual const char* GetVolumeName(void) const { return "[OzDOS]"; } + virtual const char* GetVolumeID(void) const { return "[OzDOS]"; } + virtual const char* GetBareVolumeName(void) const { return NULL; } + virtual bool GetReadWriteSupported(void) const { return false; } + virtual bool GetFSDamaged(void) const { return false; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const + { return kDIErrNotSupported; } + +private: + virtual const char* GetDebugName(void) { return "OzDOS"; } + DIError Initialize(void); + DIError OpenSubVolume(int idx); +}; + +/* + * CFFA volume. A potentially very large volume with multiple partitions. + * + * This DiskFS is just a container that describes the position and sizes + * of the sub-volumes. + */ +class DISKIMG_API DiskFSCFFA : public DiskFSContainer { +public: + DiskFSCFFA(void) : DiskFSContainer() {} + virtual ~DiskFSCFFA(void) {} + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(); + } + + virtual const char* GetVolumeName(void) const { return "[CFFA]"; } + virtual const char* GetVolumeID(void) const { return "[CFFA]"; } + virtual const char* GetBareVolumeName(void) const { return NULL; } + virtual bool GetReadWriteSupported(void) const { return false; } + virtual bool GetFSDamaged(void) const { return false; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const + { return kDIErrNotSupported; } + +private: + virtual const char* GetDebugName(void) { return "CFFA"; } + + static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder, + DiskImg::FSFormat* pFormatFound); + static DIError OpenSubVolume(DiskImg* pImg, long startBlock, + long numBlocks, bool scanOnly, DiskImg** ppNewImg, DiskFS** ppNewFS); + DIError Initialize(void); + DIError FindSubVolumes(void); + DIError AddVolumeSeries(int start, int count, long blocksPerVolume, + long& startBlock, long& totalBlocksLeft); + + enum { + kMinInterestingBlocks = 65536 + 1024, // less than this, ignore + kEarlyVolExpectedSize = 65536, // 32MB in 512-byte blocks + kOneGB = 1024*1024*(1024/512), // 1GB in 512-byte blocks + }; +}; + + +/* + * Macintosh-style partitioned disk image. + * + * This DiskFS is just a container that describes the position and sizes + * of the sub-volumes. + */ +class DISKIMG_API DiskFSMacPart : public DiskFSContainer { +public: + DiskFSMacPart(void) : DiskFSContainer() {} + virtual ~DiskFSMacPart(void) {} + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(); + } + + virtual const char* GetVolumeName(void) const { return "[MacPartition]"; } + virtual const char* GetVolumeID(void) const { return "[MacPartition]"; } + virtual const char* GetBareVolumeName(void) const { return NULL; } + virtual bool GetReadWriteSupported(void) const { return false; } + virtual bool GetFSDamaged(void) const { return false; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const + { return kDIErrNotSupported; } + +private: + virtual const char* GetDebugName(void) { return "MacPart"; } + + struct PartitionMap; // fwd + struct DriverDescriptorRecord; // fwd + static void UnpackDDR(const unsigned char* buf, + DriverDescriptorRecord* pDDR); + static void DumpDDR(const DriverDescriptorRecord* pDDR); + static void UnpackPartitionMap(const unsigned char* buf, + PartitionMap* pMap); + static void DumpPartitionMap(long block, const PartitionMap* pMap); + + static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder); + DIError OpenSubVolume(const PartitionMap* pMap); + DIError Initialize(void); + DIError FindSubVolumes(void); + + enum { + kMinInterestingBlocks = 2048, // less than this, ignore + kDDRSignature = 0x4552, // 'ER' + kPartitionSignature = 0x504d, // 'PM' + }; +}; + + +/* + * Partitioning for Joachim Lange's MicroDrive card. + * + * This DiskFS is just a container that describes the position and sizes + * of the sub-volumes. + */ +class DISKIMG_API DiskFSMicroDrive : public DiskFSContainer { +public: + DiskFSMicroDrive(void) : DiskFSContainer() {} + virtual ~DiskFSMicroDrive(void) {} + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(); + } + + virtual const char* GetVolumeName(void) const { return "[MicroDrive]"; } + virtual const char* GetVolumeID(void) const { return "[MicroDrive]"; } + virtual const char* GetBareVolumeName(void) const { return NULL; } + virtual bool GetReadWriteSupported(void) const { return false; } + virtual bool GetFSDamaged(void) const { return false; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const + { return kDIErrNotSupported; } + +private: + virtual const char* GetDebugName(void) { return "MicroDrive"; } + + struct PartitionMap; // fwd + static void UnpackPartitionMap(const unsigned char* buf, + PartitionMap* pMap); + static void DumpPartitionMap(const PartitionMap* pMap); + + static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder); + DIError OpenSubVolume(long startBlock, long numBlocks); + DIError OpenVol(int idx, long startBlock, long numBlocks); + DIError Initialize(void); + DIError FindSubVolumes(void); + + enum { + kMinInterestingBlocks = 2048, // less than this, ignore + kPartitionSignature = 0xccca, // 'JL' in little-endian high-ASCII + }; +}; + + +/* + * Partitioning for Parsons Engineering FocusDrive card. + * + * This DiskFS is just a container that describes the position and sizes + * of the sub-volumes. + */ +class DISKIMG_API DiskFSFocusDrive : public DiskFSContainer { +public: + DiskFSFocusDrive(void) : DiskFSContainer() {} + virtual ~DiskFSFocusDrive(void) {} + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(); + } + + virtual const char* GetVolumeName(void) const { return "[FocusDrive]"; } + virtual const char* GetVolumeID(void) const { return "[FocusDrive]"; } + virtual const char* GetBareVolumeName(void) const { return NULL; } + virtual bool GetReadWriteSupported(void) const { return false; } + virtual bool GetFSDamaged(void) const { return false; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const + { return kDIErrNotSupported; } + +private: + virtual const char* GetDebugName(void) { return "FocusDrive"; } + + struct PartitionMap; // fwd + static void UnpackPartitionMap(const unsigned char* buf, + const unsigned char* nameBuf, PartitionMap* pMap); + static void DumpPartitionMap(const PartitionMap* pMap); + + static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder); + DIError OpenSubVolume(long startBlock, long numBlocks, + const char* name); + DIError OpenVol(int idx, long startBlock, long numBlocks, + const char* name); + DIError Initialize(void); + DIError FindSubVolumes(void); + + enum { + kMinInterestingBlocks = 2048, // less than this, ignore + }; +}; + + +/* + * =========================================================================== + * DOS 3.2/3.3 + * =========================================================================== + */ + +class A2FileDOS; + +/* + * DOS 3.2/3.3 disk. + */ +class DISKIMG_API DiskFSDOS33 : public DiskFS { +public: + DiskFSDOS33(void) : DiskFS() { + fVTOCLoaded = false; + fDiskIsGood = false; + } + virtual ~DiskFSDOS33(void) {} + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(initMode); + } + virtual DIError Format(DiskImg* pDiskImg, const char* volName); + + virtual const char* GetVolumeName(void) const { return fDiskVolumeName; } + virtual const char* GetVolumeID(void) const { return fDiskVolumeID; } + virtual const char* GetBareVolumeName(void) const { + // this is fragile -- skip over the "DOS" part, return 3 digits + assert(strlen(fDiskVolumeName) > 3); + return fDiskVolumeName+3; + } + virtual bool GetReadWriteSupported(void) const { return true; } + virtual bool GetFSDamaged(void) const { return !fDiskIsGood; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const; + virtual DIError NormalizePath(const char* path, char fssep, + char* normalizedBuf, int* pNormalizedBufLen); + virtual DIError CreateFile(const CreateParms* pParms, A2File** ppNewFile); + virtual DIError DeleteFile(A2File* pFile); + virtual DIError RenameFile(A2File* pFile, const char* newName); + virtual DIError SetFileInfo(A2File* pFile, long fileType, long auxType, + long accessFlags); + virtual DIError RenameVolume(const char* newName); + + /* + * Unique to DOS 3.3 disks. + */ + int GetDiskVolumeNum(void) const { return fDiskVolumeNum; } + void SetDiskVolumeNum(int val); + + static bool IsValidFileName(const char* name); + static bool IsValidVolumeName(const char* name); + + // utility function + static void LowerASCII(unsigned char* buf, long len); + static void ReplaceFssep(char* str, char replacement); + + enum { + kMinTracks = 17, // need to put the catalog track here + kMaxTracks = 50, + kMaxCatalogSectors = 64, // two tracks on a 32-sector disk + }; + + /* a T/S pair */ + typedef struct TrackSector { + char track; + char sector; + } TrackSector; + + friend class A2FDDOS; // for Write + +private: + DIError Initialize(InitMode initMode); + DIError ReadVTOC(void); + void UpdateVolumeNum(void); + void DumpVTOC(void); + void SetSectorUsage(long track, long sector, + VolumeUsage::ChunkPurpose purpose); + void FixVolumeUsageMap(void); + DIError ReadCatalog(void); + DIError ProcessCatalogSector(int catTrack, int catSect, + const unsigned char* sctBuf); + DIError GetFileLengths(void); + DIError ComputeLength(A2FileDOS* pFile, const TrackSector* tsList, + int tsCount); + DIError TrimLastSectorUp(A2FileDOS* pFile, TrackSector lastTS); + void MarkFileUsage(A2FileDOS* pFile, TrackSector* tsList, int tsCount, + TrackSector* indexList, int indexCount); + //DIError TrimLastSectorDown(A2FileDOS* pFile, unsigned short* tsBuf, + // int maxZeroCount); + void DoNormalizePath(const char* name, char fssep, char* outBuf); + DIError MakeFileNameUnique(char* fileName); + DIError GetFreeCatalogEntry(TrackSector* pCatSect, int* pCatEntry, + unsigned char* sctBuf, A2FileDOS** ppPrevEntry); + void CreateDirEntry(unsigned char* sctBuf, int catEntry, + const char* fileName, TrackSector* pTSSect, unsigned char fileType, + int access); + void FreeTrackSectors(TrackSector* pList, int count); + + bool CheckDiskIsGood(void); + + DIError WriteDOSTracks(int sectPerTrack); + + DIError ScanVolBitmap(void); + DIError LoadVolBitmap(void); + DIError SaveVolBitmap(void); + void FreeVolBitmap(void); + DIError AllocSector(TrackSector* pTS); + DIError CreateEmptyBlockMap(bool withDOS); + bool GetSectorUseEntry(long track, int sector) const; + void SetSectorUseEntry(long track, int sector, bool inUse); + inline unsigned long GetVTOCEntry(const unsigned char* pVTOC, + long track) const; + + // Largest interesting volume is 400K (50 tracks, 32 sectors), but + // we may be looking at it in 16-sector mode, so max tracks is 100. + enum { + kMaxInterestingTracks = 100, + kSectorSize = 256, + kDefaultVolumeNum = 254, + kMaxExtensionLen = 4, // used when normalizing; ".gif" is 4 + }; + + // DOS track images, for initializing disk images + static const unsigned char gDOS33Tracks[]; + static const unsigned char gDOS32Tracks[]; + + /* some fields from the VTOC */ + int fFirstCatTrack; + int fFirstCatSector; + int fVTOCVolumeNumber; + int fVTOCNumTracks; + int fVTOCNumSectors; + + /* private data */ + int fDiskVolumeNum; // usually 254 + char fDiskVolumeName[7]; // "DOS" + num, e.g. "DOS001", "DOS254" + char fDiskVolumeID[32]; // sizeof "DOS 3.3 Volume " +3 +1 + unsigned char fVTOC[kSectorSize]; + bool fVTOCLoaded; + + /* + * There are some things we need to be careful of when reading the + * catalog track, like bad links and infinite loops. By storing a list + * of known good catalog sectors, we only have to handle that stuff once. + * The catalog doesn't grow or shrink, so this never needs to be updated. + */ + TrackSector fCatalogSectors[kMaxCatalogSectors]; + + bool fDiskIsGood; +}; + +/* + * File descriptor for an open DOS file. + */ +class DISKIMG_API A2FDDOS : public A2FileDescr { +public: + A2FDDOS(A2File* pFile) : A2FileDescr(pFile) { + fTSList = NULL; + fIndexList = NULL; + fOffset = 0; + fModified = false; + } + virtual ~A2FDDOS(void) { + delete[] fTSList; + delete[] fIndexList; + //fTSList = fIndexList = NULL; + } + + //typedef DiskFSDOS33::TrackSector TrackSector; + + friend class A2FileDOS; + + virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Seek(di_off_t offset, DIWhence whence); + virtual di_off_t Tell(void); + virtual DIError Close(void); + + virtual long GetSectorCount(void) const; + virtual long GetBlockCount(void) const; + virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; + virtual DIError GetStorage(long blockIdx, long* pBlock) const; + +private: + typedef DiskFSDOS33::TrackSector TrackSector; + + TrackSector* fTSList; // T/S entries for data sectors + int fTSCount; + TrackSector* fIndexList; // T/S entries for T/S list sectors + int fIndexCount; + di_off_t fOffset; // current position in file + + di_off_t fOpenEOF; // how big the file currently is + long fOpenSectorsUsed; // how many sectors it occupies + bool fModified; // if modified, update stuff on Close + + void DumpTSList(void) const; +}; + +/* + * Holds DOS files. Works for DOS33, DOS32, and "wide" DOS implementations. + * + * Catalog contents are public so anyone who wants gory details of DOS 3.3 + * stuff can poke at whatever they want. Anybody else can use the virtual + * interfaces to get standardized answers for things like file type. + * + * The embedded address and length fields found in Applesoft, Integer, and + * Binary files are quietly skipped over with the fDataOffset field when + * files are read. + * + * THOUGHT: have "get filename" and "get raw filename" interfaces? There + * are no directories, so maybe we don't care about "raw pathname"?? Might + * be better to always return the "raw" value and let the caller deal with + * things like high ASCII. + */ +class DISKIMG_API A2FileDOS : public A2File { +public: + A2FileDOS(DiskFS* pDiskFS); + virtual ~A2FileDOS(void); + + // assorted constants + enum { + kMaxFileName = 30, + }; + typedef enum { + kTypeUnknown = -1, + kTypeText = 0x00, // 'T' + kTypeInteger = 0x01, // 'I' + kTypeApplesoft = 0x02, // 'A' + kTypeBinary = 0x04, // 'B' + kTypeS = 0x08, // 'S' + kTypeReloc = 0x10, // 'R' + kTypeA = 0x20, // 'A' + kTypeB = 0x40, // 'B' + + kTypeLocked = 0x80 // bitwise OR with previous values + } FileType; + + /* + * Implementations of standard interfaces. + */ + virtual const char* GetFileName(void) const { return fFileName; } + virtual const char* GetPathName(void) const { return fFileName; } + virtual char GetFssep(void) const { return '\0'; } + virtual long GetFileType(void) const; + virtual long GetAuxType(void) const { return fAuxType; } + virtual long GetAccess(void) const; + virtual time_t GetCreateWhen(void) const { return 0; } + virtual time_t GetModWhen(void) const { return 0; } + virtual di_off_t GetDataLength(void) const { return fLength; } + virtual di_off_t GetDataSparseLength(void) const { return fSparseLength; } + virtual di_off_t GetRsrcLength(void) const { return -1; } + virtual di_off_t GetRsrcSparseLength(void) const { return -1; } + + virtual DIError Open(A2FileDescr** ppOpenFile, bool readOnly, + bool rsrcFork = false); + virtual void CloseDescr(A2FileDescr* pOpenFile) { + assert(pOpenFile == fpOpenFile); + delete fpOpenFile; + fpOpenFile = NULL; + } + virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } + + void Dump(void) const; + + typedef DiskFSDOS33::TrackSector TrackSector; + + /* + * Contents of directory entry. + * + * We don't hold deleted or unused entries, so fTSListTrack is always + * valid. + */ + short fTSListTrack; // (could use TrackSector here) + short fTSListSector; + unsigned short fLengthInSectors; + bool fLocked; + char fFileName[kMaxFileName+1]; // "fixed" version + FileType fFileType; + + TrackSector fCatTS; // track/sector for our catalog entry + int fCatEntryNum; // entry number within cat sector + + // these are computed or determined from the file contents + unsigned short fAuxType; // addr for bin, etc. + short fDataOffset; // for 'A'/'B'/'I' with embedded len + di_off_t fLength; // file length, in bytes + di_off_t fSparseLength; // file length, factoring sparse out + + void FixFilename(void); + + DIError LoadTSList(TrackSector** pTSList, int* pTSCount, + TrackSector** pIndexList = NULL, int* pIndexCount = NULL); + static FileType ConvertFileType(long prodosType, di_off_t fileLen); + static bool IsValidType(long prodosType); + static void MakeDOSName(char* buf, const char* name); + static void TrimTrailingSpaces(char* filename); + +private: + DIError ExtractTSPairs(const unsigned char* sctBuf, TrackSector* tsList, + int* pLastNonZero); + + A2FDDOS* fpOpenFile; +}; + + +/* + * =========================================================================== + * ProDOS + * =========================================================================== + */ + +class A2FileProDOS; + +/* + * ProDOS disk. + * + * THOUGHT: it would be undesirable for the CiderPress UI, but it would + * make things somewhat easier internally if we treated the volume dir + * like a subdirectory under which everything else sits, instead of special- + * casing it like we do. This is awkward because volume dirs have names + * under ProDOS, giving every pathname an extra component that they don't + * really need. We can never treat the volume dir purely as a subdir, + * because it can't expand beyond 51 files, but the storage_type in the + * header is sufficient to identify it as such (assuming the disk isn't + * broken). Certain operations, such as changing the file type or aux type, + * simply aren't possible on a volume dir, and deleting a volume dir doesn't + * make sense. So in some respects we simply trade one kind of special-case + * behavior for another. + */ +class DISKIMG_API DiskFSProDOS : public DiskFS { +public: + DiskFSProDOS(void) : fBitMapPointer(0), fTotalBlocks(0), fBlockUseMap(NULL) + {} + virtual ~DiskFSProDOS(void) { + if (fBlockUseMap != NULL) { + assert(false); // unexpected + delete[] fBlockUseMap; + } + } + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(initMode); + } + virtual DIError Format(DiskImg* pDiskImg, const char* volName); + virtual DIError NormalizePath(const char* path, char fssep, + char* normalizedBuf, int* pNormalizedBufLen); + virtual DIError CreateFile(const CreateParms* pParms, A2File** ppNewFile); + virtual DIError DeleteFile(A2File* pFile); + virtual DIError RenameFile(A2File* pFile, const char* newName); + virtual DIError SetFileInfo(A2File* pFile, long fileType, long auxType, + long accessFlags); + virtual DIError RenameVolume(const char* newName); + + // assorted constants + enum { + kMaxVolumeName = 15, + }; + typedef unsigned long ProDate; + + virtual const char* GetVolumeName(void) const { return fVolumeName; } + virtual const char* GetVolumeID(void) const { return fVolumeID; } + virtual const char* GetBareVolumeName(void) const { return fVolumeName; } + virtual bool GetReadWriteSupported(void) const { return true; } + virtual bool GetFSDamaged(void) const { return !fDiskIsGood; } + virtual long GetFSNumBlocks(void) const { return fTotalBlocks; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const; + + //A2FileProDOS* GetVolDir(void) const { return fpVolDir; } + + static bool IsValidFileName(const char* name); + static bool IsValidVolumeName(const char* name); + static unsigned short GenerateLowerCaseBits(const char* upperName, + const char* lowerName, bool forAppleWorks); + static void GenerateLowerCaseName(const char* upperName, + char* lowerNameNoTerm, unsigned short lcFlags, bool fromAppleWorks); + + friend class A2FDProDOS; + +private: + struct DirHeader; + + enum { kMaxExtensionLen = 4 }; // used when normalizing; ".gif" is 4 + + DIError Initialize(InitMode initMode); + DIError LoadVolHeader(void); + void SetVolumeID(void); + void DumpVolHeader(void); + DIError ScanVolBitmap(void); + DIError LoadVolBitmap(void); + DIError SaveVolBitmap(void); + void FreeVolBitmap(void); + long AllocBlock(void); + int GetNumBitmapBlocks(void) const { + /* use fTotalBlocks rather than GetNumBlocks() */ + assert(fTotalBlocks > 0); + const int kBitsPerBlock = 512 * 8; + int numBlocks = (fTotalBlocks + kBitsPerBlock-1) / kBitsPerBlock; + return numBlocks; + } + DIError CreateEmptyBlockMap(void); + bool GetBlockUseEntry(long block) const; + void SetBlockUseEntry(long block, bool inUse); + bool ScanForExtraEntries(void) const; + + void SetBlockUsage(long block, VolumeUsage::ChunkPurpose purpose); + DIError GetDirHeader(const unsigned char* blkBuf, DirHeader* pHeader); + DIError RecursiveDirAdd(A2File* pParent, unsigned short dirBlock, + const char* basePath, int depth); + DIError SlurpEntries(A2File* pParent, const DirHeader* pHeader, + const unsigned char* blkBuf, bool skipFirst, int* pCount, + const char* basePath, unsigned short thisBlock, int depth); + DIError ReadExtendedInfo(A2FileProDOS* pFile); + DIError ScanFileUsage(void); + void ScanBlockList(long blockCount, unsigned short* blockList, + long indexCount, unsigned short* indexList, long* pSparseCount); + DIError ScanForSubVolumes(void); + DIError FindSubVolume(long blockStart, long blockCount, + DiskImg** ppDiskImg, DiskFS** ppDiskFS); + void MarkSubVolumeBlocks(long block, long count); + + A2File* FindFileByKeyBlock(A2File* pStart, unsigned short keyBlock); + DIError AllocInitialFileStorage(const CreateParms* pParms, + const char* upperName, unsigned short dirBlock, int dirEntrySlot, + long* pKeyBlock, int* pBlocksUsed, int* pNewEOF); + DIError WriteBootBlocks(void); + DIError DoNormalizePath(const char* path, char fssep, + char** pNormalizedPath); + void UpperCaseName(char* upperName, const char* name); + bool CheckDiskIsGood(void); + DIError AllocDirEntry(A2FileDescr* pOpenSubdir, unsigned char** ppDir, + long* pDirLen, unsigned char** ppDirEntry, unsigned short* pDirKeyBlock, + int* pDirEntrySlot, unsigned short* pDirBlock); + unsigned char* GetPrevDirEntry(unsigned char* buf, unsigned char* ptr); + DIError MakeFileNameUnique(const unsigned char* dirBuf, long dirLen, + char* fileName); + bool NameExistsInDir(const unsigned char* dirBuf, long dirLen, + const char* fileName); + + DIError FreeBlocks(long blockCount, unsigned short* blockList); + DIError RegeneratePathName(A2FileProDOS* pFile); + + /* some items from the volume header */ + char fVolumeName[kMaxVolumeName+1]; + char fVolumeID[kMaxVolumeName + 16]; // add "ProDOS /" + unsigned char fAccess; + ProDate fCreateWhen; + ProDate fModWhen; + unsigned short fBitMapPointer; + unsigned short fTotalBlocks; + //unsigned short fPrevBlock; + //unsigned short fNextBlock; + //unsigned char fVersion; + //unsigned char fMinVersion; + //unsigned char fEntryLength; + //unsigned char fEntriesPerBlock; + unsigned short fVolDirFileCount; + +// A2FileProDOS* fpVolDir; // a "fake" file entry for the volume dir + + /* + * This is a working copy of the block use map from blocks 6+. It should + * be loaded when we're about to modify files on the disk and freed + * immediately afterward. The goal is to facilitate speedy updates to the + * bitmap without creating problems if the application decides to modify + * one of the bitmap blocks directly (e.g. with the disk sector editor). + * It should never be held across calls. + */ + unsigned char* fBlockUseMap; + + /* + * Set this if the disk is "perfect". If it's not, we disallow write + * access for safety reasons. + */ + bool fDiskIsGood; + + /* set if something fixes damage so CheckDiskIsGood can't see it */ + bool fEarlyDamage; +}; + +/* + * File descriptor for an open ProDOS file. + * + * This only represents one fork. + */ +class DISKIMG_API A2FDProDOS : public A2FileDescr { +public: + A2FDProDOS(A2File* pFile) : A2FileDescr(pFile), fModified(false), + fBlockList(NULL), fOffset(0) + {} + virtual ~A2FDProDOS(void) { + delete[] fBlockList; + fBlockList = NULL; + } + + friend class A2FileProDOS; + + virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Seek(di_off_t offset, DIWhence whence); + virtual di_off_t Tell(void); + virtual DIError Close(void); + + virtual long GetSectorCount(void) const; + virtual long GetBlockCount(void) const; + virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; + virtual DIError GetStorage(long blockIdx, long* pBlock) const; + + void DumpBlockList(void) const; + +private: + bool IsEmptyBlock(const unsigned char* blk); + DIError WriteDirectory(const void* buf, size_t len, size_t* pActual); + + /* state for open files */ + bool fModified; + long fBlockCount; + unsigned short* fBlockList; + di_off_t fOpenEOF; // current EOF + unsigned short fOpenBlocksUsed; // #of block used by open piece + int fOpenStorageType; + bool fOpenRsrcFork; // is this the resource fork? + di_off_t fOffset; // current file offset +}; + +/* + * Holds a ProDOS file. + */ +class DISKIMG_API A2FileProDOS : public A2File { +public: + A2FileProDOS(DiskFS* pDiskFS) : A2File(pDiskFS) { + fPathName = NULL; + fSparseDataEof = fSparseRsrcEof = -1; + fpOpenFile = NULL; + fParentDirBlock = 0; + fParentDirIdx = -1; + fpParent = NULL; + } + virtual ~A2FileProDOS(void) { + delete fpOpenFile; + delete[] fPathName; + } + + typedef DiskFSProDOS::ProDate ProDate; + + /* assorted constants */ + enum { + kMaxFileName = 15, + kFssep = ':', + kInvalidBlockNum = 1, // boot block, can't be in file + kMaxBlocksPerIndex = 256, + }; + /* ProDOS access permissions */ + enum { + kAccessRead = 0x01, + kAccessWrite = 0x02, + kAccessInvisible = 0x04, + kAccessBackup = 0x20, + kAccessRename = 0x40, + kAccessDelete = 0x80 + }; + /* contents of a directory entry */ + typedef struct DirEntry { + int storageType; + char fileName[kMaxFileName+1]; // shows lower case + unsigned char fileType; + unsigned short keyPointer; + unsigned short blocksUsed; + unsigned long eof; + ProDate createWhen; + unsigned char version; + unsigned char minVersion; + unsigned char access; + unsigned short auxType; + ProDate modWhen; + unsigned short headerPointer; + } DirEntry; + typedef struct ExtendedInfo { + unsigned char storageType; + unsigned short keyBlock; + unsigned short blocksUsed; + unsigned long eof; + } ExtendedInfo; + typedef enum StorageType { + kStorageDeleted = 0, /* indicates deleted file */ + kStorageSeedling = 1, /* <= 512 bytes */ + kStorageSapling = 2, /* < 128KB */ + kStorageTree = 3, /* < 16MB */ + kStoragePascalVolume = 4, /* see ProDOS technote 25 */ + kStorageExtended = 5, /* forked */ + kStorageDirectory = 13, + kStorageSubdirHeader = 14, + kStorageVolumeDirHeader = 15, + } StorageType; + + static bool IsRegularFile(int type) { + return (type == kStorageSeedling || type == kStorageSapling || + type == kStorageTree); + } + + /* + * Implementations of standard interfaces. + */ + virtual const char* GetFileName(void) const { return fDirEntry.fileName; } + virtual const char* GetPathName(void) const { return fPathName; } + virtual char GetFssep(void) const { return kFssep; } + virtual long GetFileType(void) const { return fDirEntry.fileType; } + virtual long GetAuxType(void) const { return fDirEntry.auxType; } + virtual long GetAccess(void) const { return fDirEntry.access; } + virtual time_t GetCreateWhen(void) const; + virtual time_t GetModWhen(void) const; + virtual di_off_t GetDataLength(void) const { + if (GetQuality() == kQualityDamaged) + return 0; + if (fDirEntry.storageType == kStorageExtended) + return fExtData.eof; + else + return fDirEntry.eof; + } + virtual di_off_t GetRsrcLength(void) const { + if (fDirEntry.storageType == kStorageExtended) { + if (GetQuality() == kQualityDamaged) + return 0; + else + return fExtRsrc.eof; + } else + return -1; + } + virtual di_off_t GetDataSparseLength(void) const { + if (GetQuality() == kQualityDamaged) + return 0; + else + return fSparseDataEof; + } + virtual di_off_t GetRsrcSparseLength(void) const { + if (GetQuality() == kQualityDamaged) + return 0; + else + return fSparseRsrcEof; + } + virtual bool IsDirectory(void) const { + return (fDirEntry.storageType == kStorageDirectory || + fDirEntry.storageType == kStorageVolumeDirHeader); + } + virtual bool IsVolumeDirectory(void) const { + return (fDirEntry.storageType == kStorageVolumeDirHeader); + } + + virtual DIError Open(A2FileDescr** ppOpenFile, bool readOnly, + bool rsrcFork = false); + virtual void CloseDescr(A2FileDescr* pOpenFile) { + assert(pOpenFile == fpOpenFile); + delete fpOpenFile; + fpOpenFile = NULL; + } + virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } + + virtual void SetParent(A2File* pParent) { fpParent = pParent; } + virtual A2File* GetParent(void) const { return fpParent; } + + static char NameToLower(char ch); + static void InitDirEntry(DirEntry* pEntry, + const unsigned char* entryBuf); + + virtual void Dump(void) const; + + /* directory entry contents for this file */ + DirEntry fDirEntry; + + /* pointer to directory entry (update dir if file size or dates change) */ + unsigned short fParentDirBlock; // directory block + int fParentDirIdx; // index in dir block + + /* these are only valid if storageType == kStorageExtended */ + ExtendedInfo fExtData; + ExtendedInfo fExtRsrc; + + void SetPathName(const char* basePath, const char* fileName); + static time_t ConvertProDate(ProDate proDate); + static ProDate ConvertProDate(time_t unixDate); + + /* returns "true" if AppleWorks aux type is used for lower-case name */ + static bool UsesAppleWorksAuxType(unsigned char fileType) { + return (fileType >= 0x19 && fileType <= 0x1b); + } + +#if 0 + /* change fPathName; should only be used by DiskFS rename */ + void SetPathName(const char* name) { + delete[] fPathName; + if (name == NULL) { + fPathName = NULL; + } else { + fPathName = new char[strlen(name)+1]; + if (fPathName != NULL) + strcpy(fPathName, name); + } + } +#endif + + DIError LoadBlockList(int storageType, unsigned short keyBlock, + long eof, long* pBlockCount, unsigned short** pBlockList, + long* pIndexBlockCount=NULL, unsigned short** pIndexBlockList=NULL); + DIError LoadDirectoryBlockList(unsigned short keyBlock, + long eof, long* pBlockCount, unsigned short** pBlockList); + + /* fork lengths without sparseness */ + di_off_t fSparseDataEof; + di_off_t fSparseRsrcEof; + +private: + DIError LoadIndexBlock(unsigned short block, unsigned short* list, + int maxCount); + DIError ValidateBlockList(const unsigned short* list, long count); + + char* fPathName; // full pathname to file on this volume + + A2FDProDOS* fpOpenFile; // only one fork can be open at a time + A2File* fpParent; +}; + + +/* + * =========================================================================== + * Pascal + * =========================================================================== + */ + +/* + * Pascal disk. + * + * There is no allocation map or file index blocks, just a linear collection + * of files with contiguous blocks. + */ +class A2FilePascal; + +class DISKIMG_API DiskFSPascal : public DiskFS { +public: + DiskFSPascal(void) : fDirectory(NULL) {} + virtual ~DiskFSPascal(void) { + if (fDirectory != NULL) { + assert(false); // unexpected + delete[] fDirectory; + } + } + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(); + } + virtual DIError Format(DiskImg* pDiskImg, const char* volName); + + // assorted constants + enum { + kMaxVolumeName = 7, + kDirectoryEntryLen = 26, + }; + typedef unsigned short PascalDate; + + virtual const char* GetVolumeName(void) const { return fVolumeName; } + virtual const char* GetVolumeID(void) const { return fVolumeID; } + virtual const char* GetBareVolumeName(void) const { return fVolumeName; } + virtual bool GetReadWriteSupported(void) const { return true; } + virtual bool GetFSDamaged(void) const { return !fDiskIsGood; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const; + virtual DIError NormalizePath(const char* path, char fssep, + char* normalizedBuf, int* pNormalizedBufLen); + virtual DIError CreateFile(const CreateParms* pParms, A2File** ppNewFile); + virtual DIError DeleteFile(A2File* pFile); + virtual DIError RenameFile(A2File* pFile, const char* newName); + virtual DIError SetFileInfo(A2File* pFile, long fileType, long auxType, + long accessFlags); + virtual DIError RenameVolume(const char* newName); + + static bool IsValidVolumeName(const char* name); + static bool IsValidFileName(const char* name); + + unsigned short GetTotalBlocks(void) const { return fTotalBlocks; } + + friend class A2FDPascal; + +private: + DIError Initialize(void); + DIError LoadVolHeader(void); + void SetVolumeID(void); + void DumpVolHeader(void); + DIError LoadCatalog(void); + DIError SaveCatalog(void); + void FreeCatalog(void); + DIError ProcessCatalog(void); + DIError ScanFileUsage(void); + void SetBlockUsage(long block, VolumeUsage::ChunkPurpose purpose); + DIError WriteBootBlocks(void); + bool CheckDiskIsGood(void); + void DoNormalizePath(const char* name, char fssep, char* outBuf); + DIError MakeFileNameUnique(char* fileName); + DIError FindLargestFreeArea(int *pPrevIdx, A2FilePascal** ppPrevFile); + unsigned char* FindDirEntry(A2FilePascal* pFile); + + enum { kMaxExtensionLen = 5 }; // used when normalizing; ".code" is 4 + + /* some items from the volume header */ + unsigned short fStartBlock; // first block of dir hdr; always 2 + unsigned short fNextBlock; // i.e. first block with data + char fVolumeName[kMaxVolumeName+1]; + char fVolumeID[kMaxVolumeName + 16]; // add "Pascal ___:" + unsigned short fTotalBlocks; + unsigned short fNumFiles; + PascalDate fAccessWhen; // PascalDate last access + PascalDate fDateSetWhen; // PascalDate last date setting + unsigned short fStuff1; // + unsigned short fStuff2; // + + /* other goodies */ + bool fDiskIsGood; + bool fEarlyDamage; + + /* + * Pascal disks have one fixed-size directory. The contents aren't + * divided into blocks, which means you can't always edit an entry + * by loading a single block from disk and writing it back. Also, + * deleted entries are squeezed out, so if we delete an entry we + * have to reshuffle the entries below it. + * + * We want to keep the copy on disk synced up, so we don't hold on + * to this longer than necessary. Possibly less efficient that way; + * if it becomes a problem it's easy enough to change the behavior. + */ + unsigned char* fDirectory; +}; + +/* + * File descriptor for an open Pascal file. + */ +class DISKIMG_API A2FDPascal : public A2FileDescr { +public: + A2FDPascal(A2File* pFile) : A2FileDescr(pFile) { + fOffset = 0; + } + virtual ~A2FDPascal(void) { + /* nothing to clean up */ + } + + friend class A2FilePascal; + + virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Seek(di_off_t offset, DIWhence whence); + virtual di_off_t Tell(void); + virtual DIError Close(void); + + virtual long GetSectorCount(void) const; + virtual long GetBlockCount(void) const; + virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; + virtual DIError GetStorage(long blockIdx, long* pBlock) const; + +private: + di_off_t fOffset; // where we are + di_off_t fOpenEOF; // how big the file currently is + long fOpenBlocksUsed; // how many blocks it occupies + bool fModified; // if modified, update dir on Close +}; + +/* + * File on a Pascal disk. + */ +class DISKIMG_API A2FilePascal : public A2File { +public: + A2FilePascal(DiskFS* pDiskFS) : A2File(pDiskFS) { + fpOpenFile = NULL; + } + virtual ~A2FilePascal(void) { + /* this comes back and calls CloseDescr */ + if (fpOpenFile != NULL) + fpOpenFile->Close(); + } + + typedef DiskFSPascal::PascalDate PascalDate; + + // assorted constants + enum { + kMaxFileName = 15, + }; + typedef enum FileType { + kTypeUntyped = 0, // NON + kTypeXdsk = 1, // BAD (bad blocks) + kTypeCode = 2, // PCD + kTypeText = 3, // PTX + kTypeInfo = 4, // ? + kTypeData = 5, // PDA + kTypeGraf = 6, // ? + kTypeFoto = 7, // FOT? (hires image) + kTypeSecurdir = 8 // ?? + } FileType; + + /* + * Implementations of standard interfaces. + */ + virtual const char* GetFileName(void) const { return fFileName; } + virtual const char* GetPathName(void) const { return fFileName; } + virtual char GetFssep(void) const { return '\0'; } + virtual long GetFileType(void) const; + virtual long GetAuxType(void) const { return 0; } + virtual long GetAccess(void) const { return DiskFS::kFileAccessUnlocked; } + virtual time_t GetCreateWhen(void) const { return 0; } + virtual time_t GetModWhen(void) const; + virtual di_off_t GetDataLength(void) const { return fLength; } + virtual di_off_t GetDataSparseLength(void) const { return fLength; } + virtual di_off_t GetRsrcLength(void) const { return -1; } + virtual di_off_t GetRsrcSparseLength(void) const { return -1; } + + virtual DIError Open(A2FileDescr** pOpenFile, bool readOnly, + bool rsrcFork = false); + virtual void CloseDescr(A2FileDescr* pOpenFile) { + assert(pOpenFile == fpOpenFile); + delete fpOpenFile; + fpOpenFile = NULL; + } + virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } + + + virtual void Dump(void) const; + + static time_t ConvertPascalDate(PascalDate pascalDate); + static A2FilePascal::PascalDate ConvertPascalDate(time_t unixDate); + static A2FilePascal::FileType ConvertFileType(long prodosType); + + /* fields pulled out of directory block */ + unsigned short fStartBlock; + unsigned short fNextBlock; + FileType fFileType; + char fFileName[kMaxFileName+1]; + unsigned short fBytesRemaining; + PascalDate fModWhen; + + /* derived fields */ + di_off_t fLength; + + /* note to self: don't try to store a directory offset here; they shift + every time you add or delete a file */ + +private: + A2FileDescr* fpOpenFile; +}; + + +/* + * =========================================================================== + * CP/M + * =========================================================================== + */ + +/* + * CP/M disk. + * + * We really ought to be using 1K blocks here, since that's the native + * CP/M format, but there's little value in making an exception for such + * a rarely used Apple II format. + * + * There is no allocation map or file index blocks, just a single 2K + * directory filled with files that have up to 16 1K blocks each. If + * a file is longer than 16K, a second entry with the identical name + * and user number is made. These "extents" may be sparse, so it's + * necessary to use the "records" field to determine the actual file length. + */ +class A2FileCPM; +class DISKIMG_API DiskFSCPM : public DiskFS { +public: + DiskFSCPM(void) : fDiskIsGood(false) {} + virtual ~DiskFSCPM(void) {} + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(); + } + + virtual const char* GetVolumeName(void) const { return "CP/M"; } + virtual const char* GetVolumeID(void) const { return "CP/M"; } + virtual const char* GetBareVolumeName(void) const { return NULL; } + virtual bool GetReadWriteSupported(void) const { return false; } + virtual bool GetFSDamaged(void) const { return !fDiskIsGood; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const + { return kDIErrNotSupported; } + + // assorted constants + enum { + kDirectoryEntryLen = 32, + kVolDirBlock = 24, // ProDOS block where volume dir starts + kDirFileNameLen = 11, // 8+3 without the '.' + kFullDirSize = 2048, // blocks 0 and 1 + kDirEntryBlockCount = 16, // #of blocks held in dir slot + kNumDirEntries = kFullDirSize/kDirectoryEntryLen, + kExtentsInLowByte = 32, + + kDirEntryFlagContinued = 0x8000, // "flags" word + }; + // Contents of the raw 32-byte directory entry. + // + // From http://www.seasip.demon.co.uk/Cpm/format31.html + // + // UU F1 F2 F3 F4 F5 F6 F7 F8 T1 T2 T3 EX S1 S2 RC .FILENAMETYP.... + // AL AL AL AL AL AL AL AL AL AL AL AL AL AL AL AL ................ + // + // If the high bit of T1 is set, the file is read-only. If the high + // bit of T2 is set, the file is a "system" file. + // + // An entry with UU=0x20 indicates a CP/M 3.1 disk label entry. + // An entry with UU=0x21 indicates a time stamp entry (2.x or 3.x). + // + // Files larger than (1024 * 16) have multiple "extent" entries, i.e. + // entries with the same user number and file name. + typedef struct DirEntry { + unsigned char userNumber; // 0-15 or 0-31 (usually 0), e5=unused + unsigned char fileName[kDirFileNameLen+1]; + unsigned short extent; // extent (EX + S2 * 32) + unsigned char S1; // Last Record Byte Count (app-specific) + unsigned char records; // #of 128-byte records in this extent + unsigned char blocks[kDirEntryBlockCount]; + bool readOnly; + bool system; + bool badBlockList; // set if block list is damaged + } DirEntry; + + static long CPMToProDOSBlock(long cpmBlock) { + return kVolDirBlock + (cpmBlock*2); + } + +private: + DIError Initialize(void); + DIError ReadCatalog(void); + DIError ScanFileUsage(void); + void SetBlockUsage(long block, VolumeUsage::ChunkPurpose purpose); + void FormatName(char* dstBuf, const char* srcBuf); + DIError ComputeLength(A2FileCPM* pFile); + bool CheckDiskIsGood(void); + + // the full set of raw dir entries + DirEntry fDirEntry[kNumDirEntries]; + + bool fDiskIsGood; +}; + +/* + * File descriptor for an open CP/M file. + */ +class DISKIMG_API A2FDCPM : public A2FileDescr { +public: + A2FDCPM(A2File* pFile) : A2FileDescr(pFile) { + //fOpen = false; + fBlockList = NULL; + } + virtual ~A2FDCPM(void) { + delete fBlockList; + fBlockList = NULL; + } + + friend class A2FileCPM; + + virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Seek(di_off_t offset, DIWhence whence); + virtual di_off_t Tell(void); + virtual DIError Close(void); + + virtual long GetSectorCount(void) const; + virtual long GetBlockCount(void) const; + virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; + virtual DIError GetStorage(long blockIdx, long* pBlock) const; + +private: + //bool fOpen; + di_off_t fOffset; + long fBlockCount; + unsigned char* fBlockList; +}; + +/* + * File on a CP/M disk. + */ +class DISKIMG_API A2FileCPM : public A2File { +public: + typedef DiskFSCPM::DirEntry DirEntry; + + A2FileCPM(DiskFS* pDiskFS, DirEntry* pDirEntry) : + A2File(pDiskFS), fpDirEntry(pDirEntry) + { + fDirIdx = -1; + fpOpenFile = NULL; + } + virtual ~A2FileCPM(void) { + delete fpOpenFile; + } + + // assorted constants + enum { + kMaxFileName = 12, // 8+3 including '.' + }; + + /* + * Implementations of standard interfaces. + */ + virtual const char* GetFileName(void) const { return fFileName; } + virtual const char* GetPathName(void) const { return fFileName; } + virtual char GetFssep(void) const { return '\0'; } + virtual long GetFileType(void) const { return 0; } + virtual long GetAuxType(void) const { return 0; } + virtual long GetAccess(void) const { + if (fReadOnly) + return DiskFS::kFileAccessLocked; + else + return DiskFS::kFileAccessUnlocked; + } + virtual time_t GetCreateWhen(void) const { return 0; } + virtual time_t GetModWhen(void) const { return 0; } + virtual di_off_t GetDataLength(void) const { return fLength; } + virtual di_off_t GetDataSparseLength(void) const { return fLength; } + virtual di_off_t GetRsrcLength(void) const { return -1; } + virtual di_off_t GetRsrcSparseLength(void) const { return -1; } + + virtual DIError Open(A2FileDescr** ppOpenFile, bool readOnly, + bool rsrcFork = false); + virtual void CloseDescr(A2FileDescr* pOpenFile) { + assert(pOpenFile == fpOpenFile); + delete fpOpenFile; + fpOpenFile = NULL; + } + virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } + + virtual void Dump(void) const; + + /* fields pulled out of directory block */ + char fFileName[kMaxFileName+1]; + bool fReadOnly; + + /* derived fields */ + di_off_t fLength; + int fDirIdx; // index into fDirEntry for part #1 + + DIError GetBlockList(long* pBlockCount, unsigned char* blockBuf) const; + +private: + const DirEntry* fpDirEntry; + A2FileDescr* fpOpenFile; +}; + + +/* + * =========================================================================== + * RDOS + * =========================================================================== + */ + +/* + * RDOS disk. + * + * There is no allocation map or file index blocks, just a linear collection + * of files with contiguous sectors. Very similar to Pascal. + * + * The one interesting quirk is the "converted 13-sector disk" format, where + * only 13 of 16 sectors are actually used. The linear sector addressing + * must take that into account. + */ +class A2FileRDOS; +class DISKIMG_API DiskFSRDOS : public DiskFS { +public: + DiskFSRDOS(void) {} + virtual ~DiskFSRDOS(void) {} + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(); + } + + virtual const char* GetVolumeName(void) const { return fVolumeName; } + virtual const char* GetVolumeID(void) const { return fVolumeName; } + virtual const char* GetBareVolumeName(void) const { return NULL; } + virtual bool GetReadWriteSupported(void) const { return false; } + virtual bool GetFSDamaged(void) const { return false; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const + { return kDIErrNotSupported; } + + int GetOurSectPerTrack(void) const { return fOurSectPerTrack; } + +private: + static DIError TestCommon(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + FSLeniency leniency, DiskImg::FSFormat* pFormatFound); + + DIError Initialize(void); + DIError ReadCatalog(void); + DIError ScanFileUsage(void); + void SetSectorUsage(long track, long sector, + VolumeUsage::ChunkPurpose purpose); + + char fVolumeName[10]; // e.g. "RDOS 3.3" + int fOurSectPerTrack; +}; + +/* + * File descriptor for an open RDOS file. + */ +class DISKIMG_API A2FDRDOS : public A2FileDescr { +public: + A2FDRDOS(A2File* pFile) : A2FileDescr(pFile) { + fOffset = 0; + } + virtual ~A2FDRDOS(void) { + /* nothing to clean up */ + } + + friend class A2FileRDOS; + + virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Seek(di_off_t offset, DIWhence whence); + virtual di_off_t Tell(void); + virtual DIError Close(void); + + virtual long GetSectorCount(void) const; + virtual long GetBlockCount(void) const; + virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; + virtual DIError GetStorage(long blockIdx, long* pBlock) const; + +private: + /* RDOS is unique in that it can put 13-sector disks on 16-sector tracks */ + inline int GetOurSectPerTrack(void) const { + DiskFSRDOS* pDiskFS = (DiskFSRDOS*) fpFile->GetDiskFS(); + return pDiskFS->GetOurSectPerTrack(); + } + + //bool fOpen; + di_off_t fOffset; +}; + +/* + * File on an RDOS disk. + */ +class DISKIMG_API A2FileRDOS : public A2File { +public: + A2FileRDOS(DiskFS* pDiskFS) : A2File(pDiskFS) { + //fOpen = false; + fpOpenFile = NULL; + } + virtual ~A2FileRDOS(void) { + delete fpOpenFile; + } + + // assorted constants + enum { + kMaxFileName = 24, + }; + typedef enum FileType { + kTypeUnknown = 0, + kTypeApplesoft, // 'A' + kTypeBinary, // 'B' + kTypeText, // 'T' + } FileType; + + /* + * Implementations of standard interfaces. + */ + virtual const char* GetFileName(void) const { return fFileName; } + virtual const char* GetPathName(void) const { return fFileName; } + virtual char GetFssep(void) const { return '\0'; } + virtual long GetFileType(void) const; + virtual long GetAuxType(void) const { return fLoadAddr; } + virtual long GetAccess(void) const { return DiskFS::kFileAccessUnlocked; } + virtual time_t GetCreateWhen(void) const { return 0; } + virtual time_t GetModWhen(void) const { return 0; }; + virtual di_off_t GetDataLength(void) const { return fLength; } + virtual di_off_t GetDataSparseLength(void) const { return fLength; } + virtual di_off_t GetRsrcLength(void) const { return -1; } + virtual di_off_t GetRsrcSparseLength(void) const { return -1; } + + virtual DIError Open(A2FileDescr** ppOpenFile, bool readOnly, + bool rsrcFork = false); + virtual void CloseDescr(A2FileDescr* pOpenFile) { + assert(pOpenFile == fpOpenFile); + delete fpOpenFile; + fpOpenFile = NULL; + } + virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } + + void FixFilename(void); + virtual void Dump(void) const; + + /* fields pulled out of directory block */ + char fFileName[kMaxFileName+1]; + FileType fFileType; + unsigned short fNumSectors; + unsigned short fLoadAddr; + unsigned short fLength; + unsigned short fStartSector; + +private: + void TrimTrailingSpaces(char* filename); + + A2FileDescr* fpOpenFile; +}; + + +/* + * =========================================================================== + * HFS + * =========================================================================== + */ + +/* + * HFS disk. + */ +class A2FileHFS; +class DISKIMG_API DiskFSHFS : public DiskFS { +public: + DiskFSHFS(void) { + fLocalTimeOffset = -1; + fDiskIsGood = true; +#ifndef EXCISE_GPL_CODE + fHfsVol = NULL; +#endif + } + virtual ~DiskFSHFS(void) { +#ifndef EXCISE_GPL_CODE + hfs_callback_close(fHfsVol); + fHfsVol = (hfsvol*) 0xcdaaaacd; +#endif + } + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(initMode); + } + +#ifndef EXCISE_GPL_CODE + /* these are optional, defined as no-ops in the parent class */ + virtual DIError Format(DiskImg* pDiskImg, const char* volName); + virtual DIError NormalizePath(const char* path, char fssep, + char* normalizedBuf, int* pNormalizedBufLen); + virtual DIError CreateFile(const CreateParms* pParms, A2File** ppNewFile); + virtual DIError DeleteFile(A2File* pFile); + virtual DIError RenameFile(A2File* pFile, const char* newName); + virtual DIError SetFileInfo(A2File* pFile, long fileType, long auxType, + long accessFlags); + virtual DIError RenameVolume(const char* newName); +#endif + + // assorted constants + enum { + kMaxVolumeName = 27, + kMaxExtensionLen = 4, // used when normalizing; ".gif" is 4 + }; + + /* mandatory functions */ + virtual const char* GetVolumeName(void) const { return fVolumeName; } + virtual const char* GetVolumeID(void) const { return fVolumeID; } + virtual const char* GetBareVolumeName(void) const { return fVolumeName; } + virtual bool GetReadWriteSupported(void) const { return true; } + virtual bool GetFSDamaged(void) const { return false; } + virtual long GetFSNumBlocks(void) const { return fTotalBlocks; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const; + +#ifndef EXCISE_GPL_CODE + hfsvol* GetHfsVol(void) const { return fHfsVol; } +#endif + + // utility function, used by app + static bool IsValidVolumeName(const char* name); + static bool IsValidFileName(const char* name); + +private: + enum { + // Macintosh 32-bit dates start in 1904, everybody else starts in + // 1970. Take the Mac date and adjust it 66 years plus 17 leap days. + // The annoying part is that HFS stores dates in local time, which + // means it's impossible to know absolutely when a file was modified. + // libhfs converts timestamps to the current time zone, so that a + // file written January 1st 2006 at 6pm in London will appear to have + // been written January 1st 2006 at 6pm in San Francisco if you + // happen to be sitting in California. + // + // This was fixed in HFS+, but we have to deal with it for now. The + // value below converts the date to local time in Greenwich; the + // current GMT offset and daylight saving time must be added to it. + // + // Curiously, the volume dates shown by Cmd-I on the volume on my + // Quadra are off by an hour, even though the file dates match. + kDateTimeOffset = (1970 - 1904) * 60 * 60 * 24 * 365 + + (60 * 60 * 24 * 17), + + kExpectedMinBlocks = 1440, // ignore volumes under 720K + }; + + struct MasterDirBlock; // fwd + static void UnpackMDB(const unsigned char* buf, MasterDirBlock* pMDB); + static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder); + + DIError Initialize(InitMode initMode); + DIError LoadVolHeader(void); + void SetVolumeID(void); + void DumpVolHeader(void); + void SetVolumeUsageMap(void); + +#ifdef EXCISE_GPL_CODE + void CreateFakeFile(void); +#else + DIError RecursiveDirAdd(A2File* pParent, const char* basePath, int depth); + //void Sanitize(unsigned char* str); + DIError DoNormalizePath(const char* path, char fssep, + char** pNormalizedPath); + static int CompareMacFileNames(const char* str1, const char* str2); + DIError RegeneratePathName(A2FileHFS* pFile); + DIError MakeFileNameUnique(const char* pathName, char** pUniqueName); + + /* libhfs stuff */ + static unsigned long LibHFSCB(void* vThis, int op, unsigned long arg1, + void* arg2); + hfsvol* fHfsVol; +#endif + + + /* some items from the volume header */ + char fVolumeName[kMaxVolumeName+1]; + char fVolumeID[kMaxVolumeName + 8]; // add "HFS :" + unsigned long fTotalBlocks; + unsigned long fAllocationBlockSize; + unsigned long fNumAllocationBlocks; + unsigned long fCreatedDateTime; + unsigned long fModifiedDateTime; + unsigned long fNumFiles; + unsigned long fNumDirectories; + + long fLocalTimeOffset; + bool fDiskIsGood; +}; + +/* + * File descriptor for an open HFS file. + */ +class DISKIMG_API A2FDHFS : public A2FileDescr { +public: +#ifdef EXCISE_GPL_CODE + A2FDHFS(A2File* pFile, void* unused) + : A2FileDescr(pFile), fOffset(0) + {} +#else + A2FDHFS(A2File* pFile, hfsfile* pHfsFile) + : A2FileDescr(pFile), fHfsFile(pHfsFile), fModified(false) + {} +#endif + virtual ~A2FDHFS(void) { +#ifndef EXCISE_GPL_CODE + if (fHfsFile != NULL) + hfs_close(fHfsFile); +#endif + } + + friend class A2FileHFS; + + virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Seek(di_off_t offset, DIWhence whence); + virtual di_off_t Tell(void); + virtual DIError Close(void); + + virtual long GetSectorCount(void) const; + virtual long GetBlockCount(void) const; + virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; + virtual DIError GetStorage(long blockIdx, long* pBlock) const; + +private: +#ifdef EXCISE_GPL_CODE + di_off_t fOffset; +#else + hfsfile* fHfsFile; + bool fModified; +#endif +}; + +/* + * File on an HFS disk. + */ +class DISKIMG_API A2FileHFS : public A2File { +public: + A2FileHFS(DiskFS* pDiskFS) : A2File(pDiskFS) { + fPathName = NULL; + fpOpenFile = NULL; +#ifdef EXCISE_GPL_CODE + fFakeFileBuf = NULL; +#else + //fOrigPathName = NULL; +#endif + } + virtual ~A2FileHFS(void) { + delete fpOpenFile; + delete[] fPathName; +#ifdef EXCISE_GPL_CODE + delete[] fFakeFileBuf; +#else + //delete[] fOrigPathName; +#endif + } + + /* + * Implementations of standard interfaces. + */ + virtual const char* GetFileName(void) const { return fFileName; } + virtual const char* GetPathName(void) const { return fPathName; } + virtual char GetFssep(void) const { return kFssep; } + virtual long GetFileType(void) const; + virtual long GetAuxType(void) const; + virtual long GetAccess(void) const { return fAccess; } + virtual time_t GetCreateWhen(void) const { return fCreateWhen; } + virtual time_t GetModWhen(void) const { return fModWhen; } + virtual di_off_t GetDataLength(void) const { return fDataLength; } + virtual di_off_t GetDataSparseLength(void) const { return fDataLength; } + virtual di_off_t GetRsrcLength(void) const { return fRsrcLength; } + virtual di_off_t GetRsrcSparseLength(void) const { return fRsrcLength; } + virtual bool IsDirectory(void) const { return fIsDir; } + virtual bool IsVolumeDirectory(void) const { return fIsVolumeDir; } + + virtual DIError Open(A2FileDescr** pOpenFile, bool readOnly, + bool rsrcFork = false); + virtual void CloseDescr(A2FileDescr* pOpenFile) { + assert(pOpenFile == fpOpenFile); + delete fpOpenFile; + fpOpenFile = NULL; + } + virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } + + enum { + kMaxFileName = 31, + kFssep = ':', + kPdosType = 0x70646f73, // 'pdos' + }; + + void SetPathName(const char* basePath, const char* fileName); + virtual void Dump(void) const; + +#ifdef EXCISE_GPL_CODE + void SetFakeFile(void* buf, long len) { + assert(len > 0); + if (fFakeFileBuf != NULL) + delete[] fFakeFileBuf; + fFakeFileBuf = new char[len]; + memcpy(fFakeFileBuf, buf, len); + fDataLength = len; + } + const void* GetFakeFileBuf(void) const { return fFakeFileBuf; } +#else + void InitEntry(const hfsdirent* dirEntry); + void SetOrigPathName(const char* pathName); + virtual void SetParent(A2File* pParent) { fpParent = pParent; } + virtual A2File* GetParent(void) const { return fpParent; } + char* GetLibHFSPathName(void) const; + static void ConvertTypeToHFS(long fileType, long auxType, + char* pType, char* pCreator); +#endif + + bool fIsDir; + bool fIsVolumeDir; + long fType; + long fCreator; + char fFileName[kMaxFileName+1]; + char* fPathName; + di_off_t fDataLength; + di_off_t fRsrcLength; + time_t fCreateWhen; + time_t fModWhen; + long fAccess; + +private: +#ifdef EXCISE_GPL_CODE + char* fFakeFileBuf; +#else + //char* fOrigPathName; + A2File* fpParent; +#endif + A2FileDescr* fpOpenFile; // only one fork can be open at a time +}; + + +/* + * =========================================================================== + * Gutenberg + * =========================================================================== + */ + +class A2FileGutenberg; + +/* + * Gutenberg disk. + */ +class DISKIMG_API DiskFSGutenberg : public DiskFS { +public: + DiskFSGutenberg(void) : DiskFS() { + fVTOCLoaded = false; + fDiskIsGood = false; + } + virtual ~DiskFSGutenberg(void) {} + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(initMode); + } + + virtual const char* GetVolumeName(void) const { return fDiskVolumeName; } + virtual const char* GetVolumeID(void) const { return fDiskVolumeID; } + virtual const char* GetBareVolumeName(void) const { + return fDiskVolumeName; + } + virtual bool GetReadWriteSupported(void) const { return true; } + virtual bool GetFSDamaged(void) const { return !fDiskIsGood; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const; + + static bool IsValidFileName(const char* name); + static bool IsValidVolumeName(const char* name); + + // utility function + static void LowerASCII(unsigned char* buf, long len); + static void ReplaceFssep(char* str, char replacement); + + enum { + kMinTracks = 17, // need to put the catalog track here + kMaxTracks = 50, + kMaxCatalogSectors = 64, // two tracks on a 32-sector disk + }; + + /* a T/S pair */ + typedef struct TrackSector { + char track; + char sector; + } TrackSector; + + friend class A2FDGutenberg; // for Write + +private: + DIError Initialize(InitMode initMode); + DIError ReadVTOC(void); + void UpdateVolumeNum(void); + void DumpVTOC(void); + void SetSectorUsage(long track, long sector, + VolumeUsage::ChunkPurpose purpose); + void FixVolumeUsageMap(void); + DIError ReadCatalog(void); + DIError ProcessCatalogSector(int catTrack, int catSect, + const unsigned char* sctBuf); + DIError GetFileLengths(void); + DIError ComputeLength(A2FileGutenberg* pFile, const TrackSector* tsList, + int tsCount); + DIError TrimLastSectorUp(A2FileGutenberg* pFile, TrackSector lastTS); + void MarkFileUsage(A2FileGutenberg* pFile, TrackSector* tsList, int tsCount, + TrackSector* indexList, int indexCount); + DIError MakeFileNameUnique(char* fileName); + DIError GetFreeCatalogEntry(TrackSector* pCatSect, int* pCatEntry, + unsigned char* sctBuf, A2FileGutenberg** ppPrevEntry); + void CreateDirEntry(unsigned char* sctBuf, int catEntry, + const char* fileName, TrackSector* pTSSect, unsigned char fileType, + int access); + void FreeTrackSectors(TrackSector* pList, int count); + + bool CheckDiskIsGood(void); + + DIError WriteDOSTracks(int sectPerTrack); + + DIError ScanVolBitmap(void); + DIError LoadVolBitmap(void); + DIError SaveVolBitmap(void); + void FreeVolBitmap(void); + DIError AllocSector(TrackSector* pTS); + DIError CreateEmptyBlockMap(bool withDOS); + bool GetSectorUseEntry(long track, int sector) const; + void SetSectorUseEntry(long track, int sector, bool inUse); + inline unsigned long GetVTOCEntry(const unsigned char* pVTOC, + long track) const; + + // Largest interesting volume is 400K (50 tracks, 32 sectors), but + // we may be looking at it in 16-sector mode, so max tracks is 100. + enum { + kMaxInterestingTracks = 100, + kSectorSize = 256, + kDefaultVolumeNum = 254, + kMaxExtensionLen = 4, // used when normalizing; ".gif" is 4 + }; + + /* some fields from the VTOC */ + int fFirstCatTrack; + int fFirstCatSector; + int fVTOCVolumeNumber; + int fVTOCNumTracks; + int fVTOCNumSectors; + + /* private data */ + char fDiskVolumeName[10]; // + char fDiskVolumeID[11+12+1]; // sizeof "Gutenberg: " + 12 + null + unsigned char fVTOC[kSectorSize]; + bool fVTOCLoaded; + + /* + * There are some things we need to be careful of when reading the + * catalog track, like bad links and infinite loops. By storing a list + * of known good catalog sectors, we only have to handle that stuff once. + * The catalog doesn't grow or shrink, so this never needs to be updated. + */ + TrackSector fCatalogSectors[kMaxCatalogSectors]; + + bool fDiskIsGood; +}; + +/* + * File descriptor for an open Gutenberg file. + */ +class DISKIMG_API A2FDGutenberg : public A2FileDescr { +public: + A2FDGutenberg(A2File* pFile) : A2FileDescr(pFile) { + fOffset = 0; + fModified = false; + } + virtual ~A2FDGutenberg(void) { + } + + friend class A2FileGutenberg; + + virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Seek(di_off_t offset, DIWhence whence); + virtual di_off_t Tell(void); + virtual DIError Close(void); + + virtual long GetSectorCount(void) const; + virtual long GetBlockCount(void) const; + virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; + virtual DIError GetStorage(long blockIdx, long* pBlock) const; + +private: + typedef DiskFSGutenberg::TrackSector TrackSector; + + int fTSCount; + di_off_t fOffset; // current position in file + + di_off_t fOpenEOF; // how big the file currently is + long fOpenSectorsUsed; // how many sectors it occupies + bool fModified; // if modified, update stuff on Close + + void DumpTSList(void) const; +}; + +/* + * Holds Gutenberg files. + * + */ +class DISKIMG_API A2FileGutenberg : public A2File { +public: + A2FileGutenberg(DiskFS* pDiskFS); + virtual ~A2FileGutenberg(void); + + // assorted constants + enum { + kMaxFileName = 12, + }; + typedef enum { + kTypeText = 0x00, // 'T' + } FileType; + + /* + * Implementations of standard interfaces. + */ + virtual const char* GetFileName(void) const { return fFileName; } + virtual const char* GetPathName(void) const { return fFileName; } + virtual char GetFssep(void) const { return '\0'; } + virtual long GetFileType(void) const; + virtual long GetAuxType(void) const { return fAuxType; } + virtual long GetAccess(void) const { return DiskFS::kFileAccessUnlocked; } + virtual time_t GetCreateWhen(void) const { return 0; } + virtual time_t GetModWhen(void) const { return 0; } + virtual di_off_t GetDataLength(void) const { return fLength; } + virtual di_off_t GetDataSparseLength(void) const { return fSparseLength; } + virtual di_off_t GetRsrcLength(void) const { return -1; } + virtual di_off_t GetRsrcSparseLength(void) const { return -1; } + + virtual DIError Open(A2FileDescr** ppOpenFile, bool readOnly, + bool rsrcFork = false); + virtual void CloseDescr(A2FileDescr* pOpenFile) { + assert(pOpenFile == fpOpenFile); + delete fpOpenFile; + fpOpenFile = NULL; + } + virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } + + void Dump(void) const; + + typedef DiskFSGutenberg::TrackSector TrackSector; + + /* + * Contents of directory entry. + * + * We don't hold deleted or unused entries, so fTSListTrack is always + * valid. + */ + short fTrack; // (could use TrackSector here) + short fSector; + unsigned short fLengthInSectors; + bool fLocked; + char fFileName[kMaxFileName+1]; // "fixed" version + FileType fFileType; + + TrackSector fCatTS; // track/sector for our catalog entry + int fCatEntryNum; // entry number within cat sector + + // these are computed or determined from the file contents + unsigned short fAuxType; // addr for bin, etc. + short fDataOffset; // for 'A'/'B'/'I' with embedded len + di_off_t fLength; // file length, in bytes + di_off_t fSparseLength; // file length, factoring sparse out + + void FixFilename(void); + + static FileType ConvertFileType(long prodosType, di_off_t fileLen); + static bool IsValidType(long prodosType); + static void MakeDOSName(char* buf, const char* name); + static void TrimTrailingSpaces(char* filename); + +private: + DIError ExtractTSPairs(const unsigned char* sctBuf, TrackSector* tsList, + int* pLastNonZero); + + A2FDGutenberg* fpOpenFile; +}; + + +/* + * =========================================================================== + * FAT (including FAT12, FAT16, and FAT32) + * =========================================================================== + */ + +/* + * MS-DOS FAT disk. + * + * This is currently just the minimum necessary to properly recognize + * the disk. + */ +class A2FileFAT; +class DISKIMG_API DiskFSFAT : public DiskFS { +public: + DiskFSFAT(void) {} + virtual ~DiskFSFAT(void) {} + + static DIError TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency); + + virtual DIError Initialize(DiskImg* pImg, InitMode initMode) { + SetDiskImg(pImg); + return Initialize(); + } + + // assorted constants + enum { + kMaxVolumeName = 11, + }; + + virtual const char* GetVolumeName(void) const { return fVolumeName; } + virtual const char* GetVolumeID(void) const { return fVolumeID; } + virtual const char* GetBareVolumeName(void) const { return fVolumeName; } + virtual bool GetReadWriteSupported(void) const { return false; } + virtual bool GetFSDamaged(void) const { return false; } + virtual long GetFSNumBlocks(void) const { return fTotalBlocks; } + virtual DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const + { return kDIErrNotSupported; } + +private: + enum { + kExpectedMinBlocks = 720, // ignore volumes under 360K + }; + + struct MasterBootRecord; // fwd + struct BootSector; + static bool UnpackMBR(const unsigned char* buf, MasterBootRecord* pOut); + static bool UnpackBootSector(const unsigned char* buf, BootSector* pOut); + static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder); + + DIError Initialize(void); + DIError LoadVolHeader(void); + void DumpVolHeader(void); + void SetVolumeUsageMap(void); + void CreateFakeFile(void); + + /* some items from the volume header */ + char fVolumeName[kMaxVolumeName+1]; + char fVolumeID[kMaxVolumeName + 8]; // add "FAT %s:" + unsigned long fTotalBlocks; +}; + +/* + * File descriptor for an open FAT file. + */ +class DISKIMG_API A2FDFAT : public A2FileDescr { +public: + A2FDFAT(A2File* pFile) : A2FileDescr(pFile) { + fOffset = 0; + } + virtual ~A2FDFAT(void) { + /* nothing to clean up */ + } + + friend class A2FileFAT; + + virtual DIError Read(void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Write(const void* buf, size_t len, size_t* pActual = NULL); + virtual DIError Seek(di_off_t offset, DIWhence whence); + virtual di_off_t Tell(void); + virtual DIError Close(void); + + virtual long GetSectorCount(void) const; + virtual long GetBlockCount(void) const; + virtual DIError GetStorage(long sectorIdx, long* pTrack, long* pSector) const; + virtual DIError GetStorage(long blockIdx, long* pBlock) const; + +private: + di_off_t fOffset; +}; + +/* + * File on a FAT disk. + */ +class DISKIMG_API A2FileFAT : public A2File { +public: + A2FileFAT(DiskFS* pDiskFS) : A2File(pDiskFS) { + fFakeFileBuf = NULL; + //fFakeFileLen = -1; + fpOpenFile = NULL; + } + virtual ~A2FileFAT(void) { + delete fpOpenFile; + delete[] fFakeFileBuf; + } + + /* + * Implementations of standard interfaces. + */ + virtual const char* GetFileName(void) const { return fFileName; } + virtual const char* GetPathName(void) const { return fFileName; } + virtual char GetFssep(void) const { return '\0'; } + virtual long GetFileType(void) const { return 0; }; + virtual long GetAuxType(void) const { return 0; } + virtual long GetAccess(void) const { return DiskFS::kFileAccessUnlocked; } + virtual time_t GetCreateWhen(void) const { return 0; } + virtual time_t GetModWhen(void) const { return 0; } + virtual di_off_t GetDataLength(void) const { return fLength; } + virtual di_off_t GetDataSparseLength(void) const { return fLength; } + virtual di_off_t GetRsrcLength(void) const { return -1; } + virtual di_off_t GetRsrcSparseLength(void) const { return -1; } + + virtual DIError Open(A2FileDescr** pOpenFile, bool readOnly, + bool rsrcFork = false); + virtual void CloseDescr(A2FileDescr* pOpenFile) { + assert(pOpenFile == fpOpenFile); + delete fpOpenFile; + fpOpenFile = NULL; + } + virtual bool IsFileOpen(void) const { return fpOpenFile != NULL; } + + enum { kMaxFileName = 31 }; + + virtual void Dump(void) const; + + void SetFakeFile(void* buf, long len) { + assert(len > 0); + if (fFakeFileBuf != NULL) + delete[] fFakeFileBuf; + fFakeFileBuf = new char[len]; + memcpy(fFakeFileBuf, buf, len); + fLength = len; + } + const void* GetFakeFileBuf(void) const { return fFakeFileBuf; } + + char fFileName[kMaxFileName+1]; + di_off_t fLength; + +private: + char* fFakeFileBuf; + //long fFakeFileLen; + A2FileDescr* fpOpenFile; +}; + +}; // namespace DiskImgLib + +#endif /*__DISKIMGDETAIL__*/ diff --git a/diskimg/DiskImgPriv.h b/diskimg/DiskImgPriv.h index d033ad6..69829d6 100644 --- a/diskimg/DiskImgPriv.h +++ b/diskimg/DiskImgPriv.h @@ -16,12 +16,12 @@ #include // "GenericFD.h" included at end -using namespace DiskImgLib; // make life easy for all internal code +using namespace DiskImgLib; // make life easy for all internal code namespace DiskImgLib { #ifndef _DEBUG_LOG -//# define _DEBUG_LOG /* define this to force log msgs in non-debug build */ +//# define _DEBUG_LOG /* define this to force log msgs in non-debug build */ #endif #if defined(_DEBUG) || defined(_DEBUG_LOG) @@ -33,17 +33,17 @@ namespace DiskImgLib { */ #ifdef _DEBUG_MSGS #define WMSG0(fmt) \ - Global::PrintDebugMsg(__FILE__, __LINE__, fmt) + Global::PrintDebugMsg(__FILE__, __LINE__, fmt) #define WMSG1(fmt, arg0) \ - Global::PrintDebugMsg(__FILE__, __LINE__, fmt, arg0) + Global::PrintDebugMsg(__FILE__, __LINE__, fmt, arg0) #define WMSG2(fmt, arg0, arg1) \ - Global::PrintDebugMsg(__FILE__, __LINE__, fmt, arg0, arg1) + Global::PrintDebugMsg(__FILE__, __LINE__, fmt, arg0, arg1) #define WMSG3(fmt, arg0, arg1, arg2) \ - Global::PrintDebugMsg(__FILE__, __LINE__, fmt, arg0, arg1, arg2) + Global::PrintDebugMsg(__FILE__, __LINE__, fmt, arg0, arg1, arg2) #define WMSG4(fmt, arg0, arg1, arg2, arg3) \ - Global::PrintDebugMsg(__FILE__, __LINE__, fmt, arg0, arg1, arg2, arg3) + Global::PrintDebugMsg(__FILE__, __LINE__, fmt, arg0, arg1, arg2, arg3) #define WMSG5(fmt, arg0, arg1, arg2, arg3, arg4) \ - Global::PrintDebugMsg(__FILE__, __LINE__, fmt, arg0, arg1, arg2, arg3, arg4) + Global::PrintDebugMsg(__FILE__, __LINE__, fmt, arg0, arg1, arg2, arg3, arg4) #else #define WMSG0(fmt) ((void) 0) #define WMSG1(fmt, arg0) ((void) 0) @@ -114,10 +114,10 @@ class CircularBufferAccess { public: CircularBufferAccess(unsigned char* buf, long len) : fBuf(buf), fLen(len) - { assert(fLen > 0); assert(fBuf != nil); } + { assert(fLen > 0); assert(fBuf != nil); } CircularBufferAccess(const unsigned char* buf, long len) : fBuf(const_cast(buf)), fLen(len) - { assert(fLen > 0); assert(fBuf != nil); } + { assert(fLen > 0); assert(fBuf != nil); } ~CircularBufferAccess(void) {} /* @@ -160,72 +160,72 @@ private: * Bits fill in from the MSB to the LSB. If we write 10 bits, the * output buffer will look like this: * - * xxxxxxxx xx000000 + * xxxxxxxx xx000000 * * Call WriteBit() repeatedly. When done, call Finish() to write any pending * data and return the number of bits in the buffer. */ class BitOutputBuffer { public: - /* pass in the output buffer and the output buffer's size */ - BitOutputBuffer(unsigned char* buf, int size) { - fBufStart = fBuf = buf; - fBufSize = size; - fBitMask = 0x80; - fByte = 0; - fOverflow = false; - } - virtual ~BitOutputBuffer(void) {} + /* pass in the output buffer and the output buffer's size */ + BitOutputBuffer(unsigned char* buf, int size) { + fBufStart = fBuf = buf; + fBufSize = size; + fBitMask = 0x80; + fByte = 0; + fOverflow = false; + } + virtual ~BitOutputBuffer(void) {} - /* write a single bit */ - void WriteBit(int val) { - if (fBuf - fBufStart >= fBufSize) { - if (!fOverflow) { - WMSG0("Overran bit output buffer\n"); - DebugBreak(); - fOverflow = true; - } - return; - } + /* write a single bit */ + void WriteBit(int val) { + if (fBuf - fBufStart >= fBufSize) { + if (!fOverflow) { + WMSG0("Overran bit output buffer\n"); + DebugBreak(); + fOverflow = true; + } + return; + } - if (val) - fByte |= fBitMask; - fBitMask >>= 1; - if (fBitMask == 0) { - *fBuf++ = fByte; - fBitMask = 0x80; - fByte = 0; - } - } + if (val) + fByte |= fBitMask; + fBitMask >>= 1; + if (fBitMask == 0) { + *fBuf++ = fByte; + fBitMask = 0x80; + fByte = 0; + } + } - /* flush pending bits; returns length in bits (or -1 on overrun) */ - int Finish(void) { - int outputBits; + /* flush pending bits; returns length in bits (or -1 on overrun) */ + int Finish(void) { + int outputBits; - if (fOverflow) - return -1; + if (fOverflow) + return -1; - outputBits = (fBuf - fBufStart) * 8; + outputBits = (fBuf - fBufStart) * 8; - if (fBitMask != 0x80) { - *fBuf++ = fByte; + if (fBitMask != 0x80) { + *fBuf++ = fByte; - assert(fBitMask != 0); - while (fBitMask != 0x80) { - outputBits++; - fBitMask <<= 1; - } - } - return outputBits; - } + assert(fBitMask != 0); + while (fBitMask != 0x80) { + outputBits++; + fBitMask <<= 1; + } + } + return outputBits; + } private: - unsigned char* fBufStart; - unsigned char* fBuf; - int fBufSize; - unsigned char fBitMask; - unsigned char fByte; - bool fOverflow; + unsigned char* fBufStart; + unsigned char* fBuf; + int fBufSize; + unsigned char fBitMask; + unsigned char fByte; + bool fOverflow; }; /* @@ -233,92 +233,92 @@ private: */ class BitInputBuffer { public: - BitInputBuffer(const unsigned char* buf, int bitCount) { - fBufStart = fBuf = buf; - fBitCount = bitCount; - fCurrentBit = 0; - fBitPosn = 7; - fBitsConsumed = 0; - } - virtual ~BitInputBuffer(void) {} + BitInputBuffer(const unsigned char* buf, int bitCount) { + fBufStart = fBuf = buf; + fBitCount = bitCount; + fCurrentBit = 0; + fBitPosn = 7; + fBitsConsumed = 0; + } + virtual ~BitInputBuffer(void) {} - /* - * Get the next bit. Returns 0 or 1. - * - * If we wrapped around to the start of the buffer, and "pWrap" is - * non-null, set "*pWrap". (This does *not* set it to "false" if we - * don't wrap.) - */ - unsigned char GetBit(bool* pWrap) { - unsigned char val; + /* + * Get the next bit. Returns 0 or 1. + * + * If we wrapped around to the start of the buffer, and "pWrap" is + * non-null, set "*pWrap". (This does *not* set it to "false" if we + * don't wrap.) + */ + unsigned char GetBit(bool* pWrap) { + unsigned char val; - //assert(fBitPosn == 7 - (fCurrentBit & 0x07)); + //assert(fBitPosn == 7 - (fCurrentBit & 0x07)); - if (fCurrentBit == fBitCount) { - /* end reached, wrap to start */ - fCurrentBit = 0; - fBitPosn = 7; - fBuf = fBufStart; - //fByte = *fBuf++; - if (pWrap != nil) - *pWrap = true; - } + if (fCurrentBit == fBitCount) { + /* end reached, wrap to start */ + fCurrentBit = 0; + fBitPosn = 7; + fBuf = fBufStart; + //fByte = *fBuf++; + if (pWrap != nil) + *pWrap = true; + } - val = (*fBuf >> fBitPosn) & 0x01; + val = (*fBuf >> fBitPosn) & 0x01; - fCurrentBit++; - fBitPosn--; - if (fBitPosn < 0) { - fBitPosn = 7; - fBuf++; - } + fCurrentBit++; + fBitPosn--; + if (fBitPosn < 0) { + fBitPosn = 7; + fBuf++; + } - fBitsConsumed++; - return val; - } + fBitsConsumed++; + return val; + } - /* - * Get the next 8 bits. - */ - unsigned char GetByte(bool* pWrap) { - unsigned char val; - int i; + /* + * Get the next 8 bits. + */ + unsigned char GetByte(bool* pWrap) { + unsigned char val; + int i; - if (true || fCurrentBit > fBitCount-8) { - /* near end, use single-bit function iteratively */ - val = 0; - for (i = 0; i < 8; i++) - val = (val << 1) | GetBit(pWrap); - } else { - /* room to spare, grab it in one or two chunks */ - assert(false); - } - return val; - } + if (true || fCurrentBit > fBitCount-8) { + /* near end, use single-bit function iteratively */ + val = 0; + for (i = 0; i < 8; i++) + val = (val << 1) | GetBit(pWrap); + } else { + /* room to spare, grab it in one or two chunks */ + assert(false); + } + return val; + } - /* - * Set the start position. - */ - void SetStartPosition(int bitOffset) { - assert(bitOffset >= 0 && bitOffset < fBitCount); - fCurrentBit = bitOffset; - fBitPosn = 7 - (bitOffset & 0x07); // mod 8, 0 to MSB - fBuf = fBufStart + (bitOffset >> 3); // div 8 - } + /* + * Set the start position. + */ + void SetStartPosition(int bitOffset) { + assert(bitOffset >= 0 && bitOffset < fBitCount); + fCurrentBit = bitOffset; + fBitPosn = 7 - (bitOffset & 0x07); // mod 8, 0 to MSB + fBuf = fBufStart + (bitOffset >> 3); // div 8 + } - /* used to ensure we consume exactly 100% of bits */ - void ResetBitsConsumed(void) { fBitsConsumed = 0; } - int GetBitsConsumed(void) const { return fBitsConsumed; } + /* used to ensure we consume exactly 100% of bits */ + void ResetBitsConsumed(void) { fBitsConsumed = 0; } + int GetBitsConsumed(void) const { return fBitsConsumed; } private: - const unsigned char* fBufStart; - const unsigned char* fBuf; - int fBitCount; // #of bits in buffer - int fCurrentBit; // where we are in buffer - int fBitPosn; // which bit to access within byte - //unsigned char fByte; + const unsigned char* fBufStart; + const unsigned char* fBuf; + int fBitCount; // #of bits in buffer + int fCurrentBit; // where we are in buffer + int fBitPosn; // which bit to access within byte + //unsigned char fByte; - int fBitsConsumed; // sanity check - all bits used? + int fBitsConsumed; // sanity check - all bits used? }; /* @@ -326,35 +326,35 @@ private: */ class LinearBitmap { public: - LinearBitmap(int numBits) { - assert(numBits > 0); - fBits = new unsigned char[(numBits + 7) / 8]; - memset(fBits, 0, (numBits + 7) / 8); - fNumBits = numBits; - } - ~LinearBitmap(void) { - delete[] fBits; - } + LinearBitmap(int numBits) { + assert(numBits > 0); + fBits = new unsigned char[(numBits + 7) / 8]; + memset(fBits, 0, (numBits + 7) / 8); + fNumBits = numBits; + } + ~LinearBitmap(void) { + delete[] fBits; + } - /* - * Set or get the status of bit N. - */ - bool IsSet(int bit) const { - assert(bit >= 0 && bit < fNumBits); - return ((fBits[bit >> 3] >> (bit & 0x07)) & 0x01) != 0; - } - void Set(int bit) { - assert(bit >= 0 && bit < fNumBits); - fBits[bit >> 3] |= 1 << (bit & 0x07); - } + /* + * Set or get the status of bit N. + */ + bool IsSet(int bit) const { + assert(bit >= 0 && bit < fNumBits); + return ((fBits[bit >> 3] >> (bit & 0x07)) & 0x01) != 0; + } + void Set(int bit) { + assert(bit >= 0 && bit < fNumBits); + fBits[bit >> 3] |= 1 << (bit & 0x07); + } private: - unsigned char* fBits; - int fNumBits; + unsigned char* fBits; + int fNumBits; }; -}; // namespace DiskImgLib +}; // namespace DiskImgLib /* * Most of the code needs these. diff --git a/diskimg/FAT.cpp b/diskimg/FAT.cpp index 99c26a4..6281747 100644 --- a/diskimg/FAT.cpp +++ b/diskimg/FAT.cpp @@ -16,96 +16,96 @@ /* * =========================================================================== - * DiskFSFAT + * DiskFSFAT * =========================================================================== */ const int kBlkSize = 512; const long kBootBlock = 0; -const unsigned short kSignature = 0xaa55; // MBR or boot sector +const unsigned short kSignature = 0xaa55; // MBR or boot sector const int kSignatureOffset = 0x1fe; -const unsigned char kOpcodeMumble = 0x33; // seen on 2nd drive +const unsigned char kOpcodeMumble = 0x33; // seen on 2nd drive const unsigned char kOpcodeBranch = 0xeb; const unsigned char kOpcodeSetInt = 0xfa; typedef struct PartitionTableEntry { - unsigned char driveNum; // dl (0x80 or 0x00) - unsigned char startHead; // dh - unsigned char startSector; // cl (&0x3f=sector, +two hi bits cyl) - unsigned char startCylinder; // ch (low 8 bits of 10-bit cylinder) - unsigned char type; // partition type - unsigned char endHead; // dh - unsigned char endSector; // cl - unsigned char endCylinder; // ch - unsigned long startLBA; // in blocks - unsigned long size; // in blocks + unsigned char driveNum; // dl (0x80 or 0x00) + unsigned char startHead; // dh + unsigned char startSector; // cl (&0x3f=sector, +two hi bits cyl) + unsigned char startCylinder; // ch (low 8 bits of 10-bit cylinder) + unsigned char type; // partition type + unsigned char endHead; // dh + unsigned char endSector; // cl + unsigned char endCylinder; // ch + unsigned long startLBA; // in blocks + unsigned long size; // in blocks } PartitionTableEntry; /* * Definition of a Master Boot Record, which is block 0 of a physical volume. */ typedef struct DiskFSFAT::MasterBootRecord { - /* - * Begins immediately with code, usually 0xfa (set interrupt flag) or - * 0xeb (relative branch). - */ - unsigned char firstByte; + /* + * Begins immediately with code, usually 0xfa (set interrupt flag) or + * 0xeb (relative branch). + */ + unsigned char firstByte; - /* - * Partition table starts at 0x1be. Four entries, each 16 bytes. - */ - PartitionTableEntry parTab[4]; + /* + * Partition table starts at 0x1be. Four entries, each 16 bytes. + */ + PartitionTableEntry parTab[4]; } MasterBootRecord; /* * Definition of a boot sector, which is block 0 of a logical volume. */ typedef struct DiskFSFAT::BootSector { - /* - * The first few bytes of the boot sector is called the BIOS Parameter - * Block, or BPB. - */ - unsigned char jump[3]; // usually EB XX 90 - unsigned char oemName[8]; // e.g. "MSWIN4.1" or "MSDOS5.0" - unsigned short bytesPerSector; // usually (always?) 512 - unsigned char sectPerCluster; - unsigned short reservedSectors; - unsigned char numFAT; - unsigned short numRootDirEntries; - unsigned short numSectors; // if set, ignore numSectorsHuge - unsigned char mediaType; - unsigned short numFATSectors; - unsigned short sectorsPerTrack; - unsigned short numHeads; - unsigned long numHiddenSectors; - unsigned long numSectorsHuge; // only if numSectors==0 - /* - * This next part can start immediately after the above (at 0x24) for - * FAT12/FAT16, or somewhat later (0x42) for FAT32. It doesn't seem - * to exist for NTFS. Probably safest to assume it doesn't exist. - * - * The only way to be sure of what we're dealing with is to know the - * partition type, but if this is our block 0 then we can't know what - * that is. - */ - unsigned char driveNum; - unsigned char reserved; - unsigned char signature; // 0x29 - unsigned long volumeID; - unsigned char volumeLabel[11]; // e.g. "FUBAR " - unsigned char fileSysType[8]; // e.g. "FAT12 " + /* + * The first few bytes of the boot sector is called the BIOS Parameter + * Block, or BPB. + */ + unsigned char jump[3]; // usually EB XX 90 + unsigned char oemName[8]; // e.g. "MSWIN4.1" or "MSDOS5.0" + unsigned short bytesPerSector; // usually (always?) 512 + unsigned char sectPerCluster; + unsigned short reservedSectors; + unsigned char numFAT; + unsigned short numRootDirEntries; + unsigned short numSectors; // if set, ignore numSectorsHuge + unsigned char mediaType; + unsigned short numFATSectors; + unsigned short sectorsPerTrack; + unsigned short numHeads; + unsigned long numHiddenSectors; + unsigned long numSectorsHuge; // only if numSectors==0 + /* + * This next part can start immediately after the above (at 0x24) for + * FAT12/FAT16, or somewhat later (0x42) for FAT32. It doesn't seem + * to exist for NTFS. Probably safest to assume it doesn't exist. + * + * The only way to be sure of what we're dealing with is to know the + * partition type, but if this is our block 0 then we can't know what + * that is. + */ + unsigned char driveNum; + unsigned char reserved; + unsigned char signature; // 0x29 + unsigned long volumeID; + unsigned char volumeLabel[11]; // e.g. "FUBAR " + unsigned char fileSysType[8]; // e.g. "FAT12 " - /* - * Code follows. Signature 0xaa55 in the last two bytes. - */ + /* + * Code follows. Signature 0xaa55 in the last two bytes. + */ } BootSector; // some values for MediaType enum MediaType { - kMediaTypeLarge = 0xf0, // 1440KB or 2800KB 3.5" disk - kMediaTypeHardDrive = 0xf8, - kMediaTypeMedium = 0xf9, // 720KB 3.5" disk or 1.2MB 5.25" disk - kMediaTypeSmall = 0xfd, // 360KB 5.25" disk + kMediaTypeLarge = 0xf0, // 1440KB or 2800KB 3.5" disk + kMediaTypeHardDrive = 0xf8, + kMediaTypeMedium = 0xf9, // 720KB 3.5" disk or 1.2MB 5.25" disk + kMediaTypeSmall = 0xfd, // 360KB 5.25" disk }; @@ -117,42 +117,42 @@ enum MediaType { /*static*/ bool DiskFSFAT::UnpackMBR(const unsigned char* buf, MasterBootRecord* pOut) { - const unsigned char* ptr; - int i; + const unsigned char* ptr; + int i; - pOut->firstByte = buf[0x00]; + pOut->firstByte = buf[0x00]; - ptr = &buf[0x1be]; - for (i = 0; i < 4; i++) { - pOut->parTab[i].driveNum = ptr[0x00]; - pOut->parTab[i].startHead = ptr[0x01]; - pOut->parTab[i].startSector = ptr[0x02]; - pOut->parTab[i].startCylinder = ptr[0x03]; - pOut->parTab[i].type = ptr[0x04]; - pOut->parTab[i].endHead = ptr[0x05]; - pOut->parTab[i].endSector = ptr[0x06]; - pOut->parTab[i].endCylinder = ptr[0x07]; - pOut->parTab[i].startLBA = GetLongLE(&ptr[0x08]); - pOut->parTab[i].size = GetLongLE(&ptr[0x0c]); + ptr = &buf[0x1be]; + for (i = 0; i < 4; i++) { + pOut->parTab[i].driveNum = ptr[0x00]; + pOut->parTab[i].startHead = ptr[0x01]; + pOut->parTab[i].startSector = ptr[0x02]; + pOut->parTab[i].startCylinder = ptr[0x03]; + pOut->parTab[i].type = ptr[0x04]; + pOut->parTab[i].endHead = ptr[0x05]; + pOut->parTab[i].endSector = ptr[0x06]; + pOut->parTab[i].endCylinder = ptr[0x07]; + pOut->parTab[i].startLBA = GetLongLE(&ptr[0x08]); + pOut->parTab[i].size = GetLongLE(&ptr[0x0c]); - ptr += 16; - } + ptr += 16; + } - if (pOut->firstByte != kOpcodeBranch && - pOut->firstByte != kOpcodeSetInt && - pOut->firstByte != kOpcodeMumble) - return false; - bool foundActive = false; - for (i = 0; i < 4; i++) { - if (pOut->parTab[i].driveNum == 0x80) - foundActive = true; - else if (pOut->parTab[i].driveNum != 0x00) - return false; // must be 0x00 or 0x80 - } - // CFFA cards don't seem to set the "active" flag - //if (!foundActive) - // return false; - return true; + if (pOut->firstByte != kOpcodeBranch && + pOut->firstByte != kOpcodeSetInt && + pOut->firstByte != kOpcodeMumble) + return false; + bool foundActive = false; + for (i = 0; i < 4; i++) { + if (pOut->parTab[i].driveNum == 0x80) + foundActive = true; + else if (pOut->parTab[i].driveNum != 0x00) + return false; // must be 0x00 or 0x80 + } + // CFFA cards don't seem to set the "active" flag + //if (!foundActive) + // return false; + return true; } /* @@ -163,26 +163,26 @@ DiskFSFAT::UnpackMBR(const unsigned char* buf, MasterBootRecord* pOut) /*static*/ bool DiskFSFAT::UnpackBootSector(const unsigned char* buf, BootSector* pOut) { - memcpy(pOut->jump, &buf[0x00], sizeof(pOut->jump)); - memcpy(pOut->oemName, &buf[0x03], sizeof(pOut->oemName)); - pOut->bytesPerSector = GetShortLE(&buf[0x0b]); - pOut->sectPerCluster = buf[0x0d]; - pOut->reservedSectors = GetShortLE(&buf[0x0e]); - pOut->numFAT = buf[0x10]; - pOut->numRootDirEntries = GetShortLE(&buf[0x11]); - pOut->numSectors = GetShortLE(&buf[0x13]); - pOut->mediaType = buf[0x15]; - pOut->numFATSectors = GetShortLE(&buf[0x16]); - pOut->sectorsPerTrack = GetShortLE(&buf[0x18]); - pOut->numHeads = GetShortLE(&buf[0x1a]); - pOut->numHiddenSectors = GetLongLE(&buf[0x1c]); - pOut->numSectorsHuge = GetLongLE(&buf[0x20]); + memcpy(pOut->jump, &buf[0x00], sizeof(pOut->jump)); + memcpy(pOut->oemName, &buf[0x03], sizeof(pOut->oemName)); + pOut->bytesPerSector = GetShortLE(&buf[0x0b]); + pOut->sectPerCluster = buf[0x0d]; + pOut->reservedSectors = GetShortLE(&buf[0x0e]); + pOut->numFAT = buf[0x10]; + pOut->numRootDirEntries = GetShortLE(&buf[0x11]); + pOut->numSectors = GetShortLE(&buf[0x13]); + pOut->mediaType = buf[0x15]; + pOut->numFATSectors = GetShortLE(&buf[0x16]); + pOut->sectorsPerTrack = GetShortLE(&buf[0x18]); + pOut->numHeads = GetShortLE(&buf[0x1a]); + pOut->numHiddenSectors = GetLongLE(&buf[0x1c]); + pOut->numSectorsHuge = GetLongLE(&buf[0x20]); - if (pOut->jump[0] != kOpcodeBranch && pOut->jump[0] != kOpcodeSetInt) - return false; - if (pOut->bytesPerSector != 512) - return false; - return true; + if (pOut->jump[0] != kOpcodeBranch && pOut->jump[0] != kOpcodeSetInt) + return false; + if (pOut->bytesPerSector != 512) + return false; + return true; } /* @@ -191,54 +191,54 @@ DiskFSFAT::UnpackBootSector(const unsigned char* buf, BootSector* pOut) /*static*/ DIError DiskFSFAT::TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder) { - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; - MasterBootRecord mbr; - BootSector bs; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; + MasterBootRecord mbr; + BootSector bs; - dierr = pImg->ReadBlockSwapped(kBootBlock, blkBuf, imageOrder, - DiskImg::kSectorOrderProDOS); - if (dierr != kDIErrNone) - goto bail; + dierr = pImg->ReadBlockSwapped(kBootBlock, blkBuf, imageOrder, + DiskImg::kSectorOrderProDOS); + if (dierr != kDIErrNone) + goto bail; - /* - * Both MBR and boot sectors have the same signature in block 0. - */ - if (GetShortLE(&blkBuf[kSignatureOffset]) != kSignature) { - dierr = kDIErrFilesystemNotFound; - goto bail; - } + /* + * Both MBR and boot sectors have the same signature in block 0. + */ + if (GetShortLE(&blkBuf[kSignatureOffset]) != kSignature) { + dierr = kDIErrFilesystemNotFound; + goto bail; + } - /* - * Decode it as an MBR and as a partition table. Figure out which - * one makes sense. If neither make sense, fail. - */ - bool hasMBR, hasBS; - hasMBR = UnpackMBR(blkBuf, &mbr); - hasBS = UnpackBootSector(blkBuf, &bs); - WMSG2(" FAT hasMBR=%d hasBS=%d\n", hasMBR, hasBS); + /* + * Decode it as an MBR and as a partition table. Figure out which + * one makes sense. If neither make sense, fail. + */ + bool hasMBR, hasBS; + hasMBR = UnpackMBR(blkBuf, &mbr); + hasBS = UnpackBootSector(blkBuf, &bs); + WMSG2(" FAT hasMBR=%d hasBS=%d\n", hasMBR, hasBS); - if (!hasMBR && !hasBS) { - dierr = kDIErrFilesystemNotFound; - goto bail; - } - if (hasMBR) { - WMSG0(" FAT partition table found:\n"); - for (int i = 0; i < 4; i++) { - WMSG4(" %d: type=0x%02x start LBA=%-9lu size=%lu\n", - i, mbr.parTab[i].type, - mbr.parTab[i].startLBA, mbr.parTab[i].size); - } - } - if (hasBS) { - WMSG0(" FAT boot sector found:\n"); - WMSG1(" OEMName is '%.8s'\n", bs.oemName); - } + if (!hasMBR && !hasBS) { + dierr = kDIErrFilesystemNotFound; + goto bail; + } + if (hasMBR) { + WMSG0(" FAT partition table found:\n"); + for (int i = 0; i < 4; i++) { + WMSG4(" %d: type=0x%02x start LBA=%-9lu size=%lu\n", + i, mbr.parTab[i].type, + mbr.parTab[i].startLBA, mbr.parTab[i].size); + } + } + if (hasBS) { + WMSG0(" FAT boot sector found:\n"); + WMSG1(" OEMName is '%.8s'\n", bs.oemName); + } - // looks good! + // looks good! bail: - return dierr; + return dierr; } /* @@ -246,30 +246,30 @@ bail: */ /*static*/ DIError DiskFSFAT::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency) + DiskImg::FSFormat* pFormat, FSLeniency leniency) { - /* must be block format, should be at least 360K */ - if (!pImg->GetHasBlocks() || pImg->GetNumBlocks() < kExpectedMinBlocks) - return kDIErrFilesystemNotFound; - if (pImg->GetIsEmbedded()) // don't look for FAT inside CFFA! - return kDIErrFilesystemNotFound; + /* must be block format, should be at least 360K */ + if (!pImg->GetHasBlocks() || pImg->GetNumBlocks() < kExpectedMinBlocks) + return kDIErrFilesystemNotFound; + if (pImg->GetIsEmbedded()) // don't look for FAT inside CFFA! + return kDIErrFilesystemNotFound; - DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; - - DiskImg::GetSectorOrderArray(ordering, *pOrder); + DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; + + DiskImg::GetSectorOrderArray(ordering, *pOrder); - for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { - if (ordering[i] == DiskImg::kSectorOrderUnknown) - continue; - if (TestImage(pImg, ordering[i]) == kDIErrNone) { - *pOrder = ordering[i]; - *pFormat = DiskImg::kFormatMSDOS; - return kDIErrNone; - } - } + for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { + if (ordering[i] == DiskImg::kSectorOrderUnknown) + continue; + if (TestImage(pImg, ordering[i]) == kDIErrNone) { + *pOrder = ordering[i]; + *pFormat = DiskImg::kFormatMSDOS; + return kDIErrNone; + } + } - WMSG0(" FAT didn't find valid FS\n"); - return kDIErrFilesystemNotFound; + WMSG0(" FAT didn't find valid FS\n"); + return kDIErrFilesystemNotFound; } /* @@ -278,19 +278,19 @@ DiskFSFAT::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DIError DiskFSFAT::Initialize(void) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - strcpy(fVolumeName, "[MS-DOS]"); // max 11 chars - strcpy(fVolumeID, "FATxx [MS-DOS]"); + strcpy(fVolumeName, "[MS-DOS]"); // max 11 chars + strcpy(fVolumeID, "FATxx [MS-DOS]"); - // take the easy way out - fTotalBlocks = fpImg->GetNumBlocks(); + // take the easy way out + fTotalBlocks = fpImg->GetNumBlocks(); - CreateFakeFile(); + CreateFakeFile(); - SetVolumeUsageMap(); + SetVolumeUsageMap(); - return dierr; + return dierr; } @@ -300,17 +300,17 @@ DiskFSFAT::Initialize(void) void DiskFSFAT::SetVolumeUsageMap(void) { - VolumeUsage::ChunkState cstate; - long block; + VolumeUsage::ChunkState cstate; + long block; - fVolumeUsage.Create(fpImg->GetNumBlocks()); + fVolumeUsage.Create(fpImg->GetNumBlocks()); - cstate.isUsed = true; - cstate.isMarkedUsed = true; - cstate.purpose = VolumeUsage::kChunkPurposeUnknown; + cstate.isUsed = true; + cstate.isMarkedUsed = true; + cstate.purpose = VolumeUsage::kChunkPurposeUnknown; - for (block = fTotalBlocks-1; block >= 0; block--) - fVolumeUsage.SetChunkState(block, &cstate); + for (block = fTotalBlocks-1; block >= 0; block--) + fVolumeUsage.SetChunkState(block, &cstate); } @@ -320,9 +320,9 @@ DiskFSFAT::SetVolumeUsageMap(void) void DiskFSFAT::CreateFakeFile(void) { - A2FileFAT* pFile; - char buf[768]; // currently running about 430 - static const char* kFormatMsg = + A2FileFAT* pFile; + char buf[768]; // currently running about 430 + static const char* kFormatMsg = "The FAT12/16/32 and NTFS filesystems are not supported. CiderPress knows\r\n" "how to recognize MS-DOS and Windows volumes so that it can identify\r\n" "PC data on removable media, but it does not know how to view or extract\r\n" @@ -335,27 +335,27 @@ DiskFSFAT::CreateFakeFile(void) "\r\n" "(CiderPress limits itself to 8GB, so larger volume sizes may not be shown.)\r\n" ; - long capacity; + long capacity; - capacity = fTotalBlocks; + capacity = fTotalBlocks; - memset(buf, 0, sizeof(buf)); - sprintf(buf, kFormatMsg, - fVolumeName, - capacity, - (double) capacity / 2048.0); + memset(buf, 0, sizeof(buf)); + sprintf(buf, kFormatMsg, + fVolumeName, + capacity, + (double) capacity / 2048.0); - pFile = new A2FileFAT(this); - pFile->SetFakeFile(buf, strlen(buf)); - strcpy(pFile->fFileName, "(not supported)"); + pFile = new A2FileFAT(this); + pFile->SetFakeFile(buf, strlen(buf)); + strcpy(pFile->fFileName, "(not supported)"); - AddFileToList(pFile); + AddFileToList(pFile); } /* * =========================================================================== - * A2FileFAT + * A2FileFAT * =========================================================================== */ @@ -365,7 +365,7 @@ DiskFSFAT::CreateFakeFile(void) void A2FileFAT::Dump(void) const { - WMSG1("A2FileFAT '%s'\n", fFileName); + WMSG1("A2FileFAT '%s'\n", fFileName); } /* @@ -373,28 +373,28 @@ A2FileFAT::Dump(void) const */ DIError A2FileFAT::Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork /*=false*/) + bool rsrcFork /*=false*/) { - A2FDFAT* pOpenFile = nil; + A2FDFAT* pOpenFile = nil; - if (fpOpenFile != nil) - return kDIErrAlreadyOpen; - if (rsrcFork) - return kDIErrForkNotFound; - assert(readOnly == true); + if (fpOpenFile != nil) + return kDIErrAlreadyOpen; + if (rsrcFork) + return kDIErrForkNotFound; + assert(readOnly == true); - pOpenFile = new A2FDFAT(this); + pOpenFile = new A2FDFAT(this); - fpOpenFile = pOpenFile; - *ppOpenFile = pOpenFile; + fpOpenFile = pOpenFile; + *ppOpenFile = pOpenFile; - return kDIErrNone; + return kDIErrNone; } /* * =========================================================================== - * A2FDFAT + * A2FDFAT * =========================================================================== */ @@ -404,25 +404,25 @@ A2FileFAT::Open(A2FileDescr** ppOpenFile, bool readOnly, DIError A2FDFAT::Read(void* buf, size_t len, size_t* pActual) { - WMSG3(" FAT reading %d bytes from '%s' (offset=%ld)\n", - len, fpFile->GetPathName(), (long) fOffset); + WMSG3(" FAT reading %d bytes from '%s' (offset=%ld)\n", + len, fpFile->GetPathName(), (long) fOffset); - A2FileFAT* pFile = (A2FileFAT*) fpFile; + A2FileFAT* pFile = (A2FileFAT*) fpFile; - /* don't allow them to read past the end of the file */ - if (fOffset + (long)len > pFile->fLength) { - if (pActual == nil) - return kDIErrDataUnderrun; - len = (size_t) (pFile->fLength - fOffset); - } - if (pActual != nil) - *pActual = len; + /* don't allow them to read past the end of the file */ + if (fOffset + (long)len > pFile->fLength) { + if (pActual == nil) + return kDIErrDataUnderrun; + len = (size_t) (pFile->fLength - fOffset); + } + if (pActual != nil) + *pActual = len; - memcpy(buf, pFile->GetFakeFileBuf(), len); + memcpy(buf, pFile->GetFakeFileBuf(), len); - fOffset += len; + fOffset += len; - return kDIErrNone; + return kDIErrNone; } /* @@ -431,7 +431,7 @@ A2FDFAT::Read(void* buf, size_t len, size_t* pActual) DIError A2FDFAT::Write(const void* buf, size_t len, size_t* pActual) { - return kDIErrNotSupported; + return kDIErrNotSupported; } /* @@ -440,34 +440,34 @@ A2FDFAT::Write(const void* buf, size_t len, size_t* pActual) DIError A2FDFAT::Seek(di_off_t offset, DIWhence whence) { - di_off_t fileLen = ((A2FileFAT*) fpFile)->fLength; + di_off_t fileLen = ((A2FileFAT*) fpFile)->fLength; - switch (whence) { - case kSeekSet: - if (offset < 0 || offset > fileLen) - return kDIErrInvalidArg; - fOffset = offset; - break; - case kSeekEnd: - if (offset > 0 || offset < -fileLen) - return kDIErrInvalidArg; - fOffset = fileLen + offset; - break; - case kSeekCur: - if (offset < -fOffset || - offset >= (fileLen - fOffset)) - { - return kDIErrInvalidArg; - } - fOffset += offset; - break; - default: - assert(false); - return kDIErrInvalidArg; - } + switch (whence) { + case kSeekSet: + if (offset < 0 || offset > fileLen) + return kDIErrInvalidArg; + fOffset = offset; + break; + case kSeekEnd: + if (offset > 0 || offset < -fileLen) + return kDIErrInvalidArg; + fOffset = fileLen + offset; + break; + case kSeekCur: + if (offset < -fOffset || + offset >= (fileLen - fOffset)) + { + return kDIErrInvalidArg; + } + fOffset += offset; + break; + default: + assert(false); + return kDIErrInvalidArg; + } - assert(fOffset >= 0 && fOffset <= fileLen); - return kDIErrNone; + assert(fOffset >= 0 && fOffset <= fileLen); + return kDIErrNone; } /* @@ -476,7 +476,7 @@ A2FDFAT::Seek(di_off_t offset, DIWhence whence) di_off_t A2FDFAT::Tell(void) { - return fOffset; + return fOffset; } /* @@ -485,8 +485,8 @@ A2FDFAT::Tell(void) DIError A2FDFAT::Close(void) { - fpFile->CloseDescr(this); - return kDIErrNone; + fpFile->CloseDescr(this); + return kDIErrNone; } /* @@ -495,14 +495,14 @@ A2FDFAT::Close(void) long A2FDFAT::GetSectorCount(void) const { - A2FileFAT* pFile = (A2FileFAT*) fpFile; - return (long) ((pFile->fLength+255) / 256); + A2FileFAT* pFile = (A2FileFAT*) fpFile; + return (long) ((pFile->fLength+255) / 256); } long A2FDFAT::GetBlockCount(void) const { - A2FileFAT* pFile = (A2FileFAT*) fpFile; - return (long) ((pFile->fLength+511) / 512); + A2FileFAT* pFile = (A2FileFAT*) fpFile; + return (long) ((pFile->fLength+511) / 512); } /* @@ -511,7 +511,7 @@ A2FDFAT::GetBlockCount(void) const DIError A2FDFAT::GetStorage(long sectorIdx, long* pTrack, long* pSector) const { - return kDIErrNotSupported; + return kDIErrNotSupported; } /* * Return the Nth 512-byte block in this file. @@ -519,5 +519,5 @@ A2FDFAT::GetStorage(long sectorIdx, long* pTrack, long* pSector) const DIError A2FDFAT::GetStorage(long blockIdx, long* pBlock) const { - return kDIErrNotSupported; + return kDIErrNotSupported; } diff --git a/diskimg/FDI.cpp b/diskimg/FDI.cpp index beb11f5..14c9ccb 100644 --- a/diskimg/FDI.cpp +++ b/diskimg/FDI.cpp @@ -36,8 +36,8 @@ DIError WrapperFDI::PackDisk(GenericFD* pSrcGFD, GenericFD* pWrapperGFD) { - DIError dierr = kDIErrGeneric; // not yet - return dierr; + DIError dierr = kDIErrGeneric; // not yet + return dierr; } @@ -59,158 +59,158 @@ WrapperFDI::PackDisk(GenericFD* pSrcGFD, GenericFD* pWrapperGFD) */ DIError WrapperFDI::UnpackDisk525(GenericFD* pGFD, GenericFD* pNewGFD, int numCyls, - int numHeads) + int numHeads) { - DIError dierr = kDIErrNone; - unsigned char nibbleBuf[kNibbleBufLen]; - unsigned char* inputBuf = nil; - bool goodTracks[kMaxNibbleTracks525]; - int inputBufLen = -1; - int badTracks = 0; - int trk, type, length256; - long nibbleLen; - bool result; + DIError dierr = kDIErrNone; + unsigned char nibbleBuf[kNibbleBufLen]; + unsigned char* inputBuf = nil; + bool goodTracks[kMaxNibbleTracks525]; + int inputBufLen = -1; + int badTracks = 0; + int trk, type, length256; + long nibbleLen; + bool result; - assert(numHeads == 1); - memset(goodTracks, false, sizeof(goodTracks)); + assert(numHeads == 1); + memset(goodTracks, false, sizeof(goodTracks)); - dierr = pGFD->Seek(kMinHeaderLen, kSeekSet); - if (dierr != kDIErrNone) { - WMSG1("FDI: track seek failed (offset=%d)\n", kMinHeaderLen); - goto bail; - } + dierr = pGFD->Seek(kMinHeaderLen, kSeekSet); + if (dierr != kDIErrNone) { + WMSG1("FDI: track seek failed (offset=%d)\n", kMinHeaderLen); + goto bail; + } - for (trk = 0; trk < numCyls * numHeads; trk++) { - GetTrackInfo(trk, &type, &length256); - WMSG5("%2d.%d: t=0x%02x l=%d (%d)\n", trk / numHeads, trk % numHeads, - type, length256, length256 * 256); + for (trk = 0; trk < numCyls * numHeads; trk++) { + GetTrackInfo(trk, &type, &length256); + WMSG5("%2d.%d: t=0x%02x l=%d (%d)\n", trk / numHeads, trk % numHeads, + type, length256, length256 * 256); - /* if we have data to read, read it */ - if (length256 > 0) { - if (length256 * 256 > inputBufLen) { - /* allocate or increase the size of the input buffer */ - delete[] inputBuf; - inputBufLen = length256 * 256; - inputBuf = new unsigned char[inputBufLen]; - if (inputBuf == nil) { - dierr = kDIErrMalloc; - goto bail; - } - } + /* if we have data to read, read it */ + if (length256 > 0) { + if (length256 * 256 > inputBufLen) { + /* allocate or increase the size of the input buffer */ + delete[] inputBuf; + inputBufLen = length256 * 256; + inputBuf = new unsigned char[inputBufLen]; + if (inputBuf == nil) { + dierr = kDIErrMalloc; + goto bail; + } + } - dierr = pGFD->Read(inputBuf, length256 * 256); - if (dierr != kDIErrNone) - goto bail; - } else { - assert(type == 0x00); - } + dierr = pGFD->Read(inputBuf, length256 * 256); + if (dierr != kDIErrNone) + goto bail; + } else { + assert(type == 0x00); + } - /* figure out what we want to do with this track */ - switch (type) { - case 0x00: - /* blank track */ - badTracks++; - memset(nibbleBuf, 0xff, sizeof(nibbleBuf)); - nibbleLen = kTrackLenNb2525; - break; - case 0x80: - case 0x90: - case 0xa0: - case 0xb0: - /* low-level pulse-index */ - nibbleLen = kNibbleBufLen; - result = DecodePulseTrack(inputBuf, length256*256, kBitRate525, - nibbleBuf, &nibbleLen); - if (!result) { - /* something failed in the decoder; fake it */ - badTracks++; - memset(nibbleBuf, 0xff, sizeof(nibbleBuf)); - nibbleLen = kTrackLenNb2525; - } else { - goodTracks[trk] = true; - } - if (nibbleLen > kTrackAllocSize) { - WMSG2(" FDI: decoded %ld nibbles, buffer is only %d\n", - nibbleLen, kTrackAllocSize); - dierr = kDIErrBadRawData; - goto bail; - } - break; - default: - WMSG1("FDI: unexpected track type 0x%04x\n", type); - dierr = kDIErrUnsupportedImageFeature; - goto bail; - } + /* figure out what we want to do with this track */ + switch (type) { + case 0x00: + /* blank track */ + badTracks++; + memset(nibbleBuf, 0xff, sizeof(nibbleBuf)); + nibbleLen = kTrackLenNb2525; + break; + case 0x80: + case 0x90: + case 0xa0: + case 0xb0: + /* low-level pulse-index */ + nibbleLen = kNibbleBufLen; + result = DecodePulseTrack(inputBuf, length256*256, kBitRate525, + nibbleBuf, &nibbleLen); + if (!result) { + /* something failed in the decoder; fake it */ + badTracks++; + memset(nibbleBuf, 0xff, sizeof(nibbleBuf)); + nibbleLen = kTrackLenNb2525; + } else { + goodTracks[trk] = true; + } + if (nibbleLen > kTrackAllocSize) { + WMSG2(" FDI: decoded %ld nibbles, buffer is only %d\n", + nibbleLen, kTrackAllocSize); + dierr = kDIErrBadRawData; + goto bail; + } + break; + default: + WMSG1("FDI: unexpected track type 0x%04x\n", type); + dierr = kDIErrUnsupportedImageFeature; + goto bail; + } - fNibbleTrackInfo.offset[trk] = trk * kTrackAllocSize; - fNibbleTrackInfo.length[trk] = nibbleLen; - FixBadNibbles(nibbleBuf, nibbleLen); - dierr = pNewGFD->Seek(fNibbleTrackInfo.offset[trk], kSeekSet); - if (dierr != kDIErrNone) - goto bail; - dierr = pNewGFD->Write(nibbleBuf, nibbleLen); - if (dierr != kDIErrNone) - goto bail; - WMSG2(" FDI: track %d: wrote %ld nibbles\n", trk, nibbleLen); + fNibbleTrackInfo.offset[trk] = trk * kTrackAllocSize; + fNibbleTrackInfo.length[trk] = nibbleLen; + FixBadNibbles(nibbleBuf, nibbleLen); + dierr = pNewGFD->Seek(fNibbleTrackInfo.offset[trk], kSeekSet); + if (dierr != kDIErrNone) + goto bail; + dierr = pNewGFD->Write(nibbleBuf, nibbleLen); + if (dierr != kDIErrNone) + goto bail; + WMSG2(" FDI: track %d: wrote %ld nibbles\n", trk, nibbleLen); - //offset += 256 * length256; - //break; // DEBUG DEBUG - } + //offset += 256 * length256; + //break; // DEBUG DEBUG + } - WMSG2(" FDI: %d of %d tracks bad or blank\n", - badTracks, numCyls * numHeads); - if (badTracks > (numCyls * numHeads) / 2) { - WMSG0("FDI: too many bad tracks\n"); - dierr = kDIErrBadRawData; - goto bail; - } + WMSG2(" FDI: %d of %d tracks bad or blank\n", + badTracks, numCyls * numHeads); + if (badTracks > (numCyls * numHeads) / 2) { + WMSG0("FDI: too many bad tracks\n"); + dierr = kDIErrBadRawData; + goto bail; + } - /* - * For convenience we want this to be 35 or 40 tracks. Start by - * reducing trk to 35 if there are no good tracks at 35+. - */ - bool want40; - int i; + /* + * For convenience we want this to be 35 or 40 tracks. Start by + * reducing trk to 35 if there are no good tracks at 35+. + */ + bool want40; + int i; - want40 = false; - for (i = kTrackCount525; i < kMaxNibbleTracks525; i++) { - if (goodTracks[i]) { - want40 = true; - break; - } - } - if (!want40 && trk > kTrackCount525) { - WMSG2(" FDI: no good tracks past %d, reducing from %d\n", - kTrackCount525, trk); - trk = kTrackCount525; // nothing good out there, roll back - } + want40 = false; + for (i = kTrackCount525; i < kMaxNibbleTracks525; i++) { + if (goodTracks[i]) { + want40 = true; + break; + } + } + if (!want40 && trk > kTrackCount525) { + WMSG2(" FDI: no good tracks past %d, reducing from %d\n", + kTrackCount525, trk); + trk = kTrackCount525; // nothing good out there, roll back + } - /* - * Now pad us *up* to 35 if we have fewer than that. - */ - memset(nibbleBuf, 0xff, sizeof(nibbleBuf)); - for ( ; trk < kMaxNibbleTracks525; trk++) { - if (trk == kTrackCount525) - break; + /* + * Now pad us *up* to 35 if we have fewer than that. + */ + memset(nibbleBuf, 0xff, sizeof(nibbleBuf)); + for ( ; trk < kMaxNibbleTracks525; trk++) { + if (trk == kTrackCount525) + break; - fNibbleTrackInfo.offset[trk] = trk * kTrackAllocSize; - fNibbleTrackInfo.length[trk] = kTrackLenNb2525; - fNibbleTrackInfo.numTracks++; + fNibbleTrackInfo.offset[trk] = trk * kTrackAllocSize; + fNibbleTrackInfo.length[trk] = kTrackLenNb2525; + fNibbleTrackInfo.numTracks++; - dierr = pNewGFD->Seek(fNibbleTrackInfo.offset[trk], kSeekSet); - if (dierr != kDIErrNone) - goto bail; - dierr = pNewGFD->Write(nibbleBuf, nibbleLen); - if (dierr != kDIErrNone) - goto bail; - } + dierr = pNewGFD->Seek(fNibbleTrackInfo.offset[trk], kSeekSet); + if (dierr != kDIErrNone) + goto bail; + dierr = pNewGFD->Write(nibbleBuf, nibbleLen); + if (dierr != kDIErrNone) + goto bail; + } - assert(trk == kTrackCount525 || trk == kMaxNibbleTracks525); - fNibbleTrackInfo.numTracks = trk; + assert(trk == kTrackCount525 || trk == kMaxNibbleTracks525); + fNibbleTrackInfo.numTracks = trk; bail: - delete[] inputBuf; - return dierr; + delete[] inputBuf; + return dierr; } /* @@ -225,120 +225,120 @@ bail: */ DIError WrapperFDI::UnpackDisk35(GenericFD* pGFD, GenericFD* pNewGFD, int numCyls, - int numHeads, LinearBitmap* pBadBlockMap) + int numHeads, LinearBitmap* pBadBlockMap) { - DIError dierr = kDIErrNone; - unsigned char nibbleBuf[kNibbleBufLen]; - unsigned char* inputBuf = nil; - unsigned char outputBuf[kMaxSectors35 * kBlockSize]; // 6KB - int inputBufLen = -1; - int badTracks = 0; - int trk, type, length256; - long nibbleLen; - bool result; + DIError dierr = kDIErrNone; + unsigned char nibbleBuf[kNibbleBufLen]; + unsigned char* inputBuf = nil; + unsigned char outputBuf[kMaxSectors35 * kBlockSize]; // 6KB + int inputBufLen = -1; + int badTracks = 0; + int trk, type, length256; + long nibbleLen; + bool result; - assert(numHeads == 2); + assert(numHeads == 2); - dierr = pGFD->Seek(kMinHeaderLen, kSeekSet); - if (dierr != kDIErrNone) { - WMSG1("FDI: track seek failed (offset=%d)\n", kMinHeaderLen); - goto bail; - } + dierr = pGFD->Seek(kMinHeaderLen, kSeekSet); + if (dierr != kDIErrNone) { + WMSG1("FDI: track seek failed (offset=%d)\n", kMinHeaderLen); + goto bail; + } - pNewGFD->Rewind(); + pNewGFD->Rewind(); - for (trk = 0; trk < numCyls * numHeads; trk++) { - GetTrackInfo(trk, &type, &length256); - WMSG5("%2d.%d: t=0x%02x l=%d (%d)\n", trk / numHeads, trk % numHeads, - type, length256, length256 * 256); + for (trk = 0; trk < numCyls * numHeads; trk++) { + GetTrackInfo(trk, &type, &length256); + WMSG5("%2d.%d: t=0x%02x l=%d (%d)\n", trk / numHeads, trk % numHeads, + type, length256, length256 * 256); - /* if we have data to read, read it */ - if (length256 > 0) { - if (length256 * 256 > inputBufLen) { - /* allocate or increase the size of the input buffer */ - delete[] inputBuf; - inputBufLen = length256 * 256; - inputBuf = new unsigned char[inputBufLen]; - if (inputBuf == nil) { - dierr = kDIErrMalloc; - goto bail; - } - } + /* if we have data to read, read it */ + if (length256 > 0) { + if (length256 * 256 > inputBufLen) { + /* allocate or increase the size of the input buffer */ + delete[] inputBuf; + inputBufLen = length256 * 256; + inputBuf = new unsigned char[inputBufLen]; + if (inputBuf == nil) { + dierr = kDIErrMalloc; + goto bail; + } + } - dierr = pGFD->Read(inputBuf, length256 * 256); - if (dierr != kDIErrNone) - goto bail; - } else { - assert(type == 0x00); - } + dierr = pGFD->Read(inputBuf, length256 * 256); + if (dierr != kDIErrNone) + goto bail; + } else { + assert(type == 0x00); + } - /* figure out what we want to do with this track */ - switch (type) { - case 0x00: - /* blank track */ - badTracks++; - memset(nibbleBuf, 0xff, sizeof(nibbleBuf)); - nibbleLen = kTrackLenNb2525; - break; - case 0x80: - case 0x90: - case 0xa0: - case 0xb0: - /* low-level pulse-index */ - nibbleLen = kNibbleBufLen; - result = DecodePulseTrack(inputBuf, length256*256, - BitRate35(trk/numHeads), nibbleBuf, &nibbleLen); - if (!result) { - /* something failed in the decoder; fake it */ - badTracks++; - memset(nibbleBuf, 0xff, sizeof(nibbleBuf)); - nibbleLen = kTrackLenNb2525; - } - if (nibbleLen > kNibbleBufLen) { - WMSG2(" FDI: decoded %ld nibbles, buffer is only %d\n", - nibbleLen, kTrackAllocSize); - dierr = kDIErrBadRawData; - goto bail; - } - break; - default: - WMSG1("FDI: unexpected track type 0x%04x\n", type); - dierr = kDIErrUnsupportedImageFeature; - goto bail; - } + /* figure out what we want to do with this track */ + switch (type) { + case 0x00: + /* blank track */ + badTracks++; + memset(nibbleBuf, 0xff, sizeof(nibbleBuf)); + nibbleLen = kTrackLenNb2525; + break; + case 0x80: + case 0x90: + case 0xa0: + case 0xb0: + /* low-level pulse-index */ + nibbleLen = kNibbleBufLen; + result = DecodePulseTrack(inputBuf, length256*256, + BitRate35(trk/numHeads), nibbleBuf, &nibbleLen); + if (!result) { + /* something failed in the decoder; fake it */ + badTracks++; + memset(nibbleBuf, 0xff, sizeof(nibbleBuf)); + nibbleLen = kTrackLenNb2525; + } + if (nibbleLen > kNibbleBufLen) { + WMSG2(" FDI: decoded %ld nibbles, buffer is only %d\n", + nibbleLen, kTrackAllocSize); + dierr = kDIErrBadRawData; + goto bail; + } + break; + default: + WMSG1("FDI: unexpected track type 0x%04x\n", type); + dierr = kDIErrUnsupportedImageFeature; + goto bail; + } - WMSG2(" FDI: track %d got %ld nibbles\n", trk, nibbleLen); + WMSG2(" FDI: track %d got %ld nibbles\n", trk, nibbleLen); - /* - fNibbleTrackInfo.offset[trk] = trk * kTrackAllocSize; - fNibbleTrackInfo.length[trk] = nibbleLen; - dierr = pNewGFD->Seek(fNibbleTrackInfo.offset[trk], kSeekSet); - if (dierr != kDIErrNone) - goto bail; - dierr = pNewGFD->Write(nibbleBuf, nibbleLen); - if (dierr != kDIErrNone) - goto bail; - */ + /* + fNibbleTrackInfo.offset[trk] = trk * kTrackAllocSize; + fNibbleTrackInfo.length[trk] = nibbleLen; + dierr = pNewGFD->Seek(fNibbleTrackInfo.offset[trk], kSeekSet); + if (dierr != kDIErrNone) + goto bail; + dierr = pNewGFD->Write(nibbleBuf, nibbleLen); + if (dierr != kDIErrNone) + goto bail; + */ - dierr = DiskImg::UnpackNibbleTrack35(nibbleBuf, nibbleLen, outputBuf, - trk / numHeads, trk % numHeads, pBadBlockMap); - if (dierr != kDIErrNone) - goto bail; + dierr = DiskImg::UnpackNibbleTrack35(nibbleBuf, nibbleLen, outputBuf, + trk / numHeads, trk % numHeads, pBadBlockMap); + if (dierr != kDIErrNone) + goto bail; - dierr = pNewGFD->Write(outputBuf, - kBlockSize * DiskImg::SectorsPerTrack35(trk / numHeads)); - if (dierr != kDIErrNone) { - WMSG2("FDI: failed writing disk blocks (%d * %d)\n", - kBlockSize, DiskImg::SectorsPerTrack35(trk / numHeads)); - goto bail; - } - } + dierr = pNewGFD->Write(outputBuf, + kBlockSize * DiskImg::SectorsPerTrack35(trk / numHeads)); + if (dierr != kDIErrNone) { + WMSG2("FDI: failed writing disk blocks (%d * %d)\n", + kBlockSize, DiskImg::SectorsPerTrack35(trk / numHeads)); + goto bail; + } + } - //fNibbleTrackInfo.numTracks = numCyls * numHeads; + //fNibbleTrackInfo.numTracks = numCyls * numHeads; bail: - delete[] inputBuf; - return dierr; + delete[] inputBuf; + return dierr; } /* @@ -347,20 +347,20 @@ bail: int WrapperFDI::BitRate35(int cyl) { - if (cyl >= 0 && cyl <= 15) - return 375000; // 394rpm - else if (cyl <= 31) - return 343750; // 429rpm - else if (cyl <= 47) - return 312500; // 472rpm - else if (cyl <= 63) - return 281250; // 525rpm - else if (cyl <= 79) - return 250000; // 590rpm - else { - WMSG1(" FDI: invalid 3.5 cylinder %d\n", cyl); - return 250000; - } + if (cyl >= 0 && cyl <= 15) + return 375000; // 394rpm + else if (cyl <= 31) + return 343750; // 429rpm + else if (cyl <= 47) + return 312500; // 472rpm + else if (cyl <= 63) + return 281250; // 525rpm + else if (cyl <= 79) + return 250000; // 590rpm + else { + WMSG1(" FDI: invalid 3.5 cylinder %d\n", cyl); + return 250000; + } } /* @@ -377,19 +377,19 @@ WrapperFDI::BitRate35(int cyl) void WrapperFDI::FixBadNibbles(unsigned char* nibbleBuf, long nibbleLen) { - int badCount = 0; + int badCount = 0; - while (nibbleLen--) { - if ((*nibbleBuf & 0x80) == 0) { - badCount++; - *nibbleBuf = 0xff; - } - nibbleBuf++; - } + while (nibbleLen--) { + if ((*nibbleBuf & 0x80) == 0) { + badCount++; + *nibbleBuf = 0xff; + } + nibbleBuf++; + } - if (badCount != 0) { - WMSG1(" FDI: fixed %d bad nibbles\n", badCount); - } + if (badCount != 0) { + WMSG1(" FDI: fixed %d bad nibbles\n", badCount); + } } @@ -402,47 +402,47 @@ WrapperFDI::FixBadNibbles(unsigned char* nibbleBuf, long nibbleLen) void WrapperFDI::GetTrackInfo(int trk, int* pType, int* pLength256) { - unsigned short trackDescr; - trackDescr = fHeaderBuf[kTrackDescrOffset + trk * 2] << 8 | - fHeaderBuf[kTrackDescrOffset + trk * 2 +1]; + unsigned short trackDescr; + trackDescr = fHeaderBuf[kTrackDescrOffset + trk * 2] << 8 | + fHeaderBuf[kTrackDescrOffset + trk * 2 +1]; - *pType = (trackDescr & 0xff00) >> 8; - *pLength256 = trackDescr & 0x00ff; + *pType = (trackDescr & 0xff00) >> 8; + *pLength256 = trackDescr & 0x00ff; - switch (trackDescr & 0xf000) { - case 0x0000: - /* high-level type */ - switch (trackDescr & 0xff00) { - case 0x0000: - /* blank track */ - break; - default: - /* miscellaneous high-level type */ - break; - } - break; - case 0x8000: - case 0x9000: - case 0xa000: - case 0xb000: - /* low-level type, length is 14 bits */ - *pType = (trackDescr & 0xc000) >> 8; - *pLength256 = trackDescr & 0x3fff; - break; - case 0xc000: - case 0xd000: - /* mid-level format, value in 0n00 holds a bit rate index */ - break; - case 0xe000: - case 0xf000: - /* raw MFM; for 0xf000, the value in 0n00 holds a bit rate index */ - break; - default: - WMSG1("Unexpected trackDescr 0x%04x\n", trackDescr); - *pType = 0x7e; // return an invalid value - *pLength256 = 0; - break; - } + switch (trackDescr & 0xf000) { + case 0x0000: + /* high-level type */ + switch (trackDescr & 0xff00) { + case 0x0000: + /* blank track */ + break; + default: + /* miscellaneous high-level type */ + break; + } + break; + case 0x8000: + case 0x9000: + case 0xa000: + case 0xb000: + /* low-level type, length is 14 bits */ + *pType = (trackDescr & 0xc000) >> 8; + *pLength256 = trackDescr & 0x3fff; + break; + case 0xc000: + case 0xd000: + /* mid-level format, value in 0n00 holds a bit rate index */ + break; + case 0xe000: + case 0xf000: + /* raw MFM; for 0xf000, the value in 0n00 holds a bit rate index */ + break; + default: + WMSG1("Unexpected trackDescr 0x%04x\n", trackDescr); + *pType = 0x7e; // return an invalid value + *pLength256 = 0; + break; + } } @@ -459,106 +459,106 @@ WrapperFDI::GetTrackInfo(int trk, int* pType, int* pLength256) */ bool WrapperFDI::DecodePulseTrack(const unsigned char* inputBuf, long inputLen, - int bitRate, unsigned char* nibbleBuf, long* pNibbleLen) + int bitRate, unsigned char* nibbleBuf, long* pNibbleLen) { - const int kSizeValueMask = 0x003fffff; - const int kSizeCompressMask = 0x00c00000; - const int kSizeCompressShift = 22; - PulseIndexHeader hdr; - unsigned long val; - bool result = false; + const int kSizeValueMask = 0x003fffff; + const int kSizeCompressMask = 0x00c00000; + const int kSizeCompressShift = 22; + PulseIndexHeader hdr; + unsigned long val; + bool result = false; - memset(&hdr, 0, sizeof(hdr)); + memset(&hdr, 0, sizeof(hdr)); - hdr.numPulses = GetLongBE(&inputBuf[0x00]); - val = Get24BE(&inputBuf[0x04]); - hdr.avgStreamLen = val & kSizeValueMask; - hdr.avgStreamCompression = (val & kSizeCompressMask) >> kSizeCompressShift; - val = Get24BE(&inputBuf[0x07]); - hdr.minStreamLen = val & kSizeValueMask; - hdr.minStreamCompression = (val & kSizeCompressMask) >> kSizeCompressShift; - val = Get24BE(&inputBuf[0x0a]); - hdr.maxStreamLen = val & kSizeValueMask; - hdr.maxStreamCompression = (val & kSizeCompressMask) >> kSizeCompressShift; - val = Get24BE(&inputBuf[0x0d]); - hdr.idxStreamLen = val & kSizeValueMask; - hdr.idxStreamCompression = (val & kSizeCompressMask) >> kSizeCompressShift; + hdr.numPulses = GetLongBE(&inputBuf[0x00]); + val = Get24BE(&inputBuf[0x04]); + hdr.avgStreamLen = val & kSizeValueMask; + hdr.avgStreamCompression = (val & kSizeCompressMask) >> kSizeCompressShift; + val = Get24BE(&inputBuf[0x07]); + hdr.minStreamLen = val & kSizeValueMask; + hdr.minStreamCompression = (val & kSizeCompressMask) >> kSizeCompressShift; + val = Get24BE(&inputBuf[0x0a]); + hdr.maxStreamLen = val & kSizeValueMask; + hdr.maxStreamCompression = (val & kSizeCompressMask) >> kSizeCompressShift; + val = Get24BE(&inputBuf[0x0d]); + hdr.idxStreamLen = val & kSizeValueMask; + hdr.idxStreamCompression = (val & kSizeCompressMask) >> kSizeCompressShift; - if (hdr.numPulses < 64 || hdr.numPulses > 131072) { - /* should be about 40,000 */ - WMSG1(" FDI: bad pulse count %ld in track\n", hdr.numPulses); - return false; - } + if (hdr.numPulses < 64 || hdr.numPulses > 131072) { + /* should be about 40,000 */ + WMSG1(" FDI: bad pulse count %ld in track\n", hdr.numPulses); + return false; + } - /* advance past the 16 hdr bytes; now pointing at "average" stream */ - inputBuf += kPulseStreamDataOffset; + /* advance past the 16 hdr bytes; now pointing at "average" stream */ + inputBuf += kPulseStreamDataOffset; - WMSG1(" pulses: %ld\n", hdr.numPulses); - //WMSG2(" avg: len=%d comp=%d\n", hdr.avgStreamLen, hdr.avgStreamCompression); - //WMSG2(" min: len=%d comp=%d\n", hdr.minStreamLen, hdr.minStreamCompression); - //WMSG2(" max: len=%d comp=%d\n", hdr.maxStreamLen, hdr.maxStreamCompression); - //WMSG2(" idx: len=%d comp=%d\n", hdr.idxStreamLen, hdr.idxStreamCompression); + WMSG1(" pulses: %ld\n", hdr.numPulses); + //WMSG2(" avg: len=%d comp=%d\n", hdr.avgStreamLen, hdr.avgStreamCompression); + //WMSG2(" min: len=%d comp=%d\n", hdr.minStreamLen, hdr.minStreamCompression); + //WMSG2(" max: len=%d comp=%d\n", hdr.maxStreamLen, hdr.maxStreamCompression); + //WMSG2(" idx: len=%d comp=%d\n", hdr.idxStreamLen, hdr.idxStreamCompression); - /* - * Uncompress or endian-swap the pulse streams. - */ - hdr.avgStream = new unsigned long[hdr.numPulses]; - if (hdr.avgStream == nil) - goto bail; - if (!UncompressPulseStream(inputBuf, hdr.avgStreamLen, hdr.avgStream, - hdr.numPulses, hdr.avgStreamCompression, 4)) - { - goto bail; - } - inputBuf += hdr.avgStreamLen; + /* + * Uncompress or endian-swap the pulse streams. + */ + hdr.avgStream = new unsigned long[hdr.numPulses]; + if (hdr.avgStream == nil) + goto bail; + if (!UncompressPulseStream(inputBuf, hdr.avgStreamLen, hdr.avgStream, + hdr.numPulses, hdr.avgStreamCompression, 4)) + { + goto bail; + } + inputBuf += hdr.avgStreamLen; - if (hdr.minStreamLen > 0) { - hdr.minStream = new unsigned long[hdr.numPulses]; - if (hdr.minStream == nil) - goto bail; - if (!UncompressPulseStream(inputBuf, hdr.minStreamLen, hdr.minStream, - hdr.numPulses, hdr.minStreamCompression, 4)) - { - goto bail; - } - inputBuf += hdr.minStreamLen; - } - if (hdr.maxStreamLen > 0) { - hdr.maxStream = new unsigned long[hdr.numPulses]; - if (!UncompressPulseStream(inputBuf, hdr.maxStreamLen, hdr.maxStream, - hdr.numPulses, hdr.maxStreamCompression, 4)) - { - goto bail; - } - inputBuf += hdr.maxStreamLen; - } - if (hdr.idxStreamLen > 0) { - hdr.idxStream = new unsigned long[hdr.numPulses]; - if (!UncompressPulseStream(inputBuf, hdr.idxStreamLen, hdr.idxStream, - hdr.numPulses, hdr.idxStreamCompression, 2)) - { - goto bail; - } - inputBuf += hdr.idxStreamLen; - } + if (hdr.minStreamLen > 0) { + hdr.minStream = new unsigned long[hdr.numPulses]; + if (hdr.minStream == nil) + goto bail; + if (!UncompressPulseStream(inputBuf, hdr.minStreamLen, hdr.minStream, + hdr.numPulses, hdr.minStreamCompression, 4)) + { + goto bail; + } + inputBuf += hdr.minStreamLen; + } + if (hdr.maxStreamLen > 0) { + hdr.maxStream = new unsigned long[hdr.numPulses]; + if (!UncompressPulseStream(inputBuf, hdr.maxStreamLen, hdr.maxStream, + hdr.numPulses, hdr.maxStreamCompression, 4)) + { + goto bail; + } + inputBuf += hdr.maxStreamLen; + } + if (hdr.idxStreamLen > 0) { + hdr.idxStream = new unsigned long[hdr.numPulses]; + if (!UncompressPulseStream(inputBuf, hdr.idxStreamLen, hdr.idxStream, + hdr.numPulses, hdr.idxStreamCompression, 2)) + { + goto bail; + } + inputBuf += hdr.idxStreamLen; + } - /* - * Convert the pulse streams to a nibble stream. - */ - result = ConvertPulseStreamsToNibbles(&hdr, bitRate, nibbleBuf, pNibbleLen); - // fall through with result + /* + * Convert the pulse streams to a nibble stream. + */ + result = ConvertPulseStreamsToNibbles(&hdr, bitRate, nibbleBuf, pNibbleLen); + // fall through with result bail: - /* clean up */ - if (hdr.avgStream != nil) - delete[] hdr.avgStream; - if (hdr.minStream != nil) - delete[] hdr.minStream; - if (hdr.maxStream != nil) - delete[] hdr.maxStream; - if (hdr.idxStream != nil) - delete[] hdr.idxStream; - return result; + /* clean up */ + if (hdr.avgStream != nil) + delete[] hdr.avgStream; + if (hdr.minStream != nil) + delete[] hdr.minStream; + if (hdr.maxStream != nil) + delete[] hdr.maxStream; + if (hdr.idxStream != nil) + delete[] hdr.idxStream; + return result; } /* @@ -577,47 +577,47 @@ bail: */ bool WrapperFDI::UncompressPulseStream(const unsigned char* inputBuf, long inputLen, - unsigned long* outputBuf, long numPulses, int format, int bytesPerPulse) + unsigned long* outputBuf, long numPulses, int format, int bytesPerPulse) { - assert(bytesPerPulse == 2 || bytesPerPulse == 4); + assert(bytesPerPulse == 2 || bytesPerPulse == 4); - /* - * Sample code has a snippet that says: if the format is "uncompressed" - * but inputLen < (numPulses*2), treat it as compressed. This may be - * for handling some badly-formed images. Not currently doing it here. - */ + /* + * Sample code has a snippet that says: if the format is "uncompressed" + * but inputLen < (numPulses*2), treat it as compressed. This may be + * for handling some badly-formed images. Not currently doing it here. + */ - if (format == kCompUncompressed) { - int i; + if (format == kCompUncompressed) { + int i; - WMSG0("NOT TESTED\n"); // remove this when we've tested it + WMSG0("NOT TESTED\n"); // remove this when we've tested it - if (inputLen != numPulses * bytesPerPulse) { - WMSG2(" FDI: got unc inputLen=%ld, outputLen=%ld\n", - inputLen, numPulses * bytesPerPulse); - return false; - } - if (bytesPerPulse == 2) { - for (i = 0; i < numPulses; i++) { - *outputBuf++ = GetShortBE(inputBuf); - inputBuf += 2; - } - } else { - for (i = 0; i < numPulses; i++) { - *outputBuf++ = GetLongBE(inputBuf); - inputBuf += 4; - } - } - } else if (format == kCompHuffman) { - if (!ExpandHuffman(inputBuf, inputLen, outputBuf, numPulses)) - return false; - //WMSG0(" FDI: Huffman expansion succeeded\n"); - } else { - WMSG1(" FDI: got weird compression format %d\n", format); - return false; - } + if (inputLen != numPulses * bytesPerPulse) { + WMSG2(" FDI: got unc inputLen=%ld, outputLen=%ld\n", + inputLen, numPulses * bytesPerPulse); + return false; + } + if (bytesPerPulse == 2) { + for (i = 0; i < numPulses; i++) { + *outputBuf++ = GetShortBE(inputBuf); + inputBuf += 2; + } + } else { + for (i = 0; i < numPulses; i++) { + *outputBuf++ = GetLongBE(inputBuf); + inputBuf += 4; + } + } + } else if (format == kCompHuffman) { + if (!ExpandHuffman(inputBuf, inputLen, outputBuf, numPulses)) + return false; + //WMSG0(" FDI: Huffman expansion succeeded\n"); + } else { + WMSG1(" FDI: got weird compression format %d\n", format); + return false; + } - return true; + return true; } /* @@ -632,100 +632,100 @@ WrapperFDI::UncompressPulseStream(const unsigned char* inputBuf, long inputLen, */ bool WrapperFDI::ExpandHuffman(const unsigned char* inputBuf, long inputLen, - unsigned long* outputBuf, long numPulses) + unsigned long* outputBuf, long numPulses) { - HuffNode root; - const unsigned char* origInputBuf = inputBuf; - bool signExtend, sixteenBits; - int i, subStreamShift; - unsigned char bits; - unsigned char bitMask; + HuffNode root; + const unsigned char* origInputBuf = inputBuf; + bool signExtend, sixteenBits; + int i, subStreamShift; + unsigned char bits; + unsigned char bitMask; - memset(outputBuf, 0, numPulses * sizeof(unsigned long)); - subStreamShift = 1; + memset(outputBuf, 0, numPulses * sizeof(unsigned long)); + subStreamShift = 1; - while (subStreamShift != 0) { - if (inputBuf - origInputBuf >= inputLen) { - WMSG0(" FDI: overran input(1)\n"); - return false; - } + while (subStreamShift != 0) { + if (inputBuf - origInputBuf >= inputLen) { + WMSG0(" FDI: overran input(1)\n"); + return false; + } - /* decode the sub-stream header */ - bits = *inputBuf++; - subStreamShift = bits & 0x7f; // low-order bit number - signExtend = (bits & 0x80) != 0; - bits = *inputBuf++; - sixteenBits = (bits & 0x80) != 0; // ignore redundant high-order + /* decode the sub-stream header */ + bits = *inputBuf++; + subStreamShift = bits & 0x7f; // low-order bit number + signExtend = (bits & 0x80) != 0; + bits = *inputBuf++; + sixteenBits = (bits & 0x80) != 0; // ignore redundant high-order - //WMSG3(" FDI: shift=%d ext=%d sixt=%d\n", - // subStreamShift, signExtend, sixteenBits); + //WMSG3(" FDI: shift=%d ext=%d sixt=%d\n", + // subStreamShift, signExtend, sixteenBits); - /* decode the Huffman tree structure */ - root.left = nil; - root.right = nil; - bitMask = 0; - inputBuf = HuffExtractTree(inputBuf, &root, &bits, &bitMask); + /* decode the Huffman tree structure */ + root.left = nil; + root.right = nil; + bitMask = 0; + inputBuf = HuffExtractTree(inputBuf, &root, &bits, &bitMask); - //WMSG1(" after tree: off=%d\n", inputBuf - origInputBuf); + //WMSG1(" after tree: off=%d\n", inputBuf - origInputBuf); - /* extract the Huffman node values */ - if (sixteenBits) - inputBuf = HuffExtractValues16(inputBuf, &root); - else - inputBuf = HuffExtractValues8(inputBuf, &root); + /* extract the Huffman node values */ + if (sixteenBits) + inputBuf = HuffExtractValues16(inputBuf, &root); + else + inputBuf = HuffExtractValues8(inputBuf, &root); - if (inputBuf - origInputBuf >= inputLen) { - WMSG0(" FDI: overran input(2)\n"); - return false; - } - //WMSG1(" after values: off=%d\n", inputBuf - origInputBuf); + if (inputBuf - origInputBuf >= inputLen) { + WMSG0(" FDI: overran input(2)\n"); + return false; + } + //WMSG1(" after values: off=%d\n", inputBuf - origInputBuf); - /* decode the data over all pulses */ - bitMask = 0; - for (i = 0; i < numPulses; i++) { - unsigned long outVal; - const HuffNode* pCurrent = &root; + /* decode the data over all pulses */ + bitMask = 0; + for (i = 0; i < numPulses; i++) { + unsigned long outVal; + const HuffNode* pCurrent = &root; - /* chase down the tree until we hit a leaf */ - /* (note: nodes have two kids or none) */ - while (true) { - if (pCurrent->left == nil) { - break; - } else { - bitMask >>= 1; - if (bitMask == 0) { - bitMask = 0x80; - bits = *inputBuf++; - } - if (bits & bitMask) - pCurrent = pCurrent->right; - else - pCurrent = pCurrent->left; - } - } + /* chase down the tree until we hit a leaf */ + /* (note: nodes have two kids or none) */ + while (true) { + if (pCurrent->left == nil) { + break; + } else { + bitMask >>= 1; + if (bitMask == 0) { + bitMask = 0x80; + bits = *inputBuf++; + } + if (bits & bitMask) + pCurrent = pCurrent->right; + else + pCurrent = pCurrent->left; + } + } - outVal = outputBuf[i]; - if (signExtend) { - if (sixteenBits) - outVal |= HuffSignExtend16(pCurrent->val) << subStreamShift; - else - outVal |= HuffSignExtend8(pCurrent->val) << subStreamShift; - } else { - outVal |= pCurrent->val << subStreamShift; - } - outputBuf[i] = outVal; - } - HuffFreeNodes(root.left); - HuffFreeNodes(root.right); - } + outVal = outputBuf[i]; + if (signExtend) { + if (sixteenBits) + outVal |= HuffSignExtend16(pCurrent->val) << subStreamShift; + else + outVal |= HuffSignExtend8(pCurrent->val) << subStreamShift; + } else { + outVal |= pCurrent->val << subStreamShift; + } + outputBuf[i] = outVal; + } + HuffFreeNodes(root.left); + HuffFreeNodes(root.right); + } - if (inputBuf - origInputBuf != inputLen) { - WMSG2(" FDI: warning: Huffman input %d vs. %ld\n", - inputBuf - origInputBuf, inputLen); - return false; - } + if (inputBuf - origInputBuf != inputLen) { + WMSG2(" FDI: warning: Huffman input %d vs. %ld\n", + inputBuf - origInputBuf, inputLen); + return false; + } - return true; + return true; } @@ -734,31 +734,31 @@ WrapperFDI::ExpandHuffman(const unsigned char* inputBuf, long inputLen, */ const unsigned char* WrapperFDI::HuffExtractTree(const unsigned char* inputBuf, HuffNode* pNode, - unsigned char* pBits, unsigned char* pBitMask) + unsigned char* pBits, unsigned char* pBitMask) { - unsigned char val; + unsigned char val; - if (*pBitMask == 0) { - *pBits = *inputBuf++; - *pBitMask = 0x80; - } - val = *pBits & *pBitMask; - (*pBitMask) >>= 1; + if (*pBitMask == 0) { + *pBits = *inputBuf++; + *pBitMask = 0x80; + } + val = *pBits & *pBitMask; + (*pBitMask) >>= 1; - //WMSG1(" val=%d\n", val); + //WMSG1(" val=%d\n", val); - if (val != 0) { - assert(pNode->left == nil); - assert(pNode->right == nil); - return inputBuf; - } else { - pNode->left = new HuffNode; - memset(pNode->left, 0, sizeof(HuffNode)); - inputBuf = HuffExtractTree(inputBuf, pNode->left, pBits, pBitMask); - pNode->right = new HuffNode; - memset(pNode->right, 0, sizeof(HuffNode)); - return HuffExtractTree(inputBuf, pNode->right, pBits, pBitMask); - } + if (val != 0) { + assert(pNode->left == nil); + assert(pNode->right == nil); + return inputBuf; + } else { + pNode->left = new HuffNode; + memset(pNode->left, 0, sizeof(HuffNode)); + inputBuf = HuffExtractTree(inputBuf, pNode->left, pBits, pBitMask); + pNode->right = new HuffNode; + memset(pNode->right, 0, sizeof(HuffNode)); + return HuffExtractTree(inputBuf, pNode->right, pBits, pBitMask); + } } /* @@ -767,14 +767,14 @@ WrapperFDI::HuffExtractTree(const unsigned char* inputBuf, HuffNode* pNode, const unsigned char* WrapperFDI::HuffExtractValues16(const unsigned char* inputBuf, HuffNode* pNode) { - if (pNode->left == nil) { - pNode->val = (*inputBuf++) << 8; - pNode->val |= *inputBuf++; - return inputBuf; - } else { - inputBuf = HuffExtractValues16(inputBuf, pNode->left); - return HuffExtractValues16(inputBuf, pNode->right); - } + if (pNode->left == nil) { + pNode->val = (*inputBuf++) << 8; + pNode->val |= *inputBuf++; + return inputBuf; + } else { + inputBuf = HuffExtractValues16(inputBuf, pNode->left); + return HuffExtractValues16(inputBuf, pNode->right); + } } /* @@ -783,13 +783,13 @@ WrapperFDI::HuffExtractValues16(const unsigned char* inputBuf, HuffNode* pNode) const unsigned char* WrapperFDI::HuffExtractValues8(const unsigned char* inputBuf, HuffNode* pNode) { - if (pNode->left == nil) { - pNode->val = *inputBuf++; - return inputBuf; - } else { - inputBuf = HuffExtractValues8(inputBuf, pNode->left); - return HuffExtractValues8(inputBuf, pNode->right); - } + if (pNode->left == nil) { + pNode->val = *inputBuf++; + return inputBuf; + } else { + inputBuf = HuffExtractValues8(inputBuf, pNode->left); + return HuffExtractValues8(inputBuf, pNode->right); + } } /* @@ -798,11 +798,11 @@ WrapperFDI::HuffExtractValues8(const unsigned char* inputBuf, HuffNode* pNode) void WrapperFDI::HuffFreeNodes(HuffNode* pNode) { - if (pNode != nil) { - HuffFreeNodes(pNode->left); - HuffFreeNodes(pNode->right); - delete pNode; - } + if (pNode != nil) { + HuffFreeNodes(pNode->left); + HuffFreeNodes(pNode->right); + delete pNode; + } } @@ -812,9 +812,9 @@ WrapperFDI::HuffFreeNodes(HuffNode* pNode) unsigned long WrapperFDI::HuffSignExtend16(unsigned long val) { - if (val & 0x8000) - val |= 0xffff0000; - return val; + if (val & 0x8000) + val |= 0xffff0000; + return val; } /* @@ -823,15 +823,15 @@ WrapperFDI::HuffSignExtend16(unsigned long val) unsigned long WrapperFDI::HuffSignExtend8(unsigned long val) { - if (val & 0x80) - val |= 0xffffff00; - return val; + if (val & 0x80) + val |= 0xffffff00; + return val; } /* use these to extract values from the index stream */ -#define ZeroStateCount(_val) (((_val) >> 8) & 0xff) -#define OneStateCount(_val) ((_val) & 0xff) +#define ZeroStateCount(_val) (((_val) >> 8) & 0xff) +#define OneStateCount(_val) ((_val) & 0xff) /* * Convert our collection of pulse streams into (what we hope will be) @@ -845,226 +845,226 @@ WrapperFDI::HuffSignExtend8(unsigned long val) */ bool WrapperFDI::ConvertPulseStreamsToNibbles(PulseIndexHeader* pHdr, int bitRate, - unsigned char* nibbleBuf, long* pNibbleLen) + unsigned char* nibbleBuf, long* pNibbleLen) { - unsigned long* fakeIdxStream = nil; - bool result = false; - int i; + unsigned long* fakeIdxStream = nil; + bool result = false; + int i; - /* - * Stream pointers. If we don't have a stream, fake it. - */ - unsigned long* avgStream; - unsigned long* minStream; - unsigned long* maxStream; - unsigned long* idxStream; - - avgStream = pHdr->avgStream; - if (pHdr->minStream != nil && pHdr->maxStream != nil) { - minStream = pHdr->minStream; - maxStream = pHdr->maxStream; + /* + * Stream pointers. If we don't have a stream, fake it. + */ + unsigned long* avgStream; + unsigned long* minStream; + unsigned long* maxStream; + unsigned long* idxStream; + + avgStream = pHdr->avgStream; + if (pHdr->minStream != nil && pHdr->maxStream != nil) { + minStream = pHdr->minStream; + maxStream = pHdr->maxStream; - /* adjust the values in the min/max streams */ - for (i = 0; i < pHdr->numPulses; i++) { - maxStream[i] = avgStream[i] + minStream[i] - maxStream[i]; - minStream[i] = avgStream[i] - minStream[i]; - } - } else { - minStream = pHdr->avgStream; - maxStream = pHdr->avgStream; - } + /* adjust the values in the min/max streams */ + for (i = 0; i < pHdr->numPulses; i++) { + maxStream[i] = avgStream[i] + minStream[i] - maxStream[i]; + minStream[i] = avgStream[i] - minStream[i]; + } + } else { + minStream = pHdr->avgStream; + maxStream = pHdr->avgStream; + } - if (pHdr->idxStream != nil) - idxStream = pHdr->idxStream; - else { - /* - * The UAE sample code has some stuff to fake it. The code there - * is broken, so I'm guessing it has never been used, but I'm going - * to replicate it here (and probably never test it either). This - * assumes that the original was written for a big-endian machine. - */ - WMSG0(" FDI: HEY: using fake index stream\n"); - DebugBreak(); - fakeIdxStream = new unsigned long[pHdr->numPulses]; - if (fakeIdxStream == nil) { - WMSG0(" FDI: unable to alloc fake idx stream\n"); - goto bail; - } - for (i = 1; i < pHdr->numPulses; i++) - fakeIdxStream[i] = 0x0200; // '1' for two, '0' for zero - fakeIdxStream[0] = 0x0101; // '1' for one, '0' for one + if (pHdr->idxStream != nil) + idxStream = pHdr->idxStream; + else { + /* + * The UAE sample code has some stuff to fake it. The code there + * is broken, so I'm guessing it has never been used, but I'm going + * to replicate it here (and probably never test it either). This + * assumes that the original was written for a big-endian machine. + */ + WMSG0(" FDI: HEY: using fake index stream\n"); + DebugBreak(); + fakeIdxStream = new unsigned long[pHdr->numPulses]; + if (fakeIdxStream == nil) { + WMSG0(" FDI: unable to alloc fake idx stream\n"); + goto bail; + } + for (i = 1; i < pHdr->numPulses; i++) + fakeIdxStream[i] = 0x0200; // '1' for two, '0' for zero + fakeIdxStream[0] = 0x0101; // '1' for one, '0' for one - idxStream = fakeIdxStream; - } + idxStream = fakeIdxStream; + } - /* - * Compute a value for maxIndex. - */ - unsigned long maxIndex; + /* + * Compute a value for maxIndex. + */ + unsigned long maxIndex; - maxIndex = 0; - for (i = 0; i < pHdr->numPulses; i++) { - unsigned long sum; + maxIndex = 0; + for (i = 0; i < pHdr->numPulses; i++) { + unsigned long sum; - /* add up the two single-byte values in the index stream */ - sum = ZeroStateCount(idxStream[i]) + OneStateCount(idxStream[i]); - if (sum > maxIndex) - maxIndex = sum; - } + /* add up the two single-byte values in the index stream */ + sum = ZeroStateCount(idxStream[i]) + OneStateCount(idxStream[i]); + if (sum > maxIndex) + maxIndex = sum; + } - /* - * Compute a value for indexOffset. - */ - int indexOffset; + /* + * Compute a value for indexOffset. + */ + int indexOffset; - indexOffset = 0; - for (i = 0; i < pHdr->numPulses && OneStateCount(idxStream[i]) != 0; i++) { - /* "falling edge, replace with ZeroStateCount for rising edge" */ - } - if (i < pHdr->numPulses) { - int start = i; - do { - i++; - if (i >= pHdr->numPulses) - i = 0; // wrapped around - } while (i != start && ZeroStateCount(idxStream[i]) == 0); - if (i != start) { - /* index pulse detected */ - while (i != start && - ZeroStateCount(idxStream[i]) > OneStateCount(idxStream[i])) - { - i++; - if (i >= pHdr->numPulses) - i = 0; - } - if (i != start) - indexOffset = i; /* index position detected */ - } - } + indexOffset = 0; + for (i = 0; i < pHdr->numPulses && OneStateCount(idxStream[i]) != 0; i++) { + /* "falling edge, replace with ZeroStateCount for rising edge" */ + } + if (i < pHdr->numPulses) { + int start = i; + do { + i++; + if (i >= pHdr->numPulses) + i = 0; // wrapped around + } while (i != start && ZeroStateCount(idxStream[i]) == 0); + if (i != start) { + /* index pulse detected */ + while (i != start && + ZeroStateCount(idxStream[i]) > OneStateCount(idxStream[i])) + { + i++; + if (i >= pHdr->numPulses) + i = 0; + } + if (i != start) + indexOffset = i; /* index position detected */ + } + } - /* - * Compute totalAvg and weakBits, and rewrite idxStream. - * (We don't actually use weakBits.) - */ - unsigned long totalAvg; - int weakBits; + /* + * Compute totalAvg and weakBits, and rewrite idxStream. + * (We don't actually use weakBits.) + */ + unsigned long totalAvg; + int weakBits; - totalAvg = weakBits = 0; - for (i = 0; i < pHdr->numPulses; i++) { - unsigned int sum; - sum = ZeroStateCount(idxStream[i]) + OneStateCount(idxStream[i]); - if (sum >= maxIndex) - totalAvg += avgStream[i]; // could this overflow...? - else - weakBits++; + totalAvg = weakBits = 0; + for (i = 0; i < pHdr->numPulses; i++) { + unsigned int sum; + sum = ZeroStateCount(idxStream[i]) + OneStateCount(idxStream[i]); + if (sum >= maxIndex) + totalAvg += avgStream[i]; // could this overflow...? + else + weakBits++; - idxStream[i] = sum; - } + idxStream[i] = sum; + } - WMSG4(" FDI: maxIndex=%lu indexOffset=%d totalAvg=%lu weakBits=%d\n", - maxIndex, indexOffset, totalAvg, weakBits); + WMSG4(" FDI: maxIndex=%lu indexOffset=%d totalAvg=%lu weakBits=%d\n", + maxIndex, indexOffset, totalAvg, weakBits); - /* - * Take our altered stream values and the stuff we've calculated, - * and convert the pulse values into bits. - */ - unsigned char bitBuffer[kBitBufferSize]; - int bitCount; - - bitCount = kBitBufferSize; + /* + * Take our altered stream values and the stuff we've calculated, + * and convert the pulse values into bits. + */ + unsigned char bitBuffer[kBitBufferSize]; + int bitCount; + + bitCount = kBitBufferSize; - if (!ConvertPulsesToBits(avgStream, minStream, maxStream, idxStream, - pHdr->numPulses, maxIndex, indexOffset, totalAvg, bitRate, - bitBuffer, &bitCount)) - { - WMSG0(" FDI: ConvertPulsesToBits() failed\n"); - goto bail; - } + if (!ConvertPulsesToBits(avgStream, minStream, maxStream, idxStream, + pHdr->numPulses, maxIndex, indexOffset, totalAvg, bitRate, + bitBuffer, &bitCount)) + { + WMSG0(" FDI: ConvertPulsesToBits() failed\n"); + goto bail; + } - //WMSG1(" Got %d bits\n", bitCount); - if (bitCount < 0) { - WMSG0(" FDI: overran output bit buffer\n"); - goto bail; - } + //WMSG1(" Got %d bits\n", bitCount); + if (bitCount < 0) { + WMSG0(" FDI: overran output bit buffer\n"); + goto bail; + } - /* - * We have a bit stream with the GCR bits as they appear coming out of - * the IWM. Convert it to 8-bit nibble form. - * - * We currently discard self-sync byte information. - */ - if (!ConvertBitsToNibbles(bitBuffer, bitCount, nibbleBuf, pNibbleLen)) - { - WMSG0(" FDI: ConvertBitsToNibbles() failed\n"); - goto bail; - } + /* + * We have a bit stream with the GCR bits as they appear coming out of + * the IWM. Convert it to 8-bit nibble form. + * + * We currently discard self-sync byte information. + */ + if (!ConvertBitsToNibbles(bitBuffer, bitCount, nibbleBuf, pNibbleLen)) + { + WMSG0(" FDI: ConvertBitsToNibbles() failed\n"); + goto bail; + } - result = true; + result = true; bail: - delete[] fakeIdxStream; - return result; + delete[] fakeIdxStream; + return result; } /* * Local data structures. Not worth putting in the header file. */ -const int kPulseLimitVal = 15; /* "tolerance of 15%" */ +const int kPulseLimitVal = 15; /* "tolerance of 15%" */ typedef struct PulseSamples { - unsigned long size; - int numBits; + unsigned long size; + int numBits; } PulseSamples; class PulseSampleCollection { public: - PulseSampleCollection(void) { - fArrayIndex = fTotalDiv = -1; - fTotal = 0; - } - ~PulseSampleCollection(void) {} - - void Create(int stdMFM2BitCellSize, int numBits) { - int i; + PulseSampleCollection(void) { + fArrayIndex = fTotalDiv = -1; + fTotal = 0; + } + ~PulseSampleCollection(void) {} + + void Create(int stdMFM2BitCellSize, int numBits) { + int i; - fArrayIndex = 0; - fTotal = 0; - fTotalDiv = 0; - for (i = 0; i < kSampleArrayMax; i++) { - // "That is (total track length / 50000) for Amiga double density" - fArray[i].size = stdMFM2BitCellSize; - fTotal += fArray[i].size; - fArray[i].numBits = numBits; - fTotalDiv += fArray[i].numBits; - } - assert(fTotalDiv != 0); - } + fArrayIndex = 0; + fTotal = 0; + fTotalDiv = 0; + for (i = 0; i < kSampleArrayMax; i++) { + // "That is (total track length / 50000) for Amiga double density" + fArray[i].size = stdMFM2BitCellSize; + fTotal += fArray[i].size; + fArray[i].numBits = numBits; + fTotalDiv += fArray[i].numBits; + } + assert(fTotalDiv != 0); + } - unsigned long GetTotal(void) const { return fTotal; } - int GetTotalDiv(void) const { return fTotalDiv; } + unsigned long GetTotal(void) const { return fTotal; } + int GetTotalDiv(void) const { return fTotalDiv; } - void AdjustTotal(long val) { fTotal += val; } - void AdjustTotalDiv(int val) { fTotalDiv += val; } - void IncrIndex(void) { - fArrayIndex++; - if (fArrayIndex >= kSampleArrayMax) - fArrayIndex = 0; - } + void AdjustTotal(long val) { fTotal += val; } + void AdjustTotalDiv(int val) { fTotalDiv += val; } + void IncrIndex(void) { + fArrayIndex++; + if (fArrayIndex >= kSampleArrayMax) + fArrayIndex = 0; + } - PulseSamples* GetCurrentArrayEntry(void) { - return &fArray[fArrayIndex]; - } + PulseSamples* GetCurrentArrayEntry(void) { + return &fArray[fArrayIndex]; + } - enum { - kSampleArrayMax = 10, - }; + enum { + kSampleArrayMax = 10, + }; private: - PulseSamples fArray[kSampleArrayMax]; - int fArrayIndex; - unsigned long fTotal; - int fTotalDiv; + PulseSamples fArray[kSampleArrayMax]; + int fArrayIndex; + unsigned long fTotal; + int fTotalDiv; }; #define MY_RANDOM @@ -1079,22 +1079,22 @@ private: * problems that the code has with (2^31-1) implementations. */ #undef RAND_MAX -#define RAND_MAX 32767 +#define RAND_MAX 32767 int WrapperFDI::MyRand(void) { - const int kNumStates = 31; - const int kQuantum = RAND_MAX / (kNumStates+1); - static int state = 0; - int retVal; + const int kNumStates = 31; + const int kQuantum = RAND_MAX / (kNumStates+1); + static int state = 0; + int retVal; - state++; - if (state == kNumStates) - state = 0; + state++; + if (state == kNumStates) + state = 0; - retVal = (kQuantum * state) + (kQuantum / 2); - assert(retVal >= 0 && retVal <= RAND_MAX); - return retVal; + retVal = (kQuantum * state) + (kQuantum / 2); + assert(retVal >= 0 && retVal <= RAND_MAX); + return retVal; } #endif @@ -1110,341 +1110,341 @@ WrapperFDI::MyRand(void) */ bool WrapperFDI::ConvertPulsesToBits(const unsigned long* avgStream, - const unsigned long* minStream, const unsigned long* maxStream, - const unsigned long* idxStream, int numPulses, int maxIndex, - int indexOffset, unsigned long totalAvg, int bitRate, - unsigned char* outputBuf, int* pOutputLen) + const unsigned long* minStream, const unsigned long* maxStream, + const unsigned long* idxStream, int numPulses, int maxIndex, + int indexOffset, unsigned long totalAvg, int bitRate, + unsigned char* outputBuf, int* pOutputLen) { - PulseSampleCollection samples; - BitOutputBuffer bitOutput(outputBuf, *pOutputLen); - /* magic numbers, from somewhere */ - const unsigned long kStdMFM2BitCellSize = (totalAvg * 5) / bitRate; - const unsigned long kStdMFM8BitCellSize = (totalAvg * 20) / bitRate; - int mfmMagic = 0; // if set to 1, decode as MFM rather than GCR - bool result = false; - int i; - //int debugCounter = 0; + PulseSampleCollection samples; + BitOutputBuffer bitOutput(outputBuf, *pOutputLen); + /* magic numbers, from somewhere */ + const unsigned long kStdMFM2BitCellSize = (totalAvg * 5) / bitRate; + const unsigned long kStdMFM8BitCellSize = (totalAvg * 20) / bitRate; + int mfmMagic = 0; // if set to 1, decode as MFM rather than GCR + bool result = false; + int i; + //int debugCounter = 0; - /* sample code doesn't do this, but I want consistent results */ - srand(0); + /* sample code doesn't do this, but I want consistent results */ + srand(0); - /* - * "detects a long-enough stable pulse coming just after another - * stable pulse" - */ - i = 1; - while (i < numPulses && - (idxStream[i] < (unsigned long) maxIndex || - idxStream[i-1] < (unsigned long) maxIndex || - minStream[i] < (kStdMFM2BitCellSize - (kStdMFM2BitCellSize / 4)) - )) - { - i++; - } - if (i == numPulses) { - WMSG0(" FDI: no stable and long-enough pulse in track\n"); - goto bail; - } + /* + * "detects a long-enough stable pulse coming just after another + * stable pulse" + */ + i = 1; + while (i < numPulses && + (idxStream[i] < (unsigned long) maxIndex || + idxStream[i-1] < (unsigned long) maxIndex || + minStream[i] < (kStdMFM2BitCellSize - (kStdMFM2BitCellSize / 4)) + )) + { + i++; + } + if (i == numPulses) { + WMSG0(" FDI: no stable and long-enough pulse in track\n"); + goto bail; + } - /* - * Set up some variables. - */ - int nextI, endOfData, adjust, bitOffset, step; - unsigned long refPulse; - long jitter; + /* + * Set up some variables. + */ + int nextI, endOfData, adjust, bitOffset, step; + unsigned long refPulse; + long jitter; - samples.Create(kStdMFM2BitCellSize, 1 + mfmMagic); - nextI = i; - endOfData = i; - i--; - adjust = 0; - bitOffset = 0; - refPulse = 0; - jitter = 0; - step = -1; + samples.Create(kStdMFM2BitCellSize, 1 + mfmMagic); + nextI = i; + endOfData = i; + i--; + adjust = 0; + bitOffset = 0; + refPulse = 0; + jitter = 0; + step = -1; - /* - * Run through the data three times: - * (-1) do stuff - * (0) do more stuff - * (1) output bits - */ - while (step < 2) { - /* - * Calculates the current average bit rate from previously - * decoded data. - */ - unsigned long avgSize; - int kCell8Limit = (kPulseLimitVal * kStdMFM8BitCellSize) / 100; + /* + * Run through the data three times: + * (-1) do stuff + * (0) do more stuff + * (1) output bits + */ + while (step < 2) { + /* + * Calculates the current average bit rate from previously + * decoded data. + */ + unsigned long avgSize; + int kCell8Limit = (kPulseLimitVal * kStdMFM8BitCellSize) / 100; - /* this is the new average size for one MFM bit */ - avgSize = (samples.GetTotal() << (2 + mfmMagic)) / samples.GetTotalDiv(); + /* this is the new average size for one MFM bit */ + avgSize = (samples.GetTotal() << (2 + mfmMagic)) / samples.GetTotalDiv(); - /* - * Prevent avgSize from getting too far out of whack. - * - * "you can try tighter ranges than 25%, or wider ranges. I would - * probably go for tighter..." - */ - if ((avgSize < kStdMFM8BitCellSize - kCell8Limit) || - (avgSize > kStdMFM8BitCellSize + kCell8Limit)) - { - avgSize = kStdMFM8BitCellSize; - } + /* + * Prevent avgSize from getting too far out of whack. + * + * "you can try tighter ranges than 25%, or wider ranges. I would + * probably go for tighter..." + */ + if ((avgSize < kStdMFM8BitCellSize - kCell8Limit) || + (avgSize > kStdMFM8BitCellSize + kCell8Limit)) + { + avgSize = kStdMFM8BitCellSize; + } - /* - * Get the next long-enough pulse (may require more than one pulse). - */ - unsigned long pulse; + /* + * Get the next long-enough pulse (may require more than one pulse). + */ + unsigned long pulse; - pulse = 0; - while (pulse < ((avgSize / 4) - (avgSize / 16))) { - unsigned long avgPulse, minPulse, maxPulse; + pulse = 0; + while (pulse < ((avgSize / 4) - (avgSize / 16))) { + unsigned long avgPulse, minPulse, maxPulse; - /* advance i */ - i++; - if (i >= numPulses) - i = 0; // wrapped around + /* advance i */ + i++; + if (i >= numPulses) + i = 0; // wrapped around - /* advance nextI */ - if (i == nextI) { - do { - nextI++; - if (nextI >= numPulses) - nextI = 0; - } while (idxStream[nextI] < (unsigned long) maxIndex); - } + /* advance nextI */ + if (i == nextI) { + do { + nextI++; + if (nextI >= numPulses) + nextI = 0; + } while (idxStream[nextI] < (unsigned long) maxIndex); + } - if (idxStream[i] >= (unsigned long) maxIndex) { - /* stable pulse */ - avgPulse = avgStream[i] - jitter; - minPulse = minStream[i]; - maxPulse = maxStream[i]; - if (jitter >= 0) - maxPulse -= jitter; - else - minPulse -= jitter; + if (idxStream[i] >= (unsigned long) maxIndex) { + /* stable pulse */ + avgPulse = avgStream[i] - jitter; + minPulse = minStream[i]; + maxPulse = maxStream[i]; + if (jitter >= 0) + maxPulse -= jitter; + else + minPulse -= jitter; - if (maxStream[nextI] - avgStream[nextI] < avgPulse - minPulse) - minPulse = avgPulse - (maxStream[nextI] - avgStream[nextI]); - if (avgStream[nextI] - minStream[nextI] < maxPulse - avgPulse) - maxPulse = avgPulse + (avgStream[nextI] - minStream[nextI]); - if (minPulse < refPulse) - minPulse = refPulse; + if (maxStream[nextI] - avgStream[nextI] < avgPulse - minPulse) + minPulse = avgPulse - (maxStream[nextI] - avgStream[nextI]); + if (avgStream[nextI] - minStream[nextI] < maxPulse - avgPulse) + maxPulse = avgPulse + (avgStream[nextI] - minStream[nextI]); + if (minPulse < refPulse) + minPulse = refPulse; - /* - * This appears to use a pseudo-random number generator - * to dither the signal. This strikes me as highly - * questionable, but I'm trying to recreate what the sample - * code does, and I don't fully understand this stuff. - */ - int randVal; + /* + * This appears to use a pseudo-random number generator + * to dither the signal. This strikes me as highly + * questionable, but I'm trying to recreate what the sample + * code does, and I don't fully understand this stuff. + */ + int randVal; - randVal = rand(); - if (randVal < (RAND_MAX / 2)) { - if (randVal > (RAND_MAX / 4)) { - if (randVal <= (3 * (RAND_MAX / 8))) - randVal = (2 * randVal) - (RAND_MAX / 4); - else - randVal = (4 * randVal) - RAND_MAX; - } - jitter = 0 - (randVal * (avgPulse - minPulse)) / RAND_MAX; - } else { - randVal -= RAND_MAX / 2; - if (randVal > (RAND_MAX / 4)) { - if (randVal <= (3 * (RAND_MAX / 8))) - randVal = (2 * randVal) - (RAND_MAX / 4); - else - randVal = (4 * randVal) - RAND_MAX; - } - jitter = (randVal * (maxPulse - avgPulse)) / RAND_MAX; - } - avgPulse += jitter; + randVal = rand(); + if (randVal < (RAND_MAX / 2)) { + if (randVal > (RAND_MAX / 4)) { + if (randVal <= (3 * (RAND_MAX / 8))) + randVal = (2 * randVal) - (RAND_MAX / 4); + else + randVal = (4 * randVal) - RAND_MAX; + } + jitter = 0 - (randVal * (avgPulse - minPulse)) / RAND_MAX; + } else { + randVal -= RAND_MAX / 2; + if (randVal > (RAND_MAX / 4)) { + if (randVal <= (3 * (RAND_MAX / 8))) + randVal = (2 * randVal) - (RAND_MAX / 4); + else + randVal = (4 * randVal) - RAND_MAX; + } + jitter = (randVal * (maxPulse - avgPulse)) / RAND_MAX; + } + avgPulse += jitter; - if (avgPulse < minPulse || avgPulse > maxPulse) { - /* this is bad -- we're out of bounds */ - WMSG3(" FDI: avgPulse out of bounds: avg=%lu min=%lu max=%lu\n", - avgPulse, minPulse, maxPulse); - } - if (avgPulse < refPulse) { - /* I guess this is also bad */ - WMSG2(" FDI: avgPulse < refPulse (%lu %lu)\n", - avgPulse, refPulse); - } - pulse += avgPulse - refPulse; - refPulse = 0; + if (avgPulse < minPulse || avgPulse > maxPulse) { + /* this is bad -- we're out of bounds */ + WMSG3(" FDI: avgPulse out of bounds: avg=%lu min=%lu max=%lu\n", + avgPulse, minPulse, maxPulse); + } + if (avgPulse < refPulse) { + /* I guess this is also bad */ + WMSG2(" FDI: avgPulse < refPulse (%lu %lu)\n", + avgPulse, refPulse); + } + pulse += avgPulse - refPulse; + refPulse = 0; - /* - * If we've reached the end, advance to the next step. - */ - if (i == endOfData) - step++; - } else if ((unsigned long) rand() <= (idxStream[i] * RAND_MAX) / maxIndex) { - /* futz with it */ - int randVal; + /* + * If we've reached the end, advance to the next step. + */ + if (i == endOfData) + step++; + } else if ((unsigned long) rand() <= (idxStream[i] * RAND_MAX) / maxIndex) { + /* futz with it */ + int randVal; - avgPulse = avgStream[i]; - minPulse = minStream[i]; - maxPulse = maxStream[i]; + avgPulse = avgStream[i]; + minPulse = minStream[i]; + maxPulse = maxStream[i]; - randVal = rand(); - if (randVal < (RAND_MAX / 2)) { - if (randVal > (RAND_MAX / 4)) { - if (randVal <= (3 * (RAND_MAX / 8))) - randVal = (2 * randVal) - (RAND_MAX / 4); - else - randVal = (4 * randVal) - RAND_MAX; - } - avgPulse -= (randVal * (avgPulse - minPulse)) / RAND_MAX; - } else { - randVal -= RAND_MAX / 2; - if (randVal > (RAND_MAX / 4)) { - if (randVal <= (3 * (RAND_MAX / 8))) - randVal = (2 * randVal) - (RAND_MAX / 4); - else - randVal = (4 * randVal) - RAND_MAX; - } - avgPulse += (randVal * (maxPulse - avgPulse)) / RAND_MAX; - } - if (avgPulse > refPulse && - avgPulse < (avgStream[nextI] - jitter)) - { - pulse += avgPulse - refPulse; - refPulse = avgPulse; - } - } else { - // do nothing - } - } + randVal = rand(); + if (randVal < (RAND_MAX / 2)) { + if (randVal > (RAND_MAX / 4)) { + if (randVal <= (3 * (RAND_MAX / 8))) + randVal = (2 * randVal) - (RAND_MAX / 4); + else + randVal = (4 * randVal) - RAND_MAX; + } + avgPulse -= (randVal * (avgPulse - minPulse)) / RAND_MAX; + } else { + randVal -= RAND_MAX / 2; + if (randVal > (RAND_MAX / 4)) { + if (randVal <= (3 * (RAND_MAX / 8))) + randVal = (2 * randVal) - (RAND_MAX / 4); + else + randVal = (4 * randVal) - RAND_MAX; + } + avgPulse += (randVal * (maxPulse - avgPulse)) / RAND_MAX; + } + if (avgPulse > refPulse && + avgPulse < (avgStream[nextI] - jitter)) + { + pulse += avgPulse - refPulse; + refPulse = avgPulse; + } + } else { + // do nothing + } + } - /* - * "gets the size in bits from the pulse width, considering the current - * average bitrate" - * - * "realSize" will end up holding the number of bits we're going - * to output for this pulse. - */ - unsigned long adjustedPulse; - int realSize; + /* + * "gets the size in bits from the pulse width, considering the current + * average bitrate" + * + * "realSize" will end up holding the number of bits we're going + * to output for this pulse. + */ + unsigned long adjustedPulse; + int realSize; - adjustedPulse = pulse; - realSize = 0; - if (mfmMagic != 0) { - while (adjustedPulse >= avgSize) { - realSize += 4; - adjustedPulse -= avgSize / 2; - } - adjustedPulse <<= 3; - while (adjustedPulse >= ((avgSize * 4) + (avgSize / 4))) { - realSize += 2; - adjustedPulse -= avgSize * 2; - } - if (adjustedPulse >= ((avgSize * 3) + (avgSize / 4))) { - if (adjustedPulse <= ((avgSize * 4) - (avgSize / 4))) { - if ((2* ((adjustedPulse >> 2) - adjust)) <= - ((2 * avgSize) - (avgSize / 4))) - { - realSize += 3; - } else { - realSize += 4; - } - } else { - realSize += 4; - } - } else { - if (adjustedPulse > ((avgSize * 3) - (avgSize / 4))) { - realSize += 3; - } else { - if (adjustedPulse >= ((avgSize * 2) + (avgSize / 4))) { - if ((2 * ((adjustedPulse >> 2) - adjust)) < - (avgSize + (avgSize / 4))) - { - realSize += 2; - } else { - realSize += 3; - } - } else { - realSize += 2; - } - } - } - } else { - /* mfmMagic == 0, whatever that means */ - while (adjustedPulse >= (2 * avgSize)) { - realSize += 4; - adjustedPulse -= avgSize; - } - adjustedPulse <<= 2; + adjustedPulse = pulse; + realSize = 0; + if (mfmMagic != 0) { + while (adjustedPulse >= avgSize) { + realSize += 4; + adjustedPulse -= avgSize / 2; + } + adjustedPulse <<= 3; + while (adjustedPulse >= ((avgSize * 4) + (avgSize / 4))) { + realSize += 2; + adjustedPulse -= avgSize * 2; + } + if (adjustedPulse >= ((avgSize * 3) + (avgSize / 4))) { + if (adjustedPulse <= ((avgSize * 4) - (avgSize / 4))) { + if ((2* ((adjustedPulse >> 2) - adjust)) <= + ((2 * avgSize) - (avgSize / 4))) + { + realSize += 3; + } else { + realSize += 4; + } + } else { + realSize += 4; + } + } else { + if (adjustedPulse > ((avgSize * 3) - (avgSize / 4))) { + realSize += 3; + } else { + if (adjustedPulse >= ((avgSize * 2) + (avgSize / 4))) { + if ((2 * ((adjustedPulse >> 2) - adjust)) < + (avgSize + (avgSize / 4))) + { + realSize += 2; + } else { + realSize += 3; + } + } else { + realSize += 2; + } + } + } + } else { + /* mfmMagic == 0, whatever that means */ + while (adjustedPulse >= (2 * avgSize)) { + realSize += 4; + adjustedPulse -= avgSize; + } + adjustedPulse <<= 2; - while (adjustedPulse >= ((avgSize * 3) + (avgSize / 4))) { - realSize += 2; - adjustedPulse -= avgSize * 2; - } - if (adjustedPulse >= ((avgSize * 2) + (avgSize / 4))) { - if (adjustedPulse <= ((avgSize * 3) - (avgSize / 4))) { - if (((adjustedPulse >> 1) - adjust) < - (avgSize + (avgSize / 4))) - { - realSize += 2; - } else { - realSize += 3; - } - } else { - realSize += 3; - } - } else { - if (adjustedPulse > ((avgSize * 2) - (avgSize / 4))) - realSize += 2; - else { - if (adjustedPulse >= (avgSize + (avgSize / 4))) { - if (((adjustedPulse >> 1) - adjust) <= - (avgSize - (avgSize / 4))) - { - realSize++; - } else { - realSize += 2; - } - } else { - realSize++; - } - } - } - } + while (adjustedPulse >= ((avgSize * 3) + (avgSize / 4))) { + realSize += 2; + adjustedPulse -= avgSize * 2; + } + if (adjustedPulse >= ((avgSize * 2) + (avgSize / 4))) { + if (adjustedPulse <= ((avgSize * 3) - (avgSize / 4))) { + if (((adjustedPulse >> 1) - adjust) < + (avgSize + (avgSize / 4))) + { + realSize += 2; + } else { + realSize += 3; + } + } else { + realSize += 3; + } + } else { + if (adjustedPulse > ((avgSize * 2) - (avgSize / 4))) + realSize += 2; + else { + if (adjustedPulse >= (avgSize + (avgSize / 4))) { + if (((adjustedPulse >> 1) - adjust) <= + (avgSize - (avgSize / 4))) + { + realSize++; + } else { + realSize += 2; + } + } else { + realSize++; + } + } + } + } - /* - * "after one pass to correctly initialize the average bitrate, - * outputs the bits" - */ - if (step == 1) { - int j; + /* + * "after one pass to correctly initialize the average bitrate, + * outputs the bits" + */ + if (step == 1) { + int j; - for (j = realSize; j > 1; j--) - bitOutput.WriteBit(0); - bitOutput.WriteBit(1); - } + for (j = realSize; j > 1; j--) + bitOutput.WriteBit(0); + bitOutput.WriteBit(1); + } - /* - * Prepare for next pulse. - */ - adjust = ((realSize * avgSize) / (4 << mfmMagic)) - pulse; + /* + * Prepare for next pulse. + */ + adjust = ((realSize * avgSize) / (4 << mfmMagic)) - pulse; - PulseSamples* pSamples; - pSamples = samples.GetCurrentArrayEntry(); - samples.AdjustTotal(-(long)pSamples->size); - samples.AdjustTotalDiv(-pSamples->numBits); - pSamples->size = pulse; - pSamples->numBits = realSize; - samples.AdjustTotal(pulse); - samples.AdjustTotalDiv(realSize); - samples.IncrIndex(); - } + PulseSamples* pSamples; + pSamples = samples.GetCurrentArrayEntry(); + samples.AdjustTotal(-(long)pSamples->size); + samples.AdjustTotalDiv(-pSamples->numBits); + pSamples->size = pulse; + pSamples->numBits = realSize; + samples.AdjustTotal(pulse); + samples.AdjustTotalDiv(realSize); + samples.IncrIndex(); + } - *pOutputLen = bitOutput.Finish(); - WMSG1(" FDI: converted pulses to %d bits\n", *pOutputLen); - result = true; + *pOutputLen = bitOutput.Finish(); + WMSG1(" FDI: converted pulses to %d bits\n", *pOutputLen); + result = true; bail: - return result; + return result; } @@ -1465,77 +1465,77 @@ bail: */ bool WrapperFDI::ConvertBitsToNibbles(const unsigned char* bitBuffer, int bitCount, - unsigned char* nibbleBuf, long* pNibbleLen) + unsigned char* nibbleBuf, long* pNibbleLen) { - BitInputBuffer inputBuffer(bitBuffer, bitCount); - const unsigned char* nibbleBufStart = nibbleBuf; - long outputBufSize = *pNibbleLen; - bool result = false; - unsigned char val; - bool wrap; + BitInputBuffer inputBuffer(bitBuffer, bitCount); + const unsigned char* nibbleBufStart = nibbleBuf; + long outputBufSize = *pNibbleLen; + bool result = false; + unsigned char val; + bool wrap; - /* - * Start 3/4 of the way through the buffer. That should give us a - * couple of self-sync zones before we hit the end of the buffer. - */ - inputBuffer.SetStartPosition(3 * (bitCount / 4)); + /* + * Start 3/4 of the way through the buffer. That should give us a + * couple of self-sync zones before we hit the end of the buffer. + */ + inputBuffer.SetStartPosition(3 * (bitCount / 4)); - /* - * Run until we wrap. We should be in sync by that point. - */ - wrap = false; - while (!wrap) { - val = inputBuffer.GetByte(&wrap); - if ((val & 0x80) == 0) - val = (val << 1) | inputBuffer.GetBit(&wrap); - if ((val & 0x80) == 0) - val = (val << 1) | inputBuffer.GetBit(&wrap); - if ((val & 0x80) == 0) { - // not allowed by GCR encoding, probably garbage between sectors - WMSG0(" FDI: WARNING: more than 2 consecutive zeroes (sync)\n"); - } - } + /* + * Run until we wrap. We should be in sync by that point. + */ + wrap = false; + while (!wrap) { + val = inputBuffer.GetByte(&wrap); + if ((val & 0x80) == 0) + val = (val << 1) | inputBuffer.GetBit(&wrap); + if ((val & 0x80) == 0) + val = (val << 1) | inputBuffer.GetBit(&wrap); + if ((val & 0x80) == 0) { + // not allowed by GCR encoding, probably garbage between sectors + WMSG0(" FDI: WARNING: more than 2 consecutive zeroes (sync)\n"); + } + } - /* - * Extract the nibbles. - */ - inputBuffer.ResetBitsConsumed(); - wrap = false; - while (true) { - val = inputBuffer.GetByte(&wrap); - if ((val & 0x80) == 0) - val = (val << 1) | inputBuffer.GetBit(&wrap); - if ((val & 0x80) == 0) - val = (val << 1) | inputBuffer.GetBit(&wrap); - if ((val & 0x80) == 0) { - WMSG0(" FDI: WARNING: more than 2 consecutive zeroes (read)\n"); - } + /* + * Extract the nibbles. + */ + inputBuffer.ResetBitsConsumed(); + wrap = false; + while (true) { + val = inputBuffer.GetByte(&wrap); + if ((val & 0x80) == 0) + val = (val << 1) | inputBuffer.GetBit(&wrap); + if ((val & 0x80) == 0) + val = (val << 1) | inputBuffer.GetBit(&wrap); + if ((val & 0x80) == 0) { + WMSG0(" FDI: WARNING: more than 2 consecutive zeroes (read)\n"); + } - if (nibbleBuf - nibbleBufStart >= outputBufSize) { - WMSG0(" FDI: bits overflowed nibble buffer\n"); - goto bail; - } - *nibbleBuf++ = val; + if (nibbleBuf - nibbleBufStart >= outputBufSize) { + WMSG0(" FDI: bits overflowed nibble buffer\n"); + goto bail; + } + *nibbleBuf++ = val; - /* if we wrapped around on this one, we've reached the start point */ - if (wrap) - break; - } + /* if we wrapped around on this one, we've reached the start point */ + if (wrap) + break; + } - if (inputBuffer.GetBitsConsumed() != bitCount) { - /* we dropped some or double-counted some */ - WMSG2(" FDI: WARNING: consumed %d of %d bits\n", - inputBuffer.GetBitsConsumed(), bitCount); - } + if (inputBuffer.GetBitsConsumed() != bitCount) { + /* we dropped some or double-counted some */ + WMSG2(" FDI: WARNING: consumed %d of %d bits\n", + inputBuffer.GetBitsConsumed(), bitCount); + } - WMSG4(" FDI: consumed %d of %d (first=0x%02x last=0x%02x)\n", - inputBuffer.GetBitsConsumed(), bitCount, - *nibbleBufStart, *(nibbleBuf-1)); + WMSG4(" FDI: consumed %d of %d (first=0x%02x last=0x%02x)\n", + inputBuffer.GetBitsConsumed(), bitCount, + *nibbleBufStart, *(nibbleBuf-1)); - *pNibbleLen = nibbleBuf - nibbleBufStart; - result = true; + *pNibbleLen = nibbleBuf - nibbleBufStart; + result = true; bail: - return result; + return result; } diff --git a/diskimg/FocusDrive.cpp b/diskimg/FocusDrive.cpp index abcb262..3737a14 100644 --- a/diskimg/FocusDrive.cpp +++ b/diskimg/FocusDrive.cpp @@ -13,10 +13,10 @@ const int kBlkSize = 512; -const int kPartMapBlock = 0; // partition map lives here -const int kMaxPartitions = 30; // max allowed partitions on a drive -const int kPartNameStart = 1; // partition names start here (2 blocks) -const int kPartNameLen = 32; // max length of partition name +const int kPartMapBlock = 0; // partition map lives here +const int kMaxPartitions = 30; // max allowed partitions on a drive +const int kPartNameStart = 1; // partition names start here (2 blocks) +const int kPartNameLen = 32; // max length of partition name static const char* kSignature = "Parsons Engin."; const int kSignatureLen = 14; @@ -28,17 +28,17 @@ const int kSignatureLen = 14; * We also make space here for the partition names, which live on blocks 1+2. */ typedef struct DiskFSFocusDrive::PartitionMap { - unsigned char signature[kSignatureLen]; - unsigned char unknown1; - unsigned char partCount; // could be ushort, combined w/unknown1 - unsigned char unknown2[16]; - struct Entry { - unsigned long startBlock; - unsigned long blockCount; - unsigned long unknown1; - unsigned long unknown2; - unsigned char name[kPartNameLen+1]; - } entry[kMaxPartitions]; + unsigned char signature[kSignatureLen]; + unsigned char unknown1; + unsigned char partCount; // could be ushort, combined w/unknown1 + unsigned char unknown2[16]; + struct Entry { + unsigned long startBlock; + unsigned long blockCount; + unsigned long unknown1; + unsigned long unknown2; + unsigned char name[kPartNameLen+1]; + } entry[kMaxPartitions]; } PartitionMap; @@ -51,36 +51,36 @@ typedef struct DiskFSFocusDrive::PartitionMap { /*static*/ DIError DiskFSFocusDrive::TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder) { - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; - int partCount; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; + int partCount; - /* - * See if block 0 is a FocusDrive partition map. - */ - dierr = pImg->ReadBlockSwapped(kPartMapBlock, blkBuf, imageOrder, - DiskImg::kSectorOrderProDOS); - if (dierr != kDIErrNone) - goto bail; + /* + * See if block 0 is a FocusDrive partition map. + */ + dierr = pImg->ReadBlockSwapped(kPartMapBlock, blkBuf, imageOrder, + DiskImg::kSectorOrderProDOS); + if (dierr != kDIErrNone) + goto bail; - if (memcmp(blkBuf, kSignature, kSignatureLen) != 0) { - WMSG0(" FocusDrive partition signature not found in first part block\n"); - dierr = kDIErrFilesystemNotFound; - goto bail; - } + if (memcmp(blkBuf, kSignature, kSignatureLen) != 0) { + WMSG0(" FocusDrive partition signature not found in first part block\n"); + dierr = kDIErrFilesystemNotFound; + goto bail; + } - partCount = blkBuf[0x0f]; - if (partCount == 0 || partCount > kMaxPartitions) { - WMSG1(" FocusDrive partition count looks bad (%d)\n", partCount); - dierr = kDIErrFilesystemNotFound; - goto bail; - } + partCount = blkBuf[0x0f]; + if (partCount == 0 || partCount > kMaxPartitions) { + WMSG1(" FocusDrive partition count looks bad (%d)\n", partCount); + dierr = kDIErrFilesystemNotFound; + goto bail; + } - // success! - WMSG1(" Looks like FocusDrive with %d partitions\n", partCount); + // success! + WMSG1(" Looks like FocusDrive with %d partitions\n", partCount); bail: - return dierr; + return dierr; } @@ -89,33 +89,33 @@ bail: */ /*static*/ void DiskFSFocusDrive::UnpackPartitionMap(const unsigned char* buf, - const unsigned char* nameBuf, PartitionMap* pMap) + const unsigned char* nameBuf, PartitionMap* pMap) { - const unsigned char* ptr; - const unsigned char* namePtr; - int i; + const unsigned char* ptr; + const unsigned char* namePtr; + int i; - memcpy(pMap->signature, &buf[0x00], kSignatureLen); - pMap->unknown1 = buf[0x0e]; - pMap->partCount = buf[0x0f]; - memcpy(pMap->unknown2, &buf[0x10], 16); + memcpy(pMap->signature, &buf[0x00], kSignatureLen); + pMap->unknown1 = buf[0x0e]; + pMap->partCount = buf[0x0f]; + memcpy(pMap->unknown2, &buf[0x10], 16); - ptr = &buf[0x20]; - namePtr = &nameBuf[kPartNameLen]; // not sure what first 32 bytes are - for (i = 0; i < kMaxPartitions; i++) { - pMap->entry[i].startBlock = GetLongLE(ptr); - pMap->entry[i].blockCount = GetLongLE(ptr+4); - pMap->entry[i].unknown1 = GetLongLE(ptr+8); - pMap->entry[i].unknown2 = GetLongLE(ptr+12); + ptr = &buf[0x20]; + namePtr = &nameBuf[kPartNameLen]; // not sure what first 32 bytes are + for (i = 0; i < kMaxPartitions; i++) { + pMap->entry[i].startBlock = GetLongLE(ptr); + pMap->entry[i].blockCount = GetLongLE(ptr+4); + pMap->entry[i].unknown1 = GetLongLE(ptr+8); + pMap->entry[i].unknown2 = GetLongLE(ptr+12); - memcpy(pMap->entry[i].name, namePtr, kPartNameLen); - pMap->entry[i].name[kPartNameLen] = '\0'; + memcpy(pMap->entry[i].name, namePtr, kPartNameLen); + pMap->entry[i].name[kPartNameLen] = '\0'; - ptr += 0x10; - namePtr += kPartNameLen; - } + ptr += 0x10; + namePtr += kPartNameLen; + } - assert(ptr == buf + kBlkSize); + assert(ptr == buf + kBlkSize); } /* @@ -124,13 +124,13 @@ DiskFSFocusDrive::UnpackPartitionMap(const unsigned char* buf, /*static*/ void DiskFSFocusDrive::DumpPartitionMap(const PartitionMap* pMap) { - int i; + int i; - WMSG1(" FocusDrive partition map (%d partitions):\n", pMap->partCount); - for (i = 0; i < pMap->partCount; i++) { - WMSG4(" %2d: %8ld %8ld '%s'\n", i, pMap->entry[i].startBlock, - pMap->entry[i].blockCount, pMap->entry[i].name); - } + WMSG1(" FocusDrive partition map (%d partitions):\n", pMap->partCount); + for (i = 0; i < pMap->partCount; i++) { + WMSG4(" %2d: %8ld %8ld '%s'\n", i, pMap->entry[i].startBlock, + pMap->entry[i].blockCount, pMap->entry[i].name); + } } @@ -139,110 +139,110 @@ DiskFSFocusDrive::DumpPartitionMap(const PartitionMap* pMap) */ DIError DiskFSFocusDrive::OpenSubVolume(long startBlock, long numBlocks, - const char* name) + const char* name) { - DIError dierr = kDIErrNone; - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; - //bool tweaked = false; + DIError dierr = kDIErrNone; + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; + //bool tweaked = false; - WMSG2("Adding %ld +%ld\n", startBlock, numBlocks); + WMSG2("Adding %ld +%ld\n", startBlock, numBlocks); - if (startBlock > fpImg->GetNumBlocks()) { - WMSG2("FocusDrive start block out of range (%ld vs %ld)\n", - startBlock, fpImg->GetNumBlocks()); - return kDIErrBadPartition; - } - if (startBlock + numBlocks > fpImg->GetNumBlocks()) { - WMSG2("FocusDrive partition too large (%ld vs %ld avail)\n", - numBlocks, fpImg->GetNumBlocks() - startBlock); - fpImg->AddNote(DiskImg::kNoteInfo, - "Reduced partition from %ld blocks to %ld.\n", - numBlocks, fpImg->GetNumBlocks() - startBlock); - numBlocks = fpImg->GetNumBlocks() - startBlock; - //tweaked = true; - } + if (startBlock > fpImg->GetNumBlocks()) { + WMSG2("FocusDrive start block out of range (%ld vs %ld)\n", + startBlock, fpImg->GetNumBlocks()); + return kDIErrBadPartition; + } + if (startBlock + numBlocks > fpImg->GetNumBlocks()) { + WMSG2("FocusDrive partition too large (%ld vs %ld avail)\n", + numBlocks, fpImg->GetNumBlocks() - startBlock); + fpImg->AddNote(DiskImg::kNoteInfo, + "Reduced partition from %ld blocks to %ld.\n", + numBlocks, fpImg->GetNumBlocks() - startBlock); + numBlocks = fpImg->GetNumBlocks() - startBlock; + //tweaked = true; + } - pNewImg = new DiskImg; - if (pNewImg == nil) { - dierr = kDIErrMalloc; - goto bail; - } + pNewImg = new DiskImg; + if (pNewImg == nil) { + dierr = kDIErrMalloc; + goto bail; + } - dierr = pNewImg->OpenImage(fpImg, startBlock, numBlocks); - if (dierr != kDIErrNone) { - WMSG3(" FocusDriveSub: OpenImage(%ld,%ld) failed (err=%d)\n", - startBlock, numBlocks, dierr); - goto bail; - } + dierr = pNewImg->OpenImage(fpImg, startBlock, numBlocks); + if (dierr != kDIErrNone) { + WMSG3(" FocusDriveSub: OpenImage(%ld,%ld) failed (err=%d)\n", + startBlock, numBlocks, dierr); + goto bail; + } - //WMSG2(" +++ CFFASub: new image has ro=%d (parent=%d)\n", - // pNewImg->GetReadOnly(), pImg->GetReadOnly()); + //WMSG2(" +++ CFFASub: new image has ro=%d (parent=%d)\n", + // pNewImg->GetReadOnly(), pImg->GetReadOnly()); - /* figure out what the format is */ - dierr = pNewImg->AnalyzeImage(); - if (dierr != kDIErrNone) { - WMSG1(" FocusDriveSub: analysis failed (err=%d)\n", dierr); - goto bail; - } + /* figure out what the format is */ + dierr = pNewImg->AnalyzeImage(); + if (dierr != kDIErrNone) { + WMSG1(" FocusDriveSub: analysis failed (err=%d)\n", dierr); + goto bail; + } - /* we allow unrecognized partitions */ - if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || - pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) - { - WMSG2(" FocusDriveSub (%ld,%ld): unable to identify filesystem\n", - startBlock, numBlocks); - DiskFSUnknown* pUnknownFS = new DiskFSUnknown; - if (pUnknownFS == nil) { - dierr = kDIErrInternal; - goto bail; - } - //pUnknownFS->SetVolumeInfo((const char*)pMap->pmParType); - pNewFS = pUnknownFS; - } else { - /* open a DiskFS for the sub-image */ - WMSG2(" FocusDriveSub (%ld,%ld) analyze succeeded!\n", startBlock, numBlocks); - pNewFS = pNewImg->OpenAppropriateDiskFS(true); - if (pNewFS == nil) { - WMSG0(" FocusDriveSub: OpenAppropriateDiskFS failed\n"); - dierr = kDIErrUnsupportedFSFmt; - goto bail; - } - } - pNewImg->AddNote(DiskImg::kNoteInfo, "Partition name='%s'.", name); + /* we allow unrecognized partitions */ + if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || + pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) + { + WMSG2(" FocusDriveSub (%ld,%ld): unable to identify filesystem\n", + startBlock, numBlocks); + DiskFSUnknown* pUnknownFS = new DiskFSUnknown; + if (pUnknownFS == nil) { + dierr = kDIErrInternal; + goto bail; + } + //pUnknownFS->SetVolumeInfo((const char*)pMap->pmParType); + pNewFS = pUnknownFS; + } else { + /* open a DiskFS for the sub-image */ + WMSG2(" FocusDriveSub (%ld,%ld) analyze succeeded!\n", startBlock, numBlocks); + pNewFS = pNewImg->OpenAppropriateDiskFS(true); + if (pNewFS == nil) { + WMSG0(" FocusDriveSub: OpenAppropriateDiskFS failed\n"); + dierr = kDIErrUnsupportedFSFmt; + goto bail; + } + } + pNewImg->AddNote(DiskImg::kNoteInfo, "Partition name='%s'.", name); - /* we encapsulate arbitrary stuff, so encourage child to scan */ - pNewFS->SetScanForSubVolumes(kScanSubEnabled); + /* we encapsulate arbitrary stuff, so encourage child to scan */ + pNewFS->SetScanForSubVolumes(kScanSubEnabled); - /* - * Load the files from the sub-image. When doing our initial tests, - * or when loading data for the volume copier, we don't want to dig - * into our sub-volumes, just figure out what they are and where. - * - * If "initialize" fails, the sub-volume won't get added to the list. - * It's important that a failure at this stage doesn't cause the whole - * thing to fall over. - */ - InitMode initMode; - if (GetScanForSubVolumes() == kScanSubContainerOnly) - initMode = kInitHeaderOnly; - else - initMode = kInitFull; - dierr = pNewFS->Initialize(pNewImg, initMode); - if (dierr != kDIErrNone) { - WMSG1(" FocusDriveSub: error %d reading list of files from disk", dierr); - goto bail; - } + /* + * Load the files from the sub-image. When doing our initial tests, + * or when loading data for the volume copier, we don't want to dig + * into our sub-volumes, just figure out what they are and where. + * + * If "initialize" fails, the sub-volume won't get added to the list. + * It's important that a failure at this stage doesn't cause the whole + * thing to fall over. + */ + InitMode initMode; + if (GetScanForSubVolumes() == kScanSubContainerOnly) + initMode = kInitHeaderOnly; + else + initMode = kInitFull; + dierr = pNewFS->Initialize(pNewImg, initMode); + if (dierr != kDIErrNone) { + WMSG1(" FocusDriveSub: error %d reading list of files from disk", dierr); + goto bail; + } - /* add it to the list */ - AddSubVolumeToList(pNewImg, pNewFS); - pNewImg = nil; - pNewFS = nil; + /* add it to the list */ + AddSubVolumeToList(pNewImg, pNewFS); + pNewImg = nil; + pNewFS = nil; bail: - delete pNewFS; - delete pNewImg; - return dierr; + delete pNewFS; + delete pNewImg; + return dierr; } /* @@ -250,22 +250,22 @@ bail: */ /*static*/ DIError DiskFSFocusDrive::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency) + DiskImg::FSFormat* pFormat, FSLeniency leniency) { - if (pImg->GetNumBlocks() < kMinInterestingBlocks) - return kDIErrFilesystemNotFound; - if (pImg->GetIsEmbedded()) // don't look for partitions inside - return kDIErrFilesystemNotFound; + if (pImg->GetNumBlocks() < kMinInterestingBlocks) + return kDIErrFilesystemNotFound; + if (pImg->GetIsEmbedded()) // don't look for partitions inside + return kDIErrFilesystemNotFound; - /* assume ProDOS -- shouldn't matter, since it's embedded */ - if (TestImage(pImg, DiskImg::kSectorOrderProDOS) == kDIErrNone) { - *pFormat = DiskImg::kFormatFocusDrive; - *pOrder = DiskImg::kSectorOrderProDOS; - return kDIErrNone; - } + /* assume ProDOS -- shouldn't matter, since it's embedded */ + if (TestImage(pImg, DiskImg::kSectorOrderProDOS) == kDIErrNone) { + *pFormat = DiskImg::kFormatFocusDrive; + *pOrder = DiskImg::kSectorOrderProDOS; + return kDIErrNone; + } - WMSG0(" FS didn't find valid FocusDrive\n"); - return kDIErrFilesystemNotFound; + WMSG0(" FS didn't find valid FocusDrive\n"); + return kDIErrFilesystemNotFound; } @@ -275,21 +275,21 @@ DiskFSFocusDrive::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DIError DiskFSFocusDrive::Initialize(void) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - WMSG1("FocusDrive initializing (scanForSub=%d)\n", fScanForSubVolumes); + WMSG1("FocusDrive initializing (scanForSub=%d)\n", fScanForSubVolumes); - /* seems pointless *not* to, but we just do what we're told */ - if (fScanForSubVolumes != kScanSubDisabled) { - dierr = FindSubVolumes(); - if (dierr != kDIErrNone) - return dierr; - } + /* seems pointless *not* to, but we just do what we're told */ + if (fScanForSubVolumes != kScanSubDisabled) { + dierr = FindSubVolumes(); + if (dierr != kDIErrNone) + return dierr; + } - /* blank out the volume usage map */ - SetVolumeUsageMap(); + /* blank out the volume usage map */ + SetVolumeUsageMap(); - return dierr; + return dierr; } @@ -299,33 +299,33 @@ DiskFSFocusDrive::Initialize(void) DIError DiskFSFocusDrive::FindSubVolumes(void) { - DIError dierr = kDIErrNone; - unsigned char buf[kBlkSize]; - unsigned char nameBuf[kBlkSize*2]; - PartitionMap map; - int i; + DIError dierr = kDIErrNone; + unsigned char buf[kBlkSize]; + unsigned char nameBuf[kBlkSize*2]; + PartitionMap map; + int i; - dierr = fpImg->ReadBlock(kPartMapBlock, buf); - if (dierr != kDIErrNone) - goto bail; - dierr = fpImg->ReadBlock(kPartNameStart, nameBuf); - if (dierr != kDIErrNone) - goto bail; - dierr = fpImg->ReadBlock(kPartNameStart+1, nameBuf+kBlkSize); - if (dierr != kDIErrNone) - goto bail; - UnpackPartitionMap(buf, nameBuf, &map); - DumpPartitionMap(&map); + dierr = fpImg->ReadBlock(kPartMapBlock, buf); + if (dierr != kDIErrNone) + goto bail; + dierr = fpImg->ReadBlock(kPartNameStart, nameBuf); + if (dierr != kDIErrNone) + goto bail; + dierr = fpImg->ReadBlock(kPartNameStart+1, nameBuf+kBlkSize); + if (dierr != kDIErrNone) + goto bail; + UnpackPartitionMap(buf, nameBuf, &map); + DumpPartitionMap(&map); - for (i = 0; i < map.partCount; i++) { - dierr = OpenVol(i, map.entry[i].startBlock, map.entry[i].blockCount, - (const char*)map.entry[i].name); - if (dierr != kDIErrNone) - goto bail; - } + for (i = 0; i < map.partCount; i++) { + dierr = OpenVol(i, map.entry[i].startBlock, map.entry[i].blockCount, + (const char*)map.entry[i].name); + if (dierr != kDIErrNone) + goto bail; + } bail: - return dierr; + return dierr; } /* @@ -334,29 +334,29 @@ bail: */ DIError DiskFSFocusDrive::OpenVol(int idx, long startBlock, long numBlocks, - const char* name) + const char* name) { - DIError dierr; + DIError dierr; - dierr = OpenSubVolume(startBlock, numBlocks, name); - if (dierr != kDIErrNone) { - if (dierr == kDIErrCancelled) - goto bail; - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; + dierr = OpenSubVolume(startBlock, numBlocks, name); + if (dierr != kDIErrNone) { + if (dierr == kDIErrCancelled) + goto bail; + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; - WMSG1(" FocusDrive failed opening sub-volume %d\n", idx); - dierr = CreatePlaceholder(startBlock, numBlocks, name, NULL, - &pNewImg, &pNewFS); - if (dierr == kDIErrNone) { - AddSubVolumeToList(pNewImg, pNewFS); - } else { - WMSG1(" FocusDrive unable to create placeholder (err=%d)\n", - dierr); - // fall out with error - } - } + WMSG1(" FocusDrive failed opening sub-volume %d\n", idx); + dierr = CreatePlaceholder(startBlock, numBlocks, name, NULL, + &pNewImg, &pNewFS); + if (dierr == kDIErrNone) { + AddSubVolumeToList(pNewImg, pNewFS); + } else { + WMSG1(" FocusDrive unable to create placeholder (err=%d)\n", + dierr); + // fall out with error + } + } bail: - return dierr; + return dierr; } diff --git a/diskimg/GenericFD.cpp b/diskimg/GenericFD.cpp index 3b63c16..2ba4982 100644 --- a/diskimg/GenericFD.cpp +++ b/diskimg/GenericFD.cpp @@ -11,7 +11,7 @@ /* * =========================================================================== - * GenericFD utility functions + * GenericFD utility functions * =========================================================================== */ @@ -24,55 +24,55 @@ */ /*static*/ DIError GenericFD::CopyFile(GenericFD* pDst, GenericFD* pSrc, di_off_t length, - unsigned long* pCRC) + unsigned long* pCRC) { - DIError dierr = kDIErrNone; - const int kCopyBufSize = 32768; - unsigned char* copyBuf = nil; - int copySize; + DIError dierr = kDIErrNone; + const int kCopyBufSize = 32768; + unsigned char* copyBuf = nil; + int copySize; - WMSG1("+++ CopyFile: %ld bytes\n", (long) length); + WMSG1("+++ CopyFile: %ld bytes\n", (long) length); - if (pDst == nil || pSrc == nil || length < 0) - return kDIErrInvalidArg; - if (length == 0) - return kDIErrNone; + if (pDst == nil || pSrc == nil || length < 0) + return kDIErrInvalidArg; + if (length == 0) + return kDIErrNone; - copyBuf = new unsigned char[kCopyBufSize]; - if (copyBuf == nil) - return kDIErrMalloc; + copyBuf = new unsigned char[kCopyBufSize]; + if (copyBuf == nil) + return kDIErrMalloc; - if (pCRC != nil) - *pCRC = crc32(0L, Z_NULL, 0); + if (pCRC != nil) + *pCRC = crc32(0L, Z_NULL, 0); - while (length != 0) { - copySize = kCopyBufSize; - if (copySize > length) - copySize = (int) length; + while (length != 0) { + copySize = kCopyBufSize; + if (copySize > length) + copySize = (int) length; - dierr = pSrc->Read(copyBuf, copySize); - if (dierr != kDIErrNone) - goto bail; + dierr = pSrc->Read(copyBuf, copySize); + if (dierr != kDIErrNone) + goto bail; - if (pCRC != nil) - *pCRC = crc32(*pCRC, copyBuf, copySize); + if (pCRC != nil) + *pCRC = crc32(*pCRC, copyBuf, copySize); - dierr = pDst->Write(copyBuf, copySize); - if (dierr != kDIErrNone) - goto bail; + dierr = pDst->Write(copyBuf, copySize); + if (dierr != kDIErrNone) + goto bail; - length -= copySize; - } + length -= copySize; + } bail: - delete[] copyBuf; - return dierr; + delete[] copyBuf; + return dierr; } /* * =========================================================================== - * GFDFile + * GFDFile * =========================================================================== */ @@ -92,42 +92,42 @@ bail: DIError GFDFile::Open(const char* filename, bool readOnly) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - if (fFp != nil) - return kDIErrAlreadyOpen; - if (filename == nil) - return kDIErrInvalidArg; + if (fFp != nil) + return kDIErrAlreadyOpen; + if (filename == nil) + return kDIErrInvalidArg; if (filename[0] == '\0') return kDIErrInvalidArg; - delete[] fPathName; - fPathName = new char[strlen(filename) +1]; - strcpy(fPathName, filename); + delete[] fPathName; + fPathName = new char[strlen(filename) +1]; + strcpy(fPathName, filename); - fFp = fopen(filename, readOnly ? "rb" : "r+b"); - if (fFp == nil) { - if (errno == EACCES) - dierr = kDIErrAccessDenied; - else - dierr = ErrnoOrGeneric(); - WMSG3(" GDFile Open failed opening '%s', ro=%d (err=%d)\n", - filename, readOnly, dierr); - return dierr; - } + fFp = fopen(filename, readOnly ? "rb" : "r+b"); + if (fFp == nil) { + if (errno == EACCES) + dierr = kDIErrAccessDenied; + else + dierr = ErrnoOrGeneric(); + WMSG3(" GDFile Open failed opening '%s', ro=%d (err=%d)\n", + filename, readOnly, dierr); + return dierr; + } fReadOnly = readOnly; - return dierr; + return dierr; } DIError GFDFile::Read(void* buf, size_t length, size_t* pActual) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; size_t actual; - if (fFp == nil) - return kDIErrNotReady; - actual = ::fread(buf, 1, length, fFp); + if (fFp == nil) + return kDIErrNotReady; + actual = ::fread(buf, 1, length, fFp); if (actual == 0) { if (feof(fFp)) return kDIErrEOF; @@ -146,97 +146,97 @@ GFDFile::Read(void* buf, size_t length, size_t* pActual) length, actual, dierr); return dierr; } - } else { + } else { *pActual = actual; } - return dierr; + return dierr; } DIError GFDFile::Write(const void* buf, size_t length, size_t* pActual) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - if (fFp == nil) - return kDIErrNotReady; - if (fReadOnly) - return kDIErrAccessDenied; - assert(pActual == nil); // not handling this yet - if (::fwrite(buf, length, 1, fFp) != 1) { - dierr = ErrnoOrGeneric(); - WMSG2(" GDFile Write failed on %d bytes (err=%d)\n", length, dierr); - return dierr; - } - return dierr; + if (fFp == nil) + return kDIErrNotReady; + if (fReadOnly) + return kDIErrAccessDenied; + assert(pActual == nil); // not handling this yet + if (::fwrite(buf, length, 1, fFp) != 1) { + dierr = ErrnoOrGeneric(); + WMSG2(" GDFile Write failed on %d bytes (err=%d)\n", length, dierr); + return dierr; + } + return dierr; } DIError GFDFile::Seek(di_off_t offset, DIWhence whence) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; //static const long kOneGB = 1024*1024*1024; //static const long kAlmostTwoGB = kOneGB + (kOneGB -1); - if (fFp == nil) - return kDIErrNotReady; - //assert(offset <= kAlmostTwoGB); - //if (::fseek(fFp, (long) offset, whence) != 0) { - if (::fseeko(fFp, offset, whence) != 0) { - dierr = ErrnoOrGeneric(); - WMSG1(" GDFile Seek failed (err=%d)\n", dierr); - return dierr; - } - return dierr; + if (fFp == nil) + return kDIErrNotReady; + //assert(offset <= kAlmostTwoGB); + //if (::fseek(fFp, (long) offset, whence) != 0) { + if (::fseeko(fFp, offset, whence) != 0) { + dierr = ErrnoOrGeneric(); + WMSG1(" GDFile Seek failed (err=%d)\n", dierr); + return dierr; + } + return dierr; } di_off_t GFDFile::Tell(void) { - DIError dierr = kDIErrNone; - di_off_t result; + DIError dierr = kDIErrNone; + di_off_t result; - if (fFp == nil) - return kDIErrNotReady; - //result = ::ftell(fFp); - result = ::ftello(fFp); - if (result == -1) { - dierr = ErrnoOrGeneric(); - WMSG1(" GDFile Tell failed (err=%d)\n", dierr); - return result; - } - return result; + if (fFp == nil) + return kDIErrNotReady; + //result = ::ftell(fFp); + result = ::ftello(fFp); + if (result == -1) { + dierr = ErrnoOrGeneric(); + WMSG1(" GDFile Tell failed (err=%d)\n", dierr); + return result; + } + return result; } DIError GFDFile::Truncate(void) { #if defined(HAVE_FTRUNCATE) - int cc; - cc = ::ftruncate(fileno(fFp), (long) Tell()); - if (cc != 0) - return kDIErrWriteFailed; + int cc; + cc = ::ftruncate(fileno(fFp), (long) Tell()); + if (cc != 0) + return kDIErrWriteFailed; #elif defined(HAVE_CHSIZE) - assert(false); // not tested - int cc; - cc = ::chsize(fFd, (long) Tell()); - if (cc != 0) - return kDIErrWriteFailed; + assert(false); // not tested + int cc; + cc = ::chsize(fFd, (long) Tell()); + if (cc != 0) + return kDIErrWriteFailed; #else # error "missing truncate" #endif - return kDIErrNone; + return kDIErrNone; } DIError GFDFile::Close(void) { - if (fFp == nil) - return kDIErrNotReady; + if (fFp == nil) + return kDIErrNotReady; - WMSG1(" GFDFile closing '%s'\n", fPathName); - fclose(fFp); - fFp = nil; - return kDIErrNone; + WMSG1(" GFDFile closing '%s'\n", fPathName); + fclose(fFp); + fFp = nil; + return kDIErrNone; } #else /*HAVE_FSEEKO*/ @@ -244,50 +244,50 @@ GFDFile::Close(void) DIError GFDFile::Open(const char* filename, bool readOnly) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - if (fFd >= 0) - return kDIErrAlreadyOpen; - if (filename == nil) - return kDIErrInvalidArg; + if (fFd >= 0) + return kDIErrAlreadyOpen; + if (filename == nil) + return kDIErrInvalidArg; if (filename[0] == '\0') return kDIErrInvalidArg; - delete[] fPathName; - fPathName = new char[strlen(filename) +1]; - strcpy(fPathName, filename); + delete[] fPathName; + fPathName = new char[strlen(filename) +1]; + strcpy(fPathName, filename); - fFd = open(filename, readOnly ? O_RDONLY|O_BINARY : O_RDWR|O_BINARY, 0); - if (fFd < 0) { - if (errno == EACCES) - dierr = kDIErrAccessDenied; - else - dierr = ErrnoOrGeneric(); - WMSG3(" GDFile Open failed opening '%s', ro=%d (err=%d)\n", - filename, readOnly, dierr); - return dierr; - } + fFd = open(filename, readOnly ? O_RDONLY|O_BINARY : O_RDWR|O_BINARY, 0); + if (fFd < 0) { + if (errno == EACCES) + dierr = kDIErrAccessDenied; + else + dierr = ErrnoOrGeneric(); + WMSG3(" GDFile Open failed opening '%s', ro=%d (err=%d)\n", + filename, readOnly, dierr); + return dierr; + } fReadOnly = readOnly; - return dierr; + return dierr; } DIError GFDFile::Read(void* buf, size_t length, size_t* pActual) { - DIError dierr; + DIError dierr; ssize_t actual; - if (fFd < 0) - return kDIErrNotReady; - actual = ::read(fFd, buf, length); + if (fFd < 0) + return kDIErrNotReady; + actual = ::read(fFd, buf, length); if (actual == 0) return kDIErrEOF; - if (actual < 0) { + if (actual < 0) { dierr = ErrnoOrGeneric(); WMSG3(" GDFile Read failed on %d bytes (actual=%d, err=%d)\n", length, actual, dierr); return dierr; - } + } if (pActual == nil) { if (actual != (ssize_t) length) { @@ -295,118 +295,118 @@ GFDFile::Read(void* buf, size_t length, size_t* pActual) length, actual); return kDIErrReadFailed; } - } else { + } else { *pActual = actual; } - return kDIErrNone; + return kDIErrNone; } DIError GFDFile::Write(const void* buf, size_t length, size_t* pActual) { - DIError dierr; - ssize_t actual; + DIError dierr; + ssize_t actual; - if (fFd < 0) - return kDIErrNotReady; - if (fReadOnly) - return kDIErrAccessDenied; - assert(pActual == nil); // not handling partial writes yet - actual = ::write(fFd, buf, length); - if (actual != (ssize_t) length) { - dierr = ErrnoOrGeneric(); - WMSG3(" GDFile Write failed on %d bytes (actual=%d err=%d)\n", - length, actual, dierr); - return dierr; - } - return kDIErrNone; + if (fFd < 0) + return kDIErrNotReady; + if (fReadOnly) + return kDIErrAccessDenied; + assert(pActual == nil); // not handling partial writes yet + actual = ::write(fFd, buf, length); + if (actual != (ssize_t) length) { + dierr = ErrnoOrGeneric(); + WMSG3(" GDFile Write failed on %d bytes (actual=%d err=%d)\n", + length, actual, dierr); + return dierr; + } + return kDIErrNone; } DIError GFDFile::Seek(di_off_t offset, DIWhence whence) { - DIError dierr = kDIErrNone; - if (fFd < 0) - return kDIErrNotReady; + DIError dierr = kDIErrNone; + if (fFd < 0) + return kDIErrNotReady; #ifdef WIN32 - __int64 newPosn; - const __int64 kFailure = (__int64) -1; - newPosn = ::_lseeki64(fFd, (__int64) offset, whence); + __int64 newPosn; + const __int64 kFailure = (__int64) -1; + newPosn = ::_lseeki64(fFd, (__int64) offset, whence); #else - di_off_t newPosn; - const di_off_t kFailure = (di_off_t) -1; - newPosn = lseek(fFd, offset, whence); + di_off_t newPosn; + const di_off_t kFailure = (di_off_t) -1; + newPosn = lseek(fFd, offset, whence); #endif - if (newPosn == kFailure) { - assert((unsigned long) offset != 0xccccccccUL); // uninitialized data! - dierr = ErrnoOrGeneric(); - WMSG3(" GDFile Seek %ld-%lu failed (err=%d)\n", - (long) (offset >> 32), (unsigned long) offset, dierr); - } - return dierr; + if (newPosn == kFailure) { + assert((unsigned long) offset != 0xccccccccUL); // uninitialized data! + dierr = ErrnoOrGeneric(); + WMSG3(" GDFile Seek %ld-%lu failed (err=%d)\n", + (long) (offset >> 32), (unsigned long) offset, dierr); + } + return dierr; } di_off_t GFDFile::Tell(void) { - DIError dierr = kDIErrNone; - di_off_t result; + DIError dierr = kDIErrNone; + di_off_t result; - if (fFd < 0) - return kDIErrNotReady; + if (fFd < 0) + return kDIErrNotReady; #ifdef WIN32 - result = ::_lseeki64(fFd, 0, SEEK_CUR); + result = ::_lseeki64(fFd, 0, SEEK_CUR); #else - result = lseek(fFd, 0, SEEK_CUR); + result = lseek(fFd, 0, SEEK_CUR); #endif - if (result == -1) { - dierr = ErrnoOrGeneric(); - WMSG1(" GDFile Tell failed (err=%d)\n", dierr); - return result; - } - return result; + if (result == -1) { + dierr = ErrnoOrGeneric(); + WMSG1(" GDFile Tell failed (err=%d)\n", dierr); + return result; + } + return result; } DIError GFDFile::Truncate(void) { #if defined(HAVE_FTRUNCATE) - int cc; - cc = ::ftruncate(fFd, (long) Tell()); - if (cc != 0) - return kDIErrWriteFailed; + int cc; + cc = ::ftruncate(fFd, (long) Tell()); + if (cc != 0) + return kDIErrWriteFailed; #elif defined(HAVE_CHSIZE) - int cc; - cc = ::chsize(fFd, (long) Tell()); - if (cc != 0) - return kDIErrWriteFailed; + int cc; + cc = ::chsize(fFd, (long) Tell()); + if (cc != 0) + return kDIErrWriteFailed; #else # error "missing truncate" #endif - return kDIErrNone; + return kDIErrNone; } DIError GFDFile::Close(void) { - if (fFd < 0) - return kDIErrNotReady; + if (fFd < 0) + return kDIErrNotReady; - WMSG1(" GFDFile closing '%s'\n", fPathName); - ::close(fFd); - fFd = -1; - return kDIErrNone; + WMSG1(" GFDFile closing '%s'\n", fPathName); + ::close(fFd); + fFd = -1; + return kDIErrNone; } #endif /*HAVE_FSEEKO else*/ /* * =========================================================================== - * GFDBuffer + * GFDBuffer * =========================================================================== */ @@ -414,16 +414,16 @@ DIError GFDBuffer::Open(void* buffer, di_off_t length, bool doDelete, bool doExpand, bool readOnly) { - if (fBuffer != nil) - return kDIErrAlreadyOpen; - if (length <= 0) - return kDIErrInvalidArg; - if (length > kMaxReasonableSize) { - // be reasonable - WMSG1(" GFDBuffer refusing to allocate buffer size(long)=%ld bytes\n", - (long) length); - return kDIErrInvalidArg; - } + if (fBuffer != nil) + return kDIErrAlreadyOpen; + if (length <= 0) + return kDIErrInvalidArg; + if (length > kMaxReasonableSize) { + // be reasonable + WMSG1(" GFDBuffer refusing to allocate buffer size(long)=%ld bytes\n", + (long) length); + return kDIErrInvalidArg; + } /* if buffer is nil, allocate it ourselves */ if (buffer == nil) { @@ -433,26 +433,26 @@ GFDBuffer::Open(void* buffer, di_off_t length, bool doDelete, bool doExpand, } else fBuffer = buffer; - fLength = (long) length; + fLength = (long) length; fAllocLength = (long) length; - fDoDelete = doDelete; + fDoDelete = doDelete; fDoExpand = doExpand; - fReadOnly = readOnly; + fReadOnly = readOnly; - fCurrentOffset = 0; + fCurrentOffset = 0; - return kDIErrNone; + return kDIErrNone; } DIError GFDBuffer::Read(void* buf, size_t length, size_t* pActual) { - if (fBuffer == nil) - return kDIErrNotReady; + if (fBuffer == nil) + return kDIErrNotReady; if (length == 0) return kDIErrInvalidArg; - if (fCurrentOffset + (long)length > fLength) { + if (fCurrentOffset + (long)length > fLength) { if (pActual == nil) { WMSG3(" GFDBuffer underrrun off=%ld len=%d flen=%ld\n", (long) fCurrentOffset, length, (long) fLength); @@ -466,23 +466,23 @@ GFDBuffer::Read(void* buf, size_t length, size_t* pActual) if (length == 0) return kDIErrEOF; } - } + } if (pActual != nil) *pActual = length; - memcpy(buf, (const char*)fBuffer + fCurrentOffset, length); - fCurrentOffset += length; + memcpy(buf, (const char*)fBuffer + fCurrentOffset, length); + fCurrentOffset += length; - return kDIErrNone; + return kDIErrNone; } DIError GFDBuffer::Write(const void* buf, size_t length, size_t* pActual) { - if (fBuffer == nil) - return kDIErrNotReady; - assert(pActual == nil); // not handling this yet - if (fCurrentOffset + (long)length > fLength) { + if (fBuffer == nil) + return kDIErrNotReady; + assert(pActual == nil); // not handling this yet + if (fCurrentOffset + (long)length > fLength) { if (!fDoExpand) { WMSG3(" GFDBuffer overrun off=%ld len=%d flen=%ld\n", (long) fCurrentOffset, length, (long) fLength); @@ -504,7 +504,7 @@ GFDBuffer::Write(const void* buf, size_t length, size_t* pActual) /* does not fit, realloc buffer */ fAllocLength = (long) fCurrentOffset + (long)length + 8*1024; WMSG1("Reallocating buffer (new size = %ld)\n", fAllocLength); - assert(fAllocLength < kMaxReasonableSize); + assert(fAllocLength < kMaxReasonableSize); char* newBuf = new char[(int) fAllocLength]; if (newBuf == nil) return kDIErrMalloc; @@ -519,78 +519,78 @@ GFDBuffer::Write(const void* buf, size_t length, size_t* pActual) fBuffer = newBuf; fLength = (long) fCurrentOffset + (long)length; } - } + } - memcpy((char*)fBuffer + fCurrentOffset, buf, length); - fCurrentOffset += length; + memcpy((char*)fBuffer + fCurrentOffset, buf, length); + fCurrentOffset += length; - return kDIErrNone; + return kDIErrNone; } DIError GFDBuffer::Seek(di_off_t offset, DIWhence whence) { - if (fBuffer == nil) - return kDIErrNotReady; + if (fBuffer == nil) + return kDIErrNotReady; - switch (whence) { - case kSeekSet: - if (offset < 0 || offset >= fLength) - return kDIErrInvalidArg; - fCurrentOffset = offset; - break; - case kSeekEnd: - if (offset > 0 || offset < -fLength) - return kDIErrInvalidArg; - fCurrentOffset = fLength + offset; - break; - case kSeekCur: - if (offset < -fCurrentOffset || - offset >= (fLength - fCurrentOffset)) - { - return kDIErrInvalidArg; - } - fCurrentOffset += offset; - break; - default: - assert(false); - return kDIErrInvalidArg; - } + switch (whence) { + case kSeekSet: + if (offset < 0 || offset >= fLength) + return kDIErrInvalidArg; + fCurrentOffset = offset; + break; + case kSeekEnd: + if (offset > 0 || offset < -fLength) + return kDIErrInvalidArg; + fCurrentOffset = fLength + offset; + break; + case kSeekCur: + if (offset < -fCurrentOffset || + offset >= (fLength - fCurrentOffset)) + { + return kDIErrInvalidArg; + } + fCurrentOffset += offset; + break; + default: + assert(false); + return kDIErrInvalidArg; + } - assert(fCurrentOffset >= 0 && fCurrentOffset <= fLength); - return kDIErrNone; + assert(fCurrentOffset >= 0 && fCurrentOffset <= fLength); + return kDIErrNone; } di_off_t GFDBuffer::Tell(void) { - if (fBuffer == nil) - return (di_off_t) -1; - return fCurrentOffset; + if (fBuffer == nil) + return (di_off_t) -1; + return fCurrentOffset; } DIError GFDBuffer::Close(void) { - if (fBuffer == nil) - return kDIErrNone; + if (fBuffer == nil) + return kDIErrNone; - if (fDoDelete) { - WMSG0(" GFDBuffer closing and deleting\n"); - delete[] (char*) fBuffer; - } else { - WMSG0(" GFDBuffer closing\n"); - } - fBuffer = nil; + if (fDoDelete) { + WMSG0(" GFDBuffer closing and deleting\n"); + delete[] (char*) fBuffer; + } else { + WMSG0(" GFDBuffer closing\n"); + } + fBuffer = nil; - return kDIErrNone; + return kDIErrNone; } #ifdef _WIN32 /* * =========================================================================== - * GFDWinVolume + * GFDWinVolume * =========================================================================== */ @@ -612,265 +612,265 @@ GFDBuffer::Close(void) DIError GFDWinVolume::Open(const char* deviceName, bool readOnly) { - DIError dierr = kDIErrNone; - HANDLE handle = nil; - //unsigned long kTwoGBBlocks; - - if (fVolAccess.Ready()) - return kDIErrAlreadyOpen; - if (deviceName == nil) - return kDIErrInvalidArg; + DIError dierr = kDIErrNone; + HANDLE handle = nil; + //unsigned long kTwoGBBlocks; + + if (fVolAccess.Ready()) + return kDIErrAlreadyOpen; + if (deviceName == nil) + return kDIErrInvalidArg; if (deviceName[0] == '\0') return kDIErrInvalidArg; - delete[] fPathName; - fPathName = new char[strlen(deviceName) +1]; - strcpy(fPathName, deviceName); + delete[] fPathName; + fPathName = new char[strlen(deviceName) +1]; + strcpy(fPathName, deviceName); - dierr = fVolAccess.Open(deviceName, readOnly); - if (dierr != kDIErrNone) - goto bail; + dierr = fVolAccess.Open(deviceName, readOnly); + if (dierr != kDIErrNone) + goto bail; - fBlockSize = fVolAccess.GetBlockSize(); // must be power of 2 - assert(fBlockSize > 0); - //kTwoGBBlocks = kTwoGB / fBlockSize; + fBlockSize = fVolAccess.GetBlockSize(); // must be power of 2 + assert(fBlockSize > 0); + //kTwoGBBlocks = kTwoGB / fBlockSize; - unsigned long totalBlocks; - totalBlocks = fVolAccess.GetTotalBlocks(); - fVolumeEOF = (di_off_t)totalBlocks * fBlockSize; + unsigned long totalBlocks; + totalBlocks = fVolAccess.GetTotalBlocks(); + fVolumeEOF = (di_off_t)totalBlocks * fBlockSize; - assert(fVolumeEOF > 0); + assert(fVolumeEOF > 0); fReadOnly = readOnly; bail: - return dierr; + return dierr; } DIError GFDWinVolume::Read(void* buf, size_t length, size_t* pActual) { - DIError dierr = kDIErrNone; - unsigned char* blkBuf = nil; + DIError dierr = kDIErrNone; + unsigned char* blkBuf = nil; - //WMSG2(" GFDWinVolume: reading %ld bytes from offset %ld\n", length, - // fCurrentOffset); + //WMSG2(" GFDWinVolume: reading %ld bytes from offset %ld\n", length, + // fCurrentOffset); - if (!fVolAccess.Ready()) - return kDIErrNotReady; + if (!fVolAccess.Ready()) + return kDIErrNotReady; - // don't allow reading past the end of file - if (fCurrentOffset + (long) length > fVolumeEOF) { - if (pActual == nil) - return kDIErrDataUnderrun; - length = (size_t) (fVolumeEOF - fCurrentOffset); - } - if (pActual != nil) - *pActual = length; - if (length == 0) - return kDIErrNone; + // don't allow reading past the end of file + if (fCurrentOffset + (long) length > fVolumeEOF) { + if (pActual == nil) + return kDIErrDataUnderrun; + length = (size_t) (fVolumeEOF - fCurrentOffset); + } + if (pActual != nil) + *pActual = length; + if (length == 0) + return kDIErrNone; - long advanceLen = length; + long advanceLen = length; - blkBuf = new unsigned char[fBlockSize]; // get this off the heap?? - long blockIndex = (long) (fCurrentOffset / fBlockSize); - int bufOffset = (int) (fCurrentOffset % fBlockSize); // req power of 2 - assert(blockIndex >= 0); + blkBuf = new unsigned char[fBlockSize]; // get this off the heap?? + long blockIndex = (long) (fCurrentOffset / fBlockSize); + int bufOffset = (int) (fCurrentOffset % fBlockSize); // req power of 2 + assert(blockIndex >= 0); - /* - * When possible, do multi-block reads directly into "buf". The first - * and last block may require special handling. - */ - while (length) { - assert(length > 0); + /* + * When possible, do multi-block reads directly into "buf". The first + * and last block may require special handling. + */ + while (length) { + assert(length > 0); - if (bufOffset != 0 || length < (size_t) fBlockSize) { - assert(bufOffset >= 0 && bufOffset < fBlockSize); + if (bufOffset != 0 || length < (size_t) fBlockSize) { + assert(bufOffset >= 0 && bufOffset < fBlockSize); - size_t thisCount; + size_t thisCount; - dierr = fVolAccess.ReadBlocks(blockIndex, 1, blkBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fVolAccess.ReadBlocks(blockIndex, 1, blkBuf); + if (dierr != kDIErrNone) + goto bail; - thisCount = fBlockSize - bufOffset; - if (thisCount > length) - thisCount = length; + thisCount = fBlockSize - bufOffset; + if (thisCount > length) + thisCount = length; - //WMSG2(" Copying %d bytes from block %d\n", - // thisCount, blockIndex); + //WMSG2(" Copying %d bytes from block %d\n", + // thisCount, blockIndex); - memcpy(buf, blkBuf + bufOffset, thisCount); - length -= thisCount; - buf = (char*) buf + thisCount; + memcpy(buf, blkBuf + bufOffset, thisCount); + length -= thisCount; + buf = (char*) buf + thisCount; - bufOffset = 0; - blockIndex++; - } else { - assert(bufOffset == 0); + bufOffset = 0; + blockIndex++; + } else { + assert(bufOffset == 0); - long blockCount = length / fBlockSize; - assert(blockCount < 32768); + long blockCount = length / fBlockSize; + assert(blockCount < 32768); - dierr = fVolAccess.ReadBlocks(blockIndex, (short) blockCount, buf); - if (dierr != kDIErrNone) - goto bail; + dierr = fVolAccess.ReadBlocks(blockIndex, (short) blockCount, buf); + if (dierr != kDIErrNone) + goto bail; - length -= blockCount * fBlockSize; - buf = (char*) buf + blockCount * fBlockSize; + length -= blockCount * fBlockSize; + buf = (char*) buf + blockCount * fBlockSize; - blockIndex += blockCount; - } + blockIndex += blockCount; + } - } + } - fCurrentOffset += advanceLen; + fCurrentOffset += advanceLen; bail: - delete[] blkBuf; - return dierr; + delete[] blkBuf; + return dierr; } DIError GFDWinVolume::Write(const void* buf, size_t length, size_t* pActual) { - DIError dierr = kDIErrNone; - unsigned char* blkBuf = nil; + DIError dierr = kDIErrNone; + unsigned char* blkBuf = nil; - //WMSG2(" GFDWinVolume: writing %ld bytes at offset %ld\n", length, - // fCurrentOffset); + //WMSG2(" GFDWinVolume: writing %ld bytes at offset %ld\n", length, + // fCurrentOffset); - if (!fVolAccess.Ready()) - return kDIErrNotReady; - if (fReadOnly) - return kDIErrAccessDenied; + if (!fVolAccess.Ready()) + return kDIErrNotReady; + if (fReadOnly) + return kDIErrAccessDenied; - // don't allow writing past the end of the volume - if (fCurrentOffset + (long) length > fVolumeEOF) { - if (pActual == nil) - return kDIErrDataOverrun; - length = (size_t) (fVolumeEOF - fCurrentOffset); - } - if (pActual != nil) - *pActual = length; - if (length == 0) - return kDIErrNone; + // don't allow writing past the end of the volume + if (fCurrentOffset + (long) length > fVolumeEOF) { + if (pActual == nil) + return kDIErrDataOverrun; + length = (size_t) (fVolumeEOF - fCurrentOffset); + } + if (pActual != nil) + *pActual = length; + if (length == 0) + return kDIErrNone; - long advanceLen = length; + long advanceLen = length; - blkBuf = new unsigned char[fBlockSize]; // get this out of the heap?? - long blockIndex = (long) (fCurrentOffset / fBlockSize); - int bufOffset = (int) (fCurrentOffset % fBlockSize); // req power of 2 - assert(blockIndex >= 0); + blkBuf = new unsigned char[fBlockSize]; // get this out of the heap?? + long blockIndex = (long) (fCurrentOffset / fBlockSize); + int bufOffset = (int) (fCurrentOffset % fBlockSize); // req power of 2 + assert(blockIndex >= 0); - /* - * When possible, do multi-block writes directly from "buf". The first - * and last block may require special handling. - */ - while (length) { - assert(length > 0); + /* + * When possible, do multi-block writes directly from "buf". The first + * and last block may require special handling. + */ + while (length) { + assert(length > 0); - if (bufOffset != 0 || length < (size_t) fBlockSize) { - assert(bufOffset >= 0 && bufOffset < fBlockSize); + if (bufOffset != 0 || length < (size_t) fBlockSize) { + assert(bufOffset >= 0 && bufOffset < fBlockSize); - size_t thisCount; + size_t thisCount; - dierr = fVolAccess.ReadBlocks(blockIndex, 1, blkBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fVolAccess.ReadBlocks(blockIndex, 1, blkBuf); + if (dierr != kDIErrNone) + goto bail; - thisCount = fBlockSize - bufOffset; - if (thisCount > length) - thisCount = length; + thisCount = fBlockSize - bufOffset; + if (thisCount > length) + thisCount = length; - //WMSG3(" Copying %d bytes into block %d (off=%d)\n", - // thisCount, blockIndex, bufOffset); + //WMSG3(" Copying %d bytes into block %d (off=%d)\n", + // thisCount, blockIndex, bufOffset); - memcpy(blkBuf + bufOffset, buf, thisCount); - length -= thisCount; - buf = (char*) buf + thisCount; + memcpy(blkBuf + bufOffset, buf, thisCount); + length -= thisCount; + buf = (char*) buf + thisCount; - dierr = fVolAccess.WriteBlocks(blockIndex, 1, blkBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fVolAccess.WriteBlocks(blockIndex, 1, blkBuf); + if (dierr != kDIErrNone) + goto bail; - bufOffset = 0; - blockIndex++; - } else { - assert(bufOffset == 0); + bufOffset = 0; + blockIndex++; + } else { + assert(bufOffset == 0); - long blockCount = length / fBlockSize; - assert(blockCount < 32768); + long blockCount = length / fBlockSize; + assert(blockCount < 32768); - dierr = fVolAccess.WriteBlocks(blockIndex, (short) blockCount, buf); - if (dierr != kDIErrNone) - goto bail; + dierr = fVolAccess.WriteBlocks(blockIndex, (short) blockCount, buf); + if (dierr != kDIErrNone) + goto bail; - length -= blockCount * fBlockSize; - buf = (char*) buf + blockCount * fBlockSize; + length -= blockCount * fBlockSize; + buf = (char*) buf + blockCount * fBlockSize; - blockIndex += blockCount; - } + blockIndex += blockCount; + } - } + } - fCurrentOffset += advanceLen; + fCurrentOffset += advanceLen; bail: - delete[] blkBuf; - return dierr; + delete[] blkBuf; + return dierr; } DIError GFDWinVolume::Seek(di_off_t offset, DIWhence whence) { - if (!fVolAccess.Ready()) - return kDIErrNotReady; + if (!fVolAccess.Ready()) + return kDIErrNotReady; - switch (whence) { - case kSeekSet: - if (offset < 0 || offset >= fVolumeEOF) - return kDIErrInvalidArg; - fCurrentOffset = offset; - break; - case kSeekEnd: - if (offset > 0 || offset < -fVolumeEOF) - return kDIErrInvalidArg; - fCurrentOffset = fVolumeEOF + offset; - break; - case kSeekCur: - if (offset < -fCurrentOffset || - offset >= (fVolumeEOF - fCurrentOffset)) - { - return kDIErrInvalidArg; - } - fCurrentOffset += offset; - break; - default: - assert(false); - return kDIErrInvalidArg; - } + switch (whence) { + case kSeekSet: + if (offset < 0 || offset >= fVolumeEOF) + return kDIErrInvalidArg; + fCurrentOffset = offset; + break; + case kSeekEnd: + if (offset > 0 || offset < -fVolumeEOF) + return kDIErrInvalidArg; + fCurrentOffset = fVolumeEOF + offset; + break; + case kSeekCur: + if (offset < -fCurrentOffset || + offset >= (fVolumeEOF - fCurrentOffset)) + { + return kDIErrInvalidArg; + } + fCurrentOffset += offset; + break; + default: + assert(false); + return kDIErrInvalidArg; + } - assert(fCurrentOffset >= 0 && fCurrentOffset <= fVolumeEOF); - return kDIErrNone; + assert(fCurrentOffset >= 0 && fCurrentOffset <= fVolumeEOF); + return kDIErrNone; } di_off_t GFDWinVolume::Tell(void) { - if (!fVolAccess.Ready()) - return (di_off_t) -1; - return fCurrentOffset; + if (!fVolAccess.Ready()) + return (di_off_t) -1; + return fCurrentOffset; } DIError GFDWinVolume::Close(void) { - if (!fVolAccess.Ready()) - return kDIErrNotReady; + if (!fVolAccess.Ready()) + return kDIErrNotReady; - WMSG0(" GFDWinVolume closing\n"); - fVolAccess.Close(); - return kDIErrNone; + WMSG0(" GFDWinVolume closing\n"); + fVolAccess.Close(); + return kDIErrNone; } #endif /*_WIN32*/ diff --git a/diskimg/GenericFD.h b/diskimg/GenericFD.h index bcd7c60..caefe13 100644 --- a/diskimg/GenericFD.h +++ b/diskimg/GenericFD.h @@ -25,43 +25,43 @@ namespace DiskImgLib { */ class DISKIMG_API EmbeddedFD { public: - EmbeddedFD(void) { - fpDiskFS = NULL; - fpA2File = NULL; - } - virtual ~EmbeddedFD(void) {} + EmbeddedFD(void) { + fpDiskFS = NULL; + fpA2File = NULL; + } + virtual ~EmbeddedFD(void) {} - typedef enum Fork { kForkData = 0, kForkRsrc = 1 } Fork; - // bit-flag values for Open call's "access" parameter - enum { - kAccessNone = 0, // somewhat useless - kAccessRead = 0x01, // O_RDONLY - kAccessWrite = 0x02, // O_WRONLY - kAccessCreate = 0x04, // O_CREAT - kAccessMustNotExist = 0x08, // O_EXCL, pointless w/o O_CREAT + typedef enum Fork { kForkData = 0, kForkRsrc = 1 } Fork; + // bit-flag values for Open call's "access" parameter + enum { + kAccessNone = 0, // somewhat useless + kAccessRead = 0x01, // O_RDONLY + kAccessWrite = 0x02, // O_WRONLY + kAccessCreate = 0x04, // O_CREAT + kAccessMustNotExist = 0x08, // O_EXCL, pointless w/o O_CREAT - kAccessReadWrite = (kAccessRead | kAccessWrite), - }; + kAccessReadWrite = (kAccessRead | kAccessWrite), + }; - /* - * Standard set of calls. - */ - DIError Open(DiskFS* pDiskFS, const char* filename, Fork fork = kForkData, - int access = kAccessRead, int fileCreatePerms = 0); - DIError OpenBlocks(DiskFS* pDiskFS, long blockStart, long blockCount, - int access = kAccessRead); - DIError Read(void* buf, size_t length); - DIError Write(const void* buf, size_t length); - DIError Seek(di_off_t offset, DIWhence whence); - DIError Close(void); + /* + * Standard set of calls. + */ + DIError Open(DiskFS* pDiskFS, const char* filename, Fork fork = kForkData, + int access = kAccessRead, int fileCreatePerms = 0); + DIError OpenBlocks(DiskFS* pDiskFS, long blockStart, long blockCount, + int access = kAccessRead); + DIError Read(void* buf, size_t length); + DIError Write(const void* buf, size_t length); + DIError Seek(di_off_t offset, DIWhence whence); + DIError Close(void); private: - // prevent bitwise copying behavior - EmbeddedFD& operator=(const EmbeddedFD&); - EmbeddedFD(const EmbeddedFD&); + // prevent bitwise copying behavior + EmbeddedFD& operator=(const EmbeddedFD&); + EmbeddedFD(const EmbeddedFD&); - DiskFS* fpDiskFS; - A2File* fpA2File; + DiskFS* fpDiskFS; + A2File* fpA2File; }; #endif @@ -95,223 +95,223 @@ private: */ class GenericFD { public: - GenericFD(void) : fReadOnly(true) {} - virtual ~GenericFD(void) {} /* = 0 */ + GenericFD(void) : fReadOnly(true) {} + virtual ~GenericFD(void) {} /* = 0 */ - // All sub-classes must provide these, plus a type-specific Open call. - virtual DIError Read(void* buf, size_t length, - size_t* pActual = nil) = 0; - virtual DIError Write(const void* buf, size_t length, - size_t* pActual = nil) = 0; - virtual DIError Seek(di_off_t offset, DIWhence whence) = 0; - virtual di_off_t Tell(void) = 0; - virtual DIError Truncate(void) = 0; - virtual DIError Close(void) = 0; + // All sub-classes must provide these, plus a type-specific Open call. + virtual DIError Read(void* buf, size_t length, + size_t* pActual = nil) = 0; + virtual DIError Write(const void* buf, size_t length, + size_t* pActual = nil) = 0; + virtual DIError Seek(di_off_t offset, DIWhence whence) = 0; + virtual di_off_t Tell(void) = 0; + virtual DIError Truncate(void) = 0; + virtual DIError Close(void) = 0; virtual const char* GetPathName(void) const = 0; - // Flush-data call, only needed for physical devices - virtual DIError Flush(void) { return kDIErrNone; } + // Flush-data call, only needed for physical devices + virtual DIError Flush(void) { return kDIErrNone; } - // Utility functions. - virtual DIError Rewind(void) { return Seek(0, kSeekSet); } + // Utility functions. + virtual DIError Rewind(void) { return Seek(0, kSeekSet); } - virtual bool GetReadOnly(void) const { return fReadOnly; } + virtual bool GetReadOnly(void) const { return fReadOnly; } - /* - typedef enum { - kGFDTypeUnknown = 0, - kGFDTypeFile, - kGFDTypeBuffer, - kGFDTypeWinVolume, - kGFDTypeGFD - } GFDType; - virtual GFDType GetGFDType(void) const = 0; - */ + /* + typedef enum { + kGFDTypeUnknown = 0, + kGFDTypeFile, + kGFDTypeBuffer, + kGFDTypeWinVolume, + kGFDTypeGFD + } GFDType; + virtual GFDType GetGFDType(void) const = 0; + */ - /* - * Utility function to copy data from one GFD to another. Both GFDs must - * be seeked to their initial positions. "length" bytes will be copied. - */ - static DIError CopyFile(GenericFD* pDst, GenericFD* pSrc, di_off_t length, - unsigned long* pCRC = nil); + /* + * Utility function to copy data from one GFD to another. Both GFDs must + * be seeked to their initial positions. "length" bytes will be copied. + */ + static DIError CopyFile(GenericFD* pDst, GenericFD* pSrc, di_off_t length, + unsigned long* pCRC = nil); protected: - GenericFD& operator=(const GenericFD&); - GenericFD(const GenericFD&); + GenericFD& operator=(const GenericFD&); + GenericFD(const GenericFD&); - bool fReadOnly; // set when file is opened + bool fReadOnly; // set when file is opened }; class GFDFile : public GenericFD { public: #ifdef HAVE_FSEEKO - GFDFile(void) : fPathName(nil), fFp(nil) {} + GFDFile(void) : fPathName(nil), fFp(nil) {} #else - GFDFile(void) : fPathName(nil), fFd(-1) {} + GFDFile(void) : fPathName(nil), fFd(-1) {} #endif - virtual ~GFDFile(void) { Close(); delete[] fPathName; } + virtual ~GFDFile(void) { Close(); delete[] fPathName; } - virtual DIError Open(const char* filename, bool readOnly); - virtual DIError Read(void* buf, size_t length, - size_t* pActual = nil); - virtual DIError Write(const void* buf, size_t length, - size_t* pActual = nil); - virtual DIError Seek(di_off_t offset, DIWhence whence); - virtual di_off_t Tell(void); - virtual DIError Truncate(void); - virtual DIError Close(void); + virtual DIError Open(const char* filename, bool readOnly); + virtual DIError Read(void* buf, size_t length, + size_t* pActual = nil); + virtual DIError Write(const void* buf, size_t length, + size_t* pActual = nil); + virtual DIError Seek(di_off_t offset, DIWhence whence); + virtual di_off_t Tell(void); + virtual DIError Truncate(void); + virtual DIError Close(void); virtual const char* GetPathName(void) const { return fPathName; } private: char* fPathName; #ifdef HAVE_FSEEKO - FILE* fFp; + FILE* fFp; #else - int fFd; + int fFd; #endif }; #ifdef _WIN32 class GFDWinVolume : public GenericFD { public: - GFDWinVolume(void) : fPathName(nil), fCurrentOffset(0), fVolumeEOF(-1) - {} - virtual ~GFDWinVolume(void) { delete[] fPathName; } + GFDWinVolume(void) : fPathName(nil), fCurrentOffset(0), fVolumeEOF(-1) + {} + virtual ~GFDWinVolume(void) { delete[] fPathName; } - virtual DIError Open(const char* deviceName, bool readOnly); - virtual DIError Read(void* buf, size_t length, - size_t* pActual = nil); - virtual DIError Write(const void* buf, size_t length, - size_t* pActual = nil); - virtual DIError Seek(di_off_t offset, DIWhence whence); - virtual di_off_t Tell(void); - virtual DIError Truncate(void) { return kDIErrNotSupported; } - virtual DIError Close(void); + virtual DIError Open(const char* deviceName, bool readOnly); + virtual DIError Read(void* buf, size_t length, + size_t* pActual = nil); + virtual DIError Write(const void* buf, size_t length, + size_t* pActual = nil); + virtual DIError Seek(di_off_t offset, DIWhence whence); + virtual di_off_t Tell(void); + virtual DIError Truncate(void) { return kDIErrNotSupported; } + virtual DIError Close(void); virtual const char* GetPathName(void) const { return fPathName; } - virtual DIError Flush(void) { return fVolAccess.FlushCache(false); } + virtual DIError Flush(void) { return fVolAccess.FlushCache(false); } private: - char* fPathName; // for display only - Win32VolumeAccess fVolAccess; - di_off_t fCurrentOffset; - di_off_t fVolumeEOF; - int fBlockSize; // usually 512 + char* fPathName; // for display only + Win32VolumeAccess fVolAccess; + di_off_t fCurrentOffset; + di_off_t fVolumeEOF; + int fBlockSize; // usually 512 }; #endif class GFDBuffer : public GenericFD { public: - GFDBuffer(void) : fBuffer(nil) {} - virtual ~GFDBuffer(void) { Close(); } + GFDBuffer(void) : fBuffer(nil) {} + virtual ~GFDBuffer(void) { Close(); } - // If "doDelete" is set, the buffer will be freed with delete[] when - // Close is called. This should ONLY be used for storage allocated - // by the DiskImg library, as under Windows it can cause problems - // because DLLs can have their own heap. + // If "doDelete" is set, the buffer will be freed with delete[] when + // Close is called. This should ONLY be used for storage allocated + // by the DiskImg library, as under Windows it can cause problems + // because DLLs can have their own heap. // // "doExpand" will cause writing past the end of the buffer to // reallocate the buffer. Again, for internally-allocated storage // only. We expect the initial size to be close to accurate, so we // don't aggressively expand the buffer. - virtual DIError Open(void* buffer, di_off_t length, bool doDelete, - bool doExpand, bool readOnly); - virtual DIError Read(void* buf, size_t length, - size_t* pActual = nil); - virtual DIError Write(const void* buf, size_t length, - size_t* pActual = nil); - virtual DIError Seek(di_off_t offset, DIWhence whence); - virtual di_off_t Tell(void); - virtual DIError Truncate(void) { - fLength = (long) Tell(); - return kDIErrNone; - } - virtual DIError Close(void); + virtual DIError Open(void* buffer, di_off_t length, bool doDelete, + bool doExpand, bool readOnly); + virtual DIError Read(void* buf, size_t length, + size_t* pActual = nil); + virtual DIError Write(const void* buf, size_t length, + size_t* pActual = nil); + virtual DIError Seek(di_off_t offset, DIWhence whence); + virtual di_off_t Tell(void); + virtual DIError Truncate(void) { + fLength = (long) Tell(); + return kDIErrNone; + } + virtual DIError Close(void); virtual const char* GetPathName(void) const { return nil; } // Back door; try not to use this. void* GetBuffer(void) const { return fBuffer; } private: - enum { kMaxReasonableSize = 256 * 1024 * 1024 }; - void* fBuffer; - long fLength; // these sit in memory, so there's no - long fAllocLength; // value in using di_off_t here - bool fDoDelete; + enum { kMaxReasonableSize = 256 * 1024 * 1024 }; + void* fBuffer; + long fLength; // these sit in memory, so there's no + long fAllocLength; // value in using di_off_t here + bool fDoDelete; bool fDoExpand; - di_off_t fCurrentOffset; // actually limited to (long) + di_off_t fCurrentOffset; // actually limited to (long) }; #if 0 class GFDEmbedded : public GenericFD { public: - GFDEmbedded(void) : fEFD(nil) {} - virtual ~GFDEmbedded(void) { Close(); } + GFDEmbedded(void) : fEFD(nil) {} + virtual ~GFDEmbedded(void) { Close(); } - virtual DIError Open(EmbeddedFD* pEFD, bool readOnly); - virtual DIError Read(void* buf, size_t length, - size_t* pActual = nil); - virtual DIError Write(const void* buf, size_t length, - size_t* pActual = nil); - virtual DIError Seek(di_off_t offset, DIWhence whence); - virtual di_off_t Tell(void); - virtual DIError Close(void); + virtual DIError Open(EmbeddedFD* pEFD, bool readOnly); + virtual DIError Read(void* buf, size_t length, + size_t* pActual = nil); + virtual DIError Write(const void* buf, size_t length, + size_t* pActual = nil); + virtual DIError Seek(di_off_t offset, DIWhence whence); + virtual di_off_t Tell(void); + virtual DIError Close(void); virtual const char* GetPathName(void) const { return nil; } private: - EmbeddedFD* fEFD; + EmbeddedFD* fEFD; }; #endif /* pass all requests straight through to another GFD (with offset bias) */ class GFDGFD : public GenericFD { public: - GFDGFD(void) : fpGFD(nil), fOffset(0) {} - virtual ~GFDGFD(void) { Close(); } + GFDGFD(void) : fpGFD(nil), fOffset(0) {} + virtual ~GFDGFD(void) { Close(); } - virtual DIError Open(GenericFD* pGFD, di_off_t offset, bool readOnly) { - if (pGFD == nil) - return kDIErrInvalidArg; - if (!readOnly && pGFD->GetReadOnly()) - return kDIErrAccessDenied; // can't convert to read-write - fpGFD = pGFD; + virtual DIError Open(GenericFD* pGFD, di_off_t offset, bool readOnly) { + if (pGFD == nil) + return kDIErrInvalidArg; + if (!readOnly && pGFD->GetReadOnly()) + return kDIErrAccessDenied; // can't convert to read-write + fpGFD = pGFD; fOffset = offset; fReadOnly = readOnly; Seek(0, kSeekSet); - return kDIErrNone; - } - virtual DIError Read(void* buf, size_t length, - size_t* pActual = nil) - { - return fpGFD->Read(buf, length, pActual); - } - virtual DIError Write(const void* buf, size_t length, - size_t* pActual = nil) - { - return fpGFD->Write(buf, length, pActual); - } - virtual DIError Seek(di_off_t offset, DIWhence whence) { - return fpGFD->Seek(offset + fOffset, whence); - } - virtual di_off_t Tell(void) { - return fpGFD->Tell() -fOffset; - } - virtual DIError Truncate(void) { - return fpGFD->Truncate(); - } - virtual DIError Close(void) { - /* do NOT close underlying descriptor */ - fpGFD = nil; - return kDIErrNone; - } + return kDIErrNone; + } + virtual DIError Read(void* buf, size_t length, + size_t* pActual = nil) + { + return fpGFD->Read(buf, length, pActual); + } + virtual DIError Write(const void* buf, size_t length, + size_t* pActual = nil) + { + return fpGFD->Write(buf, length, pActual); + } + virtual DIError Seek(di_off_t offset, DIWhence whence) { + return fpGFD->Seek(offset + fOffset, whence); + } + virtual di_off_t Tell(void) { + return fpGFD->Tell() -fOffset; + } + virtual DIError Truncate(void) { + return fpGFD->Truncate(); + } + virtual DIError Close(void) { + /* do NOT close underlying descriptor */ + fpGFD = nil; + return kDIErrNone; + } virtual const char* GetPathName(void) const { return fpGFD->GetPathName(); } private: - GenericFD* fpGFD; + GenericFD* fpGFD; di_off_t fOffset; }; -}; // namespace DiskImgLib +}; // namespace DiskImgLib #endif /*__GENERIC_FD__*/ diff --git a/diskimg/Global.cpp b/diskimg/Global.cpp index 6654260..664e2f6 100644 --- a/diskimg/Global.cpp +++ b/diskimg/Global.cpp @@ -23,65 +23,65 @@ const char* DiskImgLib::kASPIDev = "ASPI:"; /*static*/ DIError Global::AppInit(void) { - NuError nerr; - long major, minor, bug; + NuError nerr; + long major, minor, bug; - if (fAppInitCalled) { - WMSG0("DiskImg AppInit already called\n"); - return kDIErrNone; - } + if (fAppInitCalled) { + WMSG0("DiskImg AppInit already called\n"); + return kDIErrNone; + } - WMSG3("AppInit for DiskImg library v%d.%d.%d\n", - kDiskImgVersionMajor, kDiskImgVersionMinor, kDiskImgVersionBug); + WMSG3("AppInit for DiskImg library v%d.%d.%d\n", + kDiskImgVersionMajor, kDiskImgVersionMinor, kDiskImgVersionBug); #ifdef _WIN32 - HMODULE hModule; - char fileNameBuf[256]; - hModule = ::GetModuleHandle("DiskImg4.dll"); - if (hModule != nil && - ::GetModuleFileName(hModule, fileNameBuf, sizeof(fileNameBuf)) != 0) - { - // GetModuleHandle does not increase ref count, so no need to release - WMSG1("DiskImg DLL loaded from '%s'\n", fileNameBuf); - } else { - WMSG0("Unable to get DiskImg DLL filename\n"); - } + HMODULE hModule; + char fileNameBuf[256]; + hModule = ::GetModuleHandle("DiskImg4.dll"); + if (hModule != nil && + ::GetModuleFileName(hModule, fileNameBuf, sizeof(fileNameBuf)) != 0) + { + // GetModuleHandle does not increase ref count, so no need to release + WMSG1("DiskImg DLL loaded from '%s'\n", fileNameBuf); + } else { + WMSG0("Unable to get DiskImg DLL filename\n"); + } #endif - /* - * Make sure we're linked against a compatible version of NufxLib. - */ - nerr = NuGetVersion(&major, &minor, &bug, NULL, NULL); - if (nerr != kNuErrNone) { - WMSG0("Unable to get version number from NufxLib."); - return kDIErrNufxLibInitFailed; - } + /* + * Make sure we're linked against a compatible version of NufxLib. + */ + nerr = NuGetVersion(&major, &minor, &bug, NULL, NULL); + if (nerr != kNuErrNone) { + WMSG0("Unable to get version number from NufxLib."); + return kDIErrNufxLibInitFailed; + } - if (major != kNuVersionMajor || minor < kNuVersionMinor) { - WMSG3("Unexpected NufxLib version %ld.%ld.%ld\n", - major, minor, bug); - return kDIErrNufxLibInitFailed; - } + if (major != kNuVersionMajor || minor < kNuVersionMinor) { + WMSG3("Unexpected NufxLib version %ld.%ld.%ld\n", + major, minor, bug); + return kDIErrNufxLibInitFailed; + } - /* - * Do one-time init over in the DiskImg class. - */ - DiskImg::CalcNibbleInvTables(); + /* + * Do one-time init over in the DiskImg class. + */ + DiskImg::CalcNibbleInvTables(); #ifdef HAVE_WINDOWS_CDROM - if (kAlwaysTryASPI || IsWin9x()) { - fpASPI = new ASPI; - if (fpASPI->Init() != kDIErrNone) { - delete fpASPI; - fpASPI = nil; - } - } + if (kAlwaysTryASPI || IsWin9x()) { + fpASPI = new ASPI; + if (fpASPI->Init() != kDIErrNone) { + delete fpASPI; + fpASPI = nil; + } + } #endif - WMSG2("DiskImg HasSPTI=%d HasASPI=%d\n", GetHasSPTI(), GetHasASPI()); + WMSG2("DiskImg HasSPTI=%d HasASPI=%d\n", GetHasSPTI(), GetHasASPI()); fAppInitCalled = true; - return kDIErrNone; + return kDIErrNone; } /* @@ -90,9 +90,9 @@ Global::AppInit(void) /*static*/ DIError Global::AppCleanup(void) { - WMSG0("DiskImgLib cleanup\n"); - delete fpASPI; - return kDIErrNone; + WMSG0("DiskImgLib cleanup\n"); + delete fpASPI; + return kDIErrNone; } /* @@ -106,8 +106,8 @@ Global::AppCleanup(void) /*static*/ bool Global::GetHasSPTI(void) { return !IsWin9x() && fpASPI == nil; } /*static*/ bool Global::GetHasASPI(void) { return fpASPI != nil; } /*static*/ unsigned long Global::GetASPIVersion(void) { - assert(fpASPI != nil); - return fpASPI->GetVersion(); + assert(fpASPI != nil); + return fpASPI->GetVersion(); } #else /*static*/ bool Global::GetHasSPTI(void) { return false; } @@ -122,12 +122,12 @@ Global::AppCleanup(void) /*static*/ void Global::GetVersion(long* pMajor, long* pMinor, long* pBug) { - if (pMajor != nil) - *pMajor = kDiskImgVersionMajor; - if (pMinor != nil) - *pMinor = kDiskImgVersionMinor; - if (pBug != nil) - *pBug = kDiskImgVersionBug; + if (pMajor != nil) + *pMajor = kDiskImgVersionMajor; + if (pMinor != nil) + *pMinor = kDiskImgVersionMinor; + if (pBug != nil) + *pBug = kDiskImgVersionBug; } @@ -142,11 +142,11 @@ Global::GetVersion(long* pMajor, long* pMinor, long* pBug) Global::DebugMsgHandler Global::SetDebugMsgHandler(DebugMsgHandler handler) { - DebugMsgHandler oldHandler; + DebugMsgHandler oldHandler; - oldHandler = gDebugMsgHandler; - gDebugMsgHandler = handler; - return oldHandler; + oldHandler = gDebugMsgHandler; + gDebugMsgHandler = handler; + return oldHandler; } /* @@ -158,32 +158,32 @@ Global::SetDebugMsgHandler(DebugMsgHandler handler) /*static*/ void Global::PrintDebugMsg(const char* file, int line, const char* fmt, ...) { - if (gDebugMsgHandler == nil) { - /* - * This can happen if the app decides to bail with an exit() - * call. I'm not sure what's zapping the pointer. - * - * We get here on "-install" or "-uninstall", which really - * should be using a more Windows-friendly exit strategy. - */ - DebugBreak(); - return; - } + if (gDebugMsgHandler == nil) { + /* + * This can happen if the app decides to bail with an exit() + * call. I'm not sure what's zapping the pointer. + * + * We get here on "-install" or "-uninstall", which really + * should be using a more Windows-friendly exit strategy. + */ + DebugBreak(); + return; + } - char buf[512]; + char buf[512]; va_list args; va_start(args, fmt); #if defined(HAVE_VSNPRINTF) - (void) vsnprintf(buf, sizeof(buf), fmt, args); + (void) vsnprintf(buf, sizeof(buf), fmt, args); #elif defined(HAVE__VSNPRINTF) - (void) _vsnprintf(buf, sizeof(buf), fmt, args); + (void) _vsnprintf(buf, sizeof(buf), fmt, args); #else # error "hosed" #endif va_end(args); - buf[sizeof(buf)-1] = '\0'; + buf[sizeof(buf)-1] = '\0'; - (*gDebugMsgHandler)(file, line, buf); + (*gDebugMsgHandler)(file, line, buf); } diff --git a/diskimg/Gutenberg.cpp b/diskimg/Gutenberg.cpp index fa3a402..fdae3fd 100644 --- a/diskimg/Gutenberg.cpp +++ b/diskimg/Gutenberg.cpp @@ -1,671 +1,671 @@ -/* - * CiderPress - * Copyright (C) 2009 by CiderPress authors. All Rights Reserved. - * See the file LICENSE for distribution terms. - */ -/* - * Implementation of DiskFSGutenberg and A2FileGutenberg classes. - * - */ -#include "StdAfx.h" -#include "DiskImgPriv.h" - - -/* - * =========================================================================== - * DiskFSGutenberg - * =========================================================================== - */ - -const int kMaxSectors = 32; -const int kMaxVolNameLen = 9; -const int kSctSize = 256; -const int kVTOCTrack = 17; -const int kVTOCSector = 7; -const int kCatalogEntryOffset = 0x20; // first entry in cat sect starts here -const int kCatalogEntrySize = 16; // length in bytes of catalog entries -const int kCatalogEntriesPerSect = 15; // #of entries per catalog sector -const int kEntryDeleted = 0x40; // this is used to designate deleted files -const int kEntryUnused = 0x00; // this is track# in never-used entries -const int kMaxTSPairs = 0x7a; // 122 entries for 256-byte sectors -const int kTSOffset = 0x0c; // first T/S entry in a T/S list - -const int kMaxTSIterations = 32; - -/* - * Get a pointer to the Nth entry in a catalog sector. - */ -static inline unsigned char* -GetCatalogEntryPtr(unsigned char* basePtr, int entryNum) -{ - assert(entryNum >= 0 && entryNum < kCatalogEntriesPerSect); - return basePtr + kCatalogEntryOffset + entryNum * kCatalogEntrySize; -} - - -/* - * Test this image for Gutenberg-ness. - * - */ -static DIError -TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder, int* pGoodCount) -{ - DIError dierr = kDIErrNone; - unsigned char sctBuf[kSctSize]; -// int numTracks, numSectors; - int catTrack = kVTOCTrack; - int catSect = kVTOCSector; - int foundGood = 0; - int iterations = 0; - - *pGoodCount = 0; - - /* - * Walk through the catalog track to try to figure out ordering. - */ - while (iterations < DiskFSGutenberg::kMaxCatalogSectors) - { - dierr = pImg->ReadTrackSectorSwapped(catTrack, catSect, sctBuf, - imageOrder, DiskImg::kSectorOrderDOS); - if (dierr != kDIErrNone) { - dierr = kDIErrNone; - break; /* allow it if earlier stuff was okay */ - } - if (catTrack == sctBuf[0] && catSect == sctBuf[1]) { - foundGood++; - if (sctBuf[0x0f] == 0x8d && sctBuf[0x1f] == 0x8d && - sctBuf[0x2f] == 0x8d && sctBuf[0x3f] == 0x8d && - sctBuf[0x4f] == 0x8d && sctBuf[0x5f] == 0x8d && - sctBuf[0x6f] == 0x8d && sctBuf[0x7f] == 0x8d && - sctBuf[0x8f] == 0x8d && sctBuf[0x9f] == 0x8d) - foundGood++; - } - else if (catTrack >0x80) { - WMSG2(" Gutenberg detected end-of-catalog on cat (%d,%d)\n", - catTrack, catSect); - break; - } - catTrack = sctBuf[0x04]; - catSect = sctBuf[0x05]; - iterations++; // watch for infinite loops - } - if (iterations >= DiskFSGutenberg::kMaxCatalogSectors) { - /* possible cause: LF->CR conversion screws up link to sector $0a */ - dierr = kDIErrDirectoryLoop; - WMSG1(" Gutenberg directory links cause a loop (order=%d)\n", imageOrder); - goto bail; - } - - WMSG2(" Gutenberg foundGood=%d order=%d\n", foundGood, imageOrder); - *pGoodCount = foundGood; - -bail: - return dierr; -} - -/* - * Test to see if the image is a Gutenberg word processor data disk. - */ -/*static*/ DIError -DiskFSGutenberg::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency) -{ - if (pImg->GetNumTracks() > kMaxInterestingTracks) - return kDIErrFilesystemNotFound; - - DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; - - DiskImg::GetSectorOrderArray(ordering, *pOrder); - - DiskImg::SectorOrder bestOrder = DiskImg::kSectorOrderUnknown; - int bestCount = 0; - - for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { - int goodCount = 0; - - if (ordering[i] == DiskImg::kSectorOrderUnknown) - continue; - if (TestImage(pImg, ordering[i], &goodCount) == kDIErrNone) { - if (goodCount > bestCount) { - bestCount = goodCount; - bestOrder = ordering[i]; - } - } - } - - if (bestCount >= 2 || - (leniency == kLeniencyVery && bestCount >= 1)) - { - WMSG2(" Gutenberg test: bestCount=%d for order=%d\n", bestCount, bestOrder); - assert(bestOrder != DiskImg::kSectorOrderUnknown); - *pOrder = bestOrder; - *pFormat = DiskImg::kFormatGutenberg; - return kDIErrNone; - } - - WMSG0(" Gutenberg didn't find a valid filesystem.\n"); - return kDIErrFilesystemNotFound; -} - - -/* - * Get things rolling. - * - * Since we're assured that this is a valid disk, errors encountered from here - * on out must be handled somehow, possibly by claiming that the disk is - * completely full and has no files on it. - */ -DIError -DiskFSGutenberg::Initialize(InitMode initMode) -{ - DIError dierr = kDIErrNone; - - fVolumeUsage.Create(fpImg->GetNumTracks(), fpImg->GetNumSectPerTrack()); - - /* read the contents of the catalog, creating our A2File list */ - dierr = ReadCatalog(); - if (dierr != kDIErrNone) - goto bail; - - /* run through and get file lengths and data offsets */ - dierr = GetFileLengths(); - if (dierr != kDIErrNone) - goto bail; - - sprintf(fDiskVolumeID, "Gutenberg: %s\0", fDiskVolumeName); - - fDiskIsGood = CheckDiskIsGood(); - - fVolumeUsage.Dump(); - -bail: - return dierr; -} - -/* - * Get the amount of free space remaining. - */ -DIError -DiskFSGutenberg::GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const -{ - *pTotalUnits = fpImg->GetNumTracks() * fpImg->GetNumSectPerTrack(); - *pFreeUnits = 0; - *pUnitSize = kSectorSize; - return kDIErrNone; -} - - -/* - * Read the disk's catalog. - * - */ -DIError -DiskFSGutenberg::ReadCatalog(void) -{ - DIError dierr = kDIErrNone; - unsigned char sctBuf[kSctSize]; - int catTrack, catSect; - int iterations; - - catTrack = 17; - catSect = 7; - iterations = 0; - - memset(fCatalogSectors, 0, sizeof(fCatalogSectors)); - - while (catTrack < 35 && catSect < 16 && iterations < kMaxCatalogSectors) - { - WMSG2(" Gutenberg reading catalog sector T=%d S=%d\n", catTrack, catSect); - dierr = fpImg->ReadTrackSector(catTrack, catSect, sctBuf); - if (dierr != kDIErrNone) - goto bail; - memcpy(fDiskVolumeName, &sctBuf[6], kMaxVolNameLen); // Copy out the volume name; it should be the same on all catalog sectors. - fDiskVolumeName[kMaxVolNameLen] = 0x00; - DiskFSGutenberg::LowerASCII((unsigned char*)fDiskVolumeName, kMaxVolNameLen); - A2FileGutenberg::TrimTrailingSpaces(fDiskVolumeName); - - dierr = ProcessCatalogSector(catTrack, catSect, sctBuf); - if (dierr != kDIErrNone) - goto bail; - - fCatalogSectors[iterations].track = catTrack; - fCatalogSectors[iterations].sector = catSect; - - catTrack = sctBuf[0x04]; - catSect = sctBuf[0x05]; - - iterations++; // watch for infinite loops - - } - if (iterations >= kMaxCatalogSectors) { - dierr = kDIErrDirectoryLoop; - goto bail; - } - -bail: - return dierr; -} - -/* - * Process the list of files in one sector of the catalog. - * - * Pass in the track, sector, and the contents of that track and sector. - * (We only use "catTrack" and "catSect" to fill out some fields.) - */ -DIError -DiskFSGutenberg::ProcessCatalogSector(int catTrack, int catSect, - const unsigned char* sctBuf) -{ - A2FileGutenberg* pFile; - const unsigned char* pEntry; - int i; - - pEntry = &sctBuf[kCatalogEntryOffset]; - - for (i = 0; i < kCatalogEntriesPerSect; i++) { - if (pEntry[0x0d] != kEntryDeleted && pEntry[0x00] != 0xa0 && pEntry[0x00] != 0x00) { - pFile = new A2FileGutenberg(this); - - pFile->SetQuality(A2File::kQualityGood); - - pFile->fTrack = pEntry[0x0c]; - pFile->fSector = pEntry[0x0d]; - - memcpy(pFile->fFileName, &pEntry[0x00], A2FileGutenberg::kMaxFileName); - pFile->fFileName[A2FileGutenberg::kMaxFileName] = '\0'; - pFile->FixFilename(); - - - //pFile->fCatTS.track = catTrack; - //pFile->fCatTS.sector = catSect; - pFile->fCatEntryNum = i; - - /* can't do these yet, so just set to defaults */ - pFile->fLength = 0; - pFile->fSparseLength = 0; - pFile->fDataOffset = 0; - pFile->fLengthInSectors = 0; - pFile->fLengthInSectors = 0; - - AddFileToList(pFile); - } - //if (pEntry[0x00] == 0xa0) - // break; - pEntry += kCatalogEntrySize; - } - - return kDIErrNone; -} - - -/* - * Perform consistency checks on the filesystem. - * - * Returns "true" if disk appears to be perfect, "false" otherwise. - */ -bool -DiskFSGutenberg::CheckDiskIsGood(void) -{ - bool result = true; - return result; -} - - -/* - * Run through our list of files, computing the lengths and marking file - * usage in the VolumeUsage object. - */ -DIError -DiskFSGutenberg::GetFileLengths(void) -{ - A2FileGutenberg* pFile; - unsigned char sctBuf[kSctSize]; - int tsCount = 0; - unsigned short currentTrack, currentSector; - - pFile = (A2FileGutenberg*) GetNextFile(nil); - while (pFile != nil) { - DIError dierr; - tsCount = 0; - currentTrack = pFile->fTrack; - currentSector = pFile->fSector; - - while (currentTrack < 0x80) { - tsCount ++; - dierr = fpImg->ReadTrackSector(currentTrack, currentSector, sctBuf); - if (dierr != kDIErrNone) { - WMSG1("Gutenberg failed loading track/sector for '%s'\n", - pFile->GetPathName()); - goto bail; - } - currentTrack = sctBuf[0x04]; - currentSector = sctBuf[0x05]; - } - pFile->fLengthInSectors = tsCount; - pFile->fLength = tsCount * 250; // First six bytes of sector are t/s pointers - - pFile = (A2FileGutenberg*) GetNextFile(pFile); - } - -bail: - return kDIErrNone; -} - - -/* - * Convert high ASCII to low ASCII. - * - * Some people put inverse and flashing text into filenames, not to mention - * control characters, so we have to cope with those too. - * - * We modify the first "len" bytes of "buf" in place. - */ -/*static*/ void -DiskFSGutenberg::LowerASCII(unsigned char* buf, long len) -{ - while (len--) { - if (*buf & 0x80) { - if (*buf >= 0xa0) - *buf &= 0x7f; - else - *buf = (*buf & 0x7f) + 0x20; - } else - *buf = ((*buf & 0x3f) ^ 0x20) + 0x20; - - buf++; - } -} - - -/* - * =========================================================================== - * A2FileGutenberg - * =========================================================================== - */ - -/* - * Constructor. - */ -A2FileGutenberg::A2FileGutenberg(DiskFS* pDiskFS) : A2File(pDiskFS) -{ - fTrack = -1; - fSector = -1; - fLengthInSectors = 0; - fLocked = true; - fFileName[0] = '\0'; - fFileType = kTypeText; - - fCatTS.track = fCatTS.sector = 0; - fCatEntryNum = -1; - - fAuxType = 0; - fDataOffset = 0; - fLength = -1; - fSparseLength = -1; - - fpOpenFile = nil; -} - -/* - * Destructor. Make sure an "open" file gets "closed". - */ -A2FileGutenberg::~A2FileGutenberg(void) -{ - delete fpOpenFile; -} - - -/* - * Convert the filetype enum to a ProDOS type. - * - */ -long -A2FileGutenberg::GetFileType(void) const -{ - return 0x04; // TXT; -} - -/* - * "Fix" a filename. Convert DOS-ASCII to normal ASCII, and strip - * trailing spaces. - */ -void -A2FileGutenberg::FixFilename(void) -{ - DiskFSGutenberg::LowerASCII((unsigned char*)fFileName, kMaxFileName); - TrimTrailingSpaces(fFileName); -} - -/* - * Trim the spaces off the end of a filename. - * - * Assumes the filename has already been converted to low ASCII. - */ -/*static*/ void -A2FileGutenberg::TrimTrailingSpaces(char* filename) -{ - char* lastspc = filename + strlen(filename); - - assert(*lastspc == '\0'); - - while (--lastspc) { - if (*lastspc != ' ') - break; - } - - *(lastspc+1) = '\0'; -} - -/* - * Encode a filename into high ASCII, padded out with spaces to - * kMaxFileName chars. Lower case is converted to upper case. This - * does not filter out control characters or other chunk. - * - * "buf" must be able to hold kMaxFileName+1 chars. - */ -/*static*/ void -A2FileGutenberg::MakeDOSName(char* buf, const char* name) -{ - for (int i = 0; i < kMaxFileName; i++) { - if (*name == '\0') - *buf++ = (char) 0xa0; - else - *buf++ = toupper(*name++) | 0x80; - } - *buf = '\0'; -} - - -/* - * Set up state for this file. - */ -DIError -A2FileGutenberg::Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork /*=false*/) -{ - DIError dierr = kDIErrNone; - A2FDGutenberg* pOpenFile = nil; - - if (!readOnly) { - if (fpDiskFS->GetDiskImg()->GetReadOnly()) - return kDIErrAccessDenied; - if (fpDiskFS->GetFSDamaged()) - return kDIErrBadDiskImage; - } - - if (fpOpenFile != nil) { - dierr = kDIErrAlreadyOpen; - goto bail; - } - - if (rsrcFork) - return kDIErrForkNotFound; - - pOpenFile = new A2FDGutenberg(this); - - pOpenFile->fOffset = 0; - pOpenFile->fOpenEOF = fLength; - pOpenFile->fOpenSectorsUsed = fLengthInSectors; - - fpOpenFile = pOpenFile; // add it to our single-member "open file set" - *ppOpenFile = pOpenFile; - pOpenFile = nil; - -bail: - delete pOpenFile; - return dierr; -} - -/* - * Dump the contents of an A2FileGutenberg. - */ -void -A2FileGutenberg::Dump(void) const -{ - WMSG1("A2FileGutenberg '%s'\n", fFileName); - WMSG2(" TS T=%-2d S=%-2d\n", fTrack, fSector); - WMSG2(" Cat T=%-2d S=%-2d\n", fCatTS.track, fCatTS.sector); - WMSG3(" type=%d lck=%d slen=%d\n", fFileType, fLocked, fLengthInSectors); - WMSG2(" auxtype=0x%04x length=%ld\n", - fAuxType, (long) fLength); -} - - -/* - * =========================================================================== - * A2FDGutenberg - * =========================================================================== - */ - -/* - * Read data from the current offset. - * - */ -DIError -A2FDGutenberg::Read(void* buf, size_t len, size_t* pActual) -{ - WMSG3(" Gutenberg reading %d bytes from '%s' (offset=%ld)\n", - len, fpFile->GetPathName(), (long) fOffset); - - A2FileGutenberg* pFile = (A2FileGutenberg*) fpFile; - - DIError dierr = kDIErrNone; - unsigned char sctBuf[kSctSize]; - short currentTrack, currentSector; - di_off_t actualOffset = fOffset + pFile->fDataOffset; // adjust for embedded len - int bufOffset = 6; - size_t thisCount; - - if (len == 0) - return kDIErrNone; - assert(fOpenEOF != 0); - currentTrack = pFile->fTrack; - currentSector = pFile->fSector; - /* could be more clever in here and avoid double-buffering */ - while (len) { - dierr = pFile->GetDiskFS()->GetDiskImg()->ReadTrackSector( - currentTrack, - currentSector, - sctBuf); - if (dierr != kDIErrNone) { - WMSG1(" Gutenberg error reading file '%s'\n", pFile->GetPathName()); - return dierr; - } - thisCount = kSctSize - bufOffset; - if (thisCount > len) - thisCount = len; - memcpy(buf, sctBuf + bufOffset, thisCount); - len -= thisCount; - buf = (char*)buf + thisCount; - currentTrack = sctBuf[0x04]; - currentSector = sctBuf[0x05]; - } - - return dierr; -} - -/* - * Writing Gutenberg files isn't supported. - * - */ -DIError -A2FDGutenberg::Write(const void* buf, size_t len, size_t* pActual) -{ - return kDIErrNotSupported; -} - -/* - * Seek to the specified offset. - */ -DIError -A2FDGutenberg::Seek(di_off_t offset, DIWhence whence) -{ - return kDIErrNotSupported; -} - -/* - * Return current offset. - */ -di_off_t -A2FDGutenberg::Tell(void) -{ - return kDIErrNotSupported; -} - -/* - * Release file state. - * - * If the file was modified, we need to update the sector usage count in - * the catalog track, and possibly a length word in the first sector of - * the file (for A/I/B). - * - * Given the current "write all at once" implementation of Write, we could - * have handled the length word back when initially writing the data, but - * someday we may fix that and I don't want to have to rewrite this part. - * - * Most applications don't check the value of "Close", or call it from a - * destructor, so we call CloseDescr whether we succeed or not. - */ -DIError -A2FDGutenberg::Close(void) -{ - DIError dierr = kDIErrNone; - - fpFile->CloseDescr(this); - return dierr; -} - - -/* - * Return the #of sectors/blocks in the file. - */ -long -A2FDGutenberg::GetSectorCount(void) const -{ - return fTSCount; -} -long -A2FDGutenberg::GetBlockCount(void) const -{ - return (fTSCount+1)/2; -} - -/* - * Return the Nth track/sector in this file. - * - * Returns (0,0) for a sparse sector. - */ -DIError -A2FDGutenberg::GetStorage(long sectorIdx, long* pTrack, long* pSector) const -{ - return kDIErrInvalidIndex; -} -/* - * Unimplemented - */ -DIError -A2FDGutenberg::GetStorage(long blockIdx, long* pBlock) const -{ - return kDIErrInvalidIndex; -} +/* + * CiderPress + * Copyright (C) 2009 by CiderPress authors. All Rights Reserved. + * See the file LICENSE for distribution terms. + */ +/* + * Implementation of DiskFSGutenberg and A2FileGutenberg classes. + * + */ +#include "StdAfx.h" +#include "DiskImgPriv.h" + + +/* + * =========================================================================== + * DiskFSGutenberg + * =========================================================================== + */ + +const int kMaxSectors = 32; +const int kMaxVolNameLen = 9; +const int kSctSize = 256; +const int kVTOCTrack = 17; +const int kVTOCSector = 7; +const int kCatalogEntryOffset = 0x20; // first entry in cat sect starts here +const int kCatalogEntrySize = 16; // length in bytes of catalog entries +const int kCatalogEntriesPerSect = 15; // #of entries per catalog sector +const int kEntryDeleted = 0x40; // this is used to designate deleted files +const int kEntryUnused = 0x00; // this is track# in never-used entries +const int kMaxTSPairs = 0x7a; // 122 entries for 256-byte sectors +const int kTSOffset = 0x0c; // first T/S entry in a T/S list + +const int kMaxTSIterations = 32; + +/* + * Get a pointer to the Nth entry in a catalog sector. + */ +static inline unsigned char* +GetCatalogEntryPtr(unsigned char* basePtr, int entryNum) +{ + assert(entryNum >= 0 && entryNum < kCatalogEntriesPerSect); + return basePtr + kCatalogEntryOffset + entryNum * kCatalogEntrySize; +} + + +/* + * Test this image for Gutenberg-ness. + * + */ +static DIError +TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder, int* pGoodCount) +{ + DIError dierr = kDIErrNone; + unsigned char sctBuf[kSctSize]; +// int numTracks, numSectors; + int catTrack = kVTOCTrack; + int catSect = kVTOCSector; + int foundGood = 0; + int iterations = 0; + + *pGoodCount = 0; + + /* + * Walk through the catalog track to try to figure out ordering. + */ + while (iterations < DiskFSGutenberg::kMaxCatalogSectors) + { + dierr = pImg->ReadTrackSectorSwapped(catTrack, catSect, sctBuf, + imageOrder, DiskImg::kSectorOrderDOS); + if (dierr != kDIErrNone) { + dierr = kDIErrNone; + break; /* allow it if earlier stuff was okay */ + } + if (catTrack == sctBuf[0] && catSect == sctBuf[1]) { + foundGood++; + if (sctBuf[0x0f] == 0x8d && sctBuf[0x1f] == 0x8d && + sctBuf[0x2f] == 0x8d && sctBuf[0x3f] == 0x8d && + sctBuf[0x4f] == 0x8d && sctBuf[0x5f] == 0x8d && + sctBuf[0x6f] == 0x8d && sctBuf[0x7f] == 0x8d && + sctBuf[0x8f] == 0x8d && sctBuf[0x9f] == 0x8d) + foundGood++; + } + else if (catTrack >0x80) { + WMSG2(" Gutenberg detected end-of-catalog on cat (%d,%d)\n", + catTrack, catSect); + break; + } + catTrack = sctBuf[0x04]; + catSect = sctBuf[0x05]; + iterations++; // watch for infinite loops + } + if (iterations >= DiskFSGutenberg::kMaxCatalogSectors) { + /* possible cause: LF->CR conversion screws up link to sector $0a */ + dierr = kDIErrDirectoryLoop; + WMSG1(" Gutenberg directory links cause a loop (order=%d)\n", imageOrder); + goto bail; + } + + WMSG2(" Gutenberg foundGood=%d order=%d\n", foundGood, imageOrder); + *pGoodCount = foundGood; + +bail: + return dierr; +} + +/* + * Test to see if the image is a Gutenberg word processor data disk. + */ +/*static*/ DIError +DiskFSGutenberg::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, + DiskImg::FSFormat* pFormat, FSLeniency leniency) +{ + if (pImg->GetNumTracks() > kMaxInterestingTracks) + return kDIErrFilesystemNotFound; + + DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; + + DiskImg::GetSectorOrderArray(ordering, *pOrder); + + DiskImg::SectorOrder bestOrder = DiskImg::kSectorOrderUnknown; + int bestCount = 0; + + for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { + int goodCount = 0; + + if (ordering[i] == DiskImg::kSectorOrderUnknown) + continue; + if (TestImage(pImg, ordering[i], &goodCount) == kDIErrNone) { + if (goodCount > bestCount) { + bestCount = goodCount; + bestOrder = ordering[i]; + } + } + } + + if (bestCount >= 2 || + (leniency == kLeniencyVery && bestCount >= 1)) + { + WMSG2(" Gutenberg test: bestCount=%d for order=%d\n", bestCount, bestOrder); + assert(bestOrder != DiskImg::kSectorOrderUnknown); + *pOrder = bestOrder; + *pFormat = DiskImg::kFormatGutenberg; + return kDIErrNone; + } + + WMSG0(" Gutenberg didn't find a valid filesystem.\n"); + return kDIErrFilesystemNotFound; +} + + +/* + * Get things rolling. + * + * Since we're assured that this is a valid disk, errors encountered from here + * on out must be handled somehow, possibly by claiming that the disk is + * completely full and has no files on it. + */ +DIError +DiskFSGutenberg::Initialize(InitMode initMode) +{ + DIError dierr = kDIErrNone; + + fVolumeUsage.Create(fpImg->GetNumTracks(), fpImg->GetNumSectPerTrack()); + + /* read the contents of the catalog, creating our A2File list */ + dierr = ReadCatalog(); + if (dierr != kDIErrNone) + goto bail; + + /* run through and get file lengths and data offsets */ + dierr = GetFileLengths(); + if (dierr != kDIErrNone) + goto bail; + + sprintf(fDiskVolumeID, "Gutenberg: %s\0", fDiskVolumeName); + + fDiskIsGood = CheckDiskIsGood(); + + fVolumeUsage.Dump(); + +bail: + return dierr; +} + +/* + * Get the amount of free space remaining. + */ +DIError +DiskFSGutenberg::GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, + int* pUnitSize) const +{ + *pTotalUnits = fpImg->GetNumTracks() * fpImg->GetNumSectPerTrack(); + *pFreeUnits = 0; + *pUnitSize = kSectorSize; + return kDIErrNone; +} + + +/* + * Read the disk's catalog. + * + */ +DIError +DiskFSGutenberg::ReadCatalog(void) +{ + DIError dierr = kDIErrNone; + unsigned char sctBuf[kSctSize]; + int catTrack, catSect; + int iterations; + + catTrack = 17; + catSect = 7; + iterations = 0; + + memset(fCatalogSectors, 0, sizeof(fCatalogSectors)); + + while (catTrack < 35 && catSect < 16 && iterations < kMaxCatalogSectors) + { + WMSG2(" Gutenberg reading catalog sector T=%d S=%d\n", catTrack, catSect); + dierr = fpImg->ReadTrackSector(catTrack, catSect, sctBuf); + if (dierr != kDIErrNone) + goto bail; + memcpy(fDiskVolumeName, &sctBuf[6], kMaxVolNameLen); // Copy out the volume name; it should be the same on all catalog sectors. + fDiskVolumeName[kMaxVolNameLen] = 0x00; + DiskFSGutenberg::LowerASCII((unsigned char*)fDiskVolumeName, kMaxVolNameLen); + A2FileGutenberg::TrimTrailingSpaces(fDiskVolumeName); + + dierr = ProcessCatalogSector(catTrack, catSect, sctBuf); + if (dierr != kDIErrNone) + goto bail; + + fCatalogSectors[iterations].track = catTrack; + fCatalogSectors[iterations].sector = catSect; + + catTrack = sctBuf[0x04]; + catSect = sctBuf[0x05]; + + iterations++; // watch for infinite loops + + } + if (iterations >= kMaxCatalogSectors) { + dierr = kDIErrDirectoryLoop; + goto bail; + } + +bail: + return dierr; +} + +/* + * Process the list of files in one sector of the catalog. + * + * Pass in the track, sector, and the contents of that track and sector. + * (We only use "catTrack" and "catSect" to fill out some fields.) + */ +DIError +DiskFSGutenberg::ProcessCatalogSector(int catTrack, int catSect, + const unsigned char* sctBuf) +{ + A2FileGutenberg* pFile; + const unsigned char* pEntry; + int i; + + pEntry = &sctBuf[kCatalogEntryOffset]; + + for (i = 0; i < kCatalogEntriesPerSect; i++) { + if (pEntry[0x0d] != kEntryDeleted && pEntry[0x00] != 0xa0 && pEntry[0x00] != 0x00) { + pFile = new A2FileGutenberg(this); + + pFile->SetQuality(A2File::kQualityGood); + + pFile->fTrack = pEntry[0x0c]; + pFile->fSector = pEntry[0x0d]; + + memcpy(pFile->fFileName, &pEntry[0x00], A2FileGutenberg::kMaxFileName); + pFile->fFileName[A2FileGutenberg::kMaxFileName] = '\0'; + pFile->FixFilename(); + + + //pFile->fCatTS.track = catTrack; + //pFile->fCatTS.sector = catSect; + pFile->fCatEntryNum = i; + + /* can't do these yet, so just set to defaults */ + pFile->fLength = 0; + pFile->fSparseLength = 0; + pFile->fDataOffset = 0; + pFile->fLengthInSectors = 0; + pFile->fLengthInSectors = 0; + + AddFileToList(pFile); + } + //if (pEntry[0x00] == 0xa0) + // break; + pEntry += kCatalogEntrySize; + } + + return kDIErrNone; +} + + +/* + * Perform consistency checks on the filesystem. + * + * Returns "true" if disk appears to be perfect, "false" otherwise. + */ +bool +DiskFSGutenberg::CheckDiskIsGood(void) +{ + bool result = true; + return result; +} + + +/* + * Run through our list of files, computing the lengths and marking file + * usage in the VolumeUsage object. + */ +DIError +DiskFSGutenberg::GetFileLengths(void) +{ + A2FileGutenberg* pFile; + unsigned char sctBuf[kSctSize]; + int tsCount = 0; + unsigned short currentTrack, currentSector; + + pFile = (A2FileGutenberg*) GetNextFile(nil); + while (pFile != nil) { + DIError dierr; + tsCount = 0; + currentTrack = pFile->fTrack; + currentSector = pFile->fSector; + + while (currentTrack < 0x80) { + tsCount ++; + dierr = fpImg->ReadTrackSector(currentTrack, currentSector, sctBuf); + if (dierr != kDIErrNone) { + WMSG1("Gutenberg failed loading track/sector for '%s'\n", + pFile->GetPathName()); + goto bail; + } + currentTrack = sctBuf[0x04]; + currentSector = sctBuf[0x05]; + } + pFile->fLengthInSectors = tsCount; + pFile->fLength = tsCount * 250; // First six bytes of sector are t/s pointers + + pFile = (A2FileGutenberg*) GetNextFile(pFile); + } + +bail: + return kDIErrNone; +} + + +/* + * Convert high ASCII to low ASCII. + * + * Some people put inverse and flashing text into filenames, not to mention + * control characters, so we have to cope with those too. + * + * We modify the first "len" bytes of "buf" in place. + */ +/*static*/ void +DiskFSGutenberg::LowerASCII(unsigned char* buf, long len) +{ + while (len--) { + if (*buf & 0x80) { + if (*buf >= 0xa0) + *buf &= 0x7f; + else + *buf = (*buf & 0x7f) + 0x20; + } else + *buf = ((*buf & 0x3f) ^ 0x20) + 0x20; + + buf++; + } +} + + +/* + * =========================================================================== + * A2FileGutenberg + * =========================================================================== + */ + +/* + * Constructor. + */ +A2FileGutenberg::A2FileGutenberg(DiskFS* pDiskFS) : A2File(pDiskFS) +{ + fTrack = -1; + fSector = -1; + fLengthInSectors = 0; + fLocked = true; + fFileName[0] = '\0'; + fFileType = kTypeText; + + fCatTS.track = fCatTS.sector = 0; + fCatEntryNum = -1; + + fAuxType = 0; + fDataOffset = 0; + fLength = -1; + fSparseLength = -1; + + fpOpenFile = nil; +} + +/* + * Destructor. Make sure an "open" file gets "closed". + */ +A2FileGutenberg::~A2FileGutenberg(void) +{ + delete fpOpenFile; +} + + +/* + * Convert the filetype enum to a ProDOS type. + * + */ +long +A2FileGutenberg::GetFileType(void) const +{ + return 0x04; // TXT; +} + +/* + * "Fix" a filename. Convert DOS-ASCII to normal ASCII, and strip + * trailing spaces. + */ +void +A2FileGutenberg::FixFilename(void) +{ + DiskFSGutenberg::LowerASCII((unsigned char*)fFileName, kMaxFileName); + TrimTrailingSpaces(fFileName); +} + +/* + * Trim the spaces off the end of a filename. + * + * Assumes the filename has already been converted to low ASCII. + */ +/*static*/ void +A2FileGutenberg::TrimTrailingSpaces(char* filename) +{ + char* lastspc = filename + strlen(filename); + + assert(*lastspc == '\0'); + + while (--lastspc) { + if (*lastspc != ' ') + break; + } + + *(lastspc+1) = '\0'; +} + +/* + * Encode a filename into high ASCII, padded out with spaces to + * kMaxFileName chars. Lower case is converted to upper case. This + * does not filter out control characters or other chunk. + * + * "buf" must be able to hold kMaxFileName+1 chars. + */ +/*static*/ void +A2FileGutenberg::MakeDOSName(char* buf, const char* name) +{ + for (int i = 0; i < kMaxFileName; i++) { + if (*name == '\0') + *buf++ = (char) 0xa0; + else + *buf++ = toupper(*name++) | 0x80; + } + *buf = '\0'; +} + + +/* + * Set up state for this file. + */ +DIError +A2FileGutenberg::Open(A2FileDescr** ppOpenFile, bool readOnly, + bool rsrcFork /*=false*/) +{ + DIError dierr = kDIErrNone; + A2FDGutenberg* pOpenFile = nil; + + if (!readOnly) { + if (fpDiskFS->GetDiskImg()->GetReadOnly()) + return kDIErrAccessDenied; + if (fpDiskFS->GetFSDamaged()) + return kDIErrBadDiskImage; + } + + if (fpOpenFile != nil) { + dierr = kDIErrAlreadyOpen; + goto bail; + } + + if (rsrcFork) + return kDIErrForkNotFound; + + pOpenFile = new A2FDGutenberg(this); + + pOpenFile->fOffset = 0; + pOpenFile->fOpenEOF = fLength; + pOpenFile->fOpenSectorsUsed = fLengthInSectors; + + fpOpenFile = pOpenFile; // add it to our single-member "open file set" + *ppOpenFile = pOpenFile; + pOpenFile = nil; + +bail: + delete pOpenFile; + return dierr; +} + +/* + * Dump the contents of an A2FileGutenberg. + */ +void +A2FileGutenberg::Dump(void) const +{ + WMSG1("A2FileGutenberg '%s'\n", fFileName); + WMSG2(" TS T=%-2d S=%-2d\n", fTrack, fSector); + WMSG2(" Cat T=%-2d S=%-2d\n", fCatTS.track, fCatTS.sector); + WMSG3(" type=%d lck=%d slen=%d\n", fFileType, fLocked, fLengthInSectors); + WMSG2(" auxtype=0x%04x length=%ld\n", + fAuxType, (long) fLength); +} + + +/* + * =========================================================================== + * A2FDGutenberg + * =========================================================================== + */ + +/* + * Read data from the current offset. + * + */ +DIError +A2FDGutenberg::Read(void* buf, size_t len, size_t* pActual) +{ + WMSG3(" Gutenberg reading %d bytes from '%s' (offset=%ld)\n", + len, fpFile->GetPathName(), (long) fOffset); + + A2FileGutenberg* pFile = (A2FileGutenberg*) fpFile; + + DIError dierr = kDIErrNone; + unsigned char sctBuf[kSctSize]; + short currentTrack, currentSector; + di_off_t actualOffset = fOffset + pFile->fDataOffset; // adjust for embedded len + int bufOffset = 6; + size_t thisCount; + + if (len == 0) + return kDIErrNone; + assert(fOpenEOF != 0); + currentTrack = pFile->fTrack; + currentSector = pFile->fSector; + /* could be more clever in here and avoid double-buffering */ + while (len) { + dierr = pFile->GetDiskFS()->GetDiskImg()->ReadTrackSector( + currentTrack, + currentSector, + sctBuf); + if (dierr != kDIErrNone) { + WMSG1(" Gutenberg error reading file '%s'\n", pFile->GetPathName()); + return dierr; + } + thisCount = kSctSize - bufOffset; + if (thisCount > len) + thisCount = len; + memcpy(buf, sctBuf + bufOffset, thisCount); + len -= thisCount; + buf = (char*)buf + thisCount; + currentTrack = sctBuf[0x04]; + currentSector = sctBuf[0x05]; + } + + return dierr; +} + +/* + * Writing Gutenberg files isn't supported. + * + */ +DIError +A2FDGutenberg::Write(const void* buf, size_t len, size_t* pActual) +{ + return kDIErrNotSupported; +} + +/* + * Seek to the specified offset. + */ +DIError +A2FDGutenberg::Seek(di_off_t offset, DIWhence whence) +{ + return kDIErrNotSupported; +} + +/* + * Return current offset. + */ +di_off_t +A2FDGutenberg::Tell(void) +{ + return kDIErrNotSupported; +} + +/* + * Release file state. + * + * If the file was modified, we need to update the sector usage count in + * the catalog track, and possibly a length word in the first sector of + * the file (for A/I/B). + * + * Given the current "write all at once" implementation of Write, we could + * have handled the length word back when initially writing the data, but + * someday we may fix that and I don't want to have to rewrite this part. + * + * Most applications don't check the value of "Close", or call it from a + * destructor, so we call CloseDescr whether we succeed or not. + */ +DIError +A2FDGutenberg::Close(void) +{ + DIError dierr = kDIErrNone; + + fpFile->CloseDescr(this); + return dierr; +} + + +/* + * Return the #of sectors/blocks in the file. + */ +long +A2FDGutenberg::GetSectorCount(void) const +{ + return fTSCount; +} +long +A2FDGutenberg::GetBlockCount(void) const +{ + return (fTSCount+1)/2; +} + +/* + * Return the Nth track/sector in this file. + * + * Returns (0,0) for a sparse sector. + */ +DIError +A2FDGutenberg::GetStorage(long sectorIdx, long* pTrack, long* pSector) const +{ + return kDIErrInvalidIndex; +} +/* + * Unimplemented + */ +DIError +A2FDGutenberg::GetStorage(long blockIdx, long* pBlock) const +{ + return kDIErrInvalidIndex; +} diff --git a/diskimg/HFS.cpp b/diskimg/HFS.cpp index 312506c..8204b61 100644 --- a/diskimg/HFS.cpp +++ b/diskimg/HFS.cpp @@ -24,25 +24,25 @@ /* * =========================================================================== - * DiskFSHFS + * DiskFSHFS * =========================================================================== */ const int kBlkSize = 512; -const int kMasterDirBlock = 2; // also a copy in next-to-last block -const unsigned short kSignature = 0x4244; // or 0xd2d7 for MFS +const int kMasterDirBlock = 2; // also a copy in next-to-last block +const unsigned short kSignature = 0x4244; // or 0xd2d7 for MFS const int kMaxDirectoryDepth = 128; // not sure what HFS limit is //namespace DiskImgLib { /* extent descriptor */ typedef struct ExtDescriptor { - unsigned short xdrStABN; // first allocation block - unsigned short xdrNumABlks; // #of allocation blocks + unsigned short xdrStABN; // first allocation block + unsigned short xdrNumABlks; // #of allocation blocks } ExtDescriptor; /* extent data record */ typedef struct ExtDataRec { - ExtDescriptor extDescriptor[3]; + ExtDescriptor extDescriptor[3]; } ExtDataRec; /* @@ -50,36 +50,36 @@ typedef struct ExtDataRec { * chapter 2 ("Data Organization on Volumes"), pages 2-60 to 2-62. */ typedef struct DiskFSHFS::MasterDirBlock { - unsigned short drSigWord; // volume signature - unsigned long drCrDate; // date/time of volume creation - unsigned long drLsMod; // date/time of last modification - unsigned short drAtrb; // volume attributes - unsigned short drNmPls; // #of files in root directory - unsigned short drVBMSt; // first block of volume bitmap - unsigned short drAllocPtr; // start of next allocation search - unsigned short drNmAlBlks; // number of allocation blocks in volume - unsigned long drAlBlkSiz; // size (bytes) of allocation blocks - unsigned long drClpSiz; // default clump size - unsigned short drAlBlSt; // first allocation block in volume - unsigned long drNxtCNID; // next unused catalog node ID - unsigned short drFreeBks; // number of unused allocation blocks - unsigned char drVN[28]; // volume name (pascal string) - unsigned long drVolBkUp; // date/time of last backup - unsigned short drVSeqNum; // volume backup sequence number - unsigned long drWrCnt; // volume write count - unsigned long drXTClpSiz; // clump size for extents overflow file - unsigned long drCTClpSiz; // clump size for catalog file - unsigned short drNmRtDirs; // #of directories in root directory - unsigned long drFilCnt; // #of files in volume - unsigned long drDirCnt; // #of directories in volume - unsigned long drFndrInfo[8]; // information used by the Finder - unsigned short drVCSize; // size (blocks) of volume cache - unsigned short drVBMCSize; // size (blocks) of volume bitmap cache - unsigned short drCtlCSize; // size (blocks) of common volume cache - unsigned long drXTFlSize; // size (bytes) of extents overflow file - ExtDataRec drXTExtRec; // extent record for extents overflow file - unsigned long drCTFlSize; // size (bytes) of catalog file - ExtDataRec drCTExtRec; // extent record for catalog file + unsigned short drSigWord; // volume signature + unsigned long drCrDate; // date/time of volume creation + unsigned long drLsMod; // date/time of last modification + unsigned short drAtrb; // volume attributes + unsigned short drNmPls; // #of files in root directory + unsigned short drVBMSt; // first block of volume bitmap + unsigned short drAllocPtr; // start of next allocation search + unsigned short drNmAlBlks; // number of allocation blocks in volume + unsigned long drAlBlkSiz; // size (bytes) of allocation blocks + unsigned long drClpSiz; // default clump size + unsigned short drAlBlSt; // first allocation block in volume + unsigned long drNxtCNID; // next unused catalog node ID + unsigned short drFreeBks; // number of unused allocation blocks + unsigned char drVN[28]; // volume name (pascal string) + unsigned long drVolBkUp; // date/time of last backup + unsigned short drVSeqNum; // volume backup sequence number + unsigned long drWrCnt; // volume write count + unsigned long drXTClpSiz; // clump size for extents overflow file + unsigned long drCTClpSiz; // clump size for catalog file + unsigned short drNmRtDirs; // #of directories in root directory + unsigned long drFilCnt; // #of files in volume + unsigned long drDirCnt; // #of directories in volume + unsigned long drFndrInfo[8]; // information used by the Finder + unsigned short drVCSize; // size (blocks) of volume cache + unsigned short drVBMCSize; // size (blocks) of volume bitmap cache + unsigned short drCtlCSize; // size (blocks) of common volume cache + unsigned long drXTFlSize; // size (bytes) of extents overflow file + ExtDataRec drXTExtRec; // extent record for extents overflow file + unsigned long drCTFlSize; // size (bytes) of catalog file + ExtDataRec drCTExtRec; // extent record for catalog file } MasterDirBlock; //}; // namespace DiskImgLib @@ -90,38 +90,38 @@ typedef struct DiskFSHFS::MasterDirBlock { /*static*/ void DiskFSHFS::UnpackMDB(const unsigned char* buf, MasterDirBlock* pMDB) { - pMDB->drSigWord = GetShortBE(&buf[0x00]); - pMDB->drCrDate = GetLongBE(&buf[0x02]); - pMDB->drLsMod = GetLongBE(&buf[0x06]); - pMDB->drAtrb = GetShortBE(&buf[0x0a]); - pMDB->drNmPls = GetShortBE(&buf[0x0c]); - pMDB->drVBMSt = GetShortBE(&buf[0x0e]); - pMDB->drAllocPtr = GetShortBE(&buf[0x10]); - pMDB->drNmAlBlks = GetShortBE(&buf[0x12]); - pMDB->drAlBlkSiz = GetLongBE(&buf[0x14]); - pMDB->drClpSiz = GetLongBE(&buf[0x18]); - pMDB->drAlBlSt = GetShortBE(&buf[0x1c]); - pMDB->drNxtCNID = GetLongBE(&buf[0x1e]); - pMDB->drFreeBks = GetShortBE(&buf[0x22]); - memcpy(pMDB->drVN, &buf[0x24], sizeof(pMDB->drVN)); - pMDB->drVolBkUp = GetLongBE(&buf[0x40]); - pMDB->drVSeqNum = GetShortBE(&buf[0x44]); - pMDB->drWrCnt = GetLongBE(&buf[0x46]); - pMDB->drXTClpSiz = GetLongBE(&buf[0x4a]); - pMDB->drCTClpSiz = GetLongBE(&buf[0x4e]); - pMDB->drNmRtDirs = GetShortBE(&buf[0x52]); - pMDB->drFilCnt = GetLongBE(&buf[0x54]); - pMDB->drDirCnt = GetLongBE(&buf[0x58]); - for (int i = 0; i < (int) NELEM(pMDB->drFndrInfo); i++) - pMDB->drFndrInfo[i] = GetLongBE(&buf[0x5c + i * 4]); - pMDB->drVCSize = GetShortBE(&buf[0x7c]); - pMDB->drVBMCSize = GetShortBE(&buf[0x7e]); - pMDB->drCtlCSize = GetShortBE(&buf[0x80]); - pMDB->drXTFlSize = GetLongBE(&buf[0x82]); - //UnpackExtDataRec(&pMDB->drXTExtRec, &buf[0x86]); // 12 bytes - pMDB->drCTFlSize = GetLongBE(&buf[0x92]); - //UnpackExtDataRec(&pMDB->drXTExtRec, &buf[0x96]); - // next field at 0xa2 + pMDB->drSigWord = GetShortBE(&buf[0x00]); + pMDB->drCrDate = GetLongBE(&buf[0x02]); + pMDB->drLsMod = GetLongBE(&buf[0x06]); + pMDB->drAtrb = GetShortBE(&buf[0x0a]); + pMDB->drNmPls = GetShortBE(&buf[0x0c]); + pMDB->drVBMSt = GetShortBE(&buf[0x0e]); + pMDB->drAllocPtr = GetShortBE(&buf[0x10]); + pMDB->drNmAlBlks = GetShortBE(&buf[0x12]); + pMDB->drAlBlkSiz = GetLongBE(&buf[0x14]); + pMDB->drClpSiz = GetLongBE(&buf[0x18]); + pMDB->drAlBlSt = GetShortBE(&buf[0x1c]); + pMDB->drNxtCNID = GetLongBE(&buf[0x1e]); + pMDB->drFreeBks = GetShortBE(&buf[0x22]); + memcpy(pMDB->drVN, &buf[0x24], sizeof(pMDB->drVN)); + pMDB->drVolBkUp = GetLongBE(&buf[0x40]); + pMDB->drVSeqNum = GetShortBE(&buf[0x44]); + pMDB->drWrCnt = GetLongBE(&buf[0x46]); + pMDB->drXTClpSiz = GetLongBE(&buf[0x4a]); + pMDB->drCTClpSiz = GetLongBE(&buf[0x4e]); + pMDB->drNmRtDirs = GetShortBE(&buf[0x52]); + pMDB->drFilCnt = GetLongBE(&buf[0x54]); + pMDB->drDirCnt = GetLongBE(&buf[0x58]); + for (int i = 0; i < (int) NELEM(pMDB->drFndrInfo); i++) + pMDB->drFndrInfo[i] = GetLongBE(&buf[0x5c + i * 4]); + pMDB->drVCSize = GetShortBE(&buf[0x7c]); + pMDB->drVBMCSize = GetShortBE(&buf[0x7e]); + pMDB->drCtlCSize = GetShortBE(&buf[0x80]); + pMDB->drXTFlSize = GetLongBE(&buf[0x82]); + //UnpackExtDataRec(&pMDB->drXTExtRec, &buf[0x86]); // 12 bytes + pMDB->drCTFlSize = GetLongBE(&buf[0x92]); + //UnpackExtDataRec(&pMDB->drXTExtRec, &buf[0x96]); + // next field at 0xa2 } /* @@ -132,50 +132,50 @@ DiskFSHFS::UnpackMDB(const unsigned char* buf, MasterDirBlock* pMDB) /*static*/ DIError DiskFSHFS::TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder) { - DIError dierr = kDIErrNone; - MasterDirBlock mdb; - unsigned char blkBuf[kBlkSize]; + DIError dierr = kDIErrNone; + MasterDirBlock mdb; + unsigned char blkBuf[kBlkSize]; - dierr = pImg->ReadBlockSwapped(kMasterDirBlock, blkBuf, imageOrder, - DiskImg::kSectorOrderProDOS); - if (dierr != kDIErrNone) - goto bail; + dierr = pImg->ReadBlockSwapped(kMasterDirBlock, blkBuf, imageOrder, + DiskImg::kSectorOrderProDOS); + if (dierr != kDIErrNone) + goto bail; - UnpackMDB(blkBuf, &mdb); + UnpackMDB(blkBuf, &mdb); - if (mdb.drSigWord != kSignature) { - dierr = kDIErrFilesystemNotFound; - goto bail; - } - if ((mdb.drAlBlkSiz & 0x1ff) != 0) { - // allocation block size must be a multiple of 512 - WMSG1(" HFS: found allocation block size = %lu, rejecting\n", - mdb.drAlBlkSiz); - dierr = kDIErrFilesystemNotFound; - goto bail; - } - if (mdb.drVN[0] == 0 || mdb.drVN[0] > kMaxVolumeName) { - WMSG1(" HFS: volume name has len = %d, rejecting\n", mdb.drVN[0]); - dierr = kDIErrFilesystemNotFound; - goto bail; - } + if (mdb.drSigWord != kSignature) { + dierr = kDIErrFilesystemNotFound; + goto bail; + } + if ((mdb.drAlBlkSiz & 0x1ff) != 0) { + // allocation block size must be a multiple of 512 + WMSG1(" HFS: found allocation block size = %lu, rejecting\n", + mdb.drAlBlkSiz); + dierr = kDIErrFilesystemNotFound; + goto bail; + } + if (mdb.drVN[0] == 0 || mdb.drVN[0] > kMaxVolumeName) { + WMSG1(" HFS: volume name has len = %d, rejecting\n", mdb.drVN[0]); + dierr = kDIErrFilesystemNotFound; + goto bail; + } - long minBlocks; - minBlocks = mdb.drNmAlBlks * (mdb.drAlBlkSiz / kBlkSize) + mdb.drAlBlSt + 2; - if (minBlocks > pImg->GetNumBlocks()) { - // We're probably trying to open a 1GB volume as if it were only - // 32MB. Maybe this is a full HFS partition and we're trying to - // see if it's a CFFA image. Whatever the case, we can't do this. - WMSG2("HFS: volume exceeds disk image size (%ld vs %ld)\n", - minBlocks, pImg->GetNumBlocks()); - dierr = kDIErrFilesystemNotFound; - goto bail; - } + long minBlocks; + minBlocks = mdb.drNmAlBlks * (mdb.drAlBlkSiz / kBlkSize) + mdb.drAlBlSt + 2; + if (minBlocks > pImg->GetNumBlocks()) { + // We're probably trying to open a 1GB volume as if it were only + // 32MB. Maybe this is a full HFS partition and we're trying to + // see if it's a CFFA image. Whatever the case, we can't do this. + WMSG2("HFS: volume exceeds disk image size (%ld vs %ld)\n", + minBlocks, pImg->GetNumBlocks()); + dierr = kDIErrFilesystemNotFound; + goto bail; + } - // looks good! + // looks good! bail: - return dierr; + return dierr; } /* @@ -183,30 +183,30 @@ bail: */ /*static*/ DIError DiskFSHFS::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency) + DiskImg::FSFormat* pFormat, FSLeniency leniency) { - //return kDIErrFilesystemNotFound; // DEBUG DEBUG DEBUG + //return kDIErrFilesystemNotFound; // DEBUG DEBUG DEBUG - /* must be block format, should be at least 720K */ - if (!pImg->GetHasBlocks() || pImg->GetNumBlocks() < kExpectedMinBlocks) - return kDIErrFilesystemNotFound; + /* must be block format, should be at least 720K */ + if (!pImg->GetHasBlocks() || pImg->GetNumBlocks() < kExpectedMinBlocks) + return kDIErrFilesystemNotFound; - DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; - - DiskImg::GetSectorOrderArray(ordering, *pOrder); + DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; + + DiskImg::GetSectorOrderArray(ordering, *pOrder); - for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { - if (ordering[i] == DiskImg::kSectorOrderUnknown) - continue; - if (TestImage(pImg, ordering[i]) == kDIErrNone) { - *pOrder = ordering[i]; - *pFormat = DiskImg::kFormatMacHFS; - return kDIErrNone; - } - } + for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { + if (ordering[i] == DiskImg::kSectorOrderUnknown) + continue; + if (TestImage(pImg, ordering[i]) == kDIErrNone) { + *pOrder = ordering[i]; + *pFormat = DiskImg::kFormatMacHFS; + return kDIErrNone; + } + } - WMSG0(" HFS didn't find valid FS\n"); - return kDIErrFilesystemNotFound; + WMSG0(" HFS didn't find valid FS\n"); + return kDIErrFilesystemNotFound; } @@ -216,104 +216,104 @@ DiskFSHFS::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DIError DiskFSHFS::LoadVolHeader(void) { - DIError dierr = kDIErrNone; - MasterDirBlock mdb; - unsigned char blkBuf[kBlkSize]; + DIError dierr = kDIErrNone; + MasterDirBlock mdb; + unsigned char blkBuf[kBlkSize]; - if (fLocalTimeOffset == -1) { - struct tm* ptm; - struct tm tmWhen; - time_t when; - int isDst; + if (fLocalTimeOffset == -1) { + struct tm* ptm; + struct tm tmWhen; + time_t when; + int isDst; - when = time(nil); - isDst = localtime(&when)->tm_isdst; + when = time(nil); + isDst = localtime(&when)->tm_isdst; - ptm = gmtime(&when); - if (ptm != nil) { - tmWhen = *ptm; // make a copy -- static buffers in time functions - tmWhen.tm_isdst = isDst; + ptm = gmtime(&when); + if (ptm != nil) { + tmWhen = *ptm; // make a copy -- static buffers in time functions + tmWhen.tm_isdst = isDst; - fLocalTimeOffset = when - mktime(&tmWhen); - } else - fLocalTimeOffset = 0; + fLocalTimeOffset = when - mktime(&tmWhen); + } else + fLocalTimeOffset = 0; - WMSG1(" HFS computed local time offset = %.3f hours\n", - fLocalTimeOffset / 3600.0); - } + WMSG1(" HFS computed local time offset = %.3f hours\n", + fLocalTimeOffset / 3600.0); + } - dierr = fpImg->ReadBlock(kMasterDirBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpImg->ReadBlock(kMasterDirBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; - UnpackMDB(blkBuf, &mdb); + UnpackMDB(blkBuf, &mdb); - /* - * The minimum size of the volume is "number of allocation blocks" plus - * "first allocation block" (to avoid the OS overhead) plus 2 (because - * there's a backup copy of the MDB in the next-to-last block, and - * nothing at all in the very last block). + /* + * The minimum size of the volume is "number of allocation blocks" plus + * "first allocation block" (to avoid the OS overhead) plus 2 (because + * there's a backup copy of the MDB in the next-to-last block, and + * nothing at all in the very last block). * * This isn't the total size, because on larger volumes there can be * some padding between the last usable block and the backup MDB. The * only way to find the MDB is to take the DiskImg's block size and * subtract 2. - */ - assert((mdb.drAlBlkSiz % kBlkSize) == 0); - fNumAllocationBlocks = mdb.drNmAlBlks; - fAllocationBlockSize = mdb.drAlBlkSiz; + */ + assert((mdb.drAlBlkSiz % kBlkSize) == 0); + fNumAllocationBlocks = mdb.drNmAlBlks; + fAllocationBlockSize = mdb.drAlBlkSiz; fTotalBlocks = fpImg->GetNumBlocks(); unsigned long minBlocks; - minBlocks = mdb.drNmAlBlks * (mdb.drAlBlkSiz / kBlkSize) + mdb.drAlBlSt + 2; + minBlocks = mdb.drNmAlBlks * (mdb.drAlBlkSiz / kBlkSize) + mdb.drAlBlSt + 2; assert(fTotalBlocks >= minBlocks); // verified during fs tests - int volNameLen; - volNameLen = mdb.drVN[0]; - if (volNameLen > kMaxVolumeName) { - assert(false); // should've been trapped earlier - volNameLen = kMaxVolumeName; - } - memcpy(fVolumeName, &mdb.drVN[1], volNameLen); - fVolumeName[volNameLen] = '\0'; - SetVolumeID(); + int volNameLen; + volNameLen = mdb.drVN[0]; + if (volNameLen > kMaxVolumeName) { + assert(false); // should've been trapped earlier + volNameLen = kMaxVolumeName; + } + memcpy(fVolumeName, &mdb.drVN[1], volNameLen); + fVolumeName[volNameLen] = '\0'; + SetVolumeID(); - fNumFiles = mdb.drFilCnt; - fNumDirectories = mdb.drDirCnt; - fCreatedDateTime = mdb.drCrDate; - fModifiedDateTime = mdb.drLsMod; + fNumFiles = mdb.drFilCnt; + fNumDirectories = mdb.drDirCnt; + fCreatedDateTime = mdb.drCrDate; + fModifiedDateTime = mdb.drLsMod; - /* - * Create a "magic" directory entry for the volume directory. This + /* + * Create a "magic" directory entry for the volume directory. This * must come first in the file list. - */ - A2FileHFS* pFile; - pFile = new A2FileHFS(this); - if (pFile == nil) { - dierr = kDIErrMalloc; - goto bail; - } + */ + A2FileHFS* pFile; + pFile = new A2FileHFS(this); + if (pFile == nil) { + dierr = kDIErrMalloc; + goto bail; + } pFile->fIsDir = true; pFile->fIsVolumeDir = true; pFile->fType = 0; pFile->fCreator = 0; - strcpy(pFile->fFileName, fVolumeName); // vol names are shorter than - pFile->SetPathName(":", fVolumeName); // filenames, so it fits + strcpy(pFile->fFileName, fVolumeName); // vol names are shorter than + pFile->SetPathName(":", fVolumeName); // filenames, so it fits pFile->fDataLength = 0; pFile->fRsrcLength = -1; - pFile->fCreateWhen = - (time_t) (fCreatedDateTime - kDateTimeOffset) - fLocalTimeOffset; - pFile->fModWhen = - (time_t) (fModifiedDateTime - kDateTimeOffset) - fLocalTimeOffset; - pFile->fAccess = DiskFS::kFileAccessUnlocked; + pFile->fCreateWhen = + (time_t) (fCreatedDateTime - kDateTimeOffset) - fLocalTimeOffset; + pFile->fModWhen = + (time_t) (fModifiedDateTime - kDateTimeOffset) - fLocalTimeOffset; + pFile->fAccess = DiskFS::kFileAccessUnlocked; - //WMSG2("GOT *** '%s' '%s'\n", pFile->fFileName, pFile->fPathName); + //WMSG2("GOT *** '%s' '%s'\n", pFile->fFileName, pFile->fPathName); - AddFileToList(pFile); + AddFileToList(pFile); bail: - return dierr; + return dierr; } /* @@ -322,8 +322,8 @@ bail: void DiskFSHFS::SetVolumeID(void) { - strcpy(fVolumeID, "HFS "); - strcat(fVolumeID, fVolumeName); + strcpy(fVolumeID, "HFS "); + strcat(fVolumeID, fVolumeName); } /* @@ -332,17 +332,17 @@ DiskFSHFS::SetVolumeID(void) void DiskFSHFS::SetVolumeUsageMap(void) { - VolumeUsage::ChunkState cstate; - long block; + VolumeUsage::ChunkState cstate; + long block; - fVolumeUsage.Create(fpImg->GetNumBlocks()); + fVolumeUsage.Create(fpImg->GetNumBlocks()); - cstate.isUsed = true; - cstate.isMarkedUsed = true; - cstate.purpose = VolumeUsage::kChunkPurposeUnknown; + cstate.isUsed = true; + cstate.isMarkedUsed = true; + cstate.purpose = VolumeUsage::kChunkPurposeUnknown; - for (block = fTotalBlocks-1; block >= 0; block--) - fVolumeUsage.SetChunkState(block, &cstate); + for (block = fTotalBlocks-1; block >= 0; block--) + fVolumeUsage.SetChunkState(block, &cstate); } @@ -352,18 +352,18 @@ DiskFSHFS::SetVolumeUsageMap(void) void DiskFSHFS::DumpVolHeader(void) { - WMSG0("HFS volume header read:\n"); - WMSG1(" volume name = '%s'\n", fVolumeName); - WMSG4(" total blocks = %ld (allocSize=%ld [x%lu], numAllocs=%lu)\n", - fTotalBlocks, fAllocationBlockSize, fAllocationBlockSize / kBlkSize, - fNumAllocationBlocks); - WMSG2(" num directories=%ld, num files=%ld\n", - fNumDirectories, fNumFiles); - time_t when; - when = (time_t) (fCreatedDateTime - kDateTimeOffset - fLocalTimeOffset); - WMSG2(" cre date=0x%08lx %.24s\n", fCreatedDateTime, ctime(&when)); - when = (time_t) (fModifiedDateTime - kDateTimeOffset - fLocalTimeOffset); - WMSG2(" mod date=0x%08lx %.24s\n", fModifiedDateTime, ctime(&when)); + WMSG0("HFS volume header read:\n"); + WMSG1(" volume name = '%s'\n", fVolumeName); + WMSG4(" total blocks = %ld (allocSize=%ld [x%lu], numAllocs=%lu)\n", + fTotalBlocks, fAllocationBlockSize, fAllocationBlockSize / kBlkSize, + fNumAllocationBlocks); + WMSG2(" num directories=%ld, num files=%ld\n", + fNumDirectories, fNumFiles); + time_t when; + when = (time_t) (fCreatedDateTime - kDateTimeOffset - fLocalTimeOffset); + WMSG2(" cre date=0x%08lx %.24s\n", fCreatedDateTime, ctime(&when)); + when = (time_t) (fModifiedDateTime - kDateTimeOffset - fLocalTimeOffset); + WMSG2(" mod date=0x%08lx %.24s\n", fModifiedDateTime, ctime(&when)); } @@ -379,35 +379,35 @@ DiskFSHFS::DumpVolHeader(void) DIError DiskFSHFS::Initialize(InitMode initMode) { - DIError dierr = kDIErrNone; - char msg[kMaxVolumeName + 32]; + DIError dierr = kDIErrNone; + char msg[kMaxVolumeName + 32]; - dierr = LoadVolHeader(); - if (dierr != kDIErrNone) - goto bail; - DumpVolHeader(); + dierr = LoadVolHeader(); + if (dierr != kDIErrNone) + goto bail; + DumpVolHeader(); - if (initMode == kInitHeaderOnly) { - WMSG0(" HFS - headerOnly set, skipping file load\n"); - goto bail; - } + if (initMode == kInitHeaderOnly) { + WMSG0(" HFS - headerOnly set, skipping file load\n"); + goto bail; + } - sprintf(msg, "Scanning %s", fVolumeName); - if (!fpImg->UpdateScanProgress(msg)) { - WMSG0(" HFS cancelled by user\n"); - dierr = kDIErrCancelled; - goto bail; - } + sprintf(msg, "Scanning %s", fVolumeName); + if (!fpImg->UpdateScanProgress(msg)) { + WMSG0(" HFS cancelled by user\n"); + dierr = kDIErrCancelled; + goto bail; + } - /* - * Open the volume with libhfs. We used to set HFS_OPT_NOCACHE to avoid - * consistency problems and reduce the risk of disk corruption should - * CiderPress fail, but it turns out libhfs doesn't write the volume - * bitmap or master dir block unless explicitly flushed anyway. Since - * the caching helps us a lot when just reading -- 4 seconds vs. 9 for - * a CD-ROM over gigabit Ethernet -- we leave it on, and explicitly - * flush every time we make a change. - */ + /* + * Open the volume with libhfs. We used to set HFS_OPT_NOCACHE to avoid + * consistency problems and reduce the risk of disk corruption should + * CiderPress fail, but it turns out libhfs doesn't write the volume + * bitmap or master dir block unless explicitly flushed anyway. Since + * the caching helps us a lot when just reading -- 4 seconds vs. 9 for + * a CD-ROM over gigabit Ethernet -- we leave it on, and explicitly + * flush every time we make a change. + */ fHfsVol = hfs_callback_open(LibHFSCB, this, /*HFS_OPT_NOCACHE |*/ (fpImg->GetReadOnly() ? HFS_MODE_RDONLY : HFS_MODE_RDWR)); if (fHfsVol == nil) { @@ -415,24 +415,24 @@ DiskFSHFS::Initialize(InitMode initMode) return kDIErrGeneric; } - /* volume dir is guaranteed to come first; if not, we need a lookup func */ - A2FileHFS* pVolumeDir; - pVolumeDir = (A2FileHFS*) GetNextFile(nil); + /* volume dir is guaranteed to come first; if not, we need a lookup func */ + A2FileHFS* pVolumeDir; + pVolumeDir = (A2FileHFS*) GetNextFile(nil); dierr = RecursiveDirAdd(pVolumeDir, ":", 0); if (dierr != kDIErrNone) goto bail; - SetVolumeUsageMap(); + SetVolumeUsageMap(); - /* - * Make sure there's nothing lingering. libhfs will fiddle around with - * the MDB if it looks like the volume wasn't unmounted cleanly last time. - */ - hfs_flush(fHfsVol); + /* + * Make sure there's nothing lingering. libhfs will fiddle around with + * the MDB if it looks like the volume wasn't unmounted cleanly last time. + */ + hfs_flush(fHfsVol); bail: - return dierr; + return dierr; } /* @@ -453,7 +453,7 @@ DiskFSHFS::LibHFSCB(void* vThis, int op, unsigned long arg1, void* arg2) switch (op) { case HFS_CB_VOLSIZE: - //WMSG1(" HFSCB vol size = %ld blocks\n", pThis->fTotalBlocks); + //WMSG1(" HFSCB vol size = %ld blocks\n", pThis->fTotalBlocks); result = pThis->fTotalBlocks; break; case HFS_CB_READ: // arg1=block, arg2=buffer @@ -468,7 +468,7 @@ DiskFSHFS::LibHFSCB(void* vThis, int op, unsigned long arg1, void* arg2) } break; case HFS_CB_WRITE: - WMSG1(" HFSCB write block %lu\n", arg1); + WMSG1(" HFSCB write block %lu\n", arg1); if (arg1 < pThis->fTotalBlocks && arg2 != nil) { DIError err = pThis->fpImg->WriteBlock(arg1, arg2); if (err == kDIErrNone) @@ -480,7 +480,7 @@ DiskFSHFS::LibHFSCB(void* vThis, int op, unsigned long arg1, void* arg2) break; case HFS_CB_SEEK: // arg1=block, arg2=unused /* just verify that the seek is legal */ - //WMSG1(" HFSCB seek block %lu\n", arg1); + //WMSG1(" HFSCB seek block %lu\n", arg1); if (arg1 < pThis->fTotalBlocks) result = arg1; break; @@ -498,19 +498,19 @@ DiskFSHFS::LibHFSCB(void* vThis, int op, unsigned long arg1, void* arg2) */ DIError DiskFSHFS::GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const + int* pUnitSize) const { - assert(fHfsVol != nil); + assert(fHfsVol != nil); - hfsvolent volEnt; - if (hfs_vstat(fHfsVol, &volEnt) != 0) - return kDIErrGeneric; + hfsvolent volEnt; + if (hfs_vstat(fHfsVol, &volEnt) != 0) + return kDIErrGeneric; - *pTotalUnits = volEnt.totbytes / 512; - *pFreeUnits = volEnt.freebytes / 512; - *pUnitSize = 512; + *pTotalUnits = volEnt.totbytes / 512; + *pFreeUnits = volEnt.freebytes / 512; + *pUnitSize = 512; - return kDIErrNone; + return kDIErrNone; } /* @@ -531,7 +531,7 @@ DiskFSHFS::RecursiveDirAdd(A2File* pParent, const char* basePath, int depth) goto bail; } - //WMSG1(" HFS RecursiveDirAdd '%s'\n", basePath); + //WMSG1(" HFS RecursiveDirAdd '%s'\n", basePath); dir = hfs_opendir(fHfsVol, basePath); if (dir == nil) { printf(" HFS unable to open dir '%s'\n", basePath); @@ -554,21 +554,21 @@ DiskFSHFS::RecursiveDirAdd(A2File* pParent, const char* basePath, int depth) pathBuf[nameOffset] = '\0'; // not needed while (hfs_readdir(dir, &dirEntry) != -1) { - A2FileHFS* pFile; + A2FileHFS* pFile; pFile = new A2FileHFS(this); - pFile->InitEntry(&dirEntry); + pFile->InitEntry(&dirEntry); - pFile->SetPathName(basePath, pFile->fFileName); - pFile->SetParent(pParent); + pFile->SetPathName(basePath, pFile->fFileName); + pFile->SetParent(pParent); AddFileToList(pFile); - if (!fpImg->UpdateScanProgress(nil)) { - WMSG0(" HFS cancelled by user\n"); - dierr = kDIErrCancelled; - goto bail; - } + if (!fpImg->UpdateScanProgress(nil)) { + WMSG0(" HFS cancelled by user\n"); + dierr = kDIErrCancelled; + goto bail; + } if (dirEntry.flags & HFS_ISDIR) { strcpy(pathBuf + nameOffset, dirEntry.name); @@ -579,7 +579,7 @@ DiskFSHFS::RecursiveDirAdd(A2File* pParent, const char* basePath, int depth) } bail: - delete[] pathBuf; + delete[] pathBuf; return dierr; } @@ -596,19 +596,19 @@ void A2FileHFS::InitEntry(const hfsdirent* dirEntry) memcpy(fFileName, dirEntry->name, A2FileHFS::kMaxFileName+1); fFileName[A2FileHFS::kMaxFileName] = '\0'; // make sure - if (dirEntry->flags & HFS_ISLOCKED) - fAccess = DiskFS::kFileAccessLocked; - else - fAccess = DiskFS::kFileAccessUnlocked; - if (dirEntry->fdflags & HFS_FNDR_ISINVISIBLE) - fAccess |= A2FileProDOS::kAccessInvisible; + if (dirEntry->flags & HFS_ISLOCKED) + fAccess = DiskFS::kFileAccessLocked; + else + fAccess = DiskFS::kFileAccessUnlocked; + if (dirEntry->fdflags & HFS_FNDR_ISINVISIBLE) + fAccess |= A2FileProDOS::kAccessInvisible; if (dirEntry->flags & HFS_ISDIR) { fIsDir = true; fType = fCreator = 0; fDataLength = 0; fRsrcLength = -1; - } else { + } else { unsigned char* pType; fIsDir = false; @@ -623,19 +623,19 @@ void A2FileHFS::InitEntry(const hfsdirent* dirEntry) fRsrcLength = dirEntry->u.file.rsize; /* - * Resource fork must be at least 512 bytes for Finder, so if - * it has zero length then the file must not have one. - */ + * Resource fork must be at least 512 bytes for Finder, so if + * it has zero length then the file must not have one. + */ if (fRsrcLength == 0) fRsrcLength = -1; - } + } - /* - * Create/modified dates (we ignore the "last backup" date). The - * hfslib functions convert to time_t for us. - */ - fCreateWhen = dirEntry->crdate; - fModWhen = dirEntry->mddate; + /* + * Create/modified dates (we ignore the "last backup" date). The + * hfslib functions convert to time_t for us. + */ + fCreateWhen = dirEntry->crdate; + fModWhen = dirEntry->mddate; } /* @@ -644,20 +644,20 @@ void A2FileHFS::InitEntry(const hfsdirent* dirEntry) /*static*/ bool DiskFSHFS::IsValidVolumeName(const char* name) { - if (name == nil) - return false; + if (name == nil) + return false; - int len = strlen(name); - if (len < 1 || len > kMaxVolumeName) - return false; + int len = strlen(name); + if (len < 1 || len > kMaxVolumeName) + return false; - while (*name != '\0') { - if (*name == A2FileHFS::kFssep) - return false; - name++; - } + while (*name != '\0') { + if (*name == A2FileHFS::kFssep) + return false; + name++; + } - return true; + return true; } /* @@ -666,20 +666,20 @@ DiskFSHFS::IsValidVolumeName(const char* name) /*static*/ bool DiskFSHFS::IsValidFileName(const char* name) { - if (name == nil) - return false; + if (name == nil) + return false; - int len = strlen(name); - if (len < 1 || len > A2FileHFS::kMaxFileName) - return false; + int len = strlen(name); + if (len < 1 || len > A2FileHFS::kMaxFileName) + return false; - while (*name != '\0') { - if (*name == A2FileHFS::kFssep) - return false; - name++; - } + while (*name != '\0') { + if (*name == A2FileHFS::kFssep) + return false; + name++; + } - return true; + return true; } /* @@ -688,28 +688,28 @@ DiskFSHFS::IsValidFileName(const char* name) DIError DiskFSHFS::Format(DiskImg* pDiskImg, const char* volName) { - assert(strlen(volName) > 0 && strlen(volName) <= kMaxVolumeName); + assert(strlen(volName) > 0 && strlen(volName) <= kMaxVolumeName); - if (!IsValidVolumeName(volName)) - return kDIErrInvalidArg; + if (!IsValidVolumeName(volName)) + return kDIErrInvalidArg; - /* set fpImg so calls that rely on it will work; we un-set it later */ - assert(fpImg == nil); - SetDiskImg(pDiskImg); + /* set fpImg so calls that rely on it will work; we un-set it later */ + assert(fpImg == nil); + SetDiskImg(pDiskImg); - /* need this for callback function */ - fTotalBlocks = fpImg->GetNumBlocks(); + /* need this for callback function */ + fTotalBlocks = fpImg->GetNumBlocks(); - // need HFS_OPT_2048 for CD-ROM? - if (hfs_callback_format(LibHFSCB, this, 0, volName) != 0) { - WMSG1("hfs_callback_format failed (%s)\n", hfs_error); - return kDIErrGeneric; - } + // need HFS_OPT_2048 for CD-ROM? + if (hfs_callback_format(LibHFSCB, this, 0, volName) != 0) { + WMSG1("hfs_callback_format failed (%s)\n", hfs_error); + return kDIErrGeneric; + } - // no need to flush; HFS volume is closed + // no need to flush; HFS volume is closed - SetDiskImg(nil); // shouldn't really be set by us - return kDIErrNone; + SetDiskImg(nil); // shouldn't really be set by us + return kDIErrNone; } @@ -723,34 +723,34 @@ DiskFSHFS::Format(DiskImg* pDiskImg, const char* volName) */ DIError DiskFSHFS::NormalizePath(const char* path, char fssep, - char* normalizedBuf, int* pNormalizedBufLen) + char* normalizedBuf, int* pNormalizedBufLen) { - DIError dierr = kDIErrNone; - char* normalizedPath = nil; - int len; + DIError dierr = kDIErrNone; + char* normalizedPath = nil; + int len; - assert(pNormalizedBufLen != nil); - assert(normalizedBuf != nil || *pNormalizedBufLen == 0); + assert(pNormalizedBufLen != nil); + assert(normalizedBuf != nil || *pNormalizedBufLen == 0); - dierr = DoNormalizePath(path, fssep, &normalizedPath); - if (dierr != kDIErrNone) - goto bail; + dierr = DoNormalizePath(path, fssep, &normalizedPath); + if (dierr != kDIErrNone) + goto bail; - assert(normalizedPath != nil); - len = strlen(normalizedPath); - if (normalizedBuf == nil || *pNormalizedBufLen <= len) { - /* too short */ - dierr = kDIErrDataOverrun; - } else { - /* fits */ - strcpy(normalizedBuf, normalizedPath); - } + assert(normalizedPath != nil); + len = strlen(normalizedPath); + if (normalizedBuf == nil || *pNormalizedBufLen <= len) { + /* too short */ + dierr = kDIErrDataOverrun; + } else { + /* fits */ + strcpy(normalizedBuf, normalizedPath); + } - *pNormalizedBufLen = len+1; // alloc room for the '\0' + *pNormalizedBufLen = len+1; // alloc room for the '\0' bail: - delete[] normalizedPath; - return dierr; + delete[] normalizedPath; + return dierr; } /* @@ -762,107 +762,107 @@ bail: */ DIError DiskFSHFS::DoNormalizePath(const char* path, char fssep, - char** pNormalizedPath) + char** pNormalizedPath) { - DIError dierr = kDIErrNone; - char* workBuf = nil; - char* partBuf = nil; - char* outputBuf = nil; - char* start; - char* end; - char* outPtr; + DIError dierr = kDIErrNone; + char* workBuf = nil; + char* partBuf = nil; + char* outputBuf = nil; + char* start; + char* end; + char* outPtr; - assert(path != nil); - workBuf = new char[strlen(path)+1]; - partBuf = new char[strlen(path)+1 +1]; // need +1 for prepending letter - outputBuf = new char[strlen(path) * 2]; - if (workBuf == nil || partBuf == nil || outputBuf == nil) { - dierr = kDIErrMalloc; - goto bail; - } + assert(path != nil); + workBuf = new char[strlen(path)+1]; + partBuf = new char[strlen(path)+1 +1]; // need +1 for prepending letter + outputBuf = new char[strlen(path) * 2]; + if (workBuf == nil || partBuf == nil || outputBuf == nil) { + dierr = kDIErrMalloc; + goto bail; + } - strcpy(workBuf, path); - outputBuf[0] = '\0'; + strcpy(workBuf, path); + outputBuf[0] = '\0'; - outPtr = outputBuf; - start = workBuf; - while (*start != '\0') { - //char* origStart = start; // need for debug msg - int partIdx; + outPtr = outputBuf; + start = workBuf; + while (*start != '\0') { + //char* origStart = start; // need for debug msg + int partIdx; - if (fssep == '\0') { - end = nil; - } else { - end = strchr(start, fssep); - if (end != nil) - *end = '\0'; - } - partIdx = 0; + if (fssep == '\0') { + end = nil; + } else { + end = strchr(start, fssep); + if (end != nil) + *end = '\0'; + } + partIdx = 0; - /* - * Copy, converting colons to underscores. We should strip out any - * illegal characters here, but there's not much in HFS that's - * considered illegal. - */ - while (*start != '\0') { - if (*start == A2FileHFS::kFssep) - partBuf[partIdx++] = '_'; - else - partBuf[partIdx++] = *start; - start++; - } + /* + * Copy, converting colons to underscores. We should strip out any + * illegal characters here, but there's not much in HFS that's + * considered illegal. + */ + while (*start != '\0') { + if (*start == A2FileHFS::kFssep) + partBuf[partIdx++] = '_'; + else + partBuf[partIdx++] = *start; + start++; + } - /* - * Truncate at 31 chars, preserving anything that looks like a - * filename extension. "partIdx" represents the length of the - * string at this point. "partBuf" holds the string, which we - * want to null-terminate before proceeding. - * - * Try to keep the filename extension, if any. - */ - partBuf[partIdx] = '\0'; - if (partIdx > A2FileHFS::kMaxFileName) { - const char* pDot = strrchr(partBuf, '.'); - //int DEBUGDOTLEN = pDot - partBuf; - if (pDot != nil && partIdx - (pDot-partBuf) <= kMaxExtensionLen) { - int dotLen = partIdx - (pDot-partBuf); - memmove(partBuf + (A2FileProDOS::kMaxFileName - dotLen), - pDot, dotLen); // don't use memcpy, move might overlap - } - partIdx = A2FileProDOS::kMaxFileName; - } - partBuf[partIdx] = '\0'; + /* + * Truncate at 31 chars, preserving anything that looks like a + * filename extension. "partIdx" represents the length of the + * string at this point. "partBuf" holds the string, which we + * want to null-terminate before proceeding. + * + * Try to keep the filename extension, if any. + */ + partBuf[partIdx] = '\0'; + if (partIdx > A2FileHFS::kMaxFileName) { + const char* pDot = strrchr(partBuf, '.'); + //int DEBUGDOTLEN = pDot - partBuf; + if (pDot != nil && partIdx - (pDot-partBuf) <= kMaxExtensionLen) { + int dotLen = partIdx - (pDot-partBuf); + memmove(partBuf + (A2FileProDOS::kMaxFileName - dotLen), + pDot, dotLen); // don't use memcpy, move might overlap + } + partIdx = A2FileProDOS::kMaxFileName; + } + partBuf[partIdx] = '\0'; - //WMSG2(" HFS Converted component '%s' to '%s'\n", - // origStart, partBuf); + //WMSG2(" HFS Converted component '%s' to '%s'\n", + // origStart, partBuf); - if (outPtr != outputBuf) - *outPtr++ = A2FileHFS::kFssep; - strcpy(outPtr, partBuf); - outPtr += partIdx; + if (outPtr != outputBuf) + *outPtr++ = A2FileHFS::kFssep; + strcpy(outPtr, partBuf); + outPtr += partIdx; - /* - * Continue with next segment. - */ - if (end == nil) - break; - start = end+1; - } + /* + * Continue with next segment. + */ + if (end == nil) + break; + start = end+1; + } - *outPtr = '\0'; + *outPtr = '\0'; - WMSG3(" HFS Converted path '%s' to '%s' (fssep='%c')\n", - path, outputBuf, fssep); - assert(*outputBuf != '\0'); + WMSG3(" HFS Converted path '%s' to '%s' (fssep='%c')\n", + path, outputBuf, fssep); + assert(*outputBuf != '\0'); - *pNormalizedPath = outputBuf; - outputBuf = nil; + *pNormalizedPath = outputBuf; + outputBuf = nil; bail: - delete[] workBuf; - delete[] partBuf; - delete[] outputBuf; - return dierr; + delete[] workBuf; + delete[] partBuf; + delete[] outputBuf; + return dierr; } /* @@ -879,21 +879,21 @@ bail: /*static*/ int DiskFSHFS::CompareMacFileNames(const char* sstr1, const char* sstr2) { - const unsigned char* str1 = (const unsigned char*) sstr1; - const unsigned char* str2 = (const unsigned char*) sstr2; - int diff; + const unsigned char* str1 = (const unsigned char*) sstr1; + const unsigned char* str2 = (const unsigned char*) sstr2; + int diff; - while (*str1 && *str2) { - diff = hfs_charorder[*str1] - hfs_charorder[*str2]; + while (*str1 && *str2) { + diff = hfs_charorder[*str1] - hfs_charorder[*str2]; - if (diff != 0) - return diff; + if (diff != 0) + return diff; - str1++; - str2++; - } + str1++; + str2++; + } - return *str1 - *str2; + return *str1 - *str2; } /* @@ -909,79 +909,79 @@ DiskFSHFS::CompareMacFileNames(const char* sstr1, const char* sstr2) DIError DiskFSHFS::MakeFileNameUnique(const char* pathName, char** pUniqueName) { - A2File* pFile; - const int kMaxExtra = 3; - const int kMaxDigits = 999; - char* uniqueName; - char* fileName; // points inside uniqueName + A2File* pFile; + const int kMaxExtra = 3; + const int kMaxDigits = 999; + char* uniqueName; + char* fileName; // points inside uniqueName - assert(pathName != nil); - assert(pathName[0] == A2FileHFS::kFssep); + assert(pathName != nil); + assert(pathName[0] == A2FileHFS::kFssep); - /* see if it exists */ - pFile = GetFileByName(pathName+1); - if (pFile == nil) { - *pUniqueName = nil; - return kDIErrNone; - } + /* see if it exists */ + pFile = GetFileByName(pathName+1); + if (pFile == nil) { + *pUniqueName = nil; + return kDIErrNone; + } - /* make a copy we can chew on */ - uniqueName = new char[strlen(pathName) + kMaxExtra +1]; - strcpy(uniqueName, pathName); + /* make a copy we can chew on */ + uniqueName = new char[strlen(pathName) + kMaxExtra +1]; + strcpy(uniqueName, pathName); - fileName = strrchr(uniqueName, A2FileHFS::kFssep); - assert(fileName != nil); - fileName++; + fileName = strrchr(uniqueName, A2FileHFS::kFssep); + assert(fileName != nil); + fileName++; - int nameLen = strlen(fileName); - int dotOffset=0, dotLen=0; - char dotBuf[kMaxExtensionLen+1]; + int nameLen = strlen(fileName); + int dotOffset=0, dotLen=0; + char dotBuf[kMaxExtensionLen+1]; - /* ensure the result will be null-terminated */ - memset(fileName + nameLen, 0, kMaxExtra+1); + /* ensure the result will be null-terminated */ + memset(fileName + nameLen, 0, kMaxExtra+1); - /* - * If this has what looks like a filename extension, grab it. We want - * to preserve ".gif", ".c", etc., since the filetypes don't necessarily - * do everything we need. - */ - const char* cp = strrchr(fileName, '.'); - if (cp != nil) { - int tmpOffset = cp - fileName; - if (tmpOffset > 0 && nameLen - tmpOffset <= kMaxExtensionLen) { - WMSG1(" HFS (keeping extension '%s')\n", cp); - assert(strlen(cp) <= kMaxExtensionLen); - strcpy(dotBuf, cp); - dotOffset = tmpOffset; - dotLen = nameLen - dotOffset; - } - } + /* + * If this has what looks like a filename extension, grab it. We want + * to preserve ".gif", ".c", etc., since the filetypes don't necessarily + * do everything we need. + */ + const char* cp = strrchr(fileName, '.'); + if (cp != nil) { + int tmpOffset = cp - fileName; + if (tmpOffset > 0 && nameLen - tmpOffset <= kMaxExtensionLen) { + WMSG1(" HFS (keeping extension '%s')\n", cp); + assert(strlen(cp) <= kMaxExtensionLen); + strcpy(dotBuf, cp); + dotOffset = tmpOffset; + dotLen = nameLen - dotOffset; + } + } - int digits = 0; - int digitLen; - int copyOffset; - char digitBuf[kMaxExtra+1]; - do { - if (digits == kMaxDigits) - return kDIErrFileExists; - digits++; + int digits = 0; + int digitLen; + int copyOffset; + char digitBuf[kMaxExtra+1]; + do { + if (digits == kMaxDigits) + return kDIErrFileExists; + digits++; - /* not the most efficient way to do this, but it'll do */ - sprintf(digitBuf, "%d", digits); - digitLen = strlen(digitBuf); - if (nameLen + digitLen > A2FileHFS::kMaxFileName) - copyOffset = A2FileHFS::kMaxFileName - dotLen - digitLen; - else - copyOffset = nameLen - dotLen; - memcpy(fileName + copyOffset, digitBuf, digitLen); - if (dotLen != 0) - memcpy(fileName + copyOffset + digitLen, dotBuf, dotLen); - } while (GetFileByName(uniqueName+1) != nil); + /* not the most efficient way to do this, but it'll do */ + sprintf(digitBuf, "%d", digits); + digitLen = strlen(digitBuf); + if (nameLen + digitLen > A2FileHFS::kMaxFileName) + copyOffset = A2FileHFS::kMaxFileName - dotLen - digitLen; + else + copyOffset = nameLen - dotLen; + memcpy(fileName + copyOffset, digitBuf, digitLen); + if (dotLen != 0) + memcpy(fileName + copyOffset + digitLen, dotBuf, dotLen); + } while (GetFileByName(uniqueName+1) != nil); - WMSG1(" HFS converted to unique name: %s\n", uniqueName); + WMSG1(" HFS converted to unique name: %s\n", uniqueName); - *pUniqueName = uniqueName; - return kDIErrNone; + *pUniqueName = uniqueName; + return kDIErrNone; } @@ -996,320 +996,320 @@ DiskFSHFS::MakeFileNameUnique(const char* pathName, char** pUniqueName) DIError DiskFSHFS::CreateFile(const CreateParms* pParms, A2File** ppNewFile) { - DIError dierr = kDIErrNone; - char typeStr[5], creatorStr[5]; - char* normalizedPath = nil; - char* basePath = nil; - char* fileName = nil; - char* fullPath = nil; - A2FileHFS* pSubdir = nil; - A2FileHFS* pNewFile = nil; - hfsfile* pHfsFile = nil; - const bool createUnique = (GetParameter(kParm_CreateUnique) != 0); + DIError dierr = kDIErrNone; + char typeStr[5], creatorStr[5]; + char* normalizedPath = nil; + char* basePath = nil; + char* fileName = nil; + char* fullPath = nil; + A2FileHFS* pSubdir = nil; + A2FileHFS* pNewFile = nil; + hfsfile* pHfsFile = nil; + const bool createUnique = (GetParameter(kParm_CreateUnique) != 0); - assert(fHfsVol != nil); + assert(fHfsVol != nil); - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; - assert(pParms != nil); - assert(pParms->pathName != nil); - assert(pParms->storageType == A2FileProDOS::kStorageSeedling || - pParms->storageType == A2FileProDOS::kStorageExtended || - pParms->storageType == A2FileProDOS::kStorageDirectory); - // kStorageVolumeDirHeader not allowed -- that's created by Format - WMSG1(" HFS ---v--- CreateFile '%s'\n", pParms->pathName); + assert(pParms != nil); + assert(pParms->pathName != nil); + assert(pParms->storageType == A2FileProDOS::kStorageSeedling || + pParms->storageType == A2FileProDOS::kStorageExtended || + pParms->storageType == A2FileProDOS::kStorageDirectory); + // kStorageVolumeDirHeader not allowed -- that's created by Format + WMSG1(" HFS ---v--- CreateFile '%s'\n", pParms->pathName); - /* - * Normalize the pathname so that all components are HFS-safe - * and separated by ':'. - * - * This must not "sanitize" the path. We need to be working with the - * original characters, not the sanitized-for-display versions. - */ - assert(pParms->pathName != nil); - dierr = DoNormalizePath(pParms->pathName, pParms->fssep, - &normalizedPath); - if (dierr != kDIErrNone) - goto bail; - assert(normalizedPath != nil); + /* + * Normalize the pathname so that all components are HFS-safe + * and separated by ':'. + * + * This must not "sanitize" the path. We need to be working with the + * original characters, not the sanitized-for-display versions. + */ + assert(pParms->pathName != nil); + dierr = DoNormalizePath(pParms->pathName, pParms->fssep, + &normalizedPath); + if (dierr != kDIErrNone) + goto bail; + assert(normalizedPath != nil); - /* - * The normalized path lacks a leading ':', and might need to - * have some digits added to make the name unique. - */ - fullPath = new char[strlen(normalizedPath)+2]; - fullPath[0] = A2FileHFS::kFssep; - strcpy(fullPath+1, normalizedPath); - delete[] normalizedPath; - normalizedPath = nil; + /* + * The normalized path lacks a leading ':', and might need to + * have some digits added to make the name unique. + */ + fullPath = new char[strlen(normalizedPath)+2]; + fullPath[0] = A2FileHFS::kFssep; + strcpy(fullPath+1, normalizedPath); + delete[] normalizedPath; + normalizedPath = nil; - /* - * Make the name unique within the current directory. This requires - * appending digits until the name doesn't match any others. - */ - if (createUnique && - pParms->storageType != A2FileProDOS::kStorageDirectory) - { - char* uniquePath; + /* + * Make the name unique within the current directory. This requires + * appending digits until the name doesn't match any others. + */ + if (createUnique && + pParms->storageType != A2FileProDOS::kStorageDirectory) + { + char* uniquePath; - dierr = MakeFileNameUnique(fullPath, &uniquePath); - if (dierr != kDIErrNone) - goto bail; - if (uniquePath != nil) { - delete[] fullPath; - fullPath = uniquePath; - } - } else { - /* can't make unique; check to see if it already exists */ - hfsdirent dirEnt; - if (hfs_stat(fHfsVol, fullPath, &dirEnt) == 0) { - if (pParms->storageType == A2FileProDOS::kStorageDirectory) - dierr = kDIErrDirectoryExists; - else - dierr = kDIErrFileExists; - goto bail; - } - } + dierr = MakeFileNameUnique(fullPath, &uniquePath); + if (dierr != kDIErrNone) + goto bail; + if (uniquePath != nil) { + delete[] fullPath; + fullPath = uniquePath; + } + } else { + /* can't make unique; check to see if it already exists */ + hfsdirent dirEnt; + if (hfs_stat(fHfsVol, fullPath, &dirEnt) == 0) { + if (pParms->storageType == A2FileProDOS::kStorageDirectory) + dierr = kDIErrDirectoryExists; + else + dierr = kDIErrFileExists; + goto bail; + } + } - /* - * Split the base path and filename apart. - */ - char* cp; - cp = strrchr(fullPath, A2FileHFS::kFssep); - assert(cp != nil); - if (cp == fullPath) { - assert(basePath == nil); - fileName = new char[strlen(fullPath) +1]; - strcpy(fileName, fullPath); - } else { - int dirNameLen = cp - fullPath; + /* + * Split the base path and filename apart. + */ + char* cp; + cp = strrchr(fullPath, A2FileHFS::kFssep); + assert(cp != nil); + if (cp == fullPath) { + assert(basePath == nil); + fileName = new char[strlen(fullPath) +1]; + strcpy(fileName, fullPath); + } else { + int dirNameLen = cp - fullPath; - fileName = new char[strlen(cp+1) +1]; - strcpy(fileName, cp+1); - basePath = new char[dirNameLen+1]; - strncpy(basePath, fullPath, dirNameLen); - basePath[dirNameLen] = '\0'; - } + fileName = new char[strlen(cp+1) +1]; + strcpy(fileName, cp+1); + basePath = new char[dirNameLen+1]; + strncpy(basePath, fullPath, dirNameLen); + basePath[dirNameLen] = '\0'; + } - WMSG2("SPLIT: '%s' '%s'\n", basePath, fileName); + WMSG2("SPLIT: '%s' '%s'\n", basePath, fileName); - assert(fileName != nil); + assert(fileName != nil); - /* - * Open the base path. If it doesn't exist, create it recursively. - */ - if (basePath != nil) { - WMSG2(" HFS Creating '%s' in '%s'\n", fileName, basePath); - /* - * Open the named subdir, creating it if it doesn't exist. We need - * to check basePath+1 because we're comparing against what's in our - * linear file list, and that doesn't include the leading ':'. - */ - pSubdir = (A2FileHFS*)GetFileByName(basePath+1, CompareMacFileNames); - if (pSubdir == nil) { - WMSG1(" HFS Creating subdir '%s'\n", basePath); - A2File* pNewSub; - CreateParms newDirParms; - newDirParms.pathName = basePath; - newDirParms.fssep = A2FileHFS::kFssep; - newDirParms.storageType = A2FileProDOS::kStorageDirectory; - newDirParms.fileType = 0; - newDirParms.auxType = 0; - newDirParms.access = 0; - newDirParms.createWhen = newDirParms.modWhen = time(nil); - dierr = this->CreateFile(&newDirParms, &pNewSub); - if (dierr != kDIErrNone) - goto bail; - assert(pNewSub != nil); + /* + * Open the base path. If it doesn't exist, create it recursively. + */ + if (basePath != nil) { + WMSG2(" HFS Creating '%s' in '%s'\n", fileName, basePath); + /* + * Open the named subdir, creating it if it doesn't exist. We need + * to check basePath+1 because we're comparing against what's in our + * linear file list, and that doesn't include the leading ':'. + */ + pSubdir = (A2FileHFS*)GetFileByName(basePath+1, CompareMacFileNames); + if (pSubdir == nil) { + WMSG1(" HFS Creating subdir '%s'\n", basePath); + A2File* pNewSub; + CreateParms newDirParms; + newDirParms.pathName = basePath; + newDirParms.fssep = A2FileHFS::kFssep; + newDirParms.storageType = A2FileProDOS::kStorageDirectory; + newDirParms.fileType = 0; + newDirParms.auxType = 0; + newDirParms.access = 0; + newDirParms.createWhen = newDirParms.modWhen = time(nil); + dierr = this->CreateFile(&newDirParms, &pNewSub); + if (dierr != kDIErrNone) + goto bail; + assert(pNewSub != nil); - pSubdir = (A2FileHFS*) pNewSub; - } + pSubdir = (A2FileHFS*) pNewSub; + } - /* - * And now the annoying part. We need to reconstruct basePath out - * of the filenames actually present, rather than relying on the - * argument passed in. That's because HFS is case-insensitive but - * case-preserving. It's not crucial for our inner workings, but the - * linear file list in the DiskFS should have accurate strings. - * (It'll work just fine, but the display might show the wrong values - * for parent directories until they reload the disk.) - * - * On the bright side, we know exactly how long the string needs - * to be, so we can just stomp on it in place. Assuming, of course, - * that the filename created matches up with what the filename - * normalizer came up with, which we can guarantee since (a) everybody - * uses the same normalizer and (b) the "uniqueify" stuff doesn't - * kick in for subdirs because we wouldn't be creating a new subdir - * if it didn't already exist. - * - * This is essentially the same as RegeneratePathName(), but that's - * meant for a situation where the filename already exists. - */ - A2FileHFS* pBaseDir = pSubdir; - int basePathLen = strlen(basePath); - while (!pBaseDir->IsVolumeDirectory()) { - const char* fixedName = pBaseDir->GetFileName(); - int fixedLen = strlen(fixedName); - if (fixedLen > basePathLen) { - assert(false); - break; - } - assert(basePathLen == fixedLen || - *(basePath + (basePathLen-fixedLen-1)) == kDIFssep); - memcpy(basePath + (basePathLen-fixedLen), fixedName, fixedLen); - basePathLen -= fixedLen+1; + /* + * And now the annoying part. We need to reconstruct basePath out + * of the filenames actually present, rather than relying on the + * argument passed in. That's because HFS is case-insensitive but + * case-preserving. It's not crucial for our inner workings, but the + * linear file list in the DiskFS should have accurate strings. + * (It'll work just fine, but the display might show the wrong values + * for parent directories until they reload the disk.) + * + * On the bright side, we know exactly how long the string needs + * to be, so we can just stomp on it in place. Assuming, of course, + * that the filename created matches up with what the filename + * normalizer came up with, which we can guarantee since (a) everybody + * uses the same normalizer and (b) the "uniqueify" stuff doesn't + * kick in for subdirs because we wouldn't be creating a new subdir + * if it didn't already exist. + * + * This is essentially the same as RegeneratePathName(), but that's + * meant for a situation where the filename already exists. + */ + A2FileHFS* pBaseDir = pSubdir; + int basePathLen = strlen(basePath); + while (!pBaseDir->IsVolumeDirectory()) { + const char* fixedName = pBaseDir->GetFileName(); + int fixedLen = strlen(fixedName); + if (fixedLen > basePathLen) { + assert(false); + break; + } + assert(basePathLen == fixedLen || + *(basePath + (basePathLen-fixedLen-1)) == kDIFssep); + memcpy(basePath + (basePathLen-fixedLen), fixedName, fixedLen); + basePathLen -= fixedLen+1; - pBaseDir = (A2FileHFS*) pBaseDir->GetParent(); - assert(pBaseDir != nil); - } - // check the math; we should be left with the leading ':' - if (pSubdir->IsVolumeDirectory()) - assert(basePathLen == 1); - else - assert(basePathLen == 0); - } else { - /* open the volume directory */ - WMSG1(" HFS Creating '%s' in volume dir\n", fileName); - /* volume dir must be first in the list */ - pSubdir = (A2FileHFS*) GetNextFile(nil); - assert(pSubdir != nil); - assert(pSubdir->IsVolumeDirectory()); - } - if (pSubdir == nil) { - WMSG1(" HFS Unable to open subdir '%s'\n", basePath); - dierr = kDIErrFileNotFound; - goto bail; - } + pBaseDir = (A2FileHFS*) pBaseDir->GetParent(); + assert(pBaseDir != nil); + } + // check the math; we should be left with the leading ':' + if (pSubdir->IsVolumeDirectory()) + assert(basePathLen == 1); + else + assert(basePathLen == 0); + } else { + /* open the volume directory */ + WMSG1(" HFS Creating '%s' in volume dir\n", fileName); + /* volume dir must be first in the list */ + pSubdir = (A2FileHFS*) GetNextFile(nil); + assert(pSubdir != nil); + assert(pSubdir->IsVolumeDirectory()); + } + if (pSubdir == nil) { + WMSG1(" HFS Unable to open subdir '%s'\n", basePath); + dierr = kDIErrFileNotFound; + goto bail; + } - /* - * Figure out file type. - */ - A2FileHFS::ConvertTypeToHFS(pParms->fileType, pParms->auxType, - typeStr, creatorStr); + /* + * Figure out file type. + */ + A2FileHFS::ConvertTypeToHFS(pParms->fileType, pParms->auxType, + typeStr, creatorStr); - /* - * Create the file or directory. Populate "dirEnt" with the details. - */ - hfsdirent dirEnt; - if (pParms->storageType == A2FileProDOS::kStorageDirectory) { - /* create the directory */ - if (hfs_mkdir(fHfsVol, fullPath) != 0) { - WMSG2(" HFS mkdir '%s' failed: %s\n", fullPath, hfs_error); - dierr = kDIErrGeneric; - goto bail; - } - if (hfs_stat(fHfsVol, fullPath, &dirEnt) != 0) { - WMSG1(" HFS stat on new dir failed: %s\n", hfs_error); - dierr = kDIErrGeneric; - goto bail; - } - /* create date *might* be useful, but probably not worth adjusting */ - } else { - /* create, and open, the file */ - pHfsFile = hfs_create(fHfsVol, fullPath, typeStr, creatorStr); - if (pHfsFile == nil) { - WMSG1(" HFS create failed: %s\n", hfs_error); - dierr = kDIErrGeneric; - goto bail; - } - if (hfs_fstat(pHfsFile, &dirEnt) != 0) { - WMSG1(" HFS fstat on new file failed: %s\n", hfs_error); - dierr = kDIErrGeneric; - goto bail; - } + /* + * Create the file or directory. Populate "dirEnt" with the details. + */ + hfsdirent dirEnt; + if (pParms->storageType == A2FileProDOS::kStorageDirectory) { + /* create the directory */ + if (hfs_mkdir(fHfsVol, fullPath) != 0) { + WMSG2(" HFS mkdir '%s' failed: %s\n", fullPath, hfs_error); + dierr = kDIErrGeneric; + goto bail; + } + if (hfs_stat(fHfsVol, fullPath, &dirEnt) != 0) { + WMSG1(" HFS stat on new dir failed: %s\n", hfs_error); + dierr = kDIErrGeneric; + goto bail; + } + /* create date *might* be useful, but probably not worth adjusting */ + } else { + /* create, and open, the file */ + pHfsFile = hfs_create(fHfsVol, fullPath, typeStr, creatorStr); + if (pHfsFile == nil) { + WMSG1(" HFS create failed: %s\n", hfs_error); + dierr = kDIErrGeneric; + goto bail; + } + if (hfs_fstat(pHfsFile, &dirEnt) != 0) { + WMSG1(" HFS fstat on new file failed: %s\n", hfs_error); + dierr = kDIErrGeneric; + goto bail; + } - /* set the attributes according to pParms, and update the file */ - dirEnt.crdate = pParms->createWhen; - dirEnt.mddate = pParms->modWhen; - if (pParms->access & A2FileProDOS::kAccessInvisible) - dirEnt.fdflags |= HFS_FNDR_ISINVISIBLE; - else - dirEnt.fdflags &= ~HFS_FNDR_ISINVISIBLE; - if ((pParms->access & ~A2FileProDOS::kAccessInvisible) == kFileAccessLocked) - dirEnt.flags |= HFS_ISLOCKED; - else - dirEnt.flags &= ~HFS_ISLOCKED; + /* set the attributes according to pParms, and update the file */ + dirEnt.crdate = pParms->createWhen; + dirEnt.mddate = pParms->modWhen; + if (pParms->access & A2FileProDOS::kAccessInvisible) + dirEnt.fdflags |= HFS_FNDR_ISINVISIBLE; + else + dirEnt.fdflags &= ~HFS_FNDR_ISINVISIBLE; + if ((pParms->access & ~A2FileProDOS::kAccessInvisible) == kFileAccessLocked) + dirEnt.flags |= HFS_ISLOCKED; + else + dirEnt.flags &= ~HFS_ISLOCKED; - (void) hfs_fsetattr(pHfsFile, &dirEnt); - (void) hfs_close(pHfsFile); - pHfsFile = nil; - } + (void) hfs_fsetattr(pHfsFile, &dirEnt); + (void) hfs_close(pHfsFile); + pHfsFile = nil; + } - /* - * Success! - * - * Create a new entry and set the structure fields. - */ - pNewFile = new A2FileHFS(this); - pNewFile->InitEntry(&dirEnt); - pNewFile->SetPathName(basePath == nil ? "" : basePath, pNewFile->fFileName); - pNewFile->SetParent(pSubdir); + /* + * Success! + * + * Create a new entry and set the structure fields. + */ + pNewFile = new A2FileHFS(this); + pNewFile->InitEntry(&dirEnt); + pNewFile->SetPathName(basePath == nil ? "" : basePath, pNewFile->fFileName); + pNewFile->SetParent(pSubdir); - /* - * Because we're hierarchical, and we guarantee that the contents of - * subdirectories are grouped together, we must insert the file into an - * appropriate place in the list rather than just throwing it onto the - * end. - * - * The proper location for the new file in the linear list is in sorted - * order with the files in the current directory. We have to be careful - * here because libhfs is going to use Macintosh Roman sort ordering, - * which may be different from ASCII ordering. Worst case: we end up - * putting it in the wrong place and it jumps around when the disk image - * is reopened. - * - * All files in a subdir appear in the list after that subdir, but there - * might be intervening entries from deeper directories. So we have to - * chase through some or all of the file list to find the right place. - * Not great, but we don't have enough files or do adds often enough to - * make this worth optimizing. - */ - A2File* pLastSubdirFile; - A2File* pPrevFile; - A2File* pNextFile; + /* + * Because we're hierarchical, and we guarantee that the contents of + * subdirectories are grouped together, we must insert the file into an + * appropriate place in the list rather than just throwing it onto the + * end. + * + * The proper location for the new file in the linear list is in sorted + * order with the files in the current directory. We have to be careful + * here because libhfs is going to use Macintosh Roman sort ordering, + * which may be different from ASCII ordering. Worst case: we end up + * putting it in the wrong place and it jumps around when the disk image + * is reopened. + * + * All files in a subdir appear in the list after that subdir, but there + * might be intervening entries from deeper directories. So we have to + * chase through some or all of the file list to find the right place. + * Not great, but we don't have enough files or do adds often enough to + * make this worth optimizing. + */ + A2File* pLastSubdirFile; + A2File* pPrevFile; + A2File* pNextFile; - pPrevFile = pLastSubdirFile = pSubdir; - pNextFile = GetNextFile(pPrevFile); - while (pNextFile != nil) { - if (pNextFile->GetParent() == pNewFile->GetParent()) { - /* in same subdir, compare names */ - if (CompareMacFileNames(pNextFile->GetPathName(), - pNewFile->GetPathName()) > 0) - { - /* passed it; insert new after previous file */ - pLastSubdirFile = pPrevFile; - WMSG2(" HFS Found '%s' > cur(%s)\n", pNextFile->GetPathName(), - pNewFile->GetPathName()); - break; - } + pPrevFile = pLastSubdirFile = pSubdir; + pNextFile = GetNextFile(pPrevFile); + while (pNextFile != nil) { + if (pNextFile->GetParent() == pNewFile->GetParent()) { + /* in same subdir, compare names */ + if (CompareMacFileNames(pNextFile->GetPathName(), + pNewFile->GetPathName()) > 0) + { + /* passed it; insert new after previous file */ + pLastSubdirFile = pPrevFile; + WMSG2(" HFS Found '%s' > cur(%s)\n", pNextFile->GetPathName(), + pNewFile->GetPathName()); + break; + } - /* still too early; save in case it's last one in dir */ - pLastSubdirFile = pNextFile; - } - pPrevFile = pNextFile; - pNextFile = GetNextFile(pNextFile); - } + /* still too early; save in case it's last one in dir */ + pLastSubdirFile = pNextFile; + } + pPrevFile = pNextFile; + pNextFile = GetNextFile(pNextFile); + } - /* insert us after last file we saw that was part of the same subdir */ - WMSG2(" HFS inserting '%s' after '%s'\n", pNewFile->GetPathName(), - pLastSubdirFile->GetPathName()); - InsertFileInList(pNewFile, pLastSubdirFile); - //WMSG0("LIST NOW:\n"); - //DumpFileList(); + /* insert us after last file we saw that was part of the same subdir */ + WMSG2(" HFS inserting '%s' after '%s'\n", pNewFile->GetPathName(), + pLastSubdirFile->GetPathName()); + InsertFileInList(pNewFile, pLastSubdirFile); + //WMSG0("LIST NOW:\n"); + //DumpFileList(); - *ppNewFile = pNewFile; - pNewFile = nil; + *ppNewFile = pNewFile; + pNewFile = nil; bail: - delete pNewFile; - delete[] normalizedPath; - delete[] basePath; - delete[] fileName; - delete[] fullPath; - hfs_flush(fHfsVol); - WMSG1(" HFS ---^--- CreateFile '%s' DONE\n", pParms->pathName); - return dierr; + delete pNewFile; + delete[] normalizedPath; + delete[] basePath; + delete[] fileName; + delete[] fullPath; + hfs_flush(fHfsVol); + WMSG1(" HFS ---^--- CreateFile '%s' DONE\n", pParms->pathName); + return dierr; } /* @@ -1320,43 +1320,43 @@ bail: DIError DiskFSHFS::DeleteFile(A2File* pGenericFile) { - DIError dierr = kDIErrNone; - char* pathName = nil; + DIError dierr = kDIErrNone; + char* pathName = nil; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (!fDiskIsGood) - return kDIErrBadDiskImage; - if (pGenericFile->IsFileOpen()) - return kDIErrFileOpen; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (!fDiskIsGood) + return kDIErrBadDiskImage; + if (pGenericFile->IsFileOpen()) + return kDIErrFileOpen; - A2FileHFS* pFile = (A2FileHFS*) pGenericFile; - pathName = pFile->GetLibHFSPathName(); - WMSG1(" Deleting '%s'\n", pathName); + A2FileHFS* pFile = (A2FileHFS*) pGenericFile; + pathName = pFile->GetLibHFSPathName(); + WMSG1(" Deleting '%s'\n", pathName); - if (pFile->IsDirectory()) { - if (hfs_rmdir(fHfsVol, pathName) != 0) { - WMSG2(" HFS rmdir failed '%s': '%s'\n", pathName, hfs_error); - dierr = kDIErrGeneric; - goto bail; - } - } else { - if (hfs_delete(fHfsVol, pathName) != 0) { - WMSG2(" HFS delete failed '%s': '%s'\n", pathName, hfs_error); - dierr = kDIErrGeneric; - goto bail; - } - } + if (pFile->IsDirectory()) { + if (hfs_rmdir(fHfsVol, pathName) != 0) { + WMSG2(" HFS rmdir failed '%s': '%s'\n", pathName, hfs_error); + dierr = kDIErrGeneric; + goto bail; + } + } else { + if (hfs_delete(fHfsVol, pathName) != 0) { + WMSG2(" HFS delete failed '%s': '%s'\n", pathName, hfs_error); + dierr = kDIErrGeneric; + goto bail; + } + } - /* - * Remove the A2File* from the list. - */ - DeleteFileFromList(pFile); + /* + * Remove the A2File* from the list. + */ + DeleteFileFromList(pFile); bail: - hfs_flush(fHfsVol); - delete[] pathName; - return kDIErrNone; + hfs_flush(fHfsVol); + delete[] pathName; + return kDIErrNone; } /* @@ -1376,91 +1376,91 @@ bail: DIError DiskFSHFS::RenameFile(A2File* pGenericFile, const char* newName) { - DIError dierr = kDIErrNone; - A2FileHFS* pFile = (A2FileHFS*) pGenericFile; - char* colonOldName = nil; - char* colonNewName = nil; + DIError dierr = kDIErrNone; + A2FileHFS* pFile = (A2FileHFS*) pGenericFile; + char* colonOldName = nil; + char* colonNewName = nil; - if (pFile == nil || newName == nil) - return kDIErrInvalidArg; - if (!IsValidFileName(newName)) - return kDIErrInvalidArg; - if (pFile->IsVolumeDirectory()) - return kDIErrInvalidArg; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (!fDiskIsGood) - return kDIErrBadDiskImage; + if (pFile == nil || newName == nil) + return kDIErrInvalidArg; + if (!IsValidFileName(newName)) + return kDIErrInvalidArg; + if (pFile->IsVolumeDirectory()) + return kDIErrInvalidArg; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (!fDiskIsGood) + return kDIErrBadDiskImage; - char* lastColon; + char* lastColon; - colonOldName = pFile->GetLibHFSPathName(); // adds ':' to start of string - lastColon = strrchr(colonOldName, A2FileHFS::kFssep); - assert(lastColon != nil); - if (lastColon == colonOldName) { - /* in root dir */ - colonNewName = new char[1 + strlen(newName) +1]; - colonNewName[0] = A2FileHFS::kFssep; - strcpy(colonNewName+1, newName); - } else { - /* prepend subdir */ - int len = lastColon - colonOldName +1; // e.g. ":path1:path2:" - colonNewName = new char[len + strlen(newName) +1]; - strncpy(colonNewName, colonOldName, len); - strcpy(colonNewName+len, newName); - } + colonOldName = pFile->GetLibHFSPathName(); // adds ':' to start of string + lastColon = strrchr(colonOldName, A2FileHFS::kFssep); + assert(lastColon != nil); + if (lastColon == colonOldName) { + /* in root dir */ + colonNewName = new char[1 + strlen(newName) +1]; + colonNewName[0] = A2FileHFS::kFssep; + strcpy(colonNewName+1, newName); + } else { + /* prepend subdir */ + int len = lastColon - colonOldName +1; // e.g. ":path1:path2:" + colonNewName = new char[len + strlen(newName) +1]; + strncpy(colonNewName, colonOldName, len); + strcpy(colonNewName+len, newName); + } - WMSG2(" HFS renaming '%s' to '%s'\n", colonOldName, colonNewName); + WMSG2(" HFS renaming '%s' to '%s'\n", colonOldName, colonNewName); - if (hfs_rename(fHfsVol, colonOldName, colonNewName) != 0) { - WMSG3(" HFS rename('%s','%s') failed: %s\n", - colonOldName, colonNewName, hfs_error); - dierr = kDIErrGeneric; - goto bail; - } + if (hfs_rename(fHfsVol, colonOldName, colonNewName) != 0) { + WMSG3(" HFS rename('%s','%s') failed: %s\n", + colonOldName, colonNewName, hfs_error); + dierr = kDIErrGeneric; + goto bail; + } - /* - * Success! Update the file name. - */ - strcpy(pFile->fFileName, newName); + /* + * Success! Update the file name. + */ + strcpy(pFile->fFileName, newName); - /* - * Now the fun part. If we simply renamed a file, we can just update the - * one entry. If we renamed a directory, life gets interesting because - * we store the full pathname in every A2FileHFS entry. (It's an - * efficiency win most of the time, but it's really annoying here.) - * - * HFS makes this especially unpleasant because it keeps the files - * arranged in sorted order. If we change a file's name, we may have to - * move it to a new position in the linear file list. If we don't, the - * list no longer reflects the order in which the files actually appear - * on the disk, and they'll shift around when we reload. - * - * There are two approaches: re-sort the list (awkward, since it's stored - * in a linked list -- we'd probably want to sort tags in a parallel - * structure), or find the affected block of files, find the new start - * position, and shift the entire range in one shot. - * - * This doesn't seem like something that anybody but me will ever care - * about, so I'm going to skip it for now. - */ - A2File* pCur; - if (pFile->IsDirectory()) { - /* do all files that come after us */ - pCur = pFile; - while (pCur != nil) { - RegeneratePathName((A2FileHFS*) pCur); - pCur = GetNextFile(pCur); - } - } else { - RegeneratePathName(pFile); - } + /* + * Now the fun part. If we simply renamed a file, we can just update the + * one entry. If we renamed a directory, life gets interesting because + * we store the full pathname in every A2FileHFS entry. (It's an + * efficiency win most of the time, but it's really annoying here.) + * + * HFS makes this especially unpleasant because it keeps the files + * arranged in sorted order. If we change a file's name, we may have to + * move it to a new position in the linear file list. If we don't, the + * list no longer reflects the order in which the files actually appear + * on the disk, and they'll shift around when we reload. + * + * There are two approaches: re-sort the list (awkward, since it's stored + * in a linked list -- we'd probably want to sort tags in a parallel + * structure), or find the affected block of files, find the new start + * position, and shift the entire range in one shot. + * + * This doesn't seem like something that anybody but me will ever care + * about, so I'm going to skip it for now. + */ + A2File* pCur; + if (pFile->IsDirectory()) { + /* do all files that come after us */ + pCur = pFile; + while (pCur != nil) { + RegeneratePathName((A2FileHFS*) pCur); + pCur = GetNextFile(pCur); + } + } else { + RegeneratePathName(pFile); + } bail: - delete[] colonOldName; - delete[] colonNewName; - hfs_flush(fHfsVol); - return kDIErrNone; + delete[] colonOldName; + delete[] colonNewName; + hfs_flush(fHfsVol); + return kDIErrNone; } /* @@ -1477,52 +1477,52 @@ bail: DIError DiskFSHFS::RegeneratePathName(A2FileHFS* pFile) { - A2FileHFS* pParent; - char* buf = nil; - int len; + A2FileHFS* pParent; + char* buf = nil; + int len; - /* nothing to do here */ - if (pFile->IsVolumeDirectory()) - return kDIErrNone; + /* nothing to do here */ + if (pFile->IsVolumeDirectory()) + return kDIErrNone; - /* compute the length of the path name */ - len = strlen(pFile->GetFileName()); - pParent = (A2FileHFS*) pFile->GetParent(); - while (!pParent->IsVolumeDirectory()) { - len++; // leave space for the ':' - len += strlen(pParent->GetFileName()); + /* compute the length of the path name */ + len = strlen(pFile->GetFileName()); + pParent = (A2FileHFS*) pFile->GetParent(); + while (!pParent->IsVolumeDirectory()) { + len++; // leave space for the ':' + len += strlen(pParent->GetFileName()); - pParent = (A2FileHFS*) pParent->GetParent(); - } + pParent = (A2FileHFS*) pParent->GetParent(); + } - buf = new char[len+1]; - if (buf == nil) - return kDIErrMalloc; + buf = new char[len+1]; + if (buf == nil) + return kDIErrMalloc; - /* generate the new path name */ - int partLen; - partLen = strlen(pFile->GetFileName()); - strcpy(buf + len - partLen, pFile->GetFileName()); - len -= partLen; + /* generate the new path name */ + int partLen; + partLen = strlen(pFile->GetFileName()); + strcpy(buf + len - partLen, pFile->GetFileName()); + len -= partLen; - pParent = (A2FileHFS*) pFile->GetParent(); - while (!pParent->IsVolumeDirectory()) { - assert(len > 0); - buf[--len] = A2FileHFS::kFssep; + pParent = (A2FileHFS*) pFile->GetParent(); + while (!pParent->IsVolumeDirectory()) { + assert(len > 0); + buf[--len] = A2FileHFS::kFssep; - partLen = strlen(pParent->GetFileName()); - strncpy(buf + len - partLen, pParent->GetFileName(), partLen); - len -= partLen; - assert(len >= 0); + partLen = strlen(pParent->GetFileName()); + strncpy(buf + len - partLen, pParent->GetFileName(), partLen); + len -= partLen; + assert(len >= 0); - pParent = (A2FileHFS*) pParent->GetParent(); - } + pParent = (A2FileHFS*) pParent->GetParent(); + } - WMSG2("Replacing '%s' with '%s'\n", pFile->GetPathName(), buf); - pFile->SetPathName("", buf); - delete[] buf; + WMSG2("Replacing '%s' with '%s'\n", pFile->GetPathName(), buf); + pFile->SetPathName("", buf); + delete[] buf; - return kDIErrNone; + return kDIErrNone; } /* @@ -1535,45 +1535,45 @@ DiskFSHFS::RegeneratePathName(A2FileHFS* pFile) DIError DiskFSHFS::RenameVolume(const char* newName) { - DIError dierr = kDIErrNone; - A2FileHFS* pFile; - char* oldNameColon = nil; - char* newNameColon = nil; + DIError dierr = kDIErrNone; + A2FileHFS* pFile; + char* oldNameColon = nil; + char* newNameColon = nil; - if (!IsValidVolumeName(newName)) - return kDIErrInvalidArg; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; + if (!IsValidVolumeName(newName)) + return kDIErrInvalidArg; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; - /* get file list entry for volume name */ - pFile = (A2FileHFS*) GetNextFile(nil); - assert(strcmp(pFile->GetFileName(), fVolumeName) == 0); + /* get file list entry for volume name */ + pFile = (A2FileHFS*) GetNextFile(nil); + assert(strcmp(pFile->GetFileName(), fVolumeName) == 0); - oldNameColon = new char[strlen(fVolumeName)+2]; - strcpy(oldNameColon, fVolumeName); - strcat(oldNameColon, ":"); - newNameColon = new char[strlen(newName)+2]; - strcpy(newNameColon, newName); - strcat(newNameColon, ":"); + oldNameColon = new char[strlen(fVolumeName)+2]; + strcpy(oldNameColon, fVolumeName); + strcat(oldNameColon, ":"); + newNameColon = new char[strlen(newName)+2]; + strcpy(newNameColon, newName); + strcat(newNameColon, ":"); - if (hfs_rename(fHfsVol, oldNameColon, newNameColon) != 0) { - WMSG3(" HFS rename '%s' -> '%s' failed: %s\n", - oldNameColon, newNameColon, hfs_error); - dierr = kDIErrGeneric; - goto bail; - } + if (hfs_rename(fHfsVol, oldNameColon, newNameColon) != 0) { + WMSG3(" HFS rename '%s' -> '%s' failed: %s\n", + oldNameColon, newNameColon, hfs_error); + dierr = kDIErrGeneric; + goto bail; + } - /* update stuff */ - strcpy(fVolumeName, newName); - SetVolumeID(); - strcpy(pFile->fFileName, newName); - pFile->SetPathName("", newName); + /* update stuff */ + strcpy(fVolumeName, newName); + SetVolumeID(); + strcpy(pFile->fFileName, newName); + pFile->SetPathName("", newName); bail: - delete[] oldNameColon; - delete[] newNameColon; - hfs_flush(fHfsVol); - return dierr; + delete[] oldNameColon; + delete[] newNameColon; + hfs_flush(fHfsVol); + return dierr; } /* @@ -1581,60 +1581,60 @@ bail: */ DIError DiskFSHFS::SetFileInfo(A2File* pGenericFile, long fileType, long auxType, - long accessFlags) + long accessFlags) { - DIError dierr = kDIErrNone; - A2FileHFS* pFile = (A2FileHFS*) pGenericFile; - hfsdirent dirEnt; - char* colonPath; + DIError dierr = kDIErrNone; + A2FileHFS* pFile = (A2FileHFS*) pGenericFile; + hfsdirent dirEnt; + char* colonPath; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (pFile == nil) - return kDIErrInvalidArg; - if (pFile->IsDirectory() || pFile->IsVolumeDirectory()) - return kDIErrNone; // impossible; just ignore it + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (pFile == nil) + return kDIErrInvalidArg; + if (pFile->IsDirectory() || pFile->IsVolumeDirectory()) + return kDIErrNone; // impossible; just ignore it - colonPath = pFile->GetLibHFSPathName(); + colonPath = pFile->GetLibHFSPathName(); - if (hfs_stat(fHfsVol, colonPath, &dirEnt) != 0) { - WMSG2(" HFS unable to stat '%s': %s\n", colonPath, hfs_error); - dierr = kDIErrGeneric; - goto bail; - } + if (hfs_stat(fHfsVol, colonPath, &dirEnt) != 0) { + WMSG2(" HFS unable to stat '%s': %s\n", colonPath, hfs_error); + dierr = kDIErrGeneric; + goto bail; + } - A2FileHFS::ConvertTypeToHFS(fileType, auxType, - dirEnt.u.file.type, dirEnt.u.file.creator); + A2FileHFS::ConvertTypeToHFS(fileType, auxType, + dirEnt.u.file.type, dirEnt.u.file.creator); - if (accessFlags & A2FileProDOS::kAccessInvisible) - dirEnt.fdflags |= HFS_FNDR_ISINVISIBLE; - else - dirEnt.fdflags &= ~HFS_FNDR_ISINVISIBLE; + if (accessFlags & A2FileProDOS::kAccessInvisible) + dirEnt.fdflags |= HFS_FNDR_ISINVISIBLE; + else + dirEnt.fdflags &= ~HFS_FNDR_ISINVISIBLE; - if ((accessFlags & ~A2FileProDOS::kAccessInvisible) == kFileAccessLocked) - dirEnt.flags |= HFS_ISLOCKED; - else - dirEnt.flags &= ~HFS_ISLOCKED; + if ((accessFlags & ~A2FileProDOS::kAccessInvisible) == kFileAccessLocked) + dirEnt.flags |= HFS_ISLOCKED; + else + dirEnt.flags &= ~HFS_ISLOCKED; - WMSG3(" HFS setting '%s' to fdflags=0x%04x flags=0x%04x\n", - colonPath, dirEnt.fdflags, dirEnt.flags); - WMSG2(" type=0x%08lx creator=0x%08lx\n", fileType, auxType); + WMSG3(" HFS setting '%s' to fdflags=0x%04x flags=0x%04x\n", + colonPath, dirEnt.fdflags, dirEnt.flags); + WMSG2(" type=0x%08lx creator=0x%08lx\n", fileType, auxType); - if (hfs_setattr(fHfsVol, colonPath, &dirEnt) != 0) { - WMSG2(" HFS setattr '%s' failed: %s\n", colonPath, hfs_error); - dierr = kDIErrGeneric; - goto bail; - } + if (hfs_setattr(fHfsVol, colonPath, &dirEnt) != 0) { + WMSG2(" HFS setattr '%s' failed: %s\n", colonPath, hfs_error); + dierr = kDIErrGeneric; + goto bail; + } - /* update our local copy */ - pFile->fType = fileType; - pFile->fCreator = auxType; - pFile->fAccess = accessFlags; // should actually base them on HFS vals + /* update our local copy */ + pFile->fType = fileType; + pFile->fCreator = auxType; + pFile->fAccess = accessFlags; // should actually base them on HFS vals bail: - delete[] colonPath; - hfs_flush(fHfsVol); - return dierr; + delete[] colonPath; + hfs_flush(fHfsVol); + return dierr; } #endif // !EXCISE_GPL_CODE @@ -1642,7 +1642,7 @@ bail: /* * =========================================================================== - * A2FileHFS + * A2FileHFS * =========================================================================== */ @@ -1652,20 +1652,20 @@ bail: void A2FileHFS::Dump(void) const { - WMSG1("A2FileHFS '%s'\n", fFileName); + WMSG1("A2FileHFS '%s'\n", fFileName); } /* convert hex to decimal */ inline int FromHex(char hexVal) { - if (hexVal >= '0' && hexVal <= '9') - return hexVal - '0'; - else if (hexVal >= 'a' && hexVal <= 'f') - return hexVal -'a' + 10; - else if (hexVal >= 'A' && hexVal <= 'F') - return hexVal - 'A' + 10; - else - return -1; + if (hexVal >= '0' && hexVal <= '9') + return hexVal - '0'; + else if (hexVal >= 'a' && hexVal <= 'f') + return hexVal -'a' + 10; + else if (hexVal >= 'A' && hexVal <= 'F') + return hexVal - 'A' + 10; + else + return -1; } /* @@ -1690,15 +1690,15 @@ long A2FileHFS::GetFileType(void) const if ((fType & 0xffff) == 0x2020) { // 'XY ', where XY are hex digits for ProDOS file type - int digit1, digit2; + int digit1, digit2; - digit1 = FromHex((char) (fType >> 24)); - digit2 = FromHex((char) (fType >> 16)); - if (digit1 < 0 || digit2 < 0) { - WMSG1(" Unexpected: pdos + %08lx\n", fType); - return 0x00; - } - return digit1 << 4 | digit2; + digit1 = FromHex((char) (fType >> 24)); + digit2 = FromHex((char) (fType >> 16)); + if (digit1 < 0 || digit2 < 0) { + WMSG1(" Unexpected: pdos + %08lx\n", fType); + return 0x00; + } + return digit1 << 4 | digit2; } unsigned char flag = (unsigned char)(fType >> 24); @@ -1746,24 +1746,24 @@ long A2FileHFS::GetAuxType(void) const void A2FileHFS::SetPathName(const char* basePath, const char* fileName) { - assert(basePath != nil && fileName != nil); - if (fPathName != nil) - delete[] fPathName; + assert(basePath != nil && fileName != nil); + if (fPathName != nil) + delete[] fPathName; // strip leading ':' (but treat ":" specially for volume dir entry) if (basePath[0] == ':' && basePath[1] != '\0') basePath++; - int baseLen = strlen(basePath); - fPathName = new char[baseLen + 1 + strlen(fileName)+1]; - strcpy(fPathName, basePath); - if (baseLen != 0 && - !(baseLen == 1 && basePath[0] == ':')) - { - *(fPathName + baseLen) = kFssep; - baseLen++; - } - strcpy(fPathName + baseLen, fileName); + int baseLen = strlen(basePath); + fPathName = new char[baseLen + 1 + strlen(fileName)+1]; + strcpy(fPathName, basePath); + if (baseLen != 0 && + !(baseLen == 1 && basePath[0] == ':')) + { + *(fPathName + baseLen) = kFssep; + baseLen++; + } + strcpy(fPathName + baseLen, fileName); } @@ -1777,13 +1777,13 @@ A2FileHFS::SetPathName(const char* basePath, const char* fileName) char* A2FileHFS::GetLibHFSPathName(void) const { - char* nameBuf; + char* nameBuf; - nameBuf = new char[strlen(fPathName)+2]; - nameBuf[0] = kFssep; - strcpy(nameBuf+1, fPathName); + nameBuf = new char[strlen(fPathName)+2]; + nameBuf[0] = kFssep; + strcpy(nameBuf+1, fPathName); - return nameBuf; + return nameBuf; } /* @@ -1796,39 +1796,39 @@ A2FileHFS::GetLibHFSPathName(void) const */ /*static*/ void A2FileHFS::ConvertTypeToHFS(long fileType, long auxType, - char* pType, char* pCreator) + char* pType, char* pCreator) { - if (fileType == 0x00 && auxType == 0x0000) { - strcpy(pCreator, "pdos"); - strcpy(pType, "BINA"); - } else if (fileType == 0x04 && auxType == 0x0000) { - strcpy(pCreator, "pdos"); - strcpy(pType, "TEXT"); - } else if (fileType >= 0 && fileType <= 0xff && - auxType >= 0 && auxType <= 0xffff) - { - pType[0] = 'p'; - pType[1] = (unsigned char) fileType; - pType[2] = (unsigned char) (auxType >> 8); - pType[3] = (unsigned char) auxType; - pType[4] = '\0'; - pCreator[0] = 'p'; - pCreator[1] = 'd'; - pCreator[2] = 'o'; - pCreator[3] = 's'; - pCreator[4] = '\0'; - } else { - pType[0] = (unsigned char)(fileType >> 24); - pType[1] = (unsigned char)(fileType >> 16); - pType[2] = (unsigned char)(fileType >> 8); - pType[3] = (unsigned char) fileType; - pType[4] = '\0'; - pCreator[0] = (unsigned char)(auxType >> 24); - pCreator[1] = (unsigned char)(auxType >> 16); - pCreator[2] = (unsigned char)(auxType >> 8); - pCreator[3] = (unsigned char) auxType; - pCreator[4] = '\0'; - } + if (fileType == 0x00 && auxType == 0x0000) { + strcpy(pCreator, "pdos"); + strcpy(pType, "BINA"); + } else if (fileType == 0x04 && auxType == 0x0000) { + strcpy(pCreator, "pdos"); + strcpy(pType, "TEXT"); + } else if (fileType >= 0 && fileType <= 0xff && + auxType >= 0 && auxType <= 0xffff) + { + pType[0] = 'p'; + pType[1] = (unsigned char) fileType; + pType[2] = (unsigned char) (auxType >> 8); + pType[3] = (unsigned char) auxType; + pType[4] = '\0'; + pCreator[0] = 'p'; + pCreator[1] = 'd'; + pCreator[2] = 'o'; + pCreator[3] = 's'; + pCreator[4] = '\0'; + } else { + pType[0] = (unsigned char)(fileType >> 24); + pType[1] = (unsigned char)(fileType >> 16); + pType[2] = (unsigned char)(fileType >> 8); + pType[3] = (unsigned char) fileType; + pType[4] = '\0'; + pCreator[0] = (unsigned char)(auxType >> 24); + pCreator[1] = (unsigned char)(auxType >> 16); + pCreator[2] = (unsigned char)(auxType >> 8); + pCreator[3] = (unsigned char) auxType; + pCreator[4] = '\0'; + } } @@ -1842,43 +1842,43 @@ A2FileHFS::ConvertTypeToHFS(long fileType, long auxType, */ DIError A2FileHFS::Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork /*=false*/) + bool rsrcFork /*=false*/) { - DIError dierr = kDIErrNone; - A2FDHFS* pOpenFile = nil; - hfsfile* pHfsFile; - char* nameBuf = nil; + DIError dierr = kDIErrNone; + A2FDHFS* pOpenFile = nil; + hfsfile* pHfsFile; + char* nameBuf = nil; - if (fpOpenFile != nil) - return kDIErrAlreadyOpen; - //if (rsrcFork && fRsrcLength < 0) - // return kDIErrForkNotFound; + if (fpOpenFile != nil) + return kDIErrAlreadyOpen; + //if (rsrcFork && fRsrcLength < 0) + // return kDIErrForkNotFound; - nameBuf = GetLibHFSPathName(); + nameBuf = GetLibHFSPathName(); - DiskFSHFS* pDiskFS = (DiskFSHFS*) GetDiskFS(); - pHfsFile = hfs_open(pDiskFS->GetHfsVol(), nameBuf); - if (pHfsFile == NULL) { - WMSG2(" HFS hfs_open(%s) failed: %s\n", nameBuf, hfs_error); - dierr = kDIErrGeneric; // better value might be in errno - goto bail; - } - hfs_setfork(pHfsFile, rsrcFork ? 1 : 0); + DiskFSHFS* pDiskFS = (DiskFSHFS*) GetDiskFS(); + pHfsFile = hfs_open(pDiskFS->GetHfsVol(), nameBuf); + if (pHfsFile == NULL) { + WMSG2(" HFS hfs_open(%s) failed: %s\n", nameBuf, hfs_error); + dierr = kDIErrGeneric; // better value might be in errno + goto bail; + } + hfs_setfork(pHfsFile, rsrcFork ? 1 : 0); - pOpenFile = new A2FDHFS(this, pHfsFile); + pOpenFile = new A2FDHFS(this, pHfsFile); - fpOpenFile = pOpenFile; - *ppOpenFile = pOpenFile; + fpOpenFile = pOpenFile; + *ppOpenFile = pOpenFile; bail: - delete[] nameBuf; - return dierr; + delete[] nameBuf; + return dierr; } /* * =========================================================================== - * A2FDHFS + * A2FDHFS * =========================================================================== */ @@ -1888,36 +1888,36 @@ bail: DIError A2FDHFS::Read(void* buf, size_t len, size_t* pActual) { - long result; + long result; - WMSG3(" HFS reading %d bytes from '%s' (offset=%ld)\n", - len, fpFile->GetPathName(), hfs_seek(fHfsFile, 0, HFS_SEEK_CUR)); + WMSG3(" HFS reading %d bytes from '%s' (offset=%ld)\n", + len, fpFile->GetPathName(), hfs_seek(fHfsFile, 0, HFS_SEEK_CUR)); - //A2FileHFS* pFile = (A2FileHFS*) fpFile; + //A2FileHFS* pFile = (A2FileHFS*) fpFile; - result = hfs_read(fHfsFile, buf, len); - if (result < 0) - return kDIErrReadFailed; + result = hfs_read(fHfsFile, buf, len); + if (result < 0) + return kDIErrReadFailed; - if (pActual != nil) { - *pActual = (size_t) result; - } else if (result != (long) len) { - // short read, can't report it, return error - return kDIErrDataUnderrun; - } + if (pActual != nil) { + *pActual = (size_t) result; + } else if (result != (long) len) { + // short read, can't report it, return error + return kDIErrDataUnderrun; + } - /* - * To do this right we need to break the hfs_read() into smaller - * pieces. However, it only really affects us for files that are - * getting reformatted, because that's the only time we grab the - * entire thing in one big piece. - */ - long offset = hfs_seek(fHfsFile, 0, HFS_SEEK_CUR); - if (!UpdateProgress(offset)) { - return kDIErrCancelled; - } + /* + * To do this right we need to break the hfs_read() into smaller + * pieces. However, it only really affects us for files that are + * getting reformatted, because that's the only time we grab the + * entire thing in one big piece. + */ + long offset = hfs_seek(fHfsFile, 0, HFS_SEEK_CUR); + if (!UpdateProgress(offset)) { + return kDIErrCancelled; + } - return kDIErrNone; + return kDIErrNone; } /* @@ -1930,38 +1930,38 @@ A2FDHFS::Read(void* buf, size_t len, size_t* pActual) DIError A2FDHFS::Write(const void* buf, size_t len, size_t* pActual) { - long result; + long result; - WMSG3(" HFS writing %d bytes to '%s' (offset=%ld)\n", - len, fpFile->GetPathName(), hfs_seek(fHfsFile, 0, HFS_SEEK_CUR)); + WMSG3(" HFS writing %d bytes to '%s' (offset=%ld)\n", + len, fpFile->GetPathName(), hfs_seek(fHfsFile, 0, HFS_SEEK_CUR)); - fModified = true; // assume something gets changed + fModified = true; // assume something gets changed - //A2FileHFS* pFile = (A2FileHFS*) fpFile; + //A2FileHFS* pFile = (A2FileHFS*) fpFile; - result = hfs_write(fHfsFile, buf, len); - if (result < 0) - return kDIErrWriteFailed; + result = hfs_write(fHfsFile, buf, len); + if (result < 0) + return kDIErrWriteFailed; - if (pActual != nil) { - *pActual = (size_t) result; - } else if (result != (long) len) { - // short write, can't report it, return error - return kDIErrDataUnderrun; - } + if (pActual != nil) { + *pActual = (size_t) result; + } else if (result != (long) len) { + // short write, can't report it, return error + return kDIErrDataUnderrun; + } - /* to make this work right, we need to break hfs_write into pieces */ - long offset = hfs_seek(fHfsFile, 0, HFS_SEEK_CUR); - if (!UpdateProgress(offset)) { - return kDIErrCancelled; - } + /* to make this work right, we need to break hfs_write into pieces */ + long offset = hfs_seek(fHfsFile, 0, HFS_SEEK_CUR); + if (!UpdateProgress(offset)) { + return kDIErrCancelled; + } - /* - * We don't hfs_flush here, because we don't expect the application to - * hold the file open, and we flush in Close(). - */ + /* + * We don't hfs_flush here, because we don't expect the application to + * hold the file open, and we flush in Close(). + */ - return kDIErrNone; + return kDIErrNone; } /* @@ -1970,24 +1970,24 @@ A2FDHFS::Write(const void* buf, size_t len, size_t* pActual) DIError A2FDHFS::Seek(di_off_t offset, DIWhence whence) { - int hfsWhence; - unsigned long result; + int hfsWhence; + unsigned long result; - switch (whence) { - case kSeekSet: hfsWhence = HFS_SEEK_SET; break; - case kSeekEnd: hfsWhence = HFS_SEEK_END; break; - case kSeekCur: hfsWhence = HFS_SEEK_CUR; break; - default: - assert(false); - return kDIErrInvalidArg; - } + switch (whence) { + case kSeekSet: hfsWhence = HFS_SEEK_SET; break; + case kSeekEnd: hfsWhence = HFS_SEEK_END; break; + case kSeekCur: hfsWhence = HFS_SEEK_CUR; break; + default: + assert(false); + return kDIErrInvalidArg; + } - result = hfs_seek(fHfsFile, (long) offset, hfsWhence); - if (result == (unsigned long) -1) { - DebugBreak(); - return kDIErrGeneric; - } - return kDIErrNone; + result = hfs_seek(fHfsFile, (long) offset, hfsWhence); + if (result == (unsigned long) -1) { + DebugBreak(); + return kDIErrGeneric; + } + return kDIErrNone; } /* @@ -1996,11 +1996,11 @@ A2FDHFS::Seek(di_off_t offset, DIWhence whence) di_off_t A2FDHFS::Tell(void) { - di_off_t offset; + di_off_t offset; - /* get current position without moving pointer */ - offset = hfs_seek(fHfsFile, 0, HFS_SEEK_CUR); - return offset; + /* get current position without moving pointer */ + offset = hfs_seek(fHfsFile, 0, HFS_SEEK_CUR); + return offset; } /* @@ -2009,41 +2009,41 @@ A2FDHFS::Tell(void) DIError A2FDHFS::Close(void) { - hfsdirent dirEnt; + hfsdirent dirEnt; - /* - * If the file was written to, update our info. - */ - if (fModified) { - if (hfs_fstat(fHfsFile, &dirEnt) == 0) { - A2FileHFS* pFile = (A2FileHFS*) fpFile; - pFile->fDataLength = dirEnt.u.file.dsize; - pFile->fRsrcLength = dirEnt.u.file.rsize; - if (pFile->fRsrcLength == 0) - pFile->fRsrcLength = -1; - WMSG2(" HFS close set dataLen=%ld rsrcLen=%ld\n", - (long) pFile->fDataLength, (long) pFile->fRsrcLength); - } else { - WMSG1(" HFS Close fstat failed: %s\n", hfs_error); - // close it anyway - } - } + /* + * If the file was written to, update our info. + */ + if (fModified) { + if (hfs_fstat(fHfsFile, &dirEnt) == 0) { + A2FileHFS* pFile = (A2FileHFS*) fpFile; + pFile->fDataLength = dirEnt.u.file.dsize; + pFile->fRsrcLength = dirEnt.u.file.rsize; + if (pFile->fRsrcLength == 0) + pFile->fRsrcLength = -1; + WMSG2(" HFS close set dataLen=%ld rsrcLen=%ld\n", + (long) pFile->fDataLength, (long) pFile->fRsrcLength); + } else { + WMSG1(" HFS Close fstat failed: %s\n", hfs_error); + // close it anyway + } + } - hfs_close(fHfsFile); - fHfsFile = nil; + hfs_close(fHfsFile); + fHfsFile = nil; - /* flush changes */ - if (fModified) { - DiskFSHFS* pDiskFS = (DiskFSHFS*) fpFile->GetDiskFS(); + /* flush changes */ + if (fModified) { + DiskFSHFS* pDiskFS = (DiskFSHFS*) fpFile->GetDiskFS(); - if (hfs_flush(pDiskFS->GetHfsVol()) != 0) { - WMSG0("HEY: Close flush failed!\n"); - DebugBreak(); - } - } + if (hfs_flush(pDiskFS->GetHfsVol()) != 0) { + WMSG0("HEY: Close flush failed!\n"); + DebugBreak(); + } + } - fpFile->CloseDescr(this); - return kDIErrNone; + fpFile->CloseDescr(this); + return kDIErrNone; } /* @@ -2053,16 +2053,16 @@ A2FDHFS::Close(void) long A2FDHFS::GetSectorCount(void) const { - A2FileHFS* pFile = (A2FileHFS*) fpFile; - return (long) ((pFile->fDataLength+255) / 256 + - (pFile->fRsrcLength+255) / 256); + A2FileHFS* pFile = (A2FileHFS*) fpFile; + return (long) ((pFile->fDataLength+255) / 256 + + (pFile->fRsrcLength+255) / 256); } long A2FDHFS::GetBlockCount(void) const { - A2FileHFS* pFile = (A2FileHFS*) fpFile; - return (long) ((pFile->fDataLength+511) / 512 + - (pFile->fRsrcLength+511) / 512); + A2FileHFS* pFile = (A2FileHFS*) fpFile; + return (long) ((pFile->fDataLength+511) / 512 + + (pFile->fRsrcLength+511) / 512); } /* @@ -2071,7 +2071,7 @@ A2FDHFS::GetBlockCount(void) const DIError A2FDHFS::GetStorage(long sectorIdx, long* pTrack, long* pSector) const { - return kDIErrNotSupported; + return kDIErrNotSupported; } /* * Return the Nth 512-byte block in this file. Not supported. @@ -2079,7 +2079,7 @@ A2FDHFS::GetStorage(long sectorIdx, long* pTrack, long* pSector) const DIError A2FDHFS::GetStorage(long blockIdx, long* pBlock) const { - return kDIErrNotSupported; + return kDIErrNotSupported; } @@ -2097,19 +2097,19 @@ A2FDHFS::GetStorage(long blockIdx, long* pBlock) const DIError DiskFSHFS::Initialize(InitMode initMode) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - dierr = LoadVolHeader(); - if (dierr != kDIErrNone) - goto bail; - DumpVolHeader(); + dierr = LoadVolHeader(); + if (dierr != kDIErrNone) + goto bail; + DumpVolHeader(); - CreateFakeFile(); + CreateFakeFile(); - SetVolumeUsageMap(); + SetVolumeUsageMap(); bail: - return dierr; + return dierr; } @@ -2119,9 +2119,9 @@ bail: void DiskFSHFS::CreateFakeFile(void) { - A2FileHFS* pFile; - char buf[768]; // currently running about 475 - static const char* kFormatMsg = + A2FileHFS* pFile; + char buf[768]; // currently running about 475 + static const char* kFormatMsg = "The Macintosh HFS filesystem is not supported. CiderPress knows how to\r" "recognize HFS volumes so that it can identify partitions on CFFA-formatted\r" "CompactFlash cards and Apple II CD-ROMs, but the current version does not\r" @@ -2136,59 +2136,59 @@ DiskFSHFS::CreateFakeFile(void) " Last modified : %s\r" "\r" ; - char dateBuf[32]; - long capacity; - const char* timeStr; + char dateBuf[32]; + long capacity; + const char* timeStr; - capacity = (fAllocationBlockSize / kBlkSize) * fNumAllocationBlocks; + capacity = (fAllocationBlockSize / kBlkSize) * fNumAllocationBlocks; - /* get the mod time, format it, and remove the trailing '\n' */ - time_t when = - (time_t) (fModifiedDateTime - kDateTimeOffset - fLocalTimeOffset); - timeStr = ctime(&when); - if (timeStr == nil) { - WMSG2("Invalid date %ld (orig=%ld)\n", when, fModifiedDateTime); - strcpy(dateBuf, ""); - } else - strncpy(dateBuf, timeStr, sizeof(dateBuf)); - int len = strlen(dateBuf); - if (len > 0) - dateBuf[len-1] = '\0'; + /* get the mod time, format it, and remove the trailing '\n' */ + time_t when = + (time_t) (fModifiedDateTime - kDateTimeOffset - fLocalTimeOffset); + timeStr = ctime(&when); + if (timeStr == nil) { + WMSG2("Invalid date %ld (orig=%ld)\n", when, fModifiedDateTime); + strcpy(dateBuf, ""); + } else + strncpy(dateBuf, timeStr, sizeof(dateBuf)); + int len = strlen(dateBuf); + if (len > 0) + dateBuf[len-1] = '\0'; - memset(buf, 0, sizeof(buf)); - sprintf(buf, kFormatMsg, - fVolumeName, - capacity, - (double) capacity / 2048.0, - fNumFiles, - fNumDirectories, - dateBuf); + memset(buf, 0, sizeof(buf)); + sprintf(buf, kFormatMsg, + fVolumeName, + capacity, + (double) capacity / 2048.0, + fNumFiles, + fNumDirectories, + dateBuf); - pFile = new A2FileHFS(this); + pFile = new A2FileHFS(this); pFile->fIsDir = false; pFile->fIsVolumeDir = false; pFile->fType = 0; pFile->fCreator = 0; - pFile->SetFakeFile(buf, strlen(buf)); - strcpy(pFile->fFileName, "(not supported)"); + pFile->SetFakeFile(buf, strlen(buf)); + strcpy(pFile->fFileName, "(not supported)"); pFile->SetPathName("", pFile->fFileName); pFile->fDataLength = 0; pFile->fRsrcLength = -1; - pFile->fCreateWhen = 0; - pFile->fModWhen = 0; + pFile->fCreateWhen = 0; + pFile->fModWhen = 0; - pFile->SetFakeFile(buf, strlen(buf)); + pFile->SetFakeFile(buf, strlen(buf)); - AddFileToList(pFile); + AddFileToList(pFile); } /* * We could do this, but there's not much point. */ DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const + int* pUnitSize) const { - return kDIErrNotSupported; + return kDIErrNotSupported; } /* @@ -2196,28 +2196,28 @@ DIError GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, */ DIError A2FileHFS::Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork /*=false*/) + bool rsrcFork /*=false*/) { - A2FDHFS* pOpenFile = nil; + A2FDHFS* pOpenFile = nil; - if (fpOpenFile != nil) - return kDIErrAlreadyOpen; - if (rsrcFork && fRsrcLength < 0) - return kDIErrForkNotFound; - assert(readOnly == true); + if (fpOpenFile != nil) + return kDIErrAlreadyOpen; + if (rsrcFork && fRsrcLength < 0) + return kDIErrForkNotFound; + assert(readOnly == true); - pOpenFile = new A2FDHFS(this, nil); + pOpenFile = new A2FDHFS(this, nil); - fpOpenFile = pOpenFile; - *ppOpenFile = pOpenFile; + fpOpenFile = pOpenFile; + *ppOpenFile = pOpenFile; - return kDIErrNone; + return kDIErrNone; } /* * =========================================================================== - * A2FDHFS + * A2FDHFS * =========================================================================== */ @@ -2227,25 +2227,25 @@ A2FileHFS::Open(A2FileDescr** ppOpenFile, bool readOnly, DIError A2FDHFS::Read(void* buf, size_t len, size_t* pActual) { - WMSG3(" HFS reading %d bytes from '%s' (offset=%ld)\n", - len, fpFile->GetPathName(), (long) fOffset); + WMSG3(" HFS reading %d bytes from '%s' (offset=%ld)\n", + len, fpFile->GetPathName(), (long) fOffset); - A2FileHFS* pFile = (A2FileHFS*) fpFile; + A2FileHFS* pFile = (A2FileHFS*) fpFile; - /* don't allow them to read past the end of the file */ - if (fOffset + (long)len > pFile->fDataLength) { - if (pActual == nil) - return kDIErrDataUnderrun; - len = (size_t) (pFile->fDataLength - fOffset); - } - if (pActual != nil) - *pActual = len; + /* don't allow them to read past the end of the file */ + if (fOffset + (long)len > pFile->fDataLength) { + if (pActual == nil) + return kDIErrDataUnderrun; + len = (size_t) (pFile->fDataLength - fOffset); + } + if (pActual != nil) + *pActual = len; - memcpy(buf, pFile->GetFakeFileBuf(), len); + memcpy(buf, pFile->GetFakeFileBuf(), len); - fOffset += len; + fOffset += len; - return kDIErrNone; + return kDIErrNone; } /* @@ -2254,7 +2254,7 @@ A2FDHFS::Read(void* buf, size_t len, size_t* pActual) DIError A2FDHFS::Write(const void* buf, size_t len, size_t* pActual) { - return kDIErrNotSupported; + return kDIErrNotSupported; } /* @@ -2263,34 +2263,34 @@ A2FDHFS::Write(const void* buf, size_t len, size_t* pActual) DIError A2FDHFS::Seek(di_off_t offset, DIWhence whence) { - di_off_t fileLen = ((A2FileHFS*) fpFile)->fDataLength; + di_off_t fileLen = ((A2FileHFS*) fpFile)->fDataLength; - switch (whence) { - case kSeekSet: - if (offset < 0 || offset > fileLen) - return kDIErrInvalidArg; - fOffset = offset; - break; - case kSeekEnd: - if (offset > 0 || offset < -fileLen) - return kDIErrInvalidArg; - fOffset = fileLen + offset; - break; - case kSeekCur: - if (offset < -fOffset || - offset >= (fileLen - fOffset)) - { - return kDIErrInvalidArg; - } - fOffset += offset; - break; - default: - assert(false); - return kDIErrInvalidArg; - } + switch (whence) { + case kSeekSet: + if (offset < 0 || offset > fileLen) + return kDIErrInvalidArg; + fOffset = offset; + break; + case kSeekEnd: + if (offset > 0 || offset < -fileLen) + return kDIErrInvalidArg; + fOffset = fileLen + offset; + break; + case kSeekCur: + if (offset < -fOffset || + offset >= (fileLen - fOffset)) + { + return kDIErrInvalidArg; + } + fOffset += offset; + break; + default: + assert(false); + return kDIErrInvalidArg; + } - assert(fOffset >= 0 && fOffset <= fileLen); - return kDIErrNone; + assert(fOffset >= 0 && fOffset <= fileLen); + return kDIErrNone; } /* @@ -2299,7 +2299,7 @@ A2FDHFS::Seek(di_off_t offset, DIWhence whence) di_off_t A2FDHFS::Tell(void) { - return fOffset; + return fOffset; } /* @@ -2308,8 +2308,8 @@ A2FDHFS::Tell(void) DIError A2FDHFS::Close(void) { - fpFile->CloseDescr(this); - return kDIErrNone; + fpFile->CloseDescr(this); + return kDIErrNone; } /* @@ -2318,14 +2318,14 @@ A2FDHFS::Close(void) long A2FDHFS::GetSectorCount(void) const { - A2FileHFS* pFile = (A2FileHFS*) fpFile; - return (long) ((pFile->fDataLength+255) / 256); + A2FileHFS* pFile = (A2FileHFS*) fpFile; + return (long) ((pFile->fDataLength+255) / 256); } long A2FDHFS::GetBlockCount(void) const { - A2FileHFS* pFile = (A2FileHFS*) fpFile; - return (long) ((pFile->fDataLength+511) / 512); + A2FileHFS* pFile = (A2FileHFS*) fpFile; + return (long) ((pFile->fDataLength+511) / 512); } /* @@ -2334,7 +2334,7 @@ A2FDHFS::GetBlockCount(void) const DIError A2FDHFS::GetStorage(long sectorIdx, long* pTrack, long* pSector) const { - return kDIErrNotSupported; + return kDIErrNotSupported; } /* * Return the Nth 512-byte block in this file. @@ -2342,7 +2342,7 @@ A2FDHFS::GetStorage(long sectorIdx, long* pTrack, long* pSector) const DIError A2FDHFS::GetStorage(long blockIdx, long* pBlock) const { - return kDIErrNotSupported; + return kDIErrNotSupported; } -#endif // EXCISE_GPL_CODE --------------------------------------------------- +#endif // EXCISE_GPL_CODE --------------------------------------------------- diff --git a/diskimg/ImageWrapper.cpp b/diskimg/ImageWrapper.cpp index 6158562..c2d77bb 100644 --- a/diskimg/ImageWrapper.cpp +++ b/diskimg/ImageWrapper.cpp @@ -32,7 +32,7 @@ /* * =========================================================================== - * 2MG (a/k/a 2IMG) + * 2MG (a/k/a 2IMG) * =========================================================================== */ @@ -45,18 +45,18 @@ /*static*/ DIError Wrapper2MG::Test(GenericFD* pGFD, di_off_t wrappedLength) { - TwoImgHeader header; + TwoImgHeader header; - WMSG0("Testing for 2MG\n"); + WMSG0("Testing for 2MG\n"); - // HEY: should test for wrappedLength > 2GB; if so, skip + // HEY: should test for wrappedLength > 2GB; if so, skip - pGFD->Rewind(); - if (header.ReadHeader(pGFD, (long) wrappedLength) != 0) - return kDIErrGeneric; + pGFD->Rewind(); + if (header.ReadHeader(pGFD, (long) wrappedLength) != 0) + return kDIErrGeneric; - WMSG0("Looks like valid 2MG\n"); - return kDIErrNone; + WMSG0("Looks like valid 2MG\n"); + return kDIErrNone; } /* @@ -65,30 +65,30 @@ Wrapper2MG::Test(GenericFD* pGFD, di_off_t wrappedLength) DIError Wrapper2MG::Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) { - TwoImgHeader header; + TwoImgHeader header; long offset; - WMSG0("Prepping for 2MG\n"); - pGFD->Rewind(); - if (header.ReadHeader(pGFD, (long) wrappedLength) != 0) - return kDIErrGeneric; + WMSG0("Prepping for 2MG\n"); + pGFD->Rewind(); + if (header.ReadHeader(pGFD, (long) wrappedLength) != 0) + return kDIErrGeneric; - offset = header.fDataOffset; + offset = header.fDataOffset; if (header.fFlags & TwoImgHeader::kDOSVolumeSet) *pDiskVolNum = header.GetDOSVolumeNum(); - *pLength = header.fDataLen; - *pPhysical = DiskImg::kPhysicalFormatSectors; - if (header.fImageFormat == TwoImgHeader::kImageFormatDOS) - *pOrder = DiskImg::kSectorOrderDOS; - else if (header.fImageFormat == TwoImgHeader::kImageFormatProDOS) - *pOrder = DiskImg::kSectorOrderProDOS; - else if (header.fImageFormat == TwoImgHeader::kImageFormatNibble) { - *pOrder = DiskImg::kSectorOrderPhysical; + *pLength = header.fDataLen; + *pPhysical = DiskImg::kPhysicalFormatSectors; + if (header.fImageFormat == TwoImgHeader::kImageFormatDOS) + *pOrder = DiskImg::kSectorOrderDOS; + else if (header.fImageFormat == TwoImgHeader::kImageFormatProDOS) + *pOrder = DiskImg::kSectorOrderProDOS; + else if (header.fImageFormat == TwoImgHeader::kImageFormatNibble) { + *pOrder = DiskImg::kSectorOrderPhysical; if (*pLength == kTrackCount525 * kTrackLenNib525) { WMSG0(" Prepping for 6656-byte 2MG-NIB\n"); *pPhysical = DiskImg::kPhysicalFormatNib525_6656; @@ -123,7 +123,7 @@ Wrapper2MG::Create(di_off_t length, DiskImg::PhysicalFormat physical, return kDIErrInvalidArg; } header.InitHeader(TwoImgHeader::kImageFormatNibble, (long) length, - 8 * kTrackCount525); // 8 blocks per track + 8 * kTrackCount525); // 8 blocks per track break; case DiskImg::kPhysicalFormatSectors: if ((length % 512) != 0) { @@ -132,18 +132,18 @@ Wrapper2MG::Create(di_off_t length, DiskImg::PhysicalFormat physical, } if (order == DiskImg::kSectorOrderProDOS) cc = header.InitHeader(TwoImgHeader::kImageFormatProDOS, - (long) length, (long) length / 512); + (long) length, (long) length / 512); else if (order == DiskImg::kSectorOrderDOS) cc = header.InitHeader(TwoImgHeader::kImageFormatDOS, - (long) length, (long) length / 512); + (long) length, (long) length / 512); else { WMSG1("Invalid 2MG sector order %d\n", order); return kDIErrInvalidArg; } - if (cc != 0) { - WMSG1("TwoImg InitHeader failed (len=%ld)\n", (long) length); - return kDIErrInvalidArg; - } + if (cc != 0) { + WMSG1("TwoImg InitHeader failed (len=%ld)\n", (long) length); + return kDIErrInvalidArg; + } break; default: WMSG1("Invalid 2MG physical %d\n", physical); @@ -159,14 +159,14 @@ Wrapper2MG::Create(di_off_t length, DiskImg::PhysicalFormat physical, return kDIErrGeneric; } - long footerLen = header.fCmtLen + header.fCreatorLen; - if (footerLen > 0) { - // This is currently impossible, which is good because the Seek call - // will fail if pWrapperGFD is a buffer. - assert(false); - pWrapperGFD->Seek(header.fDataOffset + length, kSeekSet); - header.WriteFooter(pWrapperGFD); - } + long footerLen = header.fCmtLen + header.fCreatorLen; + if (footerLen > 0) { + // This is currently impossible, which is good because the Seek call + // will fail if pWrapperGFD is a buffer. + assert(false); + pWrapperGFD->Seek(header.fDataOffset + length, kSeekSet); + header.WriteFooter(pWrapperGFD); + } long offset = header.fDataOffset; @@ -195,7 +195,7 @@ Wrapper2MG::Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, /* * =========================================================================== - * SHK (ShrinkIt NuFX), also .SDK and .BXY + * SHK (ShrinkIt NuFX), also .SDK and .BXY * =========================================================================== */ @@ -210,17 +210,17 @@ Wrapper2MG::Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, /*static*/ NuResult WrapperNuFX::ErrMsgHandler(NuArchive* /*pArchive*/, void* vErrorMessage) { - const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage; + const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage; if (pErrorMessage->isDebug) { - Global::PrintDebugMsg(pErrorMessage->file, pErrorMessage->line, + Global::PrintDebugMsg(pErrorMessage->file, pErrorMessage->line, "[D] %s\n", pErrorMessage->message); } else { Global::PrintDebugMsg(pErrorMessage->file, pErrorMessage->line, "%s\n", pErrorMessage->message); } - return kNuOK; + return kNuOK; } /* @@ -231,120 +231,120 @@ WrapperNuFX::ErrMsgHandler(NuArchive* /*pArchive*/, void* vErrorMessage) */ /*static*/ DIError WrapperNuFX::OpenNuFX(const char* pathName, NuArchive** ppArchive, - NuThreadIdx* pThreadIdx, long* pLength, bool readOnly) + NuThreadIdx* pThreadIdx, long* pLength, bool readOnly) { - NuError nerr = kNuErrNone; - NuArchive* pArchive = nil; - NuRecordIdx recordIdx; - NuAttr attr; - const NuRecord* pRecord; - const NuThread* pThread = nil; - int idx; + NuError nerr = kNuErrNone; + NuArchive* pArchive = nil; + NuRecordIdx recordIdx; + NuAttr attr; + const NuRecord* pRecord; + const NuThread* pThread = nil; + int idx; - WMSG1("Opening file '%s' to test for NuFX\n", pathName); + WMSG1("Opening file '%s' to test for NuFX\n", pathName); - /* - * Open the archive. - */ - if (readOnly) { - nerr = NuOpenRO(pathName, &pArchive); - if (nerr != kNuErrNone) { - WMSG1(" NuFX unable to open archive (err=%d)\n", nerr); - goto bail; - } - } else { - char* tmpPath; + /* + * Open the archive. + */ + if (readOnly) { + nerr = NuOpenRO(pathName, &pArchive); + if (nerr != kNuErrNone) { + WMSG1(" NuFX unable to open archive (err=%d)\n", nerr); + goto bail; + } + } else { + char* tmpPath; - tmpPath = GenTempPath(pathName); - if (tmpPath == nil) { - nerr = kNuErrInternal; - goto bail; - } + tmpPath = GenTempPath(pathName); + if (tmpPath == nil) { + nerr = kNuErrInternal; + goto bail; + } - nerr = NuOpenRW(pathName, tmpPath, 0, &pArchive); - if (nerr != kNuErrNone) { - WMSG1(" NuFX OpenRW failed (nerr=%d)\n", nerr); - nerr = kNuErrGeneric; - delete[] tmpPath; - goto bail; - } - delete[] tmpPath; - } + nerr = NuOpenRW(pathName, tmpPath, 0, &pArchive); + if (nerr != kNuErrNone) { + WMSG1(" NuFX OpenRW failed (nerr=%d)\n", nerr); + nerr = kNuErrGeneric; + delete[] tmpPath; + goto bail; + } + delete[] tmpPath; + } NuSetErrorMessageHandler(pArchive, ErrMsgHandler); - nerr = NuGetAttr(pArchive, kNuAttrNumRecords, &attr); - if (nerr != kNuErrNone) { - WMSG1(" NuFX unable to get record count (err=%d)\n", nerr); - goto bail; - } - if (attr != 1) { - WMSG1(" NuFX archive has %ld entries, not disk-only\n", attr); - nerr = kNuErrGeneric; - if (attr > 1) - goto file_archive; - else - goto bail; // shouldn't get zero-count archives, but... - } + nerr = NuGetAttr(pArchive, kNuAttrNumRecords, &attr); + if (nerr != kNuErrNone) { + WMSG1(" NuFX unable to get record count (err=%d)\n", nerr); + goto bail; + } + if (attr != 1) { + WMSG1(" NuFX archive has %ld entries, not disk-only\n", attr); + nerr = kNuErrGeneric; + if (attr > 1) + goto file_archive; + else + goto bail; // shouldn't get zero-count archives, but... + } - /* get the first record */ - nerr = NuGetRecordIdxByPosition(pArchive, 0, &recordIdx); - if (nerr != kNuErrNone) { - WMSG1(" NuFX unable to get first recordIdx (err=%d)\n", nerr); - goto bail; - } - nerr = NuGetRecord(pArchive, recordIdx, &pRecord); - if (nerr != kNuErrNone) { - WMSG1(" NuFX unable to get first record (err=%d)\n", nerr); - goto bail; - } + /* get the first record */ + nerr = NuGetRecordIdxByPosition(pArchive, 0, &recordIdx); + if (nerr != kNuErrNone) { + WMSG1(" NuFX unable to get first recordIdx (err=%d)\n", nerr); + goto bail; + } + nerr = NuGetRecord(pArchive, recordIdx, &pRecord); + if (nerr != kNuErrNone) { + WMSG1(" NuFX unable to get first record (err=%d)\n", nerr); + goto bail; + } - /* find a disk image thread */ - for (idx = 0; idx < (int)NuRecordGetNumThreads(pRecord); idx++) { - pThread = NuGetThread(pRecord, idx); + /* find a disk image thread */ + for (idx = 0; idx < (int)NuRecordGetNumThreads(pRecord); idx++) { + pThread = NuGetThread(pRecord, idx); - if (NuGetThreadID(pThread) == kNuThreadIDDiskImage) - break; - } - if (idx == (int)NuRecordGetNumThreads(pRecord)) { - WMSG0(" NuFX no disk image found in first record\n"); - nerr = kNuErrGeneric; - goto file_archive; - } - assert(pThread != nil); - *pThreadIdx = pThread->threadIdx; + if (NuGetThreadID(pThread) == kNuThreadIDDiskImage) + break; + } + if (idx == (int)NuRecordGetNumThreads(pRecord)) { + WMSG0(" NuFX no disk image found in first record\n"); + nerr = kNuErrGeneric; + goto file_archive; + } + assert(pThread != nil); + *pThreadIdx = pThread->threadIdx; - /* - * Don't allow zero-length disks. - */ - *pLength = pThread->actualThreadEOF; - if (!*pLength) { - WMSG1(" NuFX length of disk image is bad (%ld)\n", *pLength); - nerr = kNuErrGeneric; - goto bail; - } + /* + * Don't allow zero-length disks. + */ + *pLength = pThread->actualThreadEOF; + if (!*pLength) { + WMSG1(" NuFX length of disk image is bad (%ld)\n", *pLength); + nerr = kNuErrGeneric; + goto bail; + } - /* - * Success! - */ - assert(nerr == kNuErrNone); - *ppArchive = pArchive; - pArchive = nil; + /* + * Success! + */ + assert(nerr == kNuErrNone); + *ppArchive = pArchive; + pArchive = nil; bail: - if (pArchive != nil) - NuClose(pArchive); - if (nerr == kNuErrNone) - return kDIErrNone; - else if (nerr == kNuErrBadMHCRC || nerr == kNuErrBadRHCRC) - return kDIErrBadChecksum; - else - return kDIErrGeneric; + if (pArchive != nil) + NuClose(pArchive); + if (nerr == kNuErrNone) + return kDIErrNone; + else if (nerr == kNuErrBadMHCRC || nerr == kNuErrBadRHCRC) + return kDIErrBadChecksum; + else + return kDIErrGeneric; file_archive: - if (pArchive != nil) - NuClose(pArchive); - return kDIErrFileArchive; + if (pArchive != nil) + NuClose(pArchive); + return kDIErrFileArchive; } /* @@ -364,53 +364,53 @@ file_archive: */ DIError WrapperNuFX::GetNuFXDiskImage(NuArchive* pArchive, NuThreadIdx threadIdx, - long length, char** ppData) + long length, char** ppData) { - NuError err; - NuDataSink* pDataSink = nil; - unsigned char* buf = nil; + NuError err; + NuDataSink* pDataSink = nil; + unsigned char* buf = nil; - assert(length > 0); - buf = new unsigned char[length]; - if (buf == nil) - return kDIErrMalloc; + assert(length > 0); + buf = new unsigned char[length]; + if (buf == nil) + return kDIErrMalloc; - /* - * Create a buffer and expand the disk image into it. - */ + /* + * Create a buffer and expand the disk image into it. + */ err = NuCreateDataSinkForBuffer(true, kNuConvertOff, buf, length, - &pDataSink); - if (err != kNuErrNone) { - WMSG1(" NuFX: unable to create data sink (err=%d)\n", err); - goto bail; - } + &pDataSink); + if (err != kNuErrNone) { + WMSG1(" NuFX: unable to create data sink (err=%d)\n", err); + goto bail; + } - err = NuExtractThread(pArchive, threadIdx, pDataSink); - if (err != kNuErrNone) { - WMSG1(" NuFX: unable to extract thread (err=%d)\n", err); - goto bail; - } + err = NuExtractThread(pArchive, threadIdx, pDataSink); + if (err != kNuErrNone) { + WMSG1(" NuFX: unable to extract thread (err=%d)\n", err); + goto bail; + } - //err = kNuErrBadThreadCRC; goto bail; // debug test only + //err = kNuErrBadThreadCRC; goto bail; // debug test only - *ppData = (char*)buf; + *ppData = (char*)buf; bail: - NuFreeDataSink(pDataSink); - if (err != kNuErrNone) { - WMSG1(" NuFX GetNuFXDiskImage returning after nuerr=%d\n", err); - delete buf; - } - if (err == kNuErrNone) - return kDIErrNone; - else if (err == kNuErrBadDataCRC || err == kNuErrBadThreadCRC) - return kDIErrBadChecksum; + NuFreeDataSink(pDataSink); + if (err != kNuErrNone) { + WMSG1(" NuFX GetNuFXDiskImage returning after nuerr=%d\n", err); + delete buf; + } + if (err == kNuErrNone) + return kDIErrNone; + else if (err == kNuErrBadDataCRC || err == kNuErrBadThreadCRC) + return kDIErrBadChecksum; else if (err == kNuErrBadData) return kDIErrBadCompressedData; - else if (err == kNuErrBadFormat) - return kDIErrUnsupportedCompression; - else - return kDIErrGeneric; + else if (err == kNuErrBadFormat) + return kDIErrUnsupportedCompression; + else + return kDIErrGeneric; } /* @@ -420,27 +420,27 @@ bail: /*static*/ DIError WrapperNuFX::Test(GenericFD* pGFD, di_off_t wrappedLength) { - DIError dierr; - NuArchive* pArchive = nil; - NuThreadIdx threadIdx; - long length; + DIError dierr; + NuArchive* pArchive = nil; + NuThreadIdx threadIdx; + long length; const char* imagePath; imagePath = pGFD->GetPathName(); - if (imagePath == nil) { - WMSG0("Can't test NuFX on non-file\n"); - return kDIErrNotSupported; - } - WMSG0("Testing for NuFX\n"); - dierr = OpenNuFX(imagePath, &pArchive, &threadIdx, &length, true); - if (dierr != kDIErrNone) - return dierr; + if (imagePath == nil) { + WMSG0("Can't test NuFX on non-file\n"); + return kDIErrNotSupported; + } + WMSG0("Testing for NuFX\n"); + dierr = OpenNuFX(imagePath, &pArchive, &threadIdx, &length, true); + if (dierr != kDIErrNone) + return dierr; - /* success; throw away state in case they don't like us anyway */ - assert(pArchive != nil); - NuClose(pArchive); - - return kDIErrNone; + /* success; throw away state in case they don't like us anyway */ + assert(pArchive != nil); + NuClose(pArchive); + + return kDIErrNone; } /* @@ -449,56 +449,56 @@ WrapperNuFX::Test(GenericFD* pGFD, di_off_t wrappedLength) DIError WrapperNuFX::Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) { - DIError dierr = kDIErrNone; - NuThreadIdx threadIdx; - GFDBuffer* pNewGFD = nil; - char* buf = nil; - long length = -1; + DIError dierr = kDIErrNone; + NuThreadIdx threadIdx; + GFDBuffer* pNewGFD = nil; + char* buf = nil; + long length = -1; const char* imagePath; imagePath = pGFD->GetPathName(); - if (imagePath == nil) { - assert(false); // should've been caught in Test - return kDIErrNotSupported; - } - pGFD->Close(); // don't hold the file open - dierr = OpenNuFX(imagePath, &fpArchive, &threadIdx, &length, readOnly); - if (dierr != kDIErrNone) - goto bail; + if (imagePath == nil) { + assert(false); // should've been caught in Test + return kDIErrNotSupported; + } + pGFD->Close(); // don't hold the file open + dierr = OpenNuFX(imagePath, &fpArchive, &threadIdx, &length, readOnly); + if (dierr != kDIErrNone) + goto bail; - dierr = GetNuFXDiskImage(fpArchive, threadIdx, length, &buf); - if (dierr != kDIErrNone) - goto bail; + dierr = GetNuFXDiskImage(fpArchive, threadIdx, length, &buf); + if (dierr != kDIErrNone) + goto bail; - pNewGFD = new GFDBuffer; - dierr = pNewGFD->Open(buf, length, true, false, readOnly); - if (dierr != kDIErrNone) - goto bail; - buf = nil; // now owned by pNewGFD; + pNewGFD = new GFDBuffer; + dierr = pNewGFD->Open(buf, length, true, false, readOnly); + if (dierr != kDIErrNone) + goto bail; + buf = nil; // now owned by pNewGFD; - /* - * Success! - */ - assert(dierr == kDIErrNone); - *ppNewGFD = pNewGFD; - *pLength = length; - *pPhysical = DiskImg::kPhysicalFormatSectors; - *pOrder = DiskImg::kSectorOrderProDOS; + /* + * Success! + */ + assert(dierr == kDIErrNone); + *ppNewGFD = pNewGFD; + *pLength = length; + *pPhysical = DiskImg::kPhysicalFormatSectors; + *pOrder = DiskImg::kSectorOrderProDOS; WMSG1(" NuFX is ready, threadIdx=%ld\n", threadIdx); fThreadIdx = threadIdx; bail: - if (dierr != kDIErrNone) { - NuClose(fpArchive); + if (dierr != kDIErrNone) { + NuClose(fpArchive); fpArchive = nil; - delete pNewGFD; - delete buf; - } - return dierr; + delete pNewGFD; + delete buf; + } + return dierr; } /* @@ -571,12 +571,12 @@ WrapperNuFX::Create(di_off_t length, DiskImg::PhysicalFormat physical, * makes pWrapperGFD invalid, but such is life with NufxLib.) */ imagePath = pWrapperGFD->GetPathName(); - if (imagePath == nil) { - assert(false); // must not have an outer wrapper - dierr = kDIErrNotSupported; + if (imagePath == nil) { + assert(false); // must not have an outer wrapper + dierr = kDIErrNotSupported; goto bail; - } - pWrapperGFD->Close(); // don't hold the file open + } + pWrapperGFD->Close(); // don't hold the file open tmpPath = GenTempPath(imagePath); if (tmpPath == nil) { dierr = kDIErrInternal; @@ -593,22 +593,22 @@ WrapperNuFX::Create(di_off_t length, DiskImg::PhysicalFormat physical, /* * Create a blank chunk of memory for the image. */ - assert(length > 0); - buf = new unsigned char[(int) length]; - if (buf == nil) { + assert(length > 0); + buf = new unsigned char[(int) length]; + if (buf == nil) { dierr = kDIErrMalloc; goto bail; } GFDBuffer* pNewGFD; - pNewGFD = new GFDBuffer; - dierr = pNewGFD->Open(buf, length, true, false, false); - if (dierr != kDIErrNone) { + pNewGFD = new GFDBuffer; + dierr = pNewGFD->Open(buf, length, true, false, false); + if (dierr != kDIErrNone) { delete pNewGFD; - goto bail; + goto bail; } *pDataFD = pNewGFD; - buf = nil; // now owned by pNewGFD; + buf = nil; // now owned by pNewGFD; /* * Success! Set misc stuff. @@ -628,17 +628,17 @@ bail: DIError WrapperNuFX::CloseNuFX(void) { - NuError nerr; + NuError nerr; /* throw away any un-flushed changes so that "close" can't fail */ (void) NuAbort(fpArchive); - nerr = NuClose(fpArchive); - if (nerr != kNuErrNone) { - WMSG0("WARNING: NuClose failed\n"); - return kDIErrGeneric; - } - return kDIErrNone; + nerr = NuClose(fpArchive); + if (nerr != kNuErrNone) { + WMSG0("WARNING: NuClose failed\n"); + return kDIErrGeneric; + } + return kDIErrNone; } /* @@ -660,34 +660,34 @@ WrapperNuFX::Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, NuThreadIdx threadIdx; NuDataSource* pDataSource = nil; - if (fThreadIdx != 0) { - /* - * Mark the old record for deletion. - */ - nerr = NuGetRecordIdxByPosition(fpArchive, 0, &recordIdx); - if (nerr != kNuErrNone) { - WMSG1(" NuFX unable to get first recordIdx (err=%d)\n", nerr); - goto bail; - } - nerr = NuDeleteRecord(fpArchive, recordIdx); - if (nerr != kNuErrNone) { - WMSG1(" NuFX unable to delete first record (err=%d)\n", nerr); - goto bail; - } - } + if (fThreadIdx != 0) { + /* + * Mark the old record for deletion. + */ + nerr = NuGetRecordIdxByPosition(fpArchive, 0, &recordIdx); + if (nerr != kNuErrNone) { + WMSG1(" NuFX unable to get first recordIdx (err=%d)\n", nerr); + goto bail; + } + nerr = NuDeleteRecord(fpArchive, recordIdx); + if (nerr != kNuErrNone) { + WMSG1(" NuFX unable to delete first record (err=%d)\n", nerr); + goto bail; + } + } assert((dataLen % 512) == 0); - nerr = NuSetValue(fpArchive, kNuValueDataCompression, - fCompressType + kNuCompressNone); - if (nerr != kNuErrNone) { - WMSG1("WARNING: unable to set compression to format %d\n", - fCompressType); - nerr = kNuErrNone; - } else { - WMSG2(" NuFX set compression to %d/%d\n", fCompressType, - fCompressType + kNuCompressNone); - } + nerr = NuSetValue(fpArchive, kNuValueDataCompression, + fCompressType + kNuCompressNone); + if (nerr != kNuErrNone) { + WMSG1("WARNING: unable to set compression to format %d\n", + fCompressType); + nerr = kNuErrNone; + } else { + WMSG2(" NuFX set compression to %d/%d\n", fCompressType, + fCompressType + kNuCompressNone); + } /* * Fill out the fileDetails record appropriately. @@ -757,8 +757,8 @@ WrapperNuFX::Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, goto bail; } - /* update the threadID */ - fThreadIdx = threadIdx; + /* update the threadID */ + fThreadIdx = threadIdx; bail: NuFreeDataSource(pDataSource); @@ -792,7 +792,7 @@ WrapperNuFX::UNIXTimeToDateTime(const time_t* pWhen, NuDateTime *pDateTime) /* * =========================================================================== - * DDD (DDD 2.1, DDD Pro) + * DDD (DDD 2.1, DDD Pro) * =========================================================================== */ @@ -807,7 +807,7 @@ WrapperDDD::Test(GenericFD* pGFD, di_off_t wrappedLength) { DIError dierr; GenericFD* pNewGFD = nil; - WMSG0("Testing for DDD\n"); + WMSG0("Testing for DDD\n"); pGFD->Rewind(); @@ -849,27 +849,27 @@ WrapperDDD::Test(GenericFD* pGFD, di_off_t wrappedLength) /*static*/ DIError WrapperDDD::CheckForRuns(GenericFD* pGFD) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; int kRunThreshold = 5; unsigned char buf[8192]; size_t bufCount; int runLen; - di_off_t fileLen; + di_off_t fileLen; int i; - dierr = pGFD->Seek(0, kSeekEnd); - if (dierr != kDIErrNone) - goto bail; - fileLen = pGFD->Tell(); - pGFD->Rewind(); + dierr = pGFD->Seek(0, kSeekEnd); + if (dierr != kDIErrNone) + goto bail; + fileLen = pGFD->Tell(); + pGFD->Rewind(); - fileLen -= 256; // could be extra data from DOS DDD + fileLen -= 256; // could be extra data from DOS DDD while (fileLen) { - bufCount = (size_t) fileLen; - if (bufCount > sizeof(buf)) - bufCount = sizeof(buf); - fileLen -= bufCount; + bufCount = (size_t) fileLen; + if (bufCount > sizeof(buf)) + bufCount = sizeof(buf); + fileLen -= bufCount; dierr = pGFD->Read(buf, bufCount); if (dierr != kDIErrNone) @@ -907,11 +907,11 @@ bail: DIError WrapperDDD::Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) { DIError dierr; - WMSG0("Prepping for DDD\n"); + WMSG0("Prepping for DDD\n"); assert(*ppNewGFD == nil); @@ -919,9 +919,9 @@ WrapperDDD::Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, if (dierr != kDIErrNone) return dierr; - *pLength = kNumTracks * kTrackLen; - *pPhysical = DiskImg::kPhysicalFormatSectors; - *pOrder = DiskImg::kSectorOrderDOS; + *pLength = kNumTracks * kTrackLen; + *pPhysical = DiskImg::kPhysicalFormatSectors; + *pOrder = DiskImg::kSectorOrderDOS; return dierr; } @@ -934,11 +934,11 @@ WrapperDDD::Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, WrapperDDD::Unpack(GenericFD* pGFD, GenericFD** ppNewGFD, short* pDiskVolNum) { DIError dierr; - GFDBuffer* pNewGFD = nil; + GFDBuffer* pNewGFD = nil; unsigned char* buf = nil; short diskVolNum; - pGFD->Rewind(); + pGFD->Rewind(); buf = new unsigned char[kNumTracks * kTrackLen]; if (buf == nil) { @@ -946,15 +946,15 @@ WrapperDDD::Unpack(GenericFD* pGFD, GenericFD** ppNewGFD, short* pDiskVolNum) goto bail; } - pNewGFD = new GFDBuffer; + pNewGFD = new GFDBuffer; if (pNewGFD == nil) { dierr = kDIErrMalloc; goto bail; } - dierr = pNewGFD->Open(buf, kNumTracks * kTrackLen, true, false, false); - if (dierr != kDIErrNone) - goto bail; - buf = nil; // now owned by pNewGFD; + dierr = pNewGFD->Open(buf, kNumTracks * kTrackLen, true, false, false); + if (dierr != kDIErrNone) + goto bail; + buf = nil; // now owned by pNewGFD; dierr = UnpackDisk(pGFD, pNewGFD, &diskVolNum); if (dierr != kDIErrNone) @@ -985,26 +985,26 @@ WrapperDDD::Create(di_off_t length, DiskImg::PhysicalFormat physical, assert(order == DiskImg::kSectorOrderDOS); DIError dierr; - unsigned char* buf = nil; + unsigned char* buf = nil; /* * Create a blank chunk of memory for the image. */ buf = new unsigned char[(int) length]; - if (buf == nil) { + if (buf == nil) { dierr = kDIErrMalloc; goto bail; } GFDBuffer* pNewGFD; - pNewGFD = new GFDBuffer; - dierr = pNewGFD->Open(buf, length, true, false, false); - if (dierr != kDIErrNone) { + pNewGFD = new GFDBuffer; + dierr = pNewGFD->Open(buf, length, true, false, false); + if (dierr != kDIErrNone) { delete pNewGFD; - goto bail; + goto bail; } *pDataFD = pNewGFD; - buf = nil; // now owned by pNewGFD; + buf = nil; // now owned by pNewGFD; // can't set *pWrappedLength yet @@ -1045,7 +1045,7 @@ WrapperDDD::Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, /* * =========================================================================== - * DiskCopy (primarily a Mac format) + * DiskCopy (primarily a Mac format) * =========================================================================== */ @@ -1055,22 +1055,22 @@ WrapperDDD::Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, * All values are BIG-endian. */ const int kDC42NameLen = 64; -const int kDC42ChecksumOffset = 72; // where the checksum lives -const int kDC42DataOffset = 84; // header is always this long +const int kDC42ChecksumOffset = 72; // where the checksum lives +const int kDC42DataOffset = 84; // header is always this long const int kDC42PrivateMagic = 0x100; -const int kDC42FakeTagLen = 19200; // add a "fake" tag to match Mac +const int kDC42FakeTagLen = 19200; // add a "fake" tag to match Mac typedef struct DiskImgLib::DC42Header { - char diskName[kDC42NameLen+1]; // from pascal string - long dataSize; // in bytes - long tagSize; - unsigned long dataChecksum; - unsigned long tagChecksum; - unsigned char diskFormat; // should be 1 for 800K - unsigned char formatByte; // should be $24, sometimes $22 - unsigned short privateWord; // must be 0x0100 - // userData begins at +84 - // tagData follows user data + char diskName[kDC42NameLen+1]; // from pascal string + long dataSize; // in bytes + long tagSize; + unsigned long dataChecksum; + unsigned long tagChecksum; + unsigned char diskFormat; // should be 1 for 800K + unsigned char formatByte; // should be $24, sometimes $22 + unsigned short privateWord; // must be 0x0100 + // userData begins at +84 + // tagData follows user data } DC42Header; /* @@ -1079,16 +1079,16 @@ typedef struct DiskImgLib::DC42Header { /*static*/ void WrapperDiskCopy42::DumpHeader(const DC42Header* pHeader) { - WMSG0("--- header contents:\n"); - WMSG1("\tdiskName = '%s'\n", pHeader->diskName); - WMSG2("\tdataSize = %ld (%ldK)\n", pHeader->dataSize, - pHeader->dataSize / 1024); - WMSG1("\ttagSize = %ld\n", pHeader->tagSize); - WMSG1("\tdataChecksum = 0x%08lx\n", pHeader->dataChecksum); - WMSG1("\ttagChecksum = 0x%08lx\n", pHeader->tagChecksum); - WMSG1("\tdiskFormat = %d\n", pHeader->diskFormat); - WMSG1("\tformatByte = 0x%02x\n", pHeader->formatByte); - WMSG1("\tprivateWord = 0x%04x\n", pHeader->privateWord); + WMSG0("--- header contents:\n"); + WMSG1("\tdiskName = '%s'\n", pHeader->diskName); + WMSG2("\tdataSize = %ld (%ldK)\n", pHeader->dataSize, + pHeader->dataSize / 1024); + WMSG1("\ttagSize = %ld\n", pHeader->tagSize); + WMSG1("\tdataChecksum = 0x%08lx\n", pHeader->dataChecksum); + WMSG1("\ttagChecksum = 0x%08lx\n", pHeader->tagChecksum); + WMSG1("\tdiskFormat = %d\n", pHeader->diskFormat); + WMSG1("\tformatByte = 0x%02x\n", pHeader->formatByte); + WMSG1("\tprivateWord = 0x%04x\n", pHeader->privateWord); } /* @@ -1098,14 +1098,14 @@ void WrapperDiskCopy42::InitHeader(DC42Header* pHeader) { memset(pHeader, 0, sizeof(*pHeader)); - if (fStorageName == NULL || strlen(fStorageName) == 0) - strcpy(pHeader->diskName, "-not a Macintosh disk"); - else - strcpy(pHeader->diskName, fStorageName); + if (fStorageName == NULL || strlen(fStorageName) == 0) + strcpy(pHeader->diskName, "-not a Macintosh disk"); + else + strcpy(pHeader->diskName, fStorageName); pHeader->dataSize = 819200; - pHeader->tagSize = kDC42FakeTagLen; // emulate Mac behavior - pHeader->dataChecksum = 0xffffffff; // fixed during Flush - pHeader->tagChecksum = 0x00000000; // 19200 zeroes + pHeader->tagSize = kDC42FakeTagLen; // emulate Mac behavior + pHeader->dataChecksum = 0xffffffff; // fixed during Flush + pHeader->tagChecksum = 0x00000000; // 19200 zeroes pHeader->diskFormat = 1; pHeader->formatByte = 0x24; pHeader->privateWord = kDC42PrivateMagic; @@ -1119,35 +1119,35 @@ WrapperDiskCopy42::InitHeader(DC42Header* pHeader) /*static*/ int WrapperDiskCopy42::ReadHeader(GenericFD* pGFD, DC42Header* pHeader) { - unsigned char hdrBuf[kDC42DataOffset]; + unsigned char hdrBuf[kDC42DataOffset]; if (pGFD->Read(hdrBuf, kDC42DataOffset) != kDIErrNone) - return -1; + return -1; - // test the Pascal length byte - if (hdrBuf[0] >= kDC42NameLen) - return -1; + // test the Pascal length byte + if (hdrBuf[0] >= kDC42NameLen) + return -1; - memcpy(pHeader->diskName, &hdrBuf[1], hdrBuf[0]); - pHeader->diskName[hdrBuf[0]] = '\0'; + memcpy(pHeader->diskName, &hdrBuf[1], hdrBuf[0]); + pHeader->diskName[hdrBuf[0]] = '\0'; - pHeader->dataSize = GetLongBE(&hdrBuf[64]); - pHeader->tagSize = GetLongBE(&hdrBuf[68]); - pHeader->dataChecksum = GetLongBE(&hdrBuf[72]); - pHeader->tagChecksum = GetLongBE(&hdrBuf[76]); - pHeader->diskFormat = hdrBuf[80]; - pHeader->formatByte = hdrBuf[81]; - pHeader->privateWord = GetShortBE(&hdrBuf[82]); + pHeader->dataSize = GetLongBE(&hdrBuf[64]); + pHeader->tagSize = GetLongBE(&hdrBuf[68]); + pHeader->dataChecksum = GetLongBE(&hdrBuf[72]); + pHeader->tagChecksum = GetLongBE(&hdrBuf[76]); + pHeader->diskFormat = hdrBuf[80]; + pHeader->formatByte = hdrBuf[81]; + pHeader->privateWord = GetShortBE(&hdrBuf[82]); - if (pHeader->dataSize != 800 * 1024 || - pHeader->diskFormat != 1 || - (pHeader->formatByte != 0x22 && pHeader->formatByte != 0x24) || - pHeader->privateWord != kDC42PrivateMagic) - { - return -1; - } + if (pHeader->dataSize != 800 * 1024 || + pHeader->diskFormat != 1 || + (pHeader->formatByte != 0x22 && pHeader->formatByte != 0x24) || + pHeader->privateWord != kDC42PrivateMagic) + { + return -1; + } - return 0; + return 0; } /* @@ -1156,29 +1156,29 @@ WrapperDiskCopy42::ReadHeader(GenericFD* pGFD, DC42Header* pHeader) DIError WrapperDiskCopy42::WriteHeader(GenericFD* pGFD, const DC42Header* pHeader) { - unsigned char hdrBuf[kDC42DataOffset]; + unsigned char hdrBuf[kDC42DataOffset]; pGFD->Rewind(); memset(hdrBuf, 0, sizeof(hdrBuf)); - /* - * Disks created on a Mac include the null byte in the count; not sure - * if this applies to volume labels or just the "not a Macintosh disk" - * magic string. To be safe, we only increment it if it starts with '-'. - * (Need access to a Macintosh to test this.) - */ + /* + * Disks created on a Mac include the null byte in the count; not sure + * if this applies to volume labels or just the "not a Macintosh disk" + * magic string. To be safe, we only increment it if it starts with '-'. + * (Need access to a Macintosh to test this.) + */ hdrBuf[0] = strlen(pHeader->diskName); - if (pHeader->diskName[0] == '-' && hdrBuf[0] < (kDC42NameLen-1)) - hdrBuf[0]++; - memcpy(&hdrBuf[1], pHeader->diskName, hdrBuf[0]); + if (pHeader->diskName[0] == '-' && hdrBuf[0] < (kDC42NameLen-1)) + hdrBuf[0]++; + memcpy(&hdrBuf[1], pHeader->diskName, hdrBuf[0]); - PutLongBE(&hdrBuf[64], pHeader->dataSize); - PutLongBE(&hdrBuf[68], pHeader->tagSize); - PutLongBE(&hdrBuf[72], pHeader->dataChecksum); - PutLongBE(&hdrBuf[76], pHeader->tagChecksum); - hdrBuf[80] = pHeader->diskFormat; - hdrBuf[81] = pHeader->formatByte; - PutShortBE(&hdrBuf[82], pHeader->privateWord); + PutLongBE(&hdrBuf[64], pHeader->dataSize); + PutLongBE(&hdrBuf[68], pHeader->tagSize); + PutLongBE(&hdrBuf[72], pHeader->dataChecksum); + PutLongBE(&hdrBuf[76], pHeader->tagChecksum); + hdrBuf[80] = pHeader->diskFormat; + hdrBuf[81] = pHeader->formatByte; + PutShortBE(&hdrBuf[82], pHeader->privateWord); return pGFD->Write(hdrBuf, kDC42DataOffset); } @@ -1193,20 +1193,20 @@ WrapperDiskCopy42::WriteHeader(GenericFD* pGFD, const DC42Header* pHeader) /*static*/ DIError WrapperDiskCopy42::Test(GenericFD* pGFD, di_off_t wrappedLength) { - DC42Header header; + DC42Header header; - WMSG0("Testing for DiskCopy\n"); + WMSG0("Testing for DiskCopy\n"); - if (wrappedLength < 800 * 1024 + kDC42DataOffset) - return kDIErrGeneric; + if (wrappedLength < 800 * 1024 + kDC42DataOffset) + return kDIErrGeneric; - pGFD->Rewind(); - if (ReadHeader(pGFD, &header) != 0) - return kDIErrGeneric; + pGFD->Rewind(); + if (ReadHeader(pGFD, &header) != 0) + return kDIErrGeneric; - DumpHeader(&header); + DumpHeader(&header); - return kDIErrNone; + return kDIErrNone; } /* @@ -1218,40 +1218,40 @@ WrapperDiskCopy42::Test(GenericFD* pGFD, di_off_t wrappedLength) WrapperDiskCopy42::ComputeChecksum(GenericFD* pGFD, unsigned long* pChecksum) { - DIError dierr = kDIErrNone; - unsigned char buf[512]; - long dataRem = 800 * 1024 /*pHeader->dataSize*/; - unsigned long checksum; + DIError dierr = kDIErrNone; + unsigned char buf[512]; + long dataRem = 800 * 1024 /*pHeader->dataSize*/; + unsigned long checksum; - assert(dataRem % sizeof(buf) == 0); - assert((sizeof(buf) & 0x01) == 0); // we take it two bytes at a time + assert(dataRem % sizeof(buf) == 0); + assert((sizeof(buf) & 0x01) == 0); // we take it two bytes at a time - checksum = 0; - while (dataRem) { - int i; + checksum = 0; + while (dataRem) { + int i; - dierr = pGFD->Read(buf, sizeof(buf)); - if (dierr != kDIErrNone) { + dierr = pGFD->Read(buf, sizeof(buf)); + if (dierr != kDIErrNone) { WMSG2(" DC42 read failed, dataRem=%ld (err=%d)\n", dataRem, dierr); - return dierr; + return dierr; } - for (i = 0; i < (int) sizeof(buf); i += 2) { - unsigned short val = GetShortBE(buf+i); + for (i = 0; i < (int) sizeof(buf); i += 2) { + unsigned short val = GetShortBE(buf+i); - checksum += val; - if (checksum & 0x01) - checksum = checksum >> 1 | 0x80000000; - else - checksum = checksum >> 1; - } + checksum += val; + if (checksum & 0x01) + checksum = checksum >> 1 | 0x80000000; + else + checksum = checksum >> 1; + } - dataRem -= sizeof(buf); - } + dataRem -= sizeof(buf); + } *pChecksum = checksum; - return dierr; + return dierr; } /* @@ -1260,39 +1260,39 @@ WrapperDiskCopy42::ComputeChecksum(GenericFD* pGFD, DIError WrapperDiskCopy42::Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) { DIError dierr; - DC42Header header; + DC42Header header; - WMSG0("Prepping for DiskCopy 4.2\n"); - pGFD->Rewind(); - if (ReadHeader(pGFD, &header) != 0) - return kDIErrGeneric; + WMSG0("Prepping for DiskCopy 4.2\n"); + pGFD->Rewind(); + if (ReadHeader(pGFD, &header) != 0) + return kDIErrGeneric; - /* - * Verify checksum. File should already be seeked to appropriate place. - */ + /* + * Verify checksum. File should already be seeked to appropriate place. + */ unsigned long checksum; - dierr = ComputeChecksum(pGFD, &checksum); + dierr = ComputeChecksum(pGFD, &checksum); if (dierr != kDIErrNone) - return dierr; + return dierr; - if (checksum != header.dataChecksum) { - WMSG2(" DC42 checksum mismatch (got 0x%08lx, expected 0x%08lx)\n", - checksum, header.dataChecksum); - fBadChecksum = true; - //return kDIErrBadChecksum; - } else { - WMSG0(" DC42 checksum matches!\n"); - } + if (checksum != header.dataChecksum) { + WMSG2(" DC42 checksum mismatch (got 0x%08lx, expected 0x%08lx)\n", + checksum, header.dataChecksum); + fBadChecksum = true; + //return kDIErrBadChecksum; + } else { + WMSG0(" DC42 checksum matches!\n"); + } /* looks good! */ - *pLength = header.dataSize; - *pPhysical = DiskImg::kPhysicalFormatSectors; - *pOrder = DiskImg::kSectorOrderProDOS; + *pLength = header.dataSize; + *pPhysical = DiskImg::kPhysicalFormatSectors; + *pOrder = DiskImg::kSectorOrderProDOS; *ppNewGFD = new GFDGFD; return ((GFDGFD*)*ppNewGFD)->Open(pGFD, kDC42DataOffset, readOnly); @@ -1358,17 +1358,17 @@ WrapperDiskCopy42::Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, if (dierr != kDIErrNone) goto bail; - /* add the tag bytes */ - dierr = pWrapperGFD->Seek(kDC42DataOffset + 800*1024, kSeekSet); - char* tmpBuf; - tmpBuf = new char[kDC42FakeTagLen]; - if (tmpBuf == nil) - return kDIErrMalloc; - memset(tmpBuf, 0, kDC42FakeTagLen); - dierr = pWrapperGFD->Write(tmpBuf, kDC42FakeTagLen, nil); - delete[] tmpBuf; - if (dierr != kDIErrNone) - goto bail; + /* add the tag bytes */ + dierr = pWrapperGFD->Seek(kDC42DataOffset + 800*1024, kSeekSet); + char* tmpBuf; + tmpBuf = new char[kDC42FakeTagLen]; + if (tmpBuf == nil) + return kDIErrMalloc; + memset(tmpBuf, 0, kDC42FakeTagLen); + dierr = pWrapperGFD->Write(tmpBuf, kDC42FakeTagLen, nil); + delete[] tmpBuf; + if (dierr != kDIErrNone) + goto bail; bail: return dierr; @@ -1377,30 +1377,30 @@ bail: /* * =========================================================================== - * Sim2eHDV (Sim2e virtual hard-drive images) + * Sim2eHDV (Sim2e virtual hard-drive images) * =========================================================================== */ /* -// mkhdv.c +// mkhdv.c // -// Create a Hard Disk Volume File (.HDV) for simIIe -static int mkhdv(FILE *op, uint blocks) +// Create a Hard Disk Volume File (.HDV) for simIIe +static int mkhdv(FILE *op, uint blocks) { - byte sector[512]; - byte data[15]; - uint i; + byte sector[512]; + byte data[15]; + uint i; - memset(data, 0, sizeof(data)); - memcpy(data, "SIMSYSTEM_HDV", 13); - data[13] = (blocks & 0xff); - data[14] = (blocks & 0xff00) >> 8; - fwrite(data, 1, sizeof(data), op); + memset(data, 0, sizeof(data)); + memcpy(data, "SIMSYSTEM_HDV", 13); + data[13] = (blocks & 0xff); + data[14] = (blocks & 0xff00) >> 8; + fwrite(data, 1, sizeof(data), op); - memset(sector, 0, sizeof(sector)); - for (i = 0; i < blocks; i++) - fwrite(sector, 1, sizeof(sector), op); - return 0; + memset(sector, 0, sizeof(sector)); + for (i = 0; i < blocks; i++) + fwrite(sector, 1, sizeof(sector), op); + return 0; } */ @@ -1414,20 +1414,20 @@ static const char* kSim2eID = "SIMSYSTEM_HDV"; DIError WrapperSim2eHDV::Test(GenericFD* pGFD, di_off_t wrappedLength) { - char buf[kSim2eHeaderLen]; + char buf[kSim2eHeaderLen]; WMSG0("Testing for Sim2e HDV\n"); - if (wrappedLength < 512 || - ((wrappedLength - kSim2eHeaderLen) % 4096) != 0) - { - return kDIErrGeneric; - } + if (wrappedLength < 512 || + ((wrappedLength - kSim2eHeaderLen) % 4096) != 0) + { + return kDIErrGeneric; + } pGFD->Rewind(); if (pGFD->Read(buf, sizeof(buf)) != kDIErrNone) - return kDIErrGeneric; + return kDIErrGeneric; if (strncmp(buf, kSim2eID, strlen(kSim2eID)) == 0) return kDIErrNone; @@ -1441,12 +1441,12 @@ WrapperSim2eHDV::Test(GenericFD* pGFD, di_off_t wrappedLength) DIError WrapperSim2eHDV::Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) { - *pLength = wrappedLength - kSim2eHeaderLen; - *pPhysical = DiskImg::kPhysicalFormatSectors; - *pOrder = DiskImg::kSectorOrderProDOS; + *pLength = wrappedLength - kSim2eHeaderLen; + *pPhysical = DiskImg::kPhysicalFormatSectors; + *pOrder = DiskImg::kSectorOrderProDOS; *ppNewGFD = new GFDGFD; return ((GFDGFD*)*ppNewGFD)->Open(pGFD, kSim2eHeaderLen, readOnly); @@ -1501,25 +1501,25 @@ WrapperSim2eHDV::Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, /* * =========================================================================== - * TrackStar .app images + * TrackStar .app images * =========================================================================== */ /* * File format: - * $0000 track 0 data - * $1a00 track 1 data - * $3400 track 2 data - * ... - * $3f600 track 39 data + * $0000 track 0 data + * $1a00 track 1 data + * $3400 track 2 data + * ... + * $3f600 track 39 data * * Each track consists of: - * $0000 Text description of disk contents (same on every track), in low - * ASCII, padded out with spaces ($20) - * $002e Start of zeroed-out header field - * $0080 $00 (indicates end of data when reading from end??) - * $0081 Raw nibble data (hi bit set), written backwards - * $19fe Start offset of track data + * $0000 Text description of disk contents (same on every track), in low + * ASCII, padded out with spaces ($20) + * $002e Start of zeroed-out header field + * $0080 $00 (indicates end of data when reading from end??) + * $0081 Raw nibble data (hi bit set), written backwards + * $19fe Start offset of track data * * Take the start offset, add 128, and walk backward until you find a * value with the high bit clear. If the start offset is zero, start @@ -1557,31 +1557,31 @@ WrapperSim2eHDV::Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, WrapperTrackStar::Test(GenericFD* pGFD, di_off_t wrappedLength) { DIError dierr = kDIErrNone; - WMSG0("Testing for TrackStar\n"); - int numTracks; + WMSG0("Testing for TrackStar\n"); + int numTracks; - /* check the length */ - if (wrappedLength == 6656*40) - numTracks = 40; - else if (wrappedLength == 6656*80) - numTracks = 80; - else - return kDIErrGeneric; + /* check the length */ + if (wrappedLength == 6656*40) + numTracks = 40; + else if (wrappedLength == 6656*80) + numTracks = 80; + else + return kDIErrGeneric; - WMSG1(" Checking for %d-track image\n", numTracks); + WMSG1(" Checking for %d-track image\n", numTracks); - /* verify each track */ - unsigned char trackBuf[kFileTrackStorageLen]; + /* verify each track */ + unsigned char trackBuf[kFileTrackStorageLen]; pGFD->Rewind(); - for (int trk = 0; trk < numTracks; trk++) { - dierr = pGFD->Read(trackBuf, sizeof(trackBuf)); - if (dierr != kDIErrNone) - goto bail; - dierr = VerifyTrack(trk, trackBuf); - if (dierr != kDIErrNone) - goto bail; - } - WMSG0(" TrackStar tracks verified\n"); + for (int trk = 0; trk < numTracks; trk++) { + dierr = pGFD->Read(trackBuf, sizeof(trackBuf)); + if (dierr != kDIErrNone) + goto bail; + dierr = VerifyTrack(trk, trackBuf); + if (dierr != kDIErrNone) + goto bail; + } + WMSG0(" TrackStar tracks verified\n"); bail: return dierr; @@ -1593,36 +1593,36 @@ bail: /*static*/ DIError WrapperTrackStar::VerifyTrack(int track, const unsigned char* trackBuf) { - unsigned int dataLen; + unsigned int dataLen; - if (trackBuf[0x80] != 0) { - WMSG1(" TrackStar track=%d found nonzero at 129\n", track); - return kDIErrGeneric; - } + if (trackBuf[0x80] != 0) { + WMSG1(" TrackStar track=%d found nonzero at 129\n", track); + return kDIErrGeneric; + } - dataLen = GetShortLE(trackBuf + 0x19fe); - if (dataLen > kMaxTrackLen) { - WMSG3(" TrackStar track=%d len=%d exceeds max (%d)\n", - track, dataLen, kMaxTrackLen); - return kDIErrGeneric; - } - if (dataLen == 0) - dataLen = kMaxTrackLen; + dataLen = GetShortLE(trackBuf + 0x19fe); + if (dataLen > kMaxTrackLen) { + WMSG3(" TrackStar track=%d len=%d exceeds max (%d)\n", + track, dataLen, kMaxTrackLen); + return kDIErrGeneric; + } + if (dataLen == 0) + dataLen = kMaxTrackLen; - unsigned int i; - for (i = 0; i < dataLen; i++) { - if ((trackBuf[0x81 + i] & 0x80) == 0) { - WMSG3(" TrackStar track=%d found invalid data 0x%02x at %d\n", - track, trackBuf[0x81+i], i); - return kDIErrGeneric; - } - } + unsigned int i; + for (i = 0; i < dataLen; i++) { + if ((trackBuf[0x81 + i] & 0x80) == 0) { + WMSG3(" TrackStar track=%d found invalid data 0x%02x at %d\n", + track, trackBuf[0x81+i], i); + return kDIErrGeneric; + } + } - if (track == 0) { - WMSG1(" TrackStar msg='%s'\n", trackBuf); - } + if (track == 0) { + WMSG1(" TrackStar msg='%s'\n", trackBuf); + } - return kDIErrNone; + return kDIErrNone; } /* @@ -1631,26 +1631,26 @@ WrapperTrackStar::VerifyTrack(int track, const unsigned char* trackBuf) DIError WrapperTrackStar::Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) { - WMSG0("Prepping for TrackStar\n"); - DIError dierr = kDIErrNone; + WMSG0("Prepping for TrackStar\n"); + DIError dierr = kDIErrNone; - if (wrappedLength == kFileTrackStorageLen * 40) - fImageTracks = 40; - else if (wrappedLength == kFileTrackStorageLen * 80) - fImageTracks = 80; - else - return kDIErrInternal; + if (wrappedLength == kFileTrackStorageLen * 40) + fImageTracks = 40; + else if (wrappedLength == kFileTrackStorageLen * 80) + fImageTracks = 80; + else + return kDIErrInternal; dierr = Unpack(pGFD, ppNewGFD); if (dierr != kDIErrNone) return dierr; - *pLength = kTrackStarNumTracks * kTrackAllocSize; - *pPhysical = DiskImg::kPhysicalFormatNib525_Var; - *pOrder = DiskImg::kSectorOrderPhysical; + *pLength = kTrackStarNumTracks * kTrackAllocSize; + *pPhysical = DiskImg::kPhysicalFormatNib525_Var; + *pOrder = DiskImg::kSectorOrderPhysical; return dierr; } @@ -1663,10 +1663,10 @@ DIError WrapperTrackStar::Unpack(GenericFD* pGFD, GenericFD** ppNewGFD) { DIError dierr; - GFDBuffer* pNewGFD = nil; + GFDBuffer* pNewGFD = nil; unsigned char* buf = nil; - pGFD->Rewind(); + pGFD->Rewind(); buf = new unsigned char[kTrackStarNumTracks * kTrackAllocSize]; if (buf == nil) { @@ -1674,16 +1674,16 @@ WrapperTrackStar::Unpack(GenericFD* pGFD, GenericFD** ppNewGFD) goto bail; } - pNewGFD = new GFDBuffer; + pNewGFD = new GFDBuffer; if (pNewGFD == nil) { dierr = kDIErrMalloc; goto bail; } - dierr = pNewGFD->Open(buf, kTrackStarNumTracks * kTrackAllocSize, - true, false, false); - if (dierr != kDIErrNone) - goto bail; - buf = nil; // now owned by pNewGFD; + dierr = pNewGFD->Open(buf, kTrackStarNumTracks * kTrackAllocSize, + true, false, false); + if (dierr != kDIErrNone) + goto bail; + buf = nil; // now owned by pNewGFD; dierr = UnpackDisk(pGFD, pNewGFD); if (dierr != kDIErrNone) @@ -1715,52 +1715,52 @@ bail: DIError WrapperTrackStar::UnpackDisk(GenericFD* pGFD, GenericFD* pNewGFD) { - DIError dierr = kDIErrNone; - unsigned char inBuf[kFileTrackStorageLen]; - unsigned char outBuf[kTrackAllocSize]; - int i, trk; + DIError dierr = kDIErrNone; + unsigned char inBuf[kFileTrackStorageLen]; + unsigned char outBuf[kTrackAllocSize]; + int i, trk; - assert(kTrackStarNumTracks <= kMaxNibbleTracks525); + assert(kTrackStarNumTracks <= kMaxNibbleTracks525); pGFD->Rewind(); - pNewGFD->Rewind(); + pNewGFD->Rewind(); - /* we don't currently support half-tracks */ - fNibbleTrackInfo.numTracks = kTrackStarNumTracks; - for (trk = 0; trk < kTrackStarNumTracks; trk++) { - unsigned int dataLen; + /* we don't currently support half-tracks */ + fNibbleTrackInfo.numTracks = kTrackStarNumTracks; + for (trk = 0; trk < kTrackStarNumTracks; trk++) { + unsigned int dataLen; - fNibbleTrackInfo.offset[trk] = trk * kTrackAllocSize; + fNibbleTrackInfo.offset[trk] = trk * kTrackAllocSize; - /* these were verified earlier, so assume data is okay */ - dierr = pGFD->Read(inBuf, sizeof(inBuf)); - if (dierr != kDIErrNone) - goto bail; + /* these were verified earlier, so assume data is okay */ + dierr = pGFD->Read(inBuf, sizeof(inBuf)); + if (dierr != kDIErrNone) + goto bail; - dataLen = GetShortLE(inBuf + 0x19fe); - if (dataLen == 0) - dataLen = kMaxTrackLen; - assert(dataLen <= kMaxTrackLen); - assert(dataLen <= sizeof(outBuf)); + dataLen = GetShortLE(inBuf + 0x19fe); + if (dataLen == 0) + dataLen = kMaxTrackLen; + assert(dataLen <= kMaxTrackLen); + assert(dataLen <= sizeof(outBuf)); - fNibbleTrackInfo.length[trk] = dataLen; + fNibbleTrackInfo.length[trk] = dataLen; - memset(outBuf, 0x11, sizeof(outBuf)); - for (i = 0; i < (int) dataLen; i++) - outBuf[i] = inBuf[128+dataLen-i]; + memset(outBuf, 0x11, sizeof(outBuf)); + for (i = 0; i < (int) dataLen; i++) + outBuf[i] = inBuf[128+dataLen-i]; - pNewGFD->Write(outBuf, sizeof(outBuf)); + pNewGFD->Write(outBuf, sizeof(outBuf)); - if (fImageTracks == 2*kTrackStarNumTracks) { - /* skip the odd-numbered tracks */ - dierr = pGFD->Read(inBuf, sizeof(inBuf)); - if (dierr != kDIErrNone) - goto bail; - } - } + if (fImageTracks == 2*kTrackStarNumTracks) { + /* skip the odd-numbered tracks */ + dierr = pGFD->Read(inBuf, sizeof(inBuf)); + if (dierr != kDIErrNone) + goto bail; + } + } bail: - return dierr; + return dierr; } @@ -1774,45 +1774,45 @@ WrapperTrackStar::Create(di_off_t length, DiskImg::PhysicalFormat physical, di_off_t* pWrappedLength, GenericFD** pDataFD) { assert(length == kTrackLenTrackStar525 * kTrackCount525 || - length == kTrackLenTrackStar525 * kTrackStarNumTracks); + length == kTrackLenTrackStar525 * kTrackStarNumTracks); assert(physical == DiskImg::kPhysicalFormatNib525_Var); assert(order == DiskImg::kSectorOrderPhysical); DIError dierr; - unsigned char* buf = nil; - int numTracks = (int) (length / kTrackLenTrackStar525); - int i; + unsigned char* buf = nil; + int numTracks = (int) (length / kTrackLenTrackStar525); + int i; - /* - * Set up the track offset and length table. We use the maximum - * data length (kTrackLenTrackStar525) for each. The nibble write - * routine will alter the length field as appropriate. - */ - fNibbleTrackInfo.numTracks = numTracks; - assert(fNibbleTrackInfo.numTracks <= kMaxNibbleTracks525); - for (i = 0; i < numTracks; i++) { - fNibbleTrackInfo.offset[i] = kTrackLenTrackStar525 * i; - fNibbleTrackInfo.length[i] = kTrackLenTrackStar525; - } + /* + * Set up the track offset and length table. We use the maximum + * data length (kTrackLenTrackStar525) for each. The nibble write + * routine will alter the length field as appropriate. + */ + fNibbleTrackInfo.numTracks = numTracks; + assert(fNibbleTrackInfo.numTracks <= kMaxNibbleTracks525); + for (i = 0; i < numTracks; i++) { + fNibbleTrackInfo.offset[i] = kTrackLenTrackStar525 * i; + fNibbleTrackInfo.length[i] = kTrackLenTrackStar525; + } /* * Create a blank chunk of memory for the image. */ buf = new unsigned char[(int) length]; - if (buf == nil) { + if (buf == nil) { dierr = kDIErrMalloc; goto bail; } GFDBuffer* pNewGFD; - pNewGFD = new GFDBuffer; - dierr = pNewGFD->Open(buf, length, true, false, false); - if (dierr != kDIErrNone) { + pNewGFD = new GFDBuffer; + dierr = pNewGFD->Open(buf, length, true, false, false); + if (dierr != kDIErrNone) { delete pNewGFD; - goto bail; + goto bail; } *pDataFD = pNewGFD; - buf = nil; // now owned by pNewGFD; + buf = nil; // now owned by pNewGFD; // can't set *pWrappedLength yet @@ -1834,64 +1834,64 @@ WrapperTrackStar::Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, DIError dierr = kDIErrNone; assert(dataLen == kTrackLenTrackStar525 * kTrackCount525 || - dataLen == kTrackLenTrackStar525 * kTrackStarNumTracks); - assert(kTrackLenTrackStar525 <= kMaxTrackLen); + dataLen == kTrackLenTrackStar525 * kTrackStarNumTracks); + assert(kTrackLenTrackStar525 <= kMaxTrackLen); pDataGFD->Rewind(); - unsigned char writeBuf[kFileTrackStorageLen]; - unsigned char dataBuf[kTrackLenTrackStar525]; - int track, trackLen; + unsigned char writeBuf[kFileTrackStorageLen]; + unsigned char dataBuf[kTrackLenTrackStar525]; + int track, trackLen; - for (track = 0; track < kTrackStarNumTracks; track++) { - if (track < fNibbleTrackInfo.numTracks) { - dierr = pDataGFD->Read(dataBuf, kTrackLenTrackStar525); - if (dierr != kDIErrNone) - goto bail; - trackLen = fNibbleTrackInfo.length[track]; - assert(fNibbleTrackInfo.offset[track] == kTrackLenTrackStar525 * track); - } else { - WMSG1(" TrackStar faking track %d\n", track); - memset(dataBuf, 0xff, sizeof(dataBuf)); - trackLen = kMaxTrackLen; - } + for (track = 0; track < kTrackStarNumTracks; track++) { + if (track < fNibbleTrackInfo.numTracks) { + dierr = pDataGFD->Read(dataBuf, kTrackLenTrackStar525); + if (dierr != kDIErrNone) + goto bail; + trackLen = fNibbleTrackInfo.length[track]; + assert(fNibbleTrackInfo.offset[track] == kTrackLenTrackStar525 * track); + } else { + WMSG1(" TrackStar faking track %d\n", track); + memset(dataBuf, 0xff, sizeof(dataBuf)); + trackLen = kMaxTrackLen; + } - memset(writeBuf, 0x80, sizeof(writeBuf)); // not strictly necessary - memset(writeBuf, 0x20, kCommentFieldLen); - memset(writeBuf+kCommentFieldLen, 0x00, 0x81-kCommentFieldLen); + memset(writeBuf, 0x80, sizeof(writeBuf)); // not strictly necessary + memset(writeBuf, 0x20, kCommentFieldLen); + memset(writeBuf+kCommentFieldLen, 0x00, 0x81-kCommentFieldLen); - const char* comment; - if (fStorageName != NULL && *fStorageName != '\0') - comment = fStorageName; - else - comment = "(created by CiderPress)"; - if (strlen(comment) > kCommentFieldLen) - memcpy(writeBuf, comment, kCommentFieldLen); - else - memcpy(writeBuf, comment, strlen(comment)); + const char* comment; + if (fStorageName != NULL && *fStorageName != '\0') + comment = fStorageName; + else + comment = "(created by CiderPress)"; + if (strlen(comment) > kCommentFieldLen) + memcpy(writeBuf, comment, kCommentFieldLen); + else + memcpy(writeBuf, comment, strlen(comment)); - int i; - for (i = 0; i < trackLen; i++) { - // If we write a value here with the high bit clear, we will - // reject the file when we try to open it. So, we force the - // high bit on here, on the assumption that the nibble data - // we've been handled is otherwise good. - //writeBuf[0x81+i] = dataBuf[trackLen - i -1]; - writeBuf[0x81+i] = dataBuf[trackLen - i -1] | 0x80; - } + int i; + for (i = 0; i < trackLen; i++) { + // If we write a value here with the high bit clear, we will + // reject the file when we try to open it. So, we force the + // high bit on here, on the assumption that the nibble data + // we've been handled is otherwise good. + //writeBuf[0x81+i] = dataBuf[trackLen - i -1]; + writeBuf[0x81+i] = dataBuf[trackLen - i -1] | 0x80; + } - if (trackLen == kMaxTrackLen) - PutShortLE(writeBuf + 0x19fe, 0); - else - PutShortLE(writeBuf + 0x19fe, (unsigned short) trackLen); + if (trackLen == kMaxTrackLen) + PutShortLE(writeBuf + 0x19fe, 0); + else + PutShortLE(writeBuf + 0x19fe, (unsigned short) trackLen); - dierr = pWrapperGFD->Write(writeBuf, sizeof(writeBuf)); - if (dierr != kDIErrNone) - goto bail; - } + dierr = pWrapperGFD->Write(writeBuf, sizeof(writeBuf)); + if (dierr != kDIErrNone) + goto bail; + } *pWrappedLen = pWrapperGFD->Tell(); - assert(*pWrappedLen == kFileTrackStorageLen * kTrackStarNumTracks); + assert(*pWrappedLen == kFileTrackStorageLen * kTrackStarNumTracks); bail: return dierr; @@ -1900,18 +1900,18 @@ bail: void WrapperTrackStar::SetNibbleTrackLength(int track, int length) { - assert(track >= 0); - assert(length > 0 && length <= kMaxTrackLen); - assert(track < fNibbleTrackInfo.numTracks); + assert(track >= 0); + assert(length > 0 && length <= kMaxTrackLen); + assert(track < fNibbleTrackInfo.numTracks); - WMSG2(" TrackStar: set length of track %d to %d\n", track, length); - fNibbleTrackInfo.length[track] = length; + WMSG2(" TrackStar: set length of track %d to %d\n", track, length); + fNibbleTrackInfo.length[track] = length; } /* * =========================================================================== - * FDI (Formatted Disk Image) format + * FDI (Formatted Disk Image) format * =========================================================================== */ @@ -1934,25 +1934,25 @@ WrapperTrackStar::SetNibbleTrackLength(int track, int length) WrapperFDI::Test(GenericFD* pGFD, di_off_t wrappedLength) { DIError dierr = kDIErrNone; - unsigned char headerBuf[kMinHeaderLen]; - FDIHeader hdr; + unsigned char headerBuf[kMinHeaderLen]; + FDIHeader hdr; - WMSG0("Testing for FDI\n"); + WMSG0("Testing for FDI\n"); pGFD->Rewind(); - dierr = pGFD->Read(headerBuf, sizeof(headerBuf)); - if (dierr != kDIErrNone) - goto bail; + dierr = pGFD->Read(headerBuf, sizeof(headerBuf)); + if (dierr != kDIErrNone) + goto bail; - UnpackHeader(headerBuf, &hdr); - if (strcmp(hdr.signature, kFDIMagic) != 0) { - WMSG0("FDI: FDI signature not found\n"); - return kDIErrGeneric; - } - if (hdr.version < kMinVersion) { - WMSG1("FDI: bad version 0x%.04x\n", hdr.version); - return kDIErrGeneric; - } + UnpackHeader(headerBuf, &hdr); + if (strcmp(hdr.signature, kFDIMagic) != 0) { + WMSG0("FDI: FDI signature not found\n"); + return kDIErrGeneric; + } + if (hdr.version < kMinVersion) { + WMSG1("FDI: bad version 0x%.04x\n", hdr.version); + return kDIErrGeneric; + } bail: return dierr; @@ -1964,22 +1964,22 @@ bail: /*static*/ void WrapperFDI::UnpackHeader(const unsigned char* headerBuf, FDIHeader* pHdr) { - memcpy(pHdr->signature, &headerBuf[0], kSignatureLen); - pHdr->signature[kSignatureLen] = '\0'; - memcpy(pHdr->creator, &headerBuf[27], kCreatorLen); - pHdr->creator[kCreatorLen] = '\0'; - memcpy(pHdr->comment, &headerBuf[59], kCommentLen); - pHdr->comment[kCommentLen] = '\0'; + memcpy(pHdr->signature, &headerBuf[0], kSignatureLen); + pHdr->signature[kSignatureLen] = '\0'; + memcpy(pHdr->creator, &headerBuf[27], kCreatorLen); + pHdr->creator[kCreatorLen] = '\0'; + memcpy(pHdr->comment, &headerBuf[59], kCommentLen); + pHdr->comment[kCommentLen] = '\0'; - pHdr->version = GetShortBE(&headerBuf[140]); - pHdr->lastTrack = GetShortBE(&headerBuf[142]); - pHdr->lastHead = headerBuf[144]; - pHdr->type = headerBuf[145]; - pHdr->rotSpeed = headerBuf[146]; - pHdr->flags = headerBuf[147]; - pHdr->tpi = headerBuf[148]; - pHdr->headWidth = headerBuf[149]; - pHdr->reserved = GetShortBE(&headerBuf[150]); + pHdr->version = GetShortBE(&headerBuf[140]); + pHdr->lastTrack = GetShortBE(&headerBuf[142]); + pHdr->lastHead = headerBuf[144]; + pHdr->type = headerBuf[145]; + pHdr->rotSpeed = headerBuf[146]; + pHdr->flags = headerBuf[147]; + pHdr->tpi = headerBuf[148]; + pHdr->headWidth = headerBuf[149]; + pHdr->reserved = GetShortBE(&headerBuf[150]); } /* @@ -1988,32 +1988,32 @@ WrapperFDI::UnpackHeader(const unsigned char* headerBuf, FDIHeader* pHdr) /*static*/ void WrapperFDI::DumpHeader(const FDIHeader* pHdr) { - static const char* kTypes[] = { - "8\"", "5.25\"", "3.5\"", "3\"" - }; - static const char* kTPI[] = { - "48", "67", "96", "100", "135", "192" - }; + static const char* kTypes[] = { + "8\"", "5.25\"", "3.5\"", "3\"" + }; + static const char* kTPI[] = { + "48", "67", "96", "100", "135", "192" + }; - WMSG0(" FDI header contents:\n"); - WMSG1(" signature: '%s'\n", pHdr->signature); - WMSG1(" creator : '%s'\n", pHdr->creator); - WMSG1(" comment : '%s'\n", pHdr->comment); - WMSG2(" version : %d.%d\n", pHdr->version >> 8, pHdr->version & 0xff); - WMSG1(" lastTrack: %d\n", pHdr->lastTrack); - WMSG1(" lastHead : %d\n", pHdr->lastHead); - WMSG2(" type : %d (%s)\n", pHdr->type, - (/*pHdr->type >= 0 &&*/ pHdr->type < NELEM(kTypes)) ? - kTypes[pHdr->type] : "???"); - WMSG1(" rotSpeed : %drpm\n", pHdr->rotSpeed + 128); - WMSG1(" flags : 0x%02x\n", pHdr->flags); - WMSG2(" tpi : %d (%s)\n", pHdr->tpi, - (/*pHdr->tpi >= 0 &&*/ pHdr->tpi < NELEM(kTPI)) ? - kTPI[pHdr->tpi] : "???"); - WMSG2(" headWidth: %d (%s)\n", pHdr->headWidth, - (/*pHdr->headWidth >= 0 &&*/ pHdr->headWidth < NELEM(kTPI)) ? - kTPI[pHdr->headWidth] : "???"); - WMSG1(" reserved : %d\n", pHdr->reserved); + WMSG0(" FDI header contents:\n"); + WMSG1(" signature: '%s'\n", pHdr->signature); + WMSG1(" creator : '%s'\n", pHdr->creator); + WMSG1(" comment : '%s'\n", pHdr->comment); + WMSG2(" version : %d.%d\n", pHdr->version >> 8, pHdr->version & 0xff); + WMSG1(" lastTrack: %d\n", pHdr->lastTrack); + WMSG1(" lastHead : %d\n", pHdr->lastHead); + WMSG2(" type : %d (%s)\n", pHdr->type, + (/*pHdr->type >= 0 &&*/ pHdr->type < NELEM(kTypes)) ? + kTypes[pHdr->type] : "???"); + WMSG1(" rotSpeed : %drpm\n", pHdr->rotSpeed + 128); + WMSG1(" flags : 0x%02x\n", pHdr->flags); + WMSG2(" tpi : %d (%s)\n", pHdr->tpi, + (/*pHdr->tpi >= 0 &&*/ pHdr->tpi < NELEM(kTPI)) ? + kTPI[pHdr->tpi] : "???"); + WMSG2(" headWidth: %d (%s)\n", pHdr->headWidth, + (/*pHdr->headWidth >= 0 &&*/ pHdr->headWidth < NELEM(kTPI)) ? + kTPI[pHdr->headWidth] : "???"); + WMSG1(" reserved : %d\n", pHdr->reserved); } /* @@ -2022,89 +2022,89 @@ WrapperFDI::DumpHeader(const FDIHeader* pHdr) DIError WrapperFDI::Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) { - WMSG0("Prepping for FDI\n"); - DIError dierr = kDIErrNone; - FDIHeader hdr; + WMSG0("Prepping for FDI\n"); + DIError dierr = kDIErrNone; + FDIHeader hdr; pGFD->Rewind(); - dierr = pGFD->Read(fHeaderBuf, sizeof(fHeaderBuf)); - if (dierr != kDIErrNone) - goto bail; + dierr = pGFD->Read(fHeaderBuf, sizeof(fHeaderBuf)); + if (dierr != kDIErrNone) + goto bail; - UnpackHeader(fHeaderBuf, &hdr); - if (strcmp(hdr.signature, kFDIMagic) != 0) - return kDIErrGeneric; - DumpHeader(&hdr); + UnpackHeader(fHeaderBuf, &hdr); + if (strcmp(hdr.signature, kFDIMagic) != 0) + return kDIErrGeneric; + DumpHeader(&hdr); - /* - * There are two formats that we're interested in, 3.5" and 5.25". They - * are handled differently within CiderPress, so we split here. - * - * Sometimes disk2fdi finds extra tracks. No Apple II hardware ever - * went past 40 on 5.25" disks, but we'll humor the software and allow - * images with up to 50. Ditto for 3.5" disks, which should always - * have 80 double-sided tracks. - */ - if (hdr.type == kDiskType525) { - WMSG0("FDI: decoding 5.25\" disk\n"); - if (hdr.lastHead != 0 || hdr.lastTrack >= kMaxNibbleTracks525 + 10) { - WMSG2("FDI: bad params head=%d ltrack=%d\n", - hdr.lastHead, hdr.lastTrack); - dierr = kDIErrUnsupportedImageFeature; - goto bail; - } - if (hdr.lastTrack >= kMaxNibbleTracks525) { - WMSG2("FDI: reducing hdr.lastTrack from %d to %d\n", - hdr.lastTrack, kMaxNibbleTracks525-1); - hdr.lastTrack = kMaxNibbleTracks525-1; - } + /* + * There are two formats that we're interested in, 3.5" and 5.25". They + * are handled differently within CiderPress, so we split here. + * + * Sometimes disk2fdi finds extra tracks. No Apple II hardware ever + * went past 40 on 5.25" disks, but we'll humor the software and allow + * images with up to 50. Ditto for 3.5" disks, which should always + * have 80 double-sided tracks. + */ + if (hdr.type == kDiskType525) { + WMSG0("FDI: decoding 5.25\" disk\n"); + if (hdr.lastHead != 0 || hdr.lastTrack >= kMaxNibbleTracks525 + 10) { + WMSG2("FDI: bad params head=%d ltrack=%d\n", + hdr.lastHead, hdr.lastTrack); + dierr = kDIErrUnsupportedImageFeature; + goto bail; + } + if (hdr.lastTrack >= kMaxNibbleTracks525) { + WMSG2("FDI: reducing hdr.lastTrack from %d to %d\n", + hdr.lastTrack, kMaxNibbleTracks525-1); + hdr.lastTrack = kMaxNibbleTracks525-1; + } - /* - * Unpack to a series of variable-length nibble tracks. The data - * goes into ppNewGFD, and a table of track info goes into - * fNibbleTrackInfo. - */ - dierr = Unpack525(pGFD, ppNewGFD, hdr.lastTrack+1, hdr.lastHead+1); - if (dierr != kDIErrNone) - return dierr; + /* + * Unpack to a series of variable-length nibble tracks. The data + * goes into ppNewGFD, and a table of track info goes into + * fNibbleTrackInfo. + */ + dierr = Unpack525(pGFD, ppNewGFD, hdr.lastTrack+1, hdr.lastHead+1); + if (dierr != kDIErrNone) + return dierr; - *pLength = kMaxNibbleTracks525 * kTrackAllocSize; - *pPhysical = DiskImg::kPhysicalFormatNib525_Var; - *pOrder = DiskImg::kSectorOrderPhysical; - } else if (hdr.type == kDiskType35) { - WMSG0("FDI: decoding 3.5\" disk\n"); - if (hdr.lastHead != 1 || hdr.lastTrack >= kMaxNibbleTracks35 + 10) { - WMSG2("FDI: bad params head=%d ltrack=%d\n", - hdr.lastHead, hdr.lastTrack); - dierr = kDIErrUnsupportedImageFeature; - goto bail; - } - if (hdr.lastTrack >= kMaxNibbleTracks35) { - WMSG2("FDI: reducing hdr.lastTrack from %d to %d\n", - hdr.lastTrack, kMaxNibbleTracks35-1); - hdr.lastTrack = kMaxNibbleTracks35-1; - } + *pLength = kMaxNibbleTracks525 * kTrackAllocSize; + *pPhysical = DiskImg::kPhysicalFormatNib525_Var; + *pOrder = DiskImg::kSectorOrderPhysical; + } else if (hdr.type == kDiskType35) { + WMSG0("FDI: decoding 3.5\" disk\n"); + if (hdr.lastHead != 1 || hdr.lastTrack >= kMaxNibbleTracks35 + 10) { + WMSG2("FDI: bad params head=%d ltrack=%d\n", + hdr.lastHead, hdr.lastTrack); + dierr = kDIErrUnsupportedImageFeature; + goto bail; + } + if (hdr.lastTrack >= kMaxNibbleTracks35) { + WMSG2("FDI: reducing hdr.lastTrack from %d to %d\n", + hdr.lastTrack, kMaxNibbleTracks35-1); + hdr.lastTrack = kMaxNibbleTracks35-1; + } - /* - * Unpack to 800K of 512-byte ProDOS-order blocks, with a - * "bad block" map. - */ - dierr = Unpack35(pGFD, ppNewGFD, hdr.lastTrack+1, hdr.lastHead+1, - ppBadBlockMap); - if (dierr != kDIErrNone) - return dierr; + /* + * Unpack to 800K of 512-byte ProDOS-order blocks, with a + * "bad block" map. + */ + dierr = Unpack35(pGFD, ppNewGFD, hdr.lastTrack+1, hdr.lastHead+1, + ppBadBlockMap); + if (dierr != kDIErrNone) + return dierr; - *pLength = 800 * 1024; - *pPhysical = DiskImg::kPhysicalFormatSectors; - *pOrder = DiskImg::kSectorOrderProDOS; - } else { - WMSG0("FDI: unsupported disk type\n"); - dierr = kDIErrUnsupportedImageFeature; - goto bail; - } + *pLength = 800 * 1024; + *pPhysical = DiskImg::kPhysicalFormatSectors; + *pOrder = DiskImg::kSectorOrderProDOS; + } else { + WMSG0("FDI: unsupported disk type\n"); + dierr = kDIErrUnsupportedImageFeature; + goto bail; + } bail: return dierr; @@ -2115,18 +2115,18 @@ bail: */ DIError WrapperFDI::Unpack525(GenericFD* pGFD, GenericFD** ppNewGFD, int numCyls, - int numHeads) + int numHeads) { DIError dierr = kDIErrNone; - GFDBuffer* pNewGFD = nil; + GFDBuffer* pNewGFD = nil; unsigned char* buf = nil; - int numTracks; + int numTracks; - numTracks = numCyls * numHeads; - if (numTracks < kMaxNibbleTracks525) - numTracks = kMaxNibbleTracks525; + numTracks = numCyls * numHeads; + if (numTracks < kMaxNibbleTracks525) + numTracks = kMaxNibbleTracks525; - pGFD->Rewind(); + pGFD->Rewind(); buf = new unsigned char[numTracks * kTrackAllocSize]; if (buf == nil) { @@ -2134,16 +2134,16 @@ WrapperFDI::Unpack525(GenericFD* pGFD, GenericFD** ppNewGFD, int numCyls, goto bail; } - pNewGFD = new GFDBuffer; + pNewGFD = new GFDBuffer; if (pNewGFD == nil) { dierr = kDIErrMalloc; goto bail; } - dierr = pNewGFD->Open(buf, numTracks * kTrackAllocSize, - true, false, false); - if (dierr != kDIErrNone) - goto bail; - buf = nil; // now owned by pNewGFD; + dierr = pNewGFD->Open(buf, numTracks * kTrackAllocSize, + true, false, false); + if (dierr != kDIErrNone) + goto bail; + buf = nil; // now owned by pNewGFD; dierr = UnpackDisk525(pGFD, pNewGFD, numCyls, numHeads); if (dierr != kDIErrNone) @@ -2163,13 +2163,13 @@ bail: */ DIError WrapperFDI::Unpack35(GenericFD* pGFD, GenericFD** ppNewGFD, int numCyls, - int numHeads, LinearBitmap** ppBadBlockMap) + int numHeads, LinearBitmap** ppBadBlockMap) { DIError dierr = kDIErrNone; - GFDBuffer* pNewGFD = nil; + GFDBuffer* pNewGFD = nil; unsigned char* buf = nil; - pGFD->Rewind(); + pGFD->Rewind(); buf = new unsigned char[800 * 1024]; if (buf == nil) { @@ -2177,21 +2177,21 @@ WrapperFDI::Unpack35(GenericFD* pGFD, GenericFD** ppNewGFD, int numCyls, goto bail; } - pNewGFD = new GFDBuffer; + pNewGFD = new GFDBuffer; if (pNewGFD == nil) { dierr = kDIErrMalloc; goto bail; } - dierr = pNewGFD->Open(buf, 800 * 1024, true, false, false); - if (dierr != kDIErrNone) - goto bail; - buf = nil; // now owned by pNewGFD; + dierr = pNewGFD->Open(buf, 800 * 1024, true, false, false); + if (dierr != kDIErrNone) + goto bail; + buf = nil; // now owned by pNewGFD; - *ppBadBlockMap = new LinearBitmap(1600); - if (*ppBadBlockMap == nil) { - dierr = kDIErrMalloc; - goto bail; - } + *ppBadBlockMap = new LinearBitmap(1600); + if (*ppBadBlockMap == nil) { + dierr = kDIErrMalloc; + goto bail; + } dierr = UnpackDisk35(pGFD, pNewGFD, numCyls, numHeads, *ppBadBlockMap); if (dierr != kDIErrNone) @@ -2215,47 +2215,47 @@ WrapperFDI::Create(di_off_t length, DiskImg::PhysicalFormat physical, DiskImg::SectorOrder order, short dosVolumeNum, GenericFD* pWrapperGFD, di_off_t* pWrappedLength, GenericFD** pDataFD) { - DIError dierr = kDIErrGeneric; // not yet + DIError dierr = kDIErrGeneric; // not yet #if 0 - unsigned char* buf = nil; - int numTracks = (int) (length / kTrackLenTrackStar525); - int i; + unsigned char* buf = nil; + int numTracks = (int) (length / kTrackLenTrackStar525); + int i; assert(length == kTrackLenTrackStar525 * kTrackCount525 || - length == kTrackLenTrackStar525 * kTrackStarNumTracks); + length == kTrackLenTrackStar525 * kTrackStarNumTracks); assert(physical == DiskImg::kPhysicalFormatNib525_Var); assert(order == DiskImg::kSectorOrderPhysical); - /* - * Set up the track offset and length table. We use the maximum - * data length (kTrackLenTrackStar525) for each. The nibble write - * routine will alter the length field as appropriate. - */ - fNibbleTrackInfo.numTracks = numTracks; - assert(fNibbleTrackInfo.numTracks <= kMaxNibbleTracks); - for (i = 0; i < numTracks; i++) { - fNibbleTrackInfo.offset[i] = kTrackLenTrackStar525 * i; - fNibbleTrackInfo.length[i] = kTrackLenTrackStar525; - } + /* + * Set up the track offset and length table. We use the maximum + * data length (kTrackLenTrackStar525) for each. The nibble write + * routine will alter the length field as appropriate. + */ + fNibbleTrackInfo.numTracks = numTracks; + assert(fNibbleTrackInfo.numTracks <= kMaxNibbleTracks); + for (i = 0; i < numTracks; i++) { + fNibbleTrackInfo.offset[i] = kTrackLenTrackStar525 * i; + fNibbleTrackInfo.length[i] = kTrackLenTrackStar525; + } /* * Create a blank chunk of memory for the image. */ buf = new unsigned char[(int) length]; - if (buf == nil) { + if (buf == nil) { dierr = kDIErrMalloc; goto bail; } GFDBuffer* pNewGFD; - pNewGFD = new GFDBuffer; - dierr = pNewGFD->Open(buf, length, true, false, false); - if (dierr != kDIErrNone) { + pNewGFD = new GFDBuffer; + dierr = pNewGFD->Open(buf, length, true, false, false); + if (dierr != kDIErrNone) { delete pNewGFD; - goto bail; + goto bail; } *pDataFD = pNewGFD; - buf = nil; // now owned by pNewGFD; + buf = nil; // now owned by pNewGFD; // can't set *pWrappedLength yet @@ -2275,62 +2275,62 @@ DIError WrapperFDI::Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, di_off_t dataLen, di_off_t* pWrappedLen) { - DIError dierr = kDIErrGeneric; // not yet + DIError dierr = kDIErrGeneric; // not yet #if 0 assert(dataLen == kTrackLenTrackStar525 * kTrackCount525 || - dataLen == kTrackLenTrackStar525 * kTrackStarNumTracks); - assert(kTrackLenTrackStar525 <= kMaxTrackLen); + dataLen == kTrackLenTrackStar525 * kTrackStarNumTracks); + assert(kTrackLenTrackStar525 <= kMaxTrackLen); pDataGFD->Rewind(); - unsigned char writeBuf[kFileTrackStorageLen]; - unsigned char dataBuf[kTrackLenTrackStar525]; - int track, trackLen; + unsigned char writeBuf[kFileTrackStorageLen]; + unsigned char dataBuf[kTrackLenTrackStar525]; + int track, trackLen; - for (track = 0; track < kTrackStarNumTracks; track++) { - if (track < fNibbleTrackInfo.numTracks) { - dierr = pDataGFD->Read(dataBuf, kTrackLenTrackStar525); - if (dierr != kDIErrNone) - goto bail; - trackLen = fNibbleTrackInfo.length[track]; - assert(fNibbleTrackInfo.offset[track] == kTrackLenTrackStar525 * track); - } else { - WMSG1(" TrackStar faking track %d\n", track); - memset(dataBuf, 0xff, sizeof(dataBuf)); - trackLen = kMaxTrackLen; - } + for (track = 0; track < kTrackStarNumTracks; track++) { + if (track < fNibbleTrackInfo.numTracks) { + dierr = pDataGFD->Read(dataBuf, kTrackLenTrackStar525); + if (dierr != kDIErrNone) + goto bail; + trackLen = fNibbleTrackInfo.length[track]; + assert(fNibbleTrackInfo.offset[track] == kTrackLenTrackStar525 * track); + } else { + WMSG1(" TrackStar faking track %d\n", track); + memset(dataBuf, 0xff, sizeof(dataBuf)); + trackLen = kMaxTrackLen; + } - memset(writeBuf, 0x80, sizeof(writeBuf)); // not strictly necessary - memset(writeBuf, 0x20, kCommentFieldLen); - memset(writeBuf+kCommentFieldLen, 0x00, 0x81-kCommentFieldLen); + memset(writeBuf, 0x80, sizeof(writeBuf)); // not strictly necessary + memset(writeBuf, 0x20, kCommentFieldLen); + memset(writeBuf+kCommentFieldLen, 0x00, 0x81-kCommentFieldLen); - const char* comment; - if (fStorageName != NULL && *fStorageName != '\0') - comment = fStorageName; - else - comment = "(created by CiderPress)"; - if (strlen(comment) > kCommentFieldLen) - memcpy(writeBuf, comment, kCommentFieldLen); - else - memcpy(writeBuf, comment, strlen(comment)); + const char* comment; + if (fStorageName != NULL && *fStorageName != '\0') + comment = fStorageName; + else + comment = "(created by CiderPress)"; + if (strlen(comment) > kCommentFieldLen) + memcpy(writeBuf, comment, kCommentFieldLen); + else + memcpy(writeBuf, comment, strlen(comment)); - int i; - for (i = 0; i < trackLen; i++) - writeBuf[0x81+i] = dataBuf[trackLen - i -1]; + int i; + for (i = 0; i < trackLen; i++) + writeBuf[0x81+i] = dataBuf[trackLen - i -1]; - if (trackLen == kMaxTrackLen) - PutShortLE(writeBuf + 0x19fe, 0); - else - PutShortLE(writeBuf + 0x19fe, (unsigned short) trackLen); + if (trackLen == kMaxTrackLen) + PutShortLE(writeBuf + 0x19fe, 0); + else + PutShortLE(writeBuf + 0x19fe, (unsigned short) trackLen); - dierr = pWrapperGFD->Write(writeBuf, sizeof(writeBuf)); - if (dierr != kDIErrNone) - goto bail; - } + dierr = pWrapperGFD->Write(writeBuf, sizeof(writeBuf)); + if (dierr != kDIErrNone) + goto bail; + } *pWrappedLen = pWrapperGFD->Tell(); - assert(*pWrappedLen == kFileTrackStorageLen * kTrackStarNumTracks); + assert(*pWrappedLen == kFileTrackStorageLen * kTrackStarNumTracks); bail: #endif @@ -2340,21 +2340,21 @@ bail: void WrapperFDI::SetNibbleTrackLength(int track, int length) { - assert(false); // not yet + assert(false); // not yet #if 0 - assert(track >= 0); - assert(length > 0 && length <= kMaxTrackLen); - assert(track < fNibbleTrackInfo.numTracks); + assert(track >= 0); + assert(length > 0 && length <= kMaxTrackLen); + assert(track < fNibbleTrackInfo.numTracks); - WMSG2(" FDI: set length of track %d to %d\n", track, length); - fNibbleTrackInfo.length[track] = length; + WMSG2(" FDI: set length of track %d to %d\n", track, length); + fNibbleTrackInfo.length[track] = length; #endif } /* * =========================================================================== - * Unadorned nibble format + * Unadorned nibble format * =========================================================================== */ @@ -2364,7 +2364,7 @@ WrapperFDI::SetNibbleTrackLength(int track, int length) /*static*/ DIError WrapperUnadornedNibble::Test(GenericFD* pGFD, di_off_t wrappedLength) { - WMSG0("Testing for unadorned nibble\n"); + WMSG0("Testing for unadorned nibble\n"); /* test length */ if (wrappedLength != kTrackCount525 * kTrackLenNib525 && @@ -2379,7 +2379,7 @@ WrapperUnadornedNibble::Test(GenericFD* pGFD, di_off_t wrappedLength) pGFD->Rewind(); if (pGFD->Read(buf, sizeof(buf)) != kDIErrNone) - return kDIErrGeneric; + return kDIErrGeneric; /* * Make sure this is a nibble image and not just a ProDOS volume that @@ -2406,10 +2406,10 @@ WrapperUnadornedNibble::Test(GenericFD* pGFD, di_off_t wrappedLength) DIError WrapperUnadornedNibble::Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) { - WMSG0("Prep for unadorned nibble\n"); + WMSG0("Prep for unadorned nibble\n"); if (wrappedLength == kTrackCount525 * kTrackLenNib525) { WMSG0(" Prepping for 6656-byte NIB\n"); @@ -2418,10 +2418,10 @@ WrapperUnadornedNibble::Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readO WMSG0(" Prepping for 6384-byte NB2\n"); *pPhysical = DiskImg::kPhysicalFormatNib525_6384; } else { - WMSG1(" Unexpected wrappedLength %ld for unadorned nibble\n", - (long) wrappedLength); - assert(false); - } + WMSG1(" Unexpected wrappedLength %ld for unadorned nibble\n", + (long) wrappedLength); + assert(false); + } *pLength = wrappedLength; *pOrder = DiskImg::kSectorOrderPhysical; @@ -2458,7 +2458,7 @@ WrapperUnadornedNibble::Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, /* * =========================================================================== - * Unadorned sectors + * Unadorned sectors * =========================================================================== */ @@ -2476,14 +2476,14 @@ WrapperUnadornedNibble::Flush(GenericFD* pWrapperGFD, GenericFD* pDataGFD, /*static*/ DIError WrapperUnadornedSector::Test(GenericFD* pGFD, di_off_t wrappedLength) { - WMSG2("Testing for unadorned sector (wrappedLength=%ld/%lu)\n", - (long) (wrappedLength >> 32), (unsigned long) wrappedLength); + WMSG2("Testing for unadorned sector (wrappedLength=%ld/%lu)\n", + (long) (wrappedLength >> 32), (unsigned long) wrappedLength); if (wrappedLength >= 1536 && (wrappedLength % 512) == 0) - return kDIErrNone; - if (wrappedLength == kD13Length) // 13-sector image? - return kDIErrNone; + return kDIErrNone; + if (wrappedLength == kD13Length) // 13-sector image? + return kDIErrNone; - return kDIErrGeneric; + return kDIErrGeneric; } /* @@ -2492,13 +2492,13 @@ WrapperUnadornedSector::Test(GenericFD* pGFD, di_off_t wrappedLength) DIError WrapperUnadornedSector::Prep(GenericFD* pGFD, di_off_t wrappedLength, bool readOnly, di_off_t* pLength, DiskImg::PhysicalFormat* pPhysical, - DiskImg::SectorOrder* pOrder, short* pDiskVolNum, - LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) + DiskImg::SectorOrder* pOrder, short* pDiskVolNum, + LinearBitmap** ppBadBlockMap, GenericFD** ppNewGFD) { - WMSG0("Prepping for unadorned sector\n"); - assert(wrappedLength > 0); - *pLength = wrappedLength; - *pPhysical = DiskImg::kPhysicalFormatSectors; + WMSG0("Prepping for unadorned sector\n"); + assert(wrappedLength > 0); + *pLength = wrappedLength; + *pPhysical = DiskImg::kPhysicalFormatSectors; //*pOrder = undetermined *ppNewGFD = new GFDGFD; diff --git a/diskimg/MacPart.cpp b/diskimg/MacPart.cpp index 07ce94b..50c3be9 100644 --- a/diskimg/MacPart.cpp +++ b/diskimg/MacPart.cpp @@ -13,51 +13,51 @@ const int kBlkSize = 512; -const int kDDRBlock = 0; // Driver Descriptor Record block -const int kPartMapStart = 1; // start of partition map +const int kDDRBlock = 0; // Driver Descriptor Record block +const int kPartMapStart = 1; // start of partition map /* * Format of DDR (block 0). */ typedef struct DiskFSMacPart::DriverDescriptorRecord { - unsigned short sbSig; // {device signature} - unsigned short sbBlkSize; // {block size of the device} - unsigned long sbBlkCount; // {number of blocks on the device} - unsigned short sbDevType; // {reserved} - unsigned short sbDevId; // {reserved} - unsigned long sbData; // {reserved} - unsigned short sbDrvrCount; // {number of driver descriptor entries} - unsigned short hiddenPad; // implicit in specification - unsigned long ddBlock; // {first driver's starting block} - unsigned short ddSize; // {size of the driver, in 512-byte blocks} - unsigned short ddType; // {operating system type (MacOS = 1)} - unsigned short ddPad[242]; // {additional drivers, if any} + unsigned short sbSig; // {device signature} + unsigned short sbBlkSize; // {block size of the device} + unsigned long sbBlkCount; // {number of blocks on the device} + unsigned short sbDevType; // {reserved} + unsigned short sbDevId; // {reserved} + unsigned long sbData; // {reserved} + unsigned short sbDrvrCount; // {number of driver descriptor entries} + unsigned short hiddenPad; // implicit in specification + unsigned long ddBlock; // {first driver's starting block} + unsigned short ddSize; // {size of the driver, in 512-byte blocks} + unsigned short ddType; // {operating system type (MacOS = 1)} + unsigned short ddPad[242]; // {additional drivers, if any} } DriverDescriptorRecord; /* * Format of partition map blocks. The partition map is an array of these. */ typedef struct DiskFSMacPart::PartitionMap { - unsigned short pmSig; // {partition signature} - unsigned short pmSigPad; // {reserved} - unsigned long pmMapBlkCnt; // {number of blocks in partition map} - unsigned long pmPyPartStart; // {first physical block of partition} - unsigned long pmPartBlkCnt; // {number of blocks in partition} - unsigned char pmPartName[32]; // {partition name} - unsigned char pmParType[32]; // {partition type} - unsigned long pmLgDataStart; // {first logical block of data area} - unsigned long pmDataCnt; // {number of blocks in data area} - unsigned long pmPartStatus; // {partition status information} - unsigned long pmLgBootStart; // {first logical block of boot code} - unsigned long pmBootSize; // {size of boot code, in bytes} - unsigned long pmBootAddr; // {boot code load address} - unsigned long pmBootAddr2; // {reserved} - unsigned long pmBootEntry; // {boot code entry point} - unsigned long pmBootEntry2; // {reserved} - unsigned long pmBootCksum; // {boot code checksum} - unsigned char pmProcessor[16]; // {processor type} - unsigned short pmPad[188]; // {reserved} + unsigned short pmSig; // {partition signature} + unsigned short pmSigPad; // {reserved} + unsigned long pmMapBlkCnt; // {number of blocks in partition map} + unsigned long pmPyPartStart; // {first physical block of partition} + unsigned long pmPartBlkCnt; // {number of blocks in partition} + unsigned char pmPartName[32]; // {partition name} + unsigned char pmParType[32]; // {partition type} + unsigned long pmLgDataStart; // {first logical block of data area} + unsigned long pmDataCnt; // {number of blocks in data area} + unsigned long pmPartStatus; // {partition status information} + unsigned long pmLgBootStart; // {first logical block of boot code} + unsigned long pmBootSize; // {size of boot code, in bytes} + unsigned long pmBootAddr; // {boot code load address} + unsigned long pmBootAddr2; // {reserved} + unsigned long pmBootEntry; // {boot code entry point} + unsigned long pmBootEntry2; // {reserved} + unsigned long pmBootCksum; // {boot code checksum} + unsigned char pmProcessor[16]; // {processor type} + unsigned short pmPad[188]; // {reserved} } PartitionMap; @@ -73,74 +73,74 @@ typedef struct DiskFSMacPart::PartitionMap { /*static*/ DIError DiskFSMacPart::TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder) { - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; - DriverDescriptorRecord ddr; - long pmMapBlkCnt; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; + DriverDescriptorRecord ddr; + long pmMapBlkCnt; - assert(sizeof(PartitionMap) == kBlkSize); - assert(sizeof(DriverDescriptorRecord) == kBlkSize); + assert(sizeof(PartitionMap) == kBlkSize); + assert(sizeof(DriverDescriptorRecord) == kBlkSize); - /* check the DDR block */ - dierr = pImg->ReadBlockSwapped(kDDRBlock, blkBuf, imageOrder, - DiskImg::kSectorOrderProDOS); - if (dierr != kDIErrNone) - goto bail; + /* check the DDR block */ + dierr = pImg->ReadBlockSwapped(kDDRBlock, blkBuf, imageOrder, + DiskImg::kSectorOrderProDOS); + if (dierr != kDIErrNone) + goto bail; - UnpackDDR(blkBuf, &ddr); + UnpackDDR(blkBuf, &ddr); - if (ddr.sbSig != kDDRSignature) { - dierr = kDIErrFilesystemNotFound; - goto bail; - } - if (ddr.sbBlkSize != kBlkSize || ddr.sbBlkCount == 0) { - if (ddr.sbBlkSize == 0 && ddr.sbBlkCount == 0) { - /* - * This is invalid, but it's the way floptical images formatted - * by the C.V.Tech format utilities look. - */ - WMSG0(" MacPart NOTE: found zeroed-out DDR, continuing anyway\n"); - } else if (ddr.sbBlkSize == kBlkSize && ddr.sbBlkCount == 0) { - /* - * This showed up on a disc, so handle it too. - */ - WMSG0(" MacPart NOTE: found partially-zeroed-out DDR, continuing\n"); - } else { - WMSG2(" MacPart found 'ER' signature but blkSize=%d blkCount=%ld\n", - ddr.sbBlkSize, ddr.sbBlkCount); - dierr = kDIErrFilesystemNotFound; - goto bail; - } - } - DumpDDR(&ddr); + if (ddr.sbSig != kDDRSignature) { + dierr = kDIErrFilesystemNotFound; + goto bail; + } + if (ddr.sbBlkSize != kBlkSize || ddr.sbBlkCount == 0) { + if (ddr.sbBlkSize == 0 && ddr.sbBlkCount == 0) { + /* + * This is invalid, but it's the way floptical images formatted + * by the C.V.Tech format utilities look. + */ + WMSG0(" MacPart NOTE: found zeroed-out DDR, continuing anyway\n"); + } else if (ddr.sbBlkSize == kBlkSize && ddr.sbBlkCount == 0) { + /* + * This showed up on a disc, so handle it too. + */ + WMSG0(" MacPart NOTE: found partially-zeroed-out DDR, continuing\n"); + } else { + WMSG2(" MacPart found 'ER' signature but blkSize=%d blkCount=%ld\n", + ddr.sbBlkSize, ddr.sbBlkCount); + dierr = kDIErrFilesystemNotFound; + goto bail; + } + } + DumpDDR(&ddr); - /* make sure block 1 is a partition */ - dierr = pImg->ReadBlockSwapped(kPartMapStart, blkBuf, imageOrder, - DiskImg::kSectorOrderProDOS); - if (dierr != kDIErrNone) - goto bail; + /* make sure block 1 is a partition */ + dierr = pImg->ReadBlockSwapped(kPartMapStart, blkBuf, imageOrder, + DiskImg::kSectorOrderProDOS); + if (dierr != kDIErrNone) + goto bail; - if (GetShortBE(&blkBuf[0x00]) != kPartitionSignature) { - WMSG0(" MacPart partition signature not found in first part block\n"); - dierr = kDIErrFilesystemNotFound; - goto bail; - } - pmMapBlkCnt = GetLongBE(&blkBuf[0x04]); - if (pmMapBlkCnt <= 0 || pmMapBlkCnt > 256) { - WMSG1(" MacPart unreasonable pmMapBlkCnt value %ld\n", - pmMapBlkCnt); - dierr = kDIErrFilesystemNotFound; - goto bail; - } + if (GetShortBE(&blkBuf[0x00]) != kPartitionSignature) { + WMSG0(" MacPart partition signature not found in first part block\n"); + dierr = kDIErrFilesystemNotFound; + goto bail; + } + pmMapBlkCnt = GetLongBE(&blkBuf[0x04]); + if (pmMapBlkCnt <= 0 || pmMapBlkCnt > 256) { + WMSG1(" MacPart unreasonable pmMapBlkCnt value %ld\n", + pmMapBlkCnt); + dierr = kDIErrFilesystemNotFound; + goto bail; + } - /* could test the rest -- might fix "imageOrder", might not -- but - the format is pretty unambiguous, and we don't care about the order */ + /* could test the rest -- might fix "imageOrder", might not -- but + the format is pretty unambiguous, and we don't care about the order */ - // success! - WMSG1(" MacPart partition map block count = %ld\n", pmMapBlkCnt); + // success! + WMSG1(" MacPart partition map block count = %ld\n", pmMapBlkCnt); bail: - return dierr; + return dierr; } /* @@ -148,25 +148,25 @@ bail: */ /*static*/ void DiskFSMacPart::UnpackDDR(const unsigned char* buf, - DriverDescriptorRecord* pDDR) + DriverDescriptorRecord* pDDR) { - pDDR->sbSig = GetShortBE(&buf[0x00]); - pDDR->sbBlkSize = GetShortBE(&buf[0x02]); - pDDR->sbBlkCount = GetLongBE(&buf[0x04]); - pDDR->sbDevType = GetShortBE(&buf[0x08]); - pDDR->sbDevId = GetShortBE(&buf[0x0a]); - pDDR->sbData = GetLongBE(&buf[0x0c]); - pDDR->sbDrvrCount = GetShortBE(&buf[0x10]); - pDDR->hiddenPad = GetShortBE(&buf[0x12]); - pDDR->ddBlock = GetLongBE(&buf[0x14]); - pDDR->ddSize = GetShortBE(&buf[0x18]); - pDDR->ddType = GetShortBE(&buf[0x1a]); + pDDR->sbSig = GetShortBE(&buf[0x00]); + pDDR->sbBlkSize = GetShortBE(&buf[0x02]); + pDDR->sbBlkCount = GetLongBE(&buf[0x04]); + pDDR->sbDevType = GetShortBE(&buf[0x08]); + pDDR->sbDevId = GetShortBE(&buf[0x0a]); + pDDR->sbData = GetLongBE(&buf[0x0c]); + pDDR->sbDrvrCount = GetShortBE(&buf[0x10]); + pDDR->hiddenPad = GetShortBE(&buf[0x12]); + pDDR->ddBlock = GetLongBE(&buf[0x14]); + pDDR->ddSize = GetShortBE(&buf[0x18]); + pDDR->ddType = GetShortBE(&buf[0x1a]); - int i; - for (i = 0; i < (int) NELEM(pDDR->ddPad); i++) { - pDDR->ddPad[i] = GetShortBE(&buf[0x1c] + i * sizeof(pDDR->ddPad[0])); - } - assert(0x1c + i * sizeof(pDDR->ddPad[0]) == (unsigned int) kBlkSize); + int i; + for (i = 0; i < (int) NELEM(pDDR->ddPad); i++) { + pDDR->ddPad[i] = GetShortBE(&buf[0x1c] + i * sizeof(pDDR->ddPad[0])); + } + assert(0x1c + i * sizeof(pDDR->ddPad[0]) == (unsigned int) kBlkSize); } /* @@ -175,13 +175,13 @@ DiskFSMacPart::UnpackDDR(const unsigned char* buf, /*static*/ void DiskFSMacPart::DumpDDR(const DriverDescriptorRecord* pDDR) { - WMSG0(" MacPart driver descriptor record\n"); - WMSG3(" sbSig=0x%04x sbBlkSize=%d sbBlkCount=%ld\n", - pDDR->sbSig, pDDR->sbBlkSize, pDDR->sbBlkCount); - WMSG4(" sbDevType=%d sbDevId=%d sbData=%ld sbDrvrCount=%d\n", - pDDR->sbDevType, pDDR->sbDevId, pDDR->sbData, pDDR->sbDrvrCount); - WMSG4(" (pad=%d) ddBlock=%ld ddSize=%d ddType=%d\n", - pDDR->hiddenPad, pDDR->ddBlock, pDDR->ddSize, pDDR->ddType); + WMSG0(" MacPart driver descriptor record\n"); + WMSG3(" sbSig=0x%04x sbBlkSize=%d sbBlkCount=%ld\n", + pDDR->sbSig, pDDR->sbBlkSize, pDDR->sbBlkCount); + WMSG4(" sbDevType=%d sbDevId=%d sbData=%ld sbDrvrCount=%d\n", + pDDR->sbDevType, pDDR->sbDevId, pDDR->sbData, pDDR->sbDrvrCount); + WMSG4(" (pad=%d) ddBlock=%ld ddSize=%d ddType=%d\n", + pDDR->hiddenPad, pDDR->ddBlock, pDDR->ddSize, pDDR->ddType); } /* @@ -189,35 +189,35 @@ DiskFSMacPart::DumpDDR(const DriverDescriptorRecord* pDDR) */ /*static*/ void DiskFSMacPart::UnpackPartitionMap(const unsigned char* buf, - PartitionMap* pMap) + PartitionMap* pMap) { - pMap->pmSig = GetShortBE(&buf[0x00]); - pMap->pmSigPad = GetShortBE(&buf[0x02]); - pMap->pmMapBlkCnt = GetLongBE(&buf[0x04]); - pMap->pmPyPartStart = GetLongBE(&buf[0x08]); - pMap->pmPartBlkCnt = GetLongBE(&buf[0x0c]); - memcpy(pMap->pmPartName, &buf[0x10], sizeof(pMap->pmPartName)); - pMap->pmPartName[sizeof(pMap->pmPartName)-1] = '\0'; - memcpy(pMap->pmParType, &buf[0x30], sizeof(pMap->pmParType)); - pMap->pmParType[sizeof(pMap->pmParType)-1] = '\0'; - pMap->pmLgDataStart = GetLongBE(&buf[0x50]); - pMap->pmDataCnt = GetLongBE(&buf[0x54]); - pMap->pmPartStatus = GetLongBE(&buf[0x58]); - pMap->pmLgBootStart = GetLongBE(&buf[0x5c]); - pMap->pmBootSize = GetLongBE(&buf[0x60]); - pMap->pmBootAddr = GetLongBE(&buf[0x64]); - pMap->pmBootAddr2 = GetLongBE(&buf[0x68]); - pMap->pmBootEntry = GetLongBE(&buf[0x6c]); - pMap->pmBootEntry2 = GetLongBE(&buf[0x70]); - pMap->pmBootCksum = GetLongBE(&buf[0x74]); - memcpy((char*) pMap->pmProcessor, &buf[0x78], sizeof(pMap->pmProcessor)); - pMap->pmProcessor[sizeof(pMap->pmProcessor)-1] = '\0'; + pMap->pmSig = GetShortBE(&buf[0x00]); + pMap->pmSigPad = GetShortBE(&buf[0x02]); + pMap->pmMapBlkCnt = GetLongBE(&buf[0x04]); + pMap->pmPyPartStart = GetLongBE(&buf[0x08]); + pMap->pmPartBlkCnt = GetLongBE(&buf[0x0c]); + memcpy(pMap->pmPartName, &buf[0x10], sizeof(pMap->pmPartName)); + pMap->pmPartName[sizeof(pMap->pmPartName)-1] = '\0'; + memcpy(pMap->pmParType, &buf[0x30], sizeof(pMap->pmParType)); + pMap->pmParType[sizeof(pMap->pmParType)-1] = '\0'; + pMap->pmLgDataStart = GetLongBE(&buf[0x50]); + pMap->pmDataCnt = GetLongBE(&buf[0x54]); + pMap->pmPartStatus = GetLongBE(&buf[0x58]); + pMap->pmLgBootStart = GetLongBE(&buf[0x5c]); + pMap->pmBootSize = GetLongBE(&buf[0x60]); + pMap->pmBootAddr = GetLongBE(&buf[0x64]); + pMap->pmBootAddr2 = GetLongBE(&buf[0x68]); + pMap->pmBootEntry = GetLongBE(&buf[0x6c]); + pMap->pmBootEntry2 = GetLongBE(&buf[0x70]); + pMap->pmBootCksum = GetLongBE(&buf[0x74]); + memcpy((char*) pMap->pmProcessor, &buf[0x78], sizeof(pMap->pmProcessor)); + pMap->pmProcessor[sizeof(pMap->pmProcessor)-1] = '\0'; - int i; - for (i = 0; i < (int) NELEM(pMap->pmPad); i++) { - pMap->pmPad[i] = GetShortBE(&buf[0x88] + i * sizeof(pMap->pmPad[0])); - } - assert(0x88 + i * sizeof(pMap->pmPad[0]) == (unsigned int) kBlkSize); + int i; + for (i = 0; i < (int) NELEM(pMap->pmPad); i++) { + pMap->pmPad[i] = GetShortBE(&buf[0x88] + i * sizeof(pMap->pmPad[0])); + } + assert(0x88 + i * sizeof(pMap->pmPad[0]) == (unsigned int) kBlkSize); } /* @@ -226,24 +226,24 @@ DiskFSMacPart::UnpackPartitionMap(const unsigned char* buf, /*static*/ void DiskFSMacPart::DumpPartitionMap(long block, const PartitionMap* pMap) { - WMSG1(" MacPart partition map: block=%ld\n", block); - WMSG3(" pmSig=0x%04x (pad=0x%04x) pmMapBlkCnt=%ld\n", - pMap->pmSig, pMap->pmSigPad, pMap->pmMapBlkCnt); - WMSG2(" pmPartName='%s' pmParType='%s'\n", - pMap->pmPartName, pMap->pmParType); - WMSG2(" pmPyPartStart=%ld pmPartBlkCnt=%ld\n", - pMap->pmPyPartStart, pMap->pmPartBlkCnt); - WMSG2(" pmLgDataStart=%ld pmDataCnt=%ld\n", - pMap->pmLgDataStart, pMap->pmDataCnt); - WMSG1(" pmPartStatus=%ld\n", - pMap->pmPartStatus); - WMSG2(" pmLgBootStart=%ld pmBootSize=%ld\n", - pMap->pmLgBootStart, pMap->pmBootSize); - WMSG4(" pmBootAddr=%ld pmBootAddr2=%ld pmBootEntry=%ld pmBootEntry2=%ld\n", - pMap->pmBootAddr, pMap->pmBootAddr2, - pMap->pmBootEntry, pMap->pmBootEntry2); - WMSG2(" pmBootCksum=%ld pmProcessor='%s'\n", - pMap->pmBootCksum, pMap->pmProcessor); + WMSG1(" MacPart partition map: block=%ld\n", block); + WMSG3(" pmSig=0x%04x (pad=0x%04x) pmMapBlkCnt=%ld\n", + pMap->pmSig, pMap->pmSigPad, pMap->pmMapBlkCnt); + WMSG2(" pmPartName='%s' pmParType='%s'\n", + pMap->pmPartName, pMap->pmParType); + WMSG2(" pmPyPartStart=%ld pmPartBlkCnt=%ld\n", + pMap->pmPyPartStart, pMap->pmPartBlkCnt); + WMSG2(" pmLgDataStart=%ld pmDataCnt=%ld\n", + pMap->pmLgDataStart, pMap->pmDataCnt); + WMSG1(" pmPartStatus=%ld\n", + pMap->pmPartStatus); + WMSG2(" pmLgBootStart=%ld pmBootSize=%ld\n", + pMap->pmLgBootStart, pMap->pmBootSize); + WMSG4(" pmBootAddr=%ld pmBootAddr2=%ld pmBootEntry=%ld pmBootEntry2=%ld\n", + pMap->pmBootAddr, pMap->pmBootAddr2, + pMap->pmBootEntry, pMap->pmBootEntry2); + WMSG2(" pmBootCksum=%ld pmProcessor='%s'\n", + pMap->pmBootCksum, pMap->pmProcessor); } @@ -253,128 +253,128 @@ DiskFSMacPart::DumpPartitionMap(long block, const PartitionMap* pMap) DIError DiskFSMacPart::OpenSubVolume(const PartitionMap* pMap) { - DIError dierr = kDIErrNone; - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; - long startBlock, numBlocks; - bool tweaked = false; + DIError dierr = kDIErrNone; + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; + long startBlock, numBlocks; + bool tweaked = false; - assert(pMap != nil); - startBlock = pMap->pmPyPartStart; - numBlocks = pMap->pmPartBlkCnt; + assert(pMap != nil); + startBlock = pMap->pmPyPartStart; + numBlocks = pMap->pmPartBlkCnt; - WMSG4("Adding '%s' (%s) %ld +%ld\n", - pMap->pmPartName, pMap->pmParType, startBlock, numBlocks); + WMSG4("Adding '%s' (%s) %ld +%ld\n", + pMap->pmPartName, pMap->pmParType, startBlock, numBlocks); - if (startBlock > fpImg->GetNumBlocks()) { - WMSG2("MacPart start block out of range (%ld vs %ld)\n", - startBlock, fpImg->GetNumBlocks()); - return kDIErrBadPartition; - } - if (startBlock + numBlocks > fpImg->GetNumBlocks()) { - WMSG2("MacPart partition too large (%ld vs %ld avail)\n", - numBlocks, fpImg->GetNumBlocks() - startBlock); - fpImg->AddNote(DiskImg::kNoteInfo, - "Reduced partition '%s' (%s) from %ld blocks to %ld.\n", - pMap->pmPartName, pMap->pmParType, numBlocks, - fpImg->GetNumBlocks() - startBlock); - numBlocks = fpImg->GetNumBlocks() - startBlock; - tweaked = true; - } + if (startBlock > fpImg->GetNumBlocks()) { + WMSG2("MacPart start block out of range (%ld vs %ld)\n", + startBlock, fpImg->GetNumBlocks()); + return kDIErrBadPartition; + } + if (startBlock + numBlocks > fpImg->GetNumBlocks()) { + WMSG2("MacPart partition too large (%ld vs %ld avail)\n", + numBlocks, fpImg->GetNumBlocks() - startBlock); + fpImg->AddNote(DiskImg::kNoteInfo, + "Reduced partition '%s' (%s) from %ld blocks to %ld.\n", + pMap->pmPartName, pMap->pmParType, numBlocks, + fpImg->GetNumBlocks() - startBlock); + numBlocks = fpImg->GetNumBlocks() - startBlock; + tweaked = true; + } - pNewImg = new DiskImg; - if (pNewImg == nil) { - dierr = kDIErrMalloc; - goto bail; - } + pNewImg = new DiskImg; + if (pNewImg == nil) { + dierr = kDIErrMalloc; + goto bail; + } - /* - * If "tweaked" is true, we want to make the volume read-only, so that the - * volume copier doesn't stomp on it (on the off chance we've got it - * wrong). However, that won't stop the volume copier from stomping on - * the entire thing, so we really need to change *all* members of the - * diskimg tree to be read-only. This seems counter-productive though. - * - * So far the only actual occurrence of tweakedness was from the first - * Apple "develop" CD-ROM, which had a bad Apple_Extra partition on the - * end. - */ + /* + * If "tweaked" is true, we want to make the volume read-only, so that the + * volume copier doesn't stomp on it (on the off chance we've got it + * wrong). However, that won't stop the volume copier from stomping on + * the entire thing, so we really need to change *all* members of the + * diskimg tree to be read-only. This seems counter-productive though. + * + * So far the only actual occurrence of tweakedness was from the first + * Apple "develop" CD-ROM, which had a bad Apple_Extra partition on the + * end. + */ - dierr = pNewImg->OpenImage(fpImg, startBlock, numBlocks); - if (dierr != kDIErrNone) { - WMSG3(" MacPartSub: OpenImage(%ld,%ld) failed (err=%d)\n", - startBlock, numBlocks, dierr); - goto bail; - } + dierr = pNewImg->OpenImage(fpImg, startBlock, numBlocks); + if (dierr != kDIErrNone) { + WMSG3(" MacPartSub: OpenImage(%ld,%ld) failed (err=%d)\n", + startBlock, numBlocks, dierr); + goto bail; + } - //WMSG2(" +++ CFFASub: new image has ro=%d (parent=%d)\n", - // pNewImg->GetReadOnly(), pImg->GetReadOnly()); + //WMSG2(" +++ CFFASub: new image has ro=%d (parent=%d)\n", + // pNewImg->GetReadOnly(), pImg->GetReadOnly()); - /* the partition is typed; currently no way to give hints to analyzer */ - dierr = pNewImg->AnalyzeImage(); - if (dierr != kDIErrNone) { - WMSG1(" MacPartSub: analysis failed (err=%d)\n", dierr); - goto bail; - } + /* the partition is typed; currently no way to give hints to analyzer */ + dierr = pNewImg->AnalyzeImage(); + if (dierr != kDIErrNone) { + WMSG1(" MacPartSub: analysis failed (err=%d)\n", dierr); + goto bail; + } - /* we allow unrecognized partitions */ - if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || - pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) - { - WMSG2(" MacPartSub (%ld,%ld): unable to identify filesystem\n", - startBlock, numBlocks); - DiskFSUnknown* pUnknownFS = new DiskFSUnknown; - if (pUnknownFS == nil) { - dierr = kDIErrInternal; - goto bail; - } - pUnknownFS->SetVolumeInfo((const char*)pMap->pmParType); - pNewFS = pUnknownFS; - pNewImg->AddNote(DiskImg::kNoteInfo, "Partition name='%s' type='%s'.", - pMap->pmPartName, pMap->pmParType); - } else { - /* open a DiskFS for the sub-image */ - WMSG2(" MacPartSub (%ld,%ld) analyze succeeded!\n", startBlock, numBlocks); - pNewFS = pNewImg->OpenAppropriateDiskFS(true); - if (pNewFS == nil) { - WMSG0(" MacPartSub: OpenAppropriateDiskFS failed\n"); - dierr = kDIErrUnsupportedFSFmt; - goto bail; - } - } + /* we allow unrecognized partitions */ + if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || + pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) + { + WMSG2(" MacPartSub (%ld,%ld): unable to identify filesystem\n", + startBlock, numBlocks); + DiskFSUnknown* pUnknownFS = new DiskFSUnknown; + if (pUnknownFS == nil) { + dierr = kDIErrInternal; + goto bail; + } + pUnknownFS->SetVolumeInfo((const char*)pMap->pmParType); + pNewFS = pUnknownFS; + pNewImg->AddNote(DiskImg::kNoteInfo, "Partition name='%s' type='%s'.", + pMap->pmPartName, pMap->pmParType); + } else { + /* open a DiskFS for the sub-image */ + WMSG2(" MacPartSub (%ld,%ld) analyze succeeded!\n", startBlock, numBlocks); + pNewFS = pNewImg->OpenAppropriateDiskFS(true); + if (pNewFS == nil) { + WMSG0(" MacPartSub: OpenAppropriateDiskFS failed\n"); + dierr = kDIErrUnsupportedFSFmt; + goto bail; + } + } - /* we encapsulate arbitrary stuff, so encourage child to scan */ - pNewFS->SetScanForSubVolumes(kScanSubEnabled); + /* we encapsulate arbitrary stuff, so encourage child to scan */ + pNewFS->SetScanForSubVolumes(kScanSubEnabled); - /* - * Load the files from the sub-image. When doing our initial tests, - * or when loading data for the volume copier, we don't want to dig - * into our sub-volumes, just figure out what they are and where. - * - * If "initialize" fails, the sub-volume won't get added to the list. - * It's important that a failure at this stage doesn't cause the whole - * thing to fall over. - */ - InitMode initMode; - if (GetScanForSubVolumes() == kScanSubContainerOnly) - initMode = kInitHeaderOnly; - else - initMode = kInitFull; - dierr = pNewFS->Initialize(pNewImg, initMode); - if (dierr != kDIErrNone) { - WMSG1(" MacPartSub: error %d reading list of files from disk\n", dierr); - goto bail; - } + /* + * Load the files from the sub-image. When doing our initial tests, + * or when loading data for the volume copier, we don't want to dig + * into our sub-volumes, just figure out what they are and where. + * + * If "initialize" fails, the sub-volume won't get added to the list. + * It's important that a failure at this stage doesn't cause the whole + * thing to fall over. + */ + InitMode initMode; + if (GetScanForSubVolumes() == kScanSubContainerOnly) + initMode = kInitHeaderOnly; + else + initMode = kInitFull; + dierr = pNewFS->Initialize(pNewImg, initMode); + if (dierr != kDIErrNone) { + WMSG1(" MacPartSub: error %d reading list of files from disk\n", dierr); + goto bail; + } - /* add it to the list */ - AddSubVolumeToList(pNewImg, pNewFS); - pNewImg = nil; - pNewFS = nil; + /* add it to the list */ + AddSubVolumeToList(pNewImg, pNewFS); + pNewImg = nil; + pNewFS = nil; bail: - delete pNewFS; - delete pNewImg; - return dierr; + delete pNewFS; + delete pNewImg; + return dierr; } /* @@ -382,22 +382,22 @@ bail: */ /*static*/ DIError DiskFSMacPart::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency) + DiskImg::FSFormat* pFormat, FSLeniency leniency) { - if (pImg->GetNumBlocks() < kMinInterestingBlocks) - return kDIErrFilesystemNotFound; - if (pImg->GetIsEmbedded()) // don't look for partitions inside - return kDIErrFilesystemNotFound; + if (pImg->GetNumBlocks() < kMinInterestingBlocks) + return kDIErrFilesystemNotFound; + if (pImg->GetIsEmbedded()) // don't look for partitions inside + return kDIErrFilesystemNotFound; - /* assume ProDOS -- shouldn't matter, since it's embedded */ - if (TestImage(pImg, DiskImg::kSectorOrderProDOS) == kDIErrNone) { - *pFormat = DiskImg::kFormatMacPart; - *pOrder = DiskImg::kSectorOrderProDOS; - return kDIErrNone; - } + /* assume ProDOS -- shouldn't matter, since it's embedded */ + if (TestImage(pImg, DiskImg::kSectorOrderProDOS) == kDIErrNone) { + *pFormat = DiskImg::kFormatMacPart; + *pOrder = DiskImg::kSectorOrderProDOS; + return kDIErrNone; + } - WMSG0(" FS didn't find valid MacPart\n"); - return kDIErrFilesystemNotFound; + WMSG0(" FS didn't find valid MacPart\n"); + return kDIErrFilesystemNotFound; } @@ -407,21 +407,21 @@ DiskFSMacPart::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DIError DiskFSMacPart::Initialize(void) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - WMSG1("MacPart initializing (scanForSub=%d)\n", fScanForSubVolumes); + WMSG1("MacPart initializing (scanForSub=%d)\n", fScanForSubVolumes); - /* seems pointless *not* to, but we just do what we're told */ - if (fScanForSubVolumes != kScanSubDisabled) { - dierr = FindSubVolumes(); - if (dierr != kDIErrNone) - return dierr; - } + /* seems pointless *not* to, but we just do what we're told */ + if (fScanForSubVolumes != kScanSubDisabled) { + dierr = FindSubVolumes(); + if (dierr != kDIErrNone) + return dierr; + } - /* blank out the volume usage map */ - SetVolumeUsageMap(); + /* blank out the volume usage map */ + SetVolumeUsageMap(); - return dierr; + return dierr; } @@ -434,46 +434,46 @@ DiskFSMacPart::Initialize(void) DIError DiskFSMacPart::FindSubVolumes(void) { - DIError dierr = kDIErrNone; - unsigned char buf[kBlkSize]; - PartitionMap map; - int i, numMapBlocks; + DIError dierr = kDIErrNone; + unsigned char buf[kBlkSize]; + PartitionMap map; + int i, numMapBlocks; - dierr = fpImg->ReadBlock(kPartMapStart, buf); - if (dierr != kDIErrNone) - goto bail; - UnpackPartitionMap(buf, &map); - numMapBlocks = map.pmMapBlkCnt; + dierr = fpImg->ReadBlock(kPartMapStart, buf); + if (dierr != kDIErrNone) + goto bail; + UnpackPartitionMap(buf, &map); + numMapBlocks = map.pmMapBlkCnt; - for (i = 0; i < numMapBlocks; i++) { - if (i != 0) { - dierr = fpImg->ReadBlock(kPartMapStart+i, buf); - if (dierr != kDIErrNone) - goto bail; - UnpackPartitionMap(buf, &map); - } - DumpPartitionMap(kPartMapStart+i, &map); + for (i = 0; i < numMapBlocks; i++) { + if (i != 0) { + dierr = fpImg->ReadBlock(kPartMapStart+i, buf); + if (dierr != kDIErrNone) + goto bail; + UnpackPartitionMap(buf, &map); + } + DumpPartitionMap(kPartMapStart+i, &map); - dierr = OpenSubVolume(&map); - if (dierr != kDIErrNone) { - if (dierr == kDIErrCancelled) - goto bail; - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; - WMSG1(" MacPart failed opening sub-volume %d\n", i); - dierr = CreatePlaceholder(map.pmPyPartStart, map.pmPartBlkCnt, - (const char*)map.pmPartName, (const char*)map.pmParType, - &pNewImg, &pNewFS); - if (dierr == kDIErrNone) { - AddSubVolumeToList(pNewImg, pNewFS); - } else { - WMSG1(" MacPart unable to create placeholder (err=%d)\n", - dierr); - break; // something's wrong -- bail out with error - } - } - } + dierr = OpenSubVolume(&map); + if (dierr != kDIErrNone) { + if (dierr == kDIErrCancelled) + goto bail; + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; + WMSG1(" MacPart failed opening sub-volume %d\n", i); + dierr = CreatePlaceholder(map.pmPyPartStart, map.pmPartBlkCnt, + (const char*)map.pmPartName, (const char*)map.pmParType, + &pNewImg, &pNewFS); + if (dierr == kDIErrNone) { + AddSubVolumeToList(pNewImg, pNewFS); + } else { + WMSG1(" MacPart unable to create placeholder (err=%d)\n", + dierr); + break; // something's wrong -- bail out with error + } + } + } bail: - return dierr; + return dierr; } diff --git a/diskimg/MicroDrive.cpp b/diskimg/MicroDrive.cpp index d3e3f8f..d502344 100644 --- a/diskimg/MicroDrive.cpp +++ b/diskimg/MicroDrive.cpp @@ -14,7 +14,7 @@ const int kBlkSize = 512; -const int kPartMapBlock = 0; // partition map lives here +const int kPartMapBlock = 0; // partition map lives here const unsigned int kPartSizeMask = 0x00ffffff; @@ -24,45 +24,45 @@ const unsigned int kPartSizeMask = 0x00ffffff; * * The layout was discovered through reverse-engineering. Additional notes: * - From Joachim Lange: + From Joachim Lange: - Below, this is the configuration block as it is used in all - MicroDrive cards. Please verify that my ID shortcut can be - found at offset 0, otherwise the partition info is not - valid. Most of the other parms are not useful, some are - historic and not useful anymore. As a second security - measure, verify that the first partition starts at - absolute block 256. This is also a fixed value used in all - MicroDrive cards. Of course the partition size is not two - bytes long but three (not four), the 4th byte is used for - switching drives in a two-drive configuration. So, for - completeness, when reading partition sizes, perform a - partitionLength[..] & 0x00FFFFFF, or at least issue a - warning that something may be wrong. The offset - (partitionStart) could reach into the 4th byte. - I have attached the config block in a zip file because - the mailer would probably re-format the source text. + Below, this is the configuration block as it is used in all + MicroDrive cards. Please verify that my ID shortcut can be + found at offset 0, otherwise the partition info is not + valid. Most of the other parms are not useful, some are + historic and not useful anymore. As a second security + measure, verify that the first partition starts at + absolute block 256. This is also a fixed value used in all + MicroDrive cards. Of course the partition size is not two + bytes long but three (not four), the 4th byte is used for + switching drives in a two-drive configuration. So, for + completeness, when reading partition sizes, perform a + partitionLength[..] & 0x00FFFFFF, or at least issue a + warning that something may be wrong. The offset + (partitionStart) could reach into the 4th byte. + I have attached the config block in a zip file because + the mailer would probably re-format the source text. */ const int kMaxNumParts = 8; typedef struct DiskFSMicroDrive::PartitionMap { - unsigned short magic; // partition signature - unsigned short cylinders; // #of cylinders - unsigned short reserved1; // ?? - unsigned short heads; // #of heads/cylinder - unsigned short sectors; // #of sectors/track - unsigned short reserved2; // ?? - unsigned char numPart1; // #of partitions in first chunk - unsigned char numPart2; // #of partitions in second chunk - unsigned char reserved3[10]; // bytes 0x0e-0x17 - unsigned short romVersion; // IIgs ROM01 or ROM03 - unsigned char reserved4[6]; // bytes 0x1a-0x1f - unsigned long partitionStart1[kMaxNumParts]; // bytes 0x20-0x3f - unsigned long partitionLength1[kMaxNumParts]; // bytes 0x40-0x5f - unsigned char reserved5[32]; // bytes 0x60-0x7f - unsigned long partitionStart2[kMaxNumParts]; // bytes 0x80-0x9f - unsigned long partitionLength2[kMaxNumParts]; // bytes 0xa0-0xbf + unsigned short magic; // partition signature + unsigned short cylinders; // #of cylinders + unsigned short reserved1; // ?? + unsigned short heads; // #of heads/cylinder + unsigned short sectors; // #of sectors/track + unsigned short reserved2; // ?? + unsigned char numPart1; // #of partitions in first chunk + unsigned char numPart2; // #of partitions in second chunk + unsigned char reserved3[10]; // bytes 0x0e-0x17 + unsigned short romVersion; // IIgs ROM01 or ROM03 + unsigned char reserved4[6]; // bytes 0x1a-0x1f + unsigned long partitionStart1[kMaxNumParts]; // bytes 0x20-0x3f + unsigned long partitionLength1[kMaxNumParts]; // bytes 0x40-0x5f + unsigned char reserved5[32]; // bytes 0x60-0x7f + unsigned long partitionStart2[kMaxNumParts]; // bytes 0x80-0x9f + unsigned long partitionLength2[kMaxNumParts]; // bytes 0xa0-0xbf - unsigned char padding[320]; + unsigned char padding[320]; } PartitionMap; @@ -75,44 +75,44 @@ typedef struct DiskFSMicroDrive::PartitionMap { /*static*/ DIError DiskFSMicroDrive::TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder) { - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; - int partCount1, partCount2; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; + int partCount1, partCount2; - assert(sizeof(PartitionMap) == kBlkSize); + assert(sizeof(PartitionMap) == kBlkSize); - /* - * See if block 0 is a MicroDrive partition map. - */ - dierr = pImg->ReadBlockSwapped(kPartMapBlock, blkBuf, imageOrder, - DiskImg::kSectorOrderProDOS); - if (dierr != kDIErrNone) - goto bail; + /* + * See if block 0 is a MicroDrive partition map. + */ + dierr = pImg->ReadBlockSwapped(kPartMapBlock, blkBuf, imageOrder, + DiskImg::kSectorOrderProDOS); + if (dierr != kDIErrNone) + goto bail; - if (GetShortLE(&blkBuf[0x00]) != kPartitionSignature) { - WMSG0(" MicroDrive partition signature not found in first part block\n"); - dierr = kDIErrFilesystemNotFound; - goto bail; - } - /* might assert that partCount2 be zero unless partCount1 == 8? */ - partCount1 = blkBuf[0x0c]; - partCount2 = blkBuf[0x0d]; - if (partCount1 == 0 || partCount1 > kMaxNumParts || - partCount2 > kMaxNumParts) - { - WMSG2(" MicroDrive unreasonable partCount values %d/%d\n", - partCount1, partCount2); - dierr = kDIErrFilesystemNotFound; - goto bail; - } + if (GetShortLE(&blkBuf[0x00]) != kPartitionSignature) { + WMSG0(" MicroDrive partition signature not found in first part block\n"); + dierr = kDIErrFilesystemNotFound; + goto bail; + } + /* might assert that partCount2 be zero unless partCount1 == 8? */ + partCount1 = blkBuf[0x0c]; + partCount2 = blkBuf[0x0d]; + if (partCount1 == 0 || partCount1 > kMaxNumParts || + partCount2 > kMaxNumParts) + { + WMSG2(" MicroDrive unreasonable partCount values %d/%d\n", + partCount1, partCount2); + dierr = kDIErrFilesystemNotFound; + goto bail; + } - /* consider testing other fields */ + /* consider testing other fields */ - // success! - WMSG2(" MicroDrive partition map count = %d/%d\n", partCount1, partCount2); + // success! + WMSG2(" MicroDrive partition map count = %d/%d\n", partCount1, partCount2); bail: - return dierr; + return dierr; } @@ -121,28 +121,28 @@ bail: */ /*static*/ void DiskFSMicroDrive::UnpackPartitionMap(const unsigned char* buf, - PartitionMap* pMap) + PartitionMap* pMap) { - pMap->magic = GetShortLE(&buf[0x00]); - pMap->cylinders = GetShortLE(&buf[0x02]); - pMap->reserved1 = GetShortLE(&buf[0x04]); - pMap->heads = GetShortLE(&buf[0x06]); - pMap->sectors = GetShortLE(&buf[0x08]); - pMap->reserved2 = GetShortLE(&buf[0x0a]); - pMap->numPart1 = buf[0x0c]; - pMap->numPart2 = buf[0x0d]; - memcpy(pMap->reserved3, &buf[0x0e], sizeof(pMap->reserved3)); - pMap->romVersion = GetShortLE(&buf[0x18]); - memcpy(pMap->reserved4, &buf[0x1a], sizeof(pMap->reserved4)); + pMap->magic = GetShortLE(&buf[0x00]); + pMap->cylinders = GetShortLE(&buf[0x02]); + pMap->reserved1 = GetShortLE(&buf[0x04]); + pMap->heads = GetShortLE(&buf[0x06]); + pMap->sectors = GetShortLE(&buf[0x08]); + pMap->reserved2 = GetShortLE(&buf[0x0a]); + pMap->numPart1 = buf[0x0c]; + pMap->numPart2 = buf[0x0d]; + memcpy(pMap->reserved3, &buf[0x0e], sizeof(pMap->reserved3)); + pMap->romVersion = GetShortLE(&buf[0x18]); + memcpy(pMap->reserved4, &buf[0x1a], sizeof(pMap->reserved4)); - for (int i = 0; i < kMaxNumParts; i++) { - pMap->partitionStart1[i] = GetLongLE(&buf[0x20] + i * 4); - pMap->partitionLength1[i] = GetLongLE(&buf[0x40] + i * 4) & kPartSizeMask; - pMap->partitionStart2[i] = GetLongLE(&buf[0x80] + i * 4); - pMap->partitionLength2[i] = GetLongLE(&buf[0xa0] + i * 4) & kPartSizeMask; - } - memcpy(pMap->reserved5, &buf[0x60], sizeof(pMap->reserved5)); - memcpy(pMap->padding, &buf[0x80], sizeof(pMap->padding)); + for (int i = 0; i < kMaxNumParts; i++) { + pMap->partitionStart1[i] = GetLongLE(&buf[0x20] + i * 4); + pMap->partitionLength1[i] = GetLongLE(&buf[0x40] + i * 4) & kPartSizeMask; + pMap->partitionStart2[i] = GetLongLE(&buf[0x80] + i * 4); + pMap->partitionLength2[i] = GetLongLE(&buf[0xa0] + i * 4) & kPartSizeMask; + } + memcpy(pMap->reserved5, &buf[0x60], sizeof(pMap->reserved5)); + memcpy(pMap->padding, &buf[0x80], sizeof(pMap->padding)); } /* @@ -151,27 +151,27 @@ DiskFSMicroDrive::UnpackPartitionMap(const unsigned char* buf, /*static*/ void DiskFSMicroDrive::DumpPartitionMap(const PartitionMap* pMap) { - WMSG0(" MicroDrive partition map:\n"); - WMSG4(" cyls=%d res1=%d heads=%d sects=%d\n", - pMap->cylinders, pMap->reserved1, pMap->heads, pMap->sectors); - WMSG3(" res2=%d numPart1=%d numPart2=%d\n", - pMap->reserved2, pMap->numPart1, pMap->numPart2); - WMSG1(" romVersion=ROM%02d\n", pMap->romVersion); + WMSG0(" MicroDrive partition map:\n"); + WMSG4(" cyls=%d res1=%d heads=%d sects=%d\n", + pMap->cylinders, pMap->reserved1, pMap->heads, pMap->sectors); + WMSG3(" res2=%d numPart1=%d numPart2=%d\n", + pMap->reserved2, pMap->numPart1, pMap->numPart2); + WMSG1(" romVersion=ROM%02d\n", pMap->romVersion); - int i, parts; + int i, parts; - parts = pMap->numPart1; - assert(parts <= kMaxNumParts); - for (i = 0; i < parts; i++) { - WMSG3(" %2d: startLBA=%8ld length=%ld\n", - i, pMap->partitionStart1[i], pMap->partitionLength1[i]); - } - parts = pMap->numPart2; - assert(parts <= kMaxNumParts); - for (i = 0; i < parts; i++) { - WMSG3(" %2d: startLBA=%8ld length=%ld\n", - i+8, pMap->partitionStart2[i], pMap->partitionLength2[i]); - } + parts = pMap->numPart1; + assert(parts <= kMaxNumParts); + for (i = 0; i < parts; i++) { + WMSG3(" %2d: startLBA=%8ld length=%ld\n", + i, pMap->partitionStart1[i], pMap->partitionLength1[i]); + } + parts = pMap->numPart2; + assert(parts <= kMaxNumParts); + for (i = 0; i < parts; i++) { + WMSG3(" %2d: startLBA=%8ld length=%ld\n", + i+8, pMap->partitionStart2[i], pMap->partitionLength2[i]); + } } @@ -181,109 +181,109 @@ DiskFSMicroDrive::DumpPartitionMap(const PartitionMap* pMap) DIError DiskFSMicroDrive::OpenSubVolume(long startBlock, long numBlocks) { - DIError dierr = kDIErrNone; - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; - //bool tweaked = false; + DIError dierr = kDIErrNone; + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; + //bool tweaked = false; - WMSG2("Adding %ld +%ld\n", startBlock, numBlocks); + WMSG2("Adding %ld +%ld\n", startBlock, numBlocks); - if (startBlock > fpImg->GetNumBlocks()) { - WMSG2("MicroDrive start block out of range (%ld vs %ld)\n", - startBlock, fpImg->GetNumBlocks()); - return kDIErrBadPartition; - } - if (startBlock + numBlocks > fpImg->GetNumBlocks()) { - WMSG2("MicroDrive partition too large (%ld vs %ld avail)\n", - numBlocks, fpImg->GetNumBlocks() - startBlock); - fpImg->AddNote(DiskImg::kNoteInfo, - "Reduced partition from %ld blocks to %ld.\n", - numBlocks, fpImg->GetNumBlocks() - startBlock); - numBlocks = fpImg->GetNumBlocks() - startBlock; - //tweaked = true; - } + if (startBlock > fpImg->GetNumBlocks()) { + WMSG2("MicroDrive start block out of range (%ld vs %ld)\n", + startBlock, fpImg->GetNumBlocks()); + return kDIErrBadPartition; + } + if (startBlock + numBlocks > fpImg->GetNumBlocks()) { + WMSG2("MicroDrive partition too large (%ld vs %ld avail)\n", + numBlocks, fpImg->GetNumBlocks() - startBlock); + fpImg->AddNote(DiskImg::kNoteInfo, + "Reduced partition from %ld blocks to %ld.\n", + numBlocks, fpImg->GetNumBlocks() - startBlock); + numBlocks = fpImg->GetNumBlocks() - startBlock; + //tweaked = true; + } - pNewImg = new DiskImg; - if (pNewImg == nil) { - dierr = kDIErrMalloc; - goto bail; - } + pNewImg = new DiskImg; + if (pNewImg == nil) { + dierr = kDIErrMalloc; + goto bail; + } - dierr = pNewImg->OpenImage(fpImg, startBlock, numBlocks); - if (dierr != kDIErrNone) { - WMSG3(" MicroDriveSub: OpenImage(%ld,%ld) failed (err=%d)\n", - startBlock, numBlocks, dierr); - goto bail; - } + dierr = pNewImg->OpenImage(fpImg, startBlock, numBlocks); + if (dierr != kDIErrNone) { + WMSG3(" MicroDriveSub: OpenImage(%ld,%ld) failed (err=%d)\n", + startBlock, numBlocks, dierr); + goto bail; + } - //WMSG2(" +++ CFFASub: new image has ro=%d (parent=%d)\n", - // pNewImg->GetReadOnly(), pImg->GetReadOnly()); + //WMSG2(" +++ CFFASub: new image has ro=%d (parent=%d)\n", + // pNewImg->GetReadOnly(), pImg->GetReadOnly()); - /* figure out what the format is */ - dierr = pNewImg->AnalyzeImage(); - if (dierr != kDIErrNone) { - WMSG1(" MicroDriveSub: analysis failed (err=%d)\n", dierr); - goto bail; - } + /* figure out what the format is */ + dierr = pNewImg->AnalyzeImage(); + if (dierr != kDIErrNone) { + WMSG1(" MicroDriveSub: analysis failed (err=%d)\n", dierr); + goto bail; + } - /* we allow unrecognized partitions */ - if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || - pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) - { - WMSG2(" MicroDriveSub (%ld,%ld): unable to identify filesystem\n", - startBlock, numBlocks); - DiskFSUnknown* pUnknownFS = new DiskFSUnknown; - if (pUnknownFS == nil) { - dierr = kDIErrInternal; - goto bail; - } - //pUnknownFS->SetVolumeInfo((const char*)pMap->pmParType); - pNewFS = pUnknownFS; - //pNewImg->AddNote(DiskImg::kNoteInfo, "Partition name='%s' type='%s'.", - // pMap->pmPartName, pMap->pmParType); - } else { - /* open a DiskFS for the sub-image */ - WMSG2(" MicroDriveSub (%ld,%ld) analyze succeeded!\n", startBlock, numBlocks); - pNewFS = pNewImg->OpenAppropriateDiskFS(true); - if (pNewFS == nil) { - WMSG0(" MicroDriveSub: OpenAppropriateDiskFS failed\n"); - dierr = kDIErrUnsupportedFSFmt; - goto bail; - } - } + /* we allow unrecognized partitions */ + if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || + pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) + { + WMSG2(" MicroDriveSub (%ld,%ld): unable to identify filesystem\n", + startBlock, numBlocks); + DiskFSUnknown* pUnknownFS = new DiskFSUnknown; + if (pUnknownFS == nil) { + dierr = kDIErrInternal; + goto bail; + } + //pUnknownFS->SetVolumeInfo((const char*)pMap->pmParType); + pNewFS = pUnknownFS; + //pNewImg->AddNote(DiskImg::kNoteInfo, "Partition name='%s' type='%s'.", + // pMap->pmPartName, pMap->pmParType); + } else { + /* open a DiskFS for the sub-image */ + WMSG2(" MicroDriveSub (%ld,%ld) analyze succeeded!\n", startBlock, numBlocks); + pNewFS = pNewImg->OpenAppropriateDiskFS(true); + if (pNewFS == nil) { + WMSG0(" MicroDriveSub: OpenAppropriateDiskFS failed\n"); + dierr = kDIErrUnsupportedFSFmt; + goto bail; + } + } - /* we encapsulate arbitrary stuff, so encourage child to scan */ - pNewFS->SetScanForSubVolumes(kScanSubEnabled); + /* we encapsulate arbitrary stuff, so encourage child to scan */ + pNewFS->SetScanForSubVolumes(kScanSubEnabled); - /* - * Load the files from the sub-image. When doing our initial tests, - * or when loading data for the volume copier, we don't want to dig - * into our sub-volumes, just figure out what they are and where. - * - * If "initialize" fails, the sub-volume won't get added to the list. - * It's important that a failure at this stage doesn't cause the whole - * thing to fall over. - */ - InitMode initMode; - if (GetScanForSubVolumes() == kScanSubContainerOnly) - initMode = kInitHeaderOnly; - else - initMode = kInitFull; - dierr = pNewFS->Initialize(pNewImg, initMode); - if (dierr != kDIErrNone) { - WMSG1(" MicroDriveSub: error %d reading list of files from disk", dierr); - goto bail; - } + /* + * Load the files from the sub-image. When doing our initial tests, + * or when loading data for the volume copier, we don't want to dig + * into our sub-volumes, just figure out what they are and where. + * + * If "initialize" fails, the sub-volume won't get added to the list. + * It's important that a failure at this stage doesn't cause the whole + * thing to fall over. + */ + InitMode initMode; + if (GetScanForSubVolumes() == kScanSubContainerOnly) + initMode = kInitHeaderOnly; + else + initMode = kInitFull; + dierr = pNewFS->Initialize(pNewImg, initMode); + if (dierr != kDIErrNone) { + WMSG1(" MicroDriveSub: error %d reading list of files from disk", dierr); + goto bail; + } - /* add it to the list */ - AddSubVolumeToList(pNewImg, pNewFS); - pNewImg = nil; - pNewFS = nil; + /* add it to the list */ + AddSubVolumeToList(pNewImg, pNewFS); + pNewImg = nil; + pNewFS = nil; bail: - delete pNewFS; - delete pNewImg; - return dierr; + delete pNewFS; + delete pNewImg; + return dierr; } /* @@ -291,22 +291,22 @@ bail: */ /*static*/ DIError DiskFSMicroDrive::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency) + DiskImg::FSFormat* pFormat, FSLeniency leniency) { - if (pImg->GetNumBlocks() < kMinInterestingBlocks) - return kDIErrFilesystemNotFound; - if (pImg->GetIsEmbedded()) // don't look for partitions inside - return kDIErrFilesystemNotFound; + if (pImg->GetNumBlocks() < kMinInterestingBlocks) + return kDIErrFilesystemNotFound; + if (pImg->GetIsEmbedded()) // don't look for partitions inside + return kDIErrFilesystemNotFound; - /* assume ProDOS -- shouldn't matter, since it's embedded */ - if (TestImage(pImg, DiskImg::kSectorOrderProDOS) == kDIErrNone) { - *pFormat = DiskImg::kFormatMicroDrive; - *pOrder = DiskImg::kSectorOrderProDOS; - return kDIErrNone; - } + /* assume ProDOS -- shouldn't matter, since it's embedded */ + if (TestImage(pImg, DiskImg::kSectorOrderProDOS) == kDIErrNone) { + *pFormat = DiskImg::kFormatMicroDrive; + *pOrder = DiskImg::kSectorOrderProDOS; + return kDIErrNone; + } - WMSG0(" FS didn't find valid MicroDrive\n"); - return kDIErrFilesystemNotFound; + WMSG0(" FS didn't find valid MicroDrive\n"); + return kDIErrFilesystemNotFound; } @@ -316,21 +316,21 @@ DiskFSMicroDrive::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DIError DiskFSMicroDrive::Initialize(void) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - WMSG1("MicroDrive initializing (scanForSub=%d)\n", fScanForSubVolumes); + WMSG1("MicroDrive initializing (scanForSub=%d)\n", fScanForSubVolumes); - /* seems pointless *not* to, but we just do what we're told */ - if (fScanForSubVolumes != kScanSubDisabled) { - dierr = FindSubVolumes(); - if (dierr != kDIErrNone) - return dierr; - } + /* seems pointless *not* to, but we just do what we're told */ + if (fScanForSubVolumes != kScanSubDisabled) { + dierr = FindSubVolumes(); + if (dierr != kDIErrNone) + return dierr; + } - /* blank out the volume usage map */ - SetVolumeUsageMap(); + /* blank out the volume usage map */ + SetVolumeUsageMap(); - return dierr; + return dierr; } @@ -340,35 +340,35 @@ DiskFSMicroDrive::Initialize(void) DIError DiskFSMicroDrive::FindSubVolumes(void) { - DIError dierr = kDIErrNone; - unsigned char buf[kBlkSize]; - PartitionMap map; - int i; + DIError dierr = kDIErrNone; + unsigned char buf[kBlkSize]; + PartitionMap map; + int i; - dierr = fpImg->ReadBlock(kPartMapBlock, buf); - if (dierr != kDIErrNone) - goto bail; - UnpackPartitionMap(buf, &map); - DumpPartitionMap(&map); + dierr = fpImg->ReadBlock(kPartMapBlock, buf); + if (dierr != kDIErrNone) + goto bail; + UnpackPartitionMap(buf, &map); + DumpPartitionMap(&map); - /* first part of the table */ - for (i = 0; i < map.numPart1; i++) { - dierr = OpenVol(i, - map.partitionStart1[i], map.partitionLength1[i]); - if (dierr != kDIErrNone) - goto bail; - } + /* first part of the table */ + for (i = 0; i < map.numPart1; i++) { + dierr = OpenVol(i, + map.partitionStart1[i], map.partitionLength1[i]); + if (dierr != kDIErrNone) + goto bail; + } - /* second part of the table */ - for (i = 0; i < map.numPart2; i++) { - dierr = OpenVol(i + kMaxNumParts, - map.partitionStart2[i], map.partitionLength2[i]); - if (dierr != kDIErrNone) - goto bail; - } + /* second part of the table */ + for (i = 0; i < map.numPart2; i++) { + dierr = OpenVol(i + kMaxNumParts, + map.partitionStart2[i], map.partitionLength2[i]); + if (dierr != kDIErrNone) + goto bail; + } bail: - return dierr; + return dierr; } /* @@ -378,27 +378,27 @@ bail: DIError DiskFSMicroDrive::OpenVol(int idx, long startBlock, long numBlocks) { - DIError dierr; + DIError dierr; - dierr = OpenSubVolume(startBlock, numBlocks); - if (dierr != kDIErrNone) { - if (dierr == kDIErrCancelled) - goto bail; - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; + dierr = OpenSubVolume(startBlock, numBlocks); + if (dierr != kDIErrNone) { + if (dierr == kDIErrCancelled) + goto bail; + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; - WMSG1(" MicroDrive failed opening sub-volume %d\n", idx); - dierr = CreatePlaceholder(startBlock, numBlocks, NULL, NULL, - &pNewImg, &pNewFS); - if (dierr == kDIErrNone) { - AddSubVolumeToList(pNewImg, pNewFS); - } else { - WMSG1(" MicroDrive unable to create placeholder (err=%d)\n", - dierr); - // fall out with error - } - } + WMSG1(" MicroDrive failed opening sub-volume %d\n", idx); + dierr = CreatePlaceholder(startBlock, numBlocks, NULL, NULL, + &pNewImg, &pNewFS); + if (dierr == kDIErrNone) { + AddSubVolumeToList(pNewImg, pNewFS); + } else { + WMSG1(" MicroDrive unable to create placeholder (err=%d)\n", + dierr); + // fall out with error + } + } bail: - return dierr; + return dierr; } diff --git a/diskimg/Nibble.cpp b/diskimg/Nibble.cpp index 9f28235..651dbf2 100644 --- a/diskimg/Nibble.cpp +++ b/diskimg/Nibble.cpp @@ -36,7 +36,7 @@ 0xf7, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff }; /*static*/ unsigned char DiskImg::kInvDiskBytes53[256]; // all values are 0-31 -/*static*/ unsigned char DiskImg::kInvDiskBytes62[256]; // all values are 0-63 +/*static*/ unsigned char DiskImg::kInvDiskBytes62[256]; // all values are 0-63 /* * Compute tables to convert disk bytes back to values. @@ -79,25 +79,25 @@ DiskImg::FindNibbleSectorStart(const CircularBufferAccess& buffer, int track, int i; for (i = 0; i < trackLen; i++) { - bool foundAddr = false; + bool foundAddr = false; - if (pNibbleDescr->special == kNibbleSpecialSkipFirstAddrByte) { - if (/*buffer[i] == pNibbleDescr->addrProlog[0] &&*/ - buffer[i+1] == pNibbleDescr->addrProlog[1] && - buffer[i+2] == pNibbleDescr->addrProlog[2]) - { - foundAddr = true; - } - } else { - if (buffer[i] == pNibbleDescr->addrProlog[0] && - buffer[i+1] == pNibbleDescr->addrProlog[1] && - buffer[i+2] == pNibbleDescr->addrProlog[2]) - { - foundAddr = true; - } - } + if (pNibbleDescr->special == kNibbleSpecialSkipFirstAddrByte) { + if (/*buffer[i] == pNibbleDescr->addrProlog[0] &&*/ + buffer[i+1] == pNibbleDescr->addrProlog[1] && + buffer[i+2] == pNibbleDescr->addrProlog[2]) + { + foundAddr = true; + } + } else { + if (buffer[i] == pNibbleDescr->addrProlog[0] && + buffer[i+1] == pNibbleDescr->addrProlog[1] && + buffer[i+2] == pNibbleDescr->addrProlog[2]) + { + foundAddr = true; + } + } - if (foundAddr) { + if (foundAddr) { //i += 3; /* found the address header, decode the address */ @@ -122,7 +122,7 @@ DiskImg::FindNibbleSectorStart(const CircularBufferAccess& buffer, int track, } } - i += 3; + i += 3; int j; for (j = 0; j < pNibbleDescr->addrEpilogVerifyCount; j++) { @@ -564,13 +564,13 @@ DIError DiskImg::LoadNibbleTrack(long track, long* pTrackLen) { DIError dierr = kDIErrNone; - long offset; + long offset; assert(track >= 0 && track < kMaxNibbleTracks525); *pTrackLen = GetNibbleTrackLength(track); - offset = GetNibbleTrackOffset(track); - assert(*pTrackLen > 0); - assert(offset >= 0); + offset = GetNibbleTrackOffset(track); + assert(*pTrackLen > 0); + assert(offset >= 0); if (track == fNibbleTrackLoaded) { #ifdef NIB_VERBOSE_DEBUG @@ -600,7 +600,7 @@ DiskImg::LoadNibbleTrack(long track, long* pTrackLen) fNibbleTrackLoaded = track; - return dierr; + return dierr; } /* @@ -621,7 +621,7 @@ DiskImg::SaveNibbleTrack(void) /* write the track to fpDataGFD */ dierr = CopyBytesIn(fNibbleTrackBuf, offset, trackLen); - return dierr; + return dierr; } @@ -676,21 +676,21 @@ DiskImg::TestNibbleTrack(int track, const NibbleDescr* pNibbleDescr, * On exit: * fpNibbleDescr points to the most-likely-to-succeed NibbleDescr * fDOSVolumeNum holds a volume number from one of the tracks - * fNumTracks holds the number of tracks on the disk + * fNumTracks holds the number of tracks on the disk */ DIError DiskImg::AnalyzeNibbleData(void) { assert(IsNibbleFormat(fPhysical)); - if (fPhysical == kPhysicalFormatNib525_Var) { - /* TrackStar can have up to 40 */ - fNumTracks = fpImageWrapper->GetNibbleNumTracks(); - assert(fNumTracks > 0); - } else { - /* fixed-length formats (.nib, .nb2) are always 35 tracks */ - fNumTracks = kTrackCount525; - } + if (fPhysical == kPhysicalFormatNib525_Var) { + /* TrackStar can have up to 40 */ + fNumTracks = fpImageWrapper->GetNibbleNumTracks(); + assert(fNumTracks > 0); + } else { + /* fixed-length formats (.nib, .nb2) are always 35 tracks */ + fNumTracks = kTrackCount525; + } /* * Try to read sectors from tracks 1, 16, 17, and 26. If we can get @@ -701,11 +701,11 @@ DiskImg::AnalyzeNibbleData(void) int protoVol = kVolumeNumNotSet; for (i = 0; i < fNumNibbleDescrEntries; i++) { - if (fpNibbleDescrTable[i].numSectors == 0) { - /* uninitialized "custom" entry */ - WMSG1(" Skipping '%s'\n", fpNibbleDescrTable[i].description); - continue; - } + if (fpNibbleDescrTable[i].numSectors == 0) { + /* uninitialized "custom" entry */ + WMSG1(" Skipping '%s'\n", fpNibbleDescrTable[i].description); + continue; + } WMSG1(" Trying '%s'\n", fpNibbleDescrTable[i].description); goodTracks = 0; @@ -750,16 +750,16 @@ DIError DiskImg::ReadNibbleSector(long track, int sector, void* buf, const NibbleDescr* pNibbleDescr) { - if (pNibbleDescr == nil) { - /* disk has no recognizable sectors */ - WMSG0(" DI ReadNibbleSector: pNibbleDescr is nil, returning failure\n"); - return kDIErrBadNibbleSectors; - } - if (sector >= pNibbleDescr->numSectors) { - /* e.g. trying to read sector 14 on a 13-sector disk */ - WMSG0(" DI ReadNibbleSector: bad sector number request\n"); - return kDIErrInvalidSector; - } + if (pNibbleDescr == nil) { + /* disk has no recognizable sectors */ + WMSG0(" DI ReadNibbleSector: pNibbleDescr is nil, returning failure\n"); + return kDIErrBadNibbleSectors; + } + if (sector >= pNibbleDescr->numSectors) { + /* e.g. trying to read sector 14 on a 13-sector disk */ + WMSG0(" DI ReadNibbleSector: bad sector number request\n"); + return kDIErrInvalidSector; + } assert(pNibbleDescr != nil); assert(IsNibbleFormat(fPhysical)); @@ -837,7 +837,7 @@ DiskImg::WriteNibbleSector(long track, int sector, const void* buf, DIError DiskImg::ReadNibbleTrack(long track, unsigned char* buf, long* pTrackLen) { - DIError dierr; + DIError dierr; dierr = LoadNibbleTrack(track, pTrackLen); if (dierr != kDIErrNone) { @@ -845,8 +845,8 @@ DiskImg::ReadNibbleTrack(long track, unsigned char* buf, long* pTrackLen) return dierr; } - memcpy(buf, fNibbleTrackBuf, *pTrackLen); - return kDIErrNone; + memcpy(buf, fNibbleTrackBuf, *pTrackLen); + return kDIErrNone; } /* @@ -859,26 +859,26 @@ DiskImg::ReadNibbleTrack(long track, unsigned char* buf, long* pTrackLen) DIError DiskImg::WriteNibbleTrack(long track, const unsigned char* buf, long trackLen) { - DIError dierr; - long oldTrackLen; + DIError dierr; + long oldTrackLen; - /* load the track to set the "current track" stuff */ + /* load the track to set the "current track" stuff */ dierr = LoadNibbleTrack(track, &oldTrackLen); if (dierr != kDIErrNone) { WMSG1(" DI WriteNibbleTrack: LoadNibbleTrack %ld failed\n", track); return dierr; } - if (trackLen > GetNibbleTrackAllocLength()) { - WMSG2("ERROR: tried to write too-long track len (%ld vs %d)\n", - trackLen, GetNibbleTrackAllocLength()); - return kDIErrInvalidArg; - } + if (trackLen > GetNibbleTrackAllocLength()) { + WMSG2("ERROR: tried to write too-long track len (%ld vs %d)\n", + trackLen, GetNibbleTrackAllocLength()); + return kDIErrInvalidArg; + } - if (trackLen < oldTrackLen) // pad out any extra space - memset(fNibbleTrackBuf, 0xff, oldTrackLen); - memcpy(fNibbleTrackBuf, buf, trackLen); - fpImageWrapper->SetNibbleTrackLength(track, trackLen); + if (trackLen < oldTrackLen) // pad out any extra space + memset(fNibbleTrackBuf, 0xff, oldTrackLen); + memcpy(fNibbleTrackBuf, buf, trackLen); + fpImageWrapper->SetNibbleTrackLength(track, trackLen); dierr = SaveNibbleTrack(); if (dierr != kDIErrNone) { @@ -886,7 +886,7 @@ DiskImg::WriteNibbleTrack(long track, const unsigned char* buf, long trackLen) return dierr; } - return kDIErrNone; + return kDIErrNone; } @@ -917,30 +917,30 @@ DiskImg::FormatNibbles(GenericFD* pGFD) const DIError dierr = kDIErrNone; unsigned char trackBuf[kTrackAllocSize]; - /* these should be the same except for var-len images */ - long trackAllocLen = GetNibbleTrackAllocLength(); + /* these should be the same except for var-len images */ + long trackAllocLen = GetNibbleTrackAllocLength(); long trackLen = GetNibbleTrackFormatLength(); int track; assert(trackLen > 0); pGFD->Rewind(); - /* - * If we don't have sector access, take a shortcut and just fill the - * entire image with 0xff. - */ - if (!fHasSectors) { - memset(trackBuf, 0xff, trackLen); - for (track = 0; track < GetNumTracks(); track++) { - /* write the track to the GFD */ - dierr = pGFD->Write(trackBuf, trackAllocLen); - if (dierr != kDIErrNone) - return dierr; - fpImageWrapper->SetNibbleTrackLength(track, trackAllocLen); - } + /* + * If we don't have sector access, take a shortcut and just fill the + * entire image with 0xff. + */ + if (!fHasSectors) { + memset(trackBuf, 0xff, trackLen); + for (track = 0; track < GetNumTracks(); track++) { + /* write the track to the GFD */ + dierr = pGFD->Write(trackBuf, trackAllocLen); + if (dierr != kDIErrNone) + return dierr; + fpImageWrapper->SetNibbleTrackLength(track, trackAllocLen); + } - return kDIErrNone; - } + return kDIErrNone; + } assert(fHasSectors); @@ -1037,8 +1037,8 @@ DiskImg::FormatNibbles(GenericFD* pGFD) const if (dierr != kDIErrNone) break; - /* on a variable-length image, reduce track len to match */ - fpImageWrapper->SetNibbleTrackLength(track, trackLen); + /* on a variable-length image, reduce track len to match */ + fpImageWrapper->SetNibbleTrackLength(track, trackLen); } return dierr; diff --git a/diskimg/Nibble35.cpp b/diskimg/Nibble35.cpp index b1a1283..fcb58a2 100644 --- a/diskimg/Nibble35.cpp +++ b/diskimg/Nibble35.cpp @@ -47,26 +47,26 @@ Some sources say it starts with 42 10-bit self-sync bytes instead of 36. const int kCylindersPerDisk = 80; const int kHeadsPerCylinder = 2; const int kMaxSectorsPerTrack = 12; -const int kSectorSize35 = 524; // 512 data bytes + 12 tag bytes +const int kSectorSize35 = 524; // 512 data bytes + 12 tag bytes const int kTagBytesLen = 12; const int kDataChecksumLen = 3; -const int kChunkSize35 = 175; // ceil(524 / 3) +const int kChunkSize35 = 175; // ceil(524 / 3) const int kOffsetToChecksum = 699; const int kNibblizedOutputLen = (kOffsetToChecksum + 4); -const int kMaxDataReach = 48; // should only be 6 bytes */ +const int kMaxDataReach = 48; // should only be 6 bytes */ enum { - kAddrProlog0 = 0xd5, - kAddrProlog1 = 0xaa, - kAddrProlog2 = 0x96, - kAddrEpilog0 = 0xde, - kAddrEpilog1 = 0xaa, + kAddrProlog0 = 0xd5, + kAddrProlog1 = 0xaa, + kAddrProlog2 = 0x96, + kAddrEpilog0 = 0xde, + kAddrEpilog1 = 0xaa, - kDataProlog0 = 0xd5, - kDataProlog1 = 0xaa, - kDataProlog2 = 0xad, - kDataEpilog0 = 0xde, - kDataEpilog1 = 0xaa, + kDataProlog0 = 0xd5, + kDataProlog1 = 0xaa, + kDataProlog2 = 0xad, + kDataEpilog0 = 0xde, + kDataEpilog1 = 0xaa, }; /* @@ -76,7 +76,7 @@ enum { /*static*/ int DiskImg::SectorsPerTrack35(int cylinder) { - return kMaxSectorsPerTrack - (cylinder / 16); + return kMaxSectorsPerTrack - (cylinder / 16); } /* @@ -85,22 +85,22 @@ DiskImg::SectorsPerTrack35(int cylinder) /*static*/ int DiskImg::CylHeadSect35ToBlock(int cyl, int head, int sect) { - int i, block; + int i, block; - assert(cyl >= 0 && cyl < kCylindersPerDisk); - assert(head >= 0 && head < kHeadsPerCylinder); - assert(sect >= 0 && sect < SectorsPerTrack35(cyl)); + assert(cyl >= 0 && cyl < kCylindersPerDisk); + assert(head >= 0 && head < kHeadsPerCylinder); + assert(sect >= 0 && sect < SectorsPerTrack35(cyl)); - block = 0; - for (i = 0; i < cyl; i++) - block += SectorsPerTrack35(i) * kHeadsPerCylinder; - if (head) - block += SectorsPerTrack35(i); - block += sect; + block = 0; + for (i = 0; i < cyl; i++) + block += SectorsPerTrack35(i) * kHeadsPerCylinder; + if (head) + block += SectorsPerTrack35(i); + block += sect; - //WMSG4("Nib35: c/h/s %d/%d/%d --> block %d\n", cyl, head, sect, block); - assert(block >= 0 && block < 1600); - return block; + //WMSG4("Nib35: c/h/s %d/%d/%d --> block %d\n", cyl, head, sect, block); + assert(block >= 0 && block < 1600); + return block; } /* @@ -110,80 +110,80 @@ DiskImg::CylHeadSect35ToBlock(int cyl, int head, int sect) */ /*static*/ DIError DiskImg::UnpackNibbleTrack35(const unsigned char* nibbleBuf, - long nibbleLen, unsigned char* outputBuf, int cyl, int head, - LinearBitmap* pBadBlockMap) + long nibbleLen, unsigned char* outputBuf, int cyl, int head, + LinearBitmap* pBadBlockMap) { CircularBufferAccess buffer(nibbleBuf, nibbleLen); - bool foundSector[kMaxSectorsPerTrack]; - unsigned char sectorBuf[kSectorSize35]; - unsigned char readSum[kDataChecksumLen]; - unsigned char calcSum[kDataChecksumLen]; - int i; + bool foundSector[kMaxSectorsPerTrack]; + unsigned char sectorBuf[kSectorSize35]; + unsigned char readSum[kDataChecksumLen]; + unsigned char calcSum[kDataChecksumLen]; + int i; - memset(&foundSector, 0, sizeof(foundSector)); + memset(&foundSector, 0, sizeof(foundSector)); - i = 0; - while (i < nibbleLen) { - int sector; + i = 0; + while (i < nibbleLen) { + int sector; - i = FindNextSector35(buffer, i, cyl, head, §or); - if (i < 0) - break; + i = FindNextSector35(buffer, i, cyl, head, §or); + if (i < 0) + break; - assert(sector >= 0 && sector < SectorsPerTrack35(cyl)); - if (foundSector[sector]) { - WMSG3("Nib35: WARNING: found two copies of sect %d on cyl=%d head=%d\n", - sector, cyl, head); - } else { - memset(sectorBuf, 0xa9, sizeof(sectorBuf)); - if (DecodeNibbleSector35(buffer, i, sectorBuf, readSum, calcSum)) - { - /* successfully decoded sector, copy data & verify checksum */ - foundSector[sector] = true; - memcpy(outputBuf + kBlockSize * sector, - sectorBuf + kTagBytesLen, kBlockSize); + assert(sector >= 0 && sector < SectorsPerTrack35(cyl)); + if (foundSector[sector]) { + WMSG3("Nib35: WARNING: found two copies of sect %d on cyl=%d head=%d\n", + sector, cyl, head); + } else { + memset(sectorBuf, 0xa9, sizeof(sectorBuf)); + if (DecodeNibbleSector35(buffer, i, sectorBuf, readSum, calcSum)) + { + /* successfully decoded sector, copy data & verify checksum */ + foundSector[sector] = true; + memcpy(outputBuf + kBlockSize * sector, + sectorBuf + kTagBytesLen, kBlockSize); - if (calcSum[0] != readSum[0] || - calcSum[1] != readSum[1] || - calcSum[2] != readSum[2]) - { - WMSG2("Nib35: checksum mismatch: 0x%06x vs. 0x%06x\n", - calcSum[0] << 16 | calcSum[1] << 8 | calcSum[2], - readSum[0] << 16 | readSum[1] << 8 | readSum[2]); - WMSG4("Nib35: marking cyl=%d head=%d sect=%d (block=%d)\n", - cyl, head, sector, - CylHeadSect35ToBlock(cyl, head, sector)); - pBadBlockMap->Set(CylHeadSect35ToBlock(cyl, head, sector)); - } - } - } - } + if (calcSum[0] != readSum[0] || + calcSum[1] != readSum[1] || + calcSum[2] != readSum[2]) + { + WMSG2("Nib35: checksum mismatch: 0x%06x vs. 0x%06x\n", + calcSum[0] << 16 | calcSum[1] << 8 | calcSum[2], + readSum[0] << 16 | readSum[1] << 8 | readSum[2]); + WMSG4("Nib35: marking cyl=%d head=%d sect=%d (block=%d)\n", + cyl, head, sector, + CylHeadSect35ToBlock(cyl, head, sector)); + pBadBlockMap->Set(CylHeadSect35ToBlock(cyl, head, sector)); + } + } + } + } - /* - * Check to see if we have all our parts. Anything missing sets - * a flag in the "bad block" map. - */ - for (i = SectorsPerTrack35(cyl)-1; i >= 0; i--) { - if (!foundSector[i]) { - WMSG4("Nib35: didn't find cyl=%d head=%d sect=%d (block=%d)\n", - cyl, head, i, CylHeadSect35ToBlock(cyl, head, i)); - pBadBlockMap->Set(CylHeadSect35ToBlock(cyl, head, i)); - } + /* + * Check to see if we have all our parts. Anything missing sets + * a flag in the "bad block" map. + */ + for (i = SectorsPerTrack35(cyl)-1; i >= 0; i--) { + if (!foundSector[i]) { + WMSG4("Nib35: didn't find cyl=%d head=%d sect=%d (block=%d)\n", + cyl, head, i, CylHeadSect35ToBlock(cyl, head, i)); + pBadBlockMap->Set(CylHeadSect35ToBlock(cyl, head, i)); + } - /* - // DEBUG test - if ((cyl == 0 || cyl == 12 || cyl == 79) && - (head == (cyl & 0x01)) && - (i == 1 || i == 7)) - { - WMSG4("DEBUG: setting bad %d/%d/%d (%d)\n", - cyl, head, i, CylHeadSect35ToBlock(cyl, head, i)); - pBadBlockMap->Set(CylHeadSect35ToBlock(cyl, head, i)); - } - */ - } + /* + // DEBUG test + if ((cyl == 0 || cyl == 12 || cyl == 79) && + (head == (cyl & 0x01)) && + (i == 1 || i == 7)) + { + WMSG4("DEBUG: setting bad %d/%d/%d (%d)\n", + cyl, head, i, CylHeadSect35ToBlock(cyl, head, i)); + pBadBlockMap->Set(CylHeadSect35ToBlock(cyl, head, i)); + } + */ + } - return kDIErrNone; // maybe return an error if nothing found? + return kDIErrNone; // maybe return an error if nothing found? } /* @@ -191,71 +191,71 @@ DiskImg::UnpackNibbleTrack35(const unsigned char* nibbleBuf, */ /*static*/ int DiskImg::FindNextSector35(const CircularBufferAccess& buffer, int start, - int cyl, int head, int* pSector) + int cyl, int head, int* pSector) { - int end = buffer.GetSize(); - int i; + int end = buffer.GetSize(); + int i; - for (i = start; i < end; i++) { - bool foundAddr = false; + for (i = start; i < end; i++) { + bool foundAddr = false; - if (buffer[i] == kAddrProlog0 && - buffer[i+1] == kAddrProlog1 && - buffer[i+2] == kAddrProlog2) - { - foundAddr = true; - } + if (buffer[i] == kAddrProlog0 && + buffer[i+1] == kAddrProlog1 && + buffer[i+2] == kAddrProlog2) + { + foundAddr = true; + } - if (foundAddr) { - /* decode the address field */ - int trackNum, sectNum, side, format, checksum; + if (foundAddr) { + /* decode the address field */ + int trackNum, sectNum, side, format, checksum; - trackNum = kInvDiskBytes62[buffer[i+3]]; - sectNum = kInvDiskBytes62[buffer[i+4]]; - side = kInvDiskBytes62[buffer[i+5]]; - format = kInvDiskBytes62[buffer[i+6]]; - checksum = kInvDiskBytes62[buffer[i+7]]; - if (trackNum == kInvInvalidValue || - sectNum == kInvInvalidValue || - side == kInvInvalidValue || - format == kInvInvalidValue || - checksum == kInvInvalidValue) - { - WMSG0("Nib35: garbled address header found\n"); - continue; - } - //WMSG5(" Nib35: got addr: track=%2d sect=%2d side=%d format=%d sum=0x%02x\n", - // trackNum, sectNum, side, format, checksum); - if (side != ((head * 0x20) | (cyl >> 6))) { - WMSG3("Nib35: unexpected value for side: %d on cyl=%d head=%d\n", - side, cyl, head); - } - if (sectNum >= SectorsPerTrack35(cyl)) { - WMSG2("Nib35: invalid value for sector: %d (cyl=%d)\n", - sectNum, cyl); - continue; - } - /* format seems to be 0x22 or 0x24 */ - if (checksum != (trackNum ^ sectNum ^ side ^ format)) { - WMSG2("Nib35: unexpected checksum: 0x%02x vs. 0x%02x\n", - checksum, trackNum ^ sectNum ^ side ^ format); - continue; - } + trackNum = kInvDiskBytes62[buffer[i+3]]; + sectNum = kInvDiskBytes62[buffer[i+4]]; + side = kInvDiskBytes62[buffer[i+5]]; + format = kInvDiskBytes62[buffer[i+6]]; + checksum = kInvDiskBytes62[buffer[i+7]]; + if (trackNum == kInvInvalidValue || + sectNum == kInvInvalidValue || + side == kInvInvalidValue || + format == kInvInvalidValue || + checksum == kInvInvalidValue) + { + WMSG0("Nib35: garbled address header found\n"); + continue; + } + //WMSG5(" Nib35: got addr: track=%2d sect=%2d side=%d format=%d sum=0x%02x\n", + // trackNum, sectNum, side, format, checksum); + if (side != ((head * 0x20) | (cyl >> 6))) { + WMSG3("Nib35: unexpected value for side: %d on cyl=%d head=%d\n", + side, cyl, head); + } + if (sectNum >= SectorsPerTrack35(cyl)) { + WMSG2("Nib35: invalid value for sector: %d (cyl=%d)\n", + sectNum, cyl); + continue; + } + /* format seems to be 0x22 or 0x24 */ + if (checksum != (trackNum ^ sectNum ^ side ^ format)) { + WMSG2("Nib35: unexpected checksum: 0x%02x vs. 0x%02x\n", + checksum, trackNum ^ sectNum ^ side ^ format); + continue; + } - /* check the epilog bytes */ - if (buffer[i+8] != kAddrEpilog0 || - buffer[i+9] != kAddrEpilog1) - { - WMSG0("Nib35: invalid address epilog\n"); - /* maybe we allow this anyway? */ - } + /* check the epilog bytes */ + if (buffer[i+8] != kAddrEpilog0 || + buffer[i+9] != kAddrEpilog1) + { + WMSG0("Nib35: invalid address epilog\n"); + /* maybe we allow this anyway? */ + } - *pSector = sectNum; - return i+10; // move past address field - } - } + *pSector = sectNum; + return i+10; // move past address field + } + } - return -1; + return -1; } /* @@ -277,164 +277,164 @@ DiskImg::FindNextSector35(const CircularBufferAccess& buffer, int start, */ /*static*/ bool DiskImg::DecodeNibbleSector35(const CircularBufferAccess& buffer, int start, - unsigned char* sectorBuf, unsigned char* readChecksum, - unsigned char* calcChecksum) + unsigned char* sectorBuf, unsigned char* readChecksum, + unsigned char* calcChecksum) { const int kMaxDataReach35 = 48; // fairly arbitrary - unsigned char* sectorBufStart = sectorBuf; - unsigned char part0[kChunkSize35], part1[kChunkSize35], part2[kChunkSize35]; - unsigned int chk0, chk1, chk2; - unsigned char val, nib0, nib1, nib2, twos; - int i, off; + unsigned char* sectorBufStart = sectorBuf; + unsigned char part0[kChunkSize35], part1[kChunkSize35], part2[kChunkSize35]; + unsigned int chk0, chk1, chk2; + unsigned char val, nib0, nib1, nib2, twos; + int i, off; - /* - * Find the start of the actual data. Adjust "start" to point at it. - */ - for (off = start; off < start + kMaxDataReach35; off++) { - if (buffer[off] == kDataProlog0 && - buffer[off+1] == kDataProlog1 && - buffer[off+2] == kDataProlog2) - { - start = off + 4; // 3 prolog bytes + sector number - break; - } - } - if (off == start + kMaxDataReach35) { - WMSG0("nib25: could not find start of data field\n"); - return false; - } + /* + * Find the start of the actual data. Adjust "start" to point at it. + */ + for (off = start; off < start + kMaxDataReach35; off++) { + if (buffer[off] == kDataProlog0 && + buffer[off+1] == kDataProlog1 && + buffer[off+2] == kDataProlog2) + { + start = off + 4; // 3 prolog bytes + sector number + break; + } + } + if (off == start + kMaxDataReach35) { + WMSG0("nib25: could not find start of data field\n"); + return false; + } - /* - * Assemble 8-bit bytes from 6&2 encoded values. - */ - off = start; - for (i = 0; i < kChunkSize35; i++) { - twos = kInvDiskBytes62[buffer[off++]]; - nib0 = kInvDiskBytes62[buffer[off++]]; - nib1 = kInvDiskBytes62[buffer[off++]]; - if (i != kChunkSize35-1) - nib2 = kInvDiskBytes62[buffer[off++]]; - else - nib2 = 0; + /* + * Assemble 8-bit bytes from 6&2 encoded values. + */ + off = start; + for (i = 0; i < kChunkSize35; i++) { + twos = kInvDiskBytes62[buffer[off++]]; + nib0 = kInvDiskBytes62[buffer[off++]]; + nib1 = kInvDiskBytes62[buffer[off++]]; + if (i != kChunkSize35-1) + nib2 = kInvDiskBytes62[buffer[off++]]; + else + nib2 = 0; - if (twos == kInvInvalidValue || - nib0 == kInvInvalidValue || - nib1 == kInvInvalidValue || - nib2 == kInvInvalidValue) - { - // junk found - WMSG1("Nib25: found invalid disk byte in sector data at %d\n", - off - start); - WMSG4(" (one of 0x%02x 0x%02x 0x%02x 0x%02x)\n", - buffer[off-4], buffer[off-3], buffer[off-2], buffer[off-1]); - return false; - //if (twos == kInvInvalidValue) - // twos = 0; - //if (nib0 == kInvInvalidValue) - // nib0 = 0; - //if (nib1 == kInvInvalidValue) - // nib1 = 0; - //if (nib2 == kInvInvalidValue) - // nib2 = 0; - } + if (twos == kInvInvalidValue || + nib0 == kInvInvalidValue || + nib1 == kInvInvalidValue || + nib2 == kInvInvalidValue) + { + // junk found + WMSG1("Nib25: found invalid disk byte in sector data at %d\n", + off - start); + WMSG4(" (one of 0x%02x 0x%02x 0x%02x 0x%02x)\n", + buffer[off-4], buffer[off-3], buffer[off-2], buffer[off-1]); + return false; + //if (twos == kInvInvalidValue) + // twos = 0; + //if (nib0 == kInvInvalidValue) + // nib0 = 0; + //if (nib1 == kInvInvalidValue) + // nib1 = 0; + //if (nib2 == kInvInvalidValue) + // nib2 = 0; + } - part0[i] = nib0 | ((twos << 2) & 0xc0); - part1[i] = nib1 | ((twos << 4) & 0xc0); - part2[i] = nib2 | ((twos << 6) & 0xc0); - } - assert(off == start + kOffsetToChecksum); + part0[i] = nib0 | ((twos << 2) & 0xc0); + part1[i] = nib1 | ((twos << 4) & 0xc0); + part2[i] = nib2 | ((twos << 6) & 0xc0); + } + assert(off == start + kOffsetToChecksum); - chk0 = chk1 = chk2 = 0; - i = 0; - while (true) { - chk0 = (chk0 & 0xff) << 1; - if (chk0 & 0x0100) - chk0++; + chk0 = chk1 = chk2 = 0; + i = 0; + while (true) { + chk0 = (chk0 & 0xff) << 1; + if (chk0 & 0x0100) + chk0++; - val = part0[i] ^ chk0; - chk2 += val; - if (chk0 & 0x0100) { - chk2++; - chk0 &= 0xff; - } - *sectorBuf++ = val; + val = part0[i] ^ chk0; + chk2 += val; + if (chk0 & 0x0100) { + chk2++; + chk0 &= 0xff; + } + *sectorBuf++ = val; - val = part1[i] ^ chk2; - chk1 += val; - if (chk2 > 0xff) { - chk1++; - chk2 &= 0xff; - } - *sectorBuf++ = val; + val = part1[i] ^ chk2; + chk1 += val; + if (chk2 > 0xff) { + chk1++; + chk2 &= 0xff; + } + *sectorBuf++ = val; - if (sectorBuf - sectorBufStart == 524) - break; + if (sectorBuf - sectorBufStart == 524) + break; - val = part2[i] ^ chk1; - chk0 += val; - if (chk1 > 0xff) { - chk0++; - chk1 &= 0xff; - } - *sectorBuf++ = val; + val = part2[i] ^ chk1; + chk0 += val; + if (chk1 > 0xff) { + chk0++; + chk1 &= 0xff; + } + *sectorBuf++ = val; - i++; - assert(i < kChunkSize35); - //WMSG2("i = %d, diff=%d\n", i, sectorBuf - sectorBufStart); - } + i++; + assert(i < kChunkSize35); + //WMSG2("i = %d, diff=%d\n", i, sectorBuf - sectorBufStart); + } - calcChecksum[0] = chk0; - calcChecksum[1] = chk1; - calcChecksum[2] = chk2; + calcChecksum[0] = chk0; + calcChecksum[1] = chk1; + calcChecksum[2] = chk2; - if (!UnpackChecksum35(buffer, off, readChecksum)) { - WMSG0("Nib35: failure reading checksum\n"); - readChecksum[0] = calcChecksum[0] ^ 0xff; // force a failure - return false; - } - off += 4; // skip past checksum bytes + if (!UnpackChecksum35(buffer, off, readChecksum)) { + WMSG0("Nib35: failure reading checksum\n"); + readChecksum[0] = calcChecksum[0] ^ 0xff; // force a failure + return false; + } + off += 4; // skip past checksum bytes - if (buffer[off] != kDataEpilog0 || buffer[off+1] != kDataEpilog1) { - WMSG0("nib25: WARNING: data epilog not found\n"); - // allow it, if the checksum matches - } + if (buffer[off] != kDataEpilog0 || buffer[off+1] != kDataEpilog1) { + WMSG0("nib25: WARNING: data epilog not found\n"); + // allow it, if the checksum matches + } //#define TEST_ENC_35 #ifdef TEST_ENC_35 - { - unsigned char nibBuf[kNibblizedOutputLen]; - memset(nibBuf, 0xcc, sizeof(nibBuf)); + { + unsigned char nibBuf[kNibblizedOutputLen]; + memset(nibBuf, 0xcc, sizeof(nibBuf)); - /* encode what we just decoded */ - EncodeNibbleSector35(sectorBufStart, nibBuf); - /* compare it to the original */ - for (i = 0; i < kNibblizedOutputLen; i++) { - if (buffer[start + i] != nibBuf[i]) { - /* - * The very last "twos" entry may have undefined bits when - * written by a real drive. Peel it apart and ignore the - * two flaky bits. - */ - if (i == 696) { - unsigned char val1, val2; - val1 = kInvDiskBytes62[buffer[start + i]]; - val2 = kInvDiskBytes62[nibBuf[i]]; - if ((val1 & 0xfc) != (val2 & 0xfc)) { - WMSG5("Nib35 DEBUG: output differs at byte %d" - " (0x%02x vs 0x%02x / 0x%02x vs 0x%02x)\n", - i, buffer[start+i], nibBuf[i], val1, val2); - } - } else { - // note: checksum is 699-702 - WMSG3("Nib35 DEBUG: output differs at byte %d (0x%02x vs 0x%02x)\n", - i, buffer[start+i], nibBuf[i]); - } - } - } - } + /* encode what we just decoded */ + EncodeNibbleSector35(sectorBufStart, nibBuf); + /* compare it to the original */ + for (i = 0; i < kNibblizedOutputLen; i++) { + if (buffer[start + i] != nibBuf[i]) { + /* + * The very last "twos" entry may have undefined bits when + * written by a real drive. Peel it apart and ignore the + * two flaky bits. + */ + if (i == 696) { + unsigned char val1, val2; + val1 = kInvDiskBytes62[buffer[start + i]]; + val2 = kInvDiskBytes62[nibBuf[i]]; + if ((val1 & 0xfc) != (val2 & 0xfc)) { + WMSG5("Nib35 DEBUG: output differs at byte %d" + " (0x%02x vs 0x%02x / 0x%02x vs 0x%02x)\n", + i, buffer[start+i], nibBuf[i], val1, val2); + } + } else { + // note: checksum is 699-702 + WMSG3("Nib35 DEBUG: output differs at byte %d (0x%02x vs 0x%02x)\n", + i, buffer[start+i], nibBuf[i]); + } + } + } + } #endif /*TEST_ENC_35*/ - return true; + return true; } /* @@ -446,28 +446,28 @@ DiskImg::DecodeNibbleSector35(const CircularBufferAccess& buffer, int start, */ /*static*/ bool DiskImg::UnpackChecksum35(const CircularBufferAccess& buffer, int offset, - unsigned char* checksumBuf) + unsigned char* checksumBuf) { - unsigned char nib0, nib1, nib2, twos; - - twos = kInvDiskBytes62[buffer[offset++]]; - nib2 = kInvDiskBytes62[buffer[offset++]]; - nib1 = kInvDiskBytes62[buffer[offset++]]; - nib0 = kInvDiskBytes62[buffer[offset++]]; + unsigned char nib0, nib1, nib2, twos; + + twos = kInvDiskBytes62[buffer[offset++]]; + nib2 = kInvDiskBytes62[buffer[offset++]]; + nib1 = kInvDiskBytes62[buffer[offset++]]; + nib0 = kInvDiskBytes62[buffer[offset++]]; - if (twos == kInvInvalidValue || - nib0 == kInvInvalidValue || - nib1 == kInvInvalidValue || - nib2 == kInvInvalidValue) - { - WMSG0("nib25: found invalid disk byte in checksum\n"); - return false; - } + if (twos == kInvInvalidValue || + nib0 == kInvInvalidValue || + nib1 == kInvInvalidValue || + nib2 == kInvInvalidValue) + { + WMSG0("nib25: found invalid disk byte in checksum\n"); + return false; + } - checksumBuf[0] = nib0 | ((twos << 6) & 0xc0); - checksumBuf[1] = nib1 | ((twos << 4) & 0xc0); - checksumBuf[2] = nib2 | ((twos << 2) & 0xc0); - return true; + checksumBuf[0] = nib0 | ((twos << 6) & 0xc0); + checksumBuf[1] = nib1 | ((twos << 4) & 0xc0); + checksumBuf[2] = nib2 | ((twos << 2) & 0xc0); + return true; } /* @@ -478,80 +478,80 @@ DiskImg::UnpackChecksum35(const CircularBufferAccess& buffer, int offset, */ /*static*/ void DiskImg::EncodeNibbleSector35(const unsigned char* sectorData, - unsigned char* outBuf) + unsigned char* outBuf) { - const unsigned char* sectorDataStart = sectorData; - unsigned char* outBufStart = outBuf; - unsigned char part0[kChunkSize35], part1[kChunkSize35], part2[kChunkSize35]; - unsigned int chk0, chk1, chk2; - unsigned char val, twos; - int i; + const unsigned char* sectorDataStart = sectorData; + unsigned char* outBufStart = outBuf; + unsigned char part0[kChunkSize35], part1[kChunkSize35], part2[kChunkSize35]; + unsigned int chk0, chk1, chk2; + unsigned char val, twos; + int i; - /* - * Compute checksum and split the input into 3 pieces. - */ - i = 0; - chk0 = chk1 = chk2 = 0; - while (true) { - chk0 = (chk0 & 0xff) << 1; - if (chk0 & 0x0100) - chk0++; + /* + * Compute checksum and split the input into 3 pieces. + */ + i = 0; + chk0 = chk1 = chk2 = 0; + while (true) { + chk0 = (chk0 & 0xff) << 1; + if (chk0 & 0x0100) + chk0++; - val = *sectorData++; - chk2 += val; - if (chk0 & 0x0100) { - chk2++; - chk0 &= 0xff; - } - part0[i] = (val ^ chk0) & 0xff; + val = *sectorData++; + chk2 += val; + if (chk0 & 0x0100) { + chk2++; + chk0 &= 0xff; + } + part0[i] = (val ^ chk0) & 0xff; - val = *sectorData++; - chk1 += val; - if (chk2 > 0xff) { - chk1++; - chk2 &= 0xff; - } - part1[i] = (val ^ chk2) & 0xff; + val = *sectorData++; + chk1 += val; + if (chk2 > 0xff) { + chk1++; + chk2 &= 0xff; + } + part1[i] = (val ^ chk2) & 0xff; - if (sectorData - sectorDataStart == 524) - break; + if (sectorData - sectorDataStart == 524) + break; - val = *sectorData++; - chk0 += val; - if (chk1 > 0xff) { - chk0++; - chk1 &= 0xff; - } - part2[i] = (val ^ chk1) & 0xff; - i++; - } - part2[kChunkSize35-1] = 0; // gets merged into the "twos" + val = *sectorData++; + chk0 += val; + if (chk1 > 0xff) { + chk0++; + chk1 &= 0xff; + } + part2[i] = (val ^ chk1) & 0xff; + i++; + } + part2[kChunkSize35-1] = 0; // gets merged into the "twos" - assert(i == kChunkSize35-1); + assert(i == kChunkSize35-1); - /* - * Output the nibble data. - */ - for (i = 0; i < kChunkSize35; i++) { - twos = ((part0[i] & 0xc0) >> 2) | - ((part1[i] & 0xc0) >> 4) | - ((part2[i] & 0xc0) >> 6); + /* + * Output the nibble data. + */ + for (i = 0; i < kChunkSize35; i++) { + twos = ((part0[i] & 0xc0) >> 2) | + ((part1[i] & 0xc0) >> 4) | + ((part2[i] & 0xc0) >> 6); - *outBuf++ = kDiskBytes62[twos]; - *outBuf++ = kDiskBytes62[part0[i] & 0x3f]; - *outBuf++ = kDiskBytes62[part1[i] & 0x3f]; - if (i != kChunkSize35 -1) - *outBuf++ = kDiskBytes62[part2[i] & 0x3f]; - } + *outBuf++ = kDiskBytes62[twos]; + *outBuf++ = kDiskBytes62[part0[i] & 0x3f]; + *outBuf++ = kDiskBytes62[part1[i] & 0x3f]; + if (i != kChunkSize35 -1) + *outBuf++ = kDiskBytes62[part2[i] & 0x3f]; + } - /* - * Output the checksum. - */ - twos = ((chk0 & 0xc0) >> 6) | ((chk1 & 0xc0) >> 4) | ((chk2 & 0xc0) >> 2); - *outBuf++ = kDiskBytes62[twos]; - *outBuf++ = kDiskBytes62[chk2 & 0x3f]; - *outBuf++ = kDiskBytes62[chk1 & 0x3f]; - *outBuf++ = kDiskBytes62[chk0 & 0x3f]; + /* + * Output the checksum. + */ + twos = ((chk0 & 0xc0) >> 6) | ((chk1 & 0xc0) >> 4) | ((chk2 & 0xc0) >> 2); + *outBuf++ = kDiskBytes62[twos]; + *outBuf++ = kDiskBytes62[chk2 & 0x3f]; + *outBuf++ = kDiskBytes62[chk1 & 0x3f]; + *outBuf++ = kDiskBytes62[chk0 & 0x3f]; - assert(outBuf - outBufStart == kNibblizedOutputLen); + assert(outBuf - outBufStart == kNibblizedOutputLen); } diff --git a/diskimg/OuterWrapper.cpp b/diskimg/OuterWrapper.cpp index 04e0dbb..1cb5992 100644 --- a/diskimg/OuterWrapper.cpp +++ b/diskimg/OuterWrapper.cpp @@ -14,12 +14,12 @@ */ #include "StdAfx.h" #include "DiskImgPriv.h" -#define DEF_MEM_LEVEL 8 // normally in zutil.h +#define DEF_MEM_LEVEL 8 // normally in zutil.h /* * =========================================================================== - * OuterGzip + * OuterGzip * =========================================================================== */ @@ -46,14 +46,14 @@ OuterGzip::Test(GenericFD* pGFD, di_off_t outerLength) /* don't need this here, but we will later on */ imagePath = pGFD->GetPathName(); if (imagePath == nil) { - WMSG0("Can't test gzip on non-file\n"); - return kDIErrNotSupported; - } + WMSG0("Can't test gzip on non-file\n"); + return kDIErrNotSupported; + } pGFD->Rewind(); if (pGFD->Read(&magicBuf, 2) != kDIErrNone) - return kDIErrGeneric; + return kDIErrGeneric; magic = GetShortLE((unsigned char*) &magicBuf); if (magic == kGzipMagic) @@ -84,13 +84,13 @@ OuterGzip::Test(GenericFD* pGFD, di_off_t outerLength) DIError OuterGzip::ExtractGzipImage(gzFile gzfp, char** pBuf, di_off_t* pLength) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; const int kMinEmpty = 256 * 1024; const int kStartSize = 141 * 1024; const int kNextSize1 = 801 * 1024; const int kNextSize2 = 1024 * 1024; const int kMaxIncr = 4096 * 1024; - const int kAbsoluteMax = kMaxUncompressedSize; + const int kAbsoluteMax = kMaxUncompressedSize; char* buf = nil; char* newBuf = nil; long curSize, maxSize; @@ -111,32 +111,32 @@ OuterGzip::ExtractGzipImage(gzFile gzfp, char** pBuf, di_off_t* pLength) while (1) { long len; - /* - * Try to fill the buffer. - * - * It appears that zlib v1.1.4 was more tolerant of certain kinds - * of broken archives than v1.2.1. Both give you a pile of data - * on the first read, with no error reported, but the next read - * attempt returns with z_err=-3 (Z_DATA_ERROR) and z_eof set. I'm - * not sure exactly what the flaw is, but I'm guessing something - * got lopped off the end of the archives. gzip v1.3.3 won't touch - * them either. - * - * It would be easy enough to access them, if they were accessible. - * Unfortunately the implementation is buried. Instead, we do - * a quick test against known unadorned floppy disk sizes to see - * if we can salvage the contents. (Our read attempts are all - * slightly *over* the standard disk sizes, so if it comes back right - * on one we're *probably* okay.) - */ + /* + * Try to fill the buffer. + * + * It appears that zlib v1.1.4 was more tolerant of certain kinds + * of broken archives than v1.2.1. Both give you a pile of data + * on the first read, with no error reported, but the next read + * attempt returns with z_err=-3 (Z_DATA_ERROR) and z_eof set. I'm + * not sure exactly what the flaw is, but I'm guessing something + * got lopped off the end of the archives. gzip v1.3.3 won't touch + * them either. + * + * It would be easy enough to access them, if they were accessible. + * Unfortunately the implementation is buried. Instead, we do + * a quick test against known unadorned floppy disk sizes to see + * if we can salvage the contents. (Our read attempts are all + * slightly *over* the standard disk sizes, so if it comes back right + * on one we're *probably* okay.) + */ len = gzread(gzfp, buf + curSize, maxSize - curSize); if (len < 0) { WMSG1(" ExGZ Call to gzread failed, errno=%d\n", errno); - if (curSize == 140*1024 || curSize == 800*1024) { - WMSG0("WARNING: accepting damaged gzip file\n"); - fWrapperDamaged = true; - break; // sleazy, but currently necessary - } + if (curSize == 140*1024 || curSize == 800*1024) { + WMSG0("WARNING: accepting damaged gzip file\n"); + fWrapperDamaged = true; + break; // sleazy, but currently necessary + } dierr = kDIErrReadFailed; goto bail; } else if (len == 0) { @@ -188,11 +188,11 @@ OuterGzip::ExtractGzipImage(gzFile gzfp, char** pBuf, di_off_t* pLength) } assert(curSize < maxSize); - if (curSize > kAbsoluteMax) { - WMSG0(" ExGZ excessive size, probably not a disk image\n"); - dierr = kDIErrTooBig; // close enough - goto bail; - } + if (curSize > kAbsoluteMax) { + WMSG0(" ExGZ excessive size, probably not a disk image\n"); + dierr = kDIErrTooBig; // close enough + goto bail; + } } if (curSize + (1024*1024) < maxSize) { @@ -226,56 +226,56 @@ DIError OuterGzip::Load(GenericFD* pOuterGFD, di_off_t outerLength, bool readOnly, di_off_t* pWrapperLength, GenericFD** ppWrapperGFD) { - DIError dierr = kDIErrNone; - GFDBuffer* pNewGFD = nil; - char* buf = nil; - di_off_t length = -1; + DIError dierr = kDIErrNone; + GFDBuffer* pNewGFD = nil; + char* buf = nil; + di_off_t length = -1; const char* imagePath; - gzFile gzfp = nil; + gzFile gzfp = nil; imagePath = pOuterGFD->GetPathName(); - if (imagePath == nil) { - assert(false); // should've been caught in Test - return kDIErrNotSupported; - } + if (imagePath == nil) { + assert(false); // should've been caught in Test + return kDIErrNotSupported; + } gzfp = gzopen(imagePath, "rb"); // use "readOnly" here if (gzfp == nil) { // DON'T retry RO -- should be done at higher level? WMSG1("gzopen failed, errno=%d\n", errno); - dierr = kDIErrGeneric; - goto bail; - } + dierr = kDIErrGeneric; + goto bail; + } - dierr = ExtractGzipImage(gzfp, &buf, &length); - if (dierr != kDIErrNone) - goto bail; + dierr = ExtractGzipImage(gzfp, &buf, &length); + if (dierr != kDIErrNone) + goto bail; - /* - * Everything is going well. Now we substitute a memory-based GenericFD - * for the existing GenericFD. + /* + * Everything is going well. Now we substitute a memory-based GenericFD + * for the existing GenericFD. */ - pNewGFD = new GFDBuffer; - dierr = pNewGFD->Open(buf, length, true, false, readOnly); - if (dierr != kDIErrNone) - goto bail; - buf = nil; // now owned by pNewGFD; + pNewGFD = new GFDBuffer; + dierr = pNewGFD->Open(buf, length, true, false, readOnly); + if (dierr != kDIErrNone) + goto bail; + buf = nil; // now owned by pNewGFD; - /* - * Success! - */ - assert(dierr == kDIErrNone); - *ppWrapperGFD = pNewGFD; + /* + * Success! + */ + assert(dierr == kDIErrNone); + *ppWrapperGFD = pNewGFD; pNewGFD = nil; - *pWrapperLength = length; + *pWrapperLength = length; bail: - if (dierr != kDIErrNone) { - delete pNewGFD; - } + if (dierr != kDIErrNone) { + delete pNewGFD; + } if (gzfp != nil) gzclose(gzfp); - return dierr; + return dierr; } /* @@ -289,9 +289,9 @@ DIError OuterGzip::Save(GenericFD* pOuterGFD, GenericFD* pWrapperGFD, di_off_t wrapperLength) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; const char* imagePath; - gzFile gzfp = nil; + gzFile gzfp = nil; WMSG1(" GZ save (wrapperLen=%ld)\n", (long) wrapperLength); assert(wrapperLength > 0); @@ -300,17 +300,17 @@ OuterGzip::Save(GenericFD* pOuterGFD, GenericFD* pWrapperGFD, * Reopen the file. */ imagePath = pOuterGFD->GetPathName(); - if (imagePath == nil) { - assert(false); // should've been caught long ago - return kDIErrNotSupported; - } + if (imagePath == nil) { + assert(false); // should've been caught long ago + return kDIErrNotSupported; + } gzfp = gzopen(imagePath, "wb"); if (gzfp == nil) { WMSG1("gzopen for write failed, errno=%d\n", errno); - dierr = kDIErrGeneric; - goto bail; - } + dierr = kDIErrGeneric; + goto bail; + } char buf[16384]; size_t actual; @@ -345,21 +345,21 @@ OuterGzip::Save(GenericFD* pOuterGFD, GenericFD* pWrapperGFD, WMSG1(" GZ wrote %ld bytes\n", totalWritten); - /* - * Success! - */ - assert(dierr == kDIErrNone); + /* + * Success! + */ + assert(dierr == kDIErrNone); bail: if (gzfp != nil) gzclose(gzfp); - return dierr; + return dierr; } /* * =========================================================================== - * OuterZip + * OuterZip * =========================================================================== */ @@ -369,42 +369,42 @@ bail: /*static*/ DIError OuterZip::Test(GenericFD* pGFD, di_off_t outerLength) { - DIError dierr = kDIErrNone; - CentralDirEntry cde; + DIError dierr = kDIErrNone; + CentralDirEntry cde; WMSG0("Testing for zip\n"); - dierr = ReadCentralDir(pGFD, outerLength, &cde); - if (dierr != kDIErrNone) - goto bail; + dierr = ReadCentralDir(pGFD, outerLength, &cde); + if (dierr != kDIErrNone) + goto bail; - /* - * Make sure it's a compression method we support. - */ - if (cde.fCompressionMethod != kCompressStored && - cde.fCompressionMethod != kCompressDeflated) - { - WMSG1(" ZIP compression method %d not supported\n", - cde.fCompressionMethod); - dierr = kDIErrGeneric; - goto bail; - } + /* + * Make sure it's a compression method we support. + */ + if (cde.fCompressionMethod != kCompressStored && + cde.fCompressionMethod != kCompressDeflated) + { + WMSG1(" ZIP compression method %d not supported\n", + cde.fCompressionMethod); + dierr = kDIErrGeneric; + goto bail; + } - /* - * Limit the size to something reasonable. - */ - if (cde.fUncompressedSize < 512 || - cde.fUncompressedSize > kMaxUncompressedSize) - { - WMSG1(" ZIP uncompressed size %lu is outside range\n", - cde.fUncompressedSize); - dierr = kDIErrGeneric; - goto bail; - } + /* + * Limit the size to something reasonable. + */ + if (cde.fUncompressedSize < 512 || + cde.fUncompressedSize > kMaxUncompressedSize) + { + WMSG1(" ZIP uncompressed size %lu is outside range\n", + cde.fUncompressedSize); + dierr = kDIErrGeneric; + goto bail; + } - assert(dierr == kDIErrNone); + assert(dierr == kDIErrNone); bail: - return dierr; + return dierr; } /* @@ -414,57 +414,57 @@ DIError OuterZip::Load(GenericFD* pOuterGFD, di_off_t outerLength, bool readOnly, di_off_t* pWrapperLength, GenericFD** ppWrapperGFD) { - DIError dierr = kDIErrNone; - GFDBuffer* pNewGFD = nil; - CentralDirEntry cde; - unsigned char* buf = nil; - di_off_t length = -1; - const char* pExt; + DIError dierr = kDIErrNone; + GFDBuffer* pNewGFD = nil; + CentralDirEntry cde; + unsigned char* buf = nil; + di_off_t length = -1; + const char* pExt; - dierr = ReadCentralDir(pOuterGFD, outerLength, &cde); - if (dierr != kDIErrNone) - goto bail; + dierr = ReadCentralDir(pOuterGFD, outerLength, &cde); + if (dierr != kDIErrNone) + goto bail; - if (cde.fFileNameLength > 0) { - pExt = FindExtension((const char*) cde.fFileName, kZipFssep); - if (pExt != nil) { - assert(*pExt == '.'); - SetExtension(pExt+1); + if (cde.fFileNameLength > 0) { + pExt = FindExtension((const char*) cde.fFileName, kZipFssep); + if (pExt != nil) { + assert(*pExt == '.'); + SetExtension(pExt+1); - WMSG1("OuterZip using extension '%s'\n", GetExtension()); - } + WMSG1("OuterZip using extension '%s'\n", GetExtension()); + } - SetStoredFileName((const char*) cde.fFileName); - } + SetStoredFileName((const char*) cde.fFileName); + } - dierr = ExtractZipEntry(pOuterGFD, &cde, &buf, &length); - if (dierr != kDIErrNone) - goto bail; + dierr = ExtractZipEntry(pOuterGFD, &cde, &buf, &length); + if (dierr != kDIErrNone) + goto bail; - /* - * Everything is going well. Now we substitute a memory-based GenericFD - * for the existing GenericFD. + /* + * Everything is going well. Now we substitute a memory-based GenericFD + * for the existing GenericFD. */ - pNewGFD = new GFDBuffer; - dierr = pNewGFD->Open(buf, length, true, false, readOnly); - if (dierr != kDIErrNone) - goto bail; - buf = nil; // now owned by pNewGFD; + pNewGFD = new GFDBuffer; + dierr = pNewGFD->Open(buf, length, true, false, readOnly); + if (dierr != kDIErrNone) + goto bail; + buf = nil; // now owned by pNewGFD; - /* - * Success! - */ - assert(dierr == kDIErrNone); - *ppWrapperGFD = pNewGFD; + /* + * Success! + */ + assert(dierr == kDIErrNone); + *ppWrapperGFD = pNewGFD; pNewGFD = nil; - *pWrapperLength = length; + *pWrapperLength = length; bail: - if (dierr != kDIErrNone) { - delete pNewGFD; - } - return dierr; + if (dierr != kDIErrNone) { + delete pNewGFD; + } + return dierr; } /* @@ -475,27 +475,27 @@ DIError OuterZip::Save(GenericFD* pOuterGFD, GenericFD* pWrapperGFD, di_off_t wrapperLength) { - DIError dierr = kDIErrNone; - LocalFileHeader lfh; - CentralDirEntry cde; - EndOfCentralDir eocd; - di_off_t lfhOffset; + DIError dierr = kDIErrNone; + LocalFileHeader lfh; + CentralDirEntry cde; + EndOfCentralDir eocd; + di_off_t lfhOffset; WMSG1(" ZIP save (wrapperLen=%ld)\n", (long) wrapperLength); assert(wrapperLength > 0); - dierr = pOuterGFD->Rewind(); - if (dierr != kDIErrNone) - goto bail; - dierr = pOuterGFD->Truncate(); - if (dierr != kDIErrNone) - goto bail; + dierr = pOuterGFD->Rewind(); + if (dierr != kDIErrNone) + goto bail; + dierr = pOuterGFD->Truncate(); + if (dierr != kDIErrNone) + goto bail; - dierr = pWrapperGFD->Rewind(); - if (dierr != kDIErrNone) - goto bail; + dierr = pWrapperGFD->Rewind(); + if (dierr != kDIErrNone) + goto bail; - lfhOffset = pOuterGFD->Tell(); // always 0 with only one file + lfhOffset = pOuterGFD->Tell(); // always 0 with only one file /* * Don't store an empty filename. Some applications, e.g. Info-ZIP's @@ -506,117 +506,117 @@ OuterZip::Save(GenericFD* pOuterGFD, GenericFD* pWrapperGFD, if (fStoredFileName == nil || fStoredFileName[0] == '\0') SetStoredFileName("disk"); - /* - * Write the ZIP local file header. We don't have file lengths or - * CRCs yet, so we have to go back and fill those in later. - */ - lfh.fVersionToExtract = kDefaultVersion; + /* + * Write the ZIP local file header. We don't have file lengths or + * CRCs yet, so we have to go back and fill those in later. + */ + lfh.fVersionToExtract = kDefaultVersion; #if NO_ZIP_COMPRESS - lfh.fGPBitFlag = 0; - lfh.fCompressionMethod = 0; + lfh.fGPBitFlag = 0; + lfh.fCompressionMethod = 0; #else - lfh.fGPBitFlag = 0x0002; // indicates maximum compression used - lfh.fCompressionMethod = 8; // when compressionMethod == deflate + lfh.fGPBitFlag = 0x0002; // indicates maximum compression used + lfh.fCompressionMethod = 8; // when compressionMethod == deflate #endif - GetMSDOSTime(&lfh.fLastModFileDate, &lfh.fLastModFileTime); - lfh.SetFileName(fStoredFileName); - dierr = lfh.Write(pOuterGFD); - if (dierr != kDIErrNone) - goto bail; + GetMSDOSTime(&lfh.fLastModFileDate, &lfh.fLastModFileTime); + lfh.SetFileName(fStoredFileName); + dierr = lfh.Write(pOuterGFD); + if (dierr != kDIErrNone) + goto bail; - /* - * Write the compressed data. - */ - unsigned long crc; - di_off_t compressedLen; - if (lfh.fCompressionMethod == kCompressDeflated) { - dierr = DeflateGFDToGFD(pOuterGFD, pWrapperGFD, wrapperLength, - &compressedLen, &crc); - if (dierr != kDIErrNone) - goto bail; - } else if (lfh.fCompressionMethod == kCompressStored) { - dierr = GenericFD::CopyFile(pOuterGFD, pWrapperGFD, wrapperLength, - &crc); - if (dierr != kDIErrNone) - goto bail; - compressedLen = wrapperLength; - } else { - assert(false); - dierr = kDIErrInternal; - goto bail; - } + /* + * Write the compressed data. + */ + unsigned long crc; + di_off_t compressedLen; + if (lfh.fCompressionMethod == kCompressDeflated) { + dierr = DeflateGFDToGFD(pOuterGFD, pWrapperGFD, wrapperLength, + &compressedLen, &crc); + if (dierr != kDIErrNone) + goto bail; + } else if (lfh.fCompressionMethod == kCompressStored) { + dierr = GenericFD::CopyFile(pOuterGFD, pWrapperGFD, wrapperLength, + &crc); + if (dierr != kDIErrNone) + goto bail; + compressedLen = wrapperLength; + } else { + assert(false); + dierr = kDIErrInternal; + goto bail; + } - /* - * Go back and take care of the local file header stuff. - * - * It's not supposed to be necessary, but some utilities (WinZip, - * Info-ZIP) get bent out of shape if these aren't set and the data - * is compressed. They seem okay with it when the file isn't - * compressed. I don't understand this behavior, but writing the - * local file header is easy enough. - */ - lfh.fCRC32 = crc; - lfh.fCompressedSize = (unsigned long) compressedLen; - lfh.fUncompressedSize = (unsigned long) wrapperLength; + /* + * Go back and take care of the local file header stuff. + * + * It's not supposed to be necessary, but some utilities (WinZip, + * Info-ZIP) get bent out of shape if these aren't set and the data + * is compressed. They seem okay with it when the file isn't + * compressed. I don't understand this behavior, but writing the + * local file header is easy enough. + */ + lfh.fCRC32 = crc; + lfh.fCompressedSize = (unsigned long) compressedLen; + lfh.fUncompressedSize = (unsigned long) wrapperLength; - di_off_t curPos; - curPos = pOuterGFD->Tell(); - dierr = pOuterGFD->Seek(lfhOffset, kSeekSet); - if (dierr != kDIErrNone) - goto bail; - dierr = lfh.Write(pOuterGFD); - if (dierr != kDIErrNone) - goto bail; - dierr = pOuterGFD->Seek(curPos, kSeekSet); - if (dierr != kDIErrNone) - goto bail; + di_off_t curPos; + curPos = pOuterGFD->Tell(); + dierr = pOuterGFD->Seek(lfhOffset, kSeekSet); + if (dierr != kDIErrNone) + goto bail; + dierr = lfh.Write(pOuterGFD); + if (dierr != kDIErrNone) + goto bail; + dierr = pOuterGFD->Seek(curPos, kSeekSet); + if (dierr != kDIErrNone) + goto bail; - di_off_t cdeStart, cdeFinish; - cdeStart = pOuterGFD->Tell(); + di_off_t cdeStart, cdeFinish; + cdeStart = pOuterGFD->Tell(); - /* - * Write the central dir entry. This is largely just a copy of the - * data in the local file header (and in fact some utilities will - * get rather bent out of shape if the two don't match exactly). - */ - cde.fVersionMadeBy = kDefaultVersion; - cde.fVersionToExtract = lfh.fVersionToExtract; - cde.fGPBitFlag = lfh.fGPBitFlag; - cde.fCompressionMethod = lfh.fCompressionMethod; - cde.fLastModFileDate = lfh.fLastModFileDate; - cde.fLastModFileTime = lfh.fLastModFileTime; - cde.fCRC32 = lfh.fCRC32; - cde.fCompressedSize = lfh.fCompressedSize; - cde.fUncompressedSize = lfh.fUncompressedSize; - assert(lfh.fExtraFieldLength == 0 && cde.fExtraFieldLength == 0); - cde.fExternalAttrs = 0x81b60020; // matches what WinZip does - cde.fLocalHeaderRelOffset = (unsigned long) lfhOffset; - cde.SetFileName(fStoredFileName); - dierr = cde.Write(pOuterGFD); - if (dierr != kDIErrNone) - goto bail; + /* + * Write the central dir entry. This is largely just a copy of the + * data in the local file header (and in fact some utilities will + * get rather bent out of shape if the two don't match exactly). + */ + cde.fVersionMadeBy = kDefaultVersion; + cde.fVersionToExtract = lfh.fVersionToExtract; + cde.fGPBitFlag = lfh.fGPBitFlag; + cde.fCompressionMethod = lfh.fCompressionMethod; + cde.fLastModFileDate = lfh.fLastModFileDate; + cde.fLastModFileTime = lfh.fLastModFileTime; + cde.fCRC32 = lfh.fCRC32; + cde.fCompressedSize = lfh.fCompressedSize; + cde.fUncompressedSize = lfh.fUncompressedSize; + assert(lfh.fExtraFieldLength == 0 && cde.fExtraFieldLength == 0); + cde.fExternalAttrs = 0x81b60020; // matches what WinZip does + cde.fLocalHeaderRelOffset = (unsigned long) lfhOffset; + cde.SetFileName(fStoredFileName); + dierr = cde.Write(pOuterGFD); + if (dierr != kDIErrNone) + goto bail; - cdeFinish = pOuterGFD->Tell(); + cdeFinish = pOuterGFD->Tell(); - /* - * Write the end-of-central-dir stuff. - */ - eocd.fNumEntries = 1; - eocd.fTotalNumEntries = 1; - eocd.fCentralDirSize = (unsigned long) (cdeFinish - cdeStart); - eocd.fCentralDirOffset = (unsigned long) cdeStart; - assert(eocd.fCentralDirSize >= EndOfCentralDir::kEOCDLen); - dierr = eocd.Write(pOuterGFD); - if (dierr != kDIErrNone) - goto bail; + /* + * Write the end-of-central-dir stuff. + */ + eocd.fNumEntries = 1; + eocd.fTotalNumEntries = 1; + eocd.fCentralDirSize = (unsigned long) (cdeFinish - cdeStart); + eocd.fCentralDirOffset = (unsigned long) cdeStart; + assert(eocd.fCentralDirSize >= EndOfCentralDir::kEOCDLen); + dierr = eocd.Write(pOuterGFD); + if (dierr != kDIErrNone) + goto bail; - /* - * Success! - */ - assert(dierr == kDIErrNone); + /* + * Success! + */ + assert(dierr == kDIErrNone); bail: - return dierr; + return dierr; } @@ -626,8 +626,8 @@ bail: void OuterZip::SetStoredFileName(const char* name) { - delete[] fStoredFileName; - fStoredFileName = StrcpyNew(name); + delete[] fStoredFileName; + fStoredFileName = StrcpyNew(name); } @@ -653,114 +653,114 @@ OuterZip::SetStoredFileName(const char* name) */ /*static*/ DIError OuterZip::ReadCentralDir(GenericFD* pGFD, di_off_t outerLength, - CentralDirEntry* pDirEntry) + CentralDirEntry* pDirEntry) { - DIError dierr = kDIErrNone; - EndOfCentralDir eocd; - unsigned char* buf = nil; - di_off_t seekStart; - long readAmount; - int i; + DIError dierr = kDIErrNone; + EndOfCentralDir eocd; + unsigned char* buf = nil; + di_off_t seekStart; + long readAmount; + int i; - /* too small to be a ZIP archive? */ - if (outerLength < EndOfCentralDir::kEOCDLen + 4) - return kDIErrGeneric; + /* too small to be a ZIP archive? */ + if (outerLength < EndOfCentralDir::kEOCDLen + 4) + return kDIErrGeneric; - buf = new unsigned char[kMaxEOCDSearch]; - if (buf == nil) { - dierr = kDIErrMalloc; - goto bail; - } + buf = new unsigned char[kMaxEOCDSearch]; + if (buf == nil) { + dierr = kDIErrMalloc; + goto bail; + } - if (outerLength > kMaxEOCDSearch) { - seekStart = outerLength - kMaxEOCDSearch; - readAmount = kMaxEOCDSearch; - } else { - seekStart = 0; - readAmount = (long) outerLength; - } - dierr = pGFD->Seek(seekStart, kSeekSet); - if (dierr != kDIErrNone) - goto bail; + if (outerLength > kMaxEOCDSearch) { + seekStart = outerLength - kMaxEOCDSearch; + readAmount = kMaxEOCDSearch; + } else { + seekStart = 0; + readAmount = (long) outerLength; + } + dierr = pGFD->Seek(seekStart, kSeekSet); + if (dierr != kDIErrNone) + goto bail; - /* read the last part of the file into the buffer */ - dierr = pGFD->Read(buf, readAmount); - if (dierr != kDIErrNone) - goto bail; + /* read the last part of the file into the buffer */ + dierr = pGFD->Read(buf, readAmount); + if (dierr != kDIErrNone) + goto bail; - /* find the end-of-central-dir magic */ - for (i = readAmount - 4; i >= 0; i--) { - if (buf[i] == 0x50 && - GetLongLE(&buf[i]) == EndOfCentralDir::kSignature) - { - WMSG1("+++ Found EOCD at buf+%d\n", i); - break; - } - } - if (i < 0) { - WMSG0("+++ EOCD not found, not ZIP\n"); - dierr = kDIErrGeneric; - goto bail; - } + /* find the end-of-central-dir magic */ + for (i = readAmount - 4; i >= 0; i--) { + if (buf[i] == 0x50 && + GetLongLE(&buf[i]) == EndOfCentralDir::kSignature) + { + WMSG1("+++ Found EOCD at buf+%d\n", i); + break; + } + } + if (i < 0) { + WMSG0("+++ EOCD not found, not ZIP\n"); + dierr = kDIErrGeneric; + goto bail; + } - /* extract eocd values */ - dierr = eocd.ReadBuf(buf + i, readAmount - i); - if (dierr != kDIErrNone) - goto bail; - eocd.Dump(); + /* extract eocd values */ + dierr = eocd.ReadBuf(buf + i, readAmount - i); + if (dierr != kDIErrNone) + goto bail; + eocd.Dump(); - if (eocd.fDiskNumber != 0 || eocd.fDiskWithCentralDir != 0 || - eocd.fNumEntries != 1 || eocd.fTotalNumEntries != 1) - { - WMSG0(" Probable ZIP archive has more than one member\n"); - dierr = kDIErrFileArchive; - goto bail; - } + if (eocd.fDiskNumber != 0 || eocd.fDiskWithCentralDir != 0 || + eocd.fNumEntries != 1 || eocd.fTotalNumEntries != 1) + { + WMSG0(" Probable ZIP archive has more than one member\n"); + dierr = kDIErrFileArchive; + goto bail; + } - /* - * So far so good. "fCentralDirSize" is the size in bytes of the - * central directory, so we can just seek back that far to find it. - * We can also seek forward fCentralDirOffset bytes from the - * start of the file. - * - * We're not guaranteed to have the rest of the central dir in the - * buffer, nor are we guaranteed that the central dir will have any - * sort of convenient size. We need to skip to the start of it and - * read the header, then the other goodies. - * - * The only thing we really need right now is the file comment, which - * we're hoping to preserve. - */ - dierr = pGFD->Seek(eocd.fCentralDirOffset, kSeekSet); - if (dierr != kDIErrNone) - goto bail; + /* + * So far so good. "fCentralDirSize" is the size in bytes of the + * central directory, so we can just seek back that far to find it. + * We can also seek forward fCentralDirOffset bytes from the + * start of the file. + * + * We're not guaranteed to have the rest of the central dir in the + * buffer, nor are we guaranteed that the central dir will have any + * sort of convenient size. We need to skip to the start of it and + * read the header, then the other goodies. + * + * The only thing we really need right now is the file comment, which + * we're hoping to preserve. + */ + dierr = pGFD->Seek(eocd.fCentralDirOffset, kSeekSet); + if (dierr != kDIErrNone) + goto bail; - /* - * Read the central dir entry. - */ - dierr = pDirEntry->Read(pGFD); - if (dierr != kDIErrNone) - goto bail; + /* + * Read the central dir entry. + */ + dierr = pDirEntry->Read(pGFD); + if (dierr != kDIErrNone) + goto bail; - pDirEntry->Dump(); + pDirEntry->Dump(); - { - unsigned char checkBuf[4]; - dierr = pGFD->Read(checkBuf, 4); - if (dierr != kDIErrNone) - goto bail; - if (GetLongLE(checkBuf) != EndOfCentralDir::kSignature) { - WMSG0("CDE read check failed\n"); - assert(false); - dierr = kDIErrGeneric; - goto bail; - } - WMSG0("+++ CDE read check passed\n"); - } + { + unsigned char checkBuf[4]; + dierr = pGFD->Read(checkBuf, 4); + if (dierr != kDIErrNone) + goto bail; + if (GetLongLE(checkBuf) != EndOfCentralDir::kSignature) { + WMSG0("CDE read check failed\n"); + assert(false); + dierr = kDIErrGeneric; + goto bail; + } + WMSG0("+++ CDE read check passed\n"); + } bail: - delete[] buf; - return dierr; + delete[] buf; + return dierr; } @@ -770,69 +770,69 @@ bail: */ DIError OuterZip::ExtractZipEntry(GenericFD* pOuterGFD, CentralDirEntry* pCDE, - unsigned char** pBuf, di_off_t* pLength) + unsigned char** pBuf, di_off_t* pLength) { - DIError dierr = kDIErrNone; - LocalFileHeader lfh; - unsigned char* buf = nil; + DIError dierr = kDIErrNone; + LocalFileHeader lfh; + unsigned char* buf = nil; - /* seek to the start of the local header */ - dierr = pOuterGFD->Seek(pCDE->fLocalHeaderRelOffset, kSeekSet); - if (dierr != kDIErrNone) - goto bail; + /* seek to the start of the local header */ + dierr = pOuterGFD->Seek(pCDE->fLocalHeaderRelOffset, kSeekSet); + if (dierr != kDIErrNone) + goto bail; - /* - * Read the local file header, mainly as a way to get past it. There - * are legitimate reasons why the size fields and filename might be - * empty, so we really don't want to depend on any data in the LFH. - * We just need to find where the data starts. - */ - dierr = lfh.Read(pOuterGFD); - if (dierr != kDIErrNone) - goto bail; - lfh.Dump(); + /* + * Read the local file header, mainly as a way to get past it. There + * are legitimate reasons why the size fields and filename might be + * empty, so we really don't want to depend on any data in the LFH. + * We just need to find where the data starts. + */ + dierr = lfh.Read(pOuterGFD); + if (dierr != kDIErrNone) + goto bail; + lfh.Dump(); - /* we should now be pointing at the data */ - WMSG1("File offset is 0x%08lx\n", (long) pOuterGFD->Tell()); + /* we should now be pointing at the data */ + WMSG1("File offset is 0x%08lx\n", (long) pOuterGFD->Tell()); - buf = new unsigned char[pCDE->fUncompressedSize]; - if (buf == nil) { - /* a very real possibility */ - WMSG1(" ZIP unable to allocate buffer of %lu bytes\n", - pCDE->fUncompressedSize); - dierr = kDIErrMalloc; - goto bail; - } + buf = new unsigned char[pCDE->fUncompressedSize]; + if (buf == nil) { + /* a very real possibility */ + WMSG1(" ZIP unable to allocate buffer of %lu bytes\n", + pCDE->fUncompressedSize); + dierr = kDIErrMalloc; + goto bail; + } - /* unpack or copy the data */ - if (pCDE->fCompressionMethod == kCompressDeflated) { - dierr = InflateGFDToBuffer(pOuterGFD, pCDE->fCompressedSize, - pCDE->fUncompressedSize, buf); - if (dierr != kDIErrNone) - goto bail; - } else if (pCDE->fCompressionMethod == kCompressStored) { - dierr = pOuterGFD->Read(buf, pCDE->fUncompressedSize); - if (dierr != kDIErrNone) - goto bail; - } else { - assert(false); - dierr = kDIErrInternal; - goto bail; - } + /* unpack or copy the data */ + if (pCDE->fCompressionMethod == kCompressDeflated) { + dierr = InflateGFDToBuffer(pOuterGFD, pCDE->fCompressedSize, + pCDE->fUncompressedSize, buf); + if (dierr != kDIErrNone) + goto bail; + } else if (pCDE->fCompressionMethod == kCompressStored) { + dierr = pOuterGFD->Read(buf, pCDE->fUncompressedSize); + if (dierr != kDIErrNone) + goto bail; + } else { + assert(false); + dierr = kDIErrInternal; + goto bail; + } - /* check the CRC32 */ - unsigned long crc; - crc = crc32(0L, Z_NULL, 0); - crc = crc32(crc, buf, pCDE->fUncompressedSize); + /* check the CRC32 */ + unsigned long crc; + crc = crc32(0L, Z_NULL, 0); + crc = crc32(crc, buf, pCDE->fUncompressedSize); - if (crc == pCDE->fCRC32) { - WMSG0("+++ ZIP CRCs match\n"); - } else { - WMSG2("ZIP CRC mismatch: inflated crc32=0x%08lx, stored=0x%08lx\n", - crc, pCDE->fCRC32); - dierr = kDIErrBadChecksum; - goto bail; - } + if (crc == pCDE->fCRC32) { + WMSG0("+++ ZIP CRCs match\n"); + } else { + WMSG2("ZIP CRC mismatch: inflated crc32=0x%08lx, stored=0x%08lx\n", + crc, pCDE->fCRC32); + dierr = kDIErrBadChecksum; + goto bail; + } *pBuf = buf; *pLength = pCDE->fUncompressedSize; @@ -851,26 +851,26 @@ bail: */ DIError OuterZip::InflateGFDToBuffer(GenericFD* pGFD, unsigned long compSize, - unsigned long uncompSize, unsigned char* buf) + unsigned long uncompSize, unsigned char* buf) { DIError dierr = kDIErrNone; - const unsigned long kReadBufSize = 65536; - unsigned char* readBuf = nil; + const unsigned long kReadBufSize = 65536; + unsigned char* readBuf = nil; z_stream zstream; int zerr; unsigned long compRemaining; - readBuf = new unsigned char[kReadBufSize]; - if (readBuf == nil) { - dierr = kDIErrMalloc; - goto bail; - } + readBuf = new unsigned char[kReadBufSize]; + if (readBuf == nil) { + dierr = kDIErrMalloc; + goto bail; + } compRemaining = compSize; /* * Initialize the zlib stream. */ - memset(&zstream, 0, sizeof(zstream)); + memset(&zstream, 0, sizeof(zstream)); zstream.zalloc = Z_NULL; zstream.zfree = Z_NULL; zstream.opaque = Z_NULL; @@ -880,10 +880,10 @@ OuterZip::InflateGFDToBuffer(GenericFD* pGFD, unsigned long compSize, zstream.avail_out = uncompSize; zstream.data_type = Z_UNKNOWN; - /* - * Use the undocumented "negative window bits" feature to tell zlib - * that there's no zlib header waiting for it. - */ + /* + * Use the undocumented "negative window bits" feature to tell zlib + * that there's no zlib header waiting for it. + */ zerr = inflateInit2(&zstream, -MAX_WBITS); if (zerr != Z_OK) { dierr = kDIErrInternal; @@ -909,8 +909,8 @@ OuterZip::InflateGFDToBuffer(GenericFD* pGFD, unsigned long compSize, WMSG2("+++ reading %ld bytes (%ld left)\n", getSize, compRemaining); - dierr = pGFD->Read(readBuf, getSize); - if (dierr != kDIErrNone) { + dierr = pGFD->Read(readBuf, getSize); + if (dierr != kDIErrNone) { WMSG0("inflate read failed\n"); goto z_bail; } @@ -929,7 +929,7 @@ OuterZip::InflateGFDToBuffer(GenericFD* pGFD, unsigned long compSize, goto z_bail; } - /* output buffer holds all, so no need to write the output */ + /* output buffer holds all, so no need to write the output */ } while (zerr == Z_OK); assert(zerr == Z_STREAM_END); /* other errors should've been caught */ @@ -945,7 +945,7 @@ z_bail: inflateEnd(&zstream); /* free up any allocated structures */ bail: - delete[] readBuf; + delete[] readBuf; return dierr; } @@ -957,20 +957,20 @@ void OuterZip::GetMSDOSTime(unsigned short* pDate, unsigned short* pTime) { #if 0 - /* this gets gmtime; we want localtime */ - SYSTEMTIME sysTime; - FILETIME fileTime; - ::GetSystemTime(&sysTime); - ::SystemTimeToFileTime(&sysTime, &fileTime); - ::FileTimeToDosDateTime(&fileTime, pDate, pTime); - //WMSG3("+++ Windows date: %04x %04x %d\n", *pDate, *pTime, - // (*pTime >> 11) & 0x1f); + /* this gets gmtime; we want localtime */ + SYSTEMTIME sysTime; + FILETIME fileTime; + ::GetSystemTime(&sysTime); + ::SystemTimeToFileTime(&sysTime, &fileTime); + ::FileTimeToDosDateTime(&fileTime, pDate, pTime); + //WMSG3("+++ Windows date: %04x %04x %d\n", *pDate, *pTime, + // (*pTime >> 11) & 0x1f); #endif - time_t now = time(nil); - DOSTime(now, pDate, pTime); - //WMSG3("+++ Our date : %04x %04x %d\n", *pDate, *pTime, - // (*pTime >> 11) & 0x1f); + time_t now = time(nil); + DOSTime(now, pDate, pTime); + //WMSG3("+++ Our date : %04x %04x %d\n", *pDate, *pTime, + // (*pTime >> 11) & 0x1f); } /* @@ -979,25 +979,25 @@ OuterZip::GetMSDOSTime(unsigned short* pDate, unsigned short* pTime) void OuterZip::DOSTime(time_t when, unsigned short* pDate, unsigned short* pTime) { - time_t even; + time_t even; - *pDate = *pTime = 0; + *pDate = *pTime = 0; - struct tm* ptm; + struct tm* ptm; - /* round up to an even number of seconds */ - even = (time_t)(((unsigned long)(when) + 1) & (~1)); + /* round up to an even number of seconds */ + even = (time_t)(((unsigned long)(when) + 1) & (~1)); - /* expand */ - ptm = localtime(&even); + /* expand */ + ptm = localtime(&even); - int year; - year = ptm->tm_year; - if (year < 80) - year = 80; + int year; + year = ptm->tm_year; + if (year < 80) + year = 80; - *pDate = (year - 80) << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday; - *pTime = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1; + *pDate = (year - 80) << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday; + *pTime = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1; } @@ -1006,121 +1006,121 @@ OuterZip::DOSTime(time_t when, unsigned short* pDate, unsigned short* pTime) */ DIError OuterZip::DeflateGFDToGFD(GenericFD* pDst, GenericFD* pSrc, di_off_t srcLen, - di_off_t* pCompLength, unsigned long* pCRC) + di_off_t* pCompLength, unsigned long* pCRC) { - DIError dierr = kDIErrNone; - const unsigned long kBufSize = 32768; - unsigned char* inBuf = nil; - unsigned char* outBuf = nil; - z_stream zstream; - unsigned long crc; - int zerr; + DIError dierr = kDIErrNone; + const unsigned long kBufSize = 32768; + unsigned char* inBuf = nil; + unsigned char* outBuf = nil; + z_stream zstream; + unsigned long crc; + int zerr; - /* - * Create an input buffer and an output buffer. - */ - inBuf = new unsigned char[kBufSize]; - outBuf = new unsigned char[kBufSize]; - if (inBuf == nil || outBuf == nil) { - dierr = kDIErrMalloc; - goto bail; - } + /* + * Create an input buffer and an output buffer. + */ + inBuf = new unsigned char[kBufSize]; + outBuf = new unsigned char[kBufSize]; + if (inBuf == nil || outBuf == nil) { + dierr = kDIErrMalloc; + goto bail; + } - /* - * Initialize the zlib stream. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = nil; - zstream.avail_in = 0; - zstream.next_out = outBuf; - zstream.avail_out = kBufSize; - zstream.data_type = Z_UNKNOWN; + /* + * Initialize the zlib stream. + */ + memset(&zstream, 0, sizeof(zstream)); + zstream.zalloc = Z_NULL; + zstream.zfree = Z_NULL; + zstream.opaque = Z_NULL; + zstream.next_in = nil; + zstream.avail_in = 0; + zstream.next_out = outBuf; + zstream.avail_out = kBufSize; + zstream.data_type = Z_UNKNOWN; - zerr = deflateInit2(&zstream, Z_BEST_COMPRESSION, - Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); - if (zerr != Z_OK) { - dierr = kDIErrInternal; - if (zerr == Z_VERSION_ERROR) { - WMSG1("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - WMSG1("Call to deflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } + zerr = deflateInit2(&zstream, Z_BEST_COMPRESSION, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); + if (zerr != Z_OK) { + dierr = kDIErrInternal; + if (zerr == Z_VERSION_ERROR) { + WMSG1("Installed zlib is not compatible with linked version (%s)\n", + ZLIB_VERSION); + } else { + WMSG1("Call to deflateInit2 failed (zerr=%d)\n", zerr); + } + goto bail; + } - crc = crc32(0L, Z_NULL, 0); + crc = crc32(0L, Z_NULL, 0); - /* - * Loop while we have data. - */ - do { - long getSize; - int flush; + /* + * Loop while we have data. + */ + do { + long getSize; + int flush; - /* only read if the input is empty */ - if (zstream.avail_in == 0 && srcLen) { - getSize = (srcLen > kBufSize) ? kBufSize : (long) srcLen; - WMSG1("+++ reading %ld bytes\n", getSize); + /* only read if the input is empty */ + if (zstream.avail_in == 0 && srcLen) { + getSize = (srcLen > kBufSize) ? kBufSize : (long) srcLen; + WMSG1("+++ reading %ld bytes\n", getSize); - dierr = pSrc->Read(inBuf, getSize); - if (dierr != kDIErrNone) { - WMSG0("deflate read failed\n"); - goto z_bail; - } + dierr = pSrc->Read(inBuf, getSize); + if (dierr != kDIErrNone) { + WMSG0("deflate read failed\n"); + goto z_bail; + } - srcLen -= getSize; + srcLen -= getSize; - crc = crc32(crc, inBuf, getSize); + crc = crc32(crc, inBuf, getSize); - zstream.next_in = inBuf; - zstream.avail_in = getSize; - } + zstream.next_in = inBuf; + zstream.avail_in = getSize; + } - if (srcLen == 0) - flush = Z_FINISH; /* tell zlib that we're done */ - else - flush = Z_NO_FLUSH; /* more to come! */ + if (srcLen == 0) + flush = Z_FINISH; /* tell zlib that we're done */ + else + flush = Z_NO_FLUSH; /* more to come! */ - zerr = deflate(&zstream, flush); - if (zerr != Z_OK && zerr != Z_STREAM_END) { - WMSG1("zlib deflate call failed (zerr=%d)\n", zerr); - dierr = kDIErrInternal; - goto z_bail; - } + zerr = deflate(&zstream, flush); + if (zerr != Z_OK && zerr != Z_STREAM_END) { + WMSG1("zlib deflate call failed (zerr=%d)\n", zerr); + dierr = kDIErrInternal; + goto z_bail; + } - /* write when we're full or when we're done */ - if (zstream.avail_out == 0 || - (zerr == Z_STREAM_END && zstream.avail_out != kBufSize)) - { - WMSG1("+++ writing %d bytes\n", zstream.next_out - outBuf); - dierr = pDst->Write(outBuf, zstream.next_out - outBuf); - if (dierr != kDIErrNone) { - WMSG0("write failed in deflate\n"); - goto z_bail; - } + /* write when we're full or when we're done */ + if (zstream.avail_out == 0 || + (zerr == Z_STREAM_END && zstream.avail_out != kBufSize)) + { + WMSG1("+++ writing %d bytes\n", zstream.next_out - outBuf); + dierr = pDst->Write(outBuf, zstream.next_out - outBuf); + if (dierr != kDIErrNone) { + WMSG0("write failed in deflate\n"); + goto z_bail; + } - zstream.next_out = outBuf; - zstream.avail_out = kBufSize; - } - } while (zerr == Z_OK); + zstream.next_out = outBuf; + zstream.avail_out = kBufSize; + } + } while (zerr == Z_OK); - assert(zerr == Z_STREAM_END); /* other errors should've been caught */ + assert(zerr == Z_STREAM_END); /* other errors should've been caught */ - *pCompLength = zstream.total_out; - *pCRC = crc; + *pCompLength = zstream.total_out; + *pCRC = crc; z_bail: - deflateEnd(&zstream); /* free up any allocated structures */ + deflateEnd(&zstream); /* free up any allocated structures */ bail: - delete[] inBuf; - delete[] outBuf; + delete[] inBuf; + delete[] outBuf; - return dierr; + return dierr; } /* @@ -1129,14 +1129,14 @@ bail: void OuterZip::SetExtension(const char* ext) { - delete[] fExtension; - fExtension = StrcpyNew(ext); + delete[] fExtension; + fExtension = StrcpyNew(ext); } /* * =================================== - * OuterZip::LocalFileHeader + * OuterZip::LocalFileHeader * =================================== */ @@ -1149,51 +1149,51 @@ OuterZip::SetExtension(const char* ext) DIError OuterZip::LocalFileHeader::Read(GenericFD* pGFD) { - DIError dierr = kDIErrNone; - unsigned char buf[kLFHLen]; + DIError dierr = kDIErrNone; + unsigned char buf[kLFHLen]; - dierr = pGFD->Read(buf, kLFHLen); - if (dierr != kDIErrNone) - goto bail; + dierr = pGFD->Read(buf, kLFHLen); + if (dierr != kDIErrNone) + goto bail; - if (GetLongLE(&buf[0x00]) != kSignature) { - WMSG0(" ZIP: whoops: didn't find expected signature\n"); - assert(false); - return kDIErrGeneric; - } + if (GetLongLE(&buf[0x00]) != kSignature) { + WMSG0(" ZIP: whoops: didn't find expected signature\n"); + assert(false); + return kDIErrGeneric; + } - fVersionToExtract = GetShortLE(&buf[0x04]); - fGPBitFlag = GetShortLE(&buf[0x06]); - fCompressionMethod = GetShortLE(&buf[0x08]); - fLastModFileTime = GetShortLE(&buf[0x0a]); - fLastModFileDate = GetShortLE(&buf[0x0c]); - fCRC32 = GetLongLE(&buf[0x0e]); - fCompressedSize = GetLongLE(&buf[0x12]); - fUncompressedSize = GetLongLE(&buf[0x16]); - fFileNameLength = GetShortLE(&buf[0x1a]); - fExtraFieldLength = GetShortLE(&buf[0x1c]); + fVersionToExtract = GetShortLE(&buf[0x04]); + fGPBitFlag = GetShortLE(&buf[0x06]); + fCompressionMethod = GetShortLE(&buf[0x08]); + fLastModFileTime = GetShortLE(&buf[0x0a]); + fLastModFileDate = GetShortLE(&buf[0x0c]); + fCRC32 = GetLongLE(&buf[0x0e]); + fCompressedSize = GetLongLE(&buf[0x12]); + fUncompressedSize = GetLongLE(&buf[0x16]); + fFileNameLength = GetShortLE(&buf[0x1a]); + fExtraFieldLength = GetShortLE(&buf[0x1c]); - /* grab filename */ - if (fFileNameLength != 0) { - assert(fFileName == nil); - fFileName = new unsigned char[fFileNameLength+1]; - if (fFileName == nil) { - dierr = kDIErrMalloc; - goto bail; - } else { - dierr = pGFD->Read(fFileName, fFileNameLength); - fFileName[fFileNameLength] = '\0'; - } - if (dierr != kDIErrNone) - goto bail; - } + /* grab filename */ + if (fFileNameLength != 0) { + assert(fFileName == nil); + fFileName = new unsigned char[fFileNameLength+1]; + if (fFileName == nil) { + dierr = kDIErrMalloc; + goto bail; + } else { + dierr = pGFD->Read(fFileName, fFileNameLength); + fFileName[fFileNameLength] = '\0'; + } + if (dierr != kDIErrNone) + goto bail; + } - dierr = pGFD->Seek(fExtraFieldLength, kSeekCur); - if (dierr != kDIErrNone) - goto bail; + dierr = pGFD->Seek(fExtraFieldLength, kSeekCur); + if (dierr != kDIErrNone) + goto bail; bail: - return dierr; + return dierr; } /* @@ -1202,35 +1202,35 @@ bail: DIError OuterZip::LocalFileHeader::Write(GenericFD* pGFD) { - DIError dierr = kDIErrNone; - unsigned char buf[kLFHLen]; + DIError dierr = kDIErrNone; + unsigned char buf[kLFHLen]; - PutLongLE(&buf[0x00], kSignature); - PutShortLE(&buf[0x04], fVersionToExtract); - PutShortLE(&buf[0x06], fGPBitFlag); - PutShortLE(&buf[0x08], fCompressionMethod); - PutShortLE(&buf[0x0a], fLastModFileTime); - PutShortLE(&buf[0x0c], fLastModFileDate); - PutLongLE(&buf[0x0e], fCRC32); - PutLongLE(&buf[0x12], fCompressedSize); - PutLongLE(&buf[0x16], fUncompressedSize); - PutShortLE(&buf[0x1a], fFileNameLength); - PutShortLE(&buf[0x1c], fExtraFieldLength); + PutLongLE(&buf[0x00], kSignature); + PutShortLE(&buf[0x04], fVersionToExtract); + PutShortLE(&buf[0x06], fGPBitFlag); + PutShortLE(&buf[0x08], fCompressionMethod); + PutShortLE(&buf[0x0a], fLastModFileTime); + PutShortLE(&buf[0x0c], fLastModFileDate); + PutLongLE(&buf[0x0e], fCRC32); + PutLongLE(&buf[0x12], fCompressedSize); + PutLongLE(&buf[0x16], fUncompressedSize); + PutShortLE(&buf[0x1a], fFileNameLength); + PutShortLE(&buf[0x1c], fExtraFieldLength); - dierr = pGFD->Write(buf, kLFHLen); - if (dierr != kDIErrNone) - goto bail; + dierr = pGFD->Write(buf, kLFHLen); + if (dierr != kDIErrNone) + goto bail; - /* write filename */ - if (fFileNameLength != 0) { - dierr = pGFD->Write(fFileName, fFileNameLength); - if (dierr != kDIErrNone) - goto bail; - } - assert(fExtraFieldLength == 0); + /* write filename */ + if (fFileNameLength != 0) { + dierr = pGFD->Write(fFileName, fFileNameLength); + if (dierr != kDIErrNone) + goto bail; + } + assert(fExtraFieldLength == 0); bail: - return dierr; + return dierr; } /* @@ -1239,23 +1239,23 @@ bail: void OuterZip::LocalFileHeader::SetFileName(const char* name) { - delete[] fFileName; - fFileName = nil; - fFileNameLength = 0; + delete[] fFileName; + fFileName = nil; + fFileNameLength = 0; - if (name != nil) { - fFileNameLength = strlen(name); - fFileName = new unsigned char[fFileNameLength+1]; - if (fFileName == nil) { - WMSG1("Malloc failure in SetFileName %u\n", fFileNameLength); - fFileName = nil; - fFileNameLength = 0; - } else { - memcpy(fFileName, name, fFileNameLength); - fFileName[fFileNameLength] = '\0'; - WMSG1("+++ OuterZip LFH filename set to '%s'\n", fFileName); - } - } + if (name != nil) { + fFileNameLength = strlen(name); + fFileName = new unsigned char[fFileNameLength+1]; + if (fFileName == nil) { + WMSG1("Malloc failure in SetFileName %u\n", fFileNameLength); + fFileName = nil; + fFileNameLength = 0; + } else { + memcpy(fFileName, name, fFileNameLength); + fFileName[fFileNameLength] = '\0'; + WMSG1("+++ OuterZip LFH filename set to '%s'\n", fFileName); + } + } } /* @@ -1264,21 +1264,21 @@ OuterZip::LocalFileHeader::SetFileName(const char* name) void OuterZip::LocalFileHeader::Dump(void) const { - WMSG0(" LocalFileHeader contents:\n"); - WMSG3(" versToExt=%u gpBits=0x%04x compression=%u\n", - fVersionToExtract, fGPBitFlag, fCompressionMethod); - WMSG3(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n", - fLastModFileTime, fLastModFileDate, fCRC32); - WMSG2(" compressedSize=%lu uncompressedSize=%lu\n", - fCompressedSize, fUncompressedSize); - WMSG2(" filenameLen=%u extraLen=%u\n", - fFileNameLength, fExtraFieldLength); + WMSG0(" LocalFileHeader contents:\n"); + WMSG3(" versToExt=%u gpBits=0x%04x compression=%u\n", + fVersionToExtract, fGPBitFlag, fCompressionMethod); + WMSG3(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n", + fLastModFileTime, fLastModFileDate, fCRC32); + WMSG2(" compressedSize=%lu uncompressedSize=%lu\n", + fCompressedSize, fUncompressedSize); + WMSG2(" filenameLen=%u extraLen=%u\n", + fFileNameLength, fExtraFieldLength); } /* * =================================== - * OuterZip::CentralDirEntry + * OuterZip::CentralDirEntry * =================================== */ @@ -1292,73 +1292,73 @@ OuterZip::LocalFileHeader::Dump(void) const DIError OuterZip::CentralDirEntry::Read(GenericFD* pGFD) { - DIError dierr = kDIErrNone; - unsigned char buf[kCDELen]; + DIError dierr = kDIErrNone; + unsigned char buf[kCDELen]; - dierr = pGFD->Read(buf, kCDELen); - if (dierr != kDIErrNone) - goto bail; + dierr = pGFD->Read(buf, kCDELen); + if (dierr != kDIErrNone) + goto bail; - if (GetLongLE(&buf[0x00]) != kSignature) { - WMSG0(" ZIP: whoops: didn't find expected signature\n"); - assert(false); - return kDIErrGeneric; - } + if (GetLongLE(&buf[0x00]) != kSignature) { + WMSG0(" ZIP: whoops: didn't find expected signature\n"); + assert(false); + return kDIErrGeneric; + } - fVersionMadeBy = GetShortLE(&buf[0x04]); - fVersionToExtract = GetShortLE(&buf[0x06]); - fGPBitFlag = GetShortLE(&buf[0x08]); - fCompressionMethod = GetShortLE(&buf[0x0a]); - fLastModFileTime = GetShortLE(&buf[0x0c]); - fLastModFileDate = GetShortLE(&buf[0x0e]); - fCRC32 = GetLongLE(&buf[0x10]); - fCompressedSize = GetLongLE(&buf[0x14]); - fUncompressedSize = GetLongLE(&buf[0x18]); - fFileNameLength = GetShortLE(&buf[0x1c]); - fExtraFieldLength = GetShortLE(&buf[0x1e]); - fFileCommentLength = GetShortLE(&buf[0x20]); - fDiskNumberStart = GetShortLE(&buf[0x22]); - fInternalAttrs = GetShortLE(&buf[0x24]); - fExternalAttrs = GetLongLE(&buf[0x26]); - fLocalHeaderRelOffset = GetLongLE(&buf[0x2a]); + fVersionMadeBy = GetShortLE(&buf[0x04]); + fVersionToExtract = GetShortLE(&buf[0x06]); + fGPBitFlag = GetShortLE(&buf[0x08]); + fCompressionMethod = GetShortLE(&buf[0x0a]); + fLastModFileTime = GetShortLE(&buf[0x0c]); + fLastModFileDate = GetShortLE(&buf[0x0e]); + fCRC32 = GetLongLE(&buf[0x10]); + fCompressedSize = GetLongLE(&buf[0x14]); + fUncompressedSize = GetLongLE(&buf[0x18]); + fFileNameLength = GetShortLE(&buf[0x1c]); + fExtraFieldLength = GetShortLE(&buf[0x1e]); + fFileCommentLength = GetShortLE(&buf[0x20]); + fDiskNumberStart = GetShortLE(&buf[0x22]); + fInternalAttrs = GetShortLE(&buf[0x24]); + fExternalAttrs = GetLongLE(&buf[0x26]); + fLocalHeaderRelOffset = GetLongLE(&buf[0x2a]); - /* grab filename */ - if (fFileNameLength != 0) { - assert(fFileName == nil); - fFileName = new unsigned char[fFileNameLength+1]; - if (fFileName == nil) { - dierr = kDIErrMalloc; - goto bail; - } else { - dierr = pGFD->Read(fFileName, fFileNameLength); - fFileName[fFileNameLength] = '\0'; - } - if (dierr != kDIErrNone) - goto bail; - } + /* grab filename */ + if (fFileNameLength != 0) { + assert(fFileName == nil); + fFileName = new unsigned char[fFileNameLength+1]; + if (fFileName == nil) { + dierr = kDIErrMalloc; + goto bail; + } else { + dierr = pGFD->Read(fFileName, fFileNameLength); + fFileName[fFileNameLength] = '\0'; + } + if (dierr != kDIErrNone) + goto bail; + } - /* skip over "extra field" */ - dierr = pGFD->Seek(fExtraFieldLength, kSeekCur); - if (dierr != kDIErrNone) - goto bail; + /* skip over "extra field" */ + dierr = pGFD->Seek(fExtraFieldLength, kSeekCur); + if (dierr != kDIErrNone) + goto bail; - /* grab comment, if any */ - if (fFileCommentLength != 0) { - assert(fFileComment == nil); - fFileComment = new unsigned char[fFileCommentLength+1]; - if (fFileComment == nil) { - dierr = kDIErrMalloc; - goto bail; - } else { - dierr = pGFD->Read(fFileComment, fFileCommentLength); - fFileComment[fFileCommentLength] = '\0'; - } - if (dierr != kDIErrNone) - goto bail; - } + /* grab comment, if any */ + if (fFileCommentLength != 0) { + assert(fFileComment == nil); + fFileComment = new unsigned char[fFileCommentLength+1]; + if (fFileComment == nil) { + dierr = kDIErrMalloc; + goto bail; + } else { + dierr = pGFD->Read(fFileComment, fFileCommentLength); + fFileComment[fFileCommentLength] = '\0'; + } + if (dierr != kDIErrNone) + goto bail; + } bail: - return dierr; + return dierr; } /* @@ -1367,42 +1367,42 @@ bail: DIError OuterZip::CentralDirEntry::Write(GenericFD* pGFD) { - DIError dierr = kDIErrNone; - unsigned char buf[kCDELen]; + DIError dierr = kDIErrNone; + unsigned char buf[kCDELen]; - PutLongLE(&buf[0x00], kSignature); - PutShortLE(&buf[0x04], fVersionMadeBy); - PutShortLE(&buf[0x06], fVersionToExtract); - PutShortLE(&buf[0x08], fGPBitFlag); - PutShortLE(&buf[0x0a], fCompressionMethod); - PutShortLE(&buf[0x0c], fLastModFileTime); - PutShortLE(&buf[0x0e], fLastModFileDate); - PutLongLE(&buf[0x10], fCRC32); - PutLongLE(&buf[0x14], fCompressedSize); - PutLongLE(&buf[0x18], fUncompressedSize); - PutShortLE(&buf[0x1c], fFileNameLength); - PutShortLE(&buf[0x1e], fExtraFieldLength); - PutShortLE(&buf[0x20], fFileCommentLength); - PutShortLE(&buf[0x22], fDiskNumberStart); - PutShortLE(&buf[0x24], fInternalAttrs); - PutLongLE(&buf[0x26], fExternalAttrs); - PutLongLE(&buf[0x2a], fLocalHeaderRelOffset); + PutLongLE(&buf[0x00], kSignature); + PutShortLE(&buf[0x04], fVersionMadeBy); + PutShortLE(&buf[0x06], fVersionToExtract); + PutShortLE(&buf[0x08], fGPBitFlag); + PutShortLE(&buf[0x0a], fCompressionMethod); + PutShortLE(&buf[0x0c], fLastModFileTime); + PutShortLE(&buf[0x0e], fLastModFileDate); + PutLongLE(&buf[0x10], fCRC32); + PutLongLE(&buf[0x14], fCompressedSize); + PutLongLE(&buf[0x18], fUncompressedSize); + PutShortLE(&buf[0x1c], fFileNameLength); + PutShortLE(&buf[0x1e], fExtraFieldLength); + PutShortLE(&buf[0x20], fFileCommentLength); + PutShortLE(&buf[0x22], fDiskNumberStart); + PutShortLE(&buf[0x24], fInternalAttrs); + PutLongLE(&buf[0x26], fExternalAttrs); + PutLongLE(&buf[0x2a], fLocalHeaderRelOffset); - dierr = pGFD->Write(buf, kCDELen); - if (dierr != kDIErrNone) - goto bail; + dierr = pGFD->Write(buf, kCDELen); + if (dierr != kDIErrNone) + goto bail; - /* write filename */ - if (fFileNameLength != 0) { - dierr = pGFD->Write(fFileName, fFileNameLength); - if (dierr != kDIErrNone) - goto bail; - } - assert(fExtraFieldLength == 0); - assert(fFileCommentLength == 0); + /* write filename */ + if (fFileNameLength != 0) { + dierr = pGFD->Write(fFileName, fFileNameLength); + if (dierr != kDIErrNone) + goto bail; + } + assert(fExtraFieldLength == 0); + assert(fFileCommentLength == 0); bail: - return dierr; + return dierr; } /* @@ -1411,23 +1411,23 @@ bail: void OuterZip::CentralDirEntry::SetFileName(const char* name) { - delete[] fFileName; - fFileName = nil; - fFileNameLength = 0; + delete[] fFileName; + fFileName = nil; + fFileNameLength = 0; - if (name != nil) { - fFileNameLength = strlen(name); - fFileName = new unsigned char[fFileNameLength+1]; - if (fFileName == nil) { - WMSG1("Malloc failure in SetFileName %u\n", fFileNameLength); - fFileName = nil; - fFileNameLength = 0; - } else { - memcpy(fFileName, name, fFileNameLength); - fFileName[fFileNameLength] = '\0'; - WMSG1("+++ OuterZip CDE filename set to '%s'\n", fFileName); - } - } + if (name != nil) { + fFileNameLength = strlen(name); + fFileName = new unsigned char[fFileNameLength+1]; + if (fFileName == nil) { + WMSG1("Malloc failure in SetFileName %u\n", fFileNameLength); + fFileName = nil; + fFileNameLength = 0; + } else { + memcpy(fFileName, name, fFileNameLength); + fFileName[fFileNameLength] = '\0'; + WMSG1("+++ OuterZip CDE filename set to '%s'\n", fFileName); + } + } } @@ -1437,31 +1437,31 @@ OuterZip::CentralDirEntry::SetFileName(const char* name) void OuterZip::CentralDirEntry::Dump(void) const { - WMSG0(" CentralDirEntry contents:\n"); - WMSG4(" versMadeBy=%u versToExt=%u gpBits=0x%04x compression=%u\n", - fVersionMadeBy, fVersionToExtract, fGPBitFlag, fCompressionMethod); - WMSG3(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n", - fLastModFileTime, fLastModFileDate, fCRC32); - WMSG2(" compressedSize=%lu uncompressedSize=%lu\n", - fCompressedSize, fUncompressedSize); - WMSG3(" filenameLen=%u extraLen=%u commentLen=%u\n", - fFileNameLength, fExtraFieldLength, fFileCommentLength); - WMSG4(" diskNumStart=%u intAttr=0x%04x extAttr=0x%08lx relOffset=%lu\n", - fDiskNumberStart, fInternalAttrs, fExternalAttrs, - fLocalHeaderRelOffset); + WMSG0(" CentralDirEntry contents:\n"); + WMSG4(" versMadeBy=%u versToExt=%u gpBits=0x%04x compression=%u\n", + fVersionMadeBy, fVersionToExtract, fGPBitFlag, fCompressionMethod); + WMSG3(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n", + fLastModFileTime, fLastModFileDate, fCRC32); + WMSG2(" compressedSize=%lu uncompressedSize=%lu\n", + fCompressedSize, fUncompressedSize); + WMSG3(" filenameLen=%u extraLen=%u commentLen=%u\n", + fFileNameLength, fExtraFieldLength, fFileCommentLength); + WMSG4(" diskNumStart=%u intAttr=0x%04x extAttr=0x%08lx relOffset=%lu\n", + fDiskNumberStart, fInternalAttrs, fExternalAttrs, + fLocalHeaderRelOffset); - if (fFileName != nil) { - WMSG1(" filename: '%s'\n", fFileName); - } - if (fFileComment != nil) { - WMSG1(" comment: '%s'\n", fFileComment); - } + if (fFileName != nil) { + WMSG1(" filename: '%s'\n", fFileName); + } + if (fFileComment != nil) { + WMSG1(" comment: '%s'\n", fFileComment); + } } /* * =================================== - * OuterZip::EndOfCentralDir + * OuterZip::EndOfCentralDir * =================================== */ @@ -1473,25 +1473,25 @@ OuterZip::CentralDirEntry::Dump(void) const DIError OuterZip::EndOfCentralDir::ReadBuf(const unsigned char* buf, int len) { - if (len < kEOCDLen) { - /* looks like ZIP file got truncated */ - WMSG2(" Zip EOCD: expected >= %d bytes, found %d\n", - kEOCDLen, len); - return kDIErrBadArchiveStruct; - } + if (len < kEOCDLen) { + /* looks like ZIP file got truncated */ + WMSG2(" Zip EOCD: expected >= %d bytes, found %d\n", + kEOCDLen, len); + return kDIErrBadArchiveStruct; + } - if (GetLongLE(&buf[0x00]) != kSignature) - return kDIErrInternal; + if (GetLongLE(&buf[0x00]) != kSignature) + return kDIErrInternal; - fDiskNumber = GetShortLE(&buf[0x04]); - fDiskWithCentralDir = GetShortLE(&buf[0x06]); - fNumEntries = GetShortLE(&buf[0x08]); - fTotalNumEntries = GetShortLE(&buf[0x0a]); - fCentralDirSize = GetLongLE(&buf[0x0c]); - fCentralDirOffset = GetLongLE(&buf[0x10]); - fCommentLen = GetShortLE(&buf[0x14]); + fDiskNumber = GetShortLE(&buf[0x04]); + fDiskWithCentralDir = GetShortLE(&buf[0x06]); + fNumEntries = GetShortLE(&buf[0x08]); + fTotalNumEntries = GetShortLE(&buf[0x0a]); + fCentralDirSize = GetLongLE(&buf[0x0c]); + fCentralDirOffset = GetLongLE(&buf[0x10]); + fCommentLen = GetShortLE(&buf[0x14]); - return kDIErrNone; + return kDIErrNone; } /* @@ -1500,26 +1500,26 @@ OuterZip::EndOfCentralDir::ReadBuf(const unsigned char* buf, int len) DIError OuterZip::EndOfCentralDir::Write(GenericFD* pGFD) { - DIError dierr = kDIErrNone; - unsigned char buf[kEOCDLen]; + DIError dierr = kDIErrNone; + unsigned char buf[kEOCDLen]; - PutLongLE(&buf[0x00], kSignature); - PutShortLE(&buf[0x04], fDiskNumber); - PutShortLE(&buf[0x06], fDiskWithCentralDir); - PutShortLE(&buf[0x08], fNumEntries); - PutShortLE(&buf[0x0a], fTotalNumEntries); - PutLongLE(&buf[0x0c], fCentralDirSize); - PutLongLE(&buf[0x10], fCentralDirOffset); - PutShortLE(&buf[0x14], fCommentLen); + PutLongLE(&buf[0x00], kSignature); + PutShortLE(&buf[0x04], fDiskNumber); + PutShortLE(&buf[0x06], fDiskWithCentralDir); + PutShortLE(&buf[0x08], fNumEntries); + PutShortLE(&buf[0x0a], fTotalNumEntries); + PutLongLE(&buf[0x0c], fCentralDirSize); + PutLongLE(&buf[0x10], fCentralDirOffset); + PutShortLE(&buf[0x14], fCommentLen); - dierr = pGFD->Write(buf, kEOCDLen); - if (dierr != kDIErrNone) - goto bail; + dierr = pGFD->Write(buf, kEOCDLen); + if (dierr != kDIErrNone) + goto bail; - assert(fCommentLen == 0); + assert(fCommentLen == 0); bail: - return dierr; + return dierr; } /* * Dump the contents of an EndOfCentralDir object. @@ -1527,9 +1527,9 @@ bail: void OuterZip::EndOfCentralDir::Dump(void) const { - WMSG0(" EndOfCentralDir contents:\n"); - WMSG4(" diskNum=%u diskWCD=%u numEnt=%u totalNumEnt=%u\n", - fDiskNumber, fDiskWithCentralDir, fNumEntries, fTotalNumEntries); - WMSG3(" centDirSize=%lu centDirOff=%lu commentLen=%u\n", - fCentralDirSize, fCentralDirOffset, fCommentLen); + WMSG0(" EndOfCentralDir contents:\n"); + WMSG4(" diskNum=%u diskWCD=%u numEnt=%u totalNumEnt=%u\n", + fDiskNumber, fDiskWithCentralDir, fNumEntries, fTotalNumEntries); + WMSG3(" centDirSize=%lu centDirOff=%lu commentLen=%u\n", + fCentralDirSize, fCentralDirOffset, fCommentLen); } diff --git a/diskimg/OzDOS.cpp b/diskimg/OzDOS.cpp index 837089d..1936d8a 100644 --- a/diskimg/OzDOS.cpp +++ b/diskimg/OzDOS.cpp @@ -16,21 +16,21 @@ /* * =========================================================================== - * DiskFSOzDOS + * DiskFSOzDOS * =========================================================================== */ const int kExpectedNumBlocks = 1600; -const int kExpectedTracks = 50; // 50 tracks of 32 sectors == 400K +const int kExpectedTracks = 50; // 50 tracks of 32 sectors == 400K const int kExpectedSectors = 32; const int kVTOCTrack = 17; const int kVTOCSector = 0; const int kSctSize = 256; -const int kCatalogEntrySize = 0x23; // length in bytes of catalog entries -const int kCatalogEntriesPerSect = 7; // #of entries per catalog sector -const int kMaxTSPairs = 0x7a; // 122 entries for 256-byte sectors -const int kTSOffset = 0x0c; // first T/S entry in a T/S list +const int kCatalogEntrySize = 0x23; // length in bytes of catalog entries +const int kCatalogEntriesPerSect = 7; // #of entries per catalog sector +const int kMaxTSPairs = 0x7a; // 122 entries for 256-byte sectors +const int kTSOffset = 0x0c; // first T/S entry in a T/S list const int kMaxTSIterations = 32; const int kMaxCatalogIterations = 64; @@ -42,16 +42,16 @@ const int kMaxCatalogIterations = 64; */ static DIError ReadTrackSectorAdjusted(DiskImg* pImg, int track, int sector, - int sectorOffset, unsigned char* buf, DiskImg::SectorOrder imageOrder) + int sectorOffset, unsigned char* buf, DiskImg::SectorOrder imageOrder) { - track *= 4; - sector = sector * 2 + sectorOffset; - while (sector >= 16) { - track++; - sector -= 16; - } - return pImg->ReadTrackSectorSwapped(track, sector, buf, imageOrder, - DiskImg::kSectorOrderDOS); + track *= 4; + sector = sector * 2 + sectorOffset; + while (sector >= 16) { + track++; + sector -= 16; + } + return pImg->ReadTrackSectorSwapped(track, sector, buf, imageOrder, + DiskImg::kSectorOrderDOS); } /* @@ -60,70 +60,70 @@ ReadTrackSectorAdjusted(DiskImg* pImg, int track, int sector, static DIError TestImageHalf(DiskImg* pImg, int sectorOffset, DiskImg::SectorOrder imageOrder) { - DIError dierr = kDIErrNone; - unsigned char sctBuf[kSctSize]; - int numTracks, numSectors; - int catTrack, catSect; - int foundGood = 0; - int iterations = 0; + DIError dierr = kDIErrNone; + unsigned char sctBuf[kSctSize]; + int numTracks, numSectors; + int catTrack, catSect; + int foundGood = 0; + int iterations = 0; - assert(sectorOffset == 0 || sectorOffset == 1); + assert(sectorOffset == 0 || sectorOffset == 1); - dierr = ReadTrackSectorAdjusted(pImg, kVTOCTrack, kVTOCSector, - sectorOffset, sctBuf, imageOrder); - if (dierr != kDIErrNone) - goto bail; + dierr = ReadTrackSectorAdjusted(pImg, kVTOCTrack, kVTOCSector, + sectorOffset, sctBuf, imageOrder); + if (dierr != kDIErrNone) + goto bail; - catTrack = sctBuf[0x01]; - catSect = sctBuf[0x02]; - numTracks = sctBuf[0x34]; - numSectors = sctBuf[0x35]; + catTrack = sctBuf[0x01]; + catSect = sctBuf[0x02]; + numTracks = sctBuf[0x34]; + numSectors = sctBuf[0x35]; - if (!(sctBuf[0x27] == kMaxTSPairs) || - /*!(sctBuf[0x36] == 0 && sctBuf[0x37] == 1) ||*/ // bytes per sect - !(numTracks == kExpectedTracks) || - !(numSectors == 32) || - !(catTrack < numTracks && catSect < numSectors) || - 0) - { - WMSG1(" OzDOS header test %d failed\n", sectorOffset); - dierr = kDIErrFilesystemNotFound; - goto bail; - } + if (!(sctBuf[0x27] == kMaxTSPairs) || + /*!(sctBuf[0x36] == 0 && sctBuf[0x37] == 1) ||*/ // bytes per sect + !(numTracks == kExpectedTracks) || + !(numSectors == 32) || + !(catTrack < numTracks && catSect < numSectors) || + 0) + { + WMSG1(" OzDOS header test %d failed\n", sectorOffset); + dierr = kDIErrFilesystemNotFound; + goto bail; + } - /* - * Walk through the catalog track to try to figure out ordering. - */ - while (catTrack != 0 && catSect != 0 && iterations < kMaxCatalogIterations) - { - dierr = ReadTrackSectorAdjusted(pImg, catTrack, catSect, - sectorOffset, sctBuf, imageOrder); - if (dierr != kDIErrNone) - goto bail_ok; /* allow it if not fully broken */ + /* + * Walk through the catalog track to try to figure out ordering. + */ + while (catTrack != 0 && catSect != 0 && iterations < kMaxCatalogIterations) + { + dierr = ReadTrackSectorAdjusted(pImg, catTrack, catSect, + sectorOffset, sctBuf, imageOrder); + if (dierr != kDIErrNone) + goto bail_ok; /* allow it if not fully broken */ - if (sctBuf[1] == catTrack && sctBuf[2] == catSect-1) - foundGood++; + if (sctBuf[1] == catTrack && sctBuf[2] == catSect-1) + foundGood++; - catTrack = sctBuf[1]; - catSect = sctBuf[2]; - iterations++; // watch for infinite loops - } - if (iterations >= kMaxCatalogIterations) { - dierr = kDIErrDirectoryLoop; - goto bail; - } + catTrack = sctBuf[1]; + catSect = sctBuf[2]; + iterations++; // watch for infinite loops + } + if (iterations >= kMaxCatalogIterations) { + dierr = kDIErrDirectoryLoop; + goto bail; + } bail_ok: - WMSG3(" OzDOS foundGood=%d off=%d swap=%d\n", foundGood, sectorOffset, - imageOrder); - /* foundGood hits 3 even when swap is wrong */ - if (foundGood > 4) - dierr = kDIErrNone; - else - dierr = kDIErrFilesystemNotFound; + WMSG3(" OzDOS foundGood=%d off=%d swap=%d\n", foundGood, sectorOffset, + imageOrder); + /* foundGood hits 3 even when swap is wrong */ + if (foundGood > 4) + dierr = kDIErrNone; + else + dierr = kDIErrFilesystemNotFound; bail: - return dierr; + return dierr; } /* @@ -132,19 +132,19 @@ bail: static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder) { - DIError dierr; + DIError dierr; - WMSG1(" OzDOS checking first half (swap=%d)\n", imageOrder); - dierr = TestImageHalf(pImg, 0, imageOrder); - if (dierr != kDIErrNone) - return dierr; + WMSG1(" OzDOS checking first half (swap=%d)\n", imageOrder); + dierr = TestImageHalf(pImg, 0, imageOrder); + if (dierr != kDIErrNone) + return dierr; - WMSG1(" OzDOS checking second half (swap=%d)\n", imageOrder); - dierr = TestImageHalf(pImg, 1, imageOrder); - if (dierr != kDIErrNone) - return dierr; + WMSG1(" OzDOS checking second half (swap=%d)\n", imageOrder); + dierr = TestImageHalf(pImg, 1, imageOrder); + if (dierr != kDIErrNone) + return dierr; - return kDIErrNone; + return kDIErrNone; } /* @@ -154,34 +154,34 @@ TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder) DiskFSOzDOS::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DiskImg::FSFormat* pFormat, FSLeniency leniency) { - /* only on 800K disks (at the least, insist on numTracks being even) */ - if (pImg->GetNumBlocks() != kExpectedNumBlocks) - return kDIErrFilesystemNotFound; + /* only on 800K disks (at the least, insist on numTracks being even) */ + if (pImg->GetNumBlocks() != kExpectedNumBlocks) + return kDIErrFilesystemNotFound; - /* if a value is specified, try that first -- useful for OverrideFormat */ - if (*pOrder != DiskImg::kSectorOrderUnknown) { - if (TestImage(pImg, *pOrder) == kDIErrNone) { - WMSG0(" OzDOS accepted FirstTry value\n"); - return kDIErrNone; - } - } + /* if a value is specified, try that first -- useful for OverrideFormat */ + if (*pOrder != DiskImg::kSectorOrderUnknown) { + if (TestImage(pImg, *pOrder) == kDIErrNone) { + WMSG0(" OzDOS accepted FirstTry value\n"); + return kDIErrNone; + } + } - DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; - - DiskImg::GetSectorOrderArray(ordering, *pOrder); + DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; + + DiskImg::GetSectorOrderArray(ordering, *pOrder); - for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { - if (ordering[i] == DiskImg::kSectorOrderUnknown) - continue; - if (TestImage(pImg, ordering[i]) == kDIErrNone) { - *pOrder = ordering[i]; - *pFormat = DiskImg::kFormatOzDOS; - return kDIErrNone; - } - } + for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { + if (ordering[i] == DiskImg::kSectorOrderUnknown) + continue; + if (TestImage(pImg, ordering[i]) == kDIErrNone) { + *pOrder = ordering[i]; + *pFormat = DiskImg::kFormatOzDOS; + return kDIErrNone; + } + } - WMSG0(" OzDOS didn't find valid FS\n"); - return kDIErrFilesystemNotFound; + WMSG0(" OzDOS didn't find valid FS\n"); + return kDIErrFilesystemNotFound; } #if 0 @@ -192,32 +192,32 @@ DiskFSOzDOS::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, /*static*/ DIError DiskFS::TestOzWideDOS33(const DiskImg* pImg, DiskImg::SectorOrder* pOrder) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - /* only on 400K disks (at the least, insist on numTracks being even) */ - if (pImg->GetNumBlocks() != kExpectedNumBlocks/2) - return kDIErrFilesystemNotFound; + /* only on 400K disks (at the least, insist on numTracks being even) */ + if (pImg->GetNumBlocks() != kExpectedNumBlocks/2) + return kDIErrFilesystemNotFound; - /* if a value is specified, try that first -- useful for OverrideFormat */ - if (*pOrder != DiskImg::kSectorOrderUnknown) { - if (TestImageHalf(pImg, 0, *pOrder) == kDIErrNone) { - WMSG0(" WideDOS accepted FirstTry value\n"); - return kDIErrNone; - } - } + /* if a value is specified, try that first -- useful for OverrideFormat */ + if (*pOrder != DiskImg::kSectorOrderUnknown) { + if (TestImageHalf(pImg, 0, *pOrder) == kDIErrNone) { + WMSG0(" WideDOS accepted FirstTry value\n"); + return kDIErrNone; + } + } - if (TestImageHalf(pImg, 0, DiskImg::kSectorOrderDOS) == kDIErrNone) { - *pOrder = DiskImg::kSectorOrderDOS; - } else if (TestImageHalf(pImg, 0, DiskImg::kSectorOrderProDOS) == kDIErrNone) { - *pOrder = DiskImg::kSectorOrderProDOS; - } else if (TestImageHalf(pImg, 0, DiskImg::kSectorOrderPhysical) == kDIErrNone) { - *pOrder = DiskImg::kSectorOrderPhysical; - } else { - WMSG0(" FS didn't find valid 'wide' DOS3.3\n"); - return kDIErrFilesystemNotFound; - } + if (TestImageHalf(pImg, 0, DiskImg::kSectorOrderDOS) == kDIErrNone) { + *pOrder = DiskImg::kSectorOrderDOS; + } else if (TestImageHalf(pImg, 0, DiskImg::kSectorOrderProDOS) == kDIErrNone) { + *pOrder = DiskImg::kSectorOrderProDOS; + } else if (TestImageHalf(pImg, 0, DiskImg::kSectorOrderPhysical) == kDIErrNone) { + *pOrder = DiskImg::kSectorOrderPhysical; + } else { + WMSG0(" FS didn't find valid 'wide' DOS3.3\n"); + return kDIErrFilesystemNotFound; + } - return kDIErrNone; + return kDIErrNone; } #endif @@ -227,23 +227,23 @@ DiskFS::TestOzWideDOS33(const DiskImg* pImg, DiskImg::SectorOrder* pOrder) DIError DiskFSOzDOS::Initialize(void) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - if (fScanForSubVolumes != kScanSubDisabled) { - dierr = OpenSubVolume(0); - if (dierr != kDIErrNone) - return dierr; + if (fScanForSubVolumes != kScanSubDisabled) { + dierr = OpenSubVolume(0); + if (dierr != kDIErrNone) + return dierr; - dierr = OpenSubVolume(1); - if (dierr != kDIErrNone) - return dierr; - } else { - WMSG0(" OzDOS not scanning for sub-volumes\n"); - } + dierr = OpenSubVolume(1); + if (dierr != kDIErrNone) + return dierr; + } else { + WMSG0(" OzDOS not scanning for sub-volumes\n"); + } - SetVolumeUsageMap(); + SetVolumeUsageMap(); - return kDIErrNone; + return kDIErrNone; } /* @@ -252,74 +252,74 @@ DiskFSOzDOS::Initialize(void) DIError DiskFSOzDOS::OpenSubVolume(int idx) { - DIError dierr = kDIErrNone; - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; - - pNewImg = new DiskImg; - if (pNewImg == nil) { - dierr = kDIErrMalloc; - goto bail; - } + DIError dierr = kDIErrNone; + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; + + pNewImg = new DiskImg; + if (pNewImg == nil) { + dierr = kDIErrMalloc; + goto bail; + } - // open the full 800K; SetPairedSectors cuts it in half - dierr = pNewImg->OpenImage(fpImg, 0, 0, - 2 * kExpectedTracks * kExpectedSectors); - if (dierr != kDIErrNone) { - WMSG3(" OzSub: OpenImage(%d,0,%d) failed (err=%d)\n", - 0, 2 * kExpectedTracks * kExpectedSectors, dierr); - goto bail; - } + // open the full 800K; SetPairedSectors cuts it in half + dierr = pNewImg->OpenImage(fpImg, 0, 0, + 2 * kExpectedTracks * kExpectedSectors); + if (dierr != kDIErrNone) { + WMSG3(" OzSub: OpenImage(%d,0,%d) failed (err=%d)\n", + 0, 2 * kExpectedTracks * kExpectedSectors, dierr); + goto bail; + } - assert(idx == 0 || idx == 1); - pNewImg->SetPairedSectors(true, 1-idx); + assert(idx == 0 || idx == 1); + pNewImg->SetPairedSectors(true, 1-idx); - WMSG1(" OzSub: testing for recognizable volume in idx=%d\n", idx); - dierr = pNewImg->AnalyzeImage(); - if (dierr != kDIErrNone) { - WMSG1(" OzSub: analysis failed (err=%d)\n", dierr); - goto bail; - } + WMSG1(" OzSub: testing for recognizable volume in idx=%d\n", idx); + dierr = pNewImg->AnalyzeImage(); + if (dierr != kDIErrNone) { + WMSG1(" OzSub: analysis failed (err=%d)\n", dierr); + goto bail; + } - if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || - pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) - { - WMSG0(" OzSub: unable to identify filesystem\n"); - dierr = kDIErrUnsupportedFSFmt; - goto bail; - } + if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || + pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) + { + WMSG0(" OzSub: unable to identify filesystem\n"); + dierr = kDIErrUnsupportedFSFmt; + goto bail; + } - /* open a DiskFS for the sub-image */ - WMSG1(" UNISub %d succeeded!\n", idx); - pNewFS = pNewImg->OpenAppropriateDiskFS(); - if (pNewFS == nil) { - WMSG0(" OzSub: OpenAppropriateDiskFS failed\n"); - dierr = kDIErrUnsupportedFSFmt; - goto bail; - } + /* open a DiskFS for the sub-image */ + WMSG1(" UNISub %d succeeded!\n", idx); + pNewFS = pNewImg->OpenAppropriateDiskFS(); + if (pNewFS == nil) { + WMSG0(" OzSub: OpenAppropriateDiskFS failed\n"); + dierr = kDIErrUnsupportedFSFmt; + goto bail; + } - /* load the files from the sub-image */ - dierr = pNewFS->Initialize(pNewImg, kInitFull); - if (dierr != kDIErrNone) { - WMSG1(" OzSub: error %d reading list of files from disk", dierr); - goto bail; - } + /* load the files from the sub-image */ + dierr = pNewFS->Initialize(pNewImg, kInitFull); + if (dierr != kDIErrNone) { + WMSG1(" OzSub: error %d reading list of files from disk", dierr); + goto bail; + } - /* if this really is DOS 3.3, override the "volume name" */ - if (pNewImg->GetFSFormat() == DiskImg::kFormatDOS33) { - DiskFSDOS33* pDOS = (DiskFSDOS33*) pNewFS; /* eek, a downcast */ - pDOS->SetDiskVolumeNum(idx+1); - } + /* if this really is DOS 3.3, override the "volume name" */ + if (pNewImg->GetFSFormat() == DiskImg::kFormatDOS33) { + DiskFSDOS33* pDOS = (DiskFSDOS33*) pNewFS; /* eek, a downcast */ + pDOS->SetDiskVolumeNum(idx+1); + } - /* - * Success, add it to the sub-volume list. - */ - AddSubVolumeToList(pNewImg, pNewFS); + /* + * Success, add it to the sub-volume list. + */ + AddSubVolumeToList(pNewImg, pNewFS); bail: - if (dierr != kDIErrNone) { - delete pNewFS; - delete pNewImg; - } - return dierr; + if (dierr != kDIErrNone) { + delete pNewFS; + delete pNewImg; + } + return dierr; } diff --git a/diskimg/Pascal.cpp b/diskimg/Pascal.cpp index 63548ae..5cfc677 100644 --- a/diskimg/Pascal.cpp +++ b/diskimg/Pascal.cpp @@ -14,13 +14,13 @@ /* * =========================================================================== - * DiskFSPascal + * DiskFSPascal * =========================================================================== */ const int kBlkSize = 512; -const int kVolHeaderBlock = 2; // first directory block -const int kMaxCatalogIterations = 64; // should be short, linear catalog +const int kVolHeaderBlock = 2; // first directory block +const int kMaxCatalogIterations = 64; // should be short, linear catalog const int kHugeDir = 32; static const char* kInvalidNameChars = "$=?,[#:"; @@ -33,34 +33,34 @@ static const char* kInvalidNameChars = "$=?,[#:"; static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder) { - DIError dierr = kDIErrNone; - unsigned char blkBuf[512]; - unsigned char volName[DiskFSPascal::kMaxVolumeName+1]; + DIError dierr = kDIErrNone; + unsigned char blkBuf[512]; + unsigned char volName[DiskFSPascal::kMaxVolumeName+1]; - dierr = pImg->ReadBlockSwapped(kVolHeaderBlock, blkBuf, imageOrder, - DiskImg::kSectorOrderProDOS); - if (dierr != kDIErrNone) - goto bail; + dierr = pImg->ReadBlockSwapped(kVolHeaderBlock, blkBuf, imageOrder, + DiskImg::kSectorOrderProDOS); + if (dierr != kDIErrNone) + goto bail; - if (!(blkBuf[0x00] == 0 && blkBuf[0x01] == 0) || - !(blkBuf[0x04] == 0 && blkBuf[0x05] == 0) || - !(blkBuf[0x06] > 0 && blkBuf[0x06] <= DiskFSPascal::kMaxVolumeName) || - 0) - { - dierr = kDIErrFilesystemNotFound; - goto bail; - } + if (!(blkBuf[0x00] == 0 && blkBuf[0x01] == 0) || + !(blkBuf[0x04] == 0 && blkBuf[0x05] == 0) || + !(blkBuf[0x06] > 0 && blkBuf[0x06] <= DiskFSPascal::kMaxVolumeName) || + 0) + { + dierr = kDIErrFilesystemNotFound; + goto bail; + } - /* volume name length is good, check the name itself */ - /* (this may be overly restrictive, but it's probably good to be) */ - memset(volName, 0, sizeof(volName)); - memcpy(volName, &blkBuf[0x07], blkBuf[0x06]); - if (!DiskFSPascal::IsValidVolumeName((const char*) volName)) - return kDIErrFilesystemNotFound; + /* volume name length is good, check the name itself */ + /* (this may be overly restrictive, but it's probably good to be) */ + memset(volName, 0, sizeof(volName)); + memcpy(volName, &blkBuf[0x07], blkBuf[0x06]); + if (!DiskFSPascal::IsValidVolumeName((const char*) volName)) + return kDIErrFilesystemNotFound; bail: - return dierr; + return dierr; } /* @@ -70,22 +70,22 @@ bail: DiskFSPascal::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DiskImg::FSFormat* pFormat, FSLeniency leniency) { - DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; - - DiskImg::GetSectorOrderArray(ordering, *pOrder); + DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; + + DiskImg::GetSectorOrderArray(ordering, *pOrder); - for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { - if (ordering[i] == DiskImg::kSectorOrderUnknown) - continue; - if (TestImage(pImg, ordering[i]) == kDIErrNone) { - *pOrder = ordering[i]; - *pFormat = DiskImg::kFormatPascal; - return kDIErrNone; - } - } + for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { + if (ordering[i] == DiskImg::kSectorOrderUnknown) + continue; + if (TestImage(pImg, ordering[i]) == kDIErrNone) { + *pOrder = ordering[i]; + *pFormat = DiskImg::kFormatPascal; + return kDIErrNone; + } + } - WMSG0(" Pascal didn't find valid FS\n"); - return kDIErrFilesystemNotFound; + WMSG0(" Pascal didn't find valid FS\n"); + return kDIErrFilesystemNotFound; } /* @@ -98,41 +98,41 @@ DiskFSPascal::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DIError DiskFSPascal::Initialize(void) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - fDiskIsGood = false; // hosed until proven innocent - fEarlyDamage = false; + fDiskIsGood = false; // hosed until proven innocent + fEarlyDamage = false; - fVolumeUsage.Create(fpImg->GetNumBlocks()); + fVolumeUsage.Create(fpImg->GetNumBlocks()); - dierr = LoadVolHeader(); - if (dierr != kDIErrNone) - goto bail; - DumpVolHeader(); + dierr = LoadVolHeader(); + if (dierr != kDIErrNone) + goto bail; + DumpVolHeader(); - dierr = ProcessCatalog(); - if (dierr != kDIErrNone) - goto bail; + dierr = ProcessCatalog(); + if (dierr != kDIErrNone) + goto bail; - dierr = ScanFileUsage(); - if (dierr != kDIErrNone) { - /* this might not be fatal; just means that *some* files are bad */ - goto bail; - } + dierr = ScanFileUsage(); + if (dierr != kDIErrNone) { + /* this might not be fatal; just means that *some* files are bad */ + goto bail; + } - fDiskIsGood = CheckDiskIsGood(); + fDiskIsGood = CheckDiskIsGood(); - fVolumeUsage.Dump(); + fVolumeUsage.Dump(); - //A2File* pFile; - //pFile = GetNextFile(nil); - //while (pFile != nil) { - // pFile->Dump(); - // pFile = GetNextFile(pFile); - //} + //A2File* pFile; + //pFile = GetNextFile(nil); + //while (pFile != nil) { + // pFile->Dump(); + // pFile = GetNextFile(pFile); + //} bail: - return dierr; + return dierr; } /* @@ -141,58 +141,58 @@ bail: DIError DiskFSPascal::LoadVolHeader(void) { - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; - int nameLen, maxFiles; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; + int nameLen, maxFiles; - dierr = fpImg->ReadBlock(kVolHeaderBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpImg->ReadBlock(kVolHeaderBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; - /* vol header is same size as dir entry, but different layout */ - fStartBlock = GetShortLE(&blkBuf[0x00]); - assert(fStartBlock == 0); // verified in "TestImage" - fNextBlock = GetShortLE(&blkBuf[0x02]); - assert(GetShortLE(&blkBuf[0x04]) == 0); // type - nameLen = blkBuf[0x06] & 0x07; - memcpy(fVolumeName, &blkBuf[0x07], nameLen); - fVolumeName[nameLen] = '\0'; - fTotalBlocks = GetShortLE(&blkBuf[0x0e]); - fNumFiles = GetShortLE(&blkBuf[0x10]); - fAccessWhen = GetShortLE(&blkBuf[0x12]); // time of last access - fDateSetWhen = GetShortLE(&blkBuf[0x14]); // most recent date set - fStuff1 = GetShortLE(&blkBuf[0x16]); // filler - fStuff2 = GetShortLE(&blkBuf[0x18]); // filler + /* vol header is same size as dir entry, but different layout */ + fStartBlock = GetShortLE(&blkBuf[0x00]); + assert(fStartBlock == 0); // verified in "TestImage" + fNextBlock = GetShortLE(&blkBuf[0x02]); + assert(GetShortLE(&blkBuf[0x04]) == 0); // type + nameLen = blkBuf[0x06] & 0x07; + memcpy(fVolumeName, &blkBuf[0x07], nameLen); + fVolumeName[nameLen] = '\0'; + fTotalBlocks = GetShortLE(&blkBuf[0x0e]); + fNumFiles = GetShortLE(&blkBuf[0x10]); + fAccessWhen = GetShortLE(&blkBuf[0x12]); // time of last access + fDateSetWhen = GetShortLE(&blkBuf[0x14]); // most recent date set + fStuff1 = GetShortLE(&blkBuf[0x16]); // filler + fStuff2 = GetShortLE(&blkBuf[0x18]); // filler - if (fTotalBlocks != fpImg->GetNumBlocks()) { - // saw this most recently on a 40-track .APP image; not a problem - WMSG2(" Pascal WARNING: total (%u) != img (%ld)\n", - fTotalBlocks, fpImg->GetNumBlocks()); - } + if (fTotalBlocks != fpImg->GetNumBlocks()) { + // saw this most recently on a 40-track .APP image; not a problem + WMSG2(" Pascal WARNING: total (%u) != img (%ld)\n", + fTotalBlocks, fpImg->GetNumBlocks()); + } - /* - * Sanity checks. - */ - if (fNextBlock > 34) { - // directory really shouldn't be more than 6; I'm being generous - fpImg->AddNote(DiskImg::kNoteWarning, - "Pascal directory is too big (%d blocks); trimming.", - fNextBlock - fStartBlock); - } + /* + * Sanity checks. + */ + if (fNextBlock > 34) { + // directory really shouldn't be more than 6; I'm being generous + fpImg->AddNote(DiskImg::kNoteWarning, + "Pascal directory is too big (%d blocks); trimming.", + fNextBlock - fStartBlock); + } - /* max #of file entries, including the vol dir header */ - maxFiles = ((fNextBlock - kVolHeaderBlock) * kBlkSize) / kDirectoryEntryLen; - if (fNumFiles > maxFiles-1) { - fpImg->AddNote(DiskImg::kNoteWarning, - "Pascal fNumFiles (%d) exceeds max files (%d); trimming.\n", - fNumFiles, maxFiles-1); - fEarlyDamage = true; - } + /* max #of file entries, including the vol dir header */ + maxFiles = ((fNextBlock - kVolHeaderBlock) * kBlkSize) / kDirectoryEntryLen; + if (fNumFiles > maxFiles-1) { + fpImg->AddNote(DiskImg::kNoteWarning, + "Pascal fNumFiles (%d) exceeds max files (%d); trimming.\n", + fNumFiles, maxFiles-1); + fEarlyDamage = true; + } - SetVolumeID(); + SetVolumeID(); bail: - return dierr; + return dierr; } /* @@ -201,7 +201,7 @@ bail: void DiskFSPascal::SetVolumeID(void) { - sprintf(fVolumeID, "Pascal %s:", fVolumeName); + sprintf(fVolumeID, "Pascal %s:", fVolumeName); } /* @@ -210,22 +210,22 @@ DiskFSPascal::SetVolumeID(void) void DiskFSPascal::DumpVolHeader(void) { - time_t access, dateSet; + time_t access, dateSet; - WMSG1(" Pascal volume header for '%s'\n", fVolumeName); - WMSG2(" startBlock=%d nextBlock=%d\n", - fStartBlock, fNextBlock); - WMSG4(" totalBlocks=%d numFiles=%d access=0x%04x dateSet=0x%04x\n", - fTotalBlocks, fNumFiles, fAccessWhen, fDateSetWhen); + WMSG1(" Pascal volume header for '%s'\n", fVolumeName); + WMSG2(" startBlock=%d nextBlock=%d\n", + fStartBlock, fNextBlock); + WMSG4(" totalBlocks=%d numFiles=%d access=0x%04x dateSet=0x%04x\n", + fTotalBlocks, fNumFiles, fAccessWhen, fDateSetWhen); - access = A2FilePascal::ConvertPascalDate(fAccessWhen); - dateSet = A2FilePascal::ConvertPascalDate(fDateSetWhen); - WMSG1(" -->access %.24s\n", ctime(&access)); - WMSG1(" -->dateSet %.24s\n", ctime(&dateSet)); + access = A2FilePascal::ConvertPascalDate(fAccessWhen); + dateSet = A2FilePascal::ConvertPascalDate(fDateSetWhen); + WMSG1(" -->access %.24s\n", ctime(&access)); + WMSG1(" -->dateSet %.24s\n", ctime(&dateSet)); - //WMSG2("Unconvert access=0x%04x dateSet=0x%04x\n", - // A2FilePascal::ConvertPascalDate(access), - // A2FilePascal::ConvertPascalDate(dateSet)); + //WMSG2("Unconvert access=0x%04x dateSet=0x%04x\n", + // A2FilePascal::ConvertPascalDate(access), + // A2FilePascal::ConvertPascalDate(dateSet)); } @@ -240,41 +240,41 @@ DiskFSPascal::DumpVolHeader(void) DIError DiskFSPascal::LoadCatalog(void) { - DIError dierr = kDIErrNone; - unsigned char* dirPtr; - int block, numBlocks; + DIError dierr = kDIErrNone; + unsigned char* dirPtr; + int block, numBlocks; - assert(fDirectory == nil); + assert(fDirectory == nil); - numBlocks = fNextBlock - kVolHeaderBlock; - if (numBlocks <= 0 || numBlocks > kHugeDir) { - dierr = kDIErrBadDiskImage; - goto bail; - } + numBlocks = fNextBlock - kVolHeaderBlock; + if (numBlocks <= 0 || numBlocks > kHugeDir) { + dierr = kDIErrBadDiskImage; + goto bail; + } - fDirectory = new unsigned char[kBlkSize * numBlocks]; - if (fDirectory == nil) { - dierr = kDIErrMalloc; - goto bail; - } + fDirectory = new unsigned char[kBlkSize * numBlocks]; + if (fDirectory == nil) { + dierr = kDIErrMalloc; + goto bail; + } - block = kVolHeaderBlock; - dirPtr = fDirectory; - while (numBlocks--) { - dierr = fpImg->ReadBlock(block, dirPtr); - if (dierr != kDIErrNone) - goto bail; + block = kVolHeaderBlock; + dirPtr = fDirectory; + while (numBlocks--) { + dierr = fpImg->ReadBlock(block, dirPtr); + if (dierr != kDIErrNone) + goto bail; - block++; - dirPtr += kBlkSize; - } + block++; + dirPtr += kBlkSize; + } bail: - if (dierr != kDIErrNone) { - delete[] fDirectory; - fDirectory = nil; - } - return dierr; + if (dierr != kDIErrNone) { + delete[] fDirectory; + fDirectory = nil; + } + return dierr; } /* @@ -283,26 +283,26 @@ bail: DIError DiskFSPascal::SaveCatalog(void) { - DIError dierr = kDIErrNone; - unsigned char* dirPtr; - int block, numBlocks; + DIError dierr = kDIErrNone; + unsigned char* dirPtr; + int block, numBlocks; - assert(fDirectory != nil); + assert(fDirectory != nil); - numBlocks = fNextBlock - kVolHeaderBlock; - block = kVolHeaderBlock; - dirPtr = fDirectory; - while (numBlocks--) { - dierr = fpImg->WriteBlock(block, dirPtr); - if (dierr != kDIErrNone) - goto bail; + numBlocks = fNextBlock - kVolHeaderBlock; + block = kVolHeaderBlock; + dirPtr = fDirectory; + while (numBlocks--) { + dierr = fpImg->WriteBlock(block, dirPtr); + if (dierr != kDIErrNone) + goto bail; - block++; - dirPtr += kBlkSize; - } + block++; + dirPtr += kBlkSize; + } bail: - return dierr; + return dierr; } /* @@ -311,8 +311,8 @@ bail: void DiskFSPascal::FreeCatalog(void) { - delete[] fDirectory; - fDirectory = nil; + delete[] fDirectory; + fDirectory = nil; } @@ -322,75 +322,75 @@ DiskFSPascal::FreeCatalog(void) DIError DiskFSPascal::ProcessCatalog(void) { - DIError dierr = kDIErrNone; - int i, nameLen; - A2FilePascal* pFile; - const unsigned char* dirPtr; - unsigned short prevNextBlock = fNextBlock; + DIError dierr = kDIErrNone; + int i, nameLen; + A2FilePascal* pFile; + const unsigned char* dirPtr; + unsigned short prevNextBlock = fNextBlock; - dierr = LoadCatalog(); - if (dierr != kDIErrNone) - goto bail; + dierr = LoadCatalog(); + if (dierr != kDIErrNone) + goto bail; - dirPtr = fDirectory + kDirectoryEntryLen; // skip vol dir entry - for (i = 0; i < fNumFiles; i++) { - pFile = new A2FilePascal(this); + dirPtr = fDirectory + kDirectoryEntryLen; // skip vol dir entry + for (i = 0; i < fNumFiles; i++) { + pFile = new A2FilePascal(this); - pFile->fStartBlock = GetShortLE(&dirPtr[0x00]); - pFile->fNextBlock = GetShortLE(&dirPtr[0x02]); - pFile->fFileType = (A2FilePascal::FileType) GetShortLE(&dirPtr[0x04]); - nameLen = dirPtr[0x06] & 0x0f; - memcpy(pFile->fFileName, &dirPtr[0x07], nameLen); - pFile->fFileName[nameLen] = '\0'; - pFile->fBytesRemaining = GetShortLE(&dirPtr[0x16]); - pFile->fModWhen = GetShortLE(&dirPtr[0x18]); + pFile->fStartBlock = GetShortLE(&dirPtr[0x00]); + pFile->fNextBlock = GetShortLE(&dirPtr[0x02]); + pFile->fFileType = (A2FilePascal::FileType) GetShortLE(&dirPtr[0x04]); + nameLen = dirPtr[0x06] & 0x0f; + memcpy(pFile->fFileName, &dirPtr[0x07], nameLen); + pFile->fFileName[nameLen] = '\0'; + pFile->fBytesRemaining = GetShortLE(&dirPtr[0x16]); + pFile->fModWhen = GetShortLE(&dirPtr[0x18]); - /* check bytesRem before setting length field */ - if (pFile->fBytesRemaining > kBlkSize) { - WMSG2(" Pascal found strange bytesRem %u on '%s', trimming\n", - pFile->fBytesRemaining, pFile->fFileName); - pFile->fBytesRemaining = kBlkSize; - pFile->SetQuality(A2File::kQualitySuspicious); - } + /* check bytesRem before setting length field */ + if (pFile->fBytesRemaining > kBlkSize) { + WMSG2(" Pascal found strange bytesRem %u on '%s', trimming\n", + pFile->fBytesRemaining, pFile->fFileName); + pFile->fBytesRemaining = kBlkSize; + pFile->SetQuality(A2File::kQualitySuspicious); + } - pFile->fLength = pFile->fBytesRemaining + - (pFile->fNextBlock - pFile->fStartBlock -1) * kBlkSize; + pFile->fLength = pFile->fBytesRemaining + + (pFile->fNextBlock - pFile->fStartBlock -1) * kBlkSize; - /* - * Check values. - */ - if (pFile->fStartBlock == pFile->fNextBlock) { - WMSG1(" Pascal found zero-block file '%s'\n", pFile->fFileName); - pFile->SetQuality(A2File::kQualityDamaged); - } - if (pFile->fStartBlock < prevNextBlock) { - WMSG3(" Pascal start of '%s' (%d) overlaps previous end (%d)\n", - pFile->fFileName, pFile->fStartBlock, prevNextBlock); - pFile->SetQuality(A2File::kQualityDamaged); - } + /* + * Check values. + */ + if (pFile->fStartBlock == pFile->fNextBlock) { + WMSG1(" Pascal found zero-block file '%s'\n", pFile->fFileName); + pFile->SetQuality(A2File::kQualityDamaged); + } + if (pFile->fStartBlock < prevNextBlock) { + WMSG3(" Pascal start of '%s' (%d) overlaps previous end (%d)\n", + pFile->fFileName, pFile->fStartBlock, prevNextBlock); + pFile->SetQuality(A2File::kQualityDamaged); + } - if (pFile->fNextBlock > fpImg->GetNumBlocks()) { - WMSG3(" Pascal invalid 'next' block %d (max %ld) '%s'\n", - pFile->fNextBlock, fpImg->GetNumBlocks(), pFile->fFileName); - pFile->fStartBlock = pFile->fNextBlock = 0; - pFile->fLength = 0; - pFile->SetQuality(A2File::kQualityDamaged); - } else if (pFile->fNextBlock > fTotalBlocks) { - WMSG3(" Pascal 'next' block %d exceeds max (%d) '%s'\n", - pFile->fNextBlock, fTotalBlocks, pFile->fFileName); - pFile->SetQuality(A2File::kQualitySuspicious); - } + if (pFile->fNextBlock > fpImg->GetNumBlocks()) { + WMSG3(" Pascal invalid 'next' block %d (max %ld) '%s'\n", + pFile->fNextBlock, fpImg->GetNumBlocks(), pFile->fFileName); + pFile->fStartBlock = pFile->fNextBlock = 0; + pFile->fLength = 0; + pFile->SetQuality(A2File::kQualityDamaged); + } else if (pFile->fNextBlock > fTotalBlocks) { + WMSG3(" Pascal 'next' block %d exceeds max (%d) '%s'\n", + pFile->fNextBlock, fTotalBlocks, pFile->fFileName); + pFile->SetQuality(A2File::kQualitySuspicious); + } - //pFile->Dump(); - AddFileToList(pFile); + //pFile->Dump(); + AddFileToList(pFile); - dirPtr += kDirectoryEntryLen; - prevNextBlock = pFile->fNextBlock; - } + dirPtr += kDirectoryEntryLen; + prevNextBlock = pFile->fNextBlock; + } bail: - FreeCatalog(); - return dierr; + FreeCatalog(); + return dierr; } @@ -401,26 +401,26 @@ bail: DIError DiskFSPascal::ScanFileUsage(void) { - int block; + int block; - /* start with the boot blocks */ - SetBlockUsage(0, VolumeUsage::kChunkPurposeSystem); - SetBlockUsage(1, VolumeUsage::kChunkPurposeSystem); + /* start with the boot blocks */ + SetBlockUsage(0, VolumeUsage::kChunkPurposeSystem); + SetBlockUsage(1, VolumeUsage::kChunkPurposeSystem); - for (block = kVolHeaderBlock; block < fNextBlock; block++) { - SetBlockUsage(block, VolumeUsage::kChunkPurposeVolumeDir); - } + for (block = kVolHeaderBlock; block < fNextBlock; block++) { + SetBlockUsage(block, VolumeUsage::kChunkPurposeVolumeDir); + } - A2FilePascal* pFile; - pFile = (A2FilePascal*) GetNextFile(nil); - while (pFile != nil) { - for (block = pFile->fStartBlock; block < pFile->fNextBlock; block++) - SetBlockUsage(block, VolumeUsage::kChunkPurposeUserData); + A2FilePascal* pFile; + pFile = (A2FilePascal*) GetNextFile(nil); + while (pFile != nil) { + for (block = pFile->fStartBlock; block < pFile->fNextBlock; block++) + SetBlockUsage(block, VolumeUsage::kChunkPurposeUserData); - pFile = (A2FilePascal*) GetNextFile(pFile); - } + pFile = (A2FilePascal*) GetNextFile(pFile); + } - return kDIErrNone; + return kDIErrNone; } /* @@ -429,18 +429,18 @@ DiskFSPascal::ScanFileUsage(void) void DiskFSPascal::SetBlockUsage(long block, VolumeUsage::ChunkPurpose purpose) { - VolumeUsage::ChunkState cstate; + VolumeUsage::ChunkState cstate; - fVolumeUsage.GetChunkState(block, &cstate); - if (cstate.isUsed) { - cstate.purpose = VolumeUsage::kChunkPurposeConflict; - WMSG1(" Pascal conflicting uses for bl=%ld\n", block); - } else { - cstate.isUsed = true; - cstate.isMarkedUsed = true; - cstate.purpose = purpose; - } - fVolumeUsage.SetChunkState(block, &cstate); + fVolumeUsage.GetChunkState(block, &cstate); + if (cstate.isUsed) { + cstate.purpose = VolumeUsage::kChunkPurposeConflict; + WMSG1(" Pascal conflicting uses for bl=%ld\n", block); + } else { + cstate.isUsed = true; + cstate.isMarkedUsed = true; + cstate.purpose = purpose; + } + fVolumeUsage.SetChunkState(block, &cstate); } @@ -453,13 +453,13 @@ DiskFSPascal::SetBlockUsage(long block, VolumeUsage::ChunkPurpose purpose) /*static*/ bool DiskFSPascal::IsValidVolumeName(const char* name) { - if (name == nil) { - assert(false); - return false; - } - if (strlen(name) > kMaxVolumeName) - return false; - return IsValidFileName(name); + if (name == nil) { + assert(false); + return false; + } + if (strlen(name) > kMaxVolumeName) + return false; + return IsValidFileName(name); } /* @@ -474,26 +474,26 @@ DiskFSPascal::IsValidVolumeName(const char* name) /*static*/ bool DiskFSPascal::IsValidFileName(const char* name) { - assert(name != nil); + assert(name != nil); - if (name[0] == '\0') - return false; - if (strlen(name) > A2FilePascal::kMaxFileName) - return false; + if (name[0] == '\0') + return false; + if (strlen(name) > A2FilePascal::kMaxFileName) + return false; - /* must be A-Z 0-9 '.' */ - while (*name != '\0') { - if (*name <= 0x20 || *name >= 0x7f) // no space, del, or ctrl - return false; - //if (*name >= 'a' && *name <= 'z') // no lower case - // return false; - if (strchr(kInvalidNameChars, *name) != nil) // filer metacharacters - return false; + /* must be A-Z 0-9 '.' */ + while (*name != '\0') { + if (*name <= 0x20 || *name >= 0x7f) // no space, del, or ctrl + return false; + //if (*name >= 'a' && *name <= 'z') // no lower case + // return false; + if (strchr(kInvalidNameChars, *name) != nil) // filer metacharacters + return false; - name++; - } + name++; + } - return true; + return true; } /* @@ -502,78 +502,78 @@ DiskFSPascal::IsValidFileName(const char* name) DIError DiskFSPascal::Format(DiskImg* pDiskImg, const char* volName) { - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; - long formatBlocks; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; + long formatBlocks; - if (!IsValidVolumeName(volName)) - return kDIErrInvalidArg; + if (!IsValidVolumeName(volName)) + return kDIErrInvalidArg; - /* set fpImg so calls that rely on it will work; we un-set it later */ - assert(fpImg == nil); - SetDiskImg(pDiskImg); + /* set fpImg so calls that rely on it will work; we un-set it later */ + assert(fpImg == nil); + SetDiskImg(pDiskImg); - WMSG0(" Pascal formatting disk image\n"); + WMSG0(" Pascal formatting disk image\n"); - /* write ProDOS-style blocks */ - dierr = fpImg->OverrideFormat(fpImg->GetPhysicalFormat(), - DiskImg::kFormatGenericProDOSOrd, fpImg->GetSectorOrder()); - if (dierr != kDIErrNone) - goto bail; + /* write ProDOS-style blocks */ + dierr = fpImg->OverrideFormat(fpImg->GetPhysicalFormat(), + DiskImg::kFormatGenericProDOSOrd, fpImg->GetSectorOrder()); + if (dierr != kDIErrNone) + goto bail; - formatBlocks = pDiskImg->GetNumBlocks(); - if (formatBlocks != 280 && formatBlocks != 1600) { - WMSG1(" Pascal: rejecting format req blocks=%ld\n", formatBlocks); - assert(false); - return kDIErrInvalidArg; - } + formatBlocks = pDiskImg->GetNumBlocks(); + if (formatBlocks != 280 && formatBlocks != 1600) { + WMSG1(" Pascal: rejecting format req blocks=%ld\n", formatBlocks); + assert(false); + return kDIErrInvalidArg; + } - /* - * We should now zero out the disk blocks, but this is done automatically - * on new disk images, so there's no need to do it here. - */ -// dierr = fpImg->ZeroImage(); - WMSG0(" Pascal (not zeroing blocks)\n"); + /* + * We should now zero out the disk blocks, but this is done automatically + * on new disk images, so there's no need to do it here. + */ +// dierr = fpImg->ZeroImage(); + WMSG0(" Pascal (not zeroing blocks)\n"); - /* - * Start by writing blocks 0 and 1 (the boot blocks). The file - * APPLE3:FORMATTER.DATA holds images for 3.5" and 5.25" disks. - */ - dierr = WriteBootBlocks(); - if (dierr != kDIErrNone) - goto bail; + /* + * Start by writing blocks 0 and 1 (the boot blocks). The file + * APPLE3:FORMATTER.DATA holds images for 3.5" and 5.25" disks. + */ + dierr = WriteBootBlocks(); + if (dierr != kDIErrNone) + goto bail; - /* - * Write the disk volume entry. - */ - memset(blkBuf, 0, sizeof(blkBuf)); - PutShortLE(&blkBuf[0x00], 0); // start block - PutShortLE(&blkBuf[0x02], 6); // next block - PutShortLE(&blkBuf[0x04], 0); // "file" type - blkBuf[0x06] = strlen(volName); - memcpy(&blkBuf[0x07], volName, strlen(volName)); - PutShortLE(&blkBuf[0x0e], (unsigned short) pDiskImg->GetNumBlocks()); - PutShortLE(&blkBuf[0x10], 0); // num files - PutShortLE(&blkBuf[0x12], 0); // last access date - PutShortLE(&blkBuf[0x14], 0xa87b); // last date set (Nov 7 1984) - dierr = fpImg->WriteBlock(kVolHeaderBlock, blkBuf); - if (dierr != kDIErrNone) { - WMSG2(" Format: block %d write failed (err=%d)\n", - kVolHeaderBlock, dierr); - goto bail; - } + /* + * Write the disk volume entry. + */ + memset(blkBuf, 0, sizeof(blkBuf)); + PutShortLE(&blkBuf[0x00], 0); // start block + PutShortLE(&blkBuf[0x02], 6); // next block + PutShortLE(&blkBuf[0x04], 0); // "file" type + blkBuf[0x06] = strlen(volName); + memcpy(&blkBuf[0x07], volName, strlen(volName)); + PutShortLE(&blkBuf[0x0e], (unsigned short) pDiskImg->GetNumBlocks()); + PutShortLE(&blkBuf[0x10], 0); // num files + PutShortLE(&blkBuf[0x12], 0); // last access date + PutShortLE(&blkBuf[0x14], 0xa87b); // last date set (Nov 7 1984) + dierr = fpImg->WriteBlock(kVolHeaderBlock, blkBuf); + if (dierr != kDIErrNone) { + WMSG2(" Format: block %d write failed (err=%d)\n", + kVolHeaderBlock, dierr); + goto bail; + } - /* check our work, and set some object fields, by reading what we wrote */ - dierr = LoadVolHeader(); - if (dierr != kDIErrNone) { - WMSG1(" GLITCH: couldn't read header we just wrote (err=%d)\n", dierr); - goto bail; - } + /* check our work, and set some object fields, by reading what we wrote */ + dierr = LoadVolHeader(); + if (dierr != kDIErrNone) { + WMSG1(" GLITCH: couldn't read header we just wrote (err=%d)\n", dierr); + goto bail; + } bail: - SetDiskImg(nil); // shouldn't really be set by us - return dierr; + SetDiskImg(nil); // shouldn't really be set by us + return dierr; } /* @@ -581,94 +581,94 @@ bail: * APPLE3:FORMATTER from Pascal v1.3. */ const unsigned char gPascal525Block0[] = { - 0x01, 0xe0, 0x70, 0xb0, 0x04, 0xe0, 0x40, 0xb0, 0x39, 0xbd, 0x88, 0xc0, - 0x20, 0x20, 0x08, 0xa2, 0x00, 0xbd, 0x25, 0x08, 0x09, 0x80, 0x20, 0xfd, - 0xfb, 0xe8, 0xe0, 0x1d, 0xd0, 0xf3, 0xf0, 0xfe, 0xa9, 0x0a, 0x4c, 0x24, - 0xfc, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x42, 0x4f, 0x4f, 0x54, 0x20, 0x46, - 0x52, 0x4f, 0x4d, 0x20, 0x53, 0x4c, 0x4f, 0x54, 0x20, 0x34, 0x2c, 0x20, - 0x35, 0x20, 0x4f, 0x52, 0x20, 0x36, 0x8a, 0x85, 0x43, 0x4a, 0x4a, 0x4a, - 0x4a, 0x09, 0xc0, 0x85, 0x0d, 0xa9, 0x5c, 0x85, 0x0c, 0xad, 0x00, 0x08, - 0xc9, 0x06, 0xb0, 0x0a, 0x69, 0x02, 0x8d, 0x00, 0x08, 0xe6, 0x3d, 0x6c, - 0x0c, 0x00, 0xa9, 0x00, 0x8d, 0x78, 0x04, 0xa9, 0x0a, 0x85, 0x0e, 0xa9, - 0x80, 0x85, 0x3f, 0x85, 0x11, 0xa9, 0x00, 0x85, 0x10, 0xa9, 0x08, 0x85, - 0x02, 0xa9, 0x02, 0x85, 0x0f, 0xa9, 0x00, 0x20, 0x4c, 0x09, 0xa2, 0x4e, - 0xa0, 0x06, 0xb1, 0x10, 0xd9, 0x39, 0x09, 0xf0, 0x2b, 0x18, 0xa5, 0x10, - 0x69, 0x1a, 0x85, 0x10, 0x90, 0x02, 0xe6, 0x11, 0xca, 0xd0, 0xe9, 0xc6, - 0x0e, 0xd0, 0xcc, 0x20, 0x20, 0x08, 0xa6, 0x43, 0xbd, 0x88, 0xc0, 0xa2, - 0x00, 0xbd, 0x2a, 0x09, 0x09, 0x80, 0x20, 0xfd, 0xfb, 0xe8, 0xe0, 0x15, - 0xd0, 0xf3, 0xf0, 0xfe, 0xc8, 0xc0, 0x13, 0xd0, 0xc9, 0xad, 0x81, 0xc0, - 0xad, 0x81, 0xc0, 0xa9, 0xd0, 0x85, 0x3f, 0xa9, 0x30, 0x85, 0x02, 0xa0, - 0x00, 0xb1, 0x10, 0x85, 0x0f, 0xc8, 0xb1, 0x10, 0x20, 0x4c, 0x09, 0xad, - 0x89, 0xc0, 0xa9, 0xd0, 0x85, 0x3f, 0xa9, 0x10, 0x85, 0x02, 0xa0, 0x00, - 0xb1, 0x10, 0x18, 0x69, 0x18, 0x85, 0x0f, 0xc8, 0xb1, 0x10, 0x69, 0x00, - 0x20, 0x4c, 0x09, 0xa5, 0x43, 0xc9, 0x50, 0xf0, 0x08, 0x90, 0x1a, 0xad, - 0x80, 0xc0, 0x6c, 0xf8, 0xff, 0xa2, 0x00, 0x8e, 0xc4, 0xfe, 0xe8, 0x8e, - 0xc6, 0xfe, 0xe8, 0x8e, 0xb6, 0xfe, 0xe8, 0x8e, 0xb8, 0xfe, 0x4c, 0xfb, - 0x08, 0xa2, 0x00, 0x8e, 0xc0, 0xfe, 0xe8, 0x8e, 0xc2, 0xfe, 0xa2, 0x04, - 0x8e, 0xb6, 0xfe, 0xe8, 0x8e, 0xb8, 0xfe, 0x4c, 0xfb, 0x08, 0x4e, 0x4f, - 0x20, 0x46, 0x49, 0x4c, 0x45, 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, - 0x2e, 0x41, 0x50, 0x50, 0x4c, 0x45, 0x20, 0x0c, 0x53, 0x59, 0x53, 0x54, - 0x45, 0x4d, 0x2e, 0x41, 0x50, 0x50, 0x4c, 0x45, 0x4a, 0x08, 0xa5, 0x0f, - 0x29, 0x07, 0x0a, 0x85, 0x00, 0xa5, 0x0f, 0x28, 0x6a, 0x4a, 0x4a, 0x85, - 0xf0, 0xa9, 0x00, 0x85, 0x3e, 0x4c, 0x78, 0x09, 0xa6, 0x02, 0xf0, 0x22, - 0xc6, 0x02, 0xe6, 0x3f, 0xe6, 0x00, 0xa5, 0x00, 0x49, 0x10, 0xd0, 0x04, - 0x85, 0x00, 0xe6, 0xf0, 0xa4, 0x00, 0xb9, 0x8b, 0x09, 0x85, 0xf1, 0xa2, - 0x00, 0xe4, 0x02, 0xf0, 0x05, 0x20, 0x9b, 0x09, 0x90, 0xda, 0x60, 0x00, - 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x01, 0x03, 0x05, 0x07, 0x09, - 0x0b, 0x0d, 0x0f, 0xa6, 0x43, 0xa5, 0xf0, 0x0a, 0x0e, 0x78, 0x04, 0x20, - 0xa3, 0x0a, 0x4e, 0x78, 0x04, 0x20, 0x47, 0x0a, 0xb0, 0xfb, 0xa4, 0x2e, - 0x8c, 0x78, 0x04, 0xc4, 0xf0, 0xd0, 0xe6, 0xa5, 0x2d, 0xc5, 0xf1, 0xd0, - 0xec, 0x20, 0xdf, 0x09, 0xb0, 0xe7, 0x20, 0xc7, 0x09, 0x18, 0x60, 0xa0, - 0x00, 0xa2, 0x56, 0xca, 0x30, 0xfb, 0xb9, 0x00, 0x02, 0x5e, 0x00, 0x03, - 0x2a, 0x5e, 0x00, 0x03, 0x2a, 0x91, 0x3e, 0xc8, 0xd0, 0xed, 0x60, 0xa0, - 0x20, 0x88, 0xf0, 0x61, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0x49, 0xd5, 0xd0, - 0xf4, 0xea, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xaa, 0xd0, 0xf2, 0xa0, - 0x56, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xad + 0x01, 0xe0, 0x70, 0xb0, 0x04, 0xe0, 0x40, 0xb0, 0x39, 0xbd, 0x88, 0xc0, + 0x20, 0x20, 0x08, 0xa2, 0x00, 0xbd, 0x25, 0x08, 0x09, 0x80, 0x20, 0xfd, + 0xfb, 0xe8, 0xe0, 0x1d, 0xd0, 0xf3, 0xf0, 0xfe, 0xa9, 0x0a, 0x4c, 0x24, + 0xfc, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x42, 0x4f, 0x4f, 0x54, 0x20, 0x46, + 0x52, 0x4f, 0x4d, 0x20, 0x53, 0x4c, 0x4f, 0x54, 0x20, 0x34, 0x2c, 0x20, + 0x35, 0x20, 0x4f, 0x52, 0x20, 0x36, 0x8a, 0x85, 0x43, 0x4a, 0x4a, 0x4a, + 0x4a, 0x09, 0xc0, 0x85, 0x0d, 0xa9, 0x5c, 0x85, 0x0c, 0xad, 0x00, 0x08, + 0xc9, 0x06, 0xb0, 0x0a, 0x69, 0x02, 0x8d, 0x00, 0x08, 0xe6, 0x3d, 0x6c, + 0x0c, 0x00, 0xa9, 0x00, 0x8d, 0x78, 0x04, 0xa9, 0x0a, 0x85, 0x0e, 0xa9, + 0x80, 0x85, 0x3f, 0x85, 0x11, 0xa9, 0x00, 0x85, 0x10, 0xa9, 0x08, 0x85, + 0x02, 0xa9, 0x02, 0x85, 0x0f, 0xa9, 0x00, 0x20, 0x4c, 0x09, 0xa2, 0x4e, + 0xa0, 0x06, 0xb1, 0x10, 0xd9, 0x39, 0x09, 0xf0, 0x2b, 0x18, 0xa5, 0x10, + 0x69, 0x1a, 0x85, 0x10, 0x90, 0x02, 0xe6, 0x11, 0xca, 0xd0, 0xe9, 0xc6, + 0x0e, 0xd0, 0xcc, 0x20, 0x20, 0x08, 0xa6, 0x43, 0xbd, 0x88, 0xc0, 0xa2, + 0x00, 0xbd, 0x2a, 0x09, 0x09, 0x80, 0x20, 0xfd, 0xfb, 0xe8, 0xe0, 0x15, + 0xd0, 0xf3, 0xf0, 0xfe, 0xc8, 0xc0, 0x13, 0xd0, 0xc9, 0xad, 0x81, 0xc0, + 0xad, 0x81, 0xc0, 0xa9, 0xd0, 0x85, 0x3f, 0xa9, 0x30, 0x85, 0x02, 0xa0, + 0x00, 0xb1, 0x10, 0x85, 0x0f, 0xc8, 0xb1, 0x10, 0x20, 0x4c, 0x09, 0xad, + 0x89, 0xc0, 0xa9, 0xd0, 0x85, 0x3f, 0xa9, 0x10, 0x85, 0x02, 0xa0, 0x00, + 0xb1, 0x10, 0x18, 0x69, 0x18, 0x85, 0x0f, 0xc8, 0xb1, 0x10, 0x69, 0x00, + 0x20, 0x4c, 0x09, 0xa5, 0x43, 0xc9, 0x50, 0xf0, 0x08, 0x90, 0x1a, 0xad, + 0x80, 0xc0, 0x6c, 0xf8, 0xff, 0xa2, 0x00, 0x8e, 0xc4, 0xfe, 0xe8, 0x8e, + 0xc6, 0xfe, 0xe8, 0x8e, 0xb6, 0xfe, 0xe8, 0x8e, 0xb8, 0xfe, 0x4c, 0xfb, + 0x08, 0xa2, 0x00, 0x8e, 0xc0, 0xfe, 0xe8, 0x8e, 0xc2, 0xfe, 0xa2, 0x04, + 0x8e, 0xb6, 0xfe, 0xe8, 0x8e, 0xb8, 0xfe, 0x4c, 0xfb, 0x08, 0x4e, 0x4f, + 0x20, 0x46, 0x49, 0x4c, 0x45, 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, + 0x2e, 0x41, 0x50, 0x50, 0x4c, 0x45, 0x20, 0x0c, 0x53, 0x59, 0x53, 0x54, + 0x45, 0x4d, 0x2e, 0x41, 0x50, 0x50, 0x4c, 0x45, 0x4a, 0x08, 0xa5, 0x0f, + 0x29, 0x07, 0x0a, 0x85, 0x00, 0xa5, 0x0f, 0x28, 0x6a, 0x4a, 0x4a, 0x85, + 0xf0, 0xa9, 0x00, 0x85, 0x3e, 0x4c, 0x78, 0x09, 0xa6, 0x02, 0xf0, 0x22, + 0xc6, 0x02, 0xe6, 0x3f, 0xe6, 0x00, 0xa5, 0x00, 0x49, 0x10, 0xd0, 0x04, + 0x85, 0x00, 0xe6, 0xf0, 0xa4, 0x00, 0xb9, 0x8b, 0x09, 0x85, 0xf1, 0xa2, + 0x00, 0xe4, 0x02, 0xf0, 0x05, 0x20, 0x9b, 0x09, 0x90, 0xda, 0x60, 0x00, + 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x01, 0x03, 0x05, 0x07, 0x09, + 0x0b, 0x0d, 0x0f, 0xa6, 0x43, 0xa5, 0xf0, 0x0a, 0x0e, 0x78, 0x04, 0x20, + 0xa3, 0x0a, 0x4e, 0x78, 0x04, 0x20, 0x47, 0x0a, 0xb0, 0xfb, 0xa4, 0x2e, + 0x8c, 0x78, 0x04, 0xc4, 0xf0, 0xd0, 0xe6, 0xa5, 0x2d, 0xc5, 0xf1, 0xd0, + 0xec, 0x20, 0xdf, 0x09, 0xb0, 0xe7, 0x20, 0xc7, 0x09, 0x18, 0x60, 0xa0, + 0x00, 0xa2, 0x56, 0xca, 0x30, 0xfb, 0xb9, 0x00, 0x02, 0x5e, 0x00, 0x03, + 0x2a, 0x5e, 0x00, 0x03, 0x2a, 0x91, 0x3e, 0xc8, 0xd0, 0xed, 0x60, 0xa0, + 0x20, 0x88, 0xf0, 0x61, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0x49, 0xd5, 0xd0, + 0xf4, 0xea, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xaa, 0xd0, 0xf2, 0xa0, + 0x56, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xad }; const unsigned char gPascal525Block1[] = { - 0xd0, 0xe7, 0xa9, 0x00, 0x88, 0x84, 0x26, 0xbc, 0x8c, 0xc0, 0x10, 0xfb, - 0x59, 0xd6, 0x02, 0xa4, 0x26, 0x99, 0x00, 0x03, 0xd0, 0xee, 0x84, 0x26, - 0xbc, 0x8c, 0xc0, 0x10, 0xfb, 0x59, 0xd6, 0x02, 0xa4, 0x26, 0x99, 0x00, - 0x02, 0xc8, 0xd0, 0xee, 0xbc, 0x8c, 0xc0, 0x10, 0xfb, 0xd9, 0xd6, 0x02, - 0xd0, 0x13, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xde, 0xd0, 0x0a, 0xea, - 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xaa, 0xf0, 0x5c, 0x38, 0x60, 0xa0, - 0xfc, 0x84, 0x26, 0xc8, 0xd0, 0x04, 0xe6, 0x26, 0xf0, 0xf3, 0xbd, 0x8c, - 0xc0, 0x10, 0xfb, 0xc9, 0xd5, 0xd0, 0xf0, 0xea, 0xbd, 0x8c, 0xc0, 0x10, - 0xfb, 0xc9, 0xaa, 0xd0, 0xf2, 0xa0, 0x03, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, - 0xc9, 0x96, 0xd0, 0xe7, 0xa9, 0x00, 0x85, 0x27, 0xbd, 0x8c, 0xc0, 0x10, - 0xfb, 0x2a, 0x85, 0x26, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0x25, 0x26, 0x99, - 0x2c, 0x00, 0x45, 0x27, 0x88, 0x10, 0xe7, 0xa8, 0xd0, 0xb7, 0xbd, 0x8c, - 0xc0, 0x10, 0xfb, 0xc9, 0xde, 0xd0, 0xae, 0xea, 0xbd, 0x8c, 0xc0, 0x10, - 0xfb, 0xc9, 0xaa, 0xd0, 0xa4, 0x18, 0x60, 0x86, 0x2b, 0x85, 0x2a, 0xcd, - 0x78, 0x04, 0xf0, 0x48, 0xa9, 0x00, 0x85, 0x26, 0xad, 0x78, 0x04, 0x85, - 0x27, 0x38, 0xe5, 0x2a, 0xf0, 0x37, 0xb0, 0x07, 0x49, 0xff, 0xee, 0x78, - 0x04, 0x90, 0x05, 0x69, 0xfe, 0xce, 0x78, 0x04, 0xc5, 0x26, 0x90, 0x02, - 0xa5, 0x26, 0xc9, 0x0c, 0xb0, 0x01, 0xa8, 0x20, 0xf4, 0x0a, 0xb9, 0x15, - 0x0b, 0x20, 0x04, 0x0b, 0xa5, 0x27, 0x29, 0x03, 0x0a, 0x05, 0x2b, 0xaa, - 0xbd, 0x80, 0xc0, 0xb9, 0x21, 0x0b, 0x20, 0x04, 0x0b, 0xe6, 0x26, 0xd0, - 0xbf, 0x20, 0x04, 0x0b, 0xad, 0x78, 0x04, 0x29, 0x03, 0x0a, 0x05, 0x2b, - 0xaa, 0xbd, 0x81, 0xc0, 0xa6, 0x2b, 0x60, 0xea, 0xa2, 0x11, 0xca, 0xd0, - 0xfd, 0xe6, 0x46, 0xd0, 0x02, 0xe6, 0x47, 0x38, 0xe9, 0x01, 0xd0, 0xf0, - 0x60, 0x01, 0x30, 0x28, 0x24, 0x20, 0x1e, 0x1d, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x70, 0x2c, 0x26, 0x22, 0x1f, 0x1e, 0x1d, 0x1c, 0x1c, 0x1c, 0x1c, - 0x1c, 0x20, 0x43, 0x4f, 0x50, 0x59, 0x52, 0x49, 0x47, 0x48, 0x54, 0x20, - 0x41, 0x50, 0x50, 0x4c, 0x45, 0x20, 0x43, 0x4f, 0x4d, 0x50, 0x55, 0x54, - 0x45, 0x52, 0x2c, 0x20, 0x49, 0x4e, 0x43, 0x2e, 0x2c, 0x20, 0x31, 0x39, - 0x38, 0x34, 0x2c, 0x20, 0x31, 0x39, 0x38, 0x35, 0x20, 0x43, 0x2e, 0x4c, - 0x45, 0x55, 0x4e, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x68, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb + 0xd0, 0xe7, 0xa9, 0x00, 0x88, 0x84, 0x26, 0xbc, 0x8c, 0xc0, 0x10, 0xfb, + 0x59, 0xd6, 0x02, 0xa4, 0x26, 0x99, 0x00, 0x03, 0xd0, 0xee, 0x84, 0x26, + 0xbc, 0x8c, 0xc0, 0x10, 0xfb, 0x59, 0xd6, 0x02, 0xa4, 0x26, 0x99, 0x00, + 0x02, 0xc8, 0xd0, 0xee, 0xbc, 0x8c, 0xc0, 0x10, 0xfb, 0xd9, 0xd6, 0x02, + 0xd0, 0x13, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xde, 0xd0, 0x0a, 0xea, + 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0xc9, 0xaa, 0xf0, 0x5c, 0x38, 0x60, 0xa0, + 0xfc, 0x84, 0x26, 0xc8, 0xd0, 0x04, 0xe6, 0x26, 0xf0, 0xf3, 0xbd, 0x8c, + 0xc0, 0x10, 0xfb, 0xc9, 0xd5, 0xd0, 0xf0, 0xea, 0xbd, 0x8c, 0xc0, 0x10, + 0xfb, 0xc9, 0xaa, 0xd0, 0xf2, 0xa0, 0x03, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, + 0xc9, 0x96, 0xd0, 0xe7, 0xa9, 0x00, 0x85, 0x27, 0xbd, 0x8c, 0xc0, 0x10, + 0xfb, 0x2a, 0x85, 0x26, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0x25, 0x26, 0x99, + 0x2c, 0x00, 0x45, 0x27, 0x88, 0x10, 0xe7, 0xa8, 0xd0, 0xb7, 0xbd, 0x8c, + 0xc0, 0x10, 0xfb, 0xc9, 0xde, 0xd0, 0xae, 0xea, 0xbd, 0x8c, 0xc0, 0x10, + 0xfb, 0xc9, 0xaa, 0xd0, 0xa4, 0x18, 0x60, 0x86, 0x2b, 0x85, 0x2a, 0xcd, + 0x78, 0x04, 0xf0, 0x48, 0xa9, 0x00, 0x85, 0x26, 0xad, 0x78, 0x04, 0x85, + 0x27, 0x38, 0xe5, 0x2a, 0xf0, 0x37, 0xb0, 0x07, 0x49, 0xff, 0xee, 0x78, + 0x04, 0x90, 0x05, 0x69, 0xfe, 0xce, 0x78, 0x04, 0xc5, 0x26, 0x90, 0x02, + 0xa5, 0x26, 0xc9, 0x0c, 0xb0, 0x01, 0xa8, 0x20, 0xf4, 0x0a, 0xb9, 0x15, + 0x0b, 0x20, 0x04, 0x0b, 0xa5, 0x27, 0x29, 0x03, 0x0a, 0x05, 0x2b, 0xaa, + 0xbd, 0x80, 0xc0, 0xb9, 0x21, 0x0b, 0x20, 0x04, 0x0b, 0xe6, 0x26, 0xd0, + 0xbf, 0x20, 0x04, 0x0b, 0xad, 0x78, 0x04, 0x29, 0x03, 0x0a, 0x05, 0x2b, + 0xaa, 0xbd, 0x81, 0xc0, 0xa6, 0x2b, 0x60, 0xea, 0xa2, 0x11, 0xca, 0xd0, + 0xfd, 0xe6, 0x46, 0xd0, 0x02, 0xe6, 0x47, 0x38, 0xe9, 0x01, 0xd0, 0xf0, + 0x60, 0x01, 0x30, 0x28, 0x24, 0x20, 0x1e, 0x1d, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x70, 0x2c, 0x26, 0x22, 0x1f, 0x1e, 0x1d, 0x1c, 0x1c, 0x1c, 0x1c, + 0x1c, 0x20, 0x43, 0x4f, 0x50, 0x59, 0x52, 0x49, 0x47, 0x48, 0x54, 0x20, + 0x41, 0x50, 0x50, 0x4c, 0x45, 0x20, 0x43, 0x4f, 0x4d, 0x50, 0x55, 0x54, + 0x45, 0x52, 0x2c, 0x20, 0x49, 0x4e, 0x43, 0x2e, 0x2c, 0x20, 0x31, 0x39, + 0x38, 0x34, 0x2c, 0x20, 0x31, 0x39, 0x38, 0x35, 0x20, 0x43, 0x2e, 0x4c, + 0x45, 0x55, 0x4e, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x68, 0x03, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbb }; /* @@ -676,49 +676,49 @@ const unsigned char gPascal525Block1[] = { * APPLE3:FORMATTER from Pascal v1.3. Block 1 is zeroed out. */ unsigned char gPascal35Block0[] = { - 0x01, 0xe0, 0x70, 0xb0, 0x04, 0xe0, 0x40, 0xb0, 0x39, 0xbd, 0x88, 0xc0, - 0x20, 0x20, 0x08, 0xa2, 0x00, 0xbd, 0x25, 0x08, 0x09, 0x80, 0x20, 0xfd, - 0xfb, 0xe8, 0xe0, 0x1d, 0xd0, 0xf3, 0xf0, 0xfe, 0xa9, 0x0a, 0x4c, 0x24, - 0xfc, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x42, 0x4f, 0x4f, 0x54, 0x20, 0x46, - 0x52, 0x4f, 0x4d, 0x20, 0x53, 0x4c, 0x4f, 0x54, 0x20, 0x34, 0x2c, 0x20, - 0x35, 0x20, 0x4f, 0x52, 0x20, 0x36, 0x8a, 0x85, 0x43, 0x4a, 0x4a, 0x4a, - 0x4a, 0x09, 0xc0, 0x85, 0x15, 0x8d, 0x5d, 0x09, 0xa9, 0x00, 0x8d, 0x78, - 0x04, 0x85, 0x14, 0xa9, 0x0a, 0x85, 0x0e, 0xa9, 0x80, 0x85, 0x13, 0x85, - 0x11, 0xa9, 0x00, 0x85, 0x10, 0x85, 0x0b, 0xa9, 0x02, 0x85, 0x0a, 0xa9, - 0x04, 0x85, 0x02, 0x20, 0x40, 0x09, 0xa2, 0x4e, 0xa0, 0x06, 0xb1, 0x10, - 0xd9, 0x2d, 0x09, 0xf0, 0x2b, 0x18, 0xa5, 0x10, 0x69, 0x1a, 0x85, 0x10, - 0x90, 0x02, 0xe6, 0x11, 0xca, 0xd0, 0xe9, 0xc6, 0x0e, 0xd0, 0xcc, 0x20, - 0x20, 0x08, 0xa6, 0x43, 0xbd, 0x88, 0xc0, 0xa2, 0x00, 0xbd, 0x1e, 0x09, - 0x09, 0x80, 0x20, 0xfd, 0xfb, 0xe8, 0xe0, 0x15, 0xd0, 0xf3, 0xf0, 0xfe, - 0xc8, 0xc0, 0x13, 0xd0, 0xc9, 0xad, 0x83, 0xc0, 0xad, 0x83, 0xc0, 0xa9, - 0xd0, 0x85, 0x13, 0xa0, 0x00, 0xb1, 0x10, 0x85, 0x0a, 0xc8, 0xb1, 0x10, - 0x85, 0x0b, 0xa9, 0x18, 0x85, 0x02, 0x20, 0x40, 0x09, 0xad, 0x8b, 0xc0, - 0xa9, 0xd0, 0x85, 0x13, 0xa0, 0x00, 0xb1, 0x10, 0x18, 0x69, 0x18, 0x85, - 0x0a, 0xc8, 0xb1, 0x10, 0x69, 0x00, 0x85, 0x0b, 0xa9, 0x08, 0x85, 0x02, - 0x20, 0x40, 0x09, 0xa5, 0x43, 0xc9, 0x50, 0xf0, 0x08, 0x90, 0x1a, 0xad, - 0x80, 0xc0, 0x6c, 0xf8, 0xff, 0xa2, 0x00, 0x8e, 0xc4, 0xfe, 0xe8, 0x8e, - 0xc6, 0xfe, 0xe8, 0x8e, 0xb6, 0xfe, 0xe8, 0x8e, 0xb8, 0xfe, 0x4c, 0xef, - 0x08, 0xa2, 0x00, 0x8e, 0xc0, 0xfe, 0xe8, 0x8e, 0xc2, 0xfe, 0xa2, 0x04, - 0x8e, 0xb6, 0xfe, 0xe8, 0x8e, 0xb8, 0xfe, 0x4c, 0xef, 0x08, 0x4e, 0x4f, - 0x20, 0x46, 0x49, 0x4c, 0x45, 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, - 0x2e, 0x41, 0x50, 0x50, 0x4c, 0x45, 0x20, 0x0c, 0x53, 0x59, 0x53, 0x54, - 0x45, 0x4d, 0x2e, 0x41, 0x50, 0x50, 0x4c, 0x45, 0xa9, 0x01, 0x85, 0x42, - 0xa0, 0xff, 0xb1, 0x14, 0x8d, 0x5c, 0x09, 0xa9, 0x00, 0x85, 0x44, 0xa5, - 0x13, 0x85, 0x45, 0xa5, 0x0a, 0x85, 0x46, 0xa5, 0x0b, 0x85, 0x47, 0x20, - 0x00, 0x00, 0x90, 0x03, 0x4c, 0x5b, 0x08, 0xc6, 0x02, 0xf0, 0x0c, 0xe6, - 0x13, 0xe6, 0x13, 0xe6, 0x0a, 0xd0, 0xdc, 0xe6, 0x0b, 0xd0, 0xd8, 0x60, - 0x20, 0x43, 0x4f, 0x50, 0x59, 0x52, 0x49, 0x47, 0x48, 0x54, 0x20, 0x41, - 0x50, 0x50, 0x4c, 0x45, 0x20, 0x43, 0x4f, 0x4d, 0x50, 0x55, 0x54, 0x45, - 0x52, 0x2c, 0x20, 0x49, 0x4e, 0x43, 0x2e, 0x2c, 0x20, 0x31, 0x39, 0x38, - 0x34, 0x2c, 0x20, 0x31, 0x39, 0x38, 0x35, 0x20, 0x43, 0x2e, 0x4c, 0x45, - 0x55, 0x4e, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xb0, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x01, 0xe0, 0x70, 0xb0, 0x04, 0xe0, 0x40, 0xb0, 0x39, 0xbd, 0x88, 0xc0, + 0x20, 0x20, 0x08, 0xa2, 0x00, 0xbd, 0x25, 0x08, 0x09, 0x80, 0x20, 0xfd, + 0xfb, 0xe8, 0xe0, 0x1d, 0xd0, 0xf3, 0xf0, 0xfe, 0xa9, 0x0a, 0x4c, 0x24, + 0xfc, 0x4d, 0x55, 0x53, 0x54, 0x20, 0x42, 0x4f, 0x4f, 0x54, 0x20, 0x46, + 0x52, 0x4f, 0x4d, 0x20, 0x53, 0x4c, 0x4f, 0x54, 0x20, 0x34, 0x2c, 0x20, + 0x35, 0x20, 0x4f, 0x52, 0x20, 0x36, 0x8a, 0x85, 0x43, 0x4a, 0x4a, 0x4a, + 0x4a, 0x09, 0xc0, 0x85, 0x15, 0x8d, 0x5d, 0x09, 0xa9, 0x00, 0x8d, 0x78, + 0x04, 0x85, 0x14, 0xa9, 0x0a, 0x85, 0x0e, 0xa9, 0x80, 0x85, 0x13, 0x85, + 0x11, 0xa9, 0x00, 0x85, 0x10, 0x85, 0x0b, 0xa9, 0x02, 0x85, 0x0a, 0xa9, + 0x04, 0x85, 0x02, 0x20, 0x40, 0x09, 0xa2, 0x4e, 0xa0, 0x06, 0xb1, 0x10, + 0xd9, 0x2d, 0x09, 0xf0, 0x2b, 0x18, 0xa5, 0x10, 0x69, 0x1a, 0x85, 0x10, + 0x90, 0x02, 0xe6, 0x11, 0xca, 0xd0, 0xe9, 0xc6, 0x0e, 0xd0, 0xcc, 0x20, + 0x20, 0x08, 0xa6, 0x43, 0xbd, 0x88, 0xc0, 0xa2, 0x00, 0xbd, 0x1e, 0x09, + 0x09, 0x80, 0x20, 0xfd, 0xfb, 0xe8, 0xe0, 0x15, 0xd0, 0xf3, 0xf0, 0xfe, + 0xc8, 0xc0, 0x13, 0xd0, 0xc9, 0xad, 0x83, 0xc0, 0xad, 0x83, 0xc0, 0xa9, + 0xd0, 0x85, 0x13, 0xa0, 0x00, 0xb1, 0x10, 0x85, 0x0a, 0xc8, 0xb1, 0x10, + 0x85, 0x0b, 0xa9, 0x18, 0x85, 0x02, 0x20, 0x40, 0x09, 0xad, 0x8b, 0xc0, + 0xa9, 0xd0, 0x85, 0x13, 0xa0, 0x00, 0xb1, 0x10, 0x18, 0x69, 0x18, 0x85, + 0x0a, 0xc8, 0xb1, 0x10, 0x69, 0x00, 0x85, 0x0b, 0xa9, 0x08, 0x85, 0x02, + 0x20, 0x40, 0x09, 0xa5, 0x43, 0xc9, 0x50, 0xf0, 0x08, 0x90, 0x1a, 0xad, + 0x80, 0xc0, 0x6c, 0xf8, 0xff, 0xa2, 0x00, 0x8e, 0xc4, 0xfe, 0xe8, 0x8e, + 0xc6, 0xfe, 0xe8, 0x8e, 0xb6, 0xfe, 0xe8, 0x8e, 0xb8, 0xfe, 0x4c, 0xef, + 0x08, 0xa2, 0x00, 0x8e, 0xc0, 0xfe, 0xe8, 0x8e, 0xc2, 0xfe, 0xa2, 0x04, + 0x8e, 0xb6, 0xfe, 0xe8, 0x8e, 0xb8, 0xfe, 0x4c, 0xef, 0x08, 0x4e, 0x4f, + 0x20, 0x46, 0x49, 0x4c, 0x45, 0x20, 0x53, 0x59, 0x53, 0x54, 0x45, 0x4d, + 0x2e, 0x41, 0x50, 0x50, 0x4c, 0x45, 0x20, 0x0c, 0x53, 0x59, 0x53, 0x54, + 0x45, 0x4d, 0x2e, 0x41, 0x50, 0x50, 0x4c, 0x45, 0xa9, 0x01, 0x85, 0x42, + 0xa0, 0xff, 0xb1, 0x14, 0x8d, 0x5c, 0x09, 0xa9, 0x00, 0x85, 0x44, 0xa5, + 0x13, 0x85, 0x45, 0xa5, 0x0a, 0x85, 0x46, 0xa5, 0x0b, 0x85, 0x47, 0x20, + 0x00, 0x00, 0x90, 0x03, 0x4c, 0x5b, 0x08, 0xc6, 0x02, 0xf0, 0x0c, 0xe6, + 0x13, 0xe6, 0x13, 0xe6, 0x0a, 0xd0, 0xdc, 0xe6, 0x0b, 0xd0, 0xd8, 0x60, + 0x20, 0x43, 0x4f, 0x50, 0x59, 0x52, 0x49, 0x47, 0x48, 0x54, 0x20, 0x41, + 0x50, 0x50, 0x4c, 0x45, 0x20, 0x43, 0x4f, 0x4d, 0x50, 0x55, 0x54, 0x45, + 0x52, 0x2c, 0x20, 0x49, 0x4e, 0x43, 0x2e, 0x2c, 0x20, 0x31, 0x39, 0x38, + 0x34, 0x2c, 0x20, 0x31, 0x39, 0x38, 0x35, 0x20, 0x43, 0x2e, 0x4c, 0x45, + 0x55, 0x4e, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xb0, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* @@ -727,29 +727,29 @@ unsigned char gPascal35Block0[] = { DIError DiskFSPascal::WriteBootBlocks(void) { - DIError dierr; - unsigned char block0[512]; - unsigned char block1[512]; - bool is525 = false; + DIError dierr; + unsigned char block0[512]; + unsigned char block1[512]; + bool is525 = false; - assert(fpImg->GetHasBlocks()); - if (fpImg->GetNumBlocks() == 280) - is525 = true; - else if (fpImg->GetNumBlocks() == 1600) - is525 = false; - else { - WMSG1(" Pascal boot blocks for blocks=%ld unknown\n", - fpImg->GetNumBlocks()); + assert(fpImg->GetHasBlocks()); + if (fpImg->GetNumBlocks() == 280) + is525 = true; + else if (fpImg->GetNumBlocks() == 1600) + is525 = false; + else { + WMSG1(" Pascal boot blocks for blocks=%ld unknown\n", + fpImg->GetNumBlocks()); return kDIErrInternal; - } + } - if (is525) { - memcpy(block0, gPascal525Block0, sizeof(block0)); - memcpy(block1, gPascal525Block1, sizeof(block1)); - } else { - memcpy(block0, gPascal35Block0, sizeof(block0)); - memset(block1, 0, sizeof(block1)); - } + if (is525) { + memcpy(block0, gPascal525Block0, sizeof(block0)); + memcpy(block1, gPascal525Block1, sizeof(block1)); + } else { + memcpy(block0, gPascal35Block0, sizeof(block0)); + memset(block1, 0, sizeof(block1)); + } dierr = fpImg->WriteBlock(0, block0); if (dierr != kDIErrNone) { @@ -762,7 +762,7 @@ DiskFSPascal::WriteBootBlocks(void) return dierr; } - return kDIErrNone; + return kDIErrNone; } @@ -777,33 +777,33 @@ DiskFSPascal::WriteBootBlocks(void) bool DiskFSPascal::CheckDiskIsGood(void) { - //DIError dierr; - bool result = true; + //DIError dierr; + bool result = true; - if (fEarlyDamage) - result = false; + if (fEarlyDamage) + result = false; - /* (don't need to check to see if the boot blocks or disk catalog are - marked in use -- the directory is defined by the set of blocks - in the volume header) */ + /* (don't need to check to see if the boot blocks or disk catalog are + marked in use -- the directory is defined by the set of blocks + in the volume header) */ - /* - * Scan for "damaged" or "suspicious" files diagnosed earlier. - */ - bool damaged, suspicious; - ScanForDamagedFiles(&damaged, &suspicious); + /* + * Scan for "damaged" or "suspicious" files diagnosed earlier. + */ + bool damaged, suspicious; + ScanForDamagedFiles(&damaged, &suspicious); - if (damaged) { - fpImg->AddNote(DiskImg::kNoteWarning, - "One or more files are damaged."); - result = false; - } else if (suspicious) { - fpImg->AddNote(DiskImg::kNoteWarning, - "One or more files look suspicious."); - result = false; - } + if (damaged) { + fpImg->AddNote(DiskImg::kNoteWarning, + "One or more files are damaged."); + result = false; + } else if (suspicious) { + fpImg->AddNote(DiskImg::kNoteWarning, + "One or more files look suspicious."); + result = false; + } - return result; + return result; } /* @@ -811,26 +811,26 @@ DiskFSPascal::CheckDiskIsGood(void) */ DIError DiskFSPascal::GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const + int* pUnitSize) const { - A2FilePascal* pFile; - long freeBlocks = 0; - unsigned short prevNextBlock = fNextBlock; + A2FilePascal* pFile; + long freeBlocks = 0; + unsigned short prevNextBlock = fNextBlock; - pFile = (A2FilePascal*) GetNextFile(nil); - while (pFile != nil) { - freeBlocks += pFile->fStartBlock - prevNextBlock; - prevNextBlock = pFile->fNextBlock; + pFile = (A2FilePascal*) GetNextFile(nil); + while (pFile != nil) { + freeBlocks += pFile->fStartBlock - prevNextBlock; + prevNextBlock = pFile->fNextBlock; - pFile = (A2FilePascal*) GetNextFile(pFile); - } - freeBlocks += fTotalBlocks - prevNextBlock; + pFile = (A2FilePascal*) GetNextFile(pFile); + } + freeBlocks += fTotalBlocks - prevNextBlock; - *pTotalUnits = fTotalBlocks; - *pFreeUnits = freeBlocks; - *pUnitSize = kBlockSize; + *pTotalUnits = fTotalBlocks; + *pFreeUnits = freeBlocks; + *pUnitSize = kBlockSize; - return kDIErrNone; + return kDIErrNone; } @@ -842,22 +842,22 @@ DiskFSPascal::GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, */ DIError DiskFSPascal::NormalizePath(const char* path, char fssep, - char* normalizedBuf, int* pNormalizedBufLen) + char* normalizedBuf, int* pNormalizedBufLen) { - DIError dierr = kDIErrNone; - char tmpBuf[A2FilePascal::kMaxFileName+1]; - int len; + DIError dierr = kDIErrNone; + char tmpBuf[A2FilePascal::kMaxFileName+1]; + int len; - DoNormalizePath(path, fssep, tmpBuf); - len = strlen(tmpBuf)+1; + DoNormalizePath(path, fssep, tmpBuf); + len = strlen(tmpBuf)+1; - if (*pNormalizedBufLen < len) - dierr = kDIErrDataOverrun; - else - strcpy(normalizedBuf, tmpBuf); - *pNormalizedBufLen = len; + if (*pNormalizedBufLen < len) + dierr = kDIErrDataOverrun; + else + strcpy(normalizedBuf, tmpBuf); + *pNormalizedBufLen = len; - return dierr; + return dierr; } /* @@ -869,32 +869,32 @@ DiskFSPascal::NormalizePath(const char* path, char fssep, void DiskFSPascal::DoNormalizePath(const char* name, char fssep, char* outBuf) { - char* outp = outBuf; - char* cp; + char* outp = outBuf; + char* cp; - /* throw out leading pathname, if any */ - if (fssep != '\0') { - cp = strrchr(name, fssep); - if (cp != nil) - name = cp+1; - } + /* throw out leading pathname, if any */ + if (fssep != '\0') { + cp = strrchr(name, fssep); + if (cp != nil) + name = cp+1; + } - while (*name != '\0' && (outp - outBuf) < A2FilePascal::kMaxFileName) { - if (*name > 0x20 && *name < 0x7f && - strchr(kInvalidNameChars, *name) == nil) - { - *outp++ = toupper(*name); - } + while (*name != '\0' && (outp - outBuf) < A2FilePascal::kMaxFileName) { + if (*name > 0x20 && *name < 0x7f && + strchr(kInvalidNameChars, *name) == nil) + { + *outp++ = toupper(*name); + } - name++; - } + name++; + } - *outp = '\0'; + *outp = '\0'; - if (*outBuf == '\0') { - /* nothing left */ - strcpy(outBuf, "BLANK"); - } + if (*outBuf == '\0') { + /* nothing left */ + strcpy(outBuf, "BLANK"); + } } @@ -915,141 +915,141 @@ DiskFSPascal::DoNormalizePath(const char* name, char fssep, char* outBuf) DIError DiskFSPascal::CreateFile(const CreateParms* pParms, A2File** ppNewFile) { - DIError dierr = kDIErrNone; - const bool createUnique = (GetParameter(kParm_CreateUnique) != 0); - char normalName[A2FilePascal::kMaxFileName+1]; - A2FilePascal* pNewFile = nil; + DIError dierr = kDIErrNone; + const bool createUnique = (GetParameter(kParm_CreateUnique) != 0); + char normalName[A2FilePascal::kMaxFileName+1]; + A2FilePascal* pNewFile = nil; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (!fDiskIsGood) - return kDIErrBadDiskImage; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (!fDiskIsGood) + return kDIErrBadDiskImage; - assert(pParms != nil); - assert(pParms->pathName != nil); - assert(pParms->storageType == A2FileProDOS::kStorageSeedling); - WMSG1(" Pascal ---v--- CreateFile '%s'\n", pParms->pathName); + assert(pParms != nil); + assert(pParms->pathName != nil); + assert(pParms->storageType == A2FileProDOS::kStorageSeedling); + WMSG1(" Pascal ---v--- CreateFile '%s'\n", pParms->pathName); - /* compute maxFiles, which includes the vol dir header */ - int maxFiles = - ((fNextBlock - kVolHeaderBlock) * kBlkSize) / kDirectoryEntryLen; - if (fNumFiles >= maxFiles-1) { - WMSG1("Pascal volume directory full (%d entries)\n", fNumFiles); - return kDIErrVolumeDirFull; - } + /* compute maxFiles, which includes the vol dir header */ + int maxFiles = + ((fNextBlock - kVolHeaderBlock) * kBlkSize) / kDirectoryEntryLen; + if (fNumFiles >= maxFiles-1) { + WMSG1("Pascal volume directory full (%d entries)\n", fNumFiles); + return kDIErrVolumeDirFull; + } - *ppNewFile = nil; + *ppNewFile = nil; - DoNormalizePath(pParms->pathName, pParms->fssep, normalName); + DoNormalizePath(pParms->pathName, pParms->fssep, normalName); - /* - * See if the file already exists. - * - * If "create unique" is set, we append digits until the name doesn't - * match any others. The name will be modified in place. - */ - if (createUnique) { - MakeFileNameUnique(normalName); - } else { - if (GetFileByName(normalName) != nil) { - WMSG1(" Pascal create: normalized name '%s' already exists\n", - normalName); - dierr = kDIErrFileExists; - goto bail; - } - } + /* + * See if the file already exists. + * + * If "create unique" is set, we append digits until the name doesn't + * match any others. The name will be modified in place. + */ + if (createUnique) { + MakeFileNameUnique(normalName); + } else { + if (GetFileByName(normalName) != nil) { + WMSG1(" Pascal create: normalized name '%s' already exists\n", + normalName); + dierr = kDIErrFileExists; + goto bail; + } + } - /* - * Find the largest gap in the file space. - * - * We get an index pointer and A2File pointer to the previous entry. If - * the blank space is at the head of the list, prevIdx will be zero and - * pPrevFile will be nil. - */ - A2FilePascal* pPrevFile; - int prevIdx; + /* + * Find the largest gap in the file space. + * + * We get an index pointer and A2File pointer to the previous entry. If + * the blank space is at the head of the list, prevIdx will be zero and + * pPrevFile will be nil. + */ + A2FilePascal* pPrevFile; + int prevIdx; - dierr = FindLargestFreeArea(&prevIdx, &pPrevFile); - if (dierr != kDIErrNone) - goto bail; - assert(prevIdx >= 0); + dierr = FindLargestFreeArea(&prevIdx, &pPrevFile); + if (dierr != kDIErrNone) + goto bail; + assert(prevIdx >= 0); - /* - * Make a new entry. - */ - time_t now; - pNewFile = new A2FilePascal(this); - if (pNewFile == nil) { - dierr = kDIErrMalloc; - goto bail; - } - if (pPrevFile == nil) - pNewFile->fStartBlock = fNextBlock; - else - pNewFile->fStartBlock = pPrevFile->fNextBlock; - pNewFile->fNextBlock = pNewFile->fStartBlock +1; // alloc 1 block - pNewFile->fFileType = A2FilePascal::ConvertFileType(pParms->fileType); - memset(pNewFile->fFileName, 0, A2FilePascal::kMaxFileName); - strcpy(pNewFile->fFileName, normalName); - pNewFile->fBytesRemaining = 0; - now = time(nil); - pNewFile->fModWhen = A2FilePascal::ConvertPascalDate(now); + /* + * Make a new entry. + */ + time_t now; + pNewFile = new A2FilePascal(this); + if (pNewFile == nil) { + dierr = kDIErrMalloc; + goto bail; + } + if (pPrevFile == nil) + pNewFile->fStartBlock = fNextBlock; + else + pNewFile->fStartBlock = pPrevFile->fNextBlock; + pNewFile->fNextBlock = pNewFile->fStartBlock +1; // alloc 1 block + pNewFile->fFileType = A2FilePascal::ConvertFileType(pParms->fileType); + memset(pNewFile->fFileName, 0, A2FilePascal::kMaxFileName); + strcpy(pNewFile->fFileName, normalName); + pNewFile->fBytesRemaining = 0; + now = time(nil); + pNewFile->fModWhen = A2FilePascal::ConvertPascalDate(now); - pNewFile->fLength = 0; + pNewFile->fLength = 0; - /* - * Make a hole. - */ - dierr = LoadCatalog(); - if (dierr != kDIErrNone) - goto bail; + /* + * Make a hole. + */ + dierr = LoadCatalog(); + if (dierr != kDIErrNone) + goto bail; - if (fNumFiles > prevIdx) { - WMSG1(" Pascal sliding last %d entries down a slot\n", - fNumFiles - prevIdx); - memmove(fDirectory + (prevIdx+2) * kDirectoryEntryLen, - fDirectory + (prevIdx+1) * kDirectoryEntryLen, - (fNumFiles - prevIdx) * kDirectoryEntryLen); - } + if (fNumFiles > prevIdx) { + WMSG1(" Pascal sliding last %d entries down a slot\n", + fNumFiles - prevIdx); + memmove(fDirectory + (prevIdx+2) * kDirectoryEntryLen, + fDirectory + (prevIdx+1) * kDirectoryEntryLen, + (fNumFiles - prevIdx) * kDirectoryEntryLen); + } - /* - * Fill the hole. - */ - unsigned char* dirPtr; - dirPtr = fDirectory + (prevIdx+1) * kDirectoryEntryLen; - PutShortLE(&dirPtr[0x00], pNewFile->fStartBlock); - PutShortLE(&dirPtr[0x02], pNewFile->fNextBlock); - PutShortLE(&dirPtr[0x04], (unsigned short) pNewFile->fFileType); - dirPtr[0x06] = (unsigned char) strlen(pNewFile->fFileName); - memcpy(&dirPtr[0x07], pNewFile->fFileName, A2FilePascal::kMaxFileName); - PutShortLE(&dirPtr[0x16], pNewFile->fBytesRemaining); - PutShortLE(&dirPtr[0x18], pNewFile->fModWhen); + /* + * Fill the hole. + */ + unsigned char* dirPtr; + dirPtr = fDirectory + (prevIdx+1) * kDirectoryEntryLen; + PutShortLE(&dirPtr[0x00], pNewFile->fStartBlock); + PutShortLE(&dirPtr[0x02], pNewFile->fNextBlock); + PutShortLE(&dirPtr[0x04], (unsigned short) pNewFile->fFileType); + dirPtr[0x06] = (unsigned char) strlen(pNewFile->fFileName); + memcpy(&dirPtr[0x07], pNewFile->fFileName, A2FilePascal::kMaxFileName); + PutShortLE(&dirPtr[0x16], pNewFile->fBytesRemaining); + PutShortLE(&dirPtr[0x18], pNewFile->fModWhen); - /* - * Update the #of files. - */ - fNumFiles++; - PutShortLE(&fDirectory[0x10], fNumFiles); + /* + * Update the #of files. + */ + fNumFiles++; + PutShortLE(&fDirectory[0x10], fNumFiles); - /* - * Flush. - */ - dierr = SaveCatalog(); - if (dierr != kDIErrNone) - goto bail; + /* + * Flush. + */ + dierr = SaveCatalog(); + if (dierr != kDIErrNone) + goto bail; - /* - * Add to the linear file list. - */ - InsertFileInList(pNewFile, pPrevFile); + /* + * Add to the linear file list. + */ + InsertFileInList(pNewFile, pPrevFile); - *ppNewFile = pNewFile; - pNewFile = nil; + *ppNewFile = pNewFile; + pNewFile = nil; bail: - delete pNewFile; - FreeCatalog(); - return dierr; + delete pNewFile; + FreeCatalog(); + return dierr; } /* @@ -1068,62 +1068,62 @@ bail: DIError DiskFSPascal::MakeFileNameUnique(char* fileName) { - assert(fileName != nil); - assert(strlen(fileName) <= A2FilePascal::kMaxFileName); + assert(fileName != nil); + assert(strlen(fileName) <= A2FilePascal::kMaxFileName); - if (GetFileByName(fileName) == nil) - return kDIErrNone; + if (GetFileByName(fileName) == nil) + return kDIErrNone; - WMSG1(" Pascal found duplicate of '%s', making unique\n", fileName); + WMSG1(" Pascal found duplicate of '%s', making unique\n", fileName); - int nameLen = strlen(fileName); - int dotOffset=0, dotLen=0; - char dotBuf[kMaxExtensionLen+1]; + int nameLen = strlen(fileName); + int dotOffset=0, dotLen=0; + char dotBuf[kMaxExtensionLen+1]; - /* ensure the result will be null-terminated */ - memset(fileName + nameLen, 0, (A2FilePascal::kMaxFileName - nameLen) +1); + /* ensure the result will be null-terminated */ + memset(fileName + nameLen, 0, (A2FilePascal::kMaxFileName - nameLen) +1); - /* - * If this has what looks like a filename extension, grab it. We want - * to preserve ".gif", ".c", etc. - */ - const char* cp = strrchr(fileName, '.'); - if (cp != nil) { - int tmpOffset = cp - fileName; - if (tmpOffset > 0 && nameLen - tmpOffset <= kMaxExtensionLen) { - WMSG1(" Pascal (keeping extension '%s')\n", cp); - assert(strlen(cp) <= kMaxExtensionLen); - strcpy(dotBuf, cp); - dotOffset = tmpOffset; - dotLen = nameLen - dotOffset; - } - } + /* + * If this has what looks like a filename extension, grab it. We want + * to preserve ".gif", ".c", etc. + */ + const char* cp = strrchr(fileName, '.'); + if (cp != nil) { + int tmpOffset = cp - fileName; + if (tmpOffset > 0 && nameLen - tmpOffset <= kMaxExtensionLen) { + WMSG1(" Pascal (keeping extension '%s')\n", cp); + assert(strlen(cp) <= kMaxExtensionLen); + strcpy(dotBuf, cp); + dotOffset = tmpOffset; + dotLen = nameLen - dotOffset; + } + } - const int kMaxDigits = 999; - int digits = 0; - int digitLen; - int copyOffset; - char digitBuf[4]; - do { - if (digits == kMaxDigits) - return kDIErrFileExists; - digits++; + const int kMaxDigits = 999; + int digits = 0; + int digitLen; + int copyOffset; + char digitBuf[4]; + do { + if (digits == kMaxDigits) + return kDIErrFileExists; + digits++; - /* not the most efficient way to do this, but it'll do */ - sprintf(digitBuf, "%d", digits); - digitLen = strlen(digitBuf); - if (nameLen + digitLen > A2FilePascal::kMaxFileName) - copyOffset = A2FilePascal::kMaxFileName - dotLen - digitLen; - else - copyOffset = nameLen - dotLen; - memcpy(fileName + copyOffset, digitBuf, digitLen); - if (dotLen != 0) - memcpy(fileName + copyOffset + digitLen, dotBuf, dotLen); - } while (GetFileByName(fileName) != nil); + /* not the most efficient way to do this, but it'll do */ + sprintf(digitBuf, "%d", digits); + digitLen = strlen(digitBuf); + if (nameLen + digitLen > A2FilePascal::kMaxFileName) + copyOffset = A2FilePascal::kMaxFileName - dotLen - digitLen; + else + copyOffset = nameLen - dotLen; + memcpy(fileName + copyOffset, digitBuf, digitLen); + if (dotLen != 0) + memcpy(fileName + copyOffset + digitLen, dotBuf, dotLen); + } while (GetFileByName(fileName) != nil); - WMSG1(" Pascal converted to unique name: %s\n", fileName); + WMSG1(" Pascal converted to unique name: %s\n", fileName); - return kDIErrNone; + return kDIErrNone; } /* @@ -1138,47 +1138,47 @@ DiskFSPascal::MakeFileNameUnique(char* fileName) DIError DiskFSPascal::FindLargestFreeArea(int *pPrevIdx, A2FilePascal** ppPrevFile) { - A2FilePascal* pFile; - A2FilePascal* pPrevFile; - unsigned short prevNextBlock = fNextBlock; - int gapSize, maxGap, maxIndex, idx; + A2FilePascal* pFile; + A2FilePascal* pPrevFile; + unsigned short prevNextBlock = fNextBlock; + int gapSize, maxGap, maxIndex, idx; - maxIndex = -1; - maxGap = 0; - idx = 0; - *ppPrevFile = pPrevFile = nil; + maxIndex = -1; + maxGap = 0; + idx = 0; + *ppPrevFile = pPrevFile = nil; - pFile = (A2FilePascal*) GetNextFile(nil); - while (pFile != nil) { - gapSize = pFile->fStartBlock - prevNextBlock; - if (gapSize > maxGap) { - maxGap = gapSize; - maxIndex = idx; - *ppPrevFile = pPrevFile; - } + pFile = (A2FilePascal*) GetNextFile(nil); + while (pFile != nil) { + gapSize = pFile->fStartBlock - prevNextBlock; + if (gapSize > maxGap) { + maxGap = gapSize; + maxIndex = idx; + *ppPrevFile = pPrevFile; + } - idx++; - prevNextBlock = pFile->fNextBlock; - pPrevFile = pFile; - pFile = (A2FilePascal*) GetNextFile(pFile); - } + idx++; + prevNextBlock = pFile->fNextBlock; + pPrevFile = pFile; + pFile = (A2FilePascal*) GetNextFile(pFile); + } - gapSize = fTotalBlocks - prevNextBlock; - if (gapSize > maxGap) { - maxGap = gapSize; - maxIndex = idx; - *ppPrevFile = pPrevFile; - } + gapSize = fTotalBlocks - prevNextBlock; + if (gapSize > maxGap) { + maxGap = gapSize; + maxIndex = idx; + *ppPrevFile = pPrevFile; + } - WMSG3("Pascal largest gap after entry %d '%s' (size=%d)\n", - maxIndex, - *ppPrevFile != nil ? (*ppPrevFile)->GetPathName() : "(root)", - maxGap); - *pPrevIdx = maxIndex; + WMSG3("Pascal largest gap after entry %d '%s' (size=%d)\n", + maxIndex, + *ppPrevFile != nil ? (*ppPrevFile)->GetPathName() : "(root)", + maxGap); + *pPrevIdx = maxIndex; - if (maxIndex < 0) - return kDIErrDiskFull; - return kDIErrNone; + if (maxIndex < 0) + return kDIErrDiskFull; + return kDIErrNone; } @@ -1189,59 +1189,59 @@ DiskFSPascal::FindLargestFreeArea(int *pPrevIdx, A2FilePascal** ppPrevFile) DIError DiskFSPascal::DeleteFile(A2File* pGenericFile) { - DIError dierr = kDIErrNone; - A2FilePascal* pFile = (A2FilePascal*) pGenericFile; - unsigned char* pEntry; - int dirLen, offsetToNextEntry; + DIError dierr = kDIErrNone; + A2FilePascal* pFile = (A2FilePascal*) pGenericFile; + unsigned char* pEntry; + int dirLen, offsetToNextEntry; - if (pGenericFile == nil) { - assert(false); - return kDIErrInvalidArg; - } + if (pGenericFile == nil) { + assert(false); + return kDIErrInvalidArg; + } - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (!fDiskIsGood) - return kDIErrBadDiskImage; - if (pGenericFile->IsFileOpen()) - return kDIErrFileOpen; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (!fDiskIsGood) + return kDIErrBadDiskImage; + if (pGenericFile->IsFileOpen()) + return kDIErrFileOpen; - WMSG1(" Pascal deleting '%s'\n", pFile->GetPathName()); + WMSG1(" Pascal deleting '%s'\n", pFile->GetPathName()); - dierr = LoadCatalog(); - if (dierr != kDIErrNone) - goto bail; + dierr = LoadCatalog(); + if (dierr != kDIErrNone) + goto bail; - pEntry = FindDirEntry(pFile); - if (pEntry == nil) { - assert(false); - dierr = kDIErrInternal; - goto bail; - } - dirLen = (fNumFiles+1) * kDirectoryEntryLen; - offsetToNextEntry = (pEntry - fDirectory) + kDirectoryEntryLen; - if (dirLen == offsetToNextEntry) { - WMSG0("+++ removing last entry\n"); - } else { - memmove(pEntry, pEntry+kDirectoryEntryLen, dirLen - offsetToNextEntry); - } + pEntry = FindDirEntry(pFile); + if (pEntry == nil) { + assert(false); + dierr = kDIErrInternal; + goto bail; + } + dirLen = (fNumFiles+1) * kDirectoryEntryLen; + offsetToNextEntry = (pEntry - fDirectory) + kDirectoryEntryLen; + if (dirLen == offsetToNextEntry) { + WMSG0("+++ removing last entry\n"); + } else { + memmove(pEntry, pEntry+kDirectoryEntryLen, dirLen - offsetToNextEntry); + } - assert(fNumFiles > 0); - fNumFiles--; - PutShortLE(&fDirectory[0x10], fNumFiles); + assert(fNumFiles > 0); + fNumFiles--; + PutShortLE(&fDirectory[0x10], fNumFiles); - dierr = SaveCatalog(); - if (dierr != kDIErrNone) - goto bail; + dierr = SaveCatalog(); + if (dierr != kDIErrNone) + goto bail; - /* - * Remove the A2File* from the list. - */ - DeleteFileFromList(pFile); + /* + * Remove the A2File* from the list. + */ + DeleteFileFromList(pFile); bail: - FreeCatalog(); - return dierr; + FreeCatalog(); + return dierr; } /* @@ -1250,49 +1250,49 @@ bail: DIError DiskFSPascal::RenameFile(A2File* pGenericFile, const char* newName) { - DIError dierr = kDIErrNone; - A2FilePascal* pFile = (A2FilePascal*) pGenericFile; - char normalName[A2FilePascal::kMaxFileName+1]; - unsigned char* pEntry; + DIError dierr = kDIErrNone; + A2FilePascal* pFile = (A2FilePascal*) pGenericFile; + char normalName[A2FilePascal::kMaxFileName+1]; + unsigned char* pEntry; - if (pFile == nil || newName == nil) - return kDIErrInvalidArg; - if (!IsValidFileName(newName)) - return kDIErrInvalidArg; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (!fDiskIsGood) - return kDIErrBadDiskImage; - /* not strictly necessary, but watch sanity check in Close/FindDirEntry */ - if (pGenericFile->IsFileOpen()) - return kDIErrFileOpen; + if (pFile == nil || newName == nil) + return kDIErrInvalidArg; + if (!IsValidFileName(newName)) + return kDIErrInvalidArg; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (!fDiskIsGood) + return kDIErrBadDiskImage; + /* not strictly necessary, but watch sanity check in Close/FindDirEntry */ + if (pGenericFile->IsFileOpen()) + return kDIErrFileOpen; - DoNormalizePath(newName, '\0', normalName); + DoNormalizePath(newName, '\0', normalName); - WMSG2(" Pascal renaming '%s' to '%s'\n", pFile->GetPathName(), normalName); + WMSG2(" Pascal renaming '%s' to '%s'\n", pFile->GetPathName(), normalName); - dierr = LoadCatalog(); - if (dierr != kDIErrNone) - goto bail; + dierr = LoadCatalog(); + if (dierr != kDIErrNone) + goto bail; - pEntry = FindDirEntry(pFile); - if (pEntry == nil) { - assert(false); - dierr = kDIErrInternal; - goto bail; - } + pEntry = FindDirEntry(pFile); + if (pEntry == nil) { + assert(false); + dierr = kDIErrInternal; + goto bail; + } - pEntry[0x06] = strlen(normalName); - memcpy(&pEntry[0x07], normalName, A2FilePascal::kMaxFileName); - strcpy(pFile->fFileName, normalName); + pEntry[0x06] = strlen(normalName); + memcpy(&pEntry[0x07], normalName, A2FilePascal::kMaxFileName); + strcpy(pFile->fFileName, normalName); - dierr = SaveCatalog(); - if (dierr != kDIErrNone) - goto bail; + dierr = SaveCatalog(); + if (dierr != kDIErrNone) + goto bail; bail: - FreeCatalog(); - return dierr; + FreeCatalog(); + return dierr; } /* @@ -1304,48 +1304,48 @@ bail: */ DIError DiskFSPascal::SetFileInfo(A2File* pGenericFile, long fileType, long auxType, - long accessFlags) + long accessFlags) { - DIError dierr = kDIErrNone; - A2FilePascal* pFile = (A2FilePascal*) pGenericFile; - unsigned char* pEntry; + DIError dierr = kDIErrNone; + A2FilePascal* pFile = (A2FilePascal*) pGenericFile; + unsigned char* pEntry; - if (pFile == nil) - return kDIErrInvalidArg; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (!fDiskIsGood) - return kDIErrBadDiskImage; + if (pFile == nil) + return kDIErrInvalidArg; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (!fDiskIsGood) + return kDIErrBadDiskImage; - WMSG2("Pascal SetFileInfo '%s' fileType=0x%04lx\n", - pFile->GetPathName(), fileType); + WMSG2("Pascal SetFileInfo '%s' fileType=0x%04lx\n", + pFile->GetPathName(), fileType); - dierr = LoadCatalog(); - if (dierr != kDIErrNone) - goto bail; + dierr = LoadCatalog(); + if (dierr != kDIErrNone) + goto bail; - pEntry = FindDirEntry(pFile); - if (pEntry == nil) { - assert(false); - dierr = kDIErrInternal; - goto bail; - } + pEntry = FindDirEntry(pFile); + if (pEntry == nil) { + assert(false); + dierr = kDIErrInternal; + goto bail; + } - A2FilePascal::FileType newType; + A2FilePascal::FileType newType; - newType = A2FilePascal::ConvertFileType(fileType); - PutShortLE(&pEntry[0x04], (unsigned short) newType); + newType = A2FilePascal::ConvertFileType(fileType); + PutShortLE(&pEntry[0x04], (unsigned short) newType); - dierr = SaveCatalog(); - if (dierr != kDIErrNone) - goto bail; + dierr = SaveCatalog(); + if (dierr != kDIErrNone) + goto bail; - /* update our local copy */ - pFile->fFileType = newType; + /* update our local copy */ + pFile->fFileType = newType; bail: - FreeCatalog(); - return dierr; + FreeCatalog(); + return dierr; } /* @@ -1354,33 +1354,33 @@ bail: DIError DiskFSPascal::RenameVolume(const char* newName) { - DIError dierr = kDIErrNone; - char normalName[A2FilePascal::kMaxFileName+1]; + DIError dierr = kDIErrNone; + char normalName[A2FilePascal::kMaxFileName+1]; - if (!IsValidVolumeName(newName)) - return kDIErrInvalidArg; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; + if (!IsValidVolumeName(newName)) + return kDIErrInvalidArg; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; - DoNormalizePath(newName, '\0', normalName); + DoNormalizePath(newName, '\0', normalName); - dierr = LoadCatalog(); - if (dierr != kDIErrNone) - goto bail; + dierr = LoadCatalog(); + if (dierr != kDIErrNone) + goto bail; - fDirectory[0x06] = strlen(normalName); - memcpy(&fDirectory[0x07], normalName, fDirectory[0x06]); - strcpy(fVolumeName, normalName); + fDirectory[0x06] = strlen(normalName); + memcpy(&fDirectory[0x07], normalName, fDirectory[0x06]); + strcpy(fVolumeName, normalName); - SetVolumeID(); + SetVolumeID(); - dierr = SaveCatalog(); - if (dierr != kDIErrNone) - goto bail; + dierr = SaveCatalog(); + if (dierr != kDIErrNone) + goto bail; bail: - FreeCatalog(); - return dierr; + FreeCatalog(); + return dierr; } @@ -1390,33 +1390,33 @@ bail: unsigned char* DiskFSPascal::FindDirEntry(A2FilePascal* pFile) { - unsigned char* ptr; - int i; + unsigned char* ptr; + int i; - assert(fDirectory != nil); + assert(fDirectory != nil); - ptr = fDirectory; // volume header; first iteration skips over it - for (i = 0; i < fNumFiles; i++) { - ptr += kDirectoryEntryLen; + ptr = fDirectory; // volume header; first iteration skips over it + for (i = 0; i < fNumFiles; i++) { + ptr += kDirectoryEntryLen; - if (GetShortLE(&ptr[0x00]) == pFile->fStartBlock) { - if (memcmp(&ptr[0x07], pFile->fFileName, ptr[0x06]) != 0) { - assert(false); - WMSG2("name/block mismatch on '%s' %d\n", - pFile->GetPathName(), pFile->fStartBlock); - return nil; - } - return ptr; - } - } + if (GetShortLE(&ptr[0x00]) == pFile->fStartBlock) { + if (memcmp(&ptr[0x07], pFile->fFileName, ptr[0x06]) != 0) { + assert(false); + WMSG2("name/block mismatch on '%s' %d\n", + pFile->GetPathName(), pFile->fStartBlock); + return nil; + } + return ptr; + } + } - return nil; + return nil; } /* * =========================================================================== - * A2FilePascal + * A2FilePascal * =========================================================================== */ @@ -1426,20 +1426,20 @@ DiskFSPascal::FindDirEntry(A2FilePascal* pFile) long A2FilePascal::GetFileType(void) const { - switch (fFileType) { - case kTypeUntyped: return 0x00; // NON - case kTypeXdsk: return 0x01; // BAD (was 0xf2 in v1.2.2) - case kTypeCode: return 0x02; // PCD - case kTypeText: return 0x03; // PTX - case kTypeInfo: return 0xf3; // no idea - case kTypeData: return 0x05; // PDA - case kTypeGraf: return 0xf4; // no idea - case kTypeFoto: return 0x08; // FOT - case kTypeSecurdir: return 0xf5; // no idea - default: - WMSG1("Pascal WARNING: found invalid file type %d\n", fFileType); - return 0; - } + switch (fFileType) { + case kTypeUntyped: return 0x00; // NON + case kTypeXdsk: return 0x01; // BAD (was 0xf2 in v1.2.2) + case kTypeCode: return 0x02; // PCD + case kTypeText: return 0x03; // PTX + case kTypeInfo: return 0xf3; // no idea + case kTypeData: return 0x05; // PDA + case kTypeGraf: return 0xf4; // no idea + case kTypeFoto: return 0x08; // FOT + case kTypeSecurdir: return 0xf5; // no idea + default: + WMSG1("Pascal WARNING: found invalid file type %d\n", fFileType); + return 0; + } } /* @@ -1448,32 +1448,32 @@ A2FilePascal::GetFileType(void) const /*static*/ A2FilePascal::FileType A2FilePascal::ConvertFileType(long prodosType) { - FileType newType; + FileType newType; - switch (prodosType) { - case 0x00: newType = kTypeUntyped; break; // NON - case 0x01: newType = kTypeXdsk; break; // BAD - case 0x02: newType = kTypeCode; break; // PCD - case 0x03: newType = kTypeText; break; // PTX - case 0xf3: newType = kTypeInfo; break; // ? - case 0x05: newType = kTypeData; break; // PDA - case 0xf4: newType = kTypeGraf; break; // ? - case 0x08: newType = kTypeFoto; break; // FOT - case 0xf5: newType = kTypeSecurdir; break; // ? - default: newType = kTypeData; break; // PDA for generic - } + switch (prodosType) { + case 0x00: newType = kTypeUntyped; break; // NON + case 0x01: newType = kTypeXdsk; break; // BAD + case 0x02: newType = kTypeCode; break; // PCD + case 0x03: newType = kTypeText; break; // PTX + case 0xf3: newType = kTypeInfo; break; // ? + case 0x05: newType = kTypeData; break; // PDA + case 0xf4: newType = kTypeGraf; break; // ? + case 0x08: newType = kTypeFoto; break; // FOT + case 0xf5: newType = kTypeSecurdir; break; // ? + default: newType = kTypeData; break; // PDA for generic + } - return newType; + return newType; } /* * Convert from Pascal compact date format to a time_t. * - * Format yyyyyyydddddmmmm - * Month 0..12 (0 indicates invalid date) - * Day 0..31 - * Year 0..100 (1900-1999; 100 will be rejected) + * Format yyyyyyydddddmmmm + * Month 0..12 (0 indicates invalid date) + * Day 0..31 + * Year 0..100 (1900-1999; 100 will be rejected) * * We follow the ProDOS protocol of "year < 40 == 1900 + year". We could * probably make that 1970, but the time_t epoch ends before then. @@ -1486,19 +1486,19 @@ A2FilePascal::ConvertFileType(long prodosType) /*static*/ time_t A2FilePascal::ConvertPascalDate(PascalDate pascalDate) { - int year, month, day; + int year, month, day; - month = pascalDate & 0x0f; - if (!month) - return 0; - day = (pascalDate >> 4) & 0x1f; - year = (pascalDate >> 9) & 0x7f; - if (year == 100) { - // ought to mark the file as "suspicious"? - WMSG0("Pascal WARNING: date with year=100\n"); - } - if (year < 40) - year += 100; + month = pascalDate & 0x0f; + if (!month) + return 0; + day = (pascalDate >> 4) & 0x1f; + year = (pascalDate >> 9) & 0x7f; + if (year == 100) { + // ought to mark the file as "suspicious"? + WMSG0("Pascal WARNING: date with year=100\n"); + } + if (year < 40) + year += 100; struct tm tmbuf; time_t when; @@ -1514,9 +1514,9 @@ A2FilePascal::ConvertPascalDate(PascalDate pascalDate) tmbuf.tm_isdst = -1; // let it figure DST and time zone when = mktime(&tmbuf); - if (when == (time_t) -1) - when = 0; - return when; + if (when == (time_t) -1) + when = 0; + return when; } /* @@ -1527,25 +1527,25 @@ A2FilePascal::ConvertPascalDate(PascalDate pascalDate) /*static*/ A2FilePascal::PascalDate A2FilePascal::ConvertPascalDate(time_t unixDate) { - unsigned long date, year; - struct tm* ptm; + unsigned long date, year; + struct tm* ptm; - if (unixDate == 0 || unixDate == -1 || unixDate == -2) - return 0; + if (unixDate == 0 || unixDate == -1 || unixDate == -2) + return 0; - ptm = localtime(&unixDate); - if (ptm == nil) - return 0; // must've been invalid or unspecified + ptm = localtime(&unixDate); + if (ptm == nil) + return 0; // must've been invalid or unspecified - year = ptm->tm_year; // years since 1900 - if (year >= 100) - year -= 100; - if (year < 0 || year >= 100) { - WMSG2("WHOOPS: got year %lu from %d\n", year, ptm->tm_year); - year = 70; - } - date = year << 9 | (ptm->tm_mon+1) | ptm->tm_mday << 4; - return (PascalDate) date; + year = ptm->tm_year; // years since 1900 + if (year >= 100) + year -= 100; + if (year < 0 || year >= 100) { + WMSG2("WHOOPS: got year %lu from %d\n", year, ptm->tm_year); + year = 70; + } + date = year << 9 | (ptm->tm_mon+1) | ptm->tm_mday << 4; + return (PascalDate) date; } @@ -1555,7 +1555,7 @@ A2FilePascal::ConvertPascalDate(time_t unixDate) time_t A2FilePascal::GetModWhen(void) const { - return ConvertPascalDate(fModWhen); + return ConvertPascalDate(fModWhen); } /* @@ -1564,11 +1564,11 @@ A2FilePascal::GetModWhen(void) const void A2FilePascal::Dump(void) const { - WMSG1("A2FilePascal '%s'\n", fFileName); - WMSG3(" start=%d next=%d type=%d\n", - fStartBlock, fNextBlock, fFileType); - WMSG2(" bytesRem=%d modWhen=0x%04x\n", - fBytesRemaining, fModWhen); + WMSG1("A2FilePascal '%s'\n", fFileName); + WMSG3(" start=%d next=%d type=%d\n", + fStartBlock, fNextBlock, fFileType); + WMSG2(" bytesRem=%d modWhen=0x%04x\n", + fBytesRemaining, fModWhen); } /* @@ -1576,38 +1576,38 @@ A2FilePascal::Dump(void) const */ DIError A2FilePascal::Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork /*=false*/) + bool rsrcFork /*=false*/) { - A2FDPascal* pOpenFile = nil; + A2FDPascal* pOpenFile = nil; - if (!readOnly) { - if (fpDiskFS->GetDiskImg()->GetReadOnly()) - return kDIErrAccessDenied; - if (fpDiskFS->GetFSDamaged()) - return kDIErrBadDiskImage; - } - if (fpOpenFile != nil) - return kDIErrAlreadyOpen; - if (rsrcFork) - return kDIErrForkNotFound; + if (!readOnly) { + if (fpDiskFS->GetDiskImg()->GetReadOnly()) + return kDIErrAccessDenied; + if (fpDiskFS->GetFSDamaged()) + return kDIErrBadDiskImage; + } + if (fpOpenFile != nil) + return kDIErrAlreadyOpen; + if (rsrcFork) + return kDIErrForkNotFound; - pOpenFile = new A2FDPascal(this); + pOpenFile = new A2FDPascal(this); - pOpenFile->fOffset = 0; - pOpenFile->fOpenEOF = fLength; - pOpenFile->fOpenBlocksUsed = fNextBlock - fStartBlock; - pOpenFile->fModified = false; + pOpenFile->fOffset = 0; + pOpenFile->fOpenEOF = fLength; + pOpenFile->fOpenBlocksUsed = fNextBlock - fStartBlock; + pOpenFile->fModified = false; - fpOpenFile = pOpenFile; - *ppOpenFile = pOpenFile; + fpOpenFile = pOpenFile; + *ppOpenFile = pOpenFile; - return kDIErrNone; + return kDIErrNone; } /* * =========================================================================== - * A2FDPascal + * A2FDPascal * =========================================================================== */ @@ -1617,54 +1617,54 @@ A2FilePascal::Open(A2FileDescr** ppOpenFile, bool readOnly, DIError A2FDPascal::Read(void* buf, size_t len, size_t* pActual) { - WMSG3(" Pascal reading %d bytes from '%s' (offset=%ld)\n", - len, fpFile->GetPathName(), (long) fOffset); + WMSG3(" Pascal reading %d bytes from '%s' (offset=%ld)\n", + len, fpFile->GetPathName(), (long) fOffset); - A2FilePascal* pFile = (A2FilePascal*) fpFile; + A2FilePascal* pFile = (A2FilePascal*) fpFile; - /* don't allow them to read past the end of the file */ - if (fOffset + (long)len > fOpenEOF) { - if (pActual == nil) - return kDIErrDataUnderrun; - len = (size_t) (fOpenEOF - fOffset); - } - if (pActual != nil) - *pActual = len; - long incrLen = len; + /* don't allow them to read past the end of the file */ + if (fOffset + (long)len > fOpenEOF) { + if (pActual == nil) + return kDIErrDataUnderrun; + len = (size_t) (fOpenEOF - fOffset); + } + if (pActual != nil) + *pActual = len; + long incrLen = len; - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; - long block = pFile->fStartBlock + (long) (fOffset / kBlkSize); - int bufOffset = (long) (fOffset % kBlkSize); // (& 0x01ff) - size_t thisCount; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; + long block = pFile->fStartBlock + (long) (fOffset / kBlkSize); + int bufOffset = (long) (fOffset % kBlkSize); // (& 0x01ff) + size_t thisCount; - if (len == 0) - return kDIErrNone; - assert(fOpenEOF != 0); + if (len == 0) + return kDIErrNone; + assert(fOpenEOF != 0); - while (len) { - assert(block >= pFile->fStartBlock && block < pFile->fNextBlock); + while (len) { + assert(block >= pFile->fStartBlock && block < pFile->fNextBlock); - dierr = pFile->GetDiskFS()->GetDiskImg()->ReadBlock(block, blkBuf); - if (dierr != kDIErrNone) { - WMSG1(" Pascal error reading file '%s'\n", pFile->fFileName); - return dierr; - } - thisCount = kBlkSize - bufOffset; - if (thisCount > len) - thisCount = len; + dierr = pFile->GetDiskFS()->GetDiskImg()->ReadBlock(block, blkBuf); + if (dierr != kDIErrNone) { + WMSG1(" Pascal error reading file '%s'\n", pFile->fFileName); + return dierr; + } + thisCount = kBlkSize - bufOffset; + if (thisCount > len) + thisCount = len; - memcpy(buf, blkBuf + bufOffset, thisCount); - len -= thisCount; - buf = (char*)buf + thisCount; + memcpy(buf, blkBuf + bufOffset, thisCount); + len -= thisCount; + buf = (char*)buf + thisCount; - bufOffset = 0; - block++; - } + bufOffset = 0; + block++; + } - fOffset += incrLen; + fOffset += incrLen; - return dierr; + return dierr; } /* @@ -1677,80 +1677,80 @@ A2FDPascal::Read(void* buf, size_t len, size_t* pActual) DIError A2FDPascal::Write(const void* buf, size_t len, size_t* pActual) { - DIError dierr = kDIErrNone; - A2FilePascal* pFile = (A2FilePascal*) fpFile; - DiskFSPascal* pDiskFS = (DiskFSPascal*) fpFile->GetDiskFS(); - unsigned char blkBuf[kBlkSize]; - size_t origLen = len; + DIError dierr = kDIErrNone; + A2FilePascal* pFile = (A2FilePascal*) fpFile; + DiskFSPascal* pDiskFS = (DiskFSPascal*) fpFile->GetDiskFS(); + unsigned char blkBuf[kBlkSize]; + size_t origLen = len; - WMSG2(" DOS Write len=%u %s\n", len, pFile->GetPathName()); + WMSG2(" DOS Write len=%u %s\n", len, pFile->GetPathName()); - if (len >= 0x01000000) { // 16MB - assert(false); - return kDIErrInvalidArg; - } + if (len >= 0x01000000) { // 16MB + assert(false); + return kDIErrInvalidArg; + } - assert(fOffset == 0); // big simplifying assumption - assert(fOpenEOF == 0); // another one - assert(fOpenBlocksUsed == 1); - assert(buf != nil); + assert(fOffset == 0); // big simplifying assumption + assert(fOpenEOF == 0); // another one + assert(fOpenBlocksUsed == 1); + assert(buf != nil); - /* - * Verify that there's enough room between this file and the next to - * hold the contents of the file. - */ - long blocksNeeded, blocksAvail; - A2FilePascal* pNextFile; - pNextFile = (A2FilePascal*) pDiskFS->GetNextFile(pFile); - if (pNextFile == nil) - blocksAvail = pDiskFS->GetTotalBlocks() - pFile->fStartBlock; - else - blocksAvail = pNextFile->fStartBlock - pFile->fStartBlock; + /* + * Verify that there's enough room between this file and the next to + * hold the contents of the file. + */ + long blocksNeeded, blocksAvail; + A2FilePascal* pNextFile; + pNextFile = (A2FilePascal*) pDiskFS->GetNextFile(pFile); + if (pNextFile == nil) + blocksAvail = pDiskFS->GetTotalBlocks() - pFile->fStartBlock; + else + blocksAvail = pNextFile->fStartBlock - pFile->fStartBlock; - blocksNeeded = (len + kBlkSize -1) / kBlkSize; - WMSG4("Pascal write '%s' %d bytes: avail=%ld needed=%ld\n", - pFile->GetPathName(), len, blocksAvail, blocksNeeded); - if (blocksAvail < blocksNeeded) - return kDIErrDiskFull; + blocksNeeded = (len + kBlkSize -1) / kBlkSize; + WMSG4("Pascal write '%s' %d bytes: avail=%ld needed=%ld\n", + pFile->GetPathName(), len, blocksAvail, blocksNeeded); + if (blocksAvail < blocksNeeded) + return kDIErrDiskFull; - /* - * Write the data. - */ - long block; - block = pFile->fStartBlock; - while (len != 0) { - if (len >= (size_t) kBlkSize) { - /* full block write */ - dierr = pDiskFS->GetDiskImg()->WriteBlock(block, buf); - if (dierr != kDIErrNone) - goto bail; + /* + * Write the data. + */ + long block; + block = pFile->fStartBlock; + while (len != 0) { + if (len >= (size_t) kBlkSize) { + /* full block write */ + dierr = pDiskFS->GetDiskImg()->WriteBlock(block, buf); + if (dierr != kDIErrNone) + goto bail; - len -= kBlkSize; - buf = (unsigned char*) buf + kBlkSize; - } else { - /* partial block write */ - memset(blkBuf, 0, sizeof(blkBuf)); - memcpy(blkBuf, buf, len); - dierr = pDiskFS->GetDiskImg()->WriteBlock(block, blkBuf); - if (dierr != kDIErrNone) - goto bail; + len -= kBlkSize; + buf = (unsigned char*) buf + kBlkSize; + } else { + /* partial block write */ + memset(blkBuf, 0, sizeof(blkBuf)); + memcpy(blkBuf, buf, len); + dierr = pDiskFS->GetDiskImg()->WriteBlock(block, blkBuf); + if (dierr != kDIErrNone) + goto bail; - len = 0; - } + len = 0; + } - block++; - } + block++; + } - /* - * Update FD state. - */ - fOpenBlocksUsed = blocksNeeded; - fOpenEOF = origLen; - fOffset = origLen; - fModified = true; + /* + * Update FD state. + */ + fOpenBlocksUsed = blocksNeeded; + fOpenEOF = origLen; + fOffset = origLen; + fModified = true; bail: - return dierr; + return dierr; } /* @@ -1759,34 +1759,34 @@ bail: DIError A2FDPascal::Seek(di_off_t offset, DIWhence whence) { - //di_off_t fileLen = ((A2FilePascal*) fpFile)->fLength; + //di_off_t fileLen = ((A2FilePascal*) fpFile)->fLength; - switch (whence) { - case kSeekSet: - if (offset < 0 || offset > fOpenEOF) - return kDIErrInvalidArg; - fOffset = offset; - break; - case kSeekEnd: - if (offset > 0 || offset < -fOpenEOF) - return kDIErrInvalidArg; - fOffset = fOpenEOF + offset; - break; - case kSeekCur: - if (offset < -fOffset || - offset >= (fOpenEOF - fOffset)) - { - return kDIErrInvalidArg; - } - fOffset += offset; - break; - default: - assert(false); - return kDIErrInvalidArg; - } + switch (whence) { + case kSeekSet: + if (offset < 0 || offset > fOpenEOF) + return kDIErrInvalidArg; + fOffset = offset; + break; + case kSeekEnd: + if (offset > 0 || offset < -fOpenEOF) + return kDIErrInvalidArg; + fOffset = fOpenEOF + offset; + break; + case kSeekCur: + if (offset < -fOffset || + offset >= (fOpenEOF - fOffset)) + { + return kDIErrInvalidArg; + } + fOffset += offset; + break; + default: + assert(false); + return kDIErrInvalidArg; + } - assert(fOffset >= 0 && fOffset <= fOpenEOF); - return kDIErrNone; + assert(fOffset >= 0 && fOffset <= fOpenEOF); + return kDIErrNone; } /* @@ -1795,7 +1795,7 @@ A2FDPascal::Seek(di_off_t offset, DIWhence whence) di_off_t A2FDPascal::Tell(void) { - return fOffset; + return fOffset; } /* @@ -1807,55 +1807,55 @@ A2FDPascal::Tell(void) DIError A2FDPascal::Close(void) { - DIError dierr = kDIErrNone; - DiskFSPascal* pDiskFS = (DiskFSPascal*) fpFile->GetDiskFS(); + DIError dierr = kDIErrNone; + DiskFSPascal* pDiskFS = (DiskFSPascal*) fpFile->GetDiskFS(); - if (fModified) { - A2FilePascal* pFile = (A2FilePascal*) fpFile; - unsigned char* pEntry; + if (fModified) { + A2FilePascal* pFile = (A2FilePascal*) fpFile; + unsigned char* pEntry; - dierr = pDiskFS->LoadCatalog(); - if (dierr != kDIErrNone) - goto bail; + dierr = pDiskFS->LoadCatalog(); + if (dierr != kDIErrNone) + goto bail; - /* - * Update our internal copies of stuff. - */ - pFile->fLength = fOpenEOF; - pFile->fNextBlock = pFile->fStartBlock + (unsigned short) fOpenBlocksUsed; - pFile->fModWhen = A2FilePascal::ConvertPascalDate(time(nil)); + /* + * Update our internal copies of stuff. + */ + pFile->fLength = fOpenEOF; + pFile->fNextBlock = pFile->fStartBlock + (unsigned short) fOpenBlocksUsed; + pFile->fModWhen = A2FilePascal::ConvertPascalDate(time(nil)); - /* - * Update the "next block" value and the length-in-last-block. We - * have to scan through the directory to find our entry, rather - * than remember an offset at "open" time, on the off chance that - * somebody created or deleted a file after we were opened. - */ - pEntry = pDiskFS->FindDirEntry(pFile); - if (pEntry == nil) { - // we deleted an open file? - assert(false); - dierr = kDIErrInternal; - goto bail; - } - unsigned short bytesInLastBlock; - bytesInLastBlock = (unsigned short)pFile->fLength % kBlkSize; - if (bytesInLastBlock == 0) - bytesInLastBlock = 512; // exactly filled out last block + /* + * Update the "next block" value and the length-in-last-block. We + * have to scan through the directory to find our entry, rather + * than remember an offset at "open" time, on the off chance that + * somebody created or deleted a file after we were opened. + */ + pEntry = pDiskFS->FindDirEntry(pFile); + if (pEntry == nil) { + // we deleted an open file? + assert(false); + dierr = kDIErrInternal; + goto bail; + } + unsigned short bytesInLastBlock; + bytesInLastBlock = (unsigned short)pFile->fLength % kBlkSize; + if (bytesInLastBlock == 0) + bytesInLastBlock = 512; // exactly filled out last block - PutShortLE(&pEntry[0x02], pFile->fNextBlock); - PutShortLE(&pEntry[0x16], bytesInLastBlock); - PutShortLE(&pEntry[0x18], pFile->fModWhen); + PutShortLE(&pEntry[0x02], pFile->fNextBlock); + PutShortLE(&pEntry[0x16], bytesInLastBlock); + PutShortLE(&pEntry[0x18], pFile->fModWhen); - dierr = pDiskFS->SaveCatalog(); - if (dierr != kDIErrNone) - goto bail; - } + dierr = pDiskFS->SaveCatalog(); + if (dierr != kDIErrNone) + goto bail; + } bail: - pDiskFS->FreeCatalog(); - fpFile->CloseDescr(this); - return dierr; + pDiskFS->FreeCatalog(); + fpFile->CloseDescr(this); + return dierr; } /* @@ -1864,14 +1864,14 @@ bail: long A2FDPascal::GetSectorCount(void) const { - A2FilePascal* pFile = (A2FilePascal*) fpFile; - return (pFile->fNextBlock - pFile->fStartBlock) * 2; + A2FilePascal* pFile = (A2FilePascal*) fpFile; + return (pFile->fNextBlock - pFile->fStartBlock) * 2; } long A2FDPascal::GetBlockCount(void) const { - A2FilePascal* pFile = (A2FilePascal*) fpFile; - return pFile->fNextBlock - pFile->fStartBlock; + A2FilePascal* pFile = (A2FilePascal*) fpFile; + return pFile->fNextBlock - pFile->fStartBlock; } /* @@ -1880,15 +1880,15 @@ A2FDPascal::GetBlockCount(void) const DIError A2FDPascal::GetStorage(long sectorIdx, long* pTrack, long* pSector) const { - A2FilePascal* pFile = (A2FilePascal*) fpFile; - long pascalIdx = sectorIdx / 2; - long pascalBlock = pFile->fStartBlock + pascalIdx; - if (pascalBlock >= pFile->fNextBlock) - return kDIErrInvalidIndex; + A2FilePascal* pFile = (A2FilePascal*) fpFile; + long pascalIdx = sectorIdx / 2; + long pascalBlock = pFile->fStartBlock + pascalIdx; + if (pascalBlock >= pFile->fNextBlock) + return kDIErrInvalidIndex; - /* sparse blocks not possible on Pascal volumes */ - BlockToTrackSector(pascalBlock, (sectorIdx & 0x01) != 0, pTrack, pSector); - return kDIErrNone; + /* sparse blocks not possible on Pascal volumes */ + BlockToTrackSector(pascalBlock, (sectorIdx & 0x01) != 0, pTrack, pSector); + return kDIErrNone; } /* * Return the Nth 512-byte block in this file. @@ -1896,12 +1896,12 @@ A2FDPascal::GetStorage(long sectorIdx, long* pTrack, long* pSector) const DIError A2FDPascal::GetStorage(long blockIdx, long* pBlock) const { - A2FilePascal* pFile = (A2FilePascal*) fpFile; - long pascalBlock = pFile->fStartBlock + blockIdx; - if (pascalBlock >= pFile->fNextBlock) - return kDIErrInvalidIndex; + A2FilePascal* pFile = (A2FilePascal*) fpFile; + long pascalBlock = pFile->fStartBlock + blockIdx; + if (pascalBlock >= pFile->fNextBlock) + return kDIErrInvalidIndex; - *pBlock = pascalBlock; - assert(*pBlock < pFile->GetDiskFS()->GetDiskImg()->GetNumBlocks()); - return kDIErrNone; + *pBlock = pascalBlock; + assert(*pBlock < pFile->GetDiskFS()->GetDiskImg()->GetNumBlocks()); + return kDIErrNone; } diff --git a/diskimg/ProDOS.cpp b/diskimg/ProDOS.cpp index 945cbb3..b89917a 100644 --- a/diskimg/ProDOS.cpp +++ b/diskimg/ProDOS.cpp @@ -24,19 +24,19 @@ /* * =========================================================================== - * DiskFSProDOS + * DiskFSProDOS * =========================================================================== */ const int kBlkSize = 512; -const int kVolHeaderBlock = 2; // block where Volume Header resides -const int kVolDirExpectedNumBlocks = 4; // customary #of volume header blocks -const int kMinReasonableBlocks = 16; // min size for ProDOS volume -const int kExpectedBitmapStart = 6; // block# where vol bitmap should start -const int kMaxCatalogIterations = 1024; // theoretical max is 32768? -const int kMaxDirectoryDepth = 64; // not sure what ProDOS limit is -const int kEntriesPerBlock = 0x0d; // expected value for entries per blk -const int kEntryLength = 0x27; // expected value for dir entry len +const int kVolHeaderBlock = 2; // block where Volume Header resides +const int kVolDirExpectedNumBlocks = 4; // customary #of volume header blocks +const int kMinReasonableBlocks = 16; // min size for ProDOS volume +const int kExpectedBitmapStart = 6; // block# where vol bitmap should start +const int kMaxCatalogIterations = 1024; // theoretical max is 32768? +const int kMaxDirectoryDepth = 64; // not sure what ProDOS limit is +const int kEntriesPerBlock = 0x0d; // expected value for entries per blk +const int kEntryLength = 0x27; // expected value for dir entry len const int kTypeDIR = 0x0f; @@ -45,24 +45,24 @@ const int kTypeDIR = 0x0f; * to the volume directory header. */ //namespace DiskImgLib { - + typedef struct DiskFSProDOS::DirHeader { - unsigned char storageType; - char dirName[A2FileProDOS::kMaxFileName+1]; - DiskFSProDOS::ProDate createWhen; - unsigned char version; - unsigned char minVersion; - unsigned char access; - unsigned char entryLength; - unsigned char entriesPerBlock; - unsigned short fileCount; - /* the rest are only for subdirs */ - unsigned short parentPointer; - unsigned char parentEntry; - unsigned char parentEntryLength; + unsigned char storageType; + char dirName[A2FileProDOS::kMaxFileName+1]; + DiskFSProDOS::ProDate createWhen; + unsigned char version; + unsigned char minVersion; + unsigned char access; + unsigned char entryLength; + unsigned char entriesPerBlock; + unsigned short fileCount; + /* the rest are only for subdirs */ + unsigned short parentPointer; + unsigned char parentEntry; + unsigned char parentEntryLength; } DirHeader; -//}; // namespace DiskImgLib +//}; // namespace DiskImgLib /* @@ -73,33 +73,33 @@ typedef struct DiskFSProDOS::DirHeader { static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder) { - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; - int volDirEntryLength; - int volDirEntriesPerBlock; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; + int volDirEntryLength; + int volDirEntriesPerBlock; - dierr = pImg->ReadBlockSwapped(kVolHeaderBlock, blkBuf, imageOrder, - DiskImg::kSectorOrderProDOS); - if (dierr != kDIErrNone) - goto bail; + dierr = pImg->ReadBlockSwapped(kVolHeaderBlock, blkBuf, imageOrder, + DiskImg::kSectorOrderProDOS); + if (dierr != kDIErrNone) + goto bail; - volDirEntryLength = blkBuf[0x23]; - volDirEntriesPerBlock = blkBuf[0x24]; + volDirEntryLength = blkBuf[0x23]; + volDirEntriesPerBlock = blkBuf[0x24]; - if (!(blkBuf[0x00] == 0 && blkBuf[0x01] == 0) || - !((blkBuf[0x04] & 0xf0) == 0xf0) || - !((blkBuf[0x04] & 0x0f) != 0) || - !(volDirEntryLength * volDirEntriesPerBlock <= kBlkSize) || - !(blkBuf[0x05] >= 'A' && blkBuf[0x05] <= 'Z') || - 0) - { - dierr = kDIErrFilesystemNotFound; - goto bail; - } + if (!(blkBuf[0x00] == 0 && blkBuf[0x01] == 0) || + !((blkBuf[0x04] & 0xf0) == 0xf0) || + !((blkBuf[0x04] & 0x0f) != 0) || + !(volDirEntryLength * volDirEntriesPerBlock <= kBlkSize) || + !(blkBuf[0x05] >= 'A' && blkBuf[0x05] <= 'Z') || + 0) + { + dierr = kDIErrFilesystemNotFound; + goto bail; + } bail: - return dierr; + return dierr; } /* @@ -109,22 +109,22 @@ bail: DiskFSProDOS::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DiskImg::FSFormat* pFormat, FSLeniency leniency) { - DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; - - DiskImg::GetSectorOrderArray(ordering, *pOrder); + DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; + + DiskImg::GetSectorOrderArray(ordering, *pOrder); - for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { - if (ordering[i] == DiskImg::kSectorOrderUnknown) - continue; - if (TestImage(pImg, ordering[i]) == kDIErrNone) { - *pOrder = ordering[i]; - *pFormat = DiskImg::kFormatProDOS; - return kDIErrNone; - } - } + for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { + if (ordering[i] == DiskImg::kSectorOrderUnknown) + continue; + if (TestImage(pImg, ordering[i]) == kDIErrNone) { + *pOrder = ordering[i]; + *pFormat = DiskImg::kFormatProDOS; + return kDIErrNone; + } + } - WMSG0(" ProDOS didn't find valid FS\n"); - return kDIErrFilesystemNotFound; + WMSG0(" ProDOS didn't find valid FS\n"); + return kDIErrFilesystemNotFound; } /* @@ -137,88 +137,88 @@ DiskFSProDOS::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DIError DiskFSProDOS::Initialize(InitMode initMode) { - DIError dierr = kDIErrNone; - char msg[kMaxVolumeName + 32]; + DIError dierr = kDIErrNone; + char msg[kMaxVolumeName + 32]; - fDiskIsGood = false; // hosed until proven innocent - fEarlyDamage = false; + fDiskIsGood = false; // hosed until proven innocent + fEarlyDamage = false; - /* - * NOTE: we'd probably be better off with fTotalBlocks, since that's how - * big the disk *thinks* it is, especially on a CFFA or MacPart subvol. - * However, we know that the image block count is the absolute maximum, - * so while it may not be a tight bound it is an upper bound. - */ - fVolumeUsage.Create(fpImg->GetNumBlocks()); + /* + * NOTE: we'd probably be better off with fTotalBlocks, since that's how + * big the disk *thinks* it is, especially on a CFFA or MacPart subvol. + * However, we know that the image block count is the absolute maximum, + * so while it may not be a tight bound it is an upper bound. + */ + fVolumeUsage.Create(fpImg->GetNumBlocks()); - dierr = LoadVolHeader(); - if (dierr != kDIErrNone) - goto bail; - DumpVolHeader(); + dierr = LoadVolHeader(); + if (dierr != kDIErrNone) + goto bail; + DumpVolHeader(); - dierr = ScanVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + dierr = ScanVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - if (initMode == kInitHeaderOnly) { - WMSG0(" ProDOS - headerOnly set, skipping file load\n"); - goto bail; - } + if (initMode == kInitHeaderOnly) { + WMSG0(" ProDOS - headerOnly set, skipping file load\n"); + goto bail; + } - sprintf(msg, "Scanning %s", fVolumeName); - if (!fpImg->UpdateScanProgress(msg)) { - WMSG0(" ProDOS cancelled by user\n"); - dierr = kDIErrCancelled; - goto bail; - } + sprintf(msg, "Scanning %s", fVolumeName); + if (!fpImg->UpdateScanProgress(msg)) { + WMSG0(" ProDOS cancelled by user\n"); + dierr = kDIErrCancelled; + goto bail; + } - /* volume dir is guaranteed to come first; if not, we need a lookup func */ - A2FileProDOS* pVolumeDir; - pVolumeDir = (A2FileProDOS*) GetNextFile(nil); + /* volume dir is guaranteed to come first; if not, we need a lookup func */ + A2FileProDOS* pVolumeDir; + pVolumeDir = (A2FileProDOS*) GetNextFile(nil); - dierr = RecursiveDirAdd(pVolumeDir, kVolHeaderBlock, "", 0); - if (dierr != kDIErrNone) { - WMSG0(" ProDOS RecursiveDirAdd failed\n"); - goto bail; - } + dierr = RecursiveDirAdd(pVolumeDir, kVolHeaderBlock, "", 0); + if (dierr != kDIErrNone) { + WMSG0(" ProDOS RecursiveDirAdd failed\n"); + goto bail; + } - sprintf(msg, "Processing %s", fVolumeName); - if (!fpImg->UpdateScanProgress(msg)) { - WMSG0(" ProDOS cancelled by user\n"); - dierr = kDIErrCancelled; - goto bail; - } + sprintf(msg, "Processing %s", fVolumeName); + if (!fpImg->UpdateScanProgress(msg)) { + WMSG0(" ProDOS cancelled by user\n"); + dierr = kDIErrCancelled; + goto bail; + } - dierr = ScanFileUsage(); - if (dierr != kDIErrNone) { - if (dierr == kDIErrCancelled) - goto bail; + dierr = ScanFileUsage(); + if (dierr != kDIErrNone) { + if (dierr == kDIErrCancelled) + goto bail; - /* this might not be fatal; just means that *some* files are bad */ - WMSG1("WARNING: ScanFileUsage returned err=%d\n", dierr); - dierr = kDIErrNone; - fpImg->AddNote(DiskImg::kNoteWarning, - "Some errors were encountered while scanning files."); - fEarlyDamage = true; // make sure we know it's damaged - } + /* this might not be fatal; just means that *some* files are bad */ + WMSG1("WARNING: ScanFileUsage returned err=%d\n", dierr); + dierr = kDIErrNone; + fpImg->AddNote(DiskImg::kNoteWarning, + "Some errors were encountered while scanning files."); + fEarlyDamage = true; // make sure we know it's damaged + } - fDiskIsGood = CheckDiskIsGood(); + fDiskIsGood = CheckDiskIsGood(); - if (fScanForSubVolumes != kScanSubDisabled) - (void) ScanForSubVolumes(); + if (fScanForSubVolumes != kScanSubDisabled) + (void) ScanForSubVolumes(); - if (fpImg->GetNumBlocks() <= 1600) - fVolumeUsage.Dump(); + if (fpImg->GetNumBlocks() <= 1600) + fVolumeUsage.Dump(); -// A2File* pFile; -// pFile = GetNextFile(nil); -// while (pFile != nil) { -// pFile->Dump(); -// pFile = GetNextFile(pFile); -// } +// A2File* pFile; +// pFile = GetNextFile(nil); +// while (pFile != nil) { +// pFile->Dump(); +// pFile = GetNextFile(pFile); +// } bail: - return dierr; + return dierr; } /* @@ -230,162 +230,162 @@ bail: DIError DiskFSProDOS::LoadVolHeader(void) { - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; - int nameLen; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; + int nameLen; - dierr = fpImg->ReadBlock(kVolHeaderBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpImg->ReadBlock(kVolHeaderBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; - //fPrevBlock = GetShortLE(&blkBuf[0x00]); - //fNextBlock = GetShortLE(&blkBuf[0x02]); - nameLen = blkBuf[0x04] & 0x0f; - memcpy(fVolumeName, &blkBuf[0x05], nameLen); - fVolumeName[nameLen] = '\0'; - // 0x14-15 reserved - // undocumented: GS/OS writes the modification date to 0x16-19 - fModWhen = GetLongLE(&blkBuf[0x16]); - // undocumented: GS/OS uses 0x1a-1b for lower-case handling (see below) - fCreateWhen = GetLongLE(&blkBuf[0x1c]); - //fVersion = blkBuf[0x20]; - if (blkBuf[0x21] != 0) { - /* - * We don't care about the MIN_VERSION field, but it looks like GS/OS - * rejects anything with a nonzero value here. We want to add a note - * about it. - */ - fpImg->AddNote(DiskImg::kNoteInfo, - "Volume header has nonzero min_version; could confuse GS/OS."); - } - fAccess = blkBuf[0x22]; - //fEntryLength = blkBuf[0x23]; - //fEntriesPerBlock = blkBuf[0x24]; - fVolDirFileCount = GetShortLE(&blkBuf[0x25]); - fBitMapPointer = GetShortLE(&blkBuf[0x27]); - fTotalBlocks = GetShortLE(&blkBuf[0x29]); + //fPrevBlock = GetShortLE(&blkBuf[0x00]); + //fNextBlock = GetShortLE(&blkBuf[0x02]); + nameLen = blkBuf[0x04] & 0x0f; + memcpy(fVolumeName, &blkBuf[0x05], nameLen); + fVolumeName[nameLen] = '\0'; + // 0x14-15 reserved + // undocumented: GS/OS writes the modification date to 0x16-19 + fModWhen = GetLongLE(&blkBuf[0x16]); + // undocumented: GS/OS uses 0x1a-1b for lower-case handling (see below) + fCreateWhen = GetLongLE(&blkBuf[0x1c]); + //fVersion = blkBuf[0x20]; + if (blkBuf[0x21] != 0) { + /* + * We don't care about the MIN_VERSION field, but it looks like GS/OS + * rejects anything with a nonzero value here. We want to add a note + * about it. + */ + fpImg->AddNote(DiskImg::kNoteInfo, + "Volume header has nonzero min_version; could confuse GS/OS."); + } + fAccess = blkBuf[0x22]; + //fEntryLength = blkBuf[0x23]; + //fEntriesPerBlock = blkBuf[0x24]; + fVolDirFileCount = GetShortLE(&blkBuf[0x25]); + fBitMapPointer = GetShortLE(&blkBuf[0x27]); + fTotalBlocks = GetShortLE(&blkBuf[0x29]); - if (blkBuf[0x1b] & 0x80) { - /* - * Handle lower-case conversion; see GS/OS tech note #8. Unlike - * filenames, volume names are not allowed to contain spaces. If - * they try it we just ignore them. - * - * Technote 8 doesn't actually talk about volume names. By - * experimentation the field was discovered at offset 0x1a from - * the start of the block, which is marked as "reserved" in Beneath - * Apple ProDOS. - */ - unsigned short lcFlags = GetShortLE(&blkBuf[0x1a]); + if (blkBuf[0x1b] & 0x80) { + /* + * Handle lower-case conversion; see GS/OS tech note #8. Unlike + * filenames, volume names are not allowed to contain spaces. If + * they try it we just ignore them. + * + * Technote 8 doesn't actually talk about volume names. By + * experimentation the field was discovered at offset 0x1a from + * the start of the block, which is marked as "reserved" in Beneath + * Apple ProDOS. + */ + unsigned short lcFlags = GetShortLE(&blkBuf[0x1a]); - GenerateLowerCaseName(fVolumeName, fVolumeName, lcFlags, false); - } + GenerateLowerCaseName(fVolumeName, fVolumeName, lcFlags, false); + } - if (fTotalBlocks <= kVolHeaderBlock) { - /* incr to min; don't use max, or bitmap count may be too large */ - WMSG1(" ProDOS found tiny fTotalBlocks (%d), increasing to minimum\n", - fTotalBlocks); - fpImg->AddNote(DiskImg::kNoteWarning, - "ProDOS filesystem blockcount (%d) too small, setting to %d.", - fTotalBlocks, kMinReasonableBlocks); - fTotalBlocks = kMinReasonableBlocks; - fEarlyDamage = true; - } else if (fTotalBlocks != fpImg->GetNumBlocks()) { - if (fTotalBlocks != 65535 || fpImg->GetNumBlocks() != 65536) { - WMSG2(" ProDOS WARNING: total (%u) != img (%ld)\n", - fTotalBlocks, fpImg->GetNumBlocks()); - // could AddNote here, but not really necessary - } + if (fTotalBlocks <= kVolHeaderBlock) { + /* incr to min; don't use max, or bitmap count may be too large */ + WMSG1(" ProDOS found tiny fTotalBlocks (%d), increasing to minimum\n", + fTotalBlocks); + fpImg->AddNote(DiskImg::kNoteWarning, + "ProDOS filesystem blockcount (%d) too small, setting to %d.", + fTotalBlocks, kMinReasonableBlocks); + fTotalBlocks = kMinReasonableBlocks; + fEarlyDamage = true; + } else if (fTotalBlocks != fpImg->GetNumBlocks()) { + if (fTotalBlocks != 65535 || fpImg->GetNumBlocks() != 65536) { + WMSG2(" ProDOS WARNING: total (%u) != img (%ld)\n", + fTotalBlocks, fpImg->GetNumBlocks()); + // could AddNote here, but not really necessary + } - /* - * For safety (esp. vol bitmap read), constrain fTotalBlocks. We might - * consider not doing this for ".hdv", which can start small and then - * expand as files are added. (Check "fExpanded".) - */ - if (fTotalBlocks > fpImg->GetNumBlocks()) { - fpImg->AddNote(DiskImg::kNoteWarning, - "ProDOS filesystem blockcount (%d) exceeds disk image blocks (%ld).", - fTotalBlocks, fpImg->GetNumBlocks()); - fTotalBlocks = (unsigned short) fpImg->GetNumBlocks(); - fEarlyDamage = true; - } - } + /* + * For safety (esp. vol bitmap read), constrain fTotalBlocks. We might + * consider not doing this for ".hdv", which can start small and then + * expand as files are added. (Check "fExpanded".) + */ + if (fTotalBlocks > fpImg->GetNumBlocks()) { + fpImg->AddNote(DiskImg::kNoteWarning, + "ProDOS filesystem blockcount (%d) exceeds disk image blocks (%ld).", + fTotalBlocks, fpImg->GetNumBlocks()); + fTotalBlocks = (unsigned short) fpImg->GetNumBlocks(); + fEarlyDamage = true; + } + } - /* - * Test for funky volume bitmap pointer. Some disks (e.g. /RAM and - * ProSel-16) truncate the volume directory to eke a little more storage - * out of a disk. There's nothing wrong with that, but we don't want to - * try to use a volume bitmap pointer of zero or 0xffff, because it's - * probably garbage. - */ - if (fBitMapPointer != kExpectedBitmapStart) { - if (fBitMapPointer <= kVolHeaderBlock || - fBitMapPointer > kExpectedBitmapStart) - { - fpImg->AddNote(DiskImg::kNoteWarning, - "Volume bitmap pointer (%d) is probably invalid.", - fBitMapPointer); - fBitMapPointer = 6; // just fix it and hope for the best - fEarlyDamage = true; - } else { - fpImg->AddNote(DiskImg::kNoteInfo, - "Unusual volume bitmap start (%d).", fBitMapPointer); - // try it and see - } - } + /* + * Test for funky volume bitmap pointer. Some disks (e.g. /RAM and + * ProSel-16) truncate the volume directory to eke a little more storage + * out of a disk. There's nothing wrong with that, but we don't want to + * try to use a volume bitmap pointer of zero or 0xffff, because it's + * probably garbage. + */ + if (fBitMapPointer != kExpectedBitmapStart) { + if (fBitMapPointer <= kVolHeaderBlock || + fBitMapPointer > kExpectedBitmapStart) + { + fpImg->AddNote(DiskImg::kNoteWarning, + "Volume bitmap pointer (%d) is probably invalid.", + fBitMapPointer); + fBitMapPointer = 6; // just fix it and hope for the best + fEarlyDamage = true; + } else { + fpImg->AddNote(DiskImg::kNoteInfo, + "Unusual volume bitmap start (%d).", fBitMapPointer); + // try it and see + } + } - SetVolumeID(); + SetVolumeID(); - /* - * Create a "magic" directory entry for the volume directory. - * - * Normally these values are pulled out of the file entry in the parent - * directory. Here, we synthesize them from the volume dir header. - */ - A2FileProDOS* pFile; - pFile = new A2FileProDOS(this); - if (pFile == nil) { - dierr = kDIErrMalloc; - goto bail; - } + /* + * Create a "magic" directory entry for the volume directory. + * + * Normally these values are pulled out of the file entry in the parent + * directory. Here, we synthesize them from the volume dir header. + */ + A2FileProDOS* pFile; + pFile = new A2FileProDOS(this); + if (pFile == nil) { + dierr = kDIErrMalloc; + goto bail; + } - A2FileProDOS::DirEntry* pEntry; - pEntry = &pFile->fDirEntry; + A2FileProDOS::DirEntry* pEntry; + pEntry = &pFile->fDirEntry; - int foundStorage; - foundStorage = (blkBuf[0x04] & 0xf0) >> 4; - if (foundStorage != A2FileProDOS::kStorageVolumeDirHeader) { - WMSG1(" ProDOS WARNING: unexpected vol dir file type %d\n", - pEntry->storageType); - /* keep going */ - } - pEntry->storageType = A2FileProDOS::kStorageVolumeDirHeader; - strcpy(pEntry->fileName, fVolumeName); - //nameLen = blkBuf[0x04] & 0x0f; - //memcpy(pEntry->fileName, &blkBuf[0x05], nameLen); - //pEntry->fileName[nameLen] = '\0'; - pFile->SetPathName(":", pEntry->fileName); - pEntry->fileName[nameLen] = '\0'; - pEntry->fileType = kTypeDIR; - pEntry->keyPointer = kVolHeaderBlock; - pEntry->blocksUsed = kVolDirExpectedNumBlocks; - pEntry->eof = kVolDirExpectedNumBlocks * 512; - pEntry->createWhen = GetLongLE(&blkBuf[0x1c]); - pEntry->version = blkBuf[0x20]; - pEntry->minVersion = blkBuf[0x21]; - pEntry->access = blkBuf[0x22]; - pEntry->auxType = 0; -// if (blkBuf[0x20] >= 5) - pEntry->modWhen = GetLongLE(&blkBuf[0x16]); - pEntry->headerPointer = 0; + int foundStorage; + foundStorage = (blkBuf[0x04] & 0xf0) >> 4; + if (foundStorage != A2FileProDOS::kStorageVolumeDirHeader) { + WMSG1(" ProDOS WARNING: unexpected vol dir file type %d\n", + pEntry->storageType); + /* keep going */ + } + pEntry->storageType = A2FileProDOS::kStorageVolumeDirHeader; + strcpy(pEntry->fileName, fVolumeName); + //nameLen = blkBuf[0x04] & 0x0f; + //memcpy(pEntry->fileName, &blkBuf[0x05], nameLen); + //pEntry->fileName[nameLen] = '\0'; + pFile->SetPathName(":", pEntry->fileName); + pEntry->fileName[nameLen] = '\0'; + pEntry->fileType = kTypeDIR; + pEntry->keyPointer = kVolHeaderBlock; + pEntry->blocksUsed = kVolDirExpectedNumBlocks; + pEntry->eof = kVolDirExpectedNumBlocks * 512; + pEntry->createWhen = GetLongLE(&blkBuf[0x1c]); + pEntry->version = blkBuf[0x20]; + pEntry->minVersion = blkBuf[0x21]; + pEntry->access = blkBuf[0x22]; + pEntry->auxType = 0; +// if (blkBuf[0x20] >= 5) + pEntry->modWhen = GetLongLE(&blkBuf[0x16]); + pEntry->headerPointer = 0; - pFile->fSparseDataEof = pEntry->eof; - pFile->fSparseRsrcEof = -1; + pFile->fSparseDataEof = pEntry->eof; + pFile->fSparseRsrcEof = -1; - AddFileToList(pFile); + AddFileToList(pFile); bail: - return dierr; + return dierr; } /* @@ -394,7 +394,7 @@ bail: void DiskFSProDOS::SetVolumeID(void) { - sprintf(fVolumeID, "ProDOS /%s", fVolumeName); + sprintf(fVolumeID, "ProDOS /%s", fVolumeName); } @@ -404,20 +404,20 @@ DiskFSProDOS::SetVolumeID(void) void DiskFSProDOS::DumpVolHeader(void) { - WMSG1(" ProDOS volume header for '%s'\n", fVolumeName); - WMSG4(" CreateWhen=0x%08lx access=0x%02x bitmap=%d totalbl=%d\n", - fCreateWhen, fAccess, fBitMapPointer, fTotalBlocks); + WMSG1(" ProDOS volume header for '%s'\n", fVolumeName); + WMSG4(" CreateWhen=0x%08lx access=0x%02x bitmap=%d totalbl=%d\n", + fCreateWhen, fAccess, fBitMapPointer, fTotalBlocks); - time_t when; - when = A2FileProDOS::ConvertProDate(fCreateWhen); - WMSG1(" CreateWhen is %.24s\n", ctime(&when)); + time_t when; + when = A2FileProDOS::ConvertProDate(fCreateWhen); + WMSG1(" CreateWhen is %.24s\n", ctime(&when)); - //WMSG4(" prev=%d next=%d bitmap=%d total=%d\n", - // fPrevBlock, fNextBlock, fBitMapPointer, fTotalBlocks); - //WMSG2(" create date=0x%08lx access=0x%02x\n", fCreateWhen, fAccess); - //WMSG4(" version=%d minVersion=%d entryLen=%d epb=%d\n", - // fVersion, fMinVersion, fEntryLength, fEntriesPerBlock); - //WMSG1(" volume dir fileCount=%d\n", fFileCount); + //WMSG4(" prev=%d next=%d bitmap=%d total=%d\n", + // fPrevBlock, fNextBlock, fBitMapPointer, fTotalBlocks); + //WMSG2(" create date=0x%08lx access=0x%02x\n", fCreateWhen, fAccess); + //WMSG4(" version=%d minVersion=%d entryLen=%d epb=%d\n", + // fVersion, fMinVersion, fEntryLength, fEntriesPerBlock); + //WMSG1(" volume dir fileCount=%d\n", fFileCount); } @@ -429,38 +429,38 @@ DiskFSProDOS::DumpVolHeader(void) DIError DiskFSProDOS::LoadVolBitmap(void) { - DIError dierr = kDIErrNone; - int bitBlock, numBlocks; + DIError dierr = kDIErrNone; + int bitBlock, numBlocks; - if (fBitMapPointer <= kVolHeaderBlock) - return kDIErrBadDiskImage; - if (fTotalBlocks <= kVolHeaderBlock) - return kDIErrBadDiskImage; + if (fBitMapPointer <= kVolHeaderBlock) + return kDIErrBadDiskImage; + if (fTotalBlocks <= kVolHeaderBlock) + return kDIErrBadDiskImage; - /* should not already be allocated */ - assert(fBlockUseMap == nil); - delete[] fBlockUseMap; // just in case + /* should not already be allocated */ + assert(fBlockUseMap == nil); + delete[] fBlockUseMap; // just in case - bitBlock = fBitMapPointer; + bitBlock = fBitMapPointer; - numBlocks = GetNumBitmapBlocks(); // based on fTotalBlocks - assert(numBlocks > 0); + numBlocks = GetNumBitmapBlocks(); // based on fTotalBlocks + assert(numBlocks > 0); - fBlockUseMap = new unsigned char[kBlkSize * numBlocks]; - if (fBlockUseMap == nil) - return kDIErrMalloc; + fBlockUseMap = new unsigned char[kBlkSize * numBlocks]; + if (fBlockUseMap == nil) + return kDIErrMalloc; - while (numBlocks--) { - dierr = fpImg->ReadBlock(bitBlock + numBlocks, - fBlockUseMap + kBlkSize * numBlocks); - if (dierr != kDIErrNone) { - delete[] fBlockUseMap; - fBlockUseMap = nil; - return dierr; - } - } + while (numBlocks--) { + dierr = fpImg->ReadBlock(bitBlock + numBlocks, + fBlockUseMap + kBlkSize * numBlocks); + if (dierr != kDIErrNone) { + delete[] fBlockUseMap; + fBlockUseMap = nil; + return dierr; + } + } - return kDIErrNone; + return kDIErrNone; } /* @@ -469,29 +469,29 @@ DiskFSProDOS::LoadVolBitmap(void) DIError DiskFSProDOS::SaveVolBitmap(void) { - DIError dierr = kDIErrNone; - int bitBlock, numBlocks; + DIError dierr = kDIErrNone; + int bitBlock, numBlocks; - if (fBlockUseMap == nil) { - assert(false); - return kDIErrNotReady; - } - assert(fBitMapPointer > kVolHeaderBlock); - assert(fTotalBlocks > kVolHeaderBlock); + if (fBlockUseMap == nil) { + assert(false); + return kDIErrNotReady; + } + assert(fBitMapPointer > kVolHeaderBlock); + assert(fTotalBlocks > kVolHeaderBlock); - bitBlock = fBitMapPointer; + bitBlock = fBitMapPointer; - numBlocks = GetNumBitmapBlocks(); - assert(numBlocks > 0); + numBlocks = GetNumBitmapBlocks(); + assert(numBlocks > 0); - while (numBlocks--) { - dierr = fpImg->WriteBlock(bitBlock + numBlocks, - fBlockUseMap + kBlkSize * numBlocks); - if (dierr != kDIErrNone) - return dierr; - } + while (numBlocks--) { + dierr = fpImg->WriteBlock(bitBlock + numBlocks, + fBlockUseMap + kBlkSize * numBlocks); + if (dierr != kDIErrNone) + return dierr; + } - return kDIErrNone; + return kDIErrNone; } /* @@ -502,8 +502,8 @@ DiskFSProDOS::SaveVolBitmap(void) void DiskFSProDOS::FreeVolBitmap(void) { - delete[] fBlockUseMap; - fBlockUseMap = nil; + delete[] fBlockUseMap; + fBlockUseMap = nil; } /* @@ -513,58 +513,58 @@ DiskFSProDOS::FreeVolBitmap(void) DIError DiskFSProDOS::ScanVolBitmap(void) { - DIError dierr; + DIError dierr; - dierr = LoadVolBitmap(); - if (dierr != kDIErrNone) { - WMSG1(" ProDOS failed to load volume bitmap (err=%d)\n", dierr); - return dierr; - } + dierr = LoadVolBitmap(); + if (dierr != kDIErrNone) { + WMSG1(" ProDOS failed to load volume bitmap (err=%d)\n", dierr); + return dierr; + } - assert(fBlockUseMap != nil); + assert(fBlockUseMap != nil); - /* mark the boot blocks as system */ - SetBlockUsage(0, VolumeUsage::kChunkPurposeSystem); - SetBlockUsage(1, VolumeUsage::kChunkPurposeSystem); + /* mark the boot blocks as system */ + SetBlockUsage(0, VolumeUsage::kChunkPurposeSystem); + SetBlockUsage(1, VolumeUsage::kChunkPurposeSystem); - /* mark the bitmap blocks as system */ - int i; - for (i = GetNumBitmapBlocks(); i > 0; i--) - SetBlockUsage(fBitMapPointer + i -1, VolumeUsage::kChunkPurposeSystem); + /* mark the bitmap blocks as system */ + int i; + for (i = GetNumBitmapBlocks(); i > 0; i--) + SetBlockUsage(fBitMapPointer + i -1, VolumeUsage::kChunkPurposeSystem); - /* - * Set the "isMarkedUsed" flag in VolumeUsage for all used blocks. - */ - VolumeUsage::ChunkState cstate; + /* + * Set the "isMarkedUsed" flag in VolumeUsage for all used blocks. + */ + VolumeUsage::ChunkState cstate; - long block = 0; - long numBytes = (fTotalBlocks + 7) / 8; - for (i = 0; i < numBytes; i++) { - unsigned char val = fBlockUseMap[i]; + long block = 0; + long numBytes = (fTotalBlocks + 7) / 8; + for (i = 0; i < numBytes; i++) { + unsigned char val = fBlockUseMap[i]; - for (int j = 0; j < 8; j++) { - if (!(val & 0x80)) { - /* block is in use, mark it */ - if (fVolumeUsage.GetChunkState(block, &cstate) != kDIErrNone) - { - assert(false); - // keep going, I guess - } - cstate.isMarkedUsed = true; - fVolumeUsage.SetChunkState(block, &cstate); - } - val <<= 1; - block++; + for (int j = 0; j < 8; j++) { + if (!(val & 0x80)) { + /* block is in use, mark it */ + if (fVolumeUsage.GetChunkState(block, &cstate) != kDIErrNone) + { + assert(false); + // keep going, I guess + } + cstate.isMarkedUsed = true; + fVolumeUsage.SetChunkState(block, &cstate); + } + val <<= 1; + block++; - if (block >= fTotalBlocks) - break; - } - if (block >= fTotalBlocks) - break; - } + if (block >= fTotalBlocks) + break; + } + if (block >= fTotalBlocks) + break; + } - FreeVolBitmap(); - return dierr; + FreeVolBitmap(); + return dierr; } /* @@ -573,31 +573,31 @@ DiskFSProDOS::ScanVolBitmap(void) DIError DiskFSProDOS::CreateEmptyBlockMap(void) { - DIError dierr; + DIError dierr; - /* load from disk; this is just to allocate the data structures */ - dierr = LoadVolBitmap(); - if (dierr != kDIErrNone) - return dierr; + /* load from disk; this is just to allocate the data structures */ + dierr = LoadVolBitmap(); + if (dierr != kDIErrNone) + return dierr; - /* - * Set the bits, block by block. Not the most efficient way, but it's - * fast enough, and it exercises the standard set of functions. - */ - long block; - long firstEmpty = - kVolHeaderBlock + kVolDirExpectedNumBlocks + GetNumBitmapBlocks(); - for (block = 0; block < firstEmpty; block++) - SetBlockUseEntry(block, true); - for ( ; block < fTotalBlocks; block++) - SetBlockUseEntry(block, false); + /* + * Set the bits, block by block. Not the most efficient way, but it's + * fast enough, and it exercises the standard set of functions. + */ + long block; + long firstEmpty = + kVolHeaderBlock + kVolDirExpectedNumBlocks + GetNumBitmapBlocks(); + for (block = 0; block < firstEmpty; block++) + SetBlockUseEntry(block, true); + for ( ; block < fTotalBlocks; block++) + SetBlockUseEntry(block, false); - dierr = SaveVolBitmap(); - FreeVolBitmap(); - if (dierr != kDIErrNone) - return dierr; + dierr = SaveVolBitmap(); + FreeVolBitmap(); + if (dierr != kDIErrNone) + return dierr; - return kDIErrNone; + return kDIErrNone; } /* @@ -608,18 +608,18 @@ DiskFSProDOS::CreateEmptyBlockMap(void) bool DiskFSProDOS::GetBlockUseEntry(long block) const { - assert(block >= 0 && block < fTotalBlocks); - assert(fBlockUseMap != nil); + assert(block >= 0 && block < fTotalBlocks); + assert(fBlockUseMap != nil); - int offset; - unsigned char mask; + int offset; + unsigned char mask; - offset = block / 8; - mask = 0x80 >> (block & 0x07); - if (fBlockUseMap[offset] & mask) - return false; - else - return true; + offset = block / 8; + mask = 0x80 >> (block & 0x07); + if (fBlockUseMap[offset] & mask) + return false; + else + return true; } /* @@ -628,23 +628,23 @@ DiskFSProDOS::GetBlockUseEntry(long block) const void DiskFSProDOS::SetBlockUseEntry(long block, bool inUse) { - assert(block >= 0 && block < fTotalBlocks); - assert(fBlockUseMap != nil); + assert(block >= 0 && block < fTotalBlocks); + assert(fBlockUseMap != nil); - if (block == 0 && !inUse) { - // shouldn't happen - assert(false); - } + if (block == 0 && !inUse) { + // shouldn't happen + assert(false); + } - int offset; - unsigned char mask; + int offset; + unsigned char mask; - offset = block / 8; - mask = 0x80 >> (block & 0x07); - if (!inUse) - fBlockUseMap[offset] |= mask; - else - fBlockUseMap[offset] &= ~mask; + offset = block / 8; + mask = 0x80 >> (block & 0x07); + if (!inUse) + fBlockUseMap[offset] |= mask; + else + fBlockUseMap[offset] &= ~mask; } /* @@ -655,23 +655,23 @@ DiskFSProDOS::SetBlockUseEntry(long block, bool inUse) bool DiskFSProDOS::ScanForExtraEntries(void) const { - assert(fBlockUseMap != nil); + assert(fBlockUseMap != nil); - int offset, endOffset; + int offset, endOffset; - /* sloppy: we're not checking for excess bits within last byte */ - offset = (fTotalBlocks / 8) +1; - endOffset = GetNumBitmapBlocks() * kBlkSize; + /* sloppy: we're not checking for excess bits within last byte */ + offset = (fTotalBlocks / 8) +1; + endOffset = GetNumBitmapBlocks() * kBlkSize; - while (offset < endOffset) { - if (fBlockUseMap[offset] != 0) { - WMSG2(" ProDOS found bogus bitmap junk 0x%02x at offset=%d\n", - fBlockUseMap[offset], offset); - return true; - } - offset++; - } - return false; + while (offset < endOffset) { + if (fBlockUseMap[offset] != 0) { + WMSG2(" ProDOS found bogus bitmap junk 0x%02x at offset=%d\n", + fBlockUseMap[offset], offset); + return true; + } + offset++; + } + return false; } /* @@ -684,53 +684,53 @@ DiskFSProDOS::ScanForExtraEntries(void) const long DiskFSProDOS::AllocBlock(void) { - assert(fBlockUseMap != nil); + assert(fBlockUseMap != nil); -#if 0 // whoa... this is REALLY slow - /* - * Run through the entire set of blocks until we find one that's not - * allocated. We could probably make this faster by scanning bytes and - * then shifting bits, but this is easier and fast enough. - * - * We don't scan block 0 because (a) it should never be available and - * (b) it has a special meaning in some circumstances. We could probably - * start at kVolHeaderBlock+kVolHeaderNumBlocks. - */ - long block; - for (block = kVolHeaderBlock; block < fTotalBlocks; block++) { - if (!GetBlockUseEntry(block)) { - SetBlockUseEntry(block, true); - return block; - } - } +#if 0 // whoa... this is REALLY slow + /* + * Run through the entire set of blocks until we find one that's not + * allocated. We could probably make this faster by scanning bytes and + * then shifting bits, but this is easier and fast enough. + * + * We don't scan block 0 because (a) it should never be available and + * (b) it has a special meaning in some circumstances. We could probably + * start at kVolHeaderBlock+kVolHeaderNumBlocks. + */ + long block; + for (block = kVolHeaderBlock; block < fTotalBlocks; block++) { + if (!GetBlockUseEntry(block)) { + SetBlockUseEntry(block, true); + return block; + } + } #endif - int offset; - int maxOffset = (fTotalBlocks + 7) / 8; + int offset; + int maxOffset = (fTotalBlocks + 7) / 8; - for (offset = 0; offset < maxOffset; offset++) { - if (fBlockUseMap[offset] != 0) { - /* got one, figure out which */ - int subBlock = 0; - unsigned char uch = fBlockUseMap[offset]; - while ((uch & 0x80) == 0) { - subBlock++; - uch <<= 1; - } + for (offset = 0; offset < maxOffset; offset++) { + if (fBlockUseMap[offset] != 0) { + /* got one, figure out which */ + int subBlock = 0; + unsigned char uch = fBlockUseMap[offset]; + while ((uch & 0x80) == 0) { + subBlock++; + uch <<= 1; + } - long block = offset * 8 + subBlock; - assert(!GetBlockUseEntry(block)); - SetBlockUseEntry(block, true); - if (block == 0 || block == 1) { - WMSG0("PRODOS: GLITCH: rejecting alloc of block 0\n"); - continue; - } - return block; - } - } + long block = offset * 8 + subBlock; + assert(!GetBlockUseEntry(block)); + SetBlockUseEntry(block, true); + if (block == 0 || block == 1) { + WMSG0("PRODOS: GLITCH: rejecting alloc of block 0\n"); + continue; + } + return block; + } + } - WMSG0("ProDOS: NOTE: AllocBlock just failed!\n"); - return -1; + WMSG0("ProDOS: NOTE: AllocBlock just failed!\n"); + return -1; } /* @@ -738,27 +738,27 @@ DiskFSProDOS::AllocBlock(void) */ DIError DiskFSProDOS::GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, - int* pUnitSize) const + int* pUnitSize) const { - DIError dierr; - long block, freeBlocks; - freeBlocks = 0; + DIError dierr; + long block, freeBlocks; + freeBlocks = 0; - dierr = const_cast(this)->LoadVolBitmap(); - if (dierr != kDIErrNone) - return dierr; + dierr = const_cast(this)->LoadVolBitmap(); + if (dierr != kDIErrNone) + return dierr; - for (block = 0; block < fTotalBlocks; block++) { - if (!GetBlockUseEntry(block)) - freeBlocks++; - } + for (block = 0; block < fTotalBlocks; block++) { + if (!GetBlockUseEntry(block)) + freeBlocks++; + } - *pTotalUnits = fTotalBlocks; - *pFreeUnits = freeBlocks; - *pUnitSize = kBlockSize; + *pTotalUnits = fTotalBlocks; + *pFreeUnits = freeBlocks; + *pUnitSize = kBlockSize; - const_cast(this)->FreeVolBitmap(); - return kDIErrNone; + const_cast(this)->FreeVolBitmap(); + return kDIErrNone; } @@ -770,17 +770,17 @@ DiskFSProDOS::GetFreeSpaceCount(long* pTotalUnits, long* pFreeUnits, void DiskFSProDOS::SetBlockUsage(long block, VolumeUsage::ChunkPurpose purpose) { - VolumeUsage::ChunkState cstate; + VolumeUsage::ChunkState cstate; - fVolumeUsage.GetChunkState(block, &cstate); - if (cstate.isUsed) { - cstate.purpose = VolumeUsage::kChunkPurposeConflict; - WMSG1(" ProDOS conflicting uses for bl=%ld\n", block); - } else { - cstate.isUsed = true; - cstate.purpose = purpose; - } - fVolumeUsage.SetChunkState(block, &cstate); + fVolumeUsage.GetChunkState(block, &cstate); + if (cstate.isUsed) { + cstate.purpose = VolumeUsage::kChunkPurposeConflict; + WMSG1(" ProDOS conflicting uses for bl=%ld\n", block); + } else { + cstate.isUsed = true; + cstate.purpose = purpose; + } + fVolumeUsage.SetChunkState(block, &cstate); } /* @@ -790,81 +790,81 @@ DiskFSProDOS::SetBlockUsage(long block, VolumeUsage::ChunkPurpose purpose) */ DIError DiskFSProDOS::RecursiveDirAdd(A2File* pParent, unsigned short dirBlock, - const char* basePath, int depth) + const char* basePath, int depth) { - DIError dierr = kDIErrNone; - DirHeader header; - unsigned char blkBuf[kBlkSize]; - int numEntries, iterations, foundCount; - bool first; + DIError dierr = kDIErrNone; + DirHeader header; + unsigned char blkBuf[kBlkSize]; + int numEntries, iterations, foundCount; + bool first; - /* if we get too deep, assume it's a loop */ - if (depth > kMaxDirectoryDepth) { - dierr = kDIErrDirectoryLoop; - goto bail; - } + /* if we get too deep, assume it's a loop */ + if (depth > kMaxDirectoryDepth) { + dierr = kDIErrDirectoryLoop; + goto bail; + } - if (dirBlock < kVolHeaderBlock || dirBlock >= fpImg->GetNumBlocks()) { - WMSG1(" ProDOS ERROR: directory block %u out of range\n", dirBlock); - dierr = kDIErrInvalidBlock; - goto bail; - } + if (dirBlock < kVolHeaderBlock || dirBlock >= fpImg->GetNumBlocks()) { + WMSG1(" ProDOS ERROR: directory block %u out of range\n", dirBlock); + dierr = kDIErrInvalidBlock; + goto bail; + } - numEntries = 1; - iterations = 0; - foundCount = 0; - first = true; + numEntries = 1; + iterations = 0; + foundCount = 0; + first = true; - while (dirBlock && iterations < kMaxCatalogIterations) { - dierr = fpImg->ReadBlock(dirBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; - if (pParent->IsVolumeDirectory()) - SetBlockUsage(dirBlock, VolumeUsage::kChunkPurposeVolumeDir); - else - SetBlockUsage(dirBlock, VolumeUsage::kChunkPurposeSubdir); + while (dirBlock && iterations < kMaxCatalogIterations) { + dierr = fpImg->ReadBlock(dirBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; + if (pParent->IsVolumeDirectory()) + SetBlockUsage(dirBlock, VolumeUsage::kChunkPurposeVolumeDir); + else + SetBlockUsage(dirBlock, VolumeUsage::kChunkPurposeSubdir); - if (first) { - /* this is the directory header entry */ - dierr = GetDirHeader(blkBuf, &header); - if (dierr != kDIErrNone) - goto bail; - numEntries = header.fileCount; - //WMSG1(" ProDOS got dir header numEntries = %d\n", numEntries); - } + if (first) { + /* this is the directory header entry */ + dierr = GetDirHeader(blkBuf, &header); + if (dierr != kDIErrNone) + goto bail; + numEntries = header.fileCount; + //WMSG1(" ProDOS got dir header numEntries = %d\n", numEntries); + } - /* slurp the entries out of this block */ - dierr = SlurpEntries(pParent, &header, blkBuf, first, &foundCount, - basePath, dirBlock, depth); - if (dierr != kDIErrNone) - goto bail; + /* slurp the entries out of this block */ + dierr = SlurpEntries(pParent, &header, blkBuf, first, &foundCount, + basePath, dirBlock, depth); + if (dierr != kDIErrNone) + goto bail; - dirBlock = GetShortLE(&blkBuf[0x02]); - if (dirBlock != 0 && - (dirBlock < 2 || dirBlock >= fpImg->GetNumBlocks())) - { - WMSG2(" ProDOS ERROR: invalid dir link block %u in base='%s'\n", - dirBlock, basePath); - dierr = kDIErrInvalidBlock; - goto bail; - } - first = false; - iterations++; - } - if (iterations == kMaxCatalogIterations) { - WMSG0(" ProDOS subdir iteration count exceeded\n"); - dierr = kDIErrDirectoryLoop; - goto bail; - } - if (foundCount != numEntries) { - /* not significant; just means somebody isn't updating correctly */ - WMSG3(" ProDOS WARNING: numEntries=%d foundCount=%d in base='%s'\n", - numEntries, foundCount, basePath); - } + dirBlock = GetShortLE(&blkBuf[0x02]); + if (dirBlock != 0 && + (dirBlock < 2 || dirBlock >= fpImg->GetNumBlocks())) + { + WMSG2(" ProDOS ERROR: invalid dir link block %u in base='%s'\n", + dirBlock, basePath); + dierr = kDIErrInvalidBlock; + goto bail; + } + first = false; + iterations++; + } + if (iterations == kMaxCatalogIterations) { + WMSG0(" ProDOS subdir iteration count exceeded\n"); + dierr = kDIErrDirectoryLoop; + goto bail; + } + if (foundCount != numEntries) { + /* not significant; just means somebody isn't updating correctly */ + WMSG3(" ProDOS WARNING: numEntries=%d foundCount=%d in base='%s'\n", + numEntries, foundCount, basePath); + } bail: - return dierr; + return dierr; } /* @@ -876,91 +876,91 @@ bail: */ DIError DiskFSProDOS::SlurpEntries(A2File* pParent, const DirHeader* pHeader, - const unsigned char* blkBuf, bool skipFirst, int* pCount, - const char* basePath, unsigned short thisBlock, int depth) + const unsigned char* blkBuf, bool skipFirst, int* pCount, + const char* basePath, unsigned short thisBlock, int depth) { - DIError dierr = kDIErrNone; - int entriesThisBlock = pHeader->entriesPerBlock; - const unsigned char* entryBuf; - A2FileProDOS* pFile; + DIError dierr = kDIErrNone; + int entriesThisBlock = pHeader->entriesPerBlock; + const unsigned char* entryBuf; + A2FileProDOS* pFile; - int idx = 0; - entryBuf = &blkBuf[0x04]; - if (skipFirst) { - entriesThisBlock--; - entryBuf += pHeader->entryLength; - idx++; - } + int idx = 0; + entryBuf = &blkBuf[0x04]; + if (skipFirst) { + entriesThisBlock--; + entryBuf += pHeader->entryLength; + idx++; + } - for ( ; entriesThisBlock > 0 ; - entriesThisBlock--, idx++, entryBuf += pHeader->entryLength) - { - if (entryBuf >= blkBuf + kBlkSize) { - WMSG0(" ProDOS whoops, just walked out of dirent buffer\n"); - return kDIErrBadDirectory; - } + for ( ; entriesThisBlock > 0 ; + entriesThisBlock--, idx++, entryBuf += pHeader->entryLength) + { + if (entryBuf >= blkBuf + kBlkSize) { + WMSG0(" ProDOS whoops, just walked out of dirent buffer\n"); + return kDIErrBadDirectory; + } - if ((entryBuf[0x00] & 0xf0) == A2FileProDOS::kStorageDeleted) { - /* skip deleted entries */ - continue; - } + if ((entryBuf[0x00] & 0xf0) == A2FileProDOS::kStorageDeleted) { + /* skip deleted entries */ + continue; + } - pFile = new A2FileProDOS(this); - if (pFile == nil) { - dierr = kDIErrMalloc; - goto bail; - } + pFile = new A2FileProDOS(this); + if (pFile == nil) { + dierr = kDIErrMalloc; + goto bail; + } - A2FileProDOS::DirEntry* pEntry; - pEntry = &pFile->fDirEntry; - A2FileProDOS::InitDirEntry(pEntry, entryBuf); + A2FileProDOS::DirEntry* pEntry; + pEntry = &pFile->fDirEntry; + A2FileProDOS::InitDirEntry(pEntry, entryBuf); - pFile->SetParent(pParent); - pFile->fParentDirBlock = thisBlock; - pFile->fParentDirIdx = idx; + pFile->SetParent(pParent); + pFile->fParentDirBlock = thisBlock; + pFile->fParentDirIdx = idx; - pFile->SetPathName(basePath, pEntry->fileName); + pFile->SetPathName(basePath, pEntry->fileName); - if (pEntry->keyPointer <= kVolHeaderBlock) { - WMSG2("ProDOS invalid key pointer %d on '%s'\n", - pEntry->keyPointer, pFile->GetPathName()); - pFile->SetQuality(A2File::kQualityDamaged); - } else - if (pEntry->storageType == A2FileProDOS::kStorageExtended) { - dierr = ReadExtendedInfo(pFile); - if (dierr != kDIErrNone) { - pFile->SetQuality(A2File::kQualityDamaged); - dierr = kDIErrNone; - } - } + if (pEntry->keyPointer <= kVolHeaderBlock) { + WMSG2("ProDOS invalid key pointer %d on '%s'\n", + pEntry->keyPointer, pFile->GetPathName()); + pFile->SetQuality(A2File::kQualityDamaged); + } else + if (pEntry->storageType == A2FileProDOS::kStorageExtended) { + dierr = ReadExtendedInfo(pFile); + if (dierr != kDIErrNone) { + pFile->SetQuality(A2File::kQualityDamaged); + dierr = kDIErrNone; + } + } - //pFile->Dump(); - AddFileToList(pFile); - (*pCount)++; + //pFile->Dump(); + AddFileToList(pFile); + (*pCount)++; - if (!fpImg->UpdateScanProgress(nil)) { - WMSG0(" ProDOS cancelled by user\n"); - dierr = kDIErrCancelled; - goto bail; - } + if (!fpImg->UpdateScanProgress(nil)) { + WMSG0(" ProDOS cancelled by user\n"); + dierr = kDIErrCancelled; + goto bail; + } - if (pEntry->storageType == A2FileProDOS::kStorageDirectory) { - // don't need to check for kStorageVolumeDirHeader here - dierr = RecursiveDirAdd(pFile, pEntry->keyPointer, - pFile->GetPathName(), depth+1); - if (dierr != kDIErrNone) { - if (dierr == kDIErrCancelled) - goto bail; + if (pEntry->storageType == A2FileProDOS::kStorageDirectory) { + // don't need to check for kStorageVolumeDirHeader here + dierr = RecursiveDirAdd(pFile, pEntry->keyPointer, + pFile->GetPathName(), depth+1); + if (dierr != kDIErrNone) { + if (dierr == kDIErrCancelled) + goto bail; - /* mark subdir as damaged and keep going */ - pFile->SetQuality(A2File::kQualityDamaged); - dierr = kDIErrNone; - } - } - } + /* mark subdir as damaged and keep going */ + pFile->SetQuality(A2File::kQualityDamaged); + dierr = kDIErrNone; + } + } + } bail: - return dierr; + return dierr; } @@ -970,39 +970,39 @@ bail: DIError DiskFSProDOS::GetDirHeader(const unsigned char* blkBuf, DirHeader* pHeader) { - int nameLen; + int nameLen; - pHeader->storageType = (blkBuf[0x04] & 0xf0) >> 4; - if (pHeader->storageType != A2FileProDOS::kStorageSubdirHeader && - pHeader->storageType != A2FileProDOS::kStorageVolumeDirHeader) - { - WMSG1(" ProDOS WARNING: subdir header has wrong storage type (%d)\n", - pHeader->storageType); - /* keep going... might be bad idea */ - } - nameLen = blkBuf[0x04] & 0x0f; - memcpy(pHeader->dirName, &blkBuf[0x05], nameLen); - pHeader->dirName[nameLen] = '\0'; - pHeader->createWhen = GetLongLE(&blkBuf[0x1c]); - pHeader->version = blkBuf[0x20]; - pHeader->minVersion = blkBuf[0x21]; - pHeader->access = blkBuf[0x22]; - pHeader->entryLength = blkBuf[0x23]; - pHeader->entriesPerBlock = blkBuf[0x24]; - pHeader->fileCount = GetShortLE(&blkBuf[0x25]); - pHeader->parentPointer = GetShortLE(&blkBuf[0x27]); - pHeader->parentEntry = blkBuf[0x29]; - pHeader->parentEntryLength = blkBuf[0x2a]; + pHeader->storageType = (blkBuf[0x04] & 0xf0) >> 4; + if (pHeader->storageType != A2FileProDOS::kStorageSubdirHeader && + pHeader->storageType != A2FileProDOS::kStorageVolumeDirHeader) + { + WMSG1(" ProDOS WARNING: subdir header has wrong storage type (%d)\n", + pHeader->storageType); + /* keep going... might be bad idea */ + } + nameLen = blkBuf[0x04] & 0x0f; + memcpy(pHeader->dirName, &blkBuf[0x05], nameLen); + pHeader->dirName[nameLen] = '\0'; + pHeader->createWhen = GetLongLE(&blkBuf[0x1c]); + pHeader->version = blkBuf[0x20]; + pHeader->minVersion = blkBuf[0x21]; + pHeader->access = blkBuf[0x22]; + pHeader->entryLength = blkBuf[0x23]; + pHeader->entriesPerBlock = blkBuf[0x24]; + pHeader->fileCount = GetShortLE(&blkBuf[0x25]); + pHeader->parentPointer = GetShortLE(&blkBuf[0x27]); + pHeader->parentEntry = blkBuf[0x29]; + pHeader->parentEntryLength = blkBuf[0x2a]; - if (pHeader->entryLength * pHeader->entriesPerBlock > kBlkSize || - pHeader->entryLength * pHeader->entriesPerBlock == 0) - { - WMSG2(" ProDOS invalid subdir header: entryLen=%d, entriesPerBlock=%d\n", - pHeader->entryLength, pHeader->entriesPerBlock); - return kDIErrBadDirectory; - } + if (pHeader->entryLength * pHeader->entriesPerBlock > kBlkSize || + pHeader->entryLength * pHeader->entriesPerBlock == 0) + { + WMSG2(" ProDOS invalid subdir header: entryLen=%d, entriesPerBlock=%d\n", + pHeader->entryLength, pHeader->entriesPerBlock); + return kDIErrBadDirectory; + } - return kDIErrNone; + return kDIErrNone; } /* @@ -1014,38 +1014,38 @@ DiskFSProDOS::GetDirHeader(const unsigned char* blkBuf, DirHeader* pHeader) DIError DiskFSProDOS::ReadExtendedInfo(A2FileProDOS* pFile) { - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; - dierr = fpImg->ReadBlock(pFile->fDirEntry.keyPointer, blkBuf); - if (dierr != kDIErrNone) { - WMSG1(" ProDOS ReadExtendedInfo: unable to read key block %d\n", - pFile->fDirEntry.keyPointer); - goto bail; - } + dierr = fpImg->ReadBlock(pFile->fDirEntry.keyPointer, blkBuf); + if (dierr != kDIErrNone) { + WMSG1(" ProDOS ReadExtendedInfo: unable to read key block %d\n", + pFile->fDirEntry.keyPointer); + goto bail; + } - pFile->fExtData.storageType = blkBuf[0x0000] & 0x0f; - pFile->fExtData.keyBlock = GetShortLE(&blkBuf[0x0001]); - pFile->fExtData.blocksUsed = GetShortLE(&blkBuf[0x0003]); - pFile->fExtData.eof = GetLongLE(&blkBuf[0x0005]); - pFile->fExtData.eof &= 0x00ffffff; + pFile->fExtData.storageType = blkBuf[0x0000] & 0x0f; + pFile->fExtData.keyBlock = GetShortLE(&blkBuf[0x0001]); + pFile->fExtData.blocksUsed = GetShortLE(&blkBuf[0x0003]); + pFile->fExtData.eof = GetLongLE(&blkBuf[0x0005]); + pFile->fExtData.eof &= 0x00ffffff; - pFile->fExtRsrc.storageType = blkBuf[0x0100] & 0x0f; - pFile->fExtRsrc.keyBlock = GetShortLE(&blkBuf[0x0101]); - pFile->fExtRsrc.blocksUsed = GetShortLE(&blkBuf[0x0103]); - pFile->fExtRsrc.eof = GetLongLE(&blkBuf[0x0105]); - pFile->fExtRsrc.eof &= 0x00ffffff; + pFile->fExtRsrc.storageType = blkBuf[0x0100] & 0x0f; + pFile->fExtRsrc.keyBlock = GetShortLE(&blkBuf[0x0101]); + pFile->fExtRsrc.blocksUsed = GetShortLE(&blkBuf[0x0103]); + pFile->fExtRsrc.eof = GetLongLE(&blkBuf[0x0105]); + pFile->fExtRsrc.eof &= 0x00ffffff; if (pFile->fExtData.keyBlock <= kVolHeaderBlock || pFile->fExtRsrc.keyBlock <= kVolHeaderBlock) { - WMSG2(" ProDOS ReadExtendedInfo: found bad extended key blocks %d/%d\n", - pFile->fExtData.keyBlock, pFile->fExtRsrc.keyBlock); + WMSG2(" ProDOS ReadExtendedInfo: found bad extended key blocks %d/%d\n", + pFile->fExtData.keyBlock, pFile->fExtRsrc.keyBlock); return kDIErrBadFile; } bail: - return dierr; + return dierr; } /* @@ -1058,140 +1058,140 @@ bail: DIError DiskFSProDOS::ScanFileUsage(void) { - DIError dierr = kDIErrNone; - A2FileProDOS* pFile; - long blockCount, indexCount, sparseCount; - unsigned short* blockList = nil; - unsigned short* indexList = nil; + DIError dierr = kDIErrNone; + A2FileProDOS* pFile; + long blockCount, indexCount, sparseCount; + unsigned short* blockList = nil; + unsigned short* indexList = nil; - pFile = (A2FileProDOS*) GetNextFile(nil); - while (pFile != nil) { - if (!fpImg->UpdateScanProgress(nil)) { - WMSG0(" ProDOS cancelled by user\n"); - dierr = kDIErrCancelled; - goto bail; - } + pFile = (A2FileProDOS*) GetNextFile(nil); + while (pFile != nil) { + if (!fpImg->UpdateScanProgress(nil)) { + WMSG0(" ProDOS cancelled by user\n"); + dierr = kDIErrCancelled; + goto bail; + } - //pFile->Dump(); - if (pFile->GetQuality() == A2File::kQualityDamaged) - goto skip; + //pFile->Dump(); + if (pFile->GetQuality() == A2File::kQualityDamaged) + goto skip; - if (pFile->fDirEntry.storageType == A2FileProDOS::kStorageExtended) { - /* resource fork */ - if (!A2FileProDOS::IsRegularFile(pFile->fExtRsrc.storageType)) { - /* not expecting to find a directory here, but it happens */ - dierr = kDIErrBadFile; - } else { - dierr = pFile->LoadBlockList(pFile->fExtRsrc.storageType, - pFile->fExtRsrc.keyBlock, pFile->fExtRsrc.eof, - &blockCount, &blockList, &indexCount, &indexList); - } - if (dierr != kDIErrNone) { - WMSG1(" ProDOS skipping scan rsrc '%s'\n", - pFile->fDirEntry.fileName); - pFile->SetQuality(A2File::kQualityDamaged); - goto skip; - } - ScanBlockList(blockCount, blockList, indexCount, indexList, - &sparseCount); - pFile->fSparseRsrcEof = - (di_off_t) pFile->fExtRsrc.eof - sparseCount * kBlkSize; - //WMSG3(" SparseCount %d rsrcEof %d '%s'\n", - // sparseCount, pFile->fSparseRsrcEof, pFile->fDirEntry.fileName); - delete[] blockList; - blockList = nil; - delete[] indexList; - indexList = nil; + if (pFile->fDirEntry.storageType == A2FileProDOS::kStorageExtended) { + /* resource fork */ + if (!A2FileProDOS::IsRegularFile(pFile->fExtRsrc.storageType)) { + /* not expecting to find a directory here, but it happens */ + dierr = kDIErrBadFile; + } else { + dierr = pFile->LoadBlockList(pFile->fExtRsrc.storageType, + pFile->fExtRsrc.keyBlock, pFile->fExtRsrc.eof, + &blockCount, &blockList, &indexCount, &indexList); + } + if (dierr != kDIErrNone) { + WMSG1(" ProDOS skipping scan rsrc '%s'\n", + pFile->fDirEntry.fileName); + pFile->SetQuality(A2File::kQualityDamaged); + goto skip; + } + ScanBlockList(blockCount, blockList, indexCount, indexList, + &sparseCount); + pFile->fSparseRsrcEof = + (di_off_t) pFile->fExtRsrc.eof - sparseCount * kBlkSize; + //WMSG3(" SparseCount %d rsrcEof %d '%s'\n", + // sparseCount, pFile->fSparseRsrcEof, pFile->fDirEntry.fileName); + delete[] blockList; + blockList = nil; + delete[] indexList; + indexList = nil; - /* data fork */ - if (!A2FileProDOS::IsRegularFile(pFile->fExtRsrc.storageType)) { - dierr = kDIErrBadFile; - } else { - dierr = pFile->LoadBlockList(pFile->fExtData.storageType, - pFile->fExtData.keyBlock, pFile->fExtData.eof, - &blockCount, &blockList, &indexCount, &indexList); - } - if (dierr != kDIErrNone) { - WMSG1(" ProDOS skipping scan data '%s'\n", - pFile->fDirEntry.fileName); - pFile->SetQuality(A2File::kQualityDamaged); - goto skip; - } - ScanBlockList(blockCount, blockList, indexCount, indexList, - &sparseCount); - pFile->fSparseDataEof = - (di_off_t) pFile->fExtData.eof - sparseCount * kBlkSize; - //WMSG3(" SparseCount %d dataEof %d '%s'\n", - // sparseCount, pFile->fSparseDataEof, pFile->fDirEntry.fileName); - delete[] blockList; - blockList = nil; - delete[] indexList; - indexList = nil; + /* data fork */ + if (!A2FileProDOS::IsRegularFile(pFile->fExtRsrc.storageType)) { + dierr = kDIErrBadFile; + } else { + dierr = pFile->LoadBlockList(pFile->fExtData.storageType, + pFile->fExtData.keyBlock, pFile->fExtData.eof, + &blockCount, &blockList, &indexCount, &indexList); + } + if (dierr != kDIErrNone) { + WMSG1(" ProDOS skipping scan data '%s'\n", + pFile->fDirEntry.fileName); + pFile->SetQuality(A2File::kQualityDamaged); + goto skip; + } + ScanBlockList(blockCount, blockList, indexCount, indexList, + &sparseCount); + pFile->fSparseDataEof = + (di_off_t) pFile->fExtData.eof - sparseCount * kBlkSize; + //WMSG3(" SparseCount %d dataEof %d '%s'\n", + // sparseCount, pFile->fSparseDataEof, pFile->fDirEntry.fileName); + delete[] blockList; + blockList = nil; + delete[] indexList; + indexList = nil; - /* mark the extended key block as in-use */ - SetBlockUsage(pFile->fDirEntry.keyPointer, - VolumeUsage::kChunkPurposeFileStruct); - } else if (pFile->fDirEntry.storageType == A2FileProDOS::kStorageDirectory || - pFile->fDirEntry.storageType == A2FileProDOS::kStorageVolumeDirHeader) - { - /* we already got these during the recursive descent */ - /* (could do them here if we used "fake" directory entry - for volume dir to lead off the recursion) */ - goto skip; - } else if (pFile->fDirEntry.storageType == A2FileProDOS::kStorageSeedling || - pFile->fDirEntry.storageType == A2FileProDOS::kStorageSapling || - pFile->fDirEntry.storageType == A2FileProDOS::kStorageTree) - { - /* standard file */ - dierr = pFile->LoadBlockList(pFile->fDirEntry.storageType, - pFile->fDirEntry.keyPointer, pFile->fDirEntry.eof, - &blockCount, &blockList, &indexCount, &indexList); - if (dierr != kDIErrNone) { - WMSG1(" ProDOS skipping scan '%s'\n", - pFile->fDirEntry.fileName); - pFile->SetQuality(A2File::kQualityDamaged); - goto skip; - } - ScanBlockList(blockCount, blockList, indexCount, indexList, - &sparseCount); - pFile->fSparseDataEof = - (di_off_t) pFile->fDirEntry.eof - sparseCount * kBlkSize; - //WMSG4(" +++ sparseCount=%ld blockCount=%ld sparseDataEof=%ld '%s'\n", - // sparseCount, blockCount, (long) pFile->fSparseDataEof, - // pFile->fDirEntry.fileName); + /* mark the extended key block as in-use */ + SetBlockUsage(pFile->fDirEntry.keyPointer, + VolumeUsage::kChunkPurposeFileStruct); + } else if (pFile->fDirEntry.storageType == A2FileProDOS::kStorageDirectory || + pFile->fDirEntry.storageType == A2FileProDOS::kStorageVolumeDirHeader) + { + /* we already got these during the recursive descent */ + /* (could do them here if we used "fake" directory entry + for volume dir to lead off the recursion) */ + goto skip; + } else if (pFile->fDirEntry.storageType == A2FileProDOS::kStorageSeedling || + pFile->fDirEntry.storageType == A2FileProDOS::kStorageSapling || + pFile->fDirEntry.storageType == A2FileProDOS::kStorageTree) + { + /* standard file */ + dierr = pFile->LoadBlockList(pFile->fDirEntry.storageType, + pFile->fDirEntry.keyPointer, pFile->fDirEntry.eof, + &blockCount, &blockList, &indexCount, &indexList); + if (dierr != kDIErrNone) { + WMSG1(" ProDOS skipping scan '%s'\n", + pFile->fDirEntry.fileName); + pFile->SetQuality(A2File::kQualityDamaged); + goto skip; + } + ScanBlockList(blockCount, blockList, indexCount, indexList, + &sparseCount); + pFile->fSparseDataEof = + (di_off_t) pFile->fDirEntry.eof - sparseCount * kBlkSize; + //WMSG4(" +++ sparseCount=%ld blockCount=%ld sparseDataEof=%ld '%s'\n", + // sparseCount, blockCount, (long) pFile->fSparseDataEof, + // pFile->fDirEntry.fileName); - delete[] blockList; - blockList = nil; - delete[] indexList; - indexList = nil; - } else { - WMSG2(" ProDOS found weird storage type %d on '%s', ignoring\n", - pFile->fDirEntry.storageType, pFile->fDirEntry.fileName); - pFile->SetQuality(A2File::kQualityDamaged); - } + delete[] blockList; + blockList = nil; + delete[] indexList; + indexList = nil; + } else { + WMSG2(" ProDOS found weird storage type %d on '%s', ignoring\n", + pFile->fDirEntry.storageType, pFile->fDirEntry.fileName); + pFile->SetQuality(A2File::kQualityDamaged); + } - /* - * A completely empty file written as zero blocks (as opposed to simply - * having its EOF extended, e.g. "sparse seedlings") will have zero data - * blocks but possibly an EOF that doesn't land on 512 bytes. This can - * result in a slightly negative "sparse length", which we trim to zero - * here. - */ - //if (stricmp(pFile->fDirEntry.fileName, "EMPTY.SPARSE.R") == 0) - // WMSG0("wahoo\n"); - if (pFile->fSparseDataEof < 0) - pFile->fSparseDataEof = 0; - if (pFile->fSparseRsrcEof < 0) - pFile->fSparseRsrcEof = 0; + /* + * A completely empty file written as zero blocks (as opposed to simply + * having its EOF extended, e.g. "sparse seedlings") will have zero data + * blocks but possibly an EOF that doesn't land on 512 bytes. This can + * result in a slightly negative "sparse length", which we trim to zero + * here. + */ + //if (stricmp(pFile->fDirEntry.fileName, "EMPTY.SPARSE.R") == 0) + // WMSG0("wahoo\n"); + if (pFile->fSparseDataEof < 0) + pFile->fSparseDataEof = 0; + if (pFile->fSparseRsrcEof < 0) + pFile->fSparseRsrcEof = 0; skip: - pFile = (A2FileProDOS*) GetNextFile(pFile); - } + pFile = (A2FileProDOS*) GetNextFile(pFile); + } - dierr = kDIErrNone; + dierr = kDIErrNone; bail: - return dierr; + return dierr; } /* @@ -1199,28 +1199,28 @@ bail: */ void DiskFSProDOS::ScanBlockList(long blockCount, unsigned short* blockList, - long indexCount, unsigned short* indexList, long* pSparseCount) + long indexCount, unsigned short* indexList, long* pSparseCount) { - assert(blockList != nil); - assert(indexCount == 0 || indexList != nil); - assert(pSparseCount != nil); + assert(blockList != nil); + assert(indexCount == 0 || indexList != nil); + assert(pSparseCount != nil); - *pSparseCount = 0; + *pSparseCount = 0; - int i; - for (i = 0; i < blockCount; i++) { - if (blockList[i] != 0) { - SetBlockUsage(blockList[i], VolumeUsage::kChunkPurposeUserData); - } else { - (*pSparseCount)++; // sparse data block - } - } + int i; + for (i = 0; i < blockCount; i++) { + if (blockList[i] != 0) { + SetBlockUsage(blockList[i], VolumeUsage::kChunkPurposeUserData); + } else { + (*pSparseCount)++; // sparse data block + } + } - for (i = 0; i < indexCount; i++) { - if (indexList[i] != 0) { - SetBlockUsage(indexList[i], VolumeUsage::kChunkPurposeFileStruct); - } // else sparse index block - } + for (i = 0; i < indexCount; i++) { + if (indexList[i] != 0) { + SetBlockUsage(indexList[i], VolumeUsage::kChunkPurposeFileStruct); + } // else sparse index block + } } @@ -1236,139 +1236,139 @@ DiskFSProDOS::ScanBlockList(long blockCount, unsigned short* blockList, DIError DiskFSProDOS::ScanForSubVolumes(void) { - DIError dierr = kDIErrNone; - VolumeUsage::ChunkState cstate; - int firstBlock, matchCount; - int block; + DIError dierr = kDIErrNone; + VolumeUsage::ChunkState cstate; + int firstBlock, matchCount; + int block; - /* this is guaranteed by constraint in volume header read */ - assert(fTotalBlocks <= fpImg->GetNumBlocks()); + /* this is guaranteed by constraint in volume header read */ + assert(fTotalBlocks <= fpImg->GetNumBlocks()); - if (fTotalBlocks != 1600) { - WMSG1(" ProDOS ScanForSub: not 800K disk (%ld)\n", - fpImg->GetNumBlocks()); - return kDIErrNone; // only scan 800K disks - } + if (fTotalBlocks != 1600) { + WMSG1(" ProDOS ScanForSub: not 800K disk (%ld)\n", + fpImg->GetNumBlocks()); + return kDIErrNone; // only scan 800K disks + } - matchCount = 0; - for (block = fTotalBlocks-1; block >= 0; block--) { - if (fVolumeUsage.GetChunkState(block, &cstate) != kDIErrNone) { - assert(false); - return kDIErrGeneric; - } + matchCount = 0; + for (block = fTotalBlocks-1; block >= 0; block--) { + if (fVolumeUsage.GetChunkState(block, &cstate) != kDIErrNone) { + assert(false); + return kDIErrGeneric; + } - if (!cstate.isMarkedUsed || cstate.isUsed) - break; + if (!cstate.isMarkedUsed || cstate.isUsed) + break; - matchCount++; - } - firstBlock = block+1; + matchCount++; + } + firstBlock = block+1; - WMSG1("MATCH COUNT %d\n", matchCount); - if (matchCount < 35*8) // 280 blocks on 35-track floppy - return kDIErrNone; - //if (matchCount % 8 != 0) { // must have 4K tracks - // WMSG1(" ProDOS ScanForSub: matchCount %d odd number\n", - // matchCount); - // return kDIErrNone; - //} + WMSG1("MATCH COUNT %d\n", matchCount); + if (matchCount < 35*8) // 280 blocks on 35-track floppy + return kDIErrNone; + //if (matchCount % 8 != 0) { // must have 4K tracks + // WMSG1(" ProDOS ScanForSub: matchCount %d odd number\n", + // matchCount); + // return kDIErrNone; + //} - /* - * Try #1: this is a single DOS 3.3 volume (200K or less). - */ - if ((matchCount % 8) == 0 && matchCount <= (50*8)) { // max 50 tracks - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; - WMSG0(" Sub #1: looking for single DOS volume\n"); - dierr = FindSubVolume(firstBlock, matchCount, &pNewImg, &pNewFS); - if (dierr == kDIErrNone) { - AddSubVolumeToList(pNewImg, pNewFS); - MarkSubVolumeBlocks(firstBlock, matchCount); - return kDIErrNone; - } - } + /* + * Try #1: this is a single DOS 3.3 volume (200K or less). + */ + if ((matchCount % 8) == 0 && matchCount <= (50*8)) { // max 50 tracks + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; + WMSG0(" Sub #1: looking for single DOS volume\n"); + dierr = FindSubVolume(firstBlock, matchCount, &pNewImg, &pNewFS); + if (dierr == kDIErrNone) { + AddSubVolumeToList(pNewImg, pNewFS); + MarkSubVolumeBlocks(firstBlock, matchCount); + return kDIErrNone; + } + } - /* - * Try #2: there are multiple 140K DOS 3.3 volumes here. - * - * We may want to override their volume numbers, but it looks like - * DOS Master disks have distinct volume numbers anyway. - */ - const int kBlkCount140 = 140*2; - if ((matchCount % (kBlkCount140)) == 0) { - int i, count; - bool found = false; + /* + * Try #2: there are multiple 140K DOS 3.3 volumes here. + * + * We may want to override their volume numbers, but it looks like + * DOS Master disks have distinct volume numbers anyway. + */ + const int kBlkCount140 = 140*2; + if ((matchCount % (kBlkCount140)) == 0) { + int i, count; + bool found = false; - count = matchCount / kBlkCount140; - WMSG1(" Sub #2: looking for %d 140K volumes\n", - matchCount / kBlkCount140); + count = matchCount / kBlkCount140; + WMSG1(" Sub #2: looking for %d 140K volumes\n", + matchCount / kBlkCount140); - for (i = 0; i < count; i++) { - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; - WMSG1(" Sub #2: looking for DOS volume at (%d)\n", - firstBlock + i * kBlkCount140); - dierr = FindSubVolume(firstBlock + i * kBlkCount140, - kBlkCount140, &pNewImg, &pNewFS); - if (dierr == kDIErrNone) { - AddSubVolumeToList(pNewImg, pNewFS); - MarkSubVolumeBlocks(firstBlock + i * kBlkCount140, - kBlkCount140); - found = true; - } - } - if (found) - return kDIErrNone; - } + for (i = 0; i < count; i++) { + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; + WMSG1(" Sub #2: looking for DOS volume at (%d)\n", + firstBlock + i * kBlkCount140); + dierr = FindSubVolume(firstBlock + i * kBlkCount140, + kBlkCount140, &pNewImg, &pNewFS); + if (dierr == kDIErrNone) { + AddSubVolumeToList(pNewImg, pNewFS); + MarkSubVolumeBlocks(firstBlock + i * kBlkCount140, + kBlkCount140); + found = true; + } + } + if (found) + return kDIErrNone; + } - /* - * Try #3: there are five 160K DOS 3.3 volumes here (which works out - * to exactly 800K). The first DOS volume loses early tracks as - * needed to accommodate the ProDOS directory and up to 28K of - * boot files. - * - * Because the first 160K volume starts at the front of the disk, - * we need to restrict this to non-ProDOS sub-volumes, or we'll see - * a "ghost" volume in the first position. This stuff is going to - * fail if we test for ProDOS before we check for DOS 3.3. - */ - const int kBlkCount160 = 160*2; - if (matchCount == 1537 || matchCount == 1593) { - int i, count; - bool found = false; + /* + * Try #3: there are five 160K DOS 3.3 volumes here (which works out + * to exactly 800K). The first DOS volume loses early tracks as + * needed to accommodate the ProDOS directory and up to 28K of + * boot files. + * + * Because the first 160K volume starts at the front of the disk, + * we need to restrict this to non-ProDOS sub-volumes, or we'll see + * a "ghost" volume in the first position. This stuff is going to + * fail if we test for ProDOS before we check for DOS 3.3. + */ + const int kBlkCount160 = 160*2; + if (matchCount == 1537 || matchCount == 1593) { + int i, count; + bool found = false; - count = 1600 / kBlkCount160; - WMSG1(" Sub #3: looking for %d 160K volumes\n", - matchCount / kBlkCount160); + count = 1600 / kBlkCount160; + WMSG1(" Sub #3: looking for %d 160K volumes\n", + matchCount / kBlkCount160); - for (i = 0; i < count; i++) { - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; - WMSG1(" Sub #3: looking for DOS volume at (%d)\n", - i * kBlkCount160); - dierr = FindSubVolume(i * kBlkCount160, - kBlkCount160, &pNewImg, &pNewFS); - if (dierr == kDIErrNone) { - if (pNewImg->GetFSFormat() == DiskImg::kFormatDOS33) { - AddSubVolumeToList(pNewImg, pNewFS); - if (i == 0) - MarkSubVolumeBlocks(firstBlock, kBlkCount160 - firstBlock); - else - MarkSubVolumeBlocks(i * kBlkCount160, kBlkCount160); - } else { - delete pNewFS; - delete pNewImg; - pNewFS = nil; - pNewImg = nil; - } - } - } - if (found) - return kDIErrNone; - } + for (i = 0; i < count; i++) { + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; + WMSG1(" Sub #3: looking for DOS volume at (%d)\n", + i * kBlkCount160); + dierr = FindSubVolume(i * kBlkCount160, + kBlkCount160, &pNewImg, &pNewFS); + if (dierr == kDIErrNone) { + if (pNewImg->GetFSFormat() == DiskImg::kFormatDOS33) { + AddSubVolumeToList(pNewImg, pNewFS); + if (i == 0) + MarkSubVolumeBlocks(firstBlock, kBlkCount160 - firstBlock); + else + MarkSubVolumeBlocks(i * kBlkCount160, kBlkCount160); + } else { + delete pNewFS; + delete pNewImg; + pNewFS = nil; + pNewImg = nil; + } + } + } + if (found) + return kDIErrNone; + } - return kDIErrNone; + return kDIErrNone; } /* @@ -1379,65 +1379,65 @@ DiskFSProDOS::ScanForSubVolumes(void) */ DIError DiskFSProDOS::FindSubVolume(long blockStart, long blockCount, - DiskImg** ppDiskImg, DiskFS** ppDiskFS) + DiskImg** ppDiskImg, DiskFS** ppDiskFS) { - DIError dierr = kDIErrNone; - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; + DIError dierr = kDIErrNone; + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; - pNewImg = new DiskImg; - if (pNewImg == nil) { - dierr = kDIErrMalloc; - goto bail; - } + pNewImg = new DiskImg; + if (pNewImg == nil) { + dierr = kDIErrMalloc; + goto bail; + } - dierr = pNewImg->OpenImage(fpImg, blockStart, blockCount); - if (dierr != kDIErrNone) { - WMSG3(" Sub: OpenImage(%ld,%ld) failed (err=%d)\n", - blockStart, blockCount, dierr); - goto bail; - } + dierr = pNewImg->OpenImage(fpImg, blockStart, blockCount); + if (dierr != kDIErrNone) { + WMSG3(" Sub: OpenImage(%ld,%ld) failed (err=%d)\n", + blockStart, blockCount, dierr); + goto bail; + } - dierr = pNewImg->AnalyzeImage(); - if (dierr != kDIErrNone) { - WMSG1(" Sub: analysis failed (err=%d)\n", dierr); - goto bail; - } + dierr = pNewImg->AnalyzeImage(); + if (dierr != kDIErrNone) { + WMSG1(" Sub: analysis failed (err=%d)\n", dierr); + goto bail; + } - if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || - pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) - { - WMSG0(" Sub: unable to identify filesystem\n"); - dierr = kDIErrFilesystemNotFound; - goto bail; - } + if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || + pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) + { + WMSG0(" Sub: unable to identify filesystem\n"); + dierr = kDIErrFilesystemNotFound; + goto bail; + } - /* open a DiskFS for the sub-image */ - WMSG0(" Sub DiskImg succeeded, opening DiskFS\n"); - pNewFS = pNewImg->OpenAppropriateDiskFS(); - if (pNewFS == nil) { - WMSG0(" Sub: OpenAppropriateDiskFS failed\n"); - dierr = kDIErrUnsupportedFSFmt; - goto bail; - } + /* open a DiskFS for the sub-image */ + WMSG0(" Sub DiskImg succeeded, opening DiskFS\n"); + pNewFS = pNewImg->OpenAppropriateDiskFS(); + if (pNewFS == nil) { + WMSG0(" Sub: OpenAppropriateDiskFS failed\n"); + dierr = kDIErrUnsupportedFSFmt; + goto bail; + } - /* load the files from the sub-image */ - dierr = pNewFS->Initialize(pNewImg, kInitFull); - if (dierr != kDIErrNone) { - WMSG1(" Sub: error %d reading list of files from disk", dierr); - goto bail; - } + /* load the files from the sub-image */ + dierr = pNewFS->Initialize(pNewImg, kInitFull); + if (dierr != kDIErrNone) { + WMSG1(" Sub: error %d reading list of files from disk", dierr); + goto bail; + } bail: - if (dierr != kDIErrNone) { - delete pNewFS; - delete pNewImg; - } else { - assert(pNewImg != nil && pNewFS != nil); - *ppDiskImg = pNewImg; - *ppDiskFS = pNewFS; - } - return dierr; + if (dierr != kDIErrNone) { + delete pNewFS; + delete pNewImg; + } else { + assert(pNewImg != nil && pNewFS != nil); + *ppDiskImg = pNewImg; + *ppDiskFS = pNewFS; + } + return dierr; } /* @@ -1446,24 +1446,24 @@ bail: void DiskFSProDOS::MarkSubVolumeBlocks(long block, long count) { - VolumeUsage::ChunkState cstate; + VolumeUsage::ChunkState cstate; - while (count--) { - if (fVolumeUsage.GetChunkState(block, &cstate) != kDIErrNone) { - assert(false); - return; - } + while (count--) { + if (fVolumeUsage.GetChunkState(block, &cstate) != kDIErrNone) { + assert(false); + return; + } - assert(cstate.isMarkedUsed && !cstate.isUsed); - cstate.isUsed = true; - cstate.purpose = VolumeUsage::kChunkPurposeEmbedded; - if (fVolumeUsage.SetChunkState(block, &cstate) != kDIErrNone) { - assert(false); - return; - } + assert(cstate.isMarkedUsed && !cstate.isUsed); + cstate.isUsed = true; + cstate.purpose = VolumeUsage::kChunkPurposeEmbedded; + if (fVolumeUsage.SetChunkState(block, &cstate) != kDIErrNone) { + assert(false); + return; + } - block++; - } + block++; + } } @@ -1473,139 +1473,139 @@ DiskFSProDOS::MarkSubVolumeBlocks(long block, long count) DIError DiskFSProDOS::Format(DiskImg* pDiskImg, const char* volName) { - DIError dierr = kDIErrNone; - const bool allowLowerCase = (GetParameter(kParmProDOS_AllowLowerCase) != 0); - unsigned char blkBuf[kBlkSize]; - long formatBlocks; + DIError dierr = kDIErrNone; + const bool allowLowerCase = (GetParameter(kParmProDOS_AllowLowerCase) != 0); + unsigned char blkBuf[kBlkSize]; + long formatBlocks; - if (!IsValidVolumeName(volName)) - return kDIErrInvalidArg; + if (!IsValidVolumeName(volName)) + return kDIErrInvalidArg; - /* set fpImg so calls that rely on it will work; we un-set it later */ - assert(fpImg == nil); - SetDiskImg(pDiskImg); + /* set fpImg so calls that rely on it will work; we un-set it later */ + assert(fpImg == nil); + SetDiskImg(pDiskImg); - WMSG0(" ProDOS formatting disk image\n"); + WMSG0(" ProDOS formatting disk image\n"); - /* write ProDOS blocks */ - dierr = fpImg->OverrideFormat(fpImg->GetPhysicalFormat(), - DiskImg::kFormatGenericProDOSOrd, fpImg->GetSectorOrder()); - if (dierr != kDIErrNone) - goto bail; + /* write ProDOS blocks */ + dierr = fpImg->OverrideFormat(fpImg->GetPhysicalFormat(), + DiskImg::kFormatGenericProDOSOrd, fpImg->GetSectorOrder()); + if (dierr != kDIErrNone) + goto bail; - formatBlocks = pDiskImg->GetNumBlocks(); - if (formatBlocks > 65536) { - WMSG1(" ProDOS: rejecting format req blocks=%ld\n", formatBlocks); - assert(false); - return kDIErrInvalidArg; - } - if (formatBlocks == 65536) { - WMSG0(" ProDOS: trimming FS size from 65536 to 65535\n"); - formatBlocks = 65535; - } + formatBlocks = pDiskImg->GetNumBlocks(); + if (formatBlocks > 65536) { + WMSG1(" ProDOS: rejecting format req blocks=%ld\n", formatBlocks); + assert(false); + return kDIErrInvalidArg; + } + if (formatBlocks == 65536) { + WMSG0(" ProDOS: trimming FS size from 65536 to 65535\n"); + formatBlocks = 65535; + } - /* - * We should now zero out the disk blocks, but on a 32MB volume that can - * take a little while. The blocks are zeroed for us when a disk is - * created, so this is really only needed if we're re-formatting an - * existing disk. CiderPress currently doesn't do that, so we're going - * to skip it here. - */ -// dierr = fpImg->ZeroImage(); - WMSG0(" ProDOS (not zeroing blocks)\n"); + /* + * We should now zero out the disk blocks, but on a 32MB volume that can + * take a little while. The blocks are zeroed for us when a disk is + * created, so this is really only needed if we're re-formatting an + * existing disk. CiderPress currently doesn't do that, so we're going + * to skip it here. + */ +// dierr = fpImg->ZeroImage(); + WMSG0(" ProDOS (not zeroing blocks)\n"); - /* - * Start by writing blocks 0 and 1 (the boot blocks). This is done from - * a standard boot block image that happens to be essentially the same - * for all types of disks. (Apparently these blocks are only used when - * booting 5.25" disks?) - */ - dierr = WriteBootBlocks(); - if (dierr != kDIErrNone) - goto bail; + /* + * Start by writing blocks 0 and 1 (the boot blocks). This is done from + * a standard boot block image that happens to be essentially the same + * for all types of disks. (Apparently these blocks are only used when + * booting 5.25" disks?) + */ + dierr = WriteBootBlocks(); + if (dierr != kDIErrNone) + goto bail; - /* - * Write the four-block disk volume entry. Start by writing the three - * empty ones (which only have the prev/next pointers), and finish by - * writing the first block, which has the volume directory header. - */ - int i; - memset(blkBuf, 0, sizeof(blkBuf)); - for (i = kVolHeaderBlock+1; i < kVolHeaderBlock+kVolDirExpectedNumBlocks; i++) - { - PutShortLE(&blkBuf[0x00], i-1); - if (i == kVolHeaderBlock+kVolDirExpectedNumBlocks-1) - PutShortLE(&blkBuf[0x02], 0); - else - PutShortLE(&blkBuf[0x02], i+1); + /* + * Write the four-block disk volume entry. Start by writing the three + * empty ones (which only have the prev/next pointers), and finish by + * writing the first block, which has the volume directory header. + */ + int i; + memset(blkBuf, 0, sizeof(blkBuf)); + for (i = kVolHeaderBlock+1; i < kVolHeaderBlock+kVolDirExpectedNumBlocks; i++) + { + PutShortLE(&blkBuf[0x00], i-1); + if (i == kVolHeaderBlock+kVolDirExpectedNumBlocks-1) + PutShortLE(&blkBuf[0x02], 0); + else + PutShortLE(&blkBuf[0x02], i+1); - dierr = fpImg->WriteBlock(i, blkBuf); - if (dierr != kDIErrNone) { - WMSG2(" Format: block %d write failed (err=%d)\n", i, dierr); - goto bail; - } - } + dierr = fpImg->WriteBlock(i, blkBuf); + if (dierr != kDIErrNone) { + WMSG2(" Format: block %d write failed (err=%d)\n", i, dierr); + goto bail; + } + } - char upperName[A2FileProDOS::kMaxFileName+1]; - unsigned short lcFlags; - time_t now; + char upperName[A2FileProDOS::kMaxFileName+1]; + unsigned short lcFlags; + time_t now; - now = time(nil); + now = time(nil); - /* - * Compute the lower-case flags, if desired. The test for "allowLowerCase" - * is probably bogus, because in most cases we just got created by the - * DiskImg and the app hasn't had time to set the "allow lower" flag. - * So it defaults to "enabled", which means the app needs to manually - * change the volume name to lower case. - */ - UpperCaseName(upperName, volName); - lcFlags = 0; - if (allowLowerCase) - lcFlags = GenerateLowerCaseBits(upperName, volName, false); + /* + * Compute the lower-case flags, if desired. The test for "allowLowerCase" + * is probably bogus, because in most cases we just got created by the + * DiskImg and the app hasn't had time to set the "allow lower" flag. + * So it defaults to "enabled", which means the app needs to manually + * change the volume name to lower case. + */ + UpperCaseName(upperName, volName); + lcFlags = 0; + if (allowLowerCase) + lcFlags = GenerateLowerCaseBits(upperName, volName, false); - PutShortLE(&blkBuf[0x00], 0); - PutShortLE(&blkBuf[0x02], kVolHeaderBlock+1); - blkBuf[0x04] = strlen(upperName) | (A2FileProDOS::kStorageVolumeDirHeader << 4); - strncpy((char*) &blkBuf[0x05], upperName, A2FileProDOS::kMaxFileName); - PutLongLE(&blkBuf[0x16], A2FileProDOS::ConvertProDate(now)); - PutShortLE(&blkBuf[0x1a], lcFlags); - PutLongLE(&blkBuf[0x1c], A2FileProDOS::ConvertProDate(now)); - blkBuf[0x20] = 0; // GS/OS uses 5? - /* min_version is zero */ - blkBuf[0x22] = 0xe3; // access (format/rename/backup/write/read) - blkBuf[0x23] = 0x27; // entry_length: always $27 - blkBuf[0x24] = 0x0d; // entries_per_block: always $0d - /* file_count is zero - does not include volume dir */ - PutShortLE(&blkBuf[0x27], kVolHeaderBlock + kVolDirExpectedNumBlocks); // bit_map_pointer - PutShortLE(&blkBuf[0x29], (unsigned short) formatBlocks); // total_blocks - dierr = fpImg->WriteBlock(kVolHeaderBlock, blkBuf); - if (dierr != kDIErrNone) { - WMSG2(" Format: block %d write failed (err=%d)\n", - kVolHeaderBlock, dierr); - goto bail; - } + PutShortLE(&blkBuf[0x00], 0); + PutShortLE(&blkBuf[0x02], kVolHeaderBlock+1); + blkBuf[0x04] = strlen(upperName) | (A2FileProDOS::kStorageVolumeDirHeader << 4); + strncpy((char*) &blkBuf[0x05], upperName, A2FileProDOS::kMaxFileName); + PutLongLE(&blkBuf[0x16], A2FileProDOS::ConvertProDate(now)); + PutShortLE(&blkBuf[0x1a], lcFlags); + PutLongLE(&blkBuf[0x1c], A2FileProDOS::ConvertProDate(now)); + blkBuf[0x20] = 0; // GS/OS uses 5? + /* min_version is zero */ + blkBuf[0x22] = 0xe3; // access (format/rename/backup/write/read) + blkBuf[0x23] = 0x27; // entry_length: always $27 + blkBuf[0x24] = 0x0d; // entries_per_block: always $0d + /* file_count is zero - does not include volume dir */ + PutShortLE(&blkBuf[0x27], kVolHeaderBlock + kVolDirExpectedNumBlocks); // bit_map_pointer + PutShortLE(&blkBuf[0x29], (unsigned short) formatBlocks); // total_blocks + dierr = fpImg->WriteBlock(kVolHeaderBlock, blkBuf); + if (dierr != kDIErrNone) { + WMSG2(" Format: block %d write failed (err=%d)\n", + kVolHeaderBlock, dierr); + goto bail; + } - /* check our work, and set some object fields, by reading what we wrote */ - dierr = LoadVolHeader(); - if (dierr != kDIErrNone) { - WMSG1(" GLITCH: couldn't read header we just wrote (err=%d)\n", dierr); - goto bail; - } + /* check our work, and set some object fields, by reading what we wrote */ + dierr = LoadVolHeader(); + if (dierr != kDIErrNone) { + WMSG1(" GLITCH: couldn't read header we just wrote (err=%d)\n", dierr); + goto bail; + } - /* - * Generate the initial block usage map. The only entries in use are - * right at the start of the disk. When we finish, scan what we just - * created into - */ - CreateEmptyBlockMap(); + /* + * Generate the initial block usage map. The only entries in use are + * right at the start of the disk. When we finish, scan what we just + * created into + */ + CreateEmptyBlockMap(); - /* don't do this -- assume they're going to call Initialize() later */ - //ScanVolBitmap(); + /* don't do this -- assume they're going to call Initialize() later */ + //ScanVolBitmap(); bail: - SetDiskImg(nil); // shouldn't really be set by us - return dierr; + SetDiskImg(nil); // shouldn't really be set by us + return dierr; } @@ -1626,87 +1626,87 @@ const unsigned char gFloppyBlock0[512] = { 0xc8, 0xc0, 0xeb, 0xd0, 0xf6, 0xa2, 0x06, 0xbc, 0x1d, 0x09, 0xbd, 0x24, 0x09, 0x99, 0xf2, 0x09, 0xbd, 0x2b, 0x09, 0x9d, 0x7f, 0x0a, 0xca, 0x10, 0xee, 0xa9, 0x09, 0x85, 0x49, 0xa9, 0x86, 0xa0, 0x00, 0xc9, 0xf9, 0xb0, - 0x2f, 0x85, 0x48, 0x84, 0x60, 0x84, 0x4a, 0x84, 0x4c, 0x84, 0x4e, 0x84, - 0x47, 0xc8, 0x84, 0x42, 0xc8, 0x84, 0x46, 0xa9, 0x0c, 0x85, 0x61, 0x85, - 0x4b, 0x20, 0x12, 0x09, 0xb0, 0x68, 0xe6, 0x61, 0xe6, 0x61, 0xe6, 0x46, - 0xa5, 0x46, 0xc9, 0x06, 0x90, 0xef, 0xad, 0x00, 0x0c, 0x0d, 0x01, 0x0c, - 0xd0, 0x6d, 0xa9, 0x04, 0xd0, 0x02, 0xa5, 0x4a, 0x18, 0x6d, 0x23, 0x0c, - 0xa8, 0x90, 0x0d, 0xe6, 0x4b, 0xa5, 0x4b, 0x4a, 0xb0, 0x06, 0xc9, 0x0a, - 0xf0, 0x55, 0xa0, 0x04, 0x84, 0x4a, 0xad, 0x02, 0x09, 0x29, 0x0f, 0xa8, - 0xb1, 0x4a, 0xd9, 0x02, 0x09, 0xd0, 0xdb, 0x88, 0x10, 0xf6, 0x29, 0xf0, - 0xc9, 0x20, 0xd0, 0x3b, 0xa0, 0x10, 0xb1, 0x4a, 0xc9, 0xff, 0xd0, 0x33, - 0xc8, 0xb1, 0x4a, 0x85, 0x46, 0xc8, 0xb1, 0x4a, 0x85, 0x47, 0xa9, 0x00, - 0x85, 0x4a, 0xa0, 0x1e, 0x84, 0x4b, 0x84, 0x61, 0xc8, 0x84, 0x4d, 0x20, - 0x12, 0x09, 0xb0, 0x17, 0xe6, 0x61, 0xe6, 0x61, 0xa4, 0x4e, 0xe6, 0x4e, - 0xb1, 0x4a, 0x85, 0x46, 0xb1, 0x4c, 0x85, 0x47, 0x11, 0x4a, 0xd0, 0xe7, - 0x4c, 0x00, 0x20, 0x4c, 0x3f, 0x09, 0x26, 0x50, 0x52, 0x4f, 0x44, 0x4f, - 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa5, 0x60, - 0x85, 0x44, 0xa5, 0x61, 0x85, 0x45, 0x6c, 0x48, 0x00, 0x08, 0x1e, 0x24, - 0x3f, 0x45, 0x47, 0x76, 0xf4, 0xd7, 0xd1, 0xb6, 0x4b, 0xb4, 0xac, 0xa6, - 0x2b, 0x18, 0x60, 0x4c, 0xbc, 0x09, 0xa9, 0x9f, 0x48, 0xa9, 0xff, 0x48, - 0xa9, 0x01, 0xa2, 0x00, 0x4c, 0x79, 0xf4, 0x20, 0x58, 0xfc, 0xa0, 0x1c, - 0xb9, 0x50, 0x09, 0x99, 0xae, 0x05, 0x88, 0x10, 0xf7, 0x4c, 0x4d, 0x09, - 0xaa, 0xaa, 0xaa, 0xa0, 0xd5, 0xce, 0xc1, 0xc2, 0xcc, 0xc5, 0xa0, 0xd4, - 0xcf, 0xa0, 0xcc, 0xcf, 0xc1, 0xc4, 0xa0, 0xd0, 0xd2, 0xcf, 0xc4, 0xcf, - 0xd3, 0xa0, 0xaa, 0xaa, 0xaa, 0xa5, 0x53, 0x29, 0x03, 0x2a, 0x05, 0x2b, - 0xaa, 0xbd, 0x80, 0xc0, 0xa9, 0x2c, 0xa2, 0x11, 0xca, 0xd0, 0xfd, 0xe9, - 0x01, 0xd0, 0xf7, 0xa6, 0x2b, 0x60, 0xa5, 0x46, 0x29, 0x07, 0xc9, 0x04, - 0x29, 0x03, 0x08, 0x0a, 0x28, 0x2a, 0x85, 0x3d, 0xa5, 0x47, 0x4a, 0xa5, - 0x46, 0x6a, 0x4a, 0x4a, 0x85, 0x41, 0x0a, 0x85, 0x51, 0xa5, 0x45, 0x85, - 0x27, 0xa6, 0x2b, 0xbd, 0x89, 0xc0, 0x20, 0xbc, 0x09, 0xe6, 0x27, 0xe6, - 0x3d, 0xe6, 0x3d, 0xb0, 0x03, 0x20, 0xbc, 0x09, 0xbc, 0x88, 0xc0, 0x60, - 0xa5, 0x40, 0x0a, 0x85, 0x53, 0xa9, 0x00, 0x85, 0x54, 0xa5, 0x53, 0x85, - 0x50, 0x38, 0xe5, 0x51, 0xf0, 0x14, 0xb0, 0x04, 0xe6, 0x53, 0x90, 0x02, - 0xc6, 0x53, 0x38, 0x20, 0x6d, 0x09, 0xa5, 0x50, 0x18, 0x20, 0x6f, 0x09, - 0xd0, 0xe3, 0xa0, 0x7f, 0x84, 0x52, 0x08, 0x28, 0x38, 0xc6, 0x52, 0xf0, - 0xce, 0x18, 0x08, 0x88, 0xf0, 0xf5, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x2f, 0x85, 0x48, 0x84, 0x60, 0x84, 0x4a, 0x84, 0x4c, 0x84, 0x4e, 0x84, + 0x47, 0xc8, 0x84, 0x42, 0xc8, 0x84, 0x46, 0xa9, 0x0c, 0x85, 0x61, 0x85, + 0x4b, 0x20, 0x12, 0x09, 0xb0, 0x68, 0xe6, 0x61, 0xe6, 0x61, 0xe6, 0x46, + 0xa5, 0x46, 0xc9, 0x06, 0x90, 0xef, 0xad, 0x00, 0x0c, 0x0d, 0x01, 0x0c, + 0xd0, 0x6d, 0xa9, 0x04, 0xd0, 0x02, 0xa5, 0x4a, 0x18, 0x6d, 0x23, 0x0c, + 0xa8, 0x90, 0x0d, 0xe6, 0x4b, 0xa5, 0x4b, 0x4a, 0xb0, 0x06, 0xc9, 0x0a, + 0xf0, 0x55, 0xa0, 0x04, 0x84, 0x4a, 0xad, 0x02, 0x09, 0x29, 0x0f, 0xa8, + 0xb1, 0x4a, 0xd9, 0x02, 0x09, 0xd0, 0xdb, 0x88, 0x10, 0xf6, 0x29, 0xf0, + 0xc9, 0x20, 0xd0, 0x3b, 0xa0, 0x10, 0xb1, 0x4a, 0xc9, 0xff, 0xd0, 0x33, + 0xc8, 0xb1, 0x4a, 0x85, 0x46, 0xc8, 0xb1, 0x4a, 0x85, 0x47, 0xa9, 0x00, + 0x85, 0x4a, 0xa0, 0x1e, 0x84, 0x4b, 0x84, 0x61, 0xc8, 0x84, 0x4d, 0x20, + 0x12, 0x09, 0xb0, 0x17, 0xe6, 0x61, 0xe6, 0x61, 0xa4, 0x4e, 0xe6, 0x4e, + 0xb1, 0x4a, 0x85, 0x46, 0xb1, 0x4c, 0x85, 0x47, 0x11, 0x4a, 0xd0, 0xe7, + 0x4c, 0x00, 0x20, 0x4c, 0x3f, 0x09, 0x26, 0x50, 0x52, 0x4f, 0x44, 0x4f, + 0x53, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xa5, 0x60, + 0x85, 0x44, 0xa5, 0x61, 0x85, 0x45, 0x6c, 0x48, 0x00, 0x08, 0x1e, 0x24, + 0x3f, 0x45, 0x47, 0x76, 0xf4, 0xd7, 0xd1, 0xb6, 0x4b, 0xb4, 0xac, 0xa6, + 0x2b, 0x18, 0x60, 0x4c, 0xbc, 0x09, 0xa9, 0x9f, 0x48, 0xa9, 0xff, 0x48, + 0xa9, 0x01, 0xa2, 0x00, 0x4c, 0x79, 0xf4, 0x20, 0x58, 0xfc, 0xa0, 0x1c, + 0xb9, 0x50, 0x09, 0x99, 0xae, 0x05, 0x88, 0x10, 0xf7, 0x4c, 0x4d, 0x09, + 0xaa, 0xaa, 0xaa, 0xa0, 0xd5, 0xce, 0xc1, 0xc2, 0xcc, 0xc5, 0xa0, 0xd4, + 0xcf, 0xa0, 0xcc, 0xcf, 0xc1, 0xc4, 0xa0, 0xd0, 0xd2, 0xcf, 0xc4, 0xcf, + 0xd3, 0xa0, 0xaa, 0xaa, 0xaa, 0xa5, 0x53, 0x29, 0x03, 0x2a, 0x05, 0x2b, + 0xaa, 0xbd, 0x80, 0xc0, 0xa9, 0x2c, 0xa2, 0x11, 0xca, 0xd0, 0xfd, 0xe9, + 0x01, 0xd0, 0xf7, 0xa6, 0x2b, 0x60, 0xa5, 0x46, 0x29, 0x07, 0xc9, 0x04, + 0x29, 0x03, 0x08, 0x0a, 0x28, 0x2a, 0x85, 0x3d, 0xa5, 0x47, 0x4a, 0xa5, + 0x46, 0x6a, 0x4a, 0x4a, 0x85, 0x41, 0x0a, 0x85, 0x51, 0xa5, 0x45, 0x85, + 0x27, 0xa6, 0x2b, 0xbd, 0x89, 0xc0, 0x20, 0xbc, 0x09, 0xe6, 0x27, 0xe6, + 0x3d, 0xe6, 0x3d, 0xb0, 0x03, 0x20, 0xbc, 0x09, 0xbc, 0x88, 0xc0, 0x60, + 0xa5, 0x40, 0x0a, 0x85, 0x53, 0xa9, 0x00, 0x85, 0x54, 0xa5, 0x53, 0x85, + 0x50, 0x38, 0xe5, 0x51, 0xf0, 0x14, 0xb0, 0x04, 0xe6, 0x53, 0x90, 0x02, + 0xc6, 0x53, 0x38, 0x20, 0x6d, 0x09, 0xa5, 0x50, 0x18, 0x20, 0x6f, 0x09, + 0xd0, 0xe3, 0xa0, 0x7f, 0x84, 0x52, 0x08, 0x28, 0x38, 0xc6, 0x52, 0xf0, + 0xce, 0x18, 0x08, 0x88, 0xf0, 0xf5, 0xbd, 0x8c, 0xc0, 0x10, 0xfb, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; unsigned char gHDBlock0[] = { - 0x01, 0x38, 0xb0, 0x03, 0x4c, 0x1c, 0x09, 0x78, 0x86, 0x43, 0xc9, 0x03, - 0x08, 0x8a, 0x29, 0x70, 0x4a, 0x4a, 0x4a, 0x4a, 0x09, 0xc0, 0x85, 0x49, - 0xa0, 0xff, 0x84, 0x48, 0x28, 0xc8, 0xb1, 0x48, 0xd0, 0x3a, 0xb0, 0x0e, - 0xa9, 0x03, 0x8d, 0x00, 0x08, 0xe6, 0x3d, 0xa5, 0x49, 0x48, 0xa9, 0x5b, - 0x48, 0x60, 0x85, 0x40, 0x85, 0x48, 0xa0, 0x5e, 0xb1, 0x48, 0x99, 0x94, - 0x09, 0xc8, 0xc0, 0xeb, 0xd0, 0xf6, 0xa2, 0x06, 0xbc, 0x32, 0x09, 0xbd, - 0x39, 0x09, 0x99, 0xf2, 0x09, 0xbd, 0x40, 0x09, 0x9d, 0x7f, 0x0a, 0xca, - 0x10, 0xee, 0xa9, 0x09, 0x85, 0x49, 0xa9, 0x86, 0xa0, 0x00, 0xc9, 0xf9, - 0xb0, 0x2f, 0x85, 0x48, 0x84, 0x60, 0x84, 0x4a, 0x84, 0x4c, 0x84, 0x4e, - 0x84, 0x47, 0xc8, 0x84, 0x42, 0xc8, 0x84, 0x46, 0xa9, 0x0c, 0x85, 0x61, - 0x85, 0x4b, 0x20, 0x27, 0x09, 0xb0, 0x66, 0xe6, 0x61, 0xe6, 0x61, 0xe6, - 0x46, 0xa5, 0x46, 0xc9, 0x06, 0x90, 0xef, 0xad, 0x00, 0x0c, 0x0d, 0x01, - 0x0c, 0xd0, 0x52, 0xa9, 0x04, 0xd0, 0x02, 0xa5, 0x4a, 0x18, 0x6d, 0x23, - 0x0c, 0xa8, 0x90, 0x0d, 0xe6, 0x4b, 0xa5, 0x4b, 0x4a, 0xb0, 0x06, 0xc9, - 0x0a, 0xf0, 0x71, 0xa0, 0x04, 0x84, 0x4a, 0xad, 0x20, 0x09, 0x29, 0x0f, - 0xa8, 0xb1, 0x4a, 0xd9, 0x20, 0x09, 0xd0, 0xdb, 0x88, 0x10, 0xf6, 0xa0, - 0x16, 0xb1, 0x4a, 0x4a, 0x6d, 0x1f, 0x09, 0x8d, 0x1f, 0x09, 0xa0, 0x11, - 0xb1, 0x4a, 0x85, 0x46, 0xc8, 0xb1, 0x4a, 0x85, 0x47, 0xa9, 0x00, 0x85, - 0x4a, 0xa0, 0x1e, 0x84, 0x4b, 0x84, 0x61, 0xc8, 0x84, 0x4d, 0x20, 0x27, - 0x09, 0xb0, 0x35, 0xe6, 0x61, 0xe6, 0x61, 0xa4, 0x4e, 0xe6, 0x4e, 0xb1, - 0x4a, 0x85, 0x46, 0xb1, 0x4c, 0x85, 0x47, 0x11, 0x4a, 0xd0, 0x18, 0xa2, - 0x01, 0xa9, 0x00, 0xa8, 0x91, 0x60, 0xc8, 0xd0, 0xfb, 0xe6, 0x61, 0xea, - 0xea, 0xca, 0x10, 0xf4, 0xce, 0x1f, 0x09, 0xf0, 0x07, 0xd0, 0xd8, 0xce, - 0x1f, 0x09, 0xd0, 0xca, 0x58, 0x4c, 0x00, 0x20, 0x4c, 0x47, 0x09, 0x02, - 0x26, 0x50, 0x52, 0x4f, 0x44, 0x4f, 0x53, 0xa5, 0x60, 0x85, 0x44, 0xa5, - 0x61, 0x85, 0x45, 0x6c, 0x48, 0x00, 0x08, 0x1e, 0x24, 0x3f, 0x45, 0x47, - 0x76, 0xf4, 0xd7, 0xd1, 0xb6, 0x4b, 0xb4, 0xac, 0xa6, 0x2b, 0x18, 0x60, - 0x4c, 0xbc, 0x09, 0x20, 0x58, 0xfc, 0xa0, 0x14, 0xb9, 0x58, 0x09, 0x99, - 0xb1, 0x05, 0x88, 0x10, 0xf7, 0x4c, 0x55, 0x09, 0xd5, 0xce, 0xc1, 0xc2, - 0xcc, 0xc5, 0xa0, 0xd4, 0xcf, 0xa0, 0xcc, 0xcf, 0xc1, 0xc4, 0xa0, 0xd0, - 0xd2, 0xcf, 0xc4, 0xcf, 0xd3, 0xa5, 0x53, 0x29, 0x03, 0x2a, 0x05, 0x2b, - 0xaa, 0xbd, 0x80, 0xc0, 0xa9, 0x2c, 0xa2, 0x11, 0xca, 0xd0, 0xfd, 0xe9, - 0x01, 0xd0, 0xf7, 0xa6, 0x2b, 0x60, 0xa5, 0x46, 0x29, 0x07, 0xc9, 0x04, - 0x29, 0x03, 0x08, 0x0a, 0x28, 0x2a, 0x85, 0x3d, 0xa5, 0x47, 0x4a, 0xa5, - 0x46, 0x6a, 0x4a, 0x4a, 0x85, 0x41, 0x0a, 0x85, 0x51, 0xa5, 0x45, 0x85, - 0x27, 0xa6, 0x2b, 0xbd, 0x89, 0xc0, 0x20, 0xbc, 0x09, 0xe6, 0x27, 0xe6, - 0x3d, 0xe6, 0x3d, 0xb0, 0x03, 0x20, 0xbc, 0x09, 0xbc, 0x88, 0xc0, 0x60, - 0xa5, 0x40, 0x0a, 0x85, 0x53, 0xa9, 0x00, 0x85, 0x54, 0xa5, 0x53, 0x85, - 0x50, 0x38, 0xe5, 0x51, 0xf0, 0x14, 0xb0, 0x04, 0xe6, 0x53, 0x90, 0x02, - 0xc6, 0x53, 0x38, 0x20, 0x6d, 0x09, 0xa5, 0x50, 0x18, 0x20, 0x6f, 0x09, - 0xd0, 0xe3, 0xa0, 0x7f, 0x84, 0x52, 0x08, 0x28, 0x38, 0xc6, 0x52, 0xf0, - 0xce, 0x18, 0x08, 0x88, 0xf0, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + 0x01, 0x38, 0xb0, 0x03, 0x4c, 0x1c, 0x09, 0x78, 0x86, 0x43, 0xc9, 0x03, + 0x08, 0x8a, 0x29, 0x70, 0x4a, 0x4a, 0x4a, 0x4a, 0x09, 0xc0, 0x85, 0x49, + 0xa0, 0xff, 0x84, 0x48, 0x28, 0xc8, 0xb1, 0x48, 0xd0, 0x3a, 0xb0, 0x0e, + 0xa9, 0x03, 0x8d, 0x00, 0x08, 0xe6, 0x3d, 0xa5, 0x49, 0x48, 0xa9, 0x5b, + 0x48, 0x60, 0x85, 0x40, 0x85, 0x48, 0xa0, 0x5e, 0xb1, 0x48, 0x99, 0x94, + 0x09, 0xc8, 0xc0, 0xeb, 0xd0, 0xf6, 0xa2, 0x06, 0xbc, 0x32, 0x09, 0xbd, + 0x39, 0x09, 0x99, 0xf2, 0x09, 0xbd, 0x40, 0x09, 0x9d, 0x7f, 0x0a, 0xca, + 0x10, 0xee, 0xa9, 0x09, 0x85, 0x49, 0xa9, 0x86, 0xa0, 0x00, 0xc9, 0xf9, + 0xb0, 0x2f, 0x85, 0x48, 0x84, 0x60, 0x84, 0x4a, 0x84, 0x4c, 0x84, 0x4e, + 0x84, 0x47, 0xc8, 0x84, 0x42, 0xc8, 0x84, 0x46, 0xa9, 0x0c, 0x85, 0x61, + 0x85, 0x4b, 0x20, 0x27, 0x09, 0xb0, 0x66, 0xe6, 0x61, 0xe6, 0x61, 0xe6, + 0x46, 0xa5, 0x46, 0xc9, 0x06, 0x90, 0xef, 0xad, 0x00, 0x0c, 0x0d, 0x01, + 0x0c, 0xd0, 0x52, 0xa9, 0x04, 0xd0, 0x02, 0xa5, 0x4a, 0x18, 0x6d, 0x23, + 0x0c, 0xa8, 0x90, 0x0d, 0xe6, 0x4b, 0xa5, 0x4b, 0x4a, 0xb0, 0x06, 0xc9, + 0x0a, 0xf0, 0x71, 0xa0, 0x04, 0x84, 0x4a, 0xad, 0x20, 0x09, 0x29, 0x0f, + 0xa8, 0xb1, 0x4a, 0xd9, 0x20, 0x09, 0xd0, 0xdb, 0x88, 0x10, 0xf6, 0xa0, + 0x16, 0xb1, 0x4a, 0x4a, 0x6d, 0x1f, 0x09, 0x8d, 0x1f, 0x09, 0xa0, 0x11, + 0xb1, 0x4a, 0x85, 0x46, 0xc8, 0xb1, 0x4a, 0x85, 0x47, 0xa9, 0x00, 0x85, + 0x4a, 0xa0, 0x1e, 0x84, 0x4b, 0x84, 0x61, 0xc8, 0x84, 0x4d, 0x20, 0x27, + 0x09, 0xb0, 0x35, 0xe6, 0x61, 0xe6, 0x61, 0xa4, 0x4e, 0xe6, 0x4e, 0xb1, + 0x4a, 0x85, 0x46, 0xb1, 0x4c, 0x85, 0x47, 0x11, 0x4a, 0xd0, 0x18, 0xa2, + 0x01, 0xa9, 0x00, 0xa8, 0x91, 0x60, 0xc8, 0xd0, 0xfb, 0xe6, 0x61, 0xea, + 0xea, 0xca, 0x10, 0xf4, 0xce, 0x1f, 0x09, 0xf0, 0x07, 0xd0, 0xd8, 0xce, + 0x1f, 0x09, 0xd0, 0xca, 0x58, 0x4c, 0x00, 0x20, 0x4c, 0x47, 0x09, 0x02, + 0x26, 0x50, 0x52, 0x4f, 0x44, 0x4f, 0x53, 0xa5, 0x60, 0x85, 0x44, 0xa5, + 0x61, 0x85, 0x45, 0x6c, 0x48, 0x00, 0x08, 0x1e, 0x24, 0x3f, 0x45, 0x47, + 0x76, 0xf4, 0xd7, 0xd1, 0xb6, 0x4b, 0xb4, 0xac, 0xa6, 0x2b, 0x18, 0x60, + 0x4c, 0xbc, 0x09, 0x20, 0x58, 0xfc, 0xa0, 0x14, 0xb9, 0x58, 0x09, 0x99, + 0xb1, 0x05, 0x88, 0x10, 0xf7, 0x4c, 0x55, 0x09, 0xd5, 0xce, 0xc1, 0xc2, + 0xcc, 0xc5, 0xa0, 0xd4, 0xcf, 0xa0, 0xcc, 0xcf, 0xc1, 0xc4, 0xa0, 0xd0, + 0xd2, 0xcf, 0xc4, 0xcf, 0xd3, 0xa5, 0x53, 0x29, 0x03, 0x2a, 0x05, 0x2b, + 0xaa, 0xbd, 0x80, 0xc0, 0xa9, 0x2c, 0xa2, 0x11, 0xca, 0xd0, 0xfd, 0xe9, + 0x01, 0xd0, 0xf7, 0xa6, 0x2b, 0x60, 0xa5, 0x46, 0x29, 0x07, 0xc9, 0x04, + 0x29, 0x03, 0x08, 0x0a, 0x28, 0x2a, 0x85, 0x3d, 0xa5, 0x47, 0x4a, 0xa5, + 0x46, 0x6a, 0x4a, 0x4a, 0x85, 0x41, 0x0a, 0x85, 0x51, 0xa5, 0x45, 0x85, + 0x27, 0xa6, 0x2b, 0xbd, 0x89, 0xc0, 0x20, 0xbc, 0x09, 0xe6, 0x27, 0xe6, + 0x3d, 0xe6, 0x3d, 0xb0, 0x03, 0x20, 0xbc, 0x09, 0xbc, 0x88, 0xc0, 0x60, + 0xa5, 0x40, 0x0a, 0x85, 0x53, 0xa9, 0x00, 0x85, 0x54, 0xa5, 0x53, 0x85, + 0x50, 0x38, 0xe5, 0x51, 0xf0, 0x14, 0xb0, 0x04, 0xe6, 0x53, 0x90, 0x02, + 0xc6, 0x53, 0x38, 0x20, 0x6d, 0x09, 0xa5, 0x50, 0x18, 0x20, 0x6f, 0x09, + 0xd0, 0xe3, 0xa0, 0x7f, 0x84, 0x52, 0x08, 0x28, 0x38, 0xc6, 0x52, 0xf0, + 0xce, 0x18, 0x08, 0x88, 0xf0, 0xf5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* @@ -1715,29 +1715,29 @@ unsigned char gHDBlock0[] = { DIError DiskFSProDOS::WriteBootBlocks(void) { - DIError dierr; - unsigned char block0[512]; - unsigned char block1[512]; - bool isHD; + DIError dierr; + unsigned char block0[512]; + unsigned char block1[512]; + bool isHD; - assert(fpImg->GetHasBlocks()); + assert(fpImg->GetHasBlocks()); - if (fpImg->GetNumBlocks() == 280 || fpImg->GetNumBlocks() == 1600) - isHD = false; - else - isHD = true; + if (fpImg->GetNumBlocks() == 280 || fpImg->GetNumBlocks() == 1600) + isHD = false; + else + isHD = true; - if (isHD) { - memcpy(block0, gHDBlock0, sizeof(block0)); - // repeating 0x42 0x48 pattern - int i; - unsigned char* ucp; - for (i = 0, ucp = block1; i < (int)sizeof(block1); i++) - *ucp++ = 0x42 + 6 * (i & 0x01); - } else { - memcpy(block0, gFloppyBlock0, sizeof(block0)); - memset(block1, 0, sizeof(block1)); - } + if (isHD) { + memcpy(block0, gHDBlock0, sizeof(block0)); + // repeating 0x42 0x48 pattern + int i; + unsigned char* ucp; + for (i = 0, ucp = block1; i < (int)sizeof(block1); i++) + *ucp++ = 0x42 + 6 * (i & 0x01); + } else { + memcpy(block0, gFloppyBlock0, sizeof(block0)); + memset(block1, 0, sizeof(block1)); + } dierr = fpImg->WriteBlock(0, block0); if (dierr != kDIErrNone) { @@ -1750,20 +1750,20 @@ DiskFSProDOS::WriteBootBlocks(void) return dierr; } - return kDIErrNone; + return kDIErrNone; } /* * Create a new, empty file. There are three different kinds of files we * need to be able to handle: - * (1) Standard file. Create the directory entry and an empty "seedling" - * file with one block allocated. It does not appear that "sparse" - * allocation applies to seedlings. - * (2) Extended file. Create the directory entry, the extended key block, - * and allocate one seedling block for each fork. - * (3) Subdirectory. Allocate a block for the subdir and fill in the - * details in the subdir header. + * (1) Standard file. Create the directory entry and an empty "seedling" + * file with one block allocated. It does not appear that "sparse" + * allocation applies to seedlings. + * (2) Extended file. Create the directory entry, the extended key block, + * and allocate one seedling block for each fork. + * (3) Subdirectory. Allocate a block for the subdir and fill in the + * details in the subdir header. * * In all cases we need to add a new directory entry as well. * @@ -1780,394 +1780,394 @@ DiskFSProDOS::WriteBootBlocks(void) * NOTE: kParm_CreateUnique does *not* apply to creating subdirectories. */ DIError -DiskFSProDOS::CreateFile(const CreateParms* pParms, A2File** ppNewFile) +DiskFSProDOS::CreateFile(const CreateParms* pParms, A2File** ppNewFile) { - DIError dierr = kDIErrNone; - char* normalizedPath = nil; - char* basePath = nil; - char* fileName = nil; - A2FileProDOS* pSubdir = nil; - A2FileDescr* pOpenSubdir = nil; - A2FileProDOS* pNewFile = nil; - unsigned char* subdirBuf = nil; - const bool allowLowerCase = (GetParameter(kParmProDOS_AllowLowerCase) != 0); - const bool createUnique = (GetParameter(kParm_CreateUnique) != 0); - char upperName[A2FileProDOS::kMaxFileName+1]; - char lowerName[A2FileProDOS::kMaxFileName+1]; + DIError dierr = kDIErrNone; + char* normalizedPath = nil; + char* basePath = nil; + char* fileName = nil; + A2FileProDOS* pSubdir = nil; + A2FileDescr* pOpenSubdir = nil; + A2FileProDOS* pNewFile = nil; + unsigned char* subdirBuf = nil; + const bool allowLowerCase = (GetParameter(kParmProDOS_AllowLowerCase) != 0); + const bool createUnique = (GetParameter(kParm_CreateUnique) != 0); + char upperName[A2FileProDOS::kMaxFileName+1]; + char lowerName[A2FileProDOS::kMaxFileName+1]; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (!fDiskIsGood) - return kDIErrBadDiskImage; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (!fDiskIsGood) + return kDIErrBadDiskImage; - assert(pParms != nil); - assert(pParms->pathName != nil); - assert(pParms->storageType == A2FileProDOS::kStorageSeedling || - pParms->storageType == A2FileProDOS::kStorageExtended || - pParms->storageType == A2FileProDOS::kStorageDirectory); - // kStorageVolumeDirHeader not allowed -- that's created by Format - WMSG1(" ProDOS ---v--- CreateFile '%s'\n", pParms->pathName); - *ppNewFile = nil; + assert(pParms != nil); + assert(pParms->pathName != nil); + assert(pParms->storageType == A2FileProDOS::kStorageSeedling || + pParms->storageType == A2FileProDOS::kStorageExtended || + pParms->storageType == A2FileProDOS::kStorageDirectory); + // kStorageVolumeDirHeader not allowed -- that's created by Format + WMSG1(" ProDOS ---v--- CreateFile '%s'\n", pParms->pathName); + *ppNewFile = nil; - /* - * Normalize the pathname so that all components are ProDOS-safe - * and separated by ':'. - */ - assert(pParms->pathName != nil); - dierr = DoNormalizePath(pParms->pathName, pParms->fssep, - &normalizedPath); - if (dierr != kDIErrNone) - goto bail; - assert(normalizedPath != nil); + /* + * Normalize the pathname so that all components are ProDOS-safe + * and separated by ':'. + */ + assert(pParms->pathName != nil); + dierr = DoNormalizePath(pParms->pathName, pParms->fssep, + &normalizedPath); + if (dierr != kDIErrNone) + goto bail; + assert(normalizedPath != nil); - /* - * Split the base path and filename apart. - */ - char* cp; - cp = strrchr(normalizedPath, A2FileProDOS::kFssep); - if (cp == nil) { - assert(basePath == nil); - fileName = normalizedPath; - } else { - fileName = new char[strlen(cp+1) +1]; - strcpy(fileName, cp+1); - *cp = '\0'; - basePath = normalizedPath; - } - normalizedPath = nil; // either fileName or basePath points here now + /* + * Split the base path and filename apart. + */ + char* cp; + cp = strrchr(normalizedPath, A2FileProDOS::kFssep); + if (cp == nil) { + assert(basePath == nil); + fileName = normalizedPath; + } else { + fileName = new char[strlen(cp+1) +1]; + strcpy(fileName, cp+1); + *cp = '\0'; + basePath = normalizedPath; + } + normalizedPath = nil; // either fileName or basePath points here now - assert(fileName != nil); - //WMSG2(" ProDOS normalized to '%s':'%s'\n", - // basePath == nil ? "" : basePath, fileName); + assert(fileName != nil); + //WMSG2(" ProDOS normalized to '%s':'%s'\n", + // basePath == nil ? "" : basePath, fileName); - /* - * Open the base path. If it doesn't exist, create it recursively. - */ - if (basePath != nil) { - WMSG2(" ProDOS Creating '%s' in '%s'\n", fileName, basePath); - /* open the named subdir, creating it if it doesn't exist */ - pSubdir = (A2FileProDOS*)GetFileByName(basePath); - if (pSubdir == nil) { - WMSG1(" ProDOS Creating subdir '%s'\n", basePath); - A2File* pNewSub; - CreateParms newDirParms; - newDirParms.pathName = basePath; - newDirParms.fssep = A2FileProDOS::kFssep; - newDirParms.storageType = A2FileProDOS::kStorageDirectory; - newDirParms.fileType = kTypeDIR; // 0x0f - newDirParms.auxType = 0; - newDirParms.access = 0xe3; // unlocked, backup bit set - newDirParms.createWhen = newDirParms.modWhen = time(nil); - dierr = this->CreateFile(&newDirParms, &pNewSub); - if (dierr != kDIErrNone) - goto bail; - assert(pNewSub != nil); + /* + * Open the base path. If it doesn't exist, create it recursively. + */ + if (basePath != nil) { + WMSG2(" ProDOS Creating '%s' in '%s'\n", fileName, basePath); + /* open the named subdir, creating it if it doesn't exist */ + pSubdir = (A2FileProDOS*)GetFileByName(basePath); + if (pSubdir == nil) { + WMSG1(" ProDOS Creating subdir '%s'\n", basePath); + A2File* pNewSub; + CreateParms newDirParms; + newDirParms.pathName = basePath; + newDirParms.fssep = A2FileProDOS::kFssep; + newDirParms.storageType = A2FileProDOS::kStorageDirectory; + newDirParms.fileType = kTypeDIR; // 0x0f + newDirParms.auxType = 0; + newDirParms.access = 0xe3; // unlocked, backup bit set + newDirParms.createWhen = newDirParms.modWhen = time(nil); + dierr = this->CreateFile(&newDirParms, &pNewSub); + if (dierr != kDIErrNone) + goto bail; + assert(pNewSub != nil); - pSubdir = (A2FileProDOS*) pNewSub; - } + pSubdir = (A2FileProDOS*) pNewSub; + } - /* - * And now the annoying part. We need to reconstruct basePath out - * of the filenames actually present, rather than relying on the - * argument passed in. That's because some directories might have - * lower-case flags and some might not, and we do case-insensitive - * comparisons. It's not crucial for our inner workings, but the - * linear file list in the DiskFS should have accurate strings. - * (It'll work just fine, but the display might show the wrong values - * for parent directories until they reload the disk.) - * - * On the bright side, we know exactly how long the string needs - * to be, so we can just stomp on it in place. Assuming, of course, - * that the filename created matches up with what the filename - * normalizer came up with, which we can guarantee since (a) everybody - * uses the same normalizer and (b) the "uniqueify" stuff doesn't - * kick in for subdirs because we wouldn't be creating a new subdir - * if it didn't already exist. - * - * This is essentially the same as RegeneratePathName(), but that's - * meant for a situation where the filename already exists. - */ - A2FileProDOS* pBaseDir = pSubdir; - int basePathLen = strlen(basePath); - while (!pBaseDir->IsVolumeDirectory()) { - const char* fixedName = pBaseDir->GetFileName(); - int fixedLen = strlen(fixedName); - if (fixedLen > basePathLen) { - assert(false); - break; - } - assert(basePathLen == fixedLen || - *(basePath + (basePathLen-fixedLen-1)) == kDIFssep); - memcpy(basePath + (basePathLen-fixedLen), fixedName, fixedLen); - basePathLen -= fixedLen+1; + /* + * And now the annoying part. We need to reconstruct basePath out + * of the filenames actually present, rather than relying on the + * argument passed in. That's because some directories might have + * lower-case flags and some might not, and we do case-insensitive + * comparisons. It's not crucial for our inner workings, but the + * linear file list in the DiskFS should have accurate strings. + * (It'll work just fine, but the display might show the wrong values + * for parent directories until they reload the disk.) + * + * On the bright side, we know exactly how long the string needs + * to be, so we can just stomp on it in place. Assuming, of course, + * that the filename created matches up with what the filename + * normalizer came up with, which we can guarantee since (a) everybody + * uses the same normalizer and (b) the "uniqueify" stuff doesn't + * kick in for subdirs because we wouldn't be creating a new subdir + * if it didn't already exist. + * + * This is essentially the same as RegeneratePathName(), but that's + * meant for a situation where the filename already exists. + */ + A2FileProDOS* pBaseDir = pSubdir; + int basePathLen = strlen(basePath); + while (!pBaseDir->IsVolumeDirectory()) { + const char* fixedName = pBaseDir->GetFileName(); + int fixedLen = strlen(fixedName); + if (fixedLen > basePathLen) { + assert(false); + break; + } + assert(basePathLen == fixedLen || + *(basePath + (basePathLen-fixedLen-1)) == kDIFssep); + memcpy(basePath + (basePathLen-fixedLen), fixedName, fixedLen); + basePathLen -= fixedLen+1; - pBaseDir = (A2FileProDOS*) pBaseDir->GetParent(); - assert(pBaseDir != nil); - } - // check the math - if (pSubdir->IsVolumeDirectory()) - assert(basePathLen == 0); - else - assert(basePathLen == -1); - } else { - /* open the volume directory */ - WMSG1(" ProDOS Creating '%s' in volume dir\n", fileName); - /* volume dir must be first in the list */ - pSubdir = (A2FileProDOS*) GetNextFile(nil); - assert(pSubdir != nil); - assert(pSubdir->IsVolumeDirectory()); - } - if (pSubdir == nil) { - WMSG1(" ProDOS Unable to open subdir '%s'\n", basePath); - dierr = kDIErrFileNotFound; - goto bail; - } + pBaseDir = (A2FileProDOS*) pBaseDir->GetParent(); + assert(pBaseDir != nil); + } + // check the math + if (pSubdir->IsVolumeDirectory()) + assert(basePathLen == 0); + else + assert(basePathLen == -1); + } else { + /* open the volume directory */ + WMSG1(" ProDOS Creating '%s' in volume dir\n", fileName); + /* volume dir must be first in the list */ + pSubdir = (A2FileProDOS*) GetNextFile(nil); + assert(pSubdir != nil); + assert(pSubdir->IsVolumeDirectory()); + } + if (pSubdir == nil) { + WMSG1(" ProDOS Unable to open subdir '%s'\n", basePath); + dierr = kDIErrFileNotFound; + goto bail; + } - /* - * Load the block usage map into memory. All changes, to the end of this - * function, are made to the in-memory copy and can be "undone" by simply - * throwing the temporary map away. - */ - dierr = LoadVolBitmap(); - if (dierr != kDIErrNone) - return dierr; + /* + * Load the block usage map into memory. All changes, to the end of this + * function, are made to the in-memory copy and can be "undone" by simply + * throwing the temporary map away. + */ + dierr = LoadVolBitmap(); + if (dierr != kDIErrNone) + return dierr; - /* - * Load the subdir or volume dir into memory, and alloc a new directory - * entry. - */ - dierr = pSubdir->Open(&pOpenSubdir, false); - if (dierr != kDIErrNone) - goto bail; + /* + * Load the subdir or volume dir into memory, and alloc a new directory + * entry. + */ + dierr = pSubdir->Open(&pOpenSubdir, false); + if (dierr != kDIErrNone) + goto bail; - unsigned char* dirEntryPtr; - long dirLen; - unsigned short dirBlock, dirKeyBlock; - int dirEntrySlot; - dierr = AllocDirEntry(pOpenSubdir, &subdirBuf, &dirLen, &dirEntryPtr, - &dirKeyBlock, &dirEntrySlot, &dirBlock); - if (dierr != kDIErrNone) - goto bail; + unsigned char* dirEntryPtr; + long dirLen; + unsigned short dirBlock, dirKeyBlock; + int dirEntrySlot; + dierr = AllocDirEntry(pOpenSubdir, &subdirBuf, &dirLen, &dirEntryPtr, + &dirKeyBlock, &dirEntrySlot, &dirBlock); + if (dierr != kDIErrNone) + goto bail; - assert(subdirBuf != nil); - assert(dirLen > 0); - assert(dirKeyBlock > 0); - assert(dirEntrySlot >= 0); - assert(dirBlock > 0); + assert(subdirBuf != nil); + assert(dirLen > 0); + assert(dirKeyBlock > 0); + assert(dirEntrySlot >= 0); + assert(dirBlock > 0); - /* - * Create a copy of the filename with everything in upper case and spaces - * changed to periods. - */ - UpperCaseName(upperName, fileName); + /* + * Create a copy of the filename with everything in upper case and spaces + * changed to periods. + */ + UpperCaseName(upperName, fileName); - /* - * Make the name unique within the current directory. This requires - * appending digits until the name doesn't match any others. - * - * The filename buffer ("upperName") must be able to hold kMaxFileName+1 - * chars. It will be modified in place. - */ - if (createUnique && - pParms->storageType != A2FileProDOS::kStorageDirectory) - { - MakeFileNameUnique(subdirBuf, dirLen, upperName); - } else { - /* check to see if it already exists */ - if (NameExistsInDir(subdirBuf, dirLen, upperName)) { - if (pParms->storageType == A2FileProDOS::kStorageDirectory) - dierr = kDIErrDirectoryExists; - else - dierr = kDIErrFileExists; - goto bail; - } - } + /* + * Make the name unique within the current directory. This requires + * appending digits until the name doesn't match any others. + * + * The filename buffer ("upperName") must be able to hold kMaxFileName+1 + * chars. It will be modified in place. + */ + if (createUnique && + pParms->storageType != A2FileProDOS::kStorageDirectory) + { + MakeFileNameUnique(subdirBuf, dirLen, upperName); + } else { + /* check to see if it already exists */ + if (NameExistsInDir(subdirBuf, dirLen, upperName)) { + if (pParms->storageType == A2FileProDOS::kStorageDirectory) + dierr = kDIErrDirectoryExists; + else + dierr = kDIErrFileExists; + goto bail; + } + } - /* - * Allocate file storage and initialize: - * - For directory, a single block with the directory header. - * - For seedling, an empty block. - * - For extended, an extended key block entry and two empty blocks. - */ - long keyBlock; - int blocksUsed; - int newEOF; - keyBlock = -1; - blocksUsed = newEOF = -1; + /* + * Allocate file storage and initialize: + * - For directory, a single block with the directory header. + * - For seedling, an empty block. + * - For extended, an extended key block entry and two empty blocks. + */ + long keyBlock; + int blocksUsed; + int newEOF; + keyBlock = -1; + blocksUsed = newEOF = -1; - dierr = AllocInitialFileStorage(pParms, upperName, dirBlock, - dirEntrySlot, &keyBlock, &blocksUsed, &newEOF); - if (dierr != kDIErrNone) - goto bail; + dierr = AllocInitialFileStorage(pParms, upperName, dirBlock, + dirEntrySlot, &keyBlock, &blocksUsed, &newEOF); + if (dierr != kDIErrNone) + goto bail; - assert(blocksUsed > 0); - assert(keyBlock > 0); - assert(newEOF >= 0); + assert(blocksUsed > 0); + assert(keyBlock > 0); + assert(newEOF >= 0); - /* - * Fill out the newly-created directory entry pointed to by "dirEntryPtr". - * - * ProDOS filenames are always stored in upper case. ProDOS 8 v1.8 and - * later allow lower-case names with '.' converting to ' '. We optionally - * set the flags here, using the original file name to decide which parts - * are lower case. (Some parts of the original may have been stomped - * when the name was made unique, so we need to watch for that.) - */ - dirEntryPtr[0x00] = (pParms->storageType << 4) | strlen(upperName); - strncpy((char*) &dirEntryPtr[0x01], upperName, A2FileProDOS::kMaxFileName); - if (pParms->fileType >= 0 && pParms->fileType <= 0xff) - dirEntryPtr[0x10] = (unsigned char) pParms->fileType; - else - dirEntryPtr[0x10] = 0; // HFS long type? - PutShortLE(&dirEntryPtr[0x11], (unsigned short) keyBlock); - PutShortLE(&dirEntryPtr[0x13], blocksUsed); - PutShortLE(&dirEntryPtr[0x15], newEOF); - dirEntryPtr[0x17] = 0; // high byte of EOF - PutLongLE(&dirEntryPtr[0x18], A2FileProDOS::ConvertProDate(pParms->createWhen)); - if (allowLowerCase) { - unsigned short lcBits; - lcBits = GenerateLowerCaseBits(upperName, fileName, false); - GenerateLowerCaseName(upperName, lowerName, lcBits, false); - lowerName[strlen(upperName)] = '\0'; + /* + * Fill out the newly-created directory entry pointed to by "dirEntryPtr". + * + * ProDOS filenames are always stored in upper case. ProDOS 8 v1.8 and + * later allow lower-case names with '.' converting to ' '. We optionally + * set the flags here, using the original file name to decide which parts + * are lower case. (Some parts of the original may have been stomped + * when the name was made unique, so we need to watch for that.) + */ + dirEntryPtr[0x00] = (pParms->storageType << 4) | strlen(upperName); + strncpy((char*) &dirEntryPtr[0x01], upperName, A2FileProDOS::kMaxFileName); + if (pParms->fileType >= 0 && pParms->fileType <= 0xff) + dirEntryPtr[0x10] = (unsigned char) pParms->fileType; + else + dirEntryPtr[0x10] = 0; // HFS long type? + PutShortLE(&dirEntryPtr[0x11], (unsigned short) keyBlock); + PutShortLE(&dirEntryPtr[0x13], blocksUsed); + PutShortLE(&dirEntryPtr[0x15], newEOF); + dirEntryPtr[0x17] = 0; // high byte of EOF + PutLongLE(&dirEntryPtr[0x18], A2FileProDOS::ConvertProDate(pParms->createWhen)); + if (allowLowerCase) { + unsigned short lcBits; + lcBits = GenerateLowerCaseBits(upperName, fileName, false); + GenerateLowerCaseName(upperName, lowerName, lcBits, false); + lowerName[strlen(upperName)] = '\0'; - PutShortLE(&dirEntryPtr[0x1c], lcBits); - } else { - strcpy(lowerName, upperName); - PutShortLE(&dirEntryPtr[0x1c], 0); // version, min_version - } - dirEntryPtr[0x1e] = pParms->access; - if (pParms->auxType >= 0 && pParms->auxType <= 0xffff) - PutShortLE(&dirEntryPtr[0x1f], (unsigned short) pParms->auxType); - else - PutShortLE(&dirEntryPtr[0x1f], 0); - PutLongLE(&dirEntryPtr[0x21], A2FileProDOS::ConvertProDate(pParms->modWhen)); - PutShortLE(&dirEntryPtr[0x25], dirKeyBlock); + PutShortLE(&dirEntryPtr[0x1c], lcBits); + } else { + strcpy(lowerName, upperName); + PutShortLE(&dirEntryPtr[0x1c], 0); // version, min_version + } + dirEntryPtr[0x1e] = pParms->access; + if (pParms->auxType >= 0 && pParms->auxType <= 0xffff) + PutShortLE(&dirEntryPtr[0x1f], (unsigned short) pParms->auxType); + else + PutShortLE(&dirEntryPtr[0x1f], 0); + PutLongLE(&dirEntryPtr[0x21], A2FileProDOS::ConvertProDate(pParms->modWhen)); + PutShortLE(&dirEntryPtr[0x25], dirKeyBlock); - /* - * Write updated directory. If this succeeds, we can no longer undo - * what we have done by simply bailing. If this fails partway through, - * we might have a corrupted disk, so it's best to ensure that it's not - * going to fail before we call. - * - * Assuming this isn't a nibble image with I/O errors, the only way we - * can really fail is by running out of disk space. The block has been - * pre-allocated, so this should always work. - */ - dierr = pOpenSubdir->Write(subdirBuf, dirLen); - if (dierr != kDIErrNone) { - WMSG1(" ProDOS directory write failed (dirLen=%ld)\n", dirLen); - goto bail; - } + /* + * Write updated directory. If this succeeds, we can no longer undo + * what we have done by simply bailing. If this fails partway through, + * we might have a corrupted disk, so it's best to ensure that it's not + * going to fail before we call. + * + * Assuming this isn't a nibble image with I/O errors, the only way we + * can really fail is by running out of disk space. The block has been + * pre-allocated, so this should always work. + */ + dierr = pOpenSubdir->Write(subdirBuf, dirLen); + if (dierr != kDIErrNone) { + WMSG1(" ProDOS directory write failed (dirLen=%ld)\n", dirLen); + goto bail; + } - /* - * Flush updated block usage map. - */ - dierr = SaveVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + /* + * Flush updated block usage map. + */ + dierr = SaveVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - /* - * Success! - * - * Create an A2File entry for this, and add it to the list. The calls - * below will re-process some of what we just created, which is slightly - * inefficient but helps guarantee that we aren't creating bogus data - * structures that won't match what we see when the disk is reloaded. - * - * - Regen or update internal VolumeUsage map?? Throw it away or mark - * it as invalid? - */ - pNewFile = new A2FileProDOS(this); + /* + * Success! + * + * Create an A2File entry for this, and add it to the list. The calls + * below will re-process some of what we just created, which is slightly + * inefficient but helps guarantee that we aren't creating bogus data + * structures that won't match what we see when the disk is reloaded. + * + * - Regen or update internal VolumeUsage map?? Throw it away or mark + * it as invalid? + */ + pNewFile = new A2FileProDOS(this); - A2FileProDOS::DirEntry* pEntry; - pEntry = &pNewFile->fDirEntry; + A2FileProDOS::DirEntry* pEntry; + pEntry = &pNewFile->fDirEntry; - A2FileProDOS::InitDirEntry(pEntry, dirEntryPtr); + A2FileProDOS::InitDirEntry(pEntry, dirEntryPtr); - pNewFile->fParentDirBlock = dirBlock; - pNewFile->fParentDirIdx = (dirEntrySlot-1) % kEntriesPerBlock; - pNewFile->fSparseDataEof = 0; - pNewFile->fSparseRsrcEof = 0; + pNewFile->fParentDirBlock = dirBlock; + pNewFile->fParentDirIdx = (dirEntrySlot-1) % kEntriesPerBlock; + pNewFile->fSparseDataEof = 0; + pNewFile->fSparseRsrcEof = 0; - /* - * Get the properly-cased filename for the file list. We already have - * a name in "lowerName", but it doesn't take AppleWorks aux type - * case stuff into account. If necessary, deal with it now. - */ - if (A2FileProDOS::UsesAppleWorksAuxType(pNewFile->fDirEntry.fileType)) { - DiskFSProDOS::GenerateLowerCaseName(pNewFile->fDirEntry.fileName, - lowerName, pNewFile->fDirEntry.auxType, true); - } - pNewFile->SetPathName(basePath == nil ? "" : basePath, lowerName); + /* + * Get the properly-cased filename for the file list. We already have + * a name in "lowerName", but it doesn't take AppleWorks aux type + * case stuff into account. If necessary, deal with it now. + */ + if (A2FileProDOS::UsesAppleWorksAuxType(pNewFile->fDirEntry.fileType)) { + DiskFSProDOS::GenerateLowerCaseName(pNewFile->fDirEntry.fileName, + lowerName, pNewFile->fDirEntry.auxType, true); + } + pNewFile->SetPathName(basePath == nil ? "" : basePath, lowerName); - if (pEntry->storageType == A2FileProDOS::kStorageExtended) { - dierr = ReadExtendedInfo(pNewFile); - if (dierr != kDIErrNone) { - WMSG0(" ProDOS GLITCH: readback of extended block failed!\n"); - delete pNewFile; - goto bail; - } - } + if (pEntry->storageType == A2FileProDOS::kStorageExtended) { + dierr = ReadExtendedInfo(pNewFile); + if (dierr != kDIErrNone) { + WMSG0(" ProDOS GLITCH: readback of extended block failed!\n"); + delete pNewFile; + goto bail; + } + } - pNewFile->SetParent(pSubdir); - //pNewFile->Dump(); + pNewFile->SetParent(pSubdir); + //pNewFile->Dump(); - /* - * Because we're hierarchical, and we guarantee that the contents of - * subdirectories are grouped together, we must insert the file into an - * appropriate place in the list rather than just throwing it onto the - * end. - * - * The proper location for the new file in the linear list is after the - * previous file in our subdir. If we're the first item in the subdir, - * we get added right after the parent. If not, we need to scan, starting - * from the parent, for an entry in the file list whose key block pointer - * matches that of the previous item in the list. - * - * We wouldn't be this far if the disk were damaged, so we don't have to - * worry too much about weirdness. The directory entry allocator always - * returns the first available, so we know the previous entry is valid. - */ - unsigned char* prevDirEntryPtr; - prevDirEntryPtr = GetPrevDirEntry(subdirBuf, dirEntryPtr); - if (prevDirEntryPtr == nil) { - /* previous entry is volume or subdir header */ - InsertFileInList(pNewFile, pNewFile->GetParent()); - WMSG2("Inserted '%s' after '%s'\n", - pNewFile->GetPathName(), pNewFile->GetParent()->GetPathName()); - } else { - /* dig out the key block pointer and find the matching file */ - unsigned short prevKeyBlock; - assert((prevDirEntryPtr[0x00] & 0xf0) != 0); // verify storage type - prevKeyBlock = GetShortLE(&prevDirEntryPtr[0x11]); - A2File* pPrev; - pPrev = FindFileByKeyBlock(pNewFile->GetParent(), prevKeyBlock); - if (pPrev == nil) { - /* should be impossible! */ - assert(false); - AddFileToList(pNewFile); - } else { - /* insert the new file in the list after the previous file */ - InsertFileInList(pNewFile, pPrev); - } - } -// WMSG0("LIST NOW:\n"); -// DumpFileList(); + /* + * Because we're hierarchical, and we guarantee that the contents of + * subdirectories are grouped together, we must insert the file into an + * appropriate place in the list rather than just throwing it onto the + * end. + * + * The proper location for the new file in the linear list is after the + * previous file in our subdir. If we're the first item in the subdir, + * we get added right after the parent. If not, we need to scan, starting + * from the parent, for an entry in the file list whose key block pointer + * matches that of the previous item in the list. + * + * We wouldn't be this far if the disk were damaged, so we don't have to + * worry too much about weirdness. The directory entry allocator always + * returns the first available, so we know the previous entry is valid. + */ + unsigned char* prevDirEntryPtr; + prevDirEntryPtr = GetPrevDirEntry(subdirBuf, dirEntryPtr); + if (prevDirEntryPtr == nil) { + /* previous entry is volume or subdir header */ + InsertFileInList(pNewFile, pNewFile->GetParent()); + WMSG2("Inserted '%s' after '%s'\n", + pNewFile->GetPathName(), pNewFile->GetParent()->GetPathName()); + } else { + /* dig out the key block pointer and find the matching file */ + unsigned short prevKeyBlock; + assert((prevDirEntryPtr[0x00] & 0xf0) != 0); // verify storage type + prevKeyBlock = GetShortLE(&prevDirEntryPtr[0x11]); + A2File* pPrev; + pPrev = FindFileByKeyBlock(pNewFile->GetParent(), prevKeyBlock); + if (pPrev == nil) { + /* should be impossible! */ + assert(false); + AddFileToList(pNewFile); + } else { + /* insert the new file in the list after the previous file */ + InsertFileInList(pNewFile, pPrev); + } + } +// WMSG0("LIST NOW:\n"); +// DumpFileList(); - *ppNewFile = pNewFile; - pNewFile = nil; + *ppNewFile = pNewFile; + pNewFile = nil; bail: - delete pNewFile; - if (pOpenSubdir != nil) - pOpenSubdir->Close(); // writes updated dir entry in parent dir - FreeVolBitmap(); - delete[] normalizedPath; - delete[] subdirBuf; - delete[] fileName; - delete[] basePath; - WMSG1(" ProDOS ---^--- CreateFile '%s' DONE\n", pParms->pathName); - return dierr; + delete pNewFile; + if (pOpenSubdir != nil) + pOpenSubdir->Close(); // writes updated dir entry in parent dir + FreeVolBitmap(); + delete[] normalizedPath; + delete[] subdirBuf; + delete[] fileName; + delete[] basePath; + WMSG1(" ProDOS ---^--- CreateFile '%s' DONE\n", pParms->pathName); + return dierr; } /* @@ -2177,16 +2177,16 @@ bail: A2File* DiskFSProDOS::FindFileByKeyBlock(A2File* pStart, unsigned short keyBlock) { - while (pStart != nil) { - A2FileProDOS* pPro = (A2FileProDOS*) pStart; + while (pStart != nil) { + A2FileProDOS* pPro = (A2FileProDOS*) pStart; - if (pPro->fDirEntry.keyPointer == keyBlock) - return pStart; + if (pPro->fDirEntry.keyPointer == keyBlock) + return pStart; - pStart = GetNextFile(pStart); - } + pStart = GetNextFile(pStart); + } - return nil; + return nil; } /* @@ -2202,104 +2202,104 @@ DiskFSProDOS::FindFileByKeyBlock(A2File* pStart, unsigned short keyBlock) */ DIError DiskFSProDOS::AllocInitialFileStorage(const CreateParms* pParms, - const char* upperName, unsigned short dirBlock, int dirEntrySlot, - long* pKeyBlock, int* pBlocksUsed, int* pNewEOF) + const char* upperName, unsigned short dirBlock, int dirEntrySlot, + long* pKeyBlock, int* pBlocksUsed, int* pNewEOF) { - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; - long keyBlock; - int blocksUsed; - int newEOF; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; + long keyBlock; + int blocksUsed; + int newEOF; - blocksUsed = -1; - keyBlock = -1; - newEOF = 0; - memset(blkBuf, 0, sizeof(blkBuf)); + blocksUsed = -1; + keyBlock = -1; + newEOF = 0; + memset(blkBuf, 0, sizeof(blkBuf)); - if (pParms->storageType == A2FileProDOS::kStorageSeedling) { - keyBlock = AllocBlock(); - if (keyBlock == -1) { - dierr = kDIErrDiskFull; - goto bail; - } - blocksUsed = 1; + if (pParms->storageType == A2FileProDOS::kStorageSeedling) { + keyBlock = AllocBlock(); + if (keyBlock == -1) { + dierr = kDIErrDiskFull; + goto bail; + } + blocksUsed = 1; - /* write zeroed block */ - dierr = fpImg->WriteBlock(keyBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; - } else if (pParms->storageType == A2FileProDOS::kStorageExtended) { - long dataBlock, rsrcBlock; + /* write zeroed block */ + dierr = fpImg->WriteBlock(keyBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; + } else if (pParms->storageType == A2FileProDOS::kStorageExtended) { + long dataBlock, rsrcBlock; - dataBlock = AllocBlock(); - rsrcBlock = AllocBlock(); - keyBlock = AllocBlock(); - if (dataBlock < 0 || rsrcBlock < 0 || keyBlock < 0) { - dierr = kDIErrDiskFull; - goto bail; - } - blocksUsed = 3; - newEOF = kBlkSize; + dataBlock = AllocBlock(); + rsrcBlock = AllocBlock(); + keyBlock = AllocBlock(); + if (dataBlock < 0 || rsrcBlock < 0 || keyBlock < 0) { + dierr = kDIErrDiskFull; + goto bail; + } + blocksUsed = 3; + newEOF = kBlkSize; - /* write zeroed block */ - dierr = fpImg->WriteBlock(dataBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; - dierr = fpImg->WriteBlock(rsrcBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; + /* write zeroed block */ + dierr = fpImg->WriteBlock(dataBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; + dierr = fpImg->WriteBlock(rsrcBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; - /* fill in extended key block details */ - blkBuf[0x00] = blkBuf[0x100] = A2FileProDOS::kStorageSeedling; - PutShortLE(&blkBuf[0x01], (unsigned short) dataBlock); - PutShortLE(&blkBuf[0x101], (unsigned short) rsrcBlock); - blkBuf[0x03] = blkBuf[0x103] = 1; // blocks used (lo byte) - /* 3 bytes at 0x05 hold EOF, currently 0 */ + /* fill in extended key block details */ + blkBuf[0x00] = blkBuf[0x100] = A2FileProDOS::kStorageSeedling; + PutShortLE(&blkBuf[0x01], (unsigned short) dataBlock); + PutShortLE(&blkBuf[0x101], (unsigned short) rsrcBlock); + blkBuf[0x03] = blkBuf[0x103] = 1; // blocks used (lo byte) + /* 3 bytes at 0x05 hold EOF, currently 0 */ - dierr = fpImg->WriteBlock(keyBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; - } else if (pParms->storageType == A2FileProDOS::kStorageDirectory) { - keyBlock = AllocBlock(); - if (keyBlock == -1) { - dierr = kDIErrDiskFull; - goto bail; - } - blocksUsed = 1; - newEOF = kBlkSize; + dierr = fpImg->WriteBlock(keyBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; + } else if (pParms->storageType == A2FileProDOS::kStorageDirectory) { + keyBlock = AllocBlock(); + if (keyBlock == -1) { + dierr = kDIErrDiskFull; + goto bail; + } + blocksUsed = 1; + newEOF = kBlkSize; - /* fill in directory header fields */ - // 0x00: prev, set to zero - // 0x02: next, set to zero - blkBuf[0x04] = (A2FileProDOS::kStorageSubdirHeader << 4) | strlen(upperName); - strncpy((char*) &blkBuf[0x05], upperName, A2FileProDOS::kMaxFileName); - blkBuf[0x14] = 0x76; // 0x75 under old P8, 0x76 under GS/OS - PutLongLE(&blkBuf[0x1c], A2FileProDOS::ConvertProDate(pParms->createWhen)); - blkBuf[0x20] = 5; // 0 under 1.0, 3 under v1.4?, 5 under GS/OS - blkBuf[0x21] = 0; - blkBuf[0x22] = pParms->access; - blkBuf[0x23] = kEntryLength; - blkBuf[0x24] = kEntriesPerBlock; - PutShortLE(&blkBuf[0x25], 0); // file count - PutShortLE(&blkBuf[0x27], dirBlock); - blkBuf[0x29] = (unsigned char) dirEntrySlot; - blkBuf[0x2a] = kEntryLength; // the parent dir's entry length + /* fill in directory header fields */ + // 0x00: prev, set to zero + // 0x02: next, set to zero + blkBuf[0x04] = (A2FileProDOS::kStorageSubdirHeader << 4) | strlen(upperName); + strncpy((char*) &blkBuf[0x05], upperName, A2FileProDOS::kMaxFileName); + blkBuf[0x14] = 0x76; // 0x75 under old P8, 0x76 under GS/OS + PutLongLE(&blkBuf[0x1c], A2FileProDOS::ConvertProDate(pParms->createWhen)); + blkBuf[0x20] = 5; // 0 under 1.0, 3 under v1.4?, 5 under GS/OS + blkBuf[0x21] = 0; + blkBuf[0x22] = pParms->access; + blkBuf[0x23] = kEntryLength; + blkBuf[0x24] = kEntriesPerBlock; + PutShortLE(&blkBuf[0x25], 0); // file count + PutShortLE(&blkBuf[0x27], dirBlock); + blkBuf[0x29] = (unsigned char) dirEntrySlot; + blkBuf[0x2a] = kEntryLength; // the parent dir's entry length - dierr = fpImg->WriteBlock(keyBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; - } else { - assert(false); - dierr = kDIErrInternal; - goto bail; - } + dierr = fpImg->WriteBlock(keyBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; + } else { + assert(false); + dierr = kDIErrInternal; + goto bail; + } - *pKeyBlock = keyBlock; - *pBlocksUsed = blocksUsed; - *pNewEOF = newEOF; + *pKeyBlock = keyBlock; + *pBlocksUsed = blocksUsed; + *pNewEOF = newEOF; bail: - return dierr; + return dierr; } @@ -2318,111 +2318,111 @@ bail: bool DiskFSProDOS::CheckDiskIsGood(void) { - DIError dierr; - bool result = true; - int i; + DIError dierr; + bool result = true; + int i; - if (fEarlyDamage) - result = false; + if (fEarlyDamage) + result = false; - dierr = LoadVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + dierr = LoadVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - /* - * Check the system blocks to see if any of them are marked as free. - * If so, refuse to write to this disk. - */ - if (!GetBlockUseEntry(0) || !GetBlockUseEntry(1)) { - fpImg->AddNote(DiskImg::kNoteWarning, "Block 0/1 marked as free."); - result = false; - } - for (i = GetNumBitmapBlocks(); i > 0; i--) { - if (!GetBlockUseEntry(fBitMapPointer + i -1)) { - fpImg->AddNote(DiskImg::kNoteWarning, - "One or more bitmap blocks are marked as free."); - result = false; - break; - } - } + /* + * Check the system blocks to see if any of them are marked as free. + * If so, refuse to write to this disk. + */ + if (!GetBlockUseEntry(0) || !GetBlockUseEntry(1)) { + fpImg->AddNote(DiskImg::kNoteWarning, "Block 0/1 marked as free."); + result = false; + } + for (i = GetNumBitmapBlocks(); i > 0; i--) { + if (!GetBlockUseEntry(fBitMapPointer + i -1)) { + fpImg->AddNote(DiskImg::kNoteWarning, + "One or more bitmap blocks are marked as free."); + result = false; + break; + } + } - /* - * Check for used blocks that aren't marked in-use. - * - * This requires that VolumeUsage be accurate. Since this function is - * only run during initial startup, any later deviation between VU and - * the block use map is irrelevant. - */ - VolumeUsage::ChunkState cstate; - long blk, notMarked, extraUsed, conflicts; - notMarked = extraUsed = conflicts = 0; - for (blk = 0; blk < fVolumeUsage.GetNumChunks(); blk++) { - dierr = fVolumeUsage.GetChunkState(blk, &cstate); - if (dierr != kDIErrNone) { - fpImg->AddNote(DiskImg::kNoteWarning, - "Internal volume usage error on blk=%ld.", blk); - result = false; - goto bail; - } + /* + * Check for used blocks that aren't marked in-use. + * + * This requires that VolumeUsage be accurate. Since this function is + * only run during initial startup, any later deviation between VU and + * the block use map is irrelevant. + */ + VolumeUsage::ChunkState cstate; + long blk, notMarked, extraUsed, conflicts; + notMarked = extraUsed = conflicts = 0; + for (blk = 0; blk < fVolumeUsage.GetNumChunks(); blk++) { + dierr = fVolumeUsage.GetChunkState(blk, &cstate); + if (dierr != kDIErrNone) { + fpImg->AddNote(DiskImg::kNoteWarning, + "Internal volume usage error on blk=%ld.", blk); + result = false; + goto bail; + } - if (cstate.isUsed && !cstate.isMarkedUsed) - notMarked++; - if (!cstate.isUsed && cstate.isMarkedUsed) - extraUsed++; - if (cstate.purpose == VolumeUsage::kChunkPurposeConflict) - conflicts++; - } - if (extraUsed > 0) { - fpImg->AddNote(DiskImg::kNoteInfo, - "%ld block%s marked used but not part of any file.", - extraUsed, extraUsed == 1 ? " is" : "s are"); - // not a problem, really - } - if (notMarked > 0) { - fpImg->AddNote(DiskImg::kNoteWarning, - "%ld block%s used by files but not marked used.", - notMarked, notMarked == 1 ? " is" : "s are"); - result = false; // very bad -- any change could trash files - } - if (conflicts > 0) { - fpImg->AddNote(DiskImg::kNoteWarning, - "%ld block%s used by more than one file.", - conflicts, conflicts == 1 ? " is" : "s are"); - result = false; // kinda bad -- file deletion leads to trouble - } + if (cstate.isUsed && !cstate.isMarkedUsed) + notMarked++; + if (!cstate.isUsed && cstate.isMarkedUsed) + extraUsed++; + if (cstate.purpose == VolumeUsage::kChunkPurposeConflict) + conflicts++; + } + if (extraUsed > 0) { + fpImg->AddNote(DiskImg::kNoteInfo, + "%ld block%s marked used but not part of any file.", + extraUsed, extraUsed == 1 ? " is" : "s are"); + // not a problem, really + } + if (notMarked > 0) { + fpImg->AddNote(DiskImg::kNoteWarning, + "%ld block%s used by files but not marked used.", + notMarked, notMarked == 1 ? " is" : "s are"); + result = false; // very bad -- any change could trash files + } + if (conflicts > 0) { + fpImg->AddNote(DiskImg::kNoteWarning, + "%ld block%s used by more than one file.", + conflicts, conflicts == 1 ? " is" : "s are"); + result = false; // kinda bad -- file deletion leads to trouble + } - /* - * Check for bits set past the end of the actually-needed bits. For - * some reason P8 and GS/OS both examine these bits, and GS/OS will - * freak out completely and claim the disk is unrecognizeable ("would - * you like to format?") if they're set. - */ - if (ScanForExtraEntries()) { - fpImg->AddNote(DiskImg::kNoteWarning, - "Blocks past the end of the disk are marked 'in use' in the" - " volume bitmap."); - /* don't flunk the disk just for this */ - } + /* + * Check for bits set past the end of the actually-needed bits. For + * some reason P8 and GS/OS both examine these bits, and GS/OS will + * freak out completely and claim the disk is unrecognizeable ("would + * you like to format?") if they're set. + */ + if (ScanForExtraEntries()) { + fpImg->AddNote(DiskImg::kNoteWarning, + "Blocks past the end of the disk are marked 'in use' in the" + " volume bitmap."); + /* don't flunk the disk just for this */ + } - /* - * Scan for "damaged" or "suspicious" files diagnosed earlier. - */ - bool damaged, suspicious; - ScanForDamagedFiles(&damaged, &suspicious); + /* + * Scan for "damaged" or "suspicious" files diagnosed earlier. + */ + bool damaged, suspicious; + ScanForDamagedFiles(&damaged, &suspicious); - if (damaged) { - fpImg->AddNote(DiskImg::kNoteWarning, - "One or more files are damaged."); - result = false; - } else if (suspicious) { - fpImg->AddNote(DiskImg::kNoteWarning, - "One or more files look suspicious."); - result = false; - } + if (damaged) { + fpImg->AddNote(DiskImg::kNoteWarning, + "One or more files are damaged."); + result = false; + } else if (suspicious) { + fpImg->AddNote(DiskImg::kNoteWarning, + "One or more files look suspicious."); + result = false; + } bail: - FreeVolBitmap(); - return result; + FreeVolBitmap(); + return result; } @@ -2433,14 +2433,14 @@ bail: /*static*/ bool DiskFSProDOS::IsValidVolumeName(const char* name) { - assert((int) A2FileProDOS::kMaxFileName == (int) kMaxVolumeName); - if (!IsValidFileName(name)) - return false; - while (*name != '\0') { - if (*name++ == ' ') - return false; - } - return true; + assert((int) A2FileProDOS::kMaxFileName == (int) kMaxVolumeName); + if (!IsValidFileName(name)) + return false; + while (*name != '\0') { + if (*name++ == ' ') + return false; + } + return true; } /* @@ -2454,41 +2454,41 @@ DiskFSProDOS::IsValidVolumeName(const char* name) /*static*/ bool DiskFSProDOS::IsValidFileName(const char* name) { - if (name == nil) { - assert(false); - return false; - } + if (name == nil) { + assert(false); + return false; + } - /* must be 1-15 characters long */ - if (name[0] == '\0') - return false; - if (strlen(name) > A2FileProDOS::kMaxFileName) - return false; + /* must be 1-15 characters long */ + if (name[0] == '\0') + return false; + if (strlen(name) > A2FileProDOS::kMaxFileName) + return false; - /* must begin with letter; this also catches zero-length filenames */ - if (toupper(name[0]) < 'A' || toupper(name[0]) > 'Z') - return false; + /* must begin with letter; this also catches zero-length filenames */ + if (toupper(name[0]) < 'A' || toupper(name[0]) > 'Z') + return false; - /* no trailing spaces */ - if (name[strlen(name)-1] == ' ') - return false; + /* no trailing spaces */ + if (name[strlen(name)-1] == ' ') + return false; - /* must be A-Za-z 0-9 '.' ' ' */ - name++; - while (*name != '\0') { - if (!( (toupper(*name) >= 'A' && toupper(*name) <= 'Z') || - (*name >= '0' && *name <= '9') || - (*name == '.') || - (*name == ' ') - )) - { - return false; - } + /* must be A-Za-z 0-9 '.' ' ' */ + name++; + while (*name != '\0') { + if (!( (toupper(*name) >= 'A' && toupper(*name) <= 'Z') || + (*name >= '0' && *name <= '9') || + (*name == '.') || + (*name == ' ') + )) + { + return false; + } - name++; - } + name++; + } - return true; + return true; } /* @@ -2504,34 +2504,34 @@ DiskFSProDOS::IsValidFileName(const char* name) */ /*static*/ unsigned short DiskFSProDOS::GenerateLowerCaseBits(const char* upperName, - const char* lowerName, bool forAppleWorks) + const char* lowerName, bool forAppleWorks) { - unsigned short caseMask = 0x8000; - unsigned short caseBit = 0x8000; - int len, i; - char lowch; - - len = strlen(upperName); - assert(len <= A2FileProDOS::kMaxFileName); + unsigned short caseMask = 0x8000; + unsigned short caseBit = 0x8000; + int len, i; + char lowch; + + len = strlen(upperName); + assert(len <= A2FileProDOS::kMaxFileName); - for (i = 0; i < len; i++) { - caseBit >>= 1; - lowch = A2FileProDOS::NameToLower(upperName[i]); - if (lowch == lowerName[i]) - caseMask |= caseBit; - } + for (i = 0; i < len; i++) { + caseBit >>= 1; + lowch = A2FileProDOS::NameToLower(upperName[i]); + if (lowch == lowerName[i]) + caseMask |= caseBit; + } - if (forAppleWorks) { - unsigned short adjusted; - caseMask <<= 1; - adjusted = caseMask << 8 | caseMask >> 8; - return adjusted; - } else { - if (caseMask == 0x8000) - return 0; // all upper case, don't freak out pre-v1.8 - else - return caseMask; - } + if (forAppleWorks) { + unsigned short adjusted; + caseMask <<= 1; + adjusted = caseMask << 8 | caseMask >> 8; + return adjusted; + } else { + if (caseMask == 0x8000) + return 0; // all upper case, don't freak out pre-v1.8 + else + return caseMask; + } } /* @@ -2550,45 +2550,45 @@ DiskFSProDOS::GenerateLowerCaseBits(const char* upperName, */ /*static*/ void DiskFSProDOS::GenerateLowerCaseName(const char* upperName, char* lowerName, - unsigned short lcFlags, bool fromAppleWorks) + unsigned short lcFlags, bool fromAppleWorks) { - int nameLen = strlen(upperName); - int bit; - assert(nameLen <= A2FileProDOS::kMaxFileName); + int nameLen = strlen(upperName); + int bit; + assert(nameLen <= A2FileProDOS::kMaxFileName); - if (fromAppleWorks) { - /* handle AppleWorks lower-case-in-auxtype */ - unsigned short caseMask = // swap bytes - (lcFlags << 8) | (lcFlags >> 8); - for (bit = 0; bit < nameLen ; bit++) { - if ((caseMask & 0x8000) != 0) - lowerName[bit] = A2FileProDOS::NameToLower(upperName[bit]); - else - lowerName[bit] = upperName[bit]; - caseMask <<= 1; - } - for ( ; bit < A2FileProDOS::kMaxFileName; bit++) - lowerName[bit] = '\0'; - } else { - /* handle lower-case conversion; see GS/OS tech note #8 */ - if (lcFlags != 0 && !(lcFlags & 0x8000)) { - // Should be zero or 0x8000 plus other bits; shouldn't be - // bunch of bits without 0x8000 or 0x8000 by itself. Not - // really a problem, just unexpected. - assert(false); - memcpy(lowerName, upperName, A2FileProDOS::kMaxFileName); - return; - } - for (bit = 0; bit < nameLen; bit++) { - lcFlags <<= 1; - if ((lcFlags & 0x8000) != 0) - lowerName[bit] = A2FileProDOS::NameToLower(upperName[bit]); - else - lowerName[bit] = upperName[bit]; - } - } - for ( ; bit < A2FileProDOS::kMaxFileName; bit++) - lowerName[bit] = '\0'; + if (fromAppleWorks) { + /* handle AppleWorks lower-case-in-auxtype */ + unsigned short caseMask = // swap bytes + (lcFlags << 8) | (lcFlags >> 8); + for (bit = 0; bit < nameLen ; bit++) { + if ((caseMask & 0x8000) != 0) + lowerName[bit] = A2FileProDOS::NameToLower(upperName[bit]); + else + lowerName[bit] = upperName[bit]; + caseMask <<= 1; + } + for ( ; bit < A2FileProDOS::kMaxFileName; bit++) + lowerName[bit] = '\0'; + } else { + /* handle lower-case conversion; see GS/OS tech note #8 */ + if (lcFlags != 0 && !(lcFlags & 0x8000)) { + // Should be zero or 0x8000 plus other bits; shouldn't be + // bunch of bits without 0x8000 or 0x8000 by itself. Not + // really a problem, just unexpected. + assert(false); + memcpy(lowerName, upperName, A2FileProDOS::kMaxFileName); + return; + } + for (bit = 0; bit < nameLen; bit++) { + lcFlags <<= 1; + if ((lcFlags & 0x8000) != 0) + lowerName[bit] = A2FileProDOS::NameToLower(upperName[bit]); + else + lowerName[bit] = upperName[bit]; + } + } + for ( ; bit < A2FileProDOS::kMaxFileName; bit++) + lowerName[bit] = '\0'; } /* @@ -2601,34 +2601,34 @@ DiskFSProDOS::GenerateLowerCaseName(const char* upperName, char* lowerName, */ DIError DiskFSProDOS::NormalizePath(const char* path, char fssep, - char* normalizedBuf, int* pNormalizedBufLen) + char* normalizedBuf, int* pNormalizedBufLen) { - DIError dierr = kDIErrNone; - char* normalizedPath = nil; - int len; + DIError dierr = kDIErrNone; + char* normalizedPath = nil; + int len; - assert(pNormalizedBufLen != nil); - assert(normalizedBuf != nil || *pNormalizedBufLen == 0); + assert(pNormalizedBufLen != nil); + assert(normalizedBuf != nil || *pNormalizedBufLen == 0); - dierr = DoNormalizePath(path, fssep, &normalizedPath); - if (dierr != kDIErrNone) - goto bail; + dierr = DoNormalizePath(path, fssep, &normalizedPath); + if (dierr != kDIErrNone) + goto bail; - assert(normalizedPath != nil); - len = strlen(normalizedPath); - if (normalizedBuf == nil || *pNormalizedBufLen <= len) { - /* too short */ - dierr = kDIErrDataOverrun; - } else { - /* fits */ - strcpy(normalizedBuf, normalizedPath); - } + assert(normalizedPath != nil); + len = strlen(normalizedPath); + if (normalizedBuf == nil || *pNormalizedBufLen <= len) { + /* too short */ + dierr = kDIErrDataOverrun; + } else { + /* fits */ + strcpy(normalizedBuf, normalizedPath); + } - *pNormalizedBufLen = len+1; // alloc room for the '\0' + *pNormalizedBufLen = len+1; // alloc room for the '\0' bail: - delete[] normalizedPath; - return dierr; + delete[] normalizedPath; + return dierr; } /* @@ -2648,126 +2648,126 @@ bail: */ DIError DiskFSProDOS::DoNormalizePath(const char* path, char fssep, - char** pNormalizedPath) + char** pNormalizedPath) { - DIError dierr = kDIErrNone; - char* workBuf = nil; - char* partBuf = nil; - char* outputBuf = nil; - char* start; - char* end; - char* outPtr; + DIError dierr = kDIErrNone; + char* workBuf = nil; + char* partBuf = nil; + char* outputBuf = nil; + char* start; + char* end; + char* outPtr; - assert(path != nil); - workBuf = new char[strlen(path)+1]; - partBuf = new char[strlen(path)+1 +1]; // need +1 for prepending letter - outputBuf = new char[strlen(path) * 2]; - if (workBuf == nil || partBuf == nil || outputBuf == nil) { - dierr = kDIErrMalloc; - goto bail; - } + assert(path != nil); + workBuf = new char[strlen(path)+1]; + partBuf = new char[strlen(path)+1 +1]; // need +1 for prepending letter + outputBuf = new char[strlen(path) * 2]; + if (workBuf == nil || partBuf == nil || outputBuf == nil) { + dierr = kDIErrMalloc; + goto bail; + } - strcpy(workBuf, path); - outputBuf[0] = '\0'; + strcpy(workBuf, path); + outputBuf[0] = '\0'; - outPtr = outputBuf; - start = workBuf; - while (*start != '\0') { - //char* origStart = start; // need for debug msg - int partIdx; + outPtr = outputBuf; + start = workBuf; + while (*start != '\0') { + //char* origStart = start; // need for debug msg + int partIdx; - if (fssep == '\0') { - end = nil; - } else { - end = strchr(start, fssep); - if (end != nil) - *end = '\0'; - } - partIdx = 0; + if (fssep == '\0') { + end = nil; + } else { + end = strchr(start, fssep); + if (end != nil) + *end = '\0'; + } + partIdx = 0; - /* - * Skip over everything up to the first letter. If we encounter a - * number or a '\0' first, insert a leading letter. - */ - while (*start != '\0') { - if (toupper(*start) >= 'A' && toupper(*start) <= 'Z') { - partBuf[partIdx++] = *start++; - break; - } - if (*start >= '0' && *start <= '9') { - partBuf[partIdx++] = 'A'; - break; - } + /* + * Skip over everything up to the first letter. If we encounter a + * number or a '\0' first, insert a leading letter. + */ + while (*start != '\0') { + if (toupper(*start) >= 'A' && toupper(*start) <= 'Z') { + partBuf[partIdx++] = *start++; + break; + } + if (*start >= '0' && *start <= '9') { + partBuf[partIdx++] = 'A'; + break; + } - start++; - } - if (partIdx == 0) - partBuf[partIdx++] = 'Z'; + start++; + } + if (partIdx == 0) + partBuf[partIdx++] = 'Z'; - /* - * Continue copying, dropping all illegal chars. - */ - while (*start != '\0') { - if ((toupper(*start) >= 'A' && toupper(*start) <= 'Z') || - (*start >= '0' && *start <= '9') || - (*start == '.') || - (*start == ' ') ) - { - partBuf[partIdx++] = *start++; - } else { - start++; - } - } + /* + * Continue copying, dropping all illegal chars. + */ + while (*start != '\0') { + if ((toupper(*start) >= 'A' && toupper(*start) <= 'Z') || + (*start >= '0' && *start <= '9') || + (*start == '.') || + (*start == ' ') ) + { + partBuf[partIdx++] = *start++; + } else { + start++; + } + } - /* - * Truncate at 15 chars, preserving anything that looks like a - * filename extension. "partIdx" represents the length of the - * string at this point. "partBuf" holds the string, which we - * want to null-terminate before proceeding. - */ - partBuf[partIdx] = '\0'; - if (partIdx > A2FileProDOS::kMaxFileName) { - const char* pDot = strrchr(partBuf, '.'); - //int DEBUGDOTLEN = pDot - partBuf; - if (pDot != nil && partIdx - (pDot-partBuf) <= kMaxExtensionLen) { - int dotLen = partIdx - (pDot-partBuf); - memmove(partBuf + (A2FileProDOS::kMaxFileName - dotLen), - pDot, dotLen); // don't use memcpy, move might overlap - } - partIdx = A2FileProDOS::kMaxFileName; - } - partBuf[partIdx] = '\0'; + /* + * Truncate at 15 chars, preserving anything that looks like a + * filename extension. "partIdx" represents the length of the + * string at this point. "partBuf" holds the string, which we + * want to null-terminate before proceeding. + */ + partBuf[partIdx] = '\0'; + if (partIdx > A2FileProDOS::kMaxFileName) { + const char* pDot = strrchr(partBuf, '.'); + //int DEBUGDOTLEN = pDot - partBuf; + if (pDot != nil && partIdx - (pDot-partBuf) <= kMaxExtensionLen) { + int dotLen = partIdx - (pDot-partBuf); + memmove(partBuf + (A2FileProDOS::kMaxFileName - dotLen), + pDot, dotLen); // don't use memcpy, move might overlap + } + partIdx = A2FileProDOS::kMaxFileName; + } + partBuf[partIdx] = '\0'; - //WMSG2(" ProDOS Converted component '%s' to '%s'\n", - // origStart, partBuf); + //WMSG2(" ProDOS Converted component '%s' to '%s'\n", + // origStart, partBuf); - if (outPtr != outputBuf) - *outPtr++ = A2FileProDOS::kFssep; - strcpy(outPtr, partBuf); - outPtr += partIdx; + if (outPtr != outputBuf) + *outPtr++ = A2FileProDOS::kFssep; + strcpy(outPtr, partBuf); + outPtr += partIdx; - /* - * Continue with next segment. - */ - if (end == nil) - break; - start = end+1; - } + /* + * Continue with next segment. + */ + if (end == nil) + break; + start = end+1; + } - *outPtr = '\0'; + *outPtr = '\0'; - WMSG3(" ProDOS Converted path '%s' to '%s' (fssep='%c')\n", - path, outputBuf, fssep); - assert(*outputBuf != '\0'); + WMSG3(" ProDOS Converted path '%s' to '%s' (fssep='%c')\n", + path, outputBuf, fssep); + assert(*outputBuf != '\0'); - *pNormalizedPath = outputBuf; - outputBuf = nil; + *pNormalizedPath = outputBuf; + outputBuf = nil; bail: - delete[] workBuf; - delete[] partBuf; - delete[] outputBuf; - return dierr; + delete[] workBuf; + delete[] partBuf; + delete[] outputBuf; + return dierr; } /* @@ -2782,19 +2782,19 @@ DiskFSProDOS::UpperCaseName(char* upperName, const char* name) { int i; - for (i = 0; i < A2FileProDOS::kMaxFileName; i++) { - char ch = name[i]; - if (ch == '\0') - break; - else if (ch == ' ') - upperName[i] = '.'; - else - upperName[i] = toupper(ch); - } + for (i = 0; i < A2FileProDOS::kMaxFileName; i++) { + char ch = name[i]; + if (ch == '\0') + break; + else if (ch == ' ') + upperName[i] = '.'; + else + upperName[i] = toupper(ch); + } - /* null terminate with prejudice -- we memcpy this buffer into subdirs */ - for ( ; i <= A2FileProDOS::kMaxFileName; i++) - upperName[i] = '\0'; + /* null terminate with prejudice -- we memcpy this buffer into subdirs */ + for ( ; i <= A2FileProDOS::kMaxFileName; i++) + upperName[i] = '\0'; } /* @@ -2811,12 +2811,12 @@ DiskFSProDOS::UpperCaseName(char* upperName, const char* name) * this needs to extend the directory, a new block will be allocated. * * Returns a pointer to the new entry, and a whole bunch of other stuff: - * "ppDir" gets a pointer to newly-allocated memory with the whole directory - * "pDirLen" is the size of the *ppDir buffer - * "ppDirEntry" gets a memory pointer to the start of the created entry - * "pDirKeyBlock" gets the key block of the directory as a whole - * "pDirEntrySlot" gets the slot number within the directory block (first is 1) - * "pDirBlock" gets the actual block in which the created entry resides + * "ppDir" gets a pointer to newly-allocated memory with the whole directory + * "pDirLen" is the size of the *ppDir buffer + * "ppDirEntry" gets a memory pointer to the start of the created entry + * "pDirKeyBlock" gets the key block of the directory as a whole + * "pDirEntrySlot" gets the slot number within the directory block (first is 1) + * "pDirBlock" gets the actual block in which the created entry resides * * The caller should Write the entire thing to "pOpenSubdir" after filling * in the new details for the entry. @@ -2829,172 +2829,172 @@ DiskFSProDOS::UpperCaseName(char* upperName, const char* name) */ DIError DiskFSProDOS::AllocDirEntry(A2FileDescr* pOpenSubdir, unsigned char** ppDir, - long* pDirLen, unsigned char** ppDirEntry, unsigned short* pDirKeyBlock, - int* pDirEntrySlot, unsigned short* pDirBlock) + long* pDirLen, unsigned char** ppDirEntry, unsigned short* pDirKeyBlock, + int* pDirEntrySlot, unsigned short* pDirBlock) { - assert(pOpenSubdir != nil); - *ppDirEntry = nil; - *pDirLen = -1; - *pDirKeyBlock = 0; - *pDirEntrySlot = -1; - *pDirBlock = 0; + assert(pOpenSubdir != nil); + *ppDirEntry = nil; + *pDirLen = -1; + *pDirKeyBlock = 0; + *pDirEntrySlot = -1; + *pDirBlock = 0; - DIError dierr = kDIErrNone; - unsigned char* dirBuf = nil; - long dirLen; - A2FileProDOS* pFile; - long newBlock = -1; + DIError dierr = kDIErrNone; + unsigned char* dirBuf = nil; + long dirLen; + A2FileProDOS* pFile; + long newBlock = -1; - /* - * Load the subdir into memory. - */ - pFile = (A2FileProDOS*) pOpenSubdir->GetFile(); - dirLen = (long) pFile->GetDataLength(); - if (dirLen < 512 || (dirLen % 512) != 0) { - WMSG2(" ProDOS GLITCH: funky dir EOF %ld (quality=%d)\n", - dirLen, pFile->GetQuality()); - dierr = kDIErrBadFile; - goto bail; - } - dirBuf = new unsigned char[dirLen]; - if (dirBuf == nil) { - dierr = kDIErrMalloc; - goto bail; - } + /* + * Load the subdir into memory. + */ + pFile = (A2FileProDOS*) pOpenSubdir->GetFile(); + dirLen = (long) pFile->GetDataLength(); + if (dirLen < 512 || (dirLen % 512) != 0) { + WMSG2(" ProDOS GLITCH: funky dir EOF %ld (quality=%d)\n", + dirLen, pFile->GetQuality()); + dierr = kDIErrBadFile; + goto bail; + } + dirBuf = new unsigned char[dirLen]; + if (dirBuf == nil) { + dierr = kDIErrMalloc; + goto bail; + } - dierr = pOpenSubdir->Read(dirBuf, dirLen); - if (dierr != kDIErrNone) - goto bail; + dierr = pOpenSubdir->Read(dirBuf, dirLen); + if (dierr != kDIErrNone) + goto bail; - if (dirBuf[0x23] != kEntryLength || - dirBuf[0x24] != kEntriesPerBlock) - { - WMSG1(" ProDOS GLITCH: funky entries per block %d\n", dirBuf[0x24]); - dierr = kDIErrBadDirectory; - goto bail; - } + if (dirBuf[0x23] != kEntryLength || + dirBuf[0x24] != kEntriesPerBlock) + { + WMSG1(" ProDOS GLITCH: funky entries per block %d\n", dirBuf[0x24]); + dierr = kDIErrBadDirectory; + goto bail; + } - /* - * Find the first available entry (storage_type is zero). We need to - * step through this by blocks, because the data is block-oriented. - * If we run off the end of the last block, (re)alloc a new one. - */ - unsigned char* pDirEntry; - int blockIdx; - int entryIdx; + /* + * Find the first available entry (storage_type is zero). We need to + * step through this by blocks, because the data is block-oriented. + * If we run off the end of the last block, (re)alloc a new one. + */ + unsigned char* pDirEntry; + int blockIdx; + int entryIdx; pDirEntry = nil; // make the compiler happy entryIdx = -1; // make the compiler happy - for (blockIdx = 0; blockIdx < dirLen / 512; blockIdx++) { - pDirEntry = dirBuf + 512*blockIdx + 4; // skip 4 bytes of prev/next + for (blockIdx = 0; blockIdx < dirLen / 512; blockIdx++) { + pDirEntry = dirBuf + 512*blockIdx + 4; // skip 4 bytes of prev/next - for (entryIdx = 0; entryIdx < kEntriesPerBlock; - entryIdx++, pDirEntry += kEntryLength) - { - if ((pDirEntry[0x00] & 0xf0) == 0) { - WMSG1(" ProDOS Found empty dir entry in slot %d\n", entryIdx); - break; // found one; break out of inner loop - } - } - if (entryIdx < kEntriesPerBlock) - break; // out of outer loop - } - if (blockIdx == dirLen / 512) { - if (((dirBuf[0x04] & 0xf0) >> 4) == A2FileProDOS::kStorageVolumeDirHeader) - { - /* can't extend the volume dir */ - dierr = kDIErrVolumeDirFull; - goto bail; - } + for (entryIdx = 0; entryIdx < kEntriesPerBlock; + entryIdx++, pDirEntry += kEntryLength) + { + if ((pDirEntry[0x00] & 0xf0) == 0) { + WMSG1(" ProDOS Found empty dir entry in slot %d\n", entryIdx); + break; // found one; break out of inner loop + } + } + if (entryIdx < kEntriesPerBlock) + break; // out of outer loop + } + if (blockIdx == dirLen / 512) { + if (((dirBuf[0x04] & 0xf0) >> 4) == A2FileProDOS::kStorageVolumeDirHeader) + { + /* can't extend the volume dir */ + dierr = kDIErrVolumeDirFull; + goto bail; + } - WMSG0(" ProDOS ran out of directory space, adding another block\n"); + WMSG0(" ProDOS ran out of directory space, adding another block\n"); - /* - * Request an unused block from the system. Point the "next" pointer - * in the last block at it, so that when we go to write this dir - * we will know where to put it. - */ - unsigned char* pBlock; - pBlock = dirBuf + 512 * (blockIdx-1); - if (pBlock[0x02] != 0) { - WMSG0(" ProDOS GLITCH: adding to block with nonzero next ptr!\n"); - dierr = kDIErrBadDirectory; - goto bail; - } + /* + * Request an unused block from the system. Point the "next" pointer + * in the last block at it, so that when we go to write this dir + * we will know where to put it. + */ + unsigned char* pBlock; + pBlock = dirBuf + 512 * (blockIdx-1); + if (pBlock[0x02] != 0) { + WMSG0(" ProDOS GLITCH: adding to block with nonzero next ptr!\n"); + dierr = kDIErrBadDirectory; + goto bail; + } - newBlock = AllocBlock(); - if (newBlock < 0) { - dierr = kDIErrDiskFull; - goto bail; - } + newBlock = AllocBlock(); + if (newBlock < 0) { + dierr = kDIErrDiskFull; + goto bail; + } - PutShortLE(&pBlock[0x02], (unsigned short) newBlock); // set "next" + PutShortLE(&pBlock[0x02], (unsigned short) newBlock); // set "next" - /* - * Extend our memory buffer to hold the new entry. - */ - unsigned char* newSpace = new unsigned char[dirLen + 512]; - if (newSpace == nil) { - dierr = kDIErrMalloc; - goto bail; - } - memcpy(newSpace, dirBuf, dirLen); - memset(newSpace + dirLen, 0, 512); - delete[] dirBuf; - dirBuf = newSpace; - dirLen += 512; + /* + * Extend our memory buffer to hold the new entry. + */ + unsigned char* newSpace = new unsigned char[dirLen + 512]; + if (newSpace == nil) { + dierr = kDIErrMalloc; + goto bail; + } + memcpy(newSpace, dirBuf, dirLen); + memset(newSpace + dirLen, 0, 512); + delete[] dirBuf; + dirBuf = newSpace; + dirLen += 512; - /* - * Set the "prev" pointer in the new block to point at the last - * block of the existing directory structure. - */ - long lastBlock; - dierr = pOpenSubdir->GetStorage(blockIdx-1, &lastBlock); - if (dierr != kDIErrNone) - goto bail; - pBlock = dirBuf + 512 * blockIdx; - PutShortLE(&pBlock[0x00], (unsigned short) lastBlock); // set "prev" - assert(GetShortLE(&pBlock[0x02]) == 0); // "next" pointer + /* + * Set the "prev" pointer in the new block to point at the last + * block of the existing directory structure. + */ + long lastBlock; + dierr = pOpenSubdir->GetStorage(blockIdx-1, &lastBlock); + if (dierr != kDIErrNone) + goto bail; + pBlock = dirBuf + 512 * blockIdx; + PutShortLE(&pBlock[0x00], (unsigned short) lastBlock); // set "prev" + assert(GetShortLE(&pBlock[0x02]) == 0); // "next" pointer - /* - * Finally, point pDirEntry at the first entry in the new area. - */ - pDirEntry = pBlock + 4; - entryIdx = 0; - assert(pDirEntry[0x00] == 0x00); - } + /* + * Finally, point pDirEntry at the first entry in the new area. + */ + pDirEntry = pBlock + 4; + entryIdx = 0; + assert(pDirEntry[0x00] == 0x00); + } - /* - * Success. Update the file count in the header. - */ - unsigned short count; - count = GetShortLE(&dirBuf[0x25]); - count++; - PutShortLE(&dirBuf[0x25], count); + /* + * Success. Update the file count in the header. + */ + unsigned short count; + count = GetShortLE(&dirBuf[0x25]); + count++; + PutShortLE(&dirBuf[0x25], count); - long whichBlock; + long whichBlock; - *ppDir = dirBuf; - *pDirLen = dirLen; - *ppDirEntry = pDirEntry; - *pDirKeyBlock = pFile->fDirEntry.keyPointer; - *pDirEntrySlot = entryIdx +1; - if (blockIdx == ((A2FDProDOS*)pOpenSubdir)->GetBlockCount()) { - /* not yet added to block list, so can't use GetStorage */ - assert(newBlock > 0); - *pDirBlock = (unsigned short) newBlock; - } else { - assert(newBlock < 0); - dierr = pOpenSubdir->GetStorage(blockIdx, &whichBlock); - assert(dierr == kDIErrNone); - *pDirBlock = (unsigned short) whichBlock; - } - dirBuf = nil; + *ppDir = dirBuf; + *pDirLen = dirLen; + *ppDirEntry = pDirEntry; + *pDirKeyBlock = pFile->fDirEntry.keyPointer; + *pDirEntrySlot = entryIdx +1; + if (blockIdx == ((A2FDProDOS*)pOpenSubdir)->GetBlockCount()) { + /* not yet added to block list, so can't use GetStorage */ + assert(newBlock > 0); + *pDirBlock = (unsigned short) newBlock; + } else { + assert(newBlock < 0); + dierr = pOpenSubdir->GetStorage(blockIdx, &whichBlock); + assert(dierr == kDIErrNone); + *pDirBlock = (unsigned short) whichBlock; + } + dirBuf = nil; bail: - delete[] dirBuf; - return dierr; + delete[] dirBuf; + return dierr; } /* @@ -3014,26 +3014,26 @@ bail: unsigned char* DiskFSProDOS::GetPrevDirEntry(unsigned char* buf, unsigned char* ptr) { - assert(buf != nil); - assert(ptr != nil); + assert(buf != nil); + assert(ptr != nil); - const int kStartOffset = 4; + const int kStartOffset = 4; - if (ptr == buf + kStartOffset || ptr == buf + kStartOffset + kEntryLength) - return nil; + if (ptr == buf + kStartOffset || ptr == buf + kStartOffset + kEntryLength) + return nil; - while (ptr - buf > 512) - buf += 512; + while (ptr - buf > 512) + buf += 512; - assert((ptr - buf - kStartOffset) % kEntryLength == 0); + assert((ptr - buf - kStartOffset) % kEntryLength == 0); - if (ptr == buf + kStartOffset) { - /* whoops, went too far */ - buf -= 512; - return buf + kStartOffset + kEntryLength * (kEntriesPerBlock-1); - } else { - return ptr - kEntryLength; - } + if (ptr == buf + kStartOffset) { + /* whoops, went too far */ + buf -= 512; + return buf + kStartOffset + kEntryLength * (kEntriesPerBlock-1); + } else { + return ptr - kEntryLength; + } } /* @@ -3047,72 +3047,72 @@ DiskFSProDOS::GetPrevDirEntry(unsigned char* buf, unsigned char* ptr) */ DIError DiskFSProDOS::MakeFileNameUnique(const unsigned char* dirBuf, long dirLen, - char* fileName) + char* fileName) { - assert(dirBuf != nil); - assert(dirLen > 0); - assert((dirLen % 512) == 0); - assert(fileName != nil); - assert(strlen(fileName) <= A2FileProDOS::kMaxFileName); + assert(dirBuf != nil); + assert(dirLen > 0); + assert((dirLen % 512) == 0); + assert(fileName != nil); + assert(strlen(fileName) <= A2FileProDOS::kMaxFileName); - if (!NameExistsInDir(dirBuf, dirLen, fileName)) - return kDIErrNone; + if (!NameExistsInDir(dirBuf, dirLen, fileName)) + return kDIErrNone; - WMSG1(" ProDOS found duplicate of '%s', making unique\n", fileName); + WMSG1(" ProDOS found duplicate of '%s', making unique\n", fileName); - int nameLen = strlen(fileName); - int dotOffset=0, dotLen=0; - char dotBuf[kMaxExtensionLen+1]; + int nameLen = strlen(fileName); + int dotOffset=0, dotLen=0; + char dotBuf[kMaxExtensionLen+1]; - /* ensure the result will be null-terminated */ - memset(fileName + nameLen, 0, (A2FileProDOS::kMaxFileName - nameLen) +1); + /* ensure the result will be null-terminated */ + memset(fileName + nameLen, 0, (A2FileProDOS::kMaxFileName - nameLen) +1); - /* - * If this has what looks like a filename extension, grab it. We want - * to preserve ".gif", ".c", etc., since the filetypes don't necessarily - * do everything we need. - * - * This will tend to screw up the upper/lower case stuff, especially - * since what we think is a '.' might actually be a ' '. We could work - * around this, but it's probably not necessary. - */ - const char* cp = strrchr(fileName, '.'); - if (cp != nil) { - int tmpOffset = cp - fileName; - if (tmpOffset > 0 && nameLen - tmpOffset <= kMaxExtensionLen) { - WMSG1(" ProDOS (keeping extension '%s')\n", cp); - assert(strlen(cp) <= kMaxExtensionLen); - strcpy(dotBuf, cp); - dotOffset = tmpOffset; - dotLen = nameLen - dotOffset; - } - } + /* + * If this has what looks like a filename extension, grab it. We want + * to preserve ".gif", ".c", etc., since the filetypes don't necessarily + * do everything we need. + * + * This will tend to screw up the upper/lower case stuff, especially + * since what we think is a '.' might actually be a ' '. We could work + * around this, but it's probably not necessary. + */ + const char* cp = strrchr(fileName, '.'); + if (cp != nil) { + int tmpOffset = cp - fileName; + if (tmpOffset > 0 && nameLen - tmpOffset <= kMaxExtensionLen) { + WMSG1(" ProDOS (keeping extension '%s')\n", cp); + assert(strlen(cp) <= kMaxExtensionLen); + strcpy(dotBuf, cp); + dotOffset = tmpOffset; + dotLen = nameLen - dotOffset; + } + } - const int kMaxDigits = 999; - int digits = 0; - int digitLen; - int copyOffset; - char digitBuf[4]; - do { - if (digits == kMaxDigits) - return kDIErrFileExists; - digits++; + const int kMaxDigits = 999; + int digits = 0; + int digitLen; + int copyOffset; + char digitBuf[4]; + do { + if (digits == kMaxDigits) + return kDIErrFileExists; + digits++; - /* not the most efficient way to do this, but it'll do */ - sprintf(digitBuf, "%d", digits); - digitLen = strlen(digitBuf); - if (nameLen + digitLen > A2FileProDOS::kMaxFileName) - copyOffset = A2FileProDOS::kMaxFileName - dotLen - digitLen; - else - copyOffset = nameLen - dotLen; - memcpy(fileName + copyOffset, digitBuf, digitLen); - if (dotLen != 0) - memcpy(fileName + copyOffset + digitLen, dotBuf, dotLen); - } while (NameExistsInDir(dirBuf, dirLen, fileName)); + /* not the most efficient way to do this, but it'll do */ + sprintf(digitBuf, "%d", digits); + digitLen = strlen(digitBuf); + if (nameLen + digitLen > A2FileProDOS::kMaxFileName) + copyOffset = A2FileProDOS::kMaxFileName - dotLen - digitLen; + else + copyOffset = nameLen - dotLen; + memcpy(fileName + copyOffset, digitBuf, digitLen); + if (dotLen != 0) + memcpy(fileName + copyOffset + digitLen, dotBuf, dotLen); + } while (NameExistsInDir(dirBuf, dirLen, fileName)); - WMSG1(" ProDOS converted to unique name: %s\n", fileName); + WMSG1(" ProDOS converted to unique name: %s\n", fileName); - return kDIErrNone; + return kDIErrNone; } /* @@ -3123,35 +3123,35 @@ DiskFSProDOS::MakeFileNameUnique(const unsigned char* dirBuf, long dirLen, */ bool DiskFSProDOS::NameExistsInDir(const unsigned char* dirBuf, long dirLen, - const char* fileName) + const char* fileName) { - const unsigned char* pDirEntry; - int blockIdx; - int entryIdx; - int nameLen = strlen(fileName); + const unsigned char* pDirEntry; + int blockIdx; + int entryIdx; + int nameLen = strlen(fileName); - assert(nameLen <= A2FileProDOS::kMaxFileName); + assert(nameLen <= A2FileProDOS::kMaxFileName); - for (blockIdx = 0; blockIdx < dirLen / 512; blockIdx++) { - pDirEntry = dirBuf + 512*blockIdx + 4; // skip 4 bytes of prev/next + for (blockIdx = 0; blockIdx < dirLen / 512; blockIdx++) { + pDirEntry = dirBuf + 512*blockIdx + 4; // skip 4 bytes of prev/next - for (entryIdx = 0; entryIdx < kEntriesPerBlock; - entryIdx++, pDirEntry += kEntryLength) - { - /* skip directory header */ - if (blockIdx == 0 && entryIdx == 0) - continue; + for (entryIdx = 0; entryIdx < kEntriesPerBlock; + entryIdx++, pDirEntry += kEntryLength) + { + /* skip directory header */ + if (blockIdx == 0 && entryIdx == 0) + continue; - if ((pDirEntry[0x00] & 0xf0) != 0 && - (pDirEntry[0x00] & 0x0f) == nameLen && - strncmp((char*) &pDirEntry[0x01], fileName, nameLen) == 0) - { - return true; - } - } - } + if ((pDirEntry[0x00] & 0xf0) != 0 && + (pDirEntry[0x00] & 0x0f) == nameLen && + strncmp((char*) &pDirEntry[0x01], fileName, nameLen) == 0) + { + return true; + } + } + } - return false; + return false; } @@ -3168,206 +3168,206 @@ DiskFSProDOS::NameExistsInDir(const unsigned char* dirBuf, long dirLen, DIError DiskFSProDOS::DeleteFile(A2File* pGenericFile) { - DIError dierr = kDIErrNone; - long blockCount = -1; - long indexCount = -1; - unsigned short* blockList = nil; - unsigned short* indexList = nil; + DIError dierr = kDIErrNone; + long blockCount = -1; + long indexCount = -1; + unsigned short* blockList = nil; + unsigned short* indexList = nil; - if (pGenericFile == nil) { - assert(false); - return kDIErrInvalidArg; - } + if (pGenericFile == nil) { + assert(false); + return kDIErrInvalidArg; + } - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (!fDiskIsGood) - return kDIErrBadDiskImage; - if (pGenericFile->IsFileOpen()) - return kDIErrFileOpen; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (!fDiskIsGood) + return kDIErrBadDiskImage; + if (pGenericFile->IsFileOpen()) + return kDIErrFileOpen; - /* - * If they try to delete all entries, we don't want to spit back a - * failure message over our "fake" volume dir entry. So we just silently - * ignore the request. - */ - if (pGenericFile->IsVolumeDirectory()) { - WMSG0("ProDOS not deleting volume directory\n"); - return kDIErrNone; - } + /* + * If they try to delete all entries, we don't want to spit back a + * failure message over our "fake" volume dir entry. So we just silently + * ignore the request. + */ + if (pGenericFile->IsVolumeDirectory()) { + WMSG0("ProDOS not deleting volume directory\n"); + return kDIErrNone; + } - A2FileProDOS* pFile = (A2FileProDOS*) pGenericFile; + A2FileProDOS* pFile = (A2FileProDOS*) pGenericFile; - WMSG1(" Deleting '%s'\n", pFile->GetPathName()); + WMSG1(" Deleting '%s'\n", pFile->GetPathName()); - dierr = LoadVolBitmap(); - if (dierr != kDIErrNone) - goto bail; - switch (pFile->fDirEntry.storageType) { - case A2FileProDOS::kStorageExtended: - // handle rsrc fork here, fall out for data fork - dierr = pFile->LoadBlockList( - pFile->fExtRsrc.storageType, - pFile->fExtRsrc.keyBlock, - pFile->fExtRsrc.eof, - &blockCount, &blockList, - &indexCount, &indexList); - if (dierr != kDIErrNone) - goto bail; - FreeBlocks(blockCount, blockList); - if (indexList != nil) // no indices for seedling - FreeBlocks(indexCount, indexList); - delete[] blockList; - delete[] indexList; - indexList = nil; + dierr = LoadVolBitmap(); + if (dierr != kDIErrNone) + goto bail; + switch (pFile->fDirEntry.storageType) { + case A2FileProDOS::kStorageExtended: + // handle rsrc fork here, fall out for data fork + dierr = pFile->LoadBlockList( + pFile->fExtRsrc.storageType, + pFile->fExtRsrc.keyBlock, + pFile->fExtRsrc.eof, + &blockCount, &blockList, + &indexCount, &indexList); + if (dierr != kDIErrNone) + goto bail; + FreeBlocks(blockCount, blockList); + if (indexList != nil) // no indices for seedling + FreeBlocks(indexCount, indexList); + delete[] blockList; + delete[] indexList; + indexList = nil; - // handle the key block "manually" - blockCount = 1; - blockList = new unsigned short[blockCount]; - blockList[0] = pFile->fDirEntry.keyPointer; - FreeBlocks(blockCount, blockList); - delete[] blockList; - blockList = nil; + // handle the key block "manually" + blockCount = 1; + blockList = new unsigned short[blockCount]; + blockList[0] = pFile->fDirEntry.keyPointer; + FreeBlocks(blockCount, blockList); + delete[] blockList; + blockList = nil; - dierr = pFile->LoadBlockList( - pFile->fExtData.storageType, - pFile->fExtData.keyBlock, - pFile->fExtData.eof, - &blockCount, &blockList, - &indexCount, &indexList); - break; // fall out + dierr = pFile->LoadBlockList( + pFile->fExtData.storageType, + pFile->fExtData.keyBlock, + pFile->fExtData.eof, + &blockCount, &blockList, + &indexCount, &indexList); + break; // fall out - case A2FileProDOS::kStorageDirectory: - dierr = pFile->LoadDirectoryBlockList( - pFile->fDirEntry.keyPointer, - pFile->fDirEntry.eof, - &blockCount, &blockList); - break; // fall out + case A2FileProDOS::kStorageDirectory: + dierr = pFile->LoadDirectoryBlockList( + pFile->fDirEntry.keyPointer, + pFile->fDirEntry.eof, + &blockCount, &blockList); + break; // fall out - case A2FileProDOS::kStorageSeedling: - case A2FileProDOS::kStorageSapling: - case A2FileProDOS::kStorageTree: - dierr = pFile->LoadBlockList( - pFile->fDirEntry.storageType, - pFile->fDirEntry.keyPointer, - pFile->fDirEntry.eof, - &blockCount, &blockList, - &indexCount, &indexList); - break; // fall out + case A2FileProDOS::kStorageSeedling: + case A2FileProDOS::kStorageSapling: + case A2FileProDOS::kStorageTree: + dierr = pFile->LoadBlockList( + pFile->fDirEntry.storageType, + pFile->fDirEntry.keyPointer, + pFile->fDirEntry.eof, + &blockCount, &blockList, + &indexCount, &indexList); + break; // fall out - default: - WMSG1("ProDOS can't delete unknown storage type %d\n", - pFile->fDirEntry.storageType); - dierr = kDIErrBadDirectory; - break; // fall out - } + default: + WMSG1("ProDOS can't delete unknown storage type %d\n", + pFile->fDirEntry.storageType); + dierr = kDIErrBadDirectory; + break; // fall out + } - if (dierr != kDIErrNone) - goto bail; + if (dierr != kDIErrNone) + goto bail; - FreeBlocks(blockCount, blockList); - if (indexList != nil) - FreeBlocks(indexCount, indexList); + FreeBlocks(blockCount, blockList); + if (indexList != nil) + FreeBlocks(indexCount, indexList); - /* - * Update the directory entry. After this point, failure gets ugly. - * - * It might be "proper" to open the subdir file, find the correct entry, - * and write it back, but the A2FileProDOS structure has the directory - * block and entry index stored in it. Makes it a little easier. - */ - unsigned char blkBuf[kBlkSize]; - unsigned char* ptr; - assert(pFile->fParentDirBlock > 0); - assert(pFile->fParentDirIdx >= 0 && - pFile->fParentDirIdx < kEntriesPerBlock); - dierr = fpImg->ReadBlock(pFile->fParentDirBlock, blkBuf); - if (dierr != kDIErrNone) { - WMSG1("ProDOS unable to read directory block %u\n", - pFile->fParentDirBlock); - goto bail; - } + /* + * Update the directory entry. After this point, failure gets ugly. + * + * It might be "proper" to open the subdir file, find the correct entry, + * and write it back, but the A2FileProDOS structure has the directory + * block and entry index stored in it. Makes it a little easier. + */ + unsigned char blkBuf[kBlkSize]; + unsigned char* ptr; + assert(pFile->fParentDirBlock > 0); + assert(pFile->fParentDirIdx >= 0 && + pFile->fParentDirIdx < kEntriesPerBlock); + dierr = fpImg->ReadBlock(pFile->fParentDirBlock, blkBuf); + if (dierr != kDIErrNone) { + WMSG1("ProDOS unable to read directory block %u\n", + pFile->fParentDirBlock); + goto bail; + } - ptr = blkBuf + 4 + pFile->fParentDirIdx * kEntryLength; - if ((*ptr) >> 4 != pFile->fDirEntry.storageType) { - WMSG2("ProDOS GLITCH: mismatched storage types (%d vs %d)\n", - (*ptr) >> 4, pFile->fDirEntry.storageType); - assert(false); - dierr = kDIErrBadDirectory; - goto bail; - } - ptr[0x00] = 0; // zap both storage type and name length - dierr = fpImg->WriteBlock(pFile->fParentDirBlock, blkBuf); - if (dierr != kDIErrNone) { - WMSG1("ProDOS unable to write directory block %u\n", - pFile->fParentDirBlock); - goto bail; - } + ptr = blkBuf + 4 + pFile->fParentDirIdx * kEntryLength; + if ((*ptr) >> 4 != pFile->fDirEntry.storageType) { + WMSG2("ProDOS GLITCH: mismatched storage types (%d vs %d)\n", + (*ptr) >> 4, pFile->fDirEntry.storageType); + assert(false); + dierr = kDIErrBadDirectory; + goto bail; + } + ptr[0x00] = 0; // zap both storage type and name length + dierr = fpImg->WriteBlock(pFile->fParentDirBlock, blkBuf); + if (dierr != kDIErrNone) { + WMSG1("ProDOS unable to write directory block %u\n", + pFile->fParentDirBlock); + goto bail; + } - /* - * Save our updated copy of the volume bitmap to disk. - */ - dierr = SaveVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + /* + * Save our updated copy of the volume bitmap to disk. + */ + dierr = SaveVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - /* - * One last little thing: decrement the file count in the directory - * header. We can find the appropriate place pretty easily because - * we know it's the first block in pFile->fpParent, which for a dir is - * always the block pointed to by the key pointer. - * - * Strictly speaking, failure to update this correctly isn't fatal. I - * doubt most utilities pay any attention to this. Still, it's important - * to keep the filesystem in a consistent state, so we at least must - * report the error. They'll need to run the ProSel volume repair util - * to fix it. - */ - A2FileProDOS* pParent; - unsigned short fileCount; - int storageType; - pParent = (A2FileProDOS*) pFile->GetParent(); - assert(pParent != nil); - assert(pParent->fDirEntry.keyPointer >= kVolHeaderBlock); - dierr = fpImg->ReadBlock(pParent->fDirEntry.keyPointer, blkBuf); - if (dierr != kDIErrNone) { - WMSG1("ProDOS unable to read parent dir block %u\n", - pParent->fDirEntry.keyPointer); - goto bail; - } - ptr = nil; + /* + * One last little thing: decrement the file count in the directory + * header. We can find the appropriate place pretty easily because + * we know it's the first block in pFile->fpParent, which for a dir is + * always the block pointed to by the key pointer. + * + * Strictly speaking, failure to update this correctly isn't fatal. I + * doubt most utilities pay any attention to this. Still, it's important + * to keep the filesystem in a consistent state, so we at least must + * report the error. They'll need to run the ProSel volume repair util + * to fix it. + */ + A2FileProDOS* pParent; + unsigned short fileCount; + int storageType; + pParent = (A2FileProDOS*) pFile->GetParent(); + assert(pParent != nil); + assert(pParent->fDirEntry.keyPointer >= kVolHeaderBlock); + dierr = fpImg->ReadBlock(pParent->fDirEntry.keyPointer, blkBuf); + if (dierr != kDIErrNone) { + WMSG1("ProDOS unable to read parent dir block %u\n", + pParent->fDirEntry.keyPointer); + goto bail; + } + ptr = nil; - storageType = (blkBuf[0x04] & 0xf0) >> 4; - if (storageType != A2FileProDOS::kStorageSubdirHeader && - storageType != A2FileProDOS::kStorageVolumeDirHeader) - { - WMSG1("ProDOS invalid storage type %d in dir header block\n", - storageType); - DebugBreak(); - dierr = kDIErrBadDirectory; - goto bail; - } - fileCount = GetShortLE(&blkBuf[0x25]); - if (fileCount > 0) - fileCount--; - PutShortLE(&blkBuf[0x25], fileCount); - dierr = fpImg->WriteBlock(pParent->fDirEntry.keyPointer, blkBuf); - if (dierr != kDIErrNone) { - WMSG1("ProDOS unable to write parent dir block %u\n", - pParent->fDirEntry.keyPointer); - goto bail; - } + storageType = (blkBuf[0x04] & 0xf0) >> 4; + if (storageType != A2FileProDOS::kStorageSubdirHeader && + storageType != A2FileProDOS::kStorageVolumeDirHeader) + { + WMSG1("ProDOS invalid storage type %d in dir header block\n", + storageType); + DebugBreak(); + dierr = kDIErrBadDirectory; + goto bail; + } + fileCount = GetShortLE(&blkBuf[0x25]); + if (fileCount > 0) + fileCount--; + PutShortLE(&blkBuf[0x25], fileCount); + dierr = fpImg->WriteBlock(pParent->fDirEntry.keyPointer, blkBuf); + if (dierr != kDIErrNone) { + WMSG1("ProDOS unable to write parent dir block %u\n", + pParent->fDirEntry.keyPointer); + goto bail; + } - /* - * Remove the A2File* from the list. - */ - DeleteFileFromList(pFile); + /* + * Remove the A2File* from the list. + */ + DeleteFileFromList(pFile); bail: - FreeVolBitmap(); - delete[] blockList; - delete[] indexList; - return kDIErrNone; + FreeVolBitmap(); + delete[] blockList; + delete[] indexList; + return kDIErrNone; } /* @@ -3378,32 +3378,32 @@ bail: DIError DiskFSProDOS::FreeBlocks(long blockCount, unsigned short* blockList) { - VolumeUsage::ChunkState cstate; - int i; + VolumeUsage::ChunkState cstate; + int i; - //WMSG2(" +++ FreeBlocks (blockCount=%d blockList=0x%08lx)\n", - // blockCount, blockList); - assert(blockCount >= 0 && blockCount < 65536); - assert(blockList != nil); + //WMSG2(" +++ FreeBlocks (blockCount=%d blockList=0x%08lx)\n", + // blockCount, blockList); + assert(blockCount >= 0 && blockCount < 65536); + assert(blockList != nil); - cstate.isUsed = false; - cstate.isMarkedUsed = false; - cstate.purpose = VolumeUsage::kChunkPurposeUnknown; + cstate.isUsed = false; + cstate.isMarkedUsed = false; + cstate.purpose = VolumeUsage::kChunkPurposeUnknown; - for (i = 0; i < blockCount; i++) { - if (blockList[i] == 0) // expected for "sparse" files - continue; + for (i = 0; i < blockCount; i++) { + if (blockList[i] == 0) // expected for "sparse" files + continue; - if (!GetBlockUseEntry(blockList[i])) { - WMSG1("WARNING: freeing unallocated block %u\n", blockList[i]); - assert(false); // impossible unless disk is "damaged" - } - SetBlockUseEntry(blockList[i], false); + if (!GetBlockUseEntry(blockList[i])) { + WMSG1("WARNING: freeing unallocated block %u\n", blockList[i]); + assert(false); // impossible unless disk is "damaged" + } + SetBlockUseEntry(blockList[i], false); - fVolumeUsage.SetChunkState(blockList[i], &cstate); - } + fVolumeUsage.SetChunkState(blockList[i], &cstate); + } - return kDIErrNone; + return kDIErrNone; } @@ -3417,185 +3417,185 @@ DiskFSProDOS::FreeBlocks(long blockCount, unsigned short* blockList) * Renaming the magic volume directory "file" is not allowed. * * Things to note: - * - Renaming subdirs is annoying. The name has to be changed in two - * places, and the "pathname" value cached in A2FileProDOS must be - * updated for all children of the subdir. - * - Must check for duplicates. - * - If it's an AppleWorks file type, we need to change the aux type - * according to the upper/lower case flags. This holds even if the - * "allow lower case" flag is disabled. + * - Renaming subdirs is annoying. The name has to be changed in two + * places, and the "pathname" value cached in A2FileProDOS must be + * updated for all children of the subdir. + * - Must check for duplicates. + * - If it's an AppleWorks file type, we need to change the aux type + * according to the upper/lower case flags. This holds even if the + * "allow lower case" flag is disabled. */ DIError DiskFSProDOS::RenameFile(A2File* pGenericFile, const char* newName) { - DIError dierr = kDIErrNone; - A2FileProDOS* pFile = (A2FileProDOS*) pGenericFile; - char upperName[A2FileProDOS::kMaxFileName+1]; - char upperComp[A2FileProDOS::kMaxFileName+1]; + DIError dierr = kDIErrNone; + A2FileProDOS* pFile = (A2FileProDOS*) pGenericFile; + char upperName[A2FileProDOS::kMaxFileName+1]; + char upperComp[A2FileProDOS::kMaxFileName+1]; - if (pFile == nil || newName == nil) - return kDIErrInvalidArg; - if (!IsValidFileName(newName)) - return kDIErrInvalidArg; - if (pFile->IsVolumeDirectory()) - return kDIErrInvalidArg; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (!fDiskIsGood) - return kDIErrBadDiskImage; + if (pFile == nil || newName == nil) + return kDIErrInvalidArg; + if (!IsValidFileName(newName)) + return kDIErrInvalidArg; + if (pFile->IsVolumeDirectory()) + return kDIErrInvalidArg; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (!fDiskIsGood) + return kDIErrBadDiskImage; - WMSG2(" ProDOS renaming '%s' to '%s'\n", pFile->GetPathName(), newName); + WMSG2(" ProDOS renaming '%s' to '%s'\n", pFile->GetPathName(), newName); - /* - * Check for duplicates. We do this by getting the parent subdir and - * running through it looking for an upper-case-converted match. - * - * We start in the list at our parent node, knowing that the kids are - * grouped together after it. However, we can't stop right away, - * because some of the kids might be subdirectories themselves. So we - * will probably run through a significant chunk of the list. - */ - A2File* pParent = pFile->GetParent(); - A2File* pCur; + /* + * Check for duplicates. We do this by getting the parent subdir and + * running through it looking for an upper-case-converted match. + * + * We start in the list at our parent node, knowing that the kids are + * grouped together after it. However, we can't stop right away, + * because some of the kids might be subdirectories themselves. So we + * will probably run through a significant chunk of the list. + */ + A2File* pParent = pFile->GetParent(); + A2File* pCur; - UpperCaseName(upperName, newName); - pCur = GetNextFile(pParent); - assert(pCur != nil); // at the very least, pFile is in this dir - while (pCur != nil) { - if (pCur != pFile && pCur->GetParent() == pParent) { - /* one of our siblings; see if the name matches */ - UpperCaseName(upperComp, pCur->GetFileName()); - if (strcmp(upperName, upperComp) == 0) { - WMSG0(" ProDOS rename dup found\n"); - return kDIErrFileExists; - } - } + UpperCaseName(upperName, newName); + pCur = GetNextFile(pParent); + assert(pCur != nil); // at the very least, pFile is in this dir + while (pCur != nil) { + if (pCur != pFile && pCur->GetParent() == pParent) { + /* one of our siblings; see if the name matches */ + UpperCaseName(upperComp, pCur->GetFileName()); + if (strcmp(upperName, upperComp) == 0) { + WMSG0(" ProDOS rename dup found\n"); + return kDIErrFileExists; + } + } - pCur = GetNextFile(pCur); - } + pCur = GetNextFile(pCur); + } - /* - * Grab the directory block and update the filename in the entry. If this - * was a subdir we also need to update its directory header entry. To - * minimize the chances of a partial update, we load both blocks up - * front, modify both, then write them both back. - */ - unsigned char parentDirBuf[kBlkSize]; - unsigned char thisDirBuf[kBlkSize]; + /* + * Grab the directory block and update the filename in the entry. If this + * was a subdir we also need to update its directory header entry. To + * minimize the chances of a partial update, we load both blocks up + * front, modify both, then write them both back. + */ + unsigned char parentDirBuf[kBlkSize]; + unsigned char thisDirBuf[kBlkSize]; - dierr = fpImg->ReadBlock(pFile->fParentDirBlock, parentDirBuf); - if (dierr != kDIErrNone) - goto bail; - if (pFile->IsDirectory()) { - dierr = fpImg->ReadBlock(pFile->fDirEntry.keyPointer, thisDirBuf); - if (dierr != kDIErrNone) - goto bail; - } + dierr = fpImg->ReadBlock(pFile->fParentDirBlock, parentDirBuf); + if (dierr != kDIErrNone) + goto bail; + if (pFile->IsDirectory()) { + dierr = fpImg->ReadBlock(pFile->fDirEntry.keyPointer, thisDirBuf); + if (dierr != kDIErrNone) + goto bail; + } - /* compute lower case flags as needed */ - unsigned short lcFlags, lcAuxType; - bool allowLowerCase, isAW; + /* compute lower case flags as needed */ + unsigned short lcFlags, lcAuxType; + bool allowLowerCase, isAW; - allowLowerCase = GetParameter(kParmProDOS_AllowLowerCase) != 0; - isAW = A2FileProDOS::UsesAppleWorksAuxType((unsigned char)pFile->GetFileType()); + allowLowerCase = GetParameter(kParmProDOS_AllowLowerCase) != 0; + isAW = A2FileProDOS::UsesAppleWorksAuxType((unsigned char)pFile->GetFileType()); - if (allowLowerCase) - lcFlags = GenerateLowerCaseBits(upperName, newName, false); - else - lcFlags = 0; - if (isAW) - lcAuxType = GenerateLowerCaseBits(upperName, newName, true); - else - lcAuxType = 0; + if (allowLowerCase) + lcFlags = GenerateLowerCaseBits(upperName, newName, false); + else + lcFlags = 0; + if (isAW) + lcAuxType = GenerateLowerCaseBits(upperName, newName, true); + else + lcAuxType = 0; - /* - * Possible optimization: if "upperName" matches what's in the block on - * disk and the "lcFlags"/"lcAuxType" values match as well, we don't - * need to write the blocks back. - * - * It's difficult to test for this earlier, because we need to do the - * update if (a) they're just changing the capitalization or (b) we're - * changing the capitalization for them because the "allow lower case" - * flag got turned off. - */ + /* + * Possible optimization: if "upperName" matches what's in the block on + * disk and the "lcFlags"/"lcAuxType" values match as well, we don't + * need to write the blocks back. + * + * It's difficult to test for this earlier, because we need to do the + * update if (a) they're just changing the capitalization or (b) we're + * changing the capitalization for them because the "allow lower case" + * flag got turned off. + */ - /* find the right entry, and copy our filename in */ - unsigned char* ptr; - assert(pFile->fParentDirIdx >= 0 && - pFile->fParentDirIdx < kEntriesPerBlock); - ptr = parentDirBuf + 4 + pFile->fParentDirIdx * kEntryLength; - if ((*ptr) >> 4 != pFile->fDirEntry.storageType) { - WMSG2("ProDOS GLITCH: mismatched storage types (%d vs %d)\n", - (*ptr) >> 4, pFile->fDirEntry.storageType); - assert(false); - dierr = kDIErrBadDirectory; - goto bail; - } - ptr[0x00] = (ptr[0x00] & 0xf0) | strlen(upperName); - memcpy(&ptr[0x01], upperName, A2FileProDOS::kMaxFileName); - PutShortLE(&ptr[0x1c], lcFlags); // version/min_version - if (isAW) - PutShortLE(&ptr[0x1f], lcAuxType); + /* find the right entry, and copy our filename in */ + unsigned char* ptr; + assert(pFile->fParentDirIdx >= 0 && + pFile->fParentDirIdx < kEntriesPerBlock); + ptr = parentDirBuf + 4 + pFile->fParentDirIdx * kEntryLength; + if ((*ptr) >> 4 != pFile->fDirEntry.storageType) { + WMSG2("ProDOS GLITCH: mismatched storage types (%d vs %d)\n", + (*ptr) >> 4, pFile->fDirEntry.storageType); + assert(false); + dierr = kDIErrBadDirectory; + goto bail; + } + ptr[0x00] = (ptr[0x00] & 0xf0) | strlen(upperName); + memcpy(&ptr[0x01], upperName, A2FileProDOS::kMaxFileName); + PutShortLE(&ptr[0x1c], lcFlags); // version/min_version + if (isAW) + PutShortLE(&ptr[0x1f], lcAuxType); - if (pFile->IsDirectory()) { - ptr = thisDirBuf + 4; - if ((*ptr) >> 4 != A2FileProDOS::kStorageSubdirHeader) { - WMSG1("ProDOS GLITCH: bad storage type in subdir header (%d)\n", - (*ptr) >> 4); - assert(false); - dierr = kDIErrBadDirectory; - goto bail; - } - ptr[0x00] = (ptr[0x00] & 0xf0) | strlen(upperName); - memcpy(&ptr[0x01], upperName, A2FileProDOS::kMaxFileName); - PutShortLE(&ptr[0x1c], lcFlags); // version/min_version - } + if (pFile->IsDirectory()) { + ptr = thisDirBuf + 4; + if ((*ptr) >> 4 != A2FileProDOS::kStorageSubdirHeader) { + WMSG1("ProDOS GLITCH: bad storage type in subdir header (%d)\n", + (*ptr) >> 4); + assert(false); + dierr = kDIErrBadDirectory; + goto bail; + } + ptr[0x00] = (ptr[0x00] & 0xf0) | strlen(upperName); + memcpy(&ptr[0x01], upperName, A2FileProDOS::kMaxFileName); + PutShortLE(&ptr[0x1c], lcFlags); // version/min_version + } - /* write the updated data back to the disk */ - dierr = fpImg->WriteBlock(pFile->fParentDirBlock, parentDirBuf); - if (dierr != kDIErrNone) - goto bail; - if (pFile->IsDirectory()) { - dierr = fpImg->WriteBlock(pFile->fDirEntry.keyPointer, thisDirBuf); - if (dierr != kDIErrNone) - goto bail; - } + /* write the updated data back to the disk */ + dierr = fpImg->WriteBlock(pFile->fParentDirBlock, parentDirBuf); + if (dierr != kDIErrNone) + goto bail; + if (pFile->IsDirectory()) { + dierr = fpImg->WriteBlock(pFile->fDirEntry.keyPointer, thisDirBuf); + if (dierr != kDIErrNone) + goto bail; + } - /* - * At this point the ProDOS filesystem is back in a consistent state. - * Everything we do from here on is self-inflicted. - * - * We need to update this entry's A2FileProDOS::fDirEntry.fileName, - * as well as the A2FileProDOS::fPathName. If this was a subdir, then - * we need to update A2FileProDOS::fPathName for all files inside the - * directory (including children of children). - * - * The latter is somewhat awkward, so we just re-acquire the pathname - * for every file on the disk. Less efficient but easier to code. - */ - if (isAW) - GenerateLowerCaseName(upperName, pFile->fDirEntry.fileName, - lcAuxType, true); - else - GenerateLowerCaseName(upperName, pFile->fDirEntry.fileName, - lcFlags, false); - assert(pFile->fDirEntry.fileName[A2FileProDOS::kMaxFileName] == '\0'); + /* + * At this point the ProDOS filesystem is back in a consistent state. + * Everything we do from here on is self-inflicted. + * + * We need to update this entry's A2FileProDOS::fDirEntry.fileName, + * as well as the A2FileProDOS::fPathName. If this was a subdir, then + * we need to update A2FileProDOS::fPathName for all files inside the + * directory (including children of children). + * + * The latter is somewhat awkward, so we just re-acquire the pathname + * for every file on the disk. Less efficient but easier to code. + */ + if (isAW) + GenerateLowerCaseName(upperName, pFile->fDirEntry.fileName, + lcAuxType, true); + else + GenerateLowerCaseName(upperName, pFile->fDirEntry.fileName, + lcFlags, false); + assert(pFile->fDirEntry.fileName[A2FileProDOS::kMaxFileName] == '\0'); - if (pFile->IsDirectory()) { - /* do all files that come after us */ - pCur = pFile; - while (pCur != nil) { - RegeneratePathName((A2FileProDOS*) pCur); - pCur = GetNextFile(pCur); - } - } else { - RegeneratePathName(pFile); - } + if (pFile->IsDirectory()) { + /* do all files that come after us */ + pCur = pFile; + while (pCur != nil) { + RegeneratePathName((A2FileProDOS*) pCur); + pCur = GetNextFile(pCur); + } + } else { + RegeneratePathName(pFile); + } - WMSG0("Okay!\n"); + WMSG0("Okay!\n"); bail: - return dierr; + return dierr; } /* @@ -3609,52 +3609,52 @@ bail: DIError DiskFSProDOS::RegeneratePathName(A2FileProDOS* pFile) { - A2FileProDOS* pParent; - char* buf = nil; - int len; + A2FileProDOS* pParent; + char* buf = nil; + int len; - /* nothing to do here */ - if (pFile->IsVolumeDirectory()) - return kDIErrNone; + /* nothing to do here */ + if (pFile->IsVolumeDirectory()) + return kDIErrNone; - /* compute the length of the path name */ - len = strlen(pFile->GetFileName()); - pParent = (A2FileProDOS*) pFile->GetParent(); - while (!pParent->IsVolumeDirectory()) { - len++; // leave space for the ':' - len += strlen(pParent->GetFileName()); + /* compute the length of the path name */ + len = strlen(pFile->GetFileName()); + pParent = (A2FileProDOS*) pFile->GetParent(); + while (!pParent->IsVolumeDirectory()) { + len++; // leave space for the ':' + len += strlen(pParent->GetFileName()); - pParent = (A2FileProDOS*) pParent->GetParent(); - } + pParent = (A2FileProDOS*) pParent->GetParent(); + } - buf = new char[len+1]; - if (buf == nil) - return kDIErrMalloc; + buf = new char[len+1]; + if (buf == nil) + return kDIErrMalloc; - /* generate the new path name */ - int partLen; - partLen = strlen(pFile->GetFileName()); - strcpy(buf + len - partLen, pFile->GetFileName()); - len -= partLen; + /* generate the new path name */ + int partLen; + partLen = strlen(pFile->GetFileName()); + strcpy(buf + len - partLen, pFile->GetFileName()); + len -= partLen; - pParent = (A2FileProDOS*) pFile->GetParent(); - while (!pParent->IsVolumeDirectory()) { - assert(len > 0); - buf[--len] = kDIFssep; + pParent = (A2FileProDOS*) pFile->GetParent(); + while (!pParent->IsVolumeDirectory()) { + assert(len > 0); + buf[--len] = kDIFssep; - partLen = strlen(pParent->GetFileName()); - strncpy(buf + len - partLen, pParent->GetFileName(), partLen); - len -= partLen; - assert(len >= 0); + partLen = strlen(pParent->GetFileName()); + strncpy(buf + len - partLen, pParent->GetFileName(), partLen); + len -= partLen; + assert(len >= 0); - pParent = (A2FileProDOS*) pParent->GetParent(); - } + pParent = (A2FileProDOS*) pParent->GetParent(); + } - WMSG2("Replacing '%s' with '%s'\n", pFile->GetPathName(), buf); - pFile->SetPathName("", buf); - delete[] buf; + WMSG2("Replacing '%s' with '%s'\n", pFile->GetPathName(), buf); + pFile->SetPathName("", buf); + delete[] buf; - return kDIErrNone; + return kDIErrNone; } @@ -3672,72 +3672,72 @@ DiskFSProDOS::RegeneratePathName(A2FileProDOS* pFile) */ DIError DiskFSProDOS::SetFileInfo(A2File* pGenericFile, long fileType, long auxType, - long accessFlags) + long accessFlags) { - DIError dierr = kDIErrNone; - A2FileProDOS* pFile = (A2FileProDOS*) pGenericFile; + DIError dierr = kDIErrNone; + A2FileProDOS* pFile = (A2FileProDOS*) pGenericFile; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; - if (pFile == nil) { - assert(false); - return kDIErrInvalidArg; - } - if ((fileType & ~(0xff)) != 0 || - (auxType & ~(0xffff)) != 0 || - (accessFlags & ~(0xff)) != 0) - { - return kDIErrInvalidArg; - } - if (pFile->IsVolumeDirectory()) { - WMSG0(" ProDOS refusing to change file info for volume dir\n"); - return kDIErrAccessDenied; // not quite right - } + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; + if (pFile == nil) { + assert(false); + return kDIErrInvalidArg; + } + if ((fileType & ~(0xff)) != 0 || + (auxType & ~(0xffff)) != 0 || + (accessFlags & ~(0xff)) != 0) + { + return kDIErrInvalidArg; + } + if (pFile->IsVolumeDirectory()) { + WMSG0(" ProDOS refusing to change file info for volume dir\n"); + return kDIErrAccessDenied; // not quite right + } - WMSG4("ProDOS changing values for '%s' to 0x%02lx 0x%04lx 0x%02lx\n", - pFile->GetPathName(), fileType, auxType, accessFlags); + WMSG4("ProDOS changing values for '%s' to 0x%02lx 0x%04lx 0x%02lx\n", + pFile->GetPathName(), fileType, auxType, accessFlags); - /* load the directory block for this file */ - unsigned char thisDirBuf[kBlkSize]; - dierr = fpImg->ReadBlock(pFile->fParentDirBlock, thisDirBuf); - if (dierr != kDIErrNone) - goto bail; + /* load the directory block for this file */ + unsigned char thisDirBuf[kBlkSize]; + dierr = fpImg->ReadBlock(pFile->fParentDirBlock, thisDirBuf); + if (dierr != kDIErrNone) + goto bail; - /* find the right entry, and set the fields */ - unsigned char* ptr; - assert(pFile->fParentDirIdx >= 0 && - pFile->fParentDirIdx < kEntriesPerBlock); - ptr = thisDirBuf + 4 + pFile->fParentDirIdx * kEntryLength; - if ((*ptr) >> 4 != pFile->fDirEntry.storageType) { - WMSG2("ProDOS GLITCH: mismatched storage types (%d vs %d)\n", - (*ptr) >> 4, pFile->fDirEntry.storageType); - assert(false); - dierr = kDIErrBadDirectory; - goto bail; - } - if ((size_t) (*ptr & 0x0f) != strlen(pFile->fDirEntry.fileName)) { - WMSG2("ProDOS GLITCH: wrong file? (len=%d vs %d)\n", - *ptr & 0x0f, strlen(pFile->fDirEntry.fileName)); - assert(false); - dierr = kDIErrBadDirectory; - goto bail; - } + /* find the right entry, and set the fields */ + unsigned char* ptr; + assert(pFile->fParentDirIdx >= 0 && + pFile->fParentDirIdx < kEntriesPerBlock); + ptr = thisDirBuf + 4 + pFile->fParentDirIdx * kEntryLength; + if ((*ptr) >> 4 != pFile->fDirEntry.storageType) { + WMSG2("ProDOS GLITCH: mismatched storage types (%d vs %d)\n", + (*ptr) >> 4, pFile->fDirEntry.storageType); + assert(false); + dierr = kDIErrBadDirectory; + goto bail; + } + if ((size_t) (*ptr & 0x0f) != strlen(pFile->fDirEntry.fileName)) { + WMSG2("ProDOS GLITCH: wrong file? (len=%d vs %d)\n", + *ptr & 0x0f, strlen(pFile->fDirEntry.fileName)); + assert(false); + dierr = kDIErrBadDirectory; + goto bail; + } - ptr[0x10] = (unsigned char) fileType; - ptr[0x1e] = (unsigned char) accessFlags; - PutShortLE(&ptr[0x1f], (unsigned short) auxType); + ptr[0x10] = (unsigned char) fileType; + ptr[0x1e] = (unsigned char) accessFlags; + PutShortLE(&ptr[0x1f], (unsigned short) auxType); - dierr = fpImg->WriteBlock(pFile->fParentDirBlock, thisDirBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpImg->WriteBlock(pFile->fParentDirBlock, thisDirBuf); + if (dierr != kDIErrNone) + goto bail; - /* update our local copy */ - pFile->fDirEntry.fileType = (unsigned char) fileType; - pFile->fDirEntry.auxType = (unsigned short) auxType; - pFile->fDirEntry.access = (unsigned char) accessFlags; + /* update our local copy */ + pFile->fDirEntry.fileType = (unsigned char) fileType; + pFile->fDirEntry.auxType = (unsigned short) auxType; + pFile->fDirEntry.access = (unsigned char) accessFlags; bail: - return dierr; + return dierr; } @@ -3754,94 +3754,94 @@ bail: DIError DiskFSProDOS::RenameVolume(const char* newName) { - DIError dierr = kDIErrNone; - char upperName[A2FileProDOS::kMaxFileName+1]; - A2FileProDOS* pFile; + DIError dierr = kDIErrNone; + char upperName[A2FileProDOS::kMaxFileName+1]; + A2FileProDOS* pFile; - if (!IsValidVolumeName(newName)) - return kDIErrInvalidArg; - if (fpImg->GetReadOnly()) - return kDIErrAccessDenied; + if (!IsValidVolumeName(newName)) + return kDIErrInvalidArg; + if (fpImg->GetReadOnly()) + return kDIErrAccessDenied; - pFile = (A2FileProDOS*) GetNextFile(nil); - assert(pFile != nil); - assert(strcmp(pFile->GetFileName(), fVolumeName) == 0); + pFile = (A2FileProDOS*) GetNextFile(nil); + assert(pFile != nil); + assert(strcmp(pFile->GetFileName(), fVolumeName) == 0); - WMSG2(" ProDOS renaming volume '%s' to '%s'\n", - pFile->GetPathName(), newName); + WMSG2(" ProDOS renaming volume '%s' to '%s'\n", + pFile->GetPathName(), newName); - /* - * Figure out the lower-case flags. - */ - unsigned short lcFlags; - bool allowLowerCase; + /* + * Figure out the lower-case flags. + */ + unsigned short lcFlags; + bool allowLowerCase; - UpperCaseName(upperName, newName); - allowLowerCase = GetParameter(kParmProDOS_AllowLowerCase) != 0; - if (allowLowerCase) - lcFlags = GenerateLowerCaseBits(upperName, newName, false); - else - lcFlags = 0; + UpperCaseName(upperName, newName); + allowLowerCase = GetParameter(kParmProDOS_AllowLowerCase) != 0; + if (allowLowerCase) + lcFlags = GenerateLowerCaseBits(upperName, newName, false); + else + lcFlags = 0; - /* - * Update the volume dir header. - */ - unsigned char thisDirBuf[kBlkSize]; - unsigned char* ptr; - assert(pFile->fDirEntry.keyPointer == kVolHeaderBlock); + /* + * Update the volume dir header. + */ + unsigned char thisDirBuf[kBlkSize]; + unsigned char* ptr; + assert(pFile->fDirEntry.keyPointer == kVolHeaderBlock); - dierr = fpImg->ReadBlock(pFile->fDirEntry.keyPointer, thisDirBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpImg->ReadBlock(pFile->fDirEntry.keyPointer, thisDirBuf); + if (dierr != kDIErrNone) + goto bail; - ptr = thisDirBuf + 4; - if ((*ptr) >> 4 != A2FileProDOS::kStorageVolumeDirHeader) { - WMSG1("ProDOS GLITCH: bad storage type in voldir header (%d)\n", - (*ptr) >> 4); - assert(false); - dierr = kDIErrBadDirectory; - goto bail; - } - ptr[0x00] = (ptr[0x00] & 0xf0) | strlen(upperName); - memcpy(&ptr[0x01], upperName, A2FileProDOS::kMaxFileName); - PutShortLE(&ptr[0x16], lcFlags); // reserved fields + ptr = thisDirBuf + 4; + if ((*ptr) >> 4 != A2FileProDOS::kStorageVolumeDirHeader) { + WMSG1("ProDOS GLITCH: bad storage type in voldir header (%d)\n", + (*ptr) >> 4); + assert(false); + dierr = kDIErrBadDirectory; + goto bail; + } + ptr[0x00] = (ptr[0x00] & 0xf0) | strlen(upperName); + memcpy(&ptr[0x01], upperName, A2FileProDOS::kMaxFileName); + PutShortLE(&ptr[0x16], lcFlags); // reserved fields - dierr = fpImg->WriteBlock(pFile->fDirEntry.keyPointer, thisDirBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpImg->WriteBlock(pFile->fDirEntry.keyPointer, thisDirBuf); + if (dierr != kDIErrNone) + goto bail; - /* - * Set the volume name, based on the upper-case name and lower-case flags - * we just wrote. If "allowLowerCase" was set to false, it may not be - * the same as what's in "newName". - */ - char lowerName[A2FileProDOS::kMaxFileName+1]; - memset(lowerName, 0, sizeof(lowerName)); // lowerName won't be term'ed - GenerateLowerCaseName(upperName, lowerName, lcFlags, false); + /* + * Set the volume name, based on the upper-case name and lower-case flags + * we just wrote. If "allowLowerCase" was set to false, it may not be + * the same as what's in "newName". + */ + char lowerName[A2FileProDOS::kMaxFileName+1]; + memset(lowerName, 0, sizeof(lowerName)); // lowerName won't be term'ed + GenerateLowerCaseName(upperName, lowerName, lcFlags, false); - strcpy(fVolumeName, lowerName); - SetVolumeID(); - strcpy(pFile->fDirEntry.fileName, lowerName); + strcpy(fVolumeName, lowerName); + SetVolumeID(); + strcpy(pFile->fDirEntry.fileName, lowerName); - /* update the entry in the linear file list */ - pFile->SetPathName(":", fVolumeName); + /* update the entry in the linear file list */ + pFile->SetPathName(":", fVolumeName); bail: - return dierr; + return dierr; } /* * =========================================================================== - * A2FileProDOS + * A2FileProDOS * =========================================================================== */ /* * Convert from ProDOS compact date format to a time_t. * - * Byte 0 and 1: yyyyyyymmmmddddd - * Byte 2 and 3: 000hhhhh00mmmmmm + * Byte 0 and 1: yyyyyyymmmmddddd + * Byte 2 and 3: 000hhhhh00mmmmmm * * The field is set entirely to zero if no date was assigned (which cannot * be a valid date since "day" ranges from 1 to 31). If this is found then @@ -3850,16 +3850,16 @@ bail: /*static*/ time_t A2FileProDOS::ConvertProDate(ProDate proDate) { - unsigned short prodosDate, prodosTime; - int year, month, day, hour, minute, second; + unsigned short prodosDate, prodosTime; + int year, month, day, hour, minute, second; - if (proDate == 0) - return 0; + if (proDate == 0) + return 0; - prodosDate = (unsigned short) (proDate & 0x0000ffff); - prodosTime = (unsigned short) ((proDate >> 16) & 0x0000ffff); + prodosDate = (unsigned short) (proDate & 0x0000ffff); + prodosTime = (unsigned short) ((proDate >> 16) & 0x0000ffff); - second = 0; + second = 0; minute = prodosTime & 0x3f; hour = (prodosTime >> 8) & 0x1f; day = prodosDate & 0x1f; @@ -3875,17 +3875,17 @@ A2FileProDOS::ConvertProDate(ProDate proDate) tmbuf.tm_min = minute; tmbuf.tm_hour = hour; tmbuf.tm_mday = day; - tmbuf.tm_mon = month-1; // ProDOS uses 1-12 + tmbuf.tm_mon = month-1; // ProDOS uses 1-12 tmbuf.tm_year = year; tmbuf.tm_wday = 0; tmbuf.tm_yday = 0; tmbuf.tm_isdst = -1; // let it figure DST and time zone when = mktime(&tmbuf); - if (when == (time_t) -1) - when = 0; + if (when == (time_t) -1) + when = 0; - return when; + return when; } /* @@ -3896,37 +3896,37 @@ A2FileProDOS::ConvertProDate(ProDate proDate) /*static*/ A2FileProDOS::ProDate A2FileProDOS::ConvertProDate(time_t unixDate) { - ProDate proDate; - unsigned long prodosDate, prodosTime; - struct tm* ptm; - int year; + ProDate proDate; + unsigned long prodosDate, prodosTime; + struct tm* ptm; + int year; - if (unixDate == 0 || unixDate == -1 || unixDate == -2) - return 0; + if (unixDate == 0 || unixDate == -1 || unixDate == -2) + return 0; - ptm = localtime(&unixDate); - if (ptm == nil) - return 0; // must've been invalid or unspecified + ptm = localtime(&unixDate); + if (ptm == nil) + return 0; // must've been invalid or unspecified - year = ptm->tm_year; + year = ptm->tm_year; #ifdef OLD_PRODOS_DATES - /* ProSel-16 volume repair complaints about dates < 1980 and >= Y2K */ - if (year > 100) - year -= 20; + /* ProSel-16 volume repair complaints about dates < 1980 and >= Y2K */ + if (year > 100) + year -= 20; #endif - if (year >= 100) - year -= 100; - if (year < 0 || year >= 128) { - WMSG2("WHOOPS: got year %d from %d\n", year, ptm->tm_year); - year = 70; - } + if (year >= 100) + year -= 100; + if (year < 0 || year >= 128) { + WMSG2("WHOOPS: got year %d from %d\n", year, ptm->tm_year); + year = 70; + } - prodosDate = year << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday; - prodosTime = ptm->tm_hour << 8 | ptm->tm_min; + prodosDate = year << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday; + prodosTime = ptm->tm_hour << 8 | ptm->tm_min; - proDate = prodosTime << 16 | prodosDate; - return proDate; + proDate = prodosTime << 16 | prodosDate; + return proDate; } @@ -3936,7 +3936,7 @@ A2FileProDOS::ConvertProDate(time_t unixDate) time_t A2FileProDOS::GetCreateWhen(void) const { - return ConvertProDate(fDirEntry.createWhen); + return ConvertProDate(fDirEntry.createWhen); } /* @@ -3945,7 +3945,7 @@ A2FileProDOS::GetCreateWhen(void) const time_t A2FileProDOS::GetModWhen(void) const { - return ConvertProDate(fDirEntry.modWhen); + return ConvertProDate(fDirEntry.modWhen); } /* @@ -3957,20 +3957,20 @@ A2FileProDOS::GetModWhen(void) const void A2FileProDOS::SetPathName(const char* basePath, const char* fileName) { - assert(basePath != nil && fileName != nil); - if (fPathName != nil) - delete[] fPathName; + assert(basePath != nil && fileName != nil); + if (fPathName != nil) + delete[] fPathName; - int baseLen = strlen(basePath); - fPathName = new char[baseLen + 1 + strlen(fileName)+1]; - strcpy(fPathName, basePath); - if (baseLen != 0 && - !(baseLen == 1 && basePath[0] == ':')) - { - *(fPathName + baseLen) = kFssep; - baseLen++; - } - strcpy(fPathName + baseLen, fileName); + int baseLen = strlen(basePath); + fPathName = new char[baseLen + 1 + strlen(fileName)+1]; + strcpy(fPathName, basePath); + if (baseLen != 0 && + !(baseLen == 1 && basePath[0] == ':')) + { + *(fPathName + baseLen) = kFssep; + baseLen++; + } + strcpy(fPathName + baseLen, fileName); } @@ -3983,10 +3983,10 @@ A2FileProDOS::SetPathName(const char* basePath, const char* fileName) /*static*/ char A2FileProDOS::NameToLower(char ch) { - if (ch == '.') - return ' '; - else - return tolower(ch); + if (ch == '.') + return ' '; + else + return tolower(ch); } /* @@ -3997,36 +3997,36 @@ A2FileProDOS::NameToLower(char ch) */ /*static*/ void A2FileProDOS::InitDirEntry(A2FileProDOS::DirEntry* pEntry, - const unsigned char* entryBuf) + const unsigned char* entryBuf) { - int nameLen; + int nameLen; - pEntry->storageType = (entryBuf[0x00] & 0xf0) >> 4; - nameLen = entryBuf[0x00] & 0x0f; - memcpy(pEntry->fileName, &entryBuf[0x01], nameLen); - pEntry->fileName[nameLen] = '\0'; - pEntry->fileType = entryBuf[0x10]; - pEntry->keyPointer = GetShortLE(&entryBuf[0x11]); - pEntry->blocksUsed = GetShortLE(&entryBuf[0x13]); - pEntry->eof = GetLongLE(&entryBuf[0x15]); - pEntry->eof &= 0x00ffffff; - pEntry->createWhen = GetLongLE(&entryBuf[0x18]); - pEntry->version = entryBuf[0x1c]; - pEntry->minVersion = entryBuf[0x1d]; - pEntry->access = entryBuf[0x1e]; - pEntry->auxType = GetShortLE(&entryBuf[0x1f]); - pEntry->modWhen = GetLongLE(&entryBuf[0x21]); - pEntry->headerPointer = GetShortLE(&entryBuf[0x25]); + pEntry->storageType = (entryBuf[0x00] & 0xf0) >> 4; + nameLen = entryBuf[0x00] & 0x0f; + memcpy(pEntry->fileName, &entryBuf[0x01], nameLen); + pEntry->fileName[nameLen] = '\0'; + pEntry->fileType = entryBuf[0x10]; + pEntry->keyPointer = GetShortLE(&entryBuf[0x11]); + pEntry->blocksUsed = GetShortLE(&entryBuf[0x13]); + pEntry->eof = GetLongLE(&entryBuf[0x15]); + pEntry->eof &= 0x00ffffff; + pEntry->createWhen = GetLongLE(&entryBuf[0x18]); + pEntry->version = entryBuf[0x1c]; + pEntry->minVersion = entryBuf[0x1d]; + pEntry->access = entryBuf[0x1e]; + pEntry->auxType = GetShortLE(&entryBuf[0x1f]); + pEntry->modWhen = GetLongLE(&entryBuf[0x21]); + pEntry->headerPointer = GetShortLE(&entryBuf[0x25]); - /* generate the name into the buffer; does not null-terminate */ - if (UsesAppleWorksAuxType(pEntry->fileType)) { - DiskFSProDOS::GenerateLowerCaseName(pEntry->fileName, pEntry->fileName, - pEntry->auxType, true); - } else if (pEntry->minVersion & 0x80) { - DiskFSProDOS::GenerateLowerCaseName(pEntry->fileName, pEntry->fileName, - GetShortLE(&entryBuf[0x1c]), false); - } - pEntry->fileName[sizeof(pEntry->fileName)-1] = '\0'; + /* generate the name into the buffer; does not null-terminate */ + if (UsesAppleWorksAuxType(pEntry->fileType)) { + DiskFSProDOS::GenerateLowerCaseName(pEntry->fileName, pEntry->fileName, + pEntry->auxType, true); + } else if (pEntry->minVersion & 0x80) { + DiskFSProDOS::GenerateLowerCaseName(pEntry->fileName, pEntry->fileName, + GetShortLE(&entryBuf[0x1c]), false); + } + pEntry->fileName[sizeof(pEntry->fileName)-1] = '\0'; } @@ -4037,94 +4037,94 @@ A2FileProDOS::InitDirEntry(A2FileProDOS::DirEntry* pEntry, */ DIError A2FileProDOS::Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork /*= false*/) + bool rsrcFork /*= false*/) { - DIError dierr = kDIErrNone; - A2FDProDOS* pOpenFile = nil; + DIError dierr = kDIErrNone; + A2FDProDOS* pOpenFile = nil; - WMSG3(" ProDOS Open(ro=%d, rsrc=%d) on '%s'\n", - readOnly, rsrcFork, fPathName); - //Dump(); + WMSG3(" ProDOS Open(ro=%d, rsrc=%d) on '%s'\n", + readOnly, rsrcFork, fPathName); + //Dump(); - if (!readOnly) { - if (fpDiskFS->GetDiskImg()->GetReadOnly()) - return kDIErrAccessDenied; - if (fpDiskFS->GetFSDamaged()) - return kDIErrBadDiskImage; - } + if (!readOnly) { + if (fpDiskFS->GetDiskImg()->GetReadOnly()) + return kDIErrAccessDenied; + if (fpDiskFS->GetFSDamaged()) + return kDIErrBadDiskImage; + } - if (fpOpenFile != nil) { - dierr = kDIErrAlreadyOpen; - goto bail; - } - if (rsrcFork && fDirEntry.storageType != kStorageExtended) { - dierr = kDIErrForkNotFound; - goto bail; - } + if (fpOpenFile != nil) { + dierr = kDIErrAlreadyOpen; + goto bail; + } + if (rsrcFork && fDirEntry.storageType != kStorageExtended) { + dierr = kDIErrForkNotFound; + goto bail; + } - pOpenFile = new A2FDProDOS(this); - if (pOpenFile == nil) - return kDIErrMalloc; + pOpenFile = new A2FDProDOS(this); + if (pOpenFile == nil) + return kDIErrMalloc; - pOpenFile->fOpenRsrcFork = false; + pOpenFile->fOpenRsrcFork = false; - if (fDirEntry.storageType == kStorageExtended) { - if (rsrcFork) { - dierr = LoadBlockList(fExtRsrc.storageType, fExtRsrc.keyBlock, - fExtRsrc.eof, &pOpenFile->fBlockCount, - &pOpenFile->fBlockList); - pOpenFile->fOpenEOF = fExtRsrc.eof; - pOpenFile->fOpenBlocksUsed = fExtRsrc.blocksUsed; - pOpenFile->fOpenStorageType = fExtRsrc.storageType; - pOpenFile->fOpenRsrcFork = true; - } else { - dierr = LoadBlockList(fExtData.storageType, fExtData.keyBlock, - fExtData.eof, &pOpenFile->fBlockCount, - &pOpenFile->fBlockList); - pOpenFile->fOpenEOF = fExtData.eof; - pOpenFile->fOpenBlocksUsed = fExtData.blocksUsed; - pOpenFile->fOpenStorageType = fExtData.storageType; - } - } else if (fDirEntry.storageType == kStorageDirectory || - fDirEntry.storageType == kStorageVolumeDirHeader) - { - dierr = LoadDirectoryBlockList(fDirEntry.keyPointer, - fDirEntry.eof, &pOpenFile->fBlockCount, - &pOpenFile->fBlockList); - pOpenFile->fOpenEOF = fDirEntry.eof; - pOpenFile->fOpenBlocksUsed = fDirEntry.blocksUsed; - pOpenFile->fOpenStorageType = fDirEntry.storageType; - } else if (fDirEntry.storageType == kStorageSeedling || - fDirEntry.storageType == kStorageSapling || - fDirEntry.storageType == kStorageTree) - { - dierr = LoadBlockList(fDirEntry.storageType, fDirEntry.keyPointer, - fDirEntry.eof, &pOpenFile->fBlockCount, - &pOpenFile->fBlockList); - pOpenFile->fOpenEOF = fDirEntry.eof; - pOpenFile->fOpenBlocksUsed = fDirEntry.blocksUsed; - pOpenFile->fOpenStorageType = fDirEntry.storageType; - } else { - WMSG1("PrODOS can't open unknown storage type %d\n", - fDirEntry.storageType); - dierr = kDIErrBadDirectory; - goto bail; - } - if (dierr != kDIErrNone) { - WMSG0(" ProDOS open failed\n"); - goto bail; - } + if (fDirEntry.storageType == kStorageExtended) { + if (rsrcFork) { + dierr = LoadBlockList(fExtRsrc.storageType, fExtRsrc.keyBlock, + fExtRsrc.eof, &pOpenFile->fBlockCount, + &pOpenFile->fBlockList); + pOpenFile->fOpenEOF = fExtRsrc.eof; + pOpenFile->fOpenBlocksUsed = fExtRsrc.blocksUsed; + pOpenFile->fOpenStorageType = fExtRsrc.storageType; + pOpenFile->fOpenRsrcFork = true; + } else { + dierr = LoadBlockList(fExtData.storageType, fExtData.keyBlock, + fExtData.eof, &pOpenFile->fBlockCount, + &pOpenFile->fBlockList); + pOpenFile->fOpenEOF = fExtData.eof; + pOpenFile->fOpenBlocksUsed = fExtData.blocksUsed; + pOpenFile->fOpenStorageType = fExtData.storageType; + } + } else if (fDirEntry.storageType == kStorageDirectory || + fDirEntry.storageType == kStorageVolumeDirHeader) + { + dierr = LoadDirectoryBlockList(fDirEntry.keyPointer, + fDirEntry.eof, &pOpenFile->fBlockCount, + &pOpenFile->fBlockList); + pOpenFile->fOpenEOF = fDirEntry.eof; + pOpenFile->fOpenBlocksUsed = fDirEntry.blocksUsed; + pOpenFile->fOpenStorageType = fDirEntry.storageType; + } else if (fDirEntry.storageType == kStorageSeedling || + fDirEntry.storageType == kStorageSapling || + fDirEntry.storageType == kStorageTree) + { + dierr = LoadBlockList(fDirEntry.storageType, fDirEntry.keyPointer, + fDirEntry.eof, &pOpenFile->fBlockCount, + &pOpenFile->fBlockList); + pOpenFile->fOpenEOF = fDirEntry.eof; + pOpenFile->fOpenBlocksUsed = fDirEntry.blocksUsed; + pOpenFile->fOpenStorageType = fDirEntry.storageType; + } else { + WMSG1("PrODOS can't open unknown storage type %d\n", + fDirEntry.storageType); + dierr = kDIErrBadDirectory; + goto bail; + } + if (dierr != kDIErrNone) { + WMSG0(" ProDOS open failed\n"); + goto bail; + } - pOpenFile->fOffset = 0; - //pOpenFile->DumpBlockList(); + pOpenFile->fOffset = 0; + //pOpenFile->DumpBlockList(); - fpOpenFile = pOpenFile; // add it to our single-member "open file set" - *ppOpenFile = pOpenFile; - pOpenFile = nil; + fpOpenFile = pOpenFile; // add it to our single-member "open file set" + *ppOpenFile = pOpenFile; + pOpenFile = nil; bail: - delete pOpenFile; - return dierr; + delete pOpenFile; + return dierr; } @@ -4149,148 +4149,148 @@ bail: */ DIError A2FileProDOS::LoadBlockList(int storageType, unsigned short keyBlock, - long eof, long* pBlockCount, unsigned short** pBlockList, - long* pIndexBlockCount, unsigned short** pIndexBlockList) + long eof, long* pBlockCount, unsigned short** pBlockList, + long* pIndexBlockCount, unsigned short** pIndexBlockList) { - if (storageType == kStorageDirectory || - storageType == kStorageVolumeDirHeader) - { - assert(pIndexBlockList == nil && pIndexBlockCount == nil); - return LoadDirectoryBlockList(keyBlock, eof, pBlockCount, pBlockList); - } - - assert(keyBlock != 0); - assert(pBlockCount != nil); - assert(pBlockList != nil); - assert(*pBlockList == nil); - if (storageType != kStorageSeedling && - storageType != kStorageSapling && - storageType != kStorageTree) - { - /* - * We can get here if somebody puts a bad storage type inside the - * extended key block of a forked file. Bad storage types on other - * kinds of files are caught earlier. - */ - WMSG2(" ProDOS unexpected storageType %d in '%s'\n", - storageType, GetPathName()); - return kDIErrNotSupported; - } + if (storageType == kStorageDirectory || + storageType == kStorageVolumeDirHeader) + { + assert(pIndexBlockList == nil && pIndexBlockCount == nil); + return LoadDirectoryBlockList(keyBlock, eof, pBlockCount, pBlockList); + } + + assert(keyBlock != 0); + assert(pBlockCount != nil); + assert(pBlockList != nil); + assert(*pBlockList == nil); + if (storageType != kStorageSeedling && + storageType != kStorageSapling && + storageType != kStorageTree) + { + /* + * We can get here if somebody puts a bad storage type inside the + * extended key block of a forked file. Bad storage types on other + * kinds of files are caught earlier. + */ + WMSG2(" ProDOS unexpected storageType %d in '%s'\n", + storageType, GetPathName()); + return kDIErrNotSupported; + } - DIError dierr = kDIErrNone; - unsigned short* list = nil; - long count; + DIError dierr = kDIErrNone; + unsigned short* list = nil; + long count; - assert(eof < 1024*1024*16); - count = (eof + kBlkSize -1) / kBlkSize; - if (count == 0) - count = 1; - list = new unsigned short[count+1]; - if (list == nil) { - dierr = kDIErrMalloc; - goto bail; - } + assert(eof < 1024*1024*16); + count = (eof + kBlkSize -1) / kBlkSize; + if (count == 0) + count = 1; + list = new unsigned short[count+1]; + if (list == nil) { + dierr = kDIErrMalloc; + goto bail; + } - if (pIndexBlockList != nil) { - assert(pIndexBlockCount != nil); - assert(*pIndexBlockList == nil); - } + if (pIndexBlockList != nil) { + assert(pIndexBlockCount != nil); + assert(*pIndexBlockList == nil); + } - /* this should take care of trailing sparse entries */ - memset(list, 0, sizeof(unsigned short) * count); - list[count] = kInvalidBlockNum; // overrun check + /* this should take care of trailing sparse entries */ + memset(list, 0, sizeof(unsigned short) * count); + list[count] = kInvalidBlockNum; // overrun check - if (storageType == kStorageSeedling) { - list[0] = keyBlock; + if (storageType == kStorageSeedling) { + list[0] = keyBlock; - if (pIndexBlockList != nil) { - *pIndexBlockCount = 0; - *pIndexBlockList = nil; - } - } else if (storageType == kStorageSapling) { - dierr = LoadIndexBlock(keyBlock, list, count); - if (dierr != kDIErrNone) - goto bail; + if (pIndexBlockList != nil) { + *pIndexBlockCount = 0; + *pIndexBlockList = nil; + } + } else if (storageType == kStorageSapling) { + dierr = LoadIndexBlock(keyBlock, list, count); + if (dierr != kDIErrNone) + goto bail; - if (pIndexBlockList != nil) { - *pIndexBlockCount = 1; - *pIndexBlockList = new unsigned short[1]; - **pIndexBlockList = keyBlock; - } - } else if (storageType == kStorageTree) { - unsigned char blkBuf[kBlkSize]; - unsigned short* listPtr = list; - unsigned short* outIndexPtr = nil; - long countDown = count; - int idx = 0; + if (pIndexBlockList != nil) { + *pIndexBlockCount = 1; + *pIndexBlockList = new unsigned short[1]; + **pIndexBlockList = keyBlock; + } + } else if (storageType == kStorageTree) { + unsigned char blkBuf[kBlkSize]; + unsigned short* listPtr = list; + unsigned short* outIndexPtr = nil; + long countDown = count; + int idx = 0; - dierr = fpDiskFS->GetDiskImg()->ReadBlock(keyBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpDiskFS->GetDiskImg()->ReadBlock(keyBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; - if (pIndexBlockList != nil) { - int numIndices = (count + kMaxBlocksPerIndex-1) / kMaxBlocksPerIndex; - numIndices++; // add one for the master index block - *pIndexBlockList = new unsigned short[numIndices]; - outIndexPtr = *pIndexBlockList; - *outIndexPtr++ = keyBlock; - *pIndexBlockCount = 1; - } + if (pIndexBlockList != nil) { + int numIndices = (count + kMaxBlocksPerIndex-1) / kMaxBlocksPerIndex; + numIndices++; // add one for the master index block + *pIndexBlockList = new unsigned short[numIndices]; + outIndexPtr = *pIndexBlockList; + *outIndexPtr++ = keyBlock; + *pIndexBlockCount = 1; + } - while (countDown) { - long blockCount = countDown; - if (blockCount > kMaxBlocksPerIndex) - blockCount = kMaxBlocksPerIndex; - unsigned short idxBlock; + while (countDown) { + long blockCount = countDown; + if (blockCount > kMaxBlocksPerIndex) + blockCount = kMaxBlocksPerIndex; + unsigned short idxBlock; - idxBlock = blkBuf[idx] | (unsigned short) blkBuf[idx+256] << 8; - if (idxBlock == 0) { - /* fully sparse index block */ - //WMSG1(" ProDOS that's seriously sparse (%d)!\n", idx); - memset(listPtr, 0, blockCount * sizeof(unsigned short)); - if (pIndexBlockList != nil) { - *outIndexPtr++ = idxBlock; - (*pIndexBlockCount)++; - } - } else { - dierr = LoadIndexBlock(idxBlock, listPtr, blockCount); - if (dierr != kDIErrNone) - goto bail; + idxBlock = blkBuf[idx] | (unsigned short) blkBuf[idx+256] << 8; + if (idxBlock == 0) { + /* fully sparse index block */ + //WMSG1(" ProDOS that's seriously sparse (%d)!\n", idx); + memset(listPtr, 0, blockCount * sizeof(unsigned short)); + if (pIndexBlockList != nil) { + *outIndexPtr++ = idxBlock; + (*pIndexBlockCount)++; + } + } else { + dierr = LoadIndexBlock(idxBlock, listPtr, blockCount); + if (dierr != kDIErrNone) + goto bail; - if (pIndexBlockList != nil) { - *outIndexPtr++ = idxBlock; - (*pIndexBlockCount)++; - } - } + if (pIndexBlockList != nil) { + *outIndexPtr++ = idxBlock; + (*pIndexBlockCount)++; + } + } - idx++; - listPtr += blockCount; - countDown -= blockCount; - } - } else { - assert(false); - } + idx++; + listPtr += blockCount; + countDown -= blockCount; + } + } else { + assert(false); + } - assert(list[count] == kInvalidBlockNum); + assert(list[count] == kInvalidBlockNum); - dierr = ValidateBlockList(list, count); - if (dierr != kDIErrNone) - goto bail; + dierr = ValidateBlockList(list, count); + if (dierr != kDIErrNone) + goto bail; - *pBlockCount = count; - *pBlockList = list; + *pBlockCount = count; + *pBlockList = list; bail: - if (dierr != kDIErrNone) { - delete[] list; - assert(*pBlockList == nil); + if (dierr != kDIErrNone) { + delete[] list; + assert(*pBlockList == nil); - if (pIndexBlockList != nil && *pIndexBlockList != nil) { - delete[] *pIndexBlockList; - *pIndexBlockList = nil; - } - } - return dierr; + if (pIndexBlockList != nil && *pIndexBlockList != nil) { + delete[] *pIndexBlockList; + *pIndexBlockList = nil; + } + } + return dierr; } /* @@ -4316,28 +4316,28 @@ bail: DIError A2FileProDOS::ValidateBlockList(const unsigned short* list, long count) { - DiskImg* pImg = fpDiskFS->GetDiskImg(); - bool foundBad = false; + DiskImg* pImg = fpDiskFS->GetDiskImg(); + bool foundBad = false; - while (count--) { - if (*list > pImg->GetNumBlocks() || - (*list > 0 && *list <= 2)) // not enough, but it'll do - { - WMSG2("Invalid block %d in '%s'\n", *list, fDirEntry.fileName); - SetQuality(kQualityDamaged); - return kDIErrBadFile; - } - if (*list > fpDiskFS->GetFSNumBlocks()) - foundBad = true; - list++; - } + while (count--) { + if (*list > pImg->GetNumBlocks() || + (*list > 0 && *list <= 2)) // not enough, but it'll do + { + WMSG2("Invalid block %d in '%s'\n", *list, fDirEntry.fileName); + SetQuality(kQualityDamaged); + return kDIErrBadFile; + } + if (*list > fpDiskFS->GetFSNumBlocks()) + foundBad = true; + list++; + } - if (foundBad) { - WMSG1(" --- found out-of-range block in '%s'\n", GetPathName()); - SetQuality(kQualitySuspicious); - } + if (foundBad) { + WMSG1(" --- found out-of-range block in '%s'\n", GetPathName()); + SetQuality(kQualitySuspicious); + } - return kDIErrNone; + return kDIErrNone; } /* @@ -4346,26 +4346,26 @@ A2FileProDOS::ValidateBlockList(const unsigned short* list, long count) */ DIError A2FileProDOS::LoadIndexBlock(unsigned short block, unsigned short* list, - int maxCount) + int maxCount) { - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; - int i; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; + int i; - if (maxCount > kMaxBlocksPerIndex) - maxCount = kMaxBlocksPerIndex; + if (maxCount > kMaxBlocksPerIndex) + maxCount = kMaxBlocksPerIndex; - dierr = fpDiskFS->GetDiskImg()->ReadBlock(block, blkBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpDiskFS->GetDiskImg()->ReadBlock(block, blkBuf); + if (dierr != kDIErrNone) + goto bail; - //WMSG1("LOADING 0x%04x\n", block); - for (i = 0; i < maxCount; i++) { - *list++ = blkBuf[i] | (unsigned short) blkBuf[i+256] << 8; - } + //WMSG1("LOADING 0x%04x\n", block); + for (i = 0; i < maxCount; i++) { + *list++ = blkBuf[i] | (unsigned short) blkBuf[i+256] << 8; + } bail: - return dierr; + return dierr; } /* @@ -4374,65 +4374,65 @@ bail: */ DIError A2FileProDOS::LoadDirectoryBlockList(unsigned short keyBlock, - long eof, long* pBlockCount, unsigned short** pBlockList) + long eof, long* pBlockCount, unsigned short** pBlockList) { - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; - unsigned short* list = nil; - unsigned short* listPtr; - int iterations; - long count; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; + unsigned short* list = nil; + unsigned short* listPtr; + int iterations; + long count; - assert(eof < 1024*1024*16); - count = (eof + kBlkSize -1) / kBlkSize; - if (count == 0) - count = 1; - list = new unsigned short[count+1]; - if (list == nil) { - dierr = kDIErrMalloc; - goto bail; - } + assert(eof < 1024*1024*16); + count = (eof + kBlkSize -1) / kBlkSize; + if (count == 0) + count = 1; + list = new unsigned short[count+1]; + if (list == nil) { + dierr = kDIErrMalloc; + goto bail; + } - /* this should take care of trailing sparse entries */ - memset(list, 0, sizeof(unsigned short) * count); - list[count] = kInvalidBlockNum; // overrun check + /* this should take care of trailing sparse entries */ + memset(list, 0, sizeof(unsigned short) * count); + list[count] = kInvalidBlockNum; // overrun check - iterations = 0; - listPtr = list; + iterations = 0; + listPtr = list; - while (keyBlock && iterations < kMaxCatalogIterations) { - if (keyBlock < 2 || - keyBlock >= fpDiskFS->GetDiskImg()->GetNumBlocks()) - { - WMSG1(" ProDOS ERROR: directory block %u out of range\n", keyBlock); - dierr = kDIErrInvalidBlock; - goto bail; - } + while (keyBlock && iterations < kMaxCatalogIterations) { + if (keyBlock < 2 || + keyBlock >= fpDiskFS->GetDiskImg()->GetNumBlocks()) + { + WMSG1(" ProDOS ERROR: directory block %u out of range\n", keyBlock); + dierr = kDIErrInvalidBlock; + goto bail; + } - *listPtr++ = keyBlock; + *listPtr++ = keyBlock; - dierr = fpDiskFS->GetDiskImg()->ReadBlock(keyBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpDiskFS->GetDiskImg()->ReadBlock(keyBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; - keyBlock = GetShortLE(&blkBuf[0x02]); - iterations++; - } - if (iterations == kMaxCatalogIterations) { - WMSG0(" ProDOS subdir iteration count exceeded\n"); - dierr = kDIErrDirectoryLoop; - goto bail; - } + keyBlock = GetShortLE(&blkBuf[0x02]); + iterations++; + } + if (iterations == kMaxCatalogIterations) { + WMSG0(" ProDOS subdir iteration count exceeded\n"); + dierr = kDIErrDirectoryLoop; + goto bail; + } - assert(list[count] == kInvalidBlockNum); + assert(list[count] == kInvalidBlockNum); - *pBlockCount = count; - *pBlockList = list; + *pBlockCount = count; + *pBlockList = list; bail: - if (dierr != kDIErrNone) - delete list; - return dierr; + if (dierr != kDIErrNone) + delete list; + return dierr; } /* @@ -4441,32 +4441,32 @@ bail: void A2FileProDOS::Dump(void) const { - WMSG2(" ProDOS file '%s' (path='%s')\n", - fDirEntry.fileName, fPathName); - WMSG3(" fileType=0x%02x auxType=0x%04x storage=%d\n", - fDirEntry.fileType, fDirEntry.auxType, fDirEntry.storageType); - WMSG3(" keyPointer=%d blocksUsed=%d eof=%ld\n", - fDirEntry.keyPointer, fDirEntry.blocksUsed, fDirEntry.eof); - WMSG3(" access=0x%02x create=0x%08lx mod=0x%08lx\n", - fDirEntry.access, fDirEntry.createWhen, fDirEntry.modWhen); - WMSG3(" version=%d minVersion=%d headerPtr=%d\n", - fDirEntry.version, fDirEntry.minVersion, fDirEntry.headerPointer); - if (fDirEntry.storageType == kStorageExtended) { - WMSG4(" DATA storage=%d keyBlk=%d blkUsed=%d eof=%ld\n", - fExtData.storageType, fExtData.keyBlock, fExtData.blocksUsed, - fExtData.eof); - WMSG4(" RSRC storage=%d keyBlk=%d blkUsed=%d eof=%ld\n", - fExtRsrc.storageType, fExtRsrc.keyBlock, fExtRsrc.blocksUsed, - fExtRsrc.eof); - } - WMSG2(" * sparseData=%ld sparseRsrc=%ld\n", - (long) fSparseDataEof, (long) fSparseRsrcEof); + WMSG2(" ProDOS file '%s' (path='%s')\n", + fDirEntry.fileName, fPathName); + WMSG3(" fileType=0x%02x auxType=0x%04x storage=%d\n", + fDirEntry.fileType, fDirEntry.auxType, fDirEntry.storageType); + WMSG3(" keyPointer=%d blocksUsed=%d eof=%ld\n", + fDirEntry.keyPointer, fDirEntry.blocksUsed, fDirEntry.eof); + WMSG3(" access=0x%02x create=0x%08lx mod=0x%08lx\n", + fDirEntry.access, fDirEntry.createWhen, fDirEntry.modWhen); + WMSG3(" version=%d minVersion=%d headerPtr=%d\n", + fDirEntry.version, fDirEntry.minVersion, fDirEntry.headerPointer); + if (fDirEntry.storageType == kStorageExtended) { + WMSG4(" DATA storage=%d keyBlk=%d blkUsed=%d eof=%ld\n", + fExtData.storageType, fExtData.keyBlock, fExtData.blocksUsed, + fExtData.eof); + WMSG4(" RSRC storage=%d keyBlk=%d blkUsed=%d eof=%ld\n", + fExtRsrc.storageType, fExtRsrc.keyBlock, fExtRsrc.blocksUsed, + fExtRsrc.eof); + } + WMSG2(" * sparseData=%ld sparseRsrc=%ld\n", + (long) fSparseDataEof, (long) fSparseRsrcEof); } /* * =========================================================================== - * A2FDProDOS + * A2FDProDOS * =========================================================================== */ @@ -4476,93 +4476,93 @@ A2FileProDOS::Dump(void) const DIError A2FDProDOS::Read(void* buf, size_t len, size_t* pActual) { - WMSG3(" ProDOS reading %d bytes from '%s' (offset=%ld)\n", - len, fpFile->GetPathName(), (long) fOffset); - //if (fBlockList == nil) - // return kDIErrNotReady; + WMSG3(" ProDOS reading %d bytes from '%s' (offset=%ld)\n", + len, fpFile->GetPathName(), (long) fOffset); + //if (fBlockList == nil) + // return kDIErrNotReady; - if (fOffset + (long)len > fOpenEOF) { - if (pActual == nil) - return kDIErrDataUnderrun; - len = (long) (fOpenEOF - fOffset); - } - if (pActual != nil) - *pActual = len; + if (fOffset + (long)len > fOpenEOF) { + if (pActual == nil) + return kDIErrDataUnderrun; + len = (long) (fOpenEOF - fOffset); + } + if (pActual != nil) + *pActual = len; // - long incrLen = len; + long incrLen = len; - DIError dierr = kDIErrNone; - unsigned char blkBuf[kBlkSize]; - long blockIndex = (long) (fOffset / kBlkSize); - int bufOffset = (int) (fOffset % kBlkSize); // (& 0x01ff) - size_t thisCount; - long progressCounter = 0; + DIError dierr = kDIErrNone; + unsigned char blkBuf[kBlkSize]; + long blockIndex = (long) (fOffset / kBlkSize); + int bufOffset = (int) (fOffset % kBlkSize); // (& 0x01ff) + size_t thisCount; + long progressCounter = 0; - if (len == 0) { - ///* one block allocated for empty file */ - //SetLastBlock(fBlockList[0], true); - return kDIErrNone; - } - assert(fOpenEOF != 0); + if (len == 0) { + ///* one block allocated for empty file */ + //SetLastBlock(fBlockList[0], true); + return kDIErrNone; + } + assert(fOpenEOF != 0); - assert(blockIndex >= 0 && blockIndex < fBlockCount); + assert(blockIndex >= 0 && blockIndex < fBlockCount); - while (len) { - if (fBlockList[blockIndex] == 0) { - //WMSG1(" ProDOS sparse index %d\n", blockIndex); - memset(blkBuf, 0, sizeof(blkBuf)); - } else { - //WMSG1(" ProDOS non-sparse index %d\n", blockIndex); - dierr = fpFile->GetDiskFS()->GetDiskImg()->ReadBlock(fBlockList[blockIndex], - blkBuf); - if (dierr != kDIErrNone) { - WMSG3(" ProDOS error reading block [%ld]=%d of '%s'\n", - blockIndex, fBlockList[blockIndex], fpFile->GetPathName()); - return dierr; - } - } - thisCount = kBlkSize - bufOffset; - if (thisCount > len) - thisCount = len; + while (len) { + if (fBlockList[blockIndex] == 0) { + //WMSG1(" ProDOS sparse index %d\n", blockIndex); + memset(blkBuf, 0, sizeof(blkBuf)); + } else { + //WMSG1(" ProDOS non-sparse index %d\n", blockIndex); + dierr = fpFile->GetDiskFS()->GetDiskImg()->ReadBlock(fBlockList[blockIndex], + blkBuf); + if (dierr != kDIErrNone) { + WMSG3(" ProDOS error reading block [%ld]=%d of '%s'\n", + blockIndex, fBlockList[blockIndex], fpFile->GetPathName()); + return dierr; + } + } + thisCount = kBlkSize - bufOffset; + if (thisCount > len) + thisCount = len; - memcpy(buf, blkBuf + bufOffset, thisCount); - len -= thisCount; - buf = (char*)buf + thisCount; + memcpy(buf, blkBuf + bufOffset, thisCount); + len -= thisCount; + buf = (char*)buf + thisCount; - bufOffset = 0; - blockIndex++; + bufOffset = 0; + blockIndex++; - progressCounter++; - if (progressCounter > 100 && len) { - progressCounter = 0; - /* - * Show progress within the current read request. This only - * kicks in for large reads, e.g. reformatting the entire file. - * For smaller reads, used when we're extracting w/o reformatting, - * "progressCounter" never gets large enough. - */ - if (!UpdateProgress(fOffset + incrLen - len)) { - dierr = kDIErrCancelled; - return dierr; - } - //::Sleep(100); // DEBUG DEBUG - } - } + progressCounter++; + if (progressCounter > 100 && len) { + progressCounter = 0; + /* + * Show progress within the current read request. This only + * kicks in for large reads, e.g. reformatting the entire file. + * For smaller reads, used when we're extracting w/o reformatting, + * "progressCounter" never gets large enough. + */ + if (!UpdateProgress(fOffset + incrLen - len)) { + dierr = kDIErrCancelled; + return dierr; + } + //::Sleep(100); // DEBUG DEBUG + } + } - fOffset += incrLen; + fOffset += incrLen; - if (!UpdateProgress(fOffset)) - dierr = kDIErrCancelled; + if (!UpdateProgress(fOffset)) + dierr = kDIErrCancelled; - return dierr; + return dierr; } /* * Write data at the current offset. * * For simplicity, we assume that there can only be one of two situations: - * (1) We're writing a directory, which might expand by one block; or - * (2) We're writing all of a brand-new file in one shot. + * (1) We're writing a directory, which might expand by one block; or + * (2) We're writing all of a brand-new file in one shot. * * Modifies fOpenEOF, fOpenBlocksUsed, fStorageType, and sets fModified. * @@ -4575,258 +4575,258 @@ A2FDProDOS::Read(void* buf, size_t len, size_t* pActual) DIError A2FDProDOS::Write(const void* buf, size_t len, size_t* pActual) { - DIError dierr = kDIErrNone; - A2FileProDOS* pFile = (A2FileProDOS*) fpFile; - DiskFSProDOS* pDiskFS = (DiskFSProDOS*) fpFile->GetDiskFS(); - bool allocSparse = (pDiskFS->GetParameter(DiskFS::kParmProDOS_AllocSparse) != 0); - unsigned char blkBuf[kBlkSize]; - unsigned short keyBlock; + DIError dierr = kDIErrNone; + A2FileProDOS* pFile = (A2FileProDOS*) fpFile; + DiskFSProDOS* pDiskFS = (DiskFSProDOS*) fpFile->GetDiskFS(); + bool allocSparse = (pDiskFS->GetParameter(DiskFS::kParmProDOS_AllocSparse) != 0); + unsigned char blkBuf[kBlkSize]; + unsigned short keyBlock; - if (len >= 0x01000000) { // 16MB - assert(false); - return kDIErrInvalidArg; - } + if (len >= 0x01000000) { // 16MB + assert(false); + return kDIErrInvalidArg; + } - /* use separate function for directories */ - if (pFile->fDirEntry.storageType == A2FileProDOS::kStorageDirectory || - pFile->fDirEntry.storageType == A2FileProDOS::kStorageVolumeDirHeader) - { - return WriteDirectory(buf, len, pActual); - } + /* use separate function for directories */ + if (pFile->fDirEntry.storageType == A2FileProDOS::kStorageDirectory || + pFile->fDirEntry.storageType == A2FileProDOS::kStorageVolumeDirHeader) + { + return WriteDirectory(buf, len, pActual); + } - dierr = pDiskFS->LoadVolBitmap(); - if (dierr != kDIErrNone) - goto bail; + dierr = pDiskFS->LoadVolBitmap(); + if (dierr != kDIErrNone) + goto bail; - assert(fOffset == 0); // big simplifying assumption - assert(fOpenEOF == 0); // another one - assert(fOpenBlocksUsed == 1); - assert(buf != nil); + assert(fOffset == 0); // big simplifying assumption + assert(fOpenEOF == 0); // another one + assert(fOpenBlocksUsed == 1); + assert(buf != nil); - /* nothing to do for zero-length write; don't even set fModified */ - if (len == 0) - goto bail; + /* nothing to do for zero-length write; don't even set fModified */ + if (len == 0) + goto bail; - if (pFile->fDirEntry.storageType != A2FileProDOS::kStorageExtended) - keyBlock = pFile->fDirEntry.keyPointer; - else { - if (fOpenRsrcFork) - keyBlock = pFile->fExtRsrc.keyBlock; - else - keyBlock = pFile->fExtData.keyBlock; - } + if (pFile->fDirEntry.storageType != A2FileProDOS::kStorageExtended) + keyBlock = pFile->fDirEntry.keyPointer; + else { + if (fOpenRsrcFork) + keyBlock = pFile->fExtRsrc.keyBlock; + else + keyBlock = pFile->fExtData.keyBlock; + } - /* - * Special-case seedling files. Just write the data into the key block - * and we're done. - */ - if (len <= (size_t)kBlkSize) { - memset(blkBuf, 0, sizeof(blkBuf)); - memcpy(blkBuf, buf, len); - dierr = pDiskFS->GetDiskImg()->WriteBlock(keyBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; + /* + * Special-case seedling files. Just write the data into the key block + * and we're done. + */ + if (len <= (size_t)kBlkSize) { + memset(blkBuf, 0, sizeof(blkBuf)); + memcpy(blkBuf, buf, len); + dierr = pDiskFS->GetDiskImg()->WriteBlock(keyBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; - fOpenEOF = len; - fOpenBlocksUsed = 1; - assert(fOpenStorageType == A2FileProDOS::kStorageSeedling); - fOffset += len; - fModified = true; - goto bail; - } + fOpenEOF = len; + fOpenBlocksUsed = 1; + assert(fOpenStorageType == A2FileProDOS::kStorageSeedling); + fOffset += len; + fModified = true; + goto bail; + } - /* - * Start by allocating space for the block list. The list is always the - * same size, regardless of sparse allocations. - * - * We over-alloc by one so we can have an overrun detection entry. - */ - fBlockCount = (len + kBlkSize-1) / kBlkSize; - assert(fBlockCount > 0); - delete[] fBlockList; - fBlockList = new unsigned short[fBlockCount+1]; - if (fBlockList == nil) { - dierr = kDIErrMalloc; - goto bail; - } - fBlockList[fBlockCount] = A2FileProDOS::kInvalidBlockNum; + /* + * Start by allocating space for the block list. The list is always the + * same size, regardless of sparse allocations. + * + * We over-alloc by one so we can have an overrun detection entry. + */ + fBlockCount = (len + kBlkSize-1) / kBlkSize; + assert(fBlockCount > 0); + delete[] fBlockList; + fBlockList = new unsigned short[fBlockCount+1]; + if (fBlockList == nil) { + dierr = kDIErrMalloc; + goto bail; + } + fBlockList[fBlockCount] = A2FileProDOS::kInvalidBlockNum; - /* - * Write the data blocks to disk, allocating as we go. We have to treat - * the last entry specially because it might not fill an entire block. - */ - const unsigned char* blkPtr; - long blockIdx; - bool allZero; - long progressCounter; + /* + * Write the data blocks to disk, allocating as we go. We have to treat + * the last entry specially because it might not fill an entire block. + */ + const unsigned char* blkPtr; + long blockIdx; + bool allZero; + long progressCounter; - progressCounter = 0; - allZero = true; - blkPtr = (const unsigned char*) buf; - for (blockIdx = 0; blockIdx < fBlockCount; blockIdx++) { - long newBlock; + progressCounter = 0; + allZero = true; + blkPtr = (const unsigned char*) buf; + for (blockIdx = 0; blockIdx < fBlockCount; blockIdx++) { + long newBlock; - if (blockIdx == fBlockCount-1) { - /* for last block, copy partial and move blkPtr */ - int copyLen = len - (blockIdx * kBlkSize); - assert(copyLen > 0 && copyLen <= kBlkSize); - memset(blkBuf, 0, sizeof(blkBuf)); - memcpy(blkBuf, blkPtr, copyLen); - blkPtr = blkBuf; - } + if (blockIdx == fBlockCount-1) { + /* for last block, copy partial and move blkPtr */ + int copyLen = len - (blockIdx * kBlkSize); + assert(copyLen > 0 && copyLen <= kBlkSize); + memset(blkBuf, 0, sizeof(blkBuf)); + memcpy(blkBuf, blkPtr, copyLen); + blkPtr = blkBuf; + } - if (allocSparse && IsEmptyBlock(blkPtr)) - newBlock = 0; - else { - newBlock = pDiskFS->AllocBlock(); - fOpenBlocksUsed++; - allZero = false; - } + if (allocSparse && IsEmptyBlock(blkPtr)) + newBlock = 0; + else { + newBlock = pDiskFS->AllocBlock(); + fOpenBlocksUsed++; + allZero = false; + } - if (newBlock < 0) { - WMSG0(" ProDOS disk full during write!\n"); - dierr = kDIErrDiskFull; - goto bail; - } + if (newBlock < 0) { + WMSG0(" ProDOS disk full during write!\n"); + dierr = kDIErrDiskFull; + goto bail; + } - fBlockList[blockIdx] = (unsigned short) newBlock; + fBlockList[blockIdx] = (unsigned short) newBlock; - if (newBlock != 0) { - dierr = pDiskFS->GetDiskImg()->WriteBlock(newBlock, blkPtr); - if (dierr != kDIErrNone) - goto bail; - } + if (newBlock != 0) { + dierr = pDiskFS->GetDiskImg()->WriteBlock(newBlock, blkPtr); + if (dierr != kDIErrNone) + goto bail; + } - blkPtr += kBlkSize; + blkPtr += kBlkSize; - /* - * Update the progress counter and check to see if the "cancel" button - * has been hit. We don't call UpdateProgress on the last block - * because we could be passing an offset value larger than "len". - * Also, we don't want the progress bar to hit 100% until we've - * actually finished. - * - * We do NOT want to check this after we start writing index blocks. - * If we do, we need to make sure that whatever index blocks the file - * has match up with what we've allocated in the disk block map. - * - * We don't want to save the disk block map if the user cancels here, - * because then the blocks will be marked as "used" even though the - * index blocks for this file haven't been written yet. - * - * It's tricky to get this right, which is why we allocate space - * for the index blocks now -- running out of disk space and - * user cancellation are handled the same way. Once we get to the - * point where we're updating the file structure, we can neither be - * cancelled nor run out of space. (We can still hit a bad block, - * though, which we currently don't handle.) - */ - progressCounter++; // update every N blocks - if (progressCounter > 100 && blockIdx != fBlockCount) { - progressCounter = 0; - if (!UpdateProgress(blockIdx * kBlkSize)) { - dierr = kDIErrCancelled; - goto bail; - } - } - } + /* + * Update the progress counter and check to see if the "cancel" button + * has been hit. We don't call UpdateProgress on the last block + * because we could be passing an offset value larger than "len". + * Also, we don't want the progress bar to hit 100% until we've + * actually finished. + * + * We do NOT want to check this after we start writing index blocks. + * If we do, we need to make sure that whatever index blocks the file + * has match up with what we've allocated in the disk block map. + * + * We don't want to save the disk block map if the user cancels here, + * because then the blocks will be marked as "used" even though the + * index blocks for this file haven't been written yet. + * + * It's tricky to get this right, which is why we allocate space + * for the index blocks now -- running out of disk space and + * user cancellation are handled the same way. Once we get to the + * point where we're updating the file structure, we can neither be + * cancelled nor run out of space. (We can still hit a bad block, + * though, which we currently don't handle.) + */ + progressCounter++; // update every N blocks + if (progressCounter > 100 && blockIdx != fBlockCount) { + progressCounter = 0; + if (!UpdateProgress(blockIdx * kBlkSize)) { + dierr = kDIErrCancelled; + goto bail; + } + } + } - assert(fBlockList[fBlockCount] == A2FileProDOS::kInvalidBlockNum); + assert(fBlockList[fBlockCount] == A2FileProDOS::kInvalidBlockNum); - /* - * Now we have a full block map. Allocate any needed index blocks and - * write them. - * - * If our block map is empty, i.e. the entire file is sparse, then - * there's no need to create a sapling. We just leave the file in - * seedling form. This can only happen for a completely empty file. - */ - if (allZero) { - WMSG0("+++ ProDOS storing large but empty file as seedling\n"); - /* make sure key block is empty */ - memset(blkBuf, 0, sizeof(blkBuf)); - dierr = pDiskFS->GetDiskImg()->WriteBlock(keyBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; - fOpenStorageType = A2FileProDOS::kStorageSeedling; - fBlockList[0] = keyBlock; - } else if (fBlockCount <= 256) { - /* sapling file, write an index block into the key block */ - bool allzero = true; - assert(fBlockCount > 1); - memset(blkBuf, 0, sizeof(blkBuf)); - int i; - for (i = 0; i < fBlockCount; i++) { - if (fBlockList[i] != 0) - allzero = false; - blkBuf[i] = fBlockList[i] & 0xff; - blkBuf[256 + i] = (fBlockList[i] >> 8) & 0xff; - } + /* + * Now we have a full block map. Allocate any needed index blocks and + * write them. + * + * If our block map is empty, i.e. the entire file is sparse, then + * there's no need to create a sapling. We just leave the file in + * seedling form. This can only happen for a completely empty file. + */ + if (allZero) { + WMSG0("+++ ProDOS storing large but empty file as seedling\n"); + /* make sure key block is empty */ + memset(blkBuf, 0, sizeof(blkBuf)); + dierr = pDiskFS->GetDiskImg()->WriteBlock(keyBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; + fOpenStorageType = A2FileProDOS::kStorageSeedling; + fBlockList[0] = keyBlock; + } else if (fBlockCount <= 256) { + /* sapling file, write an index block into the key block */ + bool allzero = true; + assert(fBlockCount > 1); + memset(blkBuf, 0, sizeof(blkBuf)); + int i; + for (i = 0; i < fBlockCount; i++) { + if (fBlockList[i] != 0) + allzero = false; + blkBuf[i] = fBlockList[i] & 0xff; + blkBuf[256 + i] = (fBlockList[i] >> 8) & 0xff; + } - dierr = pDiskFS->GetDiskImg()->WriteBlock(keyBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; - fOpenStorageType = A2FileProDOS::kStorageSapling; - } else { - /* tree file, write two or more indexes and write master into key */ - unsigned char masterBlk[kBlkSize]; - int idx; + dierr = pDiskFS->GetDiskImg()->WriteBlock(keyBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; + fOpenStorageType = A2FileProDOS::kStorageSapling; + } else { + /* tree file, write two or more indexes and write master into key */ + unsigned char masterBlk[kBlkSize]; + int idx; - memset(masterBlk, 0, sizeof(masterBlk)); + memset(masterBlk, 0, sizeof(masterBlk)); - for (idx = 0; idx < fBlockCount; ) { - long newBlock; - int i; + for (idx = 0; idx < fBlockCount; ) { + long newBlock; + int i; - memset(blkBuf, 0, sizeof(blkBuf)); - for (i = 0; i < 256 && idx < fBlockCount; i++, idx++) { - blkBuf[i] = fBlockList[idx] & 0xff; - blkBuf[256+i] = (fBlockList[idx] >> 8) & 0xff; - } + memset(blkBuf, 0, sizeof(blkBuf)); + for (i = 0; i < 256 && idx < fBlockCount; i++, idx++) { + blkBuf[i] = fBlockList[idx] & 0xff; + blkBuf[256+i] = (fBlockList[idx] >> 8) & 0xff; + } - /* allocate a new index block, if needed */ - if (allocSparse && IsEmptyBlock(blkBuf)) - newBlock = 0; - else { - newBlock = pDiskFS->AllocBlock(); - fOpenBlocksUsed++; - } - if (newBlock != 0) { - dierr = pDiskFS->GetDiskImg()->WriteBlock(newBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; - } + /* allocate a new index block, if needed */ + if (allocSparse && IsEmptyBlock(blkBuf)) + newBlock = 0; + else { + newBlock = pDiskFS->AllocBlock(); + fOpenBlocksUsed++; + } + if (newBlock != 0) { + dierr = pDiskFS->GetDiskImg()->WriteBlock(newBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; + } - masterBlk[(idx-1) / 256] = (unsigned char) newBlock; - masterBlk[256 + (idx-1)/256] = (unsigned char) (newBlock >> 8); - } + masterBlk[(idx-1) / 256] = (unsigned char) newBlock; + masterBlk[256 + (idx-1)/256] = (unsigned char) (newBlock >> 8); + } - dierr = pDiskFS->GetDiskImg()->WriteBlock(keyBlock, masterBlk); - if (dierr != kDIErrNone) - goto bail; - fOpenStorageType = A2FileProDOS::kStorageTree; - } + dierr = pDiskFS->GetDiskImg()->WriteBlock(keyBlock, masterBlk); + if (dierr != kDIErrNone) + goto bail; + fOpenStorageType = A2FileProDOS::kStorageTree; + } - fOpenEOF = len; - fOffset += len; - fModified = true; + fOpenEOF = len; + fOffset += len; + fModified = true; bail: - if (dierr == kDIErrNone) - dierr = pDiskFS->SaveVolBitmap(); + if (dierr == kDIErrNone) + dierr = pDiskFS->SaveVolBitmap(); - /* - * We need to check UpdateProgress *after* the volume bitmap has been - * saved. Otherwise we'll have blocks allocated in the file's structure - * but not marked in-use in the map when the "dierr" check above fails. - */ - if (dierr == kDIErrNone) { - if (!UpdateProgress(fOffset)) - dierr = kDIErrCancelled; - } + /* + * We need to check UpdateProgress *after* the volume bitmap has been + * saved. Otherwise we'll have blocks allocated in the file's structure + * but not marked in-use in the map when the "dierr" check above fails. + */ + if (dierr == kDIErrNone) { + if (!UpdateProgress(fOffset)) + dierr = kDIErrCancelled; + } - pDiskFS->FreeVolBitmap(); - return dierr; + pDiskFS->FreeVolBitmap(); + return dierr; } /* @@ -4835,14 +4835,14 @@ bail: bool A2FDProDOS::IsEmptyBlock(const unsigned char* blk) { - int i; + int i; - for (i = 0; i < kBlkSize; i++) { - if (*blk++ != 0) - return false; - } + for (i = 0; i < kBlkSize; i++) { + if (*blk++ != 0) + return false; + } - return true; + return true; } /* @@ -4857,63 +4857,63 @@ A2FDProDOS::IsEmptyBlock(const unsigned char* blk) DIError A2FDProDOS::WriteDirectory(const void* buf, size_t len, size_t* pActual) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - WMSG2("ProDOS writing %d bytes to directory '%s'\n", - len, fpFile->GetPathName()); + WMSG2("ProDOS writing %d bytes to directory '%s'\n", + len, fpFile->GetPathName()); - assert(len >= (size_t)kBlkSize); - assert((len % kBlkSize) == 0); - assert(len == (size_t)fOpenEOF || len == (size_t)fOpenEOF + kBlkSize); + assert(len >= (size_t)kBlkSize); + assert((len % kBlkSize) == 0); + assert(len == (size_t)fOpenEOF || len == (size_t)fOpenEOF + kBlkSize); - if (len > (size_t)fOpenEOF) { - /* - * Extend the block list, remembering that we add an extra item - * on the end to check for overruns. - */ - unsigned short* newBlockList; + if (len > (size_t)fOpenEOF) { + /* + * Extend the block list, remembering that we add an extra item + * on the end to check for overruns. + */ + unsigned short* newBlockList; - fBlockCount++; - newBlockList = new unsigned short[fBlockCount+1]; - memcpy(newBlockList, fBlockList, - sizeof(unsigned short) * fBlockCount); - newBlockList[fBlockCount] = A2FileProDOS::kInvalidBlockNum; + fBlockCount++; + newBlockList = new unsigned short[fBlockCount+1]; + memcpy(newBlockList, fBlockList, + sizeof(unsigned short) * fBlockCount); + newBlockList[fBlockCount] = A2FileProDOS::kInvalidBlockNum; - unsigned char* blkPtr; - blkPtr = (unsigned char*)buf + fOpenEOF - kBlkSize; - assert(blkPtr >= buf); - assert(GetShortLE(&blkPtr[0x02]) != 0); - newBlockList[fBlockCount-1] = GetShortLE(&blkPtr[0x02]); + unsigned char* blkPtr; + blkPtr = (unsigned char*)buf + fOpenEOF - kBlkSize; + assert(blkPtr >= buf); + assert(GetShortLE(&blkPtr[0x02]) != 0); + newBlockList[fBlockCount-1] = GetShortLE(&blkPtr[0x02]); - delete[] fBlockList; - fBlockList = newBlockList; + delete[] fBlockList; + fBlockList = newBlockList; - WMSG0(" ProDOS updated block list for subdir:\n"); - DumpBlockList(); - } + WMSG0(" ProDOS updated block list for subdir:\n"); + DumpBlockList(); + } - /* - * Now just run down the block list writing the directory. - */ - assert(len == (size_t)fBlockCount * kBlkSize); - int idx; - for (idx = 0; idx < fBlockCount; idx++) { - assert(fBlockList[idx] >= kVolHeaderBlock); - dierr = fpFile->GetDiskFS()->GetDiskImg()->WriteBlock(fBlockList[idx], - (unsigned char*)buf + idx * kBlkSize); - if (dierr != kDIErrNone) { - WMSG1(" ProDOS failed writing dir, block=%d\n", fBlockList[idx]); - goto bail; - } - } + /* + * Now just run down the block list writing the directory. + */ + assert(len == (size_t)fBlockCount * kBlkSize); + int idx; + for (idx = 0; idx < fBlockCount; idx++) { + assert(fBlockList[idx] >= kVolHeaderBlock); + dierr = fpFile->GetDiskFS()->GetDiskImg()->WriteBlock(fBlockList[idx], + (unsigned char*)buf + idx * kBlkSize); + if (dierr != kDIErrNone) { + WMSG1(" ProDOS failed writing dir, block=%d\n", fBlockList[idx]); + goto bail; + } + } - fOpenEOF = len; - fOpenBlocksUsed = (unsigned short) fBlockCount; // very simple for subdirs - //fOpenStorageType - fModified = true; + fOpenEOF = len; + fOpenBlocksUsed = (unsigned short) fBlockCount; // very simple for subdirs + //fOpenStorageType + fModified = true; bail: - return dierr; + return dierr; } /* @@ -4922,34 +4922,34 @@ bail: DIError A2FDProDOS::Seek(di_off_t offset, DIWhence whence) { - DIError dierr = kDIErrNone; - switch (whence) { - case kSeekSet: - if (offset < 0 || offset > fOpenEOF) - return kDIErrInvalidArg; - fOffset = offset; - break; - case kSeekEnd: - if (offset > 0 || offset < -fOpenEOF) - return kDIErrInvalidArg; - fOffset = fOpenEOF + offset; - break; - case kSeekCur: - if (offset < -fOffset || - offset >= (fOpenEOF - fOffset)) - { - return kDIErrInvalidArg; - } - fOffset += offset; - break; - default: - assert(false); - return kDIErrInvalidArg; - } + DIError dierr = kDIErrNone; + switch (whence) { + case kSeekSet: + if (offset < 0 || offset > fOpenEOF) + return kDIErrInvalidArg; + fOffset = offset; + break; + case kSeekEnd: + if (offset > 0 || offset < -fOpenEOF) + return kDIErrInvalidArg; + fOffset = fOpenEOF + offset; + break; + case kSeekCur: + if (offset < -fOffset || + offset >= (fOpenEOF - fOffset)) + { + return kDIErrInvalidArg; + } + fOffset += offset; + break; + default: + assert(false); + return kDIErrInvalidArg; + } - assert(fOffset >= 0 && fOffset <= fOpenEOF); + assert(fOffset >= 0 && fOffset <= fOpenEOF); - return dierr; + return dierr; } /* @@ -4958,10 +4958,10 @@ A2FDProDOS::Seek(di_off_t offset, DIWhence whence) di_off_t A2FDProDOS::Tell(void) { - //if (fBlockList == nil) - // return kDIErrNotReady; + //if (fBlockList == nil) + // return kDIErrNotReady; - return fOffset; + return fOffset; } /* @@ -4973,143 +4973,143 @@ A2FDProDOS::Tell(void) DIError A2FDProDOS::Close(void) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - if (fModified) { - A2FileProDOS* pFile = (A2FileProDOS*) fpFile; - unsigned char blkBuf[kBlkSize]; - unsigned char newStorageType = fOpenStorageType; - unsigned short newBlocksUsed = fOpenBlocksUsed; - unsigned long newEOF = (unsigned long) fOpenEOF; - unsigned short combinedBlocksUsed; - unsigned long combinedEOF; + if (fModified) { + A2FileProDOS* pFile = (A2FileProDOS*) fpFile; + unsigned char blkBuf[kBlkSize]; + unsigned char newStorageType = fOpenStorageType; + unsigned short newBlocksUsed = fOpenBlocksUsed; + unsigned long newEOF = (unsigned long) fOpenEOF; + unsigned short combinedBlocksUsed; + unsigned long combinedEOF; - /* - * If this is an extended file, fix the entries in the extended - * key block, and adjust the values to be stored in the directory. - */ - if (pFile->fDirEntry.storageType == A2FileProDOS::kStorageExtended) { - /* these two don't change */ - newStorageType = pFile->fDirEntry.storageType; + /* + * If this is an extended file, fix the entries in the extended + * key block, and adjust the values to be stored in the directory. + */ + if (pFile->fDirEntry.storageType == A2FileProDOS::kStorageExtended) { + /* these two don't change */ + newStorageType = pFile->fDirEntry.storageType; - dierr = fpFile->GetDiskFS()->GetDiskImg()->ReadBlock( - pFile->fDirEntry.keyPointer, blkBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpFile->GetDiskFS()->GetDiskImg()->ReadBlock( + pFile->fDirEntry.keyPointer, blkBuf); + if (dierr != kDIErrNone) + goto bail; - int offset = 0; - if (fOpenRsrcFork) - offset = 256; + int offset = 0; + if (fOpenRsrcFork) + offset = 256; - blkBuf[0x00 + offset] = fOpenStorageType; - // key block doesn't change - PutShortLE(&blkBuf[0x03 + offset], newBlocksUsed); - blkBuf[0x05 + offset] = (unsigned char) newEOF; - blkBuf[0x06 + offset] = (unsigned char) (newEOF >> 8); - blkBuf[0x07 + offset] = (unsigned char) (newEOF >> 16); + blkBuf[0x00 + offset] = fOpenStorageType; + // key block doesn't change + PutShortLE(&blkBuf[0x03 + offset], newBlocksUsed); + blkBuf[0x05 + offset] = (unsigned char) newEOF; + blkBuf[0x06 + offset] = (unsigned char) (newEOF >> 8); + blkBuf[0x07 + offset] = (unsigned char) (newEOF >> 16); - dierr = fpFile->GetDiskFS()->GetDiskImg()->WriteBlock( - pFile->fDirEntry.keyPointer, blkBuf); - if (dierr != kDIErrNone) - goto bail; + dierr = fpFile->GetDiskFS()->GetDiskImg()->WriteBlock( + pFile->fDirEntry.keyPointer, blkBuf); + if (dierr != kDIErrNone) + goto bail; - // file blocks used is sum of data and rsrc block counts +1 for key - combinedBlocksUsed = - GetShortLE(&blkBuf[0x03]) + GetShortLE(&blkBuf[0x103]) +1; - combinedEOF = 512; // for some reason this gets stuffed in - } else { - combinedBlocksUsed = newBlocksUsed; - combinedEOF = newEOF; - } + // file blocks used is sum of data and rsrc block counts +1 for key + combinedBlocksUsed = + GetShortLE(&blkBuf[0x03]) + GetShortLE(&blkBuf[0x103]) +1; + combinedEOF = 512; // for some reason this gets stuffed in + } else { + combinedBlocksUsed = newBlocksUsed; + combinedEOF = newEOF; + } - /* - * Update fields in the file's directory entry. Unless, of course, - * this is the volume directory itself. - */ - if (pFile->fParentDirBlock != 0) { - dierr = fpFile->GetDiskFS()->GetDiskImg()->ReadBlock( - pFile->fParentDirBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; + /* + * Update fields in the file's directory entry. Unless, of course, + * this is the volume directory itself. + */ + if (pFile->fParentDirBlock != 0) { + dierr = fpFile->GetDiskFS()->GetDiskImg()->ReadBlock( + pFile->fParentDirBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; - unsigned char* pParentPtr; - pParentPtr = blkBuf + 0x04 + pFile->fParentDirIdx * kEntryLength; - assert(pParentPtr + kEntryLength < blkBuf + kBlkSize); - if (toupper(pParentPtr[0x01]) != toupper(pFile->fDirEntry.fileName[0])) - { - WMSG0("ProDOS ERROR: parent pointer has wrong entry??\n"); - assert(false); - dierr = kDIErrInternal; - goto bail; - } + unsigned char* pParentPtr; + pParentPtr = blkBuf + 0x04 + pFile->fParentDirIdx * kEntryLength; + assert(pParentPtr + kEntryLength < blkBuf + kBlkSize); + if (toupper(pParentPtr[0x01]) != toupper(pFile->fDirEntry.fileName[0])) + { + WMSG0("ProDOS ERROR: parent pointer has wrong entry??\n"); + assert(false); + dierr = kDIErrInternal; + goto bail; + } - /* update the fields from the open file */ - pParentPtr[0x00] = - (pParentPtr[0x00] & 0x0f) | (newStorageType << 4); - PutShortLE(&pParentPtr[0x13], combinedBlocksUsed); - if (pFile->fDirEntry.storageType != A2FileProDOS::kStorageExtended) - { - PutShortLE(&pParentPtr[0x15], (unsigned short) newEOF); - pParentPtr[0x17] = (unsigned char) (newEOF >> 16); - } - /* don't update the mod date for now */ - //PutLongLE(&pParentPtr[0x21], A2FileProDOS::ConvertProDate(time(nil))); + /* update the fields from the open file */ + pParentPtr[0x00] = + (pParentPtr[0x00] & 0x0f) | (newStorageType << 4); + PutShortLE(&pParentPtr[0x13], combinedBlocksUsed); + if (pFile->fDirEntry.storageType != A2FileProDOS::kStorageExtended) + { + PutShortLE(&pParentPtr[0x15], (unsigned short) newEOF); + pParentPtr[0x17] = (unsigned char) (newEOF >> 16); + } + /* don't update the mod date for now */ + //PutLongLE(&pParentPtr[0x21], A2FileProDOS::ConvertProDate(time(nil))); - dierr = fpFile->GetDiskFS()->GetDiskImg()->WriteBlock( - pFile->fParentDirBlock, blkBuf); - if (dierr != kDIErrNone) - goto bail; - } + dierr = fpFile->GetDiskFS()->GetDiskImg()->WriteBlock( + pFile->fParentDirBlock, blkBuf); + if (dierr != kDIErrNone) + goto bail; + } - /* - * Find the #of sparse blocks. - */ - int sparseCount = 0; - for (int i = 0; i < fBlockCount; i++) { - if (fBlockList[i] == 0) - sparseCount++; - } + /* + * Find the #of sparse blocks. + */ + int sparseCount = 0; + for (int i = 0; i < fBlockCount; i++) { + if (fBlockList[i] == 0) + sparseCount++; + } - /* - * Update our internal copies of stuff. The EOFs have changed, and - * in theory we'd want to update the modification date. In practice - * we're usually shuffling data from one archive to another and want - * to preserve the mod date. (Could be a DiskFS global pref?) - */ - pFile->fDirEntry.storageType = newStorageType; - pFile->fDirEntry.blocksUsed = combinedBlocksUsed; - pFile->fDirEntry.eof = combinedEOF; + /* + * Update our internal copies of stuff. The EOFs have changed, and + * in theory we'd want to update the modification date. In practice + * we're usually shuffling data from one archive to another and want + * to preserve the mod date. (Could be a DiskFS global pref?) + */ + pFile->fDirEntry.storageType = newStorageType; + pFile->fDirEntry.blocksUsed = combinedBlocksUsed; + pFile->fDirEntry.eof = combinedEOF; - if (newStorageType == A2FileProDOS::kStorageExtended) { - if (!fOpenRsrcFork) { - pFile->fExtData.storageType = fOpenStorageType; - pFile->fExtData.blocksUsed = newBlocksUsed; - pFile->fExtData.eof = newEOF; - pFile->fSparseDataEof = (di_off_t) newEOF - (sparseCount * kBlkSize); - if (pFile->fSparseDataEof < 0) - pFile->fSparseDataEof = 0; - } else { - pFile->fExtRsrc.storageType = fOpenStorageType; - pFile->fExtRsrc.blocksUsed = newBlocksUsed; - pFile->fExtRsrc.eof = newEOF; - pFile->fSparseRsrcEof = (di_off_t) newEOF - (sparseCount * kBlkSize); - if (pFile->fSparseRsrcEof < 0) - pFile->fSparseRsrcEof = 0; - } - } else { - pFile->fSparseDataEof = (di_off_t) newEOF - (sparseCount * kBlkSize); - if (pFile->fSparseDataEof < 0) - pFile->fSparseDataEof = 0; - } - // update mod date? - - //WMSG1("File '%s' closed\n", pFile->GetPathName()); - //pFile->Dump(); - } + if (newStorageType == A2FileProDOS::kStorageExtended) { + if (!fOpenRsrcFork) { + pFile->fExtData.storageType = fOpenStorageType; + pFile->fExtData.blocksUsed = newBlocksUsed; + pFile->fExtData.eof = newEOF; + pFile->fSparseDataEof = (di_off_t) newEOF - (sparseCount * kBlkSize); + if (pFile->fSparseDataEof < 0) + pFile->fSparseDataEof = 0; + } else { + pFile->fExtRsrc.storageType = fOpenStorageType; + pFile->fExtRsrc.blocksUsed = newBlocksUsed; + pFile->fExtRsrc.eof = newEOF; + pFile->fSparseRsrcEof = (di_off_t) newEOF - (sparseCount * kBlkSize); + if (pFile->fSparseRsrcEof < 0) + pFile->fSparseRsrcEof = 0; + } + } else { + pFile->fSparseDataEof = (di_off_t) newEOF - (sparseCount * kBlkSize); + if (pFile->fSparseDataEof < 0) + pFile->fSparseDataEof = 0; + } + // update mod date? + + //WMSG1("File '%s' closed\n", pFile->GetPathName()); + //pFile->Dump(); + } bail: - fpFile->CloseDescr(this); - return dierr; + fpFile->CloseDescr(this); + return dierr; } @@ -5119,16 +5119,16 @@ bail: long A2FDProDOS::GetSectorCount(void) const { - //if (fBlockList == nil) - // return kDIErrNotReady; - return fBlockCount * 2; + //if (fBlockList == nil) + // return kDIErrNotReady; + return fBlockCount * 2; } long A2FDProDOS::GetBlockCount(void) const { - //if (fBlockList == nil) - // return kDIErrNotReady; - return fBlockCount; + //if (fBlockList == nil) + // return kDIErrNotReady; + return fBlockCount; } /* @@ -5137,18 +5137,18 @@ A2FDProDOS::GetBlockCount(void) const DIError A2FDProDOS::GetStorage(long sectorIdx, long* pTrack, long* pSector) const { - //if (fBlockList == nil) - // return kDIErrNotReady; - long prodosIdx = sectorIdx / 2; - if (prodosIdx < 0 || prodosIdx >= fBlockCount) - return kDIErrInvalidIndex; - long prodosBlock = fBlockList[prodosIdx]; + //if (fBlockList == nil) + // return kDIErrNotReady; + long prodosIdx = sectorIdx / 2; + if (prodosIdx < 0 || prodosIdx >= fBlockCount) + return kDIErrInvalidIndex; + long prodosBlock = fBlockList[prodosIdx]; - if (prodosBlock == 0) - *pTrack = *pSector = 0; // special-case to avoid returning (0,1) - else - BlockToTrackSector(prodosBlock, (sectorIdx & 0x01) != 0, pTrack, pSector); - return kDIErrNone; + if (prodosBlock == 0) + *pTrack = *pSector = 0; // special-case to avoid returning (0,1) + else + BlockToTrackSector(prodosBlock, (sectorIdx & 0x01) != 0, pTrack, pSector); + return kDIErrNone; } /* * Return the Nth 512-byte block in this file. @@ -5156,15 +5156,15 @@ A2FDProDOS::GetStorage(long sectorIdx, long* pTrack, long* pSector) const DIError A2FDProDOS::GetStorage(long blockIdx, long* pBlock) const { - //if (fBlockList == nil) - // return kDIErrNotReady; - if (blockIdx < 0 || blockIdx >= fBlockCount) - return kDIErrInvalidIndex; - long prodosBlock = fBlockList[blockIdx]; + //if (fBlockList == nil) + // return kDIErrNotReady; + if (blockIdx < 0 || blockIdx >= fBlockCount) + return kDIErrInvalidIndex; + long prodosBlock = fBlockList[blockIdx]; - *pBlock = prodosBlock; - assert(*pBlock < fpFile->GetDiskFS()->GetDiskImg()->GetNumBlocks()); - return kDIErrNone; + *pBlock = prodosBlock; + assert(*pBlock < fpFile->GetDiskFS()->GetDiskImg()->GetNumBlocks()); + return kDIErrNone; } /* @@ -5174,12 +5174,12 @@ A2FDProDOS::GetStorage(long blockIdx, long* pBlock) const void A2FDProDOS::DumpBlockList(void) const { - long ll; + long ll; - WMSG1(" ProDOS file block list (count=%ld)\n", fBlockCount); - for (ll = 0; ll <= fBlockCount; ll++) { - if (fBlockList[ll] != 0) { - WMSG2(" %5ld: 0x%04x\n", ll, fBlockList[ll]); - } - } + WMSG1(" ProDOS file block list (count=%ld)\n", fBlockCount); + for (ll = 0; ll <= fBlockCount; ll++) { + if (fBlockList[ll] != 0) { + WMSG2(" %5ld: 0x%04x\n", ll, fBlockList[ll]); + } + } } diff --git a/diskimg/RDOS.cpp b/diskimg/RDOS.cpp index b9e8afb..43f7032 100644 --- a/diskimg/RDOS.cpp +++ b/diskimg/RDOS.cpp @@ -12,142 +12,142 @@ /* * =========================================================================== - * DiskFSRDOS + * DiskFSRDOS * =========================================================================== */ const int kSctSize = 256; const int kCatTrack = 1; -const int kNumCatSectors = 11; // 0 through 10 +const int kNumCatSectors = 11; // 0 through 10 const int kDirectoryEntryLen = 32; -const int kNumDirEntryPerSect = (256 / kDirectoryEntryLen); // 8 +const int kNumDirEntryPerSect = (256 / kDirectoryEntryLen); // 8 /* * See if this looks like a RDOS volume. * * There are three variants: - * RDOS32 (e.g. ComputerAmbush.nib): - * 13-sector disk - * sector (1,0) starts with "RDOS 2" - * sector (1,12) has catalog code, CHAIN in (1,11) - * uses "physical" ordering - * NOTE: track 0 may be unreadable with RDOS 3.2 NibbleDescr - * RDOS33 (e.g. disk #199): - * 16-sector disk - * sector (1,0) starts with "RDOS 3" - * sector (1,12) has catalog code - * uses "ProDOS" ordering - * RDOS3 (e.g. disk #108): - * 16-sector disk, but only 13 sectors of each track are used - * sector (1,0) starts with "RDOS 2" - * sector (0,1) has catalog code - * uses "physical" orering + * RDOS32 (e.g. ComputerAmbush.nib): + * 13-sector disk + * sector (1,0) starts with "RDOS 2" + * sector (1,12) has catalog code, CHAIN in (1,11) + * uses "physical" ordering + * NOTE: track 0 may be unreadable with RDOS 3.2 NibbleDescr + * RDOS33 (e.g. disk #199): + * 16-sector disk + * sector (1,0) starts with "RDOS 3" + * sector (1,12) has catalog code + * uses "ProDOS" ordering + * RDOS3 (e.g. disk #108): + * 16-sector disk, but only 13 sectors of each track are used + * sector (1,0) starts with "RDOS 2" + * sector (0,1) has catalog code + * uses "physical" orering * * In all cases: - * catalog found on (1,0) through (1,10) + * catalog found on (1,0) through (1,10) * * The initial value of "pFormatFound" is ignored, because we can reliably * detect which variant we're looking at. */ static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder, - DiskImg::FSFormat* pFormatFound) + DiskImg::FSFormat* pFormatFound) { - DIError dierr = kDIErrNone; - unsigned char sctBuf[kSctSize]; + DIError dierr = kDIErrNone; + unsigned char sctBuf[kSctSize]; - if (pImg->GetNumSectPerTrack() == 13) { - /* must be a nibble image; check it for RDOS 3.2 */ - dierr = pImg->ReadTrackSectorSwapped(kCatTrack, 0, sctBuf, - imageOrder, DiskImg::kSectorOrderPhysical); - if (dierr != kDIErrNone) - goto bail; - } else if (pImg->GetNumSectPerTrack() == 16) { - /* could be RDOS3 or RDOS 3.3 */ - dierr = pImg->ReadTrackSectorSwapped(kCatTrack, 0, sctBuf, - imageOrder, DiskImg::kSectorOrderPhysical); - if (dierr != kDIErrNone) - goto bail; - } else { - WMSG0(" RDOS neither 13 nor 16 sector, bailing\n"); - goto bail; - } + if (pImg->GetNumSectPerTrack() == 13) { + /* must be a nibble image; check it for RDOS 3.2 */ + dierr = pImg->ReadTrackSectorSwapped(kCatTrack, 0, sctBuf, + imageOrder, DiskImg::kSectorOrderPhysical); + if (dierr != kDIErrNone) + goto bail; + } else if (pImg->GetNumSectPerTrack() == 16) { + /* could be RDOS3 or RDOS 3.3 */ + dierr = pImg->ReadTrackSectorSwapped(kCatTrack, 0, sctBuf, + imageOrder, DiskImg::kSectorOrderPhysical); + if (dierr != kDIErrNone) + goto bail; + } else { + WMSG0(" RDOS neither 13 nor 16 sector, bailing\n"); + goto bail; + } - /* check for RDOS string and correct #of blocks */ - if (!( sctBuf[0] == 'R'+0x80 && - sctBuf[1] == 'D'+0x80 && - sctBuf[2] == 'O'+0x80 && - sctBuf[3] == 'S'+0x80 && - sctBuf[4] == ' '+0x80) || - !(sctBuf[25] == 26 || sctBuf[25] == 32)) - { - WMSG1(" RDOS no signature found on (%d,0)\n", kCatTrack); - dierr = kDIErrGeneric; - goto bail; - } + /* check for RDOS string and correct #of blocks */ + if (!( sctBuf[0] == 'R'+0x80 && + sctBuf[1] == 'D'+0x80 && + sctBuf[2] == 'O'+0x80 && + sctBuf[3] == 'S'+0x80 && + sctBuf[4] == ' '+0x80) || + !(sctBuf[25] == 26 || sctBuf[25] == 32)) + { + WMSG1(" RDOS no signature found on (%d,0)\n", kCatTrack); + dierr = kDIErrGeneric; + goto bail; + } - /* - * Guess at the format based on the first catalog entry, which usually - * begins "RDOS 2.0", "RDOS 2.1", or "RDOS 3.3". - */ - if (pImg->GetNumSectPerTrack() == 13) { - *pFormatFound = DiskImg::kFormatRDOS32; - } else { - if (sctBuf[5] == '2'+0x80) - *pFormatFound = DiskImg::kFormatRDOS3; - else - *pFormatFound = DiskImg::kFormatRDOS33; - } + /* + * Guess at the format based on the first catalog entry, which usually + * begins "RDOS 2.0", "RDOS 2.1", or "RDOS 3.3". + */ + if (pImg->GetNumSectPerTrack() == 13) { + *pFormatFound = DiskImg::kFormatRDOS32; + } else { + if (sctBuf[5] == '2'+0x80) + *pFormatFound = DiskImg::kFormatRDOS3; + else + *pFormatFound = DiskImg::kFormatRDOS33; + } - /* - * The above came from sector 0, which doesn't help us figure out the - * sector ordering. Look for the catalog code. - */ - { - int track, sector, offset; - unsigned char orMask; - static const char* kCompare = ""; - DiskImg::SectorOrder order; + /* + * The above came from sector 0, which doesn't help us figure out the + * sector ordering. Look for the catalog code. + */ + { + int track, sector, offset; + unsigned char orMask; + static const char* kCompare = ""; + DiskImg::SectorOrder order; - if (*pFormatFound == DiskImg::kFormatRDOS32 || - *pFormatFound == DiskImg::kFormatRDOS3) - { - track = 1; - sector = 12; - offset = 0xa2; - orMask = 0x80; - order = DiskImg::kSectorOrderPhysical; - } else { - track = 0; - sector = 1; - offset = 0x98; - orMask = 0; - order = DiskImg::kSectorOrderProDOS; - } + if (*pFormatFound == DiskImg::kFormatRDOS32 || + *pFormatFound == DiskImg::kFormatRDOS3) + { + track = 1; + sector = 12; + offset = 0xa2; + orMask = 0x80; + order = DiskImg::kSectorOrderPhysical; + } else { + track = 0; + sector = 1; + offset = 0x98; + orMask = 0; + order = DiskImg::kSectorOrderProDOS; + } - dierr = pImg->ReadTrackSectorSwapped(track, sector, sctBuf, - imageOrder, order); - if (dierr != kDIErrNone) - goto bail; + dierr = pImg->ReadTrackSectorSwapped(track, sector, sctBuf, + imageOrder, order); + if (dierr != kDIErrNone) + goto bail; int i; - for (i = strlen(kCompare)-1; i >= 0; i--) { - if (sctBuf[offset+i] != ((unsigned char)kCompare[i] | orMask)) - break; - } - if (i >= 0) { - dierr = kDIErrGeneric; - goto bail; - } + for (i = strlen(kCompare)-1; i >= 0; i--) { + if (sctBuf[offset+i] != ((unsigned char)kCompare[i] | orMask)) + break; + } + if (i >= 0) { + dierr = kDIErrGeneric; + goto bail; + } - WMSG2(" RDOS found '%s' signature (order=%d)\n", kCompare, imageOrder); - } + WMSG2(" RDOS found '%s' signature (order=%d)\n", kCompare, imageOrder); + } - dierr = kDIErrNone; + dierr = kDIErrNone; bail: - return dierr; + return dierr; } /* @@ -155,35 +155,35 @@ bail: */ /*static*/ DIError DiskFSRDOS::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, - DiskImg::FSFormat* pFormat, FSLeniency leniency) + DiskImg::FSFormat* pFormat, FSLeniency leniency) { - if (!pImg->GetHasSectors()) { - WMSG0(" RDOS - image doesn't have sectors, not trying\n"); - return kDIErrFilesystemNotFound; - } - if (pImg->GetNumTracks() != 35) { - WMSG0(" RDOS - not a 35-track disk, not trying\n"); - return kDIErrFilesystemNotFound; - } - DiskImg::FSFormat formatFound; + if (!pImg->GetHasSectors()) { + WMSG0(" RDOS - image doesn't have sectors, not trying\n"); + return kDIErrFilesystemNotFound; + } + if (pImg->GetNumTracks() != 35) { + WMSG0(" RDOS - not a 35-track disk, not trying\n"); + return kDIErrFilesystemNotFound; + } + DiskImg::FSFormat formatFound; - DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; - - DiskImg::GetSectorOrderArray(ordering, *pOrder); + DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; + + DiskImg::GetSectorOrderArray(ordering, *pOrder); - for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { - if (ordering[i] == DiskImg::kSectorOrderUnknown) - continue; - if (TestImage(pImg, ordering[i], &formatFound) == kDIErrNone) { - *pFormat = formatFound; - *pOrder = ordering[i]; - //*pFormat = DiskImg::kFormatXXX; - return kDIErrNone; - } - } + for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { + if (ordering[i] == DiskImg::kSectorOrderUnknown) + continue; + if (TestImage(pImg, ordering[i], &formatFound) == kDIErrNone) { + *pFormat = formatFound; + *pOrder = ordering[i]; + //*pFormat = DiskImg::kFormatXXX; + return kDIErrNone; + } + } - WMSG0(" RDOS didn't find valid FS\n"); - return kDIErrFilesystemNotFound; + WMSG0(" RDOS didn't find valid FS\n"); + return kDIErrFilesystemNotFound; } #if 0 @@ -194,18 +194,18 @@ DiskFSRDOS::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DiskFSRDOS::TestFS33(DiskImg* pImg, DiskImg::SectorOrder* pOrder, FSLeniency leniency) { - DIError dierr; - DiskImg::FSFormat formatFound = DiskImg::kFormatUnknown; + DIError dierr; + DiskImg::FSFormat formatFound = DiskImg::kFormatUnknown; - dierr = TestCommon(pImg, pOrder, leniency, &formatFound); - if (dierr != kDIErrNone) - return dierr; - if (formatFound != DiskImg::kFormatRDOS33) { - WMSG0(" RDOS found RDOS but wrong type\n"); - return kDIErrFilesystemNotFound; - } + dierr = TestCommon(pImg, pOrder, leniency, &formatFound); + if (dierr != kDIErrNone) + return dierr; + if (formatFound != DiskImg::kFormatRDOS33) { + WMSG0(" RDOS found RDOS but wrong type\n"); + return kDIErrFilesystemNotFound; + } - return kDIErrNone; + return kDIErrNone; } /* @@ -215,18 +215,18 @@ DiskFSRDOS::TestFS33(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DiskFSRDOS::TestFS32(DiskImg* pImg, DiskImg::SectorOrder* pOrder, FSLeniency leniency) { - DIError dierr; - DiskImg::FSFormat formatFound = DiskImg::kFormatUnknown; + DIError dierr; + DiskImg::FSFormat formatFound = DiskImg::kFormatUnknown; - dierr = TestCommon(pImg, pOrder, leniency, &formatFound); - if (dierr != kDIErrNone) - return dierr; - if (formatFound != DiskImg::kFormatRDOS32) { - WMSG0(" RDOS found RDOS but wrong type\n"); - return kDIErrFilesystemNotFound; - } + dierr = TestCommon(pImg, pOrder, leniency, &formatFound); + if (dierr != kDIErrNone) + return dierr; + if (formatFound != DiskImg::kFormatRDOS32) { + WMSG0(" RDOS found RDOS but wrong type\n"); + return kDIErrFilesystemNotFound; + } - return kDIErrNone; + return kDIErrNone; } /* @@ -236,18 +236,18 @@ DiskFSRDOS::TestFS32(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DiskFSRDOS::TestFS3(DiskImg* pImg, DiskImg::SectorOrder* pOrder, FSLeniency leniency) { - DIError dierr; - DiskImg::FSFormat formatFound = DiskImg::kFormatUnknown; + DIError dierr; + DiskImg::FSFormat formatFound = DiskImg::kFormatUnknown; - dierr = TestCommon(pImg, pOrder, leniency, &formatFound); - if (dierr != kDIErrNone) - return dierr; - if (formatFound != DiskImg::kFormatRDOS3) { - WMSG0(" RDOS found RDOS but wrong type\n"); - return kDIErrFilesystemNotFound; - } + dierr = TestCommon(pImg, pOrder, leniency, &formatFound); + if (dierr != kDIErrNone) + return dierr; + if (formatFound != DiskImg::kFormatRDOS3) { + WMSG0(" RDOS found RDOS but wrong type\n"); + return kDIErrFilesystemNotFound; + } - return kDIErrNone; + return kDIErrNone; } #endif @@ -262,50 +262,50 @@ DiskFSRDOS::TestFS3(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DIError DiskFSRDOS::Initialize(void) { - DIError dierr = kDIErrNone; - const char* volStr; + DIError dierr = kDIErrNone; + const char* volStr; - switch (GetDiskImg()->GetFSFormat()) { - case DiskImg::kFormatRDOS33: - volStr = "RDOS 3.3"; - fOurSectPerTrack = 16; - break; - case DiskImg::kFormatRDOS32: - volStr = "RDOS 3.2"; - fOurSectPerTrack = 13; - break; - case DiskImg::kFormatRDOS3: - volStr = "RDOS 3"; - fOurSectPerTrack = 13; - break; - default: - assert(false); - return kDIErrInternal; - } - assert(strlen(volStr) < sizeof(fVolumeName)); - strcpy(fVolumeName, volStr); + switch (GetDiskImg()->GetFSFormat()) { + case DiskImg::kFormatRDOS33: + volStr = "RDOS 3.3"; + fOurSectPerTrack = 16; + break; + case DiskImg::kFormatRDOS32: + volStr = "RDOS 3.2"; + fOurSectPerTrack = 13; + break; + case DiskImg::kFormatRDOS3: + volStr = "RDOS 3"; + fOurSectPerTrack = 13; + break; + default: + assert(false); + return kDIErrInternal; + } + assert(strlen(volStr) < sizeof(fVolumeName)); + strcpy(fVolumeName, volStr); - dierr = ReadCatalog(); - if (dierr != kDIErrNone) - goto bail; + dierr = ReadCatalog(); + if (dierr != kDIErrNone) + goto bail; - fVolumeUsage.Create(fpImg->GetNumTracks(), fOurSectPerTrack); - dierr = ScanFileUsage(); - if (dierr != kDIErrNone) { - /* this might not be fatal; just means that *some* files are bad */ - goto bail; - } - fVolumeUsage.Dump(); + fVolumeUsage.Create(fpImg->GetNumTracks(), fOurSectPerTrack); + dierr = ScanFileUsage(); + if (dierr != kDIErrNone) { + /* this might not be fatal; just means that *some* files are bad */ + goto bail; + } + fVolumeUsage.Dump(); - //A2File* pFile; - //pFile = GetNextFile(nil); - //while (pFile != nil) { - // pFile->Dump(); - // pFile = GetNextFile(pFile); - //} + //A2File* pFile; + //pFile = GetNextFile(nil); + //while (pFile != nil) { + // pFile->Dump(); + // pFile = GetNextFile(pFile); + //} bail: - return dierr; + return dierr; } @@ -317,73 +317,73 @@ bail: DIError DiskFSRDOS::ReadCatalog(void) { - DIError dierr = kDIErrNone; - unsigned char* dir = nil; - unsigned char* dirPtr; - int track, sector; - - dir = new unsigned char[kSctSize * kNumCatSectors]; - if (dir == nil) { - dierr = kDIErrMalloc; - goto bail; - } + DIError dierr = kDIErrNone; + unsigned char* dir = nil; + unsigned char* dirPtr; + int track, sector; + + dir = new unsigned char[kSctSize * kNumCatSectors]; + if (dir == nil) { + dierr = kDIErrMalloc; + goto bail; + } - track = kCatTrack; - dirPtr = dir; - for (sector = 0; sector < kNumCatSectors; sector++) { - dierr = fpImg->ReadTrackSector(track, sector, dirPtr); - if (dierr != kDIErrNone) - goto bail; + track = kCatTrack; + dirPtr = dir; + for (sector = 0; sector < kNumCatSectors; sector++) { + dierr = fpImg->ReadTrackSector(track, sector, dirPtr); + if (dierr != kDIErrNone) + goto bail; - dirPtr += kSctSize; - } + dirPtr += kSctSize; + } - int i; - A2FileRDOS* pFile; - dirPtr = dir; - for (i = 0; i < kNumCatSectors * kNumDirEntryPerSect; - i++, dirPtr += kDirectoryEntryLen) - { - if (dirPtr[0] == 0x80 || dirPtr[24] == 0xa0) // deleted file - continue; - if (dirPtr[24] == 0x00) // unused entry; must be at end of catalog - break; + int i; + A2FileRDOS* pFile; + dirPtr = dir; + for (i = 0; i < kNumCatSectors * kNumDirEntryPerSect; + i++, dirPtr += kDirectoryEntryLen) + { + if (dirPtr[0] == 0x80 || dirPtr[24] == 0xa0) // deleted file + continue; + if (dirPtr[24] == 0x00) // unused entry; must be at end of catalog + break; - pFile = new A2FileRDOS(this); + pFile = new A2FileRDOS(this); - memcpy(pFile->fFileName, dirPtr, A2FileRDOS::kMaxFileName); - pFile->fFileName[A2FileRDOS::kMaxFileName] = '\0'; - pFile->FixFilename(); + memcpy(pFile->fFileName, dirPtr, A2FileRDOS::kMaxFileName); + pFile->fFileName[A2FileRDOS::kMaxFileName] = '\0'; + pFile->FixFilename(); - switch (dirPtr[24]) { - case 'A'+0x80: pFile->fFileType = A2FileRDOS::kTypeApplesoft; break; - case 'B'+0x80: pFile->fFileType = A2FileRDOS::kTypeBinary; break; - case 'T'+0x80: pFile->fFileType = A2FileRDOS::kTypeText; break; - // 0x00 is end of catalog, ' '+0x80 is deleted file, both handled above - default: pFile->fFileType = A2FileRDOS::kTypeUnknown; break; - } - pFile->fNumSectors = dirPtr[25]; - pFile->fLoadAddr = GetShortLE(&dirPtr[26]); - pFile->fLength = GetShortLE(&dirPtr[28]); - pFile->fStartSector = GetShortLE(&dirPtr[30]); + switch (dirPtr[24]) { + case 'A'+0x80: pFile->fFileType = A2FileRDOS::kTypeApplesoft; break; + case 'B'+0x80: pFile->fFileType = A2FileRDOS::kTypeBinary; break; + case 'T'+0x80: pFile->fFileType = A2FileRDOS::kTypeText; break; + // 0x00 is end of catalog, ' '+0x80 is deleted file, both handled above + default: pFile->fFileType = A2FileRDOS::kTypeUnknown; break; + } + pFile->fNumSectors = dirPtr[25]; + pFile->fLoadAddr = GetShortLE(&dirPtr[26]); + pFile->fLength = GetShortLE(&dirPtr[28]); + pFile->fStartSector = GetShortLE(&dirPtr[30]); - if (pFile->fStartSector + pFile->fNumSectors > - fpImg->GetNumTracks() * fOurSectPerTrack) - { - WMSG4(" RDOS invalid start/count (%d + %d) (max %ld) '%s'\n", - pFile->fStartSector, pFile->fNumSectors, fpImg->GetNumBlocks(), - pFile->fFileName); - pFile->fStartSector = pFile->fNumSectors = 0; - pFile->fLength = 0; - pFile->SetQuality(A2File::kQualityDamaged); - } + if (pFile->fStartSector + pFile->fNumSectors > + fpImg->GetNumTracks() * fOurSectPerTrack) + { + WMSG4(" RDOS invalid start/count (%d + %d) (max %ld) '%s'\n", + pFile->fStartSector, pFile->fNumSectors, fpImg->GetNumBlocks(), + pFile->fFileName); + pFile->fStartSector = pFile->fNumSectors = 0; + pFile->fLength = 0; + pFile->SetQuality(A2File::kQualityDamaged); + } - AddFileToList(pFile); - } + AddFileToList(pFile); + } bail: - delete[] dir; - return dierr; + delete[] dir; + return dierr; } @@ -394,26 +394,26 @@ bail: DIError DiskFSRDOS::ScanFileUsage(void) { - int track, sector, block, count; + int track, sector, block, count; - A2FileRDOS* pFile; - pFile = (A2FileRDOS*) GetNextFile(nil); - while (pFile != nil) { - block = pFile->fStartSector; - count = pFile->fNumSectors; - while (count--) { - track = block / fOurSectPerTrack; - sector = block % fOurSectPerTrack; + A2FileRDOS* pFile; + pFile = (A2FileRDOS*) GetNextFile(nil); + while (pFile != nil) { + block = pFile->fStartSector; + count = pFile->fNumSectors; + while (count--) { + track = block / fOurSectPerTrack; + sector = block % fOurSectPerTrack; - SetSectorUsage(track, sector, VolumeUsage::kChunkPurposeUserData); + SetSectorUsage(track, sector, VolumeUsage::kChunkPurposeUserData); - block++; - } + block++; + } - pFile = (A2FileRDOS*) GetNextFile(pFile); - } + pFile = (A2FileRDOS*) GetNextFile(pFile); + } - return kDIErrNone; + return kDIErrNone; } /* @@ -421,26 +421,26 @@ DiskFSRDOS::ScanFileUsage(void) */ void DiskFSRDOS::SetSectorUsage(long track, long sector, - VolumeUsage::ChunkPurpose purpose) + VolumeUsage::ChunkPurpose purpose) { - VolumeUsage::ChunkState cstate; + VolumeUsage::ChunkState cstate; - fVolumeUsage.GetChunkState(track, sector, &cstate); - if (cstate.isUsed) { - cstate.purpose = VolumeUsage::kChunkPurposeConflict; - WMSG2(" RDOS conflicting uses for sct=(%ld,%ld)\n", track, sector); - } else { - cstate.isUsed = true; - cstate.isMarkedUsed = true; - cstate.purpose = purpose; - } - fVolumeUsage.SetChunkState(track, sector, &cstate); + fVolumeUsage.GetChunkState(track, sector, &cstate); + if (cstate.isUsed) { + cstate.purpose = VolumeUsage::kChunkPurposeConflict; + WMSG2(" RDOS conflicting uses for sct=(%ld,%ld)\n", track, sector); + } else { + cstate.isUsed = true; + cstate.isMarkedUsed = true; + cstate.purpose = purpose; + } + fVolumeUsage.SetChunkState(track, sector, &cstate); } /* * =========================================================================== - * A2FileRDOS + * A2FileRDOS * =========================================================================== */ @@ -450,17 +450,17 @@ DiskFSRDOS::SetSectorUsage(long track, long sector, long A2FileRDOS::GetFileType(void) const { - long retval; + long retval; - switch (fFileType) { - case kTypeText: retval = 0x04; break; // TXT - case kTypeApplesoft: retval = 0xfc; break; // BAS - case kTypeBinary: retval = 0x06; break; // BIN - case kTypeUnknown: - default: retval = 0x00; break; // NON - } + switch (fFileType) { + case kTypeText: retval = 0x04; break; // TXT + case kTypeApplesoft: retval = 0xfc; break; // BAS + case kTypeBinary: retval = 0x06; break; // BIN + case kTypeUnknown: + default: retval = 0x00; break; // NON + } - return retval; + return retval; } @@ -470,9 +470,9 @@ A2FileRDOS::GetFileType(void) const void A2FileRDOS::Dump(void) const { - WMSG2("A2FileRDOS '%s' (type=%d)\n", fFileName, fFileType); - WMSG4(" start=%d num=%d len=%d addr=0x%04x\n", - fStartSector, fNumSectors, fLength, fLoadAddr); + WMSG2("A2FileRDOS '%s' (type=%d)\n", fFileName, fFileType); + WMSG4(" start=%d num=%d len=%d addr=0x%04x\n", + fStartSector, fNumSectors, fLength, fLoadAddr); } /* @@ -487,8 +487,8 @@ A2FileRDOS::Dump(void) const void A2FileRDOS::FixFilename(void) { - DiskFSDOS33::LowerASCII((unsigned char*)fFileName, kMaxFileName); - TrimTrailingSpaces(fFileName); + DiskFSDOS33::LowerASCII((unsigned char*)fFileName, kMaxFileName); + TrimTrailingSpaces(fFileName); } /* @@ -499,16 +499,16 @@ A2FileRDOS::FixFilename(void) void A2FileRDOS::TrimTrailingSpaces(char* filename) { - char* lastspc = filename + strlen(filename); + char* lastspc = filename + strlen(filename); - assert(*lastspc == '\0'); + assert(*lastspc == '\0'); - while (--lastspc) { - if (*lastspc != ' ') - break; - } + while (--lastspc) { + if (*lastspc != ' ') + break; + } - *(lastspc+1) = '\0'; + *(lastspc+1) = '\0'; } @@ -517,30 +517,30 @@ A2FileRDOS::TrimTrailingSpaces(char* filename) */ DIError A2FileRDOS::Open(A2FileDescr** ppOpenFile, bool readOnly, - bool rsrcFork /*=false*/) + bool rsrcFork /*=false*/) { - if (fpOpenFile != nil) - return kDIErrAlreadyOpen; - if (rsrcFork) - return kDIErrForkNotFound; - assert(readOnly == true); + if (fpOpenFile != nil) + return kDIErrAlreadyOpen; + if (rsrcFork) + return kDIErrForkNotFound; + assert(readOnly == true); - A2FDRDOS* pOpenFile = new A2FDRDOS(this); + A2FDRDOS* pOpenFile = new A2FDRDOS(this); - pOpenFile->fOffset = 0; - //fOpen = true; + pOpenFile->fOffset = 0; + //fOpen = true; - fpOpenFile = pOpenFile; - *ppOpenFile = pOpenFile; - pOpenFile = nil; + fpOpenFile = pOpenFile; + *ppOpenFile = pOpenFile; + pOpenFile = nil; - return kDIErrNone; + return kDIErrNone; } /* * =========================================================================== - * A2FDRDOS + * A2FDRDOS * =========================================================================== */ @@ -550,62 +550,62 @@ A2FileRDOS::Open(A2FileDescr** ppOpenFile, bool readOnly, DIError A2FDRDOS::Read(void* buf, size_t len, size_t* pActual) { - WMSG3(" RDOS reading %d bytes from '%s' (offset=%ld)\n", - len, fpFile->GetPathName(), (long) fOffset); - //if (!fOpen) - // return kDIErrNotReady; + WMSG3(" RDOS reading %d bytes from '%s' (offset=%ld)\n", + len, fpFile->GetPathName(), (long) fOffset); + //if (!fOpen) + // return kDIErrNotReady; - A2FileRDOS* pFile = (A2FileRDOS*) fpFile; + A2FileRDOS* pFile = (A2FileRDOS*) fpFile; - /* don't allow them to read past the end of the file */ - if (fOffset + (long)len > pFile->fLength) { - if (pActual == nil) - return kDIErrDataUnderrun; - len = (size_t) (pFile->fLength - fOffset); - } - if (pActual != nil) - *pActual = len; - long incrLen = len; + /* don't allow them to read past the end of the file */ + if (fOffset + (long)len > pFile->fLength) { + if (pActual == nil) + return kDIErrDataUnderrun; + len = (size_t) (pFile->fLength - fOffset); + } + if (pActual != nil) + *pActual = len; + long incrLen = len; - DIError dierr = kDIErrNone; - unsigned char sctBuf[kSctSize]; - long block = pFile->fStartSector + (long) (fOffset / kSctSize); - int bufOffset = (int) (fOffset % kSctSize); // (& 0xff) - int ourSectPerTrack = GetOurSectPerTrack(); - size_t thisCount; + DIError dierr = kDIErrNone; + unsigned char sctBuf[kSctSize]; + long block = pFile->fStartSector + (long) (fOffset / kSctSize); + int bufOffset = (int) (fOffset % kSctSize); // (& 0xff) + int ourSectPerTrack = GetOurSectPerTrack(); + size_t thisCount; - if (len == 0) { - ///* one block allocated for empty file */ - //SetLastBlock(block, true); - return kDIErrNone; - } - assert(pFile->fLength != 0); + if (len == 0) { + ///* one block allocated for empty file */ + //SetLastBlock(block, true); + return kDIErrNone; + } + assert(pFile->fLength != 0); - while (len) { - assert(block >= pFile->fStartSector && - block < pFile->fStartSector + pFile->fNumSectors); + while (len) { + assert(block >= pFile->fStartSector && + block < pFile->fStartSector + pFile->fNumSectors); - dierr = pFile->GetDiskFS()->GetDiskImg()->ReadTrackSector(block / ourSectPerTrack, - block % ourSectPerTrack, sctBuf); - if (dierr != kDIErrNone) { - WMSG1(" RDOS error reading file '%s'\n", pFile->fFileName); - return dierr; - } - thisCount = kSctSize - bufOffset; - if (thisCount > len) - thisCount = len; + dierr = pFile->GetDiskFS()->GetDiskImg()->ReadTrackSector(block / ourSectPerTrack, + block % ourSectPerTrack, sctBuf); + if (dierr != kDIErrNone) { + WMSG1(" RDOS error reading file '%s'\n", pFile->fFileName); + return dierr; + } + thisCount = kSctSize - bufOffset; + if (thisCount > len) + thisCount = len; - memcpy(buf, sctBuf + bufOffset, thisCount); - len -= thisCount; - buf = (char*)buf + thisCount; + memcpy(buf, sctBuf + bufOffset, thisCount); + len -= thisCount; + buf = (char*)buf + thisCount; - bufOffset = 0; - block++; - } + bufOffset = 0; + block++; + } - fOffset += incrLen; + fOffset += incrLen; - return dierr; + return dierr; } /* @@ -614,9 +614,9 @@ A2FDRDOS::Read(void* buf, size_t len, size_t* pActual) DIError A2FDRDOS::Write(const void* buf, size_t len, size_t* pActual) { - //if (!fOpen) - // return kDIErrNotReady; - return kDIErrNotSupported; + //if (!fOpen) + // return kDIErrNotReady; + return kDIErrNotSupported; } /* @@ -625,37 +625,37 @@ A2FDRDOS::Write(const void* buf, size_t len, size_t* pActual) DIError A2FDRDOS::Seek(di_off_t offset, DIWhence whence) { - //if (!fOpen) - // return kDIErrNotReady; + //if (!fOpen) + // return kDIErrNotReady; - long fileLen = ((A2FileRDOS*) fpFile)->fLength; + long fileLen = ((A2FileRDOS*) fpFile)->fLength; - switch (whence) { - case kSeekSet: - if (offset < 0 || offset > fileLen) - return kDIErrInvalidArg; - fOffset = offset; - break; - case kSeekEnd: - if (offset > 0 || offset < -fileLen) - return kDIErrInvalidArg; - fOffset = fileLen + offset; - break; - case kSeekCur: - if (offset < -fOffset || - offset >= (fileLen - fOffset)) - { - return kDIErrInvalidArg; - } - fOffset += offset; - break; - default: - assert(false); - return kDIErrInvalidArg; - } + switch (whence) { + case kSeekSet: + if (offset < 0 || offset > fileLen) + return kDIErrInvalidArg; + fOffset = offset; + break; + case kSeekEnd: + if (offset > 0 || offset < -fileLen) + return kDIErrInvalidArg; + fOffset = fileLen + offset; + break; + case kSeekCur: + if (offset < -fOffset || + offset >= (fileLen - fOffset)) + { + return kDIErrInvalidArg; + } + fOffset += offset; + break; + default: + assert(false); + return kDIErrInvalidArg; + } - assert(fOffset >= 0 && fOffset <= fileLen); - return kDIErrNone; + assert(fOffset >= 0 && fOffset <= fileLen); + return kDIErrNone; } /* @@ -664,10 +664,10 @@ A2FDRDOS::Seek(di_off_t offset, DIWhence whence) di_off_t A2FDRDOS::Tell(void) { - //if (!fOpen) - // return kDIErrNotReady; + //if (!fOpen) + // return kDIErrNotReady; - return fOffset; + return fOffset; } /* @@ -676,8 +676,8 @@ A2FDRDOS::Tell(void) DIError A2FDRDOS::Close(void) { - fpFile->CloseDescr(this); - return kDIErrNone; + fpFile->CloseDescr(this); + return kDIErrNone; } /* @@ -686,16 +686,16 @@ A2FDRDOS::Close(void) long A2FDRDOS::GetSectorCount(void) const { - //if (!fOpen) - // return kDIErrNotReady; - return ((A2FileRDOS*) fpFile)->fNumSectors; + //if (!fOpen) + // return kDIErrNotReady; + return ((A2FileRDOS*) fpFile)->fNumSectors; } long A2FDRDOS::GetBlockCount(void) const { - //if (!fOpen) - // return kDIErrNotReady; - return ((A2FileRDOS*) fpFile)->fNumSectors / 2; + //if (!fOpen) + // return kDIErrNotReady; + return ((A2FileRDOS*) fpFile)->fNumSectors / 2; } /* @@ -704,18 +704,18 @@ A2FDRDOS::GetBlockCount(void) const DIError A2FDRDOS::GetStorage(long sectorIdx, long* pTrack, long* pSector) const { - //if (!fOpen) - // return kDIErrNotReady; - A2FileRDOS* pFile = (A2FileRDOS*) fpFile; - long rdosBlock = pFile->fStartSector + sectorIdx; - int ourSectPerTrack = GetOurSectPerTrack(); - if (rdosBlock >= pFile->fStartSector + pFile->fNumSectors) - return kDIErrInvalidIndex; + //if (!fOpen) + // return kDIErrNotReady; + A2FileRDOS* pFile = (A2FileRDOS*) fpFile; + long rdosBlock = pFile->fStartSector + sectorIdx; + int ourSectPerTrack = GetOurSectPerTrack(); + if (rdosBlock >= pFile->fStartSector + pFile->fNumSectors) + return kDIErrInvalidIndex; - *pTrack = rdosBlock / ourSectPerTrack; - *pSector = rdosBlock % ourSectPerTrack; + *pTrack = rdosBlock / ourSectPerTrack; + *pSector = rdosBlock % ourSectPerTrack; - return kDIErrNone; + return kDIErrNone; } /* * Return the Nth 512-byte block in this file. @@ -723,17 +723,17 @@ A2FDRDOS::GetStorage(long sectorIdx, long* pTrack, long* pSector) const DIError A2FDRDOS::GetStorage(long blockIdx, long* pBlock) const { - //if (!fOpen) - // return kDIErrNotReady; - A2FileRDOS* pFile = (A2FileRDOS*) fpFile; - long rdosBlock = pFile->fStartSector + blockIdx*2; - if (rdosBlock >= pFile->fStartSector + pFile->fNumSectors) - return kDIErrInvalidIndex; + //if (!fOpen) + // return kDIErrNotReady; + A2FileRDOS* pFile = (A2FileRDOS*) fpFile; + long rdosBlock = pFile->fStartSector + blockIdx*2; + if (rdosBlock >= pFile->fStartSector + pFile->fNumSectors) + return kDIErrInvalidIndex; - *pBlock = rdosBlock / 2; + *pBlock = rdosBlock / 2; - if (pFile->GetDiskFS()->GetDiskImg()->GetHasBlocks()) { - assert(*pBlock < pFile->GetDiskFS()->GetDiskImg()->GetNumBlocks()); - } - return kDIErrNone; + if (pFile->GetDiskFS()->GetDiskImg()->GetHasBlocks()) { + assert(*pBlock < pFile->GetDiskFS()->GetDiskImg()->GetNumBlocks()); + } + return kDIErrNone; } diff --git a/diskimg/SCSIDefs.h b/diskimg/SCSIDefs.h index f1902e9..f257f63 100644 --- a/diskimg/SCSIDefs.h +++ b/diskimg/SCSIDefs.h @@ -18,100 +18,100 @@ * SCSI-2 operation codes. */ typedef enum { - kScsiOpTestUnitReady = 0x00, - kScsiOpRezeroUnit = 0x01, - kScsiOpRewind = 0x01, - kScsiOpRequestBlockAddr = 0x02, - kScsiOpRequestSense = 0x03, - kScsiOpFormatUnit = 0x04, - kScsiOpReadBlockLimits = 0x05, - kScsiOpReassignBlocks = 0x07, - kScsiOpRead6 = 0x08, - kScsiOpReceive = 0x08, - kScsiOpWrite6 = 0x0a, - kScsiOpPrint = 0x0a, - kScsiOpSend = 0x0a, - kScsiOpSeek6 = 0x0b, - kScsiOpTrackSelect = 0x0b, - kScsiOpSlewPrint = 0x0b, - kScsiOpSeekBlock = 0x0c, - kScsiOpPartition = 0x0d, - kScsiOpReadReverse = 0x0f, - kScsiOpWriteFilemarks = 0x10, - kScsiOpFlushBuffer = 0x10, - kScsiOpSpace = 0x11, - kScsiOpInquiry = 0x12, - kScsiOpVerify6 = 0x13, - kScsiOpRecoverBufferedData = 0x14, - kScsiOpModeSelect = 0x15, - kScsiOpReserveUnit = 0x16, - kScsiOpReleaseUnit = 0x17, - kScsiOpCopy = 0x18, - kScsiOpErase = 0x19, - kScsiOpModeSense = 0x1a, - kScsiOpStartStopUnit = 0x1b, - kScsiOpStopPrint = 0x1b, - kScsiOpLoadUnload = 0x1b, - kScsiOpReceiveDiagnosticResults = 0x1c, - kScsiOpSendDiagnostic = 0x1d, - kScsiOpMediumRemoval = 0x1e, - kScsiOpReadFormattedCapacity = 0x23, - kScsiOpReadCapacity = 0x25, - kScsiOpRead = 0x28, // READ(10) - kScsiOpWrite = 0x2a, // WRITE(10) - kScsiOpSeek = 0x2b, - kScsiOpLocate = 0x2b, - kScsiOpPositionToElement = 0x2b, - kScsiOpWriteVerify = 0x2e, - kScsiOpVerify = 0x2f, // VERIFY(10) - kScsiOpSearchDataHigh = 0x30, - kScsiOpSearchDataEqual = 0x31, - kScsiOpSearchDataLow = 0x32, - kScsiOpSetLimits = 0x33, - kScsiOpReadPosition = 0x34, - kScsiOpSynchronizeCache = 0x35, - kScsiOpCompare = 0x39, - kScsiOpCopyAndVerify = 0x3a, - kScsiOpWriteBuffer = 0x3b, - kScsiOpReadBuffer = 0x3c, - kScsiOpChangeDefinition = 0x40, - kScsiOpReadSubChannel = 0x42, - kScsiOpReadTOC = 0x43, // READ TOC/PMA/ATIP - kScsiOpReadHeader = 0x44, - kScsiOpPlayAudio = 0x45, - kScsiOpPlayAudioMSF = 0x47, - kScsiOpPlayTrackIndex = 0x48, - kScsiOpPlayTrackRelative = 0x49, - kScsiOpPauseResume = 0x4b, - kScsiOpLogSelect = 0x4c, - kScsiOpLogSense = 0x4c, - kScsiOpStopPlayScan = 0x4e, - kScsiOpReadDiscInformation = 0x51, - kScsiOpReadTrackInformation = 0x52, - kScsiOpSendOPCInformation = 0x54, - kScsiOpModeSelect10 = 0x55, - kScsiOpRepairTrack = 0x58, - kScsiOpModeSense10 = 0x5a, - kScsiOpReportLuns = 0xa0, - kScsiOpVerify12 = 0xa2, - kScsiOpSendKey = 0xa3, - kScsiOpReportKey = 0xa4, - kScsiOpMoveMedium = 0xa5, - kScsiOpLoadUnloadSlot = 0xa6, - kScsiOpExchangeMedium = 0xa6, - kScsiOpSetReadAhead = 0xa7, - kScsiOpReadDVDStructure = 0xad, - kScsiOpWriteAndVerify = 0xae, - kScsiOpRequestVolElement = 0xb5, - kScsiOpSendVolumeTag = 0xb6, - kScsiOpReadElementStatus = 0xb8, - kScsiOpReadCDMSF = 0xb9, - kScsiOpScanCD = 0xba, - kScsiOpSetCDSpeed = 0xbb, - kScsiOpPlayCD = 0xbc, - kScsiOpMechanismStatus = 0xbd, - kScsiOpReadCD = 0xbe, - kScsiOpInitElementRange = 0xe7, + kScsiOpTestUnitReady = 0x00, + kScsiOpRezeroUnit = 0x01, + kScsiOpRewind = 0x01, + kScsiOpRequestBlockAddr = 0x02, + kScsiOpRequestSense = 0x03, + kScsiOpFormatUnit = 0x04, + kScsiOpReadBlockLimits = 0x05, + kScsiOpReassignBlocks = 0x07, + kScsiOpRead6 = 0x08, + kScsiOpReceive = 0x08, + kScsiOpWrite6 = 0x0a, + kScsiOpPrint = 0x0a, + kScsiOpSend = 0x0a, + kScsiOpSeek6 = 0x0b, + kScsiOpTrackSelect = 0x0b, + kScsiOpSlewPrint = 0x0b, + kScsiOpSeekBlock = 0x0c, + kScsiOpPartition = 0x0d, + kScsiOpReadReverse = 0x0f, + kScsiOpWriteFilemarks = 0x10, + kScsiOpFlushBuffer = 0x10, + kScsiOpSpace = 0x11, + kScsiOpInquiry = 0x12, + kScsiOpVerify6 = 0x13, + kScsiOpRecoverBufferedData = 0x14, + kScsiOpModeSelect = 0x15, + kScsiOpReserveUnit = 0x16, + kScsiOpReleaseUnit = 0x17, + kScsiOpCopy = 0x18, + kScsiOpErase = 0x19, + kScsiOpModeSense = 0x1a, + kScsiOpStartStopUnit = 0x1b, + kScsiOpStopPrint = 0x1b, + kScsiOpLoadUnload = 0x1b, + kScsiOpReceiveDiagnosticResults = 0x1c, + kScsiOpSendDiagnostic = 0x1d, + kScsiOpMediumRemoval = 0x1e, + kScsiOpReadFormattedCapacity = 0x23, + kScsiOpReadCapacity = 0x25, + kScsiOpRead = 0x28, // READ(10) + kScsiOpWrite = 0x2a, // WRITE(10) + kScsiOpSeek = 0x2b, + kScsiOpLocate = 0x2b, + kScsiOpPositionToElement = 0x2b, + kScsiOpWriteVerify = 0x2e, + kScsiOpVerify = 0x2f, // VERIFY(10) + kScsiOpSearchDataHigh = 0x30, + kScsiOpSearchDataEqual = 0x31, + kScsiOpSearchDataLow = 0x32, + kScsiOpSetLimits = 0x33, + kScsiOpReadPosition = 0x34, + kScsiOpSynchronizeCache = 0x35, + kScsiOpCompare = 0x39, + kScsiOpCopyAndVerify = 0x3a, + kScsiOpWriteBuffer = 0x3b, + kScsiOpReadBuffer = 0x3c, + kScsiOpChangeDefinition = 0x40, + kScsiOpReadSubChannel = 0x42, + kScsiOpReadTOC = 0x43, // READ TOC/PMA/ATIP + kScsiOpReadHeader = 0x44, + kScsiOpPlayAudio = 0x45, + kScsiOpPlayAudioMSF = 0x47, + kScsiOpPlayTrackIndex = 0x48, + kScsiOpPlayTrackRelative = 0x49, + kScsiOpPauseResume = 0x4b, + kScsiOpLogSelect = 0x4c, + kScsiOpLogSense = 0x4c, + kScsiOpStopPlayScan = 0x4e, + kScsiOpReadDiscInformation = 0x51, + kScsiOpReadTrackInformation = 0x52, + kScsiOpSendOPCInformation = 0x54, + kScsiOpModeSelect10 = 0x55, + kScsiOpRepairTrack = 0x58, + kScsiOpModeSense10 = 0x5a, + kScsiOpReportLuns = 0xa0, + kScsiOpVerify12 = 0xa2, + kScsiOpSendKey = 0xa3, + kScsiOpReportKey = 0xa4, + kScsiOpMoveMedium = 0xa5, + kScsiOpLoadUnloadSlot = 0xa6, + kScsiOpExchangeMedium = 0xa6, + kScsiOpSetReadAhead = 0xa7, + kScsiOpReadDVDStructure = 0xad, + kScsiOpWriteAndVerify = 0xae, + kScsiOpRequestVolElement = 0xb5, + kScsiOpSendVolumeTag = 0xb6, + kScsiOpReadElementStatus = 0xb8, + kScsiOpReadCDMSF = 0xb9, + kScsiOpScanCD = 0xba, + kScsiOpSetCDSpeed = 0xbb, + kScsiOpPlayCD = 0xbc, + kScsiOpMechanismStatus = 0xbd, + kScsiOpReadCD = 0xbe, + kScsiOpInitElementRange = 0xe7, } SCSIOperationCode; @@ -119,37 +119,37 @@ typedef enum { * SCSI status codes. */ typedef enum { - kScsiStatGood = 0x00, - kScsiStatCheckCondition = 0x02, - kScsiStatConditionMet = 0x04, - kScsiStatBusy = 0x08, - kScsiStatIntermediate = 0x10, - kScsiStatIntermediateCondMet = 0x14, - kScsiStatReservationConflict = 0x18, - kScsiStatCommandTerminated = 0x22, - kScsiStatQueueFull = 0x28, + kScsiStatGood = 0x00, + kScsiStatCheckCondition = 0x02, + kScsiStatConditionMet = 0x04, + kScsiStatBusy = 0x08, + kScsiStatIntermediate = 0x10, + kScsiStatIntermediateCondMet = 0x14, + kScsiStatReservationConflict = 0x18, + kScsiStatCommandTerminated = 0x22, + kScsiStatQueueFull = 0x28, } SCSIStatus; /* * SCSI sense codes. */ typedef enum { - kScsiSenseNoSense = 0x00, - kScsiSenseRecoveredError = 0x01, - kScsiSenseNotReady = 0x02, - kScsiSenseMediumError = 0x03, - kScsiSenseHardwareError = 0x04, - kScsiSenseIllegalRequest = 0x05, - kScsiSenseUnitAttention = 0x06, - kScsiSenseDataProtect = 0x07, - kScsiSenseBlankCheck = 0x08, - kScsiSenseUnqiue = 0x09, - kScsiSenseCopyAborted = 0x0a, - kScsiSenseAbortedCommand = 0x0b, - kScsiSenseEqual = 0x0c, - kScsiSenseVolOverflow = 0x0d, - kScsiSenseMiscompare = 0x0e, - kScsiSenseReserved = 0x0f, + kScsiSenseNoSense = 0x00, + kScsiSenseRecoveredError = 0x01, + kScsiSenseNotReady = 0x02, + kScsiSenseMediumError = 0x03, + kScsiSenseHardwareError = 0x04, + kScsiSenseIllegalRequest = 0x05, + kScsiSenseUnitAttention = 0x06, + kScsiSenseDataProtect = 0x07, + kScsiSenseBlankCheck = 0x08, + kScsiSenseUnqiue = 0x09, + kScsiSenseCopyAborted = 0x0a, + kScsiSenseAbortedCommand = 0x0b, + kScsiSenseEqual = 0x0c, + kScsiSenseVolOverflow = 0x0d, + kScsiSenseMiscompare = 0x0e, + kScsiSenseReserved = 0x0f, } SCSISenseCode; @@ -157,43 +157,43 @@ typedef enum { * SCSI additional sense codes. */ typedef enum { - kScsiAdSenseNoSense = 0x00, - kScsiAdSenseInvalidMedia = 0x30, - kScsiAdSenseNoMediaInDevice = 0x3a, + kScsiAdSenseNoSense = 0x00, + kScsiAdSenseInvalidMedia = 0x30, + kScsiAdSenseNoMediaInDevice = 0x3a, } SCSIAdSenseCode; /* * SCSI device types. */ typedef enum { - kScsiDevTypeDASD = 0x00, // Disk Device - kScsiDevTypeSEQD = 0x01, // Tape Device - kScsiDevTypePRNT = 0x02, // Printer - kScsiDevTypePROC = 0x03, // Processor - kScsiDevTypeWORM = 0x04, // Write-once read-multiple - kScsiDevTypeCDROM = 0x05, // CD-ROM device - kScsiDevTypeSCAN = 0x06, // Scanner device - kScsiDevTypeOPTI = 0x07, // Optical memory device - kScsiDevTypeJUKE = 0x08, // Medium Changer device - kScsiDevTypeCOMM = 0x09, // Communications device - kScsiDevTypeRESL = 0x0a, // Reserved (low) - kScsiDevTypeRESH = 0x1e, // Reserved (high) - kScsiDevTypeUNKNOWN = 0x1f, // Unknown or no device type + kScsiDevTypeDASD = 0x00, // Disk Device + kScsiDevTypeSEQD = 0x01, // Tape Device + kScsiDevTypePRNT = 0x02, // Printer + kScsiDevTypePROC = 0x03, // Processor + kScsiDevTypeWORM = 0x04, // Write-once read-multiple + kScsiDevTypeCDROM = 0x05, // CD-ROM device + kScsiDevTypeSCAN = 0x06, // Scanner device + kScsiDevTypeOPTI = 0x07, // Optical memory device + kScsiDevTypeJUKE = 0x08, // Medium Changer device + kScsiDevTypeCOMM = 0x09, // Communications device + kScsiDevTypeRESL = 0x0a, // Reserved (low) + kScsiDevTypeRESH = 0x1e, // Reserved (high) + kScsiDevTypeUNKNOWN = 0x1f, // Unknown or no device type } SCSIDeviceType; /* * Generic 6-byte request block. */ typedef struct CDB6 { - unsigned char operationCode; - unsigned char immediate : 1; - unsigned char commandUniqueBits : 4; - unsigned char logicalUnitNumber : 3; - unsigned char commandUniqueBytes[3]; - unsigned char link : 1; - unsigned char flag : 1; - unsigned char reserved : 4; - unsigned char vendorUnique : 2; + unsigned char operationCode; + unsigned char immediate : 1; + unsigned char commandUniqueBits : 4; + unsigned char logicalUnitNumber : 3; + unsigned char commandUniqueBytes[3]; + unsigned char link : 1; + unsigned char flag : 1; + unsigned char reserved : 4; + unsigned char vendorUnique : 2; } CDB6; /* @@ -202,55 +202,55 @@ typedef struct CDB6 { * Use for READ(10), READ CAPACITY. */ typedef struct CDB10 { - unsigned char operationCode; - unsigned char relativeAddress : 1; - unsigned char reserved1 : 2; - unsigned char forceUnitAccess : 1; - unsigned char disablePageOut : 1; - unsigned char logicalUnitNumber : 3; - unsigned char logicalBlockAddr0; // MSB - unsigned char logicalBlockAddr1; - unsigned char logicalBlockAddr2; - unsigned char logicalBlockAddr3; // LSB - unsigned char reserved2; - unsigned char transferLength0; // MSB - unsigned char transferLength1; // LSB - unsigned char control; + unsigned char operationCode; + unsigned char relativeAddress : 1; + unsigned char reserved1 : 2; + unsigned char forceUnitAccess : 1; + unsigned char disablePageOut : 1; + unsigned char logicalUnitNumber : 3; + unsigned char logicalBlockAddr0; // MSB + unsigned char logicalBlockAddr1; + unsigned char logicalBlockAddr2; + unsigned char logicalBlockAddr3; // LSB + unsigned char reserved2; + unsigned char transferLength0; // MSB + unsigned char transferLength1; // LSB + unsigned char control; } CDB10; /* * INQUIRY request block. */ typedef struct CDB6Inquiry { - unsigned char operationCode; - unsigned char EVPD : 1; - unsigned char reserved1 : 4; - unsigned char logicalUnitNumber : 3; - unsigned char pageCode; - unsigned char reserved2; - unsigned char allocationLength; - unsigned char control; + unsigned char operationCode; + unsigned char EVPD : 1; + unsigned char reserved1 : 4; + unsigned char logicalUnitNumber : 3; + unsigned char pageCode; + unsigned char reserved2; + unsigned char allocationLength; + unsigned char control; } CDB6Inquiry; /* * Sense data (ASPI SenseArea). */ typedef struct CDB_SenseData { - unsigned char errorCode:7; - unsigned char valid:1; - unsigned char segmentNumber; - unsigned char senseKey:4; - unsigned char reserved:1; - unsigned char incorrectLength:1; - unsigned char endOfMedia:1; - unsigned char fileMark:1; - unsigned char information[4]; - unsigned char additionalSenseLength; - unsigned char commandSpecificInformation[4]; - unsigned char additionalSenseCode; // ASC - unsigned char additionalSenseCodeQualifier; // ASCQ - unsigned char fieldReplaceableUnitCode; - unsigned char senseKeySpecific[3]; + unsigned char errorCode:7; + unsigned char valid:1; + unsigned char segmentNumber; + unsigned char senseKey:4; + unsigned char reserved:1; + unsigned char incorrectLength:1; + unsigned char endOfMedia:1; + unsigned char fileMark:1; + unsigned char information[4]; + unsigned char additionalSenseLength; + unsigned char commandSpecificInformation[4]; + unsigned char additionalSenseCode; // ASC + unsigned char additionalSenseCodeQualifier; // ASCQ + unsigned char fieldReplaceableUnitCode; + unsigned char senseKeySpecific[3]; } CDB_SenseData; /* @@ -265,44 +265,44 @@ typedef struct CDB_SenseData { * Result from INQUIRY. */ typedef struct CDB_InquiryData { - unsigned char deviceType : 5; - unsigned char deviceTypeQualifier : 3; - unsigned char deviceTypeModifier : 7; - unsigned char removableMedia : 1; - unsigned char versions; - unsigned char responseDataFormat : 4; - unsigned char reserved1 : 2; - unsigned char trmIOP : 1; - unsigned char AENC : 1; - unsigned char additionalLength; - unsigned char reserved2[2]; - unsigned char softReset : 1; - unsigned char commandQueue : 1; - unsigned char reserved3 : 1; - unsigned char linkedCommands : 1; - unsigned char synchronous : 1; - unsigned char wide16Bit : 1; - unsigned char wide32Bit : 1; - unsigned char relativeAddressing : 1; - unsigned char vendorId[8]; - unsigned char productId[16]; - unsigned char productRevisionLevel[4]; - unsigned char vendorSpecific[20]; - unsigned char reserved4[40]; + unsigned char deviceType : 5; + unsigned char deviceTypeQualifier : 3; + unsigned char deviceTypeModifier : 7; + unsigned char removableMedia : 1; + unsigned char versions; + unsigned char responseDataFormat : 4; + unsigned char reserved1 : 2; + unsigned char trmIOP : 1; + unsigned char AENC : 1; + unsigned char additionalLength; + unsigned char reserved2[2]; + unsigned char softReset : 1; + unsigned char commandQueue : 1; + unsigned char reserved3 : 1; + unsigned char linkedCommands : 1; + unsigned char synchronous : 1; + unsigned char wide16Bit : 1; + unsigned char wide32Bit : 1; + unsigned char relativeAddressing : 1; + unsigned char vendorId[8]; + unsigned char productId[16]; + unsigned char productRevisionLevel[4]; + unsigned char vendorSpecific[20]; + unsigned char reserved4[40]; } CDB_InquiryData; /* * Result from READ CAPACITY. */ typedef struct CDB_ReadCapacityData { - unsigned char logicalBlockAddr0; // MSB - unsigned char logicalBlockAddr1; - unsigned char logicalBlockAddr2; - unsigned char logicalBlockAddr3; // LSB - unsigned char bytesPerBlock0; // MSB - unsigned char bytesPerBlock1; - unsigned char bytesPerBlock2; - unsigned char bytesPerBlock3; // LSB + unsigned char logicalBlockAddr0; // MSB + unsigned char logicalBlockAddr1; + unsigned char logicalBlockAddr2; + unsigned char logicalBlockAddr3; // LSB + unsigned char bytesPerBlock0; // MSB + unsigned char bytesPerBlock1; + unsigned char bytesPerBlock2; + unsigned char bytesPerBlock3; // LSB } CDB_ReadCapacityData; #endif /*__SCSI_DEFS__*/ diff --git a/diskimg/SPTI.cpp b/diskimg/SPTI.cpp index 3a4ee7f..1ee30ce 100644 --- a/diskimg/SPTI.cpp +++ b/diskimg/SPTI.cpp @@ -22,59 +22,59 @@ */ /*static*/ DIError SPTI::GetDeviceCapacity(HANDLE handle, unsigned long* pLastBlock, - unsigned long* pBlockSize) + unsigned long* pBlockSize) { - SCSI_PASS_THROUGH_DIRECT sptd; - unsigned long lba, blockLen; - CDB_ReadCapacityData dataBuf; - DWORD cb; - BOOL status; + SCSI_PASS_THROUGH_DIRECT sptd; + unsigned long lba, blockLen; + CDB_ReadCapacityData dataBuf; + DWORD cb; + BOOL status; - assert(sizeof(dataBuf) == 8); // READ CAPACITY returns two longs + assert(sizeof(dataBuf) == 8); // READ CAPACITY returns two longs - memset(&sptd, 0, sizeof(sptd)); - sptd.Length = sizeof(sptd); - sptd.PathId = 0; // SCSI card ID filled in by ioctl - sptd.TargetId = 0; // SCSI target ID filled in by ioctl - sptd.Lun = 0; // SCSI lun ID filled in by ioctl - sptd.CdbLength = 10; // CDB size is 10 for READ CAPACITY - sptd.SenseInfoLength = 0; // don't return any sense data - sptd.DataIn = SCSI_IOCTL_DATA_IN; // will be data from drive - sptd.DataTransferLength = sizeof(dataBuf); - sptd.TimeOutValue = 10; // SCSI timeout value, in seconds - sptd.DataBuffer = (PVOID) &dataBuf; - sptd.SenseInfoOffset = 0; // offset to request-sense buffer + memset(&sptd, 0, sizeof(sptd)); + sptd.Length = sizeof(sptd); + sptd.PathId = 0; // SCSI card ID filled in by ioctl + sptd.TargetId = 0; // SCSI target ID filled in by ioctl + sptd.Lun = 0; // SCSI lun ID filled in by ioctl + sptd.CdbLength = 10; // CDB size is 10 for READ CAPACITY + sptd.SenseInfoLength = 0; // don't return any sense data + sptd.DataIn = SCSI_IOCTL_DATA_IN; // will be data from drive + sptd.DataTransferLength = sizeof(dataBuf); + sptd.TimeOutValue = 10; // SCSI timeout value, in seconds + sptd.DataBuffer = (PVOID) &dataBuf; + sptd.SenseInfoOffset = 0; // offset to request-sense buffer - CDB10* pCdb = (CDB10*) &sptd.Cdb; - pCdb->operationCode = kScsiOpReadCapacity; - // rest of CDB is zero + CDB10* pCdb = (CDB10*) &sptd.Cdb; + pCdb->operationCode = kScsiOpReadCapacity; + // rest of CDB is zero - status = ::DeviceIoControl(handle, IOCTL_SCSI_PASS_THROUGH_DIRECT, - &sptd, sizeof(sptd), NULL, 0, &cb, NULL); + status = ::DeviceIoControl(handle, IOCTL_SCSI_PASS_THROUGH_DIRECT, + &sptd, sizeof(sptd), NULL, 0, &cb, NULL); - if (!status) { - DWORD lastError = ::GetLastError(); - WMSG1("DeviceIoControl(SCSI READ CAPACITY) failed, err=%ld\n", - ::GetLastError()); - if (lastError == ERROR_IO_DEVICE) // no disc in drive - return kDIErrDeviceNotReady; - else - return kDIErrSPTIFailure; - } + if (!status) { + DWORD lastError = ::GetLastError(); + WMSG1("DeviceIoControl(SCSI READ CAPACITY) failed, err=%ld\n", + ::GetLastError()); + if (lastError == ERROR_IO_DEVICE) // no disc in drive + return kDIErrDeviceNotReady; + else + return kDIErrSPTIFailure; + } - lba = (unsigned long) dataBuf.logicalBlockAddr0 << 24 | - (unsigned long) dataBuf.logicalBlockAddr1 << 16 | - (unsigned long) dataBuf.logicalBlockAddr2 << 8 | - (unsigned long) dataBuf.logicalBlockAddr3; - blockLen = (unsigned long) dataBuf.bytesPerBlock0 << 24 | - (unsigned long) dataBuf.bytesPerBlock1 << 16 | - (unsigned long) dataBuf.bytesPerBlock2 << 8 | - (unsigned long) dataBuf.bytesPerBlock3; + lba = (unsigned long) dataBuf.logicalBlockAddr0 << 24 | + (unsigned long) dataBuf.logicalBlockAddr1 << 16 | + (unsigned long) dataBuf.logicalBlockAddr2 << 8 | + (unsigned long) dataBuf.logicalBlockAddr3; + blockLen = (unsigned long) dataBuf.bytesPerBlock0 << 24 | + (unsigned long) dataBuf.bytesPerBlock1 << 16 | + (unsigned long) dataBuf.bytesPerBlock2 << 8 | + (unsigned long) dataBuf.bytesPerBlock3; - *pLastBlock = lba; - *pBlockSize = blockLen; + *pLastBlock = lba; + *pBlockSize = blockLen; - return kDIErrNone; + return kDIErrNone; } @@ -85,55 +85,55 @@ SPTI::GetDeviceCapacity(HANDLE handle, unsigned long* pLastBlock, */ /*static*/ DIError SPTI::ReadBlocks(HANDLE handle, long startBlock, short numBlocks, - long blockSize, void* buf) + long blockSize, void* buf) { - SCSI_PASS_THROUGH_DIRECT sptd; - DWORD cb; - BOOL status; + SCSI_PASS_THROUGH_DIRECT sptd; + DWORD cb; + BOOL status; - assert(startBlock >= 0); - assert(numBlocks > 0); - assert(buf != nil); + assert(startBlock >= 0); + assert(numBlocks > 0); + assert(buf != nil); - //WMSG2(" SPTI phys read block (%ld) %d\n", startBlock, numBlocks); + //WMSG2(" SPTI phys read block (%ld) %d\n", startBlock, numBlocks); - memset(&sptd, 0, sizeof(sptd)); - sptd.Length = sizeof(sptd); // size of struct (+ request-sense buffer) - sptd.ScsiStatus = 0; - sptd.PathId = 0; // SCSI card ID filled in by ioctl - sptd.TargetId = 0; // SCSI target ID filled in by ioctl - sptd.Lun = 0; // SCSI lun ID filled in by ioctl - sptd.CdbLength = 10; // CDB size is 10 for READ CAPACITY - sptd.SenseInfoLength = 0; // don't return any sense data - sptd.DataIn = SCSI_IOCTL_DATA_IN; // will be data from drive - sptd.DataTransferLength = blockSize * numBlocks; - sptd.TimeOutValue = 10; // SCSI timeout value (in seconds) - sptd.DataBuffer = (PVOID) buf; - sptd.SenseInfoOffset = 0; // offset from start of struct to request-sense + memset(&sptd, 0, sizeof(sptd)); + sptd.Length = sizeof(sptd); // size of struct (+ request-sense buffer) + sptd.ScsiStatus = 0; + sptd.PathId = 0; // SCSI card ID filled in by ioctl + sptd.TargetId = 0; // SCSI target ID filled in by ioctl + sptd.Lun = 0; // SCSI lun ID filled in by ioctl + sptd.CdbLength = 10; // CDB size is 10 for READ CAPACITY + sptd.SenseInfoLength = 0; // don't return any sense data + sptd.DataIn = SCSI_IOCTL_DATA_IN; // will be data from drive + sptd.DataTransferLength = blockSize * numBlocks; + sptd.TimeOutValue = 10; // SCSI timeout value (in seconds) + sptd.DataBuffer = (PVOID) buf; + sptd.SenseInfoOffset = 0; // offset from start of struct to request-sense - CDB10* pCdb = (CDB10*) &sptd.Cdb; - pCdb->operationCode = kScsiOpRead; - pCdb->logicalBlockAddr0 = (unsigned char) (startBlock >> 24); // MSB - pCdb->logicalBlockAddr1 = (unsigned char) (startBlock >> 16); - pCdb->logicalBlockAddr2 = (unsigned char) (startBlock >> 8); - pCdb->logicalBlockAddr3 = (unsigned char) startBlock; // LSB - pCdb->transferLength0 = (unsigned char) (numBlocks >> 8); // MSB - pCdb->transferLength1 = (unsigned char) numBlocks; // LSB + CDB10* pCdb = (CDB10*) &sptd.Cdb; + pCdb->operationCode = kScsiOpRead; + pCdb->logicalBlockAddr0 = (unsigned char) (startBlock >> 24); // MSB + pCdb->logicalBlockAddr1 = (unsigned char) (startBlock >> 16); + pCdb->logicalBlockAddr2 = (unsigned char) (startBlock >> 8); + pCdb->logicalBlockAddr3 = (unsigned char) startBlock; // LSB + pCdb->transferLength0 = (unsigned char) (numBlocks >> 8); // MSB + pCdb->transferLength1 = (unsigned char) numBlocks; // LSB - status = ::DeviceIoControl(handle, IOCTL_SCSI_PASS_THROUGH_DIRECT, - &sptd, sizeof(sptd), NULL, 0, &cb, NULL); + status = ::DeviceIoControl(handle, IOCTL_SCSI_PASS_THROUGH_DIRECT, + &sptd, sizeof(sptd), NULL, 0, &cb, NULL); - if (!status) { - WMSG1("DeviceIoControl(SCSI READ(10)) failed, err=%ld\n", - ::GetLastError()); - return kDIErrReadFailed; // close enough - } - if (sptd.ScsiStatus != 0) { - WMSG1("SCSI READ(10) failed, status=%d\n", sptd.ScsiStatus); - return kDIErrReadFailed; - } + if (!status) { + WMSG1("DeviceIoControl(SCSI READ(10)) failed, err=%ld\n", + ::GetLastError()); + return kDIErrReadFailed; // close enough + } + if (sptd.ScsiStatus != 0) { + WMSG1("SCSI READ(10) failed, status=%d\n", sptd.ScsiStatus); + return kDIErrReadFailed; + } - return kDIErrNone; + return kDIErrNone; } #endif /*_WIN32*/ diff --git a/diskimg/SPTI.h b/diskimg/SPTI.h index c8b8242..6f28b61 100644 --- a/diskimg/SPTI.h +++ b/diskimg/SPTI.h @@ -19,21 +19,21 @@ namespace DiskImgLib { */ class DISKIMG_API SPTI { public: - // Read blocks from the device. - static DIError ReadBlocks(HANDLE handle, long startBlock, short numBlocks, - long blockSize, void* buf); + // Read blocks from the device. + static DIError ReadBlocks(HANDLE handle, long startBlock, short numBlocks, + long blockSize, void* buf); - // Get the capacity, expressed as the highest-available LBA and the device - // block size. - static DIError GetDeviceCapacity(HANDLE handle, unsigned long* pLastBlock, - unsigned long* pBlockSize); + // Get the capacity, expressed as the highest-available LBA and the device + // block size. + static DIError GetDeviceCapacity(HANDLE handle, unsigned long* pLastBlock, + unsigned long* pBlockSize); private: - SPTI(void) {} - ~SPTI(void) {} + SPTI(void) {} + ~SPTI(void) {} }; -}; // namespace DiskImgLib +}; // namespace DiskImgLib #endif /*_WIN32*/ diff --git a/diskimg/StdAfx.cpp b/diskimg/StdAfx.cpp index f859ec7..610fe81 100644 --- a/diskimg/StdAfx.cpp +++ b/diskimg/StdAfx.cpp @@ -4,8 +4,8 @@ * See the file LICENSE for distribution terms. */ // stdafx.cpp : source file that includes just the standard includes -// diskimg.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information +// diskimg.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information #include "StdAfx.h" diff --git a/diskimg/StdAfx.h b/diskimg/StdAfx.h index 37e38b2..17e15e9 100644 --- a/diskimg/StdAfx.h +++ b/diskimg/StdAfx.h @@ -36,11 +36,11 @@ #pragma once #endif // _MSC_VER > 1000 -#define HAVE_WINDOWS_CDROM // enable CD-ROM access under Windows +#define HAVE_WINDOWS_CDROM // enable CD-ROM access under Windows #define HAVE_CHSIZE // Insert your headers here -# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include #include diff --git a/diskimg/TwoImg.cpp b/diskimg/TwoImg.cpp index 80551f7..e926f1d 100644 --- a/diskimg/TwoImg.cpp +++ b/diskimg/TwoImg.cpp @@ -13,8 +13,8 @@ #include "TwoImg.h" #include "DiskImgPriv.h" -///*static*/ const char* TwoImgHeader::kMagic = "2IMG"; // file magic # -///*static*/ const char* TwoImgHeader::kCreator = "CdrP"; // our "creator" ID +///*static*/ const char* TwoImgHeader::kMagic = "2IMG"; // file magic # +///*static*/ const char* TwoImgHeader::kCreator = "CdrP"; // our "creator" ID /* @@ -28,10 +28,10 @@ int TwoImgHeader::InitHeader(int imageFormat, long imageSize, long imageBlockCount) { - if (imageSize <= 0) - return -1; - if (imageFormat < kImageFormatDOS || imageFormat > kImageFormatNibble) - return -1; + if (imageSize <= 0) + return -1; + if (imageFormat < kImageFormatDOS || imageFormat > kImageFormatNibble) + return -1; if (imageFormat != kImageFormatNibble && imageSize != imageBlockCount * 512) @@ -41,26 +41,26 @@ TwoImgHeader::InitHeader(int imageFormat, long imageSize, long imageBlockCount) return -1; } - assert(fComment == nil); + assert(fComment == nil); - //memcpy(fMagic, kMagic, 4); - //memcpy(fCreator, kCreator, 4); - fMagic = kMagic; - fCreator = kCreatorCiderPress; - fHeaderLen = kOurHeaderLen; - fVersion = kOurVersion; - fImageFormat = imageFormat; - fFlags = 0; - fNumBlocks = imageBlockCount; - fDataOffset = kOurHeaderLen; - fDataLen = imageSize; - fCmtOffset = 0; - fCmtLen = 0; - fCreatorOffset = 0; - fCreatorLen = 0; - fSpare[0] = fSpare[1] = fSpare[2] = fSpare[3] = 0; + //memcpy(fMagic, kMagic, 4); + //memcpy(fCreator, kCreator, 4); + fMagic = kMagic; + fCreator = kCreatorCiderPress; + fHeaderLen = kOurHeaderLen; + fVersion = kOurVersion; + fImageFormat = imageFormat; + fFlags = 0; + fNumBlocks = imageBlockCount; + fDataOffset = kOurHeaderLen; + fDataLen = imageSize; + fCmtOffset = 0; + fCmtLen = 0; + fCreatorOffset = 0; + fCreatorLen = 0; + fSpare[0] = fSpare[1] = fSpare[2] = fSpare[3] = 0; - return 0; + return 0; } /* @@ -73,8 +73,8 @@ TwoImgHeader::InitHeader(int imageFormat, long imageSize, long imageBlockCount) short TwoImgHeader::GetDOSVolumeNum(void) const { - assert(fFlags & kDOSVolumeSet); - return fDOSVolumeNum; + assert(fFlags & kDOSVolumeSet); + return fDOSVolumeNum; } /* @@ -94,27 +94,27 @@ TwoImgHeader::SetDOSVolumeNum(short dosVolumeNum) void TwoImgHeader::SetComment(const char* comment) { - delete[] fComment; - if (comment == nil) { - fComment = nil; - } else { - fComment = new char[strlen(comment)+1]; - if (fComment != nil) - strcpy(fComment, comment); - // else throw alloc failure - } + delete[] fComment; + if (comment == nil) { + fComment = nil; + } else { + fComment = new char[strlen(comment)+1]; + if (fComment != nil) + strcpy(fComment, comment); + // else throw alloc failure + } - if (fComment == nil) { - fCmtLen = 0; - fCmtOffset = 0; - if (fCreatorOffset > 0) - fCreatorOffset = fDataOffset + fDataLen; - } else { - fCmtLen = strlen(fComment); - fCmtOffset = fDataOffset + fDataLen; - if (fCreatorOffset > 0) - fCreatorOffset = fCmtOffset + fCmtLen; - } + if (fComment == nil) { + fCmtLen = 0; + fCmtOffset = 0; + if (fCreatorOffset > 0) + fCreatorOffset = fDataOffset + fDataLen; + } else { + fCmtLen = strlen(fComment); + fCmtOffset = fDataOffset + fDataLen; + if (fCreatorOffset > 0) + fCreatorOffset = fCmtOffset + fCmtLen; + } } /* @@ -123,28 +123,28 @@ TwoImgHeader::SetComment(const char* comment) void TwoImgHeader::SetCreatorChunk(const void* chunk, long len) { - assert(len >= 0); + assert(len >= 0); - delete[] fCreatorChunk; - if (chunk == nil || len == 0) { - fCreatorChunk = nil; - } else { - fCreatorChunk = new char[len]; - if (fCreatorChunk != nil) - memcpy(fCreatorChunk, chunk, len); - // else throw alloc failure - } + delete[] fCreatorChunk; + if (chunk == nil || len == 0) { + fCreatorChunk = nil; + } else { + fCreatorChunk = new char[len]; + if (fCreatorChunk != nil) + memcpy(fCreatorChunk, chunk, len); + // else throw alloc failure + } - if (fCreatorChunk == nil) { - fCreatorLen = 0; - fCreatorOffset = 0; - } else { - fCreatorLen = len; - if (fCmtOffset > 0) - fCreatorOffset = fCmtOffset + fCmtLen; - else - fCreatorOffset = fDataOffset + fDataLen; - } + if (fCreatorChunk == nil) { + fCreatorLen = 0; + fCreatorOffset = 0; + } else { + fCreatorLen = len; + if (fCmtOffset > 0) + fCreatorOffset = fCmtOffset + fCmtLen; + else + fCreatorOffset = fDataOffset + fDataLen; + } } /* @@ -158,46 +158,46 @@ TwoImgHeader::SetCreatorChunk(const void* chunk, long len) int TwoImgHeader::ReadHeader(FILE* fp, long totalLength) { - unsigned char buf[kOurHeaderLen]; + unsigned char buf[kOurHeaderLen]; - fread(buf, kOurHeaderLen, 1, fp); - if (ferror(fp)) - return errno ? errno : -1; + fread(buf, kOurHeaderLen, 1, fp); + if (ferror(fp)) + return errno ? errno : -1; - if (UnpackHeader(buf, totalLength) != 0) - return -1; + if (UnpackHeader(buf, totalLength) != 0) + return -1; - /* - * Extract the comment, if any. - */ - if (fCmtOffset > 0 && fCmtLen > 0) { - if (GetChunk(fp, fCmtOffset - kOurHeaderLen, fCmtLen, - (void**) &fComment) != 0) - { - WMSG0("Throwing comment away\n"); - fCmtLen = 0; - fCmtOffset = 0; - } else { - WMSG1("Got comment: '%s'\n", fComment); - } - } + /* + * Extract the comment, if any. + */ + if (fCmtOffset > 0 && fCmtLen > 0) { + if (GetChunk(fp, fCmtOffset - kOurHeaderLen, fCmtLen, + (void**) &fComment) != 0) + { + WMSG0("Throwing comment away\n"); + fCmtLen = 0; + fCmtOffset = 0; + } else { + WMSG1("Got comment: '%s'\n", fComment); + } + } - /* - * Extract the creator chunk, if any. - */ - if (fCreatorOffset > 0 && fCreatorLen > 0) { - if (GetChunk(fp, fCreatorOffset - kOurHeaderLen, fCreatorLen, - (void**) &fCreatorChunk) != 0) - { - WMSG0("Throwing creator chunk away\n"); - fCreatorLen = 0; - fCreatorOffset = 0; - } else { - //WMSG1("Got creator chunk: '%s'\n", fCreatorChunk); - } - } + /* + * Extract the creator chunk, if any. + */ + if (fCreatorOffset > 0 && fCreatorLen > 0) { + if (GetChunk(fp, fCreatorOffset - kOurHeaderLen, fCreatorLen, + (void**) &fCreatorChunk) != 0) + { + WMSG0("Throwing creator chunk away\n"); + fCreatorLen = 0; + fCreatorOffset = 0; + } else { + //WMSG1("Got creator chunk: '%s'\n", fCreatorChunk); + } + } - return 0; + return 0; } /* @@ -208,47 +208,47 @@ TwoImgHeader::ReadHeader(FILE* fp, long totalLength) int TwoImgHeader::ReadHeader(GenericFD* pGFD, long totalLength) { - DIError dierr; - unsigned char buf[kOurHeaderLen]; + DIError dierr; + unsigned char buf[kOurHeaderLen]; - dierr = pGFD->Read(buf, kOurHeaderLen); - if (dierr != kDIErrNone) - return -1; + dierr = pGFD->Read(buf, kOurHeaderLen); + if (dierr != kDIErrNone) + return -1; - if (UnpackHeader(buf, totalLength) != 0) - return -1; + if (UnpackHeader(buf, totalLength) != 0) + return -1; - /* - * Extract the comment, if any. - */ - if (fCmtOffset > 0 && fCmtLen > 0) { - if (GetChunk(pGFD, fCmtOffset - kOurHeaderLen, fCmtLen, - (void**) &fComment) != 0) - { - WMSG0("Throwing comment away\n"); - fCmtLen = 0; - fCmtOffset = 0; - } else { - WMSG1("Got comment: '%s'\n", fComment); - } - } + /* + * Extract the comment, if any. + */ + if (fCmtOffset > 0 && fCmtLen > 0) { + if (GetChunk(pGFD, fCmtOffset - kOurHeaderLen, fCmtLen, + (void**) &fComment) != 0) + { + WMSG0("Throwing comment away\n"); + fCmtLen = 0; + fCmtOffset = 0; + } else { + WMSG1("Got comment: '%s'\n", fComment); + } + } - /* - * Extract the creator chunk, if any. - */ - if (fCreatorOffset > 0 && fCreatorLen > 0) { - if (GetChunk(pGFD, fCreatorOffset - kOurHeaderLen, fCreatorLen, - (void**) &fCreatorChunk) != 0) - { - WMSG0("Throwing creator chunk away\n"); - fCreatorLen = 0; - fCreatorOffset = 0; - } else { - //WMSG1("Got creator chunk: '%s'\n", fCreatorChunk); - } - } + /* + * Extract the creator chunk, if any. + */ + if (fCreatorOffset > 0 && fCreatorLen > 0) { + if (GetChunk(pGFD, fCreatorOffset - kOurHeaderLen, fCreatorLen, + (void**) &fCreatorChunk) != 0) + { + WMSG0("Throwing creator chunk away\n"); + fCreatorLen = 0; + fCreatorOffset = 0; + } else { + //WMSG1("Got creator chunk: '%s'\n", fCreatorChunk); + } + } - return 0; + return 0; } /* @@ -256,40 +256,40 @@ TwoImgHeader::ReadHeader(GenericFD* pGFD, long totalLength) */ int TwoImgHeader::GetChunk(GenericFD* pGFD, di_off_t relOffset, long len, - void** pBuf) + void** pBuf) { - DIError dierr; - di_off_t curPos; + DIError dierr; + di_off_t curPos; - /* remember current offset */ - curPos = pGFD->Tell(); + /* remember current offset */ + curPos = pGFD->Tell(); - /* seek out to chunk and grab it */ - dierr = pGFD->Seek(relOffset, kSeekCur); - if (dierr != kDIErrNone) { - WMSG0("2MG seek to chunk failed\n"); - return -1; - } + /* seek out to chunk and grab it */ + dierr = pGFD->Seek(relOffset, kSeekCur); + if (dierr != kDIErrNone) { + WMSG0("2MG seek to chunk failed\n"); + return -1; + } - assert(*pBuf == nil); - *pBuf = new char[len+1]; // one extra, for null termination + assert(*pBuf == nil); + *pBuf = new char[len+1]; // one extra, for null termination - dierr = pGFD->Read(*pBuf, len); - if (dierr != kDIErrNone) { - WMSG0("2MG chunk read failed\n"); - delete[] (char*) (*pBuf); - *pBuf = nil; - (void) pGFD->Seek(curPos, kSeekSet); - return -1; - } + dierr = pGFD->Read(*pBuf, len); + if (dierr != kDIErrNone) { + WMSG0("2MG chunk read failed\n"); + delete[] (char*) (*pBuf); + *pBuf = nil; + (void) pGFD->Seek(curPos, kSeekSet); + return -1; + } - /* null-terminate, in case this was a string */ - ((char*) *pBuf)[len] = '\0'; + /* null-terminate, in case this was a string */ + ((char*) *pBuf)[len] = '\0'; - /* seek back to where we were */ - (void) pGFD->Seek(curPos, kSeekSet); + /* seek back to where we were */ + (void) pGFD->Seek(curPos, kSeekSet); - return 0; + return 0; } /* @@ -297,41 +297,41 @@ TwoImgHeader::GetChunk(GenericFD* pGFD, di_off_t relOffset, long len, */ int TwoImgHeader::GetChunk(FILE* fp, di_off_t relOffset, long len, - void** pBuf) + void** pBuf) { - long curPos; - int count; + long curPos; + int count; - /* remember current offset */ - curPos = ftell(fp); - WMSG1("Current offset=%ld\n", curPos); + /* remember current offset */ + curPos = ftell(fp); + WMSG1("Current offset=%ld\n", curPos); - /* seek out to chunk and grab it */ - if (fseek(fp, (long) relOffset, SEEK_CUR) == -1) { - WMSG0("2MG seek to chunk failed\n"); - return errno ? errno : -1;; - } + /* seek out to chunk and grab it */ + if (fseek(fp, (long) relOffset, SEEK_CUR) == -1) { + WMSG0("2MG seek to chunk failed\n"); + return errno ? errno : -1;; + } - assert(*pBuf == nil); - *pBuf = new char[len+1]; // one extra, for null termination + assert(*pBuf == nil); + *pBuf = new char[len+1]; // one extra, for null termination - count = fread(*pBuf, len, 1, fp); - if (!count || ferror(fp) || feof(fp)) { - WMSG0("2MG chunk read failed\n"); - delete[] (char*) (*pBuf); - *pBuf = nil; - (void) fseek(fp, curPos, SEEK_SET); - clearerr(fp); - return errno ? errno : -1;; - } + count = fread(*pBuf, len, 1, fp); + if (!count || ferror(fp) || feof(fp)) { + WMSG0("2MG chunk read failed\n"); + delete[] (char*) (*pBuf); + *pBuf = nil; + (void) fseek(fp, curPos, SEEK_SET); + clearerr(fp); + return errno ? errno : -1;; + } - /* null-terminate, in case this was a string */ - ((char*) *pBuf)[len] = '\0'; + /* null-terminate, in case this was a string */ + ((char*) *pBuf)[len] = '\0'; - /* seek back to where we were */ - (void) fseek(fp, curPos, SEEK_SET); + /* seek back to where we were */ + (void) fseek(fp, curPos, SEEK_SET); - return 0; + return 0; } @@ -343,34 +343,34 @@ TwoImgHeader::GetChunk(FILE* fp, di_off_t relOffset, long len, int TwoImgHeader::UnpackHeader(const unsigned char* buf, long totalLength) { - fMagic = GetLongBE(&buf[0x00]); - fCreator = GetLongBE(&buf[0x04]); - fHeaderLen = GetShortLE(&buf[0x08]); - fVersion = GetShortLE(&buf[0x0a]); - fImageFormat = GetLongLE(&buf[0x0c]); - fFlags = GetLongLE(&buf[0x10]); - fNumBlocks = GetLongLE(&buf[0x14]); - fDataOffset = GetLongLE(&buf[0x18]); - fDataLen = GetLongLE(&buf[0x1c]); - fCmtOffset = GetLongLE(&buf[0x20]); - fCmtLen = GetLongLE(&buf[0x24]); - fCreatorOffset = GetLongLE(&buf[0x28]); - fCreatorLen = GetLongLE(&buf[0x2c]); - fSpare[0] = GetLongLE(&buf[0x30]); - fSpare[1] = GetLongLE(&buf[0x34]); - fSpare[2] = GetLongLE(&buf[0x38]); - fSpare[3] = GetLongLE(&buf[0x3c]); + fMagic = GetLongBE(&buf[0x00]); + fCreator = GetLongBE(&buf[0x04]); + fHeaderLen = GetShortLE(&buf[0x08]); + fVersion = GetShortLE(&buf[0x0a]); + fImageFormat = GetLongLE(&buf[0x0c]); + fFlags = GetLongLE(&buf[0x10]); + fNumBlocks = GetLongLE(&buf[0x14]); + fDataOffset = GetLongLE(&buf[0x18]); + fDataLen = GetLongLE(&buf[0x1c]); + fCmtOffset = GetLongLE(&buf[0x20]); + fCmtLen = GetLongLE(&buf[0x24]); + fCreatorOffset = GetLongLE(&buf[0x28]); + fCreatorLen = GetLongLE(&buf[0x2c]); + fSpare[0] = GetLongLE(&buf[0x30]); + fSpare[1] = GetLongLE(&buf[0x34]); + fSpare[2] = GetLongLE(&buf[0x38]); + fSpare[3] = GetLongLE(&buf[0x3c]); - fMagicStr[0] = (char) (fMagic >> 24); - fMagicStr[1] = (char) (fMagic >> 16); - fMagicStr[2] = (char) (fMagic >> 8); - fMagicStr[3] = (char) fMagic; - fMagicStr[4] = '\0'; - fCreatorStr[0] = (char) (fCreator >> 24); - fCreatorStr[1] = (char) (fCreator >> 16); - fCreatorStr[2] = (char) (fCreator >> 8); - fCreatorStr[3] = (char) fCreator; - fCreatorStr[4] = '\0'; + fMagicStr[0] = (char) (fMagic >> 24); + fMagicStr[1] = (char) (fMagic >> 16); + fMagicStr[2] = (char) (fMagic >> 8); + fMagicStr[3] = (char) fMagic; + fMagicStr[4] = '\0'; + fCreatorStr[0] = (char) (fCreator >> 24); + fCreatorStr[1] = (char) (fCreator >> 16); + fCreatorStr[2] = (char) (fCreator >> 8); + fCreatorStr[3] = (char) fCreator; + fCreatorStr[4] = '\0'; if (fMagic != kMagic) { WMSG0("Magic number does not match 2IMG\n"); @@ -379,63 +379,63 @@ TwoImgHeader::UnpackHeader(const unsigned char* buf, long totalLength) if (fVersion > 1) { WMSG1("ERROR: unsupported version=%d\n", fVersion); - return -1; // bad header until I hear otherwise + return -1; // bad header until I hear otherwise } - if (fFlags & kDOSVolumeSet) - fDOSVolumeNum = fFlags & kDOSVolumeMask; + if (fFlags & kDOSVolumeSet) + fDOSVolumeNum = fFlags & kDOSVolumeMask; - DumpHeader(); + DumpHeader(); - /* fix broken 'WOOF' images from Sweet-16 */ - if (fCreator == kCreatorSweet16 && fDataLen == 0 && - fImageFormat != kImageFormatNibble) - { - fDataLen = fNumBlocks * kBlockSize; - WMSG1("NOTE: fixing zero dataLen in 'WOOF' image (set to %ld)\n", - fDataLen); - } + /* fix broken 'WOOF' images from Sweet-16 */ + if (fCreator == kCreatorSweet16 && fDataLen == 0 && + fImageFormat != kImageFormatNibble) + { + fDataLen = fNumBlocks * kBlockSize; + WMSG1("NOTE: fixing zero dataLen in 'WOOF' image (set to %ld)\n", + fDataLen); + } - /* - * Perform some sanity checks. - */ - if (fImageFormat != kImageFormatNibble && + /* + * Perform some sanity checks. + */ + if (fImageFormat != kImageFormatNibble && fNumBlocks * kBlockSize != fDataLen) { - WMSG2("numBlocks/dataLen mismatch (%ld vs %ld)\n", - fNumBlocks * kBlockSize, fDataLen); - return -1; - } - if (fDataLen + fDataOffset > totalLength) { - WMSG3("Invalid dataLen/offset/fileLength (dl=%ld, off=%ld, tlen=%ld)\n", - fDataLen, fDataOffset, totalLength); - return -1; - } + WMSG2("numBlocks/dataLen mismatch (%ld vs %ld)\n", + fNumBlocks * kBlockSize, fDataLen); + return -1; + } + if (fDataLen + fDataOffset > totalLength) { + WMSG3("Invalid dataLen/offset/fileLength (dl=%ld, off=%ld, tlen=%ld)\n", + fDataLen, fDataOffset, totalLength); + return -1; + } if (fImageFormat < kImageFormatDOS || fImageFormat > kImageFormatNibble) { WMSG1("Invalid image format %ld\n", fImageFormat); return -1; } - if (fCmtOffset > 0 && fCmtOffset < fDataOffset + fDataLen) { - WMSG2("2MG comment is inside the data section (off=%ld, data end=%ld)\n", - fCmtOffset, fDataOffset+fDataLen); - DebugBreak(); - // ignore the comment - fCmtOffset = 0; - fCmtLen = 0; - } - if (fCreatorOffset > 0 && fCreatorLen > 0) { - long prevEnd = fDataOffset + fDataLen + fCmtLen; + if (fCmtOffset > 0 && fCmtOffset < fDataOffset + fDataLen) { + WMSG2("2MG comment is inside the data section (off=%ld, data end=%ld)\n", + fCmtOffset, fDataOffset+fDataLen); + DebugBreak(); + // ignore the comment + fCmtOffset = 0; + fCmtLen = 0; + } + if (fCreatorOffset > 0 && fCreatorLen > 0) { + long prevEnd = fDataOffset + fDataLen + fCmtLen; - if (fCreatorOffset < prevEnd) { - WMSG2("2MG creator chunk is inside prev data (off=%ld, data end=%ld)\n", - fCreatorOffset, prevEnd); - DebugBreak(); - // ignore the creator chunk - fCreatorOffset = 0; - fCreatorLen = 0; - } - } + if (fCreatorOffset < prevEnd) { + WMSG2("2MG creator chunk is inside prev data (off=%ld, data end=%ld)\n", + fCreatorOffset, prevEnd); + DebugBreak(); + // ignore the creator chunk + fCreatorOffset = 0; + fCreatorLen = 0; + } + } return 0; } @@ -448,12 +448,12 @@ TwoImgHeader::UnpackHeader(const unsigned char* buf, long totalLength) int TwoImgHeader::WriteHeader(FILE* fp) const { - unsigned char buf[kOurHeaderLen]; + unsigned char buf[kOurHeaderLen]; - PackHeader(buf); - if (fwrite(buf, kOurHeaderLen, 1, fp) != 1) - return errno ? errno : -1; - return 0; + PackHeader(buf); + if (fwrite(buf, kOurHeaderLen, 1, fp) != 1) + return errno ? errno : -1; + return 0; } /* @@ -464,14 +464,14 @@ TwoImgHeader::WriteHeader(FILE* fp) const int TwoImgHeader::WriteHeader(GenericFD* pGFD) const { - unsigned char buf[kOurHeaderLen]; + unsigned char buf[kOurHeaderLen]; - PackHeader(buf); + PackHeader(buf); - if (pGFD->Write(buf, kOurHeaderLen) != kDIErrNone) - return -1; + if (pGFD->Write(buf, kOurHeaderLen) != kDIErrNone) + return -1; - return 0; + return 0; } /* @@ -480,18 +480,18 @@ TwoImgHeader::WriteHeader(GenericFD* pGFD) const int TwoImgHeader::WriteFooter(FILE* fp) const { - WMSG1("Writing footer at offset=%ld\n", (long) ftell(fp)); + WMSG1("Writing footer at offset=%ld\n", (long) ftell(fp)); - if (fCmtLen) { - fwrite(fComment, fCmtLen, 1, fp); - } - if (fCreatorLen) { - fwrite(fCreatorChunk, fCreatorLen, 1, fp); - } - if (ferror(fp)) - return errno ? errno : -1; + if (fCmtLen) { + fwrite(fComment, fCmtLen, 1, fp); + } + if (fCreatorLen) { + fwrite(fCreatorChunk, fCreatorLen, 1, fp); + } + if (ferror(fp)) + return errno ? errno : -1; - return 0; + return 0; } @@ -501,18 +501,18 @@ TwoImgHeader::WriteFooter(FILE* fp) const int TwoImgHeader::WriteFooter(GenericFD* pGFD) const { - WMSG1("Writing footer at offset=%ld\n", (long) pGFD->Tell()); + WMSG1("Writing footer at offset=%ld\n", (long) pGFD->Tell()); - if (fCmtLen) { - if (pGFD->Write(fComment, fCmtLen) != kDIErrNone) - return -1; - } - if (fCreatorLen) { - if (pGFD->Write(fCreatorChunk, fCreatorLen) != kDIErrNone) - return -1; - } + if (fCmtLen) { + if (pGFD->Write(fComment, fCmtLen) != kDIErrNone) + return -1; + } + if (fCreatorLen) { + if (pGFD->Write(fCreatorChunk, fCreatorLen) != kDIErrNone) + return -1; + } - return 0; + return 0; } /* @@ -521,30 +521,30 @@ TwoImgHeader::WriteFooter(GenericFD* pGFD) const void TwoImgHeader::PackHeader(unsigned char* buf) const { - if (fCmtLen > 0 && fCmtOffset == 0) { - assert(false); - } - if (fCreatorLen > 0 && fCreatorOffset == 0) { - assert(false); - } + if (fCmtLen > 0 && fCmtOffset == 0) { + assert(false); + } + if (fCreatorLen > 0 && fCreatorOffset == 0) { + assert(false); + } - PutLongBE(&buf[0x00], fMagic); - PutLongBE(&buf[0x04], fCreator); - PutShortLE(&buf[0x08], fHeaderLen); - PutShortLE(&buf[0x0a], fVersion); - PutLongLE(&buf[0x0c], fImageFormat); - PutLongLE(&buf[0x10], fFlags); - PutLongLE(&buf[0x14], fNumBlocks); - PutLongLE(&buf[0x18], fDataOffset); - PutLongLE(&buf[0x1c], fDataLen); - PutLongLE(&buf[0x20], fCmtOffset); - PutLongLE(&buf[0x24], fCmtLen); - PutLongLE(&buf[0x28], fCreatorOffset); - PutLongLE(&buf[0x2c], fCreatorLen); - PutLongLE(&buf[0x30], fSpare[0]); - PutLongLE(&buf[0x34], fSpare[1]); - PutLongLE(&buf[0x38], fSpare[2]); - PutLongLE(&buf[0x3c], fSpare[3]); + PutLongBE(&buf[0x00], fMagic); + PutLongBE(&buf[0x04], fCreator); + PutShortLE(&buf[0x08], fHeaderLen); + PutShortLE(&buf[0x0a], fVersion); + PutLongLE(&buf[0x0c], fImageFormat); + PutLongLE(&buf[0x10], fFlags); + PutLongLE(&buf[0x14], fNumBlocks); + PutLongLE(&buf[0x18], fDataOffset); + PutLongLE(&buf[0x1c], fDataLen); + PutLongLE(&buf[0x20], fCmtOffset); + PutLongLE(&buf[0x24], fCmtLen); + PutLongLE(&buf[0x28], fCreatorOffset); + PutLongLE(&buf[0x2c], fCreatorLen); + PutLongLE(&buf[0x30], fSpare[0]); + PutLongLE(&buf[0x34], fSpare[1]); + PutLongLE(&buf[0x38], fSpare[2]); + PutLongLE(&buf[0x3c], fSpare[3]); } /* @@ -553,24 +553,24 @@ TwoImgHeader::PackHeader(unsigned char* buf) const void TwoImgHeader::DumpHeader(void) const { - WMSG0("--- header contents:\n"); - WMSG2("\tmagic = '%s' (0x%08lx)\n", fMagicStr, fMagic); - WMSG2("\tcreator = '%s' (0x%08lx)\n", fCreatorStr, fCreator); - WMSG1("\theaderLen = %d\n", fHeaderLen); - WMSG1("\tversion = %d\n", fVersion); - WMSG1("\timageFormat = %ld\n", fImageFormat); - WMSG1("\tflags = 0x%08lx\n", fFlags); - WMSG1("\t locked = %s\n", - (fFlags & kFlagLocked) ? "true" : "false"); - WMSG2("\t DOS volume = %s (%ld)\n", - (fFlags & kDOSVolumeSet) ? "true" : "false", - fFlags & kDOSVolumeMask); - WMSG1("\tnumBlocks = %ld\n", fNumBlocks); - WMSG1("\tdataOffset = %ld\n", fDataOffset); - WMSG1("\tdataLen = %ld\n", fDataLen); - WMSG1("\tcmtOffset = %ld\n", fCmtOffset); - WMSG1("\tcmtLen = %ld\n", fCmtLen); - WMSG1("\tcreatorOffset = %ld\n", fCreatorOffset); - WMSG1("\tcreatorLen = %ld\n", fCreatorLen); - WMSG0("\n"); + WMSG0("--- header contents:\n"); + WMSG2("\tmagic = '%s' (0x%08lx)\n", fMagicStr, fMagic); + WMSG2("\tcreator = '%s' (0x%08lx)\n", fCreatorStr, fCreator); + WMSG1("\theaderLen = %d\n", fHeaderLen); + WMSG1("\tversion = %d\n", fVersion); + WMSG1("\timageFormat = %ld\n", fImageFormat); + WMSG1("\tflags = 0x%08lx\n", fFlags); + WMSG1("\t locked = %s\n", + (fFlags & kFlagLocked) ? "true" : "false"); + WMSG2("\t DOS volume = %s (%ld)\n", + (fFlags & kDOSVolumeSet) ? "true" : "false", + fFlags & kDOSVolumeMask); + WMSG1("\tnumBlocks = %ld\n", fNumBlocks); + WMSG1("\tdataOffset = %ld\n", fDataOffset); + WMSG1("\tdataLen = %ld\n", fDataLen); + WMSG1("\tcmtOffset = %ld\n", fCmtOffset); + WMSG1("\tcmtLen = %ld\n", fCmtLen); + WMSG1("\tcreatorOffset = %ld\n", fCreatorOffset); + WMSG1("\tcreatorLen = %ld\n", fCreatorLen); + WMSG0("\n"); } diff --git a/diskimg/TwoImg.h b/diskimg/TwoImg.h index 24fe562..669be82 100644 --- a/diskimg/TwoImg.h +++ b/diskimg/TwoImg.h @@ -22,33 +22,33 @@ namespace DiskImgLib { * as filetype $e0/$0130). * * Meaning of "flags": - * bit 31 : disk is "locked"; used by emulators as write-protect sticker. - * bit 8 : if set, bits 0-7 specify DOS 3.3 volume number - * bit 0-7: if bit 8 is set, use this as DOS volume; else use 254 + * bit 31 : disk is "locked"; used by emulators as write-protect sticker. + * bit 8 : if set, bits 0-7 specify DOS 3.3 volume number + * bit 0-7: if bit 8 is set, use this as DOS volume; else use 254 * * All values are stored little-endian. */ class DISKIMG_API TwoImgHeader { public: - TwoImgHeader(void) : fDOSVolumeNum(-1), fComment(NULL), fCreatorChunk(NULL) - {} - virtual ~TwoImgHeader(void) { - delete[] fComment; - delete[] fCreatorChunk; - } + TwoImgHeader(void) : fDOSVolumeNum(-1), fComment(NULL), fCreatorChunk(NULL) + {} + virtual ~TwoImgHeader(void) { + delete[] fComment; + delete[] fCreatorChunk; + } - /* - * Header fields. - */ + /* + * Header fields. + */ //char fMagic[4]; //char fCreator[4]; - unsigned long fMagic; - unsigned long fCreator; + unsigned long fMagic; + unsigned long fCreator; short fHeaderLen; short fVersion; long fImageFormat; - unsigned long fFlags; // may include DOS volume num - long fNumBlocks; // 512-byte blocks + unsigned long fFlags; // may include DOS volume num + long fNumBlocks; // 512-byte blocks long fDataOffset; long fDataLen; long fCmtOffset; @@ -57,80 +57,80 @@ public: long fCreatorLen; long fSpare[4]; - /* - * Related constants. - */ - enum { - // imageFormat - kImageFormatDOS = 0, - kImageFormatProDOS = 1, - kImageFormatNibble = 2, - // flags - kFlagLocked = (1L<<31), - kDOSVolumeSet = (1L<<8), - kDOSVolumeMask = (0xff), - kDefaultVolumeNum = 254, + /* + * Related constants. + */ + enum { + // imageFormat + kImageFormatDOS = 0, + kImageFormatProDOS = 1, + kImageFormatNibble = 2, + // flags + kFlagLocked = (1L<<31), + kDOSVolumeSet = (1L<<8), + kDOSVolumeMask = (0xff), + kDefaultVolumeNum = 254, - // constants used when creating a new header - kOurHeaderLen = 64, - kOurVersion = 1, + // constants used when creating a new header + kOurHeaderLen = 64, + kOurVersion = 1, - kBlockSize = 512, - kMagic = 0x32494d47, // 2IMG - kCreatorCiderPress = 0x43647250, // CdrP - kCreatorSweet16 = 0x574f4f46, // WOOF - }; + kBlockSize = 512, + kMagic = 0x32494d47, // 2IMG + kCreatorCiderPress = 0x43647250, // CdrP + kCreatorSweet16 = 0x574f4f46, // WOOF + }; - /* - * Basic functions. - * - * The read header function will read the comment, but the write - * header function will not. This is because the GenericFD functions - * don't allow seeking past the current EOF. - * - * ReadHeader/WriteHeader expect the file to be seeked to the initial - * offset. WriteFooter expects the file to be seeked just past the - * end of the data section. This is done in case the file has some - * sort of wrapper outside the 2MG header. - */ + /* + * Basic functions. + * + * The read header function will read the comment, but the write + * header function will not. This is because the GenericFD functions + * don't allow seeking past the current EOF. + * + * ReadHeader/WriteHeader expect the file to be seeked to the initial + * offset. WriteFooter expects the file to be seeked just past the + * end of the data section. This is done in case the file has some + * sort of wrapper outside the 2MG header. + */ int InitHeader(int imageFormat, long imageSize, long imageBlockCount); - int ReadHeader(FILE* fp, long totalLength); - int ReadHeader(GenericFD* pGFD, long totalLength); - int WriteHeader(FILE* fp) const; - int WriteHeader(GenericFD* pGFD) const; - int WriteFooter(FILE* fp) const; - int WriteFooter(GenericFD* pGFD) const; - void DumpHeader(void) const; // for debugging + int ReadHeader(FILE* fp, long totalLength); + int ReadHeader(GenericFD* pGFD, long totalLength); + int WriteHeader(FILE* fp) const; + int WriteHeader(GenericFD* pGFD) const; + int WriteFooter(FILE* fp) const; + int WriteFooter(GenericFD* pGFD) const; + void DumpHeader(void) const; // for debugging - /* - * Getters & setters. - */ - const char* GetMagicStr(void) const { return fMagicStr; } - const char* GetCreatorStr(void) const { return fCreatorStr; } + /* + * Getters & setters. + */ + const char* GetMagicStr(void) const { return fMagicStr; } + const char* GetCreatorStr(void) const { return fCreatorStr; } short GetDOSVolumeNum(void) const; void SetDOSVolumeNum(short dosVolumeNum); - const char* GetComment(void) const { return fComment; } - void SetComment(const char* comment); - const void* GetCreatorChunk(void) const { return fCreatorChunk; } - void SetCreatorChunk(const void* creatorBlock, long len); + const char* GetComment(void) const { return fComment; } + void SetComment(const char* comment); + const void* GetCreatorChunk(void) const { return fCreatorChunk; } + void SetCreatorChunk(const void* creatorBlock, long len); private: - int UnpackHeader(const unsigned char* buf, long totalLength); - void PackHeader(unsigned char* buf) const; - int GetChunk(GenericFD* pGFD, di_off_t relOffset, long len, - void** pBuf); - int GetChunk(FILE* fp, di_off_t relOffset, long len, - void** pBuf); + int UnpackHeader(const unsigned char* buf, long totalLength); + void PackHeader(unsigned char* buf) const; + int GetChunk(GenericFD* pGFD, di_off_t relOffset, long len, + void** pBuf); + int GetChunk(FILE* fp, di_off_t relOffset, long len, + void** pBuf); - int fDOSVolumeNum; - char fMagicStr[5]; - char fCreatorStr[5]; + int fDOSVolumeNum; + char fMagicStr[5]; + char fCreatorStr[5]; - char* fComment; - char* fCreatorChunk; + char* fComment; + char* fCreatorChunk; }; -}; // namespace DiskImgLib +}; // namespace DiskImgLib #endif /*TWOIMG*/ diff --git a/diskimg/UNIDOS.cpp b/diskimg/UNIDOS.cpp index 850bc39..d2a0c5a 100644 --- a/diskimg/UNIDOS.cpp +++ b/diskimg/UNIDOS.cpp @@ -20,7 +20,7 @@ /* * =========================================================================== - * DiskFSUNIDOS + * DiskFSUNIDOS * =========================================================================== */ @@ -31,10 +31,10 @@ const int kVTOCTrack = 17; const int kVTOCSector = 0; const int kSctSize = 256; -const int kCatalogEntrySize = 0x23; // length in bytes of catalog entries -const int kCatalogEntriesPerSect = 7; // #of entries per catalog sector -const int kMaxTSPairs = 0x7a; // 122 entries for 256-byte sectors -const int kTSOffset = 0x0c; // first T/S entry in a T/S list +const int kCatalogEntrySize = 0x23; // length in bytes of catalog entries +const int kCatalogEntriesPerSect = 7; // #of entries per catalog sector +const int kMaxTSPairs = 0x7a; // 122 entries for 256-byte sectors +const int kTSOffset = 0x0c; // first T/S entry in a T/S list const int kMaxTSIterations = 32; const int kMaxCatalogIterations = 64; @@ -46,16 +46,16 @@ const int kMaxCatalogIterations = 64; */ static DIError ReadTrackSectorAdjusted(DiskImg* pImg, int track, int sector, - int trackOffset, unsigned char* buf, DiskImg::SectorOrder imageOrder) + int trackOffset, unsigned char* buf, DiskImg::SectorOrder imageOrder) { - track += trackOffset; - track *= 2; - if (sector >= 16) { - track++; - sector -= 16; - } - return pImg->ReadTrackSectorSwapped(track, sector, buf, imageOrder, - DiskImg::kSectorOrderDOS); + track += trackOffset; + track *= 2; + if (sector >= 16) { + track++; + sector -= 16; + } + return pImg->ReadTrackSectorSwapped(track, sector, buf, imageOrder, + DiskImg::kSectorOrderDOS); } /* @@ -63,78 +63,78 @@ ReadTrackSectorAdjusted(DiskImg* pImg, int track, int sector, */ static DIError TestImageHalf(DiskImg* pImg, int trackOffset, DiskImg::SectorOrder imageOrder, - int* pGoodCount) + int* pGoodCount) { - DIError dierr = kDIErrNone; - unsigned char sctBuf[kSctSize]; - int numTracks, numSectors; - int catTrack, catSect; - int foundGood = 0; - int iterations = 0; + DIError dierr = kDIErrNone; + unsigned char sctBuf[kSctSize]; + int numTracks, numSectors; + int catTrack, catSect; + int foundGood = 0; + int iterations = 0; - *pGoodCount = 0; + *pGoodCount = 0; - dierr = ReadTrackSectorAdjusted(pImg, kVTOCTrack, kVTOCSector, - trackOffset, sctBuf, imageOrder); - if (dierr != kDIErrNone) - goto bail; + dierr = ReadTrackSectorAdjusted(pImg, kVTOCTrack, kVTOCSector, + trackOffset, sctBuf, imageOrder); + if (dierr != kDIErrNone) + goto bail; - catTrack = sctBuf[0x01]; - catSect = sctBuf[0x02]; - numTracks = sctBuf[0x34]; - numSectors = sctBuf[0x35]; + catTrack = sctBuf[0x01]; + catSect = sctBuf[0x02]; + numTracks = sctBuf[0x34]; + numSectors = sctBuf[0x35]; - if (!(sctBuf[0x27] == kMaxTSPairs) || - /*!(sctBuf[0x36] == 0 && sctBuf[0x37] == 1) ||*/ // bytes per sect - !(numTracks == kExpectedTracks) || - !(numSectors == 32) || - !(catTrack < numTracks && catSect < numSectors) || - 0) - { - WMSG0(" UNI/Wide DOS header test failed\n"); - dierr = kDIErrFilesystemNotFound; - goto bail; - } + if (!(sctBuf[0x27] == kMaxTSPairs) || + /*!(sctBuf[0x36] == 0 && sctBuf[0x37] == 1) ||*/ // bytes per sect + !(numTracks == kExpectedTracks) || + !(numSectors == 32) || + !(catTrack < numTracks && catSect < numSectors) || + 0) + { + WMSG0(" UNI/Wide DOS header test failed\n"); + dierr = kDIErrFilesystemNotFound; + goto bail; + } - foundGood++; // score one for a valid-looking VTOC + foundGood++; // score one for a valid-looking VTOC - /* - * Walk through the catalog track to try to figure out ordering. - */ - while (catTrack != 0 && catSect != 0 && - iterations < DiskFSDOS33::kMaxCatalogSectors) - { - dierr = ReadTrackSectorAdjusted(pImg, catTrack, catSect, - trackOffset, sctBuf, imageOrder); - if (dierr != kDIErrNone) { - dierr = kDIErrNone; - break; /* allow it if earlier stuff was okay */ - } + /* + * Walk through the catalog track to try to figure out ordering. + */ + while (catTrack != 0 && catSect != 0 && + iterations < DiskFSDOS33::kMaxCatalogSectors) + { + dierr = ReadTrackSectorAdjusted(pImg, catTrack, catSect, + trackOffset, sctBuf, imageOrder); + if (dierr != kDIErrNone) { + dierr = kDIErrNone; + break; /* allow it if earlier stuff was okay */ + } - if (catTrack == sctBuf[1] && catSect == sctBuf[2] +1) - foundGood++; - else if (catTrack == sctBuf[1] && catSect == sctBuf[2]) { - WMSG2(" WideDOS detected self-reference on cat (%d,%d)\n", - catTrack, catSect); - break; - } + if (catTrack == sctBuf[1] && catSect == sctBuf[2] +1) + foundGood++; + else if (catTrack == sctBuf[1] && catSect == sctBuf[2]) { + WMSG2(" WideDOS detected self-reference on cat (%d,%d)\n", + catTrack, catSect); + break; + } - catTrack = sctBuf[1]; - catSect = sctBuf[2]; - iterations++; // watch for infinite loops - } - if (iterations >= DiskFSDOS33::kMaxCatalogSectors) { - dierr = kDIErrDirectoryLoop; - WMSG0(" WideDOS directory links cause a loop\n"); - goto bail; - } + catTrack = sctBuf[1]; + catSect = sctBuf[2]; + iterations++; // watch for infinite loops + } + if (iterations >= DiskFSDOS33::kMaxCatalogSectors) { + dierr = kDIErrDirectoryLoop; + WMSG0(" WideDOS directory links cause a loop\n"); + goto bail; + } - WMSG3(" WideDOS foundGood=%d off=%d swap=%d\n", foundGood, - trackOffset, imageOrder); - *pGoodCount = foundGood; + WMSG3(" WideDOS foundGood=%d off=%d swap=%d\n", foundGood, + trackOffset, imageOrder); + *pGoodCount = foundGood; bail: - return dierr; + return dierr; } /* @@ -143,27 +143,27 @@ bail: static DIError TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder, int* pGoodCount) { - DIError dierr; - int goodCount1, goodCount2; + DIError dierr; + int goodCount1, goodCount2; - *pGoodCount = 0; + *pGoodCount = 0; - WMSG1(" UNIDOS checking first half (imageOrder=%d)\n", imageOrder); - dierr = TestImageHalf(pImg, 0, imageOrder, &goodCount1); - if (dierr != kDIErrNone) - return dierr; + WMSG1(" UNIDOS checking first half (imageOrder=%d)\n", imageOrder); + dierr = TestImageHalf(pImg, 0, imageOrder, &goodCount1); + if (dierr != kDIErrNone) + return dierr; - WMSG1(" UNIDOS checking second half (imageOrder=%d)\n", imageOrder); - dierr = TestImageHalf(pImg, kExpectedTracks, imageOrder, &goodCount2); - if (dierr != kDIErrNone) - return dierr; + WMSG1(" UNIDOS checking second half (imageOrder=%d)\n", imageOrder); + dierr = TestImageHalf(pImg, kExpectedTracks, imageOrder, &goodCount2); + if (dierr != kDIErrNone) + return dierr; - if (goodCount1 > goodCount2) - *pGoodCount = goodCount1; - else - *pGoodCount = goodCount2; + if (goodCount1 > goodCount2) + *pGoodCount = goodCount1; + else + *pGoodCount = goodCount2; - return kDIErrNone; + return kDIErrNone; } /* @@ -173,42 +173,42 @@ TestImage(DiskImg* pImg, DiskImg::SectorOrder imageOrder, int* pGoodCount) DiskFSUNIDOS::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DiskImg::FSFormat* pFormat, FSLeniency leniency) { - /* only on 800K disks (at the least, insist on numTracks being even) */ - if (pImg->GetNumBlocks() != kExpectedNumBlocks) - return kDIErrFilesystemNotFound; + /* only on 800K disks (at the least, insist on numTracks being even) */ + if (pImg->GetNumBlocks() != kExpectedNumBlocks) + return kDIErrFilesystemNotFound; - DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; - - DiskImg::GetSectorOrderArray(ordering, *pOrder); + DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; + + DiskImg::GetSectorOrderArray(ordering, *pOrder); - DiskImg::SectorOrder bestOrder = DiskImg::kSectorOrderUnknown; - int bestCount = 0; + DiskImg::SectorOrder bestOrder = DiskImg::kSectorOrderUnknown; + int bestCount = 0; - for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { - int goodCount = 0; + for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { + int goodCount = 0; - if (ordering[i] == DiskImg::kSectorOrderUnknown) - continue; - if (TestImage(pImg, ordering[i], &goodCount) == kDIErrNone) { - if (goodCount > bestCount) { - bestCount = goodCount; - bestOrder = ordering[i]; - } - } - } + if (ordering[i] == DiskImg::kSectorOrderUnknown) + continue; + if (TestImage(pImg, ordering[i], &goodCount) == kDIErrNone) { + if (goodCount > bestCount) { + bestCount = goodCount; + bestOrder = ordering[i]; + } + } + } - if (bestCount >= 4 || - (leniency == kLeniencyVery && bestCount >= 2)) - { - WMSG2(" WideDOS test: bestCount=%d for order=%d\n", bestCount, bestOrder); - assert(bestOrder != DiskImg::kSectorOrderUnknown); - *pOrder = bestOrder; - *pFormat = DiskImg::kFormatUNIDOS; - return kDIErrNone; - } + if (bestCount >= 4 || + (leniency == kLeniencyVery && bestCount >= 2)) + { + WMSG2(" WideDOS test: bestCount=%d for order=%d\n", bestCount, bestOrder); + assert(bestOrder != DiskImg::kSectorOrderUnknown); + *pOrder = bestOrder; + *pFormat = DiskImg::kFormatUNIDOS; + return kDIErrNone; + } - WMSG0(" UNIDOS didn't find valid FS\n"); - return kDIErrFilesystemNotFound; + WMSG0(" UNIDOS didn't find valid FS\n"); + return kDIErrFilesystemNotFound; } /* @@ -223,46 +223,46 @@ DiskFSUNIDOS::TestFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DiskFSUNIDOS::TestWideFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DiskImg::FSFormat* pFormat, FSLeniency leniency) { - /* only on 400K "disks" */ - if (pImg->GetNumBlocks() != kExpectedNumBlocks/2) { - WMSG1(" WideDOS ignoring volume (numBlocks=%ld)\n", - pImg->GetNumBlocks()); - return kDIErrFilesystemNotFound; - } + /* only on 400K "disks" */ + if (pImg->GetNumBlocks() != kExpectedNumBlocks/2) { + WMSG1(" WideDOS ignoring volume (numBlocks=%ld)\n", + pImg->GetNumBlocks()); + return kDIErrFilesystemNotFound; + } - DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; - - DiskImg::GetSectorOrderArray(ordering, *pOrder); + DiskImg::SectorOrder ordering[DiskImg::kSectorOrderMax]; + + DiskImg::GetSectorOrderArray(ordering, *pOrder); - DiskImg::SectorOrder bestOrder = DiskImg::kSectorOrderUnknown; - int bestCount = 0; + DiskImg::SectorOrder bestOrder = DiskImg::kSectorOrderUnknown; + int bestCount = 0; - for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { - int goodCount = 0; + for (int i = 0; i < DiskImg::kSectorOrderMax; i++) { + int goodCount = 0; - if (ordering[i] == DiskImg::kSectorOrderUnknown) - continue; - if (TestImageHalf(pImg, 0, ordering[i], &goodCount) == kDIErrNone) { - if (goodCount > bestCount) { - bestCount = goodCount; - bestOrder = ordering[i]; - } - } - } + if (ordering[i] == DiskImg::kSectorOrderUnknown) + continue; + if (TestImageHalf(pImg, 0, ordering[i], &goodCount) == kDIErrNone) { + if (goodCount > bestCount) { + bestCount = goodCount; + bestOrder = ordering[i]; + } + } + } - if (bestCount >= 4 || - (leniency == kLeniencyVery && bestCount >= 2)) - { - WMSG2(" UNI/Wide test: bestCount=%d for order=%d\n", bestCount, bestOrder); - assert(bestOrder != DiskImg::kSectorOrderUnknown); - *pOrder = bestOrder; - *pFormat = DiskImg::kFormatDOS33; - // up to the caller to adjust numTracks/numSectPerTrack - return kDIErrNone; - } + if (bestCount >= 4 || + (leniency == kLeniencyVery && bestCount >= 2)) + { + WMSG2(" UNI/Wide test: bestCount=%d for order=%d\n", bestCount, bestOrder); + assert(bestOrder != DiskImg::kSectorOrderUnknown); + *pOrder = bestOrder; + *pFormat = DiskImg::kFormatDOS33; + // up to the caller to adjust numTracks/numSectPerTrack + return kDIErrNone; + } - WMSG0(" UNI/Wide didn't find valid FS\n"); - return kDIErrFilesystemNotFound; + WMSG0(" UNI/Wide didn't find valid FS\n"); + return kDIErrFilesystemNotFound; } @@ -272,23 +272,23 @@ DiskFSUNIDOS::TestWideFS(DiskImg* pImg, DiskImg::SectorOrder* pOrder, DIError DiskFSUNIDOS::Initialize(void) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - if (fScanForSubVolumes != kScanSubDisabled) { - dierr = OpenSubVolume(0); - if (dierr != kDIErrNone) - return dierr; + if (fScanForSubVolumes != kScanSubDisabled) { + dierr = OpenSubVolume(0); + if (dierr != kDIErrNone) + return dierr; - dierr = OpenSubVolume(1); - if (dierr != kDIErrNone) - return dierr; - } else { - WMSG0(" UNIDOS not scanning for sub-volumes\n"); - } + dierr = OpenSubVolume(1); + if (dierr != kDIErrNone) + return dierr; + } else { + WMSG0(" UNIDOS not scanning for sub-volumes\n"); + } - SetVolumeUsageMap(); + SetVolumeUsageMap(); - return kDIErrNone; + return kDIErrNone; } /* @@ -297,69 +297,69 @@ DiskFSUNIDOS::Initialize(void) DIError DiskFSUNIDOS::OpenSubVolume(int idx) { - DIError dierr = kDIErrNone; - DiskFS* pNewFS = nil; - DiskImg* pNewImg = nil; - - pNewImg = new DiskImg; - if (pNewImg == nil) { - dierr = kDIErrMalloc; - goto bail; - } + DIError dierr = kDIErrNone; + DiskFS* pNewFS = nil; + DiskImg* pNewImg = nil; + + pNewImg = new DiskImg; + if (pNewImg == nil) { + dierr = kDIErrMalloc; + goto bail; + } - dierr = pNewImg->OpenImage(fpImg, kExpectedTracks * idx, 0, - kExpectedTracks * kExpectedSectors); - if (dierr != kDIErrNone) { - WMSG3(" UNISub: OpenImage(%d,0,%d) failed (err=%d)\n", - kExpectedTracks * idx, kExpectedTracks * kExpectedSectors, dierr); - goto bail; - } + dierr = pNewImg->OpenImage(fpImg, kExpectedTracks * idx, 0, + kExpectedTracks * kExpectedSectors); + if (dierr != kDIErrNone) { + WMSG3(" UNISub: OpenImage(%d,0,%d) failed (err=%d)\n", + kExpectedTracks * idx, kExpectedTracks * kExpectedSectors, dierr); + goto bail; + } - dierr = pNewImg->AnalyzeImage(); - if (dierr != kDIErrNone) { - WMSG1(" UNISub: analysis failed (err=%d)\n", dierr); - goto bail; - } + dierr = pNewImg->AnalyzeImage(); + if (dierr != kDIErrNone) { + WMSG1(" UNISub: analysis failed (err=%d)\n", dierr); + goto bail; + } - if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || - pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) - { - WMSG0(" UNISub: unable to identify filesystem\n"); - dierr = kDIErrUnsupportedFSFmt; - goto bail; - } + if (pNewImg->GetFSFormat() == DiskImg::kFormatUnknown || + pNewImg->GetSectorOrder() == DiskImg::kSectorOrderUnknown) + { + WMSG0(" UNISub: unable to identify filesystem\n"); + dierr = kDIErrUnsupportedFSFmt; + goto bail; + } - /* open a DiskFS for the sub-image */ - WMSG1(" UNISub %d succeeded!\n", idx); - pNewFS = pNewImg->OpenAppropriateDiskFS(); - if (pNewFS == nil) { - WMSG0(" UNISub: OpenAppropriateDiskFS failed\n"); - dierr = kDIErrUnsupportedFSFmt; - goto bail; - } + /* open a DiskFS for the sub-image */ + WMSG1(" UNISub %d succeeded!\n", idx); + pNewFS = pNewImg->OpenAppropriateDiskFS(); + if (pNewFS == nil) { + WMSG0(" UNISub: OpenAppropriateDiskFS failed\n"); + dierr = kDIErrUnsupportedFSFmt; + goto bail; + } - /* load the files from the sub-image */ - dierr = pNewFS->Initialize(pNewImg, kInitFull); - if (dierr != kDIErrNone) { - WMSG1(" UNISub: error %d reading list of files from disk", dierr); - goto bail; - } + /* load the files from the sub-image */ + dierr = pNewFS->Initialize(pNewImg, kInitFull); + if (dierr != kDIErrNone) { + WMSG1(" UNISub: error %d reading list of files from disk", dierr); + goto bail; + } - /* if this really is DOS 3.3, override the "volume name" */ - if (pNewImg->GetFSFormat() == DiskImg::kFormatDOS33) { - DiskFSDOS33* pDOS = (DiskFSDOS33*) pNewFS; /* eek, a downcast */ - pDOS->SetDiskVolumeNum(idx+1); - } + /* if this really is DOS 3.3, override the "volume name" */ + if (pNewImg->GetFSFormat() == DiskImg::kFormatDOS33) { + DiskFSDOS33* pDOS = (DiskFSDOS33*) pNewFS; /* eek, a downcast */ + pDOS->SetDiskVolumeNum(idx+1); + } - /* - * Success, add it to the sub-volume list. - */ - AddSubVolumeToList(pNewImg, pNewFS); + /* + * Success, add it to the sub-volume list. + */ + AddSubVolumeToList(pNewImg, pNewFS); bail: - if (dierr != kDIErrNone) { - delete pNewFS; - delete pNewImg; - } - return dierr; + if (dierr != kDIErrNone) { + delete pNewFS; + delete pNewImg; + } + return dierr; } diff --git a/diskimg/VolumeUsage.cpp b/diskimg/VolumeUsage.cpp index 7c49bc0..41f91b9 100644 --- a/diskimg/VolumeUsage.cpp +++ b/diskimg/VolumeUsage.cpp @@ -16,20 +16,20 @@ DIError DiskFS::VolumeUsage::Create(long numBlocks) { - if (numBlocks <= 0 || numBlocks > 32*1024*1024) // 16GB - return kDIErrInvalidArg; + if (numBlocks <= 0 || numBlocks > 32*1024*1024) // 16GB + return kDIErrInvalidArg; - fByBlocks = true; - fNumSectors = -1; - fTotalChunks = numBlocks; - fListSize = numBlocks; - fList = new unsigned char[fListSize]; - if (fList == nil) - return kDIErrMalloc; + fByBlocks = true; + fNumSectors = -1; + fTotalChunks = numBlocks; + fListSize = numBlocks; + fList = new unsigned char[fListSize]; + if (fList == nil) + return kDIErrMalloc; - memset(fList, 0, fListSize); + memset(fList, 0, fListSize); - return kDIErrNone; + return kDIErrNone; } /* @@ -38,21 +38,21 @@ DiskFS::VolumeUsage::Create(long numBlocks) DIError DiskFS::VolumeUsage::Create(long numTracks, long numSectors) { - long count = numTracks * numSectors; - if (numTracks <= 0 || count <= 0 || count > 32*1024*1024) - return kDIErrInvalidArg; + long count = numTracks * numSectors; + if (numTracks <= 0 || count <= 0 || count > 32*1024*1024) + return kDIErrInvalidArg; - fByBlocks = false; - fNumSectors = numSectors; - fTotalChunks = count; - fListSize = count; - fList = new unsigned char[fListSize]; - if (fList == nil) - return kDIErrMalloc; + fByBlocks = false; + fNumSectors = numSectors; + fTotalChunks = count; + fListSize = count; + fList = new unsigned char[fListSize]; + if (fList == nil) + return kDIErrMalloc; - memset(fList, 0, fListSize); + memset(fList, 0, fListSize); - return kDIErrNone; + return kDIErrNone; } /* @@ -61,34 +61,34 @@ DiskFS::VolumeUsage::Create(long numTracks, long numSectors) DIError DiskFS::VolumeUsage::GetChunkState(long block, ChunkState* pState) const { - if (!fByBlocks) - return kDIErrInvalidArg; - return GetChunkStateIdx(block, pState); + if (!fByBlocks) + return kDIErrInvalidArg; + return GetChunkStateIdx(block, pState); } DIError DiskFS::VolumeUsage::GetChunkState(long track, long sector, - ChunkState* pState) const + ChunkState* pState) const { - if (fByBlocks) - return kDIErrInvalidArg; - if (track < 0 || sector < 0 || sector >= fNumSectors) - return kDIErrInvalidArg; - return GetChunkStateIdx(track * fNumSectors + sector, pState); + if (fByBlocks) + return kDIErrInvalidArg; + if (track < 0 || sector < 0 || sector >= fNumSectors) + return kDIErrInvalidArg; + return GetChunkStateIdx(track * fNumSectors + sector, pState); } DIError DiskFS::VolumeUsage::GetChunkStateIdx(int idx, ChunkState* pState) const { - if (fList == nil || idx < 0 || idx >= fListSize) { - assert(false); - return kDIErrInvalidArg; - } + if (fList == nil || idx < 0 || idx >= fListSize) { + assert(false); + return kDIErrInvalidArg; + } - unsigned char val = fList[idx]; - pState->isUsed = (val & kChunkUsedFlag) != 0; - pState->isMarkedUsed = (val & kChunkMarkedUsedFlag) != 0; - pState->purpose = (ChunkPurpose)(val & kChunkPurposeMask); + unsigned char val = fList[idx]; + pState->isUsed = (val & kChunkUsedFlag) != 0; + pState->isMarkedUsed = (val & kChunkMarkedUsedFlag) != 0; + pState->purpose = (ChunkPurpose)(val & kChunkPurposeMask); - return kDIErrNone; + return kDIErrNone; } /* @@ -97,43 +97,43 @@ DiskFS::VolumeUsage::GetChunkStateIdx(int idx, ChunkState* pState) const DIError DiskFS::VolumeUsage::SetChunkState(long block, const ChunkState* pState) { - if (!fByBlocks) - return kDIErrInvalidArg; - return SetChunkStateIdx(block, pState); + if (!fByBlocks) + return kDIErrInvalidArg; + return SetChunkStateIdx(block, pState); } DIError DiskFS::VolumeUsage::SetChunkState(long track, long sector, - const ChunkState* pState) + const ChunkState* pState) { - if (fByBlocks) - return kDIErrInvalidArg; - if (track < 0 || sector < 0 || sector >= fNumSectors) - return kDIErrInvalidArg; - return SetChunkStateIdx(track * fNumSectors + sector, pState); + if (fByBlocks) + return kDIErrInvalidArg; + if (track < 0 || sector < 0 || sector >= fNumSectors) + return kDIErrInvalidArg; + return SetChunkStateIdx(track * fNumSectors + sector, pState); } DIError DiskFS::VolumeUsage::SetChunkStateIdx(int idx, const ChunkState* pState) { - if (fList == nil || idx < 0 || idx >= fListSize) { - assert(false); - return kDIErrInvalidArg; - } + if (fList == nil || idx < 0 || idx >= fListSize) { + assert(false); + return kDIErrInvalidArg; + } - unsigned char val = 0; - if (pState->isUsed) { - if ((pState->purpose & ~kChunkPurposeMask) != 0) { - assert(false); - return kDIErrInvalidArg; - } - val |= kChunkUsedFlag; - val |= (int)pState->purpose; - } - if (pState->isMarkedUsed) - val |= kChunkMarkedUsedFlag; + unsigned char val = 0; + if (pState->isUsed) { + if ((pState->purpose & ~kChunkPurposeMask) != 0) { + assert(false); + return kDIErrInvalidArg; + } + val |= kChunkUsedFlag; + val |= (int)pState->purpose; + } + if (pState->isMarkedUsed) + val |= kChunkMarkedUsedFlag; - fList[idx] = val; + fList[idx] = val; - return kDIErrNone; + return kDIErrNone; } @@ -143,31 +143,31 @@ DiskFS::VolumeUsage::SetChunkStateIdx(int idx, const ChunkState* pState) long DiskFS::VolumeUsage::GetActualFreeChunks(void) const { - ChunkState cstate; // could probably do this bitwise... - int freeCount = 0; - int funkyCount = 0; + ChunkState cstate; // could probably do this bitwise... + int freeCount = 0; + int funkyCount = 0; - for (int i = 0; i < fTotalChunks; i++) { - if (GetChunkStateIdx(i, &cstate) != kDIErrNone) { - assert(false); - return -1; - } + for (int i = 0; i < fTotalChunks; i++) { + if (GetChunkStateIdx(i, &cstate) != kDIErrNone) { + assert(false); + return -1; + } - if (!cstate.isUsed && !cstate.isMarkedUsed) - freeCount++; + if (!cstate.isUsed && !cstate.isMarkedUsed) + freeCount++; - if ((!cstate.isUsed && cstate.isMarkedUsed) || - (cstate.isUsed && !cstate.isMarkedUsed) || - (cstate.isUsed && cstate.purpose == kChunkPurposeConflict)) - { - funkyCount++; - } - } + if ((!cstate.isUsed && cstate.isMarkedUsed) || + (cstate.isUsed && !cstate.isMarkedUsed) || + (cstate.isUsed && cstate.purpose == kChunkPurposeConflict)) + { + funkyCount++; + } + } - WMSG3(" VU total=%ld free=%d funky=%d\n", - fTotalChunks, freeCount, funkyCount); + WMSG3(" VU total=%ld free=%d funky=%d\n", + fTotalChunks, freeCount, funkyCount); - return freeCount; + return freeCount; } @@ -175,43 +175,43 @@ DiskFS::VolumeUsage::GetActualFreeChunks(void) const * Convert a ChunkState into a single, hopefully meaningful, character. * * Possible states: - * '.' - !inuse, !marked (free space) - * 'X' - !inuse, marked (could be embedded volume) - * '!' - inuse, !marked (danger!) - * '#' - inuse, marked, used by more than one thing - * 'S' - inuse, marked, used by system (directories, volume bit map) - * 'I' - inuse, marked, used by file structure (index block) - * 'F' - inuse, marked, used by file + * '.' - !inuse, !marked (free space) + * 'X' - !inuse, marked (could be embedded volume) + * '!' - inuse, !marked (danger!) + * '#' - inuse, marked, used by more than one thing + * 'S' - inuse, marked, used by system (directories, volume bit map) + * 'I' - inuse, marked, used by file structure (index block) + * 'F' - inuse, marked, used by file */ inline char DiskFS::VolumeUsage::StateToChar(ChunkState* pState) const { - if (!pState->isUsed && !pState->isMarkedUsed) - return '.'; - if (!pState->isUsed && pState->isMarkedUsed) - return 'X'; - if (pState->isUsed && !pState->isMarkedUsed) - return '!'; - assert(pState->isUsed && pState->isMarkedUsed); - if (pState->purpose == kChunkPurposeUnknown) - return '?'; - if (pState->purpose == kChunkPurposeConflict) - return '#'; - if (pState->purpose == kChunkPurposeSystem) - return 'S'; - if (pState->purpose == kChunkPurposeVolumeDir) - return 'V'; - if (pState->purpose == kChunkPurposeSubdir) - return 'D'; - if (pState->purpose == kChunkPurposeUserData) - return 'F'; - if (pState->purpose == kChunkPurposeFileStruct) - return 'I'; - if (pState->purpose == kChunkPurposeEmbedded) - return 'E'; + if (!pState->isUsed && !pState->isMarkedUsed) + return '.'; + if (!pState->isUsed && pState->isMarkedUsed) + return 'X'; + if (pState->isUsed && !pState->isMarkedUsed) + return '!'; + assert(pState->isUsed && pState->isMarkedUsed); + if (pState->purpose == kChunkPurposeUnknown) + return '?'; + if (pState->purpose == kChunkPurposeConflict) + return '#'; + if (pState->purpose == kChunkPurposeSystem) + return 'S'; + if (pState->purpose == kChunkPurposeVolumeDir) + return 'V'; + if (pState->purpose == kChunkPurposeSubdir) + return 'D'; + if (pState->purpose == kChunkPurposeUserData) + return 'F'; + if (pState->purpose == kChunkPurposeFileStruct) + return 'I'; + if (pState->purpose == kChunkPurposeEmbedded) + return 'E'; - assert(false); - return '?'; + assert(false); + return '?'; } /* @@ -221,58 +221,58 @@ void DiskFS::VolumeUsage::Dump(void) const { #define kMapInit "--------------------------------" - if (fList == nil) { - WMSG0(" VU asked to dump empty list?\n"); - return; - } + if (fList == nil) { + WMSG0(" VU asked to dump empty list?\n"); + return; + } - WMSG1(" VU VolumeUsage dump (%ld free chunks):\n", - GetActualFreeChunks()); + WMSG1(" VU VolumeUsage dump (%ld free chunks):\n", + GetActualFreeChunks()); - if (fByBlocks) { - ChunkState cstate; - char freemap[32+1] = kMapInit; - int block; - const int kEntriesPerLine = 32; // use 20 to match Copy][+ + if (fByBlocks) { + ChunkState cstate; + char freemap[32+1] = kMapInit; + int block; + const int kEntriesPerLine = 32; // use 20 to match Copy][+ - for (block = 0; block < fTotalChunks; block++) { - if (GetChunkState(block, &cstate) != kDIErrNone) { - assert(false); - return; - } + for (block = 0; block < fTotalChunks; block++) { + if (GetChunkState(block, &cstate) != kDIErrNone) { + assert(false); + return; + } - freemap[block % kEntriesPerLine] = StateToChar(&cstate); - if ((block % kEntriesPerLine) == kEntriesPerLine-1) { - WMSG2(" 0x%04x: %s\n", block-(kEntriesPerLine-1), freemap); - } - } - if ((block % kEntriesPerLine) != 0) { - memset(freemap + (block % kEntriesPerLine), '-', - kEntriesPerLine - (block % kEntriesPerLine)); - WMSG2(" 0x%04x: %s\n", block-(kEntriesPerLine-1), freemap); - } - } else { - ChunkState cstate; - char freemap[32+1] = kMapInit; - long numTracks = fTotalChunks / fNumSectors; - int track, sector; + freemap[block % kEntriesPerLine] = StateToChar(&cstate); + if ((block % kEntriesPerLine) == kEntriesPerLine-1) { + WMSG2(" 0x%04x: %s\n", block-(kEntriesPerLine-1), freemap); + } + } + if ((block % kEntriesPerLine) != 0) { + memset(freemap + (block % kEntriesPerLine), '-', + kEntriesPerLine - (block % kEntriesPerLine)); + WMSG2(" 0x%04x: %s\n", block-(kEntriesPerLine-1), freemap); + } + } else { + ChunkState cstate; + char freemap[32+1] = kMapInit; + long numTracks = fTotalChunks / fNumSectors; + int track, sector; - if (fNumSectors > 32) { - WMSG1(" VU too many sectors (%ld)\n", fNumSectors); - return; - } + if (fNumSectors > 32) { + WMSG1(" VU too many sectors (%ld)\n", fNumSectors); + return; + } - WMSG0(" map 0123456789abcdef\n"); + WMSG0(" map 0123456789abcdef\n"); - for (track = 0; track < numTracks; track++) { - for (sector = 0; sector < fNumSectors; sector++) { - if (GetChunkState(track, sector, &cstate) != kDIErrNone) { - assert(false); - return; - } - freemap[sector] = StateToChar(&cstate); - } - WMSG2(" %2d: %s\n", track, freemap); - } - } + for (track = 0; track < numTracks; track++) { + for (sector = 0; sector < fNumSectors; sector++) { + if (GetChunkState(track, sector, &cstate) != kDIErrNone) { + assert(false); + return; + } + freemap[sector] = StateToChar(&cstate); + } + WMSG2(" %2d: %s\n", track, freemap); + } + } } diff --git a/diskimg/Win32BlockIO.cpp b/diskimg/Win32BlockIO.cpp index 4093792..17865ce 100644 --- a/diskimg/Win32BlockIO.cpp +++ b/diskimg/Win32BlockIO.cpp @@ -36,7 +36,7 @@ /* * =========================================================================== - * Win32VolumeAccess + * Win32VolumeAccess * =========================================================================== */ @@ -46,59 +46,59 @@ DIError Win32VolumeAccess::Open(const char* deviceName, bool readOnly) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - assert(deviceName != nil); + assert(deviceName != nil); - if (fpBlockAccess != nil) { - assert(false); - return kDIErrAlreadyOpen; - } + if (fpBlockAccess != nil) { + assert(false); + return kDIErrAlreadyOpen; + } - if (strncmp(deviceName, kASPIDev, strlen(kASPIDev)) == 0) { - fpBlockAccess = new ASPIBlockAccess; - if (fpBlockAccess == nil) { - dierr = kDIErrMalloc; - goto bail; - } - dierr = fpBlockAccess->Open(deviceName, readOnly); - if (dierr != kDIErrNone) - goto bail; - } else if (deviceName[0] >= 'A' && deviceName[0] <= 'Z') { - fpBlockAccess = new LogicalBlockAccess; - if (fpBlockAccess == nil) { - dierr = kDIErrMalloc; - goto bail; - } - dierr = fpBlockAccess->Open(deviceName, readOnly); - if (dierr != kDIErrNone) - goto bail; - } else if (deviceName[0] >= '0' && deviceName[0] <= '9') { - fpBlockAccess = new PhysicalBlockAccess; - if (fpBlockAccess == nil) { - dierr = kDIErrMalloc; - goto bail; - } - dierr = fpBlockAccess->Open(deviceName, readOnly); - if (dierr != kDIErrNone) - goto bail; - } else { - WMSG1(" Win32VA: '%s' isn't the name of a device\n", deviceName); - return kDIErrInternal; - } + if (strncmp(deviceName, kASPIDev, strlen(kASPIDev)) == 0) { + fpBlockAccess = new ASPIBlockAccess; + if (fpBlockAccess == nil) { + dierr = kDIErrMalloc; + goto bail; + } + dierr = fpBlockAccess->Open(deviceName, readOnly); + if (dierr != kDIErrNone) + goto bail; + } else if (deviceName[0] >= 'A' && deviceName[0] <= 'Z') { + fpBlockAccess = new LogicalBlockAccess; + if (fpBlockAccess == nil) { + dierr = kDIErrMalloc; + goto bail; + } + dierr = fpBlockAccess->Open(deviceName, readOnly); + if (dierr != kDIErrNone) + goto bail; + } else if (deviceName[0] >= '0' && deviceName[0] <= '9') { + fpBlockAccess = new PhysicalBlockAccess; + if (fpBlockAccess == nil) { + dierr = kDIErrMalloc; + goto bail; + } + dierr = fpBlockAccess->Open(deviceName, readOnly); + if (dierr != kDIErrNone) + goto bail; + } else { + WMSG1(" Win32VA: '%s' isn't the name of a device\n", deviceName); + return kDIErrInternal; + } - // Need to do this now so we can use floppy geometry. - dierr = fpBlockAccess->DetectCapacity(&fTotalBlocks); - if (dierr != kDIErrNone) - goto bail; - assert(fTotalBlocks >= 0); + // Need to do this now so we can use floppy geometry. + dierr = fpBlockAccess->DetectCapacity(&fTotalBlocks); + if (dierr != kDIErrNone) + goto bail; + assert(fTotalBlocks >= 0); bail: - if (dierr != kDIErrNone) { - delete fpBlockAccess; - fpBlockAccess = nil; - } - return dierr; + if (dierr != kDIErrNone) { + delete fpBlockAccess; + fpBlockAccess = nil; + } + return dierr; } /* @@ -107,24 +107,24 @@ bail: void Win32VolumeAccess::Close(void) { - if (fpBlockAccess != nil) { - DIError dierr; - WMSG0(" Win32VolumeAccess closing\n"); + if (fpBlockAccess != nil) { + DIError dierr; + WMSG0(" Win32VolumeAccess closing\n"); - dierr = FlushCache(true); - if (dierr != kDIErrNone) { - WMSG1("WARNING: Win32VA Close: FlushCache failed (err=%ld)\n", - dierr); - // not much we can do - } - dierr = fpBlockAccess->Close(); - if (dierr != kDIErrNone) { - WMSG1("WARNING: Win32VolumeAccess BlockAccess Close failed (err=%ld)\n", - dierr); - } - delete fpBlockAccess; - fpBlockAccess = nil; - } + dierr = FlushCache(true); + if (dierr != kDIErrNone) { + WMSG1("WARNING: Win32VA Close: FlushCache failed (err=%ld)\n", + dierr); + // not much we can do + } + dierr = fpBlockAccess->Close(); + if (dierr != kDIErrNone) { + WMSG1("WARNING: Win32VolumeAccess BlockAccess Close failed (err=%ld)\n", + dierr); + } + delete fpBlockAccess; + fpBlockAccess = nil; + } } @@ -141,52 +141,52 @@ Win32VolumeAccess::Close(void) */ DIError Win32VolumeAccess::ReadBlocks(long startBlock, short blockCount, - void* buf) + void* buf) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - assert(startBlock >= 0); - assert(blockCount > 0); - assert(buf != nil); - assert(fpBlockAccess != nil); + assert(startBlock >= 0); + assert(blockCount > 0); + assert(buf != nil); + assert(fpBlockAccess != nil); - if (blockCount == 1) { - if (fBlockCache.IsBlockInCache(startBlock)) { - fBlockCache.GetFromCache(startBlock, buf); - return kDIErrNone; - } - } else { - // If they're reading in large stretches, we don't need to use - // the cache. There is some chance that what we're about to - // read might include dirty blocks currently in the cache, so - // we flush what we have before the read. - dierr = FlushCache(true); - if (dierr != kDIErrNone) - return dierr; - } + if (blockCount == 1) { + if (fBlockCache.IsBlockInCache(startBlock)) { + fBlockCache.GetFromCache(startBlock, buf); + return kDIErrNone; + } + } else { + // If they're reading in large stretches, we don't need to use + // the cache. There is some chance that what we're about to + // read might include dirty blocks currently in the cache, so + // we flush what we have before the read. + dierr = FlushCache(true); + if (dierr != kDIErrNone) + return dierr; + } - /* go read from the volume */ - dierr = fpBlockAccess->ReadBlocks(startBlock, blockCount, buf); - if (dierr != kDIErrNone) - goto bail; + /* go read from the volume */ + dierr = fpBlockAccess->ReadBlocks(startBlock, blockCount, buf); + if (dierr != kDIErrNone) + goto bail; - /* if we're doing single-block reads, put it in the cache */ - if (blockCount == 1) { - if (!fBlockCache.IsRoomInCache(startBlock)) { - dierr = FlushCache(true); // make room - if (dierr != kDIErrNone) - goto bail; - } + /* if we're doing single-block reads, put it in the cache */ + if (blockCount == 1) { + if (!fBlockCache.IsRoomInCache(startBlock)) { + dierr = FlushCache(true); // make room + if (dierr != kDIErrNone) + goto bail; + } - // after flushing, this should never fail - dierr = fBlockCache.PutInCache(startBlock, buf, false); - if (dierr != kDIErrNone) - goto bail; - } + // after flushing, this should never fail + dierr = fBlockCache.PutInCache(startBlock, buf, false); + if (dierr != kDIErrNone) + goto bail; + } bail: - return dierr; + return dierr; } @@ -198,45 +198,45 @@ bail: */ DIError Win32VolumeAccess::WriteBlocks(long startBlock, short blockCount, - const void* buf) + const void* buf) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - assert(startBlock >= 0); - assert(blockCount > 0); - assert(buf != nil); + assert(startBlock >= 0); + assert(blockCount > 0); + assert(buf != nil); - if (blockCount == 1) { - /* is this block already in the cache? */ - if (!fBlockCache.IsBlockInCache(startBlock)) { - /* not present, make sure it fits */ - if (!fBlockCache.IsRoomInCache(startBlock)) { - dierr = FlushCache(true); // make room - if (dierr != kDIErrNone) - goto bail; - } - } + if (blockCount == 1) { + /* is this block already in the cache? */ + if (!fBlockCache.IsBlockInCache(startBlock)) { + /* not present, make sure it fits */ + if (!fBlockCache.IsRoomInCache(startBlock)) { + dierr = FlushCache(true); // make room + if (dierr != kDIErrNone) + goto bail; + } + } - // after flushing, this should never fail - dierr = fBlockCache.PutInCache(startBlock, buf, true); - if (dierr != kDIErrNone) - goto bail; - } else { - // If they're writing in large stretches, we don't need to use - // the cache. We need to flush the cache in case what we're about - // to write would overwrite something in the cache -- if we don't, - // what's in the cache will effectively revert what we're about to - // write. - dierr = FlushCache(true); - if (dierr != kDIErrNone) - goto bail; - dierr = DoWriteBlocks(startBlock, blockCount, buf); - if (dierr != kDIErrNone) - goto bail; - } + // after flushing, this should never fail + dierr = fBlockCache.PutInCache(startBlock, buf, true); + if (dierr != kDIErrNone) + goto bail; + } else { + // If they're writing in large stretches, we don't need to use + // the cache. We need to flush the cache in case what we're about + // to write would overwrite something in the cache -- if we don't, + // what's in the cache will effectively revert what we're about to + // write. + dierr = FlushCache(true); + if (dierr != kDIErrNone) + goto bail; + dierr = DoWriteBlocks(startBlock, blockCount, buf); + if (dierr != kDIErrNone) + goto bail; + } bail: - return dierr; + return dierr; } @@ -255,41 +255,41 @@ bail: DIError Win32VolumeAccess::FlushCache(bool purge) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - //WMSG1(" Win32VA: FlushCache (%d)\n", purge); + //WMSG1(" Win32VA: FlushCache (%d)\n", purge); - if (fBlockCache.IsDirty()) { - long firstBlock; - int numBlocks; - void* buf; + if (fBlockCache.IsDirty()) { + long firstBlock; + int numBlocks; + void* buf; - fBlockCache.GetCachePointer(&firstBlock, &numBlocks, &buf); + fBlockCache.GetCachePointer(&firstBlock, &numBlocks, &buf); - WMSG3("FlushCache writing first=%d num=%d (purge=%d)\n", - firstBlock, numBlocks, purge); - dierr = DoWriteBlocks(firstBlock, numBlocks, buf); - if (dierr != kDIErrNone) { - WMSG1(" Win32VA: FlushCache write blocks failed (err=%d)\n", - dierr); - goto bail; - } + WMSG3("FlushCache writing first=%d num=%d (purge=%d)\n", + firstBlock, numBlocks, purge); + dierr = DoWriteBlocks(firstBlock, numBlocks, buf); + if (dierr != kDIErrNone) { + WMSG1(" Win32VA: FlushCache write blocks failed (err=%d)\n", + dierr); + goto bail; + } - // all written, clear the dirty flags - fBlockCache.Scrub(); - } + // all written, clear the dirty flags + fBlockCache.Scrub(); + } - if (purge) - fBlockCache.Purge(); + if (purge) + fBlockCache.Purge(); bail: - return dierr; + return dierr; } /* * =========================================================================== - * BlockAccess + * BlockAccess * =========================================================================== */ @@ -304,37 +304,37 @@ bail: */ DIError Win32VolumeAccess::BlockAccess::DetectCapacitySPTI(HANDLE handle, - bool isCDROM, long* pNumBlocks) + bool isCDROM, long* pNumBlocks) { #ifndef HAVE_WINDOWS_CDROM - if (isCDROM) - return kDIErrCDROMNotSupported; + if (isCDROM) + return kDIErrCDROMNotSupported; #endif - DIError dierr = kDIErrNone; - unsigned long lba, blockLen; + DIError dierr = kDIErrNone; + unsigned long lba, blockLen; - dierr = SPTI::GetDeviceCapacity(handle, &lba, &blockLen); - if (dierr != kDIErrNone) - goto bail; + dierr = SPTI::GetDeviceCapacity(handle, &lba, &blockLen); + if (dierr != kDIErrNone) + goto bail; - WMSG3("READ CAPACITY reports lba=%lu blockLen=%lu (total=%lu)\n", - lba, blockLen, lba*blockLen); + WMSG3("READ CAPACITY reports lba=%lu blockLen=%lu (total=%lu)\n", + lba, blockLen, lba*blockLen); - if (isCDROM && blockLen != kCDROMSectorSize) { - WMSG1("Unacceptable CD-ROM blockLen=%ld, bailing\n", blockLen); - dierr = kDIErrReadFailed; - goto bail; - } + if (isCDROM && blockLen != kCDROMSectorSize) { + WMSG1("Unacceptable CD-ROM blockLen=%ld, bailing\n", blockLen); + dierr = kDIErrReadFailed; + goto bail; + } - // The LBA is the last valid block on the disk. To get the disk size, - // we need to add one. + // The LBA is the last valid block on the disk. To get the disk size, + // we need to add one. - *pNumBlocks = (blockLen/512) * (lba+1); - WMSG1(" SPTI returning 512-byte block count %ld\n", *pNumBlocks); + *pNumBlocks = (blockLen/512) * (lba+1); + WMSG1(" SPTI returning 512-byte block count %ld\n", *pNumBlocks); bail: - return dierr; + return dierr; } /* @@ -351,88 +351,88 @@ bail: /*static*/ DIError Win32VolumeAccess::BlockAccess::ScanCapacity(BlockAccess* pThis, long* pNumBlocks) { - DIError dierr = kDIErrNone; - // max out at 8GB (-1 block) - const long kLargest = DiskImgLib::kVolumeMaxBlocks; - const long kTypicalSizes[] = { - // these must be in ascending order - 720*1024 / BlockAccess::kBlockSize, // 720K floppy - 1440*1024 / BlockAccess::kBlockSize, // 1.44MB floppy - 32*1024*1024 / BlockAccess::kBlockSize, // 32MB flash card - 64*1024*1024 / BlockAccess::kBlockSize, // 64MB flash card - 128*1024*1024 / BlockAccess::kBlockSize, // 128MB flash card - 256*1024*1024 / BlockAccess::kBlockSize, // 256MB flash card - //512*1024*1024 / BlockAccess::kBlockSize, // 512MB flash card - 2*1024*1024*(1024/BlockAccess::kBlockSize), // 2GB mark - kLargest - }; - long totalBlocks = 0; - int i; + DIError dierr = kDIErrNone; + // max out at 8GB (-1 block) + const long kLargest = DiskImgLib::kVolumeMaxBlocks; + const long kTypicalSizes[] = { + // these must be in ascending order + 720*1024 / BlockAccess::kBlockSize, // 720K floppy + 1440*1024 / BlockAccess::kBlockSize, // 1.44MB floppy + 32*1024*1024 / BlockAccess::kBlockSize, // 32MB flash card + 64*1024*1024 / BlockAccess::kBlockSize, // 64MB flash card + 128*1024*1024 / BlockAccess::kBlockSize, // 128MB flash card + 256*1024*1024 / BlockAccess::kBlockSize, // 256MB flash card + //512*1024*1024 / BlockAccess::kBlockSize, // 512MB flash card + 2*1024*1024*(1024/BlockAccess::kBlockSize), // 2GB mark + kLargest + }; + long totalBlocks = 0; + int i; - // Trivial check to make sure *anything* works, and to establish block 0 - // as valid in case we have to bin-search. - if (!CanReadBlock(pThis, 0)) { - WMSG0(" Win32VolumeAccess: can't read block 0\n"); - dierr = kDIErrReadFailed; - goto bail; - } + // Trivial check to make sure *anything* works, and to establish block 0 + // as valid in case we have to bin-search. + if (!CanReadBlock(pThis, 0)) { + WMSG0(" Win32VolumeAccess: can't read block 0\n"); + dierr = kDIErrReadFailed; + goto bail; + } - for (i = 0; i < NELEM(kTypicalSizes); i++) { - if (!CanReadBlock(pThis, kTypicalSizes[i])) { - /* failed reading, see if N-1 is readable */ - if (CanReadBlock(pThis, kTypicalSizes[i] - 1)) { - /* found it */ - totalBlocks = kTypicalSizes[i]; - break; - } else { - /* we overshot, binary-search backwards */ - WMSG1("OVERSHOT at %ld\n", kTypicalSizes[i]); - long good, bad; - if (i == 0) - good = 0; - else - good = kTypicalSizes[i-1]; // know this one is good - bad = kTypicalSizes[i]-1; // know this one is bad + for (i = 0; i < NELEM(kTypicalSizes); i++) { + if (!CanReadBlock(pThis, kTypicalSizes[i])) { + /* failed reading, see if N-1 is readable */ + if (CanReadBlock(pThis, kTypicalSizes[i] - 1)) { + /* found it */ + totalBlocks = kTypicalSizes[i]; + break; + } else { + /* we overshot, binary-search backwards */ + WMSG1("OVERSHOT at %ld\n", kTypicalSizes[i]); + long good, bad; + if (i == 0) + good = 0; + else + good = kTypicalSizes[i-1]; // know this one is good + bad = kTypicalSizes[i]-1; // know this one is bad - while (good != bad-1) { - long check = (good + bad) / 2; - assert(check > good); - assert(check < bad); + while (good != bad-1) { + long check = (good + bad) / 2; + assert(check > good); + assert(check < bad); - if (CanReadBlock(pThis, check)) - good = check; - else - bad = check; - } - totalBlocks = bad; - break; - } - } - } - if (totalBlocks == 0) { - if (i == NELEM(kTypicalSizes)) { - /* huge volume, we never found a bad block */ - totalBlocks = kLargest; - } else { - /* we never found a good block */ - WMSG0(" Win32VolumeAccess unable to determine size\n"); - dierr = kDIErrReadFailed; - goto bail; - } - } + if (CanReadBlock(pThis, check)) + good = check; + else + bad = check; + } + totalBlocks = bad; + break; + } + } + } + if (totalBlocks == 0) { + if (i == NELEM(kTypicalSizes)) { + /* huge volume, we never found a bad block */ + totalBlocks = kLargest; + } else { + /* we never found a good block */ + WMSG0(" Win32VolumeAccess unable to determine size\n"); + dierr = kDIErrReadFailed; + goto bail; + } + } - if (totalBlocks > (3 * 1024 * 1024) / BlockAccess::kBlockSize) { - WMSG2(" GFDWinVolume: size is %ld (%.2fMB)\n", - totalBlocks, (float) totalBlocks / (2048.0)); - } else { - WMSG2(" GFDWinVolume: size is %ld (%.2fKB)\n", - totalBlocks, (float) totalBlocks / 2.0); - } - *pNumBlocks = totalBlocks; + if (totalBlocks > (3 * 1024 * 1024) / BlockAccess::kBlockSize) { + WMSG2(" GFDWinVolume: size is %ld (%.2fMB)\n", + totalBlocks, (float) totalBlocks / (2048.0)); + } else { + WMSG2(" GFDWinVolume: size is %ld (%.2fKB)\n", + totalBlocks, (float) totalBlocks / 2.0); + } + *pNumBlocks = totalBlocks; bail: - return dierr; + return dierr; } /* @@ -441,17 +441,17 @@ bail: /*static*/ bool Win32VolumeAccess::BlockAccess::CanReadBlock(BlockAccess* pThis, long blockNum) { - DIError dierr; - unsigned char buf[BlockAccess::kBlockSize]; + DIError dierr; + unsigned char buf[BlockAccess::kBlockSize]; - dierr = pThis->ReadBlocks(blockNum, 1, buf); - if (dierr == kDIErrNone) { - WMSG1(" +++ Checked %ld (good)\n", blockNum); - return true; - } else { - WMSG1(" +++ Checked %ld (bad)\n", blockNum); - return false; - } + dierr = pThis->ReadBlocks(blockNum, 1, buf); + if (dierr == kDIErrNone) { + WMSG1(" +++ Checked %ld (good)\n", blockNum); + return true; + } else { + WMSG1(" +++ Checked %ld (bad)\n", blockNum); + return false; + } } @@ -464,46 +464,46 @@ Win32VolumeAccess::BlockAccess::CanReadBlock(BlockAccess* pThis, long blockNum) * Most of these definitions come from MSFT knowledge base article #174569, * "BUG: Int 21 Read/Write Track on Logical Drive Fails on OSR2 and Later". */ -#define VWIN32_DIOC_DOS_IOCTL 1 // Int 21h 4400h through 4411h -#define VWIN32_DIOC_DOS_INT25 2 -#define VWIN32_DIOC_DOS_INT26 3 -#define VWIN32_DIOC_DOS_INT13 4 -#define VWIN32_DIOC_DOS_DRIVEINFO 6 // Int 21h 730x commands +#define VWIN32_DIOC_DOS_IOCTL 1 // Int 21h 4400h through 4411h +#define VWIN32_DIOC_DOS_INT25 2 +#define VWIN32_DIOC_DOS_INT26 3 +#define VWIN32_DIOC_DOS_INT13 4 +#define VWIN32_DIOC_DOS_DRIVEINFO 6 // Int 21h 730x commands typedef struct _DIOC_REGISTERS { - DWORD reg_EBX; - DWORD reg_EDX; - DWORD reg_ECX; - DWORD reg_EAX; - DWORD reg_EDI; - DWORD reg_ESI; - DWORD reg_Flags; + DWORD reg_EBX; + DWORD reg_EDX; + DWORD reg_ECX; + DWORD reg_EAX; + DWORD reg_EDI; + DWORD reg_ESI; + DWORD reg_Flags; } DIOC_REGISTERS, *PDIOC_REGISTERS; #define CARRY_FLAG 1 #pragma pack(1) typedef struct _DISKIO { - DWORD dwStartSector; // starting logical sector number - WORD wSectors; // number of sectors - DWORD dwBuffer; // address of read/write buffer + DWORD dwStartSector; // starting logical sector number + WORD wSectors; // number of sectors + DWORD dwBuffer; // address of read/write buffer } DISKIO, *PDISKIO; typedef struct _DRIVEMAPINFO { - BYTE dmiAllocationLength; - BYTE dmiInfoLength; - BYTE dmiFlags; - BYTE dmiInt13Unit; - DWORD dmiAssociatedDriveMap; - DWORD dmiPartitionStartRBA_lo; - DWORD dmiPartitionStartRBA_hi; + BYTE dmiAllocationLength; + BYTE dmiInfoLength; + BYTE dmiFlags; + BYTE dmiInt13Unit; + DWORD dmiAssociatedDriveMap; + DWORD dmiPartitionStartRBA_lo; + DWORD dmiPartitionStartRBA_hi; } DRIVEMAPINFO, *PDRIVEMAPINFO; #pragma pack() -#define kInt13StatusMissingAddrMark 2 // sector number above media format -#define kInt13StatusWriteProtected 3 // disk is write protected -#define kInt13StatusSectorNotFound 4 // sector number above drive cap +#define kInt13StatusMissingAddrMark 2 // sector number above media format +#define kInt13StatusWriteProtected 3 // disk is write protected +#define kInt13StatusSectorNotFound 4 // sector number above drive cap // == 10 for bad blocks?? -#define kInt13StatusTimeout 128 // drive not responding +#define kInt13StatusTimeout 128 // drive not responding #if 0 /* @@ -515,80 +515,80 @@ typedef struct _DRIVEMAPINFO { /*static*/ DIError Win32VolumeAccess::BlockAccess::GetInt13Unit(HANDLE handle, int driveNum, int* pInt13Unit) { - DIError dierr = kDIErrNone; - BOOL result; - DWORD cb; - DRIVEMAPINFO driveMapInfo = {0}; - DIOC_REGISTERS reg = {0}; - const int kGetDriveMapInfo = 0x6f; - const int kDeviceCategory1 = 0x08; // for older stuff - const int kDeviceCategory2 = 0x48; // for FAT32 + DIError dierr = kDIErrNone; + BOOL result; + DWORD cb; + DRIVEMAPINFO driveMapInfo = {0}; + DIOC_REGISTERS reg = {0}; + const int kGetDriveMapInfo = 0x6f; + const int kDeviceCategory1 = 0x08; // for older stuff + const int kDeviceCategory2 = 0x48; // for FAT32 - assert(handle != nil); - assert(driveNum > 0 && driveNum <= kNumLogicalVolumes); - assert(pInt13Unit != nil); + assert(handle != nil); + assert(driveNum > 0 && driveNum <= kNumLogicalVolumes); + assert(pInt13Unit != nil); - *pInt13Unit = -1; + *pInt13Unit = -1; - driveMapInfo.dmiAllocationLength = sizeof(DRIVEMAPINFO); // should be 16 + driveMapInfo.dmiAllocationLength = sizeof(DRIVEMAPINFO); // should be 16 - reg.reg_EAX = 0x440d; // generic IOCTL - reg.reg_EBX = driveNum; - reg.reg_ECX = MAKEWORD(kGetDriveMapInfo, kDeviceCategory1); - reg.reg_EDX = (DWORD) &driveMapInfo; + reg.reg_EAX = 0x440d; // generic IOCTL + reg.reg_EBX = driveNum; + reg.reg_ECX = MAKEWORD(kGetDriveMapInfo, kDeviceCategory1); + reg.reg_EDX = (DWORD) &driveMapInfo; - result = ::DeviceIoControl(handle, VWIN32_DIOC_DOS_IOCTL, - ®, sizeof(reg), - ®, sizeof(reg), &cb, 0); - if (result == 0) { - WMSG1(" DeviceIoControl(Int21h, 6fh) FAILED (err=%ld)\n", - GetLastError()); - dierr = LastErrorToDIError(); - goto bail; - } + result = ::DeviceIoControl(handle, VWIN32_DIOC_DOS_IOCTL, + ®, sizeof(reg), + ®, sizeof(reg), &cb, 0); + if (result == 0) { + WMSG1(" DeviceIoControl(Int21h, 6fh) FAILED (err=%ld)\n", + GetLastError()); + dierr = LastErrorToDIError(); + goto bail; + } - if (reg.reg_Flags & CARRY_FLAG) { - WMSG1(" --- retrying GDMI with alternate device category (ax=%ld)\n", - reg.reg_EAX); - reg.reg_EAX = 0x440d; // generic IOCTL - reg.reg_EBX = driveNum; - reg.reg_ECX = MAKEWORD(kGetDriveMapInfo, kDeviceCategory2); - reg.reg_EDX = (DWORD) &driveMapInfo; - result = ::DeviceIoControl(handle, VWIN32_DIOC_DOS_IOCTL, - ®, sizeof(reg), - ®, sizeof(reg), &cb, 0); - } - if (result == 0) { - WMSG1(" DeviceIoControl(Int21h, 6fh)(retry) FAILED (err=%ld)\n", - GetLastError()); - dierr = LastErrorToDIError(); - goto bail; - } - if (reg.reg_Flags & CARRY_FLAG) { - WMSG1(" --- GetDriveMapInfo call (retry) failed (ax=%ld)\n", - reg.reg_EAX); - dierr = kDIErrReadFailed; // close enough - goto bail; - } + if (reg.reg_Flags & CARRY_FLAG) { + WMSG1(" --- retrying GDMI with alternate device category (ax=%ld)\n", + reg.reg_EAX); + reg.reg_EAX = 0x440d; // generic IOCTL + reg.reg_EBX = driveNum; + reg.reg_ECX = MAKEWORD(kGetDriveMapInfo, kDeviceCategory2); + reg.reg_EDX = (DWORD) &driveMapInfo; + result = ::DeviceIoControl(handle, VWIN32_DIOC_DOS_IOCTL, + ®, sizeof(reg), + ®, sizeof(reg), &cb, 0); + } + if (result == 0) { + WMSG1(" DeviceIoControl(Int21h, 6fh)(retry) FAILED (err=%ld)\n", + GetLastError()); + dierr = LastErrorToDIError(); + goto bail; + } + if (reg.reg_Flags & CARRY_FLAG) { + WMSG1(" --- GetDriveMapInfo call (retry) failed (ax=%ld)\n", + reg.reg_EAX); + dierr = kDIErrReadFailed; // close enough + goto bail; + } - WMSG3(" +++ DriveMapInfo len=%d flags=%d unit=%d\n", - driveMapInfo.dmiInfoLength, driveMapInfo.dmiFlags, - driveMapInfo.dmiInt13Unit); - WMSG3(" +++ driveMap=0x%08lx RBA=0x%08lx 0x%08lx\n", - driveMapInfo.dmiAssociatedDriveMap, - driveMapInfo.dmiPartitionStartRBA_hi, - driveMapInfo.dmiPartitionStartRBA_lo); + WMSG3(" +++ DriveMapInfo len=%d flags=%d unit=%d\n", + driveMapInfo.dmiInfoLength, driveMapInfo.dmiFlags, + driveMapInfo.dmiInt13Unit); + WMSG3(" +++ driveMap=0x%08lx RBA=0x%08lx 0x%08lx\n", + driveMapInfo.dmiAssociatedDriveMap, + driveMapInfo.dmiPartitionStartRBA_hi, + driveMapInfo.dmiPartitionStartRBA_lo); - if (driveMapInfo.dmiInfoLength < 4) { - /* results not covered in reply? */ - dierr = kDIErrReadFailed; // not close, but it'll do - goto bail; - } + if (driveMapInfo.dmiInfoLength < 4) { + /* results not covered in reply? */ + dierr = kDIErrReadFailed; // not close, but it'll do + goto bail; + } - *pInt13Unit = driveMapInfo.dmiInt13Unit; + *pInt13Unit = driveMapInfo.dmiInt13Unit; bail: - return dierr; + return dierr; } #endif @@ -605,49 +605,49 @@ bail: */ /*static*/ bool Win32VolumeAccess::BlockAccess::LookupFloppyGeometry(long totalBlocks, - DiskGeometry* pGeometry) + DiskGeometry* pGeometry) { - static const struct { - FloppyKind kind; - long blockCount; // total #of blocks on the disk - int numCyls; // #of cylinders - int numHeads; // #of heads per cylinder - int numSectors; // #of sectors/track - } floppyGeometry[] = { - { kFloppyUnknown, -1, -1, -1, -1 }, - { kFloppy525_360, 360*2, 40, 2, 9 }, - { kFloppy525_1200, 1200*2, 80, 2, 15 }, - { kFloppy35_720, 720*2, 80, 2, 9 }, - { kFloppy35_1440, 1440*2, 80, 2, 18 }, - { kFloppy35_2880, 2880*2, 80, 2, 36 } - }; + static const struct { + FloppyKind kind; + long blockCount; // total #of blocks on the disk + int numCyls; // #of cylinders + int numHeads; // #of heads per cylinder + int numSectors; // #of sectors/track + } floppyGeometry[] = { + { kFloppyUnknown, -1, -1, -1, -1 }, + { kFloppy525_360, 360*2, 40, 2, 9 }, + { kFloppy525_1200, 1200*2, 80, 2, 15 }, + { kFloppy35_720, 720*2, 80, 2, 9 }, + { kFloppy35_1440, 1440*2, 80, 2, 18 }, + { kFloppy35_2880, 2880*2, 80, 2, 36 } + }; - /* verify that we can directly index the table with the enum */ - for (int chk = 0; chk < NELEM(floppyGeometry); chk++) { - assert(floppyGeometry[chk].kind == chk); - } - assert(chk == kFloppyMax); + /* verify that we can directly index the table with the enum */ + for (int chk = 0; chk < NELEM(floppyGeometry); chk++) { + assert(floppyGeometry[chk].kind == chk); + } + assert(chk == kFloppyMax); - if (totalBlocks <= 0) { - // still auto-detecting volume size? - return false; - } + if (totalBlocks <= 0) { + // still auto-detecting volume size? + return false; + } - int i; - for (i = 0; i < NELEM(floppyGeometry); i++) - if (floppyGeometry[i].blockCount == totalBlocks) - break; + int i; + for (i = 0; i < NELEM(floppyGeometry); i++) + if (floppyGeometry[i].blockCount == totalBlocks) + break; - if (i == NELEM(floppyGeometry)) { - WMSG1( "GetFloppyGeometry: no match for blocks=%ld\n", totalBlocks); - return false; - } + if (i == NELEM(floppyGeometry)) { + WMSG1( "GetFloppyGeometry: no match for blocks=%ld\n", totalBlocks); + return false; + } - pGeometry->numCyls = floppyGeometry[i].numCyls; - pGeometry->numHeads = floppyGeometry[i].numHeads; - pGeometry->numSectors = floppyGeometry[i].numSectors; + pGeometry->numCyls = floppyGeometry[i].numCyls; + pGeometry->numHeads = floppyGeometry[i].numHeads; + pGeometry->numSectors = floppyGeometry[i].numSectors; - return true; + return true; } #endif @@ -660,34 +660,34 @@ Win32VolumeAccess::BlockAccess::LookupFloppyGeometry(long totalBlocks, */ /*static*/ bool Win32VolumeAccess::BlockAccess::BlockToCylinderHeadSector(long blockNum, - const DiskGeometry* pGeometry, int* pCylinder, int* pHead, - int* pSector, long* pLastBlockOnTrack) + const DiskGeometry* pGeometry, int* pCylinder, int* pHead, + int* pSector, long* pLastBlockOnTrack) { - int cylinder, head, sector; - long lastBlockOnTrack; - int leftOver; + int cylinder, head, sector; + long lastBlockOnTrack; + int leftOver; - cylinder = blockNum / (pGeometry->numSectors * pGeometry->numHeads); - leftOver = blockNum - cylinder * (pGeometry->numSectors * pGeometry->numHeads); - head = leftOver / pGeometry->numSectors; - sector = leftOver - (head * pGeometry->numSectors); + cylinder = blockNum / (pGeometry->numSectors * pGeometry->numHeads); + leftOver = blockNum - cylinder * (pGeometry->numSectors * pGeometry->numHeads); + head = leftOver / pGeometry->numSectors; + sector = leftOver - (head * pGeometry->numSectors); - assert(cylinder >= 0 && cylinder < pGeometry->numCyls); - assert(head >= 0 && head < pGeometry->numHeads); - assert(sector >= 0 && sector < pGeometry->numSectors); + assert(cylinder >= 0 && cylinder < pGeometry->numCyls); + assert(head >= 0 && head < pGeometry->numHeads); + assert(sector >= 0 && sector < pGeometry->numSectors); - lastBlockOnTrack = blockNum + (pGeometry->numSectors - sector -1); + lastBlockOnTrack = blockNum + (pGeometry->numSectors - sector -1); - if (pCylinder != nil) - *pCylinder = cylinder; - if (pHead != nil) - *pHead = head; - if (pSector != nil) - *pSector = sector+1; - if (pLastBlockOnTrack != nil) - *pLastBlockOnTrack = lastBlockOnTrack; + if (pCylinder != nil) + *pCylinder = cylinder; + if (pHead != nil) + *pHead = head; + if (pSector != nil) + *pSector = sector+1; + if (pLastBlockOnTrack != nil) + *pLastBlockOnTrack = lastBlockOnTrack; - return true; + return true; } /* @@ -695,33 +695,33 @@ Win32VolumeAccess::BlockAccess::BlockToCylinderHeadSector(long blockNum, */ /*static*/ DIError Win32VolumeAccess::BlockAccess::GetFloppyDriveKind(HANDLE handle, int unitNum, - FloppyKind* pKind) + FloppyKind* pKind) { - DIOC_REGISTERS reg = {0}; - DWORD cb; - BOOL result; + DIOC_REGISTERS reg = {0}; + DWORD cb; + BOOL result; - reg.reg_EAX = MAKEWORD(0, 0x08); // Read Diskette Drive Parameters - reg.reg_EDX = MAKEWORD(unitNum, 0); + reg.reg_EAX = MAKEWORD(0, 0x08); // Read Diskette Drive Parameters + reg.reg_EDX = MAKEWORD(unitNum, 0); - result = DeviceIoControl(handle, VWIN32_DIOC_DOS_INT13, ®, - sizeof(reg), ®, sizeof(reg), &cb, 0); + result = DeviceIoControl(handle, VWIN32_DIOC_DOS_INT13, ®, + sizeof(reg), ®, sizeof(reg), &cb, 0); - if (result == 0 || (reg.reg_Flags & CARRY_FLAG)) { - WMSG3(" GetFloppyKind failed: result=%d flags=0x%04x AH=%d\n", - result, reg.reg_Flags, HIBYTE(reg.reg_EAX)); - return kDIErrGeneric; - } + if (result == 0 || (reg.reg_Flags & CARRY_FLAG)) { + WMSG3(" GetFloppyKind failed: result=%d flags=0x%04x AH=%d\n", + result, reg.reg_Flags, HIBYTE(reg.reg_EAX)); + return kDIErrGeneric; + } - int bl = LOBYTE(reg.reg_EBX); - if (bl > 0 && bl < 6) - *pKind = (FloppyKind) bl; - else { - WMSG1(" GetFloppyKind: unrecognized kind %d\n", bl); - return kDIErrGeneric; - } + int bl = LOBYTE(reg.reg_EBX); + if (bl > 0 && bl < 6) + *pKind = (FloppyKind) bl; + else { + WMSG1(" GetFloppyKind: unrecognized kind %d\n", bl); + return kDIErrGeneric; + } - return kDIErrNone; + return kDIErrNone; } /* @@ -739,49 +739,49 @@ Win32VolumeAccess::BlockAccess::GetFloppyDriveKind(HANDLE handle, int unitNum, */ /*static*/ int Win32VolumeAccess::BlockAccess::ReadBlocksInt13h(HANDLE handle, int unitNum, - int cylinder, int head, int sector, short blockCount, void* buf) + int cylinder, int head, int sector, short blockCount, void* buf) { - DIOC_REGISTERS reg = {0}; - DWORD cb; - BOOL result; + DIOC_REGISTERS reg = {0}; + DWORD cb; + BOOL result; - if (unitNum < 0 || unitNum >= 4) { - assert(false); - return kDIErrInternal; - } + if (unitNum < 0 || unitNum >= 4) { + assert(false); + return kDIErrInternal; + } - for (int retry = 0; retry < kMaxFloppyRetries; retry++) { - reg.reg_EAX = MAKEWORD(blockCount, 0x02); // read N sectors - reg.reg_EBX = (DWORD) buf; - reg.reg_ECX = MAKEWORD(sector, cylinder); - reg.reg_EDX = MAKEWORD(unitNum, head); + for (int retry = 0; retry < kMaxFloppyRetries; retry++) { + reg.reg_EAX = MAKEWORD(blockCount, 0x02); // read N sectors + reg.reg_EBX = (DWORD) buf; + reg.reg_ECX = MAKEWORD(sector, cylinder); + reg.reg_EDX = MAKEWORD(unitNum, head); - //WMSG4(" DIOC Int13h read c=%d h=%d s=%d rc=%d\n", - // cylinder, head, sector, blockCount); - result = DeviceIoControl(handle, VWIN32_DIOC_DOS_INT13, ®, - sizeof(reg), ®, sizeof(reg), &cb, 0); + //WMSG4(" DIOC Int13h read c=%d h=%d s=%d rc=%d\n", + // cylinder, head, sector, blockCount); + result = DeviceIoControl(handle, VWIN32_DIOC_DOS_INT13, ®, + sizeof(reg), ®, sizeof(reg), &cb, 0); - if (result != 0 && !(reg.reg_Flags & CARRY_FLAG)) - break; // success! + if (result != 0 && !(reg.reg_Flags & CARRY_FLAG)) + break; // success! - /* if it's an invalid sector request, bail out immediately */ - if (HIBYTE(reg.reg_EAX) == kInt13StatusSectorNotFound || - HIBYTE(reg.reg_EAX) == kInt13StatusMissingAddrMark) - { - break; - } - WMSG1(" DIOC soft read failure, ax=0x%08lx\n", reg.reg_EAX); - } - if (!result || (reg.reg_Flags & CARRY_FLAG)) { - int ah = HIBYTE(reg.reg_EAX); - WMSG2(" DIOC read failed, result=%d ah=%ld\n", result, ah); - if (ah != 0) - return ah; - else - return -1; - } + /* if it's an invalid sector request, bail out immediately */ + if (HIBYTE(reg.reg_EAX) == kInt13StatusSectorNotFound || + HIBYTE(reg.reg_EAX) == kInt13StatusMissingAddrMark) + { + break; + } + WMSG1(" DIOC soft read failure, ax=0x%08lx\n", reg.reg_EAX); + } + if (!result || (reg.reg_Flags & CARRY_FLAG)) { + int ah = HIBYTE(reg.reg_EAX); + WMSG2(" DIOC read failed, result=%d ah=%ld\n", result, ah); + if (ah != 0) + return ah; + else + return -1; + } - return 0; + return 0; } @@ -795,57 +795,57 @@ Win32VolumeAccess::BlockAccess::ReadBlocksInt13h(HANDLE handle, int unitNum, */ /*static*/ DIError Win32VolumeAccess::BlockAccess::ReadBlocksInt13h(HANDLE handle, int unitNum, - const DiskGeometry* pGeometry, long startBlock, short blockCount, - void* buf) + const DiskGeometry* pGeometry, long startBlock, short blockCount, + void* buf) { - int cylinder, head, sector; - int status, runCount; - long lastBlockOnTrack; + int cylinder, head, sector; + int status, runCount; + long lastBlockOnTrack; - if (unitNum < 0 || unitNum >= 4) { - assert(false); - return kDIErrInternal; - } - if (startBlock < 0 || blockCount <= 0) - return kDIErrInvalidArg; - if (startBlock + blockCount > pGeometry->blockCount) { - WMSG2(" ReadInt13h: invalid request for start=%ld count=%d\n", - startBlock, blockCount); - return kDIErrReadFailed; - } + if (unitNum < 0 || unitNum >= 4) { + assert(false); + return kDIErrInternal; + } + if (startBlock < 0 || blockCount <= 0) + return kDIErrInvalidArg; + if (startBlock + blockCount > pGeometry->blockCount) { + WMSG2(" ReadInt13h: invalid request for start=%ld count=%d\n", + startBlock, blockCount); + return kDIErrReadFailed; + } - while (blockCount) { - int result; - result = BlockToCylinderHeadSector(startBlock, pGeometry, - &cylinder, &head, §or, &lastBlockOnTrack); - assert(result); + while (blockCount) { + int result; + result = BlockToCylinderHeadSector(startBlock, pGeometry, + &cylinder, &head, §or, &lastBlockOnTrack); + assert(result); - /* - * According to "The Undocumented PC", the average BIOS will read - * at most one or two tracks reliably. It's really geared toward - * writing a single track or cylinder with one call. We want to - * be sure that our read doesn't straddle tracks, so we break it - * down as needed. - */ - runCount = lastBlockOnTrack - startBlock +1; - if (runCount > blockCount) - runCount = blockCount; - //WMSG3("R runCount=%d lastBlkOnT=%d start=%d\n", - // runCount, lastBlockOnTrack, startBlock); - assert(runCount > 0); + /* + * According to "The Undocumented PC", the average BIOS will read + * at most one or two tracks reliably. It's really geared toward + * writing a single track or cylinder with one call. We want to + * be sure that our read doesn't straddle tracks, so we break it + * down as needed. + */ + runCount = lastBlockOnTrack - startBlock +1; + if (runCount > blockCount) + runCount = blockCount; + //WMSG3("R runCount=%d lastBlkOnT=%d start=%d\n", + // runCount, lastBlockOnTrack, startBlock); + assert(runCount > 0); - status = ReadBlocksInt13h(handle, unitNum, cylinder, head, sector, - runCount, buf); - if (status != 0) { - WMSG1(" DIOC read failed (status=%d)\n", status); - return kDIErrReadFailed; - } + status = ReadBlocksInt13h(handle, unitNum, cylinder, head, sector, + runCount, buf); + if (status != 0) { + WMSG1(" DIOC read failed (status=%d)\n", status); + return kDIErrReadFailed; + } - startBlock += runCount; - blockCount -= runCount; - } + startBlock += runCount; + blockCount -= runCount; + } - return kDIErrNone; + return kDIErrNone; } /* @@ -860,41 +860,41 @@ Win32VolumeAccess::BlockAccess::ReadBlocksInt13h(HANDLE handle, int unitNum, */ /*static*/ int Win32VolumeAccess::BlockAccess::WriteBlocksInt13h(HANDLE handle, int unitNum, - int cylinder, int head, int sector, short blockCount, - const void* buf) + int cylinder, int head, int sector, short blockCount, + const void* buf) { - DIOC_REGISTERS reg = {0}; - DWORD cb; - BOOL result; + DIOC_REGISTERS reg = {0}; + DWORD cb; + BOOL result; - for (int retry = 0; retry < kMaxFloppyRetries; retry++) { - reg.reg_EAX = MAKEWORD(blockCount, 0x03); // write N sectors - reg.reg_EBX = (DWORD) buf; - reg.reg_ECX = MAKEWORD(sector, cylinder); - reg.reg_EDX = MAKEWORD(unitNum, head); + for (int retry = 0; retry < kMaxFloppyRetries; retry++) { + reg.reg_EAX = MAKEWORD(blockCount, 0x03); // write N sectors + reg.reg_EBX = (DWORD) buf; + reg.reg_ECX = MAKEWORD(sector, cylinder); + reg.reg_EDX = MAKEWORD(unitNum, head); - WMSG4(" DIOC Int13h write c=%d h=%d s=%d rc=%d\n", - cylinder, head, sector, blockCount); - result = DeviceIoControl(handle, VWIN32_DIOC_DOS_INT13, ®, - sizeof(reg), ®, sizeof(reg), &cb, 0); + WMSG4(" DIOC Int13h write c=%d h=%d s=%d rc=%d\n", + cylinder, head, sector, blockCount); + result = DeviceIoControl(handle, VWIN32_DIOC_DOS_INT13, ®, + sizeof(reg), ®, sizeof(reg), &cb, 0); - if (result != 0 && !(reg.reg_Flags & CARRY_FLAG)) - break; // success! + if (result != 0 && !(reg.reg_Flags & CARRY_FLAG)) + break; // success! - if (HIBYTE(reg.reg_EAX) == kInt13StatusWriteProtected) - break; // no point retrying this - WMSG1(" DIOC soft write failure, ax=0x%08lx\n", reg.reg_EAX); - } - if (!result || (reg.reg_Flags & CARRY_FLAG)) { - int ah = HIBYTE(reg.reg_EAX); - WMSG2(" DIOC write failed, result=%d ah=%ld\n", result, ah); - if (ah != 0) - return ah; - else - return -1; - } + if (HIBYTE(reg.reg_EAX) == kInt13StatusWriteProtected) + break; // no point retrying this + WMSG1(" DIOC soft write failure, ax=0x%08lx\n", reg.reg_EAX); + } + if (!result || (reg.reg_Flags & CARRY_FLAG)) { + int ah = HIBYTE(reg.reg_EAX); + WMSG2(" DIOC write failed, result=%d ah=%ld\n", result, ah); + if (ah != 0) + return ah; + else + return -1; + } - return 0; + return 0; } /* @@ -909,54 +909,54 @@ Win32VolumeAccess::BlockAccess::WriteBlocksInt13h(HANDLE handle, int unitNum, */ /*static*/ DIError Win32VolumeAccess::BlockAccess::WriteBlocksInt13h(HANDLE handle, int unitNum, - const DiskGeometry* pGeometry, long startBlock, short blockCount, - const void* buf) + const DiskGeometry* pGeometry, long startBlock, short blockCount, + const void* buf) { - int cylinder, head, sector; - int status, runCount; - long lastBlockOnTrack; + int cylinder, head, sector; + int status, runCount; + long lastBlockOnTrack; - // make sure this is a floppy drive and we know which unit it is - if (unitNum < 0 || unitNum >= 4) { - assert(false); - return kDIErrInternal; - } - if (startBlock < 0 || blockCount <= 0) - return kDIErrInvalidArg; - if (startBlock + blockCount > pGeometry->blockCount) { - WMSG2(" WriteInt13h: invalid request for start=%ld count=%d\n", - startBlock, blockCount); - return kDIErrWriteFailed; - } + // make sure this is a floppy drive and we know which unit it is + if (unitNum < 0 || unitNum >= 4) { + assert(false); + return kDIErrInternal; + } + if (startBlock < 0 || blockCount <= 0) + return kDIErrInvalidArg; + if (startBlock + blockCount > pGeometry->blockCount) { + WMSG2(" WriteInt13h: invalid request for start=%ld count=%d\n", + startBlock, blockCount); + return kDIErrWriteFailed; + } - while (blockCount) { - int result; - result = BlockToCylinderHeadSector(startBlock, pGeometry, - &cylinder, &head, §or, &lastBlockOnTrack); - assert(result); + while (blockCount) { + int result; + result = BlockToCylinderHeadSector(startBlock, pGeometry, + &cylinder, &head, §or, &lastBlockOnTrack); + assert(result); - runCount = lastBlockOnTrack - startBlock +1; - if (runCount > blockCount) - runCount = blockCount; - //WMSG3("W runCount=%d lastBlkOnT=%d start=%d\n", - // runCount, lastBlockOnTrack, startBlock); - assert(runCount > 0); + runCount = lastBlockOnTrack - startBlock +1; + if (runCount > blockCount) + runCount = blockCount; + //WMSG3("W runCount=%d lastBlkOnT=%d start=%d\n", + // runCount, lastBlockOnTrack, startBlock); + assert(runCount > 0); - status = WriteBlocksInt13h(handle, unitNum, cylinder, head, sector, - runCount, buf); - if (status != 0) { - WMSG1(" DIOC write failed (status=%d)\n", status); - if (status == kInt13StatusWriteProtected) - return kDIErrWriteProtected; - else - return kDIErrWriteFailed; - } + status = WriteBlocksInt13h(handle, unitNum, cylinder, head, sector, + runCount, buf); + if (status != 0) { + WMSG1(" DIOC write failed (status=%d)\n", status); + if (status == kInt13StatusWriteProtected) + return kDIErrWriteProtected; + else + return kDIErrWriteFailed; + } - startBlock += runCount; - blockCount -= runCount; - } + startBlock += runCount; + blockCount -= runCount; + } - return kDIErrNone; + return kDIErrNone; } @@ -968,67 +968,67 @@ Win32VolumeAccess::BlockAccess::WriteBlocksInt13h(HANDLE handle, int unitNum, */ /*static*/ DIError Win32VolumeAccess::BlockAccess::ReadBlocksInt21h(HANDLE handle, int driveNum, - long startBlock, short blockCount, void* buf) + long startBlock, short blockCount, void* buf) { #if 0 - assert(false); // discouraged - BOOL result; - DWORD cb; - DIOC_REGISTERS reg = {0}; - DISKIO dio = {0}; + assert(false); // discouraged + BOOL result; + DWORD cb; + DIOC_REGISTERS reg = {0}; + DISKIO dio = {0}; - dio.dwStartSector = startBlock; - dio.wSectors = (WORD) blockCount; - dio.dwBuffer = (DWORD) buf; + dio.dwStartSector = startBlock; + dio.wSectors = (WORD) blockCount; + dio.dwBuffer = (DWORD) buf; - reg.reg_EAX = fDriveNum - 1; // Int 25h drive numbers are 0-based. - reg.reg_EBX = (DWORD)&dio; - reg.reg_ECX = 0xFFFF; // use DISKIO struct + reg.reg_EAX = fDriveNum - 1; // Int 25h drive numbers are 0-based. + reg.reg_EBX = (DWORD)&dio; + reg.reg_ECX = 0xFFFF; // use DISKIO struct - WMSG3(" Int25 read start=%d count=%d\n", - startBlock, blockCount); - result = ::DeviceIoControl(handle, VWIN32_DIOC_DOS_INT25, - ®, sizeof(reg), - ®, sizeof(reg), &cb, 0); + WMSG3(" Int25 read start=%d count=%d\n", + startBlock, blockCount); + result = ::DeviceIoControl(handle, VWIN32_DIOC_DOS_INT25, + ®, sizeof(reg), + ®, sizeof(reg), &cb, 0); - // Determine if the DeviceIoControl call and the read succeeded. - result = result && !(reg.reg_Flags & CARRY_FLAG); + // Determine if the DeviceIoControl call and the read succeeded. + result = result && !(reg.reg_Flags & CARRY_FLAG); - WMSG2(" +++ read from block %ld (result=%d)\n", startBlock, result); - if (!result) - return kDIErrReadFailed; + WMSG2(" +++ read from block %ld (result=%d)\n", startBlock, result); + if (!result) + return kDIErrReadFailed; #else - BOOL result; - DWORD cb; - DIOC_REGISTERS reg = {0}; - DISKIO dio = {0}; + BOOL result; + DWORD cb; + DIOC_REGISTERS reg = {0}; + DISKIO dio = {0}; - dio.dwStartSector = startBlock; - dio.wSectors = (WORD) blockCount; - dio.dwBuffer = (DWORD) buf; + dio.dwStartSector = startBlock; + dio.wSectors = (WORD) blockCount; + dio.dwBuffer = (DWORD) buf; - reg.reg_EAX = 0x7305; // Ext_ABSDiskReadWrite - reg.reg_EBX = (DWORD)&dio; - reg.reg_ECX = -1; - reg.reg_EDX = driveNum; // Int 21h, fn 7305h drive numbers are 1-based - assert(reg.reg_ESI == 0); // read/write flag + reg.reg_EAX = 0x7305; // Ext_ABSDiskReadWrite + reg.reg_EBX = (DWORD)&dio; + reg.reg_ECX = -1; + reg.reg_EDX = driveNum; // Int 21h, fn 7305h drive numbers are 1-based + assert(reg.reg_ESI == 0); // read/write flag - WMSG2(" Int21/7305h read start=%d count=%d\n", - startBlock, blockCount); - result = ::DeviceIoControl(handle, VWIN32_DIOC_DOS_DRIVEINFO, - ®, sizeof(reg), - ®, sizeof(reg), &cb, 0); + WMSG2(" Int21/7305h read start=%d count=%d\n", + startBlock, blockCount); + result = ::DeviceIoControl(handle, VWIN32_DIOC_DOS_DRIVEINFO, + ®, sizeof(reg), + ®, sizeof(reg), &cb, 0); - // Determine if the DeviceIoControl call and the read succeeded. - result = result && !(reg.reg_Flags & CARRY_FLAG); + // Determine if the DeviceIoControl call and the read succeeded. + result = result && !(reg.reg_Flags & CARRY_FLAG); - WMSG4(" +++ RB21h %ld %d (result=%d lastError=%ld)\n", - startBlock, blockCount, result, GetLastError()); - if (!result) - return kDIErrReadFailed; + WMSG4(" +++ RB21h %ld %d (result=%d lastError=%ld)\n", + startBlock, blockCount, result, GetLastError()); + if (!result) + return kDIErrReadFailed; #endif - return kDIErrNone; + return kDIErrNone; } /* @@ -1039,38 +1039,38 @@ Win32VolumeAccess::BlockAccess::ReadBlocksInt21h(HANDLE handle, int driveNum, */ /*static*/ DIError Win32VolumeAccess::BlockAccess::WriteBlocksInt21h(HANDLE handle, int driveNum, - long startBlock, short blockCount, const void* buf) + long startBlock, short blockCount, const void* buf) { - BOOL result; - DWORD cb; - DIOC_REGISTERS reg = {0}; - DISKIO dio = {0}; + BOOL result; + DWORD cb; + DIOC_REGISTERS reg = {0}; + DISKIO dio = {0}; - dio.dwStartSector = startBlock; - dio.wSectors = (WORD) blockCount; - dio.dwBuffer = (DWORD) buf; + dio.dwStartSector = startBlock; + dio.wSectors = (WORD) blockCount; + dio.dwBuffer = (DWORD) buf; - reg.reg_EAX = 0x7305; // Ext_ABSDiskReadWrite - reg.reg_EBX = (DWORD)&dio; - reg.reg_ECX = -1; - reg.reg_EDX = driveNum; // Int 21h, fn 7305h drive numbers are 1-based - reg.reg_ESI = 0x6001; // write normal data (bit flags) + reg.reg_EAX = 0x7305; // Ext_ABSDiskReadWrite + reg.reg_EBX = (DWORD)&dio; + reg.reg_ECX = -1; + reg.reg_EDX = driveNum; // Int 21h, fn 7305h drive numbers are 1-based + reg.reg_ESI = 0x6001; // write normal data (bit flags) - //WMSG2(" Int21/7305h write start=%d count=%d\n", - // startBlock, blockCount); - result = ::DeviceIoControl(handle, VWIN32_DIOC_DOS_DRIVEINFO, - ®, sizeof(reg), - ®, sizeof(reg), &cb, 0); + //WMSG2(" Int21/7305h write start=%d count=%d\n", + // startBlock, blockCount); + result = ::DeviceIoControl(handle, VWIN32_DIOC_DOS_DRIVEINFO, + ®, sizeof(reg), + ®, sizeof(reg), &cb, 0); - // Determine if the DeviceIoControl call and the read succeeded. - result = result && !(reg.reg_Flags & CARRY_FLAG); + // Determine if the DeviceIoControl call and the read succeeded. + result = result && !(reg.reg_Flags & CARRY_FLAG); - WMSG4(" +++ WB21h %ld %d (result=%d lastError=%ld)\n", - startBlock, blockCount, result, GetLastError()); - if (!result) - return kDIErrWriteFailed; + WMSG4(" +++ WB21h %ld %d (result=%d lastError=%ld)\n", + startBlock, blockCount, result, GetLastError()); + if (!result) + return kDIErrWriteFailed; - return kDIErrNone; + return kDIErrNone; } @@ -1079,44 +1079,44 @@ Win32VolumeAccess::BlockAccess::WriteBlocksInt21h(HANDLE handle, int driveNum, */ /*static*/ DIError Win32VolumeAccess::BlockAccess::ReadBlocksWin2K(HANDLE handle, - long startBlock, short blockCount, void* buf) + long startBlock, short blockCount, void* buf) { - /* - * Try to read the blocks. Under Win2K the seek and read calls appear - * to succeed, but the value in "actual" is set to zero to indicate - * that we're trying to read past EOF. - */ - DWORD posn, actual; + /* + * Try to read the blocks. Under Win2K the seek and read calls appear + * to succeed, but the value in "actual" is set to zero to indicate + * that we're trying to read past EOF. + */ + DWORD posn, actual; - /* - * Win2K: the 3rd argument holds the high 32 bits of the distance to - * move. This isn't supported in Win9x, which means Win9x is limited - * to 2GB files. - */ - LARGE_INTEGER li; - li.QuadPart = (LONGLONG) startBlock * (LONGLONG) kBlockSize; - posn = ::SetFilePointer(handle, li.LowPart, &li.HighPart, - FILE_BEGIN); - if (posn == INVALID_SET_FILE_POINTER) { - DWORD lerr = GetLastError(); - WMSG1(" GFDWinVolume ReadBlock: SFP failed (err=%ld)\n", lerr); - return LastErrorToDIError(); - } + /* + * Win2K: the 3rd argument holds the high 32 bits of the distance to + * move. This isn't supported in Win9x, which means Win9x is limited + * to 2GB files. + */ + LARGE_INTEGER li; + li.QuadPart = (LONGLONG) startBlock * (LONGLONG) kBlockSize; + posn = ::SetFilePointer(handle, li.LowPart, &li.HighPart, + FILE_BEGIN); + if (posn == INVALID_SET_FILE_POINTER) { + DWORD lerr = GetLastError(); + WMSG1(" GFDWinVolume ReadBlock: SFP failed (err=%ld)\n", lerr); + return LastErrorToDIError(); + } - //WMSG2(" ReadFile block start=%d count=%d\n", startBlock, blockCount); + //WMSG2(" ReadFile block start=%d count=%d\n", startBlock, blockCount); - BOOL result; - result = ::ReadFile(handle, buf, blockCount * kBlockSize, &actual, nil); - if (!result) { - DWORD lerr = GetLastError(); - WMSG3(" ReadBlocksWin2K: ReadFile failed (start=%ld count=%d err=%ld)\n", - startBlock, blockCount, lerr); - return LastErrorToDIError(); - } - if ((long) actual != blockCount * kBlockSize) - return kDIErrEOF; + BOOL result; + result = ::ReadFile(handle, buf, blockCount * kBlockSize, &actual, nil); + if (!result) { + DWORD lerr = GetLastError(); + WMSG3(" ReadBlocksWin2K: ReadFile failed (start=%ld count=%d err=%ld)\n", + startBlock, blockCount, lerr); + return LastErrorToDIError(); + } + if ((long) actual != blockCount * kBlockSize) + return kDIErrEOF; - return kDIErrNone; + return kDIErrNone; } @@ -1125,37 +1125,37 @@ Win32VolumeAccess::BlockAccess::ReadBlocksWin2K(HANDLE handle, */ /*static*/ DIError Win32VolumeAccess::BlockAccess::WriteBlocksWin2K(HANDLE handle, - long startBlock, short blockCount, const void* buf) + long startBlock, short blockCount, const void* buf) { - DWORD posn, actual; + DWORD posn, actual; - posn = ::SetFilePointer(handle, startBlock * kBlockSize, nil, - FILE_BEGIN); - if (posn == INVALID_SET_FILE_POINTER) { - DWORD lerr = GetLastError(); - WMSG2(" GFDWinVolume ReadBlocks: SFP %ld failed (err=%ld)\n", - startBlock * kBlockSize, lerr); - return LastErrorToDIError(); - } + posn = ::SetFilePointer(handle, startBlock * kBlockSize, nil, + FILE_BEGIN); + if (posn == INVALID_SET_FILE_POINTER) { + DWORD lerr = GetLastError(); + WMSG2(" GFDWinVolume ReadBlocks: SFP %ld failed (err=%ld)\n", + startBlock * kBlockSize, lerr); + return LastErrorToDIError(); + } - BOOL result; - result = ::WriteFile(handle, buf, blockCount * kBlockSize, &actual, nil); - if (!result) { - DWORD lerr = GetLastError(); - WMSG1(" GFDWinVolume WriteBlocks: WriteFile failed (err=%ld)\n", - lerr); - return LastErrorToDIError(); - } - if ((long) actual != blockCount * kBlockSize) - return kDIErrEOF; // unexpected on a write call? + BOOL result; + result = ::WriteFile(handle, buf, blockCount * kBlockSize, &actual, nil); + if (!result) { + DWORD lerr = GetLastError(); + WMSG1(" GFDWinVolume WriteBlocks: WriteFile failed (err=%ld)\n", + lerr); + return LastErrorToDIError(); + } + if ((long) actual != blockCount * kBlockSize) + return kDIErrEOF; // unexpected on a write call? - return kDIErrNone; + return kDIErrNone; } /* * =========================================================================== - * LogicalBlockAccess + * LogicalBlockAccess * =========================================================================== */ @@ -1165,140 +1165,140 @@ Win32VolumeAccess::BlockAccess::WriteBlocksWin2K(HANDLE handle, DIError Win32VolumeAccess::LogicalBlockAccess::Open(const char* deviceName, bool readOnly) { - DIError dierr = kDIErrNone; - const bool kPreferASPI = true; + DIError dierr = kDIErrNone; + const bool kPreferASPI = true; - assert(fHandle == nil); - fIsCDROM = false; - fDriveNum = -1; + assert(fHandle == nil); + fIsCDROM = false; + fDriveNum = -1; - if (deviceName[0] < 'A' || deviceName[0] > 'Z' || - deviceName[1] != ':' || deviceName[2] != '\\' || - deviceName[3] != '\0') - { - WMSG1(" LogicalBlockAccess: invalid device name '%s'\n", deviceName); - assert(false); - dierr = kDIErrInvalidArg; - goto bail; - } - if (deviceName[0] == 'C') { - if (readOnly == false) { - WMSG0(" REFUSING WRITE ACCESS TO C:\\ \n"); - return kDIErrVWAccessForbidden; - } - } + if (deviceName[0] < 'A' || deviceName[0] > 'Z' || + deviceName[1] != ':' || deviceName[2] != '\\' || + deviceName[3] != '\0') + { + WMSG1(" LogicalBlockAccess: invalid device name '%s'\n", deviceName); + assert(false); + dierr = kDIErrInvalidArg; + goto bail; + } + if (deviceName[0] == 'C') { + if (readOnly == false) { + WMSG0(" REFUSING WRITE ACCESS TO C:\\ \n"); + return kDIErrVWAccessForbidden; + } + } - DWORD access; - if (readOnly) - access = GENERIC_READ; - else - access = GENERIC_READ | GENERIC_WRITE; + DWORD access; + if (readOnly) + access = GENERIC_READ; + else + access = GENERIC_READ | GENERIC_WRITE; - UINT driveType; - driveType = GetDriveType(deviceName); - if (driveType == DRIVE_CDROM) { - if (!Global::GetHasSPTI() && !Global::GetHasASPI()) - return kDIErrCDROMNotSupported; + UINT driveType; + driveType = GetDriveType(deviceName); + if (driveType == DRIVE_CDROM) { + if (!Global::GetHasSPTI() && !Global::GetHasASPI()) + return kDIErrCDROMNotSupported; - fIsCDROM = true; - // SPTI needs this -- maybe to enforce exclusive access? - access |= GENERIC_WRITE; - } + fIsCDROM = true; + // SPTI needs this -- maybe to enforce exclusive access? + access |= GENERIC_WRITE; + } - if (fIsWin9x) { - if (fIsCDROM) - return kDIErrCDROMNotSupported; + if (fIsWin9x) { + if (fIsCDROM) + return kDIErrCDROMNotSupported; - fHandle = CreateFile("\\\\.\\vwin32", 0, 0, NULL, - OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL); - if (fHandle == INVALID_HANDLE_VALUE) { - DWORD lastError = GetLastError(); - WMSG1(" Win32LVOpen: CreateFile(vwin32) failed (err=%ld)\n", - lastError); - dierr = LastErrorToDIError(); - goto bail; - } - fDriveNum = deviceName[0] - 'A' +1; - assert(fDriveNum > 0 && fDriveNum <= kNumLogicalVolumes); + fHandle = CreateFile("\\\\.\\vwin32", 0, 0, NULL, + OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL); + if (fHandle == INVALID_HANDLE_VALUE) { + DWORD lastError = GetLastError(); + WMSG1(" Win32LVOpen: CreateFile(vwin32) failed (err=%ld)\n", + lastError); + dierr = LastErrorToDIError(); + goto bail; + } + fDriveNum = deviceName[0] - 'A' +1; + assert(fDriveNum > 0 && fDriveNum <= kNumLogicalVolumes); #if 0 - int int13Unit; - dierr = GetInt13Unit(fHandle, fDriveNum, &int13Unit); - if (dierr != kDIErrNone) - goto bail; - if (int13Unit < 4) { - fFloppyUnit = int13Unit; - WMSG2(" Logical volume #%d looks like floppy unit %d\n", - fDriveNum, fFloppyUnit); - } + int int13Unit; + dierr = GetInt13Unit(fHandle, fDriveNum, &int13Unit); + if (dierr != kDIErrNone) + goto bail; + if (int13Unit < 4) { + fFloppyUnit = int13Unit; + WMSG2(" Logical volume #%d looks like floppy unit %d\n", + fDriveNum, fFloppyUnit); + } #endif - } else { - char device[7] = "\\\\.\\_:"; - device[4] = deviceName[0]; - WMSG1("Opening '%s'\n", device); + } else { + char device[7] = "\\\\.\\_:"; + device[4] = deviceName[0]; + WMSG1("Opening '%s'\n", device); - // If we're reading, allow others to write. If we're writing, insist - // upon exclusive access to the volume. - DWORD shareMode = FILE_SHARE_READ; - if (access == GENERIC_READ) - shareMode |= FILE_SHARE_WRITE; + // If we're reading, allow others to write. If we're writing, insist + // upon exclusive access to the volume. + DWORD shareMode = FILE_SHARE_READ; + if (access == GENERIC_READ) + shareMode |= FILE_SHARE_WRITE; - fHandle = CreateFile(device, access, shareMode, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (fHandle == INVALID_HANDLE_VALUE) { - DWORD lastError = GetLastError(); - dierr = LastErrorToDIError(); - if (lastError == ERROR_INVALID_PARAMETER && shareMode == FILE_SHARE_READ) - { - // Win2K spits this back if the volume is open and we're - // not specifying FILE_SHARE_WRITE. Give it a try, just to - // see if it works, so we can tell the difference between - // an internal library error and an active filesystem. - HANDLE tmpHandle; - tmpHandle = CreateFile(device, access, FILE_SHARE_READ|FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (tmpHandle != INVALID_HANDLE_VALUE) { - dierr = kDIErrNoExclusiveAccess; - ::CloseHandle(tmpHandle); - } - } - WMSG2(" LBAccess Open: CreateFile failed (err=%ld dierr=%d)\n", - lastError, dierr); - goto bail; - } - } + fHandle = CreateFile(device, access, shareMode, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (fHandle == INVALID_HANDLE_VALUE) { + DWORD lastError = GetLastError(); + dierr = LastErrorToDIError(); + if (lastError == ERROR_INVALID_PARAMETER && shareMode == FILE_SHARE_READ) + { + // Win2K spits this back if the volume is open and we're + // not specifying FILE_SHARE_WRITE. Give it a try, just to + // see if it works, so we can tell the difference between + // an internal library error and an active filesystem. + HANDLE tmpHandle; + tmpHandle = CreateFile(device, access, FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (tmpHandle != INVALID_HANDLE_VALUE) { + dierr = kDIErrNoExclusiveAccess; + ::CloseHandle(tmpHandle); + } + } + WMSG2(" LBAccess Open: CreateFile failed (err=%ld dierr=%d)\n", + lastError, dierr); + goto bail; + } + } - assert(fHandle != nil && fHandle != INVALID_HANDLE_VALUE); + assert(fHandle != nil && fHandle != INVALID_HANDLE_VALUE); #if 0 - if (fIsCDROM) { - assert(Global::GetHasSPTI() || Global::GetHasASPI()); - if (Global::GetHasASPI() && (!Global::GetHasSPTI() || kPreferASPI)) { - WMSG0(" LBAccess using ASPI\n"); - fCDBaggage.fUseASPI = true; - } else { - WMSG0(" LBAccess using SPTI\n"); - fCDBaggage.fUseASPI = false; - } + if (fIsCDROM) { + assert(Global::GetHasSPTI() || Global::GetHasASPI()); + if (Global::GetHasASPI() && (!Global::GetHasSPTI() || kPreferASPI)) { + WMSG0(" LBAccess using ASPI\n"); + fCDBaggage.fUseASPI = true; + } else { + WMSG0(" LBAccess using SPTI\n"); + fCDBaggage.fUseASPI = false; + } - if (fCDBaggage.fUseASPI) { - dierr = FindASPIDriveMapping(deviceName[0]); - if (dierr != kDIErrNone) { - WMSG0("ERROR: couldn't find ASPI drive mapping\n"); - dierr = kDIErrNoASPIMapping; - goto bail; - } - } - } + if (fCDBaggage.fUseASPI) { + dierr = FindASPIDriveMapping(deviceName[0]); + if (dierr != kDIErrNone) { + WMSG0("ERROR: couldn't find ASPI drive mapping\n"); + dierr = kDIErrNoASPIMapping; + goto bail; + } + } + } #endif bail: - if (dierr != kDIErrNone) { - if (fHandle != nil && fHandle != INVALID_HANDLE_VALUE) - ::CloseHandle(fHandle); - fHandle = nil; - } - return dierr; + if (dierr != kDIErrNone) { + if (fHandle != nil && fHandle != INVALID_HANDLE_VALUE) + ::CloseHandle(fHandle); + fHandle = nil; + } + return dierr; } /* @@ -1307,11 +1307,11 @@ bail: DIError Win32VolumeAccess::LogicalBlockAccess::Close(void) { - if (fHandle != nil) { - ::CloseHandle(fHandle); - fHandle = nil; - } - return kDIErrNone; + if (fHandle != nil) { + ::CloseHandle(fHandle); + fHandle = nil; + } + return kDIErrNone; } @@ -1320,102 +1320,102 @@ Win32VolumeAccess::LogicalBlockAccess::Close(void) */ DIError Win32VolumeAccess::LogicalBlockAccess::ReadBlocksCDROM(HANDLE handle, - long startBlock, short blockCount, void* buf) + long startBlock, short blockCount, void* buf) { #ifdef HAVE_WINDOWS_CDROM - DIError dierr; + DIError dierr; - assert(handle != nil); - assert(startBlock >= 0); - assert(blockCount > 0); - assert(buf != nil); + assert(handle != nil); + assert(startBlock >= 0); + assert(blockCount > 0); + assert(buf != nil); - //WMSG2(" CDROM read block %ld (%ld)\n", startBlock, block); + //WMSG2(" CDROM read block %ld (%ld)\n", startBlock, block); - /* alloc sector buffer on first use */ - if (fLastSectorCache == nil) { - fLastSectorCache = new unsigned char[kCDROMSectorSize]; - if (fLastSectorCache == nil) - return kDIErrMalloc; - assert(fLastSectorNum == -1); - } + /* alloc sector buffer on first use */ + if (fLastSectorCache == nil) { + fLastSectorCache = new unsigned char[kCDROMSectorSize]; + if (fLastSectorCache == nil) + return kDIErrMalloc; + assert(fLastSectorNum == -1); + } - /* - * Map a range of 512-byte blocks to a range of 2048-byte blocks. - */ - assert(kCDROMSectorSize % kBlockSize == 0); - const int kFactor = kCDROMSectorSize / kBlockSize; - long sectorIndex = startBlock / kFactor; - int sectorOffset = (int) (startBlock % kFactor); // 0-3 + /* + * Map a range of 512-byte blocks to a range of 2048-byte blocks. + */ + assert(kCDROMSectorSize % kBlockSize == 0); + const int kFactor = kCDROMSectorSize / kBlockSize; + long sectorIndex = startBlock / kFactor; + int sectorOffset = (int) (startBlock % kFactor); // 0-3 - /* - * When possible, do multi-block reads directly into "buf". The first - * and last block may require special handling. - */ - while (blockCount) { - assert(blockCount > 0); + /* + * When possible, do multi-block reads directly into "buf". The first + * and last block may require special handling. + */ + while (blockCount) { + assert(blockCount > 0); - if (sectorOffset != 0 || blockCount < kFactor) { - assert(sectorOffset >= 0 && sectorOffset < kFactor); + if (sectorOffset != 0 || blockCount < kFactor) { + assert(sectorOffset >= 0 && sectorOffset < kFactor); - /* get from single-block cache or from disc */ - if (sectorIndex != fLastSectorNum) { - fLastSectorNum = -1; // invalidate, in case of error + /* get from single-block cache or from disc */ + if (sectorIndex != fLastSectorNum) { + fLastSectorNum = -1; // invalidate, in case of error - dierr = SPTI::ReadBlocks(handle, sectorIndex, 1, - kCDROMSectorSize, fLastSectorCache); - if (dierr != kDIErrNone) - return dierr; + dierr = SPTI::ReadBlocks(handle, sectorIndex, 1, + kCDROMSectorSize, fLastSectorCache); + if (dierr != kDIErrNone) + return dierr; - fLastSectorNum = sectorIndex; - } + fLastSectorNum = sectorIndex; + } - int thisNumBlocks; - thisNumBlocks = kFactor - sectorOffset; - if (thisNumBlocks > blockCount) - thisNumBlocks = blockCount; + int thisNumBlocks; + thisNumBlocks = kFactor - sectorOffset; + if (thisNumBlocks > blockCount) + thisNumBlocks = blockCount; - //WMSG3(" Small copy (sectIdx=%ld off=%d*512 size=%d*512)\n", - // sectorIndex, sectorOffset, thisNumBlocks); - memcpy(buf, fLastSectorCache + sectorOffset * kBlockSize, - thisNumBlocks * kBlockSize); + //WMSG3(" Small copy (sectIdx=%ld off=%d*512 size=%d*512)\n", + // sectorIndex, sectorOffset, thisNumBlocks); + memcpy(buf, fLastSectorCache + sectorOffset * kBlockSize, + thisNumBlocks * kBlockSize); - blockCount -= thisNumBlocks; - buf = (unsigned char*) buf + (thisNumBlocks * kBlockSize); + blockCount -= thisNumBlocks; + buf = (unsigned char*) buf + (thisNumBlocks * kBlockSize); - sectorOffset = 0; - sectorIndex++; - } else { - fLastSectorNum = -1; // invalidate single-block cache + sectorOffset = 0; + sectorIndex++; + } else { + fLastSectorNum = -1; // invalidate single-block cache - int numSectors; - numSectors = blockCount / kFactor; // rounds down + int numSectors; + numSectors = blockCount / kFactor; // rounds down - //WMSG2(" Big read (sectIdx=%ld numSect=%d)\n", - // sectorIndex, numSectors); - dierr = SPTI::ReadBlocks(handle, sectorIndex, numSectors, - kCDROMSectorSize, buf); - if (dierr != kDIErrNone) - return dierr; + //WMSG2(" Big read (sectIdx=%ld numSect=%d)\n", + // sectorIndex, numSectors); + dierr = SPTI::ReadBlocks(handle, sectorIndex, numSectors, + kCDROMSectorSize, buf); + if (dierr != kDIErrNone) + return dierr; - blockCount -= numSectors * kFactor; - buf = (unsigned char*) buf + (numSectors * kCDROMSectorSize); + blockCount -= numSectors * kFactor; + buf = (unsigned char*) buf + (numSectors * kCDROMSectorSize); - sectorIndex += numSectors; - } - } + sectorIndex += numSectors; + } + } - return kDIErrNone; + return kDIErrNone; #else - return kDIErrCDROMNotSupported; + return kDIErrCDROMNotSupported; #endif } /* * =========================================================================== - * PhysicalBlockAccess + * PhysicalBlockAccess * =========================================================================== */ @@ -1425,108 +1425,108 @@ Win32VolumeAccess::LogicalBlockAccess::ReadBlocksCDROM(HANDLE handle, DIError Win32VolumeAccess::PhysicalBlockAccess::Open(const char* deviceName, bool readOnly) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - // initialize all local state - assert(fHandle == nil); - fInt13Unit = -1; - fFloppyKind = kFloppyUnknown; - memset(&fGeometry, 0, sizeof(fGeometry)); + // initialize all local state + assert(fHandle == nil); + fInt13Unit = -1; + fFloppyKind = kFloppyUnknown; + memset(&fGeometry, 0, sizeof(fGeometry)); - // sanity-check name; not this only works for first 10 devices - if (deviceName[0] < '0' || deviceName[0] > '9' || - deviceName[1] < '0' || deviceName[1] > '9' || - deviceName[2] != ':' || deviceName[3] != '\\' || - deviceName[4] != '\0') - { - WMSG1(" PhysicalBlockAccess: invalid device name '%s'\n", deviceName); - assert(false); - dierr = kDIErrInvalidArg; - goto bail; - } + // sanity-check name; not this only works for first 10 devices + if (deviceName[0] < '0' || deviceName[0] > '9' || + deviceName[1] < '0' || deviceName[1] > '9' || + deviceName[2] != ':' || deviceName[3] != '\\' || + deviceName[4] != '\0') + { + WMSG1(" PhysicalBlockAccess: invalid device name '%s'\n", deviceName); + assert(false); + dierr = kDIErrInvalidArg; + goto bail; + } - if (deviceName[0] == '8' && deviceName[1] == '0') { - if (!gAllowWritePhys0 && readOnly == false) { - WMSG0(" REFUSING WRITE ACCESS TO 80:\\ \n"); - return kDIErrVWAccessForbidden; - } - } + if (deviceName[0] == '8' && deviceName[1] == '0') { + if (!gAllowWritePhys0 && readOnly == false) { + WMSG0(" REFUSING WRITE ACCESS TO 80:\\ \n"); + return kDIErrVWAccessForbidden; + } + } - fInt13Unit = (deviceName[0] - '0') * 16 + deviceName[1] - '0'; - if (!fIsWin9x && fInt13Unit < 0x80) { - WMSG0("GLITCH: can't open floppy as physical unit in Win2K\n"); - dierr = kDIErrInvalidArg; - goto bail; - } - if (fIsWin9x && fInt13Unit >= 0x80) { - WMSG0("GLITCH: can't access physical HD in Win9x\n"); - dierr = kDIErrInvalidArg; - goto bail; - } - if ((fInt13Unit >= 0x00 && fInt13Unit < 0x04) || - (fInt13Unit >= 0x80 && fInt13Unit < 0x88)) - { - WMSG1(" Win32VA/P: opening unit %02xh\n", fInt13Unit); - } else { - WMSG2("GLITCH: converted '%s' to %02xh\n", deviceName, fInt13Unit); - dierr = kDIErrInternal; - goto bail; - } + fInt13Unit = (deviceName[0] - '0') * 16 + deviceName[1] - '0'; + if (!fIsWin9x && fInt13Unit < 0x80) { + WMSG0("GLITCH: can't open floppy as physical unit in Win2K\n"); + dierr = kDIErrInvalidArg; + goto bail; + } + if (fIsWin9x && fInt13Unit >= 0x80) { + WMSG0("GLITCH: can't access physical HD in Win9x\n"); + dierr = kDIErrInvalidArg; + goto bail; + } + if ((fInt13Unit >= 0x00 && fInt13Unit < 0x04) || + (fInt13Unit >= 0x80 && fInt13Unit < 0x88)) + { + WMSG1(" Win32VA/P: opening unit %02xh\n", fInt13Unit); + } else { + WMSG2("GLITCH: converted '%s' to %02xh\n", deviceName, fInt13Unit); + dierr = kDIErrInternal; + goto bail; + } - DWORD access; - if (readOnly) - access = GENERIC_READ; - else - access = GENERIC_READ | GENERIC_WRITE; + DWORD access; + if (readOnly) + access = GENERIC_READ; + else + access = GENERIC_READ | GENERIC_WRITE; - if (fIsWin9x) { - fHandle = CreateFile("\\\\.\\vwin32", 0, 0, NULL, - OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL); - if (fHandle == INVALID_HANDLE_VALUE) { - DWORD lastError = GetLastError(); - WMSG1(" Win32VA/PBOpen: CreateFile(vwin32) failed (err=%ld)\n", - lastError); - dierr = LastErrorToDIError(); - goto bail; - } + if (fIsWin9x) { + fHandle = CreateFile("\\\\.\\vwin32", 0, 0, NULL, + OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, NULL); + if (fHandle == INVALID_HANDLE_VALUE) { + DWORD lastError = GetLastError(); + WMSG1(" Win32VA/PBOpen: CreateFile(vwin32) failed (err=%ld)\n", + lastError); + dierr = LastErrorToDIError(); + goto bail; + } - /* figure out the geometry */ - dierr = DetectFloppyGeometry(); - if (dierr != kDIErrNone) - goto bail; - } else { - char device[19] = "\\\\.\\PhysicalDrive_"; - assert(fInt13Unit >= 0x80 && fInt13Unit <= 0x89); - device[17] = fInt13Unit - 0x80 + '0'; - WMSG2("Opening '%s' (access=0x%02x)\n", device, access); + /* figure out the geometry */ + dierr = DetectFloppyGeometry(); + if (dierr != kDIErrNone) + goto bail; + } else { + char device[19] = "\\\\.\\PhysicalDrive_"; + assert(fInt13Unit >= 0x80 && fInt13Unit <= 0x89); + device[17] = fInt13Unit - 0x80 + '0'; + WMSG2("Opening '%s' (access=0x%02x)\n", device, access); - // If we're reading, allow others to write. If we're writing, insist - // upon exclusive access to the volume. - DWORD shareMode = FILE_SHARE_READ; - if (access == GENERIC_READ) - shareMode |= FILE_SHARE_WRITE; + // If we're reading, allow others to write. If we're writing, insist + // upon exclusive access to the volume. + DWORD shareMode = FILE_SHARE_READ; + if (access == GENERIC_READ) + shareMode |= FILE_SHARE_WRITE; - fHandle = CreateFile(device, access, shareMode, - NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (fHandle == INVALID_HANDLE_VALUE) { - DWORD lastError = GetLastError(); - dierr = LastErrorToDIError(); - WMSG2(" PBAccess Open: CreateFile failed (err=%ld dierr=%d)\n", - lastError, dierr); - goto bail; - } - } + fHandle = CreateFile(device, access, shareMode, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (fHandle == INVALID_HANDLE_VALUE) { + DWORD lastError = GetLastError(); + dierr = LastErrorToDIError(); + WMSG2(" PBAccess Open: CreateFile failed (err=%ld dierr=%d)\n", + lastError, dierr); + goto bail; + } + } - assert(fHandle != nil && fHandle != INVALID_HANDLE_VALUE); + assert(fHandle != nil && fHandle != INVALID_HANDLE_VALUE); bail: - if (dierr != kDIErrNone) { - if (fHandle != nil && fHandle != INVALID_HANDLE_VALUE) - ::CloseHandle(fHandle); - fHandle = nil; - } + if (dierr != kDIErrNone) { + if (fHandle != nil && fHandle != INVALID_HANDLE_VALUE) + ::CloseHandle(fHandle); + fHandle = nil; + } - return dierr; + return dierr; } /* @@ -1537,90 +1537,90 @@ bail: DIError Win32VolumeAccess::PhysicalBlockAccess::DetectFloppyGeometry(void) { - DIError dierr = kDIErrNone; - static const struct { - FloppyKind kind; - DiskGeometry geom; - } floppyGeometry[] = { - { kFloppyUnknown, { -1, -1, -1, -1 } }, - { kFloppy525_360, { 40, 2, 9, 360*2 } }, - { kFloppy525_1200, { 80, 2, 15, 1200*2 } }, - { kFloppy35_720, { 80, 2, 9, 720*2 } }, - { kFloppy35_1440, { 80, 2, 18, 1440*2 } }, - { kFloppy35_2880, { 80, 2, 36, 2880*2 } } - }; - unsigned char buf[kBlockSize]; - FloppyKind driveKind; - int status; + DIError dierr = kDIErrNone; + static const struct { + FloppyKind kind; + DiskGeometry geom; + } floppyGeometry[] = { + { kFloppyUnknown, { -1, -1, -1, -1 } }, + { kFloppy525_360, { 40, 2, 9, 360*2 } }, + { kFloppy525_1200, { 80, 2, 15, 1200*2 } }, + { kFloppy35_720, { 80, 2, 9, 720*2 } }, + { kFloppy35_1440, { 80, 2, 18, 1440*2 } }, + { kFloppy35_2880, { 80, 2, 36, 2880*2 } } + }; + unsigned char buf[kBlockSize]; + FloppyKind driveKind; + int status; - /* verify that we can directly index the table with the enum */ - for (int chk = 0; chk < NELEM(floppyGeometry); chk++) { - assert(floppyGeometry[chk].kind == chk); - } - assert(chk == kFloppyMax); + /* verify that we can directly index the table with the enum */ + for (int chk = 0; chk < NELEM(floppyGeometry); chk++) { + assert(floppyGeometry[chk].kind == chk); + } + assert(chk == kFloppyMax); - /* - * Issue a BIOS call to determine the kind of drive we're looking at. - */ - dierr = GetFloppyDriveKind(fHandle, fInt13Unit, &driveKind); - if (dierr != kDIErrNone) - goto bail; + /* + * Issue a BIOS call to determine the kind of drive we're looking at. + */ + dierr = GetFloppyDriveKind(fHandle, fInt13Unit, &driveKind); + if (dierr != kDIErrNone) + goto bail; - switch (driveKind) { - case kFloppy35_2880: - status = ReadBlocksInt13h(fHandle, fInt13Unit, 0, 0, 36, 1, buf); - if (status == 0) { - fFloppyKind = kFloppy35_2880; - break; - } - // else, fall through - case kFloppy35_1440: - status = ReadBlocksInt13h(fHandle, fInt13Unit, 0, 0, 18, 1, buf); - if (status == 0) { - fFloppyKind = kFloppy35_1440; - break; - } - // else, fall through - case kFloppy35_720: - status = ReadBlocksInt13h(fHandle, fInt13Unit, 0, 0, 9, 1, buf); - if (status == 0) { - fFloppyKind = kFloppy35_720; - break; - } - // else, fail - dierr = kDIErrReadFailed; - goto bail; + switch (driveKind) { + case kFloppy35_2880: + status = ReadBlocksInt13h(fHandle, fInt13Unit, 0, 0, 36, 1, buf); + if (status == 0) { + fFloppyKind = kFloppy35_2880; + break; + } + // else, fall through + case kFloppy35_1440: + status = ReadBlocksInt13h(fHandle, fInt13Unit, 0, 0, 18, 1, buf); + if (status == 0) { + fFloppyKind = kFloppy35_1440; + break; + } + // else, fall through + case kFloppy35_720: + status = ReadBlocksInt13h(fHandle, fInt13Unit, 0, 0, 9, 1, buf); + if (status == 0) { + fFloppyKind = kFloppy35_720; + break; + } + // else, fail + dierr = kDIErrReadFailed; + goto bail; - case kFloppy525_1200: - status = ReadBlocksInt13h(fHandle, fInt13Unit, 0, 0, 15, 1, buf); - if (status == 0) { - fFloppyKind = kFloppy525_1200; - break; - } - // else, fall through - case kFloppy525_360: - status = ReadBlocksInt13h(fHandle, fInt13Unit, 0, 0, 9, 1, buf); - if (status == 0) { - fFloppyKind = kFloppy525_360; - break; - } - // else, fail - dierr = kDIErrReadFailed; - goto bail; + case kFloppy525_1200: + status = ReadBlocksInt13h(fHandle, fInt13Unit, 0, 0, 15, 1, buf); + if (status == 0) { + fFloppyKind = kFloppy525_1200; + break; + } + // else, fall through + case kFloppy525_360: + status = ReadBlocksInt13h(fHandle, fInt13Unit, 0, 0, 9, 1, buf); + if (status == 0) { + fFloppyKind = kFloppy525_360; + break; + } + // else, fail + dierr = kDIErrReadFailed; + goto bail; - default: - WMSG1(" Unknown driveKind %d\n", driveKind); - assert(false); - dierr = kDIErrInternal; - goto bail; - } + default: + WMSG1(" Unknown driveKind %d\n", driveKind); + assert(false); + dierr = kDIErrInternal; + goto bail; + } - WMSG1("PBA: floppy disk appears to be type=%d\n", fFloppyKind); - fGeometry = floppyGeometry[fFloppyKind].geom; + WMSG1("PBA: floppy disk appears to be type=%d\n", fFloppyKind); + fGeometry = floppyGeometry[fFloppyKind].geom; bail: - return dierr; + return dierr; } #if 0 @@ -1630,15 +1630,15 @@ bail: DIError Win32VolumeAccess::PhysicalBlockAccess::FlushBlockDevice(void) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - if (::FlushFileBuffers(fHandle) == FALSE) { - DWORD lastError = GetLastError(); - WMSG1(" Win32VA/PBAFlush: FlushFileBuffers failed (err=%ld)\n", - lastError); - dierr = LastErrorToDIError(); - } - return dierr; + if (::FlushFileBuffers(fHandle) == FALSE) { + DWORD lastError = GetLastError(); + WMSG1(" Win32VA/PBAFlush: FlushFileBuffers failed (err=%ld)\n", + lastError); + dierr = LastErrorToDIError(); + } + return dierr; } #endif @@ -1648,17 +1648,17 @@ Win32VolumeAccess::PhysicalBlockAccess::FlushBlockDevice(void) DIError Win32VolumeAccess::PhysicalBlockAccess::Close(void) { - if (fHandle != nil) { - ::CloseHandle(fHandle); - fHandle = nil; - } - return kDIErrNone; + if (fHandle != nil) { + ::CloseHandle(fHandle); + fHandle = nil; + } + return kDIErrNone; } /* * =========================================================================== - * ASPIBlockAccess + * ASPIBlockAccess * =========================================================================== */ @@ -1669,62 +1669,62 @@ Win32VolumeAccess::PhysicalBlockAccess::Close(void) DIError Win32VolumeAccess::ASPIBlockAccess::Open(const char* deviceName, bool readOnly) { - DIError dierr = kDIErrNone; + DIError dierr = kDIErrNone; - if (fpASPI != nil) - return kDIErrAlreadyOpen; + if (fpASPI != nil) + return kDIErrAlreadyOpen; - fpASPI = Global::GetASPI(); - if (fpASPI == nil) - return kDIErrASPIFailure; + fpASPI = Global::GetASPI(); + if (fpASPI == nil) + return kDIErrASPIFailure; - if (strncmp(deviceName, kASPIDev, strlen(kASPIDev)) != 0) { - assert(false); - dierr = kDIErrInternal; - goto bail; - } + if (strncmp(deviceName, kASPIDev, strlen(kASPIDev)) != 0) { + assert(false); + dierr = kDIErrInternal; + goto bail; + } - const char* cp; - int adapter, target, lun; - int result; + const char* cp; + int adapter, target, lun; + int result; - cp = deviceName + strlen(kASPIDev); - result = 0; - result |= ExtractInt(&cp, &adapter); - result |= ExtractInt(&cp, &target); - result |= ExtractInt(&cp, &lun); - if (result != 0) { - WMSG1(" Win32VA couldn't parse '%s'\n", deviceName); - dierr = kDIErrInternal; - goto bail; - } + cp = deviceName + strlen(kASPIDev); + result = 0; + result |= ExtractInt(&cp, &adapter); + result |= ExtractInt(&cp, &target); + result |= ExtractInt(&cp, &lun); + if (result != 0) { + WMSG1(" Win32VA couldn't parse '%s'\n", deviceName); + dierr = kDIErrInternal; + goto bail; + } - fAdapter = adapter; - fTarget = target; - fLun = lun; + fAdapter = adapter; + fTarget = target; + fLun = lun; - unsigned char deviceType; - dierr = fpASPI->GetDeviceType(fAdapter, fTarget, fLun, &deviceType); - if (dierr != kDIErrNone || - (deviceType != kScsiDevTypeCDROM && deviceType != kScsiDevTypeDASD)) - { - WMSG2(" Win32VA bad GetDeviceType err=%d type=%d\n", - dierr, deviceType); - dierr = kDIErrInternal; // should not be here at all - goto bail; - } - if (deviceType == kScsiDevTypeCDROM) - fReadOnly = true; - else - fReadOnly = readOnly; + unsigned char deviceType; + dierr = fpASPI->GetDeviceType(fAdapter, fTarget, fLun, &deviceType); + if (dierr != kDIErrNone || + (deviceType != kScsiDevTypeCDROM && deviceType != kScsiDevTypeDASD)) + { + WMSG2(" Win32VA bad GetDeviceType err=%d type=%d\n", + dierr, deviceType); + dierr = kDIErrInternal; // should not be here at all + goto bail; + } + if (deviceType == kScsiDevTypeCDROM) + fReadOnly = true; + else + fReadOnly = readOnly; - WMSG4(" Win32VA successful 'open' of '%s' on %d:%d:%d\n", - deviceName, fAdapter, fTarget, fLun); + WMSG4(" Win32VA successful 'open' of '%s' on %d:%d:%d\n", + deviceName, fAdapter, fTarget, fLun); bail: - if (dierr != kDIErrNone) - fpASPI = nil; - return dierr; + if (dierr != kDIErrNone) + fpASPI = nil; + return dierr; } /* @@ -1736,21 +1736,21 @@ bail: int Win32VolumeAccess::ASPIBlockAccess::ExtractInt(const char** pStr, int* pResult) { - char* end = nil; + char* end = nil; - if (*pStr == nil) { - assert(false); - return -1; - } + if (*pStr == nil) { + assert(false); + return -1; + } - *pResult = (int) strtol(*pStr, &end, 10); + *pResult = (int) strtol(*pStr, &end, 10); - if (end == nil) - *pStr = nil; - else - *pStr = end+1; + if (end == nil) + *pStr = nil; + else + *pStr = end+1; - return 0; + return 0; } /* @@ -1761,33 +1761,33 @@ Win32VolumeAccess::ASPIBlockAccess::ExtractInt(const char** pStr, int* pResult) DIError Win32VolumeAccess::ASPIBlockAccess::DetectCapacity(long* pNumBlocks) { - DIError dierr = kDIErrNone; - unsigned long lba, blockLen; + DIError dierr = kDIErrNone; + unsigned long lba, blockLen; - dierr = fpASPI->GetDeviceCapacity(fAdapter, fTarget, fLun, &lba, - &blockLen); - if (dierr != kDIErrNone) - goto bail; + dierr = fpASPI->GetDeviceCapacity(fAdapter, fTarget, fLun, &lba, + &blockLen); + if (dierr != kDIErrNone) + goto bail; - WMSG3("READ CAPACITY reports lba=%lu blockLen=%lu (total=%lu)\n", - lba, blockLen, lba*blockLen); + WMSG3("READ CAPACITY reports lba=%lu blockLen=%lu (total=%lu)\n", + lba, blockLen, lba*blockLen); - fChunkSize = blockLen; + fChunkSize = blockLen; - if ((blockLen % 512) != 0) { - WMSG1("Unacceptable CD-ROM blockLen=%ld, bailing\n", blockLen); - dierr = kDIErrReadFailed; - goto bail; - } + if ((blockLen % 512) != 0) { + WMSG1("Unacceptable CD-ROM blockLen=%ld, bailing\n", blockLen); + dierr = kDIErrReadFailed; + goto bail; + } - // The LBA is the last valid block on the disk. To get the disk size, - // we need to add one. + // The LBA is the last valid block on the disk. To get the disk size, + // we need to add one. - *pNumBlocks = (blockLen/512) * (lba+1); - WMSG1(" ASPI returning 512-byte block count %ld\n", *pNumBlocks); + *pNumBlocks = (blockLen/512) * (lba+1); + WMSG1(" ASPI returning 512-byte block count %ld\n", *pNumBlocks); bail: - return dierr; + return dierr; } /* @@ -1798,87 +1798,87 @@ bail: */ DIError Win32VolumeAccess::ASPIBlockAccess::ReadBlocks(long startBlock, short blockCount, - void* buf) + void* buf) { - DIError dierr; + DIError dierr; - // we're expecting fBlockSize to be 512 or 2048 - assert(fChunkSize >= kBlockSize && fChunkSize <= 65536); - assert((fChunkSize % kBlockSize) == 0); + // we're expecting fBlockSize to be 512 or 2048 + assert(fChunkSize >= kBlockSize && fChunkSize <= 65536); + assert((fChunkSize % kBlockSize) == 0); - /* alloc chunk buffer on first use */ - if (fLastChunkCache == nil) { - fLastChunkCache = new unsigned char[fChunkSize]; - if (fLastChunkCache == nil) - return kDIErrMalloc; - assert(fLastChunkNum == -1); - } + /* alloc chunk buffer on first use */ + if (fLastChunkCache == nil) { + fLastChunkCache = new unsigned char[fChunkSize]; + if (fLastChunkCache == nil) + return kDIErrMalloc; + assert(fLastChunkNum == -1); + } - /* - * Map a range of N-byte blocks to a range of 2048-byte blocks. - */ - const int kFactor = fChunkSize / kBlockSize; - long chunkIndex = startBlock / kFactor; - int chunkOffset = (int) (startBlock % kFactor); // small integer + /* + * Map a range of N-byte blocks to a range of 2048-byte blocks. + */ + const int kFactor = fChunkSize / kBlockSize; + long chunkIndex = startBlock / kFactor; + int chunkOffset = (int) (startBlock % kFactor); // small integer - /* - * When possible, do multi-block reads directly into "buf". The first - * and last block may require special handling. - */ - while (blockCount) { - assert(blockCount > 0); + /* + * When possible, do multi-block reads directly into "buf". The first + * and last block may require special handling. + */ + while (blockCount) { + assert(blockCount > 0); - if (chunkOffset != 0 || blockCount < kFactor) { - assert(chunkOffset >= 0 && chunkOffset < kFactor); + if (chunkOffset != 0 || blockCount < kFactor) { + assert(chunkOffset >= 0 && chunkOffset < kFactor); - /* get from single-block cache or from disc */ - if (chunkIndex != fLastChunkNum) { - fLastChunkNum = -1; // invalidate, in case of error + /* get from single-block cache or from disc */ + if (chunkIndex != fLastChunkNum) { + fLastChunkNum = -1; // invalidate, in case of error - dierr = fpASPI->ReadBlocks(fAdapter, fTarget, fLun, chunkIndex, - 1, fChunkSize, fLastChunkCache); - if (dierr != kDIErrNone) - return dierr; + dierr = fpASPI->ReadBlocks(fAdapter, fTarget, fLun, chunkIndex, + 1, fChunkSize, fLastChunkCache); + if (dierr != kDIErrNone) + return dierr; - fLastChunkNum = chunkIndex; - } + fLastChunkNum = chunkIndex; + } - int thisNumBlocks; - thisNumBlocks = kFactor - chunkOffset; - if (thisNumBlocks > blockCount) - thisNumBlocks = blockCount; + int thisNumBlocks; + thisNumBlocks = kFactor - chunkOffset; + if (thisNumBlocks > blockCount) + thisNumBlocks = blockCount; - //WMSG3(" Small copy (chIdx=%ld off=%d*512 size=%d*512)\n", - // chunkIndex, chunkOffset, thisNumBlocks); - memcpy(buf, fLastChunkCache + chunkOffset * kBlockSize, - thisNumBlocks * kBlockSize); + //WMSG3(" Small copy (chIdx=%ld off=%d*512 size=%d*512)\n", + // chunkIndex, chunkOffset, thisNumBlocks); + memcpy(buf, fLastChunkCache + chunkOffset * kBlockSize, + thisNumBlocks * kBlockSize); - blockCount -= thisNumBlocks; - buf = (unsigned char*) buf + (thisNumBlocks * kBlockSize); + blockCount -= thisNumBlocks; + buf = (unsigned char*) buf + (thisNumBlocks * kBlockSize); - chunkOffset = 0; - chunkIndex++; - } else { - fLastChunkNum = -1; // invalidate single-block cache + chunkOffset = 0; + chunkIndex++; + } else { + fLastChunkNum = -1; // invalidate single-block cache - int numChunks; - numChunks = blockCount / kFactor; // rounds down + int numChunks; + numChunks = blockCount / kFactor; // rounds down - //WMSG2(" Big read (chIdx=%ld numCh=%d)\n", - // chunkIndex, numChunks); - dierr = fpASPI->ReadBlocks(fAdapter, fTarget, fLun, chunkIndex, - numChunks, fChunkSize, buf); - if (dierr != kDIErrNone) - return dierr; + //WMSG2(" Big read (chIdx=%ld numCh=%d)\n", + // chunkIndex, numChunks); + dierr = fpASPI->ReadBlocks(fAdapter, fTarget, fLun, chunkIndex, + numChunks, fChunkSize, buf); + if (dierr != kDIErrNone) + return dierr; - blockCount -= numChunks * kFactor; - buf = (unsigned char*) buf + (numChunks * fChunkSize); + blockCount -= numChunks * kFactor; + buf = (unsigned char*) buf + (numChunks * fChunkSize); - chunkIndex += numChunks; - } - } + chunkIndex += numChunks; + } + } - return kDIErrNone; + return kDIErrNone; } /* @@ -1889,77 +1889,77 @@ Win32VolumeAccess::ASPIBlockAccess::ReadBlocks(long startBlock, short blockCount */ DIError Win32VolumeAccess::ASPIBlockAccess::WriteBlocks(long startBlock, short blockCount, - const void* buf) + const void* buf) { - DIError dierr; + DIError dierr; - if (fReadOnly) - return kDIErrAccessDenied; + if (fReadOnly) + return kDIErrAccessDenied; - // we're expecting fBlockSize to be 512 or 2048 - assert(fChunkSize >= kBlockSize && fChunkSize <= 65536); - assert((fChunkSize % kBlockSize) == 0); + // we're expecting fBlockSize to be 512 or 2048 + assert(fChunkSize >= kBlockSize && fChunkSize <= 65536); + assert((fChunkSize % kBlockSize) == 0); - /* throw out the cache */ - fLastChunkNum = -1; + /* throw out the cache */ + fLastChunkNum = -1; - /* - * Map a range of N-byte blocks to a range of 2048-byte blocks. - */ - const int kFactor = fChunkSize / kBlockSize; - long chunkIndex = startBlock / kFactor; - int chunkOffset = (int) (startBlock % kFactor); // small integer + /* + * Map a range of N-byte blocks to a range of 2048-byte blocks. + */ + const int kFactor = fChunkSize / kBlockSize; + long chunkIndex = startBlock / kFactor; + int chunkOffset = (int) (startBlock % kFactor); // small integer - /* - * When possible, do multi-block writes directly from "buf". The first - * and last block may require special handling. - */ - while (blockCount) { - assert(blockCount > 0); + /* + * When possible, do multi-block writes directly from "buf". The first + * and last block may require special handling. + */ + while (blockCount) { + assert(blockCount > 0); - if (chunkOffset != 0 || blockCount < kFactor) { - assert(chunkOffset >= 0 && chunkOffset < kFactor); + if (chunkOffset != 0 || blockCount < kFactor) { + assert(chunkOffset >= 0 && chunkOffset < kFactor); - /* read the chunk we're writing a part of */ - dierr = fpASPI->ReadBlocks(fAdapter, fTarget, fLun, chunkIndex, - 1, fChunkSize, fLastChunkCache); - if (dierr != kDIErrNone) - return dierr; + /* read the chunk we're writing a part of */ + dierr = fpASPI->ReadBlocks(fAdapter, fTarget, fLun, chunkIndex, + 1, fChunkSize, fLastChunkCache); + if (dierr != kDIErrNone) + return dierr; - int thisNumBlocks; - thisNumBlocks = kFactor - chunkOffset; - if (thisNumBlocks > blockCount) - thisNumBlocks = blockCount; + int thisNumBlocks; + thisNumBlocks = kFactor - chunkOffset; + if (thisNumBlocks > blockCount) + thisNumBlocks = blockCount; - WMSG3(" Small copy out (chIdx=%ld off=%d*512 size=%d*512)\n", - chunkIndex, chunkOffset, thisNumBlocks); - memcpy(fLastChunkCache + chunkOffset * kBlockSize, buf, - thisNumBlocks * kBlockSize); + WMSG3(" Small copy out (chIdx=%ld off=%d*512 size=%d*512)\n", + chunkIndex, chunkOffset, thisNumBlocks); + memcpy(fLastChunkCache + chunkOffset * kBlockSize, buf, + thisNumBlocks * kBlockSize); - blockCount -= thisNumBlocks; - buf = (const unsigned char*) buf + (thisNumBlocks * kBlockSize); + blockCount -= thisNumBlocks; + buf = (const unsigned char*) buf + (thisNumBlocks * kBlockSize); - chunkOffset = 0; - chunkIndex++; - } else { - int numChunks; - numChunks = blockCount / kFactor; // rounds down + chunkOffset = 0; + chunkIndex++; + } else { + int numChunks; + numChunks = blockCount / kFactor; // rounds down - WMSG2(" Big write (chIdx=%ld numCh=%d)\n", - chunkIndex, numChunks); - dierr = fpASPI->WriteBlocks(fAdapter, fTarget, fLun, chunkIndex, - numChunks, fChunkSize, buf); - if (dierr != kDIErrNone) - return dierr; + WMSG2(" Big write (chIdx=%ld numCh=%d)\n", + chunkIndex, numChunks); + dierr = fpASPI->WriteBlocks(fAdapter, fTarget, fLun, chunkIndex, + numChunks, fChunkSize, buf); + if (dierr != kDIErrNone) + return dierr; - blockCount -= numChunks * kFactor; - buf = (const unsigned char*) buf + (numChunks * fChunkSize); + blockCount -= numChunks * kFactor; + buf = (const unsigned char*) buf + (numChunks * fChunkSize); - chunkIndex += numChunks; - } - } + chunkIndex += numChunks; + } + } - return kDIErrNone; + return kDIErrNone; } /* @@ -1968,14 +1968,14 @@ Win32VolumeAccess::ASPIBlockAccess::WriteBlocks(long startBlock, short blockCoun DIError Win32VolumeAccess::ASPIBlockAccess::Close(void) { - fpASPI = nil; - return kDIErrNone; + fpASPI = nil; + return kDIErrNone; } /* * =========================================================================== - * CBCache + * CBCache * =========================================================================== */ @@ -1985,14 +1985,14 @@ Win32VolumeAccess::ASPIBlockAccess::Close(void) bool CBCache::IsBlockInCache(long blockNum) const { - if (fFirstBlock == kEmpty) - return false; - assert(fNumBlocks > 0); + if (fFirstBlock == kEmpty) + return false; + assert(fNumBlocks > 0); - if (blockNum >= fFirstBlock && blockNum < fFirstBlock + fNumBlocks) - return true; - else - return false; + if (blockNum >= fFirstBlock && blockNum < fFirstBlock + fNumBlocks) + return true; + else + return false; } /* @@ -2001,17 +2001,17 @@ CBCache::IsBlockInCache(long blockNum) const DIError CBCache::GetFromCache(long blockNum, void* buf) { - if (!IsBlockInCache(blockNum)) { - assert(false); - return kDIErrInternal; - } + if (!IsBlockInCache(blockNum)) { + assert(false); + return kDIErrInternal; + } - //WMSG1(" CBCache: getting block %d from cache\n", blockNum); - int offset = (blockNum - fFirstBlock) * kBlockSize; - assert(offset >= 0); + //WMSG1(" CBCache: getting block %d from cache\n", blockNum); + int offset = (blockNum - fFirstBlock) * kBlockSize; + assert(offset >= 0); - memcpy(buf, fCache + offset, kBlockSize); - return kDIErrNone; + memcpy(buf, fCache + offset, kBlockSize); + return kDIErrNone; } /* @@ -2022,22 +2022,22 @@ CBCache::GetFromCache(long blockNum, void* buf) bool CBCache::IsRoomInCache(long blockNum) const { - if (fFirstBlock == kEmpty) - return true; + if (fFirstBlock == kEmpty) + return true; - // already in cache? - if (blockNum >= fFirstBlock && blockNum < fFirstBlock + fNumBlocks) - return true; + // already in cache? + if (blockNum >= fFirstBlock && blockNum < fFirstBlock + fNumBlocks) + return true; - // running off the end? - if (fNumBlocks == kMaxCachedBlocks) - return false; + // running off the end? + if (fNumBlocks == kMaxCachedBlocks) + return false; - // is it the exact next one? - if (fFirstBlock + fNumBlocks != blockNum) - return false; + // is it the exact next one? + if (fFirstBlock + fNumBlocks != blockNum) + return false; - return true; + return true; } /* @@ -2052,44 +2052,44 @@ CBCache::IsRoomInCache(long blockNum) const DIError CBCache::PutInCache(long blockNum, const void* buf, bool isDirty) { - int blockOffset = -1; - if (!IsRoomInCache(blockNum)) { - assert(false); - return kDIErrInternal; - } + int blockOffset = -1; + if (!IsRoomInCache(blockNum)) { + assert(false); + return kDIErrInternal; + } - if (fFirstBlock == kEmpty) { - //WMSG1(" CBCache: starting anew with block %ld\n", blockNum); - fFirstBlock = blockNum; - fNumBlocks = 1; - blockOffset = 0; - } else if (blockNum == fFirstBlock + fNumBlocks) { - //WMSG1(" CBCache: appending block %ld\n", blockNum); - blockOffset = fNumBlocks; - fNumBlocks++; - } else if (blockNum >= fFirstBlock && blockNum < fFirstBlock + fNumBlocks) { - blockOffset = blockNum - fFirstBlock; - } else { - assert(false); - return kDIErrInternal; - } - assert(blockOffset != -1); - assert(blockOffset < kMaxCachedBlocks); + if (fFirstBlock == kEmpty) { + //WMSG1(" CBCache: starting anew with block %ld\n", blockNum); + fFirstBlock = blockNum; + fNumBlocks = 1; + blockOffset = 0; + } else if (blockNum == fFirstBlock + fNumBlocks) { + //WMSG1(" CBCache: appending block %ld\n", blockNum); + blockOffset = fNumBlocks; + fNumBlocks++; + } else if (blockNum >= fFirstBlock && blockNum < fFirstBlock + fNumBlocks) { + blockOffset = blockNum - fFirstBlock; + } else { + assert(false); + return kDIErrInternal; + } + assert(blockOffset != -1); + assert(blockOffset < kMaxCachedBlocks); - if (fDirty[blockOffset] && !isDirty) { - WMSG1("BUG: CBCache trying to clear dirty flag for block %ld\n", - blockNum); - assert(false); - return kDIErrInternal; - } - fDirty[blockOffset] = isDirty; + if (fDirty[blockOffset] && !isDirty) { + WMSG1("BUG: CBCache trying to clear dirty flag for block %ld\n", + blockNum); + assert(false); + return kDIErrInternal; + } + fDirty[blockOffset] = isDirty; - //WMSG2(" CBCache: adding block %d to cache at %d\n", blockNum, blockOffset); - int offset = blockOffset * kBlockSize; - assert(offset >= 0); + //WMSG2(" CBCache: adding block %d to cache at %d\n", blockNum, blockOffset); + int offset = blockOffset * kBlockSize; + assert(offset >= 0); - memcpy(fCache + offset, buf, kBlockSize); - return kDIErrNone; + memcpy(fCache + offset, buf, kBlockSize); + return kDIErrNone; } /* @@ -2098,19 +2098,19 @@ CBCache::PutInCache(long blockNum, const void* buf, bool isDirty) bool CBCache::IsDirty(void) const { - if (fFirstBlock == kEmpty) - return false; + if (fFirstBlock == kEmpty) + return false; - assert(fNumBlocks > 0); - for (int i = 0; i < fNumBlocks; i++) { - if (fDirty[i]) { - //WMSG0(" CBCache: dirty blocks found\n"); - return true; - } - } + assert(fNumBlocks > 0); + for (int i = 0; i < fNumBlocks; i++) { + if (fDirty[i]) { + //WMSG0(" CBCache: dirty blocks found\n"); + return true; + } + } - //WMSG0(" CBCache: no dirty blocks found\n"); - return false; + //WMSG0(" CBCache: no dirty blocks found\n"); + return false; } /* @@ -2120,11 +2120,11 @@ CBCache::IsDirty(void) const void CBCache::GetCachePointer(long* pFirstBlock, int* pNumBlocks, void** pBuf) const { - assert(fFirstBlock != kEmpty); // not essential, but why call here if not? + assert(fFirstBlock != kEmpty); // not essential, but why call here if not? - *pFirstBlock = fFirstBlock; - *pNumBlocks = fNumBlocks; - *pBuf = (void*) fCache; + *pFirstBlock = fFirstBlock; + *pNumBlocks = fNumBlocks; + *pBuf = (void*) fCache; } /* @@ -2133,11 +2133,11 @@ CBCache::GetCachePointer(long* pFirstBlock, int* pNumBlocks, void** pBuf) const void CBCache::Scrub(void) { - if (fFirstBlock == kEmpty) - return; + if (fFirstBlock == kEmpty) + return; - for (int i = 0; i < fNumBlocks; i++) - fDirty[i] = false; + for (int i = 0; i < fNumBlocks; i++) + fDirty[i] = false; } /* @@ -2146,18 +2146,18 @@ CBCache::Scrub(void) void CBCache::Purge(void) { - if (fFirstBlock == kEmpty) - return; + if (fFirstBlock == kEmpty) + return; - if (IsDirty()) { - // Should only happen after a write failure causes us to clean up. - WMSG0("HEY: CBCache purging dirty blocks!\n"); - //assert(false); - } - Scrub(); + if (IsDirty()) { + // Should only happen after a write failure causes us to clean up. + WMSG0("HEY: CBCache purging dirty blocks!\n"); + //assert(false); + } + Scrub(); - fFirstBlock = kEmpty; - fNumBlocks = 0; + fFirstBlock = kEmpty; + fNumBlocks = 0; } diff --git a/diskimg/Win32BlockIO.h b/diskimg/Win32BlockIO.h index 0a16516..078f238 100644 --- a/diskimg/Win32BlockIO.h +++ b/diskimg/Win32BlockIO.h @@ -40,12 +40,12 @@ * vs. ASPI for CD-ROM). There is no perfect decomposition. * * Summary: - * Win9x/ME physical drive: Int13h (doesn't work for hard drives) - * Win9x/ME logical drive: Int21h/7305h - * Win9x/ME SCSI drive or CD-ROM drive: ASPI - * Win2K/XP physical drive: CreateFile("\\.\PhysicalDriveN") - * Win2K/XP logical drive: CreateFile("\\.\X") - * Win2K/XP SCSI drive or CD-ROM drive: SPTI + * Win9x/ME physical drive: Int13h (doesn't work for hard drives) + * Win9x/ME logical drive: Int21h/7305h + * Win9x/ME SCSI drive or CD-ROM drive: ASPI + * Win2K/XP physical drive: CreateFile("\\.\PhysicalDriveN") + * Win2K/XP logical drive: CreateFile("\\.\X") + * Win2K/XP SCSI drive or CD-ROM drive: SPTI */ #ifndef __WIN32BLOCKIO__ #define __WIN32BLOCKIO__ @@ -74,43 +74,43 @@ extern bool IsWin9x(void); */ class CBCache { public: - CBCache(void) : fFirstBlock(kEmpty), fNumBlocks(0) - { - for (int i = 0; i < kMaxCachedBlocks; i++) - fDirty[i] = false; - } - virtual ~CBCache(void) { Purge(); } + CBCache(void) : fFirstBlock(kEmpty), fNumBlocks(0) + { + for (int i = 0; i < kMaxCachedBlocks; i++) + fDirty[i] = false; + } + virtual ~CBCache(void) { Purge(); } - enum { kEmpty = -1 }; + enum { kEmpty = -1 }; - // is the block we want in the cache? - bool IsBlockInCache(long blockNum) const; - // read block out of cache (after verifying that it's present) - DIError GetFromCache(long blockNum, void* buf); - // can the cache store this block? - bool IsRoomInCache(long blockNum) const; - // write block to cache (after verifying that it will fit) - DIError PutInCache(long blockNum, const void* buf, bool isDirty); + // is the block we want in the cache? + bool IsBlockInCache(long blockNum) const; + // read block out of cache (after verifying that it's present) + DIError GetFromCache(long blockNum, void* buf); + // can the cache store this block? + bool IsRoomInCache(long blockNum) const; + // write block to cache (after verifying that it will fit) + DIError PutInCache(long blockNum, const void* buf, bool isDirty); - // are there any dirty blocks in the cache? - bool IsDirty(void) const; - // get start, count, and buffer so we can write the cached data - void GetCachePointer(long* pFirstBlock, int* pNumBlocks, void** pBuf) const; - // clear all the dirty flags - void Scrub(void); - // purge all cache entries (ideally after writing w/help from GetCachePtr) - void Purge(void); + // are there any dirty blocks in the cache? + bool IsDirty(void) const; + // get start, count, and buffer so we can write the cached data + void GetCachePointer(long* pFirstBlock, int* pNumBlocks, void** pBuf) const; + // clear all the dirty flags + void Scrub(void); + // purge all cache entries (ideally after writing w/help from GetCachePtr) + void Purge(void); private: - enum { - kMaxCachedBlocks = 18, // one track on 1.4MB floppy - kBlockSize = 512, // must match with Win32LogicalVolume:: - }; + enum { + kMaxCachedBlocks = 18, // one track on 1.4MB floppy + kBlockSize = 512, // must match with Win32LogicalVolume:: + }; - long fFirstBlock; // set to kEmpty when cache is empty - int fNumBlocks; - bool fDirty[kMaxCachedBlocks]; - unsigned char fCache[kMaxCachedBlocks * kBlockSize]; + long fFirstBlock; // set to kEmpty when cache is empty + int fNumBlocks; + bool fDirty[kMaxCachedBlocks]; + unsigned char fCache[kMaxCachedBlocks * kBlockSize]; }; @@ -119,283 +119,283 @@ private: */ class Win32VolumeAccess { public: - Win32VolumeAccess(void) : fpBlockAccess(NULL) - {} - virtual ~Win32VolumeAccess(void) { - if (fpBlockAccess != NULL) { - FlushCache(true); - fpBlockAccess->Close(); - } - } + Win32VolumeAccess(void) : fpBlockAccess(NULL) + {} + virtual ~Win32VolumeAccess(void) { + if (fpBlockAccess != NULL) { + FlushCache(true); + fpBlockAccess->Close(); + } + } - // "deviceName" has the form "X:\" (logical), "81:\" (physical), or - // "ASPI:x:y:z\" (ASPI) - DIError Open(const char* deviceName, bool readOnly); - // close the device - void Close(void); - // is the device open and working? - bool Ready(void) const { return fpBlockAccess != NULL; } + // "deviceName" has the form "X:\" (logical), "81:\" (physical), or + // "ASPI:x:y:z\" (ASPI) + DIError Open(const char* deviceName, bool readOnly); + // close the device + void Close(void); + // is the device open and working? + bool Ready(void) const { return fpBlockAccess != NULL; } - // return the volume's EOF - long GetTotalBlocks(void) const { return fTotalBlocks; } - // return the block size for this volume (always a power of 2) - int GetBlockSize(void) const { return BlockAccess::kBlockSize; } + // return the volume's EOF + long GetTotalBlocks(void) const { return fTotalBlocks; } + // return the block size for this volume (always a power of 2) + int GetBlockSize(void) const { return BlockAccess::kBlockSize; } - // read one or more consecutive blocks - DIError ReadBlocks(long startBlock, short blockCount, void* buf); - // write one or more consecutive blocks - DIError WriteBlocks(long startBlock, short blockCount, const void* buf); - // flush our internal cache - DIError FlushCache(bool purge); + // read one or more consecutive blocks + DIError ReadBlocks(long startBlock, short blockCount, void* buf); + // write one or more consecutive blocks + DIError WriteBlocks(long startBlock, short blockCount, const void* buf); + // flush our internal cache + DIError FlushCache(bool purge); private: - /* - * Abstract base class with some handy functions. - */ - class BlockAccess { - public: - BlockAccess(void) { fIsWin9x = DiskImgLib::IsWin9x(); } - virtual ~BlockAccess(void) {} + /* + * Abstract base class with some handy functions. + */ + class BlockAccess { + public: + BlockAccess(void) { fIsWin9x = DiskImgLib::IsWin9x(); } + virtual ~BlockAccess(void) {} - typedef struct { - int numCyls; - int numHeads; - int numSectors; - long blockCount; // total #of blocks on this kind of disk - } DiskGeometry; + typedef struct { + int numCyls; + int numHeads; + int numSectors; + long blockCount; // total #of blocks on this kind of disk + } DiskGeometry; - // generic interfaces - virtual DIError Open(const char* deviceName, bool readOnly) = 0; - virtual DIError DetectCapacity(long* pNumBlocks) = 0; - virtual DIError ReadBlocks(long startBlock, short blockCount, - void* buf) = 0; - virtual DIError WriteBlocks(long startBlock, short blockCount, - const void* buf) = 0; - virtual DIError Close(void) = 0; + // generic interfaces + virtual DIError Open(const char* deviceName, bool readOnly) = 0; + virtual DIError DetectCapacity(long* pNumBlocks) = 0; + virtual DIError ReadBlocks(long startBlock, short blockCount, + void* buf) = 0; + virtual DIError WriteBlocks(long startBlock, short blockCount, + const void* buf) = 0; + virtual DIError Close(void) = 0; - static bool BlockToCylinderHeadSector(long blockNum, - const DiskGeometry* pGeometry, int* pCylinder, int* pHead, - int* pSector, long* pLastBlockOnTrack); + static bool BlockToCylinderHeadSector(long blockNum, + const DiskGeometry* pGeometry, int* pCylinder, int* pHead, + int* pSector, long* pLastBlockOnTrack); - enum { - kNumLogicalVolumes = 26, // A-Z - kBlockSize = 512, - kCDROMSectorSize = 2048, - kMaxFloppyRetries = 3, // retry floppy reads/writes - }; + enum { + kNumLogicalVolumes = 26, // A-Z + kBlockSize = 512, + kCDROMSectorSize = 2048, + kMaxFloppyRetries = 3, // retry floppy reads/writes + }; - // BIOS floppy disk drive type; doubles here as media type - typedef enum { - kFloppyUnknown = 0, - kFloppy525_360 = 1, - kFloppy525_1200 = 2, - kFloppy35_720 = 3, - kFloppy35_1440 = 4, - kFloppy35_2880 = 5, + // BIOS floppy disk drive type; doubles here as media type + typedef enum { + kFloppyUnknown = 0, + kFloppy525_360 = 1, + kFloppy525_1200 = 2, + kFloppy35_720 = 3, + kFloppy35_1440 = 4, + kFloppy35_2880 = 5, - kFloppyMax - } FloppyKind; + kFloppyMax + } FloppyKind; - protected: - static DIError GetFloppyDriveKind(HANDLE handle, int unitNum, - FloppyKind* pKind); - // detect the #of blocks on the volume - static DIError ScanCapacity(BlockAccess* pThis, long* pNumBlocks); - // determine whether a block is readable - static bool CanReadBlock(BlockAccess* pThis, long blockNum); - // try to detect device capacity using SPTI - DIError DetectCapacitySPTI(HANDLE handle, - bool isCDROM, long* pNumBlocks); + protected: + static DIError GetFloppyDriveKind(HANDLE handle, int unitNum, + FloppyKind* pKind); + // detect the #of blocks on the volume + static DIError ScanCapacity(BlockAccess* pThis, long* pNumBlocks); + // determine whether a block is readable + static bool CanReadBlock(BlockAccess* pThis, long blockNum); + // try to detect device capacity using SPTI + DIError DetectCapacitySPTI(HANDLE handle, + bool isCDROM, long* pNumBlocks); - static int ReadBlocksInt13h(HANDLE handle, int unitNum, - int cylinder, int head, int sector, short blockCount, void* buf); - static DIError ReadBlocksInt13h(HANDLE handle, int unitNum, - const DiskGeometry* pGeometry, long startBlock, short blockCount, - void* buf); - static int WriteBlocksInt13h(HANDLE handle, int unitNum, - int cylinder, int head, int sector, short blockCount, - const void* buf); - static DIError WriteBlocksInt13h(HANDLE handle, int unitNum, - const DiskGeometry* pGeometry, long startBlock, short blockCount, - const void* buf); + static int ReadBlocksInt13h(HANDLE handle, int unitNum, + int cylinder, int head, int sector, short blockCount, void* buf); + static DIError ReadBlocksInt13h(HANDLE handle, int unitNum, + const DiskGeometry* pGeometry, long startBlock, short blockCount, + void* buf); + static int WriteBlocksInt13h(HANDLE handle, int unitNum, + int cylinder, int head, int sector, short blockCount, + const void* buf); + static DIError WriteBlocksInt13h(HANDLE handle, int unitNum, + const DiskGeometry* pGeometry, long startBlock, short blockCount, + const void* buf); - static DIError ReadBlocksInt21h(HANDLE handle, int driveNum, - long startBlock, short blockCount, void* buf); - static DIError WriteBlocksInt21h(HANDLE handle, int driveNum, - long startBlock, short blockCount, const void* buf); + static DIError ReadBlocksInt21h(HANDLE handle, int driveNum, + long startBlock, short blockCount, void* buf); + static DIError WriteBlocksInt21h(HANDLE handle, int driveNum, + long startBlock, short blockCount, const void* buf); - static DIError ReadBlocksWin2K(HANDLE handle, - long startBlock, short blockCount, void* buf); - static DIError WriteBlocksWin2K(HANDLE handle, - long startBlock, short blockCount, const void* buf); + static DIError ReadBlocksWin2K(HANDLE handle, + long startBlock, short blockCount, void* buf); + static DIError WriteBlocksWin2K(HANDLE handle, + long startBlock, short blockCount, const void* buf); - bool fIsWin9x; // Win9x/ME=true, Win2K/XP=false - }; + bool fIsWin9x; // Win9x/ME=true, Win2K/XP=false + }; - /* - * Access to a logical volume (e.g. "C:\") under Win9x and Win2K/XP. - */ - class LogicalBlockAccess : public BlockAccess { - public: - LogicalBlockAccess(void) : fHandle(NULL), fIsCDROM(false), - fDriveNum(-1), fLastSectorCache(nil), fLastSectorNum(-1) - {} - virtual ~LogicalBlockAccess(void) { - if (fHandle != NULL) { - //WMSG0("HEY: LogicalBlockAccess: forcing close\n"); - Close(); - } - delete[] fLastSectorCache; - } + /* + * Access to a logical volume (e.g. "C:\") under Win9x and Win2K/XP. + */ + class LogicalBlockAccess : public BlockAccess { + public: + LogicalBlockAccess(void) : fHandle(NULL), fIsCDROM(false), + fDriveNum(-1), fLastSectorCache(nil), fLastSectorNum(-1) + {} + virtual ~LogicalBlockAccess(void) { + if (fHandle != NULL) { + //WMSG0("HEY: LogicalBlockAccess: forcing close\n"); + Close(); + } + delete[] fLastSectorCache; + } - virtual DIError Open(const char* deviceName, bool readOnly); - virtual DIError DetectCapacity(long* pNumBlocks) { - /* use SCSI length value if at all possible */ - DIError dierr; - dierr = DetectCapacitySPTI(fHandle, fIsCDROM, pNumBlocks); - if (fIsCDROM) - return dierr; // SPTI should always work for CD-ROM - if (dierr != kDIErrNone) - return ScanCapacity(this, pNumBlocks); // fall back on scan - else - return dierr; - } - virtual DIError ReadBlocks(long startBlock, short blockCount, - void* buf) - { - if (fIsCDROM) - return ReadBlocksCDROM(fHandle, startBlock, blockCount, buf); - if (fIsWin9x) - return ReadBlocksInt21h(fHandle, fDriveNum, startBlock, - blockCount, buf); - else - return ReadBlocksWin2K(fHandle, startBlock, blockCount, buf); - } - virtual DIError WriteBlocks(long startBlock, short blockCount, - const void* buf) - { - if (fIsCDROM) - return kDIErrWriteProtected; - if (fIsWin9x) - return WriteBlocksInt21h(fHandle, fDriveNum, startBlock, - blockCount, buf); - else - return WriteBlocksWin2K(fHandle, startBlock, blockCount, buf); - } - virtual DIError Close(void); + virtual DIError Open(const char* deviceName, bool readOnly); + virtual DIError DetectCapacity(long* pNumBlocks) { + /* use SCSI length value if at all possible */ + DIError dierr; + dierr = DetectCapacitySPTI(fHandle, fIsCDROM, pNumBlocks); + if (fIsCDROM) + return dierr; // SPTI should always work for CD-ROM + if (dierr != kDIErrNone) + return ScanCapacity(this, pNumBlocks); // fall back on scan + else + return dierr; + } + virtual DIError ReadBlocks(long startBlock, short blockCount, + void* buf) + { + if (fIsCDROM) + return ReadBlocksCDROM(fHandle, startBlock, blockCount, buf); + if (fIsWin9x) + return ReadBlocksInt21h(fHandle, fDriveNum, startBlock, + blockCount, buf); + else + return ReadBlocksWin2K(fHandle, startBlock, blockCount, buf); + } + virtual DIError WriteBlocks(long startBlock, short blockCount, + const void* buf) + { + if (fIsCDROM) + return kDIErrWriteProtected; + if (fIsWin9x) + return WriteBlocksInt21h(fHandle, fDriveNum, startBlock, + blockCount, buf); + else + return WriteBlocksWin2K(fHandle, startBlock, blockCount, buf); + } + virtual DIError Close(void); - private: - //DIError DetectCapacitySPTI(long* pNumBlocks); - DIError ReadBlocksCDROM(HANDLE handle, - long startBlock, short numBlocks, void* buf); + private: + //DIError DetectCapacitySPTI(long* pNumBlocks); + DIError ReadBlocksCDROM(HANDLE handle, + long startBlock, short numBlocks, void* buf); - // Win2K/XP and Win9x/ME - HANDLE fHandle; - bool fIsCDROM; // set for CD-ROM devices - // Win9x/ME - int fDriveNum; // 1=A, 3=C, etc - // CD-ROM goodies - unsigned char* fLastSectorCache; - long fLastSectorNum; - }; + // Win2K/XP and Win9x/ME + HANDLE fHandle; + bool fIsCDROM; // set for CD-ROM devices + // Win9x/ME + int fDriveNum; // 1=A, 3=C, etc + // CD-ROM goodies + unsigned char* fLastSectorCache; + long fLastSectorNum; + }; - /* - * Access to a physical volume (e.g. 00h or 80h) under Win9x and - * Win2K/XP. - */ - class PhysicalBlockAccess : public BlockAccess { - public: - PhysicalBlockAccess(void) : fHandle(NULL), fInt13Unit(-1) {} - virtual ~PhysicalBlockAccess(void) {} + /* + * Access to a physical volume (e.g. 00h or 80h) under Win9x and + * Win2K/XP. + */ + class PhysicalBlockAccess : public BlockAccess { + public: + PhysicalBlockAccess(void) : fHandle(NULL), fInt13Unit(-1) {} + virtual ~PhysicalBlockAccess(void) {} - virtual DIError Open(const char* deviceName, bool readOnly); - virtual DIError DetectCapacity(long* pNumBlocks) { - /* try SPTI in case it happens to work */ - DIError dierr; - dierr = DetectCapacitySPTI(fHandle, false, pNumBlocks); - if (dierr != kDIErrNone) - return ScanCapacity(this, pNumBlocks); - else - return dierr; - } - virtual DIError ReadBlocks(long startBlock, short blockCount, - void* buf) - { - if (fIsWin9x) - return ReadBlocksInt13h(fHandle, fInt13Unit, - &fGeometry, startBlock, blockCount, buf); - else - return ReadBlocksWin2K(fHandle, - startBlock, blockCount, buf); - } - virtual DIError WriteBlocks(long startBlock, short blockCount, - const void* buf) - { - if (fIsWin9x) - return WriteBlocksInt13h(fHandle, fInt13Unit, - &fGeometry, startBlock, blockCount, buf); - else - return WriteBlocksWin2K(fHandle, - startBlock, blockCount, buf); - } - virtual DIError Close(void); + virtual DIError Open(const char* deviceName, bool readOnly); + virtual DIError DetectCapacity(long* pNumBlocks) { + /* try SPTI in case it happens to work */ + DIError dierr; + dierr = DetectCapacitySPTI(fHandle, false, pNumBlocks); + if (dierr != kDIErrNone) + return ScanCapacity(this, pNumBlocks); + else + return dierr; + } + virtual DIError ReadBlocks(long startBlock, short blockCount, + void* buf) + { + if (fIsWin9x) + return ReadBlocksInt13h(fHandle, fInt13Unit, + &fGeometry, startBlock, blockCount, buf); + else + return ReadBlocksWin2K(fHandle, + startBlock, blockCount, buf); + } + virtual DIError WriteBlocks(long startBlock, short blockCount, + const void* buf) + { + if (fIsWin9x) + return WriteBlocksInt13h(fHandle, fInt13Unit, + &fGeometry, startBlock, blockCount, buf); + else + return WriteBlocksWin2K(fHandle, + startBlock, blockCount, buf); + } + virtual DIError Close(void); - private: - DIError DetectFloppyGeometry(void); + private: + DIError DetectFloppyGeometry(void); - // Win2K/XP - HANDLE fHandle; - // Win9x/ME - int fInt13Unit; // 00h=floppy #1, 80h=HD#1 - FloppyKind fFloppyKind; - DiskGeometry fGeometry; - }; + // Win2K/XP + HANDLE fHandle; + // Win9x/ME + int fInt13Unit; // 00h=floppy #1, 80h=HD#1 + FloppyKind fFloppyKind; + DiskGeometry fGeometry; + }; - /* - * Access to a SCSI volume via the ASPI interface. - */ - class ASPIBlockAccess : public BlockAccess { - public: - ASPIBlockAccess(void) : fpASPI(nil), - fAdapter(0xff), fTarget(0xff), fLun(0xff), fReadOnly(false), - fLastChunkCache(nil), fLastChunkNum(-1), fChunkSize(-1) - {} - virtual ~ASPIBlockAccess(void) { delete[] fLastChunkCache; } + /* + * Access to a SCSI volume via the ASPI interface. + */ + class ASPIBlockAccess : public BlockAccess { + public: + ASPIBlockAccess(void) : fpASPI(nil), + fAdapter(0xff), fTarget(0xff), fLun(0xff), fReadOnly(false), + fLastChunkCache(nil), fLastChunkNum(-1), fChunkSize(-1) + {} + virtual ~ASPIBlockAccess(void) { delete[] fLastChunkCache; } - virtual DIError Open(const char* deviceName, bool readOnly); - virtual DIError DetectCapacity(long* pNumBlocks); - virtual DIError ReadBlocks(long startBlock, short blockCount, - void* buf); - virtual DIError WriteBlocks(long startBlock, short blockCount, - const void* buf); - virtual DIError Close(void); + virtual DIError Open(const char* deviceName, bool readOnly); + virtual DIError DetectCapacity(long* pNumBlocks); + virtual DIError ReadBlocks(long startBlock, short blockCount, + void* buf); + virtual DIError WriteBlocks(long startBlock, short blockCount, + const void* buf); + virtual DIError Close(void); - private: - int ExtractInt(const char** pStr, int* pResult); + private: + int ExtractInt(const char** pStr, int* pResult); - ASPI* fpASPI; - unsigned char fAdapter; - unsigned char fTarget; - unsigned char fLun; + ASPI* fpASPI; + unsigned char fAdapter; + unsigned char fTarget; + unsigned char fLun; - bool fReadOnly; + bool fReadOnly; - // block cache - unsigned char* fLastChunkCache; - long fLastChunkNum; - long fChunkSize; // set by DetectCapacity - }; + // block cache + unsigned char* fLastChunkCache; + long fLastChunkNum; + long fChunkSize; // set by DetectCapacity + }; - // write a series of blocks to the volume - DIError DoWriteBlocks(long startBlock, short blockCount, const void* buf) - { - return fpBlockAccess->WriteBlocks(startBlock, blockCount, buf); - } + // write a series of blocks to the volume + DIError DoWriteBlocks(long startBlock, short blockCount, const void* buf) + { + return fpBlockAccess->WriteBlocks(startBlock, blockCount, buf); + } - long fTotalBlocks; - BlockAccess* fpBlockAccess; // really LogicalBA or PhysicalBA - CBCache fBlockCache; + long fTotalBlocks; + BlockAccess* fpBlockAccess; // really LogicalBA or PhysicalBA + CBCache fBlockCache; }; }; // namespace DiskImgLib diff --git a/diskimg/Win32Extra.h b/diskimg/Win32Extra.h index 8f22291..6175388 100644 --- a/diskimg/Win32Extra.h +++ b/diskimg/Win32Extra.h @@ -12,7 +12,7 @@ #ifndef __WIN32EXTRA__ #define __WIN32EXTRA__ -#include // base definitions +#include // base definitions #ifndef IOCTL_DISK_GET_DRIVE_GEOMETRY_EX @@ -29,7 +29,7 @@ BOOL DeviceIoControl( ); */ -#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX \ +#define IOCTL_DISK_GET_DRIVE_GEOMETRY_EX \ CTL_CODE(IOCTL_DISK_BASE, 0x0028, METHOD_BUFFERED, FILE_ANY_ACCESS) typedef struct _DISK_GEOMETRY_EX { @@ -40,14 +40,14 @@ typedef struct _DISK_GEOMETRY_EX { #if 0 typedef struct _DISK_DETECTION_INFO { - DWORD SizeOfDetectInfo; - DETECTION_TYPE DetectionType; - union { - struct { - DISK_INT13_INFO Int13; - DISK_EX_INT13_INFO ExInt13; - }; - }; + DWORD SizeOfDetectInfo; + DETECTION_TYPE DetectionType; + union { + struct { + DISK_INT13_INFO Int13; + DISK_EX_INT13_INFO ExInt13; + }; + }; } DISK_DETECTION_INFO, *PDISK_DETECTION_INFO; PDISK_DETECTION_INFO DiskGeometryGetDetect(PDISK_GEOMETRY_EX Geometry); diff --git a/mdc/AboutDlg.cpp b/mdc/AboutDlg.cpp index d5b83fb..2c35522 100644 --- a/mdc/AboutDlg.cpp +++ b/mdc/AboutDlg.cpp @@ -21,17 +21,17 @@ static char THIS_FILE[] = __FILE__; AboutDlg::AboutDlg(CWnd* pParent /*=NULL*/) - : CDialog(AboutDlg::IDD, pParent) + : CDialog(AboutDlg::IDD, pParent) { - //{{AFX_DATA_INIT(AboutDlg) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT + //{{AFX_DATA_INIT(AboutDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT } BEGIN_MESSAGE_MAP(AboutDlg, CDialog) - //{{AFX_MSG_MAP(AboutDlg) - //}}AFX_MSG_MAP + //{{AFX_MSG_MAP(AboutDlg) + //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// @@ -39,18 +39,18 @@ END_MESSAGE_MAP() BOOL AboutDlg::OnInitDialog() { - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - CWnd* pWnd = GetDlgItem(IDC_ABOUT_VERS); - ASSERT(pWnd != nil); - CString fmt, newText; + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + CWnd* pWnd = GetDlgItem(IDC_ABOUT_VERS); + ASSERT(pWnd != nil); + CString fmt, newText; - pWnd->GetWindowText(fmt); - newText.Format(fmt, kAppMajorVersion, kAppMinorVersion, kAppBugVersion); - pWnd->SetWindowText(newText); - WMSG1("STR is '%s'\n", newText); + pWnd->GetWindowText(fmt); + newText.Format(fmt, kAppMajorVersion, kAppMinorVersion, kAppBugVersion); + pWnd->SetWindowText(newText); + WMSG1("STR is '%s'\n", newText); - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE } diff --git a/mdc/AboutDlg.h b/mdc/AboutDlg.h index 3b067ef..c020ad1 100644 --- a/mdc/AboutDlg.h +++ b/mdc/AboutDlg.h @@ -19,28 +19,28 @@ class AboutDlg : public CDialog { // Construction public: - AboutDlg(CWnd* pParent = NULL); // standard constructor + AboutDlg(CWnd* pParent = NULL); // standard constructor // Dialog Data - //{{AFX_DATA(AboutDlg) - enum { IDD = IDD_ABOUTBOX }; - // NOTE: the ClassWizard will add data members here - //}}AFX_DATA + //{{AFX_DATA(AboutDlg) + enum { IDD = IDD_ABOUTBOX }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA // Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(AboutDlg) - //}}AFX_VIRTUAL + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(AboutDlg) + //}}AFX_VIRTUAL // Implementation protected: - // Generated message map functions - //{{AFX_MSG(AboutDlg) - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() + // Generated message map functions + //{{AFX_MSG(AboutDlg) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} diff --git a/mdc/ChooseFilesDlg.cpp b/mdc/ChooseFilesDlg.cpp index ed00c35..f5e3ee3 100644 --- a/mdc/ChooseFilesDlg.cpp +++ b/mdc/ChooseFilesDlg.cpp @@ -19,11 +19,11 @@ void ChooseFilesDlg::ShiftControls(int deltaX, int deltaY) { - /* - * These only need to be here so that the initial move puts them - * where they belong. Once the dialog has been created, the - * CFileDialog will move things where they need to go. - */ - MoveControl(this, IDC_CHOOSEFILES_STATIC1, 0, deltaY, false); - SelectFilesDialog::ShiftControls(deltaX, deltaY); + /* + * These only need to be here so that the initial move puts them + * where they belong. Once the dialog has been created, the + * CFileDialog will move things where they need to go. + */ + MoveControl(this, IDC_CHOOSEFILES_STATIC1, 0, deltaY, false); + SelectFilesDialog::ShiftControls(deltaX, deltaY); } diff --git a/mdc/ChooseFilesDlg.h b/mdc/ChooseFilesDlg.h index eaa442e..94358ab 100644 --- a/mdc/ChooseFilesDlg.h +++ b/mdc/ChooseFilesDlg.h @@ -14,26 +14,26 @@ class ChooseFilesDlg : public SelectFilesDialog { public: - ChooseFilesDlg(CWnd* pParentWnd = NULL) : - SelectFilesDialog("IDD_CHOOSE_FILES", pParentWnd) - { - SetWindowTitle(_T("Choose Files...")); + ChooseFilesDlg(CWnd* pParentWnd = NULL) : + SelectFilesDialog("IDD_CHOOSE_FILES", pParentWnd) + { + SetWindowTitle(_T("Choose Files...")); - fAcceptButtonID = IDC_SELECT_ACCEPT; - } - virtual ~ChooseFilesDlg(void) {} + fAcceptButtonID = IDC_SELECT_ACCEPT; + } + virtual ~ChooseFilesDlg(void) {} private: - //virtual bool MyDataExchange(bool saveAndValidate); - virtual void ShiftControls(int deltaX, int deltaY); - //virtual UINT MyOnCommand(WPARAM wParam, LPARAM lParam); + //virtual bool MyDataExchange(bool saveAndValidate); + virtual void ShiftControls(int deltaX, int deltaY); + //virtual UINT MyOnCommand(WPARAM wParam, LPARAM lParam); - //void OnIDHelp(void); + //void OnIDHelp(void); - //int GetButtonCheck(int id); - //void SetButtonCheck(int id, int checkVal); + //int GetButtonCheck(int id); + //void SetButtonCheck(int id, int checkVal); - //DECLARE_MESSAGE_MAP() + //DECLARE_MESSAGE_MAP() }; #endif /*__CHOOSEFILESDIALOG__*/ \ No newline at end of file diff --git a/mdc/Main.cpp b/mdc/Main.cpp index 899a9a3..2ee1453 100644 --- a/mdc/Main.cpp +++ b/mdc/Main.cpp @@ -20,10 +20,10 @@ const char* kWebSiteURL = "http://www.faddensoft.com/"; BEGIN_MESSAGE_MAP(MainWindow, CFrameWnd) - ON_COMMAND(IDM_FILE_SCAN, OnFileScan) - ON_COMMAND(IDM_FILE_EXIT, OnFileExit) - ON_COMMAND(IDM_HELP_WEBSITE, OnHelpWebSite) - ON_COMMAND(IDM_HELP_ABOUT, OnHelpAbout) + ON_COMMAND(IDM_FILE_SCAN, OnFileScan) + ON_COMMAND(IDM_FILE_EXIT, OnFileExit) + ON_COMMAND(IDM_HELP_WEBSITE, OnHelpWebSite) + ON_COMMAND(IDM_HELP_ABOUT, OnHelpAbout) END_MESSAGE_MAP() @@ -33,32 +33,32 @@ END_MESSAGE_MAP() */ MainWindow::MainWindow() { - static const char* kAppName = "MDC"; + static const char* kAppName = "MDC"; - CString wndClass = AfxRegisterWndClass( - CS_DBLCLKS /*| CS_HREDRAW | CS_VREDRAW*/, - gMyApp.LoadStandardCursor(IDC_ARROW), - (HBRUSH) (COLOR_WINDOW + 1), - gMyApp.LoadIcon(IDI_MDC) ); + CString wndClass = AfxRegisterWndClass( + CS_DBLCLKS /*| CS_HREDRAW | CS_VREDRAW*/, + gMyApp.LoadStandardCursor(IDC_ARROW), + (HBRUSH) (COLOR_WINDOW + 1), + gMyApp.LoadIcon(IDI_MDC) ); - Create(wndClass, kAppName, WS_OVERLAPPEDWINDOW /*| WS_CLIPCHILDREN*/, - rectDefault, NULL, MAKEINTRESOURCE(IDC_MDC)); + Create(wndClass, kAppName, WS_OVERLAPPEDWINDOW /*| WS_CLIPCHILDREN*/, + rectDefault, NULL, MAKEINTRESOURCE(IDC_MDC)); - LoadAccelTable(MAKEINTRESOURCE(IDC_MDC)); + LoadAccelTable(MAKEINTRESOURCE(IDC_MDC)); - // initialize some OLE garbage - //AfxOleInit(); + // initialize some OLE garbage + //AfxOleInit(); - // required by MFC if Rich Edit controls are used - //AfxInitRichEdit(); + // required by MFC if Rich Edit controls are used + //AfxInitRichEdit(); - DiskImgLib::Global::SetDebugMsgHandler(DebugMsgHandler); - DiskImgLib::Global::AppInit(); + DiskImgLib::Global::SetDebugMsgHandler(DebugMsgHandler); + DiskImgLib::Global::AppInit(); - NuSetGlobalErrorMessageHandler(NufxErrorMsgHandler); + NuSetGlobalErrorMessageHandler(NufxErrorMsgHandler); - //fTitleAnimation = 0; - fCancelFlag = false; + //fTitleAnimation = 0; + fCancelFlag = false; } /* @@ -68,11 +68,11 @@ MainWindow::MainWindow() */ MainWindow::~MainWindow() { -// int cc; -// cc = ::WinHelp(m_hWnd, ::AfxGetApp()->m_pszHelpFilePath, HELP_QUIT, 0); -// WMSG1("Turning off WinHelp returned %d\n", cc); +// int cc; +// cc = ::WinHelp(m_hWnd, ::AfxGetApp()->m_pszHelpFilePath, HELP_QUIT, 0); +// WMSG1("Turning off WinHelp returned %d\n", cc); - DiskImgLib::Global::AppCleanup(); + DiskImgLib::Global::AppCleanup(); } /* @@ -81,7 +81,7 @@ MainWindow::~MainWindow() void MainWindow::OnFileExit(void) { - SendMessage(WM_CLOSE, 0, 0); + SendMessage(WM_CLOSE, 0, 0); } /* @@ -90,15 +90,15 @@ MainWindow::OnFileExit(void) void MainWindow::OnHelpWebSite(void) { - int err; + int err; - err = (int) ::ShellExecute(m_hWnd, _T("open"), kWebSiteURL, NULL, NULL, - SW_SHOWNORMAL); - if (err <= 32) { - CString msg; - msg.Format("Unable to launch web browser (err=%d).", err); - ShowFailureMsg(this, msg, IDS_FAILED); - } + err = (int) ::ShellExecute(m_hWnd, _T("open"), kWebSiteURL, NULL, NULL, + SW_SHOWNORMAL); + if (err <= 32) { + CString msg; + msg.Format("Unable to launch web browser (err=%d).", err); + ShowFailureMsg(this, msg, IDS_FAILED); + } } /* @@ -107,12 +107,12 @@ MainWindow::OnHelpWebSite(void) void MainWindow::OnHelpAbout(void) { - int result; + int result; - AboutDlg dlg(this); + AboutDlg dlg(this); - result = dlg.DoModal(); - WMSG1("HelpAbout returned %d\n", result); + result = dlg.DoModal(); + WMSG1("HelpAbout returned %d\n", result); } @@ -122,13 +122,13 @@ MainWindow::OnHelpAbout(void) void MainWindow::OnFileScan(void) { - if (0) { - CString msg; - msg.LoadString(IDS_MUST_REGISTER); - ShowFailureMsg(this, msg, IDS_APP_TITLE); - } else { - ScanFiles(); - } + if (0) { + CString msg; + msg.LoadString(IDS_MUST_REGISTER); + ShowFailureMsg(this, msg, IDS_APP_TITLE); + } else { + ScanFiles(); + } } /* @@ -145,25 +145,25 @@ MainWindow::OnFileScan(void) BOOL MainWindow::PeekAndPump(void) { - MSG msg; + MSG msg; - while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { - if (!AfxGetApp()->PumpMessage()) { - ::PostQuitMessage(0); - return FALSE; - } - } + while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { + if (!AfxGetApp()->PumpMessage()) { + ::PostQuitMessage(0); + return FALSE; + } + } - LONG lIdle = 0; - while (AfxGetApp()->OnIdle(lIdle++)) - ; - return TRUE; + LONG lIdle = 0; + while (AfxGetApp()->OnIdle(lIdle++)) + ; + return TRUE; } /* * ========================================================================== - * Disk image processing + * Disk image processing * ========================================================================== */ @@ -173,16 +173,16 @@ MainWindow::PeekAndPump(void) /*static*/ void MainWindow::DebugMsgHandler(const char* file, int line, const char* msg) { - ASSERT(file != nil); - ASSERT(msg != nil); + ASSERT(file != nil); + ASSERT(msg != nil); #if defined(_DEBUG_LOG) - //fprintf(gLog, "%s(%d) : %s", file, line, msg); - fprintf(gLog, "%05u %s", gPid, msg); + //fprintf(gLog, "%s(%d) : %s", file, line, msg); + fprintf(gLog, "%05u %s", gPid, msg); #elif defined(_DEBUG) - _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s", msg); + _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s", msg); #else - /* do nothing */ + /* do nothing */ #endif } /* @@ -191,34 +191,34 @@ MainWindow::DebugMsgHandler(const char* file, int line, const char* msg) /*static*/ NuResult MainWindow::NufxErrorMsgHandler(NuArchive* /*pArchive*/, void* vErrorMessage) { - const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage; + const NuErrorMessage* pErrorMessage = (const NuErrorMessage*) vErrorMessage; #if defined(_DEBUG_LOG) if (pErrorMessage->isDebug) { fprintf(gLog, "%05u [D] %s\n", gPid, pErrorMessage->message); } else { - fprintf(gLog, "%05u %s\n", gPid, pErrorMessage->message); + fprintf(gLog, "%05u %s\n", gPid, pErrorMessage->message); } #elif defined(_DEBUG) if (pErrorMessage->isDebug) { - _CrtDbgReport(_CRT_WARN, pErrorMessage->file, pErrorMessage->line, - NULL, " [D] %s\n", pErrorMessage->message); + _CrtDbgReport(_CRT_WARN, pErrorMessage->file, pErrorMessage->line, + NULL, " [D] %s\n", pErrorMessage->message); } else { - _CrtDbgReport(_CRT_WARN, pErrorMessage->file, pErrorMessage->line, - NULL, " %s\n", pErrorMessage->message); + _CrtDbgReport(_CRT_WARN, pErrorMessage->file, pErrorMessage->line, + NULL, " %s\n", pErrorMessage->message); } #else - /* do nothing */ + /* do nothing */ #endif - return kNuOK; + return kNuOK; } const int kLocalFssep = '\\'; typedef struct ScanOpts { - FILE* outfp; - ProgressDlg* pProgress; + FILE* outfp; + ProgressDlg* pProgress; } ScanOpts; /* @@ -227,161 +227,161 @@ typedef struct ScanOpts { void MainWindow::ScanFiles(void) { - ChooseFilesDlg chooseFiles; - ScanOpts scanOpts; - char curDir[MAX_PATH] = ""; - CString errMsg; - CString outPath; - bool doResetDir = false; + ChooseFilesDlg chooseFiles; + ScanOpts scanOpts; + char curDir[MAX_PATH] = ""; + CString errMsg; + CString outPath; + bool doResetDir = false; - memset(&scanOpts, 0, sizeof(scanOpts)); + memset(&scanOpts, 0, sizeof(scanOpts)); - /* choose input files */ - chooseFiles.DoModal(); - if (chooseFiles.GetExitStatus() != IDOK) - return; + /* choose input files */ + chooseFiles.DoModal(); + if (chooseFiles.GetExitStatus() != IDOK) + return; - const char* buf = chooseFiles.GetFileNames(); - WMSG2("Selected path = '%s' (offset=%d)\n", buf, - chooseFiles.GetFileNameOffset()); + const char* buf = chooseFiles.GetFileNames(); + WMSG2("Selected path = '%s' (offset=%d)\n", buf, + chooseFiles.GetFileNameOffset()); - /* choose output file */ - CFileDialog dlg(FALSE, _T("txt"), NULL, - OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN, - "Text Files (*.txt)|*.txt|All Files (*.*)|*.*||", this); + /* choose output file */ + CFileDialog dlg(FALSE, _T("txt"), NULL, + OFN_OVERWRITEPROMPT|OFN_NOREADONLYRETURN, + "Text Files (*.txt)|*.txt|All Files (*.*)|*.*||", this); - dlg.m_ofn.lpstrTitle = "Save Output As..."; - strcpy(dlg.m_ofn.lpstrFile, "mdc-out.txt"); + dlg.m_ofn.lpstrTitle = "Save Output As..."; + strcpy(dlg.m_ofn.lpstrFile, "mdc-out.txt"); - if (dlg.DoModal() != IDOK) { - goto bail; - } + if (dlg.DoModal() != IDOK) { + goto bail; + } - outPath = dlg.GetPathName(); - WMSG1("NEW FILE '%s'\n", (LPCTSTR) outPath); + outPath = dlg.GetPathName(); + WMSG1("NEW FILE '%s'\n", (LPCTSTR) outPath); - scanOpts.outfp = fopen(outPath, "w"); - if (scanOpts.outfp == nil) { - ShowFailureMsg(this, "Unable to open output file", IDS_FAILED); - goto bail; - } + scanOpts.outfp = fopen(outPath, "w"); + if (scanOpts.outfp == nil) { + ShowFailureMsg(this, "Unable to open output file", IDS_FAILED); + goto bail; + } - long major, minor, bug; - DiskImgLib::Global::GetVersion(&major, &minor, &bug); - fprintf(scanOpts.outfp, "MDC for Windows v%d.%d.%d (DiskImg library v%ld.%ld.%ld)\n", - kAppMajorVersion, kAppMinorVersion, kAppBugVersion, - major, minor, bug); - fprintf(scanOpts.outfp, - "Copyright (C) 2006 by faddenSoft, LLC. All rights reserved.\n"); - fprintf(scanOpts.outfp, - "MDC is part of CiderPress, available from http://www.faddensoft.com/.\n"); - NuGetVersion(&major, &minor, &bug, NULL, NULL); - fprintf(scanOpts.outfp, - "Linked against NufxLib v%ld.%ld.%ld and zlib v%s\n", - major, minor, bug, zlibVersion()); - fprintf(scanOpts.outfp, "\n"); + long major, minor, bug; + DiskImgLib::Global::GetVersion(&major, &minor, &bug); + fprintf(scanOpts.outfp, "MDC for Windows v%d.%d.%d (DiskImg library v%ld.%ld.%ld)\n", + kAppMajorVersion, kAppMinorVersion, kAppBugVersion, + major, minor, bug); + fprintf(scanOpts.outfp, + "Copyright (C) 2006 by faddenSoft, LLC. All rights reserved.\n"); + fprintf(scanOpts.outfp, + "MDC is part of CiderPress, available from http://www.faddensoft.com/.\n"); + NuGetVersion(&major, &minor, &bug, NULL, NULL); + fprintf(scanOpts.outfp, + "Linked against NufxLib v%ld.%ld.%ld and zlib v%s\n", + major, minor, bug, zlibVersion()); + fprintf(scanOpts.outfp, "\n"); - /* change to base directory */ - if (GetCurrentDirectory(sizeof(curDir), curDir) == 0) { - errMsg = "Unable to get current directory."; - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } - if (SetCurrentDirectory(buf) == false) { - errMsg.Format("Unable to set current directory to '%s'.", buf); - ShowFailureMsg(this, errMsg, IDS_FAILED); - goto bail; - } - doResetDir = true; + /* change to base directory */ + if (GetCurrentDirectory(sizeof(curDir), curDir) == 0) { + errMsg = "Unable to get current directory."; + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } + if (SetCurrentDirectory(buf) == false) { + errMsg.Format("Unable to set current directory to '%s'.", buf); + ShowFailureMsg(this, errMsg, IDS_FAILED); + goto bail; + } + doResetDir = true; - time_t now; - now = time(nil); - fprintf(scanOpts.outfp, - "Run started at %.24s in '%s'\n\n", ctime(&now), buf); + time_t now; + now = time(nil); + fprintf(scanOpts.outfp, + "Run started at %.24s in '%s'\n\n", ctime(&now), buf); - /* obstruct input to the main window */ - EnableWindow(FALSE); + /* obstruct input to the main window */ + EnableWindow(FALSE); - /* create a modeless dialog with a cancel button */ - scanOpts.pProgress = new ProgressDlg; - if (scanOpts.pProgress == nil) - goto bail; - scanOpts.pProgress->fpCancelFlag = &fCancelFlag; - fCancelFlag = false; - if (scanOpts.pProgress->Create(this) == FALSE) { - WMSG0("WARNING: ProgressDlg init failed\n"); - ASSERT(false); - } else { - scanOpts.pProgress->CenterWindow(this); - } + /* create a modeless dialog with a cancel button */ + scanOpts.pProgress = new ProgressDlg; + if (scanOpts.pProgress == nil) + goto bail; + scanOpts.pProgress->fpCancelFlag = &fCancelFlag; + fCancelFlag = false; + if (scanOpts.pProgress->Create(this) == FALSE) { + WMSG0("WARNING: ProgressDlg init failed\n"); + ASSERT(false); + } else { + scanOpts.pProgress->CenterWindow(this); + } - time_t start, end; - start = time(nil); + time_t start, end; + start = time(nil); - /* start cranking */ - buf += chooseFiles.GetFileNameOffset(); - while (*buf != '\0') { - if (Process(buf, &scanOpts, &errMsg) != 0) { - WMSG2("Skipping '%s': %s.\n", buf, (LPCTSTR) errMsg); - } + /* start cranking */ + buf += chooseFiles.GetFileNameOffset(); + while (*buf != '\0') { + if (Process(buf, &scanOpts, &errMsg) != 0) { + WMSG2("Skipping '%s': %s.\n", buf, (LPCTSTR) errMsg); + } - if (fCancelFlag) { - WMSG0("CANCELLED by user\n"); - MessageBox("Cancelled!", "MDC", MB_OK); - goto bail; - } + if (fCancelFlag) { + WMSG0("CANCELLED by user\n"); + MessageBox("Cancelled!", "MDC", MB_OK); + goto bail; + } - buf += strlen(buf)+1; - } - end = time(nil); - fprintf(scanOpts.outfp, "\nScan completed in %ld seconds.\n", - end - start); + buf += strlen(buf)+1; + } + end = time(nil); + fprintf(scanOpts.outfp, "\nScan completed in %ld seconds.\n", + end - start); - { - SetWindowText(_T("MDC Done!")); + { + SetWindowText(_T("MDC Done!")); - CString doneMsg; - CString appName; + CString doneMsg; + CString appName; - appName.LoadString(IDS_APP_TITLE); + appName.LoadString(IDS_APP_TITLE); #ifdef _DEBUG_LOG - doneMsg.Format("Processing completed.\r\n\r\n" - "Output is in '%s', log messages in '%s'.", - outPath, kDebugLog); + doneMsg.Format("Processing completed.\r\n\r\n" + "Output is in '%s', log messages in '%s'.", + outPath, kDebugLog); #else - doneMsg.Format("Processing completed."); + doneMsg.Format("Processing completed."); #endif - scanOpts.pProgress->MessageBox(doneMsg, appName, MB_OK|MB_ICONINFORMATION); - } + scanOpts.pProgress->MessageBox(doneMsg, appName, MB_OK|MB_ICONINFORMATION); + } bail: - if (scanOpts.outfp != nil) - fclose(scanOpts.outfp); + if (scanOpts.outfp != nil) + fclose(scanOpts.outfp); - if (doResetDir && SetCurrentDirectory(curDir) == false) { - errMsg.Format("Unable to reset current directory to '%s'.\n", curDir); - ShowFailureMsg(this, errMsg, IDS_FAILED); - // bummer - } + if (doResetDir && SetCurrentDirectory(curDir) == false) { + errMsg.Format("Unable to reset current directory to '%s'.\n", curDir); + ShowFailureMsg(this, errMsg, IDS_FAILED); + // bummer + } - // restore the main window - EnableWindow(TRUE); + // restore the main window + EnableWindow(TRUE); - if (scanOpts.pProgress != nil) - scanOpts.pProgress->DestroyWindow(); + if (scanOpts.pProgress != nil) + scanOpts.pProgress->DestroyWindow(); - SetWindowText(_T("MDC")); + SetWindowText(_T("MDC")); } /* * Directory structure and functions, based on zDIR in Info-Zip sources. */ typedef struct Win32dirent { - char d_attr; - char d_name[MAX_PATH]; - int d_first; - HANDLE d_hFindFile; + char d_attr; + char d_name[MAX_PATH]; + int d_first; + HANDLE d_hFindFile; } Win32dirent; static const char* kWildMatchAll = "*.*"; @@ -394,45 +394,45 @@ static const char* kWildMatchAll = "*.*"; Win32dirent* MainWindow::OpenDir(const char* name) { - Win32dirent* dir = nil; - char* tmpStr = nil; - char* cp; - WIN32_FIND_DATA fnd; + Win32dirent* dir = nil; + char* tmpStr = nil; + char* cp; + WIN32_FIND_DATA fnd; - dir = (Win32dirent*) malloc(sizeof(*dir)); - tmpStr = (char*) malloc(strlen(name) + (2 + sizeof(kWildMatchAll))); - if (dir == nil || tmpStr == nil) - goto failed; + dir = (Win32dirent*) malloc(sizeof(*dir)); + tmpStr = (char*) malloc(strlen(name) + (2 + sizeof(kWildMatchAll))); + if (dir == nil || tmpStr == nil) + goto failed; - strcpy(tmpStr, name); - cp = tmpStr + strlen(tmpStr); + strcpy(tmpStr, name); + cp = tmpStr + strlen(tmpStr); - /* don't end in a colon (e.g. "C:") */ - if ((cp - tmpStr) > 0 && strrchr(tmpStr, ':') == (cp - 1)) - *cp++ = '.'; - /* must end in a slash */ - if ((cp - tmpStr) > 0 && - strrchr(tmpStr, kLocalFssep) != (cp - 1)) - *cp++ = kLocalFssep; + /* don't end in a colon (e.g. "C:") */ + if ((cp - tmpStr) > 0 && strrchr(tmpStr, ':') == (cp - 1)) + *cp++ = '.'; + /* must end in a slash */ + if ((cp - tmpStr) > 0 && + strrchr(tmpStr, kLocalFssep) != (cp - 1)) + *cp++ = kLocalFssep; - strcpy(cp, kWildMatchAll); + strcpy(cp, kWildMatchAll); - dir->d_hFindFile = FindFirstFile(tmpStr, &fnd); - if (dir->d_hFindFile == INVALID_HANDLE_VALUE) - goto failed; + dir->d_hFindFile = FindFirstFile(tmpStr, &fnd); + if (dir->d_hFindFile == INVALID_HANDLE_VALUE) + goto failed; - strcpy(dir->d_name, fnd.cFileName); - dir->d_attr = (unsigned char) fnd.dwFileAttributes; - dir->d_first = 1; + strcpy(dir->d_name, fnd.cFileName); + dir->d_attr = (unsigned char) fnd.dwFileAttributes; + dir->d_first = 1; bail: - free(tmpStr); - return dir; + free(tmpStr); + return dir; failed: - free(dir); - dir = nil; - goto bail; + free(dir); + dir = nil; + goto bail; } /* @@ -443,18 +443,18 @@ failed: Win32dirent* MainWindow::ReadDir(Win32dirent* dir) { - if (dir->d_first) - dir->d_first = 0; - else { - WIN32_FIND_DATA fnd; + if (dir->d_first) + dir->d_first = 0; + else { + WIN32_FIND_DATA fnd; - if (!FindNextFile(dir->d_hFindFile, &fnd)) - return nil; - strcpy(dir->d_name, fnd.cFileName); - dir->d_attr = (unsigned char) fnd.dwFileAttributes; - } + if (!FindNextFile(dir->d_hFindFile, &fnd)) + return nil; + strcpy(dir->d_name, fnd.cFileName); + dir->d_attr = (unsigned char) fnd.dwFileAttributes; + } - return dir; + return dir; } /* @@ -463,15 +463,15 @@ MainWindow::ReadDir(Win32dirent* dir) void MainWindow::CloseDir(Win32dirent* dir) { - if (dir == nil) - return; + if (dir == nil) + return; - FindClose(dir->d_hFindFile); - free(dir); + FindClose(dir->d_hFindFile); + free(dir); } /* might as well blend in with the UNIX version */ -#define DIR_NAME_LEN(dirent) ((int)strlen((dirent)->d_name)) +#define DIR_NAME_LEN(dirent) ((int)strlen((dirent)->d_name)) /* @@ -482,48 +482,48 @@ MainWindow::CloseDir(Win32dirent* dir) */ int MainWindow::Process(const char* pathname, ScanOpts* pScanOpts, - CString* pErrMsg) + CString* pErrMsg) { - bool exists, isDir, isReadable; - struct stat sb; - int result = -1; + bool exists, isDir, isReadable; + struct stat sb; + int result = -1; - if (fCancelFlag) - return -1; + if (fCancelFlag) + return -1; - ASSERT(pathname != nil); - ASSERT(pErrMsg != nil); + ASSERT(pathname != nil); + ASSERT(pErrMsg != nil); - PathName checkPath(pathname); - int ierr = checkPath.CheckFileStatus(&sb, &exists, &isReadable, &isDir); - if (ierr != 0) { - pErrMsg->Format("Unexpected error while examining '%s': %s", pathname, - strerror(ierr)); - goto bail; - } + PathName checkPath(pathname); + int ierr = checkPath.CheckFileStatus(&sb, &exists, &isReadable, &isDir); + if (ierr != 0) { + pErrMsg->Format("Unexpected error while examining '%s': %s", pathname, + strerror(ierr)); + goto bail; + } - if (!exists) { - pErrMsg->Format("Couldn't find '%s'", pathname); - goto bail; - } - if (!isReadable) { - pErrMsg->Format("File '%s' isn't readable", pathname); - goto bail; - } - if (isDir) { - result = ProcessDirectory(pathname, pScanOpts, pErrMsg); - goto bail; - } + if (!exists) { + pErrMsg->Format("Couldn't find '%s'", pathname); + goto bail; + } + if (!isReadable) { + pErrMsg->Format("File '%s' isn't readable", pathname); + goto bail; + } + if (isDir) { + result = ProcessDirectory(pathname, pScanOpts, pErrMsg); + goto bail; + } - (void) ScanDiskImage(pathname, pScanOpts); + (void) ScanDiskImage(pathname, pScanOpts); - result = 0; + result = 0; bail: - if (result != 0 && pErrMsg->IsEmpty()) { - pErrMsg->Format("Unable to add file '%s'", pathname); - } - return result; + if (result != 0 && pErrMsg->IsEmpty()) { + pErrMsg->Format("Unable to add file '%s'", pathname); + } + return result; } /* @@ -533,58 +533,58 @@ bail: */ int MainWindow::ProcessDirectory(const char* dirName, ScanOpts* pScanOpts, - CString* pErrMsg) + CString* pErrMsg) { - Win32dirent* dirp = nil; - Win32dirent* entry; - char nbuf[MAX_PATH]; /* malloc might be better; this soaks stack */ - char fssep; - int len; - int result = -1; + Win32dirent* dirp = nil; + Win32dirent* entry; + char nbuf[MAX_PATH]; /* malloc might be better; this soaks stack */ + char fssep; + int len; + int result = -1; - ASSERT(dirName != nil); - ASSERT(pErrMsg != nil); + ASSERT(dirName != nil); + ASSERT(pErrMsg != nil); - WMSG1("+++ DESCEND: '%s'\n", dirName); + WMSG1("+++ DESCEND: '%s'\n", dirName); - dirp = OpenDir(dirName); - if (dirp == nil) { - pErrMsg->Format("Failed on '%s': %s", dirName, strerror(errno)); - goto bail; - } + dirp = OpenDir(dirName); + if (dirp == nil) { + pErrMsg->Format("Failed on '%s': %s", dirName, strerror(errno)); + goto bail; + } - fssep = kLocalFssep; + fssep = kLocalFssep; - /* could use readdir_r, but we don't care about reentrancy here */ - while ((entry = ReadDir(dirp)) != nil) { - /* skip the dotsies */ - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; + /* could use readdir_r, but we don't care about reentrancy here */ + while ((entry = ReadDir(dirp)) != nil) { + /* skip the dotsies */ + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; - len = strlen(dirName); - if (len + DIR_NAME_LEN(entry) +2 > MAX_PATH) { - WMSG4("ERROR: Filename exceeds %d bytes: %s%c%s", - MAX_PATH, dirName, fssep, entry->d_name); - goto bail; - } + len = strlen(dirName); + if (len + DIR_NAME_LEN(entry) +2 > MAX_PATH) { + WMSG4("ERROR: Filename exceeds %d bytes: %s%c%s", + MAX_PATH, dirName, fssep, entry->d_name); + goto bail; + } - /* form the new name, inserting an fssep if needed */ - strcpy(nbuf, dirName); - if (dirName[len-1] != fssep) - nbuf[len++] = fssep; - strcpy(nbuf+len, entry->d_name); + /* form the new name, inserting an fssep if needed */ + strcpy(nbuf, dirName); + if (dirName[len-1] != fssep) + nbuf[len++] = fssep; + strcpy(nbuf+len, entry->d_name); - result = Process(nbuf, pScanOpts, pErrMsg); - if (result != 0) - goto bail; - } + result = Process(nbuf, pScanOpts, pErrMsg); + if (result != 0) + goto bail; + } - result = 0; + result = 0; bail: - if (dirp != nil) - (void)CloseDir(dirp); - return result; + if (dirp != nil) + (void)CloseDir(dirp); + return result; } @@ -596,111 +596,111 @@ bail: int MainWindow::ScanDiskImage(const char* pathName, ScanOpts* pScanOpts) { - ASSERT(pathName != nil); - ASSERT(pScanOpts != nil); - ASSERT(pScanOpts->outfp != nil); + ASSERT(pathName != nil); + ASSERT(pScanOpts != nil); + ASSERT(pScanOpts->outfp != nil); - DIError dierr; - CString errMsg; - DiskImg diskImg; - DiskFS* pDiskFS = nil; - PathName path(pathName); - CString ext = path.GetExtension(); + DIError dierr; + CString errMsg; + DiskImg diskImg; + DiskFS* pDiskFS = nil; + PathName path(pathName); + CString ext = path.GetExtension(); - /* first, some housekeeping */ - PeekAndPump(); - pScanOpts->pProgress->SetCurrentFile(pathName); - if (fCancelFlag) - return -1; + /* first, some housekeeping */ + PeekAndPump(); + pScanOpts->pProgress->SetCurrentFile(pathName); + if (fCancelFlag) + return -1; - CString title; - title = _T("MDC "); - title += FilenameOnly(pathName, '\\'); - SetWindowText(title); + CString title; + title = _T("MDC "); + title += FilenameOnly(pathName, '\\'); + SetWindowText(title); - fprintf(pScanOpts->outfp, "File: %s\n", pathName); - fflush(pScanOpts->outfp); // in case we crash + fprintf(pScanOpts->outfp, "File: %s\n", pathName); + fflush(pScanOpts->outfp); // in case we crash - if (!ext.IsEmpty()) { - /* delete the leading '.' */ - ext.Delete(0, 1); - } + if (!ext.IsEmpty()) { + /* delete the leading '.' */ + ext.Delete(0, 1); + } - dierr = diskImg.OpenImage(pathName, '\\', true); - if (dierr != kDIErrNone) { - errMsg.Format("Unable to open '%s': %s", pathName, - DiskImgLib::DIStrError(dierr)); - goto bail; - } + dierr = diskImg.OpenImage(pathName, '\\', true); + if (dierr != kDIErrNone) { + errMsg.Format("Unable to open '%s': %s", pathName, + DiskImgLib::DIStrError(dierr)); + goto bail; + } - dierr = diskImg.AnalyzeImage(); - if (dierr != kDIErrNone) { - errMsg.Format("Analysis of '%s' failed: %s", pathName, - DiskImgLib::DIStrError(dierr)); - goto bail; - } + dierr = diskImg.AnalyzeImage(); + if (dierr != kDIErrNone) { + errMsg.Format("Analysis of '%s' failed: %s", pathName, + DiskImgLib::DIStrError(dierr)); + goto bail; + } - if (diskImg.GetFSFormat() == DiskImg::kFormatUnknown || - diskImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown) - { - errMsg.Format("Unable to identify filesystem on '%s'", pathName); - goto bail; - } + if (diskImg.GetFSFormat() == DiskImg::kFormatUnknown || + diskImg.GetSectorOrder() == DiskImg::kSectorOrderUnknown) + { + errMsg.Format("Unable to identify filesystem on '%s'", pathName); + goto bail; + } - /* create an appropriate DiskFS object */ - pDiskFS = diskImg.OpenAppropriateDiskFS(); - if (pDiskFS == nil) { - /* unknown FS should've been caught above! */ - ASSERT(false); - errMsg.Format("Format of '%s' not recognized.", pathName); - goto bail; - } + /* create an appropriate DiskFS object */ + pDiskFS = diskImg.OpenAppropriateDiskFS(); + if (pDiskFS == nil) { + /* unknown FS should've been caught above! */ + ASSERT(false); + errMsg.Format("Format of '%s' not recognized.", pathName); + goto bail; + } - pDiskFS->SetScanForSubVolumes(DiskFS::kScanSubEnabled); + pDiskFS->SetScanForSubVolumes(DiskFS::kScanSubEnabled); - /* object created; prep it */ - dierr = pDiskFS->Initialize(&diskImg, DiskFS::kInitFull); - if (dierr != kDIErrNone) { - errMsg.Format("Error reading list of files from disk: %s", - DiskImgLib::DIStrError(dierr)); - goto bail; - } + /* object created; prep it */ + dierr = pDiskFS->Initialize(&diskImg, DiskFS::kInitFull); + if (dierr != kDIErrNone) { + errMsg.Format("Error reading list of files from disk: %s", + DiskImgLib::DIStrError(dierr)); + goto bail; + } - int kbytes; - if (pDiskFS->GetDiskImg()->GetHasBlocks()) - kbytes = pDiskFS->GetDiskImg()->GetNumBlocks() / 2; - else if (pDiskFS->GetDiskImg()->GetHasSectors()) - kbytes = (pDiskFS->GetDiskImg()->GetNumTracks() * - pDiskFS->GetDiskImg()->GetNumSectPerTrack()) / 4; - else - kbytes = 0; - fprintf(pScanOpts->outfp, "Disk: %s%s (%dKB)\n", pDiskFS->GetVolumeID(), - pDiskFS->GetFSDamaged() ? " [*]" : "", kbytes); + int kbytes; + if (pDiskFS->GetDiskImg()->GetHasBlocks()) + kbytes = pDiskFS->GetDiskImg()->GetNumBlocks() / 2; + else if (pDiskFS->GetDiskImg()->GetHasSectors()) + kbytes = (pDiskFS->GetDiskImg()->GetNumTracks() * + pDiskFS->GetDiskImg()->GetNumSectPerTrack()) / 4; + else + kbytes = 0; + fprintf(pScanOpts->outfp, "Disk: %s%s (%dKB)\n", pDiskFS->GetVolumeID(), + pDiskFS->GetFSDamaged() ? " [*]" : "", kbytes); fprintf(pScanOpts->outfp, - " Name Type Auxtyp Modified" + " Name Type Auxtyp Modified" " Format Length\n"); fprintf(pScanOpts->outfp, - "------------------------------------------------------" + "------------------------------------------------------" "------------------------\n"); - if (LoadDiskFSContents(pDiskFS, "", pScanOpts) != 0) { - errMsg.Format("Failed while loading contents of '%s'.", pathName); - goto bail; - } + if (LoadDiskFSContents(pDiskFS, "", pScanOpts) != 0) { + errMsg.Format("Failed while loading contents of '%s'.", pathName); + goto bail; + } fprintf(pScanOpts->outfp, - "------------------------------------------------------" + "------------------------------------------------------" "------------------------\n\n"); bail: - delete pDiskFS; + delete pDiskFS; - //PeekAndPump(); + //PeekAndPump(); - if (!errMsg.IsEmpty()) { - fprintf(pScanOpts->outfp, "Failed: %s\n\n", (LPCTSTR) errMsg); - return -1; - } else { - return 0; - } + if (!errMsg.IsEmpty()) { + fprintf(pScanOpts->outfp, "Failed: %s\n\n", (LPCTSTR) errMsg); + return -1; + } else { + return 0; + } } /* @@ -708,32 +708,32 @@ bail: */ void MainWindow::AnalyzeFile(const A2File* pFile, RecordKind* pRecordKind, - LONGLONG* pTotalLen, LONGLONG* pTotalCompLen) + LONGLONG* pTotalLen, LONGLONG* pTotalCompLen) { - if (pFile->IsVolumeDirectory()) { - /* volume dir entry */ - ASSERT(pFile->GetRsrcLength() < 0); - *pRecordKind = kRecordKindVolumeDir; - *pTotalLen = pFile->GetDataLength(); - *pTotalCompLen = pFile->GetDataLength(); - } else if (pFile->IsDirectory()) { - /* directory entry */ - ASSERT(pFile->GetRsrcLength() < 0); - *pRecordKind = kRecordKindDirectory; - *pTotalLen = pFile->GetDataLength(); - *pTotalCompLen = pFile->GetDataLength(); - } else if (pFile->GetRsrcLength() >= 0) { - /* has resource fork */ - *pRecordKind = kRecordKindForkedFile; - *pTotalLen = pFile->GetDataLength() + pFile->GetRsrcLength(); - *pTotalCompLen = - pFile->GetDataSparseLength() + pFile->GetRsrcSparseLength(); - } else { - /* just data fork */ - *pRecordKind = kRecordKindFile; - *pTotalLen = pFile->GetDataLength(); - *pTotalCompLen = pFile->GetDataSparseLength(); - } + if (pFile->IsVolumeDirectory()) { + /* volume dir entry */ + ASSERT(pFile->GetRsrcLength() < 0); + *pRecordKind = kRecordKindVolumeDir; + *pTotalLen = pFile->GetDataLength(); + *pTotalCompLen = pFile->GetDataLength(); + } else if (pFile->IsDirectory()) { + /* directory entry */ + ASSERT(pFile->GetRsrcLength() < 0); + *pRecordKind = kRecordKindDirectory; + *pTotalLen = pFile->GetDataLength(); + *pTotalCompLen = pFile->GetDataLength(); + } else if (pFile->GetRsrcLength() >= 0) { + /* has resource fork */ + *pRecordKind = kRecordKindForkedFile; + *pTotalLen = pFile->GetDataLength() + pFile->GetRsrcLength(); + *pTotalCompLen = + pFile->GetDataSparseLength() + pFile->GetRsrcSparseLength(); + } else { + /* just data fork */ + *pRecordKind = kRecordKindFile; + *pTotalLen = pFile->GetDataLength(); + *pTotalCompLen = pFile->GetDataSparseLength(); + } } /* @@ -753,38 +753,38 @@ MainWindow::IsRecordReadOnly(int access) /* ProDOS file type names; must be entirely in upper case */ static const char gFileTypeNames[256][4] = { - "NON", "BAD", "PCD", "PTX", "TXT", "PDA", "BIN", "FNT", - "FOT", "BA3", "DA3", "WPF", "SOS", "$0D", "$0E", "DIR", - "RPD", "RPI", "AFD", "AFM", "AFR", "SCL", "PFS", "$17", - "$18", "ADB", "AWP", "ASP", "$1C", "$1D", "$1E", "$1F", - "TDM", "$21", "$22", "$23", "$24", "$25", "$26", "$27", - "$28", "$29", "8SC", "8OB", "8IC", "8LD", "P8C", "$2F", - "$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37", - "$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F", - "DIC", "OCR", "FTD", "$43", "$44", "$45", "$46", "$47", - "$48", "$49", "$4A", "$4B", "$4C", "$4D", "$4E", "$4F", - "GWP", "GSS", "GDB", "DRW", "GDP", "HMD", "EDU", "STN", - "HLP", "COM", "CFG", "ANM", "MUM", "ENT", "DVU", "FIN", - "$60", "$61", "$62", "$63", "$64", "$65", "$66", "$67", - "$68", "$69", "$6A", "BIO", "$6C", "TDR", "PRE", "HDV", - "$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77", - "$78", "$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F", - "$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87", - "$88", "$89", "$8A", "$8B", "$8C", "$8D", "$8E", "$8F", - "$90", "$91", "$92", "$93", "$94", "$95", "$96", "$97", - "$98", "$99", "$9A", "$9B", "$9C", "$9D", "$9E", "$9F", - "WP ", "$A1", "$A2", "$A3", "$A4", "$A5", "$A6", "$A7", - "$A8", "$A9", "$AA", "GSB", "TDF", "BDF", "$AE", "$AF", - "SRC", "OBJ", "LIB", "S16", "RTL", "EXE", "PIF", "TIF", - "NDA", "CDA", "TOL", "DVR", "LDF", "FST", "$BE", "DOC", - "PNT", "PIC", "ANI", "PAL", "$C4", "OOG", "SCR", "CDV", - "FON", "FND", "ICN", "$CB", "$CC", "$CD", "$CE", "$CF", - "$D0", "$D1", "$D2", "$D3", "$D4", "MUS", "INS", "MDI", - "SND", "$D9", "$DA", "DBM", "$DC", "DDD", "$DE", "$DF", - "LBR", "$E1", "ATK", "$E3", "$E4", "$E5", "$E6", "$E7", - "$E8", "$E9", "$EA", "$EB", "$EC", "$ED", "R16", "PAS", - "CMD", "$F1", "$F2", "$F3", "$F4", "$F5", "$F6", "$F7", - "$F8", "OS ", "INT", "IVR", "BAS", "VAR", "REL", "SYS" + "NON", "BAD", "PCD", "PTX", "TXT", "PDA", "BIN", "FNT", + "FOT", "BA3", "DA3", "WPF", "SOS", "$0D", "$0E", "DIR", + "RPD", "RPI", "AFD", "AFM", "AFR", "SCL", "PFS", "$17", + "$18", "ADB", "AWP", "ASP", "$1C", "$1D", "$1E", "$1F", + "TDM", "$21", "$22", "$23", "$24", "$25", "$26", "$27", + "$28", "$29", "8SC", "8OB", "8IC", "8LD", "P8C", "$2F", + "$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37", + "$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F", + "DIC", "OCR", "FTD", "$43", "$44", "$45", "$46", "$47", + "$48", "$49", "$4A", "$4B", "$4C", "$4D", "$4E", "$4F", + "GWP", "GSS", "GDB", "DRW", "GDP", "HMD", "EDU", "STN", + "HLP", "COM", "CFG", "ANM", "MUM", "ENT", "DVU", "FIN", + "$60", "$61", "$62", "$63", "$64", "$65", "$66", "$67", + "$68", "$69", "$6A", "BIO", "$6C", "TDR", "PRE", "HDV", + "$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77", + "$78", "$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F", + "$80", "$81", "$82", "$83", "$84", "$85", "$86", "$87", + "$88", "$89", "$8A", "$8B", "$8C", "$8D", "$8E", "$8F", + "$90", "$91", "$92", "$93", "$94", "$95", "$96", "$97", + "$98", "$99", "$9A", "$9B", "$9C", "$9D", "$9E", "$9F", + "WP ", "$A1", "$A2", "$A3", "$A4", "$A5", "$A6", "$A7", + "$A8", "$A9", "$AA", "GSB", "TDF", "BDF", "$AE", "$AF", + "SRC", "OBJ", "LIB", "S16", "RTL", "EXE", "PIF", "TIF", + "NDA", "CDA", "TOL", "DVR", "LDF", "FST", "$BE", "DOC", + "PNT", "PIC", "ANI", "PAL", "$C4", "OOG", "SCR", "CDV", + "FON", "FND", "ICN", "$CB", "$CC", "$CD", "$CE", "$CF", + "$D0", "$D1", "$D2", "$D3", "$D4", "MUS", "INS", "MDI", + "SND", "$D9", "$DA", "DBM", "$DC", "DDD", "$DE", "$DF", + "LBR", "$E1", "ATK", "$E3", "$E4", "$E5", "$E6", "$E7", + "$E8", "$E9", "$EA", "$EB", "$EC", "$ED", "R16", "PAS", + "CMD", "$F1", "$F2", "$F3", "$F4", "$F5", "$F6", "$F7", + "$F8", "OS ", "INT", "IVR", "BAS", "VAR", "REL", "SYS" }; /* @@ -795,10 +795,10 @@ static const char gFileTypeNames[256][4] = { /*static*/ const char* MainWindow::GetFileTypeString(unsigned long fileType) { - if (fileType < NELEM(gFileTypeNames)) - return gFileTypeNames[fileType]; - else - return "???"; + if (fileType < NELEM(gFileTypeNames)) + return gFileTypeNames[fileType]; + else + return "???"; } /* @@ -809,7 +809,7 @@ static void MacSanitize(char* str) { while (*str != '\0') { - *str = DiskImg::MacToASCII(*str); + *str = DiskImg::MacToASCII(*str); str++; } } @@ -821,80 +821,80 @@ MacSanitize(char* str) */ int MainWindow::LoadDiskFSContents(DiskFS* pDiskFS, const char* volName, - ScanOpts* pScanOpts) + ScanOpts* pScanOpts) { - static const char* kBlankFileName = ""; - DiskFS::SubVolume* pSubVol = nil; - A2File* pFile; + static const char* kBlankFileName = ""; + DiskFS::SubVolume* pSubVol = nil; + A2File* pFile; - ASSERT(pDiskFS != nil); - pFile = pDiskFS->GetNextFile(nil); - for ( ; pFile != nil; pFile = pDiskFS->GetNextFile(pFile)) { - CString subVolName, dispName; - RecordKind recordKind; - LONGLONG totalLen, totalCompLen; - char tmpbuf[16]; + ASSERT(pDiskFS != nil); + pFile = pDiskFS->GetNextFile(nil); + for ( ; pFile != nil; pFile = pDiskFS->GetNextFile(pFile)) { + CString subVolName, dispName; + RecordKind recordKind; + LONGLONG totalLen, totalCompLen; + char tmpbuf[16]; - AnalyzeFile(pFile, &recordKind, &totalLen, &totalCompLen); + AnalyzeFile(pFile, &recordKind, &totalLen, &totalCompLen); - if (recordKind == kRecordKindVolumeDir) { - /* this is a volume directory */ - WMSG1("Not displaying volume dir '%s'\n", pFile->GetPathName()); - continue; - } + if (recordKind == kRecordKindVolumeDir) { + /* this is a volume directory */ + WMSG1("Not displaying volume dir '%s'\n", pFile->GetPathName()); + continue; + } - /* prepend volName for sub-volumes; must be valid Win32 dirname */ - if (volName[0] != '\0') - subVolName.Format("_%s", volName); + /* prepend volName for sub-volumes; must be valid Win32 dirname */ + if (volName[0] != '\0') + subVolName.Format("_%s", volName); - const char* ccp = pFile->GetPathName(); - ASSERT(ccp != nil); - if (strlen(ccp) == 0) - ccp = kBlankFileName; + const char* ccp = pFile->GetPathName(); + ASSERT(ccp != nil); + if (strlen(ccp) == 0) + ccp = kBlankFileName; - CString path(ccp); - if (DiskImg::UsesDOSFileStructure(pFile->GetFSFormat()) && 0) - { - InjectLowercase(&path); - } + CString path(ccp); + if (DiskImg::UsesDOSFileStructure(pFile->GetFSFormat()) && 0) + { + InjectLowercase(&path); + } - if (subVolName.IsEmpty()) - dispName = path; - else { - dispName = subVolName; - dispName += ':'; - dispName += path; - } + if (subVolName.IsEmpty()) + dispName = path; + else { + dispName = subVolName; + dispName += ':'; + dispName += path; + } - /* strip out ctrl chars and high ASCII in HFS names */ - MacSanitize(dispName.GetBuffer(0)); - dispName.ReleaseBuffer(); + /* strip out ctrl chars and high ASCII in HFS names */ + MacSanitize(dispName.GetBuffer(0)); + dispName.ReleaseBuffer(); - ccp = dispName; + ccp = dispName; - int len = strlen(ccp); - if (len <= 32) { - fprintf(pScanOpts->outfp, "%c%-32.32s ", - IsRecordReadOnly(pFile->GetAccess()) ? '*' : ' ', - ccp); - } else { - fprintf(pScanOpts->outfp, "%c..%-30.30s ", - IsRecordReadOnly(pFile->GetAccess()) ? '*' : ' ', - ccp + len - 30); - } - switch (recordKind) { - case kRecordKindUnknown: - fprintf(pScanOpts->outfp, "%s- $%04lX ", - GetFileTypeString(pFile->GetFileType()), - pFile->GetAuxType()); - break; - case kRecordKindDisk: - sprintf(tmpbuf, "%ldk", totalLen / 1024); - fprintf(pScanOpts->outfp, "Disk %-6s ", tmpbuf); - break; - case kRecordKindFile: - case kRecordKindForkedFile: - case kRecordKindDirectory: + int len = strlen(ccp); + if (len <= 32) { + fprintf(pScanOpts->outfp, "%c%-32.32s ", + IsRecordReadOnly(pFile->GetAccess()) ? '*' : ' ', + ccp); + } else { + fprintf(pScanOpts->outfp, "%c..%-30.30s ", + IsRecordReadOnly(pFile->GetAccess()) ? '*' : ' ', + ccp + len - 30); + } + switch (recordKind) { + case kRecordKindUnknown: + fprintf(pScanOpts->outfp, "%s- $%04lX ", + GetFileTypeString(pFile->GetFileType()), + pFile->GetAuxType()); + break; + case kRecordKindDisk: + sprintf(tmpbuf, "%ldk", totalLen / 1024); + fprintf(pScanOpts->outfp, "Disk %-6s ", tmpbuf); + break; + case kRecordKindFile: + case kRecordKindForkedFile: + case kRecordKindDirectory: if (pDiskFS->GetDiskImg()->GetFSFormat() == DiskImg::kFormatMacHFS) { if (recordKind != kRecordKindDirectory && @@ -943,102 +943,102 @@ MainWindow::LoadDiskFSContents(DiskFS* pDiskFS, const char* volName, recordKind == kRecordKindForkedFile ? '+' : ' ', pFile->GetAuxType()); } - break; - case kRecordKindVolumeDir: - /* should've trapped this earlier */ - ASSERT(0); - fprintf(pScanOpts->outfp, "ERROR "); - break; - default: - ASSERT(0); - fprintf(pScanOpts->outfp, "ERROR "); - break; - } + break; + case kRecordKindVolumeDir: + /* should've trapped this earlier */ + ASSERT(0); + fprintf(pScanOpts->outfp, "ERROR "); + break; + default: + ASSERT(0); + fprintf(pScanOpts->outfp, "ERROR "); + break; + } - CString date; - if (pFile->GetModWhen() == 0) - FormatDate(kDateNone, &date); - else - FormatDate(pFile->GetModWhen(), &date); - fprintf(pScanOpts->outfp, "%-15s ", (LPCTSTR) date); + CString date; + if (pFile->GetModWhen() == 0) + FormatDate(kDateNone, &date); + else + FormatDate(pFile->GetModWhen(), &date); + fprintf(pScanOpts->outfp, "%-15s ", (LPCTSTR) date); - const char* fmtStr; - switch (pFile->GetFSFormat()) { - case DiskImg::kFormatDOS33: - case DiskImg::kFormatDOS32: - case DiskImg::kFormatUNIDOS: - case DiskImg::kFormatOzDOS: - fmtStr = "DOS "; - break; - case DiskImg::kFormatProDOS: - fmtStr = "ProDOS"; - break; - case DiskImg::kFormatPascal: - fmtStr = "Pascal"; - break; - case DiskImg::kFormatCPM: - fmtStr = "CP/M "; - break; - case DiskImg::kFormatRDOS33: - case DiskImg::kFormatRDOS32: - case DiskImg::kFormatRDOS3: - fmtStr = "RDOS "; - break; - case DiskImg::kFormatMacHFS: - fmtStr = "HFS "; - break; - case DiskImg::kFormatMSDOS: - fmtStr = "MS-DOS"; - break; - default: - fmtStr = "??? "; - break; - } - if (pFile->GetQuality() == A2File::kQualityDamaged) - fmtStr = "BROKEN"; - else if (pFile->GetQuality() == A2File::kQualitySuspicious) - fmtStr = "BAD? "; + const char* fmtStr; + switch (pFile->GetFSFormat()) { + case DiskImg::kFormatDOS33: + case DiskImg::kFormatDOS32: + case DiskImg::kFormatUNIDOS: + case DiskImg::kFormatOzDOS: + fmtStr = "DOS "; + break; + case DiskImg::kFormatProDOS: + fmtStr = "ProDOS"; + break; + case DiskImg::kFormatPascal: + fmtStr = "Pascal"; + break; + case DiskImg::kFormatCPM: + fmtStr = "CP/M "; + break; + case DiskImg::kFormatRDOS33: + case DiskImg::kFormatRDOS32: + case DiskImg::kFormatRDOS3: + fmtStr = "RDOS "; + break; + case DiskImg::kFormatMacHFS: + fmtStr = "HFS "; + break; + case DiskImg::kFormatMSDOS: + fmtStr = "MS-DOS"; + break; + default: + fmtStr = "??? "; + break; + } + if (pFile->GetQuality() == A2File::kQualityDamaged) + fmtStr = "BROKEN"; + else if (pFile->GetQuality() == A2File::kQualitySuspicious) + fmtStr = "BAD? "; - fprintf(pScanOpts->outfp, "%s ", fmtStr); + fprintf(pScanOpts->outfp, "%s ", fmtStr); #if 0 - /* compute the percent size */ - if ((!totalLen && totalCompLen) || (totalLen && !totalCompLen)) - fprintf(pScanOpts->outfp, "--- "); /* weird */ - else if (totalLen < totalCompLen) - fprintf(pScanOpts->outfp, ">100%% "); /* compression failed? */ - else { - sprintf(tmpbuf, "%02d%%", ComputePercent(totalCompLen, totalLen)); - fprintf(pScanOpts->outfp, "%4s ", tmpbuf); - } + /* compute the percent size */ + if ((!totalLen && totalCompLen) || (totalLen && !totalCompLen)) + fprintf(pScanOpts->outfp, "--- "); /* weird */ + else if (totalLen < totalCompLen) + fprintf(pScanOpts->outfp, ">100%% "); /* compression failed? */ + else { + sprintf(tmpbuf, "%02d%%", ComputePercent(totalCompLen, totalLen)); + fprintf(pScanOpts->outfp, "%4s ", tmpbuf); + } #endif - if (!totalLen && totalCompLen) - fprintf(pScanOpts->outfp, " ????"); /* weird */ - else - fprintf(pScanOpts->outfp, "%8ld", totalLen); + if (!totalLen && totalCompLen) + fprintf(pScanOpts->outfp, " ????"); /* weird */ + else + fprintf(pScanOpts->outfp, "%8ld", totalLen); - fprintf(pScanOpts->outfp, "\n"); - } + fprintf(pScanOpts->outfp, "\n"); + } - /* - * Load all sub-volumes. - */ - pSubVol = pDiskFS->GetNextSubVolume(nil); - while (pSubVol != nil) { - const char* subVolName; - int ret; + /* + * Load all sub-volumes. + */ + pSubVol = pDiskFS->GetNextSubVolume(nil); + while (pSubVol != nil) { + const char* subVolName; + int ret; - subVolName = pSubVol->GetDiskFS()->GetVolumeName(); - if (subVolName == nil) - subVolName = "+++"; // could probably do better than this + subVolName = pSubVol->GetDiskFS()->GetVolumeName(); + if (subVolName == nil) + subVolName = "+++"; // could probably do better than this - ret = LoadDiskFSContents(pSubVol->GetDiskFS(), subVolName, pScanOpts); - if (ret != 0) - return ret; - pSubVol = pDiskFS->GetNextSubVolume(pSubVol); - } + ret = LoadDiskFSContents(pSubVol->GetDiskFS(), subVolName, pScanOpts); + if (ret != 0) + return ret; + pSubVol = pDiskFS->GetNextSubVolume(pSubVol); + } - return 0; + return 0; } diff --git a/mdc/Main.h b/mdc/Main.h index a0565e2..f608ff3 100644 --- a/mdc/Main.h +++ b/mdc/Main.h @@ -17,12 +17,12 @@ struct Win32dirent; struct ScanOpts; typedef enum RecordKind { - kRecordKindUnknown = 0, - kRecordKindDisk, - kRecordKindFile, - kRecordKindForkedFile, - kRecordKindDirectory, - kRecordKindVolumeDir, + kRecordKindUnknown = 0, + kRecordKindDisk, + kRecordKindFile, + kRecordKindForkedFile, + kRecordKindDirectory, + kRecordKindVolumeDir, } RecordKind; @@ -31,42 +31,42 @@ typedef enum RecordKind { */ class MainWindow : public CFrameWnd { public: - MainWindow(void); - ~MainWindow(void); + MainWindow(void); + ~MainWindow(void); private: - afx_msg void OnFileScan(void); - afx_msg void OnFileExit(void); - afx_msg void OnHelpWebSite(void); - afx_msg void OnHelpAbout(void); + afx_msg void OnFileScan(void); + afx_msg void OnFileExit(void); + afx_msg void OnHelpWebSite(void); + afx_msg void OnHelpAbout(void); - BOOL PeekAndPump(void); + BOOL PeekAndPump(void); - static void DebugMsgHandler(const char* file, int line, - const char* msg); - static NuResult NufxErrorMsgHandler(NuArchive* /*pArchive*/, - void* vErrorMessage); + static void DebugMsgHandler(const char* file, int line, + const char* msg); + static NuResult NufxErrorMsgHandler(NuArchive* /*pArchive*/, + void* vErrorMessage); - void ScanFiles(void); - Win32dirent* OpenDir(const char* name); - Win32dirent* ReadDir(Win32dirent* dir); - void CloseDir(Win32dirent* dir); - int Process(const char* pathname, ScanOpts* pScanOpts, - CString* pErrMsg); - int ProcessDirectory(const char* dirName, ScanOpts* pScanOpts, - CString* pErrMsg); - int ScanDiskImage(const char* pathName, ScanOpts* pScanOpts); - int LoadDiskFSContents(DiskFS* pDiskFS, const char* volName, - ScanOpts* pScanOpts); - void AnalyzeFile(const A2File* pFile, RecordKind* pRecordKind, - LONGLONG* pTotalLen, LONGLONG* pTotalCompLen); - bool IsRecordReadOnly(int access); - static const char* GetFileTypeString(unsigned long fileType); + void ScanFiles(void); + Win32dirent* OpenDir(const char* name); + Win32dirent* ReadDir(Win32dirent* dir); + void CloseDir(Win32dirent* dir); + int Process(const char* pathname, ScanOpts* pScanOpts, + CString* pErrMsg); + int ProcessDirectory(const char* dirName, ScanOpts* pScanOpts, + CString* pErrMsg); + int ScanDiskImage(const char* pathName, ScanOpts* pScanOpts); + int LoadDiskFSContents(DiskFS* pDiskFS, const char* volName, + ScanOpts* pScanOpts); + void AnalyzeFile(const A2File* pFile, RecordKind* pRecordKind, + LONGLONG* pTotalLen, LONGLONG* pTotalCompLen); + bool IsRecordReadOnly(int access); + static const char* GetFileTypeString(unsigned long fileType); - bool fCancelFlag; - //int fTitleAnimation; + bool fCancelFlag; + //int fTitleAnimation; - DECLARE_MESSAGE_MAP() + DECLARE_MESSAGE_MAP() }; #endif /*__MAIN__*/ \ No newline at end of file diff --git a/mdc/ProgressDlg.cpp b/mdc/ProgressDlg.cpp index a98b5e7..ceb8694 100644 --- a/mdc/ProgressDlg.cpp +++ b/mdc/ProgressDlg.cpp @@ -21,20 +21,20 @@ static char THIS_FILE[] = __FILE__; #if 0 ProgressDlg::ProgressDlg(CWnd* pParent /*=NULL*/) - : CDialog(ProgressDlg::IDD, pParent) + : CDialog(ProgressDlg::IDD, pParent) { - //{{AFX_DATA_INIT(ProgressDlg) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT + //{{AFX_DATA_INIT(ProgressDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT - fpCancelFlag = nil; + fpCancelFlag = nil; } #endif BEGIN_MESSAGE_MAP(ProgressDlg, CDialog) - //{{AFX_MSG_MAP(ProgressDlg) - //}}AFX_MSG_MAP + //{{AFX_MSG_MAP(ProgressDlg) + //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// @@ -42,17 +42,17 @@ END_MESSAGE_MAP() BOOL ProgressDlg::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) { - // TODO: Add your specialized code here and/or call the base class - - return CDialog::Create(IDD, pParentWnd); + // TODO: Add your specialized code here and/or call the base class + + return CDialog::Create(IDD, pParentWnd); } void ProgressDlg::PostNcDestroy() { - // TODO: Add your specialized code here and/or call the base class - delete this; - - //CDialog::PostNcDestroy(); + // TODO: Add your specialized code here and/or call the base class + delete this; + + //CDialog::PostNcDestroy(); } /* @@ -62,17 +62,17 @@ void ProgressDlg::PostNcDestroy() void ProgressDlg::SetCurrentFile(const char* fileName) { - CWnd* pWnd = GetDlgItem(IDC_PROGRESS_FILENAME); - ASSERT(pWnd != nil); - pWnd->SetWindowText(fileName); + CWnd* pWnd = GetDlgItem(IDC_PROGRESS_FILENAME); + ASSERT(pWnd != nil); + pWnd->SetWindowText(fileName); } void ProgressDlg::OnCancel() { - // TODO: Add extra cleanup here - WMSG0("Cancel button pushed\n"); - ASSERT(fpCancelFlag != nil); - *fpCancelFlag = true; - - //CDialog::OnCancel(); + // TODO: Add extra cleanup here + WMSG0("Cancel button pushed\n"); + ASSERT(fpCancelFlag != nil); + *fpCancelFlag = true; + + //CDialog::OnCancel(); } diff --git a/mdc/ProgressDlg.h b/mdc/ProgressDlg.h index 97a9dbc..f405ed3 100644 --- a/mdc/ProgressDlg.h +++ b/mdc/ProgressDlg.h @@ -19,38 +19,38 @@ class ProgressDlg : public CDialog { // Construction public: - /*ProgressDlg(CWnd* pParent = NULL); // standard constructor*/ + /*ProgressDlg(CWnd* pParent = NULL); // standard constructor*/ // Dialog Data - //{{AFX_DATA(ProgressDlg) - enum { IDD = IDD_PROGRESS }; - // NOTE: the ClassWizard will add data members here - //}}AFX_DATA + //{{AFX_DATA(ProgressDlg) + enum { IDD = IDD_PROGRESS }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA - bool* fpCancelFlag; + bool* fpCancelFlag; // Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(ProgressDlg) - public: - virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL); - protected: - virtual void PostNcDestroy(); - //}}AFX_VIRTUAL + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(ProgressDlg) + public: + virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL); + protected: + virtual void PostNcDestroy(); + //}}AFX_VIRTUAL public: - BOOL Create(CWnd* pParentWnd = NULL) { - return CDialog::Create(IDD_PROGRESS, pParentWnd); - } - void SetCurrentFile(const char* fileName); + BOOL Create(CWnd* pParentWnd = NULL) { + return CDialog::Create(IDD_PROGRESS, pParentWnd); + } + void SetCurrentFile(const char* fileName); // Implementation protected: - // Generated message map functions - //{{AFX_MSG(ProgressDlg) - virtual void OnCancel(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() + // Generated message map functions + //{{AFX_MSG(ProgressDlg) + virtual void OnCancel(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() }; //{{AFX_INSERT_LOCATION}} diff --git a/mdc/StdAfx.cpp b/mdc/StdAfx.cpp index 1da4078..dcc6f56 100644 --- a/mdc/StdAfx.cpp +++ b/mdc/StdAfx.cpp @@ -4,8 +4,8 @@ * See the file LICENSE for distribution terms. */ // stdafx.cpp : source file that includes just the standard includes -// mdc.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information +// mdc.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information #include "stdafx.h" diff --git a/mdc/StdAfx.h b/mdc/StdAfx.h index 4ba244b..b13157b 100644 --- a/mdc/StdAfx.h +++ b/mdc/StdAfx.h @@ -15,7 +15,7 @@ #pragma once #endif // _MSC_VER > 1000 -#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers // Windows Header Files: diff --git a/mdc/mdc.cpp b/mdc/mdc.cpp index f477d38..635536a 100644 --- a/mdc/mdc.cpp +++ b/mdc/mdc.cpp @@ -25,27 +25,27 @@ int gPid = -1; */ MyApp::MyApp(LPCTSTR lpszAppName) : CWinApp(lpszAppName) { - time_t now; - now = time(nil); + time_t now; + now = time(nil); #ifdef _DEBUG_LOG - gLog = fopen(kDebugLog, "w"); - if (gLog == nil) - abort(); - ::setvbuf(gLog, nil, _IONBF, 0); + gLog = fopen(kDebugLog, "w"); + if (gLog == nil) + abort(); + ::setvbuf(gLog, nil, _IONBF, 0); - gPid = ::getpid(); - fprintf(gLog, "\n"); + gPid = ::getpid(); + fprintf(gLog, "\n"); #endif - WMSG1("MDC started at %.24s\n", ctime(&now)); + WMSG1("MDC started at %.24s\n", ctime(&now)); - int tmpDbgFlag; - // enable memory leak detection + int tmpDbgFlag; + // enable memory leak detection tmpDbgFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); tmpDbgFlag |= _CRTDBG_LEAK_CHECK_DF; _CrtSetDbgFlag(tmpDbgFlag); - WMSG0("Leak detection enabled\n"); + WMSG0("Leak detection enabled\n"); } /* @@ -53,10 +53,10 @@ MyApp::MyApp(LPCTSTR lpszAppName) : CWinApp(lpszAppName) */ MyApp::~MyApp(void) { - WMSG0("MDC SHUTTING DOWN\n\n"); + WMSG0("MDC SHUTTING DOWN\n\n"); #ifdef _DEBUG_LOG - if (gLog != nil) - fclose(gLog); + if (gLog != nil) + fclose(gLog); #endif } @@ -69,9 +69,9 @@ MyApp::~MyApp(void) BOOL MyApp::InitInstance(void) { - m_pMainWnd = new MainWindow; - m_pMainWnd->ShowWindow(m_nCmdShow); - m_pMainWnd->UpdateWindow(); + m_pMainWnd = new MainWindow; + m_pMainWnd->ShowWindow(m_nCmdShow); + m_pMainWnd->UpdateWindow(); - return TRUE; + return TRUE; } diff --git a/mdc/mdc.h b/mdc/mdc.h index 893151b..4f5b4d0 100644 --- a/mdc/mdc.h +++ b/mdc/mdc.h @@ -17,25 +17,25 @@ */ #if defined(_DEBUG_LOG) -#define kDebugLog "C:\\mdclog.txt" +#define kDebugLog "C:\\mdclog.txt" #endif /* MDC version numbers */ -#define kAppMajorVersion 2 -#define kAppMinorVersion 2 -#define kAppBugVersion 0 +#define kAppMajorVersion 2 +#define kAppMinorVersion 2 +#define kAppBugVersion 0 /* * Windows application object. */ class MyApp : public CWinApp { public: - MyApp(LPCTSTR lpszAppName = NULL); - virtual ~MyApp(void); + MyApp(LPCTSTR lpszAppName = NULL); + virtual ~MyApp(void); - // Overridden functions - virtual BOOL InitInstance(void); - //virtual BOOL OnIdle(LONG lCount); + // Overridden functions + virtual BOOL InitInstance(void); + //virtual BOOL OnIdle(LONG lCount); }; extern MyApp gMyApp; diff --git a/reformat/AWGS.cpp b/reformat/AWGS.cpp index 8bf434a..b214020 100644 --- a/reformat/AWGS.cpp +++ b/reformat/AWGS.cpp @@ -15,13 +15,13 @@ void ReformatAWGS_WP::Examine(ReformatHolder* pHolder) { - ReformatHolder::ReformatApplies applies = ReformatHolder::kApplicNot; + ReformatHolder::ReformatApplies applies = ReformatHolder::kApplicNot; - if (pHolder->GetFileType() == kTypeGWP && pHolder->GetAuxType() == 0x8010) - applies = ReformatHolder::kApplicYes; + if (pHolder->GetFileType() == kTypeGWP && pHolder->GetAuxType() == 0x8010) + applies = ReformatHolder::kApplicYes; - pHolder->SetApplic(ReformatHolder::kReformatAWGS_WP, applies, - ReformatHolder::kApplicNot, ReformatHolder::kApplicNot); + pHolder->SetApplic(ReformatHolder::kReformatAWGS_WP, applies, + ReformatHolder::kApplicNot, ReformatHolder::kApplicNot); } /* @@ -29,120 +29,120 @@ ReformatAWGS_WP::Examine(ReformatHolder* pHolder) */ int ReformatAWGS_WP::Process(const ReformatHolder* pHolder, - ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, - ReformatOutput* pOutput) + ReformatHolder::ReformatID id, ReformatHolder::ReformatPart part, + ReformatOutput* pOutput) { - const unsigned char* srcBuf = pHolder->GetSourceBuf(part); - long srcLen = pHolder->GetSourceLen(part); - fUseRTF = true; - Chunk doc, header, footer; - unsigned short val; + const unsigned char* srcBuf = pHolder->GetSourceBuf(part); + long srcLen = pHolder->GetSourceLen(part); + fUseRTF = true; + Chunk doc, header, footer; + unsigned short val; - CheckGSCharConv(); + CheckGSCharConv(); - /* must at least have the doc header and globals */ - if (srcLen < kMinExpectedLen) { - WMSG0("Too short to be AWGS\n"); - return -1; - } + /* must at least have the doc header and globals */ + if (srcLen < kMinExpectedLen) { + WMSG0("Too short to be AWGS\n"); + return -1; + } - RTFBegin(kRTFFlagColorTable); + RTFBegin(kRTFFlagColorTable); - /* - * Pull interesting values out of the document header. - */ - val = Get16LE(srcBuf + 0); - if (val != kExpectedVersion1 && val != kExpectedVersion2) { - WMSG2("AWGS_WP: unexpected version number (got 0x%04x, wanted 0x%04x)\n", - val, kExpectedVersion1); - DebugBreak(); - } - val = Get16LE(srcBuf + 2); - if (val != kDocHeaderLen) { - WMSG2("Unexpected doc header len (got 0x%04x, wanted 0x%04x)\n", - val, kDocHeaderLen); - return -1; - } - /* the color table is 32 bytes at +56, should we be interested */ + /* + * Pull interesting values out of the document header. + */ + val = Get16LE(srcBuf + 0); + if (val != kExpectedVersion1 && val != kExpectedVersion2) { + WMSG2("AWGS_WP: unexpected version number (got 0x%04x, wanted 0x%04x)\n", + val, kExpectedVersion1); + DebugBreak(); + } + val = Get16LE(srcBuf + 2); + if (val != kDocHeaderLen) { + WMSG2("Unexpected doc header len (got 0x%04x, wanted 0x%04x)\n", + val, kDocHeaderLen); + return -1; + } + /* the color table is 32 bytes at +56, should we be interested */ - srcBuf += kDocHeaderLen; - srcLen -= kDocHeaderLen; + srcBuf += kDocHeaderLen; + srcLen -= kDocHeaderLen; - /* - * Pull interesting values out of the WP global variables section. - */ - val = Get16LE(srcBuf + 0); - if (val > kExpectedIntVersion) { - WMSG2("Unexpected internal version number (got %d, expected %d)\n", - val, kExpectedIntVersion); - return -1; - } + /* + * Pull interesting values out of the WP global variables section. + */ + val = Get16LE(srcBuf + 0); + if (val > kExpectedIntVersion) { + WMSG2("Unexpected internal version number (got %d, expected %d)\n", + val, kExpectedIntVersion); + return -1; + } - /* date/time are pascal strings */ - WMSG2("File saved at '%.26s' '%.10s'\n", srcBuf + 6, srcBuf + 32); + /* date/time are pascal strings */ + WMSG2("File saved at '%.26s' '%.10s'\n", srcBuf + 6, srcBuf + 32); - srcBuf += kWPGlobalsLen; - srcLen -= kWPGlobalsLen; + srcBuf += kWPGlobalsLen; + srcLen -= kWPGlobalsLen; - /* - * Now come the three chunks, in order: main document, header, footer. - */ - WMSG0("AWGS_WP: scanning doc\n"); - if (!ReadChunk(&srcBuf, &srcLen, &doc)) - return -1; - WMSG0("AWGS_WP: scanning header\n"); - if (!ReadChunk(&srcBuf, &srcLen, &header)) - return -1; - WMSG0("AWGS_WP: scanning footer\n"); - if (!ReadChunk(&srcBuf, &srcLen, &footer)) - return -1; + /* + * Now come the three chunks, in order: main document, header, footer. + */ + WMSG0("AWGS_WP: scanning doc\n"); + if (!ReadChunk(&srcBuf, &srcLen, &doc)) + return -1; + WMSG0("AWGS_WP: scanning header\n"); + if (!ReadChunk(&srcBuf, &srcLen, &header)) + return -1; + WMSG0("AWGS_WP: scanning footer\n"); + if (!ReadChunk(&srcBuf, &srcLen, &footer)) + return -1; - if (srcLen != 0) { - WMSG1("AWGS NOTE: %ld bytes left in file\n", srcLen); - } + if (srcLen != 0) { + WMSG1("AWGS NOTE: %ld bytes left in file\n", srcLen); + } - /* - * Dump the chunks, starting with header and footer. - */ - RTFSetColor(kColorMediumBlue); - RTFSetFont(kFontCourierNew); - RTFSetFontSize(10); - BufPrintf("
"); - RTFSetColor(kColorNone); - RTFNewPara(); + /* + * Dump the chunks, starting with header and footer. + */ + RTFSetColor(kColorMediumBlue); + RTFSetFont(kFontCourierNew); + RTFSetFontSize(10); + BufPrintf("
"); + RTFSetColor(kColorNone); + RTFNewPara(); - PrintChunk(&header); + PrintChunk(&header); - RTFSetColor(kColorMediumBlue); - RTFSetFont(kFontCourierNew); - RTFSetFontSize(10); - BufPrintf("
"); - RTFSetColor(kColorNone); - RTFNewPara(); + RTFSetColor(kColorMediumBlue); + RTFSetFont(kFontCourierNew); + RTFSetFontSize(10); + BufPrintf("
"); + RTFSetColor(kColorNone); + RTFNewPara(); - RTFSetColor(kColorMediumBlue); - RTFSetFont(kFontCourierNew); - RTFSetFontSize(10); - BufPrintf("
"); - RTFSetColor(kColorNone); - RTFNewPara(); + RTFSetColor(kColorMediumBlue); + RTFSetFont(kFontCourierNew); + RTFSetFontSize(10); + BufPrintf("
"); + RTFSetColor(kColorNone); + RTFNewPara(); - PrintChunk(&footer); + PrintChunk(&footer); - RTFSetColor(kColorMediumBlue); - RTFSetFont(kFontCourierNew); - RTFSetFontSize(10); - BufPrintf("
"); - RTFSetColor(kColorNone); - RTFNewPara(); + RTFSetColor(kColorMediumBlue); + RTFSetFont(kFontCourierNew); + RTFSetFontSize(10); + BufPrintf("
"); + RTFSetColor(kColorNone); + RTFNewPara(); - WMSG0("AWGS_WP: rendering document\n"); - PrintChunk(&doc); + WMSG0("AWGS_WP: rendering document\n"); + PrintChunk(&doc); - RTFEnd(); + RTFEnd(); - SetResultBuffer(pOutput, true); - return 0; + SetResultBuffer(pOutput, true); + return 0; } /* @@ -150,56 +150,56 @@ ReformatAWGS_WP::Process(const ReformatHolder* pHolder, */ bool ReformatAWGS_WP::ReadChunk(const unsigned char** pSrcBuf, long* pSrcLen, - Chunk* pChunk) + Chunk* pChunk) { - /* starts with the saveArray count */ - pChunk->saveArrayCount = Get16LE(*pSrcBuf); - if (pChunk->saveArrayCount == 0) { - /* AWGS always has at least 1 paragraph */ - WMSG0("Save array is empty\n"); - return false; - } + /* starts with the saveArray count */ + pChunk->saveArrayCount = Get16LE(*pSrcBuf); + if (pChunk->saveArrayCount == 0) { + /* AWGS always has at least 1 paragraph */ + WMSG0("Save array is empty\n"); + return false; + } - *pSrcBuf += 2; - *pSrcLen -= 2; + *pSrcBuf += 2; + *pSrcLen -= 2; - /* locate and move past the SaveArray */ - pChunk->saveArray = *pSrcBuf; + /* locate and move past the SaveArray */ + pChunk->saveArray = *pSrcBuf; - *pSrcBuf += pChunk->saveArrayCount * kSaveArrayEntryLen; - *pSrcLen -= pChunk->saveArrayCount * kSaveArrayEntryLen; - if (*pSrcLen <= 0) { - WMSG2("SaveArray exceeds file length (count=%d len now %ld)\n", - pChunk->saveArrayCount, *pSrcLen); - return false; - } + *pSrcBuf += pChunk->saveArrayCount * kSaveArrayEntryLen; + *pSrcLen -= pChunk->saveArrayCount * kSaveArrayEntryLen; + if (*pSrcLen <= 0) { + WMSG2("SaveArray exceeds file length (count=%d len now %ld)\n", + pChunk->saveArrayCount, *pSrcLen); + return false; + } - /* - * Scan the "save array" to find the highest-numbered ruler. This tells - * us how many rulers there are. - */ - pChunk->numRulers = GetNumRulers(pChunk->saveArray, pChunk->saveArrayCount); - if (*pSrcLen < pChunk->numRulers * kRulerEntryLen) { - WMSG2("Not enough room for rulers (rem=%ld, needed=%ld)\n", - *pSrcLen, pChunk->numRulers * kRulerEntryLen); - return false; - } - WMSG1("+++ found %d rulers\n", pChunk->numRulers); + /* + * Scan the "save array" to find the highest-numbered ruler. This tells + * us how many rulers there are. + */ + pChunk->numRulers = GetNumRulers(pChunk->saveArray, pChunk->saveArrayCount); + if (*pSrcLen < pChunk->numRulers * kRulerEntryLen) { + WMSG2("Not enough room for rulers (rem=%ld, needed=%ld)\n", + *pSrcLen, pChunk->numRulers * kRulerEntryLen); + return false; + } + WMSG1("+++ found %d rulers\n", pChunk->numRulers); - pChunk->rulers = *pSrcBuf; - *pSrcBuf += pChunk->numRulers * kRulerEntryLen; - *pSrcLen -= pChunk->numRulers * kRulerEntryLen; + pChunk->rulers = *pSrcBuf; + *pSrcBuf += pChunk->numRulers * kRulerEntryLen; + *pSrcLen -= pChunk->numRulers * kRulerEntryLen; - /* - * Now we're at the docTextBlocks section. - */ - pChunk->textBlocks = *pSrcBuf; - pChunk->numTextBlocks = GetNumTextBlocks(pChunk->saveArray, - pChunk->saveArrayCount); - if (!SkipTextBlocks(pSrcBuf, pSrcLen, pChunk->numTextBlocks)) - return false; + /* + * Now we're at the docTextBlocks section. + */ + pChunk->textBlocks = *pSrcBuf; + pChunk->numTextBlocks = GetNumTextBlocks(pChunk->saveArray, + pChunk->saveArrayCount); + if (!SkipTextBlocks(pSrcBuf, pSrcLen, pChunk->numTextBlocks)) + return false; - return true; + return true; } /* @@ -208,80 +208,80 @@ ReformatAWGS_WP::ReadChunk(const unsigned char** pSrcBuf, long* pSrcLen, void ReformatAWGS_WP::PrintChunk(const Chunk* pChunk) { - const int kDefaultStatusBits = kAWGSJustifyLeft | kAWGSSingleSpace; - SaveArrayEntry sae; - const unsigned char* saveArray; - int saCount; - const unsigned char* blockPtr; - long blockLen; - const unsigned char* pRuler; - unsigned short rulerStatusBits; + const int kDefaultStatusBits = kAWGSJustifyLeft | kAWGSSingleSpace; + SaveArrayEntry sae; + const unsigned char* saveArray; + int saCount; + const unsigned char* blockPtr; + long blockLen; + const unsigned char* pRuler; + unsigned short rulerStatusBits; - saveArray = pChunk->saveArray; - saCount = pChunk->saveArrayCount; - for ( ; saCount > 0; saCount--, saveArray += kSaveArrayEntryLen) { - UnpackSaveArrayEntry(saveArray, &sae); + saveArray = pChunk->saveArray; + saCount = pChunk->saveArrayCount; + for ( ; saCount > 0; saCount--, saveArray += kSaveArrayEntryLen) { + UnpackSaveArrayEntry(saveArray, &sae); - /* - * Page-break paragraphs have no real data and an invalid value - * in the "rulerNum" field. So we just throw out a page break - * here and call it a day. - */ - if (sae.attributes == 0x0001) { - /* this is a page-break paragraph */ - RTFSetColor(kColorMediumBlue); - RTFSetFont(kFontCourierNew); - RTFSetFontSize(10); - BufPrintf(""); - RTFSetColor(kColorNone); - RTFNewPara(); - RTFPageBreak(); // only supported by Word - continue; - } + /* + * Page-break paragraphs have no real data and an invalid value + * in the "rulerNum" field. So we just throw out a page break + * here and call it a day. + */ + if (sae.attributes == 0x0001) { + /* this is a page-break paragraph */ + RTFSetColor(kColorMediumBlue); + RTFSetFont(kFontCourierNew); + RTFSetFontSize(10); + BufPrintf(""); + RTFSetColor(kColorNone); + RTFNewPara(); + RTFPageBreak(); // only supported by Word + continue; + } - if (sae.rulerNum < pChunk->numRulers) { - pRuler = pChunk->rulers + sae.rulerNum * kRulerEntryLen; - rulerStatusBits = Get16LE(pRuler + 2); - } else { - WMSG1("AWGS_WP GLITCH: invalid ruler index %d\n", sae.rulerNum); - rulerStatusBits = kDefaultStatusBits; - } + if (sae.rulerNum < pChunk->numRulers) { + pRuler = pChunk->rulers + sae.rulerNum * kRulerEntryLen; + rulerStatusBits = Get16LE(pRuler + 2); + } else { + WMSG1("AWGS_WP GLITCH: invalid ruler index %d\n", sae.rulerNum); + rulerStatusBits = kDefaultStatusBits; + } - if (rulerStatusBits & kAWGSJustifyFull) - RTFParaJustify(); - else if (rulerStatusBits & kAWGSJustifyRight) - RTFParaRight(); - else if (rulerStatusBits & kAWGSJustifyCenter) - RTFParaCenter(); - else if (rulerStatusBits & kAWGSJustifyLeft) - RTFParaLeft(); - RTFSetPara(); + if (rulerStatusBits & kAWGSJustifyFull) + RTFParaJustify(); + else if (rulerStatusBits & kAWGSJustifyRight) + RTFParaRight(); + else if (rulerStatusBits & kAWGSJustifyCenter) + RTFParaCenter(); + else if (rulerStatusBits & kAWGSJustifyLeft) + RTFParaLeft(); + RTFSetPara(); - /* - * Find the text block that holds this paragraph. We could speed - * this up by creating an array of entries rather than walking the - * list every time. However, the block count tends to be fairly - * small (e.g. 7 for a 16K doc). - */ - blockPtr = FindTextBlock(pChunk, sae.textBlock); - if (blockPtr == nil) { - WMSG1("AWGS_WP bad textBlock %d\n", sae.textBlock); - return; - } - blockLen = (long) Get32LE(blockPtr); - if (blockLen <= 0 || blockLen > 65535) { - WMSG1("AWGS_WP invalid block len %d\n", blockLen); - return; - } - blockPtr += 4; + /* + * Find the text block that holds this paragraph. We could speed + * this up by creating an array of entries rather than walking the + * list every time. However, the block count tends to be fairly + * small (e.g. 7 for a 16K doc). + */ + blockPtr = FindTextBlock(pChunk, sae.textBlock); + if (blockPtr == nil) { + WMSG1("AWGS_WP bad textBlock %d\n", sae.textBlock); + return; + } + blockLen = (long) Get32LE(blockPtr); + if (blockLen <= 0 || blockLen > 65535) { + WMSG1("AWGS_WP invalid block len %d\n", blockLen); + return; + } + blockPtr += 4; - if (sae.offset >= blockLen) { - WMSG2("AWGS_WP bad offset: %d, blockLen=%ld\n", - sae.offset, blockLen); - return; - } - PrintParagraph(blockPtr + sae.offset, blockLen - sae.offset); - } + if (sae.offset >= blockLen) { + WMSG2("AWGS_WP bad offset: %d, blockLen=%ld\n", + sae.offset, blockLen); + return; + } + PrintParagraph(blockPtr + sae.offset, blockLen - sae.offset); + } } /* @@ -294,16 +294,16 @@ ReformatAWGS_WP::PrintChunk(const Chunk* pChunk) const unsigned char* ReformatAWGS_WP::FindTextBlock(const Chunk* pChunk, int blockNum) { - const unsigned char* blockPtr = pChunk->textBlocks; - long count = pChunk->numTextBlocks; - unsigned long blockSize; + const unsigned char* blockPtr = pChunk->textBlocks; + long count = pChunk->numTextBlocks; + unsigned long blockSize; - while (blockNum--) { - blockSize = Get32LE(blockPtr); - blockPtr += 4 + blockSize; - } + while (blockNum--) { + blockSize = Get32LE(blockPtr); + blockPtr += 4 + blockSize; + } - return blockPtr; + return blockPtr; } @@ -317,91 +317,91 @@ ReformatAWGS_WP::FindTextBlock(const Chunk* pChunk, int blockNum) int ReformatAWGS_WP::PrintParagraph(const unsigned char* ptr, long maxLen) { - const unsigned char* startPtr = ptr; - unsigned short firstFont; - unsigned char firstStyle, firstSize, firstColor; - unsigned char uch; + const unsigned char* startPtr = ptr; + unsigned short firstFont; + unsigned char firstStyle, firstSize, firstColor; + unsigned char uch; - if (maxLen < 7) { - WMSG1("AWGS_WP GLITCH: not enough storage for para header (%d)\n", - maxLen); - return 1; // don't return zero or we might loop forever - } - /* pull out the paragraph header */ - firstFont = Get16LE(ptr); - firstStyle = *(ptr + 2); - firstSize = *(ptr + 3); - firstColor = *(ptr + 4); + if (maxLen < 7) { + WMSG1("AWGS_WP GLITCH: not enough storage for para header (%d)\n", + maxLen); + return 1; // don't return zero or we might loop forever + } + /* pull out the paragraph header */ + firstFont = Get16LE(ptr); + firstStyle = *(ptr + 2); + firstSize = *(ptr + 3); + firstColor = *(ptr + 4); - ptr += 7; - maxLen -= 7; + ptr += 7; + maxLen -= 7; - /* - * Set the font first; that defines the point size multiplier. Set - * the size second, because the point size determines whether we - * show underline. Set the style last. - */ - //WMSG3("+++ Para start: font=0x%04x size=%d style=0x%02x\n", - // firstFont, firstSize, firstStyle); - RTFSetGSFont(firstFont); - RTFSetGSFontSize(firstSize); - RTFSetGSFontStyle(firstStyle); + /* + * Set the font first; that defines the point size multiplier. Set + * the size second, because the point size determines whether we + * show underline. Set the style last. + */ + //WMSG3("+++ Para start: font=0x%04x size=%d style=0x%02x\n", + // firstFont, firstSize, firstStyle); + RTFSetGSFont(firstFont); + RTFSetGSFontSize(firstSize); + RTFSetGSFontStyle(firstStyle); - while (maxLen > 0) { - uch = *ptr++; - maxLen--; - switch (uch) { - case 0x01: // font change - two bytes follow - if (maxLen >= 2) { - RTFSetGSFont(Get16LE(ptr)); - ptr += 2; - maxLen -= 2; - } - break; - case 0x02: // text style change - if (maxLen >= 1) { - RTFSetGSFontStyle(*ptr++); - maxLen--; - } - break; - case 0x03: // text size change - if (maxLen >= 1) { - RTFSetGSFontSize(*ptr++); - maxLen--; - } - break; - case 0x04: // color change (0-15) - if (maxLen >= 1) { - ptr++; - maxLen--; - } - break; - case 0x05: // page token (replace with page #) - case 0x06: // date token (replace with date) - case 0x07: // time token (replace with time) - RTFSetColor(kColorMediumBlue); - if (uch == 0x05) - BufPrintf(""); - else if (uch == 0x06) - BufPrintf(""); - else - BufPrintf("