netscape-revival
lib/mac/VText/V_PowerPlant_Mods/LClipboardTube.cp
// ===========================================================================
// LClipboardTube.cp ©1995 Metrowerks Inc. All rights reserved.
// ===========================================================================
// For routine descriptions see LDataTube.cp.
#ifdef PowerPlant_PCH
#include PowerPlant_PCH
#endif
#include "LClipboardTube.h"
#include <UMemoryMgr.h>
#include <LDynamicArray.h>
#include <LTubeableItem.h>
#include <UAEGizmos.h>
#include <URange32.h>
#ifndef __SCRAP__
#include <Scrap.h>
#endif
#ifndef __ERRORS__
#include <Errors.h>
#endif
#pragma warn_unusedarg off
LClipboardTube::LClipboardTube()
/*
Create a tube from existing data on the clipboard.
*/
{
OSErr err = noErr;
ScrapStuffPtr p = InfoScrap();
ThrowIfNULL_(p);
if (!p->scrapHandle)
err = LoadScrap();
ThrowIfOSErr_(err);
p = InfoScrap();
ThrowIfNULL_(p);
mScrapHandle = p->scrapHandle;
ThrowIfNULL_(mScrapHandle);
// Get or construct tube map.
Int32 n = UScrap::CountItems(mScrapHandle, typeTubeMapItems);
Assert_(n <= 1);
if (n) {
StHandleLocker lock(mScrapHandle);
ScrapRecT *timi = UScrap::NthItem(mScrapHandle, typeTubeMapItems, 1);
ThrowIfNULL_(timi);
#if 1
mOwnedDesc.mDesc.dataHandle = NewHandle(timi->size);
ThrowIfNULL_(mOwnedDesc.mDesc.dataHandle);
BlockMove(&timi->data, *(mOwnedDesc.mDesc.dataHandle), timi->size);
mOwnedDesc.mDesc.descriptorType = typeAERecord;
mTubeMap = LAESubDesc(mOwnedDesc.mDesc);
#else
{
LAEStream stream;
stream.OpenRecord(); // base item flavors
stream.WriteKey(typeTubeMapItems);
{
AEDesc desc;
StHandleBlock handle(timi->size);
BlockMove(&timi->data, *(handle.mHandle), timi->size);
desc.dataHandle = handle.mHandle;
desc.descriptorType = typeAERecord;
stream.WriteDesc(desc);
}
stream.CloseRecord();
stream.Close(&mOwnedDesc.mDesc);
}
mTubeMap = LAESubDesc(mOwnedDesc.mDesc);
#endif
} else {
/*-
ScrapRecT *end = UScrap::Terminal(mScrapHandle),
*p = (ScrapRecT *)*mScrapHandle;
LAEStream ae;
LDynamicArray itemFlavors(sizeof(FlavorType));
FlavorType flavor;
ae.OpenList(); // items
while (p < end) {
ae.OpenList(); // item flavors
itemFlavors.RemoveItemsAt(max_Int32, 1); // empty list
while (p < end) {
flavor = p->type;
if (itemFlavors.FetchIndexOf(&flavor)) {
break;
} else {
itemFlavors.InsertItemsAt(1, max_Int32, &flavor); // append
ae.WriteTypeDesc(flavor); // need a record?
}
p = UScrap::Next(p);
}
ae.CloseList(); // item flavors
}
ae.CloseList(); // items
ae.Close(&mTubeMap.mDesc);
*/
}
}
LClipboardTube::LClipboardTube(
const LTubeableItem *inTubeableItem,
Boolean inReqdFlavorsOnly
)
{
ZeroScrap();
FillFrom(inTubeableItem, inReqdFlavorsOnly);
}
LClipboardTube::~LClipboardTube()
{
}
// ----------------------------------------------------------------------
// Reading:
Boolean LClipboardTube::FlavorExists(FlavorType inFlavor) const
{
Boolean rval = false;
if (mTubeDepth == mSwapDepth) {
if (inFlavor == typeWildCard) {
Int32 count = UScrap::CountItems(mScrapHandle, inFlavor);
count -= UScrap::CountItems(mScrapHandle, typeTubeMapItems);
rval = count > 0;
} else {
rval = UScrap::CountItems(mScrapHandle, inFlavor) > 0;
}
} else {
rval = inherited::FlavorExists(inFlavor);
}
return rval;
}
Size LClipboardTube::GetFlavorSize(FlavorType inFlavor) const
{
Size rval = 0;
if (mTubeDepth == mSwapDepth) {
ScrapRecT *p = UScrap::NthItem(mScrapHandle, inFlavor, 1);
if (p)
rval = p->size;
} else {
rval = inherited::GetFlavorSize(inFlavor);
}
return rval;
}
void * LClipboardTube::GetFlavorData(
FlavorType inFlavor,
void *outFlavorData
) const
// For routine description see LDataTube.cp.
{
void *rval = NULL;
if (mTubeDepth == mSwapDepth) {
ScrapRecT *p = UScrap::NthItem(mScrapHandle, inFlavor, 1);
if (p) {
if (outFlavorData && (p->size > 0)) {
BlockMove(&p->data, outFlavorData, p->size);
} else {
rval = &p->data;
}
}
} else {
rval = inherited::GetFlavorData(inFlavor, outFlavorData);
}
return rval;
}
// ----------------------------------------------------------------------
// Writing:
void LClipboardTube::AddFlavor(FlavorType inFlavor)
{
if (mItemStack.Depth() == mSwapDepth) {
if (mItemStack.Top().item && mAddSendsData)
mItemStack.Top().item->SendFlavorTo(inFlavor, this);
} else {
inherited::AddFlavor(inFlavor);
}
}
void LClipboardTube::SetFlavorData(
FlavorType inFlavor,
const void *inFlavorData,
Int32 inFlavorSize
)
{
if (mItemStack.Depth() == mSwapDepth) {
long err; // Long for unusual scrap calling convention
Assert_(inFlavorData);
err = PutScrap(inFlavorSize, inFlavor, (Ptr)inFlavorData);
ThrowIfOSErr_(err);
} else {
inherited::SetFlavorData(inFlavor, inFlavorData, inFlavorSize);
}
}
// ===========================================================================
// UScrap (utilities for dealing with scrap handles):
Int32 UScrap::CountItems(Handle inScrap, FlavorType inFlavor)
{
ScrapRecT *end = Terminal(inScrap),
*p = (ScrapRecT *)(*inScrap);
Int32 count = 0;
while (p < end) {
if (inFlavor == typeWildCard) {
count++;
} else if (p->type == inFlavor) {
count++;
}
p = Next(p);
}
return count;
}
ScrapRecT * UScrap::NthItem(Handle inScrap, FlavorType inFlavor, Int32 inIndex)
{
Assert_(inIndex >= 1);
ScrapRecT *rval = NULL,
*end = Terminal(inScrap),
*p = (ScrapRecT *)(*inScrap);
Int32 count = 0;
while (p < end) {
if (inFlavor == typeWildCard) {
inIndex--;
} else if (p->type == inFlavor) {
inIndex--;
}
if (!inIndex) {
rval = p;
break;
}
p = Next(p);
}
return rval;
}
ScrapRecT * UScrap::Next(ScrapRecT *inItemPtr)
{
Ptr p = (Ptr)inItemPtr;
ThrowIfNULL_(p);
p += inItemPtr->size;
p += inItemPtr->size % 2; // Records are padded to even byte.
p += sizeof(inItemPtr->type);
p += sizeof(inItemPtr->size);
return (ScrapRecT *)p;
}
ScrapRecT * UScrap::Terminal(Handle inScrap)
{
ThrowIfNULL_(inScrap);
ThrowIfNULL_(*inScrap);
Size size = GetHandleSize(inScrap);
ScrapRecT *end = (ScrapRecT *)(*inScrap + size);
return end;
}