mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Convert from LayoutData to Layout.
This commit is contained in:
@@ -206,9 +206,8 @@ public:
|
||||
|
||||
std::set<unsigned> requiredSectors(const Location& location) const override
|
||||
{
|
||||
auto layoutdata = Layout::getLayoutOfTrack(location.logicalTrack, location.head);
|
||||
auto sectors = Layout::getSectorsInTrack(layoutdata);
|
||||
return std::set<unsigned>(sectors.begin(), sectors.end());
|
||||
auto trackLayout = Layout::getLayoutOfTrack(location.logicalTrack, location.head);
|
||||
return std::set<unsigned>(trackLayout.logicalSectors.begin(), trackLayout.logicalSectors.end());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -115,14 +115,15 @@ public:
|
||||
IbmEncoderProto::TrackdataProto trackdata;
|
||||
getEncoderTrackData(trackdata, location.logicalTrack, location.head);
|
||||
|
||||
auto layoutdata =
|
||||
auto trackLayout =
|
||||
Layout::getLayoutOfTrack(location.logicalTrack, location.head);
|
||||
|
||||
int logicalSide = location.head ^ trackdata.swap_sides();
|
||||
for (int sectorId : Layout::getSectorsInTrack(layoutdata))
|
||||
for (unsigned physicalSectorId : trackLayout.physicalSectors)
|
||||
{
|
||||
unsigned logicalSectorId = trackLayout.physicalSectorToLogical(physicalSectorId);
|
||||
const auto& sector =
|
||||
image.get(location.logicalTrack, logicalSide, sectorId);
|
||||
image.get(location.logicalTrack, logicalSide, logicalSectorId);
|
||||
if (sector)
|
||||
sectors.push_back(sector);
|
||||
}
|
||||
@@ -137,7 +138,7 @@ public:
|
||||
IbmEncoderProto::TrackdataProto trackdata;
|
||||
getEncoderTrackData(trackdata, location.logicalTrack, location.head);
|
||||
|
||||
auto layoutdata =
|
||||
auto trackLayout =
|
||||
Layout::getLayoutOfTrack(location.logicalTrack, location.head);
|
||||
|
||||
auto writeBytes = [&](const Bytes& bytes)
|
||||
@@ -174,7 +175,7 @@ public:
|
||||
|
||||
uint8_t sectorSize = 0;
|
||||
{
|
||||
int s = layoutdata.sector_size() >> 7;
|
||||
int s = trackLayout.sectorSize >> 7;
|
||||
while (s > 1)
|
||||
{
|
||||
s >>= 1;
|
||||
@@ -259,7 +260,7 @@ public:
|
||||
bw.write_8(damUnencoded);
|
||||
|
||||
Bytes truncatedData =
|
||||
sectorData->data.slice(0, layoutdata.sector_size());
|
||||
sectorData->data.slice(0, trackLayout.sectorSize);
|
||||
bw += truncatedData;
|
||||
uint16_t crc = crc16(CCITT_POLY, data);
|
||||
bw.write_be16(crc);
|
||||
|
||||
@@ -29,9 +29,9 @@ void Image::createBlankImage()
|
||||
{
|
||||
unsigned track = trackAndHead.first;
|
||||
unsigned side = trackAndHead.second;
|
||||
auto layout = Layout::getLayoutOfTrack(track, side);
|
||||
Bytes blank(layout.sector_size());
|
||||
for (unsigned sectorId : Layout::getSectorsInTrack(layout))
|
||||
auto trackLayout = Layout::getLayoutOfTrack(track, side);
|
||||
Bytes blank(trackLayout.sectorSize);
|
||||
for (unsigned sectorId : trackLayout.logicalSectors)
|
||||
put(track, side, sectorId)->data = blank;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,10 +40,10 @@ public:
|
||||
if (inputFile.eof())
|
||||
break;
|
||||
|
||||
auto layoutdata = Layout::getLayoutOfTrack(track, side);
|
||||
for (int sectorId : Layout::getSectorsInTrack(layoutdata))
|
||||
auto trackLayout = Layout::getLayoutOfTrack(track, side);
|
||||
for (int sectorId : trackLayout.logicalSectors)
|
||||
{
|
||||
Bytes data(layoutdata.sector_size());
|
||||
Bytes data(trackLayout.sectorSize);
|
||||
inputFile.read((char*)data.begin(), data.size());
|
||||
|
||||
const auto& sector = image->put(track, side, sectorId);
|
||||
|
||||
@@ -36,26 +36,14 @@ public:
|
||||
int track = p.first;
|
||||
int side = p.second;
|
||||
|
||||
auto layoutdata = Layout::getLayoutOfTrack(track, side);
|
||||
auto sectors = Layout::getSectorsInTrack(layoutdata, geometry.numSectors);
|
||||
if (sectors.empty())
|
||||
{
|
||||
int maxSector = geometry.firstSector + geometry.numSectors - 1;
|
||||
for (int i = geometry.firstSector; i <= maxSector; i++)
|
||||
sectors.push_back(i);
|
||||
}
|
||||
|
||||
int sectorSize = layoutdata.has_sector_size()
|
||||
? layoutdata.sector_size()
|
||||
: geometry.sectorSize;
|
||||
|
||||
for (int sectorId : sectors)
|
||||
auto trackLayout = Layout::getLayoutOfTrack(track, side);
|
||||
for (int sectorId : trackLayout.logicalSectors)
|
||||
{
|
||||
const auto& sector = image.get(track, side, sectorId);
|
||||
if (sector)
|
||||
sector->data.slice(0, sectorSize).writeTo(outputFile);
|
||||
sector->data.slice(0, trackLayout.sectorSize).writeTo(outputFile);
|
||||
else
|
||||
outputFile.seekp(sectorSize, std::ios::cur);
|
||||
outputFile.seekp(trackLayout.sectorSize, std::ios::cur);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
116
lib/layout.cc
116
lib/layout.cc
@@ -1,6 +1,9 @@
|
||||
#include "lib/globals.h"
|
||||
#include "lib/layout.h"
|
||||
#include "lib/proto.h"
|
||||
#include <fmt/format.h>
|
||||
|
||||
static std::map<std::pair<int, int>, std::unique_ptr<Layout>> layoutCache;
|
||||
|
||||
std::vector<std::pair<int, int>> Layout::getTrackOrdering(
|
||||
unsigned guessedTracks, unsigned guessedSides)
|
||||
@@ -39,58 +42,83 @@ std::vector<std::pair<int, int>> Layout::getTrackOrdering(
|
||||
return ordering;
|
||||
}
|
||||
|
||||
LayoutProto::LayoutdataProto Layout::getLayoutOfTrack(
|
||||
unsigned track, unsigned side)
|
||||
static void expandSectors(const LayoutProto::SectorsProto& sectorsProto,
|
||||
std::vector<unsigned>& sectors)
|
||||
{
|
||||
LayoutProto::LayoutdataProto layoutdata;
|
||||
|
||||
for (const auto& f : config.layout().layoutdata())
|
||||
if (sectorsProto.has_count())
|
||||
{
|
||||
if (f.has_track() && f.has_up_to_track() &&
|
||||
((track < f.track()) || (track > f.up_to_track())))
|
||||
continue;
|
||||
if (f.has_track() && !f.has_up_to_track() && (track != f.track()))
|
||||
continue;
|
||||
if (f.has_side() && (f.side() != side))
|
||||
continue;
|
||||
|
||||
layoutdata.MergeFrom(f);
|
||||
}
|
||||
|
||||
return layoutdata;
|
||||
}
|
||||
|
||||
std::vector<unsigned> Layout::getSectorsInTrack(
|
||||
const LayoutProto::LayoutdataProto& trackdata, unsigned guessedSectors)
|
||||
{
|
||||
auto& physical = trackdata.physical();
|
||||
|
||||
std::vector<unsigned> sectors;
|
||||
if (physical.has_count())
|
||||
{
|
||||
if (physical.sector_size() != 1)
|
||||
if (sectorsProto.sector_size() != 1)
|
||||
Error() << "LAYOUT: if you use a sector count, you must specify "
|
||||
"exactly one start sector";
|
||||
|
||||
int startSector = physical.sector(0);
|
||||
for (int i = 0; i < physical.count(); i++)
|
||||
int startSector = sectorsProto.sector(0);
|
||||
for (int i = 0; i < sectorsProto.count(); i++)
|
||||
sectors.push_back(startSector + i);
|
||||
}
|
||||
else if (physical.guess_count())
|
||||
else if (sectorsProto.sector_size() > 0)
|
||||
{
|
||||
if (physical.sector_size() != 1)
|
||||
Error() << "LAYOUT: if you are guessing the number of sectors, you "
|
||||
"must specify exactly one start sector";
|
||||
|
||||
int startSector = physical.sector(0);
|
||||
for (int i = 0; i < guessedSectors; i++)
|
||||
sectors.push_back(startSector + i);
|
||||
}
|
||||
else if (trackdata.sector_size() > 0)
|
||||
{
|
||||
for (int sectorId : physical.sector())
|
||||
for (int sectorId : sectorsProto.sector())
|
||||
sectors.push_back(sectorId);
|
||||
}
|
||||
|
||||
return sectors;
|
||||
else
|
||||
Error() << "LAYOUT: no sectors in track!";
|
||||
}
|
||||
|
||||
const Layout& Layout::getLayoutOfTrack(unsigned track, unsigned side)
|
||||
{
|
||||
auto& layout = layoutCache[std::make_pair(track, side)];
|
||||
if (!layout)
|
||||
{
|
||||
layout.reset(new Layout);
|
||||
|
||||
LayoutProto::LayoutdataProto layoutdata;
|
||||
for (const auto& f : config.layout().layoutdata())
|
||||
{
|
||||
if (f.has_track() && f.has_up_to_track() &&
|
||||
((track < f.track()) || (track > f.up_to_track())))
|
||||
continue;
|
||||
if (f.has_track() && !f.has_up_to_track() && (track != f.track()))
|
||||
continue;
|
||||
if (f.has_side() && (f.side() != side))
|
||||
continue;
|
||||
|
||||
layoutdata.MergeFrom(f);
|
||||
}
|
||||
|
||||
layout->numTracks = config.layout().tracks();
|
||||
layout->numSides = config.layout().sides();
|
||||
layout->sectorSize = layoutdata.sector_size();
|
||||
expandSectors(layoutdata.physical(), layout->physicalSectors);
|
||||
if (layoutdata.has_logical())
|
||||
expandSectors(layoutdata.logical(), layout->logicalSectors);
|
||||
else
|
||||
layout->logicalSectors = layout->physicalSectors;
|
||||
|
||||
if (layout->logicalSectors.size() != layout->physicalSectors.size())
|
||||
Error() << fmt::format(
|
||||
"LAYOUT: physical and logical sectors lists are different "
|
||||
"sizes in {}.{}",
|
||||
track,
|
||||
side);
|
||||
}
|
||||
|
||||
return *layout;
|
||||
}
|
||||
|
||||
unsigned Layout::physicalSectorToLogical(unsigned physicalSectorId)
|
||||
{
|
||||
for (int i=0; i<physicalSectors.size(); i++)
|
||||
if (physicalSectors[i] == physicalSectorId)
|
||||
return logicalSectors[i];
|
||||
Error() << fmt::format("LAYOUT: physical sector {} not recognised", physicalSectorId);
|
||||
}
|
||||
|
||||
unsigned Layout::logicalSectorToPhysical(unsigned logicalSectorId)
|
||||
{
|
||||
for (int i=0; i<logicalSectors.size(); i++)
|
||||
if (logicalSectors[i] == logicalSectorId)
|
||||
return physicalSectors[i];
|
||||
Error() << fmt::format("LAYOUT: logical sector {} not recognised", logicalSectorId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
14
lib/layout.h
14
lib/layout.h
@@ -9,12 +9,18 @@ public:
|
||||
static std::vector<std::pair<int, int>> getTrackOrdering(
|
||||
unsigned guessedTracks = 0, unsigned guessedSides = 0);
|
||||
|
||||
static LayoutProto::LayoutdataProto getLayoutOfTrack(
|
||||
static const Layout& getLayoutOfTrack(
|
||||
unsigned logicalTrack, unsigned logicalHead);
|
||||
|
||||
static std::vector<unsigned> getSectorsInTrack(
|
||||
const LayoutProto::LayoutdataProto& trackdata,
|
||||
unsigned guessedSectors = 0);
|
||||
public:
|
||||
unsigned numTracks;
|
||||
unsigned numSides;
|
||||
unsigned sectorSize;
|
||||
std::vector<unsigned> physicalSectors;
|
||||
std::vector<unsigned> logicalSectors;
|
||||
|
||||
unsigned physicalSectorToLogical(unsigned sectorId);
|
||||
unsigned logicalSectorToPhysical(unsigned sectorId);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,35 +2,51 @@ syntax = "proto2";
|
||||
|
||||
import "lib/common.proto";
|
||||
|
||||
message LayoutProto {
|
||||
enum Order {
|
||||
UNDEFINED = 0;
|
||||
CHS = 1;
|
||||
HCS = 2;
|
||||
}
|
||||
message LayoutProto
|
||||
{
|
||||
enum Order
|
||||
{
|
||||
UNDEFINED = 0;
|
||||
CHS = 1;
|
||||
HCS = 2;
|
||||
}
|
||||
|
||||
message SectorsProto {
|
||||
repeated int32 sector = 1 [(help) = "sector ID"];
|
||||
oneof count_oneof {
|
||||
int32 count = 2 [(help) = "if present, add this many consecutive sectors"];
|
||||
bool guess_count = 3 [(help) = "if present, guess the number of sectors"];
|
||||
}
|
||||
}
|
||||
message SectorsProto
|
||||
{
|
||||
repeated int32 sector = 1 [ (help) = "sector ID" ];
|
||||
oneof count_oneof
|
||||
{
|
||||
int32 count = 2
|
||||
[ (help) = "if present, add this many consecutive sectors" ];
|
||||
bool guess_count = 3
|
||||
[ (help) = "if present, guess the number of sectors" ];
|
||||
}
|
||||
}
|
||||
|
||||
message LayoutdataProto {
|
||||
optional int32 track = 1 [(help) = "if present, this format only applies to this track"];
|
||||
optional int32 up_to_track = 5 [(help) = "if present, forms a range with track"];
|
||||
optional int32 side = 2 [(help) = "if present, this format only applies to this side"];
|
||||
message LayoutdataProto
|
||||
{
|
||||
optional int32 track = 1
|
||||
[ (help) = "if present, this format only applies to this track" ];
|
||||
optional int32 up_to_track = 5
|
||||
[ (help) = "if present, forms a range with track" ];
|
||||
optional int32 side = 2
|
||||
[ (help) = "if present, this format only applies to this side" ];
|
||||
|
||||
optional int32 sector_size = 3 [default=512, (help) = "number of bytes per sector"];
|
||||
optional int32 sector_size = 3
|
||||
[ default = 512, (help) = "number of bytes per sector" ];
|
||||
|
||||
optional SectorsProto physical = 4 [(help) = "physical order of sectors on disk"];
|
||||
optional SectorsProto logical = 6 [(help) = "logical order of sectors in filesystem"];
|
||||
}
|
||||
optional SectorsProto physical = 4
|
||||
[ (help) = "physical order of sectors on disk" ];
|
||||
optional SectorsProto logical = 6
|
||||
[ (help) = "logical order of sectors in filesystem" ];
|
||||
}
|
||||
|
||||
repeated LayoutdataProto layoutdata = 1 [(help) = "per-track layout information (repeatable)"];
|
||||
optional int32 tracks = 2 [default=0, (help) = "number of tracks in image"];
|
||||
optional int32 sides = 3 [default=0, (help) = "number of sides in image"];
|
||||
optional Order order = 4 [default=CHS, (help) = "the order of sectors in the filesystem"];
|
||||
repeated LayoutdataProto layoutdata = 1
|
||||
[ (help) = "per-track layout information (repeatable)" ];
|
||||
optional int32 tracks = 2
|
||||
[ default = 0, (help) = "number of tracks in image" ];
|
||||
optional int32 sides = 3
|
||||
[ default = 0, (help) = "number of sides in image" ];
|
||||
optional Order order = 4
|
||||
[ default = CHS, (help) = "the order of sectors in the filesystem" ];
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +38,10 @@ public:
|
||||
nanoseconds_t dataEndTime = 0;
|
||||
unsigned physicalTrack = 0;
|
||||
unsigned physicalHead = 0;
|
||||
unsigned physicalSector = 0;
|
||||
unsigned logicalTrack = 0;
|
||||
unsigned logicalSide = 0;
|
||||
unsigned physicalSector = 0;
|
||||
unsigned logicalSector = 0;
|
||||
Bytes data;
|
||||
std::vector<std::shared_ptr<Record>> records;
|
||||
|
||||
@@ -51,7 +52,7 @@ public:
|
||||
std::tuple<int, int, int, Status> key() const
|
||||
{
|
||||
return std::make_tuple(
|
||||
logicalTrack, logicalSide, physicalSector, status);
|
||||
logicalTrack, logicalSide, logicalSector, status);
|
||||
}
|
||||
|
||||
bool operator==(const Sector& rhs) const
|
||||
|
||||
@@ -91,8 +91,7 @@ public:
|
||||
dev.devType = DEVTYPE_FLOPDD;
|
||||
dev.cylinders = config.layout().tracks();
|
||||
dev.heads = config.layout().sides();
|
||||
dev.sectors =
|
||||
Layout::getSectorsInTrack(Layout::getLayoutOfTrack(0, 0)).size();
|
||||
dev.sectors = Layout::getLayoutOfTrack(0, 0).logicalSectors.size();
|
||||
adfInitDevice(&dev, nullptr, false);
|
||||
int res = adfCreateFlop(&dev, (char*)volumeName.c_str(), 0);
|
||||
if (res != RC_OK)
|
||||
|
||||
@@ -63,8 +63,7 @@ public:
|
||||
{
|
||||
unsigned track = trackid.first;
|
||||
unsigned side = trackid.second;
|
||||
auto layoutdata = Layout::getLayoutOfTrack(track, side);
|
||||
auto sectors = Layout::getSectorsInTrack(layoutdata);
|
||||
auto trackLayout = Layout::getLayoutOfTrack(track, side);
|
||||
locations.insert(Mapper::computeLocationFor(track, side));
|
||||
|
||||
/* If we don't have all the sectors of this track, we may need to
|
||||
@@ -72,7 +71,7 @@ public:
|
||||
* a time. */
|
||||
|
||||
if (!imageContainsAllSectorsOf(
|
||||
_changedSectors, track, side, sectors))
|
||||
_changedSectors, track, side, trackLayout.logicalSectors))
|
||||
{
|
||||
/* If we don't have any loaded sectors for this track, pre-read
|
||||
* it. */
|
||||
@@ -83,11 +82,11 @@ public:
|
||||
/* Now merge the loaded track with the changed one, and write
|
||||
* the result back. */
|
||||
|
||||
for (const unsigned sector : sectors)
|
||||
for (unsigned sectorId : trackLayout.logicalSectors)
|
||||
{
|
||||
if (!_changedSectors.contains(track, side, sector))
|
||||
_changedSectors.put(track, side, sector)->data =
|
||||
_loadedSectors.get(track, side, sector)->data;
|
||||
if (!_changedSectors.contains(track, side, sectorId))
|
||||
_changedSectors.put(track, side, sectorId)->data =
|
||||
_loadedSectors.get(track, side, sectorId)->data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,13 +164,12 @@ Filesystem::Filesystem(std::shared_ptr<SectorInterface> sectors):
|
||||
int track = p.first;
|
||||
int side = p.second;
|
||||
|
||||
auto layoutdata = Layout::getLayoutOfTrack(track, side);
|
||||
auto sectors = Layout::getSectorsInTrack(layoutdata);
|
||||
if (sectors.empty())
|
||||
auto trackLayout = Layout::getLayoutOfTrack(track, side);
|
||||
if (trackLayout.logicalSectors.empty())
|
||||
Error() << "FS: filesystem support cannot be used without concrete "
|
||||
"layout information";
|
||||
|
||||
for (int sectorId : sectors)
|
||||
for (int sectorId : trackLayout.logicalSectors)
|
||||
_locations.push_back(std::make_tuple(track, side, sectorId));
|
||||
}
|
||||
}
|
||||
@@ -269,9 +268,9 @@ Bytes Filesystem::getLogicalSector(uint32_t number, uint32_t count)
|
||||
int track = std::get<0>(it);
|
||||
int side = std::get<1>(it);
|
||||
int sector = std::get<2>(it);
|
||||
auto layoutdata = Layout::getLayoutOfTrack(track, side);
|
||||
auto trackLayout = Layout::getLayoutOfTrack(track, side);
|
||||
bw += _sectors->get(track, side, sector)
|
||||
->data.slice(0, layoutdata.sector_size());
|
||||
->data.slice(0, trackLayout.sectorSize);
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@@ -288,7 +287,7 @@ void Filesystem::putLogicalSector(uint32_t number, const Bytes& data)
|
||||
int track = std::get<0>(it);
|
||||
int side = std::get<1>(it);
|
||||
int sector = std::get<2>(it);
|
||||
int sectorSize = Layout::getLayoutOfTrack(track, side).sector_size();
|
||||
int sectorSize = Layout::getLayoutOfTrack(track, side).sectorSize;
|
||||
|
||||
_sectors->put(track, side, sector)->data = data.slice(pos, sectorSize);
|
||||
pos += sectorSize;
|
||||
@@ -317,8 +316,7 @@ unsigned Filesystem::getLogicalSectorCount()
|
||||
|
||||
unsigned Filesystem::getLogicalSectorSize(unsigned track, unsigned side)
|
||||
{
|
||||
auto trackdata = Layout::getLayoutOfTrack(track, side);
|
||||
return trackdata.sector_size();
|
||||
return Layout::getLayoutOfTrack(track, side).sectorSize;
|
||||
}
|
||||
|
||||
void Filesystem::eraseEverythingOnDisk()
|
||||
|
||||
@@ -62,9 +62,9 @@ public:
|
||||
_dndFormat(wxDF_UNICODETEXT),
|
||||
_config("FluxEngine")
|
||||
{
|
||||
wxIcon icon;
|
||||
icon.CopyFromBitmap(applicationBitmap->GetBitmap());
|
||||
SetIcon(icon);
|
||||
wxIcon icon;
|
||||
icon.CopyFromBitmap(applicationBitmap->GetBitmap());
|
||||
SetIcon(icon);
|
||||
|
||||
Logger::setLogger(
|
||||
[&](std::shared_ptr<const AnyLogMessage> message)
|
||||
@@ -924,25 +924,25 @@ public:
|
||||
if (event.GetDataFormat() != _dndFormat)
|
||||
throw CancelException();
|
||||
|
||||
#if defined __WXGTK__
|
||||
/* wxWidgets 3.0 data view DnD on GTK is borked. See
|
||||
* https://forums.wxwidgets.org/viewtopic.php?t=44752. The hit
|
||||
* detection is done against the wrong object, resulting in the
|
||||
* header size not being taken into account, so we have to manually
|
||||
* do hit detection correctly. */
|
||||
#if defined __WXGTK__
|
||||
/* wxWidgets 3.0 data view DnD on GTK is borked. See
|
||||
* https://forums.wxwidgets.org/viewtopic.php?t=44752. The hit
|
||||
* detection is done against the wrong object, resulting in the
|
||||
* header size not being taken into account, so we have to manually
|
||||
* do hit detection correctly. */
|
||||
|
||||
auto* window = browserTree->GetMainWindow();
|
||||
auto screenPos = wxGetMousePosition();
|
||||
auto relPos = screenPos - window->GetScreenPosition();
|
||||
auto* window = browserTree->GetMainWindow();
|
||||
auto screenPos = wxGetMousePosition();
|
||||
auto relPos = screenPos - window->GetScreenPosition();
|
||||
|
||||
wxDataViewItem item;
|
||||
wxDataViewColumn* column;
|
||||
browserTree->HitTest(relPos, item, column);
|
||||
if (!item.IsOk())
|
||||
throw CancelException();
|
||||
#else
|
||||
auto item = event.GetItem();
|
||||
#endif
|
||||
wxDataViewItem item;
|
||||
wxDataViewColumn* column;
|
||||
browserTree->HitTest(relPos, item, column);
|
||||
if (!item.IsOk())
|
||||
throw CancelException();
|
||||
#else
|
||||
auto item = event.GetItem();
|
||||
#endif
|
||||
|
||||
auto destDirNode = GetTargetDirectoryNode(item);
|
||||
if (!destDirNode)
|
||||
|
||||
Reference in New Issue
Block a user