boot3/Toolbox/MenuMgr/MenuMgr.a

4582 lines
181 KiB
Plaintext
Raw Normal View History

;
; File: MenuMgr.a
;
; Contains: Menu Manager for MacIntosh User Interface ToolBox
;
; This file contains the MacIntosh menu manager, which is based on Bill Atkinson<6F>s
; Lisa menu manager.
;
; Written by: Andy Hertzfeld
;
; Copyright: <09> 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<6F>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<73>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<6F>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 <20>is<69> 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
; <> <09><>HMClearMenuBarPatch still needs to be rolled in <20>
; <1> <09> Pre-SuperMario comments follow <20>
; <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<73>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<64>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 <20>MenuChanged<65> was commented out.
; <6> 7/26/90 KSM fix Darin<69>s stupid STRING ASIS bug
; <5> 7/23/90 dba change name of GetItemStyle so it doesn<73>t conflict with glue
; <4> 5/13/90 SMB Removed SMgr patches in InitMenus and DrawMenuBar if not
; <09>ForROM<4F> 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<69>
; <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<6F>t call
; InitWindows/InitMenus, but they do call SystemTask or
; WaitNextEvent which allows drivers to run. Drivers (like Deneba
; Software<72>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<6F>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
; <<3C>1.2> 10/3/88 EMT Roll in latest bug fixes.
; <<3C>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<49>s throughout the code. This was already
; done for the first test, but subsequent ones were missed. See
; PMAB214.
; <<3C>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<6F>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<6F>t leave any bits
; behind dangling.
; PMAB255> 8/31/87 FJL Don<6F>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<61>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<73>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<6F>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<64>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<72>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<6F>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<6F>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<6F>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<77>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<6F>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
;
;<3B>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<65>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<44>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<64>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<61>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<61>t be found,
; the new menu is inserted at the end of the list. If the menu is already
; in the list, don<6F>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<6F>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<6F>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<69>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<6F>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 <20> Make sure the keyboard menu state corresponds to the
; application<6F>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<64>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<69>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<6F>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<6F>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<6F>t store the menuID if we couldn<64>t find the index. No index means the <FJL C175>
; menuID doesn<73>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<6E>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<6F>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<6F>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<6F>t choose an item unless there<72>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<57>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<77>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<69>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<61>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<44>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<77>re cool
move TheMenu, MBarEnable ; set MBarEnable with DA<44>s ID
move.l FuncResult(a6),-(SP) ; push the result
_SystemMenu ; invoke desk manager
clr.l FuncResult(a6) ; pretend we didn<64>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<64>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<6F>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<64>t find it (shouldn<64>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<69>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<6F>t choose an item unless there<72>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<57>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<65>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<6E>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<6E>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<6E>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<61>s already down:
; so... 1) don<6F>t restore any menus
; 2) don<6F>t pull a new one down
; 3) don<6F>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<68>s not
;
; ask the mbarproc for the menu<6E>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<6F>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<65>s property bytes
;
; If no item selected then reset stackframe data and leave, but DON<4F>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<65>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<65>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<65>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<57>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<65>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<65>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<57>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<65>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<45>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<6E>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<6F>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<6F>t restore any, and don<6F>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<6F>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<65>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<6F>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<61>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<61>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<6E>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<6F>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<6F>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
;
;<3B> <start> roll in GetMenuBarDoesNotReturnSystemMenus from SystemMenuPatches.a
; GetMenuBarDoesNotReturnSystemMenus <20> 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<77>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
;<3B> <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 <20> 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<69>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<65>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<65>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<65>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<65>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<65>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<65>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<65>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<65>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<77>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<6F>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<65>s attribute byte list. If the item can<61>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<6F>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<77>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<64>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<64>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<73>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<64>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<64>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<6F>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<73>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<64>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<64>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<69>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<69>s just as easy to reset these each time thru, shouldn<64>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<64>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<6F>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<64>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<69>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<65>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<77>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<49>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<64>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<77>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<49>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<64>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<73>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<77>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<6F>t upshift if there is no cmd-key
BSR.S UpChar ; upshift it in D0 <EHB 11-Apr-85>
;NOTE: We<57>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<77>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<6F>t check <20>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<6E>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<61>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<77>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<44>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<77>re cool
move TheMenu, MBarEnable ; set MBarEnable with DA<44>s ID
move.l menuResult(a6),-(sp) ; push the result
_SystemMenu ; invoke desk manager
clr.l menuResult(a6) ; pretend we didn<64>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<64>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<6F>t find it, then look thru the regular menus to get the parent. This code
; doesn<73>t allow recursively defined menus, it stops looking after 8 menus (I didn<64>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<77>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<6E>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<73>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<77>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<65>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<6F>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<77>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<6F>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<6F>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<64>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<65>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<65>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<77>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<64>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<61>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