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.
Source/SVAECompare.c
/* |
File: SVAECompare.c |
Contains: |
Written by: Original version by Jon Lansdell and Nigel Humphreys. |
3.1 updates by Greg Sutton. |
Copyright: Copyright © 1995-1999 by Apple Computer, Inc., All Rights Reserved. |
You may incorporate this Apple sample source code into your program(s) without |
restriction. This Apple sample source code has been provided "AS IS" and the |
responsibility for its operation is yours. You are not permitted to redistribute |
this Apple sample source code as "Apple sample source code" after having made |
changes. If you're going to re-distribute the source, we require that you make |
it clear in the source that the code was descended from Apple sample source |
code, but that you've made changes. |
Change History (most recent first): |
7/20/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
*/ |
#include "SVAECompare.h" |
#include <AEPackObject.h> |
#include "SVEditGlobals.h" |
#include "SVEditUtils.h" |
#include "SVEditAEUtils.h" |
#include "SVEditWindow.h" |
#include "SVEditFile.h" |
#include "SVAppleEvents.h" |
#include "SVToken.h" |
#include "SVAECountElements.h" |
#include "SVAEGetData.h" |
#include <string.h> |
#pragma segment AppleEvent |
OSErr InstallObjectCallbacks(void) |
{ |
OSErr err; |
err = AESetObjectCallbacks(NewOSLCompareProc(MyCompareProc), |
NewOSLCountProc(MyCountProc), |
NULL, NULL, NULL, NULL, NULL); |
return(err); |
} |
pascal OSErr MyCompareProc(DescType oper, const AEDesc* obj1, const AEDesc* obj2, Boolean* result) |
{ |
AEDesc desc1 = {typeNull, NULL}; |
AEDesc desc2 = {typeNull, NULL}; |
AEDesc tempDesc = {typeNull, NULL}; |
OSErr err; |
err = ExtractData(obj1, &desc1); |
if (err != noErr) goto done; |
err = ExtractData(obj2, &desc2); |
if (err != noErr) goto done; |
// Make sure the 2 data types are the same |
if (desc1.descriptorType != desc2.descriptorType) |
{ |
err = AEDuplicateDesc(&desc2, &tempDesc); |
if (err != noErr) goto done; |
err = AEDisposeDesc(&desc2); |
err = AECoerceDesc(&tempDesc, desc1.descriptorType, &desc2); |
if (err != noErr) // If we can't coerce one way, try |
{ // the opposite way. |
err = AEDuplicateDesc(&tempDesc, &desc2); // We disposed of desc2 |
err = AEDisposeDesc(&tempDesc); |
err = AEDuplicateDesc(&desc1, &tempDesc); |
if (err != noErr) goto done; |
err = AEDisposeDesc(&desc1); |
err = AECoerceDesc(&tempDesc, desc2.descriptorType, &desc1); |
if (err != noErr) goto done; |
} |
} |
// Now that we know that the 2 types are the same, go ahead and run the compare |
switch(desc1.descriptorType) |
{ |
case typeChar: |
err = MyCompareText(oper, &desc1, &desc2, result); |
break; |
case typeShortInteger: |
case typeLongInteger: |
err = MyCompareInteger(oper, &desc1, &desc2, result); |
break; |
case typeBoolean: |
err = MyCompareBoolean(oper, &desc1, &desc2, result); |
break; |
default: |
err = errAEWrongDataType; |
} |
done: |
if (desc1.dataHandle) |
(void) AEDisposeDesc(&desc1); |
if (desc2.dataHandle) |
(void) AEDisposeDesc(&desc2); |
if (tempDesc.dataHandle) |
(void) AEDisposeDesc(&tempDesc); |
return(err); |
} |
OSErr ExtractData(const AEDesc *sourceDesc, AEDesc *theData) |
{ |
AEDesc intermediateDesc = {typeNull, NULL}; |
OSErr err; |
// This routine can receive: An Object specifier, an object token, a property token, or |
// some data (TEXT, Rectangle, etc.). It needs to convert whatever it's handed into data |
// and return that. |
// If we don't have any data, complain |
if (sourceDesc->descriptorType == typeNull || sourceDesc->dataHandle == NULL) |
return(errAENoSuchObject); |
// If it's an object specifier, resolve into a token |
if (sourceDesc->descriptorType == typeObjectSpecifier) |
err = AEResolve(sourceDesc, kAEIDoMinimum, &intermediateDesc); |
else // Otherwise, just copy it |
err = AEDuplicateDesc(sourceDesc, &intermediateDesc); |
if (err != noErr) goto done; |
// Now that we have a token, read from it |
switch (intermediateDesc.descriptorType) |
{ |
case typeMyApplProp: |
case typeMyTextProp: |
case typeMyWindowProp: |
case typeMyText: |
err = HandleGetData(&intermediateDesc, theData); |
break; |
default: |
// This is probably raw data , so pass it back up the line |
err = AEDuplicateDesc(&intermediateDesc, theData); |
} |
done: |
if (intermediateDesc.dataHandle) |
(void) AEDisposeDesc(&intermediateDesc); |
return(err); |
} |
OSErr MyCompareText(DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result) |
{ |
int compareResult; |
long compareSize; |
long textSize1, textSize2; |
char *testStr, *compareStr; |
OSErr err = noErr; |
textSize1 = GetHandleSize(desc1->dataHandle); |
HLockHi(desc1->dataHandle); |
textSize2 = GetHandleSize(desc2->dataHandle); |
HLockHi(desc2->dataHandle); |
if (textSize1 <= textSize2) |
{ |
switch (oper) |
{ |
case kAEBeginsWith: // Can't begin or end or contain any string |
case kAEEndsWith: // longer than itself |
case kAEContains: |
*result = false; |
return(noErr); |
} |
compareSize = textSize1; |
} |
else |
compareSize = textSize2; |
switch (oper) |
{ |
case kAEEndsWith: // Offset to end of string |
testStr = (char *)(*desc1->dataHandle + textSize1 - textSize2); |
break; |
case kAEContains: |
testStr = NewPtr(textSize1 + 1); |
BlockMove(*desc1->dataHandle, testStr, textSize1); |
testStr[textSize1] = '\0'; |
compareStr = NewPtr(textSize2 + 1); |
BlockMove(*desc2->dataHandle, compareStr, textSize2); |
compareStr[textSize2] = '\0'; |
*result = (NULL != strstr(testStr,compareStr)); |
DisposePtr(testStr); |
DisposePtr(compareStr); |
return(noErr); |
default: |
testStr = (char *)*desc1->dataHandle; |
} |
compareResult = strncmp(testStr, (char *)*desc2->dataHandle, compareSize); |
HUnlock(desc1->dataHandle); |
HUnlock(desc2->dataHandle); |
switch (oper) |
{ |
case kAEEquals: |
*result = (textSize1 == textSize2 && compareResult == 0); |
break; |
case kAEBeginsWith: |
case kAEEndsWith: |
*result = (compareResult == 0); |
break; |
case kAELessThan: |
*result = (compareResult < 0); |
break; |
case kAELessThanEquals: |
*result = (compareResult <= 0); |
break; |
case kAEGreaterThan: |
*result = (compareResult > 0); |
break; |
case kAEGreaterThanEquals: |
*result = (compareResult >= 0); |
break; |
default: |
err = errAEBadTestKey; |
} |
return(err); |
} |
OSErr MyCompareInteger(DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result) |
{ |
long num1, num2; |
AEDesc longDesc = {typeNull, NULL}; |
OSErr err; |
// Make each number is a long integer (in case it's a short integer) before extracting the data |
err = AECoerceDesc(desc1, typeLongInteger, &longDesc); |
if (err != noErr) goto done; |
num1 = **(long **)longDesc.dataHandle; |
(void) AEDisposeDesc(&longDesc); // We're done with longDesc, so dispose of it |
longDesc.dataHandle = NULL; // Mark this as disposed |
err = AECoerceDesc(desc2, typeLongInteger, &longDesc); |
if (err != noErr) goto done; |
num2 = **(long **)longDesc.dataHandle; |
// No need to dispose of this descriptor, as the code at "done" will do it for us |
switch (oper) |
{ |
case kAEEquals: |
*result = (num1 == num2); |
break; |
case kAELessThan: |
*result = (num1 < num2); |
break; |
case kAELessThanEquals: |
*result = (num1 <= num2); |
break; |
case kAEGreaterThan: |
*result = (num1 > num2); |
break; |
case kAEGreaterThanEquals: |
*result = (num1 >= num2); |
break; |
default: |
err = errAEBadTestKey; |
} |
done: |
if (longDesc.dataHandle) |
(void) AEDisposeDesc(&longDesc); |
return err; |
} // MyCompareInteger |
OSErr MyCompareBoolean (DescType oper, const AEDesc *desc1, const AEDesc *desc2, Boolean *result) |
{ |
Boolean bool1, bool2; |
OSErr err = noErr; |
// Apple events defines a boolean as a 1-byte value containing 1 for TRUE and 0 for FALSE |
// We'll use a test to convert this into C's boolean notation, just to make this easier to |
// debug |
bool1 = (**(char **)desc1->dataHandle) != 0; |
bool2 = (**(char **)desc2->dataHandle) != 0; |
if (oper == kAEEquals) |
*result = (bool1 == bool2); |
else |
err = errAEBadTestKey; // No other tests make sense |
return err; |
} // MyCompareBoolean |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-07-22