mirror of
https://github.com/rn10950/RetroZilla.git
synced 2024-11-14 19:50:12 +01:00
939 lines
25 KiB
C++
939 lines
25 KiB
C++
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||
/* ***** BEGIN LICENSE BLOCK *****
|
||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||
*
|
||
* The contents of this file are subject to the Mozilla Public License Version
|
||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||
* the License. You may obtain a copy of the License at
|
||
* http://www.mozilla.org/MPL/
|
||
*
|
||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||
* for the specific language governing rights and limitations under the
|
||
* License.
|
||
*
|
||
* The Original Code is Mozilla Communicator client code.
|
||
*
|
||
* The Initial Developer of the Original Code is
|
||
* Netscape Communications Corporation.
|
||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||
* the Initial Developer. All Rights Reserved.
|
||
*
|
||
* Contributor(s):
|
||
* Simon Fraser <sfraser@netscape.com>
|
||
*
|
||
* Alternatively, the contents of this file may be used under the terms of
|
||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||
* of those above. If you wish to allow use of your version of this file only
|
||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||
* use your version of this file under the terms of the MPL, indicate your
|
||
* decision by deleting the provisions above and replace them with the notice
|
||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||
* the provisions above, a recipient may use your version of this file under
|
||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||
*
|
||
* ***** END LICENSE BLOCK ***** */
|
||
|
||
|
||
#include <Sound.h>
|
||
#include <Scrap.h>
|
||
|
||
#include "nsAEUtils.h"
|
||
#include "nsAETokens.h"
|
||
#include "nsAECoreClass.h"
|
||
#include "nsAEDocumentClass.h"
|
||
#include "nsAEWindowClass.h"
|
||
|
||
#include "nsAEApplicationClass.h"
|
||
|
||
#include "nsINativeAppSupport.h"
|
||
#include "nsCommandLineServiceMac.h"
|
||
#include "nsCOMPtr.h"
|
||
#include "nsIAppStartup.h"
|
||
#include "nsXPFEComponentsCID.h"
|
||
|
||
#include "nsComponentManagerUtils.h"
|
||
#include "nsServiceManagerUtils.h"
|
||
|
||
#ifdef MOZ_XUL_APP
|
||
#include "nsAppRunner.h"
|
||
#endif
|
||
|
||
/*----------------------------------------------------------------------------
|
||
AEApplicationClass
|
||
|
||
----------------------------------------------------------------------------*/
|
||
AEApplicationClass::AEApplicationClass()
|
||
: AEGenericClass(cApplication, typeNull)
|
||
{
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------
|
||
~AEApplicationClass
|
||
|
||
----------------------------------------------------------------------------*/
|
||
AEApplicationClass::~AEApplicationClass()
|
||
{
|
||
}
|
||
|
||
#pragma mark -
|
||
|
||
|
||
|
||
/*----------------------------------------------------------------------------
|
||
GetPropertyFromApp
|
||
|
||
Override default to customize behaviour.
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::GetProperty( DescType desiredClass,
|
||
const AEDesc* containerToken,
|
||
DescType containerClass,
|
||
DescType keyForm,
|
||
const AEDesc* keyData,
|
||
AEDesc* resultToken)
|
||
{
|
||
OSErr err;
|
||
CoreTokenRecord token;
|
||
DescType requestedProperty = **(DescType**)keyData->dataHandle;
|
||
|
||
token.dispatchClass = GetClass();
|
||
token.objectClass = GetClass();
|
||
token.propertyCode = requestedProperty;
|
||
|
||
if (CanGetProperty(requestedProperty) || CanSetProperty(requestedProperty))
|
||
{
|
||
err = AECreateDesc(cProperty, (Ptr)&token, sizeof(CoreTokenRecord), resultToken);
|
||
ThrowIfOSErr(err);
|
||
}
|
||
else
|
||
{
|
||
ThrowIfOSErr(errAEEventNotHandled);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/*----------------------------------------------------------------------------
|
||
GetItemFromContainer
|
||
|
||
Not appropriate for the application
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::GetItemFromContainer( DescType desiredClass,
|
||
const AEDesc* containerToken,
|
||
DescType containerClass,
|
||
DescType keyForm,
|
||
const AEDesc* keyData,
|
||
AEDesc* resultToken)
|
||
{
|
||
ThrowIfOSErr(errAEEventNotHandled);
|
||
}
|
||
|
||
|
||
#pragma mark -
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandleClose
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleClose(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
OSErr err = noErr;
|
||
|
||
StAEDesc saving;
|
||
StAEDesc savingIn;
|
||
|
||
// Extract the [saving yes/no/ask] optional parameter, if present
|
||
err = AEGetParamDesc(appleEvent,
|
||
keyAESaveOptions,
|
||
typeWildCard,
|
||
&saving);
|
||
|
||
if (err != errAEDescNotFound)
|
||
ThrowIfOSErr(err);
|
||
|
||
// Extract the [saving in <alias>] optional parameter, if present
|
||
err = AEGetParamDesc(appleEvent,
|
||
keyAEFile,
|
||
typeWildCard,
|
||
&savingIn);
|
||
|
||
if (err != errAEDescNotFound)
|
||
ThrowIfOSErr(err);
|
||
|
||
// Check for any required parameters we may have missed
|
||
err = CheckForUnusedParameters(appleEvent);
|
||
ThrowIfOSErr(err);
|
||
|
||
// Now, do the application-related work
|
||
SysBeep(2);
|
||
|
||
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandleCount
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleCount(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
OSErr err = noErr;
|
||
long numberOfObjects = 0L;
|
||
|
||
DescType objectClass;
|
||
|
||
if (!reply->dataHandle)
|
||
return;
|
||
|
||
// Get the class of object that we will count
|
||
err = GetObjectClassFromAppleEvent(appleEvent, &objectClass);
|
||
ThrowIfOSErr(err);
|
||
|
||
// Make sure we got & handled all of the required paramters
|
||
err = CheckForUnusedParameters(appleEvent);
|
||
ThrowIfOSErr(err);
|
||
|
||
// Send back the results
|
||
numberOfObjects = CountApplicationObjects(token, objectClass);
|
||
err = AEPutParamPtr(reply, keyAEResult, typeLongInteger, (Ptr)&numberOfObjects, sizeof(long));
|
||
ThrowIfOSErr(err);
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandleDataSize
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleDataSize(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
OSErr err = noErr;
|
||
StAEDesc data;
|
||
long size = 0L;
|
||
|
||
// First, get the data
|
||
HandleGetData(token, appleEvent, reply);
|
||
|
||
// now, extract it from the reply
|
||
err = AEGetKeyDesc(reply, keyDirectObject, typeWildCard, &data);
|
||
ThrowIfOSErr(err);
|
||
|
||
size = data.GetDataSize();
|
||
|
||
// do we leak all the data here?
|
||
err = AEPutParamPtr(reply,
|
||
keyAEResult,
|
||
typeLongInteger,
|
||
(Ptr)&size,
|
||
sizeof(long));
|
||
ThrowIfOSErr(err);
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandleDelete
|
||
|
||
All attempts to delete an empty list are handled here
|
||
Application contains documents and windows, and they can't be deleted
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleDelete(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
OSErr err = noErr;
|
||
|
||
if (AEListUtils::TokenContainsTokenList(token))
|
||
{
|
||
long numItems;
|
||
|
||
AECountItems(token, &numItems);
|
||
|
||
if (numItems > 0)
|
||
err = errAEEventNotHandled;
|
||
}
|
||
|
||
ThrowIfOSErr(err);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandleDuplicate
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleDuplicate(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
ThrowIfOSErr(errAEEventNotHandled);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandleExists
|
||
|
||
If <referenceToObject> exists...
|
||
The AEResolve() function in AERCoreSuite.c will already have filtered
|
||
out all cases where the object did not exist, so this function should
|
||
always return TRUE.
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleExists(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
OSErr err = noErr;
|
||
Boolean foundIt = true;
|
||
|
||
err = AEPutParamPtr(reply,
|
||
keyAEResult,
|
||
typeBoolean,
|
||
(Ptr)&foundIt,
|
||
sizeof(Boolean));
|
||
|
||
ThrowIfOSErr(err);
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandleMake
|
||
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleMake(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
ThrowIfOSErr(errAEEventNotHandled);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandleMove
|
||
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleMove(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
ThrowIfOSErr(errAEEventNotHandled);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandleRun
|
||
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleRun(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
OSErr err = noErr;
|
||
|
||
// do stuff on startup that we want to do
|
||
|
||
err = CheckForUnusedParameters(appleEvent);
|
||
ThrowIfOSErr(err);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandleReOpen
|
||
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleReOpen(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
OSErr err = noErr;
|
||
nsresult rv = NS_OK;
|
||
nsCOMPtr<nsINativeAppSupport> nas;
|
||
|
||
#ifdef MOZ_XUL_APP
|
||
nas = do_CreateInstance(NS_NATIVEAPPSUPPORT_CONTRACTID);
|
||
if (!nas) ThrowIfOSErr(errAEEventNotHandled);
|
||
#else
|
||
nsCOMPtr<nsIAppStartup> appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID));
|
||
NS_WARN_IF_FALSE(appStartup, "Failed to get appstartup service");
|
||
if(!appStartup) ThrowIfOSErr(errAEEventNotHandled);
|
||
|
||
rv = appStartup->GetNativeAppSupport(getter_AddRefs(nas));
|
||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Failed to get NativeAppSupport");
|
||
if(NS_FAILED(rv)) ThrowIfOSErr(errAEEventNotHandled);
|
||
#endif
|
||
|
||
rv = nas->ReOpen();
|
||
if(NS_FAILED(rv)) ThrowIfOSErr(errAEEventNotHandled);
|
||
|
||
err = CheckForUnusedParameters(appleEvent);
|
||
ThrowIfOSErr(err);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandleOpen
|
||
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleOpen(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
OSErr err;
|
||
|
||
err = CheckForUnusedParameters(appleEvent);
|
||
ThrowIfOSErr(err);
|
||
|
||
long numItems, i;
|
||
Boolean openedGroups = false;
|
||
|
||
err = ::AECountItems(token, &numItems);
|
||
ThrowIfOSErr(err);
|
||
|
||
for (i = 1; i <= numItems; i++)
|
||
{
|
||
FSSpec fSpec;
|
||
FInfo fndrInfo;
|
||
AEKeyword keywd;
|
||
DescType returnedType;
|
||
Size actualSize;
|
||
|
||
err = ::AEGetNthPtr(token, i, typeFSS, &keywd, &returnedType, (Ptr)&fSpec, sizeof(fSpec), &actualSize);
|
||
ThrowIfOSErr(err);
|
||
|
||
err = ::FSpGetFInfo(&fSpec, &fndrInfo);
|
||
ThrowIfOSErr(err);
|
||
|
||
nsMacCommandLine& cmdLine = nsMacCommandLine::GetMacCommandLine();
|
||
cmdLine.HandleOpenOneDoc(fSpec, fndrInfo.fdType);
|
||
}
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandlePrint
|
||
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandlePrint(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
OSErr err=noErr;
|
||
|
||
err = CheckForUnusedParameters(appleEvent);
|
||
ThrowIfOSErr(err);
|
||
|
||
long numItems, i;
|
||
Boolean openedGroups = false;
|
||
|
||
err = ::AECountItems(token, &numItems);
|
||
ThrowIfOSErr(err);
|
||
|
||
for (i = 1; i <= numItems; i++)
|
||
{
|
||
FSSpec fSpec;
|
||
FInfo fndrInfo;
|
||
AEKeyword keywd;
|
||
DescType returnedType;
|
||
Size actualSize;
|
||
|
||
err = ::AEGetNthPtr(token, i, typeFSS, &keywd, &returnedType, (Ptr)&fSpec, sizeof(fSpec), &actualSize);
|
||
ThrowIfOSErr(err);
|
||
|
||
err = ::FSpGetFInfo(&fSpec, &fndrInfo);
|
||
ThrowIfOSErr(err);
|
||
|
||
nsMacCommandLine& cmdLine = nsMacCommandLine::GetMacCommandLine();
|
||
cmdLine.HandlePrintOneDoc(fSpec, fndrInfo.fdType);
|
||
}
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandleQuit
|
||
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleQuit(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
// get optional saving param
|
||
StAEDesc savingParam;
|
||
TAskSave askSave = eSaveUnspecified;
|
||
|
||
OSErr err = ::AEGetKeyDesc(appleEvent, keyAESaveOptions, typeEnumeration, &savingParam);
|
||
if (err != errAEDescNotFound)
|
||
{
|
||
DescType enumValue = savingParam.GetEnumType();
|
||
|
||
switch (enumValue)
|
||
{
|
||
case 'yes ': askSave = eSaveYes; break;
|
||
case 'no ': askSave = eSaveNo; break;
|
||
case 'ask ': askSave = eSaveAsk; break;
|
||
}
|
||
}
|
||
|
||
err = CheckForUnusedParameters(appleEvent);
|
||
ThrowIfOSErr(err);
|
||
|
||
nsMacCommandLine& cmdLine = nsMacCommandLine::GetMacCommandLine();
|
||
err = cmdLine.Quit(askSave);
|
||
ThrowIfOSErr(err);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------
|
||
HandleSave
|
||
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleSave(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
ThrowIfOSErr(errAEEventNotHandled);
|
||
}
|
||
|
||
#if 0
|
||
/*----------------------------------------------------------------------------
|
||
HandleSetData
|
||
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::HandleSetData(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
|
||
{
|
||
OSErr err = noErr;
|
||
StAEDesc tokenData;
|
||
AETokenDesc tokenDesc(token);
|
||
DescType propertyCode;
|
||
|
||
if (token->descriptorType == cProperty)
|
||
{
|
||
propertyCode = tokenDesc.GetPropertyCode();
|
||
|
||
if (CanSetProperty(propertyCode))
|
||
{
|
||
// only the clipboard property is writeable
|
||
// the clipboard data should be in a list, so we extract that list
|
||
switch (propertyCode)
|
||
{
|
||
case pClipboard:
|
||
err = AEGetKeyDesc(appleEvent, keyAEData, typeAEList, &tokenData);
|
||
ThrowIfOSErr(err);
|
||
|
||
SetDataForObject(token, &tokenData); // may throw
|
||
|
||
err = AEPutKeyDesc(reply, keyDirectObject, &tokenData); // return the requested data
|
||
ThrowIfOSErr(err);
|
||
break;
|
||
|
||
default:
|
||
ThrowIfOSErr(errAENotModifiable); // "Can't set xxx to nnn"
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ThrowIfOSErr(errAENotModifiable);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ThrowIfOSErr(errAEEventNotHandled);
|
||
}
|
||
|
||
}
|
||
#endif
|
||
|
||
#pragma mark -
|
||
|
||
/*----------------------------------------------------------------------------
|
||
CountObjects
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::CountObjects( DescType desiredType,
|
||
DescType containerClass,
|
||
const AEDesc * container,
|
||
long * result)
|
||
{
|
||
long numberOfObjects = CountApplicationObjects(container, desiredType);
|
||
*result = numberOfObjects;
|
||
}
|
||
|
||
#pragma mark -
|
||
|
||
/*----------------------------------------------------------------------------
|
||
GetDataFromObject
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::GetDataFromObject(const AEDesc *token, AEDesc *desiredTypes, AEDesc *data)
|
||
{
|
||
OSErr err = noErr;
|
||
|
||
Str255 applicationName = "\p";
|
||
Str255 versionString;
|
||
|
||
ConstAETokenDesc tokenDesc(token);
|
||
|
||
ProcessSerialNumber applicationProcessNumber;
|
||
ProcessInfoRec applicationInfo;
|
||
FSSpec appFSSpec;
|
||
|
||
Boolean isFrontProcess = true; // <20><><EFBFBD> !gInBackground;
|
||
|
||
DescType aDescType = cApplication;
|
||
|
||
long documentNumber = 0L;
|
||
unsigned long elementNumber = 0L;
|
||
|
||
Boolean usePropertyCode = tokenDesc.UsePropertyCode();
|
||
DescType propertyCode;
|
||
|
||
long free;
|
||
long contiguous;
|
||
unsigned long ticks;
|
||
|
||
err = GetCurrentProcess(&applicationProcessNumber);
|
||
|
||
if (err == noErr)
|
||
{
|
||
applicationInfo.processInfoLength = sizeof(ProcessInfoRec);
|
||
applicationInfo.processName = applicationName;
|
||
applicationInfo.processAppSpec = &appFSSpec;
|
||
err = GetProcessInformation(&applicationProcessNumber, &applicationInfo);
|
||
}
|
||
|
||
GetShortVersionString(2, versionString);
|
||
PurgeSpace(&free, &contiguous);
|
||
|
||
ticks = TickCount();
|
||
|
||
propertyCode = tokenDesc.GetPropertyCode();
|
||
|
||
switch (propertyCode)
|
||
{
|
||
case pProperties:
|
||
err = AECreateList(nil, 0, true, data);
|
||
ThrowIfOSErr(err);
|
||
|
||
err = AEPutKeyPtr(data, pObjectType, typeType, &aDescType, sizeof(DescType));
|
||
err = AEPutKeyPtr(data, pName, typeChar, &applicationName[1], applicationName[0]);
|
||
err = AEPutKeyPtr(data, pVersion, typeChar, &versionString[1], versionString[0]);
|
||
err = AEPutKeyPtr(data, pIsFrontProcess, typeBoolean, &isFrontProcess, sizeof(Boolean));
|
||
err = AEPutKeyPtr(data, pFreeMemory, typeLongInteger, &free, sizeof(long));
|
||
err = AEPutKeyPtr(data, pLargestFreeBlock, typeLongInteger, &contiguous, sizeof(long));
|
||
err = AEPutKeyPtr(data, pTicks, typeLongInteger, &ticks, sizeof(long));
|
||
break;
|
||
|
||
case pBestType:
|
||
case pClass:
|
||
case pDefaultType:
|
||
case pObjectType:
|
||
err = AECreateDesc(typeType, &aDescType, sizeof(DescType), data);
|
||
break;
|
||
|
||
case pName:
|
||
err = AECreateDesc(typeChar, &applicationName[1], applicationName[0], data);
|
||
break;
|
||
|
||
case pVersion:
|
||
err = AECreateDesc(typeChar, &versionString[1], versionString[0], data);
|
||
break;
|
||
|
||
case pIsFrontProcess:
|
||
err = AECreateDesc(typeBoolean, &isFrontProcess, sizeof(Boolean), data);
|
||
break;
|
||
|
||
case pFreeMemory:
|
||
err = AECreateDesc(typeLongInteger, &free, sizeof(long), data);
|
||
break;
|
||
|
||
case pLargestFreeBlock:
|
||
err = AECreateDesc(typeLongInteger, &contiguous, sizeof(long), data);
|
||
break;
|
||
|
||
case pTicks:
|
||
err = AECreateDesc(typeLongInteger, &ticks, sizeof(long), data);
|
||
break;
|
||
|
||
case pClipboard:
|
||
#if !TARGET_CARBON
|
||
{
|
||
// Return all of the items currently on the clipboard.
|
||
// The returned information is an AEList, and each data type
|
||
// on the scrap gets its own entry in the list
|
||
// Since the OS doesn't supply the tools for getting all
|
||
// of the types in the scrap, we have to scan the scrap ourselves
|
||
|
||
char *scrapPtr;
|
||
char *scrapEnd;
|
||
PScrapStuff scrapInfo;
|
||
OSType itemType;
|
||
long itemLength;
|
||
long index;
|
||
|
||
err = AECreateList(NULL, 0, false, data);
|
||
ThrowIfOSErr(err);
|
||
|
||
err = LoadScrap(); // Make sure the scrap is in memory, not on disk.
|
||
ThrowIfOSErr(err);
|
||
|
||
scrapInfo = InfoScrap(); // Get the base address of the scrap in RAM
|
||
MoveHHi(scrapInfo->scrapHandle);
|
||
HLock (scrapInfo->scrapHandle); // ...and lock it
|
||
|
||
scrapPtr = (char *)*scrapInfo->scrapHandle;
|
||
scrapEnd = scrapPtr + scrapInfo->scrapSize;
|
||
|
||
// scan the scrap in memory and extract each scrap type
|
||
|
||
index = 1;
|
||
while (scrapPtr < scrapEnd)
|
||
{
|
||
itemType = *(OSType *)scrapPtr;
|
||
scrapPtr += sizeof(itemType);
|
||
itemLength = *(long *)scrapPtr;
|
||
scrapPtr += sizeof(itemLength);
|
||
|
||
// Move this information into the next entry on the list
|
||
err = AEPutPtr(data, index, itemType, scrapPtr, itemLength);
|
||
ThrowIfOSErr(err);
|
||
|
||
index++;
|
||
|
||
// Adjust the pointer to the start of the next item
|
||
|
||
if (itemLength & 1)
|
||
itemLength++; // If it's odd, make it even
|
||
|
||
scrapPtr += itemLength;
|
||
}
|
||
HUnlock (scrapInfo->scrapHandle);
|
||
}
|
||
#endif
|
||
break;
|
||
|
||
default:
|
||
Inherited::GetDataFromObject(token, desiredTypes, data);
|
||
break;
|
||
}
|
||
|
||
ThrowIfOSErr(err);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------
|
||
SetDataForObject
|
||
|
||
Assumption: HandleSetData() has already filtered out all attempts
|
||
to write to a read-only property.
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::SetDataForObject(const AEDesc *token, AEDesc *data)
|
||
{
|
||
OSErr err = noErr;
|
||
ConstAETokenDesc tokenDesc(token);
|
||
Boolean usePropertyCode = tokenDesc.UsePropertyCode();
|
||
DescType propertyCode;
|
||
|
||
if (usePropertyCode)
|
||
{
|
||
propertyCode = tokenDesc.GetPropertyCode();
|
||
|
||
#if !TARGET_CARBON
|
||
long numItems;
|
||
#endif
|
||
switch (propertyCode)
|
||
{
|
||
// the clipboard is the only writeable property for the application object
|
||
case pClipboard:
|
||
// The data should be an AE list containing a series of things to be placed on the
|
||
// clipboard. The data type of each item is also the clipboard type for that data
|
||
#if !TARGET_CARBON
|
||
err = ZeroScrap();
|
||
ThrowIfOSErr(err);
|
||
|
||
AECountItems(data, &numItems);
|
||
|
||
// Copy each item onto the clipboard
|
||
|
||
for (long index = 1; index <= numItems; index++)
|
||
{
|
||
StAEDesc currentItemDesc;
|
||
AEKeyword theAEKeyword;
|
||
err = AEGetNthDesc(data, index, typeWildCard, &theAEKeyword, ¤tItemDesc);
|
||
ThrowIfOSErr(err);
|
||
|
||
HLock(currentItemDesc.dataHandle);
|
||
err = PutScrap(GetHandleSize(currentItemDesc.dataHandle),
|
||
currentItemDesc.descriptorType,
|
||
*currentItemDesc.dataHandle);
|
||
ThrowIfOSErr(err);
|
||
}
|
||
#endif
|
||
break;
|
||
|
||
default:
|
||
ThrowIfOSErr(errAENotModifiable);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------------------
|
||
GetKeyEventDataAs
|
||
|
||
----------------------------------------------------------------------------*/
|
||
DescType AEApplicationClass::GetKeyEventDataAs(DescType propertyCode)
|
||
{
|
||
DescType returnType;
|
||
|
||
switch (propertyCode)
|
||
{
|
||
case pClipboard:
|
||
returnType = typeAEList;
|
||
break;
|
||
|
||
default:
|
||
returnType = typeWildCard;
|
||
|
||
}
|
||
return returnType;
|
||
}
|
||
|
||
|
||
#pragma mark -
|
||
|
||
/*----------------------------------------------------------------------------
|
||
CanSetProperty
|
||
|
||
----------------------------------------------------------------------------*/
|
||
Boolean AEApplicationClass::CanSetProperty(DescType propertyCode)
|
||
{
|
||
Boolean result = false;
|
||
|
||
switch (propertyCode)
|
||
{
|
||
// Properties we can set:
|
||
|
||
case pClipboard:
|
||
result = true;
|
||
break;
|
||
|
||
// Properties we should be able to set, but they're not implemented yet:
|
||
|
||
|
||
// Properties that are read-only
|
||
|
||
case pBestType:
|
||
case pClass:
|
||
case pDefaultType:
|
||
case pObjectType:
|
||
|
||
case pProperties:
|
||
|
||
case pFreeMemory:
|
||
case pLargestFreeBlock:
|
||
case pTicks:
|
||
|
||
case pIsFrontProcess:
|
||
case pName:
|
||
case pVersion:
|
||
case pInsertionLoc:
|
||
case pSelection:
|
||
case pUserSelection:
|
||
result = false;
|
||
break;
|
||
|
||
default:
|
||
result = Inherited::CanSetProperty(propertyCode);
|
||
break;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------------------
|
||
CanGetProperty
|
||
|
||
----------------------------------------------------------------------------*/
|
||
Boolean AEApplicationClass::CanGetProperty(DescType propertyCode)
|
||
{
|
||
Boolean result = false;
|
||
|
||
switch (propertyCode)
|
||
{
|
||
// Properties we can get:
|
||
|
||
case pBestType:
|
||
case pClass:
|
||
case pDefaultType:
|
||
case pObjectType:
|
||
|
||
case pProperties:
|
||
|
||
case pFreeMemory:
|
||
case pLargestFreeBlock:
|
||
case pTicks:
|
||
|
||
case pIsFrontProcess:
|
||
case pName:
|
||
case pVersion:
|
||
case pInsertionLoc:
|
||
case pSelection:
|
||
case pUserSelection:
|
||
result = true;
|
||
break;
|
||
|
||
// Properties we should be able to get, but they're not implemented yet:
|
||
|
||
// Properties we should not be able to get:
|
||
|
||
default:
|
||
result = Inherited::CanGetProperty(propertyCode);
|
||
break;
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
#pragma mark -
|
||
|
||
/*----------------------------------------------------------------------------
|
||
CreateSelfSpecifier
|
||
|
||
----------------------------------------------------------------------------*/
|
||
void AEApplicationClass::CreateSelfSpecifier(const AEDesc *token, AEDesc *outSpecifier)
|
||
{
|
||
OSErr err = ::AECreateDesc(typeNull, nil, 0, outSpecifier);
|
||
ThrowIfOSErr(err);
|
||
}
|
||
|
||
#pragma mark -
|
||
|
||
/*----------------------------------------------------------------------------
|
||
CountApplicationObjects
|
||
|
||
----------------------------------------------------------------------------*/
|
||
long AEApplicationClass::CountApplicationObjects(const AEDesc *token, DescType desiredType)
|
||
{
|
||
long numberOfObjects = 0;
|
||
OSErr err = noErr;
|
||
|
||
if (AEListUtils::TokenContainsTokenList(token))
|
||
{
|
||
err = AECountItems(token, &numberOfObjects);
|
||
}
|
||
else
|
||
{
|
||
AEDispatchHandler* countHandler = AECoreClass::sAECoreHandler->GetDispatchHandler(desiredType);
|
||
if (countHandler == nil)
|
||
ThrowOSErr(errAEEventNotHandled);
|
||
|
||
countHandler->CountObjects(desiredType, typeNull, token, &numberOfObjects);
|
||
/*
|
||
switch (desiredType)
|
||
{
|
||
case cDocument:
|
||
numberOfObjects = AEDocumentClass::CountDocuments();
|
||
break;
|
||
|
||
case cWindow:
|
||
numberOfObjects = AEWindowClass::CountWindows(kAnyWindowKind);
|
||
break;
|
||
|
||
// application specific classes
|
||
case cGroupWindow:
|
||
numberOfObjects = AEWindowClass::CountWindows(kUserGroupWindowKind);
|
||
break;
|
||
|
||
|
||
default:
|
||
err = errAEEventNotHandled;
|
||
break;
|
||
}
|
||
*/
|
||
}
|
||
|
||
ThrowIfOSErr(err);
|
||
return numberOfObjects;
|
||
}
|