home *** CD-ROM | disk | FTP | other *** search
- ; TrackPopUp.a
- ; by Steve Brecher
- ; Copyright 1987 Software Supply
- ; All Publication Rights Reserved
- ; Permission is hereby granted to translate this source code work to
- ; computer-executable object or machine code and to distribute the translation
- ; without restriction. However, this work may not be published in printed
- ; form without express permission of the copyright holder.
- ; If this routine is incorporated in a software product, the author would
- ; appreciate (but does not require) credit where feasible.
-
- ; Set tabs to 10
-
- Load 'MacDefs.d' ;all of the Apple-supplied EQUates
-
- ; This code makes extensive use of "Pascal-ish" macros. The macros are
- ; identical to those which are supplied in the ProgStructMacs.a file that
- ; comes with MPW 2.0 (forthcoming as of May 1987) with a couple of exceptions:
- ; I use "Subr" instead of "Procedure"; and my version of the "Call" macro
- ; automatically generates an Import for any routine which is undefined.
- ; Refer to the MPW Asm listing output file to see the macro expansions.
- ; The Asm listing will also supply (in the object code portion) the values
- ; of symbols and that might not be defined in older EQUate files.
-
- Load 'SBMacs.d'
-
- ;
- ; function TrackPopUp(MHndl: MenuHandle;
- ; thePt: Point; {starting cursor location}
- ; crsrItem: integer; {item# of item to be initially under cursor}
- ; ): integer; {item# of selected item, 0 if none}
- ;
- ; Call this routine when the user clicks on something which should present a
- ; pop-up menu. Pass the global location of the click in thePt. If the menu is
- ; to be drawn such that the cursor is initially in the first item, pass 1 in
- ; crsrItem; if in the second item, pass 2, etc.
- ;
- ; Notes:
- ; --This code will work on all Macintosh products from 128K to Mac II, including
- ; Mac XL. If the large menu bar option is enabled with a Radius FPD, the
- ; pop up menu will use the special 16-point FPD font.
- ; --CalcMenuSize(MHndl) must have been called prior to calling TrackPopUp (it need be
- ; called only once at program startup if the items aren't changed).
- ; --PopUpMenuSelect is used only on a Mac II even if the trap is otherwise
- ; available. This is because PopUpMenuSelect is perceptibly slower than our
- ; own code when running on, e.g., a Mac Plus. PopUpMenuSelect is available
- ; on any Mac running System 4.1 or later; this routine can be shortened by
- ; about half if altered to assume the trap is always available.
- ; --The code tests for the existence of the PopUpMenuSelect trap and an
- ; up-to-date MDEF even when running on a Mac II, for historical reasons.
- ; --If there is insufficient memory to create a handle for saving the bits under
- ; the menu, MemErr will be set, no menu will display, and 0 will be returned.
- ; This doesn't apply when the _PopUpMenuSelect trap is used; the trap is smart
- ; enough to cause an update event for the area under the menu if it can't get
- ; RAM for saving the bits.
- ; --thePt is assumed to be on the main screen (i.e., within screenBits.bounds).
- ; --Menu edges are guaranteed to be at least 1 pixel from the sides of the screen
- ; and at least 2 pixels from the menu bar or bottom of the screen. The
- ; crsrItem argument will not be honored if the menu has to be moved up/down
- ; more than half an item in order fulfill the 2-pixel guarantee. The 2-pixel
- ; margin is necessary for compatibility with the PopUpMenuSelect trap.
-
- ; --The Control Panel setting for chosen item flashes is overridden by the
- ; following value if the Panel setting is larger. To honor the Panel setting,
- ; set the following value to 128.
- MaxFlashes Equ 128 ;limit flashes of chosen item to this
-
- Export Function TrackPopup(MHndl:L, thePt: L, crsrItem):W
- Var theBitMap:bitMapRec, SavePort:L, saveItem
- Var ColorMenu, SaveRGBBackColor:6
- Begin Save=D3-D6/A2-A4
-
- ; This code will make use of an application global, MenuBarHt: integer, which
- ; contains the menu bar height. If the application does not supply such
- ; a global, comment out the following line, and conditional assembly directives
- ; below will adapt to its absence.
- Import MenuBarHt:Data ;remove if not available in appl globals
-
- if &Type('MenuBarHt') = 'UNDEFINED' then
- MoveQ #20,D4 ;menu bar height if 64K ROM
- Tst ROM85
- Bmi.S @0
- Move MBarHeight,D4 ;128+K ROM
- @0
- else
- MoveQ #0,D4
- Move MenuBarHt(A5),D4
- endif
- Move D4,TopMenuItem ;needed for new MDEF, doesn't hurt old
-
- Call _GetPort(SavePort(FP):A)
- Move.L WmgrPort,A2
- Call _SetPort(A2:L)
-
- Call FPDHndl ;Radius FPD info handle in A0 <> nil?
- Beq.S CalcPos ;no
- Move.L (A0),A0 ;yes...
- Btst #5,1(A0) ;FPD big menu bar in use?
- Beq.S CalcPos ;no
- Call SetFPD(#$0100) ;yes, set largeFontEnable:=true, dontReposition=false
- Move #16,txSize(A2) ;use special 16 point Chicago
- MoveQ #-1,D0
- Move D0,CurFMFamily ;invalidate FM cache...
- Move D0,FONDID
-
- CalcPos Call _CountMItems:W(MHndl(FP):L),D2
- Move.L MHndl(FP),A0
- Move.L (A0),A0
- Move.L menuWidth(A0),D1 ;D1.hi=width, D1.lo=height
- MoveQ #0,D0
- Move D1,D0 ;height
- Divu D2,D0 ;height per item
- Move D0,D3
- Sub crsrItem(FP),D2 ;number of items to be below cursor
- Mulu D2,D0 ;height of items below cursor
- Move D3,D2
- Lsr #1,D2 ;D2 = half of an item's height
- Add D2,D0 ;height below cursor
- Sub D0,D1 ;height above cursor
- MoveQ #2,D2 ;const for later
- Move.L thePt(FP),D0
- Swap D0
- Sub.L D1,D0 ;left, top of rect
- Swap D0 ;top, left of rect
- AddQ #8,D0 ;shift it so cursor is 8 in from right
- Cmp D2,D0 ;too far left? (min margin 1 to left of frame)
- Bge.S @0 ;no
- Move D2,D0 ;yes, shift it right: left=2, frame at 1
- @0 Lea theBitMap+bounds(FP),A3
- Sub.L OneOne,D0 ;top left of frame
- Move.L D0,(A3)
- Move.L menuWidth(A0),D1
- Swap D1 ;height, width
- Add.L #$30003+8,D1 ;height, width incl. frame & shadow
- ;and extra right margin for balance
- Add.L D1,D0 ;bot,right of shadow
- Move.L (A5),A0
- Move.L screenBits+bounds+botRight(A0),D2
- SubQ #2,D2
- Sub D0,D2 ;margin of at least 1 to right?
- Bpl.S @1 ;yes
- Add D2,D0 ;no, move left...
- Add D2,left(A3)
- @1 Swap D2 ;screenBits.bounds.bottom
- SubQ #3,D2
- Swap D0 ;right, bot of frame
- Sub D0,D2 ;margin of at least 2 on bottom?
- Bpl.S @2 ;yes
- Add D2,D0 ;no, move up...
- Add D2,top(A3)
- @2 Swap D0
- Move.L D0,botRight(A3) ;bot, right of shadow
- Move MenuBarHt(A5),D2
- AddQ #2,D2
- Sub top(A3),D2 ;too high?
- Ble.S @3 ;no, ok
- Add D2,top(A3) ;yes, move down
- Add D2,bottom(A3)
-
- @3 Cmp #$3FFF,ROM85 ;Mac II or later?
- Sls ColorMenu(A6) ;tentatively, true if color Mac
- Bhi.S @5 ;earlier than Mac II
- Move #$9F,D0 ;unimplemented core routine
- _GetTrapAddress NewTool
- Move.L A0,A1
- MoveQ #$0B,D0
- _GetTrapAddress NewTool ;_PopUpMenuSelect installed?
- Cmp.L A0,A1
- Beq.S @5 ;no
- Bsr MDEFHandle
- Move.L (A0),A0
- Cmp #10,10(A0) ;got the right MDEF for PopUpMenuSelect?
- Blo.S @5 ;no
- SubQ #4,SP ;yes, use _PopUpMenuSelect; result space
- Push.L MHndl(FP)
- Call _InsertMenu((SP):L, #-1) ;must be "hierarchical"
- MoveQ #1,D2
- Add top(A3),D2 ;top excl frame
- Move thePt+v(FP),D0
- Sub D2,D0 ;height above cursor
- Ext.L D0
- Divu D3,D0 ;items above one cursor is to be in
- Move D0,D1
- Mulu D3,D0 ;height above top of cursor's item
- Add D2,D0 ;top of cursor's item
- Push D0
- Push left(A3)
- AddQ #1,(SP) ;excl frame
- AddQ #1,D1
- Push D1 ;cursor's item
- _PopUpMenuSelect
- Pop TrackPopUp(FP)
- Pop A0
- Beq.S @4
- Move A0,TrackPopUp(FP)
- @4 Bra Done
-
- @5 Clr TrackPopUp(FP)
- Add #15,D1 ;calc shadowed rowbytes...
- Lsr #4,D1
- Add D1,D1
- Move D1,D0 ;D0 = rowbytes
- Move D0,rowBytes-bounds(A3)
- Swap D1 ;D1 = height
- Mulu D1,D0 ;byte size
- _NewHandle ;get handle for saved bits
- Bne RstFPD ;whoops
- Push.L A0 ;save handle on stack for later
- Move.L (A0),baseAddr-bounds(A3) ;save the pixels in the menu's area...
- Call _CopyBits(portBits(A2):A, baseAddr-bounds(A3):A, A3:L, A3:L, #srcCopy, #0:L)
-
- Tst.B ColorMenu(FP) ;color Mac?
- Beq.S @7 ;no
- Call _GetMCEntry:L(#0:L),D3 ;color menu?
- Sne ColorMenu(FP) ;remember to restore backcolor if so
- Beq.S @7 ;no
- Move.L WMgrCPort,A2 ;yes, use color WMgrPort for drawing
- Call _SetPort(A2:L)
- Call _GetBackColor(SaveRGBBackColor(FP):A) ;save old backcolor
- Move.L D3,A0 ;menu color table's menubar entry
- Call _RGBBackColor(mctRGB2(A0):A)
-
- @7 Call _ClipRect(portRect(A2):A)
- Move.L OneOne,D3
- Sub.L D3,botRight(A3) ;rect sans shadow
- Call _EraseRect(A3:L)
- Call _FrameRect(A3:L)
- Push right(A3) ;draw shadow...
- Push top(A3)
- AddQ #3,(SP)
- Push.L botRight(A3)
- Push left(A3)
- AddQ #3,(SP)
- Push bottom(A3)
- _MoveTo
- _LineTo
- _LineTo
- Call _InsetRect(A3:L, D3:L) ;rect sans frame
-
- Sub top(A3),D4 ;D4 = -(dist from top of popup to menu bar)
- Swap D4
- Call _SetOrigin(D4:L) ;fool MDEF, which draws top at v=menubar ht
- Call _OffsetRect(A3:L, D4:L) ;and adjust our rect accordingly
- Call _ClipRect(A3:L) ;clip to inside of frame
-
- MoveQ #mDrawMsg,D0 ;draw the items
- Bsr CallMDEF
-
- TrackIt: Call _GetMouse(thePt(FP):A)
- MoveQ #mChooseMsg,D0
- Bsr CallMDEF
- Call _WaitMouseUp:B(),CC
- Bne.S TrackIt
-
- MouseUp: Move TrackPopUp(FP),saveItem(FP)
- Beq.S NoFlash
- Move menuFlash,D4
- Beq.S NoFlash
- Move.L thePt(FP),D5
- SubQ #1,D4 ;adjust menu flash for DBra
- Cmp #MaxFlashes-1,D4 ;limit per EQU (after Dbra adjust)
- Bls.S @0
- MoveQ #MaxFlashes-1,D4
- @0 Clr.L thePt(FP)
- Bsr Flasher
- Move.L D5,thePt(FP)
- Bsr Flasher
- Dbra D4,@0
- Move saveItem(FP),TrackPopUp(FP)
-
- NoFlash: Call _SetOrigin(#0:L) ;restore WMgr(C)Port's origin
- Call _ClipRect(portRect(A2):A) ;and restore its clipRgn
- Clr D4
- Neg.L D4
- Call _OffsetRect(A3:L, D4:L) ;restore rect to 0-origin basis
- Call _InsetRect(A3:L, #-1:D0) ;restore bits, incl frame
- Add.L D3,botRight(A3) ;and incl shadow
- Tst.B ColorMenu(FP) ;restore back color if we changed it...
- Beq.S @0
- Call _RGBBackColor(SaveRGBBackColor(FP):A)
- Move.L WMgrPort,A2 ;revert to old style port for CopyBits
- Call _SetPort(A2:L)
- @0 Call _CopyBits(baseAddr-bounds(A3):A, portBits(A2):A, A3:L, A3:L, #srcCopy, #0:L)
- Pop.L A0 ;bits handle
- _DisposHandle
-
- RstFPD: Call SetFPD(#0) ;if FPD, largeFontEnable := false
- Beq.S Done ;no FPD
- Clr txSize(A2) ;must clear after DisposHandle if FPD
- MoveQ #-1,D0
- Move D0,CurFMFamily ;invalidate FM cache...
- Move D0,FONDID
-
- Done: Call _SetPort(savePort(FP):L) ;restore port
- Return
-
- Flasher MoveQ #mChooseMsg,D0
- Bsr.S CallMDEF
- Move #3,A0
- _Delay
- Rts
-
- CallMDEF: Push D0 ;msg
- Bsr.S MDefHandle ;A0 = MDEF Handle, A1 = MenuHandle
- _HLock
- Move.L (A0),A0
- Push.L A1 ;menu handle
- Push.L A3 ;rect
- Push.L thePt(FP)
- Pea TrackPopUp(FP)
- Jsr (A0)
- Bsr.S MDefHandle
- _HUnlock
- Rts
-
- MDefHandle:
- Move.L MHndl(FP),A1
- Move.L (A1),A0
- Move.L menuDefHandle(A0),A0
- Rts
-
- EndP
-
- FPDHndl Proc Export ;sets A0 = Radius INFO handle, CCR Z flag reflects
-
- Call _GetNamedResource:L(#'INFO':L, FPDName:A),D0
- Move.L D0,A0
- Rts
-
- Export SetFPD
-
- ; Procedure SetFPD(Bytes4And5: integer)
- ; if FPD exists, set values of byte 4 = largeFontEnable and byte 5 = dontReposition
- ; Sets Z flag if no FPD (Beq NoFPD)
-
- SetFPD: Bsr.S FPDHndl
- Beq.S @0
- Push.L A0
- Move.L (A0),A0
- Move 4+4(SP),4(A0)
- Clr.L 6(A0) ;always use FPD default cursor routine
- Push.L #'INFO'
- Push0
- Pea FPDName
- _AddResource
- MoveQ #-1,D0 ;clear Z flag
- @0 Pop.L A0
- AddQ #2,SP
- Jmp (A0)
-
- String Pascal
- FPDName: DC.B 'Radius Display'
-
- End