home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / frntsdk1.cpt / Frontier SDK 1.0 ƒ / Frontier Do-Script / main.c < prev   
Encoding:
C/C++ Source or Header  |  1991-11-07  |  11.7 KB  |  578 lines

  1.  
  2. /*⌐ Copyright 1989-1991 UserLand Software, Inc.  All Rights Reserved.*/
  3.  
  4.  
  5. /*
  6. Frontier Do-Script -- Drives Frontier's "do-script" Apple event. You can send 
  7. any valid Frontier script across this channel. 
  8.  
  9. This program starts by sending a script with a syntax error, to test the error
  10. reporting mechanism.
  11.  
  12. Then it sends a do-script message to Frontier once every 5 seconds. You can
  13. leave this program running while you use Frontier to test do-scripting in all
  14. circumstances. Please report any problems to UserLand Software.
  15.  
  16. See the enclosed "Frontier SDK" Word 4.0 file, for background and possible uses
  17. of the do-script message.
  18.  
  19. This is a very bare bones program with one window and no menu bar. To quit FDS
  20. just close the window.
  21.  
  22. IMPORTANT NOTE: This version of Frontier Do-Script is primarily intended for
  23. developers who are building directly on top of the Apple Event Manager. If you're
  24. using the IAC Tools library implemented in iac.c, crib the version of FDS from
  25. the Applet Toolkit doscript.c file. It calls IAC Tools routines to talk to 
  26. Frontier.
  27. */
  28.  
  29.  
  30. #include <AppleEvents.h>
  31.  
  32. #define secondsbetweenmessages 5
  33.  
  34. WindowPtr mainwindow = nil; /*the menu sharing test window*/
  35.  
  36. Str255 windowmessage; /*the message that's displayed in the main window*/
  37.  
  38. Boolean flexitmainloop = false; /*when true we fall thru the main event loop*/
  39.     
  40.     
  41.  
  42.  
  43. static void initmacintosh (void) {
  44.  
  45.     /*
  46.     the magic stuff that every Macintosh application needs to do 
  47.     before doing anything else.
  48.     */
  49.  
  50.     register short i;
  51.         
  52.     MaxApplZone ();
  53.     
  54.     for (i = 0; i < 10; i++) 
  55.         MoreMasters ();
  56.     
  57.     InitGraf (&qd.thePort);
  58.     
  59.     InitFonts ();
  60.     
  61.     FlushEvents (everyEvent, 0);
  62.     
  63.     InitWindows ();
  64.     
  65.     InitMenus ();
  66.     
  67.     TEInit ();
  68.     
  69.     InitDialogs (nil);
  70.     
  71.     InitCursor ();
  72.     
  73.     for (i = 0; i < 5; i++) { /*register with Multifinder*/
  74.         
  75.         EventRecord ev;
  76.         
  77.         EventAvail (everyEvent, &ev); /*see TN180 -- splash screen*/
  78.         } /*for*/
  79.         
  80.     DrawMenuBar ();
  81.     } /*initmacintosh*/
  82.  
  83.  
  84. static void copystring (Str255 source, Str255 dest) {
  85.  
  86.     /*
  87.     create a copy of source in dest.  copy the length byte and
  88.     all the characters in the source string.
  89.  
  90.     assume the strings are pascal strings, with the length byte in
  91.     the first character of the string.
  92.     */
  93.  
  94.     register short i, len;
  95.     
  96.     len = (short) source [0];
  97.     
  98.     for (i = 0; i <= len; i++) 
  99.         dest [i] = source [i];
  100.     } /*copystring*/
  101.  
  102.  
  103. static Boolean pushstring (Str255 bssource, Str255 bsdest) {
  104.  
  105.     register short lensource = bssource [0];
  106.     register short lendest = bsdest [0];
  107.     register char *psource, *pdest;
  108.     
  109.     if ((lensource + lendest) > 255)
  110.         return (false);
  111.         
  112.     pdest = (char *) bsdest + (char) lendest + 1;
  113.     
  114.     psource = (char *) bssource + 1;
  115.     
  116.     bsdest [0] += (char) lensource;
  117.     
  118.     while (lensource--) *pdest++ = *psource++;
  119.     
  120.     return (true);
  121.     } /*pushstring*/
  122.     
  123.     
  124. static Boolean pushlong (long num, Str255 bsdest) {
  125.  
  126.     Str255 bsint;
  127.     
  128.     NumToString (num, bsint);
  129.     
  130.     return (pushstring (bsint, bsdest));
  131.     } /*pushlong*/
  132.     
  133.  
  134. static void ellipsize (Str255 s, short width) {
  135.  
  136.     /*
  137.     if the string fits inside the given number of pixels, fine -- do nothing
  138.     and return.
  139.     
  140.     if not, return a string that does fit, with ellipses representing the 
  141.     deleted characters.  ellipses are generated by pressing option-semicolon.
  142.     */
  143.     
  144.     register char len;
  145.     register short newwidth;
  146.     
  147.     if ((newwidth = StringWidth (s)) <= width) /*nothing to do, the string fits*/
  148.         return;
  149.     
  150.     len = s [0]; /* current length in characters*/
  151.     
  152.     width -= CharWidth ('╔'); /* subtract width of ellipses*/
  153.         
  154.     do { /*until it fits (or we run out of characters)*/
  155.     
  156.         newwidth -= CharWidth (s [len]);
  157.         
  158.         --len;
  159.     } while ((newwidth > width) && (len != 0));
  160.     
  161.     ++len; /*make room for the ellipses*/
  162.     
  163.     s [len] = '╔'; 
  164.     
  165.     s [0] = (char) len;
  166.     } /*ellipsize*/
  167.  
  168.  
  169. static void centerstring (Rect r, Str255 s) {
  170.     
  171.     /*
  172.     draw the string in the current font, size and style, centered inside
  173.     the indicated rectangle.
  174.     */
  175.     
  176.     register short rh = r.bottom - r.top;
  177.     register short rw = r.right - r.left;
  178.     register short h, v;
  179.     FontInfo fi;
  180.     
  181.     GetFontInfo (&fi);
  182.     
  183.     ellipsize (s, rw); /*make sure it fits inside the rectangle, width-wise*/
  184.     
  185.     h = r.left + ((rw - StringWidth (s)) / 2);
  186.     
  187.     v = r.top + ((rh - (fi.ascent + fi.descent)) / 2) + fi.ascent;
  188.     
  189.     MoveTo (h, v);
  190.     
  191.     ClipRect (&r);
  192.     
  193.     DrawString (s);
  194.     } /*centerstring*/
  195.  
  196.  
  197. static void setfontsizestyle (short fontnum, short fontsize, short fontstyle) {
  198.  
  199.     TextFont (fontnum);
  200.     
  201.     TextSize (fontsize);
  202.     
  203.     TextFace (fontstyle);
  204.     } /*setfontsizestyle*/
  205.     
  206.     
  207. static void updatemainwindow (void) {
  208.     
  209.     Rect r;
  210.     Str255 s;
  211.     
  212.     r = (*mainwindow).portRect;
  213.     
  214.     EraseRect (&r);
  215.     
  216.     setfontsizestyle (helvetica, 12, 0);
  217.     
  218.     centerstring (r, windowmessage);
  219.     
  220.     NumToString (FreeMem () / 1024, s);
  221.     
  222.     MoveTo (r.left + 3, r.bottom - 3);
  223.     
  224.     setfontsizestyle (geneva, 9, 0);
  225.     
  226.     DrawString (s);
  227.     
  228.     DrawString ("\pK");
  229.     } /*updatemainwindow*/
  230.     
  231.     
  232. static void setwindowmessage (Str255 script, Str255 result) {
  233.     
  234.     copystring (script, windowmessage);
  235.             
  236.     pushstring ("\p returns ", windowmessage);
  237.             
  238.     pushstring (result, windowmessage);
  239.     
  240.     pushstring ("\p", windowmessage);
  241.             
  242.     SetPort (mainwindow);
  243.     
  244.     updatemainwindow ();
  245.     } /*setwindowmessage*/
  246.  
  247.  
  248. static Boolean initmainwindow (void) {
  249.     
  250.     register WindowPtr w;
  251.     
  252.     w = mainwindow = GetNewWindow (128, nil, (WindowPtr) -1);
  253.     
  254.     if (w == nil)
  255.         return (false);
  256.     
  257.     ShowWindow (w);
  258.     
  259.     return (true);
  260.     } /*initmainwindow*/
  261.  
  262.  
  263. static Boolean stringtotext (Str255 s, Handle *htext) {
  264.     
  265.     register long len;
  266.     register Handle h;
  267.     
  268.     len = s [0];
  269.     
  270.     h = NewHandle (len);
  271.     
  272.     if (h == nil)
  273.         return (false);
  274.         
  275.     BlockMove (&s [1], *h, len);
  276.     
  277.     *htext = h;
  278.     
  279.     return (true);
  280.     } /*stringtotext*/
  281.     
  282.     
  283. static Boolean texttostring (Handle htext, Str255 s) {
  284.     
  285.     long len;
  286.     
  287.     len = GetHandleSize (htext);
  288.     
  289.     if (len > 255)
  290.         len = 255;
  291.         
  292.     BlockMove (*htext, &s [1], len);
  293.     
  294.     s [0] = (char) len;
  295.     
  296.     return (true);
  297.     } /*texttostring*/
  298.     
  299.     
  300. static Boolean IACpushtextparam (AppleEvent *event, Handle val, OSType keyword) {
  301.  
  302.     AEDesc desc;
  303.     register OSErr ec;
  304.     register long len;
  305.     
  306.     desc.descriptorType = 'TEXT';
  307.     
  308.     desc.dataHandle = val;
  309.     
  310.     ec = AEPutParamDesc (event, (AEKeyword) keyword, &desc);
  311.     
  312.     return (ec == noErr);
  313.     } /*IACpushtextparam*/
  314.  
  315.  
  316. static Boolean IACgettextparam (AppleEvent *event, OSType keyword, Handle *htext) {
  317.     
  318.     AEDesc result;
  319.     OSErr ec;
  320.     Boolean fl;
  321.     
  322.     ec = AEGetParamDesc (event, (AEKeyword) keyword, 'TEXT', &result);
  323.     
  324.     if (ec != noErr)
  325.         return (false);
  326.         
  327.     *htext = result.dataHandle;
  328.     
  329.     fl = HandToHand (htext) == noErr;
  330.     
  331.     AEDisposeDesc (&result);
  332.     
  333.     return (fl);
  334.     } /*IACgettextparam*/
  335.  
  336.  
  337. static Boolean IACerrorreply (AppleEvent *reply, Str255 errorstring) {
  338.     
  339.     /*
  340.     return true if the reply is an error -- if so it has an 'errn' value
  341.     and an 'errs' value. if we return false, the reply is not an error.
  342.     */
  343.     
  344.     OSErr ec;
  345.     AEDesc desc;
  346.     
  347.     ec = AEGetParamDesc (reply, (AEKeyword) 'errn', 'shor', &desc);
  348.     
  349.     if (ec != noErr) /*the reply isn't an error*/
  350.         return (false);
  351.  
  352.     AEDisposeDesc (&desc);
  353.     
  354.     ec = AEGetParamDesc (reply, (AEKeyword) 'errs', 'TEXT', &desc);
  355.     
  356.     if (ec != noErr) {
  357.         
  358.         copystring ("\pUnknown error.", errorstring);
  359.         
  360.         return (true);
  361.         }
  362.     else
  363.         texttostring (desc.dataHandle, errorstring);
  364.     
  365.     AEDisposeDesc (&desc);
  366.     
  367.     return (true); /*there was an error returned*/
  368.     } /*IACerrorreply*/
  369.     
  370.  
  371. static pascal short WaitRoutine (ev, sleep, mousergn) EventRecord *ev; long *sleep; RgnHandle *mousergn; {
  372.     
  373.     return (0); /*keep waiting*/
  374.     } /*WaitRoutine*/
  375.     
  376.  
  377. static Boolean FrontierDoScript (Str255 script, Str255 returns) {
  378.     
  379.     /*
  380.     Send a Do Script message to Frontier. The first parameter contains a short
  381.     script to be run. The second parameter is the string that Frontier returned 
  382.     as the value generated by running the script. 
  383.     
  384.     Returns true if we were able to send the message to Frontier, and Frontier
  385.     was able to compile and run the script and Frontier replied with a returned
  386.     value. FrontierDoScript returns false if Frontier isn't running, or if the
  387.     script didn't compile or if there was a communications error.
  388.     
  389.     Frontier is not limited to running 255-character scripts or returning 
  390.     255-character returned values. This routine can easily be enhanced to handle 
  391.     larger scripts and returned values. 
  392.     
  393.     11/6/91 DW: Set return string to "IAC Error" if we failed to create an Apple
  394.     event descriptor or if the send failed. We're not suggesting that your
  395.     error messages should be so brief, rather they should be custom-fit to the
  396.     appropriate audience. Here, we want to show you how to locate errors relating
  397.     to the IAC channel -- either you're low on memory, or the Apple Event Manager
  398.     isn't present, or Frontier isn't running. Watch for this string in FDS's 
  399.     little window...
  400.     */
  401.  
  402.     register OSErr ec;
  403.     AEAddressDesc adr; 
  404.     AppleEvent event, reply;
  405.     OSType idfrontier;
  406.     Handle htext = nil;
  407.     register Boolean flhavereply = false;
  408.     
  409.     copystring ("\pIAC Error.", returns); /*default return string*/
  410.     
  411.     idfrontier = 'LAND';
  412.     
  413.     ec = AECreateDesc (typeApplSignature, (Ptr) &idfrontier, sizeof (idfrontier), &adr);
  414.     
  415.     if (ec != noErr)
  416.         return (false);
  417.     
  418.     ec = AECreateAppleEvent (
  419.         
  420.         'misc', 'dosc', &adr, kAutoGenerateReturnID, 
  421.         
  422.         kAnyTransactionID, &event);
  423.     
  424.     AEDisposeDesc (&adr);
  425.     
  426.     if (ec != noErr)
  427.         return (false);
  428.         
  429.     if (!stringtotext (script, &htext))
  430.         return (false);
  431.         
  432.     if (!IACpushtextparam (&event, htext, '----')) {
  433.         
  434.         DisposeHandle (htext);
  435.         
  436.         return (false);
  437.         }
  438.     
  439.     DisposeHandle (htext);
  440.     
  441.     ec = AESend (
  442.         
  443.         &event, &reply, kAEWaitReply + kAECanInteract + kAECanSwitchLayer, 
  444.         
  445.         kAEHighPriority, kNoTimeOut, (ProcPtr) WaitRoutine, nil);
  446.     
  447.     if (ec != noErr)
  448.         goto error;
  449.         
  450.     flhavereply = true;
  451.     
  452.     if (IACerrorreply (&reply, returns)) /*syntax error or runtime error*/
  453.         goto error;
  454.         
  455.     if (IACgettextparam (&reply, '----', &htext)) {
  456.     
  457.         texttostring (htext, returns);
  458.     
  459.         DisposeHandle (htext);
  460.         }
  461.     
  462.     AEDisposeDesc (&event);    
  463.     
  464.     AEDisposeDesc (&reply);
  465.     
  466.     return (true);
  467.     
  468.     error:
  469.     
  470.     AEDisposeDesc (&event);    
  471.     
  472.     if (flhavereply)
  473.         AEDisposeDesc (&reply);
  474.     
  475.     return (false);
  476.     } /*FrontierDoScript*/
  477.     
  478.     
  479. static void handledrag (EventRecord ev, WindowPtr w) {
  480.     
  481.     Rect r;
  482.  
  483.     r = screenBits.bounds; 
  484.    
  485.     r.top = r.top + GetMBarHeight (); 
  486.                
  487.     r.left = r.left + 4;  
  488.                
  489.     r.right = r.right - 4;
  490.                
  491.     r.bottom = r.bottom - 4;
  492.              
  493.     DragWindow (w, ev.where, &r);   
  494.     } /*handledrag*/
  495.     
  496.     
  497. static Boolean exitprogram (void) {
  498.     
  499.     /*
  500.     returns true if the user clicks in the go-away box.
  501.     */
  502.     
  503.     EventRecord ev;
  504.     WindowPtr w;
  505.     
  506.     if (!WaitNextEvent (everyEvent, &ev, 60 * secondsbetweenmessages, nil))
  507.         return (false);
  508.     
  509.     if (ev.what != mouseDown)
  510.         return (false);
  511.         
  512.     switch (FindWindow (ev.where, &w)) {
  513.     
  514.         case inGoAway: /*click in go-away box to exit program*/
  515.             return (TrackGoAway (w, ev.where));
  516.         
  517.         case inSysWindow:
  518.             SystemClick (&ev, w); 
  519.             
  520.             return (false);
  521.         
  522.         case inDrag:
  523.             handledrag (ev, w);
  524.             
  525.             return (false);
  526.             
  527.         } /*switch*/
  528.         
  529.     return (false); /*don't exit the program*/
  530.     } /*exitprogram*/
  531.  
  532.  
  533. void main (void) {
  534.     
  535.     short i;
  536.     Str255 script, result, s;
  537.     long timenextmessage;
  538.     long ct = 0; 
  539.     Boolean shouldbefalse;
  540.     
  541.     initmacintosh ();
  542.     
  543.     initmainwindow (); 
  544.     
  545.     copystring ("\p94 + ", script);
  546.     
  547.     if (FrontierDoScript (script, result))
  548.         copystring ("\pFrontierDoScript should have returned false.", result);
  549.     
  550.     setwindowmessage (script, result); /*should say "Can't compile this script..."*/
  551.     
  552.     timenextmessage = TickCount () + (60 * secondsbetweenmessages);
  553.  
  554.     while (true) {
  555.         
  556.         if (exitprogram ()) /*returns true if user clicks in go away box*/
  557.             return;
  558.             
  559.         if (TickCount () >= timenextmessage) { /*send a script every N seconds*/
  560.         
  561.             copystring ("\pstates.nthState ((", script);
  562.             
  563.             pushlong (ct++, script);
  564.             
  565.             pushstring ("\p % 50) + 1)", script);
  566.             
  567.             if (!FrontierDoScript (script, result))
  568.                 SysBeep (1);
  569.                 
  570.             setwindowmessage (script, result);
  571.             
  572.             timenextmessage = TickCount () + (60 * secondsbetweenmessages);
  573.             }
  574.         } /*while*/
  575.     } /*main*/
  576.  
  577.  
  578.