home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / MacPerl 5.0.3 / MacPerl Source ƒ / MacPerl5 / MPMain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-28  |  28.0 KB  |  1,301 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPMain.c            -    The main event loop
  4. Author    :    Matthias Neeracher
  5.  
  6. A lot of this code is borrowed from 7Edit written by
  7. Apple Developer Support UK
  8.  
  9. Language    :    MPW C
  10.  
  11. $Log: MPMain.c,v $
  12. Revision 1.2  1994/05/04  02:52:40  neeri
  13. Inline Input.
  14.  
  15. Revision 1.1  1994/02/27  23:01:21  neeri
  16. Initial revision
  17.  
  18. Revision 0.9  1993/12/30  00:00:00  neeri
  19. DeferredKeys
  20.  
  21. Revision 0.8  1993/12/20  00:00:00  neeri
  22. Trying to be more subtle about cursors
  23.  
  24. Revision 0.7  1993/12/12  00:00:00  neeri
  25. SacrificialGoat
  26.  
  27. Revision 0.6  1993/10/17  00:00:00  neeri
  28. Mercutio Support
  29.  
  30. Revision 0.5  1993/08/17  00:00:00  neeri
  31. Preferences
  32.  
  33. Revision 0.4  1993/08/16  00:00:00  neeri
  34. Moved scripting to separate file
  35.  
  36. Revision 0.3  1993/07/15  00:00:00  neeri
  37. Beginning to see the light
  38.  
  39. Revision 0.2  1993/05/30  00:00:00  neeri
  40. Support Console Windows
  41.  
  42. Revision 0.1  1993/05/29  00:00:00  neeri
  43. Compiles correctly
  44.  
  45. *********************************************************************/
  46.  
  47. #include <Memory.h>
  48. #include <QuickDraw.h>
  49. #include <Types.h>
  50. #include <Menus.h>
  51. #include <Windows.h>
  52. #include <Dialogs.h>
  53. #include <Traps.h>
  54. #include <Packages.h>
  55. #include <DiskInit.h>
  56. #include <PPCToolbox.h>
  57. #include <Resources.h>
  58. #include <Editions.h>
  59. #include <Printing.h>
  60. #include <ToolUtils.h>
  61. #include <Desk.h>
  62. #include <Scrap.h>
  63. #include <OSEvents.h>
  64. #include <AppleEvents.h>
  65. #include <AEObjects.h>
  66. #include <Errors.h>
  67. #include <StandardFile.h>
  68. #include <Balloons.h>
  69. #include <String.h>
  70. #include <CType.h>
  71. #include <PLStringFuncs.h>
  72. #include <StdLib.h>
  73. #include <CursorCtl.h>
  74. #include <Script.h>
  75. #include <SegLoad.h>
  76.  
  77. #include "MPGlobals.h"
  78. #include "MPUtils.h"
  79. #include "MPEditions.h"
  80. #include "MPAppleEvents.h"
  81. #include "MPWindow.h"
  82. #include "MPFile.h"
  83. #include "MPHelp.h"
  84. #include "MPScript.h"
  85. #include "MPUtils.h"
  86. #include "MPPreferences.h"
  87. #include "Mercutio.h"
  88. #include "MPConsole.h"
  89. #include "MPPseudoFile.h"
  90.  
  91. #if !defined(powerc) && !defined(__powerc)
  92. #pragma segment MPMain
  93. #endif
  94.  
  95. pascal void MaintainCursor()
  96. {
  97.     Point         pt;
  98.     WindowPtr     wPtr;
  99.     GrafPtr       savePort;
  100.     DPtr          theDoc;
  101.     Boolean        inText = false;
  102.     
  103.     wPtr = FrontWindow();
  104.     if (Ours(wPtr)) {
  105.         theDoc = DPtrFromWindowPtr(wPtr);
  106.         GetPort(&savePort);
  107.         SetPort(wPtr);
  108.         GetMouse(&pt);
  109.         if (gTextServicesImplemented && SetTSMCursor(pt))
  110.             return;
  111.         if (theDoc->theText)
  112.             if (inText = PtInRect(pt, &(**(theDoc->theText)).viewRect))
  113.                 SetCursor(&editCursor);
  114.             else
  115.                 SetCursor(&qd.arrow);
  116.         else
  117.             SetCursor(&qd.arrow);
  118.  
  119.         if (theDoc->theText)
  120.             TEIdle(theDoc->theText);
  121.  
  122.         SetPort(savePort);
  123.     } else if (!wPtr)
  124.         SetCursor(&qd.arrow);
  125. }
  126.  
  127. #if !defined(powerc) && !defined(__powerc)
  128. #pragma segment MPMain
  129. #endif
  130.  
  131. FSSpec        jumpFile;
  132. WindowPtr    jumpWindow;
  133. short            jumpLine;
  134.  
  135. Boolean  SeriousFSSpec(char * name)
  136. {
  137.     CInfoPBRec    info;
  138.     
  139.     if (Path2FSSpec(name, &jumpFile))
  140.         return false;
  141.     if (FSpCatInfo(&jumpFile, &info) 
  142.      || info.dirInfo.ioFlAttrib & 0x10 
  143.      || !info.hFileInfo.ioFlLgLen
  144.     ) {
  145.         if (strchr(name, ':') || !(jumpWindow = AlreadyOpen(&jumpFile, jumpFile.name)))
  146.             return false;
  147.     } else
  148.         jumpWindow = nil;
  149.     
  150.     return true;
  151. }
  152.  
  153. Boolean    ParseJump(DPtr    theDoc)
  154. {
  155.     char        endCh;
  156.     char     endFileCh;
  157.     Boolean    result = false;
  158.     TEHandle    te     = theDoc->theText;
  159.     short        len    = (*te)->selEnd - (*te)->selStart;
  160.     char *    text;
  161.     char *   end;
  162.     char *   endFile;
  163.     Str255    jumpText;
  164.     
  165.     if (len <= 0)
  166.         goto fixupMenuItem;
  167.     
  168.     HLock((*te)->hText);
  169.     text = *(*te)->hText + (*te)->selStart;
  170.     end  = text + len;
  171.     endCh= *end;
  172.     *end = 0;
  173.  
  174. rescan:    
  175.     while (isspace(*text))
  176.         ++text;
  177.     
  178.     switch (*text) {
  179.     case 'F':
  180.     case 'f':
  181.         if (toupper(text[1]) == 'I' 
  182.          && toupper(text[2]) == 'L' 
  183.          && toupper(text[3]) == 'E'
  184.          && isspace(text[4])
  185.         ) {
  186.             /* Strip off "File" prefix */
  187.             text += 5;
  188.             
  189.             goto rescan;
  190.         } else
  191.             goto slurp;
  192.     case '\'':
  193.     case '\"':
  194.         if (endFile = strchr(text+1, *text)) {
  195.             *endFile = 0;
  196.             
  197.             if (endFile - text < 1 || !SeriousFSSpec(text+1)) {
  198.                 *endFile = *text;
  199.                 
  200.                 goto repair;
  201.             }
  202.             
  203.             *endFile = *text;
  204.             text = endFile + 1;
  205.             
  206.             break;
  207.         } 
  208.         
  209.         /* Unbalanced quote, skip & fall through */
  210.         ++text;
  211.     default:
  212. slurp:
  213.         /* Break at end of line */
  214.         if (endFile = strchr(text, '\n')) {
  215.             /* Strip trailing whitespace */
  216.             while (endFile > text && isspace(endFile[-1]))
  217.                 --endFile;
  218.                 
  219.             *endFile = 0;
  220.             
  221.             if (endFile - text < 1 || !SeriousFSSpec(text)) {
  222.                 *endFile = '\n';
  223.                 
  224.                 goto repair;
  225.             }
  226.             
  227.             *endFile = '\n';
  228.             text = endFile + 1;
  229.             
  230.             break;
  231.         } 
  232.         
  233.         if (end - text < 1 || !SeriousFSSpec(text))
  234.             goto repair;
  235.         
  236.         text = end;
  237.         break;
  238.     }
  239.     
  240.     /* Try to parse line # */
  241.     
  242.     jumpLine = 0;
  243.     
  244.     while (*text)
  245.         if (isdigit(*text)) {
  246.             while (isdigit(*text))
  247.                 jumpLine = jumpLine * 10 + *text++ - '0';
  248.             
  249.             break;
  250.         } else
  251.             ++text;
  252.     
  253.     result = true;
  254.         
  255. repair:    
  256.     *end = endCh;
  257.     HUnlock((*te)->hText);
  258.  
  259. fixupMenuItem:
  260.     if (result) {
  261.         jumpFile.name[jumpFile.name[0]+1] = 0;
  262.         jumpText[0] = sprintf((char *) jumpText+1, "Jump to \"%s\"", jumpFile.name+1);
  263.         if (jumpLine)
  264.             jumpText[0] += 
  265.                 sprintf((char *) jumpText+jumpText[0]+1, ", Line %d", jumpLine);
  266.         SetMenuItemText(myMenus[editM], emJumpTo, jumpText);
  267.     } else 
  268.         SetMenuItemText(myMenus[editM], emJumpTo, (StringPtr) "\pJump To…");
  269.  
  270.     return result;    
  271. }
  272.  
  273. #if !defined(powerc) && !defined(__powerc)
  274. #pragma segment MPMain
  275. #endif
  276.  
  277. static Boolean    mRunningPerl;
  278.  
  279. pascal void MaintainMenuBar()
  280. {
  281.     if (gRunningPerl != mRunningPerl) {
  282.         if (gRunningPerl) 
  283.             DeleteMenu(perlID);
  284.         else
  285.             InsertMenu(myMenus[perlM], 0);
  286.         
  287.         mRunningPerl = gRunningPerl;
  288.         
  289.         DrawMenuBar();
  290.     }
  291. }
  292.  
  293. pascal void MaintainMenus()
  294. {
  295.     DPtr               theDoc;
  296.     WindowPtr          firstWindow;
  297.     SectHandle         currSection;
  298.     
  299.     MaintainMenuBar();
  300.     
  301.     firstWindow = FrontWindow();
  302.     if (!Ours(firstWindow)) {
  303.         EnableItem(myMenus[fileM], fmNew);
  304.         EnableItem(myMenus[fileM], fmOpen);
  305.         DisableItem(myMenus[fileM], fmClose);
  306.         DisableItem(myMenus[fileM], fmSave);
  307.         DisableItem(myMenus[fileM], fmSaveAs);
  308.         DisableItem(myMenus[fileM], fmRevert);
  309.         DisableItem(myMenus[fileM], fmPrint);
  310.         DisableItem(myMenus[fileM], fmPageSetUp);
  311.         EnableItem(myMenus[fileM], fmQuit);
  312.  
  313.         if (firstWindow) {
  314.             EnableItem(myMenus[editM], undoCommand);
  315.             EnableItem(myMenus[editM], cutCommand);
  316.             EnableItem(myMenus[editM], copyCommand);
  317.             EnableItem(myMenus[editM], pasteCommand);
  318.             EnableItem(myMenus[editM], clearCommand);
  319.         } else {
  320.             DisableItem(myMenus[editM], undoCommand);
  321.             DisableItem(myMenus[editM], cutCommand);
  322.             DisableItem(myMenus[editM], copyCommand);
  323.             DisableItem(myMenus[editM], pasteCommand);
  324.             DisableItem(myMenus[editM], clearCommand);
  325.         }
  326.         EnableItem(myMenus[editM],  emPreferences);
  327.         DisableItem(myMenus[editM], selectAllCommand);
  328.  
  329.         DisableItem(myMenus[editM],  emJumpTo);
  330.         
  331.         DisableItem(myMenus[editM],  cPublisher);
  332.         DisableItem(myMenus[editM],  cSubscriber);
  333.         DisableItem(myMenus[editM],  cOptions);
  334.         DisableItem(myMenus[editM],  cBorders);
  335.  
  336.         EnableItem(myMenus[helpM], hmExplain);
  337.         
  338.         if (!mRunningPerl) {
  339.             SetItem(myMenus[perlM], pmRunFront, (StringPtr) "\pRun Front Window");
  340.             DisableItem(myMenus[perlM], pmRunFront);
  341.             SetItem(myMenus[perlM], pmCheckSyntax, (StringPtr) "\pSyntax Check");
  342.             DisableItem(myMenus[perlM], pmCheckSyntax);
  343.         }
  344.     } else {
  345.         theDoc = DPtrFromWindowPtr(firstWindow);
  346.         
  347.         if (theDoc->kind == kDocumentWindow) {
  348.             EnableItem(myMenus[editM], pasteCommand);
  349.             EnableItem(myMenus[editM], cBorders);
  350.             if (!mRunningPerl) {
  351.                 Str255    title;
  352.                 short        origLen;
  353.                 
  354.                 PLstrcpy(title, (StringPtr) "\pRun ");
  355.                 origLen                 = title[0];
  356.                 GetWTitle(firstWindow, title+origLen+1);
  357.                 title[0]             = title[origLen+1] + origLen + 2;
  358.                 title[origLen+1]    = '"';
  359.                 title[title[0]]    = '"';
  360.                 SetItem(myMenus[perlM], pmRunFront, title);
  361.                 EnableItem(myMenus[perlM], pmRunFront);
  362.                 
  363.                 PLstrcpy(title, (StringPtr) "\pSyntax Check ");
  364.                 origLen                 = title[0];
  365.                 GetWTitle(firstWindow, title+origLen+1);
  366.                 title[0]             = title[origLen+1] + origLen + 2;
  367.                 title[origLen+1]    = '"';
  368.                 title[title[0]]    = '"';
  369.                 SetItem(myMenus[perlM], pmCheckSyntax, title);
  370.                 EnableItem(myMenus[perlM], pmCheckSyntax);
  371.             }
  372.         } else {
  373.             DisableItem(myMenus[editM], cBorders);
  374.             
  375.             if ((*theDoc->theText)->selStart < theDoc->u.cons.fence)
  376.                 DisableItem(myMenus[editM], pasteCommand);
  377.             else
  378.                 EnableItem(myMenus[editM], pasteCommand);
  379.  
  380.             if (!mRunningPerl) {
  381.                 SetItem(myMenus[perlM], pmRunFront, (StringPtr) "\pRun Front Window");
  382.                 DisableItem(myMenus[perlM], pmRunFront);
  383.                 SetItem(myMenus[perlM], pmCheckSyntax, (StringPtr) "\pSyntax Check");
  384.                 DisableItem(myMenus[perlM], pmCheckSyntax);
  385.             }
  386.         }
  387.         
  388.         EnableItem(myMenus[fileM], fmClose);
  389.         EnableItem(myMenus[fileM], fmSave);
  390.         EnableItem(myMenus[fileM], fmSaveAs);
  391.         EnableItem(myMenus[fileM], fmPrint);
  392.         EnableItem(myMenus[fileM], fmPageSetUp);
  393.         EnableItem(myMenus[fileM], fmQuit);
  394.  
  395.         if (theDoc->kind == kDocumentWindow && theDoc->u.reg.everSaved && theDoc->dirty)
  396.             EnableItem(myMenus[fileM], fmRevert);
  397.         else
  398.             DisableItem(myMenus[fileM], fmRevert);
  399.  
  400.         DisableItem(myMenus[editM], undoCommand);
  401.  
  402.         if (((**(theDoc->theText)).selEnd - (**(theDoc->theText)).selStart) > 0) {
  403.             EnableItem(myMenus[editM], cutCommand);
  404.             EnableItem(myMenus[editM], copyCommand);
  405.             EnableItem(myMenus[editM], clearCommand);
  406.             EnableItem(myMenus[editM], cPublisher);
  407.         } else {
  408.             DisableItem(myMenus[editM], cutCommand);
  409.             DisableItem(myMenus[editM], copyCommand);
  410.             DisableItem(myMenus[editM], clearCommand);
  411.             DisableItem(myMenus[editM], cPublisher);
  412.         }
  413.         
  414.         EnableItem(myMenus[editM],  selectAllCommand);
  415.         EnableItem(myMenus[editM],  emPreferences);
  416.  
  417.         if (ParseJump(theDoc))
  418.             EnableItem(myMenus[editM],  emJumpTo);
  419.         else
  420.             DisableItem(myMenus[editM],  emJumpTo);
  421.  
  422.         currSection =
  423.             GetSection(
  424.                 (**(theDoc->theText)).selStart,
  425.                 (**(theDoc->theText)).selEnd,
  426.                 theDoc);
  427.  
  428.         if (theDoc->kind != kDocumentWindow) {
  429.             DisableItem(myMenus[editM], cPublisher);
  430.             DisableItem(myMenus[editM], cSubscriber);
  431.             DisableItem(myMenus[editM], cOptions);
  432.         } else if (currSection) {
  433.             DisableItem(myMenus[editM], cPublisher);
  434.             DisableItem(myMenus[editM], cSubscriber);
  435.             EnableItem(myMenus[editM],  cOptions);
  436.             if ((**(**currSection).fSectHandle).kind == stPublisher)
  437.                 SetItem(myMenus[editM], cOptions, (StringPtr) "\pPublisher Options…");
  438.             else
  439.                 SetItem(myMenus[editM], cOptions, (StringPtr) "\pSubscriber Options…");
  440.         } else {
  441.             EnableItem(myMenus[editM],  cPublisher);
  442.             EnableItem(myMenus[editM],  cSubscriber);
  443.             DisableItem(myMenus[editM], cOptions);
  444.         }
  445.         
  446.         EnableItem(myMenus[helpM], hmExplain);
  447.     }
  448. }
  449.  
  450. #if !defined(powerc) && !defined(__powerc)
  451. #pragma segment MPMain
  452. #endif
  453.  
  454. pascal void SetUpCursors(void)
  455. {
  456.     CursHandle  hCurs;
  457.  
  458.     hCurs = GetCursor(1);
  459.     editCursor = **hCurs;
  460.     hCurs = GetCursor(watchCursor);
  461.     waitCursor = **hCurs;
  462. }
  463.  
  464. #if !defined(powerc) && !defined(__powerc)
  465. #pragma segment MPMain
  466. #endif
  467.  
  468. static short gExplainItem;
  469.  
  470. pascal void SetUpMenus(void)
  471. {
  472.     short             i;
  473.     StringHandle    str;
  474.  
  475.     myMenus[appleM] = GetMenu(appleID);
  476.     AddResMenu(myMenus[appleM], 'DRVR');
  477.     myMenus[fileM] = GetMenu(fileID);
  478.     myMenus[editM] = GetMenu(editID);
  479.     myMenus[windowM]    = GetMenu(windowID);
  480.     myMenus[perlM]    = GetMenu(perlID);
  481.  
  482.     for (i = appleM; i < kLastMenu; i++)
  483.         InsertMenu(myMenus[i], 0);
  484.  
  485.     HMGetHelpMenuHandle(&myMenus[helpM]);
  486.     str = GetString(helpID);
  487.     
  488.     HLock((Handle) str);
  489.     AppendMenu(myMenus[helpM], *str);
  490.     ReleaseResource((Handle) str);
  491.     
  492.     gExplainItem = CountMItems(myMenus[helpM]);
  493.     
  494.     SetShortMenus(); /* Does a DrawMenuBar() */
  495. }
  496.  
  497. pascal void DoFile(short theItem)
  498. {
  499.     short   alertResult;
  500.     DPtr    theDoc;
  501.     FSSpec  theFSSpec;
  502.     OSErr   fileErr;
  503.     TPrint  thePSetup;
  504.  
  505.     switch (theItem){
  506.     case fmNew:
  507.         IssueAENewWindow();
  508.         break;
  509.  
  510.     case fmOpen:
  511.         if (GetFile(&theFSSpec)==noErr)
  512.             fileErr = IssueAEOpenDoc(theFSSpec);
  513.         break;
  514.  
  515.     case fmClose:
  516.         IssueCloseCommand(FrontWindow());
  517.         break;
  518.  
  519.     case fmSave:
  520.     case fmSaveAs:
  521.         theDoc = DPtrFromWindowPtr(FrontWindow());
  522.  
  523.         if (theItem==fmSaveAs || theDoc->kind != kDocumentWindow || !theDoc->u.reg.everSaved) {
  524.             fileErr = GetFileNameToSaveAs(theDoc);
  525.             if (!fileErr)
  526.                 fileErr = IssueSaveCommand(theDoc, &theDoc->theFSSpec);
  527.             else if (fileErr != userCanceledErr)    
  528.                 FileError((StringPtr) "\perror saving ", theDoc->theFileName);
  529.         } else
  530.             fileErr = IssueSaveCommand(theDoc, nil);
  531.         break;
  532.  
  533.     case fmRevert:
  534.         SetCursor(&qd.arrow);
  535.         theDoc = DPtrFromWindowPtr(FrontWindow());
  536.  
  537.         ParamText(theDoc->theFileName, (StringPtr) "", (StringPtr) "", (StringPtr) "");
  538.         alertResult = Alert(RevertAlert, nil);
  539.         switch (alertResult){
  540.             case aaSave:
  541.                 if (IssueRevertCommand(theDoc->theWindow))
  542.                     FileError((StringPtr) "\perror reverting ", theDoc->theFileName);
  543.         }
  544.         break;
  545.  
  546.     case fmPageSetUp:
  547.         theDoc = DPtrFromWindowPtr(FrontWindow());
  548.         if (DoPageSetup(theDoc)) {
  549.              thePSetup = **(theDoc->thePrintSetup);
  550.              IssuePageSetupWindow(theDoc->theWindow, thePSetup);
  551.          }
  552.         break;
  553.  
  554.     case fmPrint:
  555.         IssuePrintWindow(FrontWindow());
  556.          break;
  557.  
  558.     case fmQuit:
  559.         IssueQuitCommand();
  560.         break;
  561.     } /*of switch*/
  562. }
  563.  
  564. #if !defined(powerc) && !defined(__powerc)
  565. #pragma segment MPMain
  566. #endif
  567.  
  568. pascal void DoCommand(long mResult, Boolean option, Boolean mousing)
  569. {
  570.     short          theMenu;
  571.     short       theItem;
  572.     short       err;
  573.     Str255      name;
  574.     DPtr        theDocument;
  575.  
  576.     if (!mResult) {
  577.         /*
  578.          * Hierarchical submenus of the Help menu are broken. We therefore
  579.          * special case for them but prevent this route from being taken for
  580.          * any other menu
  581.          */
  582.         
  583.         if (mousing)
  584.             mResult = MenuChoice();
  585.         
  586.         if (!mResult)
  587.             return;
  588.         else
  589.             mResult |= 0x80000000;
  590.     }
  591.     
  592.     theDocument = DPtrFromWindowPtr(FrontWindow());
  593.         
  594.     if (gTextServicesImplemented && TSMMenuSelect(mResult))
  595.         goto done;
  596.     if (theDocument && theDocument->tsmDoc)
  597.         FixTSMDocument(theDocument->tsmDoc);
  598.  
  599.     theItem = LoWord(mResult);
  600.  
  601.     switch (theMenu = HiWord(mResult)) {
  602.     case appleID:
  603.         if (theItem == aboutItem) {
  604.             DoAbout(option);
  605.         } else {
  606.             GetItem(myMenus[appleM], theItem, name);
  607.             err = OpenDeskAcc(name);
  608.             SetPort(FrontWindow());
  609.         }
  610.           break;
  611.  
  612.     case fileID:
  613.         DoFile(theItem);
  614.         break;
  615.  
  616.     case editID:
  617.         SystemEdit(theItem - 1);
  618.  
  619.         switch (theItem) {
  620.         case cutCommand:
  621.             IssueCutCommand(theDocument);
  622.             break;
  623.  
  624.         case copyCommand:
  625.             IssueCopyCommand(theDocument);
  626.             break;
  627.  
  628.         case pasteCommand :
  629.             IssuePasteCommand(theDocument);
  630.             break;
  631.  
  632.         case clearCommand :
  633.             IssueClearCommand(theDocument);
  634.             break;
  635.  
  636.         case selectAllCommand:
  637.             if (theDocument)
  638.                 TESetSelect(0, (**(theDocument->theText)).teLength, theDocument->theText);
  639.             break;
  640.  
  641.         case cPublisher:
  642.             IssueCreatePublisher(theDocument);
  643.             break;
  644.  
  645.         case cSubscriber:
  646.             DoSubscribe(theDocument);
  647.             break;
  648.  
  649.         case cOptions:
  650.             DoSectionOptions(theDocument);
  651.             break;
  652.  
  653.         case cBorders:
  654.             IssueShowBorders(theDocument->theWindow, !theDocument->u.reg.showBorders);
  655.             break;
  656.  
  657.         case emJumpTo:
  658.             IssueJumpCommand(&jumpFile, jumpWindow, jumpLine);
  659.             break;
  660.             
  661.         case emFormat:
  662.             IssueFormatCommand(theDocument);
  663.             break;
  664.             
  665.         case emPreferences:
  666.             DoPrefDialog();
  667.             break;
  668.         }     /*of switch*/
  669.  
  670.         ShowSelect(theDocument);
  671.          break;
  672.     
  673.     case windowID:
  674.         DoSelectWindow(theItem);
  675.         break;
  676.  
  677.     case perlID:
  678.         DoScriptMenu(theItem);
  679.         break;
  680.  
  681.     case kHMHelpMenuID:
  682.         if (theItem == gExplainItem)
  683.             Explain(theDocument);
  684.         else
  685.             DoHelp(0, theItem);
  686.         break;
  687.     
  688.     default:
  689.         theMenu &= 0x7FFF;
  690.         
  691.         if (theMenu > kHierHelpMenu && theMenu < kHierHelpMenu+20)
  692.             DoHelp(theMenu - kHierHelpMenu, theItem);
  693.         break;
  694.     }                 /*of switch*/
  695.  
  696. done:
  697.     HiliteMenu(0);
  698. }
  699.  
  700. #if !defined(powerc) && !defined(__powerc)
  701. #pragma segment MPMain
  702. #endif
  703.  
  704. pascal void DoMouseDown(EventRecord *myEvent)
  705. {
  706.     WindowPtr whichWindow;
  707.     Point     p;
  708.     Rect      dragRect;
  709.  
  710.     p = myEvent->where;
  711.     switch (FindWindow(p, &whichWindow)) {
  712.     case inDesk:
  713.         SysBeep(10);
  714.         break;
  715.  
  716.     case inGoAway:
  717.         if (Ours(whichWindow))
  718.             if (TrackGoAway(whichWindow, p))
  719.                 IssueCloseCommand(whichWindow);
  720.         break;
  721.  
  722.     case inMenuBar:
  723.         SetCursor(&qd.arrow);
  724.         SetupWindowMenu();
  725.         MaintainMenus();
  726.         DoCommand(MenuSelect(p), (myEvent->modifiers & optionKey) == optionKey, true);
  727.         HiliteMenu(0);
  728.         break;
  729.  
  730.     case inSysWindow:
  731.         SystemClick(myEvent, whichWindow);
  732.         break;
  733.  
  734.     case inDrag:
  735.         dragRect = qd.screenBits.bounds;
  736.  
  737.         if (Ours(whichWindow)) {
  738.             DragWindow(whichWindow, p, &dragRect);
  739.             /*
  740.                 As rgnBBox may be passed by address
  741.             */
  742.             dragRect = (**((WindowPeek)whichWindow)->strucRgn).rgnBBox;
  743.             /*
  744.                 The windows already there, but still tell
  745.                 the our AppleEvents core about the move in case
  746.                 they want to do anything
  747.             */
  748.             IssueMoveWindow(whichWindow, dragRect);
  749.         }
  750.           break;
  751.  
  752.     case inGrow:
  753.         SetCursor(&qd.arrow);
  754.         if (Ours(whichWindow))
  755.             MyGrowWindow(whichWindow, p);
  756.         break;
  757.  
  758.     case inZoomIn:
  759.         DoZoom(whichWindow, inZoomIn, p);
  760.         break;
  761.  
  762.     case inZoomOut:
  763.         DoZoom(whichWindow, inZoomOut, p);
  764.         break;
  765.  
  766.     case inContent:
  767.         if (whichWindow != FrontWindow())
  768.             SelectWindow(whichWindow);
  769.         else
  770.             if (Ours(whichWindow))
  771.                 DoContent(whichWindow, myEvent);
  772.         break;
  773.     }                 /*of switch*/
  774. }
  775.  
  776. #if !defined(powerc) && !defined(__powerc)
  777. #pragma segment MPMain
  778. #endif
  779.  
  780. pascal long GetSleep(void)
  781. {
  782.     long      sleep;
  783.     WindowPtr theWindow;
  784.     DPtr      theDoc;
  785.  
  786.     sleep = 30;
  787.     if (!gInBackground)
  788.         {
  789.             theWindow = FrontWindow();
  790.             if (theWindow)
  791.                 {
  792.                     theDoc = DPtrFromWindowPtr(theWindow);
  793.                     if ((**(theDoc->theText)).selStart == (**(theDoc->theText)).selEnd)
  794.                         sleep = GetCaretTime();
  795.                 }
  796.         }
  797.     return(sleep);
  798. }                     /*GetSleep*/
  799.  
  800. long FindMenuKey(EventRecord * ev)
  801. {
  802.     /* Work around Help manager bug */
  803.     short    key;
  804.     
  805.     GetItemCmd(myMenus[helpM], gExplainItem, &key);
  806.     
  807.     if (toupper((char) key) == toupper(ev->message & charCodeMask))
  808.         return (kHMHelpMenuID << 16) | gExplainItem;
  809.     else {
  810.         MaintainMenus();
  811.  
  812.         return PowerMenuKey(ev->message, ev->modifiers, myMenus[fileM]);
  813.     }
  814. }
  815.  
  816. #if !defined(powerc) && !defined(__powerc)
  817. #pragma segment MPMain
  818. #endif
  819.  
  820. typedef enum {keyOK, keyRetry, keyAbort} KeyStatus;
  821.  
  822. #define kHome        1
  823. #define kEnd        4
  824. #define kHelp        5
  825. #define kPageUp    11
  826. #define kPageDown    12
  827.  
  828. KeyStatus TryKey(DPtr theDoc, char theChar)
  829. {
  830.     short value;
  831.     
  832.     if (theDoc->kind != kDocumentWindow && DoRawConsole(theDoc->u.cons.cookie, theChar))
  833.         return keyOK;
  834.  
  835.     switch (theChar) {
  836.     case 0:
  837.     case 2:
  838.     case 6:
  839.     case 7:
  840.     case 10:
  841.     case 14:
  842.     case 15:
  843.     case 16:
  844.     case 17:
  845.     case 18:
  846.     case 19:
  847.     case 20:
  848.     case 21:
  849.     case 22:
  850.     case 23:
  851.     case 24:
  852.     case 25:
  853.     case 26:
  854.     case 27:
  855.     case 0x7F:
  856.         return keyAbort;
  857.     case kHome:
  858.         value = GetCtlValue(theDoc->vScrollBar);
  859.         SetCtlValue(theDoc->vScrollBar, GetCtlMin(theDoc->vScrollBar));
  860.         DoThumb(theDoc, theDoc->vScrollBar, value);
  861.         
  862.         return keyOK;
  863.     case kEnd:
  864.         value = GetCtlValue(theDoc->vScrollBar);
  865.         SetCtlValue(theDoc->vScrollBar, GetCtlMax(theDoc->vScrollBar));
  866.         DoThumb(theDoc, theDoc->vScrollBar, value);
  867.         
  868.         return keyOK;
  869.     case kPageUp:
  870.         VActionProc(theDoc->vScrollBar, inPageUp);
  871.         return keyOK;
  872.     case kPageDown:
  873.         VActionProc(theDoc->vScrollBar, inPageDown);
  874.         return keyOK;
  875.     case kHelp:
  876.         Explain(theDoc);
  877.         return keyOK;
  878.     case ETX:
  879.         theChar = CR;
  880.         
  881.         break;
  882.     default:
  883.         break;
  884.     }
  885.  
  886.     {
  887.         SectHandle  currSection;
  888.         
  889.         /*
  890.             don't allow a subscriber to be changed
  891.         */
  892.         currSection =
  893.             GetSection(
  894.                 (**(theDoc->theText)).selStart,
  895.                 (**(theDoc->theText)).selEnd,
  896.                 theDoc);
  897.     
  898.         if (currSection)
  899.             if ((**(**currSection).fSectHandle).kind == stSubscriber)
  900.                 if (!KeyOKinSubscriber(theChar))
  901.                     return keyAbort;
  902.     }
  903.  
  904.     if (theDoc->kind == kDocumentWindow) {
  905.         DoTEKeySectionRecalc(theDoc, theChar);
  906.     } else if (theChar == BS) {
  907.         if (AllSelected(theDoc->theText)) {
  908.             if (theDoc->u.cons.fence < 32767)
  909.                 theDoc->u.cons.fence = 0;
  910.         } else if ((*theDoc->theText)->selStart == (*theDoc->theText)->selEnd)
  911.             if ((*theDoc->theText)->selStart-1 < theDoc->u.cons.fence)
  912.                 return keyAbort;
  913.             else if ((*theDoc->theText)->selStart < theDoc->u.cons.fence)
  914.                 return keyAbort;
  915.     } else if (
  916.         (*theDoc->theText)->selStart < theDoc->u.cons.fence &&
  917.         !KeyOKinSubscriber(theChar)
  918.     ) 
  919.         return keyAbort;
  920.     else if (!theDoc->u.cons.selected)
  921.         return gRunningPerl ? keyRetry : keyAbort;
  922.  
  923.     AddKeyToTypingBuffer(theDoc, theChar);
  924.     TEKey(theChar, theDoc->theText);
  925.     EnforceMemory(theDoc, theDoc->theText);
  926.     AdjustScrollbars(theDoc, false);
  927.     ShowSelect(theDoc);
  928.  
  929.     theDoc->dirty = true;
  930.     
  931.     return keyOK;
  932. }
  933.  
  934. #if !defined(powerc) && !defined(__powerc)
  935. #pragma segment MPMain
  936. #endif
  937.  
  938. static Boolean IntlTSMEvent(EventRecord *event)
  939. {
  940.     short oldFont;
  941.     ScriptCode keyboardScript;
  942.     
  943.     if (qd.thePort != nil)
  944.     {
  945.         oldFont = qd.thePort->txFont;
  946.         keyboardScript = GetScriptManagerVariable(smKeyScript);
  947.         if (FontToScript(oldFont) != keyboardScript)
  948.             TextFont(GetScriptVariable(keyboardScript, smScriptAppFond));
  949.     };
  950.     return TSMEvent(event);
  951. }
  952.  
  953. /* Our cursor/WaitNextEvent strategy */
  954.  
  955. #define BUSY_WAIT            120
  956. #define FRONT_FREQUENCY    30
  957. #define BACK_FREQUENCY  10
  958.  
  959. static long            lastNonBusy     = 0;
  960. static long         lastWNE         = 0;
  961. static char            deferredKeys[256];
  962. static short        deferredRd        = 0;
  963. static short        deferredWr        = 0;
  964. static WindowPtr    deferredWindow    = 0;
  965. static RgnHandle    mouseRgn;
  966.  
  967. #if !defined(powerc) && !defined(__powerc)
  968. #pragma segment MPMain
  969. #endif
  970.  
  971. void HandleEvent(EventRecord * myEvent)
  972. {
  973.     char        theChar;
  974.     Boolean     activate;
  975.     Point            mouse;
  976.     WindowPtr   theWindow;
  977.     DPtr        theDoc;
  978.  
  979.     theDoc = DPtrFromWindowPtr(FrontWindow());
  980.     
  981.     switch (myEvent->what) {
  982.     case mouseDown:
  983.         FlushAndRecordTypingBuffer();
  984.         DoMouseDown(myEvent);
  985.         lastNonBusy = TickCount();
  986.         break;
  987.  
  988.     case keyDown:
  989.     case autoKey:
  990.         if (WeirdChar(myEvent, cmdKey, ETX) 
  991.          || WeirdChar(myEvent, controlKey, 'd')
  992.         )    {
  993.             if (theDoc && theDoc->kind != kDocumentWindow) {
  994.                 gGotEof            =    theDoc;
  995.                 theDoc->dirty     =     true;
  996.             } 
  997.             
  998.             break;
  999.         } 
  1000.         
  1001.         theChar = myEvent->message & charCodeMask;
  1002.  
  1003.         if ((myEvent->modifiers & cmdKey) == cmdKey) {
  1004.             FlushAndRecordTypingBuffer();
  1005.             DoCommand(FindMenuKey(myEvent), (myEvent->modifiers & optionKey) == optionKey, false);
  1006.             HiliteMenu(0);
  1007.         } else if (theDoc && theDoc->theText)
  1008.             switch (TryKey(theDoc, theChar)) {
  1009.             case keyOK:
  1010.             case keyAbort:
  1011.                 break;
  1012.             case keyRetry:
  1013.                 if (FrontWindow() != deferredWindow) {
  1014.                     deferredRd = deferredWr;
  1015.                     deferredWindow = FrontWindow();
  1016.                 }
  1017.                 deferredKeys[deferredWr] = theChar;
  1018.                 deferredWr = (deferredWr + 1) & 255;
  1019.                 break;
  1020.             }
  1021.         break;
  1022.  
  1023.     case activateEvt:
  1024.         activate = ((myEvent->modifiers & activeFlag) != 0);
  1025.         theWindow = (WindowPtr)myEvent->message;
  1026.         DoActivate(theWindow, activate);
  1027.         break;
  1028.  
  1029.     case updateEvt:
  1030.         theWindow = (WindowPtr)myEvent->message;
  1031.         DoUpdate(DPtrFromWindowPtr(theWindow), theWindow);
  1032.         break;
  1033.  
  1034.     case kHighLevelEvent:
  1035.         FlushAndRecordTypingBuffer();
  1036.         DoAppleEvent(*myEvent);
  1037.         
  1038.         if (gDelayedScript.dataHandle) {
  1039.             DoScript(&gDelayedScript, nil, 0);
  1040.             AEDisposeDesc(&gDelayedScript);
  1041.         }
  1042.         break;
  1043.  
  1044.     case kOSEvent:
  1045.         switch (myEvent->message & osEvtMessageMask) { /*high byte of message*/
  1046.         case 0x01000000:
  1047.                 FlushAndRecordTypingBuffer();
  1048.                 gInBackground = ((myEvent->message & resumeFlag) == 0);
  1049.                 if (!gInBackground)
  1050.                     InitCursor();
  1051.                 DoActivate(FrontWindow(), !gInBackground);
  1052.         }
  1053.         break;
  1054.     case diskEvt:
  1055.         if (myEvent->message & 0xFFFF0000) {
  1056.             DILoad();
  1057.             SetPt(&mouse, 120, 120);
  1058.             DIBadMount(mouse, myEvent->message);
  1059.             DIUnload();
  1060.         }
  1061.     }
  1062. }
  1063.  
  1064. pascal void MainEvent(Boolean busy)
  1065. {
  1066.     DPtr        theDoc;
  1067.     Boolean        gotEvent;
  1068.     WindowPtr   theWindow;
  1069.     long            now;
  1070.     EventRecord myEvent;
  1071.     Point            mouse;
  1072.  
  1073.     if (!gSacrificialGoat)        /* Memory trouble */
  1074.         if (gRunningPerl)            /* This script has gone too far */
  1075.             die("Out of memory ! Aborting script for your own good...\n");
  1076.         else                            /* We aborted it, now buy a new goat */
  1077.             if (!(gSacrificialGoat = NewHandle(SACRIFICE)))
  1078.                 exit(0);        /* Save our sorry ass. Shouldn't happen */
  1079.     
  1080.     now = TickCount();
  1081.     if (busy) {
  1082.         if (now - lastNonBusy < BUSY_WAIT)
  1083.             busy = false;
  1084.     } else
  1085.         lastNonBusy = now;
  1086.     
  1087.     MaintainMenuBar();
  1088.  
  1089.     if (busy) {
  1090.         SpinCursor(1);
  1091.         
  1092.         if (now - lastWNE < (gInBackground ? BACK_FREQUENCY : FRONT_FREQUENCY))
  1093.             return;
  1094.     } else
  1095.         MaintainCursor();
  1096.     
  1097.     lastWNE = now;    
  1098.     gGotEof = nil;
  1099.     
  1100.     if (!gRunningPerl && GetHandleSize((Handle) gWaitingScripts)) {
  1101.         AppleEvent * ev    =    (*gWaitingScripts)[0];
  1102.         AppleEvent * repl    =    (*gWaitingScripts)[1];
  1103.         
  1104.         Munger((Handle) gWaitingScripts, 0, nil, 8, (Ptr) -1, 0);
  1105.         
  1106.         AEResumeTheCurrentEvent(
  1107.             ev, repl, (AEEventHandlerUPP) kAEUseStandardDispatch, -1);
  1108.     }
  1109.     
  1110.     if ((theDoc = DPtrFromWindowPtr(FrontWindow())) && theDoc->theText) 
  1111.         while (deferredKeys[deferredRd]) {
  1112.             switch (deferredWindow != FrontWindow() ? keyAbort : TryKey(theDoc, deferredKeys[deferredRd])) {
  1113.             case keyOK:
  1114.             case keyAbort:
  1115.                 deferredKeys[deferredRd] = 0;
  1116.                 deferredRd = (deferredRd + 1) & 255;
  1117.                 continue;
  1118.             }
  1119.             break;
  1120.         }
  1121.  
  1122.     if (!(theWindow = FrontWindow()))
  1123.         GetWMgrPort(&theWindow);
  1124.         
  1125.     SetPort(theWindow);
  1126.  
  1127.     SetScriptManagerVariable(smFontForce, gSavedFontForce);
  1128.  
  1129.     if (!busy) {
  1130.         if (!mouseRgn) 
  1131.             mouseRgn    =    NewRgn();
  1132.         
  1133.         GetMouse(&mouse);
  1134.         SetRectRgn(mouseRgn, mouse.h, mouse.v, mouse.h, mouse.v);
  1135.         gotEvent = WaitNextEvent(everyEvent, &myEvent, GetSleep(), mouseRgn);
  1136.     } else 
  1137.         gotEvent = WaitNextEvent(everyEvent, &myEvent, 0, nil);
  1138.  
  1139.     // clear fontForce again so it doesn't upset our operations
  1140.     gSavedFontForce = GetScriptManagerVariable(smFontForce);
  1141.     (void) SetScriptManagerVariable(smFontForce, 0);
  1142.         
  1143.     if (gotEvent && gTextServicesImplemented && IntlTSMEvent(&myEvent))
  1144.         gotEvent = false;        // TSMTE handled it without our help
  1145.  
  1146.     if (gotEvent)
  1147.         HandleEvent(&myEvent);
  1148.         
  1149.     if (gQuitting && gRunningPerl)
  1150.         my_exit(-128);
  1151. }
  1152.  
  1153. pascal long VoodooChile(Size cbNeeded)
  1154. {
  1155. #if !defined(powerc) && !defined(__powerc)
  1156.     long    oldA5 = SetCurrentA5();
  1157. #endif
  1158.     long    res;
  1159.     
  1160.     if (gSacrificialGoat && (GZSaveHnd() != gSacrificialGoat)) {
  1161.         /* Oh Memory Manager, our dark Lord. Take the blood of this animal to
  1162.            unwield thy power to crush our enemies.
  1163.             
  1164.             (Chant 7 times)
  1165.         */
  1166.         DisposeHandle(gSacrificialGoat);
  1167.         
  1168.         gSacrificialGoat     =     0;
  1169.         res                    =    SACRIFICE;
  1170.     } else
  1171.         res                     =    0;
  1172.         
  1173. #if !defined(powerc) && !defined(__powerc)
  1174.     SetA5(oldA5);
  1175. #endif
  1176.     
  1177.     return res;
  1178. }
  1179.  
  1180.  
  1181. #if USESROUTINEDESCRIPTORS
  1182. RoutineDescriptor    uVoodooChile = 
  1183.         BUILD_ROUTINE_DESCRIPTOR(uppGrowZoneProcInfo, VoodooChile);
  1184. #else
  1185. #define uVoodooChile *(GrowZoneUPP)&VoodooChile
  1186. #endif
  1187.  
  1188. #if !defined(powerc) && !defined(__powerc)
  1189. #pragma segment MPMain
  1190. #endif
  1191.  
  1192. double * cs;
  1193. double * ps;
  1194.  
  1195. void main()
  1196. {
  1197.     OSErr  err;
  1198.     short  result;
  1199.  
  1200.     InitGraf(&qd.thePort);
  1201.     InitFonts();
  1202.     FlushEvents(everyEvent, 0);
  1203.     InitWindows();
  1204.     InitMenus();
  1205.     TEInit();
  1206.     InitDialogs(nil);
  1207.     InitCursor();
  1208.  
  1209.     SetApplLimit(GetApplLimit() - 65535);    /* We need moore stack */
  1210.     MaxApplZone();
  1211.     SetGrowZone(&uVoodooChile);
  1212.     SetUpCursors();
  1213.  
  1214.     /*check environment checks to see if we are running 7.0*/
  1215.     if (!CheckEnvironment()) {
  1216.         SetCursor(&qd.arrow);
  1217.         /*pose the only 7.0 alert*/
  1218.         result = Alert(302, nil);
  1219.         return;
  1220.     }
  1221.  
  1222.     gAppFile                = CurResFile();
  1223.  
  1224.     ICStart(&gICInstance, MPAppSig);
  1225.     if (gICInstance)
  1226.         ICFindConfigFile(gICInstance, 0, nil);
  1227.     
  1228.     gPerlPrefs.version             =     PerlPrefVersion500;
  1229.     gPerlPrefs.runFinderOpens    =    false;
  1230.     gPerlPrefs.checkType            =    false;
  1231.     gPerlPrefs.inlineInput        =     true;
  1232.     
  1233.     OpenPreferences();
  1234.     
  1235.     SetUpMenus();
  1236.  
  1237.     gWCount                = 0;
  1238.     gNewDocCount         = 0;
  1239.     gQuitting              = false;
  1240.     gWarnings              = false;
  1241.     gDebug                  = false;
  1242.     gFontMItem             = 0;
  1243.     gConsoleList        = nil;
  1244.     gActiveWindow        = nil;
  1245.     gScriptFile            = gAppFile;
  1246.     gWaitingScripts    = (AppleEvent ***) NewHandle(0);
  1247.     gGotEof                = nil;
  1248.     gSacrificialGoat    = NewHandle(SACRIFICE);
  1249.     gPerlPool            = new_malloc_pool('PERL', SUGGESTED_BLK_SIZE);
  1250.  
  1251.     if (err = InitEditionPack()) {
  1252.         ShowError((StringPtr) "\pInitEditionPack", err);
  1253.         gQuitting = true;
  1254.     }
  1255.  
  1256.     if (err = AEObjectInit()) {
  1257.         ShowError((StringPtr) "\pAEObjectInit", err);
  1258.         gQuitting = true;
  1259.     }
  1260.  
  1261.     InitAppleEvents();
  1262.  
  1263.     if (err = PPCInit()) {
  1264.         ShowError((StringPtr) "\pPPCInit", err);
  1265.         gQuitting = true;
  1266.     }
  1267.  
  1268.     if (!(gTSMTEImplemented && !InitTSMAwareApplication())) {
  1269.         gTextServicesImplemented = false;
  1270.         gTSMTEImplemented = false;
  1271.     }
  1272.     
  1273.     InitConsole();
  1274.     InitPseudo();
  1275.     InitHelp();
  1276.     InitHelpIndex();
  1277.     EndHelp();
  1278.  
  1279.     gSavedFontForce = GetScriptManagerVariable(smFontForce);
  1280.     (void) SetScriptManagerVariable(smFontForce, 0);
  1281.     
  1282.     if (gQuitting)
  1283.         exit(0);
  1284.         
  1285.     InitPerlEnviron();
  1286.     
  1287.     GUSISetSpin(MPConsoleSpin);
  1288.     
  1289.     for (gQuitting = DoRuntime(); !gQuitting; )
  1290.         MainEvent(false);
  1291.  
  1292.     if (gICInstance)
  1293.         ICStop(gICInstance);
  1294.         
  1295.     if (gTextServicesImplemented)
  1296.         CloseTSMAwareApplication();
  1297.     SetScriptManagerVariable(smFontForce, gSavedFontForce);
  1298.     
  1299.     ExitToShell();
  1300. }
  1301.