(******************************************************************************)
(*                                                                            *)
(*    The global constants and variables defined in this module are optional: *)
(* if you don't want to access their features, you needn't import them into   *)
(* your program. The variables in the parameter lists of the procedures are   *)
(* the only variables you are required to supply.                             *)
(*    The global variables correspond to fields of the structures used in the *)
(* procedures. By changing the values of these variables, you may safely and  *)
(* easily access the sophisticated capabilities of Intuition. As much as fea- *)
(* sible, I have tried to prevent illegal values from being sent to the Intu- *)
(* ition and ROM Kernal procedures.                                           *)
(*    These variables are initialized prior to use, either by importing this  *)
(* module or by calling one of the initialization procedures below. Many of   *)
(* the variables are automatically reset prior to exit from certain routines. *)
(* Those variables are listed following the routines in which they are reset. *)
(*    When describing the order in which certain routines are called, I have  *)
(* adopted the curly-bracket notation of EBNF: routines in curly brackets {}  *)
(* may be called an arbitrary number of times (0 to n). A, {B}, {C, {D}} thus *)
(* implies that A is called once, followed by an arbitrary number of calls to *)
(* to B, followed by an arbitrary number of calls to C. Each of the calls to  *)
(* C may be followed by an arbitrary number of calls to D. Likewise, {{C},{D}}*)
(* implies an arbitrary number of calls to C and D in any order.              *)
(*                                                                            *)
(**************************   Aaaaagggghhhhh!   *******************************)
(*                                                                            *)
(*    ModulaTools is SHAREWARE!!! That means you had better send me all your  *)
(* money right now whether you like it or not. Pronto. Ooorrrrr, you can send *)
(* me $7.50 if you find the code useful. If you want the source code to the   *)
(* implementation module (featuring MORE documentation), a version of Modula- *)
(* Tools which is broken into smaller modules (ALL of them documented)  and   *)
(* some disk-based documentation that I found in the dumpster behind my house,*)
(* send me $10.00 and a disk (or $15.00 -- I don't like buying disks), either *)
(* in addition to or instead of the $7.50 mentioned above, to the address     *)
(* listed below.                                                              *)
(*                                                                            *)
(*****************************    Address   ***********************************)
(*                                                                            *)
(*  Version 1.00a.002 (Beta) :   August 7, 1987                               *)
(*                                                                            *)
(*    These procedures were originally written under version 2.00 of the TDI  *)
(* Modula-2 compiler. I have rewritten this module to operate under the v3.00 *)
(* compiler. However, should you find any problem or inconsistency with the   *)
(* functionality of this code, please contact me at the following address:    *)
(*                                                                            *)
(*                               Jerry Mack                                   *)
(*                               23 Prospect Hill Ave.                        *)
(*                               Waltham, MA   02154                          *)
(*                                                                            *)
(*    Check the module MenuUtils for TDI's (considerably less powerful) ver-  *)
(* sions of my Menu and IntuitionText procedures. The modules GadgetUtils and *)
(* EasyGadgets should also be of great help. Had these utilities been avail-  *)
(* able earlier, I would have been spared the months of agony trying to create*)
(* these routines. (Compile, link, run, CRASH! Compile, link,...)             *)
(*                                                                            *)
(******************************   Beware!   ***********************************)
(*                                                                            *)
(*    ModulaTools is a package consisting of three files: this definition     *)
(* module and its associated symbol and link files. ModulaTools may only be   *)
(* distributed intact and in its original form, except as noted below. In par-*)
(* ticular, no comments may be excised from this definition module, except as *)
(* noted below. No license is granted to distribute or disseminate, in any    *)
(* machine-readable or recorded form, a partial or derivative version of this *)
(* this definition module, except as noted below.                             *)
(*                                                                            *)
(*                                                                            *)
(*    If you have made the shareware contribution to me as stated above, you  *)
(* are granted the following and sole useage and distribution exceptions:     *)
(*                                                                            *)
(*  a) You may freely utilize portions or derivatives of ModulaTools in any   *)
(* program for which you do not seek recompense and which you will not distri-*)
(* bute in any machine-readable or recorded form. (If it's for your personal  *)
(* use only, do whatever the hell you want.)                                  *)
(*                                                                            *)
(*  b) You may freely utilize portions or derivatives of ModulaTools in any   *)
(* program for which you do not seek recompense but which you will distribute *)
(* in a machine-readable or recorded form, so long as your program contains a *)
(* notice or comment stating that I am the source of the utilized code. (If   *)
(* you use ModulaTools in a program for your friends or the public domain,    *)
(* give me some credit, please.)                                              *)
(*                                                                            *)
(*  c) You may freely utilize portions or derivatives of ModulaTools in any   *)
(* program for which you seek recompense only if you allow your program to be *)
(* FREELY distributed in ANY machine-readable or recorded form and only if    *)
(* your program includes a notice or comment stating that I am the source of  *)
(* the utilized code. (Commercial applications of this program are expressly  *)
(* forbidden, without my written permission, as they require payment prior to *)
(* or accompanying distribution. Shareware and/or freeware {what's the diff?} *)
(* applications of ModulaTools are encouraged.)                               *)
(*                                                                            *)
(*  d) The above exceptions apply only to programs which are functionally dis-*)
(* distinct from ModulaTools. No license is granted to use ModulaTools or a   *)
(* derivative, in whole or in part, to create or distribute a program which   *)
(* reproduces the functionality of ModulaTools in whole or in part. The sole  *)
(* exception to this exception is the creation of an interactive, graphical   *)
(* Modula-2 source-code generator. If you are interested in using ModulaTools *)
(* to create such a generator, please contact me at the above address. I will *)
(* be more than happy to assist you as my time allows.                        *)
(*                                                                            *)
(*    Any other use of ModulaTools, in either its original or a derivative    *)
(* form, is expressly forbidden and will be vigorously prosecuted to the ful- *)
(* lest extent of the law. (Scared yet?)                                      *)
(*                                                                            *)
(*************************  On the Other Hand  ********************************)
(*                                                                            *)
(*    No warranties are expressed or implied by the use or non-use of this de-*)
(* finition module. It is designed solely as a utility to be used at your own *)
(* risk. I accept no liability for any damage or suffering resulting from the *)
(* use or non-use of this definition module or any program derived from it in *)
(* whole or in part.                                                          *)
(*    I make no claims as to the performance or functionality of this defini- *)
(* tion module in whole or in part. In particular, I make no claim that this  *)
(* definition module can perform as listed in the comments below. I make no   *)
(* claim that this definition module can perform any function whatsoever. If  *)
(* this definition module performs any function whatsoever, I am wholly re-   *)
(* sponsible for that functionality but I accept no liability whatsoever for  *)
(* any deficiencies in that functionality. I accept no liability whatsoever   *)
(* for any deaths or injuries resulting from the use of this definition mo-   *)
(* dule or any program derived from it in whole or in part. Insurrections,    *)
(* terrorist strikes, acts of war or any domestic or international violence   *)
(* which can be shown to be directly or indirectly related to the functional- *)
(* ity or the lack therof of this definition module shall not be construed as *)
(* an admission of liability on my part: the blame in such cases rests solely *)
(* with the user.  In such cases, the user is responsible for easing world    *)
(* tensions and avoiding a conventional, biological, chemical and/or nuclear  *)
(* retaliation by the jingoistic extremist elements of the offended factions. *)
(*                                                                            *)
(******************************************************************************)
(*                                                                            *)
(*    Feel free to experiment with the procedures below: you never know till  *)
(* you try...                                                                 *)
(*                                                                            *)
(******************************************************************************)

DEFINITION MODULE ModulaTools;

FROM DiskFontLibrary IMPORT AvailFontsHeaderPtr;
FROM GraphicsBase    IMPORT GfxBasePtr;
FROM GraphicsLibrary IMPORT BitMapPtr, DrawingModeSet;
FROM Intuition       IMPORT ScreenPtr, ScreenFlagSet, WindowPtr, WindowFlags,
                            WindowFlagSet,  SmartRefresh,IDCMPFlags,
                            IDCMPFlagSet,MenuPtr, MenuFlags, MenuFlagSet,
                            MenuItemPtr, ItemFlags, ItemFlagSet,
                            IntuitionBasePtr, IntuitionTextPtr, IntuiMessagePtr;
FROM Libraries       IMPORT LibraryPtr;
FROM Menus           IMPORT HighComp;
FROM Strings         IMPORT String;
FROM SYSTEM          IMPORT ADDRESS;
FROM Views           IMPORT Modes, ModeSet;
FROM Text            IMPORT TextAttrPtr;


CONST
   NoTitle = 0C;                      (* no title for screen and/or window *)

VAR
   ViewFeatures    : ModeSet;         (* ViewPort type and capabilities    *)
   ScreenBitMap    : BitMapPtr;       (* custom Screen bitmap, if desired  *)
   ScreenFeatures  : ScreenFlagSet;   (* Screen type and capabilities      *)
   TextPen         : INTEGER;         (* color of text drawn in Screen     *)
   FillPen         : INTEGER;         (* color of background in Screen     *)
   MinWindowWide   : INTEGER;         (* minimum width  of next Window     *)
   MaxWindowWide   : INTEGER;         (* maximum width  of next Window     *)
   MinWindowHigh   : INTEGER;         (* minimum height of next Window     *)
   MaxWindowHigh   : INTEGER;         (* maximum height of next Windwo     *)
   WindowBitMap    : BitMapPtr;       (* custom Window bitmap, if desired  *)
   WindowFeatures  : WindowFlagSet;   (* Window type and capabilities      *)
   IDCMPFeatures   : IDCMPFlagSet;    (* types of Intuition messages wanted*)
   UserIntuiBase   : IntuitionBasePtr;(* address of IntuitionBase          *)
   UserGraphBase   : GfxBasePtr;      (* address of GraphicsBase           *)


   PROCEDURE OpenGraphics () : BOOLEAN;

   PROCEDURE CreateScreen (Left, Top, Wide, High : INTEGER;   (* Input *)
                           Bitplanes             : INTEGER;   (* Input *)
                           VAR ScreenTitle       : String)    : ScreenPtr;
   
   PROCEDURE CreateWindow (Left, Top, Wide, High : INTEGER;   (* Input *)
                           VAR WindowTitle       : String;    (* Input *)
                           UserScreen            : ScreenPtr) : WindowPtr;
                         
   PROCEDURE CloseGraphics ();


          (* Variables reset in PROCEDURE OpenGraphics (): *)

(*  TextPen = 0  MinWindowWide = 30  MinWindowHigh = 20  ScreenBitMap = NULL *)
(*  FillPen = 1  MaxWindowWide =  0  MaxWindowHigh =  0  WindowBitMap = NULL *)
(*  ViewFeatures   = Empty                                                   *)
(*  ScreenFeatures = CustomScreen                                            *)
(*  IDCMPFeatures  = MenuPick, CloseWindowFlag, NewSize, GadgetUp            *)
(*  WindowFeatures = SmartRefresh, WindowSizing, WindowDrag, WindowDepth,    *)
(*                   Activate, ReportMouseFlag                               *)
 
(* OpenGraphics may return a value of FALSE if either the IntuitionLibrary   *)
(* or the GraphicsLibrary could not be opened. Whichever of UserIntuiBase or *)
(* UserGraphBase = NULL is the library which could not be opened. You needn't*)
(* call CloseGraphics in such a case.                                        *) 

(* Both CreateScreen and CreateWindow do extensive checking to ensure that   *)
(* you don't exceed the performance limits of the Amiga. (I am FED UP with   *)
(* crashes!!) If you find any combination which doesn't work properly, I     *)
(* would appreciate your dropping me a line describing the invocation. Also, *)
(* Left and Top are measured from the upper-left corner of the display in    *)
(* CreateScreen, whereas in CreateWindow they are measured from the upper-   *)
(* left corner of the Screen in which the Window will appear.                *) 

(* If UserScreen = NULL, then the Window will open in the WorkBench Screen;  *)
(* otherwise, it will open in the UserScreen.                                *) 

(* ScreenBitMap and WindowBitMap are pointers to custom bitmaps. Unless you  *)
(* want to manage your own bitmaps, you should leave these alone (= NULL).   *)
 
(* TextPen and FillPen are chosen from the color palette; the number of pens *)
(* available = 2**bitplanes { or 2^bitplanes }. Any pen choice outside of    *)
(* this range results in choice wraparound, which I assume is done by ignor- *)
(* ing illegal higher-order bits.                                            *)
 
(* ViewFeatures determines the type of ViewPort in which you wish your Screen*)
(* to be rendered. Setting this to the appropriate value allows you to obtain*)
(* high-resolution, interlaced, HAM, ExtraHalfBright, etc. ViewPorts.        *)

(* ScreenFeatures determines how the Screen will appear in the display and   *)
(* whether or not the new Screen will be a CustomScreen.                     *)

(* WindowFeatures determines how the Window will appear in the display,what  *)
(* type of Gadgets you wish attached to it and how it will be refreshed.     *)

(* MinWindowWide, MaxWindowWide, MinWindowHigh and MaxWindowHigh are only of *)
(* use if the Window has a sizing gadget: INCL(WindowFeatures, WindowSizing).*) 
(* If any of these is set to 0, then the limit of that dimension will be the *)
(* current dimension of the Window.                                          *)
 
(* IDCMPFeatures determines which messages your Window will receive from In- *)
(* tuition. If your program isn't responding to certain gadgets or events,   *)
(* check that you have included the proper notification flags here.          *)
 
(* CloseGraphics should not be called until you close ALL the Windows and    *)
(* Screens opened with the above procedures. Otherwise...                    *)
 
(* If you want to open Windows and/or Screens without using these procedures,*)
(* you should assign IntuitionBase and GraphicsBase to UserIntuiBase and     *)
(* UserGraphBase, resp. This allows you to use the libraries opened in the   *)
(* procedure OpenGraphics as opposed to opening your own versions of these   *)
(* libraries.                                                                *)
 
(* The order in which these procedures is called is as follows: OpenGraphics,*)
(* {{CreateScreen}, {CreateWindow}}, CloseGraphics.                          *)
 
  
 
 
VAR
   FrontTextPen : INTEGER;   (* these pens are chosen from the screen pen- *)
   BackTextPen  : INTEGER;   (* palette; e.g., 3 bit planes = 8 pens (0-7);*)
   CurrentFont  : TextAttrPtr;       (* in case you want a different font; *)
   LastText     : IntuitionTextPtr;  (* connect current text to last text; *)
   TextDrawMode : DrawingModeSet;             (* method used to draw text; *)

 
   PROCEDURE GetIntuiText     (TextItem          : String;        (* Input *)
                               TextLeft, TextTop : INTEGER;       (* Input *)
                               VAR IntuiText     : IntuitionTextPtr); 

   PROCEDURE DestroyIntuiText (VAR IntuiText     : IntuitionTextPtr;
                               DestroyAllText    : BOOLEAN); 
 

        (* Default values upon importing this module: *)
        (* FrontTextPen =  0    CurrentFont = NULL    *)
        (* BackTextPen  =  1    LastText    = NULL    *)
        (* TextDrawMode = Jam2                        *)
 
    (* GetIntuiText returns an IntuitionText structure containing the    *)
    (* desired text. TextLeft and TextTop are the pixel positions where  *)
    (* the lower-left corner of the text will be placed. If LastText <>  *)
    (* NULL, then LastText will point to IntuiText, thus creating a      *)
    (* linked list of IntuitionText structures. Just call GetIntuiText,  *)
    (* assign LastText to IntuiText and call GetIntuiText again.         *)
 
    (* LastText is set to NULL following the call to GetIntuiText.       *)

    (* DestroyIntuiText DISPOSEs of IntuitionText: If DestroyAllText is  *)
    (* TRUE, then it also DISPOSEs of all IntuitionText forward-linked   *)
    (* to IntuiText. If DestroyAllText is FALSE, then only the Intuition-*)
    (* Text pointed to by IntuiText is DISPOSEd. If IntuiText is forward-*)
    (* linked to other IntuitionText upon entry to this procedure, then, *)
    (* upon return, IntuiText will point to the next IntuitionText in the*)
    (* linked list.                                                      *)


 
VAR
   UserDiskFontBase  : LibraryPtr;      (* entry point into DiskFont library *)


   PROCEDURE GetAndSortAllFonts (VAR FontBuffer : AvailFontsHeaderPtr): BOOLEAN;

   PROCEDURE ReturnFontResourcesToSystem (VAR FontBuffer : AvailFontsHeaderPtr);


 (* GetAndSortAllFonts returns an array of AvailFonts structures, each of    *)
 (* which contains a TextAttr structure and a flag informing whether the     *)
 (* font resides in memory or on disk. The array contains data for the ROM   *)
 (* fonts and all fonts in the FONTS: directory. The array is sorted by name *)
 (* and also by point-size for fonts with identical names. Thus, the list on *)
 (* the left would be returned in the order shown on the right:              *)
 (*                                                                          *)
 (*   9 point  diamond.font                   9 point  diamond.font          *)
 (*  12 point  ruby.font                      9 point  garnet.font           *)
 (*   8 point  topaz.font                    16 point  garnet.font           *)
 (*   9 point  topaz.font                    12 point  ruby.font             *)
 (*  19 point  sapphire.font                 19 point  sapphire.font         *)
 (*  11 point  topaz.font                     8 point  topaz.font            *)
 (*   9 point  garnet.font                    9 point  topaz.font            *)
 (*  16 point  garnet.font                   11 point  topaz.font            *)
 (*                                                                          *)
 (* After calling GetAndSortAllFonts, you must call OpenFont or OpenDiskFont *)
 (* to allow your program to load and utilize the available fonts.           *)
 
 (* ReturnFontResourcesToSystem should be called when you are finished with  *)
 (* the FontBuffer. Also, you must call ReturnFontResourcesToSystem prior to *)
 (* calling GetAndSortAllFonts again. However, unless you reassign the FONTS:*)
 (* directory, there is little need to call GetAndSortAllFonts more than     *)
 (* once. ReturnFontResourcesToSystem closes the DiskFont library which Get- *)
 (* AndSortAllFonts opened (and which you may access via UserDiskFontBase),  *)
 (* and DEALLOCATES the memory used by FontBuffer. Prior to calling Return-  *)
 (* FontResourcesToSystem, you should call CloseFont and RemFont for each    *)
 (* font that your program has opened. This ensures that all font-management *)
 (* resources used by the system are released.                               *)
 
 
 
CONST                  (* set Commandkey to this if you do not want a    *)
   NoKey  = " ";       (* key-equivalent for the current Item or SubItem *)

                    (* common assignments for ItemSetting & MenuSetting: *)
CONST
   Checkable = ItemFlagSet{CheckIt, MenuToggle};
   CheckNow  = ItemFlagSet{Checked};              (* requires Checkable  *)
   ItemOn    = ItemFlagSet{ItemEnabled} + HighComp;
   ItemOff   = ItemFlagSet{};
   MenuOn    = MenuFlagSet{MenuEnabled}; (* default value of MenuSetting *)
   MenuOff   = MenuFlagSet{};

VAR
   FirstMenu      : MenuPtr;        (* pointer to first Menu in Menu bar *)
   CurrentMenu    : MenuPtr;        (* current Menu    in Menu bar       *)
   CurrentItem    : MenuItemPtr;    (* current Item    in Menu bar       *)
   CurrentSubItem : MenuItemPtr;    (* current SubItem in Menu bar       *)
   LoneMenuStrip  : MenuPtr;        (* unattached, DISPOSEable MenuStrip *)
   SelectText     : String;         (* (Sub)Item text shown if selected  *)
   VerPixPerChar  : CARDINAL;       (* vertical   pixels per character   *)
   HorPixPerChar  : CARDINAL;       (* horizontal pixels per character   *)
   MenuSetting    : MenuFlagSet;    (* characteristics of current Menu   *)
   HiResScreen    : BOOLEAN;        (* high resolution screen?           *)
   AutoIndent     : BOOLEAN;        (* shift (Sub)Items to right?        *)
   RightJustify   : BOOLEAN;        (* extend select boxes to right?     *)
   Left, Top      : INTEGER;        (* left & top location and width &   *)
   Wide, High     : INTEGER;        (* height of current Menu, (Sub)Item *)
   NewItemColumn  : BOOLEAN;        (* flag: start new (Sub)Item column? *)

                                    (* all of these parameters are inputs *)
   PROCEDURE InitializeMenuStrip;

   PROCEDURE AddMenu    (MenuBarText : String);

   PROCEDURE AddItem    (ItemText    : String;
                         Commandkey  : CHAR;
                         ItemSetting : ItemFlagSet;
                         Exclusion   : LONGINT);
 
   PROCEDURE AddSubItem (SubItemText : String;
                         Commandkey  : CHAR;
                         ItemSetting : ItemFlagSet;
                         Exclusion   : LONGINT);

   PROCEDURE DestroyMenuStrip (WindowPointer : WindowPtr);


         (* Variables reset in PROCEDURE InitializeMenuStrip : *)
 
         (* CurrentMenu = NULL    MenuSetting   = MenuOn       *)
         (* FirstMenu   = NULL    AutoIndent    = FALSE        *)
         (* SelectText  = NoText  HorPixPerChar = 8            *)
         (* MenuLeft    = 0       VerPixPerChar = 8            *)
         (* HiResScreen = FALSE   RightJustify  = TRUE         *)

 (* ItemSetting := Checkable + CheckNow --> this (Sub)Item can be and is  *)
 (* now checked; the routines above automatically set the ItemText flag.  *)

 (* Left, Top, Wide & High are recalculated in each subroutine to yield   *)
 (* a pleasing MenuStrip; if you dislike it, you may change them prior to *)
 (* calling AddMenu, AddItem and/or AddSubItem; also, Left & Wide affect  *)
 (* the placement of text in AddMenu but affect the placement and size    *)
 (* of the select boxes in AddItem and AddSubItem;                        *)

 (* To what are Left, Top, Wide and High measured relative? For Menus,    *)
 (* they are relative to the upper-left corner of the Screen. For Items,  *)
 (* they are relative to the lower-left corner of the Menu. For SubItems, *)
 (* they are relative to the lower-left corner of the Item.               *) 

 (* If AutoIndent = TRUE, all Items under the CurrentMenu (or all SubItems*)
 (* under the CurrentItem) will be shifted to the right to allow for a    *)
 (* checkmark. If AutoIndent = FALSE, then only those (Sub)Items which    *)
 (* request a checkmark in ItemSetting will be shifted to the right. The  *)
 (* amount of space added to the left of the select box depends upon the  *)
 (* value of HiresScreen.                                                 *)

 (* If RightJustify is TRUE, then the right edge of each Item extends to  *)
 (* the edge of its Menu. Otherwise, the right edge of each Item is deter-*)
 (* mined by the width of the longest Item in the current Item-column.    *)
 (* This is of most use when multiple Item-columns are desired: setting   *)
 (* RightJustify to FALSE ensures that the first column of Items isn't    *)
 (* excessively wide.                                                     *)
 
 (* If CommandKey <> NoKey, then space will be added to the right of the  *)
 (* (Sub)Item's select box according to the value of HiresScreen.         *)
 
 (* In addition, TextFlag is included in all Itemsetting values above,    *)
 (* since these routines are designed to create text Menus and (Sub)Items.*)

 (* HorPixPerChar and VerPixPerChar are used to determine the width and   *)
 (* height of the Menus, Items and SubItems. You may change these values  *)
 (* to quickly obtain larger select boxes.                                *)

 (* SelectText allows you to specify a different text be displayed when   *)
 (* the (Sub)Item is chosen, though it prevents use of other highlighting.*)
 (* SelectText = NoText upon exit from each of the above four procedures. *)
 (* As stated above, Left, Wide, Top and High are reset or recalculated   *)
 (* prior to exit from the above four routines. Don't change these values *)
 (* unless you know where you want a specific Menu or (Sub)Item placed.   *)
  
 (* CurrentMenu, CurrentItem and CurrentSubItem point to the Menu, Item   *)
 (* or SubItem, respectively, which was just added to the MenuStrip. Thus,*)
 (* if you require access to a particular node in the MenuStrip, you may  *)
 (* copy these pointers as needed following the call to AddMenu, AddItem  *)
 (* or AddSubItem.                                                        *)
 
 (* DestroyMenuStrip is designed to remove a MenuStrip from a Window and  *)
 (* DISPOSE of its Menus, Items and SubItems, as well as the IntuitionText*)
 (* structures to which they point. ANY non-NULL pointer in the MenuStrip *)
 (* has its contents DISPOSED. If you wish only to DISPOSE of a MenuStrip *)
 (* (one that is not attached to a Window), then set WindowPointer to NULL*)
 (* and assign LoneMenuStrip to the MenuStrip of which to DISPOSE. Just   *)
 (* prior to exit, DestroyMenuStrip calls InitializeMenuStrip. Thus, you  *)
 (* need only call InitializeMenuStrip for the first MenuStrip and if you *)
 (* want multiple MenuStrips defined at one time. I didn't call the pro-  *)
 (* cedure in the module body because it looked unusual to call it for the*)
 (* second and subsequent concurrent MenuStrips but not the first.        *)
 
 (* You can easily create multiple MenuStrips by calling InitializeMenu-  *)
 (* Strip once for each MenuStrip. Be sure to save the value of FirstMenu *)
 (* prior to the call, as that is the pointer to the first Menu of the    *)
 (* current MenuStrip.                                                    *)

 (* Since the IntuiText routines above are used to create the Intuition-  *)
 (* Text structures for the MenuStrip, you may change the values of the   *)
 (* global variables associated with those routines to obtain different   *)
 (* colors and fonts for your MenuStrip.                                  *)
 
 (* Be sure to add at least one Item to each Menu to prevent a crash.     *)
 
 (* In case you haven't figured it out, the order in which you call these *)
 (* routines is as follows:  InitializeMenuStrip, {AddMenu,  AddItem,     *)
 (* {AddSubItem}, {AddItem, {AddSubItem}}}, DestroyMenuStrip.             *)
 
 
 
 
TYPE
   ChoiceType = RECORD
                   MenuChosen    : CARDINAL;
                   ItemChosen    : CARDINAL;
                   SubItemChosen : CARDINAL;
                   ChoicePointer : MenuItemPtr;
                END; (* ChoiceType *)


   PROCEDURE GotMessage     (VAR IMessage   : IntuiMessagePtr;
                             CurrentWindow  : WindowPtr)     : BOOLEAN;

   PROCEDURE GetMenuChoice  (MenuSelection  : CARDINAL;        (* Input  *)
                             FirstMenu      : MenuPtr;         (* Input  *)
                             VAR MenuChoice : ChoiceType);     (* Output *)

 (* GotMessage quickly copies any message from Intuition and returns the *)
 (* original to Intuition. This helps reduce the number of IntuiMessages *)
 (* Intuition allocates. Since Intuition doesn't deallocate them unless  *)
 (* it is reinitialized, this is definitely a desireable practice. Also, *)
 (* Imessage is DISPOSEd of if it is non-NULL upon entering GotMessage.  *)
 (* This means you don't have to worry about disposing of the copies of  *)
 (* the Intuition messages, either. If IMessage^.Class = MenuPick, then  *)
 (* you may obtain the (Sub)Item chosen by calling GetMenuChoice. If no  *)
 (* message was pending from Intuition, then GotMessage returns FALSE.   *)
 (* CurrentWindow is the only input, pointing to the Window in which you *)
 (* wish to determine whether an Intuition message is pending.           *)
 
 (* GetMenuChoice determines the FIRST (Sub)Item chosen, and returns a   *)
 (* a pointer to it. Be certain to check the NextSelect field of the cho-*)
 (* sen (Sub)Item, as it is possible to click-select or drag-select mul- *)
 (* tiple choices before releasing the right mousebutton. Thus, MenuSe-  *)
 (* lection will be either IMessage^.Code or ChoicePointer^.NextSelect.  *)
 
 

 
   (* These color values are from p.294 of the Amiga Programmer's Handbook *)
   (*  Vol. 1 by Eugene P. Mortimore; Sybex, Inc., Berkeley; 1987.         *)

CONST
   White     = 0FFFH;    GoldenOrange  = 0FB0H;    LightAqua = 01FBH;
   BrickRed  = 0D00H;    CadmiumYellow = 0FD0H;    SkyBlue   = 06FEH;
   Red       = 0F00H;    LemonYellow   = 0FF0H;    LightBlue = 06CEH;
   RedOrange = 0F80H;    ForestGreen   = 00B1H;    Blue      = 000FH;
   Orange    = 0F90H;    LightGreen    = 08E0H;    Purple    = 091FH;
   LimeGreen = 0BF0H;    BrightBlue    = 061FH;    Violet    = 0C1FH;
   Green     = 00F0H;    DarkBlue      = 006DH;    Pink      = 0FACH;
   DarkGreen = 02C0H;    MediumGrey    = 0999H;    Tan       = 0DB9H;
   BlueGreen = 00BBH;    LightGrey     = 0CCCH;    Brown     = 0C80H;
   Aqua      = 00DBH;    Magenta       = 0F1FH;    DarkBrown = 0A87H;
   Black     = 0000H;
   MaxColors = 32;     (* # of colors to load when calling SetScreenColors *)

VAR
   ScreenColors : ARRAY [0..MaxColors-1] OF CARDINAL;


   PROCEDURE SetScreenColors (CurrentScreen : ScreenPtr);


 (* SetScreenColors assigns ScreenColors to the color registers of Current- *)
 (* Screen. Though ScreenColors is assigned values upon import of this mo-  *)
 (* dule, I have spent little time determining which combinations are aes-  *)
 (* thetically appealing. Thus, don't count on ScreenColors having the same *)
 (* default values in later versions of this module.                        *)

END ModulaTools.
