ciderpress/app/DiskFSTree.cpp
Andy McFadden 8c34eb1213 Volume name and font fixes
More volume name MOR conversions.  I think I got them all.

This also switches the "archive info", "add files", and "extract
files" dialogs to use the System Font.  We were using "MS Sans
Serif" before, which looks a bit ratty on Windows 7 because it
doesn't take advantage of ClearType.  (Apparently the ClearType
version is "Microsoft Sans Serif", though when you set the "use
system font" boolean to true it changes the font name to "MS Shell
Dlg".)  The old font also seems to be missing certain glyphs, e.g.
my HFS volume name had 'TM' in it, but that just showed up as a box
(which is why, in case you were wondering, these changes ended up
together).

The new font seems to work equally well on WinXP, so I may enable
it for all dialogs in a follow-up change.  As far as I can tell it
has the same font metrics -- I haven't seen anything weird looking
in the dialogs I've updated so far.

Also, bumped the version to 4.0.0-b3.
2015-01-15 11:35:48 -08:00

225 lines
7.1 KiB
C++

/*
* CiderPress
* Copyright (C) 2007 by faddenSoft, LLC. All Rights Reserved.
* See the file LICENSE for distribution terms.
*/
#include "StdAfx.h"
#include "DiskFSTree.h"
#include "ChooseAddTargetDialog.h"
#include "../reformat/Charset.h"
using namespace DiskImgLib;
bool DiskFSTree::BuildTree(DiskFS* pDiskFS, CTreeCtrl* pTree)
{
ASSERT(pDiskFS != NULL);
ASSERT(pTree != NULL);
pTree->SetImageList(&fTreeImageList, TVSIL_NORMAL);
return AddDiskFS(pTree, TVI_ROOT, pDiskFS, 1);
}
bool DiskFSTree::AddDiskFS(CTreeCtrl* pTree, HTREEITEM parent,
DiskImgLib::DiskFS* pDiskFS, int depth)
{
const DiskFS::SubVolume* pSubVol;
TargetData* pTarget;
HTREEITEM hLocalRoot;
TVITEM tvi;
TVINSERTSTRUCT tvins;
/*
* Insert an entry for the current item.
*
* The TVITEM struct wants a pointer to WCHAR* storage for the item
* text. The DiskFS only provides narrow chars, so we need to create
* some local storage for the widened version. Some calls that take a
* TVITEM allow the text to be edited, so the field is LPWSTR rather
* than LPCWSTR, but our uses don't allow editing, so we're okay
* passing it a pointer to storage inside a CString.
*/
pTarget = AllocTargetData();
pTarget->kind = kTargetDiskFS;
pTarget->pDiskFS = pDiskFS;
pTarget->pFile = NULL; // could also use volume dir for ProDOS
tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
CStringA volumeIdA(pDiskFS->GetVolumeID());
CString volumeId(Charset::ConvertMORToUNI(volumeIdA));
int index = fStringHolder.Add(volumeId);
tvi.pszText = (LPWSTR)(LPCWSTR) fStringHolder.GetAt(index);
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 == NULL) {
LOGW("Tree root InsertItem failed");
return false;
}
/*
* Scan for and handle all sub-volumes.
*/
pSubVol = pDiskFS->GetNextSubVolume(NULL);
while (pSubVol != NULL) {
if (!AddDiskFS(pTree, hLocalRoot, pSubVol->GetDiskFS(), depth+1))
return false;
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, NULL, depth);
}
/*
* 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);
}
return true;
}
DiskImgLib::A2File* DiskFSTree::AddSubdir(CTreeCtrl* pTree, HTREEITEM parent,
DiskImgLib::DiskFS* pDiskFS, DiskImgLib::A2File* pParentFile,
int depth)
{
A2File* pFile;
TargetData* pTarget;
HTREEITEM hLocalRoot;
TVITEM tvi;
TVINSERTSTRUCT tvins;
pFile = pDiskFS->GetNextFile(pParentFile);
if (pFile == NULL && pParentFile == NULL) {
/* this can happen on an empty DOS 3.3 disk; under ProDOS, we always
have the volume entry */
/* note pFile will be NULL if this happens to be a subdirectory
positioned as the very last file on the disk */
return NULL;
}
if (pParentFile == NULL) {
/*
* 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).
*
* This has the same wide-vs-narrow storage issues as AddDiskFS().
*/
pTarget = AllocTargetData();
pTarget->kind = kTargetSubdir;
pTarget->selectable = true;
pTarget->pDiskFS = pDiskFS;
pTarget->pFile = pParentFile;
tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
CString fileNameW(pParentFile->GetFileName());
int index = fStringHolder.Add(fileNameW);
tvi.pszText = (LPWSTR)(LPCWSTR) fStringHolder.GetAt(index);
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 == NULL) {
LOGW("Tree insert '%ls' failed", tvi.pszText);
return NULL;
}
}
while (pFile != NULL) {
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 == NULL)
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);
return pFile;
}
DiskFSTree::TargetData* DiskFSTree::AllocTargetData(void)
{
TargetData* pNew = new TargetData;
if (pNew == NULL)
return NULL;
/* insert it at the head of the list, and update the head pointer */
pNew->pNext = fpTargetData;
fpTargetData = pNew;
return pNew;
}
void DiskFSTree::FreeAllTargetData(void)
{
TargetData* pTarget;
TargetData* pNext;
pTarget = fpTargetData;
while (pTarget != NULL) {
pNext = pTarget->pNext;
delete pTarget;
pTarget = pNext;
}
fpTargetData = NULL;
}