mirror of
https://github.com/fadden/ciderpress.git
synced 2024-11-26 17:49:21 +00:00
5946481b4e
This handles version 1 and 2, and copes with the broken files created by the Mac OS X "applesingle" command-line tool (which is unable to decode the broken files it creates). I get the sense that many AppleSingle files don't end with ".AS", so the filespec includes "*.*" as well. Some AppleSingle files don't include a filename. In that case, we use the file's name as the entry name, minus any ".as" extension. The current implementation doesn't convert from Unicode to Mac OS Roman, so non-ASCII characters are mishandled unless the file was generated by GS/ShrinkIt. (We assume version 1 AppleSingle files use MOR name strings.) Also, version bump to 4.0.0d3.
418 lines
13 KiB
C++
418 lines
13 KiB
C++
/*
|
|
* CiderPress
|
|
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
|
* See the file LICENSE for distribution terms.
|
|
*/
|
|
/*
|
|
* Implementation of the various ArchiveInfo dialog classes.
|
|
*/
|
|
#include "StdAfx.h"
|
|
#include "ArchiveInfoDialog.h"
|
|
#include "../nufxlib/NufxLib.h"
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* ArchiveInfoDialog
|
|
* ===========================================================================
|
|
*/
|
|
|
|
BEGIN_MESSAGE_MAP(ArchiveInfoDialog, CDialog)
|
|
ON_COMMAND(IDHELP, OnHelp)
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* NufxArchiveInfoDialog
|
|
* ===========================================================================
|
|
*/
|
|
|
|
BOOL NufxArchiveInfoDialog::OnInitDialog(void)
|
|
{
|
|
CString notAvailable = "(not available)";
|
|
NuArchive* pNuArchive;
|
|
const NuMasterHeader* pMasterHeader;
|
|
CWnd* pWnd;
|
|
CString tmpStr;
|
|
NuAttr attr;
|
|
NuError nerr;
|
|
time_t when;
|
|
|
|
ASSERT(fpArchive != NULL);
|
|
|
|
pNuArchive = fpArchive->GetNuArchivePointer();
|
|
ASSERT(pNuArchive != NULL);
|
|
(void) NuGetMasterHeader(pNuArchive, &pMasterHeader);
|
|
ASSERT(pMasterHeader != NULL);
|
|
|
|
pWnd = GetDlgItem(IDC_AI_FILENAME);
|
|
CString pathName(fpArchive->GetPathName());
|
|
pWnd->SetWindowText(pathName);
|
|
|
|
pWnd = GetDlgItem(IDC_AINUFX_RECORDS);
|
|
nerr = NuGetAttr(pNuArchive, kNuAttrNumRecords, &attr);
|
|
if (nerr == kNuErrNone)
|
|
tmpStr.Format(L"%ld", attr);
|
|
else
|
|
tmpStr = notAvailable;
|
|
pWnd->SetWindowText(tmpStr);
|
|
|
|
pWnd = GetDlgItem(IDC_AINUFX_FORMAT);
|
|
nerr = NuGetAttr(pNuArchive, kNuAttrArchiveType, &attr);
|
|
switch (attr) {
|
|
case kNuArchiveNuFX: tmpStr = L"NuFX"; break;
|
|
case kNuArchiveNuFXInBNY: tmpStr = L"NuFX in Binary II"; break;
|
|
case kNuArchiveNuFXSelfEx: tmpStr = L"Self-extracting NuFX"; break;
|
|
case kNuArchiveNuFXSelfExInBNY: tmpStr = L"Self-extracting NuFX in Binary II";
|
|
break;
|
|
case kNuArchiveBNY: tmpStr = L"Binary II"; break;
|
|
default:
|
|
tmpStr = L"(unknown)";
|
|
break;
|
|
};
|
|
pWnd->SetWindowText(tmpStr);
|
|
|
|
pWnd = GetDlgItem(IDC_AINUFX_MASTERVERSION);
|
|
tmpStr.Format(L"%ld", pMasterHeader->mhMasterVersion);
|
|
pWnd->SetWindowText(tmpStr);
|
|
|
|
pWnd = GetDlgItem(IDC_AINUFX_CREATEWHEN);
|
|
when = NufxArchive::DateTimeToSeconds(&pMasterHeader->mhArchiveCreateWhen);
|
|
tmpStr.Format(L"%.24hs", ctime(&when));
|
|
pWnd->SetWindowText(tmpStr);
|
|
|
|
pWnd = GetDlgItem(IDC_AINUFX_MODIFYWHEN);
|
|
when = NufxArchive::DateTimeToSeconds(&pMasterHeader->mhArchiveModWhen);
|
|
tmpStr.Format(L"%.24hs", ctime(&when));
|
|
pWnd->SetWindowText(tmpStr);
|
|
|
|
pWnd = GetDlgItem(IDC_AINUFX_JUNKSKIPPED);
|
|
nerr = NuGetAttr(pNuArchive, kNuAttrJunkOffset, &attr);
|
|
if (nerr == kNuErrNone)
|
|
tmpStr.Format(L"%ld bytes", attr);
|
|
else
|
|
tmpStr = notAvailable;
|
|
pWnd->SetWindowText(tmpStr);
|
|
|
|
return ArchiveInfoDialog::OnInitDialog();
|
|
}
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* DiskArchiveInfoDialog
|
|
* ===========================================================================
|
|
*/
|
|
|
|
BEGIN_MESSAGE_MAP(DiskArchiveInfoDialog, ArchiveInfoDialog)
|
|
ON_CBN_SELCHANGE(IDC_AIDISK_SUBVOLSEL, OnSubVolSelChange)
|
|
END_MESSAGE_MAP()
|
|
|
|
BOOL DiskArchiveInfoDialog::OnInitDialog(void)
|
|
{
|
|
CWnd* pWnd;
|
|
CString tmpStr;
|
|
const DiskImg* pDiskImg;
|
|
const DiskFS* pDiskFS;
|
|
|
|
ASSERT(fpArchive != NULL);
|
|
|
|
pDiskImg = fpArchive->GetDiskImg();
|
|
ASSERT(pDiskImg != NULL);
|
|
pDiskFS = fpArchive->GetDiskFS();
|
|
ASSERT(pDiskFS != NULL);
|
|
|
|
/*
|
|
* Volume characteristics.
|
|
*/
|
|
pWnd = GetDlgItem(IDC_AI_FILENAME);
|
|
pWnd->SetWindowText(fpArchive->GetPathName());
|
|
|
|
pWnd = GetDlgItem(IDC_AIDISK_OUTERFORMAT);
|
|
CStringW outerFormat(DiskImg::ToString(pDiskImg->GetOuterFormat()));
|
|
pWnd->SetWindowText(outerFormat);
|
|
|
|
pWnd = GetDlgItem(IDC_AIDISK_FILEFORMAT);
|
|
CStringW fileFormat(DiskImg::ToString(pDiskImg->GetFileFormat()));
|
|
pWnd->SetWindowText(fileFormat);
|
|
|
|
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 != NULL)
|
|
tmpStr.Format(L"%hs, layout is \"%hs\"",
|
|
DiskImg::ToString(physicalFormat), pNibbleDescr->description);
|
|
else
|
|
tmpStr = DiskImg::ToString(physicalFormat); // unexpected
|
|
pWnd->SetWindowText(tmpStr);
|
|
} else {
|
|
CString physicalFormat(DiskImg::ToString(physicalFormat));
|
|
pWnd->SetWindowText(physicalFormat);
|
|
}
|
|
|
|
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;
|
|
|
|
AddSubVolumes(pDiskFS, L"", &idx);
|
|
ASSERT(idx > 0); // must have at least the top-level DiskFS
|
|
|
|
pCombo->SetCurSel(0);
|
|
if (idx == 1)
|
|
pCombo->EnableWindow(FALSE);
|
|
|
|
return ArchiveInfoDialog::OnInitDialog();
|
|
}
|
|
|
|
void DiskArchiveInfoDialog::AddSubVolumes(const DiskFS* pDiskFS,
|
|
const WCHAR* prefix, int* pIdx)
|
|
{
|
|
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 everything beneath the current level.
|
|
*/
|
|
DiskFS::SubVolume* pSubVol;
|
|
pSubVol = pDiskFS->GetNextSubVolume(NULL);
|
|
tmpStr = prefix;
|
|
tmpStr += L" ";
|
|
while (pSubVol != NULL) {
|
|
AddSubVolumes(pSubVol->GetDiskFS(), tmpStr, pIdx);
|
|
|
|
pSubVol = pDiskFS->GetNextSubVolume(pSubVol);
|
|
}
|
|
}
|
|
|
|
void DiskArchiveInfoDialog::OnSubVolSelChange(void)
|
|
{
|
|
CComboBox* pCombo = (CComboBox*) GetDlgItem(IDC_AIDISK_SUBVOLSEL);
|
|
ASSERT(pCombo != NULL);
|
|
//LOGI("+++ SELECTION IS NOW %d", pCombo->GetCurSel());
|
|
|
|
const DiskFS* pDiskFS;
|
|
pDiskFS = (DiskFS*) pCombo->GetItemData(pCombo->GetCurSel());
|
|
ASSERT(pDiskFS != NULL);
|
|
FillInVolumeInfo(pDiskFS);
|
|
}
|
|
|
|
void DiskArchiveInfoDialog::FillInVolumeInfo(const DiskFS* pDiskFS)
|
|
{
|
|
const DiskImg* pDiskImg = pDiskFS->GetDiskImg();
|
|
CString unknown = L"(unknown)";
|
|
CString tmpStr;
|
|
DIError dierr;
|
|
CWnd* pWnd;
|
|
|
|
pWnd = GetDlgItem(IDC_AIDISK_SECTORORDER);
|
|
CStringW sectorOrderW(DiskImg::ToString(pDiskImg->GetSectorOrder()));
|
|
pWnd->SetWindowText(sectorOrderW);
|
|
|
|
pWnd = GetDlgItem(IDC_AIDISK_FSFORMAT);
|
|
CStringW fsFormat(DiskImg::ToString(pDiskImg->GetFSFormat()));
|
|
pWnd->SetWindowText(fsFormat);
|
|
|
|
pWnd = GetDlgItem(IDC_AIDISK_FILECOUNT);
|
|
tmpStr.Format(L"%ld", pDiskFS->GetFileCount());
|
|
pWnd->SetWindowText(tmpStr);
|
|
|
|
long totalUnits, freeUnits;
|
|
int unitSize;
|
|
CString reducedSize;
|
|
|
|
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(L"%ld blocks (%ls)",
|
|
totalUnits, (LPCWSTR) reducedSize);
|
|
if (totalUnits != pDiskImg->GetNumBlocks()) {
|
|
CString tmpStr2;
|
|
tmpStr2.Format(L", image has room for %ld blocks",
|
|
pDiskImg->GetNumBlocks());
|
|
tmpStr += tmpStr2;
|
|
}
|
|
pWnd->SetWindowText(tmpStr);
|
|
|
|
pWnd = GetDlgItem(IDC_AIDISK_FREESPACE);
|
|
GetReducedSize(freeUnits, unitSize, &reducedSize);
|
|
tmpStr.Format(L"%ld blocks (%ls)",
|
|
freeUnits, (LPCWSTR) reducedSize);
|
|
pWnd->SetWindowText(tmpStr);
|
|
} else {
|
|
ASSERT(unitSize == DiskImgLib::kSectorSize);
|
|
|
|
pWnd = GetDlgItem(IDC_AIDISK_CAPACITY);
|
|
GetReducedSize(totalUnits, unitSize, &reducedSize);
|
|
tmpStr.Format(L"%ld sectors (%ls)",
|
|
totalUnits, (LPCWSTR) reducedSize);
|
|
pWnd->SetWindowText(tmpStr);
|
|
|
|
pWnd = GetDlgItem(IDC_AIDISK_FREESPACE);
|
|
GetReducedSize(freeUnits, unitSize, &reducedSize);
|
|
tmpStr.Format(L"%ld sectors (%ls)",
|
|
freeUnits, (LPCWSTR) 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(L"%ld blocks (%ls)",
|
|
totalUnits, (LPCWSTR) reducedSize);
|
|
} else if (pDiskImg->GetHasSectors()) {
|
|
tmpStr.Format(L"%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_WRITEABLE);
|
|
tmpStr = pDiskFS->GetReadWriteSupported() ? L"Yes" : L"No";
|
|
pWnd->SetWindowText(tmpStr);
|
|
|
|
pWnd = GetDlgItem(IDC_AIDISK_DAMAGED);
|
|
tmpStr = pDiskFS->GetFSDamaged() ? L"Yes" : L"No";
|
|
pWnd->SetWindowText(tmpStr);
|
|
|
|
const char* cp;
|
|
WCHAR* outp;
|
|
|
|
pWnd = GetDlgItem(IDC_AIDISK_NOTES);
|
|
cp = pDiskImg->GetNotes();
|
|
// GetBuffer wants length in code units, which will be 2x since it's
|
|
// wide chars. The 2x mult below is for worst-case linefeed conversion.
|
|
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);
|
|
}
|
|
|
|
void DiskArchiveInfoDialog::GetReducedSize(long numUnits, int unitSize,
|
|
CString* pOut) const
|
|
{
|
|
LONGLONG sizeInBytes = numUnits;
|
|
sizeInBytes *= unitSize;
|
|
long reducedSize;
|
|
|
|
if (sizeInBytes < 0) {
|
|
ASSERT(false);
|
|
pOut->Format(L"<bogus>");
|
|
return;
|
|
}
|
|
|
|
if (sizeInBytes >= 1024*1024*1024) {
|
|
reducedSize = (long) (sizeInBytes / (1024*1024));
|
|
pOut->Format(L"%.2fGB", reducedSize / 1024.0);
|
|
} else if (sizeInBytes >= 1024*1024) {
|
|
reducedSize = (long) (sizeInBytes / 1024);
|
|
pOut->Format(L"%.2fMB", reducedSize / 1024.0);
|
|
} else {
|
|
pOut->Format(L"%.2fKB", ((long) sizeInBytes) / 1024.0);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* BnyArchiveInfoDialog
|
|
* ===========================================================================
|
|
*/
|
|
|
|
BOOL BnyArchiveInfoDialog::OnInitDialog(void)
|
|
{
|
|
CWnd* pWnd;
|
|
CString tmpStr;
|
|
|
|
ASSERT(fpArchive != NULL);
|
|
|
|
pWnd = GetDlgItem(IDC_AI_FILENAME);
|
|
pWnd->SetWindowText(fpArchive->GetPathName());
|
|
tmpStr.Format(L"%ld", fpArchive->GetNumEntries());
|
|
pWnd = GetDlgItem(IDC_AIBNY_RECORDS);
|
|
pWnd->SetWindowText(tmpStr);
|
|
|
|
return ArchiveInfoDialog::OnInitDialog();
|
|
}
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* AcuArchiveInfoDialog
|
|
* ===========================================================================
|
|
*/
|
|
|
|
BOOL AcuArchiveInfoDialog::OnInitDialog(void)
|
|
{
|
|
CWnd* pWnd;
|
|
CString tmpStr;
|
|
|
|
ASSERT(fpArchive != NULL);
|
|
|
|
pWnd = GetDlgItem(IDC_AI_FILENAME);
|
|
pWnd->SetWindowText(fpArchive->GetPathName());
|
|
tmpStr.Format(L"%ld", fpArchive->GetNumEntries());
|
|
pWnd = GetDlgItem(IDC_AIBNY_RECORDS);
|
|
pWnd->SetWindowText(tmpStr);
|
|
|
|
return ArchiveInfoDialog::OnInitDialog();
|
|
}
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* AppleSingleArchiveInfoDialog
|
|
* ===========================================================================
|
|
*/
|
|
|
|
BOOL AppleSingleArchiveInfoDialog::OnInitDialog(void)
|
|
{
|
|
CWnd* pWnd;
|
|
|
|
ASSERT(fpArchive != NULL);
|
|
|
|
pWnd = GetDlgItem(IDC_AI_FILENAME);
|
|
pWnd->SetWindowText(fpArchive->GetPathName());
|
|
pWnd = GetDlgItem(IDC_AIBNY_RECORDS);
|
|
pWnd->SetWindowText(fpArchive->GetInfoString());
|
|
|
|
return ArchiveInfoDialog::OnInitDialog();
|
|
}
|