home *** CD-ROM | disk | FTP | other *** search
/ AppleScript - The Beta Release / AppleScript - The Beta Release.iso / Development Tools / Unsupported Tools / Sample OSA Component / OSASampleComponent.p < prev    next >
Encoding:
Text File  |  1992-11-25  |  24.0 KB  |  809 lines  |  [TEXT/MPS ]

  1. { Copyright © 1992 Apple Computer, Inc. All rights reserved.}
  2.  
  3. { This is a sample program to implement the OSA interface. }
  4. { In this sample program, the source is the same as the internal compiled form. }
  5. { So compile and decompile just consists of copying and rename, and this is very unlike other OSA implementation. }
  6. { However, there is a lot of scripting language which just interprets the source and this sample program can be useful }
  7.  
  8. UNIT OSASample;
  9.  
  10. INTERFACE
  11.  
  12.     USES Errors, Notification, Components, Processes, Aliases, AppleEvents, OSA, OSAComp;
  13.  
  14.     FUNCTION Main(VAR params: ComponentParameters;
  15.                                 storage: Handle): ComponentResult;
  16.  
  17. IMPLEMENTATION
  18.  
  19.     CONST
  20.         MaxIDSlot = 100;
  21.         MySignature = 'SMPL';
  22.  
  23.     TYPE
  24.         GlobalsHandle = ^GlobalsPtr;
  25.         GlobalsPtr = ^GlobalsRecord;
  26.         GlobalsRecord = RECORD
  27.                                             gSelf: ComponentInstance;
  28.                                             errorNumber: OSErr;
  29.                                             errorDesc: AEDesc;
  30.                                             scriptIDSlot: ARRAY [1..MaxIDSlot] OF AEDesc;
  31.                                         END;
  32.  
  33.     PROCEDURE IgnoreOSErr(anErr: OSErr);
  34.         INLINE $548F; { addq #2,sp }
  35.  
  36.     FUNCTION MyClose(globals: GlobalsHandle;
  37.                                      self: ComponentInstance): ComponentResult;
  38.         FORWARD;
  39.  
  40.     FUNCTION MyCanDo(void: GlobalsHandle;
  41.                                      selector: INTEGER): ComponentResult;
  42.         FORWARD;
  43.  
  44.     FUNCTION DoOSALoad(globals: GlobalsHandle;
  45.                                          scriptData: AEDesc;
  46.                                          modeFlags: LONGINT;
  47.                                          VAR resultingScriptID: OSAID): ComponentResult;
  48.         FORWARD;
  49.  
  50.     FUNCTION DoOSAStore(globals: GlobalsHandle;
  51.                                             scriptID: OSAID;
  52.                                             desiredType: DescType;
  53.                                             modeFlags: LONGINT;
  54.                                             VAR resultingScriptData: AEDesc): ComponentResult;
  55.         FORWARD;
  56.  
  57.     FUNCTION DoOSADispose(globals: GlobalsHandle;
  58.                                                 scriptID: OSAID): ComponentResult;
  59.         FORWARD;
  60.  
  61.     FUNCTION DoOSAScriptError(globals: GlobalsHandle;
  62.                                                         selector: OSType;
  63.                                                         desiredType: DescType;
  64.                                                         VAR resultingErrorDescription: AEDesc): ComponentResult;
  65.         FORWARD;
  66.  
  67.     FUNCTION DoOSAExecute(globals: GlobalsHandle;
  68.                                                 compiledScriptID: OSAID;
  69.                                                 contextID: OSAID;
  70.                                                 modeFlags: LONGINT;
  71.                                                 VAR resultingScriptValueID: OSAID): ComponentResult;
  72.         FORWARD;
  73.  
  74.     FUNCTION DoOSAScriptingComponentName(globals: GlobalsHandle;
  75.                                                                              VAR resultingScriptingComponentName: AEDesc): OSAError;
  76.         FORWARD;
  77.  
  78.     FUNCTION DoOSACompile(globals: GlobalsHandle;
  79.                                                 sourceData: AEDesc;
  80.                                                 modeFlags: LONGINT;
  81.                                                 VAR resultingCompiledScriptID: OSAID): ComponentResult;
  82.         FORWARD;
  83.  
  84.     FUNCTION DoOSAGetSource(globals: GlobalsHandle;
  85.                                                     scriptID: OSAID;
  86.                                                     desiredType: DescType;
  87.                                                     VAR resultingSourceData: AEDesc): ComponentResult;
  88.         FORWARD;
  89.  
  90.     FUNCTION DoOSACoerceFromDesc(globals: GlobalsHandle;
  91.                                                              scriptData: AEDesc;
  92.                                                              VAR resultingScriptValueID: OSAID): ComponentResult;
  93.         FORWARD;
  94.  
  95.     FUNCTION DoOSACoerceToDesc(globals: GlobalsHandle;
  96.                                                          scriptValueID: OSAID;
  97.                                                          desiredType: DescType;
  98.                                                          VAR result: AEDesc): ComponentResult;
  99.         FORWARD;
  100.  
  101.     FUNCTION DoOSALoadExecute(globals: GlobalsHandle;
  102.                                                         scriptData: AEDesc;
  103.                                                         contextID: OSAID;
  104.                                                         modeFlags: LONGINT;
  105.                                                         VAR resultingScriptValueID: OSAID): ComponentResult;
  106.         FORWARD;
  107.  
  108.     FUNCTION DoOSACompileExecute(globals: GlobalsHandle;
  109.                                                              sourceData: AEDesc;
  110.                                                              contextID: OSAID;
  111.                                                              modeFlags: LONGINT;
  112.                                                              VAR resultingScriptValueID: OSAID): ComponentResult;
  113.         FORWARD;
  114.  
  115.     FUNCTION DoOSADoScript(globals: GlobalsHandle;
  116.                                                  sourceData: AEDesc;
  117.                                                  contextID: OSAID;
  118.                                                  desiredType: DescType;
  119.                                                  modeFlags: LONGINT;
  120.                                                  VAR resultingText: AEDesc): ComponentResult;
  121.         FORWARD;
  122.  
  123.     FUNCTION DoOSAMakeContext(contextName: StringPtr;
  124.                                                         parentContext: OSAID;
  125.                                                         VAR resultingContextID: OSAID): ComponentResult;
  126.         FORWARD;
  127.  
  128.     FUNCTION DoOSADisplay(globals: GlobalsHandle;
  129.                                                 scriptValueID: OSAID;
  130.                                                 desiredType: DescType;
  131.                                                 modeFlags: LONGINT;
  132.                                                 VAR resultingText: AEDesc): ComponentResult;
  133.         FORWARD;
  134.  
  135.     FUNCTION Main(VAR params: ComponentParameters;
  136.                                 storage: Handle): ComponentResult;
  137.  
  138.         VAR
  139.             globals: GlobalsHandle;
  140.             self: ComponentInstance;
  141.             err: ComponentResult;
  142.             myErrDesc: AEDesc;
  143.  
  144.         BEGIN
  145.             IF params.what < 0 THEN { Negative selectors used for component manager calls }
  146.                 CASE (params.what) OF
  147.  
  148.                     kComponentOpenSelect:
  149.                         BEGIN
  150.                         globals := GlobalsHandle(NewHandleClear(sizeof(GlobalsRecord)));
  151.                         IF globals = NIL THEN
  152.                             err := MemError
  153.                         ELSE
  154.                             BEGIN
  155.                             err := AECreateDesc(typeChar, NIL, 0, myErrDesc);
  156.                             IF err = NoErr THEN
  157.                                 BEGIN
  158.                                 self := ComponentInstance(params.params[0]);
  159.                                 SetComponentInstanceStorage(self, Handle(globals));
  160.                                 WITH globals^^ DO
  161.                                     BEGIN
  162.                                     gSelf := self;
  163.                                     errorDesc := myErrDesc;
  164.                                     END;
  165.                                 END
  166.                             ELSE
  167.                                 DisposHandle(Handle(globals));
  168.                             END;
  169.                         END;
  170.  
  171.                     kComponentCloseSelect: err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@MyClose));
  172.  
  173.                     kComponentCanDoSelect: err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@MyCanDo));
  174.  
  175.                     kComponentVersionSelect: err := 0;
  176.  
  177.                     OTHERWISE err := badComponentSelector;
  178.                 END { Component Manager calls }
  179.  
  180.             ELSE { Specific component routines called through the component manager }
  181.                 BEGIN
  182.                 CASE (params.what) OF
  183.                     kOSASelectLoad: err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@DoOSALoad));
  184.  
  185.                     kOSASelectStore: err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@DoOSAStore));
  186.  
  187.                     kOSASelectExecute:
  188.                         err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@DoOSAExecute));
  189.  
  190.                     kOSASelectDisplay:
  191.                         err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@DoOSADisplay));
  192.  
  193.                     kOSASelectScriptError:
  194.                         err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@DoOSAScriptError));
  195.  
  196.                     kOSASelectDispose:
  197.                         err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@DoOSADispose));
  198.  
  199.                     kOSASelectCompile:
  200.                         err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@DoOSACompile));
  201.  
  202.                     kOSASelectGetSource:
  203.                         err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@DoOSAGetSource));
  204.  
  205.                     kOSASelectScriptingComponentName:
  206.                         err := CallComponentFunctionWithStorage(storage, params,
  207.                                                                                                              ComponentRoutine(@DoOSAScriptingComponentName));
  208.  
  209.                     kOSASelectCoerceFromDesc:
  210.                         err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@DoOSACoerceFromDesc));
  211.  
  212.                     kOSASelectCoerceToDesc:
  213.                         err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@DoOSACoerceToDesc));
  214.  
  215.                     kOSASelectLoadExecute:
  216.                         err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@DoOSALoadExecute));
  217.  
  218.                     kOSASelectCompileExecute:
  219.                         err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@DoOSACompileExecute));
  220.  
  221.                     kOSASelectDoScript:
  222.                         err := CallComponentFunctionWithStorage(storage, params, ComponentRoutine(@DoOSADoScript));
  223.  
  224.                     kOSASelectMakeContext: err := CallComponentFunction(params, ComponentRoutine(@DoOSAMakeContext));
  225.  
  226.                     OTHERWISE
  227.                         BEGIN
  228.                         err := badComponentSelector;
  229.                         END;
  230.                 END;
  231.                 END;
  232.             Main := err;
  233.         END;
  234.  
  235.     FUNCTION MyClose(globals: GlobalsHandle;
  236.                                      self: ComponentInstance): ComponentResult;
  237.  
  238.         VAR
  239.             i: integer;
  240.  
  241.         BEGIN
  242.             HLock(Handle(globals));
  243.             WITH globals^^ DO
  244.                 BEGIN
  245.                 IgnoreOSErr(AEDisposeDesc(errorDesc));
  246.                 FOR i := 1 TO MaxIDSlot DO { dispose all the descriptors in the slots }
  247.                     IgnoreOSErr(AEDisposeDesc(scriptIDSlot[i]));
  248.                 END;
  249.             HUnLock(Handle(globals));
  250.             MyClose := noErr;
  251.         END;
  252.  
  253.     FUNCTION MyCanDo(void: GlobalsHandle;
  254.                                      selector: INTEGER): ComponentResult;
  255.  
  256.         BEGIN
  257.             MyCanDo := 1 { Should have gone through every selector that is supported }
  258.         END;
  259.  
  260.     { utility procedures }
  261.  
  262.     PROCEDURE ClearErrorDesc(globals: GlobalsHandle);
  263.     { clean up the error message }
  264.  
  265.         BEGIN
  266.             WITH globals^^ DO
  267.                 BEGIN
  268.                 errorNumber := NoErr;
  269.                 SetHandleSize(errorDesc.dataHandle, 0);
  270.                 END;
  271.         END;
  272.  
  273.     FUNCTION TryDoScript(globals: GlobalsHandle;
  274.                                              scriptData: AEDesc;
  275.                                              VAR num: Integer): ComponentResult;
  276.     { try to compile the text and return the result }
  277.     { we just try to translate one, two, three etc into number in this simple example }
  278.  
  279.         VAR
  280.             aStr: Str255;
  281.             err: OSErr;
  282.  
  283.         BEGIN
  284.             num := 0;
  285.             IF scriptData.descriptorType = MySignature THEN
  286.                 BEGIN
  287.                 GetIText(scriptData.dataHandle, aStr);
  288.                 UprString(aStr, false);
  289.                 IF aStr = 'ONE' THEN
  290.                     num := 1
  291.                 ELSE IF aStr = 'TWO' THEN
  292.                     num := 2
  293.                 ELSE IF aStr = 'THREE' THEN
  294.                     num := 3
  295.                 ELSE IF aStr = 'FOUR' THEN
  296.                     num := 4
  297.                 ELSE IF aStr = 'FIVE' THEN
  298.                     num := 5
  299.                 ELSE IF aStr = 'SIX' THEN
  300.                     num := 6
  301.                 ELSE IF aStr = 'SEVEN' THEN
  302.                     num := 7
  303.                 ELSE IF aStr = 'EIGHT' THEN
  304.                     num := 8
  305.                 ELSE IF aStr = 'NINE' THEN
  306.                     num := 9
  307.                 ELSE IF aStr = 'TEN' THEN num := 10;
  308.                 ClearErrorDesc(globals);
  309.                 IF num = 0 THEN
  310.                     BEGIN
  311.                     err := errOSAScriptError;
  312.                     aStr := Concat('Cannot understand ', aStr);
  313.                     WITH globals^^ DO
  314.                         BEGIN
  315.                         errorNumber := err;
  316.                         IgnoreOSErr(PtrToXHand(@aStr[1], errorDesc.dataHandle, length(aStr)));
  317.                         END;
  318.                     END
  319.                 ELSE
  320.                     err := 0;
  321.                 END
  322.             ELSE
  323.                 err := errOSABadStorageType;
  324.             TryDoScript := err;
  325.         END;
  326.  
  327.     FUNCTION ActualDoScript(globals: GlobalsHandle;
  328.                                                     scriptData: AEDesc;
  329.                                                     VAR result: AEDesc): ComponentResult;
  330.     { execute the script and return a number or set the error result }
  331.  
  332.         VAR
  333.             num: integer;
  334.             err: OSErr;
  335.  
  336.         BEGIN
  337.             err := TryDoScript(globals, scriptData, num);
  338.             IF err = NoErr THEN err := AECreateDesc(typeShortInteger, @num, SizeOf(Integer), result);
  339.             ActualDoScript := err;
  340.         END;
  341.  
  342.     PROCEDURE NukeIt(VAR theDesc: AEDesc);
  343.     { make a null descriptor }
  344.  
  345.         BEGIN
  346.             WITH theDesc DO
  347.                 BEGIN
  348.                 descriptorType := typeNull;
  349.                 dataHandle := NIL;
  350.                 END;
  351.         END;
  352.  
  353.     FUNCTION FindScriptIDSlot(globals: GlobalsHandle): longint;
  354.     { search for a empty slot and return the slot ID, return 0 if none is available }
  355.  
  356.         VAR
  357.             i: integer;
  358.  
  359.         BEGIN
  360.             FindScriptIDSlot := 0;
  361.             WITH globals^^ DO
  362.                 FOR i := 1 TO MaxIDSlot DO
  363.                     IF scriptIDSlot[i].dataHandle = NIL THEN
  364.                         BEGIN
  365.                         FindScriptIDSlot := i;
  366.                         LEAVE;
  367.                         END;
  368.         END;
  369.  
  370.     FUNCTION FindSlotAndPutIt(globals: GlobalsHandle;
  371.                                                         theDesc: AEDesc;
  372.                                                         VAR slotID: longint): ComponentResult;
  373.     { put a desc into a slot, if slotID starts as 0 find a new slot, otherwise reuse the slot ID }
  374.  
  375.         VAR
  376.             err: OSErr;
  377.             oldDesc: AEDesc;
  378.  
  379.         BEGIN
  380.             IF theDesc.dataHandle = NIL THEN
  381.                 BEGIN { we don't have a descriptor, return 0 }
  382.                 slotID := 0;
  383.                 err := memFullErr;
  384.                 END
  385.             ELSE
  386.                 BEGIN
  387.                 IF slotID = 0 THEN
  388.                     slotID := FindScriptIDSlot(globals) { find an empty slot }
  389.                 ELSE
  390.                     BEGIN { reuse an existing slot, we first dispose the old content }
  391.                     oldDesc := globals^^.ScriptIDSlot[slotID];
  392.                     IgnoreOSErr(AEDisposeDesc(oldDesc));
  393.                     END;
  394.                 IF slotID <> 0 THEN
  395.                     BEGIN { now we put the descriptor inot the slot }
  396.                     globals^^.ScriptIDSlot[slotID] := theDesc;
  397.                     err := NoErr;
  398.                     END
  399.                 ELSE
  400.                     BEGIN
  401.                     err := memFullErr; { no slot available, treat it as memory error because in a more realistic program we
  402.                                                             would expand the slot s }
  403.                     slotID := 0;
  404.                     IgnoreOSErr(AEDisposeDesc(theDesc));
  405.                     END;
  406.                 END;
  407.             FindSlotAndPutIt := err;
  408.         END;
  409.  
  410.     FUNCTION TextToStxt(textDesc: AEDesc;
  411.                                             VAR result: AEDesc): OSErr;
  412.     { convert TEXT to styled text }
  413.  
  414.         TYPE
  415.             myStyleRec = RECORD
  416.                                          scrpNStyles: integer;
  417.                                          scrpStyle: ScrpSTElement;
  418.                                      END;
  419.  
  420.         VAR
  421.             err: OSErr;
  422.             theRec: AERecord;
  423.             myStyle: myStyleRec;
  424.  
  425.         BEGIN
  426.             result.dataHandle := NIL;
  427.             myStyle.scrpNStyles := 1;
  428.             WITH myStyle.scrpStyle DO
  429.                 BEGIN
  430.                 scrpStartChar := 0;
  431.                 scrpHeight := 16;
  432.                 scrpAscent := 12;
  433.                 scrpFont := 1;
  434.                 scrpFace := [bold];
  435.                 scrpSize := 12;
  436.                 scrpColor.red := 0;
  437.                 scrpColor.green := 0;
  438.                 scrpColor.blue := 0;
  439.                 END;
  440.             err := AECreateList(NIL, 0, true, theRec);
  441.             IF err = NoErr THEN
  442.                 BEGIN
  443.                 err := AEPutKeyPtr(theRec, 'ksty', 'styl', @myStyle, SizeOf(myStyle));
  444.                 IF err = NoErr THEN err := AEPutKeyDesc(theRec, 'ktxt', textDesc);
  445.                 IF err = NoErr THEN
  446.                     BEGIN
  447.                     err := AECoerceDesc(theRec, 'STXT', result);
  448.                     IgnoreOSErr(AEDisposeDesc(theRec));
  449.                     END
  450.                 ELSE
  451.                     IgnoreOSErr(AEDisposeDesc(theRec));
  452.                 END;
  453.             TextToStxt := err;
  454.         END;
  455.  
  456.     { the OSA component procedures }
  457.  
  458.     FUNCTION DoOSALoad(globals: GlobalsHandle;
  459.                                          scriptData: AEDesc;
  460.                                          modeFlags: LONGINT;
  461.                                          VAR resultingScriptID: OSAID): ComponentResult;
  462.     { make a copy, strip the trailer and put it into a slot }
  463.  
  464.         VAR
  465.             err: ComponentResult;
  466.             descCopy: AEDesc;
  467.             itsType: DescType;
  468.  
  469.         BEGIN
  470.             err := errOSABadStorageType;
  471.             IF (scriptData.descriptorType = kOSAGenericScriptingComponentSubtype) THEN
  472.                 IF OSAGetStorageType(scriptData.dataHandle, itsType) = NoErr THEN
  473.                     IF itsType = MySignature THEN
  474.                         BEGIN
  475.                         err := AEDuplicateDesc(scriptData, descCopy);
  476.                         IF err = NoErr THEN err := OSARemoveStorageType(descCopy.dataHandle);
  477.                         descCopy.descriptorType := MySignature; { internally we store as as type 'SMPL' }
  478.                         resultingScriptID := 0; { we want a new OSAID }
  479.                         err := FindSlotAndPutIt(globals, descCopy, resultingScriptID);
  480.                         END;
  481.             DoOSALoad := err;
  482.         END;
  483.  
  484.     FUNCTION DoOSAStore(globals: GlobalsHandle;
  485.                                             scriptID: OSAID;
  486.                                             desiredType: DescType;
  487.                                             modeFlags: LONGINT;
  488.                                             VAR resultingScriptData: AEDesc): ComponentResult;
  489.     { make a copy of content in the slot and add trailer }
  490.  
  491.         VAR
  492.             err: ComponentResult;
  493.  
  494.         BEGIN
  495.             NukeIt(resultingScriptData);
  496.             IF (scriptID = 0) | (scriptID > MaxIDSlot) THEN
  497.                 err := errOSAInvalidID
  498.             ELSE
  499.                 BEGIN
  500.                 resultingScriptData := globals^^.ScriptIDSlot[scriptID];
  501.                 IF resultingScriptData.dataHandle = NIL THEN
  502.                     err := errOSAInvalidID
  503.                 ELSE
  504.                     BEGIN
  505.                     err := HandToHand(resultingScriptData.dataHandle);
  506.                     IF err <> NoErr THEN NukeIt(resultingScriptData);
  507.                     END;
  508.                 IF err = NoErr THEN
  509.                     BEGIN
  510.                     err := OSAAddStorageType(resultingScriptData.dataHandle, resultingScriptData.descriptorType);
  511.                     IF err = NoErr THEN
  512.                         resultingScriptData.descriptorType := kOSAGenericScriptingComponentSubtype
  513.                     ELSE
  514.                         IgnoreOSErr(AEDisposeDesc(resultingScriptData));
  515.                     END;
  516.                 END;
  517.             DoOSAStore := err;
  518.         END;
  519.  
  520.     FUNCTION DoOSAScriptError(globals: GlobalsHandle;
  521.                                                         selector: OSType;
  522.                                                         desiredType: DescType;
  523.                                                         VAR resultingErrorDescription: AEDesc): ComponentResult;
  524.     { fetch the content of the error descriptor }
  525.  
  526.         VAR
  527.             err: ComponentResult;
  528.             i: longint;
  529.             aRec: AERecord;
  530.             myErrorDesc: AEDesc;
  531.             errNum: integer;
  532.  
  533.         BEGIN
  534.             NukeIt(resultingErrorDescription);
  535.             IF selector = kOSAErrorNumber THEN
  536.                 BEGIN
  537.                 errNum := globals^^.errorNumber;
  538.                 err := AECoercePtr(typeShortInteger, @errNum, SizeOf(Integer), desiredType, resultingErrorDescription);
  539.                 END
  540.             ELSE IF selector = kOSAErrorMessage THEN
  541.                 BEGIN
  542.                 myErrorDesc := globals^^.errorDesc;
  543.                 IF (desiredType = typeChar) | (desiredType = typeWildCard) THEN
  544.                     err := AEDuplicateDesc(myErrorDesc, resultingErrorDescription)
  545.                 ELSE IF desiredType = 'STXT' THEN
  546.                     err := TextToStxt(myErrorDesc, resultingErrorDescription)
  547.                 ELSE
  548.                     err := AECoerceDesc(myErrorDesc, desiredType, resultingErrorDescription);
  549.                 END
  550.             ELSE IF selector = kOSAErrorRange THEN
  551.                 BEGIN { in this simple example, we make the error range to include everything }
  552.                 err := AECreateList(NIL, 0, true, aRec);
  553.                 IF err = NoErr THEN
  554.                     BEGIN
  555.                     i := 0;
  556.                     IgnoreOSErr(AEPutKeyPtr(aRec, keySourceStart, typeLongInteger, @i, SizeOf(i)));
  557.                     i := 30000;
  558.                     IgnoreOSErr(AEPutKeyPtr(aRec, keySourceEnd, typeLongInteger, @i, SizeOf(i)));
  559.                     IF desiredType = typeAERecord THEN
  560.                         resultingErrorDescription := aRec
  561.                     ELSE
  562.                         BEGIN
  563.                         IF desiredType = typeWildCard THEN desiredType := typeOSAErrorRange;
  564.                         err := AECoerceDesc(aRec, desiredType, resultingErrorDescription);
  565.                         IgnoreOSErr(AEDisposeDesc(aRec));
  566.                         END;
  567.                     END;
  568.                 END
  569.             ELSE
  570.                 err := errOSABadSelector;
  571.             DoOSAScriptError := err;
  572.         END;
  573.  
  574.     FUNCTION DoOSADispose(globals: GlobalsHandle;
  575.                                                 scriptID: OSAID): ComponentResult;
  576.     { dispose the descriptor in the slot }
  577.  
  578.         BEGIN
  579.             IF (scriptID > 0) & (scriptID <= MaxIDSlot) THEN
  580.                 BEGIN
  581.                 HLock(Handle(globals));
  582.                 IgnoreOSErr(AEDisposeDesc(globals^^.ScriptIDSlot[scriptID]));
  583.                 HUnLock(Handle(globals));
  584.                 END;
  585.             DoOSADispose := NoErr;
  586.         END;
  587.  
  588.     FUNCTION DoOSAExecute(globals: GlobalsHandle;
  589.                                                 compiledScriptID: OSAID;
  590.                                                 contextID: OSAID;
  591.                                                 modeFlags: LONGINT;
  592.                                                 VAR resultingScriptValueID: OSAID): ComponentResult;
  593. { since in this sample program, internal form is the same as source form except for the descriptor type, we can just call CompileExecute }
  594.  
  595.         BEGIN
  596.             resultingScriptValueID := 0;
  597.             IF (compiledScriptID <= 0) | (compiledScriptID > MaxIDSlot) THEN
  598.                 DoOSAExecute := errOSAInvalidID
  599.             ELSE
  600.                 DoOSAExecute := DoOSACompileExecute(globals, globals^^.ScriptIDSlot[compiledScriptID], contextID, modeFlags,
  601.                                                                                         resultingScriptValueID);
  602.         END;
  603.  
  604.     FUNCTION DoOSADisplay(globals: GlobalsHandle;
  605.                                                 scriptValueID: OSAID;
  606.                                                 desiredType: DescType;
  607.                                                 modeFlags: LONGINT;
  608.                                                 VAR resultingText: AEDesc): ComponentResult;
  609.     { in this program, we have no special form for display so just coerce it }
  610.  
  611.         BEGIN
  612.             DoOSADisplay := DoOSACoerceToDesc(globals, scriptValueID, desiredType, resultingText);
  613.         END;
  614.  
  615.     FUNCTION DoOSACompile(globals: GlobalsHandle;
  616.                                                 sourceData: AEDesc;
  617.                                                 modeFlags: LONGINT;
  618.                                                 VAR resultingCompiledScriptID: OSAID): ComponentResult;
  619. { since internal form is same as source, just change the dataType and call TryDoScript, if it compiles then just store it }
  620.  
  621.         VAR
  622.             err: ComponentResult;
  623.             descCopy, oldCopy: AEDesc;
  624.             num: integer;
  625.  
  626.         BEGIN
  627.             descCopy.dataHandle := NIL;
  628.             oldCopy.dataHandle := NIL;
  629.             IF sourceData.descriptorType = typeChar THEN
  630.                 BEGIN
  631.                 sourceData.descriptorType := MySignature;
  632.                 err := TryDoScript(globals, sourceData, num);
  633.                 IF err = NoErr THEN
  634.                     BEGIN
  635.                     err := AEDuplicateDesc(sourceData, descCopy);
  636.                     IF err = NoErr THEN err := FindSlotAndPutIt(globals, descCopy, resultingCompiledScriptID);
  637.                     END;
  638.                 END
  639.             ELSE
  640.                 err := errOSABadStorageType;
  641.             DoOSACompile := err;
  642.         END;
  643.  
  644.     FUNCTION DoOSAGetSource(globals: GlobalsHandle;
  645.                                                     scriptID: OSAID;
  646.                                                     desiredType: DescType;
  647.                                                     VAR resultingSourceData: AEDesc): ComponentResult;
  648.     { in this sample program, source is same as internal form and there is no special formatting, so just call coerce }
  649.  
  650.         BEGIN
  651.             DoOSAGetSource := DoOSACoerceToDesc(globals, scriptID, desiredType, resultingSourceData);
  652.         END;
  653.  
  654.     FUNCTION DoOSACoerceFromDesc(globals: GlobalsHandle;
  655.                                                              scriptData: AEDesc;
  656.                                                              VAR resultingScriptValueID: OSAID): ComponentResult;
  657.     { just store a copy into the slot }
  658.  
  659.         VAR
  660.             err: ComponentResult;
  661.             descCopy: AEDesc;
  662.  
  663.         BEGIN
  664.             err := NoErr;
  665.             descCopy.dataHandle := NIL;
  666.             err := AEDuplicateDesc(scriptData, descCopy);
  667.             IF err = NoErr THEN
  668.                 BEGIN
  669.                 resultingScriptValueID := 0; { put it in a new slot }
  670.                 err := FindSlotAndPutIt(globals, descCopy, resultingScriptValueID);
  671.                 END;
  672.             DoOSACoerceFromDesc := err;
  673.         END;
  674.  
  675.     FUNCTION DoOSACoerceToDesc(globals: GlobalsHandle;
  676.                                                          scriptValueID: OSAID;
  677.                                                          desiredType: DescType;
  678.                                                          VAR result: AEDesc): ComponentResult;
  679. { fetch from the slot and coerce it, if it is source we rename the type because internal form is same as the source text }
  680.  
  681.         VAR
  682.             err: ComponentResult;
  683.             myScriptValue: AEDesc;
  684.  
  685.         BEGIN
  686.             IF (scriptValueID <= 0) | (scriptValueID > MaxIDSlot) THEN
  687.                 err := errOSAInvalidID
  688.             ELSE
  689.                 BEGIN
  690.                 myScriptValue := globals^^.ScriptIDSlot[scriptValueID];
  691.                 IF myScriptValue.descriptorType = MySignature THEN myScriptValue.descriptorType := typeChar;
  692.                 IF myScriptValue.descriptorType = desiredType THEN
  693.                     err := AEDuplicateDesc(myScriptValue, result)
  694.                 ELSE IF desiredType = 'STXT' THEN
  695.                     err := TextToStxt(myScriptValue, result)
  696.                 ELSE
  697.                     err := AECoerceDesc(myScriptValue, desiredType, result);
  698.                 END;
  699.             DoOSACoerceToDesc := err;
  700.         END;
  701.  
  702.     FUNCTION DoOSALoadExecute(globals: GlobalsHandle;
  703.                                                         scriptData: AEDesc;
  704.                                                         contextID: OSAID;
  705.                                                         modeFlags: LONGINT;
  706.                                                         VAR resultingScriptValueID: OSAID): ComponentResult;
  707.     { strip the trailer, execute it and put back the trailer }
  708.     { there is chance we cannot restore the original form although we are try our best }
  709.     { this really calls for a GetScriptDataSize call in OSAComp }
  710.  
  711.         VAR
  712.             err: ComponentResult;
  713.             itsType: DescType;
  714.  
  715.         BEGIN
  716.             err := errOSABadStorageType;
  717.             IF (scriptData.descriptorType = kOSAGenericScriptingComponentSubtype) THEN
  718.                 IF OSAGetStorageType(scriptData.dataHandle, itsType) = NoErr THEN
  719.                     IF itsType = MySignature THEN
  720.                         BEGIN
  721.                         err := OSARemoveStorageType(scriptData.dataHandle);
  722.                         IF err = NoErr THEN
  723.                             BEGIN
  724.                             err := DoOSACompileExecute(globals, scriptData, 0, 0, resultingScriptValueID);
  725.                             IF OSAAddStorageType(scriptData.dataHandle, MySignature) <> NoErr THEN
  726.                                 BEGIN { we are in deep trouble, we change scriptData and cannot put it back }
  727.                                 IgnoreOSErr(DoOSADispose(globals, resultingScriptValueID)); { dispose result to get back the memory }
  728.                                 resultingScriptValueID := 0;
  729.                                 IgnoreOSErr(OSAAddStorageType(scriptData.dataHandle, MySignature)); { now try again }
  730.                                 err := memFullErr; { fail because we don't have enough memory }
  731.                                 END;
  732.                             END;
  733.                         END;
  734.             DoOSALoadExecute := err;
  735.         END;
  736.  
  737.     FUNCTION DoOSACompileExecute(globals: GlobalsHandle;
  738.                                                              sourceData: AEDesc;
  739.                                                              contextID: OSAID;
  740.                                                              modeFlags: LONGINT;
  741.                                                              VAR resultingScriptValueID: OSAID): ComponentResult;
  742.     { since source is same as internal form, just execute it and store the result }
  743.  
  744.         VAR
  745.             err: ComponentResult;
  746.             resultDesc: AEDesc;
  747.  
  748.         BEGIN
  749.             sourceData.descriptorType := MySignature;
  750.             err := ActualDoScript(globals, sourceData, resultDesc);
  751.             IF err = NoErr THEN err := FindSlotAndPutIt(globals, resultDesc, resultingScriptValueID);
  752.             DoOSACompileExecute := err;
  753.         END;
  754.  
  755.     FUNCTION DoOSADoScript(globals: GlobalsHandle;
  756.                                                  sourceData: AEDesc;
  757.                                                  contextID: OSAID;
  758.                                                  desiredType: DescType;
  759.                                                  modeFlags: LONGINT;
  760.                                                  VAR resultingText: AEDesc): ComponentResult;
  761.     { since source is same as internal form, just execute it and return the result }
  762.  
  763.         VAR
  764.             err: ComponentResult;
  765.             resultDesc: AEDesc;
  766.  
  767.         BEGIN
  768.             sourceData.descriptorType := MySignature;
  769.             NukeIt(resultingText);
  770.             err := ActualDoScript(globals, sourceData, resultDesc);
  771.             IF err = NoErr THEN
  772.                 BEGIN
  773.                 IF (desiredType = resultDesc.descriptorType) | (desiredType = typeWildCard) THEN
  774.                     resultingText := resultDesc
  775.                 ELSE
  776.                     BEGIN
  777.                     IF desiredType = 'STXT' THEN
  778.                         err := TextToStxt(resultDesc, resultingText)
  779.                     ELSE
  780.                         err := AECoerceDesc(resultDesc, desiredType, resultingText);
  781.                     IgnoreOSErr(AEDisposeDesc(resultDesc));
  782.                     END;
  783.                 END;
  784.             DoOSADoScript := err;
  785.         END;
  786.  
  787.     FUNCTION DoOSAMakeContext(contextName: StringPtr;
  788.                                                         parentContext: OSAID;
  789.                                                         VAR resultingContextID: OSAID): ComponentResult;
  790.     { context is not used in this sample program }
  791.  
  792.         BEGIN
  793.             resultingContextID := 0;
  794.             DoOSAMakeContext := NoErr;
  795.         END;
  796.  
  797.     FUNCTION DoOSAScriptingComponentName(globals: GlobalsHandle;
  798.                                                                              VAR resultingScriptingComponentName: AEDesc): OSAError;
  799.  
  800.         VAR
  801.             aStr: Str255;
  802.  
  803.         BEGIN
  804.             aStr := 'SampleScript';
  805.             DoOSAScriptingComponentName := AECreateDesc(typeChar, @aStr[1], length(aStr), resultingScriptingComponentName);
  806.         END;
  807.  
  808. END.
  809.