home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / AppleScript / Development Tools / Sample Code / MenuScripter / Sources / MSUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-25  |  16.2 KB  |  609 lines  |  [TEXT/MPS ]

  1. /*
  2.     MSUtils.c
  3.     
  4.     Version 1.0d6
  5.     
  6.     Copyright © SRL Data 1992, 1993
  7.     
  8.     All rights reserved.
  9.     
  10.     Produced by : SRL Data
  11.     Originally Developed for UK.DTS
  12. */
  13.  
  14.  
  15. #include <PLStringFuncs.h>
  16. #include <Events.h>
  17. #include <Traps.h>
  18. #include <Dialogs.h>
  19. #include <Fonts.h>
  20. #include <Packages.h>
  21. #include <AppleEvents.h>
  22. #include <TextUtils.h>
  23. #include "MSUtils.h"
  24.  
  25. /**-----------------------------------------------------------------------
  26.         Name:             LesserOf
  27.         Purpose:        Returns the Lesser of two longints.
  28.     -----------------------------------------------------------------------**/
  29. #pragma segment Utils
  30.         
  31. pascal long LesserOf(long A, long B)
  32.  {
  33.    if (A<B)
  34.        return(A);
  35.      else
  36.        return(B);
  37.  }   /*LesserOf*/
  38.             
  39. /**-----------------------------------------------------------------------
  40.         Name:             GreaterOf
  41.         Purpose:        Returns the Greater of two longints.
  42.     -----------------------------------------------------------------------**/
  43.     
  44. #pragma segment Utils
  45.         
  46. pascal long GreaterOf(long A, long B)
  47.  {
  48.    if (A>B)
  49.        return(A);
  50.      else
  51.        return(B);
  52.  }  /*GreaterOf*/
  53.             
  54. /**-----------------------------------------------------------------------
  55.         Name:             ShowError
  56.         Purpose:        Reports an error to the user as both string and number.
  57.     -----------------------------------------------------------------------**/
  58. #pragma segment Utils
  59.         
  60. pascal void ShowError(Str255  theError,
  61.                                           long    theErrorCode)
  62. {
  63.    short     alertResult;
  64.    Str255    theString;
  65.      OSErr     myErr;
  66.      
  67.      myErr = AEInteractWithUser(kAEDefaultTimeout, nil,nil);
  68.      
  69.      if (myErr == noErr)
  70.        {
  71.              SetCursor(&qd.arrow);
  72.              NumToString(theErrorCode, theString);
  73.              ParamText(theError, theString, (unsigned char *)"", (unsigned char *)"");
  74.              alertResult = Alert(300, nil);
  75.          }
  76. } /* ShowError */
  77.  
  78. /**-----------------------------------------------------------------------
  79.         Name:             Ours
  80.         Purpose:        Checks the frontmost window belongs to the app.
  81.     -----------------------------------------------------------------------**/
  82. #pragma segment Utils        
  83.     
  84. pascal Boolean Ours(WindowPtr aWindow)
  85.  {
  86.         if (aWindow)
  87.             if (((WindowPeek)aWindow)->windowKind == zoomDocProc)
  88.                 return(true);
  89.         return(false);
  90. } /* Ours */
  91.  
  92. /**-----------------------------------------------------------------------
  93.         Name:             SetShortMenus
  94.         Purpose:        Cuts the menus down to a minimum - Apple File Edit.
  95.                                 Greys out the unavailable options - used when no docs open
  96.     -----------------------------------------------------------------------**/
  97. #pragma segment Utils        
  98.  
  99. pascal void SetShortMenus()
  100.     DeleteMenu(mfontID);
  101.     DeleteMenu(sizeID);
  102.     DeleteMenu(styleID);
  103.     DeleteMenu(mscriptID);
  104.  
  105.     DisableItem(myMenus[fileM], fmClose);
  106.     DisableItem(myMenus[fileM], fmSave);
  107.     DisableItem(myMenus[fileM], fmSaveAs);
  108.     DisableItem(myMenus[fileM], fmRevert);
  109.     DisableItem(myMenus[fileM], fmPrint);
  110.     DisableItem(myMenus[fileM], fmPageSetUp);
  111.  
  112.     /* now the unnecessary items on the edit menu */
  113.                 
  114.     DisableItem(myMenus[editM], undoCommand);
  115.     DisableItem(myMenus[editM], cutCommand);
  116.     DisableItem(myMenus[editM], copyCommand);
  117.     DisableItem(myMenus[editM], clearCommand);
  118.     DisableItem(myMenus[editM], pasteCommand);
  119.     DisableItem(myMenus[editM], selectAllCommand);
  120.  
  121.     DrawMenuBar();
  122. }  /* SetShortMenus */
  123.  
  124. /**-----------------------------------------------------------------------
  125.         Name:             SetLongMenus
  126.         Purpose:        Reinstates the full menu bar - called when first document
  127.                     opened.
  128.     -----------------------------------------------------------------------**/
  129. #pragma segment Utils        
  130.  
  131. pascal void SetLongMenus()
  132.   {
  133.         InsertMenu(myMenus[fontM], 0);
  134.         InsertMenu(myMenus[sizeM], 0);
  135.         InsertMenu(myMenus[styleM], 0);
  136.         InsertMenu(myMenus[scriptM], 0);
  137.  
  138.         EnableItem(myMenus[fileM], fmClose);
  139.         EnableItem(myMenus[fileM], fmSave);
  140.         EnableItem(myMenus[fileM], fmSaveAs);
  141.         EnableItem(myMenus[fileM], fmRevert);
  142.         EnableItem(myMenus[fileM], fmPrint);
  143.         EnableItem(myMenus[fileM], fmPageSetUp);
  144.  
  145.         /* now the necessary items on the edit menu -
  146.             many other items fixed on each pass thru the main event
  147.             loop or before the window pulled down
  148.         */
  149.         
  150.         EnableItem(myMenus[editM], selectAllCommand);
  151.  
  152.         DrawMenuBar();
  153.     }  /* SetLongMenus */
  154.  
  155. /**-----------------------------------------------------------------------
  156.         Name:             SetStyleMenu
  157.         Purpose:        Sets the style menu checking to reflect the style of the
  158.                     first character of the current selection in the given
  159.                                 document.
  160.     -----------------------------------------------------------------------**/
  161. #pragma segment Utils        
  162.         
  163. pascal void SetStyleMenu(DPtr theDoc)
  164.   {
  165.     TextStyle        theTStyle;
  166.         short       contMode;
  167.         short       i;
  168.         
  169.         contMode = doFace;
  170.         
  171.         TEContinuousStyle(&contMode,&theTStyle,theDoc->theText);
  172.         
  173.         if ((contMode & doFace) != 0)
  174.             {
  175.                 CheckItem(myMenus[styleM], cPlain,     (theTStyle.tsFace == 0));
  176.                 CheckItem(myMenus[styleM], cBold,      (bold      & theTStyle.tsFace));
  177.                 CheckItem(myMenus[styleM], cItalic,    (italic    & theTStyle.tsFace));
  178.                 CheckItem(myMenus[styleM], cUnderline, (underline & theTStyle.tsFace));
  179.                 CheckItem(myMenus[styleM], cOutline,   (outline   & theTStyle.tsFace));
  180.                 CheckItem(myMenus[styleM], cShadow,    (shadow    & theTStyle.tsFace));
  181.                 CheckItem(myMenus[styleM], cCondense,  (condense  & theTStyle.tsFace));
  182.                 CheckItem(myMenus[styleM], cExtend,    (extend    & theTStyle.tsFace));
  183.           }
  184.         else
  185.             for (i=cPlain; i<= cExtend; i++)
  186.                 CheckItem(myMenus[styleM], i,     false);
  187.   }
  188.  
  189. /**-----------------------------------------------------------------------
  190.     Name:       SetSizeMenu
  191.     Purpose:    Outline all the items if the current font is an
  192.                 outline font. Check the size of the current selection
  193.   -----------------------------------------------------------------------**/
  194. #pragma segment Utils        
  195.  
  196. pascal void SetSizeMenu(DPtr theDoc)
  197.   {
  198.       short             i;
  199.         short                aSize;
  200.         short                max;
  201.     long                 theSize;
  202.     Str255        name;
  203.     Boolean       sizeinMenu;
  204.     Boolean       oldState;
  205.     Point         numer;
  206.     TextStyle        theStyle;
  207.         TEHandle    myText;
  208.         short       contMode;
  209.       
  210.     numer.h = 1;
  211.     numer.v = 1;
  212.  
  213.     myText = theDoc->theText;
  214.         
  215.         contMode = doSize+doFont;
  216.         
  217.         TEContinuousStyle(&contMode,&theStyle,theDoc->theText);
  218.         
  219.     sizeinMenu = false;
  220.     max = CountMItems(myMenus[sizeM]);
  221.         for (i = 1; i <= max - 5; i++)
  222.       {
  223.                 GetItem(myMenus[sizeM], i, (unsigned char *)&name);
  224.                 StringToNum(name, &theSize);
  225.                 aSize = (short)theSize;
  226.  
  227.                 if (RealFont(theStyle.tsFont, aSize) && (contMode & doFont) != 0) // there is only one font and this size exists
  228.                     SetItemStyle(myMenus[sizeM], i, outline);
  229.                 else
  230.                     SetItemStyle(myMenus[sizeM], i, 0);
  231.  
  232.                 if ((aSize == theStyle.tsSize) && (contMode & doSize) != 0)
  233.                     {
  234.                         sizeinMenu = true;
  235.                         CheckItem(myMenus[sizeM], i, true);
  236.                     }
  237.                 else
  238.                     CheckItem(myMenus[sizeM], i, false);
  239.             }
  240.         
  241.             /*
  242.                 if it's not a size in the menu,and there is only one size in the
  243.               selection range check the other item
  244.             */
  245.             
  246.             if (!sizeinMenu && (contMode & doSize) != 0)
  247.               CheckItem(myMenus[sizeM], max, true);
  248.             else
  249.                 CheckItem(myMenus[sizeM], max, false);
  250.  
  251.             /*if this is an outline font, set the rest of the items to outline style*/
  252.             /*RealFont will ensure that the sizes are outlined*/
  253.  
  254.             oldState = GetOutlinePreferred();
  255.             SetOutlinePreferred(true);
  256.             for (i = max-4; i <= max; i++)
  257.                 {
  258.                     if (IsOutline(numer, numer) && (contMode & doFont)!= 0)
  259.                         SetItemStyle(myMenus[sizeM], i, outline);
  260.                     else
  261.                         SetItemStyle(myMenus[sizeM], i, 0);
  262.                 }
  263.                 
  264.             SetOutlinePreferred(oldState);
  265.     }
  266.  
  267. /**-----------------------------------------------------------------------
  268.     Name:       SetEditMenu
  269.     Purpose:    Set the text of the edit menu according to the state of
  270.                                 current document.
  271.   -----------------------------------------------------------------------**/
  272.  
  273. #pragma segment Utils
  274.  
  275. pascal void SetEditMenu(DPtr theDoc)
  276.     {
  277.         if (theDoc->showBorders)
  278.             SetItem(myMenus[editM], cBorders, (unsigned char *)"\pHide Borders");
  279.         else
  280.             SetItem(myMenus[editM], cBorders, (unsigned char *)"\pShow Borders");
  281.     }  /* SetEditMenu */
  282.             
  283. /**-----------------------------------------------------------------------
  284.     Name:       SetFontMenu
  285.     Purpose:    Set the font menu according to the state of
  286.                                 current selection of the supplied document.
  287.   -----------------------------------------------------------------------**/
  288. #pragma segment Utils
  289.         
  290. pascal void SetFontMenu(DPtr theDoc)
  291.   {
  292.     MenuHandle        theMHandle;
  293.     short         theNumber;
  294.     short         i;
  295.     short                max;
  296.     Str255        name;
  297.     TextStyle     theStyle;
  298.         short         contMode;
  299.  
  300.         theMHandle = GetMHandle(mfontID);
  301.  
  302.         if (gFontMItem)
  303.       CheckItem(theMHandle, gFontMItem, false);
  304.             
  305.         max = CountMItems(theMHandle);
  306.  
  307.         contMode = doFont;
  308.         TEContinuousStyle(&contMode,&theStyle,theDoc->theText);
  309.  
  310.         gFontMItem = 0;
  311.         
  312.     if (contMode & doFont)
  313.             for (i=1; i<=max; i++)
  314.                 {
  315.                     GetItem(theMHandle, i, (unsigned char *)&name);
  316.                     GetFNum(name, &theNumber);
  317.                     if (theNumber == theStyle.tsFont)
  318.                         gFontMItem = i;
  319.                 }
  320.  
  321.     if (gFontMItem)
  322.       CheckItem(theMHandle, gFontMItem, true);
  323.             
  324.         SetSizeMenu(theDoc);
  325.         SetStyleMenu(theDoc);
  326.     }
  327.  
  328. /**-----------------------------------------------------------------------
  329.     Name:       GetTempFileName
  330.     Purpose:    Fills newstring with a temporary file name.
  331.   -----------------------------------------------------------------------**/
  332.  
  333. #pragma segment Utils
  334.  
  335. pascal void GetTempFileName(DPtr aDoc,
  336.                             Str255 newString)
  337.  
  338.     {
  339.        Str255        s;
  340.      Str255        fileName;
  341.  
  342.         if (aDoc->everSaved == false)
  343.           PLstrcpy(fileName, (unsigned char *)"\pTEXTra");
  344.         else
  345.             PLstrcpy(fileName, aDoc->theFileName);
  346.  
  347.     /*generate a unique(ish) temporary filename*/
  348.         
  349.         if (fileName[0] > 21)
  350.           fileName[0] = 21;
  351.                 
  352.         NumToString(TickCount(), s);
  353.         
  354.         PLstrcat(fileName, s);
  355.         
  356.         PLstrcpy(newString,fileName);
  357.     }
  358.  
  359. /**-----------------------------------------------------------------------
  360.     Name:       SetText
  361.     Purpose:    Sets the text of the supplied itemNo in aDialog to 
  362.                                 theString and select it.
  363.   -----------------------------------------------------------------------**/
  364.  
  365. #pragma segment Utils
  366.  
  367. pascal void SetText(DialogPtr aDialog,
  368.                     short     itemNo,
  369.                     Str255    theString)
  370.   {
  371.     Handle      itemHandle;
  372.     Rect        box;
  373.     short       kind;
  374.     TEHandle    theTEHandle;
  375.  
  376.         GetDItem(aDialog, itemNo, &kind, &itemHandle, &box);
  377.         SetIText(itemHandle, theString);
  378.         
  379.         theTEHandle = ((DialogPeek)aDialog)->textH;
  380.  
  381.         /*set all the text to be selected*/
  382.         if (theTEHandle)
  383.             TESetSelect(0, 255, theTEHandle);
  384.     }
  385.             
  386. /**-----------------------------------------------------------------------
  387.     Name:       RetrieveText
  388.     Purpose:    Returns the text of anItem in aDialog in aString.
  389.   -----------------------------------------------------------------------**/
  390.  
  391. #pragma segment Utils
  392.  
  393. pascal void RetrieveText(DialogPtr aDialog,
  394.                                                short     anItem,
  395.                                                Str255    aString)
  396.   {
  397.      short      kind;
  398.      Rect       box;
  399.      Handle     itemHandle;
  400.  
  401.          GetDItem(aDialog, anItem, &kind, &itemHandle, &box);
  402.          GetIText(itemHandle, aString);
  403.   }
  404.  
  405. /**-----------------------------------------------------------------------
  406.     Name:       DrawDefaultOutline
  407.     Purpose:    Draws an outline around theItem.
  408.                                 Called as a useritem Proc by the dialog manager.
  409.                                 To use place a useritem over the default item in the
  410.                                 dialog and install the address of this proc as the item
  411.                                 handle.
  412.   -----------------------------------------------------------------------**/
  413.  
  414. #pragma segment Utils
  415.  
  416. pascal void DrawDefaultOutline(DialogPtr theDialog, short theItem)
  417.   {
  418.       short       kind;
  419.     Handle      itemHandle;
  420.     Rect        box;
  421.                 
  422.     GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
  423.     PenSize(3, 3);
  424.     InsetRect(&box, - 4, - 4);
  425.     FrameRoundRect(&box, 16, 16);
  426.     PenNormal();
  427.         
  428.     }  /* DrawDefaultOutline */
  429.             
  430. /**-----------------------------------------------------------------------
  431.     Name:       AdornDefaultButton
  432.     Purpose:    Installs DrawDefaultOutline as the useritem proc
  433.                     for the given item.
  434.   -----------------------------------------------------------------------**/
  435.  
  436. #pragma segment Utils
  437.         
  438. pascal void AdornDefaultButton(DialogPtr theDialog,short theItem)
  439.   {
  440.       short       kind;
  441.     Handle      itemHandle;
  442.     Rect        box;
  443.  
  444.         GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
  445.         SetDItem(theDialog, theItem, kind, (Handle)&DrawDefaultOutline, &box);
  446.   }
  447.  
  448.     /*-------  Determining of Gestalt is available ---------------*/
  449.     /*The following routines come from the Inside Mac VI recommendations*/
  450.     /*about how to find if a trap is available*/
  451.          /*
  452.             The glue for Gestalt will be in MPW 3.2, so if it is available we will also
  453.              need to check the system version
  454.         */
  455.  
  456. pascal void GetRectOfDialogItem(DialogPtr theDialog, short theItem, Rect *theRect)
  457.     {
  458.       short       kind;
  459.     Handle      itemHandle;
  460.         
  461.         GetDItem(theDialog, theItem, &kind, &itemHandle, theRect);
  462.     }
  463.  
  464. #pragma segment Utils
  465.  
  466. pascal short NumToolboxTraps()
  467.   {
  468.         if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xAA6E, ToolTrap))
  469.             return(0x200);
  470.         else
  471.             return(0x400);
  472.     }
  473.  
  474. #pragma segment Utils
  475.  
  476. #define TrapMask  0x0800
  477.  
  478. pascal TrapType GetTrapType(short theTrap)
  479.   {
  480.         if ((theTrap & TrapMask) > 0)
  481.             return(ToolTrap);
  482.         else
  483.             return(OSTrap);
  484.     }
  485.  
  486. #pragma segment Utils
  487.  
  488. pascal Boolean TrapAvailable(short theTrap)
  489.   {
  490.         TrapType  tType;
  491.  
  492.         tType = GetTrapType(theTrap);
  493.         if (tType == ToolTrap)
  494.             {
  495.                 theTrap = theTrap & 0x07FF;
  496.                 if (theTrap >= NumToolboxTraps())
  497.                     theTrap = _Unimplemented;
  498.             }
  499.         return(NGetTrapAddress(theTrap, tType) != NGetTrapAddress(_Unimplemented,ToolTrap));
  500.     }
  501.  
  502. #pragma segment Utils
  503.  
  504. #define _Gestalt 0xA1AD
  505.  
  506. pascal Boolean GestaltAvailable()
  507.   {
  508.         return(TrapAvailable(_Gestalt));
  509.     }
  510.  
  511. /**------  FeatureIsImplemented    ------------**/
  512. /*This is called to use Gestalt to determine if a feature is implemented.
  513.  This applies to only those referenced by OSType*/
  514.  
  515. #pragma segment Utils
  516.  
  517. pascal Boolean FeatureIsImplemented(OSType  theFeature,
  518.                                                           short   theTestBit)
  519.   {
  520.     OSErr     err;
  521.     long      result;
  522.  
  523.         err = Gestalt(theFeature, &result);
  524.         if (err == noErr)
  525.             if ((result & theTestBit) == theTestBit)
  526.                 return(true);
  527.                 
  528.       return(false);
  529.     }
  530.  
  531. #pragma segment Utils
  532.  
  533. pascal Boolean CheckEnvironment()
  534.   {
  535.         /*
  536.          first determine of Gestalt is available- if it isn't exit
  537.          as we only run under 7.0.  It could it present in 6.04 - so we need
  538.          to do some further checks for important features
  539.         */
  540.  
  541.         gGestaltAvailable = GestaltAvailable();
  542.         
  543.         if (!gGestaltAvailable)
  544.             return(false);
  545.  
  546.     /*first check if the Edition Manager is present*/
  547.                 
  548.     gEditionManagerImplemented = FeatureIsImplemented(gestaltEditionMgrAttr,
  549.                                                                                                           gestaltEditionMgrPresent);
  550.  
  551.         /*and for good measure- the Alias manager*/
  552.                 
  553.         gAliasManagerImplemented  = FeatureIsImplemented(gestaltAliasMgrAttr,
  554.                                                                                                          gestaltAliasMgrPresent);
  555.             
  556.         /*check for the AppleEvents manager - we certainly can't work without it*/
  557.         
  558.         gAppleEventsImplemented   = FeatureIsImplemented(gestaltAppleEventsAttr,
  559.                                                                                                          gestaltAppleEventsPresent);
  560.             
  561.         /*check for the Outline fonts*/
  562.         
  563.         gOutlineFontsImplemented  = FeatureIsImplemented(gestaltFontMgrAttr,
  564.                                                                                                          gestaltOutlineFonts);
  565.         
  566.         return (gEditionManagerImplemented &&
  567.                         gAliasManagerImplemented   &&
  568.                         gAppleEventsImplemented    &&
  569.                         gOutlineFontsImplemented);
  570.                                 
  571.     }  /* CheckEnvironment */
  572.             
  573.     /*
  574.         DoPageSetup returns true if the page setup of the document is altered
  575.     */
  576.     
  577.     pascal Boolean DoPageSetup(DPtr theDoc)
  578.         {
  579.             Boolean result = false;
  580.                 
  581.                 if (theDoc)
  582.                     {
  583.                         PrOpen();
  584.                         result =  PrStlDialog(theDoc->thePrintSetup);
  585.                         PrClose();
  586.                     }
  587.                     
  588.                 return(result);
  589.         }  /* DoPageSetup */
  590.  
  591. /*
  592.     Name:    CtrlKeyPressed
  593.     Purpose: Returns true if control key pressed during event
  594. */
  595. pascal Boolean CtrlKeyPressed(const EventRecord *theEvent)
  596.     {
  597.         return((theEvent->modifiers & controlKey) != 0);
  598.     }
  599.     
  600. /*
  601.     Name:    OptionKeyPressed
  602.     Purpose: Returns true if option key pressed during event
  603. */
  604. pascal Boolean OptionKeyPressed(const EventRecord *theEvent)
  605.     {
  606.         return((theEvent->modifiers & optionKey) != 0);
  607.     }
  608.