unit AEDispatch; { This module is adds some AppleEvent support to Image Written and partly debugged by Rob Douglas University of British Columbia douglas@org.ecc.ubc.ca McKellar Designs rdouglas@mckellar.com AppleEvents.p AEObjects.p AERegistry.p Errors.p 30/6/95 RMD Created Image command to send Frontier a script 2/7/95 RMD Added AppleEvents Load Macros from File "file name" Load macros with "text tring" Run Macro Number n Run Macro Named "macro name" 3/7/95 RMD Do Script "text string" AppleEvents - does not need surrounding macro/begin/end etc. RMD new Image macro command Return( arg ); sets the return value for AE } interface uses Memory, QuickDraw, Packages, Menus, Events, Fonts, Scrap, ToolUtils,Resources, Errors, Palettes, LowMem, AppleEvents,AEObjects, AERegistry, Errors,SegLoad,globals, Utilities,Text,Macros2, { Math,Background,Analysis,Camera,Stacks,Projection, globals, Utilities, Edit, Filters, Graphics, Camera, PlugIns, Macros1, Macros2, File1, File2, Lut, Text, User, } AEUtility, Msc,AEWindow,AEPicture,AEStack,AESlice,AEProfile,AERoi,AEOther,AEApplication; procedure InitAE; implementation type AppleEventPtr = ^AppleEvent; ExtendedPtr = ^Extended; BooleanPtr = ^Boolean; PointPtr = ^Point; var gFrontierAddress : AEAddressDesc; replyPtr : AppleEventPtr; ImagePSN: ProcessSerialNumber; gObjIndex:LongInt; function WindowEvents(var inAppleEvent, reply:AppleEvent; inToken: TokenPtr; theCommand: OSType):OSerr; forward; function MakeROI(var inAppleEvent:AppleEvent):OSerr; forward; function CountAEObjects(desiredType: DescType; containerClass: DescType; VAR container: AEDesc; VAR result: LONGINT): OSErr; var theError, ignoreErr:OSErr; theAEToken : AEDesc; theInfo:InfoPtr; token:TokenPtr; begin theAEToken.descriptorType := typeNull; theAEToken.dataHandle := nil; theInfo := info; if container.descriptorType = typeObjectSpecifier then begin theError := AEResolve (container, kAEIDoMinimum, @theAEToken); if theError = noErr then begin token := TokenPtr(theAEToken.dataHandle^); info := token^.containerInfo; end; end; result := CountObjects(desiredType); info := theInfo; CountAEObjects := noErr; end; function HandleGetData(var inAppleEvent, reply:AppleEvent; inToken: TokenPtr):OSerr; VAR theError:OSErr; theValueL:LongInt; theValueX:extended; theState : boolean; begin SaveCurrent(inToken); theError := errAEDescNotFound; with inToken^ do begin if containerType = 'null' then theError := ApplicationGetData(inAppleEvent, reply, inToken) else if containerType = 'cwin' then theError := WindowGetData(inAppleEvent, reply, inToken) else if containerType = 'Ipic' then theError := PictureGetData(inAppleEvent, reply, inToken) else if containerType = 'Stak' then theError := StackGetData(inAppleEvent, reply, inToken) else if containerType = 'cROI' then theError := RoiGetData(inAppleEvent, reply, inToken) else if containerType = 'wRES' then theError := ResultsGetData(inAppleEvent, reply, inToken) else if containerType = 'wPRO' then theError := ProfileGetData(inAppleEvent, reply, inToken) else if containerType = 'wHST' then theError := HistogramGetData(inAppleEvent, reply, inToken) else theError := WindowGetData(inAppleEvent, reply, inToken) end; RestoreCurrent; HandleGetData := theError; end; function HandlePutData(var inAppleEvent, reply:AppleEvent; inToken: TokenPtr) : OSErr; VAR theError:OSErr; theValueL:LongInt; theValueX:extended; theState : boolean; begin theError := errAEDescNotFound; SaveCurrent(inToken); with inToken^ do begin if containerType = 'null' then theError := ApplicationPutData(inAppleEvent, reply, inToken) else if containerType = 'cwin' then theError := WindowPutData(inAppleEvent, reply, inToken) else if containerType = 'Ipic' then theError := PicturePutData(inAppleEvent, reply, inToken) else if containerType = 'Stak' then theError := StackPutData(inAppleEvent, reply, inToken) else if containerType = 'cROI' then theError := RoiPutData(inAppleEvent, reply, inToken) else if containerType = 'wRES' then theError := ResultsPutData(inAppleEvent, reply, inToken) else if containerType = 'wPRO' then theError := ProfilePutData(inAppleEvent, reply, inToken) else theError := WindowPutData(inAppleEvent, reply, inToken); end; RestoreCurrent; HandlePutData := theError; end; { *************************************************************************************** This AE handler tried to handle object-oriented events of the core suite. *************************************************************************************** } function DispatchCoreEvents(var inAppleEvent, reply:AppleEvent; theAEToken : AEDesc; theID:OSType):OSerr; VAR theError:OSErr; begin DispatchCoreEvents := errAEEventNotHandled; if theAEToken.dataHandle = nil then exit(DispatchCoreEvents); SaveCurrent(TokenPtr(theAEToken.dataHandle^)); if theAEToken.descriptorType = 'cwin' then theError := WindowEvents(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^), theID) else if theAEToken.descriptorType = 'Ipic' then theError := PictureEvents(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^), theID) else if theAEToken.descriptorType = 'Stak' then theError := StackEvents(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^), theID) else if theAEToken.descriptorType = 'cROI' then theError := RoiEvents(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^), theID) else if theAEToken.descriptorType = 'wRES' then theError := ResultsEvents(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^), theID) else if theAEToken.descriptorType = 'wPCW' then theError := PasteEvents(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^), theID) else if theAEToken.descriptorType = 'wTXT' then theError := TextWindowEvents(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^), theID) else if theAEToken.descriptorType = 'wHST' then theError := HistogramEvents(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^), theID) else if theAEToken.descriptorType = 'wLUT' then theError := LUTEvents(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^), theID) else if theAEToken.descriptorType = 'Slic' then theError := SliceEvents(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^), theID) else if theAEToken.descriptorType = 'wPro' then theError := ProfileEvents(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^), theID) else theError := WindowEvents(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^), theID); DispatchCoreEvents := theError; RestoreCurrent; end; function HandleObjectEvents(var inAppleEvent, reply:AppleEvent; theAEObject : AEDesc; RefCon:LongInt):OSerr; VAR theError, ignoreErr:OSErr; theID, theClass:OSType; resultType:DescType; actualSize:Size; theAEToken : AEDesc; theObjectPtr : longIntPtr; theObject : Ptr; theString: str255; macroState:Boolean; objexists:Boolean; begin replyPtr := @reply; macroState := macro; macro := true; theAEToken.descriptorType := typeNull; theAEToken.dataHandle := nil; theError := AEGetAttributePtr(inAppleEvent,keyEventIDAttr, typeType, resultType, @theID, Sizeof(OSType),actualSize); theError := AEGetAttributePtr(inAppleEvent,keyEventClassAttr, typeType, resultType, @theClass, Sizeof(OSType),actualSize); if theAEObject.descriptorType = typeObjectSpecifier then begin theError := AEResolve (theAEObject, kAEIDoMinimum , @theAEToken); if theID = 'doex' then begin objexists := (theError = noErr) and (TokenPtr(theAEToken.dataHandle^)^.containerWindow <> nil); theError := ReturnBooleanProperty(reply, objexists); end else if theError = noErr then begin if theAEToken.descriptorType = typeNull then begin { theError := ApplicationEvents(inAppleEvent, reply, theAEObject, theID); if theError = errAEEventNotHandled then begin } MakeDefaultToken(theAEToken); theError := DispatchCoreEvents(inAppleEvent, reply, theAEToken, theID); { end; } end else if theAEToken.descriptorType = 'Ipro' then begin if (theID = 'getd') then theError := HandleGetData(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^)); if (theID = 'setd') then theError := HandlePutData(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^)); end else theError := DispatchCoreEvents(inAppleEvent, reply, theAEToken, theID); end else begin MakeTokenDesc(nil,'cwin',theAEToken); theError := WindowEvents(inAppleEvent, reply, TokenPtr(theAEToken.dataHandle^), theID) end; end else begin { no object specfied, try default picture } if theID = 'doex' then begin objexists := false; theError := ReturnBooleanProperty(reply, objexists); end else if (theID = 'open') or (theID = 'Impo') then begin theError := GetAEStr255(inAppleEvent, keyDirectObject, theString); MakeNewTokenDesc(theString, 'cwin', theAEToken); end else MakeDefaultToken(theAEToken); theError := DispatchCoreEvents(inAppleEvent, reply, theAEToken, theID); end; ignoreErr := AEDisposeDesc(theAEObject); ignoreErr := AEDisposeDesc(theAEToken); HandleObjectEvents := theError; replyPtr := nil; macro := macroState; end; function HandleCoreEvents(var inAppleEvent, reply:AppleEvent; RefCon:LongInt):OSerr; VAR theAEObject : AEDesc; begin HandleCoreEvents := AEGetParamDesc(inAppleEvent, keyDirectObject, typeWildCard, theAEObject); HandleCoreEvents := HandleObjectEvents(inAppleEvent, reply,theAEObject,RefCon); end; function HandleSecondEvents(var inAppleEvent, reply:AppleEvent; RefCon:LongInt):OSerr; VAR theAEObject : AEDesc; begin HandleSecondEvents := AEGetParamDesc(inAppleEvent, 'Targ', typeWildCard, theAEObject); HandleSecondEvents := HandleObjectEvents(inAppleEvent, reply,theAEObject,RefCon); end; { *************************************************************************************** This AE handler tries to create objects such as windows. *****************************ND******************************************************** } function HandleCreateEvents(var inAppleEvent, reply:AppleEvent; RefCon:LongInt):OSerr; type ODTypePtr = ^OSType; VAR result:Boolean; theError, ignoreErr:OSErr; theID:OSType; resultType:DescType; actualSize:Size; theAEObject,theAEProperties : AEDesc; theToken : AEDesc; theObjectPtr : longIntPtr; theObject : Ptr; theName : str255; theWidth, theHeight, thePicN : LongInt; begin theError := AEGetParamDesc(inAppleEvent, 'kocl', typeType, theAEObject); theName := 'Untitled'; theWidth := NewPicWidth; theHeight := NewPicHeight; ignoreErr := AEGetParamDesc(inAppleEvent, 'prdt', typeAERecord, theAEProperties); if ignoreErr = noErr then begin ignoreErr := AEStringFromKeyDesc(theAEProperties, 'pnam', theName); ignoreErr := AEIntegerFromKeyDesc(theAEProperties, 'winW', theWidth); ignoreErr := AEIntegerFromKeyDesc(theAEProperties, 'winH', theHeight); end; theID := OSTypePtr(theAEObject.dataHandle^)^; if theID = 'Stak' then begin result := NewPicWindow(theName, theWidth, theHeight); result := MakeStackFromWindow; thePicN := nPics; theError := AEPutParamPtr(reply, keyDirectObject, typeLongInteger, Ptr(@info^.PidNum), sizeof(LongInt)); end else if theID = 'Ipic' then begin result := NewPicWindow(theName, theWidth, theHeight); thePicN := nPics; theError := AEPutParamPtr(reply, keyDirectObject, typeLongInteger, Ptr(@info^.PidNum), sizeof(LongInt)); end else if theID = 'cwin' then begin result := MakeNewTextWindow(theName, theWidth, theHeight); theError := AEPutParamPtr(reply, keyDirectObject, 'TEXT', Ptr(@theName[1]), length(theName)); end else theError := errAEEventNotHandled; ignoreErr := AEDisposeDesc(theAEObject); { delete outToken ???} HandleCreateEvents := theError; end; function LookupMacroIdentifier(theString:SymbolType):integer; var i: integer; begin if MacrosP<> nil then with MacrosP^ do for i := 1 to nSymbols do begin if theString = SymbolTable[i].symbol then with SymbolTable[i] do begin LookupMacroIdentifier := i; exit(LookupMacroIdentifier); end; end; {for} LookupMacroIdentifier := 0; end; function LookupMacroVariable(theString:SymbolType):integer; var VarFound: boolean; i: integer; begin with MacrosP^ do begin VarFound := false; i := TopOfStack + 1; repeat i := i - 1; VarFound := theString = SymbolTable[ Stack[i].SymbolTableIndex ].symbol; until VarFound or (i = 1); if VarFound then end; {with} LookupMacroVariable := i; end; FUNCTION FindAnythingAccessor(desiredClass: DescType; containerToken: AEDesc; containerClass: DescType; keyForm: DescType; keyData: AEDesc; VAR outToken: AEDesc; theRefCon: LongInt): OSErr; VAR pt:Point; theToken:ObjectToken; cont:TokenPtr; theError:OSErr; theName:str255; theType:OSType; index, kind:integer; theWindow:WindowPtr; inf:InfoPtr; sym:SymbolType; BEGIN if desiredClass = 'Slic' then begin FindAnythingAccessor := FindSliceAccessor(containerToken,containerClass,keyForm,keyData,outToken); exit(FindAnythingAccessor); end; theToken.index := 0; theToken.thru := 0; FindAnythingAccessor := noErr; inf := info; theWindow := info^.wptr; if (containerToken.dataHandle <> nil) then begin cont := TokenPtr(containerToken.dataHandle^); theToken.containerWindow := cont^.containerWindow; theToken.containerInfo := cont^.containerInfo; theToken.containerType := cont^.containerType; if (theToken.containerWindow <> nil) then begin theWindow := theToken.containerWindow; info := theToken.containerInfo; end; end else begin theToken.containerWindow := nil; theToken.containerInfo := NoInfo; theToken.containerType := typeNull; end; theToken.index := 0; theToken.thru := 0; IF keyForm = formPropertyID THEN with theToken do begin { check for array names; otherwise pass as is } name := OSTypePtr(keyData.dataHandle^)^; if name = 'WdwR' then MakeTokenDesc(ResultsWindow,'wRES',outToken) else if name = 'pROI' then begin if (theToken.containerType = 'Ipic') or (theToken.containerType = 'Stak') then MakeTokenDesc(theToken.containerWindow,'cROI',outToken) else MakeTokenDesc(info^.wptr,'cROI',outToken); end else if name = 'WdwV' then MakeTokenDesc(PasteControl,'wPCW',outToken) else if name = 'WdwH' then MakeTokenDesc(HistoWindow,'wHST',outToken) else if name = 'WdwL' then MakeTokenDesc(LUTWindow,'wLUT',outToken) else if name = 'WdwP' then MakeTokenDesc(PlotWindow,'wPro',outToken) else if name = 'CurW' then MakeTokenDesc(info^.wptr,'Ipic',outToken) else if name = 'NxtW' then begin index := inf^.PicNum + 1; if index > nPics then index := 1; MakeTokenDesc(PicWindow[index],'Ipic',outToken) end else if (name = 'SliN') or (name = 'Sli+') or (name = 'Sli-') then begin if inf^.stackInfo <> nil then begin if theToken.containerWindow = nil then begin theToken.containerWindow := theWindow; theToken.containerInfo := info; end; theToken.containerType := 'Slic'; theToken.index := inf^.stackInfo^.CurrentSlice; if name = 'Sli+' then theToken.index := theToken.index + 1; if name = 'Sli-' then theToken.index := theToken.index - 1; if theToken.index > inf^.stackInfo^.nSlices then theToken.index := 1 else if theToken.index < 1 then theToken.index := inf^.stackInfo^.nSlices; end; end else if name = 'All ' then MakeTokenDesc(info^.wptr,'wAll',outToken) else if name = 'CamR' then MakeTokenDesc(nil,'VidR',outToken) else if name = 'fron' then MakeWindowToken(CurrentWPtr,outToken) else theError := AECreateDesc('Ipro', @theToken, SizeOf(ObjectToken), outToken); end else IF keyForm = formAbsolutePosition THEN begin if keyData.descriptorType = 'list' then begin theError := PointFromDesc(keyData, pt); theToken.name := desiredClass; if desiredClass = 'cPix' then begin theToken.index := LongInt(pt); end else begin theToken.index := pt.h; theToken.thru := pt.v; end; FindAnythingAccessor := AECreateDesc('Ipro', @theToken, SizeOf(ObjectToken), outToken); end else if keyData.descriptorType = typeAbsoluteOrdinal then begin theToken.name := desiredClass; if (desiredClass = 'Red ') or (desiredClass = 'Gree') or (desiredClass = 'Blue') then begin AbsoluteOrdinal(keyData, @theToken, 256); if theToken.containerWindow = nil then begin theToken.containerWindow := info^.wptr; theToken.containerInfo := info; end; theToken.containerType := 'Ipic'; FindAnythingAccessor := AECreateDesc('Ipro', @theToken, SizeOf(ObjectToken), outToken) end else if (desiredClass = 'uAvg') or (desiredClass = 'yCor') then begin AbsoluteOrdinal(keyData, @theToken, MaxStandards); FindAnythingAccessor := AECreateDesc('Ipro', @theToken, SizeOf(ObjectToken), outToken) end else if (desiredClass = 'xCor') or (desiredClass = 'Stds') then begin AbsoluteOrdinal(keyData, @theToken, nCoordinates); FindAnythingAccessor := AECreateDesc('Ipro', @theToken, SizeOf(ObjectToken), outToken) end else begin AbsoluteOrdinal(keyData, @theToken, mCount); FindAnythingAccessor := AECreateDesc('Ipro', @theToken, SizeOf(ObjectToken), outToken) end; end else begin theError := ShortFromDesc(keyData, index); theToken.name := desiredClass; theToken.index := index; FindAnythingAccessor := AECreateDesc('Ipro', @theToken, SizeOf(ObjectToken), outToken); end; end else IF keyForm = formRange THEN begin theError := GetRange(keyData, theToken.index, theToken.thru); theToken.name := desiredClass; FindAnythingAccessor := AECreateDesc('Ipro', @theToken, SizeOf(ObjectToken), outToken); end else IF (keyForm = formName ) and ( desiredClass = 'Ivar' ) then BEGIN theError := StringFromDesc(keyData, theName); if (theError = noErr) then begin sym := BlankSymbol; for index:= 1 to length(theName) do sym[index] := theName[index]; { theToken.index := LookupMacroIdentifier(sym); } theToken.index := LookupMacroVariable(sym); theToken.name := desiredClass; FindAnythingAccessor := AECreateDesc('Ipro', @theToken, SizeOf(ObjectToken), outToken); end else FindAnythingAccessor := errAEEventNotHandled; END ELSE FindAnythingAccessor := errAEEventNotHandled; gObjIndex := theToken.index; END; { *************************************************************************************** Called by Image.p when the program starts. It installs some additional AppleEvent handlers and precomputes a few things. *************************************************************************************** } procedure InitAE; var theError:OSErr; begin theError := AEObjectInit; { may not be present, so then what? Quit? } if theError <> noErr then ExitToShell; theError := AEInstallEventHandler('Imag', '****', NewAEEventHandlerProc(@HandleApplicationEvents), 0, false); theError := AEInstallEventHandler('core', 'crel', NewAEEventHandlerProc(@HandleCreateEvents), 0, false); theError := AEInstallEventHandler('Obj2', '****', NewAEEventHandlerProc(@HandleSecondEvents), 0, false); theError := AEInstallEventHandler('core', '****', NewAEEventHandlerProc(@HandleCoreEvents), 0, false); theError := AEInstallEventHandler('misc', '****', NewAEEventHandlerProc(@HandleCoreEvents), 0, false); theError := AEInstallEventHandler('Ipic', '****', NewAEEventHandlerProc(@HandleCoreEvents), 0, false); theError := AEInstallEventHandler('iRoi', '****', NewAEEventHandlerProc(@HandleCoreEvents), 0, false); theError := AEInstallEventHandler('Stak', '****', NewAEEventHandlerProc(@HandleCoreEvents), 0, false); theError := AESetObjectCallbacks(nil, NewOSLCountProc(@CountAEObjects), nil, nil,nil,nil,nil); theError := AEInstallObjectAccessor ('cwin', typeNull, NewAEEventHandlerProc(@FindWindowAccessor), 0, false); theError := AEInstallObjectAccessor ('Ipic', typeNull, NewAEEventHandlerProc(@FindPictureAccessor), 0, false); theError := AEInstallObjectAccessor ('Stak', typeNull, NewAEEventHandlerProc(@FindStackAccessor), 0, false); theError := AEInstallObjectAccessor ('****', '****', NewAEEventHandlerProc(@FindAnythingAccessor), 0, false); theError := GetTargetFromSignature('LAND', gFrontierAddress); theError := GetCurrentProcess(ImagePSN); AEisActive := false; end; end.