Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Sources/MSAECreate.c
// MSAECreate.c |
// |
// Original version by Jon Lansdell and Nigel Humphreys. |
// 4.0 and 3.1 updates by Greg Sutton. |
// ©Apple Computer Inc 1996, all rights reserved. |
/* |
14-Nov-95 : GS : Removed unused local varibale in DoNewElement(). |
*/ |
#include "MSAECreate.h" |
#include "MSGlobals.h" |
#include "MSWindow.h" |
#include "MSAEUtils.h" |
#include "MSAETextUtils.h" |
#include "MSAppleEvents.h" |
#include "MSAccessors.h" |
#include "MSAERecording.h" |
#include "MSAESelect.h" |
#include "MSAEWindowUtils.h" |
#include "MSAESetData.h" |
#pragma segment AppleEvent |
// ------------------------------------------------------------------------ |
// Name: DoNewElement |
// Purpose: Handles the NewElement AppleEvent. Creates windows and |
// text. |
// ------------------------------------------------------------------------ |
pascal OSErr DoNewElement(const AppleEvent *theAppleEvent, |
AppleEvent *reply, |
long handlerRefCon) |
{ |
#ifdef __MWERKS__ |
#pragma unused (handlerRefCon) |
#endif |
DescType returnedType, |
newElemClass; |
Size actualSize; |
AEDesc dataDesc = {typeNull, NULL}, |
insertHereDesc = {typeNull, NULL}, |
propertyDesc = {typeNull, NULL}, |
resultDesc = {typeNull, NULL}; |
OSErr ignoreErr, |
err; |
err = AEGetParamPtr(theAppleEvent, keyAEObjectClass, typeType, |
&returnedType, (Ptr)&newElemClass, sizeof(newElemClass), &actualSize); |
if (noErr != err) goto done; // We have to know what object to create |
// Get optional parameters |
ignoreErr = AEGetParamDesc(theAppleEvent, keyAEData, typeWildCard, &dataDesc); |
ignoreErr = AEGetParamDesc(theAppleEvent, keyAEInsertHere, typeWildCard, &insertHereDesc); |
ignoreErr = AEGetParamDesc(theAppleEvent, keyAEPropData, typeWildCard, &propertyDesc); |
// check for missing required parameters |
err = GotRequiredParams(theAppleEvent); |
if (noErr != err) goto done; |
switch (newElemClass) |
{ |
case cWindow: |
case cDocument: |
err = CreateDocument(&dataDesc, &insertHereDesc, &propertyDesc, &resultDesc); |
break; |
case cChar: |
case cText: |
case cWord: |
case cParagraph: |
err = CreateText(newElemClass, &dataDesc, &insertHereDesc, &propertyDesc, &resultDesc); |
break; |
default: |
err = errAEWrongDataType; |
} |
err = AddResultToReply(&resultDesc, reply, err); |
done: |
if (dataDesc.dataHandle) |
AEDisposeDesc(&dataDesc); |
if (insertHereDesc.dataHandle) |
AEDisposeDesc(&insertHereDesc); |
if (propertyDesc.dataHandle) |
AEDisposeDesc(&propertyDesc); |
if (resultDesc.dataHandle) |
AEDisposeDesc(&resultDesc); |
return(err); |
} // DoNewElement |
OSErr CreateDocument(AEDesc* dataDesc, AEDesc* insertHereDesc, |
AEDesc* propertyDesc, AEDesc* result) |
{ |
AEDesc insertDesc = {typeNull, NULL}; |
DescType insertType; |
DPtr docPtr; |
WindowPtr behindWindow; |
OSErr err; |
err = GetInsertDescFromInsertHere(insertHereDesc, &insertDesc, &insertType); |
if (noErr != err) goto done; |
err = GetBehindWindow(&insertDesc, insertType, &behindWindow); |
if (noErr != err) goto done; |
docPtr = NewDocument(false, behindWindow); |
if (! docPtr) |
{ |
err = errAENoSuchObject; |
goto done; |
} |
if (propertyDesc->dataHandle) |
err = SetDocumentPropertyRecord(docPtr->theWindow, propertyDesc); |
if (noErr != err) goto done; |
if ( dataDesc->dataHandle && dataDesc->descriptorType != typeAEList ) |
{ |
err = SetDocumentData(docPtr->theWindow, dataDesc); |
docPtr->dirty = true; |
} |
else |
docPtr->dirty = false; |
if (noErr != err) goto done; |
ShowMSWindow(docPtr->theWindow); |
err = MakeDocumentObj(docPtr->theWindow, result); |
done: |
(void)AEDisposeDesc(&insertDesc); |
return(err); |
} |
OSErr GetBehindWindow(AEDesc* insertDesc, DescType insertType, WindowPtr* behindWindow) |
{ |
AEDesc windowDesc = {typeNull, NULL}; |
WindowToken aWindowToken; |
Size actualSize; |
short index; |
OSErr err; |
if (typeNull == insertDesc->descriptorType) |
{ |
*behindWindow = (WindowPtr) -1L; |
return(noErr); |
} |
err = AECoerceDesc(insertDesc, typeMyWndw, &windowDesc); |
if (noErr != err) goto done; |
GetRawDataFromDescriptor(&windowDesc, (Ptr)&aWindowToken, |
sizeof(aWindowToken), &actualSize); |
switch (insertType) |
{ |
case kAEBeginning: |
*behindWindow = (WindowPtr) -1L; |
break; |
case kAEEnd: |
*behindWindow = NULL; |
break; |
case kAEBefore: |
index = GetWindowIndex(aWindowToken.tokenWindow); |
if (index > 1) |
*behindWindow = GetNthWindow(index - 1); |
else |
*behindWindow = (WindowPtr) -1L; // Stick at front because no |
break; // windows before that. |
case kAEAfter: |
*behindWindow = aWindowToken.tokenWindow; |
break; |
case kAEReplace: |
default: |
err = errAEEventFailed; // We won't allow a new window to replace an existing one |
} |
done: |
if (windowDesc.dataHandle) |
(void)AEDisposeDesc(&windowDesc); |
return(err); |
} |
OSErr SetDocumentPropertyRecord(WindowPtr theWindow, AEDesc* propertyRecord) |
{ |
WindowPropToken aWindowPropToken; |
AEDesc dataDesc = {typeNull, NULL}, |
propertyDesc = {typeNull, NULL}; |
AEKeyword theAEKeyword; |
long index; |
OSErr err; |
aWindowPropToken.tokenWindowToken.tokenWindow = theWindow; |
err = AECountItems(propertyRecord, &index); |
if (noErr != err) goto done; |
// Step through each property - creating a window property token AEDesc |
// and letting SetDocumentProperty() do the work. |
for (; index > 0; index--) |
{ |
err = AEGetNthDesc(propertyRecord, index, typeWildCard, &theAEKeyword, &dataDesc); |
if (noErr != err) goto done; |
aWindowPropToken.tokenProperty = theAEKeyword; |
err = AECreateDesc(typeMyDocumentProp, (Ptr)&aWindowPropToken, |
sizeof(aWindowPropToken), &propertyDesc); |
if (noErr != err) goto done; |
err = SetDocumentProperty(&propertyDesc, &dataDesc); |
if (noErr != err) goto done; |
(void)AEDisposeDesc(&dataDesc); |
(void)AEDisposeDesc(&propertyDesc); |
} |
done: |
(void)AEDisposeDesc(&dataDesc); |
(void)AEDisposeDesc(&propertyDesc); |
return(err); |
} |
// We'll just assume it's text and put it through as the selection. |
OSErr SetDocumentData( WindowPtr theWindow, AEDesc* dataDesc) |
{ |
WindowPropToken aPropToken; |
OSErr err; |
aPropToken.tokenWindowToken.tokenWindow = theWindow; |
aPropToken.tokenProperty = pSelection; |
err = SetDocumentTokenProperty( &aPropToken, dataDesc ); |
return err; |
} |
OSErr CreateText(DescType textType, AEDesc* dataDesc, AEDesc* insertHereDesc, |
AEDesc* propertyDesc, AEDesc* result) |
{ |
AEDesc insertDesc = {typeNull, NULL}; |
DescType insertType; |
TextToken anInsertToken; |
short ignore; |
OSErr err = noErr; |
err = GetInsertDescFromInsertHere(insertHereDesc, &insertDesc, &insertType); |
if (noErr != err) goto done; |
if (typeNull == insertType) // Default to setting the selection in the front window |
err = GetWindowSelection(FrontWindow(), &anInsertToken, &ignore); |
else // Otherwise get a selection from the insertDesc |
err = GetInsertToken(&insertDesc, insertType, &anInsertToken); |
if (noErr != err) goto done; |
err = CreateAtTextToken(textType, dataDesc, &anInsertToken, propertyDesc, result); |
done: |
if (insertDesc.dataHandle) |
AEDisposeDesc(&insertDesc); |
return(err); |
} |
// Get a TextToken for the location of where to insert the text. If the insertType is |
// a relative position then work this out. Otherwise just use the insertDesc. |
OSErr GetInsertToken(AEDesc* insertDesc, DescType insertType, TextToken* resultToken) |
{ |
AEDesc textDesc = {typeNull, NULL}; |
TextToken aTextToken; |
Size actualSize; |
OSErr err; |
err = AECoerceDesc(insertDesc, typeMyText, &textDesc); |
if (noErr != err) goto done; |
GetRawDataFromDescriptor(&textDesc, (Ptr)&aTextToken, |
sizeof(aTextToken), &actualSize); |
resultToken->tokenWindow = aTextToken.tokenWindow; |
switch (insertType) |
{ |
case kAEBeginning: |
case kAEBefore: |
resultToken->tokenOffset = aTextToken.tokenOffset; |
resultToken->tokenLength = 0; |
break; |
case kAEEnd: |
case kAEAfter: |
resultToken->tokenOffset = aTextToken.tokenOffset + aTextToken.tokenLength; |
resultToken->tokenLength = 0; |
break; |
case kAEReplace: |
default: // default is probably some text token to replace |
// e.g make new word at middle word of document 1 with data "Iris" |
// It has been coerced to text so it's okay |
resultToken->tokenOffset = aTextToken.tokenOffset; |
resultToken->tokenLength = aTextToken.tokenLength; |
break; |
} |
done: |
if (textDesc.dataHandle) |
(void)AEDisposeDesc(&textDesc); |
return(err); |
} |
// Create text using the dataDesc (which could be text, styled text, etcÉ) at the |
// the location held in the TextToken. |
// Properties in the propertyDesc will be applied to the new text. |
// Returns an object specifier to the text. |
OSErr CreateAtTextToken(DescType textType, const AEDesc* dataDesc, TextToken* theToken, |
AEDesc* propertyDesc, AEDesc* result) |
{ |
#ifdef __MWERKS__ |
#pragma unused(textType) |
#endif |
DPtr docPtr; |
TextToken aSelectionToken; |
short oldLength; |
OSErr err; |
docPtr = DPtrFromWindowPtr(theToken->tokenWindow); |
if (! docPtr) |
return(errAENoSuchObject); |
// Copy the current selection - so we can restore it after |
err = GetWindowSelection(theToken->tokenWindow, &aSelectionToken, &oldLength); |
if (noErr != err) goto done; |
// Set the selection we want to insert the new text into |
err = SelectTextToken(theToken); |
if (noErr != err) goto done; |
err = PutStyledTextFromDescIntoTEHandle(dataDesc, docPtr->theText); |
if (noErr != err) goto done; |
// Update the selection and get the length of the insertion |
err = UpdateSelectionToken(theToken, &aSelectionToken, oldLength, |
&theToken->tokenLength); |
if (noErr != err) goto done; |
// Need to check on token type in here and make what user wanted |
// e.g. make sure a word is a word. |
// Would have to remember to balance token for any chages to TEHandle. |
if (propertyDesc->dataHandle) |
{ // I doubt we'll handle setting the text property |
// or anything that changes the token lengthÉ oh well |
err = SetTextPropertyRecord(theToken, propertyDesc); |
if (noErr != err) goto done; |
} |
// Make the returned object |
err = MakeTextObjFromToken(theToken, result); |
done: |
return(err); |
} |
// Take a TextToken and apply the properties in the propertyRecord descriptor |
// to the text. |
// e.g. make new word at beginning of document 1 with data "Bert" Â |
// with properties {size:32, font:"Courier"} |
// The with properties part is the property record. |
OSErr SetTextPropertyRecord(TextToken* aTextToken, AEDesc* propertyRecord) |
{ |
TextPropToken aTextPropToken; |
AEDesc dataDesc = {typeNull, NULL}, |
propertyDesc = {typeNull, NULL}; |
AEKeyword theAEKeyword; |
long index; |
OSErr err; |
aTextPropToken.tokenTextToken = *aTextToken; |
err = AECountItems(propertyRecord, &index); |
if (noErr != err) goto done; |
// Step through each property - creating a window property token AEDesc |
// and letting SetWindowProperty() do the work. |
for (; index > 0; index--) |
{ |
err = AEGetNthDesc(propertyRecord, index, typeWildCard, &theAEKeyword, &dataDesc); |
if (noErr != err) goto done; |
aTextPropToken.tokenProperty = theAEKeyword; |
err = AECreateDesc(typeMyTextProp, (Ptr)&aTextPropToken, |
sizeof(aTextPropToken), &propertyDesc); |
if (noErr != err) goto done; |
err = SetTextProperty(&propertyDesc, &dataDesc); |
if (noErr != err) goto done; |
if (dataDesc.dataHandle) |
AEDisposeDesc(&dataDesc); |
if (propertyDesc.dataHandle) |
AEDisposeDesc(&propertyDesc); |
} |
done: |
if (dataDesc.dataHandle) |
AEDisposeDesc(&dataDesc); |
if (propertyDesc.dataHandle) |
AEDisposeDesc(&propertyDesc); |
return(err); |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14