home *** CD-ROM | disk | FTP | other *** search
- /*
- File: Clipbd.cpp
-
- Contains: Implementation for ODClipboard class.
-
- Owned by: Craig Carper
-
- Copyright: © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <7> 8/13/96 DM 1362809: use TempSuppressFatalBentoError to
- ensure old flag value is restored
- <6> 7/11/96 TJ Fixed Name of function to check for MacOS 8
- <5> 5/24/96 jpa 1246074: SOM_CATCH --> SOM_TRY..SOM_ENDTRY
- <3> 3/29/96 DM 1296171: suppress fatal Bento container
- errors in all clipboard methods
- <2> 3/26/96 CC 1333462: CloseClipboard: ClearAllPromises
- if not externalizing the clipboard draft.
-
- To Do:
- • Reuse fContainerHandle when possible after exporting it.
- • Add a resolvePromises parameter to ExportClipboard (but maybe we need to
- do this all the time).
- • Vincent will add a draft change seed. The clipboard object can examine
- the seed for the clipboard draft to determine if the clipboard has
- been changed since it was exported (if the clipboard generation is the
- same).
- • XMPClipboard::Clear() should clear the system clipboard.
-
- In Progress:
-
- */
-
- #define VARIABLE_MACROS
-
- #define ODClipboard_Class_Source
- #include <Clipbd.xih>
-
- #ifndef SOM_Module_OpenDoc_StdDefs_defined
- #include <StdDefs.xh>
- #endif
-
- #ifndef _EXCEPT_
- #include <Except.h>
- #endif
-
- #ifndef _ODMEMORY_
- #include <ODMemory.h>
- #endif
-
- #ifndef _CONSTDEF_
- #include <ConstDef.h>
- #endif
-
- #ifndef _PLFMDEF_
- #include <PlfmDef.h>
- #endif
-
- #ifndef _ISOSTR_
- #include <ISOStr.h>
- #endif
-
- #ifndef _ODUTILS_
- #include <ODUtils.h>
- #endif
-
- #ifndef SOM_Module_OpenDoc_StdProps_defined
- #include <StdProps.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_StdTypes_defined
- #include <StdTypes.xh>
- #endif
-
- #ifndef SOM_Module_OpenDoc_Foci_defined
- #include <Foci.xh>
- #endif
-
- #ifndef SOM_ODSession_xh
- #include <ODSessn.xh>
- #endif
-
- #ifndef _BENTOSUPPRESS_
- #include "BentoSuppress.h"
- #endif
-
- #ifndef SOM_ODArbitrator_xh
- #include <Arbitrat.xh>
- #endif
-
- #ifndef SOM_ODContainer_xh
- #include <ODCtr.xh>
- #endif
-
- #ifndef SOM_ODDocument_xh
- #include <Document.xh>
- #endif
-
- #ifndef SOM_ODDraft_xh
- #include <Draft.xh>
- #endif
-
- #ifndef SOM_ODStorageSystem_xh
- #include <ODStor.xh>
- #endif
-
- #ifndef SOM_ODStorageUnit_xh
- #include <StorageU.xh>
- #endif
-
- #ifndef SOM_ODTranslation_xh
- #include <Translt.xh>
- #endif
-
- #ifndef SOM_ODTypeList_xh
- #include <TypeList.xh>
- #endif
-
- #ifndef SOM_ODPlatformTypeList_xh
- #include <PfTypLs.xh>
- #endif
-
- #ifndef _LINKDLGS_
- #include <LinkDlgs.h>
- #endif
-
- #ifndef __SCRAP__
- #include <Scrap.h>
- #endif
-
- #ifndef _ODDEBUG_
- #include <ODDebug.h>
- #endif
-
- #ifndef __ERRORS__
- #include <Errors.h>
- #endif
-
- #ifndef _STDTYPIO_
- #include <StdTypIO.h>
- #endif
-
- #ifndef _TEMPOBJ_
- #include <TempObj.h>
- #endif
-
- #ifndef _STORUTIL_
- #include <StorUtil.h>
- #endif
-
- #ifndef _UTILERRS_
- #include "UtilErrs.h"
- #endif
-
- #ifndef __TEXTEDIT__
- #include <TextEdit.h> // for ScrpSTElement
- #endif
-
- #pragma segment ODClipboard
-
- #include "ClipbdB.cpp" // Platform-independent methods, if any
-
- #if ODDebug
- #define ODDebugClipboard 0
- #undef _REPORT_SCRAP_ERRORS_
- #else
- #define ODDebugClipboard 0
- #undef _REPORT_SCRAP_ERRORS_
- #endif
-
- //==============================================================================
- // Constants
- //==============================================================================
-
- const short kInvalidScrapCount = -1; // Must never match the scrap count!
-
- // Mac Scrap state constants
- const short kUninitializedScrap = -1;
- const short kScrapOnDisk = 0;
-
- //==============================================================================
- // Function Prototypes
- //==============================================================================
-
- ODStatic ODULong ApplicationHeapFree();
- ODStatic short GetMacScrapCount();
- ODStatic ODBoolean IsFrontProcess();
- ODStatic void ImportStyledTextType(ODClipboard *somSelf, Environment *ev);
- ODStatic OSErr ExportStylType(ODPtr stxtData);
- ODStatic void CloseClipboard(ODClipboard *somSelf, Environment *ev, ODBoolean externalize);
- ODStatic void OpenClipboard(ODClipboard *somSelf, Environment *ev);
- ODStatic ODBoolean ScrapIsInconsistent();
- ODStatic ODBoolean ScrapHasData();
- ODStatic ODBoolean ScrapHasType(ODPlatformType type);
- ODStatic OSErr ForceZeroScrap();
- ODStatic ODBoolean ScrapMemoryAvailable(Size dataSize);
- ODStatic OSErr UnloadScrapIfMemLow(Size dataSize);
- ODStatic OSErr ClipboardLoadScrap();
- ODStatic OSErr ClipboardPutScrap(Size dataSize, ODPlatformType platformType, ODPtr data);
-
- //==============================================================================
- // Utility Functions
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // SetOriginalCloneKind
- //------------------------------------------------------------------------------
-
- static void SetOriginalCloneKind(Environment* ev, ODDraft* draft, ODCloneKind cloneKind)
- {
- if ( draft != kODNULL )
- {
- TempODStorageUnit draftProperties = draft->AcquireDraftProperties(ev);
- ODSetULongProp(ev, draftProperties, kODPropOriginalCloneKind, kODULong, (ODULong)cloneKind);
- }
- }
-
- //------------------------------------------------------------------------------
- // GetOriginalDraft
- //------------------------------------------------------------------------------
- // Returns kODNULL if the original draft is unknown. This is the case when content
- // was placed in the draft without cloning.
-
- static ODDraft* GetOriginalDraft(Environment* ev, ODDraft* draft)
- {
- TempODStorageUnit draftProperties = draft->AcquireDraftProperties(ev);
- return (ODDraft*)ODGetULongProp(ev, draftProperties, kODPropOriginalDraft, kODULong);
- }
-
- //==============================================================================
- // ODClipboard
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // ODClipboard::somUninit
- //------------------------------------------------------------------------------
-
- SOM_Scope void SOMLINK ODClipboardsomUninit(ODClipboard *somSelf)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","somUninit");
-
- TempSuppressFatalBentoError tempSuppress;
-
- Environment *ev = somGetGlobalEnvironment();
- // somSelf->DiscardClipboard(ev);
- // It is incorrect to call methods on somSelf inside somUninit,
- // a subclass may have already been somUninited. See OpenDoc Building Code for details.
- // Instead the implementation of DiscardClipboard has been copied here.
-
- // BEGIN copy of DiscardClipboard implementation
- CloseClipboard(somSelf, ev, kODFalse);
-
- ODDisposeHandle(_fContainerHandle);
- _fContainerHandle = (ODHandle) kODNULL;
- // END copy of DiscardClipboard implementation
-
- parent_somUninit(somSelf);
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::InitClipboard
- //------------------------------------------------------------------------------
-
- SOM_Scope void SOMLINK ODClipboardInitClipboard(ODClipboard *somSelf, Environment *ev,
- ODSession* session)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","InitClipboard");
-
- TempSuppressFatalBentoError tempSuppress;
-
- /* Moved from somInit. SOM itself sets fields to zero
- _fSession = (ODSession*) kODNULL;
- _fContainerHandle = (ODHandle) kODNULL;
- _fContainer = (ODContainer*) kODNULL;
- _fDocument = (ODDocument*) kODNULL;
- _fDraft = (ODDraft*) kODNULL;
- _fSU = (ODStorageUnit*) kODNULL;
-
- _fOriginalDraft = (ODDraft*) kODNULL;
- _fExportedLinkSpec = kODFalse;
-
- _fClonePasteCount = 0;
- */
- somSelf->InitObject(ev);
-
- _fSession = session;
-
- // Initialize our scrap count to an invalid value so a paste will force copying
- // from the platform scrap.
- _fScrapCount = kInvalidScrapCount;
- _fScrapCountLastChange = kInvalidScrapCount;
-
- _fUpdateID = kODUnknownUpdate;
- _fNextUpdateID = _fSession->UniqueUpdateID(ev);
-
- _fOriginalCloneKind = kODCloneCopy;
- }
-
- //------------------------------------------------------------------------------
- // ApplicationHeapFree
- //------------------------------------------------------------------------------
-
- ODStatic ODULong ApplicationHeapFree()
- {
- ODULong free;
- THz curZone = GetZone();
- SetZone(ApplicationZone());
- free = FreeMem();
- SetZone(curZone);
- return free;
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::Purge (OVERRIDE)
- //------------------------------------------------------------------------------
-
- SOM_Scope ODSize SOMLINK ODClipboardPurge(ODClipboard *somSelf, Environment *ev,
- ODSize size)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","Purge");
-
- ODSize freed = 0;
- ODVolatile(freed);
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- Size scrapSize = InfoScrap()->scrapSize;
- short scrapCount = GetMacScrapCount();
-
- if ( InfoScrap()->scrapState > kScrapOnDisk )
- {
- freed += scrapSize;
- if ( (scrapCount == _fScrapCountLastChange) && (scrapCount == _fScrapCount) )
- {
- ForceZeroScrap();
- // Update scrap later
- _fScrapCountLastChange = _fScrapCount = GetMacScrapCount();
-
- #if ODDebugClipboard
- PRINT("ODClipboard::Purge: Scrap cleared\n");
- #endif
- }
- else
- {
- UnloadScrap();
-
- #if ODDebugClipboard
- if ( InfoScrap()->scrapState > kScrapOnDisk )
- PRINT("ODClipboard::Purge: Scrap unloaded\n");
- #endif
- }
- #if ODDebugClipboard
- PRINT("ODClipboard::Purge: Freed %ld bytes in app heap\n", freed);
- #endif
- }
-
- freed += parent_Purge(somSelf, ev, size); // always call parent version of Purge()
-
- SOM_CATCH_ALL
- WARN("Error %ld trying to purge in ODClipboardPurge",ErrorCode());
- SetErrorCode(kODNoError); // Eat the exception; Purge should not
- // propagate it because clients function
- // fine whether memory was purged or not.
- SOM_ENDTRY
-
- return freed;
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::NewClipboard
- //------------------------------------------------------------------------------
-
- SOM_Scope void SOMLINK ODClipboardNewClipboard(ODClipboard *somSelf, Environment *ev)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","NewClipboard");
-
- ODStorageUnit* draftProperties = kODNULL;
-
- ODVolatile(draftProperties);
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- // Create a new clipboard in-memory container
- _fContainerHandle = ODNewHandle(0);
- _fContainer = CreateMemoryContainer(ev, _fSession, _fContainerHandle, kODBentoMemoryContainer);
-
- // Create the root content storage unit
- _fDocument = _fContainer->AcquireDocument(ev, kODDefaultDocument);
- _fDraft = _fDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
- _fSU = _fDraft->CreateStorageUnit(ev);
-
- // Store a reference to the content storage unit in the draft properties
- draftProperties = _fDraft->AcquireDraftProperties(ev);
- ODSetStrongSURefProp(ev, draftProperties, kODPropRootPartSU, kODStrongStorageUnitRef, _fSU->GetID(ev));
- draftProperties->Release(ev);
-
- SOM_CATCH_ALL
- #ifdef _REPORT_SCRAP_ERRORS_
- WARN("ODClipboard: Cannot create clipboard - error %ld",ErrorCode());
- #endif
- somSelf->DiscardClipboard(ev);
- ODReleaseObject(ev, draftProperties);
- SOM_ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // CloseClipboard
- //------------------------------------------------------------------------------
- // Close the current clipboard container, without disposing of the container handle.
- // Note: CloseClipboard must not make any method calls to somSelf, since
- // CloseClipboard is called from the somUninit method.
-
- ODStatic void CloseClipboard(ODClipboard *somSelf, Environment *ev, ODBoolean externalize)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
-
- TempSuppressFatalBentoError tempSuppress;
-
- // If the draft must be externalized, first externalize the root storage unit
- // to resolve promises. Otherwise, externalizing the draft may fail with an
- // iterator-out-of-sync error because resolving promises may add storage units
- // to the draft's collection during iteration. In theory, the only promises
- // should be in the root storage unit, so explicitly externalize it first to
- // resolve promises before interating over all storage units.
-
- if ( _fSU != kODNULL )
- {
- if ( externalize )
- _fSU->Externalize(ev);
- else
- _fSU->ClearAllPromises(ev);
- }
-
- if ( (_fDraft != kODNULL) && externalize )
- {
- _fDraft->Externalize(ev);
- }
-
- ODReleaseObject(ev,_fSU);
- ODReleaseObject(ev,_fDraft);
- ODReleaseObject(ev,_fDocument);
- ODReleaseObject(ev,_fContainer);
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::DiscardClipboard
- //------------------------------------------------------------------------------
-
- SOM_Scope void SOMLINK ODClipboardDiscardClipboard(ODClipboard *somSelf, Environment *ev)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","DiscardClipboard");
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- CloseClipboard(somSelf, ev, kODFalse);
-
- ODDisposeHandle(_fContainerHandle);
- _fContainerHandle = (ODHandle) kODNULL;
-
- SOM_CATCH_ALL
- SOM_ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::ImportContent
- //------------------------------------------------------------------------------
- //
- // On entry, assumes the scrap has already been checked for consistency.
- // Returns an exception if the scrap can't be loaded into memory.
-
- SOM_Scope void SOMLINK ODClipboardImportContent(ODClipboard *somSelf, Environment *ev)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","ImportContent");
-
- ODHandle hData = kODNULL;
- long scrapOffset = 0;
-
- ODVolatile(hData);
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- hData = ODNewHandle(0);
-
- // Because we walk the scrap, it must be loaded in memory.
- THROW_IF_ERROR(ClipboardLoadScrap());
-
- PScrapStuff myScrapStuff = InfoScrap();
- Handle hScrap = myScrapStuff->scrapHandle;
-
- while ( scrapOffset < myScrapStuff->scrapSize )
- {
- long scrapTypeLength;
- ResType theType;
- ODULong realOffset;
-
- // There is more in the scrap
- theType = *(ResTypePtr)(((long) *hScrap) + scrapOffset);
- scrapTypeLength = GetScrap((Handle) hData, theType, (long*) &realOffset);
- if ( scrapTypeLength < 0 )
- THROW(scrapTypeLength);
-
- if ( realOffset < scrapOffset )
- {
- // We tried to read a second occurance of the same resource type
- // on the scrap. Since the result of GetScrap is the length
- // of the first occurance, we can't read the scrap past this point.
- // So just quit.
- #ifdef _REPORT_SCRAP_ERRORS_
- PRINT("ODClipboard: ImportContent: Duplicate resource on scrap, type = \'%.4s\'\n", &theType);
- #endif
- break;
- }
-
- #if ODDebugClipboard
- PRINT("Found scrap type \'%.4s\'\n", &theType);
- #endif
- if ( scrapTypeLength > 0 )
- {
- #ifdef _REPORT_SCRAP_ERRORS_
- if ( theType == kODScrapTypeODBentoContainer )
- {
- // Internal error
- WARN("ODClipboard: ImportContent: Reading BentoContainer as scrap type!");
- }
- #endif
- // Special case: If 'styl' is present, create an 'stxt' if one
- // isn't also on the scrap
- if ( theType == 'styl' )
- {
- long dummy;
- if ( GetScrap(nil, 'stxt', &dummy) == noTypeErr )
- ImportStyledTextType(somSelf, ev);
- }
-
- TempODType theISOType = kODNULL;
- theISOType = _fSession->GetTranslation(ev)->GetISOTypeFromPlatformType(ev, theType, kODPlatformDataType);
-
- if ( theISOType != (ODType) kODNULL )
- {
- if ( ODSUExistsThenFocus(ev, _fSU, kODPropContents, (ODType) theISOType) )
- {
- WARN("ODClipboard: Replacing value on clipboard");
- _fSU->Remove(ev);
- }
- ODSUForceFocus(ev, _fSU, kODPropContents, (ODType) theISOType);
- ODValue pData = ODLockHandle(hData);
- StorageUnitSetValue(_fSU, ev, (ODULong) scrapTypeLength, pData);
- ODUnlockHandle(hData);
- }
- }
-
- // The length must be EVEN!
- if (scrapTypeLength & 1)
- {
- scrapTypeLength += 1;
- }
- scrapOffset = realOffset + scrapTypeLength;
- }
-
- SOM_CATCH_ALL
-
- #ifdef _REPORT_SCRAP_ERRORS_
- WARN("ODClipboard: ImportContent: Failed with error %ld",ErrorCode());
- #endif
- if ( ErrorCode() == memFullErr )
- SetErrorCode(kODErrOutOfMemory);
-
- SOM_ENDTRY
-
- ODDisposeHandle(hData);
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::PutContentOnPlatformClipboard
- //------------------------------------------------------------------------------
- //
- // Copy values with corresponding platform types onto the desk scrap.
- // THROWs an exception if any error occurs, which may cause the desk scrap to
- // be only partially updated. The desk scrap requires copying the data in one chunk.
-
- SOM_Scope void SOMLINK ODClipboardPutContentOnPlatformClipboard(ODClipboard *somSelf, Environment *ev)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","PutContentOnPlatformClipboard");
-
- ODULong count;
- ODULong index;
- ODPlatformType platformType;
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- if ( (_fSU == kODNULL) && (_fContainerHandle != kODNULL) )
- OpenClipboard(somSelf, ev);
-
- if ( _fSU )
- {
- _fSU->Focus(ev, kODPropContents, kODPosUndefined, 0, 0, kODPosUndefined);
- count = _fSU->CountValues(ev);
- for (index = 1; index <= count; ++index)
- {
- _fSU->Focus(ev, kODPropContents, kODPosUndefined, 0, index, kODPosUndefined);
- TempODType theISOType = _fSU->GetType(ev);
- platformType = _fSession->GetTranslation(ev)->GetPlatformTypeFromISOType(ev, (ODType) theISOType);
- if (platformType != (ODPlatformType) kODNULL)
- {
- _fSU->Focus(ev, kODPropContents, kODPosUndefined, (ODType) theISOType, 0, kODPosUndefined);
- Size dataSize = _fSU->GetSize(ev);
-
- TempODPtr data = kODNULL;
- data = ODNewPtr(dataSize, kDefaultHeapID);
-
- StorageUnitGetValue(_fSU, ev, dataSize, (ODValue) data);
-
- THROW_IF_ERROR(ClipboardPutScrap(dataSize, platformType, data));
-
- // If styled text ('stxt') was just written to the scrap, also write
- // 'stly' if a 'TEXT' representation will also be written.
- if ( platformType == 'stxt' )
- if ( _fSU->Exists(ev, kODPropContents, kODAppleTEXT, 0) )
- if ( !_fSU->Exists(ev, kODPropContents, kODApplestyl, 0) )
- THROW_IF_ERROR(ExportStylType(data));
- }
- }
- }
-
- SOM_CATCH_ALL
-
- SOM_ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::ExportPlatformTypes
- //------------------------------------------------------------------------------
- //
- // Export data of the argument platform types to the host clipboard.
- // Since only one ISO type corresponds directly to a platform type (no translation
- // is attempted), we just examine each value on the clipboard and check if
- // its platform equivalent is present in the argument set.
-
-
- SOM_Scope void SOMLINK ODClipboardExportPlatformTypes(ODClipboard *somSelf, Environment *ev,
- ODPlatformTypeList* typeList)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","ExportPlatformTypes");
-
- ODULong countOfValues;
- ODULong index;
- ODULong countToExport;
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- if ( (_fSU == kODNULL) && (_fContainerHandle != kODNULL) )
- OpenClipboard(somSelf, ev);
-
- if ( _fSU )
- {
- _fSU->Focus(ev, kODPropContents, kODPosUndefined, 0, 0, kODPosUndefined);
- countOfValues = _fSU->CountValues(ev);
- if (typeList != (ODPlatformTypeList*) kODNULL)
- countToExport = typeList->Count(ev);
- else
- countToExport = countOfValues;
-
- for (index = 1; (index <= countOfValues) && (countToExport > 0); ++index)
- {
- _fSU->Focus(ev, kODPropContents, kODPosUndefined, 0, index, kODPosUndefined);
- TempODType theISOType = _fSU->GetType(ev);
-
- ODPlatformType platformType =
- _fSession->GetTranslation(ev)->GetPlatformTypeFromISOType(ev, (ODType) theISOType);
- if ( platformType != (ODPlatformType) 0 )
- {
- if ((typeList == (ODPlatformTypeList*) kODNULL) || (typeList->Contains(ev, platformType)))
- {
- _fSU->Focus(ev, kODPropContents, kODPosUndefined, (ODType) theISOType, 0, kODPosUndefined);
- Size dataSize = _fSU->GetSize(ev);
-
- TempODPtr data = kODNULL;
- data = ODNewPtr(dataSize, kDefaultHeapID);
-
- StorageUnitGetValue(_fSU, ev, dataSize, (ODValue) data);
-
- THROW_IF_ERROR(ClipboardPutScrap(dataSize, platformType, data));
-
- if (typeList != (ODPlatformTypeList*) kODNULL)
- typeList->Remove(ev, platformType);
- countToExport -= 1;
- }
- }
- }
- }
-
- SOM_CATCH_ALL
-
- if ( ErrorCode() == memFullErr )
- SetErrorCode(kODErrOutOfMemory);
-
- SOM_ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // OpenClipboard
- //------------------------------------------------------------------------------
-
- ODStatic void OpenClipboard(ODClipboard *somSelf, Environment *ev)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
-
- ODStorageUnitID suID;
-
- ODVolatile(somSelf);
- ODVolatile(ev);
-
- TempSuppressFatalBentoError tempSuppress;
-
- if ( _fContainerHandle )
- {
- TRY
- _fContainer = GetMemoryContainer(ev, _fSession, _fContainerHandle, kODBentoMemoryContainer);
- _fDocument = _fContainer->AcquireDocument(ev, kODDefaultDocument);
- _fDraft = _fDocument->AcquireBaseDraft(ev, kODDPExclusiveWrite);
-
- { TempODStorageUnit draftProperties = _fDraft->AcquireDraftProperties(ev);
- suID = ODGetStrongSURefProp(ev, draftProperties, kODPropRootPartSU, kODStrongStorageUnitRef);
- }
-
- _fSU = _fDraft->AcquireStorageUnit(ev, suID);
- CATCH_ALL
- CloseClipboard(somSelf, ev, kODFalse);
- RERAISE;
- ENDTRY
- }
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::PutClipboardOnPlatformClipboard
- //------------------------------------------------------------------------------
- //
- // This method has the side effect of closing the clipboard container.
- // Also note that by externalizing the clipboard draft, all promises are resolved.
-
- SOM_Scope void SOMLINK ODClipboardPutClipboardOnPlatformClipboard(ODClipboard *somSelf, Environment *ev)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","PutClipboardOnPlatformClipboard");
-
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- // Externalize then close the clipboard container
- CloseClipboard(somSelf, ev, kODTrue);
-
- if ( _fContainerHandle )
- {
- OSErr error;
- Size dataSize;
- char flags;
-
- dataSize = ODGetHandleSize(_fContainerHandle);
-
- THROW_IF_ERROR(UnloadScrapIfMemLow(dataSize));
-
- flags = HGetState((Handle) _fContainerHandle);
- Ptr containerPtr = (Ptr) ODLockHandle(_fContainerHandle);
- error = (OSErr) PutScrap(dataSize, kODScrapTypeODBentoContainer, containerPtr);
- HSetState((Handle) _fContainerHandle, flags);
-
- #ifdef _REPORT_SCRAP_ERRORS_
- WASSERTM(error == noErr, "ODClipboard: PutScrap() failed");
- #endif
- THROW_IF_ERROR(error);
- }
- #ifdef _REPORT_SCRAP_ERRORS_
- else
- {
- // Internal error
- WARN("ODClipboard: PutClipboardOnPlatformClipboard: No Clipboard to export!\n");
- }
- #endif
-
- SOM_CATCH_ALL
-
- #ifdef _REPORT_SCRAP_ERRORS_
- WARN("ODClipboard: PutClipboardOnPlatformClipboard: Raising exception %d\n", ErrorCode());
- #endif
-
- SOM_ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::ImportClipboard
- //------------------------------------------------------------------------------
- //
- // A bento memory container is always used for data interchange.
- // If OpenClipboard throws, its probably because a bad resource of type
- // kODScrapTypeODBentoContainer was found on the clipboard (currently error 1012,
- // but it may change and there may be others).
- // This routine returns:
- // kODFalse, if the platform clipboard does not contain an OpenDoc clipboard;
- // kODTrue, if an OpenDoc clipboard is successfully imported;
- // an exception if an OpenDoc clipboard could not be imported
-
- SOM_Scope ODBoolean SOMLINK ODClipboardImportClipboard(ODClipboard *somSelf, Environment *ev)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","ImportClipboard");
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- ODHandle hData = kODNULL;
- Size dataSize;
- long dummy;
-
- WASSERTM(_fContainerHandle == (ODHandle) kODNULL, "ODClipboard: fContainerHandle not null");
- WASSERTM(_fContainer == (ODContainer*) kODNULL, "ODClipboard: fContainer not null");
- WASSERTM(_fDocument == (ODDocument*) kODNULL, "ODClipboard: fDocument not null");
- WASSERTM(_fDraft == (ODDraft*) kODNULL, "ODClipboard: fDraft not null");
- WASSERTM(_fSU == (ODStorageUnit*) kODNULL, "ODClipboard: fSU not null");
-
- if ( !ScrapHasType(kODScrapTypeODBentoContainer) )
- return kODFalse;
-
- ODVolatile(hData);
-
- TRY
- hData = ODNewHandle(0);
-
- dataSize = GetScrap((Handle) hData, kODScrapTypeODBentoContainer, &dummy);
- if ( dataSize < 0 )
- {
- if ( dataSize == memFullErr )
- THROW(kODErrOutOfMemory);
- else
- THROW(dataSize);
- }
-
- _fContainerHandle = hData;
-
- OpenClipboard(somSelf, ev);
- CATCH_ALL
- #ifdef _REPORT_SCRAP_ERRORS_
- WARN("ODClipboard: Cannot import clipboard - error %ld",ErrorCode());
- #endif
- _fContainerHandle = kODNULL;
- ODDisposeHandle(hData);
- RERAISE;
- ENDTRY
-
- SOM_CATCH_ALL
- SOM_ENDTRY
-
- return kODTrue;
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::GetUpdateID
- //------------------------------------------------------------------------------
-
- SOM_Scope ODUpdateID SOMLINK ODClipboardGetUpdateID(ODClipboard *somSelf, Environment *ev)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","GetUpdateID");
-
- short curScrapCount = GetMacScrapCount();
-
- // If the desk scrap has not changed since we last imported it,
- // or if the desk scrap has not changed since the last change to this clipboard,
- // return the current change id, otherwise, return the next change id.
- // Note that this routine will return the same "next" change id
- // even if the desk scrap has changed since the last call to this routine.
- if (curScrapCount == _fScrapCount)
- return _fUpdateID;
- else if (curScrapCount == _fScrapCountLastChange)
- return _fUpdateID;
- else
- return _fNextUpdateID;
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::Clear
- //------------------------------------------------------------------------------
-
- SOM_Scope void SOMLINK ODClipboardClear(ODClipboard *somSelf, Environment *ev)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","Clear");
-
- #if ODDebugClipboard
- PRINT("ODClipboard::Clear \n");
- #endif
-
- TempSuppressFatalBentoError tempSuppress;
-
- if ( !IsFrontProcess() )
- {
- ODSetSOMException(ev, kODErrBackgroundClipboardClear);
- return;
- }
-
- #if ODDebugClipboard
- if ( (_fSU != (ODStorageUnit*) kODNULL) && (_fSU->GetRefCount(ev) != 1) )
- PRINT("ODClipboard::Clear - Storage unit refCount = %d\n", _fSU->GetRefCount(ev));
- #endif
-
- // Unless called when the process is in the background,
- // don't return an error so this method can be called in a failure handler.
- TRY
- somSelf->DiscardClipboard(ev);
- _fUpdateID = _fNextUpdateID;
- _fNextUpdateID = _fSession->UniqueUpdateID(ev);
-
- CATCH_ALL
- // ignore errors
- ENDTRY
-
- #if ODDebugClipboard
- PRINT("ODClipboard::Clear _fOriginalDraft = kODNULL\n");
- #endif
-
- _fOriginalDraft = kODNULL;
- _fOriginalCloneKind = kODCloneCopy;
- _fClonePasteCount = 0;
-
- // Remember to export to desk scrap
- _fScrapCountLastChange = _fScrapCount = GetMacScrapCount();
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::GetContentStorageUnit
- //------------------------------------------------------------------------------
- //
- // If importing from the host clipboard fails, this method returns a new, empty
- // storage unit. No alert is displayed to inform the user. This method will
- // retry importing until Clear() is called. An exception is returned only if
- // an empty clipboard cannot be created.
- //
- // If this routine is called when the process is in the background, GetScrap()
- // will probably return memFullError. Even if it did return scrap data, the
- // data would not be reliable because the forground application might be keeping
- // the true clipboard data in a private scrap. So rather than returning a scrap
- // error, just return an empty clipboard.
-
- SOM_Scope ODStorageUnit* SOMLINK ODClipboardGetContentStorageUnit(ODClipboard *somSelf, Environment *ev)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","GetContentStorageUnit");
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- short curScrapCount = GetMacScrapCount();
-
- #if ODDebugClipboard
- if ( (_fSU != (ODStorageUnit*) kODNULL) && (_fSU->GetRefCount(ev) != 1) )
- PRINT("ODClipboard::GetContentStorageUnit - Storage unit refCount = %d\n", _fSU->GetRefCount(ev));
- #endif
-
- // _fScrapCount is the platform scrap count that was last imported or in effect when the clipboard changed.
- // If "curScrapCount == _fScrapCount", the platform scrap has not changed since it was last imported.
- // _fScrapCountLastChange is the platform scrap count at the time the OpenDoc clipboard last changed.
- // If "curScrapCount == _fScrapCountLastChange", the platform scrap has not changed since the
- // OpenDoc clipboard last changed.
-
- if ( (curScrapCount != _fScrapCount) && (curScrapCount != _fScrapCountLastChange) )
- {
- // Import from desk scrap into the OpenDoc clipboard
- #if ODDebugClipboard
- PRINT("ODClipboard: GetContentStorageUnit: Updating clipboard from scrap\n");
- #endif
-
- somSelf->DiscardClipboard(ev);
-
- TRY
- if ( ScrapHasData() )
- {
- if ( !somSelf->ImportClipboard(ev) )
- {
- somSelf->NewClipboard(ev);
- somSelf->ImportContent(ev);
- }
- }
- else
- {
- somSelf->NewClipboard(ev);
- }
- _fScrapCount = curScrapCount;
- _fUpdateID = _fNextUpdateID;
- _fNextUpdateID = _fSession->UniqueUpdateID(ev);
- CATCH_ALL
- #ifdef _REPORT_SCRAP_ERRORS_
- if ( IsFrontProcess() )
- WARN("ODClipboard: GetContentStorageUnit: Importing from desk scrap raised exception %d\n", ErrorCode());
- #endif
- // Importing an OpenDoc clipboard, content, or NewClibpard failed;
- // just create a new, empty clipboard
- somSelf->DiscardClipboard(ev);
- somSelf->NewClipboard(ev);
- ENDTRY
- _fOriginalDraft = kODNULL;
- _fOriginalCloneKind = kODCloneCopy;
- _fClonePasteCount = 0;
- }
- else if ( _fContainerHandle == (ODHandle) kODNULL )
- {
- // Open a new clipboard container if a container handle doesn't exist
- // This case can only happen after an error or after Clear() is called
- somSelf->NewClipboard(ev);
- _fOriginalDraft = kODNULL;
- _fOriginalCloneKind = kODCloneCopy;
- _fClonePasteCount = 0;
- }
- else
- {
- // reopen the container handle if necessary.
- if ( _fContainer == kODNULL )
- OpenClipboard(somSelf, ev);
- if ( _fOriginalDraft == kODNULL )
- _fOriginalDraft = GetOriginalDraft(ev, _fDraft);
- }
-
- SOM_CATCH_ALL
- #ifdef _REPORT_SCRAP_ERRORS_
- WARN("ODClipboard: GetContentStorageUnit: Raising exception %d\n", ErrorCode());
- #endif
- SOM_ENDTRY
-
- return _fSU;
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::ActionDone
- //------------------------------------------------------------------------------
-
- SOM_Scope ODUpdateID SOMLINK ODClipboardActionDone(ODClipboard *somSelf, Environment *ev,
- ODCloneKind cloneKind)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","ActionDone");
-
- ODUpdateID update = kODUnknownUpdate;
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- // Note that if the clipboard is changed by one OpenDoc document,
- // and used (via Paste) in another, the sequence of undo, redo,
- // and paste actions is separate in each document. That is, the
- // first document is unaware of the Paste in the second document.
- // This isn't semantically correct, but doesn't cause errors [cc].
-
- if ( (cloneKind == kODCloneCut) || (cloneKind == kODCloneCopy) )
- {
- _fOriginalCloneKind = cloneKind;
- _fClonePasteCount = 0;
- }
- else if ( cloneKind == kODClonePaste )
- {
- _fClonePasteCount += 1;
- }
- else
- THROW(kODErrIllegalClipboardCloneKind);
-
- update = _fUpdateID;
-
- SOM_CATCH_ALL
-
- SOM_ENDTRY
-
- return update;
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::ActionUndone
- //------------------------------------------------------------------------------
-
- SOM_Scope void SOMLINK ODClipboardActionUndone(ODClipboard *somSelf, Environment *ev,
- ODUpdateID update,
- ODCloneKind originalCloneKind)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","ActionUndone");
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- if ( update == _fUpdateID )
- {
- if ( originalCloneKind == kODCloneCut )
- {
- SetOriginalCloneKind(ev, _fDraft, kODCloneCopy);
- }
- else if ( originalCloneKind == kODClonePaste )
- {
- _fClonePasteCount -= 1;
- if ( (_fClonePasteCount == 0) && (_fOriginalCloneKind == kODCloneCut) )
- SetOriginalCloneKind(ev, _fDraft, kODCloneCut);
- }
- else if ( originalCloneKind != kODCloneCopy )
- THROW(kODErrIllegalClipboardCloneKind);
- }
-
- SOM_CATCH_ALL
-
- SOM_ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::ActionRedone
- //------------------------------------------------------------------------------
-
- SOM_Scope void SOMLINK ODClipboardActionRedone(ODClipboard *somSelf, Environment *ev,
- ODUpdateID update,
- ODCloneKind originalCloneKind)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","ActionRedone");
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- if ( update == _fUpdateID )
- {
- if ( originalCloneKind == kODCloneCut )
- {
- SetOriginalCloneKind(ev, _fDraft, kODCloneCut);
- }
- else if ( originalCloneKind == kODClonePaste )
- {
- _fClonePasteCount += 1;
- if ( (_fClonePasteCount == 1) )
- SetOriginalCloneKind(ev, _fDraft, kODCloneCopy);
- }
- else if ( originalCloneKind != kODCloneCopy )
- THROW(kODErrIllegalClipboardCloneKind);
- }
-
- SOM_CATCH_ALL
-
- SOM_ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::SetPlatformClipboard
- //------------------------------------------------------------------------------
-
- SOM_Scope void SOMLINK ODClipboardSetPlatformClipboard(ODClipboard *somSelf, Environment *ev,
- ODPlatformTypeList* typeList)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","SetPlatformClipboard");
-
- ODPlatformTypeList* requestedTypes = (ODPlatformTypeList*) kODNULL;
- ODVolatile(requestedTypes);
-
- TempSuppressFatalBentoError tempSuppress;
-
- short scrapCount = GetMacScrapCount();
-
- if ( (scrapCount == _fScrapCountLastChange) && (scrapCount == _fScrapCount) )
- {
- SOM_TRY
-
- THROW_IF_ERROR(ForceZeroScrap());
-
- if ( _fSU != (ODStorageUnit*) kODNULL )
- {
- if ( typeList )
- requestedTypes = _fSession->GetStorageSystem(ev)->CreatePlatformTypeList(ev, typeList);
-
- TRY
- somSelf->ExportPlatformTypes(ev, requestedTypes);
- CATCH_ALL
- ZeroScrap();
- RERAISE;
- ENDTRY
- }
-
- SOM_CATCH_ALL
-
- SOM_ENDTRY
-
- if ( requestedTypes )
- delete requestedTypes;
-
- // Since the scrap has only been partially updated, or an error has
- // occurred, we still need to remember to transfer everything later [cc]
- _fScrapCountLastChange = _fScrapCount = GetMacScrapCount();
- }
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::ExportClipboard
- //------------------------------------------------------------------------------
- //
- // Returns a SOM exception if setting the platform clipboard fails.
- // Unfortunately, until the clipboard container is closed its size isn't known.
-
- SOM_Scope void SOMLINK ODClipboardExportClipboard(ODClipboard *somSelf, Environment *ev)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","ExportClipboard");
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- // If this clipboard was the last change to the platform scrap ("count == _fScrapCountLastChange"),
- // and this clipboard has not already been copied to the platform scrap
- // ("count == _fScrapCount"), update the platform scrap now. [cc]
-
- short count = GetMacScrapCount();
-
- #if ODDebugClipboard
- PRINT("ODClipboard::ExportClipboard called\n");
- if (count == _fScrapCountLastChange)
- {
- PRINT("ExportClipboard: OpenDoc clipboard contains last change\n");
- if ( count == _fScrapCount )
- {
- PRINT("ExportClipboard: OpenDoc clipboard needs exporting");
- if ( _fSU && _fSU->Exists(ev, kODPropLinkSpec, kODNULL, 0) )
- PRINT(" (has link spec)");
- PRINT("\n");
- }
- else if ( _fExportedLinkSpec && _fSU && !_fSU->Exists(ev, kODPropLinkSpec, kODNULL, 0) )
- PRINT("ExportClipboard: OpenDoc clipboard needs exporting to remove link spec\n");
- else
- PRINT("ExportClipboard: OpenDoc clipboard already copied to platform scrap\n");
- }
- #endif
-
- ODBoolean needToExport = kODFalse;
- ODBoolean needToExportToRemoveLinkSpec = kODFalse;
- if (count == _fScrapCountLastChange )
- {
- if ( count == _fScrapCount )
- {
- needToExport = kODTrue;
- _fExportedLinkSpec = _fSU && _fSU->Exists(ev, kODPropLinkSpec, kODNULL, 0);
- }
- else if ( _fExportedLinkSpec )
- {
- needToExportToRemoveLinkSpec = _fSU && !_fSU->Exists(ev, kODPropLinkSpec, kODNULL, 0);
- }
- }
-
- // Immediately after changing the clipboard, _fOriginalDraft won't be set correctly
- // because the clipboard is not informed when a part is finished writing. [cc]
- if ( needToExport && (_fOriginalDraft == kODNULL) )
- {
- ASSERT(_fDraft != kODNULL, kODErrAssertionFailed);
- _fOriginalDraft = GetOriginalDraft(ev, _fDraft);
- WASSERTM(_fOriginalDraft != kODNULL, "Last clipboard change did not clone");
- }
-
- if ( needToExport || needToExportToRemoveLinkSpec )
- {
- // Copy the OpenDoc clipboard to the scrap
- THROW_IF_ERROR(ForceZeroScrap());
-
- // Optimistically load the scrap into memory if it was unloaded
- LoadScrap();
-
- TRY
- somSelf->PutContentOnPlatformClipboard(ev);
- somSelf->PutClipboardOnPlatformClipboard(ev);
-
- _fScrapCountLastChange = GetMacScrapCount();
- CATCH_ALL
- // If writing the scrap fails, remove any scrap types written [cc]
- ZeroScrap();
- #ifdef _REPORT_SCRAP_ERRORS_
- PRINT("ODClipboard::ExportClipboard failed; clearing scrap\n");
- #endif
- RERAISE;
- ENDTRY
-
- #if ODDebugClipboard
- PRINT("ODClipboard::ExportClipboard updated the scrap, size is %ld\n", InfoScrap()->scrapSize);
- #endif
- }
-
- // Exporting was successful
- if ( needToExportToRemoveLinkSpec )
- _fExportedLinkSpec = kODFalse;
-
- SOM_CATCH_ALL
-
- // If we fail to update the scrap for any reason, ensure fScrapCountLastChanged
- // and fScrapCount equals the Mac scrap count, so we can try again later if
- // no other cut or copy is attempted.
- _fScrapCountLastChange = _fScrapCount = GetMacScrapCount();
-
- #if ODDebugClipboard
- PRINT("ODClipboard::ExportClipboard failed!\n");
- #endif
-
- SOM_ENDTRY
-
- #if ODDebugClipboard
- PRINT("ODClipboard::ExportClipboard done, fExportedLinkSpec = %d\n", _fExportedLinkSpec);
- #endif
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::DraftClosing
- //------------------------------------------------------------------------------
- //
- // Forces resolution of promises, and prevents moving content across draft closings
- // via the clipboard. In order to work correctly, parts MUST use BeginClone-EndClone
- // when writing to the clipboard.
-
- SOM_Scope void SOMLINK ODClipboardDraftClosing(ODClipboard *somSelf, Environment *ev,
- ODDraft* draft)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","DraftClosing");
-
- #if ODDebugClipboard
- PRINT("ODClipboard::DraftClosing called, draft is %x\n", draft);
- #endif
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- if ( draft )
- {
- // Immediately after changing the clipboard, _fOriginalDraft won't be set correctly
- // because the clipboard is not informed when a part is finished writing.
-
- short scrapCount = GetMacScrapCount();
- ODBoolean needToExport = (scrapCount == _fScrapCountLastChange) && (scrapCount == _fScrapCount);
- if ( needToExport && (_fOriginalDraft == kODNULL) )
- {
- ASSERT(_fDraft != kODNULL, kODErrAssertionFailed);
- _fOriginalDraft = GetOriginalDraft(ev, _fDraft);
- WASSERTM(_fOriginalDraft != kODNULL, "Last clipboard change did not clone");
- }
-
- #if ODDebugClipboard
- PRINT("Last draft to change clipboard is %x\n", _fOriginalDraft);
- #endif
-
- if ( _fOriginalDraft == draft )
- {
- // Last draft that wrote the clipboard is being closed.
-
- #if ODDebugClipboard
- PRINT("ODClipboard::Draft that last wrote clipboard is closing\n", draft);
- if ( needToExport )
- PRINT("ODClipboard::Clipboard needs exporting\n");
- #endif
- // If the clipboard container is open, force resolution of promises
- // by externalizing the clipboard draft. (If there are unresolved promises,
- // the clipboard hasn't be exported yet). Otherwise open the container.
-
- if ( _fContainer )
- _fDraft->Externalize(ev);
- else
- OpenClipboard(somSelf, ev);
-
- // Remove a link spec if present
- ODSURemoveProperty(ev, _fSU, kODPropLinkSpec);
-
- // Check to see if content was cut (not copied) to the clipboard.
- // If so, change the original clone kind to copy, so any future
- // paste won't be treated as a move.
-
- if ( GetOriginalCloneKind(ev, _fDraft) == kODCloneCut )
- {
- SetOriginalCloneKind(ev, _fDraft, kODCloneCopy);
- // Force exporting to platform clipboard
- _fScrapCountLastChange = _fScrapCount = GetMacScrapCount();
- }
-
- _fOriginalDraft = kODNULL;
- }
- }
-
- SOM_CATCH_ALL
- SOM_ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::DraftSaved
- //------------------------------------------------------------------------------
- //
-
- SOM_Scope void SOMLINK ODClipboardDraftSaved(ODClipboard *somSelf, Environment *ev,
- ODDraft* draft)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","DraftSaved");
-
- #if ODDebugClipboard
- PRINT("ODClipboard::DraftSaved called, draft %08x, orig %08x, fDraft %08x\n",
- (long) draft, (long) _fOriginalDraft, (long) _fDraft);
- #endif
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- // ODDraft* tDraft = _fDraft;
- // ODDraft* tOriginalDraft = _fOriginalDraft;
-
- if ( draft )
- {
- if ( _fOriginalDraft == kODNULL )
- {
- if (_fDraft != kODNULL) // can be null if never accessed
- _fOriginalDraft = GetOriginalDraft(ev, _fDraft);
-
- #if ODDebugClipboard
- PRINT(" ODClipboard::DraftSaved orig %08x\n",
- (long) _fOriginalDraft);
- #endif
- }
-
- if ( _fOriginalDraft == draft && _fDraft )
- {
- // Check to see if content was cut (not copied) to the clipboard.
- // If so, change the original clone kind to copy, so any future
- // paste won't be treated as a move.
-
- #if ODDebugClipboard
- PRINT(" ODClipboard::DraftSaved try cut -> copy\n");
- #endif
-
- if ( GetOriginalCloneKind(ev, _fDraft) == kODCloneCut )
- {
- SetOriginalCloneKind(ev, _fDraft, kODCloneCopy);
-
- #if ODDebugClipboard
- PRINT(" ODClipboard::DraftSaved perform cut -> copy\n");
- #endif
- }
- }
- }
-
- SOM_CATCH_ALL
- SOM_ENDTRY
- }
-
- //------------------------------------------------------------------------------
- // ODClipboard::ShowPasteAsDialog
- //------------------------------------------------------------------------------
-
- SOM_Scope ODBoolean SOMLINK ODClipboardShowPasteAsDialog(ODClipboard *somSelf, Environment *ev,
- ODBoolean canPasteLink,
- ODPasteAsMergeSetting mergeSetting,
- ODFacet* facet,
- ODTypeToken viewType,
- ODPasteAsResult* result)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
- ODClipboardMethodDebug("ODClipboard","ShowPasteAsDialog");
-
- ODBoolean returnValue = kODFalse;
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- THROW_IF_NULL(facet, kODErrNullFacetInput);
- THROW_IF_NULL(result, kODErrNullPasteAsResultInput);
-
- ODTypeToken modalFocus = _fSession->Tokenize(ev, kODModalFocus);
- ODArbitrator* arbitrator = _fSession->GetArbitrator(ev);
- TempODFrame currentOwner = arbitrator->AcquireFocusOwner(ev, modalFocus);
-
- if ( arbitrator->RequestFocus(ev, modalFocus, facet->GetFrame(ev)) )
- {
- ODStorageUnit* clipContentSU = somSelf->GetContentStorageUnit(ev);
-
- ODBoolean isMove = (GetOriginalCloneKind(ev, clipContentSU->GetDraft(ev)) == kODCloneCut);
-
- returnValue = ShowPasteAsDialog(
- canPasteLink,
- mergeSetting,
- isMove,
- clipContentSU,
- facet,
- viewType,
- result);
-
- arbitrator->TransferFocus(ev, modalFocus, facet->GetFrame(ev), currentOwner);
- }
- else
- {
- SysBeep(2);
- }
-
- SOM_CATCH_ALL
- SOM_ENDTRY
-
- return returnValue;
- }
-
- //==============================================================================
- // Local Functions
- //==============================================================================
-
- //------------------------------------------------------------------------------
- // GetMacScrapCount
- //------------------------------------------------------------------------------
- //
- // This function returns the identification stamp of the last mac scrap change,
- // NOT the count of items on the scrap!
-
- ODStatic short GetMacScrapCount()
- {
- return InfoScrap()->scrapCount;
- }
-
- //------------------------------------------------------------------------------
- // IsFrontProcess
- //------------------------------------------------------------------------------
-
- ODStatic ODBoolean IsFrontProcess()
- {
- ProcessSerialNumber psnFront, psnMine;
- ODBoolean frontmost;
-
- GetFrontProcess(&psnFront);
- GetCurrentProcess(&psnMine);
- SameProcess(&psnFront, &psnMine, &frontmost);
-
- return frontmost;
- }
-
- //------------------------------------------------------------------------------
- // ImportStyledTextType
- //------------------------------------------------------------------------------
-
- ODStatic void ImportStyledTextType(ODClipboard *somSelf, Environment *ev)
- {
- ODClipboardData *somThis = ODClipboardGetData(somSelf);
-
- ODHandle hndl = kODNULL;
- ODValue value;
- long dummy;
-
- ODVolatile(hndl);
-
- SOM_TRY
- TempSuppressFatalBentoError tempSuppress;
-
- // Make sure both 'TEXT' and 'styl' are present
- ODULong sizeText = GetScrap(nil, 'TEXT', &dummy);
- ODULong sizeStyl = GetScrap(nil, 'styl', &dummy);
-
- if ( (sizeText < 0) || (sizeStyl < 0) )
- return;
-
- if ( ODSUExistsThenFocus(ev, _fSU, kODPropContents, kODApplestxt) )
- {
- #ifdef _REPORT_SCRAP_ERRORS_
- WARN("ODClipboard: Replacing value on clipboard");
- #endif
- _fSU->Remove(ev);
- }
-
- ODSUForceFocus(ev, _fSU, kODPropContents, kODApplestxt);
-
- hndl = ODNewHandle(sizeStyl);
-
- sizeStyl = GetScrap((Handle) hndl, 'styl', &dummy);
- if ( sizeStyl < 0 )
- THROW(sizeStyl);
-
- value = (ODValue) ODLockHandle(hndl);
- StorageUnitSetValue(_fSU, ev, sizeStyl, value);
- ODUnlockHandle(hndl);
- ODDisposeHandle(hndl);
- hndl = kODNULL;
-
- hndl = ODNewHandle(sizeText);
-
- sizeText = GetScrap((Handle) hndl, 'TEXT', &dummy);
- if ( sizeText < 0 )
- THROW(sizeText);
-
- value = (ODValue) ODLockHandle(hndl);
- StorageUnitSetValue(_fSU, ev, sizeText, value);
-
- SOM_CATCH_ALL
- if ( ODSUExistsThenFocus(ev, _fSU, kODPropContents, kODApplestxt) )
- _fSU->Remove(ev);
- SOM_ENDTRY
-
- ODDisposeHandle(hndl);
- }
-
- //------------------------------------------------------------------------------
- // ExportStylType
- //------------------------------------------------------------------------------
- //
- // Argument is a pointer to styled text, with begins with a style record.
-
- ODStatic OSErr ExportStylType(ODPtr stxtData)
- {
- Size stylSize = *((short *) stxtData);
- stylSize = (stylSize * sizeof(ScrpSTElement)) + sizeof(short);
-
- return ClipboardPutScrap(stylSize, 'styl', stxtData);
- }
-
- //------------------------------------------------------------------------------
- // ScrapIsInconsistent
- //------------------------------------------------------------------------------
-
- ODStatic ODBoolean ScrapIsInconsistent()
- {
- // Return false if the scrap in an inconsistent state and thus cannot
- // be read. [cc]
-
- #if ODDebugClipboard
- if ( (InfoScrap()->scrapState > 0) && (InfoScrap()->scrapHandle == nil) )
- PRINT("ODClipboard: Scrap is inconsistent!\n");
- #endif
-
- return ((InfoScrap()->scrapState > 0) && (InfoScrap()->scrapHandle == nil));
-
- }
-
- //------------------------------------------------------------------------------
- // ScrapHasData
- //------------------------------------------------------------------------------
-
- ODStatic ODBoolean ScrapHasData()
- {
- // Return true if the scrap size is greater than zero and the scrap is
- // in a consistent state. [cc]
-
- return ((InfoScrap()->scrapSize > 0) && (!ScrapIsInconsistent()));
- }
-
- //------------------------------------------------------------------------------
- // ScrapHasType
- //------------------------------------------------------------------------------
-
- ODStatic ODBoolean ScrapHasType(ODPlatformType type)
- {
- long dummy;
- Size dataSize;
- ODBoolean result = kODFalse;
-
- if ( ScrapHasData() )
- {
- dataSize = GetScrap(nil, type, &dummy);
- if ( dataSize >= 0 )
- result = kODTrue;
- #ifdef _REPORT_SCRAP_ERRORS_
- else
- {
- if (dataSize != noTypeErr )
- WARN("ODClipboard: ScrapHasType: GetScrap() returned error %ld, type = %.4s", dataSize, &type);
- }
- #endif
- }
-
- return result;
- }
-
- //------------------------------------------------------------------------------
- // ForceZeroScrap
- //------------------------------------------------------------------------------
-
- ODStatic OSErr ForceZeroScrap()
- {
- OSErr err = ZeroScrap();
- if ( err == nilHandleErr )
- {
- #ifdef _REPORT_SCRAP_ERRORS_
- PRINT("ODClipboard: ZeroScrap returned error -109\n");
- #endif
- // According to Dylan Ashe, if the scrap is inconsistent the best thing to
- // do is force re-initiaization of the scrap. Use of this constant to
- // force re-initiaization will continue to work in MacOS8. [cc]
- InfoScrap()->scrapState = kUninitializedScrap;
- err = ZeroScrap();
- }
- return err;
- }
-
- //------------------------------------------------------------------------------
- // ScrapMemoryAvailable
- //------------------------------------------------------------------------------
- //
- // This function ensures than allocating dataSize bytes would still leave
- // a 40K contiguous block free, as recommended by Inside Mac, Memory, 1-43. [cc]
-
- ODStatic ODBoolean ScrapMemoryAvailable(Size dataSize)
- {
- const Size kMemCushion = 40*1024;
-
- Size totalFree;
- Size contigFree;
-
- PurgeSpace(&totalFree, &contigFree);
-
- #if ODDebugClipboard
- PRINT("Request %ld bytes with %ld available\n", dataSize, contigFree);
- #endif
-
- return (dataSize + kMemCushion) < contigFree;
- }
-
- //------------------------------------------------------------------------------
- // UnloadScrapIfMemLow
- //------------------------------------------------------------------------------
-
- ODStatic OSErr UnloadScrapIfMemLow(Size dataSize)
- {
- OSErr unloadError = noErr;
-
- if ( InfoScrap()->scrapState != kScrapOnDisk )
- {
- if ( !ScrapMemoryAvailable(dataSize) )
- {
- unloadError = UnloadScrap();
-
- #if ODDebugClipboard
- PRINT("ODClipboard: Scrap unloaded with error %d\n", unloadError);
- #endif
- }
- }
-
- return unloadError;
- }
-
- //------------------------------------------------------------------------------
- // ClipboardLoadScrap
- //------------------------------------------------------------------------------
-
- ODStatic OSErr ClipboardLoadScrap()
- {
- OSErr loadError = noErr;
-
- if ( InfoScrap()->scrapState == kScrapOnDisk )
- {
- if ( ScrapMemoryAvailable(InfoScrap()->scrapSize) )
- {
- loadError = LoadScrap();
-
- #if ODDebugClipboard
- PRINT("ODClipboard: Scrap loaded with error %d\n", loadError);
- #endif
- }
- else
- {
- loadError = kODErrOutOfMemory;
- }
- }
-
- return loadError;
- }
-
- //------------------------------------------------------------------------------
- // ClipboardPutScrap
- //------------------------------------------------------------------------------
-
- ODStatic OSErr ClipboardPutScrap(Size dataSize, ODPlatformType platformType, ODPtr data)
- {
- OSErr error = UnloadScrapIfMemLow(dataSize);
-
- if ( error == noErr )
- {
- error = (OSErr) PutScrap(dataSize, platformType, data);
-
- #ifdef _REPORT_SCRAP_ERRORS_
- WASSERTM(error == noErr, "ODClipboard: PutScrap() failed");
- #endif
- }
-
- return error;
- }