ciderpress/app/DiskArchive.h

254 lines
9.3 KiB
C++

/*
* CiderPress
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
* See the file LICENSE for distribution terms.
*/
/*
* Disk image "archive" support.
*/
#ifndef APP_DISKARCHIVE_H
#define APP_DISKARCHIVE_H
#include "GenericArchive.h"
#include "../diskimg/DiskImg.h"
class RenameEntryDialog;
/*
* One file in a disk image.
*/
class DiskEntry : public GenericEntry {
public:
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
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();
}
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;
A2File* fpFile;
};
/*
* Disk image add-ons to GenericArchive.
*/
class DiskArchive : public GenericArchive {
public:
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;
struct {
NewOptionsBase base;
long numBlocks;
} blank;
struct {
NewOptionsBase base;
const WCHAR* volName;
long numBlocks;
} prodos;
struct {
NewOptionsBase base;
const WCHAR* volName;
long numBlocks;
} pascalfs; // "pascal" is reserved token in MSVC++
struct {
NewOptionsBase base;
const WCHAR* 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);
virtual OpenResult Open(const WCHAR* filename, bool readOnly, CString* pErrMsg);
virtual CString New(const WCHAR* 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 WCHAR* 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 WCHAR* newName);
virtual CString TestVolumeName(const DiskFS* pDiskFS,
const WCHAR* 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; }
/* 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, BYTE** pDataBuf,
long dataLen, BYTE** pRsrcBuf, long rsrcLen);
virtual void XferAbort(CWnd* pMsgWnd);
virtual void XferFinish(CWnd* pMsgWnd);
/* DiskImg callback, 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, char* fsNormalPath) {
fDetails = *pDetails;
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; }
const FileDetails* GetDetails(void) const { return &fDetails; }
/*
* Get the "FS-normal" path, i.e. exactly what we want to appear
* on the disk image. This has the result of any conversions, so
* we need to store it as a narrow string.
*/
const char* GetFSNormalPath(void) const { return fFSNormalPath; }
private:
// Three filenames stored inside FileDetails:
// fDetails.origName -- the name of the Windows file
// fDetails.storageName -- origName with type-preservation goodies
// stripped out
// fFSNormalPath -- the FS-normalized version of "storageName", i.e.
// the name as it will appear on the Apple II disk image
FileDetails fDetails;
CStringA fFSNormalPath;
FileAddData* fpOtherFork;
FileAddData* fpNext;
};
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);
int LoadContents(void);
int LoadDiskFSContents(DiskFS* pDiskFS, const WCHAR* 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 WCHAR* pathName, BYTE** pBuf, long* pLen,
GenericEntry::ConvertEOL conv, GenericEntry::ConvertHighASCII convHA) const;
DIError AddForksToDisk(DiskFS* pDiskFS, const DiskFS::CreateParms* pParms,
const BYTE* dataBuf, long dataLen,
const BYTE* 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);
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;
/* state during xfer */
//CString fXferStoragePrefix;
DiskFS* fpXferTargetFS;
};
#endif /*APP_DISKARCHIVE_H*/