home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / defproc / mdefproc.hqx / mdefproc.a
Encoding:
Text File  |  1990-03-05  |  105.2 KB  |  2,743 lines

  1. ;EASE$$$ READ ONLY COPY of file ╥MdefProc.a╙
  2. ; 1.6    PKE 08/22/1989 Rolling in from reality sources (YAY)
  3. ;<1.7>    PKE 08/21/1989 NEEDED FOR 6.0.4: (really dba) Fix bug in bug fix. GrayRect takes
  4. ;        its parameter in A0, so A0 must be set up with TempRect before calling
  5. ;        GrayRect. I tried to fix the earlier bug by not relying on A0 -- big mistake.
  6. ;        Instead, get TempRect into a0.
  7. ; 1.5    PKE 08/15/1989  Rolling in from Reality sources
  8. ;<1.6>    dba 08/15/1989  NEEDED FOR 6.0.4: fix bug in GetItemHeight where it relies
  9. ;        on GetIconSize not trashing A0
  10. ;<1.5>    RLC 08/10/1989 Changed selector message to Help Mgr Pack to MOVEQ
  11. ;        #select,D0
  12. ; 1.1    CCH 11/11/1988 Fixed Header.
  13. ; 1.0    CCH 11/ 9/1988 Adding to EASE.
  14. ; OLD REVISIONS BELOW
  15. ;Ñ1.3    EMT 10/3/88 Roll in latest bug fixes.
  16. ; END EASE MODIFICATION HISTORY 
  17. ;----------------------------------------------------------------
  18. ;    ⌐ Apple Computer, Inc.    1982, 1983, 1984, 1985, 1986, 1987, 1988
  19. ;    All Rights Reserved
  20. ;----------------------------------------------------------------
  21. ;File mDefProc.ASM
  22. ;------------------------------------------------------------
  23. ;
  24. ;    Standard Menu Definition Procedure for Text Menus
  25. ;
  26. ;    written by Andy Hertzfeld    July 1982
  27. ;
  28. ;    Here is the default menu definition procedure for text menus.  It knows how to
  29. ;    draw a text menu, or select from within a text menu.  It is always called from the
  30. ;    window manager port with clipping set to the menuRect. (Not CalcMenuSize)
  31. ;
  32. ; MODIFICATION HISTORY:
  33. ;    27-Dec-82    AJH    Broke off into separate file for resources
  34. ;    28-Jan-83    AJH    made "GrayRect" use FillRect and a hardwired gray
  35. ;    17-Mar-83    AJH    Fixed 4 pixel choosing offset
  36. ;    17-Mar-83    AJH    no more forcing bold
  37. ;    28-Apr-83    AJH    added "calcMenuSize" message
  38. ;    30-Oct-83    AJH    changed disabling
  39. ;    06-Nov-83    AJH    back to old disabling; special-cased "-" item
  40. ;    13-Feb-84    AJH    speeded up CalcMenuSize message (linear instead of N squared)
  41. ;    11-Jan-85    JTC    convert to MDS
  42. ;    14-Feb-85    JTC    named rsrc.
  43. ;    15-Feb-85    SC    fixed applemark/commandMark bug in command keys
  44. ;    10-Apr-85    EHB    fixed CalcMenuSize for items with 0 length
  45. ;    29-Jul-85    EHB    converted back to porkshop
  46. ;v3    01-Aug-85    EHB    adapted for variable height system fonts
  47. ;v4    26-Aug-85    EHB    ROM/Ram version (tests ROM85)
  48. ;v5    27-Sep-85    EHB    Added International menu display.
  49. ;                    Added emergency menu scrolling.
  50. ;    30-Sep-85    EHB    Made scrolling smoother.
  51. ;    11-Oct-85    EHB    Do test byte of low memory justification word, so intl. people
  52. ;                    can use the high byte for further discrimination (yuck).
  53. ;    15-Oct-85    EHB    Fixed bugs in display of menu icons
  54. ;
  55. ;------------------    Lonely Hearts ROMs ------------------------
  56. ;
  57. ;        Dec-85    EHB    Different low memory locations if on old ROMs
  58. ;
  59. ; -----------------    System File 3.0 ---------------------------
  60. ;
  61. ;    07-Jan-86    EHB    Fixed enable bug for items > 31 (see C466 below)
  62. ;    07-Jan-86    EHB    Don't leave extra space at bottom of screen (reversed 30 Jan)
  63. ;    30-Jan-86    EHB    Re-did scrolling so icons would work
  64. ;
  65. ;    01-Oct-86    DAF    Changed include headers
  66. ;    30-Oct-86    FJL    C222    Fixes for hierarchical menus
  67. ;    04-Nov-86    FJL    CXXX    General clean up of menu manager.
  68. ;                            When #ScriptMenuCmd ($1C) in itemCmd field item
  69. ;                            to be printed in script whose ID is in the itemIcon field --
  70. ;                            also, command keys draw as cmdletter/cmdchar rather
  71. ;                            than normal cmdchar/cmdletter (for International).
  72. ;                            Also slow down scrolling.
  73. ;    08-Dec-86    FJL    C408    Added color support
  74. ;    25-Nov-86    FJL    C466    Fixed ENABLETEST (local label) so enables items > 31 unless whole
  75. ;                            menu disabled.
  76. ;    10-Feb-87    FJL    C792    Add scrolling indicator to top and bottom of scrollable menus.
  77. ;    20-Feb-87    FJL    C838    Sped up menu scrolling by an amazing amount.
  78. ;    20-Feb-87    FJL    C844    New routine PopUpMenuSelect.
  79. ;    06-Mar-87    FJL            Clean up all OnNuMac conditionals for System Disk --> Universal defproc
  80. ;    09-Mar-87    FJL            Add variable speed menu scrolling
  81. ;    17-Mar-87    FJL            Do invert for MacPlus/MacSE rather than redraw (for MacDraw custom menu)
  82. ;                            when choosing item
  83. ;    30-Mar-87    FJL    PMAB155 Don't reference MenuDisable in mdefproc.a on 64K ROMs.
  84. ;    08-Apr-87    DBG&JTC S171 Save D2 (volatile register) around call to CalcMenuSize in PopUpMenu
  85. ;                            message.
  86. ;    14-Apr-87    FJL    PMAB177 Use CopyBits instead of CopyMask for drawing hierarchical and scrolling
  87. ;                            arrows.  Do moveq #BitMapRec, d0 instead of move.w #BitMapRec, d0
  88. ;                            before call to NewHandle.
  89. ;
  90. ;------------------------------- System 4.2 and beyond -----------------------------------
  91. ;
  92. ;    14-Jul-87    FJL    PMAB205 Juggler support -- support shrunken and small icons
  93. ;    21-Aug-87    FJL    PMAB239 Calculate menu width correctly when have shrunken or small icons
  94. ;    15-Sep-87    FJL    PMAB276 Allow item = 0 to popupmenuselect
  95. ;    PMAB364    23Jan88    EMT        Fix Pop-up menus to come up on any screen
  96. ;    S394    12Feb88    DBG        Fixed errant branch, which was reversed, causing crash on +/SE
  97. ;    S422    08Mar88 MED        Fixed mdefproc.a to use SetScriptFont uniformally instead of inaccurate calculation
  98. ;    S476    22Apr88    EMT        Fixed hierchical menus being forced below menu bar
  99. ;    S550    27Jul88    EMT        Removed references to WMgrPort for ROM
  100. ;                            Fixed problems when teSysJust set for right-to-left drawing
  101. ;                            Treat dash as special only if no icon or cmd.  Primarily for MultiFinder
  102. ;                            Handle color icons other than 32x32
  103. ;                            And some miscellaneous code cleanup
  104. ;---------------------------------------------------------------
  105.  
  106. ;
  107. ; PROCEDURE TextMenuProc(    message        :Integer,
  108. ;                            theMenu        :menuHandle,
  109. ;                        VAR menuRect    :Rect,
  110. ;                            hitPt        :Point,
  111. ;                        VAR whichItem    :Integer);
  112. ;
  113. ;Msg        theMenu        menuRect            hitPt        whichItem
  114. ;------        -----------    -----------            -------        -----------
  115. ; 0 Draw    handle        entry: ptr to        not used    not used
  116. ;                        return: no chg
  117. ; 1    Choose    handle        entry: ptr to        mouse pt    entry: ptr to currently selected item
  118. ;                        return: no chg                    return: newly selected item
  119. ; 2 Calc    handle        not used            not used    not used
  120. ; 3 PopUp    handle        entry: none            top/left    entry: CrsrItem to be placed at HitPt
  121. ;                        return:    menu rect                return: TopMenuItem
  122.  
  123.             BLANKS        ON
  124.             STRING        ASIS
  125.  
  126. ;----------------------------------------------------------------------------------------
  127. ;
  128. ;    Conditional Definitions
  129. ;
  130. ;----------------------------------------------------------------------------------------
  131.  
  132.     IF (&TYPE('forTESTING') = 'UNDEFINED') THEN
  133. forTESTING EQU 0
  134.     ENDIF
  135.  
  136.     IF (&TYPE('forRAM') = 'UNDEFINED') THEN
  137. forRAM EQU 0
  138.     ENDIF
  139.  
  140.             INCLUDE    'inc.sum.a'
  141.             LOAD    'nequ.d'
  142.             INCLUDE    'colorequ.a'
  143.  
  144.     IF forTESTING THEN                            ; uggghhhlllyyy
  145.             INCLUDE 'myEquates.a'
  146.     ENDIF
  147.  
  148.  
  149. ShrunkenIconCmd    EQU        $1D                        ; itemCmd == $1D ==> large icon plotted in 16x16
  150. SmallIconCmd    EQU        $1E                        ; itemCmd == $1E ==> small icon plotted
  151. ;----------------------------------------------------------------------------------------
  152. ;
  153. ;    StackFrame and Global Definitions
  154. ;
  155. ;----------------------------------------------------------------------------------------
  156.  
  157. MDEF0            PROC    EXPORT
  158.  
  159. ;
  160. ; Stack Frame Definition for TextMenuProc
  161. ;
  162.  
  163. MFHeight        EQU        -2                ; <1Aug85> cell height
  164. MWidMax            EQU        MFHeight - 2    ; <1Aug85>
  165. MDescent        EQU        MWidMax - 2        ; <1Aug85>
  166. MAscent            EQU        MDescent - 2    ; <1Aug85>
  167. MInfoRec        EQU        MAscent            ; <1Aug85>
  168. MSpaceWidth        EQU        MInfoRec - 2    ; <S550    27Jul88    EMT>
  169. saveForeColor    EQU        MSpaceWidth - 6    ; <FJL C408>
  170. saveBackColor    EQU        saveForeColor-6    ; <FJL C408>
  171. pixelDepth        EQU        saveBackColor-2 ; <FJL C408>
  172. colorOffset        EQU        pixelDepth - 2    ; <FJL C408>
  173. invertFlag        EQU        colorOffset - 2    ; <FJL C408>    0 = normal item, 1 = inverted item
  174. scrollFlag        EQU        invertFlag - 2    ; <FJL 17Mar87>    0 = scrolling item, 1 = choosing item
  175. HItemFlag        EQU        scrollFlag - 2    ; <FJL 17Mar87>    0 = no sub menu, 1 = item has submenu
  176. iconHandle        EQU        HItemFlag - 4    ; <FJL C408>
  177. HierArrowRect    EQU        iconHandle - 8    ; <FJL 25Jan87>
  178. OrigMenuRect    EQU        HierArrowRect-8    ; <FJL C792>
  179. ScrollSpeed        EQU        OrigMenuRect - 4; <FJL 09Mar87>
  180. SlowPixels        EQU        ScrollSpeed - 2    ; <FJL 09Mar87>
  181. onColorMachine    EQU        SlowPixels-2    ; <FJL 06Mar87>
  182. lastItemStrPtr    EQU        onColorMachine-4    ; <KSM/RLC    31May89>
  183. lastAttrPtr        EQU        lastItemStrPtr-4    ; <KSM/RLC    31May89>
  184. LinkSize        EQU        lastAttrPtr        ; <FJL C792>
  185.  
  186.  
  187. MWHICHITEM        EQU        8
  188. MPopUpItem        EQU        MWhichItem        ; <FJL C844>
  189.  
  190. MPOINT            EQU        MWHICHITEM+4
  191. MLeftTop        EQU        MPoint            ; <FJL C844>
  192.  
  193. MMENURECT        EQU        MPOINT+4
  194. MMENUHANDLE        EQU        MMENURECT+4
  195. MMESSAGE        EQU        MMENUHANDLE+4
  196.  
  197. FastSpeed        EQU        0
  198. SlowSpeed        EQU        10
  199.  
  200. FirstMDMsg        EQU        0                ; first message
  201. LastMDMsg        EQU        3                ; last message
  202.  
  203.  
  204. ;----------------------------------------------------------------------------------------
  205. ;
  206. ;    Start of Code -- save work registers and dispatch on message number
  207. ;
  208. ;----------------------------------------------------------------------------------------
  209.  
  210.             BRA.S    StartMDEF
  211.  
  212. ; Standard Header
  213.  
  214.             DC.W    0                    ; flags word
  215.             DC.B    'MDEF'                ; type
  216.             DC.W    0                    ; ID
  217.             DC.W    12                    ; version 4 = MacPlus
  218.                                         ; version 5 = Alladin
  219.                                         ; version 6 = onNuMac ROM
  220.                                         ; version 10= Universal
  221.                                         ; version 11= Universal 4.2                    <FJL PMAB205>
  222.                                         ; version 12= Universal 6.0                    <PMAB364    23Jan88    EMT>
  223.  
  224. StartMDEF
  225.             LINK    A6,#LinkSize        ; set up a stack frame                        <1Aug85>
  226.             MOVEM.L D3-D7/A2-A4,-(SP)    ; save a whole bunch of work registers
  227.  
  228.             MOVE.L    MMENUHANDLE(A6),A3    ; keep menuHandle in A3
  229.             move.l    a3, a0                ;                                            <FJL 27Jan87>
  230.             _HLock                        ; lock it down
  231.             clr        invertFlag(a6)        ; most drawing done in normal (not inverted) mode <FJL C408>
  232.             clr        scrollFlag(a6)        ; only set this flag when call InvertItem    <FJL 17Mar87>
  233.                                         ; while scrolling
  234.             clr        onColorMachine(a6)    ; clear color machine flag                    <FJL 06Mar87>
  235.             cmpi.w    #$3FFF, ROM85        ; color machine ?
  236.             sls        onColorMachine(a6)    ; set byte to 1's if yes
  237.  
  238.             lea        GoMdefProc, a0        ; get the dispatch table base                <FJL>
  239.             move.w    mMessage(a6), d0    ; get the message type
  240.  
  241.             cmpi    #LastMDMsg, d0        ; is the message within bounds?                <FJL>
  242.             bhi.s    @InvalidMsg            ; oops, its too high
  243.             cmpi    #FirstMDMsg, d0        ;
  244.             blo.s    @InvalidMsg            ; oops, its too low
  245.  
  246.             add.w    d0, d0                ; double to get words
  247.             add.w    GoMdefProc(d0), a0    ; compute the dispatch address
  248.  
  249.             jsr        (a0)                ; and dispatch
  250.  
  251. @InvalidMsg
  252.             move.l    a3, a0                ; get menuHandle
  253.             _HUnlock                    ; and unlock it before we leave
  254.             MOVEM.L (SP)+,D3-D7/A2-A4    ; restore work registers
  255.             UNLK    A6                    ; unbuild the stack frame
  256.  
  257.             MOVE.L    (SP)+,A0            ; get return address
  258.             ADD        #18,SP                ; strip parameters
  259.             JMP        (A0)                ; return to caller
  260.  
  261. ; Dispatch Table
  262.  
  263. GoMdefProc        dc.w    DoDrawMsg-GoMdefProc            ; draw is message            #0
  264.                 dc.w    DoChooseMsg-GoMdefProc            ; choose menu size is msg    #1
  265.                 dc.w    DoCalcMsg-GoMdefProc            ; calc menu is msg            #2
  266.                 dc.w    DoPopUpItemMsg-GoMdefProc        ; calc top of popup item    #3
  267.  
  268. ;********************************************************************************************
  269. ;*                                                                                            *
  270. ;* IF YOU ADD ANOTHER MESSAGE YOU MUST UPDATE THE VARIABLE "LastMDMsg" FOUND ABOVE !!!!!!    *
  271. ;*                                                                                            *
  272. ;********************************************************************************************
  273.  
  274. ;----------------------------------------------------------------------------------------
  275. ;
  276. ;    Msg #1 -- Choose -- examine the mouse position and hilite the appropriate item
  277. ;
  278. ;----------------------------------------------------------------------------------------
  279.  
  280. DoChooseMsg
  281.  
  282. ;
  283. ; --------------------------    DO SETUP STUFF    ---------------------------
  284. ;
  285.             bsr        GetSizes            ; get font info into stackframe
  286.  
  287.             MOVE.L    MWHICHITEM(A6),A4    ; get pointer to whichItem
  288.             MOVE.W    (A4),D3                ; remember oldWhichItem
  289.             CLR        (A4)                ; set whichItem to zero
  290.             MOVE.L    MMENURECT(A6),A2    ; get the menu rect                            <27Sep85>
  291.                                         ; store original menurect in the stackframe    <FJL C792>
  292.             move.l    Top(a2), OrigMenuRect+Top(a6)
  293.             move.l    Bottom(a2), OrigMenuRect+Bottom(a6)
  294.             move.l    #FastSpeed,    ScrollSpeed(a6) ; assume fast-speed                    <FJL 09Mar87>
  295.             move    MFHeight(a6), d0    ; get height of scroll arrow                <FJL 09Mar87>
  296.             asr        #1, d0                ; num pixels for slow scroll = height/2        <FJL 09Mar87>
  297.             move    d0, SlowPixels(a6)
  298.  
  299.             clr        HItemFlag(a6)        ; assume "old" item has no submenu            <FJL 17Mar87>
  300.             move    d3, d0                ; get item
  301.             move.l    (a3),a0                ; get menuPtr
  302.             bsr        GetItemRecord        ; look it up
  303.             cmp.b    #HMenuCmd, ItemCmd(a1)    ; does item have sub-menu?
  304.             bne.s    @NoSubMenu            ; no    ==> leave flag cleared
  305.             move    #1, HItemFlag(a6)    ; yes ==> set flag
  306.  
  307. @NoSubMenu    MOVE.W    TopMenuItem,D4        ; get top of (scrolled) menu            <30Jan86>
  308.             MOVE.L    MPOINT(A6),D5        ; get the mouse point                    <27Sep85>
  309.             BEQ        NOITEMSEL            ; => special case for flashing            <27Sep85>
  310.  
  311. ;
  312. ; -------------------    ADJUST MENURECT BASED ON SCROLLING ARROWS    ----------------
  313. ;
  314.             move    AtMenuBottom, d0    ; check for down scrolling arrow            <FJL C792>
  315.             cmp        Bottom(a2), d0        ; is AtMenuBottom > bottom of menu rect ?
  316.             ble.s    @NoScroll            ; no, so chk top
  317.             move    MFHeight(a6), d0    ; yes, so make menuRect smaller by down scrolling arrow rect
  318.             sub        d0, Bottom(a2)
  319. @NoScroll
  320.             move    TopMenuItem, d0        ; check for up scrolling arrow
  321.             cmp        Top(a2), d0            ; is TopMenuItem < top of menu rect ?
  322.             bge.s    @NoScroll2            ; no, so just do PtInRect
  323.             move    MFHeight(a6), d0    ; yes, so make menuRect smaller by up scrolling arrow rect
  324.             add        d0, Top(a2)
  325. @NoScroll2
  326. ;
  327. ; If the point isn't in the adjusted menuRect, check for autoscrolling
  328. ;
  329.             CLR.W    -(SP)                ; make room for PtInRect result
  330.             MOVE.L    D5,-(SP)            ; push the point
  331.             MOVE.L    A2,-(SP)            ; push the rect
  332.             _PtInRect                    ; test if the point is in the rect
  333.             TST.B    (SP)+                ; was it?
  334.             BNE        @3                    ; => yes, go select something
  335.  
  336. ;-----------------------    CHECK FOR AUTOSCROLLING DOWN    -------------------------------
  337. ;
  338. ; Only scroll if mouse pt directly above/below menu.  This allows
  339. ; hierarchical menus to work properly -- scroll when mouse above/below menu,
  340. ; -- return to a previous menu if outside of the scrolling rectangles.
  341. ;
  342.  
  343.             cmp        left(a2), d5        ; to left of menu's left side?            <FJL C222>
  344.             blt        NoItemSel            ; yes, so no item selected                <FJL C222>
  345.             cmp        right(a2), d5        ; to right of menu's right side?        <FJL C222>
  346.             bgt        NoItemSel            ; yes, so no item selected                <FJL C222>
  347.  
  348.             MOVE.W    MFHeight(A6),D7        ; get distance for scroll                    <30Sep85>
  349.             SWAP    D5                    ; get mouse.v into low word                    <27Sep85>
  350.             CMP.W    top(A2),D5            ; above top?                                <27Sep85>
  351.             BGE        @2                    ; => no, check bottom                        <27Sep85>
  352.             ADD.W    D7,D4                ; try to go up an item                        <27Sep85>
  353.             CMP.W    top(A2),D4            ; menu top must be <= to MenuRect.Top        <30Jan86>
  354.             BGT        NOITEMSEL            ; => can't go up                            <27Sep85>
  355.  
  356.                                         ; how far is mouse into scrolling arrow?    <FJL 09Mar87>
  357.             move    top(a2), d0            ; get top of menu into d0                    <FJL 09Mar87>
  358.             sub        d5, d0                ; subtract mouse.v                            <FJL 09Mar87>
  359.             cmp        SlowPixels(a6), d0    ; is it more than slow num ?                <FJL 09Mar87>
  360.             bgt.s    @ContDown                    ; yes ==> do it fast                <FJL 09Mar87>
  361.             move.l    #SlowSpeed, ScrollSpeed(a6)    ; no    ==> do it slow                <FJL 09Mar87>
  362.  
  363. @ContDown
  364. ;+++            move    AtMenuBottom, d0    ;                                        <FJL C792>
  365. ;+++            cmp        Bottom(a2), d0        ; is AtMenuBottom<> bottom of menu?
  366. ;+++            bne.s    @1                    ; yes, so just do scrolling
  367.  
  368.             move    AtMenuBottom, D0    ;                                            <FJL PMAB205>
  369.             cmp        Bottom(A2), D0        ; is AtMenuBottom > bottom of menu ?
  370.             bgt.s    @1                    ; yes -> no scrolling arrow needed
  371.             add        MFHeight(a6), d0
  372.             cmp        Bottom(A2), D0        ; is AtMenuBottom+scrollamt > bottom of menu ?    <FJL PMAB276>
  373.             ble.s    @1                    ; yes -> no scrolling arrow needed                <FJL PMAB276>
  374.  
  375. ; If we get here then we are scrolling down and the last item is showing.  Therefore
  376. ; we want to draw the down scroll arrow before scrolling.
  377.  
  378.             move.l    a2, a0                ; BlitScrollIndic expects menuRect ptr in A0
  379.             bsr        BlitDownScrollIndic
  380.             move    MFHeight(a6), d0    ; move bottom of menuRect up so arrow doesn't get scrolled
  381.             sub        d0, Bottom(a2)        ; and fall into scrolling code
  382.  
  383. ;-----------------------    DO THE AUTOSCROLLING    --------------------------------------
  384.  
  385. @1
  386.             MOVE.W    D3,D0                ; get the current selection                <30Sep85>
  387.             BSR    InvertItem                ; and deselect it                        <30Sep85>
  388.  
  389. ; When a HMenu is up and the item with the HMenu is the topmost or bottommost item
  390. ; garbage is left on the screen unless we bring down the HMenu first.
  391. ; Solution: 1) Don't scroll if an HMenu is up.
  392. ;            2) DrawMenu clears a flag in mbSaveLoc every time a menu is drawn.
  393. ;            3) If that flag is clear, then we set the flag and skip scrolling.
  394. ;                This gives MenuSelect a chance to bring down the HMenu before
  395. ;                the MDEF is called again.
  396. ;            4) If the flag is set, then it is okay to scroll.
  397.  
  398. ;>>>>>------------- MacPlus/MacSE patches ------------------>>>>>
  399.  
  400.         IF forRAM THEN
  401.  
  402.             cmp.w        #$FFFF, ROM85            ; on old Mac or MacXL?
  403.             beq.s        @OkToScroll                ; yes -> skip HMenu specific stuff
  404.  
  405.                                                 ; RADIUS patches out complete menu mgr ==> could
  406.                                                 ;    have GetItemCmd installed, but mbSaveLoc
  407.                                                 ;    not initialized.
  408.             cmpi.l        #$FFFFFFFF, mbSaveLoc    ; has the MBDF data structure been initialized?
  409.             beq.s        @OkToScroll
  410.  
  411.             move.w        #$009F, d0                ; load _Unimplemented number
  412.             _GetTrapAddress                        ; load _Unimplemented address
  413.             move.l        a0, d1                    ; copy routine address
  414.             move.w        #$004E, d0                ; load _GetItemCmd number
  415.             _GetTrapAddress    ,newTool            ; load _GetItemCmd address
  416.             cmp.l        a0, d1                    ; new HMenu Mgr installed?
  417.             beq.s        @OkToScroll                ; no -> skip HMenu specific stuff
  418.  
  419.         ENDIF    ; if forRAM
  420.  
  421. ;<<<<<--------------------------------------<<<<<
  422.  
  423.             move.l    mbSaveLoc, a0        ; get mbUglyScroll in mbSaveLoc
  424.             move.l    (a0), a0
  425.             tst        mbUglyScroll(a0)    ; is mbUglyScroll set ?
  426.             bne.s    @OkToScroll            ; yes, so HMenu was already brought down
  427.             move    #1, mbUglyScroll(a0); no, so set field
  428.             bra.s    @DoneScroll            ; and skip scrolling this time through
  429.  
  430. @OkToScroll
  431.             MOVE.W    D4,topMenuItem        ; stuff new topItem                        <27Sep85>
  432.  
  433.             CLR.L    -(SP)                ; room for region #1                    <30Sep85>
  434.             _NewRgn                        ; get it                                <30Sep85>
  435.             MOVE.L    (SP),D6                ; save in D6                            <30Jan86>
  436.             CLR.L    -(SP)                ; room for region #2                    <30Jan86>
  437.             _NewRgn                        ; get it                                <30Jan86>
  438.  
  439.             bsr        SaveCurrentColors    ; save current colors in stack frame            <FJL C408>
  440.             move    #mctRGB2, colorOffset(a6)    ; this offset is unimportant here        <FJL C408>
  441.                                                 ; since all we care about is bkgd color    <FJL C408>
  442.             bsr        SetColors            ; set proper colors    for ScrollRect                <FJL C408>
  443. ;
  444. ; Delay depending on how far cursor is into the scroll arrow.                            <FJL 09Mar87>
  445. ;
  446.             bsr        DoScrollWait
  447.  
  448. @DoTheScroll
  449.             MOVE.L    A2,-(SP)            ; push rect                                <27Sep85>
  450.             CLR.W    -(SP)                ; dh = 0                                <30Sep85>
  451.             MOVE.W    D7,-(SP)            ; dv = itemHeight                        <30Sep85>
  452.             MOVE.L    D6,-(SP)            ; push update region
  453.             _ScrollRect                    ; scroll the menu                        <30Sep85>
  454.  
  455.             bsr        ChkScrollArrows        ; chk if scrolling arrows should still be up    <FJL C792>
  456.             bsr        ResetPreviousColors    ; reset colors stored in stackframe                <FJL C408>
  457.  
  458.             MOVE.L    (SP),-(SP)            ; point to region #2                    <30Jan86>
  459.             _GetClip                    ; save the clip in it                    <30Jan86>
  460.             MOVE.L    D6,-(SP)            ; point to update region                <30Jan86>
  461.             _SetClip                    ; set clip to it                        <30Jan86>
  462.  
  463.             BSR        DrawScrolledItem    ; call fast routine to draw item        <FJL C838>
  464.             ADD        D7, AtMenuBottom    ; update new menu bottom                <FJL C838>
  465.  
  466.             MOVE.L    (SP),-(SP)            ; point to saved clip                    <30Jan86>
  467.             _SetClip                    ; and restore it                        <30Jan86>
  468.             _DisposRgn                    ; dispose of region #2                    <30Jan86>
  469.             _DisposRgn                    ; dispose of region #1                    <30Jan86>
  470.  
  471. ;
  472. ; When scrolling, no item is selected, so clear the Item in MenuDisable global    <FJL C792>
  473. ;
  474. @DoneScroll
  475.  
  476.         IF forRAM THEN
  477.  
  478.             tst.w    ROM85                ; on old Mac or MacXL?
  479.             bmi.s    @NoMenuDisable        ; yes -> MenuDisable is not available in low-memory , so skip
  480.  
  481.         ENDIF    ;forRAM
  482.  
  483.             clr        MenuDisable+2        ; clear Item only, not ID
  484.  
  485. @NoMenuDisable
  486.             BRA        DoChooseDone        ; and return                            <27Sep85>
  487.  
  488.  
  489. ;-----------------------    CHECK FOR AUTOSCROLLING UP    ----------------------------------
  490.  
  491. @2            MOVE.W    bottom(A2),D0        ; get bottom                            <30Jan86>
  492.             CMP.W    D0,D5                ; below bottom?                            <30Jan86>
  493.             BLT        NOITEMSEL            ; => no                                    <27Sep85>
  494.             CMP.W    atMenuBottom,D0    ; done scrolling?                            <30Jan86>
  495.             BGE        NOITEMSEL            ; => yes, nothing below us                <30Jan86>
  496.             NEG.W    D7                    ; change direction of scroll            <30Sep85>
  497.             ADD.W    D7,D4                ; else scroll down                        <27Sep85>
  498.  
  499.                                         ; how far is mouse into scrolling arrow?<FJL 09Mar87>
  500.             move    d5, d0                ; get mouse.v into d0                    <FJL 09Mar87>
  501.             sub        bottom(a2), d0        ; subtract bottom of menu                <FJL 09Mar87>
  502.             cmp        SlowPixels(a6), d0    ; is it more than slow num ?            <FJL 09Mar87>
  503.             bgt.s    @ContUp                        ; yes ==> do it fast            <FJL 09Mar87>
  504.             move.l    #SlowSpeed, ScrollSpeed(a6)    ; no    ==> do it slow            <FJL 09Mar87>
  505.  
  506. @ContUp
  507.             move    TopMenuItem, d0        ;                                        <FJL C792>
  508.             cmp        Top(a2), d0            ; is TopMenuItem <> top of menu rect ?
  509.             bne        @1                    ; yes, so just do scrolling
  510.  
  511. ; If we get here then we are scrolling up and the first item is showing.  Therefore
  512. ; we want to draw the up scroll arrow before scrolling.
  513.  
  514.             move.l    a2, a0                ; BlitScrollIndic expects menuRect ptr in A0
  515.             bsr        BlitUpScrollIndic
  516.             move    MFHeight(a6), d0    ; move top of menuRect up so arrow doesn't get scrolled
  517.             add        d0, Top(a2)            ; and fall into scrolling code
  518.             bra        @1
  519.  
  520. ;--------------------------------    DO THE CHOOSE    ------------------------------------
  521.  
  522. ; the point is in the menu, so waltz through the itemList keeping track of vertical
  523. ; position seeing which item it's in.  In the following loop, D4 holds the item number
  524. ; while D2 has the cumulative vertical space
  525. ;
  526. @3
  527. ;
  528. ; With popup menus it is possible to have the mouse pt above TopMenuItem            <FJL 22Mar87>
  529. ; but no down-scrolling taking place because TopMenuItem may be below top
  530. ; of the menuRect.  "Choose" must recognize this case and branch to NoItemSel.
  531. ;
  532.             CMP        Top(a2), D4            ; is TopMenuItem > top of menuRect ?
  533.             BLE.S    @DoChoose            ; no    ==> ok to choose
  534.             CMP        MPoint+V(a6), D4    ; yes ==> is TopMenuItem > mouse pt ?
  535.             BGT.S    NoItemSel            ; yes ==> no choice
  536.  
  537. @DoChoose    MOVE.W    D4,D2                ; top of menu into D2                        <30Jan86>
  538.             MOVEQ    #1,D4                ; start with first item                        <30Jan86>
  539.  
  540. MSELOOP        MOVE.L    (A3),A0                ; get menuPtr
  541.             MOVE    D4,D0                ; get item number
  542.             BSR        GETITEMRECORD        ; look it up
  543.             BEQ.S    NOITEMSEL            ; if so, nothing selected
  544.  
  545.             BSR        GetItemHeight        ; get item height in D0                        <1Aug85>
  546.             ADD        D0,D2                ; update vertical                            <1Aug85>
  547.             CMP        MPOINT+V(A6),D2        ; compare with mouse point
  548.             BGT.S    GOTSEL                ; when D2 is bigger, we found it
  549. ;
  550. ; we didn't reach it yet, so keep stepping down till we do
  551. ;
  552. NEXTMSEL    ADDQ    #1,D4                ; bump to next item
  553.             BRA.S    MSELOOP                ; loop till we find it
  554. ;
  555. ; we found it so update whichItem.  First we better make sure it's enabled
  556.  
  557. GOTSEL
  558. ;
  559. ; put item rect in mbSaveLoc so MenuSelect has it to do Hierarchical menu drag        <FJL C222>
  560. ; must store this regardless of whether item changed (consider case where an item
  561. ; has a HMenu and you move to the HMenu, and then back into the item with that HMenu).
  562. ;
  563.             LEA        TEMPRECT,A0            ; get pointer to temporary rectangle
  564.             MOVE.L    MMENURECT(A6),A1    ; point to menuRect
  565.             MOVE.L    (A1)+,(A0)            ; copy menuRect into tempRect
  566.             MOVE.L    (A1),4(A0)
  567.             MOVE    D2,BOTTOM(A0)        ; D2 has the bottom coordinate
  568.             SUB        D0,D2                ; subtract the height
  569.             MOVE    D2,TOP(A0)            ; set up the top
  570.  
  571. ;>>>>>------------- MacPlus/MacSE patches ------------------>>>>>
  572.  
  573.         IF forRAM THEN
  574.  
  575.             cmp.w        #$FFFF, ROM85            ; on old Mac or MacXL?
  576.             beq.s        @SkipRectStore            ; yes -> skip HMenu specific stuff
  577.  
  578.                                                 ; RADIUS patches out complete menu mgr ==> could
  579.                                                 ; have GetItemCmd installed, but mbSaveLoc
  580.                                                 ; not initialized.
  581.             cmpi.l        #$FFFFFFFF, mbSaveLoc    ; has the MBDF data structure been initialized?
  582.             beq.s        @SkipRectStore
  583.  
  584.             move.w        #$009F, d0                ; load _Unimplemented number
  585.             _GetTrapAddress                        ; load _Unimplemented address
  586.             move.l        a0, d1                    ; copy routine address
  587.             move.w        #$004E, d0                ; load _GetItemCmd number
  588.             _GetTrapAddress    ,newTool            ; load _GetItemCmd address
  589.             cmp.l        a0, d1                    ; new HMenu Mgr installed?
  590.             beq.s        @SkipRectStore            ; no -> skip HMenu specific stuff
  591.  
  592.         ENDIF    ; if forRAM
  593.  
  594. ;<<<<<--------------------------------------<<<<<
  595.             move.l    mbSaveLoc, a0                    ; get handle to save loc
  596.             move.l    (a0), a0                        ; dereference
  597.             move.l    TempRect, mbItemRect(a0)        ; save top, left
  598.             move.l    TempRect+4, mbItemRect+4(a0)    ; save bottom, right
  599.  
  600. @SkipRectStore
  601.             BSR        ENABLETEST            ; make sure whole menu is enabled
  602.             BEQ.S    DoInverting            ; if not, no selection
  603.             MOVE    D4,(A4)                ; menu is enabled, so store item
  604.             bra.s    DoInverting            ; and continue
  605.  
  606. ;
  607. ; At this label the mouse is not in any item, so clear d4 so we return the            <FJL C531>
  608. ; correct value in low-memory MenuDisable.  Can only reach here by a branch.
  609. ;
  610. NOITEMSEL    clr        d4                    ; at this label no item selected
  611.  
  612. ;
  613. ; see if whichItem changed; if it has, unselect the old item and select the new one
  614. ;
  615. DoInverting
  616.             CMP        (A4),D3                ; have they changed?
  617.             BEQ.S    GetDisabledItem        ; if not, we're all done, no hiliting change
  618.  
  619.  
  620.             MOVE    D3,D0                ; unhilite old item
  621.             BSR        INVERTITEM            ;
  622.             MOVE    (A4),D0                ; hilite new item
  623.             not        invertFlag(a6)        ; tell InvertItem to draw in reverse colors        <FJL C408>
  624.             BSR        INVERTITEM            ;
  625.             clr        invertFlag(a6)        ; reset invertFlag                                <FJL C408>
  626.  
  627. ;
  628. ; "User ed" requested that apps be able to find out if a disabled menu item was chosen.    <FJL C531>
  629. ; We return the ID and item in the global MenuDisable.  If the item is zero then        <FJL C531>
  630. ; no item was chosen (i.e. the mouse was outside the menu), or was in the title.        <FJL C531>
  631. ;
  632. GetDisabledItem
  633.  
  634.             move.l    (a3), a0            ; get menu ptr
  635.             swap    d4                    ; put item in hi-byte
  636.             move    menuID(a0), d4        ; put menuID in lo-byte
  637.             swap    d4                    ; restore d4
  638.  
  639.         IF forRAM THEN
  640.  
  641.             tst.w    ROM85                ; on old Mac or MacXL?
  642.             bmi.s    @NoMenuDisable        ; yes -> MenuDisable is not available in low-memory , so skip
  643.  
  644.         ENDIF    ;forRAM
  645.  
  646.             move.l        d4, MenuDisable    ; put in low-memory where apps can query it if they want
  647.  
  648. @NoMenuDisable
  649.  
  650. DoChooseDone
  651.             move.l    OrigMenuRect(a6), Top(a2)    ; reset menuRect in case we changed it<FJL C792>
  652.             move.l    OrigMenuRect+Bottom(a6), Bottom(a2)
  653.  
  654.             rts                            ; return to dispatcher
  655.             
  656.  
  657. ;-------------------------------    DONE CHOOSE MSG    ------------------------------------
  658.  
  659. ;---------------------------------------
  660. ;    Utility -- DoScrollWait                                                            <FJL 09Mar87>
  661. ;---------------------------------------
  662. ;
  663. ; Delay for ScrollSpeed ticks.  If cursor moves out of slow scroll area then leave wait loop.
  664. ;
  665. DoScrollWait
  666.             tst.l    ScrollSpeed(a6)        ; how fast should we scroll?
  667.             beq.s    @NoWait                ; zero means fast as possible
  668.  
  669.             move.l    d3, -(sp)            ; save temp reg on the stack
  670.             subq    #4, sp                ; space for result
  671.             _TickCount                    ; get current tick count
  672.             move.l    (sp)+, d3
  673.             add.l    ScrollSpeed(a6), d3    ; we want to wait until tick count in d3
  674.  
  675. @Loop        subq    #4, sp                ; space for VAR parameter
  676.             move.l    sp, -(sp)            ; push address of parameter
  677.             _GetMouse
  678.             move.l    (sp)+, d5            ; get mouse pt
  679.             swap    d5                    ; get .v into lo-word
  680.  
  681.             tst        d7
  682.             bge.s    @ScrollingDown
  683.                                         ; how far is mouse into scrolling arrow?    <FJL 09Mar87>
  684.             move    d5, d0                ; get mouse.v into d0                        <FJL 09Mar87>
  685.             sub        bottom(a2), d0        ; subtract bottom of menu                    <FJL 09Mar87>
  686.             cmp        SlowPixels(a6), d0    ; is it more than slow num ?                <FJL 09Mar87>
  687.             bgt.s    @DoneWait            ; yes    ==> do it fast ==> stop waiting        <FJL 09Mar87>
  688.             bra.s    @ContLoop
  689.  
  690. @ScrollingDown                            ; how far is mouse into scrolling arrow?
  691.             move    top(a2), d0            ; get top of menu into d0
  692.             sub        d5, d0                ; subtract mouse.v
  693.             cmp        SlowPixels(a6), d0    ; is it more than slow num ?
  694.             bgt.s    @DoneWait            ; yes ==> do it fast ==> stop waiting
  695. @ContLoop
  696.             subq    #4, sp                ; space for result
  697.             _TickCount
  698.             cmp.l    (sp)+, d3            ; reached desired tick count yet?
  699.             bgt.s    @Loop                ; no    ==> keep looping
  700.                                         ; yes ==> we're done waiting
  701. @DoneWait
  702.             move.l    (sp)+, d3            ; restore work register
  703. @NoWait
  704.             rts
  705.  
  706. ;---------------------------------------
  707. ;    Utility -- ChkScrollArrows
  708. ;---------------------------------------
  709. ; if scrolling up, and if last item is appearing, then lower clip by height of        <FJL C792>
  710. ; rectangle containing indicator arrow, and erase arrow rectangle.
  711. ChkScrollArrows
  712.  
  713.             tst        d7
  714.             bge.s    @ChkScrollDown        ; if D7 >= 0 then scrolling down not up
  715.             move    d7, d0                ; get amount of scroll
  716.             neg        d0                    ; take negative since to make it positive
  717.             add        MFHeight(a6), d0    ; add in height of scroll arrow
  718.             add        Bottom(a2), d0        ; add to bottom of menuRect
  719.             cmp        AtMenuBottom, d0    ; is new bottom of menuRect >= AtMenuBottom
  720.             blt.s    @NotLastItem        ; no ==> not showing last item
  721.  
  722. ; last item is being drawn -> open clip so scroll arrow gets erased and last item gets drawn <FJL C792>
  723.  
  724.             move.l    d6, a0                ; change the bottom of the update region
  725.             move.l    (a0), a0            ; get ptr to rgn
  726.             move    MFHeight(a6), d0    ; get menu item height
  727.             add        d0, 2+Bottom(a0)    ; Bottom = Bottom + menu item height
  728.             add        d0, Bottom(a2)        ; update bottom of menuRect                        <FJL C838>
  729.             move.l    d6, -(sp)            ; and erase the whole region
  730.             _EraseRgn
  731. @NotLastItem
  732.  
  733.             rts
  734.  
  735. ; if scrolling down, and if first item is appearing, then increase clip by height of    <FJL C792>
  736. ; rectangle containing indicator arrow, and erase arrow rectangle.
  737. ; NOTE: TopMenuItem has already been adjusted by scroll amount, so don't subtract it here
  738. @ChkScrollDown
  739.             move    Top(a2), d0            ; get Top of menuRect
  740.             sub        MFHeight(a6), d0    ; sub height of scroll arrow
  741.             cmp        TopMenuItem, d0        ; is new top of menuRect <= TopMenuItem
  742.             bgt.s    @NotFirstItem        ; no ==> not showing first item
  743.  
  744. ; first item is being drawn -> open clip so scroll arrow gets erased and first item gets drawn <FJL C792>
  745.  
  746.             move.l    d6, a0                ; change the top of the update region
  747.             move.l    (a0), a0            ; get ptr to rgn
  748.             move    MFHeight(a6), d0    ; get menu item height
  749.             sub        d0, 2+Top(a0)        ; Top = Top - menu item height
  750.             sub        d0, Top(a2)            ; update top of menuRect                        <FJL C838>
  751.             move.l    d6, -(sp)            ; and erase the whole region
  752.             _EraseRgn
  753. @NotFirstItem
  754.  
  755.             rts
  756.  
  757. ;---------------------------------------
  758. ;    Utility -- GetSizes
  759. ;---------------------------------------
  760. ; GetSizes reads the size of the current font into the stack frame.  It puts
  761. ; ascent+descent+leading into the leading field and tweaks width for chicago
  762.  
  763. GetSizes    LEA        MInfoRec(A6),A2        ; point to our info rec                        <1Aug85>
  764.             MOVE.L    A2,-(SP)            ; push a pointer                            <1Aug85>
  765.             _GetFontInfo                ; and get the font's info                    <1Aug85>
  766.             MOVE.W    (A2)+,D0            ; get ascent                                <1Aug85>
  767.             ADD.W    (A2)+,D0            ; add descent                                <1Aug85>
  768.  
  769. ; fudge width if font is Chicago so that space between command key and command        <FJL 21Jan87>
  770. ; character look better.  Can't assume that a width of 14 means chicago, so check
  771. ; explicitly.
  772.  
  773.             TST.W    ROM85                ; running on new roms?
  774.             BMI.S    @ChkCurFM            ; => no, then only check CurFMFamily
  775.             TST.W    SysFontFam            ; We ar on post-MacPlus so can check SysFontFamily
  776.             BNE.S    @NotChicago            ; If SysFontFam <> 0 then not Chicago
  777.                                         ; If on post-MacPlus then check CurFMFamily too.
  778. @ChkCurFM    TST.W    CurFMFamily            ; is CurFMFamily == 0 ?
  779.             BNE.S    @NotChicago            ; no, so not Chicago
  780.             SUBQ    #2,(A2)                ; yes its Chicago, so fudge width                    <1Aug85>
  781.  
  782. @NotChicago    ADDQ    #2,A2                ; skip over widmax                                    <1Aug85>
  783.             ADD.W    D0,(A2)                ; add leading, store total height in MFHeight(A6)    <1Aug85>
  784.  
  785.             SUBQ.L    #2, SP                ; Make room in stack                        <S550    27Jul88    EMT>
  786.             MOVE.W    #' ', -(SP)            ; ch = space                                <S550    27Jul88    EMT>
  787.             _CharWidth                    ; See how wide it is                        <S550    27Jul88    EMT>
  788.             MOVE.W    (SP)+, MSpaceWidth(A6)    ; Put it in our stack frame                <S550    27Jul88    EMT>
  789.  
  790.             RTS
  791.  
  792.  
  793. ;---------------------------------------
  794. ;    Utility -- GetIconSize
  795. ;---------------------------------------
  796. ; GetIconSize is a utility which returns the height and width of an icon.  The item pointer is in
  797. ; A1 and the result is returned in D1.  The height is in the high word.            <S550    27Jul88    EMT>
  798. GetIconSize
  799.             cmpi.b    #ScriptMenuCmd, itemCmd(a1)    ; is there a script defined?    <FJL CXXX>
  800.             beq.s    @noIcon                ; yes, icon field stores scriptID        <FJL CXXX>
  801.  
  802.             TST.B    ITEMICON(A1)        ; does it have an icon?                    <1Aug85>
  803.             BNE.S    @hasIcon            ; skip around if it does                <1Aug85>
  804. @noIcon
  805.             MOVEQ.L    #0, D1                ; No icon - return 0                    <S550    27Jul88    EMT>
  806.             RTS                            ; Go home                                <S550    27Jul88    EMT>
  807.  
  808. @hasIcon
  809.             tst.b    onColorMachine(a6)    ; If color, than check color icon        <S550    27Jul88    EMT>
  810.             beq.s    @noColor            ;                                        <S550    27Jul88    EMT>
  811.  
  812. ; Get the cicn resource because its faster than calling GetCIcon                <S550    27Jul88    EMT>
  813.             SUBQ.L    #4, SP                ; make room for function result            <S550    27Jul88    EMT>
  814.             MOVE.L    #'cicn',-(SP)        ; push the resource type                <S550    27Jul88    EMT>
  815.             MOVE.W    #$0100,D0            ; menu icons are 256-511                <S550    27Jul88    EMT>
  816.             MOVE.B    ITEMICON(A1),D0        ;                                         <S550    27Jul88    EMT>
  817.             MOVE.W    D0,-(SP)            ; push icon number                        <S550    27Jul88    EMT>
  818.             _GetResource                ; get handle to cicn resource            <S550    27Jul88    EMT>
  819.             MOVE.L    (SP)+, D1            ; get it in D1                            <S550    27Jul88    EMT>
  820.             BEQ.S    @noColor            ; no color icon, must be regular icon    <S550    27Jul88    EMT>
  821.  
  822.             MOVE.L    D1, -(SP)            ; Since we don't know what resLoad is    <S550    27Jul88    EMT>
  823.             _LoadResource                ; call LoadResource to be sure            <S550    27Jul88    EMT>
  824.             MOVE.L    D1, A0                ; get cicn resource handle in a0        <S550    27Jul88    EMT>
  825.             MOVE.L    (A0), A0            ; dereference, cicn begins with pixMap    <S550    27Jul88    EMT>
  826.             MOVE.L    pBounds+botRight(A0), D1    ; get bottom,right in D1        <S550    27Jul88    EMT>
  827.             SUB.L    pBounds+topLeft(a0), D1    ; height = bottom,right - top,left    <S550    27Jul88    EMT>
  828.             BRA.S    @testShrunk            ;                                        <S550    27Jul88    EMT>
  829.  
  830. @noColor                                ;                                        <S550    27Jul88    EMT>
  831.             MOVE.L    #$00200020, D1        ; Large b/w icons are 32 x 32            <S550    27Jul88    EMT>
  832.  
  833. @testShrunk                                ;                                        <S550    27Jul88    EMT>
  834.             cmpi.b    #ShrunkenIconCmd, itemCmd(A1)    ; is there a shrunken icon?    <FJL PMAB205>
  835.             beq.s    @0                    ; yes -> branch
  836.             cmpi.b    #SmallIconCmd, itemCmd(A1)    ; is there a small icon?        <FJL PMAB205>
  837.             bne.s    @1                    ; no    -> branch                        <S550    27Jul88    EMT>
  838. @0
  839.             LSR.L    #1, D1                ; Divide by 2 to get smaller size        <S550    27Jul88    EMT>
  840.             BCLR    #15, D1                ; Clear out because height could be odd    <S550    27Jul88    EMT>
  841.  
  842. @1
  843.             RTS
  844.  
  845.  
  846. ;---------------------------------------
  847. ;    Utility -- GetItemHeightA4                                                <FJL PMAB205>
  848. ;---------------------------------------
  849. ; GetItemHeight gets the height of the current menu item into D0.
  850. ; The item pointer is in A4.  Use GetItemHeight.
  851. GetItemHeightA4
  852.             MoveM.L    A1, -(SP)            ; save work register
  853.             Move.L    A4, A1                ; set up for call to GetItemHeight
  854.             Bsr.S    GetItemHeight
  855.             MoveM.L    (SP)+, A1            ; restore work register
  856.             Rts
  857.  
  858. ;---------------------------------------
  859. ;    Utility -- GetItemHeight
  860. ;---------------------------------------
  861. ; GetItemHeight gets the height of the current menu item into D0.
  862. ; The item pointer is in A1.  Width of icon (if any) is in the high word of D1.
  863.  
  864. GetItemHeight
  865.             BSR.S    GetIconSize            ; Returns height, width in D1            <S550    27Jul88    EMT>
  866.             SWAP    D1                    ; Get height in low word                <S550    27Jul88    EMT>
  867.  
  868.             MOVE.W    MFHeight(A6),D0        ; get menu item height                    <1Aug85>
  869.  
  870.             ADDQ.W    #4, D1                ; Add 4 for good measure                <S550    27Jul88    EMT>
  871.             CMP.W    D0, D1                ; Is height + 4 > MFHeight?                <S550    27Jul88    EMT>
  872.             BLT.S    @1                    ; Nope, skip around                        <S550    27Jul88    EMT>
  873.             MOVE.W    D1, D0                ; Yes, use height + 4 instead            <S550    27Jul88    EMT>
  874.  
  875. @1            RTS
  876.  
  877.  
  878. ;---------------------------------------
  879. ;    Utility -- EnableTest
  880. ;---------------------------------------
  881. ; EnableTest is a utility which tests if an item is enabled.  It expects a menuHandle
  882. ; in A3 and the item number in D4.  It returns the result in the Z-flag
  883.  
  884. ENABLETEST    MOVE.L    (A3),A0                ; get menu pointer
  885.             MOVE.L    MENUENABLE(A0),D0    ; get enable flags
  886.             CMPI.W    #31,D4                ; is item > 32                        <7Jan86><FJL C466>
  887.             BGT.S    @0                    ; => no enable/disable                <7Jan86><FJL C466>
  888.             BTST    D4,D0                ; is item enabled?
  889.             BEQ.S    ETDONE                ; if not, return 0
  890. @0            BTST    #0,D0                ; test menu bit
  891.             BEQ.S    ETDONE                ; if off, return 0                    <S550    27Jul88    EMT>
  892.             MOVE.W    D4, D0                ; Put item number in D0                <S550    27Jul88    EMT>
  893.             BSR        GetItemRecord        ; Go get it                            <S550    27Jul88    EMT>
  894.             BSR        IsDash                ; Is it a dash?                        <S550    27Jul88    EMT>
  895. ETDONE        RTS                            ; return to caller
  896.  
  897.  
  898. ;---------------------------------------
  899. ;    Utility -- InvertItem
  900. ;---------------------------------------
  901. ; InvertItem is an internal utility that hilites/unHilites an item.  The item number is
  902. ; passed in D0.  It also assumes A3 has the menuHandle.  If the high bit of D0
  903. ; is set, bit-clear with gray instead of inverting the item (used by DoDrawMsg routine).
  904.  
  905. INVERTITEM    MOVEM.L D3-D4,-(SP)            ; save work registers
  906.             MOVE    D0,D3                ; keep item number in safe place
  907.             BEQ        INVERTDONE            ; if zero, ignore
  908.             MOVE.W    TopMenuItem,D2        ; start at top of menu                <30Jan86>
  909.             MOVEQ    #1,D4                ; D4 hold item index                <27Sep85>
  910.  
  911. IILOOP        MOVE    D4,D0                ; get item
  912.             MOVE.L    (A3),A0                ; get menuPtr
  913.             BSR        GETITEMRECORD        ; look it up
  914.             beq        InvertDone            ; z-flag ==> can't find it            <FJL 22Mar87>
  915.             BSR.S    GetItemHeight        ; get item height into D0            <1Aug85>
  916.  
  917.             CMP.B    D3,D4                ; found the item we want yet?
  918.             BEQ.S    GOINVERT            ; if so, go invert it
  919.             ADD        D0,D2                ; add total to cumulative v position
  920.             ADDQ    #1,D4                ; bump to next position
  921.             BRA.S    IILOOP                ; loop till we find it
  922.  
  923. ; it's time to invert the item.  The menuRect contains the horizontal bounds, D2 contains
  924. ; the top of the vertical, D0 has the vertical size
  925.  
  926. GOINVERT    MOVE.B    1(A0),D1            ; remember 1st char of item
  927.             LEA        TEMPRECT,A0            ; get pointer to temporary rectangle
  928.             MOVE.L    MMENURECT(A6),A1    ; point to menuRect
  929.             MOVE.L    (A1)+,(A0)            ; copy menuRect into tempRect
  930.             MOVE.L    (A1),4(A0)
  931.             MOVE    D2,TOP(A0)            ; D2 has the top coordinate
  932.             ADD        D0,D2                ; add in the height
  933.             MOVE    D2,BOTTOM(A0)        ; set up the bottom
  934.  
  935. ;
  936. ; Instead of inverting the item's rectangle we redraw it.  If the invertFlag(a6)    <FJL C408>
  937. ; is set then SetColors will invert the colors properly for us.  If it isn't set    <FJL C408>
  938. ; then the item will just be redrawn in normal colors.                                <FJL C408>
  939. ;
  940.             movem.l    a2-a4/d3-d7, -(sp)    ; save same work registers as does DrawMsg
  941.  
  942.             move    #srcOr,    -(sp)
  943.             _TextMode                    ; set mode to srcOr
  944.  
  945. ; set up for call to DrawTheItem.  Before doing this, we must clip to the item's rectangle
  946. ; so that outline and shadowed text will not draw outside of the item rect.  But, because
  947. ; scrolling with icons can produce "parts of items", we must clip to the intersection of the
  948. ; menu rect and the item rect.  AND we must clip to screen in case menu draws past screen bounds.
  949.  
  950.             subq    #4, sp                ; space for result
  951.             _NewRgn
  952.             move.l    (sp), -(sp)            ; make copy of region so can delete later
  953.             _GetClip
  954.  
  955.             subq    #2, sp                ; space for boolean result
  956.             move.l    MMenuRect(a6), -(sp); push menurect address
  957.             pea        TempRect            ; push itemrect address
  958.             pea        HierArrowRect(a6)    ; push dest rect (reuse stackframe variable)
  959.             _SectRect
  960.             addq    #2, sp                ; ignore result
  961.  
  962.             subq    #4, sp                ; get current portRect
  963.             move.l    sp, -(sp)            ; make space on stack for return
  964.             _GetPort
  965.             move.l    (sp)+, a0            ; get port
  966.  
  967.             subq    #2, sp                ; space for boolean result
  968.             pea        portRect(a0)        ; push portRect address
  969.             pea        HierArrowRect(a6)    ; push clip rect address
  970.             pea        HierArrowRect(a6)    ; push dest address
  971.             _SectRect
  972.             addq    #2, sp                ; ignore result
  973.             pea        HierArrowRect(a6)    ; push clip rect
  974.             _ClipRect
  975.  
  976.             tst        scrollFlag(a6)        ; being called from scroll routine?
  977.             bne.s    @DoRedraw            ; yes, so do the drawing
  978.  
  979. ; On MacPlus and MacSE do InvertRect instead of redrawing when choosing an item.    <FJL 17Mar87>
  980. ; Do this because MacDraw's custom "line" menu does not handle "choose item" message properly.
  981. ; Of course it's not as easy as that since we use the Choose message as a way to clean up
  982. ; the garbage left over when a hierarchical menu is brought down, and this assumes that
  983. ; the item is redrawn, NOT inverted.  If this is the case then HItemFlag will be set.
  984.  
  985.             tst        onColorMachine(a6)    ; on MacII ?
  986.             bne.s    @DoRedraw            ; yes ==> always redraw
  987.  
  988.             tst        HItemFlag(a6)        ; does item have submenu?
  989.             bne.s    @DoRedraw            ; yes ==> then redraw to eliminate garbage beneath submenu
  990.  
  991.             pea        TempRect            ; push ptr to item's rectangle
  992.             _InverRect                    ; invert it
  993.             bra.s    @RedrawDone            ; and leave
  994.  
  995. @DoRedraw
  996. ; erase the rect to the proper background color
  997.             bsr        SaveCurrentColors    ; save current colors in stack frame            <FJL C408>
  998.             move    #mctRGB2, colorOffset(a6)    ; this offset is unimportant here        <FJL C408>
  999.                                                 ; since all we care about is bkgd color    <FJL C408>
  1000.             bsr        SetColors            ; set proper colors    for EraseRect                <FJL C408>
  1001.  
  1002.             pea        TempRect            ; push a pointer to the rectangle
  1003.             _EraseRect                    ; erase it
  1004.  
  1005.             bsr        ResetPreviousColors ; reset colors after EraseRect
  1006.  
  1007. ; and draw the item
  1008.             lea        TempRect, a0        ; get address of item's rectangle
  1009.             move    Top(a0), d3            ; get top
  1010.             add        MAscent(a6),d3        ; add in the ascent for baseline
  1011. ;            move    Left(a0), d5        ; move left edge into d5                    <S550    27Jul88    EMT>
  1012. ;            move    Right(a0), d6        ; move right edge into d6                    <S550    27Jul88    EMT>
  1013. ;                                                                                    <S550    27Jul88    EMT>
  1014. ;            move    d4,d0                ; get item                                    <S550    27Jul88    EMT>
  1015. ;            move.l    (a3),a0                ; get menuPtr                                <S550    27Jul88    EMT>
  1016. ;            bsr        GetItemRecord        ; look it up                                <S550    27Jul88    EMT>
  1017. ;            move.l    a0,a2                ; keep string pointer in A2                    <S550    27Jul88    EMT>
  1018. ;            move.l    a1,a4                ; keep properties in A4                        <S550    27Jul88    EMT>
  1019.  
  1020.             bsr        DrawTheItem            ; call drawing routine (it calls ResetPreviousColors)
  1021.  
  1022. @RedrawDone    move.l    (sp), -(sp)            ; reset clip to region it was before drawing item
  1023.             _SetClip
  1024.             _DisposRgn
  1025.  
  1026.             movem.l    (sp)+, a2-a4/d3-d7    ; restore work registers
  1027.  
  1028. INVERTDONE    MOVEM.L (SP)+,D3-D4            ; recover work regs
  1029.             RTS
  1030.  
  1031. ;---------------------------------------
  1032. ;    Utility -- GrayRect
  1033. ;---------------------------------------
  1034. ;    GrayRect is a utility that bit-clears the current "tempRect" with gray
  1035. ;
  1036. ; We assume that this routine is only called by Draw msg, that SaveCurrentColors    <FJL C408>
  1037. ; has been called already, and that ResetPreviousColors will be called after this.    <FJL C408>
  1038.  
  1039. GRAYRECT
  1040.             MOVE.L    A0,-(SP)            ; push rect address
  1041.             MOVE.L    (A5),A0                ; get QuickDraw globals
  1042.             PEA        Gray(A0)            ; push gray
  1043.             _PenPat                        ; set pen to it
  1044.             MOVE    #PatBIC,-(SP)        ; push patBIC penMode
  1045.             _PenMode                    ; set penMode
  1046.             move    #mctRGB2, colorOffset(a6)    ; use text color for fore color    <FJL C408>
  1047.             bsr        SetColors            ; set colors for bit clear                <FJL C408>
  1048.  
  1049.             _PaintRect                    ; "OR" on the dim pattern
  1050.  
  1051.             _PenNormal
  1052.  
  1053.             RTS
  1054. ;---------------------------------------
  1055. ;    Utility -- TweakPos
  1056. ;---------------------------------------
  1057. ; TweakPos is passed an element size in D0.  It gets a horizontal offset into
  1058. ; D2 depending on whether things are right justified or not.  It also adjusts
  1059. ; D5 and D6 (the left and right positions).
  1060.  
  1061. TweakPos
  1062.             MOVE    D5,D2                ; assume left to right                    <27Sep85>
  1063. ;            ADDQ    #2,D2                ; and indent element a little            <27Sep85>    <S550    27Jul88    EMT>
  1064.             ADD.W    D0,D5                ; assume bump past icon                    <27Sep85>
  1065.             TST.B    TESysJust+1            ; check for right just                    <11oct85>
  1066.             BPL.S    @1                    ; => guessed right                        <27Sep85>
  1067.             SUB.W    D0,D6                ; else back up for icon                    <27Sep85>
  1068.             SUB.W    D0,D5                ; and fix up left                        <27Sep85>
  1069.             MOVE.W    D6,D2                ; and set position                        <27Sep85>
  1070. @1            RTS
  1071.  
  1072. ;---------------------------------------
  1073. ;    Utility -- DrawScrolledItem                                                    <FJL C838>
  1074. ;---------------------------------------
  1075. ; DrawScrolledItem is a faster way to draw the item that appears after a menu is scrolled.
  1076. ; The old method was to redraw the whole menu, and because clipping was set to just
  1077. ; the item that appeared no flashing occured.  The problem is that with the new features,
  1078. ; most noticeably color and hierarchical menus, scrolling can be fairly slow.  Actually this
  1079. ; method turns out to speed up scrolling by a factor of 2-3!!
  1080. ;
  1081. DrawScrolledItem
  1082.  
  1083.             MOVE.W    D4,D2                ; top of menu into D2
  1084.             MOVEQ    #1, D4                ; start with first item
  1085.  
  1086.             TST        D7
  1087.             BGE.S    @ScrollingDown        ; if D7 >= 0 then scrolling down not up
  1088. @ScrollingUp
  1089.             MOVE    Bottom(a2), D3        ; fake mouse pt to be just above bottom of menu
  1090.             SUBQ    #1, D3                ; one pixel above menu bottom, or down scroll arrow
  1091.             BRA.S    @Loop
  1092.  
  1093. @ScrollingDown
  1094.             MOVE    Top(a2), D3            ; fake mouse pt to be just below top of menu
  1095.             ADDQ    #1, D3                ; one pixel below menu top, or up scroll arrow
  1096.  
  1097.  
  1098. @Loop        MOVE.L    (A3),A0                ; get menuPtr
  1099.             MOVE    D4,D0                ; get item number
  1100.             BSR        GetItemRecord        ; look it up
  1101.             BEQ.S    @LastItemSel        ; if none then must be last item
  1102.  
  1103.             BSR        GetItemHeight        ; get item height in D0
  1104.             ADD        D0,D2                ; update vertical
  1105.             CMP        D3,D2                ; compare with mouse point
  1106.             BGT.S    @GotSel                ; when D2 is bigger, we found it
  1107. ;
  1108. ; we didn't reach it yet, so keep stepping down till we do
  1109. ;
  1110.             ADDQ    #1,D4                ; bump to next item
  1111.             BRA.S    @Loop                ; loop till we find it
  1112. ;
  1113. ; we found it so draw the item
  1114. ;
  1115. @LastItemSel
  1116.             SUBQ    #1, D4                ; back up one item
  1117.  
  1118. @GotSel        MOVE    D4, D0                ; InvertItem wants item number in D0
  1119.             MOVE    #1, scrollFlag(a6)    ; set flag for InvertItem                    <FJL 17Mar87>
  1120.             BSR        InvertItem            ; InvertItem will draw the item
  1121.  
  1122. ; Because of fucking icons, there could be just part of the scrolled item showing, so if
  1123. ; we are scrolling up then redraw the item above too, or if scrolling down then redraw the
  1124. ; item below.
  1125.  
  1126.             TST        D7
  1127.             BGE.S    @ScrollingDown2        ; if D7 >= 0 then scrolling down not up
  1128. @ScrollingUp2
  1129.             SUBQ    #1, D4                ; draw item above this one
  1130.             MOVE    D4, D0
  1131.             BSR        InvertItem
  1132.             BRA.S    @NoItemSel
  1133.  
  1134. @ScrollingDown2
  1135.             ADDQ    #1, D4                ; draw item below this one
  1136.             MOVE    D4, D0
  1137.             BSR        InvertItem
  1138.  
  1139. @NoItemSel    CLR        scrollFlag(a6)        ; clear flag after InvertItem call            <FJL 17Mar87>
  1140.             rts
  1141.  
  1142.  
  1143. ;----------------------------------------------------------------------------------------
  1144. ;
  1145. ;    Msg #0 -- Draw Menu -- bits behind have been saved, menu structure has been drawn,
  1146. ;                            and menu rectangle is cleared to proper color (all by mbarproc)
  1147. ;
  1148. ;----------------------------------------------------------------------------------------
  1149. ;
  1150. ; here is the part of the TextMenuProc that draws the menu.  For most of this routine,
  1151. ; A3 holds the menuHandle, D4 is the item counter and D3 holds the cumulative
  1152. ; vertical position.  DrawMenu is broken off for use in scrolling.
  1153. ;
  1154. ; To clear up a very tricky scrolling menu bug, we need to NOT SCROLL when a hierarchical menu
  1155. ; is up in the last item (i.e. topmost or bottommost).  If we don't bring the HMenu down first
  1156. ; a little bit of garbage is left on the screen.  We clear the field mbUglyScroll each
  1157. ; time a menu is drawn, then set it when the first time into the scrolling routine.  Thereafter
  1158. ; we check it and realize that the HMenu is already down, so it's ok to scroll.
  1159. ;
  1160. ; Changed so that caller sets global TopMenuItem so that can be forced to draw from <FJL C844>
  1161.  
  1162. DoDrawMsg
  1163.             bsr        GetSizes            ; get font info into stackframe
  1164.  
  1165.             MOVE.L    MMenuRect(A6),A0    ; get menu rect pointer                        <30Jan86>
  1166.             clr        atMenuBottom        ; clear bottom memory                        <FJL C222>
  1167.  
  1168. ;>>>>>------------- MacPlus/MacSE patches ------------------>>>>>
  1169.  
  1170.         IF forRAM THEN
  1171.  
  1172.             cmp.w        #$FFFF, ROM85            ; on old Mac or MacXL?
  1173.             beq.s        @SetTMI                    ; yes -> skip HMenu specific stuff
  1174.  
  1175.                                                 ; RADIUS patches out complete menu mgr ==> could
  1176.                                                 ; have GetItemCmd installed, but mbSaveLoc
  1177.                                                 ; not initialized.
  1178.             cmpi.l        #$FFFFFFFF, mbSaveLoc    ; has the MBDF data structure been initialized?
  1179.             beq.s        @SetTMI
  1180.  
  1181.             move.w        #$009F, d0                ; load _Unimplemented number
  1182.             _GetTrapAddress                        ; load _Unimplemented address
  1183.             move.l        a0, d1                    ; copy routine address
  1184.             move.w        #$004E, d0                ; load _GetItemCmd number
  1185.             _GetTrapAddress    ,newTool            ; load _GetItemCmd address
  1186.             cmp.l        a0, d1                    ; new HMenu Mgr installed?
  1187.             bne.s        @ScrollClrOK            ; yes -> MenuSelect sets TopMenuItem properly
  1188.  
  1189. @SetTMI        MOVE.L        MMenuRect(A6),A0        ; get menu rect pointer                    <30Jan86>
  1190.             MOVE.W        top(A0),topMenuItem        ; no    -> say to draw from top            <30Jan86>
  1191.             bra.s        @SkipScrollClr            ; and skip HMenu specific stuff
  1192. @ScrollClrOK
  1193.         ENDIF    ; if forRAM
  1194.  
  1195. ;<<<<<--------------------------------------<<<<<
  1196.             move.l    mbSaveLoc, a0        ; clear mbUglyScroll every time draw a menu    <FJL C792>
  1197.             move.l    (a0), a0
  1198.             clr        mbUglyScroll(a0)
  1199.  
  1200. @SkipScrollClr
  1201.             bsr.s    DrawMenu            ; call draw menu
  1202.             bsr.s    ChkScrollIndic        ; draw scrolling indicator (if necessary) <FJL C792>
  1203.             rts
  1204.  
  1205. ;---------------------------------------
  1206. ;    Utility -- DrawMenu
  1207. ;---------------------------------------
  1208.  
  1209. DRAWMENU    MOVEM.L a2-A4/D3-D7,-(SP)    ; save some regs                        <27Sep85>
  1210.             MOVEQ    #1,D4                ; start with first item
  1211.             MOVE.W    topMenuItem,D3        ; and point to top of first item
  1212.             ADD.W    MAscent(A6),D3        ; add in the ascent for baseline
  1213.  
  1214. ; apps that screw around with the wmgrport textfont and textface unwittingly, have    <FJL CXXX>
  1215. ; menu items show up in the wrong font/face/etc....
  1216.  
  1217.             CLR.L    -(SP)                ; push empty set for TextFace and TextFont
  1218.             _TextFace                    ; change textface to normal
  1219.             _TextFont                    ; change textfont to normal
  1220.  
  1221.             move    #srcOr, -(sp)        ; set text mode to srcOr                    <FJL C408>
  1222.             _TextMode                    ;                                            <FJL C408>
  1223.  
  1224. DRAW1MLOOP    MOVE.L    MMENURECT(A6),A0    ; get menuRect pointer                        <27Sep85>
  1225. ;            MOVE.L    (A0)+,D5            ; get left edge                                <27Sep85>    <S550    27Jul88    EMT>
  1226. ;            MOVE.L    (A0),D6                ; get right edge, too                        <27Sep85>    <S550    27Jul88    EMT>
  1227. ;                                                                                                <S550    27Jul88    EMT>
  1228. ;            MOVE    D4,D0                ; get item number in D0                                    <S550    27Jul88    EMT>
  1229. ;            MOVE.L    (A3),A0                ; get menu pointer                                        <S550    27Jul88    EMT>
  1230. ;            BSR        GETITEMRECORD        ; look it up                                            <S550    27Jul88    EMT>
  1231. ;                                                                                                <S550    27Jul88    EMT>
  1232. ;            MOVE.L    A0,A2                ; keep string pointer in A2                                <S550    27Jul88    EMT>
  1233. ;            MOVE.L    A1,A4                ; keep properties in A4                                    <S550    27Jul88    EMT>
  1234.             bsr        DrawTheItem            ; call drawing routine
  1235.             BEQ.S    DONEDRAW            ; if null item, EXIT W/atBottom TRUE        <27Sep85>    <S550    27Jul88    EMT>
  1236.  
  1237. ;
  1238. ; we're done with this item so bump to the next one
  1239. ;
  1240.             cmpi.b    #ScriptMenuCmd, itemCmd(a4)    ; is there a script defined?        <FJL CXXX>
  1241.             beq.s    @1                    ; yes, icon field stores scriptID            <FJL CXXX>
  1242.  
  1243.             TST.B    ITEMICON(A4)        ; does it have an icon?
  1244.             BEQ.S    @1                    ; skip if it doesnt
  1245.             MOVE.W    D7,D0                ; get delta height
  1246.             LSR.W    #1,D0                ; divide by 2
  1247.             SUB.W    D0,D7                ; and get remainder
  1248.             ADD        D7,D3                ; bump the rest of the difference for icon
  1249.  
  1250. @1            ADD        MFHeight(A6),D3        ; bump to next baseline
  1251.             ADDQ    #1,D4                ; bump to next item
  1252.             BRA.s    DRAW1MLOOP            ; loop till done
  1253.  
  1254. ; When we return to DoneDraw, D3 points to the baseline of the cell that would follow the
  1255. ; last cell.  Back up to the bottom of the last cell and save as menubottom.
  1256.  
  1257. DONEDRAW    SUB.W    MAscent(A6),D3        ; back up to "top of cell"                    <30Jan86>
  1258.             MOVE.W    D3,AtMenuBottom        ; update bottom                                <30Jan86>
  1259.             MOVEM.L (SP)+,a2-A4/D3-D7    ; restore some regs                            <27Sep85>
  1260.             RTS
  1261.  
  1262.  
  1263.  
  1264. ;---------------------------------------
  1265. ;    Utility -- ChkScrollIndic                                                        <FJL C792>
  1266. ;---------------------------------------
  1267. ; Blit up the scrolling down arrow if we need to
  1268. ;
  1269. ChkScrollIndic
  1270.             move.l    MMenuRect(a6), a0        ; get menu rect ptr
  1271.             move    AtMenuBottom, d0        ; get AtMenuBottom
  1272.             cmp        Bottom(a0), d0            ; is AtMenuBottom > bottom of MenuRect
  1273.             ble.s    @CkUpIndic                ; no ==> don't need down arrow, see if need up arrow
  1274.             bsr.s    BlitDownScrollIndic        ; yes ==> blit the down arrow
  1275.  
  1276. @CkUpIndic    move.l    MMenuRect(a6), a0        ; get menu rect ptr                        <FJL C844>
  1277.             move    TopMenuItem, d0            ; get TopMenuItem
  1278.             cmp        Top(a0), d0                ; is TopMenuItem < top of MenuRect
  1279.             bge.s    @DoneChk                ; no ==> don't need up arrow
  1280.             bsr.s    BlitUpscrollIndic        ; yes ==> blit the up arrow
  1281. @DoneChk    rts
  1282.  
  1283. ;---------------------------------------
  1284. ;    Utility -- BlitDownScrollIndic / BlitUpScrollIndic                                                    <FJL C792>
  1285. ;---------------------------------------
  1286. ; Blit up the scrolling arrows
  1287. ;
  1288. BlitDownScrollIndic
  1289.             movem.l    a3-a4/d4, -(sp)            ; store work registers
  1290.  
  1291. ; calculate where bottom of menu is
  1292.             move    Bottom(a0), HierArrowRect+Bottom(a6)    ; store bottom
  1293.             move    Bottom(a0), HierArrowRect+Top(a6)        ; top = bottom - MFHeight
  1294.             move    MFHeight(a6), d0
  1295.             sub        d0, HierArrowRect+Top(a6)
  1296.             move    Left(a0), HierArrowRect+Left(a6)        ; store left
  1297.             move    Right(a0), HierArrowRect+Right(a6)        ; store right
  1298.             lea        DownArrow, a4            ; store arrow address in a4 for DoTheBlit
  1299.             bra.s    DoTheBlit
  1300.  
  1301. BlitUpScrollIndic
  1302.             movem.l    a3-a4/d4, -(sp)            ; store work registers
  1303.  
  1304. ; calculate where top of menu is
  1305.             move    Top(a0), HierArrowRect+Top(a6)            ; store top
  1306.             move    Top(a0), HierArrowRect+Bottom(a6)        ; bottom = top + MFHeight
  1307.             move    MFHeight(a6), d0
  1308.             add        d0, HierArrowRect+Bottom(a6)
  1309.             move    Left(a0), HierArrowRect+Left(a6)        ; store left
  1310.             move    Right(a0), HierArrowRect+Right(a6)        ; store right
  1311.             lea        UpArrow, a4            ; store arrow address in a4 for DoTheBlit
  1312.                                         ; and drop into DoTheBlit
  1313.  
  1314. DoTheBlit
  1315.             bsr        SaveCurrentColors        ; save current colors in stack frame
  1316.             move    #-1, d4                    ; force SetColors to get the title color
  1317.                                             ;    entry not an item entry
  1318.             move    #mctRGB2, colorOffset(a6)    ; set fore/back colors for this item
  1319.             bsr        SetColors                ; set proper colors for blit
  1320.  
  1321. ; erase rect now that the fore/back colors are set properly
  1322.             pea        HierArrowRect(a6)
  1323.             _EraseRect
  1324.  
  1325. ; create bitMap for arrow
  1326.             moveq    #bitMapRec, d0            ; alloc bitmap for 16Vert x 16Horiz x 1Deep bit map
  1327.             _NewHandle
  1328.             _HLock
  1329.             move.l    (a0), a3                ; dereference
  1330.             move    #2, rowBytes(a3)        ; 16 x 1 bits wide
  1331.             move.l    #$00000000,bounds(a3)    ; top = 0, left = 0
  1332.             move.l    #$00100010,bounds+4(a3)    ; bottom = $10, right = $10
  1333.             move.l    a4, baseAddr(a3)        ; store correct arrow bitmap in baseAddr
  1334.  
  1335. ; set arrow rect
  1336. ;+++;    left = left + MWidMax
  1337. ;+++;    right = newleft + MWidMax + 4
  1338. ;+++            move    MWidMax(a6), d0
  1339. ;+++            add        d0, HierArrowRect+Left(a6)
  1340. ;+++            move    HierArrowRect+Left(a6), HierArrowRect+Right(a6)
  1341. ;+++            add        #4, d0
  1342. ;+++            add        d0, HierArrowRect+Right(a6)
  1343.  
  1344. ; left = MenuRect.left + MWidMax                                    <FJL PMAB205>
  1345. ; right = left + min(16,MFHeight(A6))
  1346. ; bottom = top + min(16,MFHeight(A6))
  1347.             move    MWidMax(A6), d0
  1348.             add        HierArrowRect+Left(A6), d0
  1349.             move    d0, HierArrowRect+Left(A6)
  1350.             move    d0, HierArrowRect+Right(A6)
  1351.             moveq    #16, d0
  1352.             cmp.w    MFHeight(A6), d0
  1353.             bge.s    @1
  1354.             move    MFHeight(A6), d0
  1355. @1            add        d0, HierArrowRect+Right(A6)
  1356.             move    HierArrowRect+Top(A6), HierArrowRect+Bottom(A6)
  1357.             add        d0, HierArrowRect+Bottom(A6)
  1358.  
  1359. ; get current portRect
  1360.             subq    #4, sp
  1361.             move.l    sp, -(sp)                ; make space on stack for return
  1362.             _GetPort
  1363.             move.l    (sp)+, a0                ; get port
  1364.  
  1365. ; copy from the bitMap into the port
  1366.             move.l    a3, -(sp)                ; push src bitMap ptr
  1367.             pea        portBits(a0)            ; push dest pointer (for the screen)
  1368.             pea        bounds(a3)                ; push src bounds rect
  1369.             pea        HierArrowRect(a6)        ; push dest bounds rect
  1370.             move    #srcOr, -(sp)            ; srcOr
  1371.             clr.l    -(sp)                    ; no maskRgn
  1372.             _CopyBits
  1373.  
  1374.             move.l    a3, a0                    ; get bitMap ptr
  1375.             _RecoverHandle                    ; get bitMap handle
  1376.             _DisposHandle                    ; and toss it
  1377.             movem.l    (sp)+, a3-a4/d4            ; restore work registers
  1378.  
  1379.             bsr        ResetPreviousColors        ; reset colors stored in stackframe
  1380.  
  1381.             rts
  1382.             
  1383. ;---------------------------------------
  1384. ;    Utility -- IsDash
  1385. ;---------------------------------------
  1386. ; IsDash is a utility which tests if an item is the special dash separator.
  1387. ; It returns the result in the Z-flag                                                <S550    27Jul88    EMT>
  1388. IsDash
  1389.             CMP.B    #$2D,1(A0)            ; first char a dash?
  1390.             BNE.S    @NoDash                ; No dash, skip.
  1391.             TST.B    itemIcon(A1)        ; Does it have an icon?
  1392.             BNE.S    @NoDash                ; No dash, skip.
  1393.             TST.B    itemCmd(A1)            ; Does it have a cmd?
  1394. @NoDash
  1395.             RTS                            ; Return result in Z
  1396.  
  1397. ;----------------------------------------
  1398. ;    Utility -- DrawTheItem
  1399. ;----------------------------------------
  1400. ; separated actual drawing routine out so
  1401. ; can ChooseMsg can call it since we now
  1402. ; redraw the selected item rather than
  1403. ; just inverting it.
  1404. ;
  1405. ; Used to be:                                                                        <S550    27Jul88    EMT>
  1406. ; On entry:        d3        Item's baseline, top of item + font's ascent
  1407. ;                d4        Item Number
  1408. ;                d5        left edge, pixels
  1409. ;                d6        right edge, pixels
  1410. ;                a2        item's string pointer
  1411. ;                a4        item's properties pointer
  1412. ;                --        GetSizes has been called
  1413. ;
  1414. ; Now:                                                                                <S550    27Jul88    EMT>
  1415. ; On entry:        D3        Item's baseline, top of item + font's ascent
  1416. ;                D4        Item Number
  1417. ;                A0        Menu rectangle pointer (for left and right edge)
  1418. ;                A3        Menu handle
  1419. ;                --        GetSizes has been called
  1420. ;                --        GetItemRecord has been called
  1421. ;                --        D5, D6, A2, and A4 are all set up just like old times
  1422. ;
  1423. ; On exit:        Z        Set if the item does not exist
  1424. ;
  1425. DrawTheItem
  1426.             MOVE.W    Left(A0), D5        ; Get the left edge                            <S550    27Jul88    EMT>
  1427.             MOVE.W    Right(A0), D6        ; Get the right edge                        <S550    27Jul88    EMT>
  1428.  
  1429.             MOVE.W    D4, D0                ; Prepare item number for GetItemRecord        <S550    27Jul88    EMT>
  1430.             MOVE.L    (A3), A0            ; Dereference menu handle                    <S550    27Jul88    EMT>
  1431.             BSR        GetItemRecord        ; Go get it                                    <S550    27Jul88    EMT>
  1432.             BEQ        NoDrawItem            ; Skip whole mess if not a valid item        <S550    27Jul88    EMT>
  1433.             MOVE.L    A0, A2                ; Store string pointer in A2                <S550    27Jul88    EMT>
  1434.             MOVE.L    A1, A4                ; And properties in A4                        <S550    27Jul88    EMT>
  1435.  
  1436.             bsr        SaveCurrentColors    ; save fore/back colors in stackframe        <FJL C408>
  1437.  
  1438.             MOVE.L    A2, A0                ; Get string pointer for IsDash                <S550    27Jul88    EMT>
  1439.             MOVE.L    A4, A1                ; And properties too                        <S550    27Jul88    EMT>
  1440.             BSR.S    IsDash                ; Is it a dash?                                <S550    27Jul88    EMT>
  1441.             BNE.S    NotDash                ; If not, draw item normally                <S550    27Jul88    EMT>
  1442.  
  1443. ;---------------------------------------
  1444. ;    Utility -- DrawDash
  1445. ;---------------------------------------
  1446. ; handle the case of a dash item by drawing a line
  1447. DrawDash
  1448.             move    #mctRGB2, colorOffset(a6) ; use the item color if there is an entry <FJL C408>
  1449.             bsr        SetColors            ; set colors                                    <FJL C408>
  1450.  
  1451.             MOVE.L    (A5),A0                ; get QuickDraw globals
  1452.             PEA        Gray(A0)            ; set pattern to gray
  1453.             _PenPat
  1454.  
  1455.             MOVE.W    D3,-(SP)            ; save y position
  1456.             MOVE.W    D5,-(SP)            ; push x position
  1457.             MOVE.W    MFHeight(A6),D0    ; center the dash
  1458.             LSR.W    #1,D0                ; by backing up to top of cell
  1459.             SUB.W    MAscent(A6),D0        ; and going halfway down
  1460.             ADD.W    D0,D3                ; add to current position
  1461.             MOVE.W    D3,-(SP)            ; push new y position
  1462.             _MoveTo
  1463.  
  1464.             MOVE.W    D6,-(SP)            ; push    right edge
  1465.             MOVE    D3,-(SP)            ; push    y
  1466.             _LineTo                        ; draw    the line
  1467.             MOVE.W    (SP)+,D3            ; restore baseline
  1468.  
  1469.             _PenNormal                    ; pen back to normal
  1470.             BRA        DoneDrawItem        ; dive    back into mainstream
  1471.  
  1472. NotDash
  1473.             ADDQ.W    #2, D5                ; Add the 2 pixels here instead                <S550    27Jul88    EMT>
  1474.             cmpi.b    #ScriptMenuCmd, itemCmd(a4)    ; is there a script defined?        <FJL CXXX>
  1475.             beq.s    DrawMark            ; yes, icon field stores scriptID            <FJL CXXX>
  1476.  
  1477.             MOVE.B    ITEMICON(A4),D0        ; does it have an icon?
  1478.             BEQ.S    DrawMark            ; if not, skip
  1479.  
  1480. ; for icon, center the baseline in the item's rect
  1481.  
  1482.             Bsr        GetItemHeightA4        ; get item's height in D0
  1483.             SUB.W    MFHeight(A6),D0        ; subtract font height                        <1Aug85>
  1484.             MOVE.W    D0,D7                ; save font height in D7                    <1Aug85>
  1485.             LSR.W    #1,D0                ; get delta                                    <1Aug85>
  1486.             ADD.W    D0,D3                ; keep baseline in D3                        <1Aug85>
  1487.  
  1488. ; ---------------------    draw the mark    --------------------------
  1489.  
  1490. DrawMark    MOVE.W    MWidMax(A6),D0        ; get char width                            <27Sep85>
  1491.             BSR        TweakPos            ; get hpos into D2, adjust d5,d6            <27Sep85>
  1492.  
  1493. ;            When itemCmd == HMenuCmd ($1B) the itemMark field is used to store        <FJL C222>
  1494. ;            the hierarchical menu number so don't draw a mark by mistake.            <FJL C222>
  1495.  
  1496.             cmpi.b    #HMenuCmd, itemCmd(a4)    ; hierarchical menu for this item?        <FJL C222>
  1497.             beq.s    ChkDrawIcon
  1498.  
  1499.             TST.B    ITEMMARK(A4)        ; does it have a mark?
  1500.             BEQ.S    CHKDRAWICON            ; if not, skip
  1501.  
  1502.             MOVE.W    D2,-(SP)            ;
  1503.             MOVE    D3,-(SP)            ; push v position
  1504.             _MoveTo                        ; position pen
  1505.  
  1506.             move    #mctRGB1, colorOffset(a6) ; tell SetColors to get the MARK        <FJL C408>
  1507.             bsr        SetColors            ; set mark colors                            <FJL C408>
  1508.  
  1509.             CLR    D0                        ; clear out high part
  1510.             MOVE.B    ITEMMARK(A4),D0        ; get the mark character
  1511.             MOVE.W    D0,-(SP)            ; push it
  1512.             _DrawChar
  1513.  
  1514.  
  1515. ; ---------------------    draw the icon    --------------------------
  1516.  
  1517. CHKDRAWICON
  1518. ;            when itemCmd == ScriptMenuCmd ($1C) the itemIcon field is used to        <FJL CXXX>
  1519. ;            store the script ID number, so don't draw an icon by mistake.            <FJL CXXX>
  1520.  
  1521. ;            when itemCmd == ShrunkenIconCmd ($1D) we draw the icon into a 16x16        <FJL PMAB205>
  1522. ;            area instead of the normal 32x32
  1523.  
  1524. ;            when itemCmd == SmallIconCmd ($1E) we draw a small icon into a 16x16    <FJL PMAB205>
  1525. ;            area
  1526.  
  1527. ;            cmpi.b    #ScriptMenuCmd, itemCmd(a4)    ; script for this item?                <FJL CXXX>
  1528. ;            beq        DrawCmdChar
  1529. ;
  1530. ;            TST.B    ITEMICON(A4)        ; does it have an icon?                        <15Oct85>
  1531.  
  1532.             MOVE.L    A4, A1                ; Copy A4 into A1 for GetIconSize            <S550    27Jul88    EMT>
  1533.             BSR        GetIconSize            ; Get the height, width of the icon            <S550    27Jul88    EMT>
  1534.             TST.L    D1                    ; Is there one?                                <S550    27Jul88    EMT>
  1535.             BEQ        DrawCmdChar            ; if not, skip
  1536. ;
  1537. ; get horizontal position into D2
  1538. ;
  1539. ;            MOVEQ    #40,D0                ; get field size (width) for large icon        <27Sep85>
  1540. ;
  1541. ;            Cmpi.b    #ShrunkenIconCmd, itemCmd(A4)    ;is this a shrunken icon ?        <FJL PMAB205>
  1542. ;            Beq.s    @SmallDst            ; yes    -> branch                            <FJL PMAB205>
  1543. ;            Cmpi.b    #SmallIconCmd, itemCmd(A4)        ;is this a small icon ?
  1544. ;            Bne.s    @DoTweak            ; no    -> branch
  1545. ;@SmallDst    Bsr        GetItemHeightA4        ; get item height for small icons into D0
  1546. ;@DoTweak    BSR        TweakPos            ; get hpos into D2, adjust D5,D6            <27Sep85>
  1547.  
  1548. ; draw the icon.  First back up to top of rect
  1549.  
  1550.             LEA        TEMPRECT,A0            ; get pointer to rectangle
  1551.             MOVE.L    A0,-(SP)            ; push rect for plotIcon call
  1552.  
  1553.             MOVE.L    D1, -(SP)            ; Save height, width on stack                <S550    27Jul88    EMT>
  1554.             MOVE.W    D3,D1                ; get baseline                                <1Aug85>
  1555.             MOVE.W    D7,D0                ; font height from D7                        <15Oct85>
  1556.             LSR.W    #1,D0                ; get delta                                    <15Oct85>
  1557.             SUB.W    D0,D1                ; subtract delta                            <15Oct85>
  1558.             SUB.W    MAscent(A6),D1        ; subtract font height                        <15Oct85>
  1559.             ADDQ.W    #2,D1                ; down from top of item                        <15Oct85>
  1560.             MOVE.L    (SP)+, D0            ; Restore it into D0 instead                <S550    27Jul88    EMT>
  1561.  
  1562. ;            cmpi.b    #ShrunkenIconCmd, itemCmd(A4); is this a shrunken icon ?        <FJL PMAB205>
  1563. ;            beq.s    @SetupSmallDstIcon            ; yes -> branch                        <FJL PMAB205>
  1564. ;            cmpi.b    #SmallIconCmd, itemCmd(A4)    ; is this a smallicon ?
  1565. ;            bne.s    @SetupRegularIcon
  1566. ;
  1567. ;@SetupSmallDstIcon
  1568. ;            move    D1, (A0)+            ; and stuff top
  1569. ;            move    D2, (A0)            ; push left
  1570. ;            subq.w    #3, (A0)+            ; fudge to line up small icon on the left
  1571. ;            move.l    -4(A0),(A0)            ; copy bottom/right
  1572. ;            add        #16, (A0)+            ; bottom := top + 16
  1573. ;            add        #16, (A0)            ; right := left + 16
  1574. ;            bra.s    @DoneSetup
  1575. ;
  1576. ;
  1577. ;@SetupRegularIcon
  1578.             MOVE.W    D1,(A0)+            ; and stuff top                            <1Aug85>
  1579.             MOVE.W    D5, D2                ; Assume left-to-right                    <S550    27Jul88    EMT>
  1580.             TST.B    TESysJust+1            ; Test for right just                    <S550    27Jul88    EMT>
  1581.             BPL.S    @LeftRight            ; Guessed right                            <S550    27Jul88    EMT>
  1582.  
  1583.             MOVE.W    D6, D2                ; Otherwise get right side                <S550    27Jul88    EMT>
  1584.             SUB.W    D0, D2                ; And subtract out width                <S550    27Jul88    EMT>
  1585.  
  1586. @LeftRight                                ;                                        <S550    27Jul88    EMT>
  1587.             MOVE.W    D2,(A0)+            ; push left                                <27Sept85>    <S550    27Jul88    EMT>
  1588. ;            ADDQ.W    #3,(A0)+            ; indent a little                        <15Oct85>
  1589.             MOVE.L    -4(A0),(A0)            ; copy bottom right
  1590.             ADD.L    D0, (A0)            ; Add height, width to get bottom, right    <S550    27Jul88    EMT>
  1591.  
  1592. ;            ADD        #32,(A0)+            ; bottom := top + 32
  1593. ;            ADD        #32,(A0)            ; right := left + 32
  1594. ;@DoneSetup
  1595.  
  1596.             ADD.W    MSpaceWidth(A6), D0    ; Add single space to width of icon            <S550    27Jul88    EMT>
  1597.             BSR        TweakPos            ; get hpos into D2, adjust D5,D6            <S550    27Jul88    EMT>
  1598.  
  1599. ;>>>>>------------- NuMac ------------------>>>>>
  1600.  
  1601. ;+++        IF onNuMac THEN
  1602.             tst.b    onColorMachine(a6)
  1603.             beq.s    @DoPlotIcon
  1604.  
  1605. ; attempt to get color icon first and if unsuccessful then get regular icon        <FJL C408>
  1606.             subq    #4, sp                ; make room for function result
  1607.             move    #$0100, d0            ; menu icons are 256-511
  1608.             move.b    itemIcon(a4), d0    ; get icon number - 256
  1609.             move    d0, -(sp)            ; push icon number
  1610.             _GetCIcon
  1611.             move.l    (sp)+, iconHandle(a6)    ; get icon handle, and save in stackframe
  1612.             beq.s    @DoPlotIcon            ; no color icon, must be regular icon
  1613.  
  1614. ; check to be sure icon is <= 32 x 32
  1615. ; no longer care about icon size                                                <S550    27Jul88    EMT>
  1616. ;            move.l    iconHandle(a6), a0    ; get icon handle
  1617. ;            move.l    (a0), a0            ; dereference, a0 points at pixMap
  1618. ;            move.l    pBounds+Top(a0), d0    ; get top, left
  1619. ;            move.l    pBounds+Bottom(a0), d1    ; get bottom, right
  1620. ;            sub        d0, d1                ; width = right - left
  1621. ;            cmp        #32, d1                ; width == 32 ?
  1622. ;            bne.s    @DispIcon            ; if not then don't plot it
  1623. ;            swap    d0
  1624. ;            swap    d1
  1625. ;            sub        d0, d1                ; height = bottom - top
  1626. ;            cmp        #32, d1                ; height == 32?
  1627. ;            bne.s    @DispIcon            ; if not then don't plot it
  1628.  
  1629. ; force colors to black on white for PlotCIcon regardless of InvertFlag,
  1630. ; unless it's 1 or 2 bit mode in which case we want it white on black so icon mask
  1631. ; is inverted properly
  1632.             cmpi.w    #4, PixelDepth(a6)    ; is this 4+ mode ?
  1633.             blt.s    @FunkySettings        ; no, so branch and do funky color setting
  1634.             pea        RGBBlack            ; in 4+ mode force black on white always
  1635.             _RGBForeColor
  1636.             pea        RGBWhite
  1637.             _RGBBackColor
  1638.             bra.s    @1
  1639.  
  1640. @FunkySettings                            ; in 1 or 2 bit, use black on white for normal
  1641.                                         ; and white on black for selected
  1642.             pea        RGBBlack
  1643.             pea        RGBWhite
  1644.             tst        invertFlag(a6)        ; invert mode?
  1645.             bne.s    @2                    ; yes --> branch
  1646.             _RGBBackColor
  1647.             _RGBForeColor
  1648.             bra.s    @1
  1649.  
  1650. @2            _RGBForeColor
  1651.             _RGBBackColor
  1652.  
  1653. ; everything checks out so plot it
  1654. @1            move.l    iconHandle(a6), -(sp)    ; got a color icon so push it on the stack
  1655.             _PlotCIcon                        ; rect is already on the stack
  1656.  
  1657. ;@DispIcon does not properly clean up stack.  Good thing we don't use it anymore.
  1658.             move.l    iconHandle(a6), -(sp)    ; dispose of CIcon
  1659.             _DisposCIcon
  1660.             bra.s    DrawCmdChar                ; and continue
  1661.  
  1662. ;+++        ENDIF
  1663.  
  1664. ;<<<<<--------------------------------------<<<<<
  1665.  
  1666.  
  1667. @DoPlotIcon
  1668.             Cmpi.B    #SmallIconCmd, itemCmd(A4)    ; is it a small icon ?            <FJL PMAB205>
  1669.             Bne.S    @GetLargeIcon        ; no    -> get large icon
  1670.             Clr.L    -(SP)                ; yes -> get small icon
  1671.             Move.L    #'SICN', -(SP)        ; push res type
  1672.             Bra.S    @GetIconCommon        ; and use common code
  1673.  
  1674. @GetLargeIcon
  1675.             CLR.L    -(SP)                ; make room for function result
  1676.             MOVE.L    #'ICON',-(SP)        ; push the resource type
  1677. @GetIconCommon
  1678.             MOVE.W    #$0100,D0            ; menu icons are 256-511
  1679.             MOVE.B    ITEMICON(A4),D0        ; does it have an icon?
  1680.             MOVE    D0,-(SP)            ; push icon number
  1681.             _GetResource                ; get the icon handle
  1682.  
  1683.             move.l    #$00100010, D0        ; assume src icon is 16x16
  1684.             moveq    #2, D1                ; and rowbytes is 2
  1685.             cmpi.b    #SmallIconCmd, itemCmd(a4)    ; is it?
  1686.             beq.s    @PushIconSrcSize    ; yes -> branch
  1687.             add.l    d0,d0                ; double it to make 32x32
  1688.             add.l    d1,d1                ; double rowbytes too
  1689. @PushIconSrcSize
  1690.             move.l    d0,-(sp)            ; push size
  1691.             move    d1,-(sp)            ; push rowbytes
  1692.  
  1693.             move    #mctRGB2, colorOffset(a6) ; use the item color if there is an entry <FJL C408>
  1694.             bsr        SetColors            ; set colors                                    <FJL C408>
  1695.  
  1696. @PlotIt        bsr        PlotAnySizeIcon    ; plot the icon                                        <FJL PMAB205>
  1697.  
  1698. @DonePlot
  1699.  
  1700. ; ---------------------    draw the command character    --------------------------
  1701.  
  1702. DrawCmdChar
  1703.             TST.B    ITEMCMD(A4)            ; is there one?
  1704.             BEQ.S    DRAWITEXT            ; if not, skip
  1705.  
  1706.             cmpi.b    #ScriptMenuCmd, itemCmd(a4)    ; script for this item?                    <FJL CXXX>
  1707.             beq.s    DrawIText            ; if so, skip                                    <FJL CXXX>
  1708.  
  1709.             cmpi.b    #ShrunkenIconCmd, itemCmd(a4)    ; shrunken icon?                    <FJL PMAB205>
  1710.             beq.s    DrawIText            ; if so, skip
  1711.  
  1712.             cmpi.b    #SmallIconCmd, itemCmd(a4)    ; small icon?                            <FJL PMAB205>
  1713.             beq.s    DrawIText            ; if so, skip
  1714.  
  1715.             move    #mctRGB3, colorOffset(a6) ; tell SetColors to get the CMD            <FJL C408>
  1716.             bsr        SetColors            ; set colors for command character                <FJL C408>
  1717.  
  1718.             MOVE.W    MWidMax(A6),D0        ; get width                                        <27Sep85>
  1719.             ADD.W    D0,D0                ; *2                                            <27Sep85>
  1720.  
  1721.             SUB.W    D0,D6                ; assume it will go on right                    <27Sep85>
  1722.             MOVE    D6,-(SP)            ; put it on stack                                <27Sep85>
  1723.             TST.B    TESysJust+1            ; check for right just                            <11oct85>
  1724.             BPL.S    @1                    ; => guessed right                                <27Sep85>
  1725.             ADDQ    #2,D5                ; else indent a little FIRST                    <S550    27Jul88    EMT>
  1726.             MOVE.W    D5,(SP)                ; else do it from left                            <27Sep85>
  1727.             ADD.W    D0,D5                ; and bump left position                        <27Sep85>
  1728.             ADD.W    D0,D6                ; else back up for icon                            <27Sep85>
  1729.  
  1730. @1            MOVE.W    D3,-(SP)            ; push vertical position
  1731.             _MoveTo                        ; position pen
  1732. ;
  1733. ; if this item has a sub-menu, then blit an arrow in the command key                    <FJL C222>
  1734. ; field to indicate its existence .                                                        <FJL C222>
  1735. ;
  1736.             cmpi.b    #HMenuCmd, itemCmd(a4)    ; is there a H Menu?                        <FJL C222>
  1737.             bne.s    @NormalCmd                ; no, so do as normal                        <FJL C222>
  1738.  
  1739.             bsr        BlitHierArrow            ; draw the Hierarchical arrow
  1740.  
  1741.             bra.s    DrawIText                ; continue                                    <FJL C222>
  1742.  
  1743. @NormalCmd    MOVE.B    TESysJust+1,D1        ; need special justification?                    <FJL CXXX>
  1744.             EXT.W    D1                    ; make it a signed word                            <FJL CXXX>
  1745.             BNE.S    @JustifiedCmd        ; => yes                                        <FJL CXXX>
  1746.  
  1747.             MOVE.W    #commandMark,-(SP)    ; push command mark (propeller)                    <15Feb85>
  1748.             _DrawChar                    ; draw the character
  1749.             CLR    D0                        ; clear high part
  1750.             MOVE.B    ITEMCMD(A4),D0        ; get command character
  1751.             MOVE.W    D0,-(SP)            ; push command char
  1752.             _DrawChar                    ; draw it
  1753.             bra.s    DrawIText            ; and continue
  1754.  
  1755. @JustifiedCmd                            ; draw commandletter/propeller                    <FJL CXXX>
  1756.             CLR    D0                        ; clear high part
  1757.             MOVE.B    ITEMCMD(A4),D0        ; get command character
  1758.             MOVE.W    D0,-(SP)            ; push command char
  1759.             _DrawChar                    ; draw it
  1760.             MOVE.W    #commandMark,-(SP)    ; push command character                        <15Feb85>
  1761.             _DrawChar                    ; draw the character
  1762.  
  1763. ; ----------------    draw the text of the item (position in D5)    ----------------------
  1764.  
  1765. DRAWITEXT
  1766.  
  1767.             move    #mctRGB2, colorOffset(a6) ; tell SetColors to get the TEXT            <FJL C408>
  1768.             bsr        SetColors            ; set colors for text                            <FJL C408>
  1769.  
  1770.             CLR    D0                        ; clear it out
  1771.             MOVE.B    ITEMSTYLE(A4),D0    ; push the style parameter
  1772.             MOVE.W    D0,-(SP)            ; push style parameter
  1773.             _TextFace                    ; get into that face
  1774.  
  1775. ; if there is a script for this font then set it
  1776.  
  1777.             cmpi.b    #ScriptMenuCmd, itemCmd(a4)    ; script for this item?            <FJL CXXX>
  1778.             bne.s    @1                    ; no, so skip                            <FJL CXXX>
  1779.             move.b    itemIcon(a4), d0    ; pass script number                    <S422    08Mar88 MED>
  1780.             bsr        SetScriptFont        ; yes, so set the proper font            <FJL CXXX>
  1781.  
  1782. @1            MOVE.B    TESysJust+1,D1        ; need special justification?            <11oct85>
  1783.             EXT.W    D1                    ; make it a signed word                    <11oct85>
  1784.             BNE.S    @DrawIntl            ; => yes                                <27Sep85>
  1785.  
  1786.             MOVE.W    D5,-(SP)            ; and baseline left                        <27Sep85>
  1787.             MOVE.W    D3,-(SP)            ; else push baseline vertical            <27Sep85>
  1788.             _MoveTo                        ; push the pen                            <27Sep85>
  1789.  
  1790.             MOVE.L    A2,-(SP)            ; point to the string                    <27Sep85>
  1791.             _DrawString                    ; and draw it                            <27Sep85>
  1792.             BRA.S    @2
  1793. ;
  1794. ; do International stuff here if TESysJust is negative
  1795. ;
  1796. @DrawIntl    LEA        TempRect,A0            ; build rect for TextBox                <27Sep85>
  1797.             SUBQ    #1,D5                ; textBox indents by one                <27Sep85>
  1798.             MOVE.W    D3,(A0)                ; get y position                        <27Sep85>
  1799.             MOVE.W    MAscent(A6),D0        ; move up to top of rect                <27Sep85>
  1800.             SUB.W    D0,(A0)+            ;                                        <27Sep85>
  1801.             MOVE.W    D5,(A0)+            ; D5 is left                            <27Sep85>
  1802.             MOVE.W    D3,(A0)                ; as top and bottom                        <27Sep85>
  1803.             MOVE.W    MDescent(A6),D0        ; and move down to bottom                <27Sep85>
  1804.             ADD.W    D0,(A0)+            ;                                        <27Sep85>
  1805.             MOVE.W    D6,(A0)                ; and setup right                        <27Sep85>
  1806.  
  1807.             MOVEQ    #0,D0                ; get length                            <27Sep85>
  1808.             MOVE.B    (A2)+,D0            ; into D0                                <27Sep85>
  1809.             MOVE.L    A2,-(SP)            ; push text pointer                        <27Sep85>
  1810.             MOVE.L    D0,-(SP)            ; and length                            <27Sep85>
  1811.             PEA        TempRect            ; push rect of rects                    <27Sep85>
  1812.             MOVE.W    D1,-(SP)            ; and justification word                <11oct85>
  1813.             _TextBox
  1814.  
  1815. @2            CLR.L    -(SP)                ; push empty set for TextFace and TextFont
  1816.             _TextFace                    ; restore textface to normal
  1817.             _TextFont                    ; restore textfont to normal
  1818. ;
  1819. ; if the item is disabled, gray it out
  1820. ;
  1821.             BSR        ENABLETEST            ; is it enabled?
  1822.             BNE.S    DoneDrawItem        ; branch if it is
  1823.             bsr.s    BitClearItem        ; bit clear the item, notice that colors are set properly
  1824.  
  1825. DoneDrawItem
  1826.             bsr        ResetPreviousColors    ; restore colors saved in the stackframe <FJL C408>
  1827.             MOVEQ    #1, D0                ; Force Z flag off for normal return    <S550    27Jul88    EMT>
  1828.  
  1829. NoDrawItem                                ;                                        <S550    27Jul88    EMT>
  1830. ; Z flag is already set                                                            <S550    27Jul88    EMT>
  1831.             rts                            ; and return to caller
  1832.  
  1833.  
  1834. ;---------------------------------------
  1835. ;    Utility -- BitClearItem                ; attempt to speed graying of menu items    <FJL 26Jan87>
  1836. ;---------------------------------------
  1837. ; Paint the item with gray.  Speed up is about 20%!!
  1838. ;
  1839. ;    On Entry:    D4        item number
  1840. ;
  1841. BitClearItem
  1842.             movem.l    d3/d7, -(sp)        ; save work registers
  1843.  
  1844.             TST.B    ITEMICON(A4)        ; does it have an icon?
  1845.             BEQ.S    @1                    ; skip if it doesnt
  1846.             MOVE.W    D7,D0                ; get delta height
  1847.             LSR.W    #1,D0                ; divide by 2
  1848.             SUB.W    D0,D7                ; and get remainder
  1849.             ADD        D7,D3                ; bump the rest of the difference for icon
  1850.  
  1851. @1            ADD    MFHeight(A6),D3    ; bump to next baseline
  1852.  
  1853.             LEA        TEMPRECT,A0            ; get pointer to temporary rectangle
  1854.             MOVE.L    MMenuRect(a6), A1    ; get pointer to menu rect
  1855.             MOVE.L    (A1),(A0)            ; copy menuRect into tempRect
  1856.             MOVE.L    4(A1),4(A0)
  1857.             SUB        MAscent(A6), D3        ; move up by the fon't ascent to get bottom of item
  1858.             MOVE    D3, Bottom(A0)        ; store as bottom
  1859.  
  1860.             Bsr        GetItemHeightA4        ; get item height into D0                <FJL PMAB205>
  1861.             Sub.W    D0, D3
  1862.             lea        TempRect,a0            ; get rectangle in A0                    <1.7>
  1863.             MOVE    D3,top(a0)            ; D3 has the height                        <1.6> <1.7>
  1864.             BSR        GRAYRECT            ; bit clear tempRect with gray
  1865.  
  1866. @ClearDone
  1867.             movem.l    (sp)+, d3/d7        ; restore work registers
  1868.             rts
  1869.  
  1870. ;---------------------------------------
  1871. ;    Utility -- SetScriptFont
  1872. ;---------------------------------------
  1873. ; Input        d0:        script number
  1874. ;
  1875. ; set the script's base font.  No need to check if script manager is installed
  1876. ; since AddResMenu has already done that
  1877. ;
  1878. SetScriptFont
  1879.             clr.l        -(sp)                ; make room for long result
  1880. ;;            clr            d0                    ; clear lo-word
  1881. ;;            move.b        itemIcon(a4), d0    ; get script number
  1882.  
  1883. ; make d0 an argument, the script number                                    <S422    08Mar88 MED>
  1884.  
  1885.             and.w        #$00FF,d0            ; get bottom byte for script    <S422    08Mar88 MED>
  1886.             move        d0, -(sp)            ; push script number
  1887.             move        #smScriptSysFond, -(sp)    ; push base font verb
  1888.             _GetScript
  1889.             move.l        (sp)+, d0            ; get result
  1890.             blt.s        @verbErr            ; verb error if d0 < 0
  1891.             move        d0, -(sp)            ; push font number
  1892.             _TextFont
  1893.  
  1894. @verbErr    rts
  1895.  
  1896. ;---------------------------------------
  1897. ;    Utility -- BlitHierArrow
  1898. ;---------------------------------------
  1899. ; Blit up the hierarchical arrow
  1900. ;
  1901. BlitHierArrow
  1902.  
  1903.             movem.l    a3/d4, -(sp)            ; store work registers
  1904.  
  1905. ; calculate where arrow should go
  1906.             subq    #4, sp
  1907.             move.l    sp, -(sp)                ; reserve space on stack for result
  1908.             _GetPen
  1909.             move.l    (sp)+, d4                ; get y,x
  1910.             swap    d4                        ; get x,y
  1911.             sub        MAscent(a6), d4            ; move up by the fon't ascent to get top of item
  1912.             swap    d4                        ; have top, left of where will blit arrow
  1913.             move.l    d4, HierArrowRect(a6)    ; store top, left
  1914.             move.l    d4, HierArrowRect+4(a6)    ; calculate bottom, right
  1915.             move    MFHeight(a6), d4        ; get height
  1916.             cmpi    #16, d4                    ; make height/width = 16 unless smaller than 16.<FJL PMAB205>
  1917.             ble.s    @1
  1918.             move    #16, d4
  1919. @1            add        d4, HierArrowRect+Bottom(a6); bottom = top + height
  1920.             add        d4, HierArrowRect+Right(a6)    ; right = left + width
  1921.  
  1922. ; create bitMap for arrow
  1923.             moveq    #bitMapRec, d0            ; alloc bitmap for 16Vert x 16Horiz x 1Deep bit map
  1924.             _NewHandle
  1925.             _HLock
  1926.             move.l    (a0), a3                ; dereference
  1927.             move    #2, rowBytes(a3)        ; 16 x 1 bits wide
  1928.             move.l    #$00000000,bounds(a3)    ; top = 0, left = 0
  1929.             move.l    #$00100010,bounds+4(a3)    ; bottom = 0, right = 0
  1930.             lea        HierArrow, a1            ; get mask data address
  1931.             move.l    a1, baseAddr(a3)        ; store it
  1932.  
  1933. ; get current portRect
  1934. CommonBlit    subq    #4, sp
  1935.             move.l    sp, -(sp)                ; make space on stack for return
  1936.             _GetPort
  1937.             move.l    (sp)+, a0                ; get port
  1938.  
  1939. ; copy from the bitMap into the port
  1940.             move.l    a3, -(sp)                ; push src bitMap ptr
  1941.             pea        portBits(a0)            ; push dest pointer (for the screen)
  1942.             pea        bounds(a3)                ; push src bounds rect
  1943.             pea        HierArrowRect(a6)        ; push dest bounds rect
  1944.             move    #srcOr, -(sp)            ; srcOr
  1945.             clr.l    -(sp)                    ; no maskRgn
  1946.             _CopyBits
  1947.  
  1948.             move.l    a3, a0                    ; get bitMap ptr
  1949.             _RecoverHandle                    ; get bitMap handle
  1950.             _DisposHandle                    ; and toss it
  1951.             movem.l    (sp)+, a3/d4            ; restore work registers
  1952.  
  1953.             rts
  1954.  
  1955. ;---------------------------------------
  1956. ;    Utility -- GetItemRecord
  1957. ;---------------------------------------
  1958.  
  1959. ;    GetItemRecord is the main utility used for accessing the menu item data structure.
  1960. ;    It has a register interface to save code.  On entry, A0 points to a menuInfo block,
  1961. ;    while D0 has the item number of interest.  On exit, A0 points to the item string
  1962. ;    of interest while A1 points to that item's attribute byte list.  If the item can't
  1963. ;    be found, A0 and A1 both return NIL.
  1964. ;
  1965. ; TODO:    If this is called inside a loop, then we have a factorial function!!
  1966. ;        Therefore look where this is called from and see if we can't be smarter about
  1967. ;        how to move thru the menulist
  1968.  
  1969. GETITEMRECORD
  1970.             TST D0                        ; make sure item number is valid
  1971.             BLE.S    NOITEM                ; if it's not, don't bother
  1972. ;
  1973.             MOVEQ    #0,D1                ; clear D1 for byte arithmetic
  1974.             LEA        MENUDATA(A0),A1        ; get menuData handle
  1975.             MOVE.B    (A1)+,D1            ; get title length
  1976.             ADD        D1,A1                ; skip over title string
  1977. ;
  1978. ; here is the item search loop.  A1 points to the beginning of the next item.
  1979. ;
  1980. GETILOOP    SUBQ    #1,D0                ; is this the one we're looking for?
  1981.             BEQ.S    GOTITEM                ; if so, we got it
  1982.             MOVE.B    (A1)+,D1            ; get length of current item
  1983.             BEQ.S    NOITEM                ; length zero marks end of list
  1984. ;
  1985.             ADDQ    #4,D1                ; there are 4 bytes of item properties
  1986.             ADD        D1,A1                ; bump to next item
  1987.             BRA.S    GETILOOP            ; loop till done
  1988. ;
  1989. ;    the item couldn't be found so return NIL
  1990. ;
  1991. NOITEM        SUB.L    A0,A0                ; zero A0
  1992.             MOVE.L    A0,A1                ; and A1 too
  1993.             MOVE.L    A0,D0                ; and set the z-flag
  1994.             CLR.L    lastItemStrPtr(A6)    ; <KSM/RLC    31May89>
  1995.             CLR.L    lastAttrPtr(A6)        ; <KSM/RLC    31May89>
  1996.             RTS                            ; return to caller
  1997. ;
  1998. ; we found the item so return a pointer to it in A0 and a pointer to the item properties
  1999. ; in A1
  2000. ;
  2001. GOTITEM        TST.B    (A1)                ; is this the NIL item?
  2002.             BEQ.S    NOITEM                ; if so, we really didn't get one
  2003. ;
  2004.             MOVE.L    A1,A0                ; A0 points to item string
  2005.             MOVE.B    (A1)+,D1            ; get length
  2006.             ADD        D1,A1                ; bump to item properties
  2007.             MOVE.L    A0,lastItemStrPtr(A6)    ; <KSM/RLC    31May89>
  2008.             MOVE.L    A1,lastAttrPtr(A6)        ; <KSM/RLC    31May89>
  2009.             RTS                            ; return to caller
  2010.  
  2011. ;----------------------------------------------------------------------------------------
  2012. ;
  2013. ;    Msg #2 -- Calc Menu Size
  2014. ;
  2015. ;----------------------------------------------------------------------------------------
  2016. ; Calculate the menu size for the given text menu.  The handle is in A3.
  2017. ;
  2018. ; DONE: <FJL PMAB205> Menus with icons did not show scroll arrows properly after you had
  2019. ;                        scrolled all the way up, then start to scroll down again.  The reason
  2020. ;                        was that the menu height is not an even multiple of MFHeight.
  2021. ;                        This code returns an even multiple of MFHeight if the menu scrolls.
  2022.  
  2023. DoCalcMsg
  2024.         IF forRAM THEN
  2025.             SUBQ    #4,SP
  2026.             MOVE.L    SP,-(SP)                ; point to top of stack
  2027.             _GetPort                        ; get the current port
  2028.  
  2029. ;            CMP.W    #$3FFF, ROM85            ; color machine ?                            <PMAB364    23Jan88    EMT>
  2030.             TST.B    onColorMachine(A6)        ; color machine ?                            <S394    12Feb88    DBG>
  2031.             BEQ.S    @SetBWPort                ;                                            <PMAB364    23Jan88    EMT>
  2032.  
  2033.             MOVE.L    WMgrCPort, -(SP)        ; get color port                            <PMAB364    23Jan88    EMT>
  2034.  
  2035.             BRA.S    @SetPort                ;                                            <PMAB364    23Jan88    EMT>
  2036.  
  2037. @SetBWPort                                    ;                                            <PMAB364    23Jan88    EMT>
  2038.             MOVE.L    WmgrPort,-(SP)            ; push the wmgr port, do not use color port here.
  2039.  
  2040. @SetPort                                    ;                                            <PMAB364    23Jan88    EMT>
  2041.             _SetPort                        ; set it                                    <PMAB364    23Jan88    EMT>
  2042.         ENDIF    ; if forRAM
  2043.  
  2044. ; since calc msg could be called at any time, we need to reset the wmgr's textfont here else
  2045. ; could get incorrectly sized menus
  2046.  
  2047.             clr        -(sp)                    ; clear stack for TextFont                    <FJL CXXX>
  2048.             _TextFont                        ; use system font in menus                    <FJL CXXX>
  2049.             bsr        GetSizes                ; get font sizes from wmgr port                <FJL CXXX>
  2050.  
  2051.             SUBQ.L    #4, SP                    ;                                            <PMAB364    23Jan88    EMT>
  2052.             MOVE.L    SP, -(SP)                ;                                            <PMAB364    23Jan88    EMT>
  2053.             _GetPort                        ; Get the current port                        <PMAB364    23Jan88    EMT>
  2054.             MOVE.L    (SP)+, A0                ; Put it in A0                                <PMAB364    23Jan88    EMT>
  2055.  
  2056. ;            MOVE.L    WMgrPort,A0                ; get the port                                <27Sep85>
  2057.             MOVE.W    PortRect+bottom(A0),D5    ; get the screen bottom                        <27Sep85>
  2058.             SUB.W    portRect+top(A0), D5    ; subtract the top                            <S476    22Apr88    EMT>
  2059.  
  2060. ; the maximum size for a menu is screen height minus menubar height minus a fudge factor.
  2061.  
  2062. GetMBHeight
  2063.             TST.W    ROM85                    ; running on new roms?                        <EHB 26Aug85>
  2064.             BMI.S    @0                        ; => no, use old menubar height                <EHB 26Aug85>
  2065.             SUB.W    MBarHeight,D5            ; get what low memory says                    <EHB 5Aug85>
  2066.             BNE.S    @1                        ; => it's a good height                        <EHB 5Aug85>
  2067. @0            SUB.W    #20,D5                    ; else stuff default height                    <EHB 5Aug85>
  2068. @1
  2069.  
  2070.             sub        #16, d5                    ; hierarchical menus need a little more margin    <FJL C222>
  2071.  
  2072. ; make d5 an even multiple of MFHeight so that scrolling with different sized items    <FJL PMAB205>
  2073. ; will work properly.
  2074. ;+++            dc.w    $a9ff
  2075. ;+++            Divu    MFHeight(A6), d5    ; (max menu height) div (MFHeight)
  2076. ;+++            Move    D5,D6                ; get quotient
  2077. ;+++            MoveQ    #0,D5                ; clear D5
  2078. ;+++            Move    D6,D5                ; return quotient
  2079. ;+++            Mulu    MFHeight(A6), D5    ; max menu height = MFHeight x quotient
  2080.  
  2081.             MOVEQ    #0,D6                ; set initial <height,width> to 0
  2082.             MOVEQ    #1,D0                ; find item 1
  2083.             MOVE.L    (A3),A0                ; point to the menuRecord
  2084.             BSR.S    GetItemRecord        ; point to first item
  2085.             BEQ        DoCalcDone1            ; if zero, we're done                            <EHB 10-Apr-85>
  2086.             MOVE.L    A0,A4                ; keep pointer in A4
  2087. ;
  2088. ; here is the main loop of calcMenuSize.  Process each item one at a time, keeping the
  2089. ; height and maximum width in D6
  2090. ;
  2091. CMLOOP
  2092.             MOVEQ    #0,D7                ; set "extra" width to zero
  2093.  
  2094.             MOVE.L    (A3),A0                ; handle -> pointer
  2095.             MOVEQ    #0,D0                ; clear out high part
  2096.             MOVE.B    (A4),D0                ; get length of item
  2097.             BEQ        DoCalcDone            ; if zero, we're done with this menu
  2098.             LEA        1(A4,D0),A1            ; point A1 at the properties
  2099.  
  2100. ; handle the vertical
  2101.  
  2102.             BSR        GetItemHeight        ; get height of item into D0
  2103.             SWAP    D1                    ; Get width of icon into low word            <S550    27Jul88    EMT>
  2104.             MOVE.W    D1, D7                ; Copy width into D7                        <S550    27Jul88    EMT>
  2105.             ADD.W    MSpaceWidth(A6), D7    ; Add in width of a single space            <S550    27Jul88    EMT>
  2106.  
  2107. ;            cmpi.b    #ScriptMenuCmd, itemCmd(a1)    ; is there a script defined?    <FJL CXXX>
  2108. ;            beq.s    @0                    ; yes, icon field stores scriptID        <FJL CXXX>
  2109. ;
  2110. ;            TST.B    ITEMICON(A1)        ; is there an icon for this item?
  2111. ;            BEQ.S    @0                    ; if not, don't adjust height
  2112. ;            MOVEQ    #40,D7                ; add 40 to width for icons
  2113. ;            MOVEQ    #36,D0                ; and 36 to height for icons            <27Sep85>
  2114. ;
  2115. ;            Cmpi.B    #ShrunkenIconCmd, itemCmd(A1)    ; is there a shrunken icon?    <FJL PMAB205>
  2116. ;            Beq.s    @NewWidth            ; yes    -> different width
  2117. ;            Cmpi.B    #SmallIconCmd, itemCmd(A1)    ; is there a small icon ?
  2118. ;            Bne.S    @0                    ; no    -> branch
  2119. ;@NewWidth    MoveQ    #20, D7                ; yes -> width is half size of regular icon
  2120. ;            Bsr        GetItemHeight        ;        get height into D0
  2121.  
  2122. @0            SWAP    D6                    ; get vertical into low word                <27Sep85>
  2123.             ADD.W    D0,D6                ; increment vertical height                    <27Sep85>
  2124.             CMP.W    D5,D6                ; past bottom of screen?                    <27Sep85>
  2125.             BLT.S    @1                    ; => no                                        <27Sep85>
  2126.             SUB.W    D0,D6                ; yes, don't make menu taller                <27Sep85>
  2127.  
  2128. ; handle the horizontal
  2129.  
  2130. @1            SWAP    D6                    ; but get vertical in high first            <27Sep85>
  2131.             MOVE.W    MWidMax(A6),D1        ; get char width                            <1Aug85>
  2132.             ADD.W    D1,D7                ; add once for mark                            <1Aug85>
  2133.  
  2134.             cmpi.b    #ScriptMenuCmd, itemCmd(a1)    ; is there a script defined?        <FJL CXXX>
  2135.             beq.s    @2                    ; yes, then no command                        <FJL CXXX>
  2136.             cmpi.b    #ShrunkenIconCmd, itemCmd(a1) ; is there a shrunken icon?        <FJL PMAB239>
  2137.             beq.s    @2                    ; yes, then no command                        <FJL PMAB239>
  2138.             cmpi.b    #SmallIconCmd, itemCmd(a1)        ; is there a small icon defined?    <FJL PMAB239>
  2139.             beq.s    @2                    ; yes, then no command                        <FJL PMAB239>
  2140.  
  2141.             TST.B    ITEMCMD(A1)            ; is there a commmand?
  2142.             BEQ.S    @2                    ; if not, skip
  2143.             ADD.W    D1,D7                ; add twice for command equivalent            <1Aug85>
  2144.             ADD.W    D1,D7                ;                                            <1Aug85>
  2145.             ADD.W    #8,D7                ; plus an eight pixel margin                <1Aug85>
  2146. @2
  2147.             MOVEQ    #0,D1                ; clear out high byte
  2148.             MOVE.B    ITEMSTYLE(A1),D1    ; get style setting
  2149.  
  2150. @3            MOVE.W    D1,-(SP)            ; push the style
  2151.             _TextFace                    ; tell LisaGraf about new style
  2152.  
  2153. ;
  2154. ; If there is a script defined for this item, then set font for proper string width calc,
  2155. ; do calc, and restore font to #0.
  2156. ;
  2157.             cmpi.b    #ScriptMenuCmd, itemCmd(a1)    ; is there a script defined?    <FJL CXXX>
  2158.             bne.s    @NoScript            ; yes, icon field stores scriptID        <FJL CXXX>
  2159.  
  2160. ;;            clr        d0                    ; clear it out                            <FJL CXXX>
  2161. ;;            move.b    itemCmd(a1), d0        ; get scriptID                            <FJL CXXX>
  2162. ;;            mulu    #512, d0            ; calculate font num = ID*512-512+$4000    <FJL CXXX>
  2163. ;;            addi    #$3C00, d0            ;                                        <FJL CXXX>
  2164. ;;            move    d0, -(sp)            ; push font num                            <FJL CXXX>
  2165. ;;            _TextFont                    ; and set font                            <FJL CXXX>
  2166.  
  2167. ; use utility routine for setting the font from the script
  2168.  
  2169.             move.b    itemIcon(a1), d0    ; pass script number                    <S422    08Mar88 MED>
  2170.             bsr        SetScriptFont        ; set TextFont according to script        <S422    08Mar88 MED>
  2171.             
  2172.             clr        -(sp)                ; make room for StringWidth result        <FJL CXXX>
  2173.             move.l    a4, -(sp)            ; move string pointer                    <FJL CXXX>
  2174.             _StringWidth                ; find out the width                    <FJL CXXX>
  2175.             clr        -(sp)                ; restore font to normal                <FJL CXXX>
  2176.             _TextFont                    ;                                        <FJL CXXX>
  2177.             bra.s    @ContCalc            ; and continue with the calculation        <FJL CXXX>
  2178.  
  2179. @NoScript    CLR        -(SP)                ; make room for stringWidth result
  2180.             MOVE.L    A4,-(SP)            ; move string pointer
  2181.             _StringWidth                ; find out the width
  2182.  
  2183. @ContCalc    ADD.W    (SP)+,D7            ; add width to extra
  2184.             CMP        D7,D6                ; compare with maxWidth
  2185.             BGE.S    CALCNEXT            ; if max is bigger, go process next one
  2186.             MOVE    D7,D6                ; this one was the biggest
  2187. ;
  2188. ; go process next item; loop till we get a null one
  2189. ;
  2190. CALCNEXT
  2191.             MOVEQ    #0,D0                ; zero high part
  2192.             MOVE.B    (A4),D0                ; get the length of current item
  2193.             LEA        5(A4,D0),A4            ; point to the next item
  2194.             BRA        CMLOOP                ; loop till done
  2195.  
  2196. ;    we've scanned all the items update menuHeight and menuWidth
  2197.  
  2198. DoCalcDone    ADDQ.W    #4,D6                ; add some extra for right margin
  2199. DoCalcDone1                                ; if NIL menu, return 0                <EHB 10-Apr-85>
  2200. ; Ensure that the menu is not too wide.
  2201.             SUBQ.L    #4, SP                    ;                                            <PMAB364    23Jan88    EMT>
  2202.             MOVE.L    SP, -(SP)                ;                                            <PMAB364    23Jan88    EMT>
  2203.             _GetPort                        ; Get the current port                        <PMAB364    23Jan88    EMT>
  2204.             MOVE.L    (SP)+, A0                ; Put it in A0                                <PMAB364    23Jan88    EMT>
  2205.             MOVE.W    portRect+Right(A0), D0    ; Get right edge                            <PMAB364    23Jan88    EMT>
  2206.             SUB.W    portRect+Left(A0), D0    ; Subtract left edge to get width            <PMAB364    23Jan88    EMT>
  2207.             SUB.W    #16, D0                    ; Subtract a little more for margin            <PMAB364    23Jan88    EMT>
  2208.             CMP.W    D0, D6                    ; Is menu too wide?                            <PMAB364    23Jan88    EMT>
  2209.             BLE.S    @1                        ; Nope, move along                            <PMAB364    23Jan88    EMT>
  2210.             MOVE.W    D0, D6                    ; Too wide, clip its wings                    <PMAB364    23Jan88    EMT>
  2211. @1                                            ;                                            <PMAB364    23Jan88    EMT>
  2212.             MOVE.L    (A3),A0                    ; get menu pointer
  2213.             MOVE.W    D6,MENUWIDTH(A0)        ; update menu width
  2214.             SWAP    D6
  2215.  
  2216. ; if menu is taller than max allowable (which is now an even multiple of MFHeight)    <FJL PMAB205>
  2217. ; then make it equal to the max allowable.
  2218.  
  2219. ;+++            Cmp.W    D5,D6                ; too tall ?
  2220. ;+++            Blt.S    @SizeOK                ; => no
  2221. ;+++            Move.W    D5,D6                ; yes, make it equal to max allowable
  2222. @SizeOK
  2223.             MOVE.W    D6,MENUHEIGHT(A0)        ; update menu height
  2224.  
  2225.             CLR.W    -(SP)                    ; better restore style to normal
  2226.             _TextFace                        ; set the style
  2227.  
  2228.         IF forRAM THEN
  2229.             _SetPort                        ; restore original grafPort                    <PMAB364    23Jan88    EMT>
  2230.         ENDIF    ; if forRAM
  2231.  
  2232.             rts                                ; all done! so return to dispatcher
  2233.  
  2234.  
  2235. ;----------------------------------------------------------------------------------------
  2236. ;
  2237. ;    Msg #3 -- Calc TopMenuItem and MenuRect so that the top of PopUpItem is at TopLeft
  2238. ;
  2239. ;----------------------------------------------------------------------------------------
  2240. ; Begin by calculating how far the top of WhichItem is from the top of the menu.
  2241. ; Then place the menu.  The various possibilities are:
  2242. ;    1. The whole menu fits on the screen and PopUpItem lines up with TopLeft
  2243. ;    2. The whole menu fits on the screen and PopUpItem cannot line up with TopLeft without
  2244. ;        causing the menu to scroll.  In this case adjust menuRect so that complete menu is
  2245. ;        is on the screen, but PopUpItem is as close to TopLeft as possible.
  2246. ;    3. The whole menu is not on the screen.  In this case adjust the menuRect so that as much
  2247. ;        of the menu is showing as possible on the screen, and position PopUpItem so that
  2248. ;        it is showing and as close as possible to TopLeft.
  2249. ;
  2250. ; Return the MenuRect and TopMenuItem.  TopMenuItem is returned in the VAR PopUpItem param.;
  2251. ;
  2252. ; Historical Note:    It would be desireable to have popups change vertical size as they scrolled,
  2253. ;                    instead of having all that white space when the scrolling menu is first
  2254. ;                    displayed.  The reason for this is due to the design of the MBDF.
  2255. ;                    The MBDF saves the bits behind and draws the drop shadow at the same
  2256. ;                    time.  If there were two messages instead, one to save the bits behind
  2257. ;                    and one to draw the drop shadow, the we could save all of the bits behind
  2258. ;                    the menurect, from the top of the screen to the bottom, and then change
  2259. ;                    the menu's vertical height without worrying about saving more bits each
  2260. ;                    time it got bigger.  But we can't, so...
  2261. ;
  2262. ;    <FJL PMAB205> Pass PopUpItem = 0 and force top of menuRect to Top parameter
  2263.  
  2264. DoPopUpItemMsg
  2265.             BSR        GetSizes            ; get font info into the stack
  2266.             MOVE.L    MPopUpItem(A6), A4    ; get ptr to PopUpItem
  2267.             MOVE    (A4), D3            ; store item in D3
  2268.             CLR        D2                    ; top of menu starts at zero
  2269.             CLR        D6                    ; ditto
  2270. ;+++            Tst.W    D3                    ; item == 0 ?                        <FJL PMAB234><FJL PMAB276>
  2271. ;+++            Beq.S    @LoopComplete        ; yes -> special case                <FJL PMAB234><FJL PMAB276>
  2272.                 MOVEQ    #1, D4                ; start with first item
  2273.  
  2274. @Loop        CMP    D3,D4                    ; have we reached the PopUpItem yet?
  2275.  
  2276.             BGT.S    @1                    ; no ==> continue calculating            <FJL PMAB205><FJL PMAB234>
  2277.             MOVE    D6, D2                ; yes ==> save item's vertical in D2, and continue
  2278. ;
  2279. ; We didn't reach it yet, so get the height and keep stepping down.
  2280. ;
  2281. @1            MOVE.L    (A3),A0                ; get menuPtr
  2282.             MOVE    D4,D0                ; get item number
  2283.             BSR        GetItemRecord        ; look it up
  2284.             BEQ.S    @LoopComplete        ; if item not found then must be end of item list
  2285.             BSR        GetItemHeight        ; get item height in D0
  2286.             ADD        D0,D6                ; update vertical
  2287.  
  2288.             ADDQ    #1,D4                ; bump to next item
  2289.             BRA.S    @Loop                ; loop till we get to end of item list
  2290.  
  2291. ; If we couldn't find the item then default to item number 1
  2292.  
  2293. @LoopComplete
  2294.             TST        D2                    ; is D2 still zero ?
  2295.             BNE.S    @GotItem            ; no ==> got the item, and it's vertical is in D2
  2296.             MOVEQ    #1, D4                ; yes ==> couldn't find item, use item #1
  2297.  
  2298. ; Distance from top of menu to top of PopUpItem is now in D2.
  2299.  
  2300. @GotItem    MOVE.L    (A3), A0            ; get menu ptr
  2301.             TST.L    MenuWidth(A0)        ; is the size valid?
  2302.             BPL.S    @SkipCalcSize        ; yes, so no need to recalc (oooohhhh, recursion)
  2303.             MOVE.L    D2, -(SP)            ; Save D2 around call <S171 DBG&JTC 08Apr87>
  2304.             MOVE.L    A3, -(SP)            ; push menu handle
  2305.             _CalcMenuSize                ; get valid height and width
  2306.             MOVE.L    (SP)+, D2            ; Restore D2 <S171 DBG&JTC 08Apr87>
  2307.  
  2308. @SkipCalcSize
  2309. ;
  2310. ; First check if menu has to scroll, i.e. its height is larger than the screen size
  2311. ; minus 8 pixels of slop.  <FJL PMAB205, no longer include menubar height in this calc>
  2312. ;
  2313. ; Register Usage:-- A0        menuRect ptr
  2314. ;                    A1        port ptr
  2315. ;                    A2        menu ptr
  2316. ;                    A3        menu handle
  2317. ;                    A4        PopUpItem ptr
  2318. ;                -- D2        Distance from top of menu to PopUpItem
  2319. ;                    D3        PopUpItem
  2320. ;                    D4        TopMenuItem
  2321. ;                    D5        Desired top of PopUpItem, the "Top" in MLeftTop
  2322. ;                    D6        Total menu height, including all menu items
  2323. ;
  2324.             SUBQ    #4, SP                ; get current portRect
  2325.             MOVE.L    SP, -(SP)            ; make space on stack of return
  2326.             _GetPort
  2327.             MOVE.L    (SP)+, A1            ; put port in A1
  2328.  
  2329.             MOVE.L    MMenuRect(A6), A0    ; put ptr to menuRect in A0
  2330.             MOVE.L    (A3), A2            ; put menu ptr in A2
  2331.             MOVE    MLeftTop+2(a6), D5    ; put desired Top of PopUpItem in D5
  2332.             MOVE    D5, D4                ; put TopMenuItem = D5 - D2 in D4
  2333.             SUB        D2, D4
  2334.  
  2335.             Cmpi.w    #0, D3                ; is PopUpItem = 0 ?                    <FJL PMAB205>
  2336.             Bne.s    @StdPopUp            ; no    -> branch
  2337.             Move    portRect+Bottom(A1),D0    ; calc max allowable menu height = bottom of
  2338.             Sub        D5, D0                    ;    screen - 8 - Top of PopUpItem
  2339.             Sub        #8, D0
  2340.             Cmp        D6, D0                ; is max allowable menu height < total menuHeight ?
  2341.             Blt.s    @HasToScroll
  2342.             Bra.S    @WontScroll
  2343.  
  2344. @StdPopUp    MOVE    portRect+Bottom(A1),D0    ; calculate max allowable menu height based on
  2345.             SUB        portRect+Top(A1), D0    ;    screen height - 8 pixels of slop
  2346.             SUB        #8, D0
  2347.             CMP        D6, D0                ; is max allowable menu height < total menuHeight ?
  2348.             BLT.S    @HasToScroll        ; yes ==> has to scroll
  2349.  
  2350. ;-------------------------------------------------------------------------------------------------
  2351. ; If here, then the complete menu WILL fit on the screen
  2352. ;-------------------------------------------------------------------------------------------------
  2353. ; Check the following possibilities:
  2354. ;    1. Top and bottom are both on the screen ==> leave it alone, PopUpItem and TopLeft will match
  2355. ;    2. Top is on screen, bottom is not ==> move bottom of menurect up until it is at least
  2356. ;            5 pixels above the bottom of the screen.  Leave TopMenuItem alone
  2357. ;    3. Bottom is on screen, top is not ==> move top of menurect down until it is at least
  2358. ;            5 pixels below the top of the screen.  Leave TopMenuItem alone
  2359.  
  2360. @WontScroll    MOVE    D4, Top(A0)            ; assume TopMenuItem, and top and bottom of menu are ok
  2361.             MOVE    D4, (A4)            ; return TopMenuItem in VAR PopUpItem
  2362.             MOVE    D4, Bottom(A0)
  2363.             ADD        D6, Bottom(A0)
  2364.  
  2365.             MOVE    portRect+Top(A1),D0    ; get the top of the screen
  2366.             ADD        MBarHeight, D0        ; move down 2 pixels from menubar
  2367.             ADD        #2, D0
  2368.             CMP        D0, D4                ; is TopMenuItem < 2 pixels below menu bar?
  2369.             BGE.S    @ChkBottom            ; no ==> therefore Top is ok
  2370.  
  2371.                                         ; yes ==> therefore move top down by multiple of MFHeight
  2372.                                         ;            until we get at least 2 pixels below the menu bar
  2373.             MOVE    D4, D1                ; start at TopMenuItem
  2374. @TopLoop    ADD        MFHeight(a6), D1    ; move down to next item
  2375.             CMP        D0, D1                ; is top of menu >= 2 pixels below menu bar?
  2376.             BLT.S    @TopLoop            ; no    ==> haven't moved top down far enough yet
  2377.             MOVE    D1, Top(A0)            ; yes ==> store new top
  2378.             ADD        D6, D1
  2379.             MOVE    D1, Bottom(A0)        ; store bottom of menu
  2380.             BRA.S    @AdjustLeftRight    ; do left/right adjustment                        <PMAB364    23Jan88    EMT>
  2381.  
  2382. @ChkBottom    MOVE    D4, D0                ; find bottom of menu = TopMenuItem + total menu height
  2383.             ADD        D6, D0
  2384.             MOVE    portRect+Bottom(A1),D1    ; calc bottom of screen - 5 pixels
  2385.             SUB        #5, D1
  2386.             CMP        D1, D0                ; is Bottom of menu > 5 pixels above screen bottom ?
  2387.             BLE.S    @AdjustLeftRight    ; no ==> therefore Bottom is ok too                <PMAB364    23Jan88    EMT>
  2388.  
  2389.                                         ; yes ==> move bottom up by multiple of MFHeight until
  2390.                                         ;            we get at least 5 pixels above the screen bottom
  2391. @BotLoop    SUB        MFHeight(a6), D0    ; move up to next item
  2392.             CMP        D1, D0                ; is bottom of menu <= 5 pixels above screen bottom ?
  2393.             BGT.S    @BotLoop            ; no    ==> haven't moved bottom up far enough yet
  2394.             MOVE    D0, Bottom(A0)        ; store bottom
  2395.             SUB        D6, D0                ; calc top of menu
  2396.             MOVE    D0, Top(a0)
  2397.             BRA.S    @AdjustLeftRight    ; do left/right adjustment                        <PMAB364    23Jan88    EMT>
  2398.  
  2399. ;-------------------------------------------------------------------------------------------------
  2400. ; If here then the complete menu WILL NOT fit on the screen
  2401. ;-------------------------------------------------------------------------------------------------
  2402. ; Leave TopMenuItem alone, but calculate where menurect should go so that when the items scroll
  2403. ; they fill up the menu exactly, i.e. as the menu is scrolled, TopMenuItem will match the
  2404. ; top of the menu rect at some point exactly.  If we don't do this there may be strange
  2405. ; behavior when the menu is scrolled completely down, i.e. the top item is showing.
  2406. ;
  2407. ; If PopUpItem = 0 then force top of menu to be at Top/Left            <FJL PMAB205>
  2408. ;
  2409. ;
  2410. @HasToScroll
  2411.             MOVE    D4, (A4)            ; return TopMenuItem in VAR PopUpItem
  2412.  
  2413.             Move    D4, D1                ; set up D1                                <FJL PMAB205>
  2414.             Move    D1, Top(A0)            ; assume PopUpItem = 0 and store Top of menuRect
  2415.             Cmpi.w    #0, D3                ; is PopUpItem = 0 ?
  2416.             Beq.s    @CalcBottom            ; yes    -> branch and only calc the bottom of the rect
  2417.  
  2418.             MOVE    portRect+Top(a1), D0; calc 2 pixels below the top of the screen <FJL PMAB205>
  2419.             ADDQ    #2, D0                ;
  2420.             CMP        D0, D4                ; is TopMenuItem >    2 pixels below top of screen?
  2421.             BLE.S    @CalcBelow            ; no    ==> branch and calc top of menuRect as
  2422.                                         ;            (MFHeight x N) **BELOW** TopMenuItem
  2423.                                         ; yes ==> fall thru and calc top of menuRect as
  2424.                                         ;                (MFHeight x N) **ABOVE** TopMenuItem
  2425. ;
  2426. ; Start at TopMenuItem, and move **UP** by increments of MFHeight until we reach at
  2427. ;    least 2 pixels below the menubar.
  2428. ;
  2429.             MOVE    D4, D1                ; start at TopMenuItem
  2430. @UpLoop        SUB        MFHeight(a6), D1    ; move up one MFHeight
  2431.             CMP        D0, D1                ; is top of menu rect < 2 pixels below the menubar ?
  2432.             BGE.S    @UpLoop                ; no    ==> keep moving up
  2433.             ADD        MFHeight(a6), D1    ; yes ==> force top of menurect to be on the screen
  2434.             MOVE    D1, Top(a0)            ; store top of menurect
  2435.             BRA.S    @CalcBottom            ; calc bottom of menurect
  2436.  
  2437. ;
  2438. ; Start at TopMenuItem, and move **DOWN** by increments of MFHeight until we reach at
  2439. ;    least 2 pixels below the menubar.
  2440. ;
  2441. @CalcBelow    MOVE    D4, D1                ; start at TopMenuItem
  2442. @DownLoop    ADD        MFHeight(a6), D1    ; move down one MFHeight
  2443.             CMP        D0, D1                ; is top of menu rect >= 2 pixels below the menubar ?
  2444.             BLT.S    @DownLoop            ; no    ==> keep moving down
  2445.             MOVE    D1, Top(a0)            ; store top of menurect
  2446. ;
  2447. ; Start at top of menurect and move down by multiples of MFHeight until the bottom of the
  2448. ;        menurect is about 5 pixels above the screen bottom.  This makes the menurect an exact
  2449. ;    multiple of MFHeight.
  2450. ;
  2451. @CalcBottom    MOVE    portRect+Bottom(a1), D0    ; calc 5 pixels above screen bottom
  2452.             SUBQ    #5, D0
  2453. @BotLoop2    ADD        MFHeight(a6), D1    ; move down by one MFHeight
  2454.             CMP        D0, D1                ; is bottom of menurect > 5 pixels above screen bottom ?
  2455.             BLE.S    @BotLoop2            ; no    ==> keep moving down
  2456.             SUB        MFHeight(a6), D1    ; yes ==> force bottom of menurect onto the screen
  2457.             MOVE    D1, Bottom(a0)        ; store bottom of menuRect
  2458.  
  2459. ;-------------------------------------------------------------------------------------------------
  2460. ; Now adjust menuLeft and menuRight if menu hangs over left or right edge of the screen.
  2461. ;-------------------------------------------------------------------------------------------------
  2462.  
  2463. @AdjustLeftRight
  2464.             MOVE    MLeftTop(A6), D0    ; get left edge
  2465.             MOVE.W    portRect+Left(A1), D2    ; Get left edge of screen                    <PMAB364    23Jan88    EMT>
  2466.             ADDQ.W    #4, D2                ; Leave room for border                            <PMAB364    23Jan88    EMT>
  2467.             CMP.W    D2, D0                ; Compare with left edge of screen                <PMAB364    23Jan88    EMT>
  2468.             BGE.S    @TryRight            ; If greater, it's OK                            <PMAB364    23Jan88    EMT>
  2469.  
  2470. ; Adjust so the menu fits on the screen.
  2471.             MOVE    D2, D0                ; make left edge equal to (fake) screen edge    <PMAB364    23Jan88    EMT>
  2472.  
  2473. @TryRight
  2474.             MOVE.W    D0, D1                ;                                                <PMAB364    23Jan88    EMT>
  2475.             ADD.W    MenuWidth(A2), D1    ; calc right edge                                <PMAB364    23Jan88    EMT>
  2476.             MOVE.W    portRect+Right(A1), D2    ; Get right edge of screen                    <PMAB364    23Jan88    EMT>
  2477.             SUBQ.W    #4, D2                ; Leave room for border                            <PMAB364    23Jan88    EMT>
  2478.             CMP.W    D2, D1                ; Compare with right edge of screen                <PMAB364    23Jan88    EMT>
  2479.             BLE.S    @StoreLeftRight        ; if smaller, we're cool
  2480.  
  2481. ; Adjust so the menu fits on the screen.
  2482.             MOVE    D2, D1                ; make right edge equal to (fake) screen edge    <PMAB364    23Jan88    EMT>
  2483.             MOVE.W    D1, D0                ;                                                <PMAB364    23Jan88    EMT>
  2484.             SUB.W    menuWidth(A2), D0    ; left = right - menuWidth                        <PMAB364    23Jan88    EMT>
  2485.  
  2486. @StoreLeftRight
  2487.             MOVE.W    D0, Left(A0)        ; store left                                    <PMAB364    23Jan88    EMT>
  2488.             MOVE.W    D1, Right(A0)        ; store right                                    <PMAB364    23Jan88    EMT>
  2489.             RTS
  2490.  
  2491. ;----------------------------------------
  2492. ;    Utility -- SaveCurrentColors                                            <FJL C408>
  2493. ;----------------------------------------
  2494. ; Save the current fore/back colors in the stackframe.
  2495. ; Get the device's pixel depth in the stackframe too.
  2496. ; Only need to save if color machine
  2497.  
  2498. SaveCurrentColors
  2499.  
  2500. ;>>>>>------------- NuMac ------------------>>>>>
  2501.  
  2502. ;+++        IF    onNuMac THEN
  2503.             tst.b    onColorMachine(a6)
  2504.             beq.s    @SaveEnd
  2505.  
  2506.             pea        saveForeColor(a6)    ; push location to save fore color
  2507.             pea        saveBackColor(a6)    ; push location to save back color
  2508.             _GetBackColor                ; and get 'em
  2509.             _GetForeColor
  2510.  
  2511.  
  2512.             SUBQ    #4,SP
  2513.             MOVE.L    SP,-(SP)                ; point to top of stack
  2514.             _GetPort                        ; get the current port
  2515.             move.l    (sp)+, a0
  2516.  
  2517.             subq    #4, sp                    ; space for GDHandle return
  2518.             pea        portRect(a0)            ; draw menus on main screen
  2519.             _GetMaxDevice                    ; get max pixel device
  2520.             MOVE.L    (sp)+, A0                ; get the grafDevice
  2521.             MOVE.L    (A0),A0                    ; hndl->ptr
  2522.             MOVE.L    GDPMap(A0),A1            ; get the device's pixmap
  2523.             MOVE.L    (A1),A1                    ; hndl->ptr
  2524.             move.w    pixelSize(a1), PixelDepth(a6)    ; and store the value
  2525.  
  2526. ;+++        ENDIF
  2527.  
  2528. @SaveEnd
  2529.  
  2530. ;<<<<<--------------------------------------<<<<<
  2531.  
  2532.             rts
  2533.  
  2534. ;----------------------------------------
  2535. ;    Utility -- ResetPreviousColors                                            <FJL C408>
  2536. ;----------------------------------------
  2537. ; Restore the fore/back colors from those saved
  2538. ; in the stackframe in SaveCurrentColors.
  2539. ; Need to reset on both color and b/w machines.  Assume b/w machine always have
  2540. ; black on white.
  2541.  
  2542. ResetPreviousColors
  2543.  
  2544. ;>>>>>------------- NuMac ------------------>>>>>
  2545.  
  2546. ;+++        IF    onNuMac THEN
  2547.             tst.b    onColorMachine(a6)
  2548.             beq.s    @ResetBW
  2549.  
  2550.             pea        saveForeColor(a6)    ; push location of saved fore color
  2551.             pea        saveBackColor(a6)    ; push location of saved back color
  2552.             _RGBBackColor
  2553.             _RGBForeColor
  2554.             bra.s    @ResetEnd
  2555.  
  2556. ;+++        ELSE                            ;===============================================
  2557. @ResetBW
  2558.             moveq    #BlackColor, d0        ; always reset to black on white
  2559.             move.l    d0, -(sp)
  2560.             _ForeColor
  2561.             moveq    #WhiteColor, d0
  2562.             move.l    d0, -(sp)
  2563.             _BackColor
  2564.  
  2565. ;+++        ENDIF
  2566.  
  2567. ;<<<<<--------------------------------------<<<<<
  2568. @ResetEnd
  2569.             rts
  2570.  
  2571. ;----------------------------------------
  2572. ;    Utility -- SetColors                                                    <FJL C408>
  2573. ;----------------------------------------
  2574. ;
  2575. ; On Entry:        A3                    MenuHandle
  2576. ;                D4                    Item Number
  2577. ;                colorOffset(a6)        Offset into menu color table indicating mark/text/cmd
  2578. ; Used:        A0, D1
  2579.  
  2580. SetColors
  2581.  
  2582. ;>>>>>------------- NuMac ------------------>>>>>
  2583.  
  2584. ;+++        IF    onNuMac THEN
  2585.             tst.b    onColorMachine(a6)
  2586.             beq        @SetBW
  2587.  
  2588.             cmpi.w    #2, PixelDepth(a6)    ; is this 2+ mode and color ?
  2589.             blt.s    @SetDefault            ; if 1 bit mode then use Black/White only
  2590.  
  2591.             tst        invertFlag(a6)        ; normal or inverted colors ?
  2592.             beq.s    @1                    ; 0 = normal colors, so branch
  2593.  
  2594. ; for inverted menu colors always invert the background color with the item name's color
  2595.             move    #mctRGB2, colorOffset(a6)
  2596.  
  2597. @1
  2598.             subq    #4, sp                ; save space for result
  2599.             move.l    (a3), a0            ; get menu ptr
  2600.             move    menuID(a0), -(sp)    ; push ID
  2601.             move    d4, -(sp)            ; push Item
  2602.             _GetMCEntry                    ; get item's color entry
  2603.             move.l    (sp)+, d1            ; get the result, and set/un-set z-flag
  2604.             beq.s    @TryTitleEntry        ; couldn't find item entry so try title entry
  2605.  
  2606.             move.l    d1, a0                ; get color record ptr in A0
  2607.             move    colorOffset(a6), d0    ; offset for mark/cmd/char
  2608.             pea        (a0, d0)            ; push foreground color
  2609.             pea        mctRGB4(a0)            ; push background color
  2610.             bra.s    @DoTheSet            ; branch to do actual color setting
  2611.  
  2612. @TryTitleEntry
  2613.             subq    #4, sp                ; save space for result
  2614.             move.l    (a3), a0            ; get menu ptr
  2615.             move    menuID(a0), -(sp)    ; push ID
  2616.             clr        -(sp)                ; Item = 0 ===> title entry
  2617.             _GetMCEntry                    ; get title's color entry
  2618.             move.l    (sp)+, d1            ; get the result, and set/un-set z-flag
  2619.             beq.s    @TryMenuBarEntry    ; couldn't find title entry so try menu bar entry
  2620.  
  2621.             move.l    d1, a0                ; get color record ptr in A0
  2622.             move    #mctRGB3, d0        ; offset for items default color
  2623.             pea        (a0, d0)            ; push foreground color
  2624.             pea        mctRGB4(a0)            ; push background color
  2625.             bra.s    @DoTheSet            ; branch to do actual color setting
  2626.  
  2627. @TryMenuBarEntry
  2628.             subq    #4, sp                ; save space for result
  2629.             clr.l    -(sp)                ; ID = 0, Item = 0 ===> menu bar entry
  2630.             _GetMCEntry                    ; get menu bar's color entry
  2631.             move.l    (sp)+, d1            ; get the result, and set/un-set z-flag
  2632.             beq.s    @SetDefault            ; couldn't find menu bar entry so use black/white
  2633.  
  2634.             move.l    d1, a0                ; get color record ptr in A0
  2635.             move    #mctRGB3, d0        ; offset for items default color
  2636.             pea        (a0,d0)                ; push foreground color
  2637.             pea        mctRGB2(a0)            ; push background color
  2638.             bra.s    @DoTheSet            ; and branch to do the actual color setting
  2639.  
  2640. @SetDefault
  2641.             pea        RGBBlack            ; use black as default forecolor
  2642.             pea        RGBWhite            ; use white as default background color
  2643.  
  2644. @DoTheSet    tst        invertFlag(a6)        ; normal or inverted colors ?
  2645.             beq.s    @2                    ; 0 = normal colors, so branch
  2646.  
  2647.             _RGBForeColor                ; set fore/back colors
  2648.             _RGBBackColor
  2649.             bra.s    @SetColorsDone
  2650.  
  2651. @2            _RGBBackColor                ; set back/fore colors
  2652.             _RGBForeColor
  2653.  
  2654.             bra.s    @SetColorsDone
  2655.  
  2656. ;+++        ELSE                            ;===============================================
  2657. @SetBW
  2658.             moveq    #BlackColor, d0
  2659.             move.l    d0, -(sp)
  2660.             moveq    #WhiteColor, d0
  2661.             move.l    d0, -(sp)
  2662.  
  2663.             tst        invertFlag(a6)        ; normal or inverted colors ?
  2664.             beq.s    @3                    ; 0 = normal colors, so branch
  2665.  
  2666.             _ForeColor
  2667.             _BackColor
  2668.             bra.s    @SetColorsDone
  2669.  
  2670. @3            _BackColor
  2671.             _ForeColor
  2672.  
  2673. ;+++        ENDIF
  2674.  
  2675. ;<<<<<--------------------------------------<<<<<
  2676.  
  2677. @SetColorsDone
  2678.  
  2679.             rts
  2680.  
  2681. ;-----------------------------------------------------------------------------------------------
  2682. ; PROCEDURE PlotAnySizeIcon(theRect: Rect; theIcon: IconHandle; iconSize: Point;
  2683. ;                            rowBytes: Integer)                                        <FJLPMAB205>
  2684. ;
  2685. ;    Plots a given icon of arbitrary size at a given place in your local coordinate system.
  2686. ;
  2687.  
  2688. PlotAnySizeIcon
  2689.                 LEA        ICONBITMAP,A1            ;get address of icon mgr bitMap
  2690.                 MOVE.L    10(SP),D0                ;get the icon handle
  2691.                 BEQ.S    DONEIPLOT                ;if NIL, dont plot
  2692.                 MOVE.L    D0,A0                    ;get iconHandle in address reg
  2693. ;
  2694.                 MOVE.L    (A0),(A1)+                ;icon mptr is the base address
  2695.                 MOVE    4(sp),(A1)+                ;set up rowBytes
  2696.                 CLR.L    (A1)+                    ;set up topLeft
  2697.                 MOVE.L    6(SP),(A1)                ;set up botRight
  2698. ;
  2699.                 MOVE.L    14(SP),D1                ;get theRect
  2700.                 LEA        IconBitMap,A1            ;point A1 at bitmap again
  2701. ;
  2702. ; push parameters for copyBits call
  2703. ;
  2704.                 MOVE.L    A1,-(SP)                ;source bitMap is iconBitMap
  2705.                 MOVE.L    GrafGLOBALS(A5),A0        ;get lisaGraf global baseaddress
  2706.                 MOVE.L    THEPORT(A0),A0            ;get thePort
  2707.                 PEA        PORTBITS(A0)            ;that's the destination bitmap
  2708. ;
  2709.                 PEA        BOUNDS(A1)                ;boundsRect of bitmap is source
  2710.                 MOVE.L    D1,-(SP)                ;theRect is the destination
  2711.                 CLR.W    -(SP)                    ;theMode is srcCopy (0)
  2712.                 CLR.L    -(SP)                    ;no mask region
  2713.                 _CopyBits                        ;let Bill blit those bits
  2714.  
  2715. DONEIPLOT        MOVE.L    (SP)+,A0                ;get return address
  2716.                 ADD        #14,SP                    ;strip 12 bytes of parameters
  2717.                 JMP        (A0)                    ;return to caller
  2718.  
  2719. ;
  2720. ;--------------------------------------------------------------------------------------------
  2721. ;
  2722. ;    End of Code.  Begin Data Definitions.
  2723. ;
  2724. ;--------------------------------------------------------------------------------------------
  2725.  
  2726.             ; bounds rect for hier arrow is top=0, left=0, bottom=$10, right=$10
  2727.  
  2728. HierArrow    DC.W    $0000, $0000, $0020, $0030, $0038, $003C, $003E, $003F
  2729.             DC.W    $003E, $003C, $0038, $0030, $0020, $0000, $0000, $0000
  2730.  
  2731.             ; bounds rect for down arrow is top=0, left=0, bottom=$10, right=$10
  2732.  
  2733. DownArrow    DC.W    $0000, $0000, $0000, $0000, $0000, $7FF0, $3FE0, $1FC0
  2734.             DC.W    $0F80, $0700, $0200, $0000, $0000, $0000, $0000, $0000
  2735.  
  2736.             ; bounds rect for up arrow is top=0, left=0, bottom=$10, right=$10
  2737.  
  2738. UpArrow        DC.W    $0000, $0000, $0000, $0000, $0000, $0200, $0700, $0F80
  2739.             DC.W    $1FC0, $3FE0, $7FF0, $0000, $0000, $0000, $0000, $0000
  2740.  
  2741.             END                        ; of menu defproc!!
  2742.  
  2743.