mirror of
https://github.com/fadden/ciderpress.git
synced 2024-11-29 20:49:27 +00:00
00e6b3ab5e
This updates GenericEntry's filename handling to be more careful about Mac OS Roman vs. Unicode. Most of the work is still done with a CP-1252 conversion instead of MOR, but we now do a proper conversion on the "display name", so we see the right thing in the content list and file viewer. Copy & paste, disk-to-file-archive, and file-archive-to-disk conversions should work (correctly) as before. Extracted files will still have "_" or "%AA" instead of a Unicode TRADE MARK SIGN, but that's fine for now -- we can extract and re-add the files losslessly. The filenames are now stored in CStrings rather than WCHAR*. Also, fixed a bad initializer in the file-archive-to-disk conversion dialog.
301 lines
9.7 KiB
C++
301 lines
9.7 KiB
C++
/*
|
|
* CiderPress
|
|
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
|
* See the file LICENSE for distribution terms.
|
|
*/
|
|
#include "stdafx.h"
|
|
#include "ConvDiskOptionsDialog.h"
|
|
#include "NufxArchive.h"
|
|
#include "Main.h"
|
|
#include "ActionProgressDialog.h"
|
|
#include "DiskArchive.h"
|
|
#include "NewDiskSize.h"
|
|
#include "../diskimg/DiskImgDetail.h" // need ProDOS filename validator
|
|
|
|
BEGIN_MESSAGE_MAP(ConvDiskOptionsDialog, CDialog)
|
|
ON_WM_HELPINFO()
|
|
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()
|
|
|
|
|
|
// TODO: get this from DiskImgLib header?
|
|
const int kProDOSVolNameMax = 15; // longest possible ProDOS volume name
|
|
|
|
BOOL ConvDiskOptionsDialog::OnInitDialog(void)
|
|
{
|
|
CEdit* pEdit = (CEdit*) GetDlgItem(IDC_CONVDISK_VOLNAME);
|
|
ASSERT(pEdit != NULL);
|
|
pEdit->SetLimitText(kProDOSVolNameMax);
|
|
|
|
ResetSizeControls();
|
|
|
|
pEdit = (CEdit*) GetDlgItem(IDC_CONVDISK_SPECIFY_EDIT);
|
|
ASSERT(pEdit != NULL);
|
|
pEdit->SetLimitText(5); // enough for "65535"
|
|
pEdit->EnableWindow(FALSE);
|
|
|
|
return UseSelectionDialog::OnInitDialog();
|
|
}
|
|
|
|
void ConvDiskOptionsDialog::DoDataExchange(CDataExchange* pDX)
|
|
{
|
|
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);
|
|
|
|
ASSERT(fDiskSizeIdx >= 0 && fDiskSizeIdx < (int)NewDiskSize::GetNumSizeEntries());
|
|
|
|
if (pDX->m_bSaveAndValidate) {
|
|
|
|
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.";
|
|
}
|
|
|
|
|
|
if (fVolName.IsEmpty() || fVolName.GetLength() > kProDOSVolNameMax) {
|
|
errMsg = "You must specify a volume name 1-15 characters long.";
|
|
} else {
|
|
if (!IsValidVolumeName_ProDOS(fVolName)) {
|
|
CheckedLoadString(&errMsg, IDS_VALID_VOLNAME_PRODOS);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!errMsg.IsEmpty()) {
|
|
CString appName;
|
|
CheckedLoadString(&appName, IDS_MB_APP_NAME);
|
|
MessageBox(errMsg, appName, MB_OK);
|
|
pDX->Fail();
|
|
}
|
|
|
|
UseSelectionDialog::DoDataExchange(pDX);
|
|
}
|
|
|
|
void ConvDiskOptionsDialog::OnRadioChangeRange(UINT nID)
|
|
{
|
|
LOGI("OnChangeRange id=%d", nID);
|
|
|
|
CButton* pButton = (CButton*) GetDlgItem(IDC_CONVDISK_SPECIFY);
|
|
CEdit* pEdit = (CEdit*) GetDlgItem(IDC_CONVDISK_SPECIFY_EDIT);
|
|
pEdit->EnableWindow(pButton->GetCheck() == BST_CHECKED);
|
|
|
|
NewDiskSize::UpdateSpecifyEdit(this);
|
|
}
|
|
|
|
bool ConvDiskOptionsDialog::IsValidVolumeName_ProDOS(const WCHAR* name)
|
|
{
|
|
CStringA nameA(name);
|
|
return DiskImgLib::DiskFSProDOS::IsValidVolumeName(nameA);
|
|
}
|
|
|
|
void ConvDiskOptionsDialog::ResetSizeControls(void)
|
|
{
|
|
CWnd* pWnd;
|
|
CString spaceReq;
|
|
|
|
LOGI("Resetting size controls");
|
|
spaceReq.Format(IDS_CONVDISK_SPACEREQ, L"(unknown)");
|
|
pWnd = GetDlgItem(IDC_CONVDISK_SPACEREQ);
|
|
ASSERT(pWnd != NULL);
|
|
pWnd->SetWindowText(spaceReq);
|
|
|
|
#if 0
|
|
int i;
|
|
for (i = 0; i < NELEM(gDiskSizes); i++) {
|
|
pWnd = GetDlgItem(gDiskSizes[i].ctrlID);
|
|
ASSERT(pWnd != NULL);
|
|
pWnd->EnableWindow(TRUE);
|
|
}
|
|
#endif
|
|
NewDiskSize::EnableButtons(this);
|
|
}
|
|
|
|
void ConvDiskOptionsDialog::LimitSizeControls(long totalBlocks, long blocksUsed)
|
|
{
|
|
LOGD("LimitSizeControls %ld %ld", totalBlocks, blocksUsed);
|
|
LOGD("Full volume requires %ld bitmap blocks",
|
|
NewDiskSize::GetNumBitmapBlocks_ProDOS(totalBlocks));
|
|
|
|
CWnd* pWnd;
|
|
long usedWithoutBitmap =
|
|
blocksUsed - NewDiskSize::GetNumBitmapBlocks_ProDOS(totalBlocks);
|
|
long sizeInK = usedWithoutBitmap / 2;
|
|
CString sizeStr, spaceReq;
|
|
sizeStr.Format(L"%dK", sizeInK);
|
|
spaceReq.Format(IDS_CONVDISK_SPACEREQ, sizeStr);
|
|
|
|
pWnd = GetDlgItem(IDC_CONVDISK_SPACEREQ);
|
|
ASSERT(pWnd != NULL);
|
|
pWnd->SetWindowText(spaceReq);
|
|
|
|
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;
|
|
|
|
CButton* pButton;
|
|
pButton = (CButton*) GetDlgItem(gDiskSizes[i].ctrlID);
|
|
ASSERT(pButton != NULL);
|
|
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
|
|
}
|
|
|
|
void ConvDiskOptionsDialog::OnCompute(void)
|
|
{
|
|
MainWindow* pMain = (MainWindow*)::AfxGetMainWnd();
|
|
const Preferences* pPreferences = GET_PREFERENCES();
|
|
|
|
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;
|
|
|
|
if (fFilesToAction == UseSelectionDialog::kActionSelection) {
|
|
selSet.CreateFromSelection(pMain->GetContentList(), threadMask);
|
|
} else {
|
|
selSet.CreateFromAll(pMain->GetContentList(), threadMask);
|
|
}
|
|
|
|
if (selSet.GetNumEntries() == 0) {
|
|
/* should be impossible */
|
|
MessageBox(L"No files matched the selection criteria.",
|
|
L"No match", MB_OK|MB_ICONEXCLAMATION);
|
|
return;
|
|
}
|
|
|
|
XferFileOptions xferOpts;
|
|
//xferOpts.fAllowLowerCase =
|
|
// pPreferences->GetPrefBool(kPrProDOSAllowLower) != 0;
|
|
//xferOpts.fUseSparseBlocks =
|
|
// pPreferences->GetPrefBool(kPrProDOSUseSparse) != 0;
|
|
|
|
LOGI("New volume name will be '%ls'", (LPCWSTR) fVolName);
|
|
|
|
/*
|
|
* Create a new disk image file.
|
|
*/
|
|
CString errStr;
|
|
WCHAR nameBuf[MAX_PATH];
|
|
UINT unique;
|
|
unique = GetTempFileName(pMain->GetPreferences()->GetPrefString(kPrTempPath),
|
|
L"CPdisk", 0, nameBuf);
|
|
if (unique == 0) {
|
|
DWORD dwerr = ::GetLastError();
|
|
errStr.Format(L"GetTempFileName failed on '%ls' (err=0x%08lx)\n",
|
|
pMain->GetPreferences()->GetPrefString(kPrTempPath), dwerr);
|
|
ShowFailureMsg(this, errStr, IDS_FAILED);
|
|
return;
|
|
}
|
|
LOGI(" Will xfer to file '%ls'", nameBuf);
|
|
// annoying -- DiskArchive insists on creating it
|
|
(void) _wunlink(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;
|
|
|
|
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;
|
|
|
|
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(NULL);
|
|
|
|
if (result == GenericArchive::kXferOK) {
|
|
DiskFS* pDiskFS;
|
|
long totalBlocks, freeBlocks;
|
|
int unitSize;
|
|
DIError dierr;
|
|
|
|
LOGI("SUCCESS");
|
|
|
|
pDiskFS = ((DiskArchive*) xferOpts.fTarget)->GetDiskFS();
|
|
ASSERT(pDiskFS != NULL);
|
|
|
|
dierr = pDiskFS->GetFreeSpaceCount(&totalBlocks, &freeBlocks,
|
|
&unitSize);
|
|
if (dierr != kDIErrNone) {
|
|
errStr.Format(L"Unable to get free space count: %hs.\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) {
|
|
LOGI("CANCEL - cancel button hit");
|
|
ResetSizeControls();
|
|
} else {
|
|
LOGI("FAILURE (result=%d)", result);
|
|
ResetSizeControls();
|
|
}
|
|
}
|
|
|
|
// debug
|
|
((DiskArchive*) (xferOpts.fTarget))->GetDiskFS()->DumpFileList();
|
|
|
|
/* clean up */
|
|
delete xferOpts.fTarget;
|
|
(void) _wunlink(nameBuf);
|
|
}
|