mirror of
https://github.com/fadden/ciderpress.git
synced 2024-11-26 17:49:21 +00:00
d42b9c6dc0
The static analyzer was annoyed that the return value from calls to CString::LoadString() was being ignored. This adds a wrapper function that checks the value and logs a failure message if the string can't be found.
1415 lines
40 KiB
C++
1415 lines
40 KiB
C++
/*
|
|
* CiderPress
|
|
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
|
|
* See the file LICENSE for distribution terms.
|
|
*/
|
|
/*
|
|
* Disk editor implementation.
|
|
*
|
|
* Note to self: it should be possible to open an image in "nibble" mode,
|
|
* switch to one of the various "sector" modes, and maybe even try out a
|
|
* "block" mode for a while. Locking the editor into one particular mode
|
|
* makes for a cumbersome interface when dealing with certain kinds of disks.
|
|
* It should also be possible to configure the "custom" NibbleDescr and then
|
|
* re-analyze the disk, possibly transferring the customization over to
|
|
* the main file listing. (Perhaps the customization affects a global slot?
|
|
* Probably want more than one set of custom nibble values, with the config
|
|
* dialog accessible from main menu and from within disk editor.)
|
|
*
|
|
* A track copier would be neat too.
|
|
*/
|
|
#include "stdafx.h"
|
|
#include "SubVolumeDialog.h"
|
|
#include "DEFileDialog.h"
|
|
#include "DiskEditDialog.h"
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* 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()
|
|
END_MESSAGE_MAP()
|
|
|
|
BOOL DiskEditDialog::OnInitDialog(void)
|
|
{
|
|
ASSERT(!fFileName.IsEmpty());
|
|
ASSERT(fpDiskFS != NULL);
|
|
|
|
/*
|
|
* Disable the write button.
|
|
*/
|
|
if (fReadOnly) {
|
|
CButton* pButton = (CButton*) GetDlgItem(IDC_DISKEDIT_DOWRITE);
|
|
ASSERT(pButton != NULL);
|
|
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);
|
|
|
|
|
|
|
|
/*
|
|
* Configure the RichEdit control.
|
|
*/
|
|
CRichEditCtrl* pEdit = (CRichEditCtrl*) GetDlgItem(IDC_DISKEDIT_EDIT);
|
|
ASSERT(pEdit != NULL);
|
|
|
|
/* set the font to 10-point Courier New */
|
|
CHARFORMAT cf;
|
|
cf.cbSize = sizeof(CHARFORMAT);
|
|
cf.dwMask = CFM_FACE | CFM_SIZE;
|
|
wcscpy(cf.szFaceName, L"Courier New");
|
|
cf.yHeight = 10 * 20; // point size in twips
|
|
BOOL cc = pEdit->SetDefaultCharFormat(cf);
|
|
if (cc == FALSE) {
|
|
LOGI("SetDefaultCharFormat failed?");
|
|
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);
|
|
|
|
/*
|
|
* Disable the sub-volume and/or file open buttons if the DiskFS doesn't
|
|
* have the appropriate stuff inside.
|
|
*/
|
|
if (fpDiskFS->GetNextFile(NULL) == NULL) {
|
|
CWnd* pWnd = GetDlgItem(IDC_DISKEDIT_OPENFILE);
|
|
pWnd->EnableWindow(FALSE);
|
|
}
|
|
if (fpDiskFS->GetNextSubVolume(NULL) == NULL) {
|
|
CWnd* pWnd = GetDlgItem(IDC_DISKEDIT_SUBVOLUME);
|
|
pWnd->EnableWindow(FALSE);
|
|
}
|
|
|
|
/*
|
|
* 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);
|
|
}
|
|
|
|
/*
|
|
* Set the window title.
|
|
*/
|
|
CString title("Disk Viewer - ");
|
|
title += fFileName;
|
|
if (fpDiskFS->GetVolumeID() != NULL) {
|
|
title += " (";
|
|
title += fpDiskFS->GetVolumeID();
|
|
title += ")";
|
|
}
|
|
SetWindowText(title);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void DiskEditDialog::InitNibbleParmList(void)
|
|
{
|
|
ASSERT(fpDiskFS != NULL);
|
|
DiskImg* pDiskImg = fpDiskFS->GetDiskImg();
|
|
CComboBox* pCombo;
|
|
|
|
pCombo = (CComboBox*) GetDlgItem(IDC_DISKEDIT_NIBBLE_PARMS);
|
|
ASSERT(pCombo != NULL);
|
|
|
|
if (pDiskImg->GetHasNibbles()) {
|
|
const DiskImg::NibbleDescr* pTable;
|
|
const DiskImg::NibbleDescr* pCurrent;
|
|
int i, count;
|
|
|
|
pTable = pDiskImg->GetNibbleDescrTable(&count);
|
|
if (pTable == NULL || count <= 0) {
|
|
LOGI("WHOOPS: nibble parm got table=0x%08lx, count=%d",
|
|
(long) pTable, count);
|
|
return;
|
|
}
|
|
pCurrent = pDiskImg->GetNibbleDescr();
|
|
|
|
/* configure the selection to match the disk analysis */
|
|
int dflt = -1;
|
|
if (pCurrent != NULL) {
|
|
for (i = 0; i < count; i++) {
|
|
if (memcmp(&pTable[i], pCurrent, sizeof(*pCurrent)) == 0) {
|
|
LOGI(" NibbleParm match on entry %d", i);
|
|
dflt = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dflt == -1) {
|
|
LOGI(" GLITCH: no match on nibble descr in table?!");
|
|
dflt = 0;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < count; i++) {
|
|
if (pTable[i].numSectors > 0) {
|
|
CString description(pTable[i].description);
|
|
pCombo->AddString(description);
|
|
} else {
|
|
/* only expecting this on the last, "custom" entry */
|
|
ASSERT(i == count-1);
|
|
}
|
|
}
|
|
pCombo->SetCurSel(dflt);
|
|
} else {
|
|
pCombo->AddString(L"Nibble Parms");
|
|
pCombo->SetCurSel(0);
|
|
pCombo->EnableWindow(FALSE);
|
|
}
|
|
}
|
|
|
|
int DiskEditDialog::ReplaceSpinCtrl(MySpinCtrl* pNewSpin, int idSpin, int idEdit)
|
|
{
|
|
CSpinButtonCtrl* pSpin;
|
|
// CRect rect;
|
|
DWORD style;
|
|
|
|
pSpin = (CSpinButtonCtrl*)GetDlgItem(idSpin);
|
|
if (pSpin == NULL)
|
|
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;
|
|
}
|
|
|
|
BOOL DiskEditDialog::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
if (pMsg->message == WM_KEYDOWN &&
|
|
pMsg->wParam == VK_RETURN)
|
|
{
|
|
//LOGI("RETURN!");
|
|
LoadData();
|
|
return TRUE;
|
|
}
|
|
|
|
return CDialog::PreTranslateMessage(pMsg);
|
|
}
|
|
|
|
void DiskEditDialog::OnDone(void)
|
|
{
|
|
LOGI("DiskEditDialog OnDone");
|
|
EndDialog(IDOK);
|
|
}
|
|
|
|
void DiskEditDialog::OnHexMode(void)
|
|
{
|
|
int base;
|
|
|
|
CButton* pButton = (CButton*) GetDlgItem(IDC_DISKEDIT_HEX);
|
|
ASSERT(pButton != NULL);
|
|
|
|
if (pButton->GetCheck() == 0)
|
|
base = 10;
|
|
else
|
|
base = 16;
|
|
|
|
SetSpinMode(IDC_DISKEDIT_TRACKSPIN, base);
|
|
SetSpinMode(IDC_DISKEDIT_SECTORSPIN, base);
|
|
}
|
|
|
|
void DiskEditDialog::OnSubVolume(void)
|
|
{
|
|
SubVolumeDialog subv(this);
|
|
bool showAsBlocks;
|
|
|
|
subv.Setup(fpDiskFS);
|
|
if (subv.DoModal() == IDOK) {
|
|
LOGI("SELECTED subv %d", subv.fListBoxIndex);
|
|
DiskFS::SubVolume* pSubVol = fpDiskFS->GetNextSubVolume(NULL);
|
|
if (pSubVol == NULL)
|
|
return;
|
|
|
|
while (subv.fListBoxIndex-- > 0) {
|
|
pSubVol = fpDiskFS->GetNextSubVolume(pSubVol);
|
|
}
|
|
ASSERT(pSubVol != NULL);
|
|
|
|
BlockEditDialog blockEdit;
|
|
SectorEditDialog sectorEdit;
|
|
DiskEditDialog* pEditDialog;
|
|
|
|
showAsBlocks = pSubVol->GetDiskImg()->ShowAsBlocks();
|
|
if (showAsBlocks)
|
|
pEditDialog = &blockEdit;
|
|
else
|
|
pEditDialog = §orEdit;
|
|
CString volumeID(fpDiskFS->GetVolumeID());
|
|
pEditDialog->Setup(pSubVol->GetDiskFS(), volumeID);
|
|
pEditDialog->SetPositionShift(8);
|
|
(void) pEditDialog->DoModal();
|
|
}
|
|
}
|
|
|
|
void DiskEditDialog::SetSpinMode(int id, int base)
|
|
{
|
|
CString valStr;
|
|
|
|
ASSERT(base == 10 || base == 16);
|
|
|
|
MySpinCtrl* pSpin = (MySpinCtrl*) GetDlgItem(id);
|
|
if (pSpin == NULL) {
|
|
// expected behavior in "block" mode for sector button
|
|
LOGI("Couldn't find spin button %d", id);
|
|
return;
|
|
}
|
|
|
|
long val = pSpin->GetPos();
|
|
if (val & 0xff000000) {
|
|
LOGI("NOTE: hex transition while value is invalid");
|
|
val = 0;
|
|
}
|
|
|
|
if (base == 10)
|
|
valStr.Format(L"%d", val);
|
|
else
|
|
valStr.Format(L"%X", val);
|
|
|
|
pSpin->SetBase(base);
|
|
pSpin->GetBuddy()->SetWindowText(valStr);
|
|
LOGI("Set spin button base to %d val=%d", base, val);
|
|
}
|
|
|
|
int DiskEditDialog::ReadSpinner(int id, long* pVal)
|
|
{
|
|
MySpinCtrl* pSpin = (MySpinCtrl*) GetDlgItem(id);
|
|
ASSERT(pSpin != NULL);
|
|
|
|
long val = pSpin->GetPos();
|
|
if (val & 0xff000000) {
|
|
/* error */
|
|
CString msg, err;
|
|
|
|
CheckedLoadString(&err, IDS_ERROR);
|
|
int lower, upper;
|
|
pSpin->GetRange32(lower, upper);
|
|
msg.Format(L"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;
|
|
}
|
|
|
|
void DiskEditDialog::SetSpinner(int id, long val)
|
|
{
|
|
MySpinCtrl* pSpin = (MySpinCtrl*) GetDlgItem(id);
|
|
ASSERT(pSpin != NULL);
|
|
|
|
/* sanity check */
|
|
int lower, upper;
|
|
pSpin->GetRange32(lower, upper);
|
|
ASSERT(val >= lower && val <= upper);
|
|
|
|
pSpin->SetPos(val);
|
|
}
|
|
|
|
void DiskEditDialog::DisplayData(const uint8_t* srcBuf, int size)
|
|
{
|
|
WCHAR textBuf[80 * 16 * 2];
|
|
WCHAR* cp;
|
|
int i, j;
|
|
|
|
ASSERT(srcBuf != NULL);
|
|
ASSERT(size == kSectorSize || size == kBlockSize);
|
|
|
|
CRichEditCtrl* pEdit = (CRichEditCtrl*)GetDlgItem(IDC_DISKEDIT_EDIT);
|
|
ASSERT(pEdit != NULL);
|
|
|
|
/*
|
|
* 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 = L" "
|
|
L" ";
|
|
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';
|
|
}
|
|
wcscpy(&textBuf[i], msg);
|
|
pEdit->SetWindowText(textBuf);
|
|
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* No alert, do the usual thing.
|
|
*/
|
|
cp = textBuf;
|
|
for (i = 0; i < size/16; i++) {
|
|
if (size == kSectorSize) {
|
|
/* two-nybble addr */
|
|
wsprintf(cp, L" %02x: %02x %02x %02x %02x %02x %02x %02x %02x "
|
|
L"%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 */
|
|
wsprintf(cp, L"%03x: %02x %02x %02x %02x %02x %02x %02x %02x "
|
|
L"%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(wcslen(cp) == 54);
|
|
cp += 54; // strlen(cp)
|
|
for (j = 0; j < 16; j++)
|
|
*cp++ = PrintableChar(srcBuf[j]);
|
|
|
|
*cp++ = '\r';
|
|
*cp++ = '\n';
|
|
|
|
srcBuf += 16;
|
|
}
|
|
/* kill the last EOL, so the cursor doesn't move past that line */
|
|
cp--;
|
|
*cp = '\0';
|
|
|
|
pEdit->SetWindowText(textBuf);
|
|
}
|
|
|
|
void DiskEditDialog::DisplayNibbleData(const unsigned char* srcBuf, int size)
|
|
{
|
|
ASSERT(srcBuf != NULL);
|
|
ASSERT(size > 0);
|
|
ASSERT(fAlertMsg.IsEmpty());
|
|
|
|
int bufSize = ((size+15) / 16) * 80;
|
|
WCHAR* textBuf = new WCHAR[bufSize];
|
|
WCHAR* cp;
|
|
int i;
|
|
|
|
if (textBuf == NULL)
|
|
return;
|
|
|
|
cp = textBuf;
|
|
for (i = 0; size > 0; i++) {
|
|
if (size >= 16) {
|
|
wsprintf(cp, L"%04x: %02x %02x %02x %02x %02x %02x %02x %02x "
|
|
L"%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(wcslen(cp) == 53);
|
|
cp += 53; // strlen(cp)
|
|
} else {
|
|
wsprintf(cp, L"%04x:", i * 16);
|
|
cp += 5;
|
|
for (int j = 0; j < size; j++) {
|
|
wsprintf(cp, L" %02x", srcBuf[j]);
|
|
cp += 3;
|
|
}
|
|
}
|
|
|
|
*cp++ = '\r';
|
|
*cp++ = '\n';
|
|
|
|
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 != NULL);
|
|
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;
|
|
|
|
const int kStretchHeight = 249;
|
|
CRect 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);
|
|
}
|
|
|
|
delete[] textBuf;
|
|
}
|
|
|
|
DIError DiskEditDialog::OpenFile(const WCHAR* fileName, bool openRsrc,
|
|
A2File** ppFile, A2FileDescr** ppOpenFile)
|
|
{
|
|
A2File* pFile;
|
|
A2FileDescr* pOpenFile = NULL;
|
|
|
|
LOGI(" OpenFile '%ls' rsrc=%d", fileName, openRsrc);
|
|
CStringA fileNameA(fileName);
|
|
pFile = fpDiskFS->GetFileByName(fileNameA);
|
|
if (pFile == NULL) {
|
|
CString msg, failed;
|
|
|
|
msg.Format(IDS_DEFILE_FIND_FAILED, fileName);
|
|
CheckedLoadString(&failed, 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;
|
|
|
|
msg.Format(IDS_DEFILE_OPEN_FAILED, fileName,
|
|
DiskImgLib::DIStrError(dierr));
|
|
CheckedLoadString(&failed, IDS_FAILED);
|
|
MessageBox(msg, failed, MB_OK | MB_ICONSTOP);
|
|
return dierr;
|
|
}
|
|
|
|
*ppFile = pFile;
|
|
*ppOpenFile = pOpenFile;
|
|
|
|
return kDIErrNone;
|
|
}
|
|
|
|
void DiskEditDialog::OnNibbleParms(void)
|
|
{
|
|
DiskImg* pDiskImg = fpDiskFS->GetDiskImg();
|
|
CComboBox* pCombo;
|
|
int sel;
|
|
|
|
ASSERT(pDiskImg != NULL);
|
|
ASSERT(pDiskImg->GetHasNibbles());
|
|
|
|
pCombo = (CComboBox*) GetDlgItem(IDC_DISKEDIT_NIBBLE_PARMS);
|
|
ASSERT(pCombo != NULL);
|
|
|
|
sel = pCombo->GetCurSel();
|
|
if (sel == CB_ERR)
|
|
return;
|
|
|
|
LOGI(" OnNibbleParms: entry %d now selected", sel);
|
|
const DiskImg::NibbleDescr* pNibbleTable;
|
|
int count;
|
|
pNibbleTable = pDiskImg->GetNibbleDescrTable(&count);
|
|
ASSERT(sel < count);
|
|
pDiskImg->SetNibbleDescr(sel);
|
|
|
|
LoadData();
|
|
}
|
|
|
|
|
|
#if 0
|
|
/*
|
|
* Make a "sparse" block in a file obvious by filling it with the word
|
|
* "sparse".
|
|
*/
|
|
void
|
|
DiskEditDialog::FillWithPattern(unsigned char* buf, int size,
|
|
const char* pattern)
|
|
{
|
|
const char* cp;
|
|
unsigned char* ucp;
|
|
|
|
ucp = buf;
|
|
cp = pattern;
|
|
while (ucp < buf+size) {
|
|
*ucp++ = *cp++;
|
|
if (*cp == '\0')
|
|
cp = pattern;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* SectorEditDialog
|
|
* ===========================================================================
|
|
*/
|
|
|
|
BOOL SectorEditDialog::OnInitDialog(void)
|
|
{
|
|
/*
|
|
* Do base-class construction.
|
|
*/
|
|
DiskEditDialog::OnInitDialog();
|
|
|
|
/*
|
|
* Change track/sector text.
|
|
*/
|
|
CString trackStr;
|
|
CWnd* pWnd;
|
|
trackStr.Format(L"Track (%d):", fpDiskFS->GetDiskImg()->GetNumTracks());
|
|
pWnd = GetDlgItem(IDC_STEXT_TRACK);
|
|
ASSERT(pWnd != NULL);
|
|
pWnd->SetWindowText(trackStr);
|
|
trackStr.Format(L"Sector (%d):", fpDiskFS->GetDiskImg()->GetNumSectPerTrack());
|
|
pWnd = GetDlgItem(IDC_STEXT_SECTOR);
|
|
ASSERT(pWnd != NULL);
|
|
pWnd->SetWindowText(trackStr);
|
|
|
|
/*
|
|
* Configure the spin buttons.
|
|
*/
|
|
MySpinCtrl* pSpin;
|
|
pSpin = (MySpinCtrl*)GetDlgItem(IDC_DISKEDIT_TRACKSPIN);
|
|
ASSERT(pSpin != NULL);
|
|
pSpin->SetRange32(0, fpDiskFS->GetDiskImg()->GetNumTracks()-1);
|
|
pSpin->SetPos(0);
|
|
pSpin = (MySpinCtrl*)GetDlgItem(IDC_DISKEDIT_SECTORSPIN);
|
|
ASSERT(pSpin != NULL);
|
|
pSpin->SetRange32(0, fpDiskFS->GetDiskImg()->GetNumSectPerTrack()-1);
|
|
pSpin->SetPos(0);
|
|
|
|
/* give us something to look at */
|
|
LoadData();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int SectorEditDialog::LoadData(void)
|
|
{
|
|
//LOGI("SED LoadData");
|
|
ASSERT(fpDiskFS != NULL);
|
|
ASSERT(fpDiskFS->GetDiskImg() != NULL);
|
|
|
|
if (ReadSpinner(IDC_DISKEDIT_TRACKSPIN, &fTrack) != 0)
|
|
return -1;
|
|
if (ReadSpinner(IDC_DISKEDIT_SECTORSPIN, &fSector) != 0)
|
|
return -1;
|
|
|
|
LOGI("LoadData reading t=%d s=%d", fTrack, fSector);
|
|
|
|
fAlertMsg = "";
|
|
DIError dierr;
|
|
dierr = fpDiskFS->GetDiskImg()->ReadTrackSector(fTrack, fSector, fSectorData);
|
|
if (dierr != kDIErrNone) {
|
|
LOGI("SED sector read failed: %hs", 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);
|
|
CheckedLoadString(&fAlertMsg, IDS_DISKEDITMSG_BADSECTOR);
|
|
//return -1;
|
|
}
|
|
|
|
DisplayData();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void SectorEditDialog::OnDoRead(void)
|
|
{
|
|
LoadData();
|
|
}
|
|
|
|
void SectorEditDialog::OnDoWrite(void)
|
|
{
|
|
MessageBox(L"Write!");
|
|
}
|
|
|
|
void SectorEditDialog::OnReadPrev(void)
|
|
{
|
|
if (fTrack == 0 && fSector == 0)
|
|
return;
|
|
|
|
if (fSector == 0) {
|
|
fSector = fpDiskFS->GetDiskImg()->GetNumSectPerTrack() -1;
|
|
fTrack--;
|
|
} else {
|
|
fSector--;
|
|
}
|
|
|
|
SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack);
|
|
SetSpinner(IDC_DISKEDIT_SECTORSPIN, fSector);
|
|
|
|
LoadData();
|
|
}
|
|
|
|
void SectorEditDialog::OnReadNext(void)
|
|
{
|
|
int numTracks = fpDiskFS->GetDiskImg()->GetNumTracks();
|
|
int numSects = fpDiskFS->GetDiskImg()->GetNumSectPerTrack();
|
|
|
|
if (fTrack == numTracks-1 && fSector == numSects-1)
|
|
return;
|
|
|
|
if (fSector == numSects-1) {
|
|
fSector = 0;
|
|
fTrack++;
|
|
} else {
|
|
fSector++;
|
|
}
|
|
|
|
SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack);
|
|
SetSpinner(IDC_DISKEDIT_SECTORSPIN, fSector);
|
|
|
|
LoadData();
|
|
}
|
|
|
|
void SectorEditDialog::OnOpenFile(void)
|
|
{
|
|
DEFileDialog fileDialog(this);
|
|
|
|
if (fileDialog.DoModal() == IDOK) {
|
|
SectorFileEditDialog fileEdit(this, this);
|
|
A2File* pFile;
|
|
A2FileDescr* pOpenFile = NULL;
|
|
DIError dierr;
|
|
|
|
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();
|
|
|
|
pOpenFile->Close();
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* SectorFileEditDialog
|
|
* ===========================================================================
|
|
*/
|
|
|
|
BOOL SectorFileEditDialog::OnInitDialog(void)
|
|
{
|
|
BOOL retval;
|
|
|
|
/* do base class first */
|
|
retval = SectorEditDialog::OnInitDialog();
|
|
|
|
/* disable direct entry of tracks and sectors */
|
|
CWnd* pWnd;
|
|
pWnd = GetDlgItem(IDC_DISKEDIT_TRACKSPIN);
|
|
ASSERT(pWnd != NULL);
|
|
pWnd->EnableWindow(FALSE);
|
|
pWnd = GetDlgItem(IDC_DISKEDIT_SECTORSPIN);
|
|
ASSERT(pWnd != NULL);
|
|
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 != NULL);
|
|
pEdit->SetReadOnly(TRUE);
|
|
pEdit = (CEdit*) GetDlgItem(IDC_DISKEDIT_SECTOR);
|
|
ASSERT(pEdit != NULL);
|
|
pEdit->SetReadOnly(TRUE);
|
|
|
|
/* set the window title */
|
|
CString title;
|
|
CString rsrcIndic;
|
|
CheckedLoadString(&rsrcIndic, IDS_INDIC_RSRC);
|
|
title.Format(L"Disk Viewer - %hs%ls (%I64d bytes)",
|
|
(LPCSTR) fpFile->GetPathName(), // use fpFile version to get case
|
|
fOpenRsrcFork ? (LPCWSTR)rsrcIndic : L"", (LONGLONG) fLength);
|
|
SetWindowText(title);
|
|
|
|
return retval;
|
|
}
|
|
|
|
int SectorFileEditDialog::LoadData(void)
|
|
{
|
|
ASSERT(fpDiskFS != NULL);
|
|
ASSERT(fpDiskFS->GetDiskImg() != NULL);
|
|
|
|
DIError dierr;
|
|
LOGI("SFED LoadData reading index=%d", fSectorIdx);
|
|
|
|
#if 0
|
|
LOGI("LoadData reading offset=%d", 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) {
|
|
LOGI(" SFED partial read of %d bytes", 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)
|
|
|
|
;
|
|
#endif
|
|
|
|
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 "));
|
|
CheckedLoadString(&fAlertMsg, IDS_DISKEDITMSG_EMPTY);
|
|
} else if (dierr != kDIErrNone) {
|
|
CString msg, failed;
|
|
CheckedLoadString(&failed, IDS_FAILED);
|
|
msg.Format(IDS_DISKEDIT_FIRDFAILED, DiskImgLib::DIStrError(dierr));
|
|
MessageBox(msg, failed, MB_OK);
|
|
CheckedLoadString(&fAlertMsg, IDS_FAILED);
|
|
// TO DO: mark contents as invalid, so editing fails
|
|
return -1;
|
|
} else {
|
|
if (fTrack == 0 && fSector == 0) {
|
|
LOGI("LoadData Sparse sector");
|
|
//FillWithPattern(fSectorData, sizeof(fSectorData), _T("SPARSE "));
|
|
fAlertMsg.Format(IDS_DISKEDITMSG_SPARSE, fSectorIdx);
|
|
} else {
|
|
LOGI("LoadData reading T=%d S=%d", 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);
|
|
CheckedLoadString(&fAlertMsg, IDS_DISKEDITMSG_BADSECTOR);
|
|
//return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack);
|
|
SetSpinner(IDC_DISKEDIT_SECTORSPIN, fSector);
|
|
|
|
CWnd* pWnd;
|
|
pWnd = GetDlgItem(IDC_DISKEDIT_PREV);
|
|
ASSERT(pWnd != NULL);
|
|
pWnd->EnableWindow(fSectorIdx > 0);
|
|
if (!pWnd->IsWindowEnabled() && GetFocus() == NULL)
|
|
GetDlgItem(IDC_DISKEDIT_NEXT)->SetFocus();
|
|
|
|
pWnd = GetDlgItem(IDC_DISKEDIT_NEXT);
|
|
ASSERT(pWnd != NULL);
|
|
pWnd->EnableWindow(fSectorIdx+1 < fpOpenFile->GetSectorCount());
|
|
if (!pWnd->IsWindowEnabled() && GetFocus() == NULL)
|
|
GetDlgItem(IDC_DISKEDIT_PREV)->SetFocus();
|
|
|
|
DisplayData();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void SectorFileEditDialog::OnReadPrev(void)
|
|
{
|
|
if (fSectorIdx == 0)
|
|
return;
|
|
|
|
fSectorIdx--;
|
|
ASSERT(fSectorIdx >= 0);
|
|
LoadData();
|
|
}
|
|
|
|
void SectorFileEditDialog::OnReadNext(void)
|
|
{
|
|
if (fSectorIdx+1 >= fpOpenFile->GetSectorCount())
|
|
return;
|
|
|
|
fSectorIdx++;
|
|
ASSERT(fSectorIdx < fpOpenFile->GetSectorCount());
|
|
LoadData();
|
|
}
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* BlockEditDialog
|
|
* ===========================================================================
|
|
*/
|
|
|
|
/*
|
|
* Rearrange the DiskEdit dialog (which defaults to SectorEdit mode) to
|
|
* accommodate block editing.
|
|
*/
|
|
BOOL BlockEditDialog::OnInitDialog(void)
|
|
{
|
|
/*
|
|
* 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();
|
|
|
|
CString blockStr;
|
|
//blockStr.LoadString(IDS_BLOCK);
|
|
blockStr.Format(L"Block (%d):", fpDiskFS->GetDiskImg()->GetNumBlocks());
|
|
pWnd = GetDlgItem(IDC_STEXT_TRACK);
|
|
ASSERT(pWnd != NULL);
|
|
pWnd->SetWindowText(blockStr);
|
|
|
|
/*
|
|
* 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);
|
|
|
|
CRichEditCtrl* pEdit = (CRichEditCtrl*)GetDlgItem(IDC_DISKEDIT_EDIT);
|
|
ASSERT(pEdit != NULL);
|
|
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);
|
|
|
|
/*
|
|
* 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 != NULL);
|
|
pSpin->SetRange32(0, fpDiskFS->GetDiskImg()->GetNumBlocks()-1);
|
|
pSpin->SetPos(0);
|
|
|
|
/* give us something to look at */
|
|
if (LoadData() != 0) {
|
|
LOGI("WHOOPS: LoadData() failed, but we're in OnInitDialog");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
#if 0
|
|
/*
|
|
* Move a control so it maintains its same position relative to the bottom
|
|
* and right edges.
|
|
*/
|
|
void
|
|
BlockEditDialog::MoveControl(int id, int deltaX, int deltaY)
|
|
{
|
|
CWnd* pWnd;
|
|
CRect rect;
|
|
|
|
pWnd = GetDlgItem(id);
|
|
ASSERT(pWnd != NULL);
|
|
|
|
pWnd->GetWindowRect(&rect);
|
|
ScreenToClient(&rect);
|
|
rect.left += deltaX;
|
|
rect.right += deltaX;
|
|
rect.top += deltaY;
|
|
rect.bottom += deltaY;
|
|
pWnd->MoveWindow(&rect, TRUE);
|
|
}
|
|
#endif
|
|
|
|
|
|
int BlockEditDialog::LoadData(void)
|
|
{
|
|
//LOGI("BED LoadData");
|
|
ASSERT(fpDiskFS != NULL);
|
|
ASSERT(fpDiskFS->GetDiskImg() != NULL);
|
|
|
|
if (ReadSpinner(IDC_DISKEDIT_TRACKSPIN, &fBlock) != 0)
|
|
return -1;
|
|
|
|
LOGI("LoadData reading block=%d", fBlock);
|
|
|
|
fAlertMsg = "";
|
|
DIError dierr;
|
|
dierr = fpDiskFS->GetDiskImg()->ReadBlock(fBlock, fBlockData);
|
|
if (dierr != kDIErrNone) {
|
|
LOGI("BED block read failed: %hs", DiskImgLib::DIStrError(dierr));
|
|
//CString msg;
|
|
//CString err;
|
|
//err.LoadString(IDS_ERROR);
|
|
//msg.Format(IDS_DISKEDIT_NOREADBLOCK, fBlock);
|
|
//MessageBox(msg, err, MB_OK|MB_ICONSTOP);
|
|
CheckedLoadString(&fAlertMsg, IDS_DISKEDITMSG_BADBLOCK);
|
|
//return -1;
|
|
}
|
|
|
|
DisplayData();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void BlockEditDialog::OnDoRead(void)
|
|
{
|
|
LoadData();
|
|
}
|
|
|
|
void BlockEditDialog::OnDoWrite(void)
|
|
{
|
|
MessageBox(L"Write!");
|
|
}
|
|
|
|
void BlockEditDialog::OnReadPrev(void)
|
|
{
|
|
if (fBlock == 0)
|
|
return;
|
|
|
|
fBlock--;
|
|
SetSpinner(IDC_DISKEDIT_TRACKSPIN, fBlock);
|
|
LoadData();
|
|
}
|
|
|
|
void
|
|
BlockEditDialog::OnReadNext(void)
|
|
{
|
|
ASSERT(fpDiskFS != NULL);
|
|
if (fBlock == fpDiskFS->GetDiskImg()->GetNumBlocks() - 1)
|
|
return;
|
|
|
|
fBlock++;
|
|
SetSpinner(IDC_DISKEDIT_TRACKSPIN, fBlock);
|
|
LoadData();
|
|
}
|
|
|
|
void BlockEditDialog::OnOpenFile(void)
|
|
{
|
|
DEFileDialog fileDialog(this);
|
|
|
|
if (fileDialog.DoModal() == IDOK) {
|
|
BlockFileEditDialog fileEdit(this, this);
|
|
A2File* pFile;
|
|
A2FileDescr* pOpenFile = NULL;
|
|
DIError dierr;
|
|
|
|
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();
|
|
|
|
pOpenFile->Close();
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* BlockFileEditDialog
|
|
* ===========================================================================
|
|
*/
|
|
|
|
BOOL BlockFileEditDialog::OnInitDialog(void)
|
|
{
|
|
BOOL retval;
|
|
|
|
/* do base class first */
|
|
retval = BlockEditDialog::OnInitDialog();
|
|
|
|
/* disable direct entry of tracks and Blocks */
|
|
CWnd* pWnd;
|
|
pWnd = GetDlgItem(IDC_DISKEDIT_TRACKSPIN);
|
|
ASSERT(pWnd != NULL);
|
|
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 != NULL);
|
|
pEdit->SetReadOnly(TRUE);
|
|
|
|
/* set the window title */
|
|
CString title;
|
|
CString rsrcIndic;
|
|
CheckedLoadString(&rsrcIndic, IDS_INDIC_RSRC);
|
|
title.Format(L"Disk Viewer - %hs%ls (%I64d bytes)",
|
|
(LPCSTR) fpFile->GetPathName(), // use fpFile version to get case
|
|
fOpenRsrcFork ? (LPCWSTR)rsrcIndic : L"", (LONGLONG) fLength);
|
|
SetWindowText(title);
|
|
|
|
return retval;
|
|
}
|
|
|
|
int BlockFileEditDialog::LoadData(void)
|
|
{
|
|
ASSERT(fpDiskFS != NULL);
|
|
ASSERT(fpDiskFS->GetDiskImg() != NULL);
|
|
|
|
DIError dierr;
|
|
LOGI("BFED LoadData reading index=%d", fBlockIdx);
|
|
|
|
#if 0
|
|
LOGI("LoadData reading offset=%d", 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) {
|
|
LOGI(" BFED partial read of %d bytes", 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)
|
|
;
|
|
#endif
|
|
|
|
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 "));
|
|
CheckedLoadString(&fAlertMsg, IDS_DISKEDITMSG_EMPTY);
|
|
} else if (dierr != kDIErrNone) {
|
|
CString msg, failed;
|
|
CheckedLoadString(&failed, IDS_FAILED);
|
|
msg.Format(IDS_DISKEDIT_FIRDFAILED, DiskImgLib::DIStrError(dierr));
|
|
MessageBox(msg, failed, MB_OK);
|
|
CheckedLoadString(&fAlertMsg, IDS_FAILED);
|
|
// TO DO: mark contents as invalid, so editing fails
|
|
return -1;
|
|
} else {
|
|
if (fBlock == 0) {
|
|
LOGI("LoadData Sparse block");
|
|
//FillWithPattern(fBlockData, sizeof(fBlockData), _T("SPARSE "));
|
|
fAlertMsg.Format(IDS_DISKEDITMSG_SPARSE, fBlockIdx);
|
|
} else {
|
|
LOGI("LoadData reading B=%d", 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);
|
|
CheckedLoadString(&fAlertMsg, IDS_DISKEDITMSG_BADBLOCK);
|
|
//return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
SetSpinner(IDC_DISKEDIT_TRACKSPIN, fBlock);
|
|
|
|
CWnd* pWnd;
|
|
pWnd = GetDlgItem(IDC_DISKEDIT_PREV);
|
|
ASSERT(pWnd != NULL);
|
|
pWnd->EnableWindow(fBlockIdx > 0);
|
|
if (!pWnd->IsWindowEnabled() && GetFocus() == NULL)
|
|
GetDlgItem(IDC_DISKEDIT_NEXT)->SetFocus();
|
|
|
|
pWnd = GetDlgItem(IDC_DISKEDIT_NEXT);
|
|
ASSERT(pWnd != NULL);
|
|
pWnd->EnableWindow(fBlockIdx+1 < fpOpenFile->GetBlockCount());
|
|
if (!pWnd->IsWindowEnabled() && GetFocus() == NULL)
|
|
GetDlgItem(IDC_DISKEDIT_PREV)->SetFocus();
|
|
|
|
DisplayData();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void BlockFileEditDialog::OnReadPrev(void)
|
|
{
|
|
if (fBlockIdx == 0)
|
|
return;
|
|
|
|
fBlockIdx--;
|
|
ASSERT(fBlockIdx >= 0);
|
|
LoadData();
|
|
}
|
|
|
|
void BlockFileEditDialog::OnReadNext(void)
|
|
{
|
|
if (fBlockIdx+1 >= fpOpenFile->GetBlockCount())
|
|
return;
|
|
|
|
fBlockIdx++;
|
|
ASSERT(fBlockIdx < fpOpenFile->GetBlockCount());
|
|
LoadData();
|
|
}
|
|
|
|
|
|
/*
|
|
* ===========================================================================
|
|
* NibbleEditDialog
|
|
* ===========================================================================
|
|
*/
|
|
|
|
BOOL NibbleEditDialog::OnInitDialog(void)
|
|
{
|
|
/*
|
|
* 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();
|
|
|
|
CString trackStr;
|
|
trackStr.Format(L"Track (%d):", fpDiskFS->GetDiskImg()->GetNumTracks());
|
|
pWnd = GetDlgItem(IDC_STEXT_TRACK);
|
|
ASSERT(pWnd != NULL);
|
|
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 != NULL);
|
|
const int kStretchHeight = 249;
|
|
CRect 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.
|
|
*/
|
|
#if 0
|
|
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);
|
|
|
|
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);
|
|
|
|
/*
|
|
* 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);
|
|
|
|
/*
|
|
* Configure the track spin button.
|
|
*/
|
|
MySpinCtrl* pSpin;
|
|
pSpin = (MySpinCtrl*)GetDlgItem(IDC_DISKEDIT_TRACKSPIN);
|
|
ASSERT(pSpin != NULL);
|
|
pSpin->SetRange32(0, fpDiskFS->GetDiskImg()->GetNumTracks()-1);
|
|
pSpin->SetPos(0);
|
|
|
|
/* give us something to look at */
|
|
LoadData();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int NibbleEditDialog::LoadData(void)
|
|
{
|
|
//LOGI("BED LoadData");
|
|
ASSERT(fpDiskFS != NULL);
|
|
ASSERT(fpDiskFS->GetDiskImg() != NULL);
|
|
|
|
if (ReadSpinner(IDC_DISKEDIT_TRACKSPIN, &fTrack) != 0)
|
|
return -1;
|
|
|
|
LOGI("LoadData reading track=%d", fTrack);
|
|
|
|
fAlertMsg = "";
|
|
DIError dierr;
|
|
dierr = fpDiskFS->GetDiskImg()->ReadNibbleTrack(fTrack, fNibbleData,
|
|
&fNibbleDataLen);
|
|
if (dierr != kDIErrNone) {
|
|
LOGI("NED track read failed: %hs", DiskImgLib::DIStrError(dierr));
|
|
CheckedLoadString(&fAlertMsg, IDS_DISKEDITMSG_BADTRACK);
|
|
}
|
|
|
|
DisplayData();
|
|
|
|
return 0;
|
|
}
|
|
|
|
void NibbleEditDialog::OnDoRead(void)
|
|
{
|
|
LoadData();
|
|
}
|
|
|
|
void NibbleEditDialog::OnDoWrite(void)
|
|
{
|
|
MessageBox(L"Write!");
|
|
}
|
|
|
|
void NibbleEditDialog::OnReadPrev(void)
|
|
{
|
|
if (fTrack == 0)
|
|
return;
|
|
|
|
fTrack--;
|
|
SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack);
|
|
LoadData();
|
|
}
|
|
|
|
void NibbleEditDialog::OnReadNext(void)
|
|
{
|
|
ASSERT(fpDiskFS != NULL);
|
|
if (fTrack == fpDiskFS->GetDiskImg()->GetNumTracks() - 1)
|
|
return;
|
|
|
|
fTrack++;
|
|
SetSpinner(IDC_DISKEDIT_TRACKSPIN, fTrack);
|
|
LoadData();
|
|
}
|