mac-rom/Toolbox/MenuMgr/MenuMgr.a
Elliot Nunn 4325cdcc78 Bring in CubeE sources
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included.

The Tools directory, containing mostly junk, is also excluded.
2017-12-26 09:52:23 +08:00

4582 lines
181 KiB
Plaintext

;
; File: MenuMgr.a
;
; Contains: Menu Manager for MacIntosh User Interface ToolBox
;
; This file contains the MacIntosh menu manager, which is based on Bill AtkinsonÕs
; Lisa menu manager.
;
; Written by: Andy Hertzfeld
;
; Copyright: © 1982-1993 by Apple Computer, Inc. All rights reserved.
;
; Change History (most recent first):
;
; <20> 11/5/93 IH Sync with Excelsior.
; <SM19> 6/14/93 kc Roll in Ludwig (this replaces SM16).
; <LW5> 5/3/93 chp Flush the caches for MDEF handles smaller than 32 bytes. It used
; to be 16 bytes, but a 22-byte, unflushed, fake defproc has been
; discovered in Software Ventures Microphone II and Microphone
; Pro. (RADAR #1082386)
; <LW4> 3/8/93 fau Modified the <SM16> checkin to only flush the cache for those
; MDEFs that are only 16 bytes or less in size. See the comment
; for more description.
; <SM18> 5/21/93 CSS Remove call and import of SMgrCalcRect in InitMenus routine per
; P. Edberg's review.
; <SM17> 1/12/93 CSS Rollin a patch from MenuMgrPatch.a to syncronize the keyboard
; menu within draw menubar. Fixes Radar bug #1057927.
; <SM16> 11/18/92 CSS Cache flush hack to get Persuasion to work without putting
; cache flushing back in hlock. I am cache flushing when I
; call the MDEF.
; <SM15> 11-06-92 jmp MenuSelect was NOT preserving A2, so I fixed it.
; <SM14> 11/5/92 SWC Changed PackMacs.a->Packages.a.
; <SM13> 8/13/92 JSM Changes from where no man has gone before: change references to
; MrMacHook to MBarHook to avoid confusing future generations,
; move call to SetTickCounters in MenuSelect after menuDelaySave
; and menuDragSave are set up, get rid of unused local tRect1 in
; MenuSelect, put back in the RTS at the end of InitMenus that was
; mysteriously deleted long ago.
; <SM12> 6/22/92 RB Rolled-in the Help Manager patch to MenuSelect from
; BalloonPthc28.a, HMMenuSelectPatch and cleaned up MenuSelect a
; little bit.
; <SM11> 6/12/92 CS Roll-in Reality Changes:
; <31> 6/12/92 FM Remove obsolete call to the internal ScriptMgr routine SwapIcon.
; <30> 6/1/92 DTY Remove InsrtResMenu from this file. Always use the one from
; MenuMgr.c. Make GetIndex an Exported procedure so that it can
; be used from MenuDispatch.a in the ROM build.
; <29> 5/24/92 JSM DonÕt use forTesting (always false), TearOffMenus (always
; false), or ScriptMgrKeyboardMenu (always true) conditionals.
; <28> 5/14/92 KSM #1028474,<DCC>: Speed up MenuKey by not upper-casing the command
; key character for a menu item when there isnÕt one (ASCII NULL).
; <27> 5/14/92 KSM #1029927,<DCC>: Roll back to version <19> (what an unbelievable
; mess!).
; <SM10> 5/27/92 JSM Changes from Reality: DonÕt use forTesting (always false) or
; TearOffMenus (always false). NOTE: Before this file is rolled
; back into Reality, someone needs to put back in all the forROM
; and hasCQD conditionals Philip deleted. This file ¥is¥ used in
; System builds, and is patched in on non-color QD machines.
; <SM9> 4/8/92 PN Fix previous header
; <SM8> 4/8/92 PN Throw out extraneous push and pop stackpointer in SetMenuBar
; <SM7> 4/6/92 PN Change GetMenuBar to the way it was. forROM condition does
; belong here after all. ScriptMgrKeyboardMenu condition needs to
; be investigated and either put back in or leave out .
; <SM6> 4/3/92 PN Clean up patch roll-ins to make them more readable. Changes are
; in DrawMenuBar/HiliteMenu/GetMenubar/SetMenuBar and alse get rid
; of forROM and hasCQD conditions since this file is used in ROM
; only
; <5> 3/24/92 PN Back out FixBTSTBugInMenuKey since it's been rolled in already.
; Eliminate the forROM condition
; in Upchar to use only the correct version. Roll in
; PatchMDDrawMenuBar,PatchMDHiliteMenu, PatchMDMenuKey,
; PatchMDMenuSelect from ModalDialogMenuPatches.a.
; <4> 3/9/92 PN Roll in HMClearMenuBarPatch PatchProc _ClearMenuBar from
; Balloonptch28.a
; <2> 2/13/92 PN ; Roll in FixBTSTbuginMenuKey, SetMenuBarAddsSystemMenus,
; GetMenuBarDoesNotReturnSystemMenus, Savea5AroundCallMDEFPRoc,
; DrawMenuBarIfInvalidOnMenuSelect,
; DrawMenuBarIfInvalidOnHiliteMenu, ValidateMenuBarWhenDrawing,
; PatchInsertMenu in SystemMenuPatch.a
; <> ¥ÊHMClearMenuBarPatch still needs to be rolled in ¥
; <1> ¥ Pre-SuperMario comments follow ¥
; <26> 1/25/92 csd In order to let Cube-E go alpha, IÕm reversing the change to
; GetMenuBar that was made in <22> (the change history says it was
; made in <24>) since it doesnÕt work.
; <25> 1/21/92 PN Get rid of duplicate EQU in MenuMgr.a
; (CmdChar,MenuResult,mItemResult,searchMenu HorRMenus,KeyFrame)
; <24> 1/21/92 PN Rolled in SetMenuBarAddsSystemMenus from SystemMenusPatch.a
; Rolled in GetMenuBarDoesNotReturnSystemMenus from
; SystemMenusPatch.a
; Rolled in PatchInsertMenu from SystemMenusPatch.a
; Rolled in ValidateMenuBarWhenDrawing from InvalMenuBarPatch.a
; Rolled in DrawMenuBarIfInvalidOnHiliteMenu from
; InvalMenuBarPatch.a
; Rolled in FixBTSTBugInMenuKey from MenuMgrPatch.a
; <23> 1/20/92 PN Roll in patches into MenuMgr.a, in this file using the routine
; InsrResMenu from MenuMgr.c
; <22> 1/20/92 PN Roll-in all the linked patches into MenuMgr.a
; <21> 12/31/91 RB Undo change <20>, I tell you.. you gotta read the change
; history...nice try
; <20> 12/31/91 RB Added an END directive to get rid of the warning.
; <19> 10/10/91 PKE #1012672, For Cube-E (and Bruges): Use new SCUpperText routine
; in MenuKey instead of UpperText, so we are independent of any
; grafPort font.
; <18> 8/28/91 JSM Leave InsrtResMenu here for ROM builds for now.
; <17> 8/22/91 KSM csd,#Bruges: Change MenuKey to call _UpperText instead of
; _UprString,MARKS (in the subroutine UpChar). This is the
; internationally correct routine (new for 7.0). 2) Conditionalize
; out InsertResMenu here, now in MenuMgr.c
; <16> 7/9/91 JSM Remove obsolete 7.0 related SysVers conditionals.
; <15> 3/31/91 dba gbm, csd: change DisposeMenu so it handles properly the case
; when a resource-based menu has been purged
; <12> 3/6/91 gbm dba: Take out change <11>, because Philip didnÕt understand that
; this would break the system build.
; <11> 3/5/91 PN Fix the warning by putting back the END statement at the end
; <10> 12/14/90 KSM <dba>Fix bug in MenuKey where it is BTSTing a register for each
; item, but when the item is greater than 31, the BTST instruction
; wraps and we get flags for previous items.
; <9> 9/28/90 KSM <dba>Guarantee A5 world for calls into MDEFs.
; <8> 9/15/90 KSM Patch InsMenuItem to fix a PixelPaint bug!!*!
; <7> 7/30/90 KSM On the first day Ed was gone, we found a bug he created in
; version 2. An arbitrary line in ÒMenuChangedÓ was commented out.
; <6> 7/26/90 KSM fix DarinÕs stupid STRING ASIS bug
; <5> 7/23/90 dba change name of GetItemStyle so it doesnÕt conflict with glue
; <4> 5/13/90 SMB Removed SMgr patches in InitMenus and DrawMenuBar if not
; ÔForROMÕ since adding the Keyboard Menu. Will not patch out the
; ROM version of InitMenus since its call to SMgrCalcRect is
; harmless. However, am patching the SMgr's SwapIcon routine
; (called by DrawMenuBar) to do nothing. Need ScriptPriv.a all the
; time now due to the new flag used here.
; <3> 4/29/90 KSM Fix a bug in SetItemProperty which only is a bug if we turn on
; TearOffMenus againÉ
; <2> 12/19/89 EMT PROCize for more efficient dead code stripping. Nuked
; GetMenuInfo. Rearranged procedures for better branches. Renamed
; topEdge and leftEdge to not conflict with ColorEqu.a
; <1.9> 11/17/89 dba got rid of checks for 64K ROMs
; <1.8> 10/31/89 dba concatenated source files MenuMgr1.a and MenuMgr2.a to this one
; <2.7> 8/29/89 KSM Uses new vector routines to call Script Manager from RAM
; <1.9> 8/22/89 SES Changed mctSanityChk (which was in nFiles) to mctReserved (which
; is the official equ).
; <1.6> 8/22/89 SES removed references to nFiles.
; <2.5> 8/16/89 dba NEEDED FOR 6.0.4: InitProcMenu bug fixed: MBDF ID was not put in
; MenuList if MenuList was already allocated (InitMenus already
; called)
; <2.4> 8/8/89 dba NEEDED FOR 6.0.4: used TearOffMenus conditional; fixed
; InitProcMenu
; <2.3> 7/11/89 EMT Backed out 07Sep88 change to InitProcMenu to make Excel 2.2
; happy. Needed for Aurora, Esprit, and 6.0.4.
; <2.2> 6/14/89 JSM Fixed System 7.0 IF statement (700 => $700).
; <2.1> 6/14/89 KSM Fixed stack handling.
; <2.0> 6/14/89 DAF Added missing Big Bang conditional.
; <1.9> 6/14/89 KSM Added command key tear off method
; <1.7> 6/14/89 KSM Fixed incorrect branch offset
; <1.4> 6/5/89 CCH Conditionalized out include of MenuDispatch.a.
; <1.8> 6/2/89 KSM Changed all (NOT forRAM) to (forROM).
; <1.6> 6/2/89 KSM Updated conditionals for ROM/SYS build
; <1.3> 6/2/89 KSM Added include for MenuDispatch.
; <1.5> 6/1/89 KSM TEAR OFF MENU feature added.
; <1.4> 4/29/89 KSM Updated comments for 1.3
; <1.3> 4/25/89 KSM Fixed GetMenuBar bug <BRC#41545> to check for NIL MenuList and
; returns NIL instead of crashing. This problem exists because
; MultiFinder "faceless" applications donÕt call
; InitWindows/InitMenus, but they do call SystemTask or
; WaitNextEvent which allows drivers to run. Drivers (like Deneba
; SoftwareÕs Spelling Coach) which call GetMenuBar when the
; Backgrounder is running - CRASH.
; Also Fixed DelMCEntries bug <BRC#40826> to correctly delete
; the entries in the table correctly (not just 1st one). Also
; keeps it from running rampant thru memory if next to last was
; deleted.
; <1.2> 2/20/89 rwh re-spelled conditional in comment, wonÕt show up in searches.
; <1.1> 11/10/88 CCH Fixed Header.
; <1.0> 11/9/88 CCH Adding to EASE.
; <1.5> 11/2/88 GGD Got rid of machine specific conditionals in favor of feature
; based conditionals.
; <1.4> 10/27/88 PKE added script manager support for initmenus
; <1.3> 10/7/88 rwh make NuMac support work for MvMac as well
; <¥1.2> 10/3/88 EMT Roll in latest bug fixes.
; <¥1.2> 9/23/88 CCH Got rid of inc.sum.d and empty nFiles
; PMAB568> 9/7/88 EMT Fix DeleteMenu so that highlighted menus are unhighlighted
; before being deleted. Custom menus should blink; fix ill-fated
; C222. Call MenuHook in CheckDragging And some miscellaneous code
; cleanup.
; PMAB568> 9/7/88 EMT AppendMenu calls CharByte to make sure meta characters are real.
; PMAB539> 7/19/88 EMT PopUpMenuSelect will now call CalcMenuSize when it invalidates
; sizes.
; <PP467> 4/18/88 DHD Fix InsertMenu patch to compare with -1 instead of checking
; negative for BeforeIDÕs throughout the code. This was already
; done for the first test, but subsequent ones were missed. See
; PMAB214.
; <¥1.1> 3/22/88 EMT Roll in menu manager patches from 6.0 system.
; PMAB417> 3/3/88 EMT Patch GetMenuBar and SetMenuBar to handle saved bits correctly.
; <PB403> 2/24/88 DBG Fixed bug in PMAB364 which caused crash in PopupMenuSelect.
; PMAB364> 1/23/88 EMT Fix Pop-up menus to come up on any screen
; PMAB303> 11/21/87 EMT Use ROM override to install MBDF from S297 instead of
; MBDFPatchHndl.
; PMAB282> 9/20/87 FJL DonÕt let DelMenuItem fool with EnableBits when item > 31.
; PMAB280> 9/18/87 FJL Set MBarEnable around SystemMenu call only if MBar not already
; owned by DA.
; PMAB280> 9/18/87 FJL Removed some overzealous lines added in PMAB255
; PMAB255> 9/1/87 FJL Call HiliteMenu around DrawMenuBar so donÕt leave any bits
; behind dangling.
; PMAB255> 8/31/87 FJL DonÕt insert enable bit if item is > 31
; PMAB233> 8/7/87 FJL HiliteMenu must do nothing if MBarHeight <= 3.
; PMAB214> 7/20/87 FJL InsertMenu inserts in HMenuList if (beforeID == -1) rather than
; (<= -1)
; <PM213> 7/20/87 FJL Check HwCfgFlags for valid PRAM when getting HMenu drag and
; delay settings
;
; System 4.2
;
; 3/26/87 FJL Changed MenuKey so that popups may have menu keys.
; <PMA133> 3/24/87 DAF Fixed DelMenuItem to call DelMCEntry only on nuMac.
; 3/6/87 FJL Clean up all NuMac conditionals for System Disk <1.2>
; <C844> 2/22/87 FJL New routines, GetItemCmd, SetItemCmd, PopUpMenuSelect
; <C826> 2/17/87 FJL Fixed FlashMenuBar to pass MenuList offset to mbarproc rather
; than menuID.
; <C808> 2/13/87 FJL Changed AddResMenu to call IUMagString. To do so needed to lock
; the menuHandle. This causes problems with Munger since it canÕt
; relocate the locked block. Therefore only lock the handle around
; the IUMagString call.
; <C466> 12/2/86 FJL EnableItem and DisableItem now ignore items > 31.
; <A428> 11/20/86 FJL Interesting problem in HiliteMenu
; <C408> 11/15/86 FJL Added support for color menus
; <A/C391> 11/10/86 FJL Use GetResource to get the mbarproc each time we call it.
; <C341> 11/2/86 RDC Added pad char to menu table for asm problem
; <C338> 11/2/86 RDC Changed equ name to fix asm problem
; <A278> 10/27/86 FJL The application OVERVUE assumed D1 was clear on exit from
; MenuSelect, so we clear it for them (cough cough)
; <C222> 10/15/86 FJL Added hierarchical menus.
; <C175> 10/1/86 FJL Exported InitProcMenu.See notes in MenuMgr1.a for fix to
; MenuSelect bug, etc.
; <C174> 9/24/86 DAF New menuBar defproc menu manager. See StandardMBDF.a also
; <C174> 9/24/86 DAF Updated MenuSelect for menuBar defproc
; <C169> JTC Cleaned up GetTheMDef/UnlkMDef for 32-bit robustness.
; 8/20/86 DAF Menu Bar DefProc modifications (see StandardMBDF.a)
; <C175> 8/8/86 FJL Fix to InitProcMenu and InitMenus for possible _GetResource
; error. Problem when moved mouse out of menu bar quickly, fixed
; with change in MenuSelect. Scrolling menus were drawing outside
; of their region, so set ClipRect in DrawTheMenu. Changed
; InitMenus so doesnÕt realloc menu struct if global menuList is
; not NIL (this allows InitWindows to call InitMenus to get
; MBarHeight without reallocing space when user calls InitMenus).
; Fix to _HiliteMenu -- when HiliteMenu was called with a
; non-existent menuID it would store that ID in theMenu global and
; cause the mbarproc to flip the bar when HiliteMenu(0) was next
; called.
; <C60> 6/30/86 EHB Made MenuSelect save off more bits for color.
; 4/10/86 SAB rolled in a patch from ROM75 to fix inserting into the middle of
; a resmenu.
; 2/19/86 BBM Made some modifications to work under MPW
;
; Lonely Hearts ROMs (Macintosh Plus)
;
; 11/2/85 EHB Reinstated call to _TextFont in InsertMenu (no one should change
; it, but...).
; 9/30/85 EHB Removed underline of FONDs in AddResMenu (put back CalcMenuSize)
; 9/6/85 EHB GetItemProperty was clearing a word result instead of a byte.
; 8/5/85 EHB .DEF CalcMBHeight for use by wmgr
; 8/5/85 EHB Modified for variable sized system font
; 7/9/85 EHB Get MDEF 0 from ROM map
; 5/21/85 EHB Made AddResMenu, InsertResMenu sort items as they go in
; 5/9/85 EHB Added new procedure InsMenuItem -- like append menu, but inserts
; anywhere. Now AppendMenu,InsMenuItem,AddResMenu,InsrtResMenu all
; share same insert code.
; 5/7/85 EHB In AddResMenu, make sure each name added is unique. Compare is
; done using CompString, also used by the Res Manager for
; getNamedResource.
; 5/3/85 EHB Oops! forgot to delete enable bits in DelMenuItem. All better
; now.
; 4/23/85 EHB In Insert/AddResMenu, if adding 'FONT', add 'FOND' too.
; 4/15/85 EHB Added new procedure DelMenuItem -- remove a menu item from its
; menu
; 4/15/85 EHB In routine MenuKey, use UprString to upshift the passed
; keystroke.
; 4/11/85 EHB Check for purged menuList and menu on all internal references If
; purged, I generate DS #54 (MenuPrgErr).
; 4/11/85 EHB Made menus of 0 size work. To do this, tweaked DirtyMenuSize to
; invalidate size with -1 instead of 0.
; 4/9/85 EHB Do GetMouse after WaitMouseUp to avoid invalid flashes CLR.L
; FuncResult(A6) to avoid returning invalid items
; 3/13/85 EHB Fixed stack frame for MenuSelect
; 3/13/85 EHB Fixed stack offset in DirtyMenuSize (oops!)
; 3/6/85 EHB Use update to restore menus if out of memory
; 3/5/85 EHB Added Routine DirtyMenuSize so that CalcMenuSize only gets
; called before drawing.
; 3/5/85 EHB Call CalcMenuSize, if necessary, before drawing
; 3/5/85 EHB In AddResMenu, preserve state of resLoad
; 1/24/85 EHB In SetItemProperty, donÕt CalcMenuSize if item = check mark
; 1/24/85 EHB Preserved the clip region in FlashMenuBar
; 1/24/85 EHB Tweaked DrawTheMenu to not save the menu bar
; 1/24/85 EHB Reset alarm parity in DrawMenuBar
; 9/7/83 AJH save in DrawMBar
; 8/27/83 AJH saved a little code in CalcMenuSize (use common subroutine)
; 8/27/83 AJH Made it include "SysErr"
; 8/27/83 AJH handled out of memory case in SaveBits by deep-shitting
; 8/23/83 BLH (with LAK) Fixed bug in GetMHandle (didnÕt return result!)
; 8/19/83 AJH Moved loc of menu flash bits.
; 8/13/83 SC The code scrunch-a-matic pass... Made NoIndex fall into GotIndex
; Moved getIndex, invertTitle. Added utility GetNInvert. Made
; saveBits inline.
; 8/9/83 AJH Made it reference "WmgrGray"
; 6/30/83 AJH fixed bug in InsrtResMenu when thereÕs none of that type
; 6/15/83 AJH Added InsrtResMenu
; 6/14/83 AJH made SetItem call CalcMenuSize
; 5/18/83 AJH fixed GetMHandle bug
; 5/11/83 AJH Added CountMItems
; 5/6/83 AJH fixed PlotIcon bug (didnt set up topLeft)
; 4/28/83 AJH moved calcMenuSize into the defProc
; 4/21/83 AJH Made CalcMenuSize add some extra for command line
; 4/17/83 AJH Made MenuKey know about desk ornament menus
; 4/13/83 AJH Tweaked MBarEnable logic in MenuSelect
; 4/4/83 AJH Made it get menuFlash from parameter RAM
; 3/18/83 AJH Made InvertTitle go one pixel higher
; 3/16/83 AJH Made CalcMenuSize not bold disabled items
; 3/15/83 AJH Made Enable/DisableItem not recalc menu size
; 2/13/83 AJH Made PlotIcon use copyBits instead of XferRect
; 2/5/83 AJH Changed "AddRsrcMenu" to "AddResMenu" to keep Caroline happy
; 2/5/83 AJH AddRsrcMenu -> AddResMenu; made it not load the objects
; 1/28/83 AJH Added "FlashMenuBar"
; 1/28/83 AJH Improved CalcMenuSize
; 1/25/83 AJH Fixed outline/shadow reversal bug
; 1/25/83 AJH Fixed MenuSelect mouse-ahead problem
; 1/24/83 AJH Added support for deskOrns stealing the menuBar
; 1/23/83 LAK Adapted for new equate files.
; 1/21/83 AJH Fixed bug in GetSizeLeft in SetItem
; 1/20/83 AJH Fixed purged defProc problem (lock after LoadResource)
; 12/27/82 AJH Moved menuData to end of block; defProc as resource
; 12/19/82 AJH Added "AddRsrcMenu" call
; 12/11/82 AJH Made space between menus less wide (14 pixels)
; 11/22/82 AJH Made TextMenuProc and CalcMenuSize externally accessible
; 11/16/82 AJH Made the menuBar 4 pixels wider
; 11/7/82 AJH Made menuKey case insensitive
; 10/25/82 AJH Made space between menus wider for 512 dots (12 -> 18)
; 10/16/82 AJH Made it independent of screen size (use wmgr^.portRect)
; 10/10/82 AJH Converted to QuickDraw Trap Interface
; 9/20/82 AJH Fixed problem in DeleteMenu
; 9/7/82 AJH Added "DrawMBar" entry point
; 9/7/82 AJH Made DrawMBar a separate routine to save code
; 8/22/82 AJH Got rid of menu manager dependency on icon manager
; 8/2/82 AJH Converted for new memory manager; no more ohÕs!
; 7/24/82 AJH Fixed left corner problem in DrawMenuBar
; 6/29/82 AJH New today.
;
;-------------------------------------------------------------------------
;
; Conditional Definitions and Includes
;
;-------------------------------------------------------------------------
string asis
LOAD 'StandardEqu.d'
include 'InternalMacros.a' ;<SM5> <PN>
include 'DialogsPriv.a' ;<SM5> <PN>
INCLUDE 'ColorEqu.a'
INCLUDE 'MenuMgrPriv.a'
INCLUDE 'Packages.a' ; for IUMagString
INCLUDE 'ScriptPriv.a' ; <1.7> for Ram vectors to ScriptMgr internal routines
INCLUDE 'Balloons.a' ;
INCLUDE 'BalloonsPriv.a' ;
IMPORT Find6BOFromID
MACHINE MC68020 ; needed for cache flush <LW2> fau
GetParamRamData PROC ENTRY
;------------------------------------------------
; Utility -- GetParamRamData <FJL C222>
;------------------------------------------------
; Get menuDelay and menuDrag tick counts from
; parameter ram and store in mbSaveLoc
;
; Trashes: A0, D0
move.l mbSaveLoc, a0 ; get mbSaveLoc lo-mem
move.l (a0), a0 ; dereference
move.b #0, mbMenuDelay(a0) ; set default in case no new pram <FJL PM213>
move.b #0, mbMenuDrag(a0) ; ditto
btst #5, HwCfgFlags ; is larger pram valid ?
beq.s @SetLowMem ; no -> branch, no pram
lea mbMenuDelay(a0), a0 ; a0 has address of buffer
moveq #1, d0 ; want one byte
swap d0 ; put #1 in hi-byte
move #menuDelay, d0 ; param ram address in lo-byte
_ReadXPRam
move.l mbSaveLoc, a0 ; get mbSaveLoc lo-mem
move.l (a0), a0 ; dereference
lea mbMenuDrag(a0), a0 ; a0 has address of buffer
moveq #1, d0 ; want one byte
swap d0 ; put #1 in hi-byte
move #menuDrag, d0 ; param ram address in lo-byte
_ReadXPRam
@SetLowMem move.l mbSaveLoc, a0 ; see if need to set defaults
move.l (a0), a0 ; dereference
tst.b mbMenuDelay(a0)
bne.s @1 ; not zero --> donÕt set default
addi.b #8, mbMenuDelay(a0) ; default == 8 Ticks (tried and true by FJL)
@1 tst.b mbMenuDrag(a0)
bne.s @GetParmDone ; not zero --> donÕt set default
addi.b #60, mbMenuDrag(a0) ; default == 1 second (no reason not to be huge
; default value because of way dragging works)
@GetParmDone
rts
ENDPROC
InitProcMenu PROC EXPORT
; Begin <2.3 EMT>
;
; procedure InitProcMenu ( mbResID : integer);
;
; The resID is stored in the MenuList header as a word at location $4. <FJL C428>
; The low 3 bits of mbResID are used as the variant!! The whole mbResID <FJL 23Jan87>
; is used as the resID.
;
; This routine performs the same function as InitMenus, except it allows
; specification of the MBDF resID rather than assuming MBDF=0.
;
;
; MBarProc routine <C175>
;
move.l (sp)+,a0 ; get the return address <2.4>
move.w (sp)+,d1 ; get the MBDF resource ID <2.4>
move.l a0,-(sp) ; put return address back on the stack <2.4>
IMPORT IMCommon
bra IMCommon ; go join InitMenus <2.4>
; End <2.3 EMT>
ENDPROC
INITMENUS PROC EXPORT
;
; PROCEDURE InitMenus -- initialize the menu manager by allocating an empty menuList
;
MOVEQ #0,D1 ; standard rom based MBDF is #0 <DAF 20Aug86>
ENTRY IMCommon
IMCommon ; D0 contains resID now. <PMAB568 07Sep88 EMT> <2.4>
MOVE.W #MapTRUE,ROMMapInsert ; set flag to load from ROM <DAF 20Aug86>
SUBQ #4,SP ; make room for function return <DAF 20Aug86>
MOVE.L #'MBDF',-(SP) ; load the standard menu bar defProc <DAF 20Aug86>
MOVE.W D1,-(SP) ; push the resID <DAF 20Aug86>
_GetResource ; load it <DAF 20Aug86>
move.l (SP)+, MBDFHndl ; save defproc handle in lomem <C175 FJL>
bne.s @gotIt ; if handle not NIL, then continue <C175 FJL> <PMAB568 07Sep88 EMT>
TST.W D1 ; standard rom based MBDF is #0 <PMAB568 07Sep88 EMT>
BNE.S INITMENUS ; Try the default <PMAB568 07Sep88 EMT>
MOVE.W #dsMBarNFnd,D0 ; if defproc could not be loaded, die <DAF 20Aug86>
_SysError ;
@gotIt ; <PMAB568 07Sep88 EMT>
; InitApplZone clears MenuList global. <C175 FJL>
; If it is NIL, then init data structures, <C175 FJL>
; else they are already inited, so return. <C175 FJL>
move.l MenuList,d0 ; test the menu list handle <2.5>
ble.s CreateMenuList ; if NIL then menu list needs to be created <2.5>
move.l d0,a0 ; get the menu list; it already exists <2.5>
move.l (a0),a0 ; dereference the menu list <2.5>
move.w d1,mbResID(a0) ; store MBDF ID <2.5>
bra.s IMDone ; now, weÕre done <2.5>
CreateMenuList
bsr.s InitMList ;allocate and initialize a menuList block <FJL C222>
MOVE.L A0,MENULIST ;make it the current menuList
MOVE.L (A0), A0 ; get the menuPtr <PMAB568 07Sep88 EMT>
move.w D1, mbResID(a0) ; store resID <FJL C428> <PMAB568 07Sep88 EMT>
clr theMenu ; clear lo mem so no hilited menu <FJL C222>
move.l a1, MenuCInfo ; store the color table too <FJL C408>
IMPORT GetMBColors
bsr GetMBColors ; get menubar color info from the system <FJL C408>
MOVEQ #$0C,D0 ;only use 2 bits worth
AND.B SPMisc2,D0 ;get pRam flags
LSR #2,D0 ;get menuFlash in the low bits
MOVE D0,MenuFlash ;set up menuFlash field
CLR.W MBarEnable ;initally, application owns MBar
CLR.L MBarHook ;<SM13> init MBarHook
CLR.L MENUHOOK ;init user hook
; tell the MBarProc to init any data structures
MOVEQ #3,D0 ; set up for the init message <DAF 20Aug86>
MOVE.L #0,D1 ; parameter is 0 for cleared bar only <DAF 20Aug86>
IMPORT CallMBarProc
BSR CallMBarProc ; execute the defproc,ignoring the result <DAF 20Aug86>
IMPORT GETPARAMRAMDATA
bsr GETPARAMRAMDATA ;read MenuDrag/MenuDelay into mbSaveLoc
_ClearMenuBar ;initialize menuBar parameters and clear it
_DrawMenuBar
IMDone
RTS ; <SM13> this was mistakenly deleted at some point
; InitMList allocÕs a menuList with no menus and no hierarchical menus <FJL C222>
ENTRY InitMList
InitMList
moveq #mctEntrySize, d0 ; allocate one record in the color tbl <FJL C408>
_NewHandle ; <FJL C408>
move.l (a0), a1 ; dereference
move #mctLastIDIndic, mctID(a1) ; store -99 as ID ==> last entry <FJL C408>
move.l a0, -(SP) ; store it on the stack temporarily <FJL C408>
moveq #InitMListSize, d0 ; get size of menuList d.s.
_NewHandle CLEAR ; alloc it
move.l (a0), a1 ; dereference the handle
;set up the menu header
move.w #mbMenu1Loc, lastRight(a1) ; set lastRight to ten (decimal)
move.l (SP)+, a1 ; get the color tbl handle in a1 <FJL C408>
rts
ENDPROC
GetMBColors PROC ENTRY
;-----------------------------------------------
; Utility -- GetMBColors
;-----------------------------------------------
; See if there is a menubar color table entry. It will automatically look for one in <FJL C408>
; the applications resfile then in the system res file. <FJL C408>
;
move.b #1, -(SP) ; force Resource Load to true
_SetResLoad
subq #4, SP ; make room for the result
move.l #'mctb', -(SP) ; push resource type
clr.w -(SP) ; push menuID 0 = menu bar
_GetResource ; get the resource
move.l (SP)+, a0 ; get the handle in a0
move.l a0, d0 ; set z-flag
beq.s @1 ; handle is nil, so no color table
_HGetState ; get state of resource
move.b d0, -(SP) ; store them on the stack
move.l a0, -(SP) ; store handle on stack too
_HLock ; lock the handle down temporarily
move.l (a0), a0 ; get ptr to resource
move (a0)+, -(SP) ; push number of table entries
move.l a0, -(SP) ; push base address of table
_SetMCEntries ; call trap
move.l (SP)+, a0 ; get handle
move.b (SP)+, d0 ; and previous state
_HSetState ; return handle to previous state
@1 rts
ENDPROC
CLEARMENUBAR PROC EXPORT
;
; PROCEDURE ClearMenuBar -- clear the menuBar/menuList data structure
;
;¥HMClearMenuBarPatch roll in from BalloonPatch28.a
IMPORT ptchHMGetBalloons
JSR ptchHMGetBalloons ; what is the state of What Is? mode?
BEQ.S @BalloonsOff ; EQ means no, so, let's not do anything.
SUBQ #2,SP ; remove any balloons that might have been up
_HMRemoveBalloon ; do the remove
TST.W (SP)+ ; toss result
@BalloonsOff
IMPORT GetA0List
BSR GetA0List ; check for purged list <EHB 11-Apr-85>
MOVE.L MENULIST,A0 ; get handle to menuList
_DisposHandle ; dispose of the handle <FJL C222>
move.l MenuCInfo, a0 ; get handle to color tbl <FJL C408>
_DisposHandle ; and toss it <FJL C408>
IMPORT InitMList
bsr InitMList ; init a new one <FJL C222>
move.l a0, menuList ; and store it <FJL C222>
move.l a1, MenuCInfo ; and store it too <FJL C408>
IMPORT GetMBColors
bsr GetMBColors ; get menubar color info from the system <FJL C408>
CLR.W THEMENU ; no menu is hilited
RTS
ENDPROC
GetMenuRgn Proc Export
; Utility GetMenuRgn -- returns the region occupied by the MenuBar.
;
Move.l (Sp)+,D0 ; Save the return address.
Move.l (Sp)+,D1 ; Get the callerÕs RgnHandle.
Move.l D0,-(Sp) ; Restore return address.
Moveq #12,D0 ; Call MBarProc to return RgnHandle.
Import CallMBarProc
Bsr CallMBarProc ; Call the DefProc.
Rts
Endproc
CalcMBHeight PROC EXPORT ; <EHB 5 Aug 85>
; call MBarProc to calc height <FJL 11Mar87>
MOVEQ #6,D0 ; set up for the height message, no params
EXPORT CallMBarProc ; <FJL C222>
CallMBarProc
;-------------------------------------------------------------------------------------------
;
; Utility -- CallMBarProc
;
; On Entry: d0 lo-word=message number, hi-word=parameter1 <FJL 3Feb87>
; d1 parameter2
; Use: a0
; On Exit: d0 return value
;
; mbResID: comes from menuList
; mbVariant: the low 3 bits of mbResID are the variant
;
; Note that we store the MBDFÕs Hndl in low memory location MBDFHndl but this is for
; convenience only. We do not count on its being there between calls to this utility.
;
;-------------------------------------------------------------------------------------------
movem.l d4, -(SP) ; save work register
CLR.L -(SP) ; make room for defproc return <DAF 20Aug86>
MOVE.L MenuList,A0 ; get the menuList head <DAF 20Aug86>
MOVE.L (A0),A0 ; handle->pointer <DAF 20Aug86>
move mbResID(a0), -(SP) ; get resource ID <FJL C428><24Jan87>
andi.w #0007, (SP) ; use low 3 bits only <FJL 24Jan87>
MOVE.W D0,-(SP) ; push the message number <DAF 20Aug86>
swap d0 ; get parameter1 in lo-word
move.w d0, -(SP) ; push parameter1 <FJL 3Feb87>
MOVE.L D1,-(SP) ; push parameter2 <DAF 20Aug86>
;
; get the mbarproc each time we call it instead of counting on low mem to be correct <FJL A/C391>
;
subq #4, SP ; space for return result
move.l #'MBDF', -(SP)
move mbResID(a0), -(SP) ; get resource ID
MOVE.W #MapTRUE,ROMMapInsert ; set flag to load from ROM <DAF 20Aug86>
_GetResource
move.l (SP)+, MBDFHndl
MOVE.L MBDFHndl,A0 ; get the menu bar defproc handle
_HGetState ; get the current state
move.l d0, d4 ; save state in d4
_HLock ; lock it
MOVE.L (A0),A0 ; get a pointer to it
JSR (A0) ; jump to it
; returned from defproc, return handle to previous state before exiting
MOVE.L MBDFHndl,A0 ; get the handle
move.l d4, d0 ; get previous state from d4
_HSetState ; reset previous state
MOVE.L (SP)+,D0 ; get the defproc return
movem.l (SP)+, d4 ; restore work register
RTS ; and return
ENDPROC
DELETEMENU PROC EXPORT
;
; PROCEDURE DeleteMenu(menuID: INTEGER) -- delete a given menu from the menuList.
; Note that deleteMenu will not de-allocate the menu, since it may be in other
; menuLists.
;
; Look first in the Hmenu list, then in the regular menu list <FJL C222><FJL 4Mar87>
; Delete all color table entries for this menuID <FJL C408>
MOVE.W theMenu, D0 ; Get the currently highlighted menu <PMAB568 07Sep88 EMT>
CMP.W 4(SP), D0 ; Is it this one? <PMAB568 07Sep88 EMT>
BNE.S @NotHilited ; Nope, skip <PMAB568 07Sep88 EMT>
CLR.W -(SP) ; <PMAB568 07Sep88 EMT>
_HiliteMenu ; Unhighlight it <PMAB568 07Sep88 EMT>
@NotHilited ; <PMAB568 07Sep88 EMT>
move 4(SP), -(SP) ; push the menuID <FJL C408>
move #mctAllItems, -(SP) ; push flag meaning all items <FJL C408>
_DelMCEntries ; call delete routine <FJL C408>
moveq #0, d1 ; clear d1 for GetHIndex <FJL C222>
MOVE.W 4(SP),D1 ; get the menuID
IMPORT GetHIndex
bsr GetHIndex ; try H Menu <FJL C222>
bne.s @FoundHMenu ; found a HMenu so delete it <FJL C222>
IMPORT GetIndex
BSR GETINDEX ; get the index into D0
beq.s TwoBytExit ; didnÕt find either, so nada to delete <FJL C222>
@FoundMenu
IMPORT GetA1List
BSR GetA1List ; get menuList into A1 <EHB 11-Apr-85>
CMP.W LASTMENU(A1),D0 ;is this one the last one?
BNE.S @OneLessMenu ;if not, go and delete it
; special case deleting the last menu
; make lastRight = old menuLeft
MOVE.W MenuLeft(A1,D0),lastRight(A1) ;set new lastRight
@OneLessMenu SUBQ #6,LASTMENU(A1) ; one less menu in list
bra.s @MungeIt ; and delete it <FJL C222>
@FoundHMenu
IMPORT GetHA1List
bsr GetHA1List ; get HMenuList into A1 <FJL C222>
subq #6, lastHMenu(a1) ; one less menu in list <FJL C222>
@MungeIt moveq #0, d1 ; clear all of d1
move.w d0, d1 ; move low word of d0 only, hiword has garbage
move.l menuList, a0 ; get menuList handle
move.l (a0), a0 ; dereference
adda.l d1, a0 ; get pointer to 6 bytes to be deleted
subq #4, SP ; space for result
move.l menuList, -(SP) ; move the menuList handle onto the stack
move.l d1, -(SP) ; d1 has offset into menuList or HMenuList
move.l a0, -(SP) ; ptr to target string
moveq #6, d0 ; len1 = 6 bytes
move.l d0, -(SP)
moveq #4, d0
move.l d0, -(SP) ; make replacement string non-NIL so deletes properly
; just point at an even byte in low-mem
clr.l -(SP) ; and its length is zero ===> delete
_Munger ; oooohhh -- aaaahhh -- do it baby
addq #4, SP ; ignore dem results
MOVEQ #2,D0 ; set up for the menu-edge-calc msg
CLR.L D1 ; calc entire bar
IMPORT CallMBarProc
BSR CallMBarProc ; execute the defproc
; Now delete all of the entries in the color table for this
ENTRY TwoBytExit
TWOBYTEXIT MOVE.L (SP)+,A0 ;get return address
ADDQ #2,SP ;strip parameter
JMP (A0) ;return to caller
ENDPROC
GetHIndex PROC ENTRY
;---------------------------------------------------------------------------------------------
;
; GetHIndex is similar to GetIndex but it looks thru the hierarchical menu list for a <FJL C222>
; menu of the given menuID. The menuID is passed in D1 and the index is returned in <FJL C222>
; D0. If the menuID canÕt be found, D0 returns zero. If D1 = $FFFFFFFF then D0 returns <FJL C222>
; the index to the HMenu header info. The z-flag can be used to determine if one was <FJL C222>
; found.
;
move.l d3, -(SP) ; save work register
tst.l d1 ; is index 0?
beq.s @HNotFound ; if so, return 0
IMPORT GetA1List
bsr GetA1List ; get menuList ptr into a1
move lastMenu(a1), d2 ; get # regular menus
addq #6, d2 ; now d2 has index to H Menu header info
cmpi.l #$FFFFFFFF, d1 ; is index = $FFFFFFFF?
beq.s @GotHIndex ; yes, so return index to H Menu info
; no, so look thru H Menus
move (a1,d2), d3 ; get # hierarchical menus
beq.s @HNotFound ; if none then H Menu not found
; there are H Menus, so search them for the rsrcID in D1
add d2, d3 ; d3 is now index to last H Menu
exg d2, d3 ; d2 - index to last H Menu
; d3 - index to H Menu header info
@GetHILoop move.l menuHOH(a1,d2), a0 ; get the handle
move.l (a0), a0 ; get the pointer
cmp menuID(a0), d1 ; is this the right menuID
beq.s @GotHIndex ; yes, so return
@ChkNxtIndex subq #6, d2 ; bump down to next entry
cmp d2, d3 ; are we at the H Menu header info?
bne.s @GetHILoop ; no, so continue checking
; yes, drop thru and return 0 meaning not found
@HNotFound moveq #0, d2
;
; take the index in d2 and return it in d0
;
@GotHIndex move.l (SP)+, d3 ; restore work register
move d2, d0 ; get index in d0 and set z-flag
rts
ENDPROC
EXPORT GETINDEX
GETINDEX PROC ENTRY
;---------------------------------------------------------------------------------------------
;
; GetIndex is a utility routine that returns an index into the menuList given a
; menuId. The menuId is passed in D1 while the index is returned in D0. If the
; menuId can't be found, D0 will return a zero. A0, A1 and D2 are trashed.
; The Z-flag can be used to determine if one was found. As a special bonus, on
; exit A0 points to the menu, if a menu was found.
;
TST D1 ; is index 0?
BEQ.S NOINDEX ; if so, return 0
IMPORT GetA1List
BSR GetA1List ; get menuList into A1 <EHB 11-Apr-85>
MOVE LASTMENU(A1),D2 ; get # of menus
BEQ.S NOINDEX ; if none, say we can't find it
;
; here is the search loop. Get the next handle, and check the menuID
;
GILOOP MOVE.L MENUOH(A1,D2),D0 ; get the handle
MOVE.L D0,A0 ; get handle in A-reg
MOVE.L (A0),A0 ; handle -> pointer
CMP MENUID(A0),D1 ; is this the one?
BEQ.S GOTINDEX ; if they match, we're done
;
NEXTINDEX SUBQ #6,D2 ; bump to next entry
BNE.S GILOOP ; loop if there's more to do
;
; we couldn't find it so return zero in D0
;
NOINDEX MOVEQ #0,D2 ; return 0
;
; we found it so return index in D0
;
GOTINDEX MOVE D2,D0 ; get index in D0
RTS
ENDPROC
INSERTMENU PROC EXPORT
;
; PROCEDURE InsertMenu(menu: menuInfoHandle; beforeId: INTEGER);
;
; insert a menu into the menuList. beforeID is the menuID of the menu
; that the new menu should be inserted before. If beforeID canÕt be found,
; the new menu is inserted at the end of the list. If the menu is already
; in the list, donÕt insert it
;
; If beforeID = -1 then insert menu at front of HMenuList <FJL C222>
; Used < 0 as the criteria for inserting in HMenus, changed to = -1 <FJL 8May87>
; Roll in PatchInsertMenu in SystemMenuPatch.a
; When this patch sees a system menu (-16385 thru -32768), it adds it to the system menu bar.
; If the system menu bar doen't exist, this patch creates it.
; If the menu is not a system menu, ensure that the beforeID is modified so that the
; menu is inserted before the system menu partition.
IMPORT FindFirstSystemMenu6BO
InsertStack RECORD {base},DECR
ParamBegin: EQU * ; start parameters after this point
menuHdl DS.L 1
beforeID DS.W 1
ParamSize: EQU ParamBegin-*
retAddr DS.L 1
base DS.W 0
LocalSize: EQU *
ENDR
WITH InsertStack
CMP.W #$FFFF, beforeID(SP) ; beforeID = -1 ==> H Menu
beq OldInsertMenu
; If a system menu is being inserted, put it into the System Menu Bar
MOVE.L menuHdl(SP), A0 ; Get the MenuHandle
MOVE.L (A0), A0 ; dereference
SUBQ.L #4,SP ; Make Room for result & VAR
MOVE.W menuID(A0),-(SP) ; Push the menuID
PEA 4(SP) ; Point to VAR
_IsSystemMenu ; Do it the standard way
ADDQ.L #2,SP ; Eat the result
TST.B (SP)+ ; Is it a system menu?
BNE.S @DoSystemMenu ; EQ means it is a system menu
; Menu for main list, be sure it is inserted before all the system menus
BSR FindFirstSystemMenu6BO ; Find the system menu partition
beq OldInsertMenu ; Do old stuff if no system menus
MOVE.W D0, D1 ; Save off 6BO of 1st system menu
MOVE.W beforeID(SP), D0 ; Get the beforeID
BEQ.S @forceBeforeSys ; branch if zero
BSR Find6BOFromID ; Find its offset
BEQ.S @forceBeforeSys ; branch if the beforeID not in list
CMP.W D1, D0 ; Is it after the system partition?
ble OldInsertMenu ; No, do as caller wanted
MOVE.W D0, D1 ; It is after the system partition
@forceBeforeSys ; the beforeID must be changed to before the 1st system menu
MOVE.L MenuList, A0 ; get the menulist
MOVE.L (A0), A0 ; deref
MOVE.L menuOH(A0,D1.W), A0 ; get the menuhandle to insert before
MOVE.L (A0), A0 ; deref
MOVE.W menuID(A0), beforeID(SP) ; Make beforeID be 1st system menu
bra OldInsertMenu ; Now go do it
@DoSystemMenu
; If menuID already exists in system menulist, we're done!
MOVE.L MenuList, A1 ; Save Menulist
MOVE.L SystemMenuList, MenuList ; Store system as menulist
JSR Find6BOFromID ; Is this menuID already in the list?
MOVE.L A1, MenuList ; Restore Menulist
TST.W D0 ; Was the menuID found?
BNE.S @Done ; Don't double insert it, done.
; Swap the two menu lists so this menu inserts into the system menu
MOVE.W beforeID(SP), D0 ; Get the beforeID
BEQ.S @AddAtEnd ; Yes, branch
MOVE.L MenuList, A1 ; Save Menulist
MOVE.L SystemMenuList, MenuList ; Store system as menulist
JSR Find6BOFromID ; Look up the beforeID
MOVE.L A1, MenuList ; Restore Menulist
TST.W D0 ; Was the menuID found?
BNE.S @DoTheAdd
@AddAtEnd
MOVE.L SystemMenuList, A0 ; Get system menulist
MOVE.L (A0), A0 ; deref
MOVE.W lastMenu(A0), D0 ; Get last menu
ADDQ.W #6, D0 ; Insert "before" the end
@DoTheAdd
SUBQ.L #4, SP ; Make room for result
MOVE.L SystemMenuList, -(SP) ; handle
MOVE.W D0, -(SP) ; Move the offset
CLR.W -(SP) ; as a long with high cleared
CLR.L -(SP) ; ptr1 = 0
CLR.L -(SP) ; len1 = 0
PEA 6+20(SP) ; ptr2 = menuhandle parameter
MOVEQ.L #6, D0
MOVE.L D0, -(SP) ; len2 = 6
_Munger ; Munge away! Left coord will be junk.
ADDQ.L #4, SP ; Dump result
; Remember to update the lastMenu field
MOVE.L SystemMenuList, A0 ; Get system menulist
MOVE.L (A0), A0 ; handle -> ptr
ADDQ.W #6, lastMenu(A0) ; Bump the count
@Done
MOVE.L (SP)+, A0 ; Get the return address
ADDQ.L #ParamSize, SP ; Cut back the parameters
JMP (A0)
OldInsertMenu
movem.l d3/a3-a4,-(SP) ; save working registers
cmp.w #$FFFF, 16(SP) ; beforeID = -1 ==> H Menu <FJL 8May87>
beq.s @InsertHMenu ; yes, so branch <FJL C222>
IMPORT GetA0List
BSR GetA0List ; get menuList into A0 <EHB 11-Apr-85>
MOVE.L A0,A3 ; get pointer into A3 <EHB 11-Apr-85>
move.l 18(SP),a0 ; get menuInfoHandle
move.l (a0),a0 ; get ptr to menu block
MOVE menuID(a0), d1 ; get menuId of menu to be installed
IMPORT GetIndex
BSR GETINDEX ; is it already in the list?
BNE @DONEINSERT ; donÕt insert same one twice
move.w 16(SP),d1 ; get beforeID
BSR GETINDEX ; get index into menuList of beforeID menu
bne.s @AllocEntry ; if we found one, branch and insert it
; the "beforeID" menu was not in the list, so insert this one at the end of the list
MOVE LASTMENU(A3),D0 ; get # of menus in menuList.
addq #6, d0 ; and insert this one AFTER it <FJL C222>
BRA.S @AllocEntry ; go insert it
;
; insert a H Menu at the front of the HMenuList if id not already in the HMenuList <FJL C222>
@InsertHMenu
IMPORT GetHA0List
bsr GetHA0List ; get ptr to HMenuList in A0
move.l a0, a3 ; and save it in a3
move.l 18(SP), a0 ; get menuInfoHandle
move.l (a0),a0 ; get ptr to menu block
moveq #0, d1 ; clear d1 (for GetHIndex call)
move menuID(a0), d1 ; get menuId of menu to be installed
IMPORT GetHIndex
bsr GetHIndex ; is it already in the list?
bne.s @DoneInsert ; donÕt insert same one twice
addq #6, lastHMenu(a3) ; bump total of HMenus
move.l MinusOne, d1 ; set up for GetHIndex call
bsr GetHIndex ; get index to HMenuList header info in d0
addq #6, d0 ; point to first entry in HMenuList
;
; Now, use _Munger to insert space into the new, wild and wooly, dynamic menuList.
;
; allocate 6 bytes and store the menuInfoHandle in it
@AllocEntry moveq #0, d3 ; clear d3
move.w d0, d3 ; store menuList offset in d3
clr.l TempRect ; use TempRect for temp data
clr.l TempRect+4 ; clear temp data loc first
lea TempRect, a0
move.l 18(SP), menuOH(a0) ; init regular menu, store the menuInfoHandle <PP467 18Apr88>
cmp.w #$FFFF, 16(SP) ; beforeID = -1 ==> H Menu <PP467 18Apr88>
;// tst.w 16(SP) ; is this a H Menu? <PP467 18Apr88>
beq.s @InitHEntry ; yes, so init header info differently <PP467 18Apr88>
IMPORT GetA1List
bsr GetA1List ; get menuList ptr in A1, A3 could be bad! <FJL CXXX>
addq #6, lastMenu(A1) ; bump total number of menus
;// bra.s @MungeIt ; and continue <DHD PP467>
@InitHEntry ;////move.l 18(SP), menuHoH(a0) ; store menuInfoHandle <PP467 18Apr88>
;
; now Munge those 6 bytes into the menuList
;
@MungeIt subq #4, SP ; space for result
move.l menuList, -(SP) ; move the menuList handle onto the stack
move.l d3, -(SP) ; d3 has offset into menuList
clr.l -(SP) ; no target string
clr.l -(SP) ; len1 = 0 ===> want an insert
move.l a0, -(SP) ; push replacement string
move.l #6, -(SP) ; and itÕs length
_Munger ; oooohhh -- aaaahhh -- do it baby
addq #4, SP ; ignore dem results
cmp.w #$FFFF, 16(SP) ; beforeID = -1 ==> H Menu <PP467 18Apr88>
;// tst.w 16(SP) ; is this a H Menu? <DHD PP467>
beq.s @DoneInsert ; yes, so no need for menu-edge recalc <DHD PP467>
MOVEQ #2,D0 ; set up for the menu-edge-calc msg <DAF 20Aug86>
CLR.L D1 ; calc entire bar
IMPORT CallMBarProc
BSR CallMBarProc ; execute the defproc <DAF 20Aug86>
@DONEINSERT movem.l (SP)+,d3/a3-a4 ; restore registers
ENTRY SixBytExit
SIXBYTEXIT MOVE.L (SP)+,A0 ; get return address
ADDQ #6,SP ; strip parameters
JMP (A0) ; return to caller
ENDPROC
DrawMBar PROC EXPORT
; Utility DrawMBar -- clear the menuBar and draw the line underneath it, leaving
; the wmgrPort clipRgn clipped to it. This is a separate routine so InitWindows
; can call it to save code.
MOVEQ #0,D0 ; set up for the draw message <DAF 20Aug86>
MOVE.L #-1,D1 ; parameter is -1 for cleared bar only <DAF 20Aug86>
IMPORT CallMBarProc
BSR CallMBarProc ; execute the defproc <DAF 20Aug86>
RTS
ENDPROC
DRAWMENUBAR PROC EXPORT
;
; PROCEDURE DrawMenuBar -- draw the current menuList on the menuBar
;
; Call HiliteMenu around DrawMenuBar so that donÕt have dangling bits behind all around <FJL PMAB255>
; Clear the low memory bits whenever we draw the menu bar.
; <SM17> CSS
;Roll in SynchKeyboardMenuState Ñ Make sure the keyboard menu state corresponds to the
; applicationÕs desired setting (enable/disable) in the
; application-specific global flag, scriptDisableKybds
; from MenuMgrPatch.a, this patch says that it shouldn't be rolled in because the
; it should be in the process manager. Well, for 7.1 it is not in the process manager,
; so I am rolling it in anyways.
moveq #smKeySynchKbdMenuState,d0 ; Set up the KeyScript verb
move.w d0,-(sp) ; to just synchronize the keyboard menu
_KeyScript ; Do it.
;end Roll in SyncKeyboardMenuState
;Roll in ValidateMenuBarWhenDrawing
bclr #MenuBarInvalidBit,MenuBarInvalidByte ; clear the local invalid bit
bclr #MenuBarGlobalInvalidBit,MenuBarGlobalInvalidByte ; clear the global invalid bit <6>
;Roll in PatchMDDrawMenuBar from ModialDiaglogMenuPatches.a <PN> <SM5>
import PushMenuState,PopMenuState ;<PN> <SM5>
jsr PushMenuState ; Potentially save off the menu state <PN> <SM5>
Move.W TheMenu, -(SP) ; save off currently hilited menu <FJL PMAB255>
Clr.W -(SP) ; call HiliteMenu(0)
_HiliteMenu
BSET #7,AlarmState ; reset alarm parity <EHB 1/24/85>
MOVEQ #0,D0 ; set up for the draw message <DAF 20Aug86>
MOVE.L #0,D1 ; parameter is non-neg to draw bar text <DAF 20Aug86>
IMPORT CallMBarProc
BSR CallMBarProc ; execute the defproc <DAF 20Aug86>
_HiliteMenu ; TheMenu is already on the stack. <FJL PMAB255>
jsr PopMenuState ; Restore the menu state if it was saved <PN> <SM5>
RTS
ENDPROC
FlashMenuBar PROC EXPORT
;------------------------------------------------------------------------------------
;
; FlashMenuBar
;
;------------------------------------------------------------------------------------
;
; PROCEDURE FlashMenuBar(menuID: INTEGER);
;
; FlashMenuBar inverts the title of a given menu item. If the menuID is 0,
; it inverts the whole menu bar.
;
; No longer is it possible to have more than one menu hilited at once due to saving <FJL 28Jan87>
; the bits behind the menu title. This routine has been changed so that when
; menuID <> 0 if TheMenu=MenuID then it clears that menu, else it just uses the HilitMenu code.
;
tst 4(SP) ; test menuID
beq.s @FlashWholeBar ; menuID == 0 ==> flip bar
move theMenu, d0 ; get currently hilited menu
beq.s @DoHiliteMenu ; if no menu hilited, then use HiliteMenu code
cmp 4(SP), d0 ; flashing currently hilited menu ?
bne.s @DoHiliteMenu ; no ==> so use HiliteMenu code
; yes ==> so turn this title off
move 4(SP), d1 ; get menuID of new selection <FJL C826>
IMPORT GetIndex
bsr GetIndex ; convert ID to offset in menuList <FJL C826>
beq.s @FlashExit ; couldnÕt find in list, so exit <FJL C826>
IMPORT TurnIndexOff
bsr TurnIndexOff ; MenuList offset is in D0 <FJL C826>
clr theMenu ; clear low-mem theMenu to show no menu hilited
IMPORT TwoBytExit
bra TwoBytExit
@DoHiliteMenu
IMPORT HiliteMenu
bra HiliteMenu ; menuID <> 0 ==> use HiliteMenu code
@FlashWholeBar ; call mbarproc to invert menu.
MOVEQ #0,D0 ; menuIndex = 0 ==> flip bar
IMPORT TurnIndexOn
BSR TurnIndexOn ; call mbarproc
@FlashExit BRA TwoBytExit ; save code by returning thru common label
ENDPROC
TurnIndexOff PROC ENTRY
;--------------------------------------------------------------------------------------------
; TurnIndexOff and TurnIndexOn take a menuIndex in D0 and set itÕs hilite state
; to the appropriate level. These calls replace InvertTitle.
;
; On Entry: D0 Offset into MenuList of menu to be hilited/unhilited
;
MOVEQ #0,D1 ; set hi word to 0 for normal text <DAF 20Aug86>
BRA TurnIndexCom ;
ENTRY TurnIndexOn
TurnIndexOn
MOVEQ #1,D1 ; set hi word to one for selected text <DAF 20Aug86>
TurnIndexCom
SWAP D1 ;
MOVE.W D0,D1 ; set lo word to new selection <DAF 20Aug86>
MOVEQ #5,D0 ; set up the hilite message <DAF 20Aug86>
; fall thru to execute the defproc <DAF 20Aug86>
; returns to caller directly
IMPORT CallMBarProc
BRA CallMBarProc
ENDPROC
HILITEMENU PROC EXPORT
;
; PROCEDURE HiliteMenu(menuID: INTEGER); -- hilite the title of the menu with the
; specified menuID. Since only one menu can be hilited at a time, unhilite any other one
;
; if MBarHeight <= 3 then donÕt hilite. Otherwise MBarProc will save off a VERY LARGE
; handle for the bits behind the menu title.
; HiliteMenu draw menu bar if invalid
; ROLL IN ValidateMenuBarWhenDrawing
IMPORT ValidateMenuBar
jsr ValidateMenuBar
; Roll in PatchMDHiliteMenu
; The saves menus state, calls old HiliteMenu, then restores state
import PushMenuState,PopMenuState ;<SM5> <PN>
parametersStackFrame
menuID ds.w 1 ; the menuID <SM5> <PN>
endStackFrame
linkSave
jsr PushMenuState ; Potentially save off the menu state <SM5> <PN>
move.w menuID(a6),-(sp) ; Push the parameter <SM5> <PN>
Cmpi.W #3, MBarHeight ; is height > 3 <PMAB233 FJL>
Bgt.S @HeightOK ; yes -> ok
Bra.S HLNone ; no -> nope, skip entirely
; first, turn off the current hilited title if present
@HeightOK MOVE.W theMenu,D1 ; get the currently hilited menu
BEQ.S HLOn ; if theMenu is 0, then donÕt unhilite <DAF 20Aug86>
CMP.W (SP),D1 ; is this the currently hilited menu <DAF 20Aug86>
BEQ.S HLDone ; already hilited, so skip <DAF 20Aug86>
IMPORT GetIndex
BSR GetIndex ; convert to menuIndex
beq.s HLOn ; if zero, invalid menuID <FJL A466>
MOVEQ #0,D1 ; clear hi half for normal text
MOVE.W D0,D1 ; move to D1
MOVEQ #5,D0 ; set up the hilite message <DAF 20Aug86>
IMPORT CallMBarProc
BSR CallMBarProc ; execute the defproc <DAF 20Aug86>
; now, turn on the selected menu
HLOn
MOVE.W (SP),D1 ; get menuID of new selection <DAF 20Aug86>
BSR GetIndex ; convert to menuIndex
BEQ.S HLNone ; if zero, invalid menuID <FJL C175>
SWAP D0 ; save menuIndex in hi half
MOVE.W #1,D0 ; set hi word to one for selected text <DAF 20Aug86>
SWAP D0 ; flip half back to correct positions
MOVE.L D0,D1 ; copy to D1 for CallMBarProc
MOVEQ #5,D0 ; set up the hilite message <DAF 20Aug86>
BSR CallMBarProc ; execute the defproc <DAF 20Aug86>
HLDone
MOVE.W (SP)+,theMenu ; update theMenu <FJL C175>
bra Done
; donÕt store the menuID if we couldnÕt find the index. No index means the <FJL C175>
; menuID doesnÕt exist on the menu bar, and storing a non-existent menuID <FJL C175>
; in theMenu global causes the next HiliteMenu(0) to flip the bar (ugh-ly). <FJL C175>
HLNone ; get the return address <FJL C175>
addq.l #2, SP ; throw away the parameter <FJL C175>
clr.w theMenu ; update theMenu <FJL C175>
Done
jsr PopMenuState ; Restore the menu state if it was saved <SM5> <PN>
restoreUnlinkReturn
ENDPROC
ENABLEITEM PROC EXPORT
; PROCEDURE EnableItem(menuHandle,item) -- enable an item in a menu or, if the item
; number is zero, enable the entire menu. It has no effect if the item is already
; enabled.
;
IMPORT EnableFetch
BSR ENABLEFETCH ;set up registers with shared code
cmp #31, d0 ; is the item > 31 ? <FJL C466>
bhi.s EnableDone ; yes, so leave without updating flags <FJL C466>
BSET D0,D1 ;enable the item
ENTRY EnableCom
ENABLECOM
MOVE.L D1,MENUENABLE(A0) ; update the menuÕs flags
ENTRY EnableDone
EnableDone
IMPORT SixBytExit
BRA SIXBYTEXIT ; common exit saves code
ENDPROC
ENABLEFETCH PROC ENTRY
MOVE.L 10(SP),A0 ; get the menu handle
MOVE.L (A0),A0 ; handle to pointer
MOVE 8(SP),D0 ; get bit index
MOVE.L MENUENABLE(A0),D1 ; pick up current state of flags
RTS
ENDPROC
DISABLEITEM PROC EXPORT
;
; PROCEDURE DisableItem(menuHandle, item) -- disable an item in a menu, or if the item
; is zero, disable the entire menu. Shares code with EnableItem to stay small
;
IMPORT EnableFetch
BSR ENABLEFETCH ;set up registers
cmp #31, d0 ; is the item > 31 ? <FJL C466>
bls.s @ok
IMPORT EnableDone
jmp EnableDone ; yes, so leave without updating flags <FJL C466>
@ok
BCLR D0,D1 ;disable the item
IMPORT EnableCom
BRA ENABLECOM ;go update flags and return
ENDPROC
GETMENUPTR PROC ENTRY
;-------------------------------------------------------------------------------------------
; GetMenuPtr is a utility routine that given an index into the current menuList in D5,
; returns a pointer to the menu in A0. It returns a handle to the same menu in A1.
;
BSR.S GetA0List ; get menuList pointer into A0 <EHB 11-Apr-85>
MOVE.L MENUOH(A0,D5),A1 ; get menu handle
GMPContinue TST.L (A1) ; has menu been purged? <EHB 11-Apr-85>
BEQ.S ListPurged ; => yes, go to purgeatory <EHB 11-Apr-85>
MOVE.L (A1),A0 ; handle -> pointer
RTS
ENTRY GetA0List
GetA0List
;-------------------------------------------------------------------------------------------
; GetA0List is a routine to get the menuList pointer into A0. GetA1List is a routine to
; get the menuList pointer into A1. The reason for two routines is due to the complexity
; and risk of getting the dozen routines that get menuList pointer to agree with each other.
; These routines check to see if the menuList has been purged. If it has it generates
; a DS #54 (MenuPrgErr).
MOVE.L MenuList,A0 ; get the menuList handle <EHB 11-Apr-85>
TST.L (A0) ; has it been purged? <EHB 11-Apr-85>
BEQ.S ListPurged ; => yes, go to purgeatory <EHB 11-Apr-85>
MOVE.L (A0),A0 ; else get the pointer <EHB 11-Apr-85>
RTS ; and return <EHB 11-Apr-85>
ENTRY GetA1List
GetA1List
MOVE.L MenuList,A1 ; get the menuList handle <EHB 11-Apr-85>
TST.L (A1) ; has it been purged? <EHB 11-Apr-85>
BEQ.S ListPurged ; => yes, go to purgeatory <EHB 11-Apr-85>
MOVE.L (A1),A1 ; else get the pointer <EHB 11-Apr-85>
RTS ; and go to heaven
ListPurged
MOVEQ #MenuPrgErr,D0 ; get our error code <EHB 11-Apr-85>
_SysError ; and roast in eternal damnation <EHB 11-Apr-85>
ENTRY GetHA0List
GetHA0List
;-------------------------------------------------------------------------------------------
; GetHA0List is a routine to get the HMenuList pointer into A0. GetHA1List is a routine to
; get the HMenuList pointer into A1. The reason for two routines is due to the complexity
; and risk of getting the dozen routines that get HMenuList pointer to agree with each other.
; These routines check to see if the menuList has been purged. If it has it generates
; a DS #54 (MenuPrgErr).
; <FJL C222>
bsr.s GetA0List ; get the menuList ptr in a0
adda.w lastMenu(a0), a0 ; a0 now points at last regular menu
addq #6, a0 ; a0 now points at HMenuList header info
rts
ENTRY GetHA1List
GetHA1List
bsr.s GetA1List ; get the menuList ptr in a1 <FJL C222>
adda.w lastMenu(a1), a1 ; a1 now points at last regular menu
addq #6, a1 ; a1 now points at HMenuList header info
rts
ENDPROC
;-----------------------------------------------
; Stack Frame Definitions for MenuSelect and PopUpMenuSelect
;-----------------------------------------------
STARTPT EQU 8 ; 1st parameter is 8, and is 4 bytes long
FUNCRESULT EQU 12 ; longword function result (menu,item)
ITEMRESULT EQU 14 ; item portion of funcResult
MENURECT EQU -8 ; rectangle (8 bytes) <C60/30JUN86>
MSavePort EQU MENURECT-4 ; saved grafPort <C60/30JUN86>
msLastMenu EQU MSavePort-2 ; how many menus are on the screen <FJL C222>
DelayTicks EQU msLastMenu - 4 ; how long mouse in HItem <FJL C222>
DragTicks EQU DelayTicks - 4 ; how long mouse moving towards HMenu <FJL C222>
menuDelaySave EQU DragTicks - 1 ; store menuDelay from param ram <FJL C222>
menuDragSave EQU menuDelaySave - 1 ; store menuDrag from param ram <FJL C222>
lastFuncResult EQU menuDragSave - 2 ; funcResult last time thru MSLoop <FJL C222>
lastItemResult EQU lastFuncResult - 2 ; itemResult last time thru MSLoop <FJL C222>
firstMenuID EQU lastItemResult - 2 ; ID of REGULAR menu up <FJL C222>
NewHMenuOffset EQU firstMenuID - 2 ; offset into MenuList of new HMenu <FJL C222>
SelectFrame EQU NewHMenuOffset ; number of bytes to save <FJL C222>
msHMenuStorage EQU 4 ; 4 bytes per menu needed for temp storage <FJL C222>
MENUSELECT PROC EXPORT
;------------------------------------------------------------------------------------------------
;
; MenuSelect -- main loop that tracks mouse in title bar and thru hierarchical menus
;
;------------------------------------------------------------------------------------------------
;
; FUNCTION MenuSelect(mousePt:Point): LongInt -- MenuSelect is the most important
; routine in the menu manager. It is called when the application receives a
; mouse button down event on the menuBar and retains control until the mouse button
; goes up. It returns a long integer contain 2 16 bit values. The high word
; is called "whichMenu" and holds the menuId of the menu that was chosen; if its
; zero, no menu was chosen. The low word is called "whichItem" and contains the item
; number of the selected item. If no choice was selected, the longWord result is zero
; MenuSelect draw menu bar if invalid
; ROLL IN DrawMenuBarIfInvalidOnMenuSelect
IMPORT ValidateMenuBar
IMPORT ptchHMUpdateHelpMenu
IMPORT ptchHMShowHelpAboutDialog
IMPORT ptchHMToggleWhatIs
jsr ValidateMenuBar
;Roll in PatchMDMenuSelect
;The saves menus state, calls old MenuSelect, then restores state
import PushMenuState,PopMenuState ;<PN> <SM5>
resultsStackFrame
result ds.l 1 ; the MenuSelect result <PN> <SM5>
parametersStackFrame
startPt ds.l 1 ; the start point <PN> <SM5>
endStackFrame
linkSave A2 ; <SM15> To preserve A2!
MOVE.L MenuList,D0 ; check if menu list is nil. <SM12> rb, start
BEQ.S @CallOldCode ; if NIL just call the old trap
JSR ptchHMUpdateHelpMenu ; update the menu checked status
MOVE.L ExpandMem,A2 ; <33> point to the expand mem ptr
MOVE.L ExpandMemRec.emHelpGlobals(A2),A2 ; <33> A2 = global ptr
CLR.W hmgSystemMenuID(A2) ; <33> clear the last system menu ID
CLR.W hmgSystemMenuItem(A2) ; <33> clear the last system menu item
ST hmgInMenuSelectFlag(A2) ; <33> say that we're in MenuSelect
@CallOldCode ; <SM12> rb, end
jsr PushMenuState ; Potentially save off the menu state <PN> <SM5>
subq #4,sp ; Make room for result <PN> <SM5>
move.l startPt(a6),-(sp) ; Push the parameter <PN> <SM5>
jsr OrigninalMenuSelect ;<PN> <SM5>
move.l (sp)+,result(a6) ; Store the result <PN> <SM5>
jsr PopMenuState ; Restore the menu state if it was saved <PN> <SM5>
MOVE.L result(a6),D0 ; get the result of the _MenuSelect call <SM12> rb, start
MOVE.L ExpandMem,A2 ; <33> point to the expand mem ptr
MOVE.L ExpandMemRec.emHelpGlobals(A2),A2 ; <33> A2 = global ptr
SWAP D0 ; put menu ID in low word for test
TST.W D0 ; was the menu ID non-zero?
BNE.S @NormalMenuSelect ; yes, so just return result of _MenuSelect
MOVE.W hmgSystemMenuID(A2),D1 ; return the last system menu ID
BEQ.S @NormalMenuSelect ; if zero then the menu wasn't the help menu
SWAP D1 ; put menu ID in hiword
MOVE.W hmgSystemMenuItem(A2),D1 ; return the last help menu item
@HandleHelpMenu
CMP #kHMAboutHelpItem,D1 ; was it the about item
BNE.S @TryShowBalloonsItem ; no, check for Show/Hide Balloons item
JSR ptchHMShowHelpAboutDialog ; show the about dialog
BRA.S @HelpMenuHandled ; exit w/ zeroed menu result long
@TryShowBalloonsItem
CMP.W #kHMShowBalloonsItem,D1 ; was the selection Show/Hide Balloons??
BNE.S @DoneHelpMenu ; no, it was some other item
JSR ptchHMToggleWhatIs ; toggles state of "Show Balloons" global,
BRA.S @HelpMenuHandled ; exit w/ zeroed menu result long
@DoneHelpMenu
MOVE.L D1,D0 ; put the setup menu result in D0 for result(A6)
BRA.S @CorrectedResult ; exit
@HelpMenuHandled
MOVEQ #0,D0 ; say that hi and lo words are zero
@NormalMenuSelect
SWAP D0 ; put item number back in lo word
@CorrectedResult
MOVE.L D0,result(a6) ; stuff the non-corrected result
CLR.W hmgInMenuSelectFlag(A2) ; <33> say that we're out of MenuSelect
restoreUnlinkReturn
OrigninalMenuSelect
LINK A6,#SelectFrame ;set up a stack frame
MOVEM.L D2-D7/A2-a4,-(SP) ;save work registers
CLR.W -(SP) ;push zero for this
_HiliteMenu ;make sure no menu is hilited
CLR.L FUNCRESULT(A6) ;assume nothing will be selected
clr.l MenuDisable ; clear the low-memory location MenuDisable
; <1.9 KSM> Removed this check to allow double-click processing to work properly
; Double-click is one possibility for tearing off menus. (Kevin, I think that this
; WaitMouseUp should still be here. You should find another way to keep the guy here
; in MenuSelect for the double-click case.) <dba>
CLR.W -(SP) ;push zero for this
_WaitMouseUp ;is the mouse still down?
TST.B (SP)+ ;examine result
BEQ DONEMSELECT ;if not still down, donÕt bother
; need to set the port here else ClipRects do not work
PEA MSavePort(A6)
_GetPort
move.l wMgrCPort, a2 ; get color port
move.l a2, -(SP) ; set the port
_SetPort
;
; during the main loop of menuSelect, D3 holds the mouse point, D4 holds the old
; menuIndex into the menuList and D5 holds the current menuIndex. A4 holds handle to
; HMenu ID storage (of menus currently up).
;
; First initialize these variables
;
CLR D5 ; current menuIndex is empty
CLR D4 ; oldMenuIndex is empty
clr msLastMenu(a6) ; clear msLastMenu index <FJL C222>
clr.l lastItemResult(a6) ; clear both lastFuncResult and lastItemResult
clr firstMenuID(a6) ; no menu selected at start
move.l mbSaveLoc, a0 ; store MenuDrag and MenuDelay in stackframe
move.l (a0), a0
move.b mbMenuDelay(a0), menuDelaySave(a6)
move.b mbMenuDrag(a0), menuDragSave(a6)
IMPORT SetTickCounters ; <SM13> call SetTickCounters after
; menuDelaySave and menuDragSave are set up
bsr SetTickCounters ; set DelayTicks and DragTicks <FJL C222>
MOVE.L STARTPT(A6),D3 ; start off with initial mouse point
move.l #5*msHMenuStorage, d0 ; alloc space for 5 menuIndices [words] <FJL C222>
; and 5 items [words] <FJL C222>
_NewHandle
move.l a0, a4 ; store it in a4 for the duration of MenuSelect
; NOTE: a4 is used as an implicit parameter
; to MenuSelect subroutines
;------------------------------------------------
; Menu Select Loop
;------------------------------------------------
; Call the mBar defProcÕs hit routine to see where the mouse is.
; Major revisions for hierarchical menus. <FJL C222>
MSLoop
MOVEQ #1,D0 ; hit message is #1
MOVE.L D3,D1 ; send point in parameter
IMPORT CallMBarProc
BSR CallMBarProc ; execute the defproc <DAF 20Aug86>
TST.L D0 ; where is the hit?
BMI.s SameMenu ; branch if its not in a title or any menu
beq.s InTitleNoMenu ; branch if its IN the menubar but NOT IN a title
MOVE.w D0,D5 ; move result to D5
BSR GetMenuPtr ; get the menuData handle
move menuID(a0),funcResult(a6) ;return which Menu the mouse is currently in
bra.s ChgMenu
;
; if in menu bar but not in a title, want to bring down all menus
; no menus and no funcResult
;
InTitleNoMenu clr d5 ; no menu
clr funcResult(a6) ; no menu, so no result either
; At this point, D5 contains the menuIndex of the menu that the mouse points at,
; or a zero if no menu is pointed at. Check to see if this menu is different than
; the previous one pointed at
ChgMenu cmp d5, d4 ; menuIndex = oldMenuIndex ?
beq.s SameMenu ; if the same, nothing to pull down
IMPORT MenuChanged
bsr MenuChanged ; change variables that affect current menu
bmi DoneMS ; n-flag set means that MBarHook aborted MenuSelect
SameMenu tst d5 ; examine menu index
beq.s NextMouse ; donÕt choose an item unless thereÕs one down
IMPORT ResetRectScrollData
bsr ResetRectScrollData ; before choosing item be sure menuRect(a6) is
; correct as are scrolling globals
IMPORT ChooseItem
bsr ChooseItem ; choose item by calling mdefproc
IMPORT CheckHItem
bsr CheckHItem ; check for hierarchical stuff
; I put GetMouse after WaitMouseUp. This ensures that FlashTheMenu is called with the <EHB 9-Apr-85>
; same mouse position that was processed above.
NextMouse ; I Put GetMouse after WaitMouseUp <EHB 9-Apr-85>
MUpEntryPt
CLR.W -(SP) ;make room for stillDown result
_WaitMouseUp ;is the button still down?
TST.B (SP)+ ;test _WaitMouseUp result
BEQ.S @MouseUp ; => if up, flash user (oh Mr. Mac!)
; mouse still down, so get the mouse position and store in D3
SUBQ #4,SP ;allocate place to get mouse
MOVE.L SP,-(SP) ;use temp buffer for mouse point
_GetMouse ;get mouse in wmgr coordinates
MOVE.L (SP)+,D3 ;keep mouse point in D3
; The mouse button is still down. WeÕve read the mouse position already,
; so call the user hook (if its installed) and loop.
MOVE.L MENUHOOK,D0
BEQ.S @NoMenuHook
MOVE.L D0,A0
JSR (A0)
@NoMenuHook
BRA.s MSLOOP ; => continue tracking mouse
;------------------------------------------------
; End of Menu Select Loop
;------------------------------------------------
@MouseUp
; the mouse button went up. Give feedback to the user if she made a choice
TST D5 ;was one selected?
BEQ.S NOFLASH ;if not, dont bother
;
; If the item has a hierarchical menu attached DO NOT return the menu or item
;
bsr GetMenuPtr ; get ptr to chosen menu in a0 (which we want for
; GetItemRecord call)
move itemResult(a6), d0
IMPORT GetItemRecord
bsr GetItemRecord ; on return a1 points to items property bytes
beq.s @FlashIt ; if z-flag set then item not found <PMAB568 07Sep88 EMT>
cmpi.b #HMenuCmd, itemCmd(a1) ; does this item have a hierarchical menu?
bne.s @FlashIt ; no, so branch and flash
clr itemResult(a6) ; yes, so clear the item
bra.s @JustRestore ; and skip the flashing
@FlashIt
IMPORT FlashFeedback
BSR FLASHFEEDBACK ;flash the choice for feedback
@JustRestore
IMPORT RestoreAllBits
BSR RestoreAllBits ;restore bits under all menus <FJL C222>
; if no item selected, then no menu either
;
NOFLASH TST ITEMRESULT(A6) ; was an item selected?
BNE.S @SetTheMenu ; if so, weÕre cool
CLR.W FUNCRESULT(A6) ; otherwise, no menu was either
MOVE firstMenuID(a6),D0 ; better make sure no menu hilited in menu bar
BEQ.S @SetTheMenu ; if itÕs zero, then we can skip unhiliting it
move d5, d0 ; set up for TurnIndexOff
;*** WRONG WRONG WRONG; the only reason this works is that the MBDF ignores the index
;*** this value is always wrong once a hierarchical menu has been tracked
IMPORT TurnIndexOff
BSR TurnIndexOff ; otherwise turn it off
clr firstMenuID(a6) ; and remember that no menu hilited in title bar
@SetTheMenu MOVE firstMenuID(a6),TheMenu ;remember menuID of hilited menu
;+++ tst funcResult(a6) ; is it a system menu?
; CanÕt just use funcResult(a6) since could<FJL 09Mar87>
; be a HMenu associated with the desk acc<FJL 09Mar87>
tst TheMenu ; Is it a system menu? <FJL 09Mar87>
BMI.s DoSysMenu ; if < 0 then handle it
TST.W MBarEnable ;does deskOrn own the menuBar?
BMI.s DoSysMenu ;if so, go tell it about it
ENTRY DoneMS
DONEMS move.l a4, a0 ; set up for DisposHandle
_DisposHandle ; and toss temp storage
MOVE.L MSavePort(A6),-(SP) ;get old port
_SetPort ;restore callers grafPort
ENTRY DoneMSelect
DONEMSELECT
MOVEM.L (SP)+,D2-D7/A2-a4 ;restore registers
UNLK A6 ;dismantle stack frame
MOVE.L (SP)+,(SP) ;strip sole parameter
clr.l d1 ; clear D1 because some stupid app <FJL A278>
; assumes it is zero <FJL A278>
; the next 3 lines are a little kludge. Infrequently lastMBSave is non-zero when exiting
; MenuSelect, though it should always be zero. Just to be safe force it to be zero.
move.l mbSaveLoc, a0 ; get mbSaveLoc
move.l (a0), a0 ; dereference
clr lastMBSave(a0) ; force no menus down
RTS ;return to caller
;-----------------------------------------------
; Utility -- DoSysMenu
;-----------------------------------------------
;
; handle system menus
;
; HMenus cause problems here. Since the menu ID (funcResult) is not = to the DAÕs <FJL 09Mar87>
; menu ID, SystemMenu will never find the DA in the DA list. To force it to pass
; the HMenu ID we can set MBarEnable temporarily.
;
; Need to allow a DA that owns the menu bar to reset MBarEnable in the middle of _SystemMenu <FJL PMAB280>
; Had to move around some parts of this routine. Only set/clear MBarEnable when MBar not
; already owned by DA.
;
DoSysMenu
tst.w MBarEnable ; who owns menu bar?
bmi.s @1 ; desk acc ==> weÕre cool
move TheMenu, MBarEnable ; set MBarEnable with DAÕs ID
move.l FuncResult(a6),-(SP) ; push the result
_SystemMenu ; invoke desk manager
clr.l FuncResult(a6) ; pretend we didnÕt get anything
; NOTE: clears funcResult AND itemResult !!!
clr.w MBarEnable ; clear MBarEnable
bra.s @Done
@1 move.l FuncResult(a6),-(SP) ; push the result
_SystemMenu ; invoke desk manager
clr.l FuncResult(a6) ; pretend we didnÕt get anything
; NOTE: clears funcResult AND itemResult !!!
@Done BRA.S DoneMS ;let common code finish up
;------------------------------------------------------------------------------------------------
; End of MenuSelect
;------------------------------------------------------------------------------------------------
ENDPROC
; PopUpMenuSelect Equates:
PopUpMenuH EQU StartPt ; menu handle parameter, same offset as StartPt
; after the stack is fixed
PopUpItem EQU SelectFrame - 2 ; PopUpItem parameter
msTopEdge EQU PopUpItem - 2 ; Top parameter
msLeftEdge EQU msTopEdge - 2 ; Left parameter
msTopLeft EQU msLeftEdge ; Top left point of menu
PopUpSelectFrame EQU msLeftEdge
PopUpMenuSelect PROC EXPORT ;;<FJL C844>
;------------------------------------------------------------------------------------------------
;
; PopUpMenuSelect -- brings up a menu in a user-specified location, then
; tracks mouse in the menu and thru any hierarchical menus
;
;------------------------------------------------------------------------------------------------
;
; FUNCTION PopUpMenuSelect(theMenu: menuHandle; top, left, PopUpItem: integer): LongInt
;
; PopUpMenuSelect is called when an application receives a mouse down in a pop-up menu area.
; A pop-up menu area is typically a box with a shadow. It first brings up the menu with
; the left edge given by the parameter Left, and the top of PopUpItem at Top. It tracks the
; mouse just like MenuSelect, allowing five levels of hierarchical menus. It ignores
; mouse movement into the menubar by changing the low-memory location MBHeight to zero before
; it starts (it does so so that it can call the mbarproc with a HitMessage, and have the
; mbarproc ignore the menubar area). It returns a LongInt that has the same meaning as
; MenuSelect.
; Begin by removing parameters so that we are left with the same parameter setup as MenuSelect.
; This allows us to use all of the subroutines from MenuSelect.
move 4(SP), d0 ; save PopUpItem
move.l 6(SP), d1 ; save left, top
move.l (SP), 6(SP) ; move RTS, leave 4 bytes of parameter on the stack
addq #6, SP ; and update stack ptr
link a6,#PopUpSelectFrame ; set up a stack frame
movem.l d2-d7/a2-a4,-(SP) ; save work registers
move d0, PopUpItem(a6) ; store parameters in stackframe
move.l d1, msTopLeft(a6) ; store Left and Top in one instruction
clr.l funcResult(A6) ; assume nothing will be selected
clr.l MenuDisable ; clear the low-memory location MenuDisable
subq #2, SP ; leave room for result
_WaitMouseUp ; is the mouse still down?
tst.b (SP)+ ; examine result
beq @EndPopUpMS ; if not StillDown, donÕt bother
; need to set the port here else ClipRects do not work
PEA MSavePort(A6)
_GetPort
move.l wMgrCPort, a2 ; get color port
move.l a2, -(SP) ; set the port
_SetPort
;
; during the main loop of PopUpMenuSelect, D3 holds the mouse point, D4 holds the old
; menuIndex into the menuList and D5 holds the current menuIndex. A4 holds handle to
; HMenu ID storage (of menus currently up).
;
; First initialize these variables
;
clr d5 ; current menuIndex is empty
clr d4 ; oldMenuIndex is empty
clr msLastMenu(a6) ; clear msLastMenu index
IMPORT SetTickCounters
bsr SetTickCounters ; set DelayTicks and DragTicks
clr.l lastItemResult(a6) ; clear both lastFuncResult and lastItemResult
move.l mbSaveLoc, a0 ; store MenuDrag and MenuDelay in stackframe
move.l (a0), a0
move.b mbMenuDelay(a0), menuDelaySave(a6)
move.b mbMenuDrag(a0), menuDragSave(a6)
move.l #5*msHMenuStorage, d0 ; alloc space for 5 menuIndices [words]
; and 5 items [words]
_NewHandle
move.l a0, a4 ; store it in a4 for the duration of MenuSelect
; NOTE: a4 is used as an implicit parameter
; to PopUpMenuSelect subroutines
;------------------------------------------------
; PopUpMenuSelect Loop
;------------------------------------------------
; First bring up the pop-up menu, then track it.
move.l PopUpMenuH(a6), a0 ; get menuID
move.l (a0), a0 ; dereference menuHandle
move menuID(a0), d1 ; store the menuID in D1 for GetHIndex call
IMPORT GetHIndex
bsr GetHIndex ; convert ID to index
move d0, d4 ; save index in D4 <PMAB364 23Jan88 EMT>
beq @EndPopUpMS ; zero index ==> couldnÕt find it (shouldnÕt happen)
; Alter WMgr portRect to point to the rect of the device the cursor is on
MOVE.L CrsrDevice, A1 ; Get the cursor GDevice <PMAB364 23Jan88 EMT>
MOVE.L (A1), A1 ; Dereference <PMAB364 23Jan88 EMT>
MOVE.L gdRect+topLeft(A1), portRect+topLeft(A2) ; Copy to <PMAB364 23Jan88 EMT>
MOVE.L gdRect+botRight(A1), portRect+botRight(A2) ; WMgr portRect <PMAB364 23Jan88 EMT>
IMPORT DirtyHMenus
BSR DirtyHMenus ; Dirty size of all hierchical menus <PMAB364 23Jan88 EMT>
MOVE.L PopUpMenuH(A6), -(SP) ; Push the menuHandle <PMAB539 19Jul88 EMT>
_CalcMenuSize ; And recalculate it <PMAB539 19Jul88 EMT>
move d4, d5 ; copy saved index to D5 <PMAB364 23Jan88 EMT>
IMPORT DrawFirstMenu
bsr DrawFirstMenu ; use special routine to place first menu
move MBarHeight, -(SP) ; save MBarHeight on the stack
clr MBarHeight ; clear MBarHeight so Hit Message to mbarproc
; ignores menu bar.
@PopUpMSLoop
moveq #1, d0 ; hit message is #1
move.l d3, d1 ; send point in parameter
IMPORT CallMBarProc
bsr CallMBarProc ; execute the defproc
tst.l d0 ; where is the hit?
bmi.s @SameMenu ; branch if its not in a title or any menu
; else itÕs in a menu
move d0, d5 ; move result to D5
bsr GetMenuPtr ; get the menuData handle
move menuID(a0),funcResult(a6) ;return which Menu the mouse is currently in
; At this point, D5 contains the menuIndex of the menu that the mouse points at,
; or a zero if no menu is pointed at. Check to see if this menu is different than
; the previous one pointed at
cmp d5, d4 ; menuIndex = oldMenuIndex ?
beq.s @SameMenu ; if the same, nothing to pull down
IMPORT MenuChanged
bsr MenuChanged ; change variables that affect current menu
bmi.s @DonePopUpMS ; n-flag set means that MBarHook aborted MenuSelect
@SameMenu tst d5 ; examine menu index
beq.s @NextMouse ; donÕt choose an item unless thereÕs one down
IMPORT ResetRectScrollData
bsr ResetRectScrollData ; before choosing item be sure menuRect(a6) is
; correct as are scrolling globals
IMPORT ChooseItem
bsr ChooseItem ; choose item by calling mdefproc
IMPORT CheckHItem
bsr CheckHItem ; check for hierarchical stuff
@NextMouse clr -(SP) ; make room for stillDown result
_WaitMouseUp ; is the button still down?
tst.b (SP)+ ; test _WaitMouseUp result
beq.s @MouseUp ; => if up, flash user (oh Mr. Mac!)
; mouse still down, so get the mouse position and store in D3
subq #4,SP ; allocate place to get mouse
move.l SP,-(SP) ; use temp buffer for mouse point
_GetMouse ; get mouse in wmgr coordinates
move.l (SP)+,d3 ; keep mouse point in D3
; The mouse button is still down. WeÕve read the mouse position already,
; so call the user hook (if its installed) and loop.
move.l MenuHook, d0
beq.s @NoMenuHook
move.l d0, a0
jsr (a0)
@NoMenuHook
bra.s @PopUpMSLoop ; => continue tracking mouse
;------------------------------------------------
; End of PopUpMenuSelect Loop
;------------------------------------------------
@MouseUp
; the mouse button went up. Give feedback to the user if she made a choice
tst d5 ;was one selected?
beq.s @NoFlash ;if not, dont bother
;
; If the item has a hierarchical menu attached DO NOT return the menu or item
;
bsr GetMenuPtr ; get ptr to chosen menu in a0 (which we want for
; GetItemRecord call)
move ItemResult(a6), d0
IMPORT GetItemRecord
bsr GetItemRecord ; on return a1 points to itemÕs property bytes
beq.s @FlashIt ; if z-flag set then item not found <PMAB568 07Sep88 EMT>
cmpi.b #HMenuCmd, itemCmd(a1) ; does this item have a hierarchical menu?
bne.s @FlashIt ; no ==> branch and flash
clr ItemResult(a6) ; yes ==> so clear the item
bra.s @JustRestore ; and skip the flashing
@FlashIt
IMPORT FlashFeedback
bsr FlashFeedBack ; flash the choice for feedback
@JustRestore
IMPORT RestoreAllBits
bsr RestoreAllBits ; restore bits under all menus
; if no item selected, then no menu either
@NoFlash tst ItemResult(a6) ; any Item? (we could get here several ways,
; so do it this way)
bne.s @DonePopUpMS ; yes ==> then leave Func alone
clr funcResult(A6) ; no Item ==> so clear Func too
@DonePopUpMS move (SP)+, MBarHeight ; restore previous MBarHeight saved on the stack
; Restore WMgr portRect. WMgrCPort is in A2
MOVE.L WMgrPort, A0 ; Get b&w WMgrPort <PMAB364 23Jan88 EMT>
MOVE.L portRect+topLeft(A0), portRect+topLeft(A2) ; Copy to <PMAB364 23Jan88 EMT>
MOVE.L portRect+botRight(A0), portRect+botRight(A2) ; WMgr portRect <PMAB364 23Jan88 EMT>
IMPORT DirtyHMenus
BSR DirtyHMenus ; Dirty size of all hierchical menus <PMAB364 23Jan88 EMT>
IMPORT DoneMS
bra DoneMS ; use common code
@EndPopUpMS
IMPORT DoneMSelect
bra DoneMSelect ; use common end code
ENDPROC
DirtyHMenus PROC ENTRY
;-----------------------------------------------
; Utility -- DirtyHMenus <PMAB364 23Jan88 EMT>
;-----------------------------------------------
;
; Mark the size of all hierchical menus as dirty. Used by PopUpMenuSelect.
;
IMPORT GetHA0List
BSR GetHA0List ; get HMenuList ptr in A0
MOVE.W lastHMenu(a0), d5 ; get #HMenus
; we know there are HMenus so check them backwards
MOVE.L MinusOne, d1 ; set up for GetHIndex
IMPORT GetHIndex
BSR GetHIndex ; d0 now has index to HMenuList header info
ADD.W d0, d5 ; d5 has index to last HMenu
MOVE.W d0, d6 ; d6 has index to HMenuList header
@MenuLoop
BSR GetMenuPtr ; get menu ptr in A0 from ID in D5
; PB403: use A1 (handle), not A0 (pointer)
MOVE.L A1,-(SP) ; push menu handle <PB403 24Feb88>
BSR.S DirtyMenuSize ; invalidate size
SUBQ.W #6, d5 ; bump to next menu
CMP.W d6, d5 ; at end of list?
BGT.S @MenuLoop ; no, so try the next menu
RTS
ENTRY DirtyMenuSize
DirtyMenuSize ; <EHB 5-Mar-85>
;-----------------------------------------------
; Utility -- DirtyMenuSize
;-----------------------------------------------
;
; Utility DirtyMenuSize(menuHandle) -- Say that the menuÕs size is no longer valid by
; setting the width and height to -1.
MOVE.L 4(SP),A0 ; get menuHandle
MOVE.L (A0),A0 ; get menuPointer
MOVE.L #-1,MenuWidth(A0) ; clear size
MOVE.L (SP)+,(SP) ;strip parameter
RTS ;return to caller
ENDPROC
CALCMENUSIZE PROC EXPORT
; PROCEDURE CalcMenuSize(menuHandle) -- scan the menuData of a menu and set the menuÕs
; width and heigth fields accordingly, by invoking the menu definition proc
SUBQ.L #4, SP ; <PMAB364 23Jan88 EMT>
MOVE.L SP, -(SP) ; <PMAB364 23Jan88 EMT>
_GetPort ; <PMAB364 23Jan88 EMT>
MOVE.L WMgrCPort, A1 ; Get color port <PMAB364 23Jan88 EMT>
MOVE.L A1, -(SP) ; Set the port <PMAB364 23Jan88 EMT>
_SetPort ; <PMAB364 23Jan88 EMT>
MOVE #2,-(SP) ; Tell mProc to calc size
MOVE.L 10(SP),A0 ; Get the menu handle <PMAB364 23Jan88 EMT>
MOVE.L A0,-(SP) ; Push it
CLR.L -(SP) ; Pass 12 bytes of bogus addresses/junk
CLR.L -(SP)
CLR.L -(SP)
MOVE.L (A0),A0 ; Get the menu ptr
IMPORT CallMDefProc
BSR CallMDefProc ; Call the menu definition proc <PMAB364 23Jan88 EMT>
_SetPort ; Restore the port (on stack) <PMAB364 23Jan88 EMT>
ENTRY StripIt
StripIt
MOVE.L (SP)+,(SP) ;strip parameter
RTS ;return to caller
ENDPROC
SetTickCounters PROC ENTRY
;------------------------------------------------
; Utility -- SetTickCounters <FJL C222>
;------------------------------------------------
; Set (Reset) stackframe tick counters DelayTicks
; and DragTicks. Get counts from parameter ram
; data that has been stored in stackframe.
;
subq #4, SP ; space for result
_TickCount ; get tick count
move.l (SP), DelayTicks(a6) ; set DelayTicks
clr.l d0
move.b menuDelaySave(a6), d0 ; get delta from param ram
add.l d0, DelayTicks(a6)
move.l (SP)+, DragTicks(a6) ; set DragTicks
move.b menuDragSave(a6), d0 ; get delta from param ram
add.l d0, DragTicks(a6)
rts
ENDPROC
ResetRectScrollData PROC ENTRY
;------------------------------------------------
; Utility -- ResetRectScrollData <FJL C222>
;------------------------------------------------
;
; The mouse is in a menu or title. If the last time thru MSLoop a HMenu was
; brought up, then menuRect(a6) will have the HMenuÕs rect and not the rect
; the mouse is currently in, so ask the MBarProc to give us the rect the
; mouse is in. Next ask the mbarproc to restore the scrolling globals
; topMenuItem, atMenuBottom for the menu the mouse is in.
;
moveq #9, d0 ; rect message is #9
moveq #0, d1 ; clear hi-word of d1 since mbarproc WILL
; have this menu in its data structure already
move d5, d1 ; send 6 byte offset in parameter
IMPORT CallMBarProc
bsr CallMBarProc ; execute the defproc
move.l d0, a0 ; move ptr into a0
move.l Top(a0), menuRect(a6) ; move Top, Left
move.l Bottom(a0), menuRect+4(a6) ; move Bottom, Right
moveq #11, d0 ; reset scroll globals message is #11
move d5, d1 ; send 6 byte offset in parameter
bsr CallMBarProc ; execute the defproc
rts
ENDPROC
MenuChanged PROC ENTRY
;-----------------------------------------------
; Utility -- MenuChanged
;-----------------------------------------------
; 1. If mouse moved into a new menu title then:
; A. restore all menus on the screen
; B. draw a new one
; C. reset stackframe data for the new menu.
; 2. If just move into a menu that is already down then:
; A. just reset stackframe data for the new menu
;
; On entry: d4 has index to last menu
; d5 has index to new menu
; On exit: d4 == d5 == index to new menu
;
; start by clearing stackframe variables
clr.w itemResult(A6) ; no item chosen... <FJL C175>
tst d4 ; was there one up already?
beq.s @SkipRestore ; if not, skip restoring
IMPORT GetA0List
bsr GetA0List ; get menuList ptr into a0
cmp lastMenu(a0), d5 ; is the new menu in regular menuList?
bgt.s @EndMenuChg ; no, its a HMenu thatÕs already down:
; so... 1) donÕt restore any menus
; 2) donÕt pull a new one down
; 3) donÕt call MBarHook
;
; if we got to here ==> mouse in the title of a NEW 'regular' menu, so restore all
; of the menus that are currently showing on the screen
;
tst d5 ; a menu chosen ?
beq.s @1 ; no, so skip resetting data
IMPORT ResetRectScrollData
bsr ResetRectScrollData ; before choosing item be sure menuRect(a6) is
; correct as are scrolling globals
@1
IMPORT RestoreSomeBits
BSR RestoreSomeBits ; restore bits under menus <FJL C222>
IMPORT SetTickCounters
bsr SetTickCounters ; set tick counters for HMenus <FJL 26Jan87>
; did RestoreSomeBits leave exactly one menu up ?
cmpi #msHMenuStorage, msLastMenu(a6)
beq.s @EndMenuChg ; yes, so skip menu draw
MOVE D4,D0 ; get menuIndex for title invert
IMPORT TurnIndexOff
BSR TurnIndexOff ; unhilite old title
@SkipRestore
; if the new menuIndex is non-zero (i.e., one was chosen), pull down the menu.
move.w funcResult(a6), firstMenuID(a6) ; save ID of first menu down (for TheMenu)
tst d5 ;is there a new one chosen?
beq.s @EndMenuChg ;if not, go read the mouse again
MOVE D5,D0 ; get menu index
IMPORT TurnIndexOn
BSR TurnIndexOn ; hilite the menu bar
MOVE.L MBarHook,D0 ;<SM13> is MBarHook installed?
BEQ.S @DoTheDraw ;too bad, heÕs not
;
; ask the mbarproc for the menuÕs rectangle since MBarHook needs it. Remember that MBarHook
; is only called before regular menus go up, never HMenus.
;
moveq #9, d0 ; rect message is #9
moveq #0, d1 ; clear d1 since this menu is a regular menu,
; not a HMenu
move d5, d1 ; send 6 byte offset in parameter
IMPORT CallMBarProc
bsr CallMBarProc ; execute the defproc
move.l d0, a0 ; get address of rectangle in a0
move.l (a0), menuRect(a6) ; move top,left into stackframe
move.l 4(a0), menuRect+4(a6) ; move bottom, right into stackframe
MOVE.L MBarHook,A0 ;<SM13>get address in register
PEA MENURECT(A6) ;tell the hook where to draw
JSR (A0) ;call it
TST D0 ;did it get him?
; <FJL C222>
beq.s @DoTheDraw ; yes, and he says to continue with MenuSelect
move #-1, d5 ; oops, he told us to abort, so set n-flag
bra.s @EndMenuChg ; and leave without drawing anything
@DoTheDraw
IMPORT DrawTheMenu
bsr DrawTheMenu ; draw the menu
@EndMenuChg MOVE D5, D4 ;old menuIndex = current menuIndex
rts
ENDPROC
ChooseItem PROC ENTRY
;-----------------------------------------------
; Utility -- ChooseItem
;-----------------------------------------------
;
PEA MENURECT(A6) ;donÕt let menuProc write outside of rect
_ClipRect ;clip to menuRect
BSR GETMENUPTR ;get handle to menu in A1
;
MOVE #MCHOOSEMSG,-(SP) ;tell menu to choose itself
MOVE.L A1,-(SP) ;push menu handle
PEA MENURECT(A6) ;push menuRect
MOVE.L D3,-(SP) ;push mouse point
PEA ITEMRESULT(A6) ;push place to stick result
IMPORT CallMDefProc
BSR CallMDefProc ; Call the menu definition proc <PMAB364 23Jan88 EMT>
;
; every time the menu is chosen it could have scrolled, so re-save the scrolling data
;
moveq #10, d0 ; set up for "save alt data" call
move d5, d1 ; param is menuIndex of menu the mouse is in
IMPORT CallMBarProc
bsr CallMBarProc ; execute mbar defproc (ignore result in d0)
rts
ENDPROC
CheckHItem PROC ENTRY
;-----------------------------------------------
; Utility -- CheckHItem
;-----------------------------------------------
; Check if itemResult(a6) has a hierarchical menu, and if so update various stackframe <FJL C222>
; structures. If user has delayed in item long enough then put up the hier menu. <FJL C222>
;
; On Entry: A1 ptr to itemÕs property bytes
;
; If no item selected then reset stackframe data and leave, but DONÕT restore any HMenus
; that might be up. (If no item selected then mouse is in the menu bar or outside all menus)
;
bsr GetMenuPtr ; get ptr to menuInfo into a0 from index in d5
move itemResult(a6), d0 ; set up for GetItemRecord call, move item to d0
beq.s @NoItem ; if no item currently selected then leave
;
; If item does not have a hierarchical item then reset stackframe data,
; restore any HMenus up to the menu the mouse pt is in
;
IMPORT GetItemRecord
bsr GetItemRecord ; ptr to itemÕs record returned in a0
; its properties in a1
cmpi.b #HMenuCmd, itemCmd(a1) ; does it have a hierarchical menu?
bne.s @NotHItem ; no, then leave
;
; If funcResult or itemResult are not the same as last time thru the MSLoop then reset
; stackframe data and restore any HMenus up to the menu the mouse pt is in
;
move funcResult(a6), d0 ; do this for "cmp" to work
cmp lastFuncResult(a6), d0 ; is it the same menu as last time thru?
bne.s @NotSameItem ; no, so reset data and menus
move itemResult(a6), d0 ; do this for "cmp" to work
cmp lastItemResult(a6), d0 ; is it the same item as last time thru?
bne.s @NotSameItem ; no, so reset data
move.l a1, -(SP) ; store work register on the stack
subq #4, SP ; space for result
_TickCount ; get current Ticks
move.l (SP)+, d0 ; get Ticks in d0
move.l (SP)+, a1 ; restore work register
cmp.l DelayTicks(a6), d0 ; have we reached right number of ticks ?
blt.s @EndChkHItem ; no, so continue
;
; N ticks have passed with mouse in same item that has hierarchical menu, so bring
; the dang thing up. A1 has ptr to itemÕs properties.
;
moveq #0, d1 ; clear out d1 for GetHIndex
move.b itemMark(a1), d1 ; set up for GetHIndex -- move HMenu ID into d1
IMPORT GetHIndex
bsr GetHIndex ; get the index in menuList in d0
beq.s @NotHItem ; oops, got invalid HMenu ID, so just ignore it
move d0, d5 ; set up for DrawTheMenu
IMPORT DrawTheMenu
bsr DrawTheMenu ; and draw it
move d5, NewHMenuOffset(a6) ; save d5 in stackframe
move d4, d5 ; set up for call to ResetScrollRect
IMPORT ResetRectScrollData
bsr ResetRectScrollData ; and reset the scroll/rect for menu mouse is in
IMPORT CheckDragging
bsr CheckDragging ; check for mouse dragging towards HMenu
; If we get thru CheckDragging three states can exist:
; 1) The mouse is now in the HMenu --> select an item there
; 2) The mouse is in another menu item in the original menu --> bring HMenu down
; 3) The mouse has moved out of the menu --> bring HMenu down
bra.s @EndChkHItem
@NoItem
@NotHItem
@NotSameItem
;
; now restore bits behind any menus up
;
IMPORT RestoreSomeBits
bsr RestoreSomeBits ; Restore the bits behind all menus up to the
; one the mouse is currently in.
IMPORT SetTickCounters
bsr SetTickCounters ; reset tick counters
@EndChkHItem move itemResult(a6), lastItemResult(a6) ; save values from this time thru
move funcResult(a6), lastFuncResult(a6)
rts
ENDPROC
CheckDragging PROC ENTRY
;-----------------------------------------------
; Utility -- CheckDragging
;-----------------------------------------------
; Allow the user to move the mouse towards the hierarchical
; menu for DragTicks.
; Wait for the mouse to leave the item, when it does, look
; to see if it is moving towards the menu. If it is moving
; towards the HMenu then wait MenuDrag ticks.
;
; On Entry: D5 Offset of newly drawn HMenu in MenuList.
; We need lots of registers, so save D5 in stackframe
movem.l d4, -(SP) ; save d4 on stack
subq #4, SP ; get mouse pt in D3
move.l SP, -(SP) ; temp mouse buffer on stack
_GetMouse
move.l (SP)+, d3
@InRectLoop
; see if mouse up yet
clr -(SP) ; make room for stilldown result
_WaitMouseUp ; is the button still down?
tst.b (SP)+ ; test result
beq @DoneDragging ; if up then done dragging
; call the mbarproc to see if mouse has entered the new HMenu
moveq #1, d0 ; hit message is #1
move.l d3, d1 ; send point in parameter
IMPORT CallMBarProc
bsr CallMBarProc ; execute the defproc
cmp NewHMenuOffset(a6), d0 ; is the hit in the newly drawn HMenu?
beq @DoneDragging ; yes, so no more dragging needed
; not in new HMenu, so see if it is still in the itemÕs rect
subq #2, SP ; save space for PtInRect result
subq #4, SP ; space for GetMouse result
move.l SP, -(SP) ; temp mouse buffer on stack
_GetMouse ; point is on the stack
move.l (SP), d3 ; store pt in d3 and leave on stack for PtInRect
; The mouse button is still down. WeÕve read the mouse position already,
; so call the user hook (if its installed) and loop.
MOVE.L MENUHOOK,D0 ; <PMAB568 07Sep88 EMT>
BEQ.S @NoMHook ; <PMAB568 07Sep88 EMT>
MOVE.L D0,A0 ; <PMAB568 07Sep88 EMT>
JSR (A0) ; <PMAB568 07Sep88 EMT>
@NoMHook ; <PMAB568 07Sep88 EMT>
move.l mbSaveLoc, a0 ; get itemÕs rect from mbSaveLoc
move.l (a0), a0 ; dereference
pea mbItemRect(a0) ; push rect
_PtInRect
move.b (SP)+, d0 ; get boolean result
bne.s @InRectLoop ; still in rect, wait for it to leave
; if get here then mouse has moved out of itemRect but not into HMenu.
; First get menurect of HMenu by calling mbarproc. D3 has latest mouse pt from
; which we will draw the triangle allowing mouse to move towards HMenu.
moveq #9, d0 ; CalcRect message is #9
moveq #0, d1 ; clear hi-word of d1 since mbarproc WILL
; have this menu in its data structure already
move NewHMenuOffset(a6), d1 ; send MenuList offset as parameter
IMPORT CallMBarProc
bsr CallMBarProc ; execute the defproc
move.l d0, a0
move.l (a0), d4 ; store top, left in d4
move Bottom(a0), d5 ; store bottom, left in d5
swap d5
move Left(a0), d5
cmp d3, d4 ; if horizontal of D4 < D3 then menu to left
bgt.s @1 ; yes --> menu to left
; if menu is to the left then want to use
; right edge for angle calculations, otherwise
; will get angles too close to 90 degrees
move Right(a0), d4 ; store top, right in d4
move Right(a0), d5 ; store bottom, right in d5
; reset MenuDrag as of when mouse left the itemÕs rect
@1
IMPORT SetTickCounters
bsr SetTickCounters
; On Entry: D3 original mouse pt
; D4 top, left edge of HMenu
; D5 bottom, left edge of HMenu
; D7 hi-word has right pixel of newly drawn HMenu
; Used: D6 latest mouse pt
; D7 for intermediate calculations
@DragLoop
; see if mouse up yet
clr -(SP) ; make room for stilldown result
_WaitMouseUp ; is the button still down?
tst.b (SP)+ ; test result
beq @DoneDragging ; if up then done dragging
; see if have returned to the item rect, if so return to @InRectLoop, otherwise the same
; HMenu that is currently up will appear again. At the same time we are getting the mouse
; pt in D6.
subq #2, SP ; save space for PtInRect result
subq #4, SP ; space for GetMouse result
move.l SP, -(SP) ; temp mouse buffer on stack
_GetMouse ; point is on the stack
move.l (SP), d6 ; store pt in d6 and leave on stack for PtInRect
; The mouse button is still down. WeÕve read the mouse position already,
; so call the user hook (if its installed) and loop.
MOVE.L MENUHOOK,D0 ; <PMAB568 07Sep88 EMT>
BEQ.S @NoMHook2 ; <PMAB568 07Sep88 EMT>
MOVE.L D0,A0 ; <PMAB568 07Sep88 EMT>
JSR (A0) ; <PMAB568 07Sep88 EMT>
@NoMHook2 ; <PMAB568 07Sep88 EMT>
move.l mbSaveLoc, a0 ; get itemÕs rect from mbSaveLoc
move.l (a0), a0 ; dereference
pea mbItemRect(a0) ; push rect
_PtInRect
move.b (SP)+, d0 ; get boolean result
bne.s @InRectLoop ; BACK IN ITEMÕS RECT, WAIT FOR IT TO LEAVE AGAIN!!!
; call the mbarproc to see if mouse has entered the new HMenu
moveq #1, d0 ; hit message is #1
move.l d6, d1 ; send point in parameter
IMPORT CallMBarProc
bsr CallMBarProc ; execute the defproc
cmp NewHMenuOffset(a6), d0 ; is the hit in the newly drawn HMenu?
beq.s @DoneDragging ; yes, so no more dragging needed
; see if current mouse pt (D6) is within triangle bounded by D3, D4 and D5
;
; /D4
; / |
; / |
; / |
; D3 D6 | An obvious place to save code, but not on ROM build day!! <FJL 27Jan87>
; \ |
; \ |
; \ |
; \D5
;
; first check whether menuÕs direction was right or left or previous menu
@ChkToRight
cmp d3, d4 ; if horizontal of D4 < D3 then menu to left
blt.s @ChkToLeft
; first see if D6 < D3 horizontally
cmp d3, d6 ; is D6 < D3
blt.s @DoneDragging ; yes, so moving wrong way
;draw a line from D3 to D6, calculate its slope and from that its angle
MOVE.L D6, D1 ; <PMAB568 07Sep88 EMT>
MOVE.L D3, D0 ; <PMAB568 07Sep88 EMT>
BSR.S @SlopeFromLine ; <PMAB568 07Sep88 EMT>
move d0, d7 ; <PMAB568 07Sep88 EMT>
;draw a line from D3 to D4, calculate its slope and from that its angle
MOVE.L D4, D1 ; <PMAB568 07Sep88 EMT>
MOVE.L D3, D0 ; <PMAB568 07Sep88 EMT>
BSR.S @SlopeFromLine ; <PMAB568 07Sep88 EMT>
cmp d0, d7 ; is angle to mouse >= angle to D4 ? <PMAB568 07Sep88 EMT>
blt.s @DoneDragging ; no, so mouse outside triangle
;draw a line from D3 to D5, calculate its slope and from that its angle
MOVE.L D5, D1 ; <PMAB568 07Sep88 EMT>
MOVE.L D3, D0 ; <PMAB568 07Sep88 EMT>
BSR.S @SlopeFromLine ; <PMAB568 07Sep88 EMT>
cmp d0, d7 ; is angle to mouse >= angle to D4 ? <PMAB568 07Sep88 EMT>
bgt.s @DoneDragging ; yes, so mouse outside triangle
bra.s @ChkTimeOut
;draw a line from D0 to D1, calculate its slope and from that its angle. Returned in D0.
@SlopeFromLine ; <PMAB568 07Sep88 EMT>
LEA -10(SP), SP ; 2 (AngleFromSlope) + 4 (FixRatio) + 4 (DeltaPoint)
MOVE.L D1, -(SP)
MOVE.L D0, -(SP)
_DeltaPoint ; now have dv and dh on the stack
_FixRatio
_AngleFromSlope
MOVE.W (SP)+, D0
RTS
@ChkToLeft
; first see if D6 > D3 horizontally
cmp d3, d6 ; is D6 > D3
bgt.s @DoneDragging ; yes, so moving wrong way
;draw a line from D3 to D6, calculate its slope and from that its angle
MOVE.L D3, D1 ; <PMAB568 07Sep88 EMT>
MOVE.L D6, D0 ; <PMAB568 07Sep88 EMT>
BSR.S @SlopeFromLine ; <PMAB568 07Sep88 EMT>
move d0, d7 ; <PMAB568 07Sep88 EMT>
;draw a line from D3 to D4, calculate its slope and from that its angle
MOVE.L D3, D1 ; <PMAB568 07Sep88 EMT>
MOVE.L D4, D0 ; <PMAB568 07Sep88 EMT>
BSR.S @SlopeFromLine ; <PMAB568 07Sep88 EMT>
cmp d0, d7 ; is angle to mouse <= angle to D4 ? <PMAB568 07Sep88 EMT>
bgt.s @DoneDragging ; no, so mouse outside triangle
;draw a line from D3 to D5, calculate its slope and from that its angle
MOVE.L D3, D1 ; <PMAB568 07Sep88 EMT>
MOVE.L D5, D0 ; <PMAB568 07Sep88 EMT>
BSR.S @SlopeFromLine ; <PMAB568 07Sep88 EMT>
cmp d0, d7 ; is angle to mouse <= angle to D4 ? <PMAB568 07Sep88 EMT>
blt.s @DoneDragging ; yes, so mouse outside triangle
; fall thru to @ChkTimeOut
@ChkTimeOut
; mouse is still moving towards HMenu, see if timeout yet
subq #4, SP ; space for result
_TickCount ; get current Ticks
move.l (SP)+, d0 ; get Ticks in d0
cmp.l DragTicks(a6), d0 ; have we reached DragTicks ?
bge.s @DoneDragging ; yes, so quit dragging
bra.s @DragLoop ; no, so keep dragging
@DoneDragging movem.l (SP)+, d4 ; restore work register
move d4, d5 ; restore d5 (since d4==d5 before HMenu was drawn)
rts
ENDPROC
RestoreBits PROC ENTRY
;-----------------------------------------------
; Utility -- RestoreBits
;-----------------------------------------------
;
; RESTOREBITS is a utility that takes the bits that were saved by SaveBits and <FJL C222>
; puts them back on the screen.
;
subq #msHMenuStorage, msLastMenu(a6) ; reduce counter <FJL C222>
MOVEQ #8,D0 ; set restore message
IMPORT CallMBarProc
BRA CallMBarProc ; execute the defproc (result in D0)
; and let CallMBarProc return
ENDPROC
RestoreSomeBits PROC ENTRY
;-----------------------------------------------
; Utility -- RestoreSomeBits
;-----------------------------------------------
; RestoreSomeBits loops thru each menu up on the screen looking to see if it should
; be restored, and if it should be, restoring it. The condition for restoration is
; if the mouse pt is in the current menu then donÕt restore it.
;
move.l (a4), a0 ; get ptr to temp storage
move msLastMenu(a6), d0 ; get offset to last menu on screen
beq.s @RSBNone ; if no menus then exit (should never happen but...)
cmp -4(a0, d0), d5 ; is the 'last' menu the one the mouse is in?
beq.s @RSBNone ; yes, so donÕt restore any, and donÕt redraw menu
@RSBLoop move.l (a4), a0 ; get ptr to temp storage
move msLastMenu(a6), d0 ; get offset to last menu on screen
beq.s @RSBNone ; if no menus then exit
cmp -4(a0, d0), d5 ; is the 'last' menu the one the mouse is in?
beq.s @RSBDone ; yes, so done restoring
move -2(a0, d0), itemResult(a6) ; no, so restore previous selected item
IMPORT RestoreBits
bsr RestoreBits ; restore dem bits
bra.s @RSBLoop ; and loop
@RSBDone
;
; If here then at least one menu was restored, and as a result of the HMenu
; overlap the menu has strange black and white patches. Calling ChooseItem
; with the item that was selected in the menu before the HMenu was
; brought up will cause both old and new items to be redrawn.
tst msLastMenu(a6) ; any menus left up ?
beq.s @RSBNone ; no, so donÕt choose anything
IMPORT ChooseItem
bsr ChooseItem ; tell MDEF to choose after redraw
@RSBNone RTS
ENDPROC
RestoreAllBits PROC ENTRY
;-----------------------------------------------
; Utility -- RestoreAllBits
;-----------------------------------------------
; RestoreAllBits loops thru every menu up on the screen and restores the bits <FJL C222>
; behind each in turn. It is called when 1) the mouse button has gone up, or 2) the mouse
; has gone into another menu title.
;
tst msLastMenu(a6) ; could have already restored all
beq.s @RestoreDone ; the menus ?
IMPORT RestoreBits
bsr RestoreBits ; restore dem bits
bra.s RestoreAllBits ; yes, so loop
@RestoreDone RTS
ENDPROC
DrawFirstMenu PROC ENTRY
;-----------------------------------------------
; Utility -- DrawFirstMenu
;-----------------------------------------------
; DrawFirstMenu draws the first pop-up menu. This is separate because of the special placement
; needed for the pop-up menu. The top left edge of the item PopUpItem must match the parameters
; Top and Left. All subsequent menus are drawn using the same routines that MenuSelect uses.
;
; TODO: Call MBarHook after sending msg #3 to MDEF but before drawing menu.
addq #msHMenuStorage, msLastMenu(a6) ; bump up counter <FJL C222>
move msLastMenu(a6), d0 ; get offset into temp storage
move.l (a4), a0 ; get ptr to temp storage
move d5, -4(a0, d0) ; store MenuList offset
move itemResult(a6), -2(a0,d0) ; and item number
; Call MDEF to calculate where pop-up menu should go. This is a new message to the MDEF.
; Pass: MenuHandle, Top, Left, Item
; Return: MenuRect, TopMenuItem
move #3, -(SP) ; message = calc item top
bsr GetMenuPtr ; get a handle to the menu record into A1 using
; menuIndex in D5, and ptr in A0
move.l a1,-(SP) ; push menu handle
pea menuRect(a6) ; push menuRect pointer
move.l msTopLeft(a6), -(SP) ; push left and top at same time
pea PopUpItem(a6) ; push the itemÕs address
IMPORT CallMDefProc
BSR CallMDefProc ; Call the menu definition proc <PMAB364 23Jan88 EMT>
; Call MBDF to save bits behind and draw the drop shadow
MOVEQ #7, D0 ; set up for save message
SWAP D0 ; put parameter1 in hi-word of D0
MOVE D5, D0 ; parameter1 is menuList offset
SWAP D0
LEA menuRect(a6), A0 ; parameter2 is address of menuRect
MOVE.L A0, D1 ; put in D1 for CallMBarProc
IMPORT CallMBarProc
BSR CallMBarProc ; tell it to save. No result.
; MDEF returns TopMenuItem in WhichItem parameter, store it in low-memory
move PopUpItem(a6), TopMenuItem
IMPORT CallDrawMDEF
bsr CallDrawMDEF ; ask the MDEF to draw the menu
@DoneDraw RTS
ENDPROC
DRAWTHEMENU PROC ENTRY
;-----------------------------------------------
; Utility -- DrawTheMenu
;-----------------------------------------------
; DrawTheMenu is an internal utility that draws the structure of a menu. It uses
; the menu whose index is in D5.
;
; call the mBar defproc to draw the pulldown and save the bits
; behind.
;
cmpi #5*msHMenuStorage, msLastMenu(a6) ; are there 5 menus up already??? <FJL C222>
beq.s @DoneDraw ; yes, so leave without doing anything <FJL C222>
addq #msHMenuStorage, msLastMenu(a6) ; bump up counter <FJL C222>
move msLastMenu(a6), d0 ; get offset into temp storage
move.l (a4), a0 ; get ptr to temp storage
move d5, -4(a0, d0) ; store menuID
move itemResult(a6), -2(a0,d0) ; and item number
clr.l d1 ; clear out d1 for mbarproc call <FJL C222>
cmpi #msHMenuStorage, msLastMenu(a6) ; is this a hierarchical menu?
; If so, we need to send the vertical
; mouse pt to mbarproc
beq.s @NotHMenu ; no, so just do normal stuff
move.l d3, d1 ; yes, so move mouse pt into d1. Vertical
; mouse pt is in hi-word of d3
@NotHMenu MOVEQ #9,D0 ; set up for the rect message
MOVE.w D5,D1 ; parameter is the menuIndex (affects lo-word
; of D1 only, hi-word still has vert mouse pt)
IMPORT CallMBarProc
BSR CallMBarProc ; execute the defproc (result in D0)
MOVE.L D0,A0 ; move menuRect ptr to A-reg
MOVE.L (A0),menuRect(A6) ; copy the rect
MOVE.L 4(A0),menuRect+4(A6) ;
MOVEQ #7, D0 ; set up for save message
SWAP D0 ; put parameter1 in hi-word of D0
MOVE D5, D0 ; parameter1 is menuList offset
SWAP D0
LEA menuRect(a6), A0 ; parameter2 is address of menuRect
MOVE.L A0, D1 ; put in D1 for CallMBarProc
BSR CallMBarProc ; tell it to save. No result.
move menuRect+Top(a6), TopMenuItem ; tell MDEF to draw from top of menu
IMPORT CallDrawMDEF
bsr CallDrawMDEF ; ask the MDEF to draw the menu
@DoneDraw RTS
ENDPROC
CallDrawMDEF PROC ENTRY
;-----------------------------------------------
; Utility -- CallDrawMDEF
;-----------------------------------------------
; CallDrawMDEF is an internal utility that asks the MDEF
; to draw the menu whose offset is in D5. Immediately after
; the menu is drawn the MBDF is told to save the two scrolling
; globals topMenuItem and atMenuBottom. See note in MBDF
; about why this was done this way.
;
; before drawing, clip to intersection of menuRect and portRect in case user has multiple screens
; Just clip to menuRect now. <PMAB364 23Jan88 EMT>
; subq #2, SP ; space for boolean result
; pea menuRect(a6) ; push src rectangle 1
; pea portRect(a2) ; push src rectangle 2
; pea tRect1(a6) ; push dest rectangle
; _SectRect
; addq #2, SP ; ignore result
;
; PEA tRect1(a6) ;donÕt let menuProc write outside of rect <FJL C175>
PEA menuRect(A6) ; Just use menuRect now. <PMAB364 23Jan88 EMT>
_ClipRect ;clip to menuRect <FJL C175>
CLR.W -(SP) ;message = draw
BSR GETMENUPTR ;get a handle to the menu record into A1 using
; menuIndex in D5
MOVE.L A1,-(SP) ;push menu handle
PEA menuRect(A6) ;push menuRect pointer
SUBQ #8,SP ;point and whichItem are not looked at
IMPORT CallMDefProc
BSR CallMDefProc ; Call the menu definition proc <PMAB364 23Jan88 EMT>
moveq #10, d0 ; set up for "save alt data" call
move d5, d1 ; param is menuIndex of menu the mouse is in
IMPORT CallMBarProc
bsr CallMBarProc ; execute mbar defproc (ignore result in d0)
rts
ENDPROC
CallMDefProc PROC ENTRY
;-----------------------------------------------
; Utility -- CallMDefProc(message: INTEGER; theMenu: MenuHandle; VAR menuRec:
; Rect; hitPt: Point; VAR whichItem: INTEGER); <PMAB364 23Jan88 EMT>
; (menuRecord pointer in A0)
;-----------------------------------------------
; Utility CallMDefProc -- given a menuRecord pointer in A0, calls the menu definition
; procedure. It does this by de-referencing the defProc handle, reloading it into
; memory if necessary. If there is no MenuDefProc, it simply cleans up the stack and returns.
; This routine replaces GetTheMProc UnlockMProc, and UnlkMDef.
paramSize EQU 18
MOVEM.L D3/A5, -(SP) ; Save some registers
MOVE.L MenuDefHandle(A0),D3 ; get the handle
BEQ.S @NoMenuDef ; Skip if there is none.
LEA 8+4(SP), A0 ; Original parameters
MOVEQ #paramSize, D0 ; Size of parameters
SUB.L D0, SP ; Prepare to make a copy of the parameters
MOVE.L SP, A1 ; Copy
_BlockMove ; Do it.
MOVE.L D3,-(SP) ; get the MDEF handle
_LoadResource ; load it
MOVE.L D3, A0 ; get the MDEF handle
; Some programmers are pretty slimy and load a MDEF that is empty. They then <LW4> fau
; stuff some code into it. However, since HLOCK does not flush the cache anymore, <LW4> fau
; the code that they stuff into it might not get written back to memory. To solve this, <LW4> fau
; we check here whether the MDEF resource size is less than, say, 32 bytes. If so, we <LW5> chp
; assume that they have already loaded the MDEF and modified it, so we flush the cache <LW4> fau
; for them.
_GetHandleSize ; How big is our MDEF Handle <LW4> fau
cmp.l #32,D0 ; Is it "small" <LW5> chp
bhi.s @RealMDEF ; no, don't flush the cache <LW4> fau
jsr ([jCacheFlush]) ; else, flush the caches. <LW4> fau
@RealMDEF ; <LW4> fau
_HLock ; lock it the gentlemanÕs way <C169>
MOVE.L (A0),A0 ; handle -> pointer
MOVE.L CurrentA5, A5 ; fix up his A5 world
JSR (A0) ; call it
MOVE.L D3, A0 ; get the MDEF handle
_HUnlock ; unlock the gentlemanÕs way <C169>
@NoMenuDef
MOVEM.L (SP)+, D3/A5 ; Restore some registers
MOVE.L (SP)+, A0 ; get the return address
LEA paramSize(SP), SP ; strip off the parameters
JMP (A0) ; and return
ENDPROC
CALLCHOOSE PROC EXPORT
;
; CallChoose is a utility procedure to call a menuÕs menuProc to select an item
;
MOVE #MCHOOSEMSG,-(SP) ;the message is choose
BSR GETMENUPTR ;get handle to menu specified by D5
MOVE.L A1,-(SP) ;push menuHandle
PEA MENURECT(A6) ;push rectangle of current menu
MOVE.L D1,-(SP) ;mouse point
PEA TOOLSCRATCH ;scratch location to store result
IMPORT CallMDefProc
BSR CallMDefProc ; Call the menu definition proc <PMAB364 23Jan88 EMT>
;
; delay based on TICKS
;
move.l #3, a0 ; 1/20 second delay (tune it!) <FJL CXXX>
_Delay ; for the Unix folks <FJL CXXX>
RTS
ENDPROC
FLASHFEEDBACK PROC ENTRY
;-----------------------------------------------
; Utility -- FlashFeedBack
;-----------------------------------------------
;
; FlashFeedBack is a utility routine that implements flash feedback on menu selections.
; tThe "MenuFlash" global determines the number of flashes
;
MOVE D4,-(SP) ;save work register
MOVE MENUFLASH,D4 ;get menu flash count
BEQ.S FLASHDONE ;if zero, no flashing at all
MOVE ITEMRESULT(A6),TOOLSCRATCH ;was anything selected?
BEQ.S FLASHDONE ;if not, donÕt give feedback
PEA MENURECT(A6) ;clip to the menu
_ClipRect
;
; Here is the flash loop. It uses TICKS for timing.
;
FLASHLOOP MOVEQ #0,D1 ;zero point to force selection off
IMPORT CallChoose
BSR CALLCHOOSE ;call the menuProc to turn it off
MOVE.L D3,D1 ;now use real point to turn it on
BSR CALLCHOOSE ;call menuProc to turn it on
SUBQ #1,D4 ;any more times?
BNE.S FLASHLOOP ;do it flashCount times
IMPORT FullClip
BSR FULLCLIP ;restore full screen clipping
FLASHDONE MOVE (SP)+,D4 ;restore D4
RTS ;return to caller
ENDPROC
FULLCLIP PROC EXPORT
;-----------------------------------------------
; Utility -- FullClip
;-----------------------------------------------
; FullClip is a utility that sets the clipping region of the wmgrPort to the portRect
; It is used to save code.
;
; Note: It is not really necessary to set clip full open here because the mbarproc is
; called after this to restore the menu, and it sets the clip full open. But
; because it is so close to ROM build we wonÕt take it out. <FJL 8Feb87>
;
MOVE.L GrafGlobals(A5), A0 ; <PMAB364 23Jan88 EMT>
MOVE.L wideOpen(A0), -(SP) ; set the clip to wide open <PMAB364 23Jan88 EMT>
_SetClip ; <PMAB364 23Jan88 EMT>
RTS
ENDPROC
MenuChoice PROC EXPORT
;------------------------------------------------------------------------------------
;
; FUNCTION MenuChoice : LONGINT; <FJL CXXX>
;
;------------------------------------------------------------------------------------
; FUNCTION MenuChoice : LONGINT;
;
; Returns the menuID in the hi-word and menu Item in the lo-word from the lo-mem location
; MenuDisable ($B54). This feature was requested by User-Ed who want to use
; it with training programs.
;
move.l MenuDisable, 4(SP) ; set function result
rts
ENDPROC
GetMenuBar PROC EXPORT
;------------------------------------------------------------------------------------
;
; GetMenuBar
; do not return system menus in the returned menu list <22> PN
;------------------------------------------------------------------------------------
;
; FUNCTION GetMenuBar: MenuListHandle -- allocate a menuList data structure and copy
; the current menuList into it
;
;¥ <start> roll in GetMenuBarDoesNotReturnSystemMenus from SystemMenuPatches.a
; GetMenuBarDoesNotReturnSystemMenus Ñ do not return system menus in the returned menu list
IF forROM THEN
IMPORT FindFirstSystemMenu6BO
jsr FindFirstSystemMenu6BO ; Are there any system menus?
beq OriginalTrap
MOVE.L d3,-(SP) ; Save off a work register
MOVEQ #0,D3
MOVE.W D0,D3 ; Save off index
SUBQ.L #4,SP ; Make room for result
JSR OriginalTrap
MOVE.L (SP)+,A0 ; Get copy of menulist
MOVE.L A0,8(SP) ; Return as result
BEQ.S @done ; EQ means no menulist or memfull
; Munger(menuH, d3, NIL, d1, POINTER(-1), 0);
MOVE.L (A0),A1 ; Get copymenulist ptr
moveq #0,d1 ; clear out high word <10>
MOVE.W lastMenu(A1),D1 ; Offset to last menu (could be zero but weÕve chkd that)
ADDQ.W #6,D1 ; Offset past last menu entry
SUB.W d3,D1 ; D1 = Offset to last menu - Offset to 1st sysmenu
; (i.e., # bytes for system menus)
SUB.W D1,lastMenu(A1) ; Set new count for the list
SUBQ.L #4,SP ; Make room for Munger result
MOVE.L A0,-(SP) ; Push the handle
MOVE.L d3,-(SP) ; offset=first system menu offset
CLR.L -(SP) ; ptr1=NIL <10>
MOVE.L D1,-(SP) ; len1=# of bytes to delete
MOVE.L A0,-(SP) ; ptr2=anything non-nil will do
CLR.L -(SP) ; len2=0 means delete
_Munger ; Rip out system menus
ADDQ.L #4,SP ; ignore Munger result
@done
MOVE.L (SP)+,d3 ; Restore work register
RTS
OriginalTrap
ENDIF
;¥ <end> roll in GetMenuBarDoesNotReturnSystemMenus from SystemMenuPatches.a
move.l menuList, a0 ; get the menuList handle <FJL C222>
MOVE.L A0, 4(SP) ; Is this NIL? If yes, return as function result <KSM BRC41545>
beq.s @1 ; YES, - faceless MF app is running <KSM BRC41545>
_HandToHand ; make a copy of it <FJL C222>
move.l a0, 4(SP) ; return it as the function result <FJL C222>
MOVE.L (A0), A0 ; Dereference it <PMAB417 03Mar88 EMT>
MOVE.W lastMenu(A0), D0 ; Get last regular menu <PMAB417 03Mar88 EMT>
CLR.L menuTitleSave+6(A0, D0) ; Clear out saved handle <PMAB417 03Mar88 EMT>
@1 ; Branch here when menulist is NIL <KSM BRC41545>
rts ; <FJL C222>
ENDPROC
GetMCInfo PROC EXPORT ; <FJL C408>
;------------------------------------------------------------------------------------
;
; GetMCInfo <FJL C408>
;
;------------------------------------------------------------------------------------
;
; FUNCTION GetMCInfo: MenuCTblHandle -- allocate a new color table, and copy the
; current one into it.
;
move.l MenuCInfo, a0 ; get the color table handle
_HandToHand ; make a copy of it
beq.s @OK ; check error result
moveq #0, a0 ; on error return zero
@OK move.l a0, 4(SP) ; return it as the function result
rts
ENDPROC
SetMenuBar PROC EXPORT
;------------------------------------------------------------------------------------
;
; SetMenuBar
;
;------------------------------------------------------------------------------------
;
; PROCEDURE SetMenuBar(menuListHandle) -- copy the parameter menu list into the current
; menu List.
; SetMenuBarAddsSystemMenus Ñ SetMenuBar should add the system menus to the current menu list
; Roll in SetMenuBarAddsSystemMenus from SystemMenuPatch.a
CLR.W -(SP) ; A new menu bar invalidates the <PMAB417 03Mar88 EMT>
_HiliteMenu ; currently selected title <PMAB417 03Mar88 EMT>
move.l menuList, a0 ; get the old menuList <FJL C222>
_DisposHandle ; and dispose of it <FJL C222>
move.l 4(SP), a0 ; get the parameter menuList handle <FJL C222>
move.l (SP)+, (SP) ; strip the parameter <FJL C222>
_HandToHand ; make a copy of the parameter list <FJL C222>
move.l a0, menuList ; store the new menuList <FJL C222>
MOVE.L a0,D0 ; Get result
BEQ.S @done ; EQ means no menulist or memfull
; Call the MBDF to put in the system menus
MOVEQ #2,D0 ; set up for the menu-edge-calc msg
CLR.L D1 ; calc entire bar
IMPORT CallMBarProc
jsr CallMBarProc
@done
RTS
ENDPROC
SetMCInfo PROC EXPORT ; <FJL C408>
;------------------------------------------------------------------------------------
;
; SetMCInfo <FJL C408>
;
;------------------------------------------------------------------------------------
;
; PROCEDURE SetMCInfo(menuCTblHandle) -- copy the parameter menu color table into the
; current menu color table. MemErr will be set for caller if HandToHand failed.
move.l 4(SP), a0 ; get the parameter menuList handle
move.l (SP)+, (SP) ; strip the parameter
_HandToHand ; make a copy of the parameter list
bne.s @NoMemory ; check error result
; on error do not change color table
@OK move.l MenuCInfo, a1 ; get the old color table
move.l a0, MenuCInfo ; store the new menuList
move.l a1, a0 ; move old color table handle to a0
_DisposHandle ; and dispose of it
IMPORT MenuCTblSanityChk
bsr MenuCTblSanityChk ; check the table for consistency
@NoMemory rts ; return
ENDPROC
DISPOSEMENU PROC EXPORT
;------------------------------------------------------------------------------------
;
; DisposeMenu
;
;------------------------------------------------------------------------------------
; PROCEDURE DisposeMenu(menuHandle) -- dispose of the dynamic storage used by the
; menu data structure
; <15> DisposeMenu supports disposing both menus that are resource handles and other menus.
; Thus, it has the responsibility of disposing the handle and removing it from the
; resource map. One way to do this would be to call DetachResource and then DisposeHandle,
; since the Resource Manager is tolerant of non-resource handles, and would just return
; an error. However, the Process Manager depends on ReleaseResource to keep track of
; Apple menu handles, so we instead do a ReleaseResource, followed by a DisposeHandle if
; the ReleaseResource returns resNotFound (which is what it will do if you pass it something
; other than a resource handle).
move.l 4(sp),-(sp) ; first, call ReleaseResource on the menu handle
_ReleaseResource
subq #2,sp ; check the error
_ResError
cmp.w #resNotFound,(sp)+ ; did ReleaseResource dispose the handle?
bne.s Done ; yes, we are done
move.l 4(sp),a0 ; now call DisposeHandle on the menu handle
_DisposeHandle
Done
move.l (sp)+,(sp) ; strip menu handle parameter
rts
ENDPROC
DispMCInfo PROC EXPORT ; <FJL C408>
;------------------------------------------------------------------------------------
;
; DispMCInfo <FJL C408>
;
;------------------------------------------------------------------------------------
; PROCEDURE DispMCInfo(menuCTblHandle) -- dispose of the dynamic storage used by the
; menu color table
MOVE.L 4(SP),A0 ; get menu color table Handle
_DisposHandle ; itÕs not a resource, so just toss it
move.l (SP)+, (SP) ; strip parameter
RTS
ENDPROC
CHECKITEM PROC EXPORT
;
; PROCEDURE CheckItem(menuHandle,itemNumber, checked: BOOLEAN) -- check or unCheck
; an item. Strategy: transform the boolean into the proper char right on the stack
;
TST.B 4(SP) ;test the boolean
BEQ.S CNOMARK ;go use noMark symbol
MOVE #CHECKMARK,4(SP)
IMPORT SetItemMark
BRA SETITEMMARK ;go mark it
CNOMARK MOVE #NOMARK,4(SP) ;unCheck it
BRA SETITEMMARK ;go do it
ENDPROC
GETITEMMARK PROC EXPORT
;
; PROCEDURE GetItemMark(menuHandle,itemNumber,VAR markChar) -- get the current value of
; an itemÕs markfield. Use GetItemProperty.
;
MOVEQ #ITEMMARK,D2 ;set up property selector
IMPORT GetItemProperty
BRA GETITEMPROPERTY ;do it!
ENDPROC
GETITEMICON PROC EXPORT
;
; PROCEDURE GetItemIcon(menuHandle,itemNumber,VAR iconChar) -- get the current value of
; an itemÕs icon field. Use GetItemProperty.
;
MOVEQ #ITEMICON,D2 ;set up property selector
IMPORT GetItemProperty
BRA GETITEMPROPERTY ;do it!
ENDPROC
GETITEMCMD PROC EXPORT ;<FJL C844>
;
; PROCEDURE GetItemCmd(menuHandle,itemNumber,VAR cmdChar) -- get the current value of <FJL C844>
; an itemÕs cmd field. Use GetItemProperty. Needed for hierarchical menus.
;
MOVEQ #ITEMCMD,D2 ;set up property selector
IMPORT GetItemProperty
BRA GETITEMPROPERTY ;do it!
ENDPROC
__GETITEMSTYLE PROC EXPORT
;
; PROCEDURE GetItemStyle(menuHandle,itemNumber,VAR styleChar) -- get the current value of
; an itemÕs style field. Use GetItemProperty.
;
MOVEQ #ITEMSTYLE,D2 ;set up property selector
IMPORT GetItemProperty
BRA GETITEMPROPERTY ;do it!
ENDPROC
SETITEMMARK PROC EXPORT
;
; PROCEDURE SetItemMark(menuHandle,itemNumber,markChar) -- set the current value of an
; itemÕs mark field. Use SetItemProperty.
;
MOVEQ #ITEMMARK,D2 ;set up property selector
IMPORT SetItemProperty
BRA SETITEMPROPERTY
ENDPROC
SETITEMICON PROC EXPORT
;
; PROCEDURE SetItemIcon(menuHandle,itemNumber, iconChar) -- set the current value of
; an itemÕs icon field. Use SetItemProperty.
;
MOVEQ #ITEMICON,D2 ;set up property selector
IMPORT SetItemProperty
BRA SETITEMPROPERTY ;do it!
ENDPROC
SETITEMCMD PROC EXPORT ;<FJL C844>
;
; PROCEDURE SetItemCmd(menuHandle,itemNumber, cmdChar) -- set the current value of <FJL C844>
; an itemÕs cmd field. Use SetItemProperty. Needed for hierarchical menus.
;
MOVEQ #ITEMCMD,D2 ;set up property selector
IMPORT SetItemProperty
BRA SETITEMPROPERTY ;do it!
ENDPROC
SETITEMSTYLE PROC EXPORT
;
; PROCEDURE SetItemStyle(menuHandle,itemNumber,styleChar) -- set the current value of
; an itemÕs style field. Use SetItemProperty.
;
MOVEQ #ITEMSTYLE,D2 ;set up property selector
IMPORT SetItemProperty
BRA SETITEMPROPERTY ;do it!
ENDPROC
GETITEMPROPERTY PROC ENTRY
;
; PROCEDURE GetItemProperty(menuHandle,itemNumber, VAR propertyValue) -- is an internal
; routine similar to SetItemProperty that gets a property of a requested item.
; The property is selected by the small integer in D2.
;
MOVE.L 10(SP),A0 ;get menuHandle
MOVE.L (A0),A0 ;turn into menu pointer
MOVE 8(SP),D0 ;get item number
IMPORT GetItemRecord
BSR GETITEMRECORD ;look it up
MOVE.L 4(SP),A0 ;get result pointer
CLR.B (A0) ;assume result of zero <EHB 6-Sep-85>
MOVE.L A1,D0 ;did we find the item?
BEQ.S TENBYTEXIT ;if not, weÕre done
MOVE.B 0(A1,D2),1(A0) ;move the requested property byte
ENTRY TenBytExit
TENBYTEXIT MOVE.L (SP)+,A0 ;get return address
ADD #10,SP ;strip 10 bytes of parameters
JMP (A0) ;return to caller
ENDPROC
SETITEMPROPERTY PROC ENTRY
;
; PROCEDURE SetItemProperty(menuHandle,itemNumber,propertyValue) -- an internal routine
; to set a property byte of an item. A small integer offset in D2 determines
; which property.
;
MOVE.L 8(SP),A0 ;get menuHandle
MOVE.L (A0),A0 ;handle -> pointer
MOVE 6(SP),D0 ;get item number
IMPORT GetItemRecord
BSR GETITEMRECORD ;find the item
BEQ.S TWOPARMEXIT ;if not, skip
MOVE.B 5(SP),0(A1,D2) ;move in the property byte
SUBQ #ItemMark,D2 ; is it the check mark? <EHB 1/24/85>
BEQ.S TwoParmExit ; yes, donÕt recalculate <EHB 1/24/85>
MOVE.L 8(SP),-(SP) ;push the menuHandle
IMPORT DirtyMenuSize
BSR DirtyMenuSize ; invalidate size <EHB 5-Mar-85>
ENTRY TwoParmExit
TWOPARMEXIT MOVE.L (SP)+,A0 ;get return address
ADDQ #8,SP ;strip 8 bytes of parameters
JMP (A0) ;return to caller
ENDPROC
GETITEMRECORD PROC ENTRY
;
; GetItemRecord is the main utility used for accessing the menu item data structure.
; It has a register interface to save code. On entry, A0 points to a menuInfo block,
; while D0 has the item number of interest. On exit, A0 points to the item string
; of interest while A1 points to that itemÕs attribute byte list. If the item canÕt
; be found, A0 and A1 both return NIL and the z-flag is set.
;
TST D0 ; make sure item number is valid
BLE.S NOITEM ; => invalid, donÕt bother
DOITEM MOVEQ #0,D1 ; clear D1 for byte arithmetic
LEA MENUDATA(A0),A1 ; get menuData ptr
MOVE.B (A1)+,D1 ; get title length
ADD D1,A1 ; skip over title string
;
; here is the item search loop. A1 points to the beginning of the next item.
;
GETILOOP SUBQ #1,D0 ; is this the one weÕre looking for?
BEQ.S GOTITEM ; if so, we got it
MOVE.B (A1),D1 ; get length of current item <EHB 8-May-85>
BEQ.S NOITEM ; length zero marks end of list
ADDQ #5,D1 ; 4 bytes of properties + 1 length <EHB 8-May-85>
ADD D1,A1 ; bump to next item
BRA.S GETILOOP ; loop till done
;
; the item couldnÕt be found so return NIL
; put string pointer into D1 in case we want to find end byte
;
NOITEM
MOVE.L A1,D1 ; return pointer to 0 byte in D1 <EHB 8-May-85>
SUB.L A0,A0 ;zero A0
MOVE.L A0,A1 ;and A1 too
MOVE.L A0,D0 ;set the z-flag
RTS ;return to caller
;
; we found the item so return a pointer to it in A0 and a pointer to the item properties in A1
;
GOTITEM TST.B (A1) ;is this the NIL item?
BEQ.S NOITEM ;if so, we really didnÕt get one
MOVE.L A1,A0 ;A0 points to item string
MOVE.B (A1)+,D1 ;get length
ADD D1,A1 ;bump to item properties
RTS ;return to caller (z-clear)
ENDPROC
GetMCEntry PROC EXPORT ; <FJL C408>
;------------------------------------------------------------------------------------
;
; GetMCEntry <FJL C408>
;
;------------------------------------------------------------------------------------
; FUNCTION GetMCEntry(ID, Item : integer) : CMenuStruct --
; Find a color table entry for the given ID/Item combination. Return an index into
; the color table, or a zero if the entry wasnÕt found.
;
move.l d2, -(sp) ; save work register
move.l MenuCInfo, a0 ; get color table handle
move.l (a0), a0 ; dereference
move 8(sp), d0 ; get Item
move 10(sp), d1 ; get ID
clr d2 ; start search at beginning of the table
IMPORT FindCEntry
bsr FindCEntry ; do the search
beq.s @NotFound ; oops couldnÕt find it
lea (a0,d2), a0 ; get the table entry address in a0
move.l a0, 12(sp) ; return it as the result
bra.s @GetDone ; and return
@NotFound move.l #0, 12(sp) ; return zero as result
@GetDone move.l (sp)+, d2 ; restore work register
move.l (sp)+, a0 ; get return address
addq #4, sp ; strip the parameters
jmp (a0) ; and return
ENDPROC
DelMCEntries PROC EXPORT
;-------------------------------------------------------------------------------------
;
; DelMCEntries <FJL C408>
;
;-------------------------------------------------------------------------------------
;
; PROCEDURE DelMCEntries (ID, Item : integer)
;
; Given an ID and Item number, this routine will find the appropriate
; entry in the menu color table and delete it. If the item number is
; equal to #mbAllItems (-98), then all items for the given ID will be deleted.
;
movem.l d2-d4, -(SP) ; save work registers
move 16(SP), d3 ; get Item number
move 18(SP), d4 ; get menuID
clr.l d2 ; start search at beginning of table
@DeleteLoop move d3, d0 ; set up for FindCEntry
move d4, d1
; Get MenuCInfo each time since munger chgs it <KSM BRC40826>
move.l MenuCInfo, a0 ; get handle to color table <KSM BRC40826>
move.l (a0), a0 ; dereference <KSM BRC40826>
IMPORT FindCEntry
bsr FindCEntry; find the entry
beq.s @DoneDelete ; z-flag set ==> couldnÕt find it
; we have a match on both ID and Item so delete it using Munger
@DeleteIt subq #4, SP ; space for result
move.l MenuCInfo, -(SP) ; move the color table handle onto the stack
move.l d2, -(SP) ; d2 is offset into color table
pea (a0,d2) ; push ptr to target string
move.l #mctEntrySize, -(SP) ; len1 = 6 bytes
moveq #4, d0
move.l d0, -(SP) ; make replacement string non-NIL so deletes
; properly, point at an even byte in lo-mem
clr.l -(SP) ; and its length is zero ==> delete
_Munger
addq #4, SP ; ignore the result
; DonÕt need to bump D2 because munger moved data down to where D2 points <KSM BRC40826>
; addi #mctEntrySize, d2 ; start looking at next table entry <KSM BRC40826>
cmpi #mctAllItems, d3 ; is the Item = "all items" flag?
beq.s @DeleteLoop ; yes, so loop
@DoneDelete
IMPORT MenuCTblSanityChk
bsr MenuCTblSanityChk ; check the table for consistency
movem.l (SP)+, d2-d4 ; restore work registers
move.l (SP)+, a0 ; get return address
addq #4, SP ; strip parameters
jmp (a0)
ENDPROC
FindCEntry PROC ENTRY
;-----------------------------------------------
; Utility -- FindCEntry <FJL C408>
;-----------------------------------------------
; This utility will find the color table entry for the
; given ID and Item and table offset.
;
; Special case seaching: if ID = mctAllIds (=-97) ===> return any ID with correct Item
; if Item = mctAllItems (=-98) ===> return any Item with correct ID
;
; 1) If it finds the entry the z-flag will not be set and
; it returns an index into the table in d2.
; 2) If it doesnÕt find the entry the z-flag will be set,
; and d2 will be the offset to the end of the table.
;
; On Entry: A0 ptr pointer to color table
; D0 Item item number looking for, if = mctAllItems (-98) then any item number
; D1 ID ID of menu looking for, if = mctAllIds (-97) then any ID number
; D2 offset offset into the table where we should start looking
;
; On Exit: D2 offset offset into the color table where the given ID/Item was found
; z-flag set if not found
;
; Called From:
cmpi #mctLastIDIndic, mctID(a0,d2) ; are we at the last entry?
beq.s @DoneFind ; yes, so branch
cmpi #mctAllIds, d1 ; are we finding all IDs for the given Item?
beq.s @CheckItem ; yes, so go and check Item for this entry
cmp mctID(a0,d2), d1 ; do we have a match with the given ID?
bne.s @CheckNextID ; no, so branch and try some more
; we have a match on the ID, so check if the Item matches
@CheckItem cmpi #mctAllItems, d0 ; are we finding all items for the given ID?
beq.s @DoneFind ; yes, so just grab this entry
cmp mctItem(a0,d2), d0 ; do we have a match with the Item?
beq.s @DoneFind ; yes, so branch and try some more
; didnÕt find it so try the next item
@CheckNextID addi #mctEntrySize, d2 ; offset to next color table entry
bra FindCEntry ; and loop
@DoneFind cmpi #mctLastIDIndic, mctID(a0, d2) ; set z-flag if didnÕt find the entry
rts ; (check if at last entry flag)
ENDPROC
SetMCEntries PROC EXPORT ; <FJL C408>
;------------------------------------------------------------------------------------
;
; SetMCEntries <FJL C408>
;
;------------------------------------------------------------------------------------
; PROCEDURE SetMCEntries(numEntries: integer; colorEntries: CMenuStruct) --
; Enter all of the given color entries in the menu color table. If an entry
; exists it will be replaced, if itÕs new it will be added.
;
movem.l d2-d3, -(sp) ; save work register
move 16(sp), d3 ; get numEntries
subq #1, d3 ; sub 1 to get right offset to end of table
mulu #mctEntrySize, d3 ; start at last entry
; reuse the following code to reset registers that may have been trashed by Munger
; itÕs just as easy to reset these each time thru, shouldnÕt be a speed hit
@FindItLoop move.l 12(sp), a1 ; get ptr to colorEntries
move.l MenuCInfo, a0 ; get handle to color table
move.l (a0), a0 ; dereference
; first see if the entry exists in the table already
move mctID(a1,d3), d1 ; set up d0, d1 for FindCEntry call
move mctItem(a1,d3), d0
clr.l d2 ; d2 = 0 ===> start at top of table
IMPORT FindCEntry
bsr FindCEntry
beq.s @InsertEntry ; couldnÕt find it so insert it
; found it in the table, so change the entry in place (table offset was returned in d2)
; store RGB1, 2, 3 and 4
add.l d3, a1
add.l d2, a0
exg a0, a1
moveq #mctEntrySize, d0
_BlockMove
;+++ move.l mctRGB1(a1,d3), mctRGB1(a0,d2) ; store RGB1
;+++ move mctRGB1+4(a1,d3), mctRGB1+4(a0,d2)
;+++ move.l mctRGB2(a1,d3), mctRGB2(a0,d2) ; store RGB2
;+++ move mctRGB2+4(a1,d3), mctRGB2+4(a0,d2)
;+++ move.l mctRGB3(a1,d3), mctRGB3(a0,d2) ; store RGB3
;+++ move mctRGB3+4(a1,d3), mctRGB3+4(a0,d2)
;+++ move.l mctRGB4(a1,d3), mctRGB4(a0,d2) ; store background color, donÕt worry
;+++ move mctRGB4+4(a1,d3), mctRGB4+4(a0,d2) ; if this is wrong here, since we
; will make a sanity check later
bra.s @DoNextEntry ; loop to the next entry
; didnÕt find entry so insert it at the end of the table, this is good because this forces the
; first entry to always be the menubar entry (if there is one) and since that is the most
; frequently accessed entry it is best to have it in the front.
@InsertEntry subq #4, sp ; save space for result
move.l MenuCInfo, -(sp) ; move the color table handle onto the stack
move.l d2, -(sp) ; d2 is offset to the end of the color table
clr.l -(sp) ; no target string
clr.l -(sp) ; len1 = 0 ===> want to insert
pea (a1,d3) ; push ptr to insertion string
move.l #mctEntrySize, -(sp) ; and itÕs length
_Munger
addq #4, sp ; ignore the result
@DoNextEntry subi #mctEntrySize, d3 ; go to next entry
bge.s @FindItLoop ; if > or = 0 then continue
@SetMenuColorDone
IMPORT MenuCTblSanityChk
bsr MenuCTblSanityChk ; look thru color table and clean it all up
movem.l (sp)+, d2-d3 ; restore work register
move.l (sp)+, a0 ; get return address
addq #6, sp ; strip parameters
jmp (a0) ; and return
ENDPROC
ClearSanityChks PROC ENTRY
;-----------------------------------------------
; Utility within a Utility -- ClearSanityChks <FJL C408>
;-----------------------------------------------
; Cruise thru the color table, and clear the mctSanityChk
; field for every entry. Later we will set this field as
; we update entries during the sanity chk. Ones that
; werenÕt checked were missed, and will be handled in a
; second pass where default colors will be entered.
move.l MenuCInfo, a0 ; get color table handle
move.l (a0), a0 ; dereference
clr d2 ; start at top of table
@ClearLoop cmpi #mctLastIDIndic, mctID(a0,d2) ; are we at the last entry?
beq.s @ClearDone ; yes, so weÕre done
clr mctReserved(a0,d2) ; no, so clear the sanity check field <1.9>
addi #mctEntrySize, d2 ; bump index to next entry
bra.s @ClearLoop ; and loop
@ClearDone rts
ENDPROC
MenuCTblSanityChk PROC ENTRY
;-----------------------------------------------
; Utility -- MenuCTblSanityChk <FJL C408>
;-----------------------------------------------
; Check thru the whole color table and be sure all
; of the entries are consistent:
; 1) Item = 0 ===> title, so store menu bar color in mctRGB2 slot
; 2) Item != 0 ==> not title, so store menu background color in mctRGB4 slot
;
CkMBColor EQU -6 ; RGB for menu bar
CkBackColor EQU CkMBColor - 6 ; RGB for current IDÕs background color
CkIDSave EQU CkBackColor - 2 ; save d2 as we loop thru Items for an ID
CkFrame EQU CkIDSave ; size of stackframe
link a6, #CkFrame ; set up a stack frame
move.l d2, -(sp) ; save work register
IMPORT ClearSanityChks
bsr ClearSanityChks ; clear sanity checks for all table entries
move.l MenuCInfo, a0 ; get table handle
move.l (a0), a0 ; dereference
; 1) Find menubar color. Menubar has ID == 0, Item == 0, and menubar color is stored in
; mctRGB4 field. It should be copied to RGB2 field for every title entry (Item == 0)
clr d0 ; Item 0
clr d1 ; ID 0
clr d2 ; start at beginning of table
IMPORT FindCEntry
bsr FindCEntry
bne.s @GotMBColor ; found it so get color
; didnÕt find menu bar entry, so use default menubar color -- white
moveq #-1, d0
move.l d0, CkMBColor(a6) ; set RG
move d0, CkMBColor+4(a6) ; set B
bra.s @1 ; and branch
; get color we found
@GotMBColor move.l mctRGB4(a0,d2), CkMBColor(a6) ; set R & G
move mctRGB4+4(a0,d2), CkMBColor+4(a6) ; set B
@1 addq.w #1, mctReserved(a0,d2) ; set sanity check field <1.9>
; 2) Find each title entry (Item = 0), set its menubar color, get its background color and
; save it in the stackframe, then find each of its items and set their background colors
clr CkIDSave(a6) ; start at top of table
@IDLoop clr d0 ; Item 0
move #mctAllIds, d1 ; any ID
move CkIDSave(a6), d2 ; get saved d2 value
bsr FindCEntry ; look for the next title entry in the table
beq.s @SecondPass ; z-flag set means we hit the end of the table
move d2, CkIDSave(a6) ; save d2 since weÕll want to start there next time
addi #mctEntrySize, CkIDSave(a6) ; actually want to start at NEXT entry!
addq #1, mctReserved(a0,d2) ; set sanity check field <1.9>
tst mctID(a0,d2) ; did we get the menu bar entry?
beq.s @IDLoop ; yes, skip it and continue
move.l CkMBColor(a6), mctRGB2(a0,d2) ; set title menubar color R & G
move CkMBColor+4(a6), mctRGB2+4(a0,d2) ; set title menubar color B
move.l mctRGB4(a0,d2), CkBackColor(a6) ; get menu background color R & G
move mctRGB4+4(a0,d2), CkBackColor+4(a6) ; get menu background color B
move mctID(a0,d2), d1 ; put ID we found in d1
move #mctAllItems, d0 ; find any Item with that ID
clr d2 ; start at beginning of the table
@ItemLoop bsr FindCEntry ; look for an entry
beq.s @IDLoop ; got the end of the table, so find the next ID
addq.w #1, mctReserved(a0,d2) ; set sanity check field <1.9>
tst mctItem(a0,d2) ; did we get the title entry?
beq.s @NextItemSetUp ; yes, so skip this entry and continue
move.l CkBackColor(a6), mctRGB4(a0,d2) ; set Item background R & G
move CkBackColor+4(a6), mctRGB4+4(a0,d2) ; set Item background B
@NextItemSetUp addi #mctEntrySize, d2 ; start next Item search at NEXT table entry
bra.s @ItemLoop
; 3) ItÕs possible that there are Items in the table that have no title entry -- these
; items would have zero in the SanityCheck field. So for every entry with SanityCheck = 0
; set the background color to the menu bar default, or white if there is no default.
@SecondPass
clr d0 ; Item 0
clr d1 ; ID 0
clr d2 ; start at beginning of table
bsr FindCEntry
bne.s @GotMBColor2 ; found it so get color
; didnÕt find menu bar entry, so use default background color -- white
moveq #-1, d0
move.l d0, CkBackColor(a6) ; set RG
move d0, CkBackColor+4(a6) ; set B
bra.s @2 ; and branch
; save the color we found in the stackframe
@GotMBColor2 move.l mctRGB2(a0,d2), CkBackColor(a6) ; set R & G
move mctRGB2+4(a0,d2), CkBackColor+4(a6) ; set B
@2 clr d2 ; start search at beginning of color table
@SecondPassLoop
bsr.s FindSanityChks ; get the next one that wasnÕt set
beq.s @SanityDone ; z-flag set means end of table, so done
; found one, so set its background color
move.l CkBackColor(a6), mctRGB4(a0,d2) ; set R & G
move CkBackColor+4(a6), mctRGB4+4(a0,d2) ; set B
addi #mctEntrySize, d2 ; skip to next table entry
bra.s @SecondPassLoop ; and find the next one
@SanityDone move.l (sp)+, d2 ; restore work register
unlk a6 ; toss the stack frame
rts
FindSanityChks
;-----------------------------------------------
; Utility within a Utility -- FindSanityChks <FJL C408>
;-----------------------------------------------
; Cruise thru the color table, and find the next
; entry whose SanityCheck field in zero.
cmpi #mctLastIDIndic, mctID(a0,d2) ; are we at the last entry?
beq.s @FindDone ; yes, so weÕre done
tst mctReserved(a0,d2) ; is the sanity field set? <1.9>
beq.s @FoundEntry ; nope, so branch
addi #mctEntrySize, d2 ; yes, so bump index to next entry
bra.s FindSanityChks ; and loop
@FoundEntry moveq #1, d0 ; z-flag not set tells caller that we found an entry
@FindDone rts
ENDPROC
PROC
;-----------------------------------------------
; MenuKey Stack Frame Definitions
;-----------------------------------------------
;
CmdChar EQU 9 ; command char is in lo-byte of param [byte/word]
MenuResult EQU 10 ; menu ID part of result
mItemResult EQU 12 ; Item part of result
searchMenu EQU -8 ; looking for the parent of...
HorRMenus EQU searchMenu - 2 ; looking thru HMenus (=0), or Regular Menus (=1)
KeyFrame EQU HorRMenus - 2
; Utility UpChar -- Upshift the character in D0
; Given a character in D0, it uses the UprString routine to upshift the char
; (stripping diacriticals) and returns it in D0
UpChar
MOVE.B D0,-(SP) ; push character <EHB 15-Apr-85>
;<SM5> <PN> Use the following for SuperMario
move.l sp,-(sp) ; push text ptr <19>
move.w #1,-(sp) ; push length <19>
move.w #smSystemScript,-(sp) ; use system script, ignore port <19>
_SCUpperText ; (stack based!) <19>
MOVE.B (SP)+,D0 ; return shifted character <EHB 15-Apr-85>
RTS
EXPORT MENUKEY
MENUKEY
;------------------------------------------------------------------------------------------------
;
; MenuKey -- determine if a command key is valid and if so what menu and item it refers to
;
;------------------------------------------------------------------------------------------------
;
; FUNCTION MenuKey(commandChr): LongInt -- menuKey is kind of a companion routine to
; MenuSelect; it is called when a command character is typed and scans the current
; menu data structure, returning a (whichMenu, whichItem) pair that corresponds to the
; selected command. If a command is not recognized, the result returned is zero
;
; Check thru the regular menus first, then the hierarchical menus. Use D6 as flag <FJL C222>
; so we know whether checking regular or H Menus
;
; Hilite the "parent" menu when a hierarchical menu is chosen. <FJL C222>
; Roll in PatchMDMenuKey <SM5> <PN>
import PushMenuState,PopMenuState ;<SM5> <PN>
resultsStackFrame
result ds.l 1 ; the menukey result <SM5> <PN>
parametersStackFrame
ch ds.w 1 ; the char to pass thru <SM5> <PN>
endStackFrame
linkSave
jsr PushMenuState ; Potentially save off the menu state <SM5> <PN>
subq #4,sp ; Make room for MenuKey result <SM5> <PN>
move.w ch(a6),-(sp) ; Push the character <SM5> <PN>
jsr OriginalMenuKey ;<SM5> <PN>
move.l (sp)+,result(a6) ; Save off the result <SM5> <PN>
jsr PopMenuState ; Restore the menu state if it was saved <SM5> <PN>
restoreUnlinkReturn
OriginalMenuKey
link a6, #KeyFrame ; set up stackframe
MOVEM.L D3-D6/A3,-(SP) ;save work registers
move.b CmdChar(a6), d0 ; get character to search for
BSR.S UpChar ; upshift in D0 <EHB 15-Apr-85>
MOVE.B D0,D4 ; and save in D4 <EHB 15-Apr-85>
IMPORT GetA0List
bsr GetA0List ; get menuList pointer into A0
move lastMenu(a0), d5 ; go to last menu
clr d6 ; zero flag == checking regular menus <FJL C222>
; here is the outer loop where each menu in the menuList is considered
KEYBARLOOP BSR GETMENUPTR ;get menu pointer in A0 from index in D5
MOVE.L A0,A3 ;stash in A3 for safe keeping
BTST #0,MENUENABLE+3(A3) ;is this menu enabled?
BEQ.S NEXTBAR ;if not, skip it
MOVEQ #1,D3 ;start with item number 1
;
; here is the inner loop where each item is considered
;
KEYITEMLOOP MOVE.L MENUENABLE(A3),D0 ;get enable flags
BTST D3,D0 ;make sure this item is enabled
BEQ.S KEYNEXTITEM ;if not, skip it
EnabledKeyItemLoop ; <10> Loops to here when item in D3 > 31
MOVE.L A3,A0 ;get menuPtr in A0
MOVE D3,D0 ;get item number in D0
IMPORT GetItemRecord
BSR GETITEMRECORD ;search for item
BEQ.S NEXTBAR ;if not, this menu is exhausted
MOVE.B ItemCmd(A1),D0 ;get the command char
BEQ.S KEYNEXTITEM ; donÕt upshift if there is no cmd-key
BSR.S UpChar ; upshift it in D0 <EHB 11-Apr-85>
;NOTE: WeÕve reserved the values $1B thru $1F in cmdItem as having meanings other than <FJL C222>
; than that of a command key.
; Value: $1B (HMenuCmd) - item has hierarchical menu
; (menuID of HMenu is in itemMark field)
; $1C (ScriptMenuCmd) - item has script defined
; (script number is in itemIcon field)
; $1D - $1F - undefined at this time
;
cmpi.b #FirstAltMenuCmd, d0 ; item between $1B and $1F? <FJL C222>
blt.s @DoCompare ; no, so continue <FJL C222>
cmpi.b #LastAltMenuCmd, d0 ; <FJL C222>/<C338>
bhi.s @DoCompare ; no, so continue <FJL C222>
bra.s KeyNextItem ; if here then cmdItem is between <FJL C222>
; $1B and $1F so skip comparison <FJL C222>
@DoCompare CMP.B D0,D4 ;do they match?
BEQ.S GOTMKEY ;if they do, weÕve found it!
KEYNEXTITEM ADDQ #1,D3 ;bump to next item
CMPI.W #31,D3 ;<10> items > 31 are always enabled
BHI.S EnabledKeyItemLoop ;<10> so skip moving the flags and the btst
BRA.S KEYITEMLOOP ;loop till we find it or no more
NEXTBAR subq #6, d5 ; bump to next item
cmp d6, d5 ; have we reached the value in d6?
bgt.s KeyBarLoop ; loop till we reach it
tst d6 ; does d6 have a value? <FJL C222>
bne.s KeyNotFound ; yes, so have checked regular AND HMenus <FJL C222>
;
; d6 was equal to zero, so now check thru the hierarchical menus
;
IMPORT GetHA0List
bsr GetHA0List ; get HMenuList ptr in A0
move lastHMenu(a0), d5 ; get #HMenus
beq.s KeyNotFound ; none, so donÕt check Õem
; yes there are menus so check them backwards
move.l MinusOne, d1 ; set up for GetHIndex call
IMPORT GetHIndex
bsr GetHIndex ; d0 now has ptr to HMenuList header info
add d0, d5 ; d5 points at last HMenu
move d0, d6 ; d6 points at HMenuList header
bra.s KeyBarLoop ; and start checking
;
; no corresponding command key was found, so return zero as the result
;
KEYNOTFOUND clr.l menuResult(a6) ; clear the function result -- menu and item
MKEYDONE MOVEM.L (SP)+,D3-D6/A3 ; restore work registers
unlk a6 ; dismantle the stack frame
IMPORT TwoBytExit
BRA TWOBYTEXIT ; standard exit saves code
;
; we got a good key so return the result (whichMenu, whichItem)
;
GOTMKEY BSR GETMENUPTR ;get pointer to correct menuID
move menuID(a0), menuResult(a6) ; store the menuID <FJL C222>
move d3, mItemResult(a6) ; and the Item <FJL C222>
move menuResult(a6), searchMenu(a6) ; init searchMenu(a6) <FJL C222>
tst d6 ; is d6 clear? <FJL C222>
beq.s @HiliteMBar ; yes, so was a regular menu <FJL C222>
clr HorRMenus(a6) ; init HorRMenus(a6) to HMenus <FJL C222>
moveq #8, d4 ; d4 is recursive test counter
bsr.s FindParentMenu ; no, so find the HMenuÕs parent <FJL C222>
@HiliteMBar MOVE searchMenu(a6),-(SP) ;push menuID as parameter <FJL C222>
_HiliteMenu ;hilite it
;
; check to see if this one belongs to a desk ornament
;
TST MBarEnable ;does desk ornament own menuBar?
BMI.S @DeskMKey ;if so, handle it
;+++ move.l menuResult(a6), d0 ; if theMenu negative?
; CanÕt just use menuResult(a6) since could<FJL 09Mar87>
; be a HMenu associated with the desk acc<FJL 09Mar87>
tst TheMenu ; Is it a system menu? <FJL 09Mar87>
BPL.S MKEYDONE ;if not, weÕre done
;
; the menu belonged to a desk ornament so tell the desk manager about it
;
; HMenus cause problems here. Since the menu ID (funcResult) is not = to the DAÕs <FJL 09Mar87>
; menu ID, SystemMenu will never find the DA in the DA list. To force it to pass
; the HMenu ID we can set MBarEnable temporarily.
;
; Need to allow a DA that owns the menu bar to reset MBarEnable in the middle of _SystemMenu <FJL PMAB280>
; Had to move around some parts of this routine. Only set/clear MBarEnable when MBar not
; already owned by DA.
;
@DeskMKey
tst.w MBarEnable ; who owns menu bar?
bmi.s @1 ; desk acc ==> weÕre cool
move TheMenu, MBarEnable ; set MBarEnable with DAÕs ID
move.l menuResult(a6),-(sp) ; push the result
_SystemMenu ; invoke desk manager
clr.l menuResult(a6) ; pretend we didnÕt get anything
; NOTE: clears funcResult AND itemResult !!!
clr.w MBarEnable ; clear MBarEnable
bra.s MKeyDone
@1 move.l menuResult(a6),-(sp) ; push the result
_SystemMenu ; invoke desk manager
clr.l menuResult(a6) ; pretend we didnÕt get anything
; NOTE: clears funcResult AND itemResult !!!
BRA.S MKEYDONE ;all done
FindParentMenu
;-----------------------------------------------
; Utility -- FindParentMenu <FJL C222>
;-----------------------------------------------
;
; We have a hierarchical menu, so we need to find its regular menu "parent" and hilite it.
; It could be several levels of hierarchy deep, so look thru the HMenus until
; we donÕt find it, then look thru the regular menus to get the parent. This code
; doesnÕt allow recursively defined menus, it stops looking after 8 menus (I didnÕt want
; to test the boundary condition of whether it is 5 or 6 or 7 that should stop at with
; five levels of hierarchy, so just made it 8 to be safe).
;
; Allowed a hierarchical menu to not have a parent in the menubar. Did this so <FJL 26Mar87>
; that could have menu keys on popup menus.
;
subq #1, d4 ; reduce recursive count
beq.s @NoParent ; got to zero, so must be recursive
IMPORT GetHA0List
bsr GetHA0List ; get HMenuList ptr in A0
move lastHMenu(a0), d5 ; get #HMenus
; we know there are HMenus so check them backwards
move.l MinusOne, d1 ; set up for GetHIndex
IMPORT GetHIndex
bsr GetHIndex ; d0 now has index to HMenuList header info
add d0, d5 ; d5 has index to last HMenu
move d0, d6 ; d6 has index to HMenuList header
@MenuLoop
bsr GetMenuPtr ; get menu ptr in A0 from ID in D5
move.l a0, a3 ; stash in A3 for safe keeping
moveq #1, d3 ; start with item number 1
;
; inner loop where each item is considered
;
@ItemLoop move.l a3, a0 ; set up for GetItemRecord, put menuPtr in a0
move.l d3, d0 ; and put item number in d0
IMPORT GetItemRecord
bsr GetItemRecord ; search for item
beq.s @NextMenu ; if not, this menu is exhausted
cmpi.b #HMenuCmd, itemCmd(a1) ; does this menu have a HMenu?
bne.s @NextItem ; no, so keep looking
moveq #0, d1 ; clear d1
move.b itemMark(a1), d1 ; get menuID of HMenu for this item
cmp searchMenu(a6), d1 ; is this the menu we are looking for?
bne.s @NextItem ; no, so keep looking
move menuID(a3), searchMenu(a6) ; found a parent so save it
tst HorRMenus(a6) ; still searching HMenus?
beq.s FindParentMenu ; yes, so try again with the parent menuID
bra.s @FindParentEnd ; no, so found oldest ancestor amongst regular menus
@NextItem addq #1, d3 ; go to next item
bra.s @ItemLoop
@NextMenu subq #6, d5 ; bump to next menu
cmp d6, d5 ; at end of list?
bgt.s @MenuLoop ; no, so try the next menu
;
; if weÕre here then have exhausted HMenuList without finding a parent, so we now search
; the regular menu list to find the oldest ancestor of the HMenu being returned as the result.
;
tst HorRMenus(a6) ; HorRMenus = 0 means just finished checking
; hierarchical menus, try regular menus <FJL 26Mar87>
beq.s @WereOK
bra.s @FindParentEnd ; HorRMenus = 1 means finished checking <FJL 26Mar87>
; regular menus, stop trying, and return
@NoParent move #dsHMenuFindErr, d0 ; error code for recursive menus <FJL 26Mar87>
_SysError
@WereOK addq #1, HorRMenus(a6) ; flag that searching regular menus
IMPORT GetA0List
bsr GetA0List ; get menuList ptr into A0
move lastMEnu(a0), d5 ; go to last regular menu
clr d6 ; stop searching when index == 0
bra.s @MenuLoop ; go find it
@FindParentEnd
rts
ENDPROC
GETITEM PROC EXPORT
;
; PROCEDURE GetItem(menuHandle,itemNumber,VAR string); -- get the text of a menu item
;
MOVE.L 10(SP),A0 ;get menuInfo handle
MOVE.L (A0),A0 ;handle to pointer
MOVE.W 8(SP),D0 ;get item number
IMPORT GetItemRecord
BSR GETITEMRECORD ;look it up
;
MOVE.L 4(SP),A1 ;get result stringPtr,(zflag preserved)
BEQ.S NOITEM1 ;if not, return empty string
;
; use blockMove to copy the string
;
MOVEQ #0,D0 ;clear out D0
MOVE.B (A0),D0 ;get length of string
ADDQ #1,D0 ;move length byte, too
_BLOCKMOVE ;let memory manager move it fast
DONEGI
IMPORT TenBytExit
BRA TENBYTEXIT ;standard exit saves code
;
; item not found, so return the null string
;
NOITEM1 CLR.B (A1) ;set result string length to zero
BRA.S DONEGI ;standard exit saves code
ENDPROC
NEWMENU PROC EXPORT
;
; FUNCTION NewMenu(menuID,titleString):menuHandle -- allocate a new menu block with
; the specified menuID and title.
;
MOVEQ #0,D1 ;clear out the high part
MOVEQ #MenuBlkSize+2,D0 ;get size of menuInfo block
MOVE.L 4(SP),A0 ;point to the title string
MOVE.B (A0),D1 ;get its length
ADD.W D1,D0 ;compute real length
_NEWHANDLE ;allocate it
MOVE.L A0,10(SP) ;return menuHandle as result
MOVE.L (A0),A1 ;get menu pointer
MOVE.W D1,-(SP) ;save title size for later
;
; initialize the fields of the menu definition record
;
MOVE.W 10(SP),(A1)+ ;init menuID
CLR.L (A1)+ ;zero width and heigth initially
; initialize the menu defProc handle
MOVEQ #0,D0 ; standard rom based MDEF is #0
SUBQ #4,SP ;make room for function result
MOVE.L #'MDEF',-(SP) ;push MDEF resource type
move.W d0, -(SP) ;push the rsrcID <TESTX>
MOVE.W #MapTRUE,ROMMapInsert ;get MDEF 0 from the ROM Map <9 July 85>
_GetResource ;get it
MOVE.L (SP)+,A0 ;get mDef handle in A0
; since GetResource can allocate memory, better rebuild the ptr from its handle
MOVE.L 12(SP),A1 ;get menuHandle
MOVE.L (A1),A1 ;get menuPtr
ADDQ #MenuDefHandle,A1 ;bump to defHandle
MOVE.L A0,(A1)+ ;install menuProc
MOVE.L MinusOne,(A1)+ ;everythingÕs enabled to start
;
; move in the title string
MOVE.W (SP)+,D1 ;get length of string
MOVE.L 4(SP),A0 ;get string ptr
@1 MOVE.B (A0)+,(A1)+ ;move in the string
DBRA D1,@1 ;loop till done
;
; add the string of length zero on the end
;
CLR.B (A1)+ ;string of length zero
IMPORT SixBytExit
BRA SIXBYTEXIT ;all done -- standard exit saves code
ENDPROC
;
; AppendMenu Stack Frame Definition
;
ITEMPROPERTIES EQU -280 ;4 attribute bytes of item
ITEMSTATE EQU ITEMPROPERTIES+4 ;one byte parse state field
ITEMFLAGS EQU ITEMSTATE+1 ;one byte enable flag field
ITEMCOUNT EQU ITEMFLAGS+1 ;integer -- number of chars in buffer
ITEMBUFFER EQU ITEMCOUNT+2 ;256 byte buffer for items
;+4 for copying properties
ItemFontNum EQU ItemProperties - 2 ; use for GetFNum call <FJL CXXX>
FontFondFlag EQU ItemFontNum - 2 ; 0 = not font/fond, 1 = font/fond <FJL CXXX>
ItemLinkSize EQU FontFondFlag ; <FJL CXXX>
APPENDMENU PROC EXPORT
;
; PROCEDURE AppendMenu(menuHandle,itemString) -- add the list of items represented by
; the item string to the menu. The itemString may contain one or more items, seperated
; by carriage returns or semicolon characters. The item strings are also scanned for
; special meta-characters that change their initial properties.
MOVE.L (SP)+,A0 ; add an "afterItem" param so <EHB 8-May-85>
MOVE.W #999,-(SP) ; it looks like an InsMenuItem call <EHB 8-May-85>
MOVE.L A0,-(SP) ; and fall into InsMenuItem <EHB 8-May-85>
EXPORT INSMENUITEM
INSMENUITEM ; <EHB 8-May-85>
; PROCEDURE InsMenuItems(MenuHandle: Handle; itemstring: str255; itemNum: INTEGER)
; -- insert the items in the itemstring after the specified item (to insert at
; beginning, pass item of 0). ItemString is parsed just like the itemstring in
; AppendMenu. Multiple items are inserted in the reverse of their order in the
; string.
IMPORT TenBytExit
TST.L 6(SP) ; Is the StringPtr NIL? <8>
BEQ.S @PixelPaintError ; EQ means it is - BAIL <8>
MOVE.L 10(SP),D0 ; Is the menuHandle NIL? <8>
BEQ.S @PixelPaintError ; EQ means it is, bail <8>
BTST #0,D0 ; Is the handle odd? <8>
BNE.S @PixelPaintError ; NE means it is odd, bail <8>
LINK A6,#ItemLinkSize ; allocate local space
MOVEM.L D3-D7/A2-A4,-(SP) ; save some work registers
MOVE.L 10(A6),A4 ; get itemString ptr in A4
MOVE.L 14(A6),A3 ; get menuHandle in A3
MOVE.W 8(A6),D6 ; get insert point in D6
ADDQ #1,D6 ; make it a true index
IMPORT AddString
BSR AddString ; make menu items out of the string
MOVEM.L (SP)+,D3-D7/A2-A4 ; restore the registers
UNLK A6 ; unbuild the stack frame
@PixelPaintError ; <6>
BRA TenBytExit ; standard exit save code
ENDPROC
AddString PROC ENTRY
; AddString parses the specified string, placing it into the ITEMBUFFER, and setting up
; the other item properties. When it encounters the end of an item, it transfers
; it from the buffer into the menu.
; On Entry: A3 MenuHandle
; A4 ItemString pointer
; D6 Item to insert before
; CLR D3 ; <PMAB568 07Sep88 EMT>
; MOVE.B (A4)+,D3 ;get length of itemString <PMAB568 07Sep88 EMT>
IMPORT InitItem
BSR INITITEM ; initialize local buffer for new item
; SUBQ #1,D3 ; bias for DBRA loop <PMAB568 07Sep88 EMT>
MOVEQ.L #0, D3 ; Initialize counter <PMAB568 07Sep88 EMT>
BRA.S EndApLoop ; Go to end of loop <PMAB568 07Sep88 EMT>
;
; process each character in the itemString, one character at a time
;
APLOOP
SUBQ.L #2, SP ; Make room for result <PMAB568 07Sep88 EMT>
MOVE.L A4, -(SP) ; textBuf pointer <PMAB568 07Sep88 EMT>
MOVE.W D3, -(SP) ; textOffset <PMAB568 07Sep88 EMT>
_CharByte ; <PMAB568 07Sep88 EMT>
MOVE.W (SP)+, D2 ; Stuff result into D2 <PMAB568 07Sep88 EMT>
MOVE.B (A4, D3), D0 ;get next character <PMAB568 07Sep88 EMT>
IMPORT AppendChar
BSR APPENDCHAR ;process it
; DBRA D3,APLOOP ;process each character <PMAB568 07Sep88 EMT>
EndApLoop ; <PMAB568 07Sep88 EMT>
ADDQ.L #1, D3 ; Increment character index <PMAB568 07Sep88 EMT>
CMP.B (A4), D3 ; Done yet? <PMAB568 07Sep88 EMT>
BLS.S APLOOP ; Nope, continue <PMAB568 07Sep88 EMT>
IMPORT CloseItem
BSR CLOSEITEM ;close out any item that may be open
MOVE.L A3,-(SP) ; push menu handle
IMPORT DirtyMenuSize
BSR DirtyMenuSize ; invalidate size <EHB 5-Mar-85>
RTS
ENDPROC
INITITEM PROC ENTRY
;
; InitItem initializes the item buffer
;
LEA ITEMPROPERTIES(A6),A0 ;get address of item properties
CLR.L (A0)+ ;clear property parameters
CLR.L (A0) ;clear out state/flags/count
RTS
ENDPROC
APPENDCHAR PROC ENTRY
; AppendChar does all the real work. It processes the character in D0 by checking out
; what state its in. If in a command state, it uses the character to update a
; property byte. In normal state, characters go into a buffer that is added to the
; menu when a carriage return or semicolon is scanned
;
MOVEQ #0,D1
MOVE.B ITEMSTATE(A6),D1 ;get current state
BEQ.S NORMSTATE ;if normal state, go handle it
;
CMP.B #ITEMICON+1,D1 ;is it an icon item?
BNE.S @1 ;if not,skip
SUB #$30,D0 ;adjust ASCII
;
@1 CMP.B #ITEMSTYLE+1,D1 ;is it a style?
BNE.S UPDATEPROP ;handle style characters special
;
; handle style properties special by scanning table and oring bits
;
MOVEQ #4,D2 ;start at last one
@2 CMP.B STYLECHRTAB(D2),D0 ;is it in the table?
BEQ.S ADDTOSTYLE ;if so, modify D0
DBRA D2,@2 ;bump to next one
;
; if its not in table, just ignore it
;
RTS
;
; Meta character definition table -- this table defines which meta-character
; perform what functions; the order is icon,command,mark,style,delimiter,delimiter,
; disable.
;
MCHARTABLE DC.B '^' ;arrow is the icon character
DC.B '/' ;slash is command character
DC.B '!' ;exclamation point is mark character
DC.B '<' ;less-than is the style character
DC.B $0D ;carriage return is one delimiter
DC.B ';' ;semi-colon is the other
DC.B '(' ;leftParen is disable character
dc.b HMenuCmd ;hierarchical menu character ($1B) <FJL C222>
;****** BE SURE THE ABOVE TABLE IS OF EVEN LENGTH IF YOU ADD NEW SYMBOLS *********
;
; style character table
;
STYLECHRTAB DC.B 'BIUOS' ;bold,italic,underline,outline,shadow
ALIGN
ADDTOSTYLE LEA ITEMPROPERTIES-1(A6),A0 ;get property table address
MOVE.B 0(A0,D1),D0 ;get current property
BSET D2,D0 ;set appropriate property
UPDATEPROP LEA ITEMPROPERTIES-1(A6),A0 ;get address of item property table
cmp #8, d1 ; do we have a hierarchical menu here? <FJL C222>
bne.s @NotHierMenu ; no, so branch <FJL C222>
move.w #2, d1 ; for a HMenu <FJL C222>
move.b #HMenuCmd, 0(a0, d1) ; ==> itemCmd (byte 2) = $1B(HMenuCmd) <FJL C222>
move.w #3, d1 ; ==> itemMark(byte 3) = char in d0 <FJL C222>
@NotHierMenu MOVE.B D0,0(A0,D1) ;update the property <FJL C222>
CLR.B ITEMSTATE(A6) ;return state to normal
RTS
;
; Handle the normal state by scanning for any of the 8 (not 7) special characters <FJL C222>
;
NORMSTATE
TST.W D2 ; See if it is a single byte character <PMAB568 07Sep88 EMT>
BNE.S MultiChar ; Skip if not <PMAB568 07Sep88 EMT>
LEA MCHARTABLE,A0 ;get address of character table
MOVEQ #7,D1 ;scan it backwards, 8 characters now <FJL C222>
NSLOOP CMP.B 0(A0,D1),D0 ;is it one of the special ones?
BNE.S @loop
IMPORT SpecialChar
JMP SPECIALCHAR ;if so, go handle it
@loop
DBRA D1,NSLOOP
;
; it wasnÕt in the exception table so it must be a normal character. Just append it
; to the item buffer.
;
MultiChar ; <PMAB568 07Sep88 EMT>
MOVE ITEMCOUNT(A6),D1 ;get total number of characters
LEA ITEMBUFFER(A6),A0 ;get address of buffer
MOVE.B D0,0(A0,D1) ;stick character in buffer
ADDQ #1,ITEMCOUNT(A6) ;bump buffer index
RTS
ENDPROC
;
; it was one of the special characters -- first see if its a property command -- ^ / ! < $1B
;
SPECIALCHAR PROC ENTRY ; Get around bug in assembler with short branches.
CMP #3,D1 ; which char was it?
BLE.S @PropertyChar ; if 0 through 3, is a property cmd
cmp #7, d1 ; is it the hierarchical menu character?
bne.s CheckTerm ; not a hierarchical item
;
; it was a property meta-character so update the state accordingly
;
@PropertyChar ADDQ #1,D1 ;bump state
MOVE.B D1,ITEMSTATE(A6) ;update state
RTS
;
; check for termination characters like carriage return or semicolon
;
CHECKTERM SUBQ #6,D1 ;was it enable character?
BNE.S CLOSEITEM ;it must have been a termination character
;
; disable the item
;
ST ITEMFLAGS(A6) ;flag the item to be disabled
RTS
ENTRY CloseItem
CLOSEITEM
;
; CloseItem is called to add the item in the buffer (and its associated properties) to
; the actual menu data structure. After this is done, re-initialize for the next item
; On entry, the item insertion index is in D6
;
MOVE ITEMCOUNT(A6),D0 ;get the # of characters in buffer
BEQ.S CLOSEDONE ;if none, weÕre done
IMPORT InsertTheItem
BSR InsertTheItem ; put the new item into the menu <EHB 8-May-85>
IMPORT InitItem
BSR INITITEM ; prepare for next item
CLOSEDONE RTS
ENDPROC
GetGoodIndex PROC ENTRY
; ---------------
; Utility GetGoodIndex -- takes an index into the menu list in D6 and a menu handle in A3.
; Returns a valid insertion index in D5. Trashes D0-D2, A0-A1
; <PMAB280>
MOVE.W D6,D5 ; get proposed index
SUBQ #2,SP ; count menu items
MOVE.L A3,-(SP) ; push menu handle
_CountMItems
MOVE.W (SP)+,D0 ; get count
ADDQ #1,D0 ; make it an insertion index
CMP.W D0,D5 ; if D5 is bigger
BLE.S @0 ; then use count+1
MOVE.W D0,D5 ; preserve in D5
@0 Rts
ENDPROC
InsertTheItem PROC ENTRY ; <EHB 8-May-85>
; InsertTheItem -- inserts the item in the item buffer before the item designated by D6.
; If D6 is bigger than the last item, append the item to the end of the list. Keeps true
; insertion item # in D5
IMPORT GetGoodIndex
BSR GetGoodIndex ; index in D6 -> good index in D5
MOVE.W D5,D0 ; get insertion index
MOVE.L (A3),A0 ; get menu pointer
IMPORT GetItemRecord
BSR GetItemRecord ; point to itemÕs string
BEQ.S @1 ; => out of range. End pointer in D1
MOVE.L A0,D1 ; else get pointer in D1
; only need to insert enable bit if insert within range. (bits at end are all alike)
MOVE.L (A3),A0 ; get menu list pointer
IMPORT InsertEnableBit
BSR InsertEnableBit ; insert bit in posÕn in D5
@1
LEA ITEMBUFFER(A6),A0 ; point to string data
MOVE.L A0,A2 ; save insertion string in A2
MOVE.W ITEMCOUNT(A6),D2 ; get the string length
ADDA.W D2,A0 ; point past end of string
LEA ITEMPROPERTIES(A6),A1 ; get address of properties
MOVEQ #3,D0 ; and move in 4 property bytes
@2 MOVE.B (A1)+,(A0)+ ; move a byte
DBRA D0,@2 ; loop till done
SUBQ #1,A2 ; point to insertion count byte
ADD.W #5,D2 ; get length of data into D2
EXT.L D2 ; (itemCount + 1 length + 4 property)
MOVE.L D1,A1 ; get address of data
SUB.L (A3),A1 ; get offset into menu list
SUBQ #4,SP ; weÕre here to get results
MOVE.L A3,-(SP) ; push handle to menu list
MOVE.L A1,-(SP) ; push offset into menu list
CLR.L -(SP) ; no source string
CLR.L -(SP)
MOVE.L A2,-(SP) ; just an insertion string
MOVE.L D2,-(SP) ; and its length
_Munger
ADDQ #4,SP ; ignore results
TST.B ITEMFLAGS(A6) ; was it disabled?
BEQ.S InsertDone ; => no, donÕt need to disable
MOVE.L A3,-(SP) ; push menu handle
MOVE.W D5,-(SP) ; and item number
BSR DisableItem ; and disable it
InsertDone
RTS
ENDPROC
InsertEnableBit PROC ENTRY
; InsertEnableBit -- insert a bit into the MenuEnable byte, turned on.
; Index is in D5, menulist pointer is in A0.
; Trashes D0,D2.
;
;DONE: donÕt do this if D5 > 31 otherwise we wind up screwing up the rotation.
; Recall that all items > 31 are always enabled
cmp #31, d5 ; is the item > 31 ? <FJL PMAB255>
bhi.s @DoneInsert ; yes, so leave without updating flags <FJL PMAB255>
MOVE.L MenuEnable(A0),D2 ; get current enable flags
ROR.L D5,D2 ; rotate n bits <EHB 3-May-85>
MOVE.W D5,D0 ; get 32-n with extend
SUB.W #32,D0 ; by negating n-32
NEG.W D0 ; extend is inserted 1 bit
ROXR.L D0,D2 ; rotate in others
MOVE.L D2,MenuEnable(A0) ; replace the flags <EHB 3-May-85>
@DoneInsert RTS
ENDPROC
GETMHANDLE PROC EXPORT
; FUNCTION GetMHandle(menuID): menuHandle -- convenience procedure which returns
; a menuHandle given a menuID. If the menuID cannot be found in the current menuList,
; NIL is returned
;
; Look in HMenu list first, then in regular portion of MenuList <FJL C222>
;
CLR.L 6(SP) ;set result to NIL
moveq #0, d1 ;clear hi-word for GetHIndex call <FJL C222>
MOVE 4(SP),D1 ;get menuID
IMPORT GetHIndex
bsr GetHIndex ; look in H Menus for the menuID <FJL C222>
bne.s @GotRMenu ; branch if menuID in HMenus <FJL C222>
IMPORT GetIndex
BSR GETINDEX ; get menuIndex
beq.s @1 ; branch if couldnÕt find it at all <FJL C222>
@GotRMenu MOVE D5,-(SP) ;preserve D5
MOVE D0,D5 ;get menuIndex in D5
BSR GETMENUPTR ;get handle to menu in A1
MOVE (SP)+,D5 ;restore D5
MOVE.L A1,6(SP) ;set function result
IMPORT TwoBytExit
@1 BRA TWOBYTEXIT ;standard exit saves code
ENDPROC
DELMENUITEM PROC EXPORT ; <EHB 15-Apr-85>
; PROCEDURE DelMenuItem(MenuHandle:Handle; itemNum: INTEGER) -- delete the specified
; item from the specified menu. Shoves an extra return address on the stack to
; make stack parallel with SetItem, below.
MOVE.L (SP),-(SP) ; old RTS -> phony newItem
MOVEM.L D3-D4/A2-A4,-(SP) ; save work registers
; begin by removing itemÕs entry in menu color table <FJL C408>
MOVE.L 30(SP),A3 ; get menu handle <FJL C408>
MOVE.L (A3),A0 ; get menu ptr <FJL C408>
move menuID(a0), -(sp) ; push menuID on stack <FJL C408>
MOVE.W 30(SP),-(sp) ; push itemNum on stack <FJL C408>
_DelMCEntries ; and remove item's menu color entry <FJL C408>
; set up for rest of DelMenuItem
MOVE.L 30(SP),A3 ; get menu handle
MOVE.L (A3),A0 ; get menu for GetItemRecord
MOVE.W 28(SP),D0 ; get item for GetItemRecord
; need to delete the itemÕs enable bit from MenuEnable
Cmpi.W #31, D0 ; item number > 31 ? <FJL PMAB282>
Bhi.S @1 ; yes -> skip enable bits stuff <FJL PMAB282>
MOVE.L MenuEnable(A0),D1 ; get enable bits for menu items <EHB 3-May-85>
MOVE.W D0,D2 ; get 32-n with extend set
SUB.W #32,D2 ; by negating n-32
NEG.W D2
ROXL.L D2,D1 ; shift in new high bit (set)
ROL.L D0,D1 ; leave deleted bit in extend
MOVE.L D1,MenuEnable(A0) ; and save updated enable bits
@1
IMPORT GetItemRecord
BSR GetItemRecord ; look up the specified
BNE.S @continue
IMPORT SetIDone
JMP SetIDone ; => item not found
@continue
MOVEQ #5,D4 ; 4 property bytes + 1 length byte
MOVEQ #0,D2 ; length of replacement string
MOVE.L D2,A2 ; and NIL replacement string
IMPORT SICommon
BRA SICommon ; go parasitize host...
ENDPROC
SETITEM PROC EXPORT
; PROCEDURE SetItem(menuHandle:Handle; itemNum: INTEGER; newItem: String) -- change
; the specified item to the new string, keeping the same attributes as the old one
MOVEM.L D3-D4/A2-A4,-(SP) ;save work registers
MOVE.L 30(SP),A3 ;get menu handle
MOVE.W 28(SP),D3 ;get item number
MOVE.L 24(SP),A2 ;get string pointer
MOVE.W D3,D0 ;get item in D0
MOVE.L (A3),A0 ;get menu ptr in A0
IMPORT GetItemRecord
BSR GETITEMRECORD ;find our entry
BEQ.S SETIDONE ;if not, weÕre done
MOVEQ #1,D4 ; get 1 for length byte
MOVEQ #1,D2 ; get 1 for length byte
ADD.B (A2),D2 ; add in length of new string
ENTRY SICommon
SICommon
MOVE.L A0,A4 ; remember item ptr in A4
SUB.L (A3),A4 ; offset = item pointer - menu start
ADD.B (A0),D4 ; Length = D4 + menuString length
SUBQ #4,SP ; make room for result
MOVE.L A3,-(SP) ; push menu handle
MOVE.L A4,-(SP) ; offset to string to be replaced
CLR.L -(SP) ; no search string
MOVE.L D4,-(SP) ; old length
MOVE.L A2,-(SP) ; ptr to new
MOVE.L D2,-(SP) ; length of new
_Munger
ADDQ #4,SP ; ignore result
MOVE.L A3,-(SP) ; push the menu handle
IMPORT DirtyMenuSize
BSR DirtyMenuSize ; invalidate size <EHB 5-Mar-85>
;
; all done with SetItem
;
ENTRY SetIDone
SETIDONE MOVEM.L (SP)+,D3-D4/A2-A4 ;restore work registers
IMPORT TenBytExit
BRA TENBYTEXIT ;standard exit saves code
ENDPROC
SETMENUFLASH PROC EXPORT
;
; PROCEDURE SetMenuFlash(flashCount: INTEGER) -- set the system global "flashCount" to
; a new value, controlling the duration of the flash feedback given when a menu item
; is selected
;
MOVE.W 4(SP),MENUFLASH ;update flashcount
IMPORT TwoBytExit
BRA TWOBYTEXIT ;standard exit saves code
ENDPROC
AddResMenu PROC EXPORT
IMPORT InsrtResMenu
;
; PROCEDURE AddResMenu(theMenu: menuHandle; theType: RsrcType);
;
; AddResMenu appends all the names of a given resource type class
; to the menu passed as a parameter. It ignores names with a period or
; percent sign as their first character. It is simply a cover for InsrtResMenu,
; which it falls into.
;
MOVE.L (SP)+,A0 ; get return address
MOVE.W #999,-(SP) ; push large "afterItem"
MOVE.L A0,-(SP) ; restore return address
JMP InsrtResMenu
ENDPROC
CountMItems PROC EXPORT
; FUNCTION CountMItems(mHandle: MenuHandle): INTEGER
;
; CountMItems returns the number of items in a given menu
;
; TODO: Do not call GetItemRecord, since this just loops again! Stupid way to do it.
;
MOVEQ #0,D2 ;start with item 0
CountMLoop
ADDQ #1,D2 ;bump item number
MOVE.L 4(SP),A0 ;get menu handle
MOVE.L (A0),A0 ;handle -> pointer
MOVE.W D2,D0 ;get item number in D0
IMPORT GetItemRecord
BSR GetItemRecord ;look it up
BNE.S CountMLoop ;if we got it, bump count and try again
; we couldnÕt get the item in D2, so D2 must have the number of items + 1
SUBQ #1,D2 ;get number of items
MOVE.W D2,8(SP) ;return it as the result
MOVE.L (SP)+,(SP) ;strip the parameter
RTS ;return to caller
ENDPROC
PlotIcon PROC EXPORT
;-----------------------------------------------------------------------------------------------
; PROCEDURE PlotIcon(theRect: Rect; theIcon: IconHandle)
;
; Plots a given icon at a given place in your local coordinate system.
; theMode is the LisaGraf penMode for the transfer
;
LEA ICONBITMAP,A1 ;get address of icon mgr bitMap
MOVE.L 4(SP),D0 ;get the icon handle
BEQ.S DONEIPLOT ;if NIL, dont plot
MOVE.L D0,A0 ;get iconHandle in address reg
MOVE.L (A0),(A1)+ ;icon mptr is the base address
MOVE #4,(A1)+ ;set up rowBytes
CLR.L (A1)+ ;set up topLeft
MOVE.L #$00200020,(A1) ;set up botRight
MOVE.L 8(SP),D1 ;get theRect
LEA IconBitMap,A1 ;point A1 at bitmap again
;
; push parameters for copyBits call
;
MOVE.L A1,-(SP) ;source bitMap is iconBitMap
MOVE.L GrafGLOBALS(A5),A0 ;get lisaGraf global baseaddress
MOVE.L THEPORT(A0),A0 ;get thePort
PEA PORTBITS(A0) ;thatÕs the destination bitmap
PEA BOUNDS(A1) ;boundsRect of bitmap is source
MOVE.L D1,-(SP) ;theRect is the destination
CLR.W -(SP) ;theMode is srcCopy (0)
CLR.L -(SP) ;no mask region
_CopyBits ;let Bill blit those bits
DONEIPLOT
IMPORT TwoParmExit
BRA TWOPARMEXIT ;standard exit saves code
ENDPROC