home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 August: Tool Chest / Apple_Developer_Group_August_1996_Tool_Chest.iso / Sample Code / Interapplication Communication / MenuScripter 3.1 / Sources / MSScript.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-20  |  36.2 KB  |  1,363 lines  |  [TEXT/MPS ]

  1. /*
  2.     MSScript.c
  3.     
  4.     Version 3.1
  5.     
  6.     Copyright © 1995 Apple Computer, Inc., all rights reserved.
  7.     
  8.     MenuScripter by Nigel Humphreys and Jon Lansdell
  9.     AppleEvent to script extensions by Greg Sutton
  10. */
  11.  
  12.  
  13. #include <Memory.h>
  14. #include <Resources.h>
  15. #include <TextEdit.h>
  16. #include <Controls.h>
  17. #include <Dialogs.h>
  18. #include <Errors.h>
  19. #include <Files.h>
  20. #include <Folders.h>
  21. #include <Components.h>
  22. #include <AppleEvents.h>
  23. #include <OSA.h>
  24. #include <AppleScript.h>
  25. #include <AERegistry.h>
  26. #include <Processes.h>
  27.  
  28. #include "MSScript.h"
  29. #include "MSGlobals.h"
  30. #include "MSUtils.h"
  31. #include "MSAEUtils.h"
  32. #include "MSWindow.h"
  33.  
  34. /*
  35.     Each menu (or menu item) can have a script associated with it. This
  36.     script has an ID equal to 32 * theMenuID + theItem number. A script
  37.     with an item number of 0 applies to the whole menu unless it is 
  38.     overridden by a particular script for an item in the menu.
  39.     
  40.     Scripts are stored in two resource types
  41.         'scpt' is a compiled script as returned by OSAStore()
  42.         'SCPT' is a raw text script as defined in the resource file
  43.         
  44.     At open application time scripts are built from the 'SCPT' resources 
  45.     if there are not any existing complied scripts of that resource ID.
  46.     These are stored in the preferences file for the application.
  47.     
  48.     One problem with the scripted menu commands is that if the application
  49.     name is changed the target is no longer found. This may be addressed later.
  50.  
  51.     
  52. */
  53.  
  54. #define kMaxScriptsInApp 100
  55. #define kCompiledScriptType kOSAScriptResourceType
  56. #define kTextScriptType 'SCPT'
  57.  
  58. struct MyScriptRecord {
  59.   OSAID  theScriptID;
  60.     short  theResID;
  61. };
  62.  
  63. typedef struct MyScriptRecord MyScriptRecord;
  64.  
  65. ComponentInstance gScriptingComponent;
  66. short             gActiveMenuItem;
  67. OSASendUPP             oldSendProc;
  68. long              refCon;
  69. MyScriptRecord   *menuScripts;
  70. short             gNumScripts;
  71. short             gPrefsRefFile;
  72. OSAActiveUPP      gOSAActiveUPP;
  73. Boolean           gEditingScript; /* is the script editing dialog up ? */
  74.  
  75. /*
  76.     These are used in documentation but not defined in the interfaces
  77. */
  78.  
  79. #ifndef kComponentNotFound
  80. #define kComponentNotFound -1
  81. #endif
  82.  
  83. #define kAEDontRecord 0x00001000
  84.  
  85. pascal OSErr MySendProc(const AppleEvent*        theAppleEvent,
  86.                                                 AppleEvent*                    reply,
  87.                                                 AESendMode                     sendMode,
  88.                                                 AESendPriority             sendPriority,
  89.                                                 long                           timeOutInTicks,
  90.                                                 AEIdleUPP                      idleProc,
  91.                                                 AEFilterUPP                  filterProc,
  92.                                                 long                           refCon)
  93.     { 
  94. #pragma unused(refCon)
  95.         DescType     typeCode;
  96.         Size         descSize;
  97.         OSErr        myErr;
  98.         OSErr        ignoreErr;
  99.         OSType       whatEvent;
  100.         AppleEvent   myCopyAEvt;
  101.         
  102.         myErr = AEDuplicateDesc(theAppleEvent, &myCopyAEvt);
  103.     
  104.         myErr = AEGetAttributePtr(&myCopyAEvt,
  105.                                                             keyEventIDAttr,
  106.                                                             typeType,
  107.                                                             &typeCode,
  108.                                                             (Ptr) &whatEvent,
  109.                                                             sizeof(whatEvent),
  110.                                                             &descSize);
  111.                                                             
  112.         ignoreErr = AEDisposeDesc(&myCopyAEvt);
  113.         
  114.         if (myErr != noErr) whatEvent = 0x3F3F3F3F;
  115.         
  116.         /*
  117.             Record the final Set Data that occurs due to a script
  118.             'gdte' = id sent to get 'aete' resource from app, dealt with
  119.             by system handler.
  120.         */
  121.       if ((sendMode & kAEDontRecord) && 
  122.                 ((whatEvent!=kAEGetData) && (whatEvent!='gdte')))
  123.           sendMode = sendMode - kAEDontRecord;
  124.             
  125.         /* will be this when a5 bug fixed
  126.         return((*oldSendProc)(theAppleEvent,
  127.                                      reply,
  128.                                      sendMode,
  129.                                      sendPriority,
  130.                                      timeOutInTicks,
  131.                                      idleProc,
  132.                                      filterProc,
  133.                                      refCon));
  134.         */
  135.         
  136.         return(AESend(theAppleEvent,
  137.                       reply,
  138.                                     sendMode,
  139.                                     sendPriority,
  140.                                     timeOutInTicks,
  141.                                     idleProc,
  142.                                     filterProc));                            
  143.     }    /* MySendProc */
  144.  
  145.  
  146. /* our activeProc is called at various times during script execution and compilation */
  147. /* we use this to detect when the application is being sent to the background. This can happen */
  148. /* when a script is targetted to another application, causing this application to be */
  149. /* brought to the front. Since HiliteMenu(0) is called when the menu command has completed- and */
  150. /* this will be called when the script has completed, we must ensure that the application is */
  151. /* in the foreground when HiliteMenu is called. Otherwise the menu bar gets drawn over the frontmost */
  152. /* application, which is not what we want. */
  153.  
  154.  
  155. pascal OSErr StdActiveProc(long refCon)
  156. {
  157. #pragma unused(refCon)
  158.  
  159.   /* call WNE to get suspend event */
  160.         EventRecord myEvent;
  161.  
  162.     if (!gEditingScript)
  163.      {
  164.     
  165.                     if (WaitNextEvent(everyEvent, &myEvent, 0, nil))
  166.                         {
  167.                         switch (myEvent.what) {
  168.             
  169.                                 case kOSEvent:
  170.                                 
  171.                                     HiliteMenu(0); // don't call HiliteMenu in the background 
  172.                                             // so clear it before we switch to the background
  173.                                     
  174.                                     switch (myEvent.message & osEvtMessageMask) { /*high byte of message*/
  175.                                         case 0x01000000:
  176.                                             {
  177.                                                 gInBackground = ((myEvent.message & resumeFlag) == 0);
  178.                                                 
  179.                                             }
  180.                                     }
  181.                             }
  182.                     }
  183.             
  184.                 // now call the stdActiveProc
  185.      }
  186.   return CallOSAActiveProc(gOSAActiveUPP,0);
  187.  
  188. }
  189.  
  190.     
  191. pascal OSAID GetScriptIDForResID(short lookForID)
  192.     {
  193.         short ctr;
  194.         
  195.         for (ctr=0; ctr<gNumScripts; ctr++)
  196.             {
  197.                 if (menuScripts[ctr].theResID==lookForID)
  198.                     return(menuScripts[ctr].theScriptID);
  199.             }
  200.             
  201.         return(kOSANullScript);
  202.     }
  203.     
  204. /*
  205.     Name : GetOpenPreferencesResourceFile
  206.     Purpose : Opens the prefs file, in the system prefs folder
  207.               creating it if it is not found. Sets the current
  208.                         resource file to the prefs file so that resources
  209.                         will be read from there in preference to the app
  210.                         if they have been overridden, and new resources
  211.                         will be created in it.
  212. */
  213.     
  214. pascal OSErr GetOpenPreferencesResourceFile(short *theRefNum)
  215.     {
  216.       short  foundVRefNum;
  217.         long   foundDirID;
  218.         OSErr  myErr;
  219.         
  220.         myErr = FindFolder(kOnSystemDisk,
  221.                            kPreferencesFolderType,
  222.                                              kCreateFolder,
  223.                          &foundVRefNum,
  224.                                              &foundDirID);
  225.                                              
  226.         if (myErr==noErr)
  227.             {
  228.  
  229.                 *theRefNum = HOpenResFile(foundVRefNum, foundDirID, (unsigned char *)"\pMenuScripter Prefs", fsWrPerm);
  230.                 myErr = ResError();
  231.                 
  232.                 if (myErr==fnfErr)
  233.                     {
  234.                         HCreateResFile(foundVRefNum, foundDirID, (unsigned char *)"\pMenuScripter Prefs");
  235.                         myErr = ResError();
  236.  
  237.                         *theRefNum = HOpenResFile(foundVRefNum, foundDirID, (unsigned char *)"\pMenuScripter Prefs", fsWrPerm);
  238.                         myErr = ResError();
  239.                     }
  240.             }
  241.         return(myErr);
  242.     }
  243.     
  244. pascal OSErr ClosePrefsResFile(short theRefNum)
  245.     {
  246.         CloseResFile(theRefNum);
  247.         return(ResError());
  248.     }
  249.  
  250. /*
  251.     Name : AddMenuScript
  252.     Purpose : Adds a compiled script OSAID into the
  253.               global menuScripts array for later access
  254. */
  255. pascal void AddMenuScript(short thisID, OSAID thisScriptID)
  256.     {
  257.         if (gNumScripts<kMaxScriptsInApp)
  258.             {
  259.                 menuScripts[gNumScripts].theResID    = thisID;
  260.                 menuScripts[gNumScripts].theScriptID = thisScriptID;
  261.                 gNumScripts ++;
  262.             }
  263.     }
  264.  
  265. /*
  266.     Name : BuildMenuScripts
  267.     Purpose : Reads compiled scripts from the prefs file,
  268.               Any uncompiled scripts ('SCPT' resources with
  269.                         no 'Scpt' of same id are compiled, and a compiled
  270.                         version stored in the prefs file. Any which fail
  271.                         to compile are ignored.
  272. */
  273. pascal void BuildMenuScripts(void)
  274.     {
  275.         short   numScripts;
  276.         short   index;
  277.         short   thisID;
  278.         ResType thisType;
  279.         Handle  myScript;
  280.         AEDesc  myLoadScriptDesc;
  281.         AEDesc  myStoreScriptDesc;
  282.         OSAID   myLoadID;
  283.         OSErr   myErr;
  284.         OSErr   ignoreErr;
  285.         Str255  resName;
  286.         
  287.         GetOpenPreferencesResourceFile(&gPrefsRefFile);
  288.         
  289.         gNumScripts = 0;
  290.         
  291.         menuScripts = (MyScriptRecord *)NewPtr(sizeof(MyScriptRecord)*kMaxScriptsInApp);
  292.         
  293.         numScripts  = Count1Resources(kCompiledScriptType);
  294.         for (index=0; index <numScripts; index++)
  295.             {
  296.                 myScript  = Get1IndResource(kCompiledScriptType, index+1);
  297.                 GetResInfo(myScript, &thisID, &thisType, resName);
  298.                 
  299.               HLock(myScript);
  300.                 
  301.                 myErr = AECreateDesc(typeOSAGenericStorage,
  302.                                                          (Ptr)*myScript,
  303.                                                          GetHandleSize(myScript),
  304.                                                          &myLoadScriptDesc);
  305.                 
  306.                 HUnlock(myScript);
  307.                 
  308.                 if (myErr==noErr)
  309.                     {
  310.                         myLoadID = 0; 
  311.                         
  312.                         myErr = OSALoad(gScriptingComponent,
  313.                                                         &myLoadScriptDesc,
  314.                                                         0,
  315.                                                         &myLoadID);
  316.                                                         
  317.                       if (myErr==noErr)
  318.                             AddMenuScript(thisID,myLoadID);
  319.                     }
  320.                 
  321.                 ignoreErr = AEDisposeDesc(&myLoadScriptDesc);
  322.             }
  323.             
  324.         numScripts  = CountResources(kTextScriptType);
  325.         for (index=0; index <numScripts; index++)
  326.             {
  327.                 myScript  = GetIndResource(kTextScriptType, index+1);
  328.                 GetResInfo(myScript, &thisID, &thisType, resName);
  329.                 
  330.                 if (GetScriptIDForResID(thisID)==kOSANullScript)
  331.                     {
  332.                         HLock(myScript);
  333.                         
  334.                         myErr = AECreateDesc(typeChar,
  335.                                                                  (Ptr)*myScript,
  336.                                                                  GetHandleSize(myScript),
  337.                                                                  &myLoadScriptDesc);
  338.                         
  339.                         HUnlock(myScript);
  340.                         
  341.                         if (myErr==noErr)
  342.                             {
  343.                                 myLoadID = 0;
  344.                                 
  345.                                 myErr = OSACompile(gScriptingComponent,
  346.                                                                      &myLoadScriptDesc,
  347.                                                                      0,
  348.                                                                      &myLoadID);
  349.                                                                 
  350.                                 if (myErr==noErr)
  351.                                     AddMenuScript(thisID,myLoadID);
  352.                                     
  353.                                 if (myErr==noErr)
  354.                                     {
  355.                                         myErr = OSAStore(gScriptingComponent,
  356.                                                                          myLoadID,
  357.                                                                          typeOSAGenericStorage,
  358.                                                                          0,
  359.                                                                          &myStoreScriptDesc);
  360.                                                                          
  361.                                         if (myErr==noErr)
  362.                                             {
  363.                                                 myScript = myStoreScriptDesc.dataHandle;
  364.                                                 
  365.                                                 HandToHand(&myScript);                                 
  366.                                                 AddResource(myScript, kCompiledScriptType, thisID, (unsigned char *)"\pMenu Script");
  367.                                             }
  368.                                         
  369.                                         myErr = AEDisposeDesc(&myStoreScriptDesc);
  370.                                     }
  371.                                     
  372.                             }
  373.                         
  374.                         ignoreErr = AEDisposeDesc(&myLoadScriptDesc);
  375.                     }
  376.             }
  377.     }
  378.  
  379.  
  380.  
  381. /*
  382.     Name:   InitEditorScripting
  383.     Purpose:Connects to the AppleScript component.
  384. */
  385.  
  386. pascal OSErr InitEditorScripting(void)
  387. {
  388.     OSAError                 err = 0;
  389.     ComponentDescription     descr;
  390.     Component               aComponent;
  391.     ComponentInstance         aScriptingComponent;
  392.     
  393.     descr.componentType         = kOSAComponentType;
  394.     descr.componentSubType      = (OSType) 0;
  395.     descr.componentManufacturer = (OSType) 0;
  396.     descr.componentFlags        = kOSASupportsCompiling + 
  397.                                       kOSASupportsGetSource + 
  398.                                                                 kOSASupportsAESending;
  399.     descr.componentFlagsMask    = descr.componentFlags;
  400.  
  401.   gEditingScript = false;
  402.     
  403.     aComponent = FindNextComponent(nil, &descr);
  404.         
  405.     if (!aComponent)
  406.         return(kComponentNotFound);
  407.     else
  408.     {
  409.         aScriptingComponent = OpenComponent(aComponent);
  410.                                                                                                 
  411.         if (! aScriptingComponent)
  412.             return(kComponentNotFound);
  413.     }
  414.         
  415.     gScriptingComponent = aScriptingComponent;
  416.  
  417.             
  418.     err = OSAGetSendProc(gScriptingComponent,
  419.                                                      &oldSendProc,
  420.                                                      &refCon);
  421.                                                 
  422.     err = OSASetSendProc(gScriptingComponent,
  423.                                                      NewOSASendProc(MySendProc),
  424.                                                      0);
  425.         
  426.     menuScripts = nil;
  427.         
  428.     BuildMenuScripts();
  429.  
  430.     return err;
  431. }
  432.  
  433.  
  434. pascal OSErr    SetOSAActiveProcedure(void)
  435. {
  436.   OSErr err;
  437.   long    theRefCon;
  438.  
  439.  /* store the old active proc in order to call this from ours */
  440.   err = OSAGetActiveProc(gScriptingComponent, &gOSAActiveUPP, &theRefCon);
  441.  
  442.     return(OSASetActiveProc(gScriptingComponent, 
  443.                               NewOSAActiveProc(StdActiveProc),
  444.                                                      0));
  445. }
  446.  
  447. /*
  448.     Name    : CloseEditorScripting
  449.     Purpose : Shutdown of editor scripting capabilities
  450. */
  451. pascal OSErr CloseEditorScripting(void)
  452.     {
  453.       OSErr myErr;
  454.         short ctr;
  455.         
  456.         ClosePrefsResFile(gPrefsRefFile);
  457.         
  458.         for (ctr=0; ctr<gNumScripts; ctr++)
  459.             myErr = OSADispose(gScriptingComponent, menuScripts[ctr].theScriptID);
  460.  
  461.         myErr = CloseComponent(gScriptingComponent);
  462.         
  463.         return(myErr);
  464.     }
  465.  
  466.     
  467. /*
  468.     Name:    DisplayErrorInScript
  469.     Purpose: Put up an alert showing the error text for the last error.
  470.              Also selects the responsible text in theHTE if one is supplied
  471. */
  472.  
  473. pascal void DisplayErrorInScript(TEHandle theHTE)
  474.     {
  475.         Str255   errorMessageText;
  476.         AEDesc   errRangeDesc;
  477.         AEDesc   errRecordDesc;
  478.         AEDesc   errTextDesc;
  479.         AEDesc   errNumberDesc;
  480.         DescType typeCode;
  481.         Size     actSize;
  482.         OSErr    myErr;
  483.         OSErr    ignoreErr;
  484.         OSErr    errorNumber;
  485.         short    errorStart;
  486.         short    errorEnd;
  487.         
  488.         SetCursor(&qd.arrow);
  489.         
  490.         myErr = OSAScriptError(gScriptingComponent,
  491.                                                      kOSAErrorNumber,
  492.                                                      typeShortInteger,
  493.                                                      &errNumberDesc);
  494.         
  495.         myErr = GetIntegerFromDescriptor(&errNumberDesc, &errorNumber);
  496.                 
  497.         ignoreErr = AEDisposeDesc(&errNumberDesc);
  498.         
  499.         myErr = OSAScriptError(gScriptingComponent,
  500.                                                      kOSAErrorMessage,
  501.                                                      typeChar,
  502.                                                      &errTextDesc);
  503.                                                      
  504.         myErr = GetPStringFromDescriptor(&errTextDesc, (char *)errorMessageText);
  505.         
  506.         ignoreErr = AEDisposeDesc(&errTextDesc);
  507.         
  508.         if (theHTE)
  509.             {
  510.                 myErr = OSAScriptError(gScriptingComponent,
  511.                                                              kOSAErrorRange,
  512.                                                              typeOSAErrorRange,
  513.                                                              &errRangeDesc);
  514.                                                              
  515.                 myErr = AECoerceDesc(&errRangeDesc, typeAERecord, &errRecordDesc);
  516.                 
  517.                 ignoreErr = AEDisposeDesc(&errRangeDesc);
  518.                 
  519.                 myErr = AEGetKeyPtr(&errRecordDesc,
  520.                                     keyOSASourceStart,
  521.                                                         typeShortInteger,
  522.                                                         &typeCode,
  523.                                                         (Ptr)&errorStart,
  524.                                                         sizeof(errorStart),
  525.                                                         &actSize);
  526.                                                         
  527.                 myErr = AEGetKeyPtr(&errRecordDesc,
  528.                                     keyOSASourceEnd,
  529.                                                         typeShortInteger,
  530.                                                         &typeCode,
  531.                                                         (Ptr)&errorEnd,
  532.                                                         sizeof(errorEnd),
  533.                                                         &actSize);
  534.                                                         
  535.                 ignoreErr = AEDisposeDesc(&errRecordDesc);
  536.                 
  537.                 TESetSelect(errorStart, errorEnd, theHTE);
  538.             }
  539.         
  540.         ShowError(errorMessageText, errorNumber);
  541.     }
  542. /*
  543.     Name    : CompileDocument
  544.     Purpose : Compiles the text of the supplied document - does NOT keep
  545.               a compiled version - merely checks that it will compile for now
  546. */
  547. pascal OSErr CompileDocument(DPtr theDoc)
  548.     {
  549.         OSErr             myErr;
  550.         OSErr             ignoreErr;
  551.         TEHandle          theHTE;
  552.         AEDesc            windowTextDesc;
  553.         AEDesc            myCompiledText;
  554.         AEDesc            styledTextDesc;
  555.         AEDesc            textStyleDesc;
  556.         AEDesc            rawTextDesc;
  557.         OSAID             myScriptID;
  558.         
  559.         /*
  560.           Initialise handles
  561.         */
  562.         
  563.         myCompiledText.dataHandle = nil;
  564.         windowTextDesc.dataHandle = nil;
  565.         
  566.         theHTE = theDoc->theText;
  567.         
  568.         HLock((Handle)(**theHTE).hText);
  569.         myErr = AECreateDesc(typeChar,
  570.                                                  (Ptr)&(*(**theHTE).hText)[0],
  571.                                                  (**theHTE).teLength,
  572.                                                  &windowTextDesc);
  573.                                                  
  574.         HUnlock((Handle)(**theHTE).hText);
  575.         
  576.         if (myErr==noErr)
  577.             {
  578.                 myScriptID = 0; // Added for Gustav 1.0a8
  579.                 
  580.                 myErr = OSACompile(gScriptingComponent,
  581.                                    &windowTextDesc,
  582.                                                      0,
  583.                                                      &myScriptID);
  584.                 
  585.                 if (myErr==noErr)
  586.                   {
  587.                         myErr = OSAGetSource(gScriptingComponent,
  588.                                                                  myScriptID,
  589.                                                                  typeStyledText,
  590.                                                                  &myCompiledText);
  591.                         if (myErr==noErr)
  592.                             {
  593.                                 styledTextDesc.dataHandle = nil;
  594.                                 textStyleDesc.dataHandle  = nil;
  595.                                 rawTextDesc.dataHandle    = nil;
  596.                             
  597.                               /*
  598.                                     Coerce to an AERecord and then extract the parts of the
  599.                                     styled text
  600.                                 */
  601.                                 myErr = AECoerceDesc(&myCompiledText, typeAERecord, &styledTextDesc);
  602.                                 
  603.                                 myErr = AEGetKeyDesc(&styledTextDesc,
  604.                                                      keyAEText,
  605.                                                                          typeChar,
  606.                                                                          &rawTextDesc);
  607.                                                                          
  608.                                 myErr = AEGetKeyDesc(&styledTextDesc,
  609.                                                      keyAEStyles,
  610.                                                                          typeScrapStyles,
  611.                                                                          &textStyleDesc);
  612.                                                                          
  613.                                 TESetSelect(0,32000, theHTE);
  614.                                 TEDelete(theHTE);
  615.                                 
  616.                                 HLock((Handle)rawTextDesc.dataHandle);
  617.                                                                          
  618.                                 TEStylInsert((const void *) (*rawTextDesc.dataHandle),
  619.                                              GetHandleSize(rawTextDesc.dataHandle),
  620.                                                          (StScrpHandle) textStyleDesc.dataHandle,
  621.                                                          theHTE);
  622.                                                          
  623.                                 HUnlock((Handle)rawTextDesc.dataHandle);
  624.                                 
  625.                                 if (textStyleDesc.dataHandle)
  626.                                     ignoreErr = AEDisposeDesc(&textStyleDesc);
  627.                         
  628.                                 if (rawTextDesc.dataHandle)
  629.                                     ignoreErr = AEDisposeDesc(&rawTextDesc);
  630.  
  631.                                 if (styledTextDesc.dataHandle)
  632.                                     ignoreErr = AEDisposeDesc(&styledTextDesc);
  633.  
  634.                             }
  635.                         
  636.                     }
  637.                 else
  638.                     DisplayErrorInScript(theHTE);
  639.                     
  640.                 if (myErr==noErr)
  641.                   ignoreErr = OSADispose(gScriptingComponent,
  642.                                            myScriptID);
  643.             }
  644.             
  645.         if (myCompiledText.dataHandle)
  646.             ignoreErr = AEDisposeDesc(&myCompiledText);
  647.             
  648.         if (windowTextDesc.dataHandle)
  649.             ignoreErr = AEDisposeDesc(&windowTextDesc);
  650.  
  651.         return(myErr);
  652.         
  653.     }
  654.     
  655. /*
  656.     Name    : ExecuteDocument
  657.     Purpose : Compiles the text of the supplied document and then executes it
  658.               - does NOT keep a compiled version after execution
  659. */
  660. pascal OSErr ExecuteDocument(DPtr theDoc)
  661.   {
  662.         OSErr             myErr;
  663.         OSErr             ignoreErr;
  664.         TEHandle          theHTE;
  665.         AEDesc            windowTextDesc;
  666.         AEDesc            myCompiledText;
  667.         OSAID             myScriptID;
  668.         OSAID             myExecutedScriptID;
  669.         
  670.         /*
  671.           Initialise handles
  672.         */
  673.         
  674.         myCompiledText.dataHandle = nil;
  675.         windowTextDesc.dataHandle = nil;
  676.         
  677.         theHTE = theDoc->theText;
  678.         
  679.         HLock((Handle)(**theHTE).hText);
  680.         myErr = AECreateDesc(typeChar,
  681.                                                  (Ptr)&(*(**theHTE).hText)[0],
  682.                                                  (**theHTE).teLength,
  683.                                                  &windowTextDesc);
  684.                                                  
  685.         HUnlock((Handle)(**theHTE).hText);
  686.         
  687.         if (myErr==noErr)
  688.             {
  689.                 myScriptID = 0; // Added for Gustav 1.0a8
  690.                 
  691.                 myErr = OSACompile(gScriptingComponent,
  692.                                    &windowTextDesc,
  693.                                                      0,
  694.                                                      &myScriptID);
  695.                                                      
  696.                 if (myErr==noErr)
  697.                   {
  698.                         myErr = OSAExecute(gScriptingComponent,
  699.                                            myScriptID,
  700.                                                              kOSANullScript,
  701.                                                              0,
  702.                                                              &myExecutedScriptID);
  703.                 
  704.                       if (myErr!=noErr)
  705.                           DisplayErrorInScript(theHTE);
  706.                             
  707.                         myErr = OSAGetSource(gScriptingComponent,
  708.                                                                  myScriptID,
  709.                                                                  typeStyledText,
  710.                                                                  &myCompiledText);
  711.                         if (myErr==noErr)
  712.                             {
  713.                                 /* Zap current contents and
  714.                                      replace with returned source */
  715.                                                                  
  716.                                 TESetSelect(0, 32000, theHTE);
  717.                                 TEDelete(theHTE);
  718.  
  719.                                 myErr = GetStyledTextFromDescIntoTEHandle(&myCompiledText, theHTE);
  720.                                     
  721.                                 if (myErr==noErr)
  722.                                     ignoreErr = OSADispose(gScriptingComponent,
  723.                                                                                  myExecutedScriptID);
  724.                             }
  725.                         
  726.                     }
  727.                 else
  728.                     DisplayErrorInScript(theHTE);
  729.                     
  730.                 if (myErr==noErr)
  731.                   ignoreErr = OSADispose(gScriptingComponent,
  732.                                            myScriptID);
  733.             }
  734.             
  735.         if (myCompiledText.dataHandle)
  736.             ignoreErr = AEDisposeDesc(&myCompiledText);
  737.             
  738.         if (windowTextDesc.dataHandle)
  739.             ignoreErr = AEDisposeDesc(&windowTextDesc);
  740.  
  741.         return(myErr);        
  742.     }
  743.  
  744. /* 
  745.     Name   : ScriptForMenuExists
  746.     Purpose: Tests for the existance of a valid script for a given menu item             
  747. */
  748.     
  749. pascal OSErr ScriptForMenuExists(short theMenu, short theItem, Boolean *exists)
  750.     {
  751.         short  resID;
  752.         OSAID  myScriptID;
  753.         OSErr  myErr;
  754.         
  755.         myErr = noErr;
  756.         
  757.         resID = (theMenu<<5) + theItem;
  758.         
  759.         myScriptID = GetScriptIDForResID(resID);
  760.         
  761.         if (myScriptID==kOSANullScript)
  762.             if (theItem!=0)
  763.                 myErr = ScriptForMenuExists(theMenu, 0, exists);
  764.             else
  765.                 *exists = false;
  766.         else
  767.           *exists = true;
  768.                 
  769.         return(myErr);        
  770.     } /* ScriptForMenuExists */
  771.     
  772.     
  773. /* 
  774.     Name   : ExecuteScriptForMenu
  775.     Purpose: Executes a script associated with the menu item.
  776.              Should be called only after ScriptForMenuExists
  777.                      returns exists.
  778. */    
  779. pascal OSErr ExecuteScriptForMenu(short theMenu, short theItem)
  780.   {
  781.         short  resID;
  782.         OSAID  myScriptID;
  783.         OSAID  myExecuteID;
  784.         OSErr  myErr;
  785.         OSErr  ignoreErr;
  786.                 
  787.         resID = (theMenu<<5) + theItem;
  788.         
  789.         myScriptID = GetScriptIDForResID(resID);
  790.                 
  791.         if (myScriptID==kOSANullScript)
  792.           {
  793.                 resID = (theMenu<<5); /* look for a script for the whole menu - item 0 */
  794.                 myScriptID = GetScriptIDForResID(resID);
  795.             }
  796.         
  797.         if (myScriptID != kOSANullScript)
  798.           {
  799.                 gActiveMenuItem = theItem;
  800.                 
  801.                 myErr = OSAExecute(gScriptingComponent,
  802.                                                      myScriptID,
  803.                                                      kOSANullScript,
  804.                                                      0,
  805.                                                      &myExecuteID);
  806.                                                      
  807.                 ignoreErr = OSADispose(gScriptingComponent,
  808.                                        myExecuteID);
  809.                 
  810.                 gActiveMenuItem = 0;
  811.             }
  812.  
  813.         return(myErr);
  814.     }
  815.  
  816. /*
  817.     Name :   GetScriptActiveItem
  818.     Purpose : Used by SVAppleEvents for the active item property of a menu.
  819.               Allows a script associated with more than one menu item to
  820.                         find which menu item it was called by.
  821. */
  822. pascal short GetScriptActiveItem(void)
  823.     {
  824.         return(gActiveMenuItem);
  825.     }
  826.     
  827. /*
  828.     Routines used in the StyledTextEdit Dialog Item
  829. */
  830.  
  831. struct StyleTextInfo {
  832.     ControlHandle theScrollBar;
  833.     TEHandle      theTEHandle;
  834. };
  835.  
  836. typedef struct StyleTextInfo StyleTextInfo;
  837.  
  838. typedef StyleTextInfo *pStyleTextInfo;
  839.  
  840. pascal void DrawStyledTextEditRec(DialogPtr theDialog, short theItem)
  841.     {
  842.         short   theType;
  843.         Handle  theHandle;
  844.         Rect    itemRect;
  845.                 
  846.         GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  847.         FrameRect(&itemRect);
  848.         InsetRect(&itemRect, 5, 5);
  849.         
  850.         TEUpdate(&itemRect, ((pStyleTextInfo) GetWRefCon(theDialog))->theTEHandle);
  851.     }
  852.     
  853. pascal void DrawScrollBar(DialogPtr theDialog, short theItem)
  854.     {        
  855. #pragma unused(theItem)
  856.  
  857.         Draw1Control(((pStyleTextInfo) GetWRefCon(theDialog))->theScrollBar);
  858.     }
  859.  
  860. /*
  861.     Name:    SetDrawProcForUserItem
  862.     Purpose: Installs a procedure that will be called when theItem needs
  863.              to be drawn.
  864. */
  865. pascal void SetDrawProcForUserItem(DialogPtr theDialog, short theItem, ControlActionUPP theProc)
  866.     {
  867.         short  theType;
  868.         Handle theHandle;
  869.         Rect   itemRect;
  870.         
  871.         GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  872.         SetDItem(theDialog, theItem, theType, (Handle)theProc, &itemRect);
  873.     }
  874.     
  875. /*
  876.     Name:    FlashButton
  877.     Purpose: Provide visual effect of button having been
  878.              selected.
  879. */
  880.  
  881. pascal void FlashButton(DialogPtr theDialog, short theItem)
  882.     {
  883.         short    theType;
  884.         Handle   theHandle;
  885.         Rect     itemRect;
  886.         
  887.         GetDItem(theDialog, theItem, &theType, &theHandle, &itemRect);
  888.         
  889.         HiliteControl((ControlHandle)theHandle, inButton);
  890.         HiliteControl((ControlHandle)theHandle, 0);
  891.     }
  892.     
  893. /* 
  894.     Name:    ScrollVActionProc
  895.     Purpose: Called as scrollbar is tracked in buttons or page up/down.
  896.              Keeps text in sync with scrollBar
  897. */
  898. pascal void ScrollVActionProc(ControlHandle control, short part)
  899.   {
  900.         short  amount;
  901.         short  initialValue;
  902.         
  903.     if (part)
  904.       {
  905.                 switch (part) {
  906.                   case inUpButton:
  907.                     case inDownButton : amount = 24;
  908.                                         break;
  909.                   case inPageUp:
  910.                     case inPageDown   : amount = (**control).contrlRect.bottom - 
  911.                                                  (**control).contrlRect.top;
  912.                                         break;
  913.                                                             
  914.                 }   /* case */
  915.                 
  916.                 if (part == inUpButton || part == inPageUp)
  917.           amount = -amount; /* reverse direction */
  918.             
  919.                 initialValue = GetCtlValue(control);
  920.  
  921.               SetCtlValue(control, initialValue+amount); /* Pinned within Min/Max automatically */
  922.                 
  923.                 amount  = GetCtlValue(control)-initialValue;                
  924.                 
  925.                 if (amount)
  926.           TEScroll(0, -amount, ((pStyleTextInfo)GetWRefCon((**control).contrlOwner))->theTEHandle);
  927.  
  928.             }     /* if */
  929.     }  /* ScrollVActionProc */
  930.     
  931. /*
  932.     Name:    TrackTEPosn
  933.     Purpose: Ensures that the scrollbar value matches the position
  934.              of the text edit record.
  935. */
  936. pascal void TrackTEPosn(ControlHandle theControl, TEHandle theHTE)
  937.     {
  938.         short shouldBe;
  939.         
  940.       shouldBe = (**theHTE).viewRect.top - 
  941.                                 (**theHTE).destRect.top;
  942.                                 
  943.         if (GetCtlValue(theControl)!=shouldBe)
  944.             SetCtlValue(theControl,shouldBe);
  945.     }
  946.  
  947. /*
  948.     Name:    SetScrollLimit
  949.     Purpose: Ensures that the maximum value of the scrollbar is sufficient
  950.              to allow showing of all text, and no more.
  951. */
  952. pascal void SetScrollLimit(ControlHandle newScroll, TEHandle theHTE)
  953.     {
  954.         Point     teLimit;
  955.         short     currentMax;
  956.         short     currentValue;
  957.         TextStyle theStyle;
  958.         short     lineHeight;
  959.         short     fontAscent;
  960.         
  961.         currentMax = GetCtlMax(newScroll);
  962.         
  963.         /*
  964.             Scroll max should be position of bottom of bottom line when unscrolled
  965.             This is equal to
  966.               The position of the bottom line relative to current position +
  967.                 The amount currently scrolled -
  968.                 The height of the visible part
  969.         */
  970.                 
  971.         teLimit    = TEGetPoint((**theHTE).teLength, theHTE); // Position of bottom relative to current posn
  972.         
  973.         TEGetStyle((**theHTE).teLength, &theStyle, &lineHeight, &fontAscent,theHTE);        
  974.         teLimit.v += lineHeight-fontAscent; // Add in for descent - TEGetPoint is posn of baseline not bottom of chars
  975.         
  976.         teLimit.v    += ((**theHTE).viewRect.top -(**theHTE).destRect.top); // Amount already scrolled
  977.         
  978.         teLimit.v -= ((**theHTE).viewRect.bottom - (**theHTE).viewRect.top); // Height of page
  979.         
  980.         if (teLimit.v<0) // Cannot be negative
  981.             teLimit.v = 0;
  982.             
  983.         if (currentMax>teLimit.v)
  984.             {
  985.                 currentValue = GetCtlValue(newScroll);
  986.                 if (currentValue>teLimit.v)
  987.                     {
  988.                         TEScroll(0, teLimit.v - currentValue, theHTE);
  989.                         SetCtlValue(newScroll, teLimit.v);
  990.                     }
  991.                 SetCtlMax(newScroll, teLimit.v);
  992.             }
  993.             
  994.         if (currentMax<teLimit.v)
  995.             SetCtlMax(newScroll, teLimit.v);
  996.     }
  997.  
  998. #define kCompile   3
  999. #define kTextItem  4
  1000. #define kScrollBar 5
  1001.  
  1002. pascal Boolean MyFilterProc(DialogPtr theDialog, EventRecord *myEvent, short *itemHit)
  1003.     {
  1004.       short         myPart;
  1005.         WindowPtr     whichWindow;
  1006.         TEHandle      newTE;
  1007.         Boolean       extend;
  1008.         GrafPtr       oldPort;
  1009.         Point         mousePt;
  1010.         char          myKey;
  1011.         Boolean       returnVal;
  1012.         long          menuResult;
  1013.         Rect          teItemRect;
  1014.         Rect          scrollItemRect;
  1015.         ControlHandle newScroll;
  1016.         ControlHandle theControl;
  1017.         short         part;
  1018.         short         value;
  1019.         short         cntlCode;
  1020.         
  1021.         GetPort(&oldPort);
  1022.         
  1023.         returnVal = false;
  1024.         
  1025.         newTE     = ((pStyleTextInfo)GetWRefCon(theDialog))->theTEHandle;
  1026.         newScroll = ((pStyleTextInfo)GetWRefCon(theDialog))->theScrollBar;
  1027.         
  1028.         TEIdle(newTE);
  1029.         
  1030.         /* Maintain the cursor */
  1031.         
  1032.         SetPort(theDialog);
  1033.         GetMouse(&mousePt);
  1034.         
  1035.         GetRectOfDialogItem(theDialog, kTextItem,  &teItemRect);
  1036.         GetRectOfDialogItem(theDialog, kScrollBar, &scrollItemRect);
  1037.         
  1038.         if (PtInRect(mousePt, &teItemRect))
  1039.             SetCursor(&editCursor);
  1040.         else
  1041.             SetCursor(&qd.arrow);
  1042.             
  1043.         switch (myEvent->what) {
  1044.             case mouseDown: myPart = FindWindow(myEvent->where, &whichWindow);
  1045.                                             if (whichWindow==theDialog)
  1046.                                                 switch (myPart) {
  1047.                                                     case inContent:
  1048.                                                     case inGrow:        SetPort(whichWindow);
  1049.                                                                                     mousePt = myEvent->where;
  1050.                                                                                     GlobalToLocal(&mousePt);
  1051.  
  1052.                                                                                     extend = ((myEvent->modifiers & shiftKey) != 0);
  1053.                                                                                     if (PtInRect(mousePt, &(*(newTE))->viewRect))
  1054.                                                                                         {
  1055.                                                                                             TEClick(mousePt, extend, newTE);
  1056.                                                                                             TrackTEPosn(newScroll, newTE);
  1057.                                                                                         }
  1058.  
  1059.                                                                                     if (PtInRect(mousePt, &scrollItemRect))
  1060.                                                                                          {
  1061.                                                                                                  cntlCode = FindControl(mousePt, theDialog, &theControl);
  1062.                                                                                                 if (theControl)
  1063.                                                                                                     if (cntlCode == inThumb)
  1064.                                                                                                         {
  1065.                                                                                                             value = GetCtlValue(theControl);
  1066.                                                                                                             part  = TrackControl(theControl,
  1067.                                                                                                                                                      mousePt,
  1068.                                                                                                                                                      nil);
  1069.                                                                                                             if (part)
  1070.                                                                                                                 {
  1071.                                                                                                                     value -= GetCtlValue(theControl);
  1072.                                                                                                                     if (value)
  1073.                                                                                                                         TEScroll(0, value, newTE);
  1074.                                                                                                                 } /* if */
  1075.                                                                                                         }
  1076.                                                                                                     else
  1077.                                                                                                       if (cntlCode!=0)
  1078.                                                                                                           part = TrackControl(theControl, mousePt, gScrollScriptVActionUPP);
  1079.                                                                                             }
  1080.                                                                                     break;
  1081.                                                         
  1082.                                                     case inDrag:      DragWindow(whichWindow,
  1083.                                                                                                          myEvent->where,
  1084.                                                                                                          &qd.screenBits.bounds);
  1085.                                                                                     returnVal = true; /* Stops modal dialog beeping */
  1086.                                                                                     break;
  1087.                                                     
  1088.                                                     case inMenuBar: /* Allows turn on/off of ballon help */
  1089.                                                                                     menuResult = MenuSelect(myEvent->where);
  1090.                                                                                     break;                                                                                        
  1091.                                                     }
  1092.                                             break;
  1093.             case keyDown:
  1094.             case autoKey: /* Need hooks here for command keys if menus enabled */
  1095.                                         myKey = myEvent->message & charCodeMask;
  1096.                                         if (myKey==3)
  1097.                                             {
  1098.                                                 *itemHit = kCompile;
  1099.                                                 FlashButton(theDialog, kCompile);
  1100.                                                 returnVal = true;
  1101.                                             }
  1102.                                         else
  1103.                                             {
  1104.                                                 TEKey(myKey, newTE);
  1105.                                                 SetScrollLimit(newScroll, newTE);
  1106.                                                 TrackTEPosn(newScroll, newTE);
  1107.                                             }
  1108.                                         break;
  1109.                                         
  1110.             case activateEvt: if (((myEvent->modifiers & activeFlag) != 0))
  1111.                                                     if ((WindowPtr)myEvent->message == theDialog)
  1112.                                                         TEActivate(newTE);
  1113.                                                     else
  1114.                                                         DoActivate((WindowPtr)myEvent->message, true); /* Should not get here! */
  1115.                                                 else
  1116.                                                     if ((WindowPtr)myEvent->message == theDialog)
  1117.                                                         TEDeactivate(newTE);
  1118.                                                     else
  1119.                                                         DoActivate((WindowPtr)myEvent->message, false);
  1120.                                                         
  1121.                                                 break;
  1122.                                                 
  1123.             case updateEvt  : if (Ours((WindowPtr)myEvent->message))
  1124.                                                     DoUpdate(DPtrFromWindowPtr((WindowPtr)myEvent->message));
  1125.                                                 break;
  1126.         }
  1127.         
  1128.         SetPort(oldPort);
  1129.         
  1130.         return(returnVal);
  1131.     }
  1132.  
  1133. pascal OSErr EditMenuScript(short theMenu, short theItem)
  1134.  {
  1135.         short         resID;
  1136.         OSAID         myScriptID;
  1137.         OSErr         myErr;
  1138.         OSErr         ignoreErr;
  1139.         AEDesc        scriptTextDesc;
  1140.         DialogPtr     scriptEditDlog;
  1141.         short         itemHit;
  1142.         TEHandle      newTE;
  1143.         GrafPtr       oldPort;
  1144.         Rect          itemRect;
  1145.         OSAID         myCompiledID;
  1146.         Handle        myScript;
  1147.         Boolean       wholeMenu;
  1148.         ControlHandle myScrollBar;
  1149.         StyleTextInfo theStyleTextInfo;
  1150.         ModalFilterUPP modalFilterDescriptor;
  1151.  
  1152.     gEditingScript = true;
  1153.  
  1154.         GetPort(&oldPort);
  1155.         
  1156.         /*
  1157.             Look for a script associated with theItem first,
  1158.             and if not found look for one associated with 
  1159.             the whole menu
  1160.         */
  1161.         
  1162.         wholeMenu = false;
  1163.         
  1164.         resID = (theMenu<<5) + theItem;
  1165.         
  1166.         myScriptID = GetScriptIDForResID(resID);
  1167.         
  1168.         if (myScriptID==kOSANullScript)
  1169.           {
  1170.                 resID = (theMenu<<5);
  1171.                 myScriptID = GetScriptIDForResID(resID);
  1172.                 wholeMenu = true;
  1173.             }
  1174.                 
  1175.         scriptEditDlog = GetNewDialog(400, nil, (WindowPtr)-1);                     
  1176.         SetPort(scriptEditDlog);
  1177.         /*
  1178.             Create a styled text edit record for the userItem
  1179.             and install it
  1180.         */
  1181.         GetRectOfDialogItem(scriptEditDlog, kTextItem,  &itemRect);
  1182.         
  1183.         InsetRect(&itemRect, 5, 5);
  1184.         
  1185.         newTE = TEStylNew(&itemRect, &itemRect);
  1186.         
  1187.         TEAutoView(true, newTE);
  1188.         
  1189.         SetDrawProcForUserItem(scriptEditDlog, kTextItem, gDrawStyledTextUPP);
  1190.         
  1191.         /*
  1192.             Now create a scrollbar and install it
  1193.         */
  1194.         
  1195.         GetRectOfDialogItem(scriptEditDlog, kScrollBar, &itemRect);
  1196.         
  1197.         myScrollBar = NewControl(scriptEditDlog,
  1198.                                  &itemRect,
  1199.                                                          (unsigned char *)"",
  1200.                                                          true,
  1201.                                                          0,
  1202.                                                          0,
  1203.                                                          32000, // Will be fixed up later - by SetScrollLimit()
  1204.                                                          scrollBarProc,
  1205.                                                          0);
  1206.                                                          
  1207.         SetDrawProcForUserItem(scriptEditDlog, kScrollBar, gDrawScrollBarUPP);
  1208.         
  1209.         /*
  1210.             Use the dialog window refcon to allow access to the 
  1211.             TEHandle and scrollHandle avoiding the use
  1212.             of globals
  1213.         */
  1214.         
  1215.         theStyleTextInfo.theTEHandle  = newTE;
  1216.         theStyleTextInfo.theScrollBar = myScrollBar;
  1217.         
  1218.         SetWRefCon(scriptEditDlog, (long) &theStyleTextInfo);
  1219.  
  1220.         /*
  1221.             Put the source of the script into the 
  1222.             text edit record
  1223.         */
  1224.         
  1225.         myErr = OSAGetSource(gScriptingComponent,
  1226.                                                  myScriptID,
  1227.                                                  typeStyledText,
  1228.                                                  &scriptTextDesc);
  1229.       GetStyledTextFromDescIntoTEHandle(&scriptTextDesc, newTE);
  1230.         
  1231.         ignoreErr = AEDisposeDesc(&scriptTextDesc);
  1232.         
  1233.         SetScrollLimit(myScrollBar, newTE);
  1234.         TrackTEPosn(myScrollBar, newTE);
  1235.         
  1236.         /*    Added during PowerPC port: */
  1237.         
  1238.         modalFilterDescriptor = NewModalFilterProc(MyFilterProc);
  1239.         
  1240.         do {
  1241.             ModalDialog(modalFilterDescriptor, &itemHit);
  1242.             switch (itemHit){
  1243.                 case ok        :
  1244.                 case kCompile  :  SetCursor(&waitCursor);
  1245.                                                     HLock((Handle)(**newTE).hText);
  1246.                                   myErr = AECreateDesc(typeChar,
  1247.                                                                                             (Ptr)*((**newTE).hText),
  1248.                                                                                             (**newTE).teLength,
  1249.                                                                                             &scriptTextDesc);
  1250.                                                                                             
  1251.                                                   HUnlock((Handle)(**newTE).hText);
  1252.                                                     
  1253.                                                     myCompiledID = 0; // Added for Gustav 1.0a8
  1254.                                                     myErr = OSACompile(gScriptingComponent,
  1255.                                                                                          &scriptTextDesc,
  1256.                                                                                          0,
  1257.                                                                                          &myCompiledID);
  1258.                                                                                          
  1259.                                                     ignoreErr = AEDisposeDesc(&scriptTextDesc);
  1260.                                                     
  1261.                                                     scriptTextDesc.dataHandle = nil;
  1262.                                                     
  1263.                                                   if (myErr==noErr)
  1264.                                                       {
  1265.                                                             myErr = OSAGetSource(gScriptingComponent,
  1266.                                                                                                      myCompiledID,
  1267.                                                                                                      typeStyledText,
  1268.                                                                                                      &scriptTextDesc);
  1269.                                                                                                      
  1270.                                                             /* Zap current contents and
  1271.                                                                replace with returned source */
  1272.                                                                  
  1273.                                                             TESetSelect(0, 32000, newTE);
  1274.                                                             TEDelete(newTE);
  1275.                                                             SetCtlValue(myScrollBar, 0); // We deleted all the text so it won't be scrolled anymore
  1276.                                                             
  1277.                                                             GetStyledTextFromDescIntoTEHandle(&scriptTextDesc, newTE);
  1278.                                                             
  1279.                                                             DrawStyledTextEditRec(scriptEditDlog, kTextItem);
  1280.                                                                                                  
  1281.                                                             ignoreErr = AEDisposeDesc(&scriptTextDesc);
  1282.                                                         }
  1283.                                                     else
  1284.                                                         {
  1285.                                                             DisplayErrorInScript(newTE);
  1286.                                                             itemHit  = 0; // Stop dialog going away
  1287.                                                         }
  1288.                                                         
  1289.                                                     SetScrollLimit(myScrollBar, newTE);
  1290.                                                     TrackTEPosn(myScrollBar, newTE);
  1291.                                                 
  1292.                                                     SetCursor(&qd.arrow);
  1293.                                                         
  1294.                                                     if (itemHit==ok)
  1295.                                                         if (myErr==noErr)
  1296.                                                             {
  1297.                                                                 // Swap this script for the old one unless whole menu 
  1298.                                                               
  1299.                                                                 if (wholeMenu)
  1300.                                                                     myScriptID = kOSANullScript;
  1301.                                                                     
  1302.                                                                 myErr = OSACopyID(gScriptingComponent,
  1303.                                                                                                      myCompiledID,
  1304.                                                                                                      &myScriptID);
  1305.                                                                                                      
  1306.                                                                 myErr = OSAStore(gScriptingComponent,
  1307.                                                                                                  myScriptID,
  1308.                                                                                                  typeOSAGenericStorage,
  1309.                                                                                                  0,
  1310.                                                                                                  &scriptTextDesc);
  1311.                                                                                                  
  1312.                                                                 if (myErr==noErr)
  1313.                                                                     {
  1314.                                                                         /* should prompt for whole menu if mod 32 == 0 */
  1315.                                                                       
  1316.                                                                         resID = (theMenu<<5) + theItem;
  1317.                                                                         
  1318.                                                                         /* Remove it if it's already in the prefs file */
  1319.                                                                         
  1320.                                                                         myScript = Get1Resource(kCompiledScriptType, resID);
  1321.                                                                         
  1322.                                                                         if (myScript!=nil && ResError()==noErr)
  1323.                                                                             RemoveResource(myScript);
  1324.                                                                         
  1325.                                                                         /* And create a new resource */
  1326.                                                                         
  1327.                                                                         myScript = scriptTextDesc.dataHandle;
  1328.                                                                         
  1329.                                                                         HLock((Handle)myScript);
  1330.                                                                         HandToHand(&myScript);                                 
  1331.                                                                         AddResource(myScript, kCompiledScriptType, resID, (unsigned char *)"\pMenu Script");
  1332.                                                                         UpdateResFile(CurResFile());
  1333.                                                                         HUnlock((Handle)myScript);
  1334.                                                                         
  1335.                                                                         if (wholeMenu)
  1336.                                                                           AddMenuScript(resID, myScriptID);
  1337.                                                                     }
  1338.                                                                 myErr = AEDisposeDesc(&scriptTextDesc);
  1339.                                                             }
  1340.                                                         else
  1341.                                                             itemHit = -1;
  1342.                                                             
  1343.                                                     ignoreErr = OSADispose(gScriptingComponent,
  1344.                                                                                                  myCompiledID);
  1345.                                                     
  1346.                 case cancel    : 
  1347.                 case kTextItem : 
  1348.                 case kScrollBar: break;
  1349.             }
  1350.     } while (itemHit!=ok && itemHit!=cancel);
  1351.                 
  1352.         DisposeRoutineDescriptor(modalFilterDescriptor);
  1353.                 
  1354.         DisposeDialog(scriptEditDlog);
  1355.         
  1356.         SetPort(oldPort);
  1357.  
  1358.     gEditingScript = false;
  1359.         
  1360.         return(noErr);
  1361.  }
  1362.     
  1363.