home *** CD-ROM | disk | FTP | other *** search
/ BCI NET 2 / BCI NET 2.iso / archives / programming / languages / obrn-a_1.5_lib.lha / oberon-a / source2.lha / Source / AmigaUtil / IntuiUtil.mod < prev    next >
Encoding:
Text File  |  1995-01-26  |  16.4 KB  |  659 lines

  1. (***************************************************************************
  2.  
  3.      $RCSfile: IntuiUtil.mod $
  4.   Description: Support for clients of intuition.library
  5.  
  6.    Created by: fjc (Frank Copeland)
  7.     $Revision: 3.7 $
  8.       $Author: fjc $
  9.         $Date: 1995/01/26 00:30:04 $
  10.  
  11.   Copyright © 1994-1995, Frank Copeland.
  12.   This file is part of the Oberon-A Library.
  13.   See Oberon-A.doc for conditions of use and distribution.
  14.  
  15. ***************************************************************************)
  16.  
  17. <* STANDARD- *> <* INITIALISE- *> <* MAIN- *>
  18. <*$ CaseChk-  IndexChk- LongVars+ NilChk-  *>
  19. <*$ RangeChk- StackChk- TypeChk-  OvflChk- *>
  20.  
  21. MODULE IntuiUtil;
  22.  
  23. IMPORT
  24.   SYS := SYSTEM, e := Exec, gfx := Graphics, l := Layers, i := Intuition,
  25.   u := Util;
  26.  
  27.  
  28. (* Passed as a parameter to GetMenuChoice () *)
  29.  
  30. TYPE
  31.  
  32.   Choice * = RECORD
  33.     menuChosen *    : INTEGER;
  34.     itemChosen *    : INTEGER;
  35.     subItemChosen * : INTEGER;
  36.     pointer *       : i.MenuItemPtr;
  37.   END; (* ChoiceType *)
  38.  
  39. CONST
  40.  
  41.   halfPot  = i.maxPot DIV 2;
  42.   halfBody = i.maxBody DIV 2;
  43.  
  44. VAR
  45.   autoIntuiText : i.IntuiText;
  46.  
  47.  
  48. (* ===== Preferences ===== *)
  49.  
  50.  
  51. (*------------------------------------*)
  52. PROCEDURE PrefsFontHeight * () : SHORTINT;
  53. (*
  54.   Returns the height of the default system font.
  55. *)
  56.  
  57. VAR
  58.   prefsBuffer : i.Preferences;
  59.  
  60. BEGIN
  61.   i.GetPrefs (prefsBuffer, SIZE(i.Preferences));
  62.   RETURN prefsBuffer.fontHeight;
  63. END PrefsFontHeight;
  64.  
  65.  
  66. (* ===== Gadget ===== *)
  67.  
  68.  
  69. (*------------------------------------*)
  70. PROCEDURE CentreGadget *
  71.   ( VAR gadget : i.Gadget; left, top, width, height : INTEGER );
  72. (*
  73.   Adjusts the gadget's position to centre it within a rectangle defined by
  74.   (left, top, width, height).
  75. *)
  76.  
  77. BEGIN (* CentreGadget *)
  78.   gadget.leftEdge := ( ( width - gadget.width ) DIV 2 ) + left;
  79.   gadget.topEdge := ( ( height - gadget.height ) DIV 2 ) + top;
  80. END CentreGadget;
  81.  
  82.  
  83. (*------------------------------------*)
  84. PROCEDURE ConvertPot *
  85.   ( potValue, totalUnits, visibleUnits : INTEGER )
  86.   : INTEGER;
  87.  
  88. VAR
  89.   value, hidden : LONGINT;
  90.  
  91. BEGIN (* ConvertPot *)
  92.   IF (potValue = 0) THEN
  93.     RETURN 0
  94.   ELSE
  95.     IF (visibleUnits >= totalUnits) THEN
  96.       RETURN 0
  97.     ELSE
  98.       IF potValue < 0 THEN value := potValue + 010000H
  99.       ELSE value := potValue
  100.       END;
  101.       hidden := totalUnits - visibleUnits;
  102.       RETURN SHORT ((hidden * value + halfPot) DIV i.maxPot)
  103.     END; (* ELSE *)
  104.   END; (* ELSE *)
  105. END ConvertPot;
  106.  
  107.  
  108. (*------------------------------------*)
  109. PROCEDURE ConvertToPot *
  110.   ( units, totalUnits, visibleUnits : INTEGER )
  111.   : INTEGER;
  112.  
  113. VAR
  114.   hidden, lUnits : LONGINT;
  115.  
  116. BEGIN (* ConvertToPot *)
  117.   IF units = 0 THEN
  118.     RETURN 0
  119.   ELSE
  120.     IF visibleUnits >= totalUnits THEN
  121.       RETURN 0
  122.     ELSE
  123.       IF units < 0 THEN lUnits := units + 010000H
  124.       ELSE lUnits := units
  125.       END;
  126.       hidden := totalUnits - visibleUnits;
  127.       IF lUnits >= hidden THEN
  128.         RETURN -1 (*i.maxPot*)
  129.       ELSE
  130.         RETURN SHORT ((i.maxPot * lUnits) DIV hidden)
  131.       END; (* ELSE *)
  132.     END; (* ELSE *)
  133.   END; (* ELSE *)
  134. END ConvertToPot;
  135.  
  136.  
  137. (*------------------------------------*)
  138. PROCEDURE ConvertBody * (bodyValue, totalUnits : INTEGER) : INTEGER;
  139.  
  140.   VAR value : LONGINT;
  141.  
  142. BEGIN (* ConvertBody *)
  143.   IF bodyValue = 0 THEN
  144.     RETURN 0
  145.   ELSIF (bodyValue = i.maxBody) OR (totalUnits < 2) THEN
  146.     RETURN totalUnits
  147.   ELSE
  148.     IF bodyValue < 0 THEN value := bodyValue + 010000H
  149.     ELSE value := bodyValue
  150.     END;
  151.     RETURN SHORT ((totalUnits * value) DIV i.maxBody);
  152.   END
  153. END ConvertBody;
  154.  
  155.  
  156. (*------------------------------------*)
  157. PROCEDURE ConvertToBody * ( totalUnits, visibleUnits : INTEGER ) : INTEGER;
  158.  
  159. BEGIN (* ConvertToBody *)
  160.   IF visibleUnits = 0 THEN
  161.     RETURN 0
  162.   ELSIF visibleUnits >= totalUnits THEN
  163.     RETURN -1 (*i.maxBody*)
  164.   ELSE
  165.     RETURN SHORT ((i.maxBody * visibleUnits) DIV totalUnits)
  166.   END; (* ELSE *)
  167. END ConvertToBody;
  168.  
  169.  
  170. (*------------------------------------*)
  171. PROCEDURE SetString * (VAR gadget : i.Gadget; string : ARRAY OF CHAR);
  172.  
  173. VAR
  174.   stringInfo : i.StringInfoPtr;
  175.  
  176. <*$CopyArrays-*>
  177. BEGIN (* SetString *)
  178.   stringInfo := SYS.VAL (i.StringInfoPtr, gadget.specialInfo);
  179.   SYS.MOVE
  180.     ( SYS.ADR (string), stringInfo.buffer,
  181.       u.MaxInt
  182.         ( SHORT (SYS.STRLEN (string) + 1), stringInfo.maxChars - 1 ) );
  183.   stringInfo.buffer [stringInfo.maxChars] := 0X
  184. END SetString;
  185.  
  186.  
  187. (*------------------------------------*)
  188. PROCEDURE GetString *  (VAR gadget : i.Gadget; VAR string : ARRAY OF CHAR);
  189.  
  190. VAR
  191.   stringInfo : i.StringInfoPtr;
  192.  
  193. BEGIN (* SetString *)
  194.   stringInfo := SYS.VAL (i.StringInfoPtr, gadget.specialInfo);
  195.   COPY (stringInfo.buffer^, string)
  196. END GetString;
  197.  
  198.  
  199. (*------------------------------------*)
  200. PROCEDURE SetInteger * ( VAR gadget : i.Gadget; integer : LONGINT );
  201.  
  202.   VAR
  203.     stringInfo : i.StringInfoPtr;
  204.     buffer : ARRAY 12 OF CHAR;
  205.     index : INTEGER;
  206.     negative : BOOLEAN;
  207.  
  208.   (*------------------------------------*)
  209.   PROCEDURE Digits ( integer : LONGINT ) : INTEGER;
  210.  
  211.   VAR
  212.     digits : INTEGER;
  213.  
  214.   BEGIN (* Digits *)
  215.     digits := 0;
  216.     WHILE ( integer > 0 ) DO
  217.       INC( digits );
  218.       integer := integer DIV 10;
  219.     END; (* WHILE *)
  220.     RETURN digits;
  221.   END Digits;
  222.  
  223. BEGIN (* SetInteger *)
  224.   stringInfo := SYS.VAL (i.StringInfoPtr, gadget.specialInfo);
  225.   stringInfo.longInt := integer;
  226.   negative := (integer < 0); integer := ABS(integer);
  227.   index := Digits( integer );
  228.   IF negative THEN INC(index) END;
  229.   buffer [index] := 0X;
  230.   WHILE integer > 0 DO
  231.     DEC (index);
  232.     buffer[index] := CHR (integer MOD 10 + ORD ("0"));
  233.     integer := integer DIV 10;
  234.   END; (* WHILE *)
  235.   IF negative THEN buffer [0] := "-" END;
  236.   SetString (gadget, buffer);
  237. END SetInteger;
  238.  
  239.  
  240. (*------------------------------------*)
  241. PROCEDURE GetInteger * ( VAR gadget : i.Gadget ) : LONGINT;
  242.  
  243. VAR
  244.   stringInfo : i.StringInfoPtr;
  245.  
  246. BEGIN (* GetInteger *)
  247.   stringInfo := SYS.VAL (i.StringInfoPtr, gadget.specialInfo);
  248.   RETURN stringInfo^.longInt;
  249. END GetInteger;
  250.  
  251.  
  252. (* ===== IntuiText ===== *)
  253.  
  254.  
  255. (*------------------------------------*)
  256. PROCEDURE IntuiTextHeight * ( VAR intuiText : i.IntuiText ) : INTEGER;
  257. (*
  258.   Returns the height in scan lines of the text held in intuiText.
  259. *)
  260.  
  261. BEGIN (* IntuiTextHeight *)
  262.   IF intuiText.iTextFont = NIL THEN
  263.     RETURN PrefsFontHeight()
  264.   ELSE
  265.     RETURN intuiText.iTextFont.ySize
  266.   END; (* ELSE *)
  267. END IntuiTextHeight;
  268.  
  269.  
  270. (*------------------------------------*)
  271. PROCEDURE CentreIntuiText * (
  272.   VAR intuiText : i.IntuiText;
  273.   left, top, width, height : INTEGER );
  274. (*
  275.   Adjusts the text's position to centre it within a rectangle defined by
  276.   (left, top, width, height).
  277. *)
  278.  
  279. BEGIN (* CentreIntuiText *)
  280.   intuiText.leftEdge :=
  281.     ( ( width - SHORT (i.IntuiTextLength(intuiText)) ) DIV 2 ) + left;
  282.   intuiText.topEdge :=
  283.     ( ( height - IntuiTextHeight(intuiText) ) DIV 2 ) + top;
  284. END CentreIntuiText;
  285.  
  286.  
  287. (*------------------------------------*)
  288. PROCEDURE CalcTextBox *
  289.   ( text              : ARRAY OF CHAR;
  290.     font              : gfx.TextAttrPtr;
  291.     VAR width, height : INTEGER );
  292. (*
  293.   Returns the minimum size of the rectangle that will enclose the given text
  294.   if rendered in the given font.
  295. *)
  296.  
  297. VAR
  298.   intuiText : i.IntuiText;
  299.  
  300. <*$CopyArrays-*>
  301. BEGIN (* CalcTextBox *)
  302.   intuiText.iText := SYS.ADR (text);
  303.   intuiText.iTextFont := font;
  304.   width := SHORT (i.IntuiTextLength (intuiText));
  305.   height := IntuiTextHeight (intuiText);
  306. END CalcTextBox;
  307.  
  308.  
  309. (* ===== Window ===== *)
  310.  
  311.  
  312. (*------------------------------------*)
  313. PROCEDURE ClipWindow *
  314.   ( window                 : i.WindowPtr;
  315.     minX, minY, maxX, maxY : INTEGER;
  316.     VAR oldRegion          : gfx.RegionPtr )
  317.   : BOOLEAN;
  318. (*
  319.   Sets up the window's clipping region to permit drawing only inside the
  320.   rectangle defined by (minX, minY, maxX, maxY). It returns FALSE if the
  321.   attempt fails and puts the existing clipping region in oldRegion.  It
  322.   should immediately be followed by drawing routines, then
  323.   UnclipWindow( window, oldRegion ).
  324. *)
  325.  
  326. VAR
  327.   newRegion : gfx.RegionPtr; myRectangle : gfx.Rectangle;
  328.  
  329. BEGIN (* ClipWindow *)
  330.   myRectangle.minX := minX;
  331.   myRectangle.minY := minY;
  332.   myRectangle.maxX := maxX;
  333.   myRectangle.maxY := maxY;
  334.   newRegion := gfx.NewRegion();
  335.   IF newRegion # NIL THEN
  336.     IF gfx.OrRectRegion (newRegion, myRectangle) THEN
  337.       oldRegion := l.InstallClipRegion (window.wLayer, newRegion);
  338.       RETURN TRUE;
  339.     END
  340.   END;
  341.   IF newRegion # NIL THEN
  342.     gfx.DisposeRegion (newRegion);
  343.   END;
  344.   RETURN FALSE;
  345. END ClipWindow;
  346.  
  347.  
  348. (*------------------------------------*)
  349. PROCEDURE ClipWindowToBorders *
  350.   ( window : i.WindowPtr; VAR oldRegion : gfx.RegionPtr )
  351.   : BOOLEAN;
  352. (*
  353.   Sets up the window's clipping region to permit drawing only inside the
  354.   rectangle defined by the window's borders.  It returns FALSE if the
  355.   attempt fails and puts the existing clipping region in oldRegion.  It
  356.   should immediately be followed by drawing routines, then
  357.   UnclipWindow( window, oldRegion ).
  358. *)
  359.  
  360. BEGIN (* ClipWindowToBorders *)
  361.   RETURN
  362.     ClipWindow
  363.       ( window, window.borderLeft, window.borderTop,
  364.         window.width - window.borderRight - 1,
  365.         window.height - window.borderBottom - 1, oldRegion );
  366. END ClipWindowToBorders;
  367.  
  368.  
  369. (*------------------------------------*)
  370. PROCEDURE UnclipWindow * (window : i.WindowPtr; prevRegion : gfx.RegionPtr);
  371. (*
  372.   Restores a window's clipping region after a call to ClipWindow() or
  373.   ClipWindowToBorders();
  374. *)
  375.  
  376. VAR
  377.   oldRegion : gfx.RegionPtr;
  378.  
  379. BEGIN (* UnclipWindow *)
  380.   oldRegion := l.InstallClipRegion (window.wLayer, prevRegion);
  381.   IF oldRegion # NIL THEN
  382.     gfx.DisposeRegion (oldRegion);
  383.   END
  384. END UnclipWindow;
  385.  
  386.  
  387. (*------------------------------------*)
  388. PROCEDURE DrawWidth * ( window : i.WindowPtr ) : INTEGER;
  389. (*
  390.   Returns the width of the window's inner drawing region.
  391. *)
  392.  
  393. BEGIN
  394.   RETURN (window.width - window.borderLeft - window.borderRight)
  395. END DrawWidth;
  396.  
  397.  
  398. (*------------------------------------*)
  399. PROCEDURE DrawHeight *
  400.   ( window : i.WindowPtr )
  401.   : INTEGER;
  402. (*
  403.   Returns the height of the window's inner drawing region.
  404. *)
  405.  
  406. BEGIN
  407.   RETURN (window.height - window.borderTop - window.borderBottom)
  408. END DrawHeight;
  409.  
  410.  
  411. (*------------------------------------*)
  412. PROCEDURE AdjustForBorders *
  413.   ( window : i.WindowPtr; VAR left, top : INTEGER );
  414. (*
  415.   Adjusts a window co-ordinate to ensure the origin is the top left of the
  416.   window's inner drawing region.
  417. *)
  418.  
  419. BEGIN (* AdjustForBorders *)
  420.   IF ~(i.gimmeZeroZero IN window.flags) THEN
  421.     INC( left, window.borderLeft); INC( top, window.borderTop)
  422.   END
  423. END AdjustForBorders;
  424.  
  425.  
  426. (*------------------------------------*)
  427. PROCEDURE StripIntuiMessages *
  428.   ( mp : e.MsgPortPtr; win : i.WindowPtr );
  429. (*
  430.   Function to remove and reply all IntuiMessages on a port that have
  431.   been sent to a particular window (note that we don't rely on the
  432.   lnSucc pointer of a message after we have replied it).
  433.  
  434.   This is from the RKM:Libraries, 3d Ed, p255.
  435. *)
  436.  
  437.   VAR msg : i.IntuiMessagePtr; succ : e.NodePtr;
  438.  
  439. BEGIN (* StripIntuiMessages *)
  440.   msg := SYS.VAL (i.IntuiMessagePtr, mp.msgList.head);
  441.   WHILE msg.execMessage.node.succ # NIL DO
  442.     succ := msg.execMessage.node.succ;
  443.     IF msg.idcmpWindow = win THEN
  444.       (*
  445.         Intuition is about to free this message.  Make sure that we have
  446.         politely sent it back.
  447.       *)
  448.       e.Remove (msg);
  449.       e.ReplyMsg (msg)
  450.     END;
  451.     msg := SYS.VAL (i.IntuiMessagePtr, succ)
  452.   END
  453. END StripIntuiMessages;
  454.  
  455. (*------------------------------------*)
  456. PROCEDURE CloseWindowSafely *
  457.   ( win : i.WindowPtr );
  458. (*
  459.   Strip all IntuiMessages from an IDCMP which are waiting for a specific
  460.   window.  When the messages are gone, set the UserPort of the window to
  461.   NIL and call ModifyIDCMP (win, {}).  This will free the Intuition
  462.   parts of the IDCMP and turn off messages to this port without changing
  463.   the original UserPort (which may be in use by other windows).
  464.  
  465.   This is from the RKM:Libraries, 3d Ed, p255.
  466. *)
  467.  
  468.   VAR
  469.  
  470. BEGIN (* CloseWindowSafely *)
  471.   (* We forbid here to keep out of race conditions with Intuition *)
  472.   e.Forbid ();
  473.  
  474.   (*
  475.     Send back any messages for this window that have not yet been processed
  476.   *)
  477.   StripIntuiMessages (win.userPort, win);
  478.  
  479.   (* Clear UserPort so Intuition will not free it *)
  480.   win.userPort := NIL;
  481.  
  482.   (* Tell Intuition to stop sending messages *)
  483.   i.OldModifyIDCMP (win, {});
  484.  
  485.   (* Turn multitasking back on *)
  486.   e.Permit ();
  487.  
  488.   (* Now it's safe to really close the window *)
  489.   i.CloseWindow (win)
  490. END CloseWindowSafely;
  491.  
  492. (*------------------------------------*)
  493. PROCEDURE FindSizeGadget *
  494.   ( win : i.WindowPtr; VAR width, height : INTEGER )
  495.   : BOOLEAN;
  496.  
  497.   CONST
  498.     Sizing = i.sysGadget + i.sizing;
  499.  
  500.   VAR gadget : i.GadgetPtr;
  501.  
  502. BEGIN (* FindSizeGadget *)
  503.   gadget := win.firstGadget;
  504.   WHILE (gadget # NIL) & (gadget.gadgetType # Sizing) DO
  505.     gadget := gadget.nextGadget
  506.   END;
  507.   IF gadget # NIL THEN
  508.     width := gadget.width; height := gadget.height
  509.   END;
  510.   RETURN (gadget # NIL)
  511. END FindSizeGadget;
  512.  
  513. (* ===== Requesters ===== *)
  514.  
  515. (*------------------------------------*)
  516.  
  517. <*$LongVars-*>
  518.  
  519. PROCEDURE MultiRequest *
  520.   ( window                     : i.WindowPtr;
  521.     VAR bodyText               : ARRAY OF e.APTR;
  522.     lines                      : INTEGER;
  523.     positiveText, negativeText : e.APTR )
  524.   : BOOLEAN;
  525.  
  526. CONST
  527.   NoFlags = {};
  528.   ExtraWidth = 32;
  529.   ExtraHeight = 22;
  530.  
  531. VAR
  532.   newTextPtr, bodyTextPtr, positiveTextPtr, negTextPtr : i.IntuiTextPtr;
  533.   positiveIntuiText, negativeIntuiText : i.IntuiText;
  534.   textHeight, maxLength, width, height : INTEGER;
  535.   memory : i.RememberPtr;
  536.   result : BOOLEAN;
  537.  
  538. BEGIN (* MultiRequest *)
  539.   IF (lines > 0) THEN
  540.     IF positiveText # NIL THEN
  541.       positiveIntuiText := autoIntuiText;
  542.       positiveIntuiText.iText := positiveText;
  543.       positiveTextPtr := SYS.ADR (positiveIntuiText);
  544.     ELSE
  545.       positiveTextPtr := NIL;
  546.     END;
  547.     IF negativeText # NIL THEN
  548.       negativeIntuiText := autoIntuiText;
  549.       negativeIntuiText.iText := negativeText;
  550.       negTextPtr := SYS.ADR (negativeIntuiText);
  551.     ELSE
  552.       RETURN FALSE
  553.     END;
  554.     memory := NIL;
  555.     bodyTextPtr := NIL;
  556.     maxLength := 0;
  557.     textHeight := PrefsFontHeight() + 1;
  558.     height := ((lines + 2) * textHeight) + ExtraHeight;
  559.     WHILE lines > 0 DO
  560.       newTextPtr := i.AllocRemember (memory, SIZE(i.IntuiText), {});
  561.       IF newTextPtr # NIL THEN
  562.         DEC (lines);
  563.         newTextPtr^ := autoIntuiText;
  564.         INC (newTextPtr^.topEdge, lines * textHeight);
  565.         newTextPtr.iText := bodyText [lines];
  566.         newTextPtr.nextText := bodyTextPtr;
  567.         maxLength :=
  568.           u.MaxInt
  569.             (maxLength, SHORT (i.IntuiTextLength(newTextPtr^)));
  570.         bodyTextPtr := newTextPtr;
  571.       ELSE
  572.         i.FreeRemember (memory, e.LTRUE);
  573.         RETURN FALSE;
  574.       END
  575.     END; (* WHILE *)
  576.     width := maxLength + ExtraWidth;
  577.     result :=
  578.       i.AutoRequest
  579.         ( window, bodyTextPtr, positiveTextPtr, negTextPtr, NoFlags,
  580.           NoFlags, width, height );
  581.     i.FreeRemember (memory, e.LTRUE);
  582.     RETURN result;
  583.   ELSE
  584.     RETURN FALSE;
  585.   END
  586. END MultiRequest;
  587.  
  588. <*$LongVars+*>
  589.  
  590. (*------------------------------------*)
  591. PROCEDURE SimpleRequest * (
  592.   window                               : i.WindowPtr;
  593.   bodyText, positiveText, negativeText : e.APTR )
  594.   : BOOLEAN;
  595.  
  596. VAR
  597.   bodyTextArray : ARRAY 1 OF e.APTR;
  598.  
  599. BEGIN (* SimpleRequest *)
  600.   IF bodyText # NIL THEN
  601.     bodyTextArray [0] := bodyText;
  602.     RETURN
  603.       MultiRequest (window, bodyTextArray, 1, positiveText, negativeText);
  604.   ELSE
  605.     RETURN FALSE;
  606.   END
  607. END SimpleRequest;
  608.  
  609.  
  610. (*------------------------------------*)
  611. PROCEDURE SimpleNotice *
  612.   ( window : i.WindowPtr; bodyText : e.APTR );
  613.  
  614. BEGIN (* SimpleNotice *)
  615.   SYS.PUTREG (0, SimpleRequest (window, bodyText, NIL, SYS.ADR("Continue")))
  616. END SimpleNotice;
  617.  
  618.  
  619. (*------------------------------------*)
  620. PROCEDURE MultiNotice *
  621.   ( window : i.WindowPtr; VAR bodyText : ARRAY OF e.APTR; lines : INTEGER );
  622.  
  623. BEGIN (* MultiNotice *)
  624.   SYS.PUTREG
  625.     (0, MultiRequest (window, bodyText, lines, NIL, SYS.ADR("Continue")))
  626. END MultiNotice;
  627.  
  628.  
  629. (* ===== Menus ===== *)
  630.  
  631.  
  632. (*------------------------------------*)
  633. PROCEDURE GetMenuChoice *
  634.   ( menuSelection  : INTEGER;
  635.     VAR firstMenu  : i.Menu;
  636.     VAR menuChoice : Choice );
  637.  
  638. BEGIN (* GetMenuChoice *)
  639.   menuChoice.menuChosen := (menuSelection MOD 32);
  640.   menuChoice.itemChosen := (SYS.LSH (menuSelection, -5) MOD 64);
  641.   menuChoice.subItemChosen := (SYS.LSH (menuSelection, -11) MOD 32);
  642.   menuChoice.pointer := i.ItemAddress (firstMenu, menuSelection);
  643. END GetMenuChoice;
  644.  
  645.  
  646. <*$LongVars-*>
  647.  
  648. BEGIN (* IntuiUtil *)
  649.   autoIntuiText.leftEdge  := i.autoLeftEdge;
  650.   autoIntuiText.topEdge   := i.autoTopEdge;
  651.   autoIntuiText.frontPen  := i.autoFrontPen;
  652.   autoIntuiText.backPen   := i.autoBackPen;
  653.   autoIntuiText.drawMode  := i.autoDrawMode;
  654.   autoIntuiText.iTextFont := i.autoITextFont;
  655.   autoIntuiText.iText     := NIL;
  656.   autoIntuiText.nextText  := i.autoNextText;
  657. END IntuiUtil.
  658.  
  659.