supermario/base/SuperMarioProj.1994-02-09/Toolbox/HelpMgr/BalloonPACK.a

3530 lines
132 KiB
Plaintext
Raw Normal View History

2019-06-29 15:17:50 +00:00
;__________________________________________________________________________________________________
; File: BalloonPACK.a
;
; Contains: Assembly routines for the Balloon Help Package
;
; Written by: Randy Carr
;
; Copyright: © 1989-1992 by Apple Computer, Inc., all rights reserved.
;
; This file is used in these builds: BigBang
;
;
;
; Change History (most recent first):
;
; <SM3> 10/22/92 CSS Change some branch short instructions to word branches.
; <72> 5/14/92 KST #1027497 <JH>: #1025797,#1027497: In '__HMScanHWinResource', we
; ask TSM if the mouse is over a floating window. If it is, then
; TSM will try to locate and open the resource file to load the
; Help resources for the floating window. Balloon help now works
; when mouse is over a floating window.
; <71> 4/6/91 DTY csd, #86370: IsMouseInMenuBar popped off the incorrect number of
; bytes from the stack if it couldnt get the 'MBDF' resource,
; which would happen if MenuList was nil. Check to make sure that
; MenuList contains a real handle before trying to get the 'MBDF',
; and pop off the correct number of bytes if this fails anyway.
; <70> 3/19/91 RLC ksm,#BUG.GUIDE Item #8510137 - Fix typo in FillInDialogMsg()
; that was not filling in the variant & proc numbers from an
; 'hdlg' resource from the right register offset.
; <69> 3/13/91 RLC ksm,#83253 - Change call to SaveBits() to create purgeable bits
; so that if we get short on memory, the bits we saved behind the
; balloon will get invalidated by RestoreBits(). GO5 approved.
; <68> 2/20/91 RLC ksm, #BH-TC-0076 Fix modal dialog menu balloons so that apps can
; get special balloons for menu titles and items when a modal
; dialog is up. (GO5 approved)
; <67> 2/8/91 RLC <ksm> #82161 Add the HMStripNullFromProcessName routine that
; removes leading null characters from a pstring so that Text Edit
; doesn't word break a process name in a balloon. [Change approved
; by GO5]
; <66> 2/5/91 stb gs: include MenuMgrPriv.a
; <65> 1/24/91 RLC <gbm> #81591 Change __HMFillInDialogMessage() to respect the
; resource file whether a specified resource file refnum or -1
; from HMScanTemplateItems(). If -1 then have those routines call
; GetResource() else call Get1Resource() [which means specifically
; search a resource file for a help resource].
; <64> 1/22/91 RLC <dc> #81592 Fix bug that leaves a balloon up if the mouse
; moves from a system tracked balloon to the menubar.
; <63> 1/18/91 KSM <RLC> Change include of BalloonPACKEqu to BalloonsPriv.a.
; <62> 1/14/91 RLC <ksm> Change a call to GetResource into Get1Resource when
; fetching a 'hdlg' resource as we must make sure where we're
; fetching the resource from when handling multiple help resources
; with the same ID.
; <61> 1/10/91 RLC <ksm> Fix the check of any setup DialogResID value from
; HMSetDialogResID. Fix a bug that was smashing the return value
; from a call to the HMScanTemplateItems call - this fixes a bug
; that wouldn't track a helpItem driven 'hdlg' and a
; HMSetDialogResID assigned 'hdlg' in the same dialog.
; <60> 1/3/91 RLC <vl> Fix IsBalloonChanged routine to NOT remove a balloon if
; hmgLastMenuID says that there wasn't a balloon that we put up
; ourselves (via HMShowTitleBalloon). This change will allow
; developers to call HMShowBalloon for menu titles instead of
; requiring that they have an 'hmnu' resource.
; <59> 12/18/90 RLC <ksm> Change HMStuffWindow routine to do the right thing in 32
; bit mode and to fix the bug that called _GetAuxWin on B & W
; machines.
; <58> 12/14/90 RLC <ngk> Shorten code in HMSetupBalloonRgns by fetching translation
; of varCode to balloon drawing directions from table instead of a
; giant case statement. Added check in HMFillInMenuMsg that makes
; sure we're in MenuSelect so that popups & hiearchicals menus get
; the right state message in modal dialogs (and movable modals).
; <57> 12/3/90 RLC <ksm> Fix bug that wasn't appending a menu item's mark character to
; the name to fetch when looking up a GetNamedResource item when
; filling out the help msg record in HMFillInMenuMsg.
; <56> 11/29/90 RLC <ksm> Repair the HMStuffWindowInfo code that ksm & gbm made at
; 2:00AM so that it actually works when window does NOT have an
; aux wind record.
; <55> 11/28/90 gbm (with KSM) _HMStuffWindowInfo wasn't 32-bit clean, since it
; messed directly with the window variant in top byte of the
; handle...
; <54> 11/16/90 RLC <ksm> Fix bug that was not respecting the ModalDialog state for
; Apple Menu item help messages. The enabled message was always
; displayed.
; <52+> 10/4/90 RLC <ksm> Optimization in help mgr resource walks. Fixed bug in
; GetIndHelpMsg() that was not returning the correct data in the
; case of a HMCompareItem in an 'hmnu' resource. Fix bug that
; wasn't allowing an 'hmnu' resource to have HMNamedResourceItem
; as the first item (the title balloon msg) and map 'modal dialog'
; title & item balloons to the checked and marked w/ a diamond.
; Change the 'hwin' resource scanning routine to call
; HMScanTemplateItems instead of duplicating this code (saves >
; 720 bytes).
; <52> 10/3/90 RLC Fix a bug when extracting help message data from a help resource
; that wasn't clearing the lower (upper) nibble of the pstring
; index when reaching to 'other' items.
; <51> 9/30/90 RLC Do some code reduction and change most routines to use the link
; patch macros.
; <50> 9/25/90 RLC Move the __HMExtractHelpMsg to be in the BalloonPack.p file and
; just have this routine call the __HMGetIndHelpMsg routine and
; ignore the extraneous params that are returned from this call
; (saves >370 bytes).
; <48+> 9/22/90 RLC Add a routine to resize and restuff the window variant for the
; balloon window.
; <48> 9/17/90 RLC (JSM) Fix HMCallCustomWDEFCalc that was doing a MOVE.L into the
; result instead of the correct MOVE.W instruction. This was
; causing a crash in HMShowBalloon by smashing the hiword of the
; HMGlobalPtr that was on the stack.
; <47> 9/13/90 RLC Changed name of routines to have '__' chars in front of
; procedure name (in jump table as well); Fix bug that put up menu
; title balloons in front of pulled down menu just b4 menu
; disappears; Fixed bug that was bit testing wrong bit when
; scanning 'hrct' resources for hmAbsoluteCoords (Change it to
; match Inside Mac VI doc).
; <46> 8/31/90 RLC Remove priority 2 bug that flashes ModalDialog balloons once
; when dialog first comes up, reentrant support in HMBalloonBulk,
; support for CloseView, fix process & help menu balloons when
; modal dialog is up.
; <44+> 8/21/90 RLC Add in a reentrancy test for BalloonBulk code.
; <43+> 8/20/90 RLC Repair Philip's restored old code and move in _ProcHelper
; dispatcher.
; <46+> 8/9/90 RLC Add some glue to read shift key quickly.
; <44+> 8/3/90 RLC Fix tipProc calling convention: tip,rgn,varCode.
; <43+> 7/31/90 RLC Fix bug that doesn't range check correctly in FillDialogMsg for
; offset msgs.
; <42+> 7/25/90 RLC Add code to support Easy Access and remove calls to Extract…
; <41+> 7/17/90 RLC Fix HMExtract routine to be 1 based and check ranges.
; <41> 7/13/90 RLC Fix modal dialog w/ enabled menu help msg case by calling new
; dialogmgr dispatcher, shortened code by calling globals
; directly, added HMScanHRCTResource routine.
; <39+> 7/6/90 RLC More changes for those modal dialog variants.
; <38+> 7/5/90 RLC Tweak some routines to make sure multiple help items are
; supported correctly.
; <37+> 6/19/90 RLC More variant correction routines.
; <37> 6/18/90 RLC Fix indexing to fetch application's help menu msgs & initial
; variant.
; <35+> 6/15/90 RLC Allow enabled items to get normal hmnu msg in ModalDialogMenu
; state.
; <34+> 6/14/90 RLC Add support for “Balloons On” balloon, fix window move bug.
; <34> 6/8/90 KSM Update for new IsFrontWindowModal.
; <33> 6/7/90 RLC Add Kevin's ModalDialogMenus private selector.
; <31+> 6/5/90 RLC Fix a potential front window bug
; <30+> 6/4/90 RLC Fix bug in hmgLastWindowPtr global dereferencing NIL ptr.
; <29+> 5/31/90 RLC Special case the process menu for Finder open only message &
; support for App added help menu messages.
; <28+> 5/4/90 RLC Fix bug in AppendMenu.
; <27+> 5/3/90 RLC Fix bugs in modal dialogs, launching balloons, etc.
; <26+> 4/19/90 RLC Roll in new font & size in reference to script mgr globals
; <26> 4/18/90 RLC Fix bug in NIL test for hdlg items.
; <24+> 4/16/90 RLC Special case the process (MF) menu by hand.
; <23+> 4/10/90 KSM Roll in the System menus.
; <22+> 4/9/90 RLC Frontwindow modal fixes.
; <21+> 4/5/90 RLC More Modal Dialog handling.
; <21> 4/4/90 RLC Fix clicks in modal dialogs.
; <19+> 4/2/90 RLC Reconnect HMSetDialogResID & HMSetMenuResID.
; <19> 3/29/90 HJR Fixed an assembler out of range error.
; <18> 3/29/90 RLC Fix dangling pointer possible bug.
; <17> 3/27/90 RLC Make sure resource driven help msgs use theProc & variant.
; <16> 3/22/90 RLC Change IsThisAModalDialog call to call GetWVariant as well.
; <15> 3/20/90 RLC Hack AppleMenu items separately.
; <14> 3/13/90 RLC Bug fixes.
; <13> 3/8/90 RLC Fix non-frontmost windows & layers balloons to be ignored when
; modal dialog is up.
; <12> 2/8/90 RLC Fix missing msg parameter to include NIL as a 'missing' msg.
; <11> 2/7/90 RLC Fix non-Removal of 'hdlg' driven balloons.
; <10> 2/5/90 RLC Add delay controls.
; <9> 2/2/90 RLC Fix selector return codes.
; <8> 1/30/90 RLC Add remove extraneous calls
; <7> 1/26/90 RLC Add support to remove modal dialog balloons at the right time.
; <6> 1/12/90 RLC Tweak dispatcher to correctly handle extended selector codes.
; <5> 1/11/90 RLC Fix code to scan HMSkipItem in hdlg resource correctly.
; <4> 1/4/90 RLC Support the new resource format.
; <3> 12/22/89 RC Fix some modality conditionals
; <2> 12/21/89 RC Fix error conditions in scanning hwin resource.
; <3.5> 12/15/89 RLC Added TipProc call.
; <3.4> 12/6/89 RLC Fix the odd addressing problem when copying a help msg string
; when filling in record.
; <3.3> 12/1/89 RLC Add short routine to allow Pascal to determine if dialogPtr is a
; modal dialog.
; <3.2> 11/30/89 RLC Fix bug in hdlg scanner that ADD.B was clipping hdlg offset
; length to 256 bytes.
; <3.1> 11/16/89 RLC Update 'hrct' scanning routines as hotRect parameter no longer
; exists.
; <3.0> 11/16/89 RLC Change calling interface to HMTrackTemplateHelpItems.
; <2.9> 11/15/89 RLC Add and fix routines to support tip & altRect in 'hdlg's/
; <2.8> 11/13/89 RLC Changed 'hdlg' scan routines to scan tip and altRect parameters.
; <2.7> 11/9/89 RLC Add support for HMSkipItem in 'hrct' scanning routine.
; <2.6> 11/7/89 RLC Add support for window parts balloons.
; <2.5> 11/2/89 RLC Changed the code into a REAL Package (PACK14)
; <2.4> 10/27/89 RLC Fix bug in NIL menu msg that would loop infinitely.
; <2.3> 10/2/89 RLC Add preflight check when scanning hwin's to make sure the mouse
; is in the portrect before scanning the hrct.
; <2.2> 9/25/89 RLC Added support for MultiFinder application icon, use _CmpString
; trap when comparing window titles to hwin resources.
; <2.1> 9/21/89 RLC Made missing 'hmnu' item work if array contains
; HMCompareItem(s).
; <2.0> 9/20/89 RLC Bug Fixes, set CurResFile to refnum returned from GetIndResource
; when searching for hrcts. Add subrange option to hwin resources.
; <1.9> 9/19/89 RLC Fixed NIL string & Menu Item Checked byte in 'hmnu' scan.
; <1.8> 9/19/89 RLC Bug Fixes again.
; <1.7> 9/18/89 RLC Bug fixes, DrawString patch speedup.
; <1.6> 9/15/89 RLC Fixed ADD.B instructions to allow word length indexing.
; <1.5> 9/14/89 RLC Fixed Register useage problem in ScanHWin routine.
; <1.4> 9/13/89 RLC Bug Fixes, Added new 'hmnu','hdlg' resource template readers.
; <1.3> 8/29/89 RLC Update _Pack14 calling method and added 'hmnu','hdlg', &'hrct'
; scanning routines.
; <1.2> 8/10/89 RLC Added support code for autocontents help balloons
; <1.1> 7/20/89 RLC Added code to support the help menu for What Is? mode.
; <1.0> 6/29/89 RLC Created Today.
;
TITLE 'BalloonPack.a - Balloon HelpMgr trap'
STRING ASIS
IF &TYPE('HelpMgrTesting')='UNDEFINED' THEN
HelpMgrTesting EQU 0
ENDIF
AllowCloseViewChanges EQU 0 ; *** someday I'll make this work!
LOAD 'StandardEqu.d'
INCLUDE 'MFPrivate.a' ; some mf private _GetAuxMenuItem things
INCLUDE 'LayerEqu.a'
INCLUDE 'ScriptPriv.a' ; some private script mgr global records
INCLUDE 'BalloonsPriv.a' ; my private help manager equates
INCLUDE 'InternalMacros.a'
INCLUDE 'Processes.a'
INCLUDE 'DialogsPriv.a'
INCLUDE 'MenuMgrPriv.a' ; for Save|RestoreBits
INCLUDE 'TSMPrivate.a' ; for input method's floating window
;
; Macro to put in debug symbols for MacsBug
;
IF HelpMgrTesting THEN
MACRO
DoDebugSymbols &name
DC.B $80 + &LEN(&name), '&name'
ALIGN
DC.W $0000
ENDM
ENDIF
PackEntry MAIN EXPORT
DC.W $A9FF ; package entry point (unused now)
DC.L ('PACK') ; make sure this is preceded by STRING ASIS
DC.W 14 ; package number
DC.W hmBalloonHelpVersion ; version number
DispatchTable
DC.W 0 ; flags, 0 = selectors are sequential
DC.B minSelector ; first legal selector
DC.B maxSelector ; last legal selector
MACRO
JT &entry
IMPORT &entry
DC.W &entry - DispatchTable
ENDM
JumpStart JT __HMCountDITLHelpItems ; called by: Standard file somewhere
JT __HMModalDialogMenuSetup ; called by: ':DialogMgr:ModalDialogMenuPatches.a'
JT __HMInvalidateSavedBits ; called by: ':WindowMgr:LayerMgr.c'
JT __HMTrackModalHelpItems ; called in patches to _IsDialogEventPatch & _ModalDialog
JT __HMBalloonBulk ; called in patch to _SystemTask
DC.W 0 ; HMInitHelpMenu (return an error if someone calls the pack directly)
JT __HMDrawBalloonFrame ; called by: ':HelpMgr:BalloonWDEF.p' & BalloonPack.p
JT __HMSetupBalloonRgns ; called by: ':HelpMgr:BalloonWDEF.p' & BalloonPack.p
JumpTable JT __HMGetHelpMenuHandle
JT __HMShowBalloon
JT __HMRemoveBalloon
JT __HMGetBalloons
JT __HMSetBalloons
JT __HMShowMenuBalloon
JT __HMGetIndHelpMsg
JT __HMIsBalloon
JT __HMSetFont
JT __HMSetFontSize
JT __HMGetFont
JT __HMGetFontSize
JT __HMSetDialogResID
JT __HMSetMenuResID
JT __HMBalloonRect
JT __HMBalloonPict
JT __HMScanTemplateItems
JT __HMExtractHelpMsg
JT __HMFillCitationString
JT __HMGetDialogResID
JT __HMGetMenuResID
JT __HMGetBalloonWindow
JumpEnd
minSelector EQU (JumpStart - JumpTable) / 2
maxSelector EQU (JumpEnd - JumpTable) / 2 - 1
ENDPROC ; PackEntry
;---------------------------------------------------------------------------------------------
;
; Start of routines needed in Help Manager Package
;
;---------------------------------------------------------------------------------------------
;
; FUNCTION __HMGetHelpGlobal: HMGlobalPtr; ; we need this code for pascal
;
; Returns our global ptr for the help manager globals on stack
;
__HMGetHelpGlobal PROC EXPORT
MOVE.L ExpandMem,A0 ; point to the expand mem ptr
MOVE.L ExpandMemRec.emHelpGlobals(A0),4(SP) ; return the global handle on the stack
RTS ; return to caller
ENDP
;---------------------------------------------------------------------------------------------
;
; FUNCTION __HMGetGlobalMouse: Point; ; we need this code for pascal
;
__HMGetGlobalMouse PROC EXPORT
MOVE.L Mouse,4(SP) ; return the current global mouse on stack
RTS
ENDP
;---------------------------------------------------------------------------------------------
;
; FUNCTION __HMSlopMouse(tip: Point): BOOLEAN;
;
; Returns true if mouse moved beyond our slop rect
;
__HMSlopMouse PROC EXPORT
MOVE.L (SP)+,A0 ; return addr
MOVE.L (SP)+,D2 ; tip point
MOVEQ #0,D0 ; result placeholder
MOVE.L Mouse,D1 ; get the current mouse
CMP.L D1,D2 ; is the tip the same
BEQ.S @NoSlop ; yes, exit now
SUB D1,D2 ; compute Dx
BPL.S @wasHPositive
NEG.W D2 ; abs(deltaX)
@wasHPositive
CMP #kHMSlopPix,D2 ; did the mouse slop (in pixels)?
BGT.S @MouseMoved ; yes, exit true
SWAP D2 ; switch to vertical word
SWAP D1
SUB D1,D2 ; compute Dy
BPL.S @wasVPositive
NEG.W D2 ; abs(deltaX)
@wasVPositive
CMP #kHMSlopPix,D2 ; did the mouse slop?
BLE.S @NoSlop ; no, exit false
@MouseMoved
MOVEQ #1,D0 ; the mouse moved beyond the pixel slop
@NoSlop
MOVE.B D0,(SP) ; return result on stack
JMP (A0) ; return to caller
IF HelpMgrTesting THEN
DoDebugSymbols __HMSlopMouse ; label for MacsBug
ENDIF
ENDP
;---------------------------------------------------------------------------------------------
;
; FUNCTION __HMCallTipProc(tipProc: Ptr;
; tip: Point;
; structure: RgnHandle;
; VAR bounds: Rect;
; VAR varCode: INTEGER); OsErr; EXTERNAL;
;
; Calls the user tip procedure for modifying the varCode just calculated
;
__HMCallTipProc PROC EXPORT
resultsStackFrame
result ds.w 1 ; the resulting OsErr
parametersStackFrame
theTipProc ds.l 1 ; the procPtr to call
theTip ds.l 1 ; the tip of the iceberg
theStructure ds.l 1 ; the structure rgn of the balloon
theBounds ds.l 1 ; the VAR rect (long)
theVarCode ds.l 1 ; the VAR varCode (word)
endStackFrame
linkSave
SUBQ #2,SP ; room for result
MOVE.L theTip(A6),-(SP) ; push the tip point of the balloon
MOVE.L theStructure(A6),-(SP) ; push the structure region of the balloon
MOVE.L theBounds(A6),-(SP) ; push VAR bounds rect
MOVE.L theVarCode(A6),-(SP) ; push VAR varCode
MOVE.L theTipProc(A6),A0 ; get the proc ptr
JSR (A0) ; go call it and return
MOVE (SP)+,result(A6) ; return result
restoreUnlinkReturn
IF HelpMgrTesting THEN
DoDebugSymbols __HMCallTipProc ; label for MacsBug
ENDIF
ENDP
;---------------------------------------------------------------------------------------------
;
; FUNCTION __HMBalloonBulk: OsErr;
;
; Scans for presence of mouse over menu bar and detects hwin & hrcts for Balloon Help
;
; Should only be called if Balloon Help is ON
;
__HMBalloonBulk PROC EXPORT ; *** Note: private pack call
IMPORT __HMIsBalloon
IMPORT __HMRemoveBalloon
IMPORT __HMShowTitleBalloon
IMPORT __HMGetWindowPartCode
IMPORT __HMShowWindowPartBalloon
IMPORT __HMScanHWinResource
IMPORT __HMScanTemplateItems
IMPORT __HMShowEasyAccessBalloon
IMPORT __HMSetBalloons
IMPORT __HMPushMenuState
IMPORT __HMPopMenuState
IMPORT __HMGetDialogResID ; <54>
SaveRegs REG A2-A3/D3-D4 ; Standard registers to save
resultsStackFrame
result ds.w 1 ; the result
localsStackFrame
frontPSN ds.l 2 ; process serial number double longword
currentPSN ds.l 2 ; process serial number double longword
dialogResID ds.w 1 ; <54> a place to put any overridden dialog res ID
sameResult ds.w 1
endStackFrame
linkSave SaveRegs
MOVE.L ExpandMem,A0 ; point to the expand mem ptr
MOVE.L ExpandMemRec.emHelpGlobals(A0),A2 ; A2 = global ptr (used to be a handle)
MOVE hmgBulkReentrantCount(A2),D0 ; get last reentrant count
BNE.S ReentrantCase
ADD #1,hmgBulkReentrantCount(A2) ; say that we're currently executing this routine
SUBQ #2,SP ; make room for OsErr
PEA currentPSN(A6) ; push ptr to cereal number storage (crunch)
_GetCurrentProcess ; get the current process PSN
; do we need to check err? (make room for daddy)
PEA frontPSN(A6) ; push ptr to cereal number storage (crunch)
_GetFrontProcess ; get the frontmost process PSN
; do we need to check err? (make room for daddy)
PEA currentPSN(A6) ; push ptr to cereal number storage (crunch)
PEA frontPSN(A6) ; push ptr to cereal number storage (crunch)
PEA sameResult(A6) ; push a place for the result of call
_SameProcess ; were the PSNs the same?
ADDQ #2,SP ; do we need to check for error?
TST.B sameResult(A6) ; is the front process current?
BEQ.S ScanStandardExit ; EQ means no, so exit
SUBQ #2,SP
_Button ; This used to be _Stilldown, but seems to cause some
; sort of state problem in MF (*** I'll figure it out later)
TST.B (SP)+
BNE.S ScanStandardExit
SUBQ #2,SP
JSR __HMIsBalloon ; was there a balloon up?
MOVE.B (SP)+,D0 ; EQ means no
BEQ.S GoContextualizeMouse ; no, so figure out where the mouse actually is
IF AllowCloseViewChanges THEN
MOVE hmgCloseViewCount(A2),D0 ; get the value of the closeview balloon state (>0 means were ready to remove)
BNE.S @RemoveAndExit
ENDIF
; call IsBalloonPlaceChanged w/ A2 -> globals
BSR IsBalloonPlaceChanged ; go see if the Balloon place has changed
BNE.S @RemoveAndExit ; if changed (NE) then remove the showing balloon and exit
BSR IsMouseOutsideSlop ; go see if the mouse has drifted outside slop rect
BNE.S ScanStandardExit ; NE means mouse is still in rect, so exit
@RemoveAndExit
SUBQ #2,SP ; remove any balloons that might have been up
JSR __HMRemoveBalloon ; do the remove
ADDQ.L #2,SP ; toss result
ScanStandardExit
CLR hmgBulkReentrantCount(A2) ; reset last reentrant count
ReentrantCase
CLR result(A6) ; always return noErr
restoreUnlinkReturn
;
IF HelpMgrTesting THEN
DoDebugSymbols __HMBalloonBulk ; label for MacsBug
ENDIF
;
;
; GoContextualizeMouse
;
; What this routine does is determine whether or not to put up a balloon depending on
; where the mouse is. This routine ONLY gets called if there wasn't a balloon already
; up!
;
GoContextualizeMouse
BSR IsMouseInMenuBar ; returns 'MBAR' proc's test result in D0.L
BMI.S TryWindowParts ; if -1 then mouse wasn't in bar
BEQ.S InBarNoTitle ; if 0 then mouse was in bar, but no title
MOVE.L SavedHandle,D1 ; were there bits being saved behind balloon?
BNE ExitContextualize ; yes, so exit quickly, no title balloon in this case
MOVE.L D0,-(SP)
_DMgrPushMenuState
MOVE.L (SP)+,A1
MOVE.L (SP)+,D0
MOVE.L MenuList,A0 ; mouse was in a title, use the offset in D0.L
MOVE.L (A0),A0 ; A0 -> menuList
MOVE.L menuoH(A0,D0.L),A0 ; get the menu handle
MOVE.L (A0),A0 ; deref to get ptr
MOVE.W menuID(A0),-(SP) ; put the menuID on stack
MOVE.L menuEnable(A0),-(SP) ; push menu flags
MOVE.L A1,-(SP)
_DMgrPopMenuState
JSR __HMShowTitleBalloon ; put a balloon up
BRA ExitContextualize
InBarNoTitle
JSR __HMShowEasyAccessBalloon ; see if we should put up a balloon for easy access icons
@NothingElse
BRA ExitContextualize
;
;
;
TryWindowParts
; First: Fetch the window and part code for that window that
; the mouse was over.
SUBQ #6,SP ; room for INTEGER & VAR port
PEA 2(SP) ; push address of port on stack
JSR __HMGetWindowPartCode ; returns corrected FindWindow result & VAR port
MOVE (SP)+,D0 ; D0 = FindWindow result code for the window (if any)
MOVE.L (SP)+,D1 ; D1 = port that the mouse is in (includes layer, if any)
; Second: Check to see if the mouse is in the content
; area of the window or desk
CMP #inContent,D0 ; was the mouse in a content area of the window?
BEQ.S TryAppWindow ; EQ means yes, so check for hwin driven balloons
CMP #inDesk,D0 ; was the mouse in the desk?
BEQ.S TryInDesk ; EQ means yes, so tell 'em about the desk.
; Third: If it was somewhere else, then show the
; appropriate window part balloon
SUBQ #2,SP
MOVE.L D1,-(SP) ; push the port
MOVE D0,-(SP) ; push findwindow result code
JSR __HMShowWindowPartBalloon
MOVE.B (SP)+,D0 ; returns nonzero if a balloon was shown
BRA.S ExitContextualize
TryInDesk
BSR IsMouseInDesk
BRA.S ExitContextualize
;
; See if someone has setup any dialog res id to be used for the current window
;
TryAppWindow
SUBQ #2,SP ; <54> make some room for the OsErr result
PEA dialogResID(A6) ; <54> put any overridden dialog res id here
JSR __HMGetDialogResID ; <54> call: FUNCTION __HMGetDialogResID(VAR theResID: INTEGER): OsErr;
TST.W (SP)+ ; <54> see if we got a noErr result
BNE.S @noDialogResIDSetup ; <54> NE means there wasn't a currently overridden dialog ID
SUBQ #2,SP ; make some room for the OsErr result
MOVE.W dialogResID(A6),-(SP) ; <54> push the ID
MOVE #-1,-(SP) ; scan this resfile (-1 means current)
MOVE.L #'hdlg',-(SP) ; scan a 'hdlg' resource
JSR __HMScanTemplateItems ; scan any 'hdlg' resource of this ID
TST (SP)+ ; <61> don't scan any hwin stuff if we got a hit
BEQ.S ExitContextualize ; <61> branch to the common exit point
@noDialogResIDSetup
BSR __HMScanHWinResource
;
; do something here
;
ExitContextualize
BRA ScanStandardExit
IF HelpMgrTesting THEN
DoDebugSymbols GoContextualizeMouse ; label for MacsBug
ENDIF
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; IsBalloonPlaceChanged
;
; Enter: A2 = global ptr
;
; Note: lastMenuID EQU lastPartCode
; lastWindowPtr EQU lastEnabled
;
;
imiTempRect EQU -8 ; temprect rect
imiTempPt EQU imiTempRect-4 ; point to test mouse with
imiPort EQU imiTempPt-4 ; the previous port goes here
imiSize EQU imiPort
;
IsBalloonPlaceChanged
LINK A6,#imiSize ; make a stack frame
MOVEM.L D6-D7,-(SP) ; save regs (<64> save D6 as well)
BSR IsMouseInMenuBar ; returns 'MBAR' proc's test result in D0.L (not handle safe)
BMI.S @notInBar ; if -1 then mouse wasn't in bar
BEQ.S @specialBar ; if 0 then mouse was in bar, but no title,
; branch and check any special balloons
MOVE.L MenuList,A0 ; mouse was in a title, use the offset in D0.L
MOVE.L (A0),A0 ; A0 -> menuList
MOVE.L menuoH(A0,D0.L),A0 ; get the menu handle
MOVE.L (A0),A0 ; deref to get ptr
MOVE.W menuID(A0),D6 ; get the menu ID we're examining in D6
MOVE.L A0,-(SP) ; push ptr to menu handle data
_DMgrPushMenuState ; restore off modal dialog menu enable flags if they were pushed
MOVE.L (SP)+,A1 ; get those changed enable flags for pop later
MOVE.L (SP)+,A0 ; restore the ptr to the menu handle data (DMgrPush is handle safe)
MOVE.B menuEnable+3(A0),D7 ; save off flags in D7 for compare later
AND.B #$01,D7 ; toss all bits except title
MOVE.L A1,-(SP) ; restore handle state (if any)
_DMgrPopMenuState
MOVE hmgLastMenuID(A2),D0 ; if -1 then there wasn't a previous menu title balloon up
CMP.W #-1,D0 ; <60> check to see if there was a menu title balloon up
BEQ @ResetMenuTitleBalloon ; <60> -1 means exit with CCRs cleared in this case so that the balloon isn't removed
CMP D6,D0 ; <64> go compare it [menu ID in D6]
BNE @Changed ; if different then toss the current balloon (branch to Changed w/ CCRs set)
MOVE.B hmgLastEnabled+3(A2),D0 ; get original menu handle flags
AND.B #$01,D0 ; toss all bits except title
CMP.B D0,D7 ; Note: EOR.B takes 12 cycles instead of 8
; set CCRs, if menu state changed then mark NE and exit
BRA @Changed ; the current balloon will be removed if NE on exit
@ResetMenuTitleBalloon
MOVE.W D6,-(SP) ; <64> put the menuID on stack
MOVE.L D7,-(SP) ; <64> put the menu flags on stack (we only look at the title bit anyway)
JSR __HMShowTitleBalloon ; <64> put a title balloon up if old menu state (hmgLastMenuID) was -1
BRA @ZipOla ; <64> return with zero set CCRs
@specialBar
JSR __HMShowEasyAccessBalloon ; put up the Easy Access balloon if EA is active and mouse is in EA area of menubar
MOVE.W hmgMenuID(A2),D0
CMPI.W #kwasEasyAccess,D0
BEQ @ZipOla
BRA @Changed ; was in EA icon area (next to MF icon)
@notInBar
SUBQ #2,SP ; make space for Find Window result INTEGER
PEA imiPort(A6) ; returns the findwindow VAR result windowptr
JSR __HMGetWindowPartCode ; returns corrected findwindow result code (Handle safe)
MOVE (SP)+,D7 ; put result code [inDrag..inZoomOut] in D7
CMP hmgLastPartCode(A2),D7 ; A2 is a ptr to our globals
BNE @Changed ; NE means that the current examined part code changed, so,
; remove any balloon up
MOVE.L hmgLastWindowPtr(A2),D0 ; OK, get the last examined window ptr
BEQ @NoChange ; if last examined window ptr was NIL then don't compare it's attributes
MOVE.L D0,A0 ; oops! forgot this in a11! Put the window ptr in A0 for attribute check
CMP.L imiPort(A6),A0 ; see if the current 'mouse-is-over-window' <> last window ptr
BNE @Changed ; if NE then go toss that balloon
; <53> There was a bug in B1 (and A11-A12) that would autohide the
; balloon if someone just changed the origin for whatever reason.
; We now calculate (and keep) the portRect's size and watch the
; difference between the portRect.topLeft & portbits.topLeft…
MOVE.W PortRect+right(A0),D0 ; <53> get the window's portrect's right coord
SUB.W PortRect+left(A0),D0 ; <53> less the left, gives us the width of the window in D0
CMP.W hmgLastWidth(A2),D0 ; <53> did the width of the window change?
BNE.S @Changed
MOVE.W PortRect+bottom(A0),D0 ; <53> get the window's portrect's bottom
SUB.W PortRect+top(A0),D0 ; <53> less the top, gives us the height of the window in D0
CMP.W hmgLastHeight(A2),D0 ; <53> did the height of the window change?
BNE.S @Changed
MOVE.W PortRect+left(A0),D1 ; <53> get the window's portrect's left coord again
MOVE.W PortRect+top(A0),D7 ; <53> and the window's portrect's top
MOVE portVersion(A0),D0 ; get window port version of last window ptr
AND #$C000,D0 ; see if it was an old style port
BEQ.S @oldPort
MOVE.L portPixMap(A0),A0 ; if it's a new port then check the port's pixmap's bounds
MOVE.L (A0),A0
LEA bounds(A0),A0
BRA.S @newPort
@oldPort
LEA PortBits+bounds(A0),A0 ; otherwise use the window's portbits.bounds
@newPort
MOVE.W left(A0),D0 ; <53> get the left coord of the bounds
SUB.W D1,D0 ; <53> less the left coord of the portRect to get the difference
CMP.W hmgLastLeft(A2),D0 ; <53> was it the same as the last time we checked it?
BNE.S @Changed ; <53> set ccr's and exit if NE
MOVE.W top(A0),D0 ; <53> get the top coord of the bounds
SUB.W D7,D0 ; <53> less the top coord of the portRect to get the difference
CMP.W hmgLastTop(A2),D0 ; <53> was it the same as the last time we checked it?
BNE.S @Changed ; <53> set ccr's and exit if NE
@NoChange
BSR __HMScanHWinResource ; returns a zero in D0 if something found
@ZipOla
MOVEQ #0,D0 ; always return a clear result (these days!)
@Changed
MOVEM.L (SP)+,D6-D7 ; restore regs (but don't set CCRs [MOVEM]) (<64> restore D6 as well)
UNLK A6
RTS
IF HelpMgrTesting THEN
DoDebugSymbols IsBalloonPlaceChanged ; label for MacsBug
ENDIF
;
;
; IsMouseOutsideSlop
;
IsMouseOutsideSlop
MOVE.L ExpandMem,A0 ; point to the expand mem ptr
MOVE.L ExpandMemRec.emHelpGlobals(A0),A0 ; A0 = global ptr
MOVE.L hmgSlopRect(A0),D0
BNE.S @notEmpty
MOVE.L hmgSlopRect+4(A0),D0
BNE.S @notEmpty
MOVEQ #1,D0
RTS
@notEmpty
SUBQ #2,SP ;
MOVE.L Mouse,-(SP) ; push mouse (global coords)
PEA hmgSlopRect(A0) ; push
_PtInRect
TST.B (SP)+
RTS
;
IF HelpMgrTesting THEN
DoDebugSymbols IsMouseOutsideSlop ; label for MacsBug
ENDIF
;
;
; IsMouseInDesk
;
IsMouseInDesk
; *** call FindLayer and PIDName from Layer to make other kHMInOtherLayer balloon
RTS
IF HelpMgrTesting THEN
DoDebugSymbols IsMouseInDesk ; label for MacsBug
ENDIF
;
; IsMouseInMenuBar
;
; Returns NE if mouse was in menubar
;
IsMouseInMenuBar
MOVEM.L D4-D5,-(SP) ; save regs
MOVE.L MenuList,d4 ; Check to see if there is a menu list <71>
beq.s @noMBDF ; If not, exit. <71>
move.l d4,a0 ; <71>
MOVE.L (A0),A0 ; <71>
move.w mbResID(a0),d4 ; Save MBDF resource ID <71>
;
; Try to get the MBDF before pushing parameters on the stack for it. <71>
;
SUBQ #4,SP ; space for return result
MOVE.L #'MBDF',-(SP)
move.w d4,-(SP) ; get resource ID <71>
MOVE.W #MapTRUE,ROMMapInsert ; set flag to load from ROM [someday, I suppose]
_GetResource
MOVE.L (SP)+,D5 ; D5 = 'MBDF' resource handle
BEQ.S @noMBDF ; ack! how can this happen?
CLR.L -(SP) ; make room for defproc return
move.w d4,-(SP) ; Push MBDF resource ID <71>
AND #$0007,(SP) ; low 3 bits is the variant (selector)
MOVE #1,-(SP) ; message # = hit
CLR -(SP) ; parameter 1 = none
MOVE.L Mouse,-(SP) ; push mouse (global coords)
MOVE.L D5,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
MOVE.L D5,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
@noMBDF
MOVEM.L (SP)+,D4-D5 ; restore regs
RTS
IF HelpMgrTesting THEN
DoDebugSymbols IsMouseInMenuBar ; label for MacsBug
ENDIF
;
; End __HMBalloonBulk
;
ENDP
;---------------------------------------------------------------------------------------------
;
;
; FUNCTION __HMMungeSearch(MainString,SubString : Ptr): INTEGER;
;
; Searches MainString looking for SubString.
;
; Returns a 1 if SubString was found in MainString
;
; (Each parameter is a ptr to a PString)
;
__HMMungeSearch FUNC EXPORT
;
mmSubString EQU 8 ; stringptr 1
mmMainString EQU mmSubString+4 ; stringptr 1
mmParamSize EQU mmMainString+4-8 ; # of bytes of parameters
mmMungeValue EQU mmMainString+4 ; return value
;
;
; Follows standard pascal register saving conventions
;
LINK A6,#0 ; set up a stack frame
MOVEM.L D3-D7/A3-A4,-(SP) ; save the usual stuff
CLR mmMungeValue(A6) ; clear initial value
MOVEQ #0,D3
MOVEQ #0,D4
MOVE.L mmSubString(A6),A3 ; get the substring 2 addr
MOVE.L mmMainString(A6),A4 ; get the main string 1 addr
MOVE.B (A3)+,D3 ; D3 = size of substring
MOVE.B (A4)+,D4 ; D4 = size of mainstring
CMP.B D4,D3 ; compare lengths
BGT.S @99 ; if MainString's len>SubString's then exit
; A4 contains string to be searched
; D4 contains len
;
; A3 contains target string pointer doing the search
; D3 contains length
MOVE.L A4,D6 ; put main string in D6
MOVE.L D4,D7 ; get size of string
SUB.L D3,D7 ; subtract len of string
ADD.L D6,D7 ; point to last valid search loc
@outer
MOVE.L D3,D1 ; inner loop ctr for compare
MOVE.L D6,A0 ; working copy of main string
MOVE.L A3,A1 ; working copy of search string
BRA.S @startDBRA
@inner
CMP.L D6,D7 ; see if anchor if past limit
BCS.S @notFound
CMPM.B (A0)+,(A1)+ ; compare bytes
BNE.S @tryNext
@startDBRA
DBRA D1,@inner ;
; If it gets to here, the target string matched!
MOVE #1,mmMungeValue(A6)
BRA.S @99
; The match failed on this byte, move anchor to next and try again
@tryNext
ADDQ.L #1,D6 ; anchor ++
BRA.S @outer
; The match failed entirely, go home with with a zero
@notFound
@99
MOVEM.L (SP)+,D3-D7/A3-A4 ; restore the usual stuff
UNLK A6
MOVE.L (SP)+,A0
ADDA.L #mmParamSize,SP ; or LEA mmParamSize(SP),SP but this is slower
JMP (A0)
IF HelpMgrTesting THEN
DoDebugSymbols __HMMungeSearch ; label for MacsBug
ENDIF
ENDP
;---------------------------------------------------------------------------------------------
;
; __HMScanHWinResource
;
; This routine is called from the _SystemTask patch and scans a 'hwin' resource
; looking for a match for the _FrontWindow's window title and a name in the 'hwin'
; window array. If found, it then scans the corresponding 'hrct' or 'hdlg' resource that
; 'belongs' to the 'hwin' resource. A 'hrct' resource contains an array of tip, altRect,
; and balloon data for the 'hot' rects & the 'hdlg' resource is an array of tip, altRect,
; and balloon data.
;
; Returns 0 if call handled, -1 if missing or false scan
;
; Modification history:
; 08May92 KSCT added code to support Input Method's floating window ... <#72>
;
; some local variables
;
scanHotRect EQU -8 ; hot rect
scanIndex EQU scanHotRect-2 ; current index
scanTempPt EQU scanIndex-4 ; point to test mouse with
scanPort EQU scanTempPt-4 ; the previous port goes here
scanWTitle EQU scanPort-256
scanResFile EQU scanWTitle-2
scanCurResFile EQU scanResFile-2
scanResID EQU scanCurResFile-2
scanResType EQU scanResID-4
scanResName EQU scanResType-256
scanResHandle EQU scanResName-4
scanhwinCount EQU scanResHandle-2
scanhwinIndex EQU scanhwinCount-2
scanHelpMsg EQU scanhwinIndex-khmmMsgSize ; max size of help msg
scanSize EQU scanHelpMsg
;
; Note that the _GetIndResource call below searches all open resource files for
; the current layer. We MUST set the CurResFile to be the matching 'hwin'
; resource's resource reference number in order to find the correct 'hrct' resource.
;
;
__HMScanHWinResource PROC EXPORT
IMPORT __HMScanTemplateItems
IMPORT __HMFillInHelpMessage
IMPORT __HMShowContentBalloon
IMPORT __HMRemoveBalloon
IMPORT __HMMungeSearch
move.l a3,-(sp) ; save a3 <#72>
suba.w #(2+tsmHelpRecSize),sp ; OSErr result + tsmRecSize <#72>
move.w #kMsgHelpHELPMgr,-(sp) ; message number <#72>
pea 4(sp) ; param ptr <#72>
_InformTSM ; call Text Services Manager <#72>
move.w (sp)+,d0 ; is this IM's window? <#72>
movea.l sp,a3 ; a3 = param record <#72>
; (got window/refnum if d0 = noErr) <#72>
clr.l tsmHelpSavedLayer(a3) ; clear layer local <#72>
tst.w d0 ; over a floater? <#72>
bne.s @notIMWindow ; not over a floating, then cool => <#72>
;; need to swap the layer to IM layer ......
subq #2,sp ; space for layer result <#72>
pea tsmHelpSavedLayer(a3) ; for layer result <#72>
_NewFloatLayer ; get the IMLayer <#72>
move.w (sp)+,d0 ; error? <#72>
beq.s @3 ; no <#72>
clr.l tsmHelpSavedLayer(a3) ; if error, clear layer local <#72>
bne.s @notIMWindow ; something is wrong <#72>
@3
move.l tsmHelpSavedLayer(a3),d0 ; layer in d0 <#72>
subq #4,sp ; space for layer result <#72>
move.l d0,-(sp) ; push IMlayer <#72>
_SwapCurLayer ; swap it <#72>
move.l (sp)+,tsmHelpSavedLayer(a3) ; save prev layer in a3 <#72>
@notIMWindow
SUBQ #2,SP ; room for result
MOVE.L #kHMWindListResType,-(SP) ; get these types, always 'hwin'
_CountResources ; how many 'hwin's are there?
MOVE (SP)+,D0 ; put count here
BEQ @NoHWIN ; there were no 'hwin's, so give up
LINK A6,#scanSize ; make a stack frame
MOVEM.L D2-D7/A2/A4,-(SP) ; save some regs (A3 can't be used !!! <#72>)
MOVE D0,scanhwinCount(A6) ; save how many we found (D0 got it from _CountResources call above)
move.l tsmHelpWindowPtr(a3),d7 ; do we have the flaoting window? <#72>
beq.s @5 ; no, use original code <#72>
movea.l d7,a2 ; save in a2 too <#72>
bra.s @9 ; join the original code <#72>
@5
SUBQ #4,SP ; room for the _FrontWindow call…
_FrontWindow ; don't look at lomem here, layer mgr is in!
MOVE.L (SP)+,A2 ; A2 -> frontwindow
MOVE.L A2,D7 ; save in D7 for later
@9
PEA scanPort(A6) ; a place to put the old port
_GetPort ; layer manager munges this
MOVE.L A2,-(SP) ; always force port to be that ol' frontwindow
_SetPort ; do it
MOVE.L wTitleHandle(A2),A0 ; get the window's title string handle in A0
MOVE.L (A0),A0 ; deref to get pointer
LEA scanWTitle(A6),A1 ; compute address of our local title storage
MOVEQ #0,D0 ; clear some hi bits
MOVE.B (A0),D0 ; and copy the window title
@CopyWTitleLoop
MOVE.B (A0)+,(A1)+
DBRA D0,@CopyWTitleLoop
MOVE.W windowKind(A2),D6 ; <53> window's kind used when matching a negative hwinLength field
SUB #2,SP ; make space for the _CurResFile call
_CurResFile ; get this if any
MOVE (SP)+,scanCurResFile(A6) ; put the curResFile Here
MOVEQ #1,D0 ; put in D0 for _GetIndResource call
MOVE D0,scanhwinIndex(A6) ; and start at the first one
CLR.L scanResHandle(A6) ; clear the hwin resource handle area
@MoreHWins
SUBQ #4,SP ; room for res handle
MOVE.L #kHMWindListResType,-(SP) ; get these types, always 'hwin'
MOVE D0,-(SP) ; start at the last resource (hopefully only 1)
_GetIndResource ; get the resource (indexed via D4)
MOVE.L (SP)+,A0 ; handle in A0
MOVE.L A0,D0 ; did we get it? (need for later too!)
BEQ @CouldntGetHWIN ; no, exit!
_HLock ; always lock the 'hwin' resource
MOVE.L A0,scanResHandle(A6) ; save it for later
MOVE.L (A0),A4 ; A4 -> 'hwin' resource data
SUB #2,SP ; make space for the _HomeResFile call
MOVE.L A0,-(SP) ; push the 'hwin' resource
_HomeResFile ; get resource ref num of the 'hwin' resource
MOVE (SP),scanResFile(A6) ; put refnum of 'hwin' in here (leave on stack)
_UseResFile ; force it to be the CurResFile
MOVE.W hwinCount(A4),D4 ; get 'hwin' array count
BEQ.S @CouldntGetHWIN ; skip this hwin if zero, go to next hwin
MOVEQ #0,D5 ; clear our counter
MOVEQ #0,D3 ; clear offset len (for each array item)
@moreHWinArray
LEA hwinArray(A4,D3.L),A2 ; find next array rec @ (start of array + D3)
MOVEQ #0,D1
MOVE.B hwinString(A2),D1 ; we need to do this because overflow w/ ADD.B
ADD D1,D3 ; length of 'hwin' window title string
ADD.W #hwinString+2,D3 ; length byte + offset to next array item = size in bytes
; + 1 to round it up
AND #$FFFE,D3 ; make it even to compensate for word align
MOVE.W hwinLength(A2),D0 ; <53> get the hwin's length field now
BPL.S @MatchStringWise ; <53> if negative then use window's windowkind as a matching
; <53> mechanism
NOT.W D0 ; <53> invert length to make it positive
ADDQ #1,D0 ; <53> add 1 to make -(-x) = x
CMP.W D6,D0 ; <53> D6 has the window's window kind
BEQ.W @FoundHWinArray ; <53> if window kind matches then consider this an hwin match
BRA.S @NoSubMatch ; <53> otherwise index to next element in hwin resource
@MatchStringWise
MOVE.L hwinOptions(A4),D0 ; get the hwin options long
MOVEQ #0,D1
MOVE #kBTSTMatchInTitle,D1
BTST D1,D0 ; do we want to match via HMMunge?
BEQ.S @MatchRegularly ; no, just use the regular CmpString call
SUBQ #2,SP ; room for result from HMMunge
PEA scanWTitle(A6) ; push ptr to original window title string
PEA hwinString(A2) ; and substring to match…
JSR __HMMungeSearch
MOVE (SP)+,D0
BNE @FoundHWinArray ; 1 if a match was found (differs from result of CmpString)
BRA.S @NoSubMatch
@MatchRegularly
; MOVE hwinLength(A2),D0 ; D0 = hwin compare len (low bits)
; CMP.B D0,D1 ; is the specified compare len < hwinString?
; BLT.S @lenOK ;
; MOVE D1,D0 ; force it to be the same
;@lenOK
MOVE hwinLength(A2),D0 ; D0 = hwin compare len (low bits)
SWAP D0 ; put len in hi bits
MOVE hwinLength(A2),D0 ; D0 = hwin compare len (low bits)
LEA scanWTitle+1(A6),A0 ; watchit! this is odd (A0 -> to string1+1)
LEA hwinString+1(A2),A1 ; A1 -> to string2+1
_CmpString ; compare strings by using EqualString call,
; EQ if they match
BEQ.S @FoundHWinArray ; found a 'hrct' template entry for this window
@NoSubMatch
ADDQ #1,D5 ; index to next
CMP D4,D5 ; are we done scanning array list
BLT.S @moreHWinArray ; no.
; if we finished the whole array then fall thru.
@CouldntGetHWIN
MOVE scanCurResFile(A6),-(SP) ; get the old ResFile ref num
_UseResFile ; set it back
MOVE.L scanResHandle(A6),A0 ; restore the hwin resource so we can unlock it
MOVE.L A0,D0 ; set some ccr's
BEQ.S @dontUnlockIt ; never unlock a NIL handle
_HUnlock
@dontUnlockIt
ADDQ #1,scanhwinIndex(A6) ; go to next index
MOVE scanhwinIndex(A6),D0 ; put index back in D0
CMP scanhwinCount(A6),D0 ; and see if we're done
BLE.S @MoreHWins ; no, loop (else fall thru)
MOVE.L scanPort(A6),-(SP) ; push the old port
_SetPort ; and set it
MOVEM.L (SP)+,D2-D7/A2/A4 ; restore 'em
UNLK A6
MOVEQ #0,D0 ; that we handled the call…
bra.s @cleanup4TSMandRet
@NoHWIN
MOVEQ #1,D0 ; say we handled the check, just exit _systask
;; added code to support Input Method's floating window ... <KSCT #72>
@cleanup4TSMandRet
move.l d0,-(sp) ; save the result (I have no idea why it returns 0 and 1) < #72>
move.w tsmHelpRefnum(a3),d0 ; is resource file open? < #72>
beq.s @notOpen ; no < #72>
subq #2,sp ; room for result < #72>
move.w d0,-(sp) ; refnum to close < #72>
_CloseComponentResFile ; use Component Manager < #72>
addq #2,sp ; ignore error < #72>
@notOpen
move.l tsmHelpSavedLayer(a3),d0; prev. layer in d0 < #72>
beq.s @noSavedLayer ; no saved layer < #72>
move.l d0,-(sp) ; pass in saved layer < #72>
_SetCurLayer ; restore the layer < #72>
@noSavedLayer
move.l (sp)+,d0 ; restore the result < #72>
lea tsmHelpRecSize(sp),sp ; restore stack < #72>
movea.l (sp)+,a3 ; restore a3 < #72>
RTS ; finished w/ scan of help content resource
;
; If we got here then the frontwindow's title was in the 'hwin' resource for the current
; application heap's resource map. Now, let's get the 'hwin' resource's corresponding
; 'hrct' or 'hdlg' resource that contains the 'hot' rects for the balloons where ever the mouse
; is. The port has just been set to the frontwindow's port, so check the mouse and
; see if the any 'hot' rects should be showing a help balloon…
;
; The routine uses the help globals to determine if the balloon that we should show is
; already showing by comparing the windowptr & itemrect from the last time.
;
; entry: A2 -> hwinArray[i]
; A4 -> hwinResource
; D3 = offset into hwinArray
; D7 = frontwindow window ptr (port is set to this window at this point)
;
@FoundHWinArray
PEA scanTempPt(A6) ; push a point to put the result of _GetMouse
_GetMouse ; remember, _GetMouse returns local coords (we want them this way)!
CLR.W -(SP) ; space for result
MOVE.L scanTempPt(A6),-(SP) ; move the mouse pt on the stack
MOVE.L D7,A0 ; get window ptr in A0
PEA PORTRECT(A0) ; push window's portrect
_PtInRect
TST.B (SP)+ ; was the pt in the window's portrect rect?
BEQ.S @CouldntGetHWIN
MOVE.L hwinOptions(A4),D0 ; get the hwin options long
BTST #kBTSTUseSubID,D0 ; was the hwin a DA's type, using SUB ID's?
BEQ.S @UseResID ; no, just use the regular resource ID
; yes, we need to get the hwin's resID
; and add in the sub ID
MOVE.L scanResHandle(A6),-(SP) ; push the hwin resource handle
PEA scanResID(A6) ; VAR theID : INTEGER
PEA scanResType(A6) ; VAR theType : ResType
PEA scanResName(A6) ; VAR name : STR255;
_GetResInfo ; get some info on the resource
MOVE scanResID(A6),D0 ; put the resource ID in D0
ADD hwinResID(A2),D0 ; add in the SUB ID
BRA.S @UsedSubID
@UseResID
MOVE hwinResID(A2),D0 ; D0 hrct resource ID for this search
@UsedSubID
SUBQ #2,SP ; <61> make some room for the OsErr result
; <61> Ack! we forgot to make this space in pre-b4 builds!!
MOVE D0,-(SP) ; push the ID
MOVE #-1,-(SP) ; scan this resfile (-1 means current)
MOVE.L hwinResType(A2),-(SP) ; was just 'hdlg'
JSR __HMScanTemplateItems ; scan any 'hdlg' resource of this ID
ADDQ #2,SP ; <61> forget the result
BRA @CouldntGetHWIN ; exit as we scanned a 'hdlg' instead
IF HelpMgrTesting THEN
DoDebugSymbols __HMScanHWinResource ; label for MacsBug
ENDIF
ENDP
;---------------------------------------------------------------------------------------------
;
;
; FUNCTION __HMScanHRCTResource(whichWindow: WindowPtr; whichResID: INTEGER; whichPt: Point;
; VAR whichMsg: INTEGER): OsErr;
;
; Exit:
; Follows PASCAL standard trashing conventions
;
;
__HMScanHRCTResource FUNC EXPORT ; retrieve & scan 'hrct' resource from the curResFile
SaveRegs REG D3-D7/A2-A4 ; Standard registers to save
resultsStackFrame
result ds.w 1 ; the result
parametersStackFrame
whichWindow ds.l 1 ; the window to track to
whichResID ds.w 1 ; the resource ID to get
whichPt ds.l 1 ; the point to track
whichMsg ds.l 1 ; this is the VAR to fill
endStackFrame
linkSave SaveRegs
MOVE #resNotFound,result(A6) ; return resource not found as initial default error
SUBQ #4,SP
MOVE.L #kHMRectListResType,-(SP) ; push the resource type (should be 'hrct' if we got this far)
MOVE whichResID(A6),-(SP) ; push the hrct resource ID for this search
_Get1Resource ; get the handle (search only the current resfile)
MOVE.L (SP)+,D0 ; did we get it?
BEQ @CouldntGetHRCT ; no, exit!
MOVE.L D0,A0 ; put in A0 for deref
MOVE.L (A0),A4 ; put a ptr to the 'hrct' resource in A4
MOVE.W #hmWrongVersion,result(A6) ; <66> make default return code bad version
CMP #hmBalloonHelpVersion,hrctVersion(A4) ; was the version of the resource correct?
BGT @CouldntGetHRCT ; no, exit!
MOVE.W hrctCount(A4),D4 ; get hrct array count
BEQ.S @regularExit ; there are no items in array so exit!
MOVE.L hrctOptions(A4),D0 ; get the options longword in D0
BTST #kBTSTAbsoluteCoords,D0 ; see if we're to use absolute mouse position (local)
BEQ.S @UseWindowOrigin ; no, just leave the mouse point alone!
MOVE.L whichWindow(A6),A0 ; get window ptr in A0
MOVE PORTRECT+TOP(A0),D0 ; get the window's portrect top coord
SUB D0,whichPt+v(A6) ; subtract the origin vertical
MOVE PORTRECT+LEFT(A0),D0 ; get the window's portrect left coord
SUB D0,whichPt+h(A6) ; subtract the origin horizontal
; now mouse pt is converted to window's origin
@UseWindowOrigin
MOVEQ #0,D5 ; clear the index
MOVEQ #0,D3 ; and offset size
@moreHRctArray
LEA hrctArray(A4,D3.L),A2 ; compute start of next record
SUBQ #2,SP ; space for result
MOVE.L whichPt(A6),-(SP) ; move the mouse pt on the stack
PEA hrctHotRect(A2) ; push current array item's rect (always word aligned)
_PtInRect
TST.B (SP)+ ; was the pt in the array rect?
BNE.S @FoundARect ; yes, so put up a help balloon
ADDQ #1,D5 ; index to next
CMP D4,D5 ; is count > indexer?
BGE.S @CouldntGetHRCT ; yes, we're done scanning 'hot' rects
ADD hrctHelpMsgSize(A2),D3 ; add the size of the message for next loop
BRA.S @moreHRctArray ; and go index to next array element
@FoundARect
MOVE.L whichMsg(A6),A0 ; get ptr to VAR index
ADDQ.W #1,D5 ; make it one based
MOVE D5,(A0) ; save the index in the VAR
@regularExit
MOVE #noErr,result(A6) ; return noErr
@CouldntGetHRCT
restoreUnlinkReturn
IF HelpMgrTesting THEN
DoDebugSymbols __HMScanHRCTResource ; label for MacsBug
ENDIF
ENDP
;---------------------------------------------------------------------------------------------
;
;
; FUNCTION __HMGetIndHelpMsg(whichType: ResType;
; whichResID, whichMsg, whichState: INTEGER;
; VAR options: LongInt;
; VAR tip: Point;
; hotRect: RectPtr; {same as VAR hotRect: Rect}
; VAR theProc: INTEGER; VAR variant: INTEGER;
; VAR aHelpMsg: HMMessageRecord;
; VAR count: INTEGER): OsErr;
;
;
; Enter:
; whichType = kHMMenuResType, kHMDialogResType, kHMRectListResType, kHMOverrideResType, kHMFinderApplResType
; whichResID = Resource ID of the help resource to search
; whichMsg = Index into the resource (which message in the resource)
; whichState = kHMEnabledItem, kHMDisabledItem, kHMCheckedItem, kHMOtherItem
;
; Exit:
; Follows PASCAL standard trashing conventions
;
;
__HMGetIndHelpMsg FUNC EXPORT
IMPORT __HMFillInHelpMessage
IMPORT __HMTypeCheck
SaveRegs REG D2-D7/A2-A4 ; Standard registers to save
resultsStackFrame
result ds.w 1 ; the result
parametersStackFrame
whichType ds.l 1 ; the resource type to get
whichResID ds.w 1 ; the resource ID to get
whichMsg ds.w 1 ; which index into msg record to fetch
whichState ds.w 1 ; the state to fetch
aOptions ds.l 1 ; the options long
aTip ds.l 1 ; the tip to fetch or 0,0
aHotRect ds.l 1 ; the rect to fetch or EmptyRect()
aProc ds.l 1 ; the Proc
aVariant ds.l 1 ; the variant
aHelpMsg ds.l 1 ; this is the VAR to fill
aCount ds.l 1 ; this is the count of items in resource
localsStackFrame
firstTime ds.w 1 ; flag to say we've been thru the msg rec once
resourceSize ds.l 1 ; size for the resource
endStackFrame
linkSave SaveRegs
MOVE whichMsg(A6),D0 ; check index against zero
BEQ @BadIndexStateOrType
MOVE.L whichType(A6),D0 ; get the resource type in D0
BSR __HMTypeCheck ; call Typecheck routine (register interface) to see if resType was in:
; [kHMMenuResType,kHMDialogResType,kHMRectListResType,kHMOverrideResType,kHMFinderApplResType]
BNE @BadIndexStateOrType ; returns w/ condition codes set (true means that it wasn't a supported resource)
SUBQ #4,SP
MOVE.L whichType(A6),-(SP) ; push the resource type
MOVE.W whichResID(A6),-(SP) ; push the resource ID
_Get1Resource ; get the handle
MOVE.L (SP)+,D0 ; D0 = handle or NIL
BEQ @MissingResource ; if NIL then we didn't get the resource!
MOVE.L D0,A0 ; put in A0 for deref
MOVE.L (A0),A4 ; put a ptr to the resource in A4
CMP #hmBalloonHelpVersion,hmnuVersion(A4) ; was the version of the resource correct?
BGT @BadVersion ; no, it was too new
SUBQ #4,SP ; make room for a longInt
MOVE.L A0,-(SP) ; push resource handle for a size check
_SizeRsrc ; (we have to do this due to HMCompareItem)
MOVE.L (SP)+,resourceSize(A6) ; put the size of the resource here
MOVEQ #0,D0 ; clear a stuffer
MOVE.L aTip(A6),A0
MOVE.L D0,(A0) ; initially clear the tip parameter
MOVE.L aHotRect(A6),A0
MOVE.L D0,(A0)+
MOVE.L D0,(A0) ; and clear the hotRect
MOVE D0,firstTime(A6) ; clear the firsttime flag too
CMP.L #kHMDialogResType,whichType(A6) ; was the type 'hdlg' ?
BNE.S @NoDITLOffset ; no, so there is nothing to skip
ADDA #2,A4 ; else skip the DITL offset INTEGER
@NoDITLOffset
MOVE.L aOptions(A6),A0 ; get the ptr to the options long VAR
MOVE.L hmnuOptions(A4),(A0) ; return options longword
MOVE.L aProc(A6),A0 ; get the ptr to the theProc VAR
MOVE.W hmnuProcID(A4),(A0) ; return theProc integer
MOVE.L aVariant(A6),A0 ; get the ptr to the variant VAR
MOVE.W hmnuVariant(A4),(A0) ; return variant integer
MOVE.L aCount(A6),A0 ; get the ptr to the count VAR
MOVE.W hmnuCount(A4),D4 ; get array count (all offsets are = at this pt)
MOVE.W D4,(A0) ; D4 = count of messages,
BEQ.S @ExtractMissingMsg ; see if there is a missing message b4 exiting
CMP whichMsg(A6),D4 ; is the index in range?
BLT.S @ExtractMissingMsg ; no, compute the missing msg
MOVEQ #1,D5 ; setup the item counter index, starting with 1
MOVEQ #0,D3 ; clear hibits (D3.L is the offset into the array)
MOVE #hmnuHeaderSize,D3 ; skip header size as well (each resource type has this size)
CMP.L #kHMFinderApplResType,whichType(A6) ; was it 'hfdr'?
BEQ.S @moreArrayItems ; yes, branch as there is no missing message to skip over
CMP.L #kHMRectListResType,whichType(A6) ; was the type 'hrct' ?
BEQ.S @moreArrayItems ; yes, branch as there is no missing message to skip over
ADD hmnuMissingSize(A4),D3 ; skip over missing message by adding its length as well
; ('hdlg','hmnu','hovr' resources have missing messages)
@moreArrayItems
LEA hmnuArray(A4,D3.L),A2 ; compute next help message beginning
MOVE hmnuHelpType(A2),D6 ; D6 = help message type (setup in case this is the item)
CMP whichMsg(A6),D5 ; is this the index?
BEQ.S @foundtherecord ; yeah! this is the record we want
; go and stuff the hmmessagerecord
ADDQ #1,D5 ; else increment index to next item
ADD hmnuHelpMsgSize(A2),D3 ; skip over size of record
;
; Now make sure that we don't run off the end of the resource:
MOVE.L resourceSize(A6),D0 ; get the original resource size
LEA hmnuArray(A4,D3.L),A0 ; find array rec @ (start of array + D3)
SUB.L A4,A0 ; compute its size
CMP.L A0,D0 ; is the offset to the next msg past the end?
BGT.S @moreArrayItems ; no, it's less so we can go on to the next record
;
; if we fall thru, this means that the count parameter in the
; resource was bogus, so return with a paramErr result
@BadIndexStateOrType
MOVE #ParamErr,result(A6) ; say that it was a bad index
BRA @ExitHMExtract
@MissingResource
MOVE #resNotFound,result(A6) ; assume that it was not found
BRA @ExitHMExtract
@BadVersion
MOVE #hmWrongVersion,result(A6) ; now assume that it was wrong version
BRA @ExitHMExtract
@ExtractNILMsg
MOVE #hmSkippedBalloon,result(A6) ; say that it was a skipped result
BRA @ExitHMExtract
@ExtractMissingMsg
CMP.L #kHMFinderApplResType,whichType(A6) ; was it 'hfdr'?
BEQ.S @ExtractNILMsg
CMP.L #kHMRectListResType,whichType(A6) ; was the type 'hrct' ?
BEQ.S @ExtractNILMsg ; yes, so there is no missing msg, so NIL it and exit
TST firstTime(A6) ; was this the first time here?
BNE @ExtractNILMsg ; exit if this is the 2nd time that we did this…
ADD #1,firstTime(A6) ; set the flag word to say we've been here before
LEA hmnuMissingSize(A4),A2 ; compute missing msg beginning
MOVE hmnuMissingType(A4),D6 ; D6 = help message type
; fall thru to recalc the message record for missing msg
@foundtherecord
CMP #kHMSkipItem,D6 ; if it was a skip item then make msg NIL
BEQ @ExtractNILMsg ; EQ means it was skip
MOVE #hmnuHelpData,D3 ; assume we wanted to extract a hmnu, hovr, or hfdr msg
CMP #kHMCompareItem,D6 ; <53> add enough data to skip over the junk in a compare
BNE.S @NoCompareJunk ; <53> item to reach the beginning of the help msg data
LEA hmnuHelpData+hmnuCompareStr(A2),A1 ; <53> A1 -> the pstring to compare against
MOVEQ #0,D1 ; <53> clr hi bits
MOVE.B (A1),D1 ; <53> get the compare string's length
; <53> now, skip over the pstring's length by adding it's length
ADDQ #hmnuCompHeaderSize+1+1,D1 ; <53> plus the compare's header size and + 1 to make it align
AND #$FFFE,D1 ; <53> make it even to compensate for word align
ADD D1,A2 ; <53> increment A2 to point to start of help msg data (-2 cuz no size word)
MOVE hmnuCompType+2(A2),D6 ; <53> reset the message type, the +2 is because there is no size word between
; <53> compared strings and the help msg data
CMP.W #kHMSkipItem,D6 ; <59> don't fill in the message record for a skip item (the record doesn't have this case)
BEQ.S @ExtractNILMsg ; <59> return the 'skipped' result code
@NoCompareJunk
CMP.L #kHMDialogResType,whichType(A6) ; was it a 'hdlg' type?
BEQ.S @HasTipAndRectParams ; yes, make offset cover for tip & rect params
CMP.L #kHMRectListResType,whichType(A6) ; was it a 'hrct' type?
BNE.S @StateCheck ; no, don't skip over tip & rect params in message record
@HasTipAndRectParams
MOVE #hdlgHelpData,D3 ; offset to reach the hrct help message data (includes tip & rect)
@StateCheck
;
; A2 = address of message record
; D3 = offset to help message data
; D6 = type of message
; D2 = in [kHMEnabledItem..kHMOtherItem] to get the right message:
; default state always kHMEnabledItem in 'hrct','hovr', & 'hfdr' resources
;
MOVEQ #kHMEnabledItem,D2 ; default state (always kHMEnabledItem in 'hrct','hovr', & 'hfdr')
CMP.L #kHMOverrideResType,whichType(A6) ; was it a 'hovr' type?
BEQ.S @noStateOrRects ; yes, so ignore state parameter & don't copy any tip & rect params
CMP.L #kHMFinderApplResType,whichType(A6) ; was it a 'hfdr' type?
BEQ.S @noStateOrRects ; yes, so ignore state parameter & don't copy any tip & rect params
CMP.L #kHMMenuResType,whichType(A6) ; was it a 'hmnu' type?
BEQ.S @noTipOrHotRect ; yes, just use the state parameter, no tip & rects
MOVE.L aTip(A6),A0 ; get ptr to tip VAR
MOVE.L hdlgTip(A2),(A0) ; stuff the tip parameter from message record
MOVE.L aHotRect(A6),A0 ; get ptr to hotRect VAR
MOVE.L hdlgHotRect+topleft(A2),(A0)+ ; stuff topleft first
MOVE.L hdlgHotRect+botRight(A2),(A0) ; then botRight
@noTipOrHotRect
MOVE whichState(A6),D2 ; use the state as an index
@noStateOrRects
ADDA.W D3,A2 ; A2 -> helpmsg data
CMP #kHMStringItem,D6 ; was it a string?
BEQ @StuffString ; yes, figure out where the string is…
CMP #kHMStringResItem,D6 ; was it a string res ID?
BEQ.S @StuffLong ; yes, copy over the two integers info
ASL.W #1, D2 ; * 2 for offset (one integer)
MOVE (A2,D2),D1 ; get integer message in D1
BEQ.S @ExtractMissingMsg ; if 0 then let's try for a missing message
MOVE D1,A3 ; put in the integer message (resID) in A3 for fill in
BRA @StuffMsgData ; branch to stuffer code
@StuffLong
ASL.W #2, D2 ; * 4 for offset (one long)
MOVE.L (A2,D2),D1 ; get longword message in D1
BEQ.S @ExtractMissingMsg ; if 0 then let's try for a missing message
MOVE.L D1,A3 ; put in the long (STR# resID & index) in A3
BRA @StuffMsgData ; branch to stuffer code
@StuffString
MOVEQ #0,D0 ; clear index
CMP #kHMEnabledItem,D2 ; is the item enabled? (kHMEnabledItem if 'hovr' or 'hrct')
BEQ.S @ReadyToStuff ; yes, the msg is ready
MOVE.B (A2),D0 ; add pstring length (no ADD.B carry prob cuz D0 was 0 at this point)
ADDQ #1,D0 ; plus 1 for the length byte
CMP #kHMDisabledItem,D2 ; was the item disabled?
BEQ.S @ReadyToStuff ; yes, the msg is ready
MOVEQ #0,D1 ; clear MOVE.B adder
MOVE.B 0(A2,D0.W),D1 ; put in D1 for add (can't do a ADD.B here due to possible overflow)
ADD D1,D0 ; and add in the disabled pstring length
ADDQ #1,D0 ; plus 1 for the length byte
CMP #kHMCheckedItem,D2 ; was the item checked?
BEQ.S @ReadyToStuff ; yes, the msg is ready
MOVE.B 0(A2,D0.W),D1 ; put in D1 for add [<52> was hmnuHelpData(A2,D0.W) previously]
ADD D1,D0 ; no, add in the checked pstring length
ADDQ #1,D0 ; plus 1 for the length byte
; else, item must have been 'other', just fall thru
@ReadyToStuff
LEA (A2,D0.W),A3 ; recompute the address of the message
MOVE.B (A3),D2 ; was the string NIL? (while copying the pstring len)
BEQ @ExtractMissingMsg ; yes, the message is zero, so fetch the missing message
@StuffMsgData
SUBQ #2,SP
MOVE D6,-(SP) ; push the help message type
MOVE.L A3,-(SP) ; push some info data to fill in
MOVE.L aHelpMsg(A6),-(SP) ; push the help message record to fill in
JSR __HMFillInHelpMessage
MOVE (SP)+,result(A6) ; return result (always noErr for now)
@ExitHMExtract
restoreUnlinkReturn
IF HelpMgrTesting THEN
DoDebugSymbols __HMGetIndHelpMsg ; label for MacsBug
ENDIF
ENDP
;---------------------------------------------------------------------------------------------
;
; Routine: __HMTypeCheck
; checks to see if D0 was in:
; [kHMMenuResType,kHMDialogResType,kHMRectListResType,kHMOverrideResType,kHMFinderApplResType]
;
; returns w/ ccrs false if EQ (in set of help message set)
;
__HMTypeCheck PROC EXPORT
CMP.L #kHMMenuResType,D0
BEQ.S @TypeCheckExit
CMP.L #kHMDialogResType,D0
BEQ.S @TypeCheckExit
CMP.L #kHMRectListResType,D0
BEQ.S @TypeCheckExit
CMP.L #kHMOverrideResType,D0
BEQ.S @TypeCheckExit
CMP.L #kHMFinderApplResType,D0
@TypeCheckExit
RTS
ENDP
;---------------------------------------------------------------------------------------------
;
;
; FUNCTION __HMFillInMenuMessage(menuID,item,resID: INTEGER; flags: LongInt;
; VAR variant: INTEGER;
; VAR aHelpMsg: HMMessageRecord): OsErr;
;
__HMFillInMenuMessage PROC EXPORT
IMPORT __HMGetMenuItemStatus
IMPORT __HMFillInHelpMessage
IMPORT __HMFillFrontProcessString
IMPORT __HMFillCitationString
IMPORT GetIndString
;
;
fimHelpMsg EQU 8 ; ptr to HMMessageRecord
fimVariant EQU fimHelpMsg+4
fimFlags EQU fimVariant+4 ; menu flags
fimUseResID EQU fimFlags+4 ; overriding resID
fimItem EQU fimUseResID+2 ; menu item
fimMenuID EQU fimItem+2 ; menu ID
fimParamSize EQU fimMenuID+2-8 ; # bytes params
fimResult EQU fimMenuID+2 ; return value
fimItemString EQU -256 ; space for a STR255 used in GetItem
fimTempString EQU fimItemString-256
fimAuxMenuItemRec EQU fimTempString-Sizeof_auxdata
fimResID EQU fimAuxMenuItemRec-2
fimResType EQU fimResID-4
fimResourceSize EQU fimResType-4
fimMarkChar EQU fimResourceSize-2
fimFirstTime EQU fimMarkChar-2
fimWasHelpMenuCustom EQU fimFirstTime-2
fimWasModalMenu EQU fimWasHelpMenuCustom-2
fimMenuState EQU fimWasModalMenu-4
fimLocalSize EQU fimMenuState ; size of our locals
;
LINK A6,#fimLocalSize ; make a stack frame
MOVEM.L D2-D7/A2-A4,-(SP) ; save 'em
MOVE.W #resNotFound,fimResult(A6) ; set error result (message not found)
MOVEQ #0,D0
MOVE D0,fimFirstTime(A6) ; clear this flag in case item is NIL AND missing
MOVE D0,fimWasHelpMenuCustom(A6) ; and this variable…
MOVE D0,fimWasModalMenu(A6)
SUBQ #4,SP ; room for handle
MOVE fimMenuID(A6),-(SP) ; we need the menu handle so we can get
_GetMHandle ; the menu item's itemstring and the item's attributes
MOVE.L (SP)+,D4 ; D4 = menuhandle or NIL
BEQ @nohmnu ; yikes! how could we get a NIL menuhandle at this point?
SUBQ #4,SP ; Make room for result and create space for boolean
PEA 2(SP) ; Address of result area
_GetFrontWindowModalClass ; call FUNC GetFrontWindowModalClass(VAR integer):OsErr;
TST (SP)+ ; Any error (popping OsErr)
BEQ.S @donewithmodalcheck ; Nope, take off
MOVE.B #0,(SP) ; force return to be 0
@donewithmodalcheck
MOVE.W (SP)+,D0 ; <58> get frontwindow's modal class
CMP.W #dBoxProc,D0 ; <58> dBoxProc is only the truely modal dialog type
BNE.S @NoNeedToPushMenuState ; <58> NE means that the frontwindow was NOT modal!
MOVE.W D0,fimWasModalMenu(A6) ; set CCRs and save the INTEGER (dBoxProc = 1)
_DMgrPushMenuState ; push the disabled menu state for menu status
MOVE.L (SP)+,fimMenuState(A6) ; and save the state for later restore
@NoNeedToPushMenuState
SUBQ #2,SP
MOVE.L D4,-(SP) ; push the menu handle for _GetItemMark
MOVE.L fimFlags(A6),-(SP) ; push the menu enabled flags
MOVE fimItem(A6),-(SP) ; push the item number
JSR __HMGetMenuItemStatus ; Get the item's status (Handle safe)
MOVE (SP)+,D7 ; D7 now has [kHMEnabledItem..kHMOtherItem] in it
TST.W fimWasModalMenu(A6) ; did we push the menu state?
BEQ.S @NoNeedToPopMenuState ; EQ means no
MOVE.L fimMenuState(A6),-(SP) ; push the pushed menu state
_DMgrPopMenuState ; and pop it
@NoNeedToPopMenuState
;
; at this point D4 = MenuHandle, D7 = menu item state, fimWasModal state flag is setup
;
MOVE.L D4,A0 ; put a copy in A0 for deref
MOVE.L (A0),A4 ; A4 -> menuData
CMP #$0114,menudata(A4) ; is the title the AppleMark?
BEQ @WasAppleMenu ; yup, just handle the desk accessories, though.
CMP #kHMProcessMenuID,fimMenuID(A6) ; was it the process menu?
BEQ @WasProcessMenu ; EQ means yes, so do the process menu
CMP #kHMHelpMenuID,fimMenuID(A6) ; was it the help menu?
BNE @RegularMenu ; NE means no, so go handle regular menu
;
; Handle the help menu
;
@WasHelpMenu
CMP #kHMMenuItemCount,fimItem(A6) ; was the item in help menu > our items?
BLE.S @FetchOurHMNU ; LE means no, so go fetch our 'hmnu' resource
; out of the system file, not the application
TST.W fimWasModalMenu(A6) ; was a modal dialog up?
BNE @FetchOurHMNU ; EQ means no, so fetch regular hmnu
ST fimWasHelpMenuCustom(A6) ; flag saying we were in the help menu, but in an app's
; added item in the help menu, so, go get it
BRA @RegularMenu ; from the application supplied resource
@FetchOurHMNU
SUB #2,SP ; make space for the CurRes call
_CurResFile ; get current res file ref # if any
MOVE SysMap,-(SP) ; make the res file the system file
_UseResFile ; search for resources here
SUBQ #4,SP
MOVE.L #kHMMenuResType,-(SP) ; push the resource type, always 'hmnu'
MOVE fimMenuID(A6),-(SP) ; of this ID
_GetResource ; get the resource handle
MOVE.L (SP)+,A2 ; A2 = 'hmnu' resource handle
_UseResFile ; restore the current resfile
MOVE.L A2,A0 ; put in A0 for warm entry
BRA @UseA0hmnuResource ; go extract the messages from the hmnu
;
; Handle the process menu
;
@WasProcessMenu
MOVE fimItem(A6),D0 ; was the item 0 (meaning the title)?
BEQ @RegularMenu
TST.W fimWasModalMenu(A6) ; was the world in a ModalDialogMenu state?
BNE @RegularMenu
CMP #kHMProcessDashItem,D0 ; was the process menu item > dash?
BGT.S @WasProcessItem ; GT means yes
; else do the show/hide window menu items
SUBQ #2,SP
PEA fimItemString(A6)
JSR __HMFillFrontProcessString ; get the process name in fimItemString(A6)
MOVE (SP)+,D0 ; *** whaddayl I do if an error occurs?
CMP.W #kHMEnabledItem,D7 ; <58> was it an kHMEnabledItem? (was MOVE D7,D0)
; MOVE D7,D0 ; was it an kHMEnabledItem? (0)
BNE.S @AddDisabledOffset ; nope, add the disabled offset into string list
MOVE #kHMShowHideEnabled-1,D7 ; start at enabled offset (less 1 'cuz items start at 1)
BRA.S @WasntDisabled ; skip to adding item in
@AddDisabledOffset
CMP #kHMShowAllItem,fimItem(A6) ; are we on the show all item?
BNE.S @NoSpecialShowAll ; nah, just put up the correct disabled message
SUBQ #2,SP
MOVE.L D4,-(SP) ; count the items of the process menu
_CountMItems
MOVE (SP)+,D0
CMP #kHMProcessesItem,D0 ; were there more than 5 items in the menu?
BGT.S @NoSpecialShowAll ; yes, just put up the usual message
MOVE #kHMShowHideDisabled+kHMShowAllDisabled,D7 ; *** Remove this soon! special case the Finder only balloon message
BRA.S @FilledMFString
@NoSpecialShowAll
MOVE #kHMShowHideDisabled-1,D7 ; start at disabled offset (less 1 'cuz items start at 1)
@WasntDisabled
ADD fimItem(A6),D7 ; add the item index in
BRA.S @FilledMFString ; go stuff the process string if any
@WasProcessItem
ADD #kHMActiveApplEnabled,D7 ; for processes, use this string index base
; <58> (D7 had kHMEnabledItem, kHMDisabledItem, kHMCheckedItem, kHMOtherItem in it)
BSR GetPItemPtr ; get a ptr to the item data
MOVE.L A0,D0 ; if NIL then the menu is corrupt or uninitialized
BEQ.S @NoProcessAuxData ; exit before we get into trouble
CLR.L fimAuxMenuItemRec+auxMenuHelpString(A6) ; clear this for yuks!
SUBQ #2,SP
MOVE.L D4,-(SP) ; push the menuhandle
MOVE.L A0,-(SP) ; push ptr to pitem
PEA fimAuxMenuItemRec(A6) ; push a place to put the AuxMenuItem information
MOVE.L #Sizeof_auxdata,-(SP) ; push the size of the AuxMenuItem record
_GetAuxMenuItem ; fill in the AuxMenuItem record
MOVE (SP)+,D0 ; if an error occurred, then there is no AuxMenu data
BNE.S @NoProcessAuxData
MOVE fimAuxMenuItemRec+auxMenuIconGray(A6),D0 ; was the auxIcon grayed?
BEQ.S @NoProcessAuxData ; non-zero means yes
ADDQ #1,D7 ; bump Enabled to Disabled
@NoProcessAuxData
MOVE.L D4,-(SP) ; push the menuhandle
MOVE fimItem(A6),-(SP) ; push the item number (we're walking the array)
PEA fimItemString(A6) ; a place to put the item string
_GetItem ; get the item string for the compare
@FilledMFString
PEA fimTempString(A6) ; fetch the base working string in tempstr
MOVE #kHMBalloonHelpID,-(SP) ; of this resID
MOVE D7,-(SP) ; and index <58> (D7 has STR#'s index to these process string in it)
JSR GetIndString
SUBQ #2,SP
PEA fimTempString(A6) ; search this string for citation
PEA fimItemString(A6) ; stuff this menu item text
MOVE #$0030,-(SP) ; search for '^0'
JSR __HMFillCitationString ; go search and stuff
MOVE (SP)+,D0 ; ignore result
MOVE #kHMStringItem,D6 ; say that the help message was a string
LEA fimTempString(A6),A3 ; put a ptr to the string in A3
BRA @Fillitin ; stuff the record and put up a balloon
@WasAppleMenu
MOVE.W #kHMStringResItem,D6 ; say that we want to fetch the string from a STR# resource
TST.W fimItem(A6) ; was the item 0 (meaning the title)?
BNE.S @wasAppleMenuItem
; <54> Rewrite the handling of the apple menu:
; <54> I made the mistake of watching the condition fimWasModalMenu(A6)
; <54> and assuming that if that was true then the title and any items MUST
; <54> be disabled. Instead, I should have been respecting the state of the
; <54> title or item in D7 (I also reduced the code by more than 40 bytes).
MOVE.L #(kHMBalloonHelpID<<16)+kHMAppleMenuTitle,A3 ; <54> assume that the title is enabled
CMP.W #kHMEnabledItem,D7 ; <54> was the title enabled?
BEQ @Fillitin ; <54> EQ means yes, so let's not worry about fimWasModalMenu flag
; <54> and just fetch the regular title's message
MOVE.L #(kHMBalloonHelpID<<16)+kHMActiveApplDisabledTitle,A3 ; <54> now assume that the title was disabled via modal dialog
BRA.S @testForAppleModality ; <54> and now test to see if the dialog is really causing the disabled title
@wasAppleMenuItem
MOVE.L #(kHMBalloonHelpID<<16)+kHMActiveApplDisabledItem,A3 ; <54> assume that the item was a disabled item via a modal dialog
CMP.W #kHMEnabledItem,D7 ; <54> was the item enabled?
BEQ.S @RegularMenu ; <54> EQ means yes, so let's not worry about fimWasModalMenu flag
; <54> and just fetch the regular item's message
@testForAppleModality
TST.W fimWasModalMenu(A6) ; <54> was the world in a ModalDialogMenu state?
BNE @Fillitin ; <54> NE means yes, so just jump to the filler routine
; <54> else fall thru as a regular item
;
; Here we call get the hmnu from the current application's resource file
; (The MenuID is now checked to see if it needs to be overridden by someone having called __HMSetMenuResID)
;
@RegularMenu
MOVE fimUseResID(A6),D0 ; get any alternate resource ID to fetch (From __HMGetMenuResID)
CMP #-1,D0 ; -1 means that we should just use the MenuID as a ResID
BNE.S @WasValidAlternate ; NE means we have a valid alternate
MOVE fimMenuID(A6),D0 ; else use what was passed in…
@WasValidAlternate
SUBQ #4,SP
MOVE.L #kHMMenuResType,-(SP) ; push the resource type, always 'hmnu'
MOVE.W D0,-(SP) ; get the ID in D0
_GetResource ; get the resource handle
MOVE.L (SP)+,A0 ; A0 = 'hmnu' resource handle
@UseA0hmnuResource
MOVE.L A0,D0 ; did we get it? (need for later too!)
BEQ @nohmnu ; no, exit!
MOVE.L (A0),A4 ; A4 -> 'hmnu' resource data
CMP #hmBalloonHelpVersion,hmnuVersion(A4) ; was the resource the right version?
BGT @wronghmnuVersion ; nope, so exit
SUBQ #4,SP ; make room for a longInt
MOVE.L A0,-(SP) ; push 'hmnu' resource handle for a size check
_SizeRsrc ; (we have to do this due to HMCompareItem)
MOVE.L (SP)+,D0
BEQ @nohmnu ; for some reason, hmnu resource was empty!
MOVE.L D0,fimResourceSize(A6) ; else, put the size of the resource here
MOVE.L fimVariant(A6),A0
MOVE hmnuVariant(A4),(A0) ; put in variant early
;
; <68> The code below handles the following methodology:
;
; if item = 0 then
; if modaldialogisup then
; putupmodaltitleballoon
; else putupregulartitleballoon
; else
; if inmenuselect and modaldialogisup then
; putupmodalitemballoon
; else putupregularitemballoon
;
;
;
TST.W fimItem(A6) ; was the item the title message? (0)
BNE.S @wasInAnItem ; NE means we were in an item in a pull-down or popup menu
TST.W fimWasModalMenu(A6) ; was there a modal dialog up? (1 means yes)
BEQ.S @doTheTitleBalloon ; EQ means no, so fetch the regular hmnu's msg for the title
CMP #kHMEnabledItem,D7 ; was the title enabled?
BEQ.S @doTheTitleBalloon ; yes, so use the regular title msg
MOVE.W #kHMCheckedItem,D7 ; assume that we want the 'modal' menu title message (the 'checked' msg)
BRA.S @doTheTitleBalloon ; branch to show the balloon
@wasInAnItem
MOVE.L ExpandMem,A0
MOVE.L ExpandMemRec.emHelpGlobals(A0),A0
TST.W hmgInMenuSelectFlag(A0) ; was the flag saying we were in _MenuSelect true?
BEQ.S @doTheMenuItemBalloon ; EQ means we were NOT in a pulldown menu, so it was a popup
TST.W fimWasModalMenu(A6) ; was there a modal dialog up? (1 means yes)
BEQ.S @doTheMenuItemBalloon ; EQ means no, so fetch the regular hmnu's msg for the item
CMP #kHMEnabledItem,D7 ; was the item enabled?
BEQ.S @doTheMenuItemBalloon ; yes, so use the regular item msg
MOVE.W #kHMOtherItem,D7 ; yes, so make it the 'modal' menu item message
; and fall thru to get the zeroth message from the resource
@doTheTitleBalloon
CLR fimItem(A6) ; make it fetch the msg for the title
MOVE #1,fimFirstTime(A6) ; mark it as we've already fetched the missing message
@doTheMenuItemBalloon
MOVE.W hmnuCount(A4),D0 ; get 'hmnu' array count in D0
BEQ @fetchhmnuMissingMsg ; if zero then fetch missing message (as all items were missing)
TST.B fimWasHelpMenuCustom(A6) ; was the mouse in help menu and in custom item?
BEQ.S @RegMissingItem ; EQ means no, so just fetch the hmnu's message for this title or item
ADD #kHMMenuItemCount+1,D0 ; normalize missing count from resource
@RegMissingItem
CMP fimItem(A6),D0 ; is the specified menu item in range? (D0)
BLT @fetchhmnuMissingMsg ; no, the item was out of range, therefore
; we should fetch the 'missing' message
MOVEQ #0,D5 ; clear the item counter index
MOVEQ #0,D3 ; clear offset (D3 is the offset into the array)
ADD #hmnuHeaderSize,D3 ; skip header size
ADD hmnuMissingSize(A4),D3 ; skip over missing message by adding its length as well
; A4 + D3 = start of hmnuArray records
@moreArrayItems
LEA hmnuArray(A4,D3.L),A2 ; compute next help message beginning
MOVE hmnuHelpType(A2),D6 ; D6 = help message type
CMP #kHMCompareItem,D6 ; is this a string compare test item?
BNE.S @RegularItem ; no, there isn't a pstring to test here
MOVE.L D4,-(SP) ; push the menuhandle
MOVE D5,-(SP) ; push the item number (we're walking the array)
PEA fimItemString(A6) ; a place to put the item string
_GetItem ; get the item string for the compare
MOVE.L A2,A3 ; save a copy of start of array record beginning
LEA hmnuHelpData+hmnuCompareStr(A2),A1 ; A1 -> the pstring to compare against
MOVEQ #0,D1 ; <53> clr hi bits
MOVE.B (A1),D1 ; <53> get the compare string's length
; now, skip over the pstring's length by adding it's length
ADDQ #hmnuCompHeaderSize+1+1,D1 ; plus the comp header size and + 1 to make it align
AND #$FFFE,D1 ; make it even to compensate for word align
ADD D1,A2 ; increment A2 to point to start of HelpData (-2 cuz no size word)
LEA fimItemString(A6),A0 ; A0 -> the menu item's itemstring
MOVEQ #0,D0 ; clr hi bits
MOVE.B (A0)+,D0 ; length of menu item's string (hi bits already clear)
SWAP D0 ; put in hi bits
MOVE.B (A1)+,D0 ; length of string to compare
_CmpString ; compare! & put result in D0
TST D0 ; make sure ccr's are set (I don't trust the dispatcher anymore)
BNE.S @noCmpMatch ; NE means that the CMP match failed, so lets skip over the item
MOVE hmnuCompType+2(A2),D6 ; setup the type in case we're on the right item
; (the +2 is to make calc work below cuz we don't have a size word)
CMP fimItem(A6),D5 ; do we want this item?
BEQ @foundtherecord ; yes, so go display its contents
ADDQ #1,D5 ; else, index to next item
@noCmpMatch
MOVE.L A3,A2 ; reset A2 as this isn't the record we wanted
BRA.S @SkipCompareItem ; skip down w/o incrementing the menu item count
; as though the item didn't exist
@RegularItem
TST.B fimWasHelpMenuCustom(A6) ; were we in the help menu and a custom item
BEQ.S @NoHelpItemCorrection ; EQ means no, so just check to see if this is the item we want
MOVE D5,D0 ; correct the item to match a 1 based entry in the appended help menu
ADD #kHMMenuItemCount+2,D0 ; skip over our items in the help menu and the dash
CMP fimItem(A6),D0 ; and then check to see if we're on the right index
BEQ.S @foundtherecord ; EQ means we're on the user's help item, so fetch its help msg
BRA.S @Nope ; if we got here then just go on to the next item in the menu
@NoHelpItemCorrection
CMP fimItem(A6),D5 ; is this right message for this item?
BEQ.S @foundtherecord ; yeah! this is the record we want
; go and show a balloon
@Nope
ADDQ #1,D5 ; increment index to next item
@SkipCompareItem
ADD hmnuHelpMsgSize(A2),D3 ; skip over size of record
MOVE.L fimResourceSize(A6),D0 ; get the original resource size
LEA hmnuArray(A4,D3.L),A0 ; find array rec @ (start of array + D3)
SUB.L A4,A0 ; make it a size
CMP.L A0,D0 ; is the offset to the next msg past the end?
BGT.S @moreArrayItems ; no, it's less so it's kosher.
; yes, so fetch the missing message as we ran out of records in array
@fetchhmnuMissingMsg
TST fimFirstTime(A6) ; this may be nonzero if a modal dialog menu item is
; being examined…
BNE @skipBalloon ; exit if this is the 2nd time that we did this…
ADD #1,fimFirstTime(A6) ; set the flag word to say we've been here before
LEA hmnuMissingSize(A4),A2 ; compute missing msg beginning
MOVE hmnuMissingType(A4),D6 ; D6 = help message type
; fall thru to go put it up
;
; We found the message record that we want… so, put up a balloon
;
@foundtherecord ; A2 -> array record; D6 = msg type
CMP #kHMSkipItem,D6 ; if it was a skip item then leave w/o displaying
BEQ @skipBalloon ; any balloon.
TST.W fimWasModalMenu(A6) ; was there a modal dialog up? (NE means yes)
BNE.S @ExtractTheMsg
SUBQ #2,SP
MOVE.L D4,-(SP) ; push the menu handle
MOVE.L fimFlags(A6),-(SP) ; push the menu enabled flags
MOVE fimItem(A6),-(SP) ; push the item number
JSR __HMGetMenuItemStatus ; Get the item's status
MOVE (SP)+,D7 ; D7 has [kHMEnabledItem..kHMOtherItem] in it
;
; This is the place to add extraction of new types of Help Messages.
;
; Unfortunately, you have to 'know' how each type is structured so that you can calculate
; the correct offset for disabled, checked, and other message starts.
;
; A2 = address of message data
; D6 = type of message
; D7 = in [kHMEnabledItem..kHMOtherItem] to get the right message
;
@ExtractTheMsg
;
CMP #kHMStringItem,D6 ; was it a string?
BEQ @Calcthestringaddr ; yes, figure out where the string is…
MOVE D7,D0 ; copy the flags byte
EXT.W D0 ; make it wordy
CMP #kHMStringResItem,D6 ; was it a string res ID?
BEQ.S @Copythelong ; yes, copy over the long sized info
CMP #kHMNamedResourceItem,D6
BEQ.S @FetchANamedResource ; yes, go get a named resource for this item
CMP #kHMSkipItem,D6 ; is the item type >= skip?
BGE @UnknownHelpType
ASL.W #1, D0 ; * 2 for offset (one integer)
MOVE hmnuHelpData(A2,D0),D1 ; what was in the help data?
BEQ @fetchhmnuMissingMsg ; EQ means zero, so fetch the missing msg (aka NIL msg)
MOVE D1,A3 ; put in the integer message (resID)
BRA @Fillitin ;
@Copythelong
ASL.W #2, D0 ; * 4 for offset (one long)
MOVE.L hmnuHelpData(A2,D0),A3 ; put in the long (STR# resID & index)
MOVE A3,D1
BEQ @fetchhmnuMissingMsg
BRA @Fillitin
@FetchANamedResource
MOVE fimItem(A6),D0 ; get the item for title check
BNE.S @InMenuItem ; NE means we were in a menu item and not the title
; EQ means title, so, extract the title name from the menu handle
MOVE.L D4,A0 ; put a copy of menu handle in A0 for deref
MOVE.L (A0),A0 ; deref
LEA menudata(A0),A0 ; this is the beginning of the menuhandle data
LEA fimItemString(A6),A1 ; put the title here
MOVEQ #0,D0 ; clear hi bits
MOVE.B (A0),D0 ; get the len of title string
@copyMenuTitle
MOVE.B (A0)+,(A1)+ ; copy each byte (including length)
DBRA D0,@copyMenuTitle ; loop 'til done
; <58> OK, the item was really the title. See if the mark was checked or other which really means
; <58> that a modal dialog was up, and we were fetching a help message from the
; <58> first item for the title or item message that supposed to appear when a modal dialog is up.
; <58> The code forced the item to be checked or other for title and item messages, but there is no mark
; <58> for this item as it is always the title. We can't call _GetItmMark for item #0 (title).
CMP #kHMCheckedItem,D7 ; <58> was the item supposed to be checked, but wasn't?
BNE.S @HowAboutOtherMark ; <58> NE means it was other, so make the mark a diamond character
MOVE #checkMark,D1 ; <58> make the checked message really have a checked mark when fetching by name
BRA.S @CommonResName ; <58> branch down to the append a character code
@HowAboutOtherMark
CMP #kHMOtherItem,D7 ; <58> was it the 'other' item (modal dialog up - item message)
BNE.S @TitleCopied ; <58> means no, so branch to the common code
MOVE #diamondMark,D1 ; <58> for an item that appeared to be 'other' but had no mark, force the
; <58> mark to be a diamond.
BRA.S @CommonResName ; <58> and now go fetch the named resource
@InMenuItem
MOVE.L D4,-(SP) ; push the menuhandle
MOVE D0,-(SP) ; push the menu item were on
PEA fimItemString(A6) ; a place to put the item string
_GetItem ; get the item's string for the GetNamedResource
@TitleCopied
CMP #kHMEnabledItem,D7 ; was the item enabled?
BEQ.S @ResNameReady ; yes, the msg is ready as is
CMP #kHMDisabledItem,D7 ; was the item disabled?
BNE.S @ResNameNotDisabled ; no
MOVE.B #'!',D1 ; ! appended means that we want disabled msg
BRA.S @CommonResName ; go retrieve the resource named: "name!"
@ResNameNotDisabled
MOVE.L D4,-(SP) ; push the menu handle
MOVE fimItem(A6),-(SP) ; push the menu item number
PEA fimMarkChar(A6) ; push a place to put the mark character
_GetItmMark ; get it
MOVE fimMarkChar(A6),D1 ; <57> put the marked character in D1
@CommonResName
LEA fimItemString(A6),A0 ; get string address in A0
MOVEQ #0,D0 ; clear hi bits for add
MOVE.B (A0),D0 ; get string length
ADDQ #1,D0 ; add 1 for char to be appended ( *** watch for overflow!)
MOVE.B D0,(A0) ; update length byte in string
ADDA D0,A0 ; add in offset
MOVE.B D1,(A0) ; put the char in the length of string
@ResNameReady
SUBQ #4,SP ; room for resource
MOVE.L hmnuHelpData(A2),-(SP) ; push res type
PEA fimItemString(A6) ; get this named resource
_GetNamedResource ; get the resource handle
MOVE.L (SP)+,A0 ; A0 = resource handle
MOVE.L A0,D0 ; did we get it? (need for later too!)
BEQ @nohmnu ; no, exit!
CMP.L #'STR ',hmnuHelpData(A2) ; was it a 'plain' string resource type?
BEQ.S @WasStringHandle ; yes, go use it as is (we already fetched the resource)
MOVE.L D0,-(SP) ; push the resource handle
PEA fimResID(A6) ; VAR theID : INTEGER
PEA fimResType(A6) ; VAR theType : ResType
PEA fimItemString(A6) ; VAR name : STR255;
_GetResInfo ; get some info on the resource
CMP.L #'PICT',hmnuHelpData(A2) ; was it a PICT?
BNE.S @WasntPictResource ; no, try another type
MOVE #kHMPictItem,D6 ; say that it was a pict item and use the found res id
@quikMsgFiller
MOVE fimResID(A6),A3 ; put the (word) res ID in A3
BRA @Fillitin ; go show the balloon
@WasntPictResource
CMP.L #'STR#',hmnuHelpData(A2) ; was it a string list?
BEQ.S @WasStringListResource ; yes, do it
CMP.L #kHMTETextResType,hmnuHelpData(A2) ; was it a 'TEXT' resource
BEQ.S @WasTextHandleResource
CMP.L #kHMTEStyleResType,hmnuHelpData(A2) ; was it a 'styl' resource
BNE @UnknownHelpType ; branch outta here as we don't know what else it could be
@WasTextHandleResource
MOVE #kHMTEResItem,D6 ; say that it was a te resource item and use the found res id
BRA.S @quikMsgFiller ; branch to the res ID stuff for the 'PICT' item above and exit
@WasStringListResource
MOVE #kHMStringResItem,D6 ; say that it was a 'STR#' item and use it's resID
MOVE fimResID(A6),D0 ; get the res ID in D0
SWAP D0 ; put the resID in hiword of D0
MOVE #1,D0 ; always use the first string in the 'STR#' resource
MOVE.L D0,A3 ; put the long (resID & index)
BRA @Fillitin ; go show the balloon
@WasStringHandle
MOVE #kHMStringItem,D6 ; say that it was a pstring (not a 'STR ' resource)
MOVE.L (A0),A3 ; A3 -> string (the next routine copies the string data)
; i.e. no need to lock the handle…
BRA @Fillitin ; go show the balloon
@Calcthestringaddr
MOVEQ #0,D0 ; clear index
CMP #kHMEnabledItem,D7 ; is the item enabled?
BEQ.S @MessageReady ; yes, the msg is ready
ADD.B hmnuHelpData(A2),D0 ; add pstring length (no ADD.B carry prob cuz D0 was 0 at this point)
ADDQ #1,D0 ; plus 1 for the length byte
CMP #kHMDisabledItem,D7 ; was the item disabled?
BEQ.S @MessageReady ; yes, the msg is ready
MOVEQ #0,D1 ; clear MOVE.B adder
MOVE.B hmnuHelpData(A2,D0.W),D1 ; put in D1 for add (can't do a ADD.B here due to possible overflow)
ADD D1,D0 ; and add in the disabled pstring length
ADDQ #1,D0 ; plus 1 for the length byte
CMP #kHMCheckedItem,D7 ; was the item checked?
BEQ.S @MessageReady ; yes, the msg is ready
MOVE.B hmnuHelpData(A2,D0.W),D1 ; put in D1 for add
ADD D1,D0 ; no, add in the checked pstring length
ADDQ #1,D0 ; plus 1 for the length byte
; else, item must have been 'other', just fall thru
@MessageReady
LEA hmnuHelpData(A2,D0.W),A3 ; recompute the address of the message
TST.B (A3) ; was the string NIL?
BEQ @fetchhmnuMissingMsg ; yes, the message is zero, so fetch the missing message
@Fillitin
SUBQ #2,SP
MOVE D6,-(SP) ; push the help message type
MOVE.L A3,-(SP) ; push some info data to fill in
MOVE.L fimHelpMsg(A6),-(SP) ; push the help message record to fill in
JSR __HMFillInHelpMessage
MOVE (SP)+,D0 ; get result (always returns noErr for now)
@FillhmnuResult
MOVE D0,fimResult(A6) ; stuff the result
@nohmnu
MOVEM.L (SP)+,D2-D7/A2-A4 ; restore the regs
UNLK A6
MOVE.L (SP)+,A0
ADDA.L #fimParamSize,SP ; or LEA fimParamSize(SP),SP but this is slower
JMP (A0)
@skipBalloon
MOVE #hmBalloonAborted,D0 ; say that the result was hmBalloonAborted
BRA.S @FillhmnuResult ; and stuff it
@UnknownHelpType
MOVE #hmUnknownHelpType,D0 ; say that the result was of an unknown type
BRA.S @FillhmnuResult
@wronghmnuVersion
MOVE #hmWrongVersion,D0
BRA.S @FillhmnuResult
;
;
; GetPItemPtr
;
; Returns PItem Ptr in A0
;
; Pass pointer to menuhandle data in A4, item number to get in fimItem(A6)
;
; Smashes D0-D2,A0
;
GetPItemPtr MOVEQ #0,D2 ; clear an adder
MOVEQ #1,D1 ; start at menu item 1
MOVEQ #0,D0 ; clear offset
MOVE.B menudata(A4),D0 ; get menu title length byte
ADDQ #1,D0 ; plus 1 to skip (we always skip the title)
@morePItems
LEA menudata(A4,D0),A0 ; calculate the new menu item's start
CMP fimItem(A6),D1 ; see if this is the item we wanted
BEQ.S @ThisItem ; EQ means yes
MOVE.B (A0),D2 ; can't use ADD.B due to possible overflow (msg data > 255 bytes)
BEQ.S @NoAuxData ; EQ means that we went all the way to the end (corrupt data?)
ADD D2,D0 ; add that menu item's length to offset
ADD #1+4,D0 ; plus the length byte + size of trailing data
ADDQ #1,D1 ; bump the counter
BRA.S @morePItems ; loop 'til we're on it
@NoAuxData
MOVE.L #0,A0 ; clear the address if we couldn't find the item
@ThisItem
RTS ; return to caller
IF HelpMgrTesting THEN
DoDebugSymbols __HMFillInMenuMessage ; label for MacsBug
ENDIF
ENDP
;---------------------------------------------------------------------------------------------
;
; FUNCTION __HMFillInDialogMessage( resID,item,whichHelpItem,totalHelpItems,state,offset,resFile: INTEGER;
; VAR options: LongInt;
; VAR tip: Point; altRect: RectPtr;
; VAR theProc: INTEGER; VAR variant: INTEGER;
; VAR aHelpMsg: HMMessageRecord): OsErr;
;
__HMFillInDialogMessage PROC EXPORT
IMPORT __HMFillInHelpMessage
fidHelpMsg EQU 8 ; ptr to HMMessageRecord
fidVariant EQU fidHelpMsg+4 ; ptr to variant parameter
fidProc EQU fidVariant+4 ; ptr to variant parameter
fidHotRect EQU fidProc+4 ; ptr to tip parameter
fidTip EQU fidHotRect+4 ; ptr to HotRect parameter
fidOptions EQU fidTip+4 ; ptr to hdlg option longword
fidResFile EQU fidOptions+4 ; specified resource file to be searched
fidOffset EQU fidResFile+2 ; additional offset into DITL
fidState EQU fidOffset+2 ; dialog item state value
fidTotalHelpItems EQU fidState+2 ; how many help items are in current dialog
fidWhichHelpItem EQU fidTotalHelpItems+2 ; which help item are we scanning
fidItem EQU fidWhichHelpItem+2 ; which dialog item (aka which message)
fidResID EQU fidItem+2 ; using this help item's resource ID
fidParamSize EQU fidResID+2-8 ; # bytes params
fidResult EQU fidResID+2 ; return value
fidResInfoID EQU -2
fidResType EQU fidResInfoID-4
fidResName EQU fidResType-256
fidResHandle EQU fidResName-4
fidFirstTime EQU fidResHandle-4
fidLocalSize EQU fidFirstTime ; size of our locals
;
LINK A6,#fidLocalSize ; make a stack frame
MOVEM.L D3-D7/A2-A4,-(SP) ; save 'em
MOVE.W #resNotFound,fidResult(A6) ; set error result (message not found)
SUBQ #4,SP
MOVE.L #kHMDialogResType,-(SP) ; push the resource type, always 'hdlg'
MOVE.W fidResID(A6),-(SP) ; get this ID
CMP.W #-1,fidResFile(A6) ; <65> was the resource file specified -1?
BEQ.S @UseGetResource ; <65> EQ means yes so call GetResource()
; <65> else call Get1Resource()
_Get1Resource ; get the resource handle
BRA.S @GetResourceCalled ;
@UseGetResource
_GetResource ; get the resource handle
@GetResourceCalled
MOVE.L (SP)+,D0 ; D0 = 'hdlg' resource handle
BEQ @Nohdlg ; no handle, exit!
MOVE.L D0,A0 ; put in A0
MOVE.L (A0),A4 ; A4 -> 'hdlg' resource data
CMP #hmBalloonHelpVersion,hdlgVersion(A4) ; was the version of the resource correct?
BGT @wronghdlgVersion ; no, exit!
MOVE.L fidOptions(A6),A0 ; get the VAR options address
MOVE.L hdlgOptions(A4),(A0) ; return the options longword
CLR fidFirstTime(A6) ; clear the NIL & missing flag
MOVE.W hdlgCount(A4),D4 ; get 'hdlg' array count
BEQ @fetchhdlgMissingMsg ; if zero then fetch the missing message
ADD hdlgOffset(A4),D4 ; correct count to compensate for offset value in hdlg
ADD fidOffset(A6),D4 ; correct for any additional offset from ScanAppendHdlg
CMP fidItem(A6),D4 ; is the dialog item in range?
BLT.S @checkIfMissing ; no, see if we should satisfy the missing msg
MOVE D4,D0 ; make copy of last item count to look for
SUB fidItem(A6),D0 ; less the # of items in the resource
CMP hdlgCount(A4),D0 ; was the item in range for the resource?
BLE.S @fetchhdlgMsg ; yes, go get the message from the resource
BRA.S @timeToExit ; no, say that it was out of range and exit
@checkIfMissing
MOVE fidTotalHelpItems(A6),D0 ; get the count of how many help items were in dialog
BEQ.S @fetchhdlgMissingMsg ; if zero then just fetch the missing message
SUBQ #1,D0
BEQ.S @fetchhdlgMissingMsg ; also, if 1 then just fetch the missing message
MOVE fidWhichHelpItem(A6),D0 ; see what help item in the DITL resource were on
CMP fidTotalHelpItems(A6),D0 ; if it's the last help item then fetch the missing msg
BEQ.S @fetchhdlgMissingMsg ; otherwise just fall thru saying we didn't find a match
@timeToExit
MOVE #hmGetNextHelpItem,D0 ; tell the caller that we want a different hdlg
BRA @FillhdlgResult ; and stuff and exit
@fetchhdlgMsg
MOVEQ #1,D5 ; clear record array counter
ADD hdlgOffset(A4),D5 ; correct item # for offset into dialog template
ADD fidOffset(A6),D5 ; <58> oops! forgot to include the ScanAppendHdlg offset from DITL
; <58> to correct for any additional offset from ScanAppendHdlg
MOVEQ #hdlgHeaderSize,D3 ; skip header size
ADD hdlgMissingSize(A4),D3 ; skip over missing message
@morehdlgArray
LEA hdlgArray(A4,D3.L),A2 ; compute start of next array record
CMP fidItem(A6),D5 ; is this the index?
BEQ.S @foundtherecord ; yeah! this is the record we want, branch!
ADDQ #1,D5 ; index to next item
ADD hdlgHelpMsgSize(A2),D3 ; add the size of the message for next loop
BRA.S @morehdlgArray ; and go index to next array element
@fetchhdlgMissingMsg
TST fidFirstTime(A6)
BNE @skipBalloon ; exit if this is the 2nd time that we did this…
ADD #1,fidFirstTime(A6) ; set the flag word to say we've been here before
LEA hdlgMissingSize(A4),A2 ; compute missing msg beginning. At this point,
; every thing is the same as any other help array record,
; so fall thru.
@foundtherecord
;
; At this point:
; A2 -> array record (in resource)
;
; Now fill in VAR tip & VAR HotRect
;
MOVE hdlgHelpType(A2),D6 ; D6 = help message type
CMP #kHMSkipItem,D6 ; if it was skip then leave
BEQ @skipBalloon ; without displaying a Balloon (this includes missing msg)
MOVE.L fidProc(A6),A0
MOVE hdlgProcID(A4),(A0) ; put theProc in the VAR
MOVE.L fidVariant(A6),A0
MOVE hdlgVariant(A4),(A0) ; put variant in the VAR
MOVE.L fidTip(A6),A0 ; get the VAR tip address
MOVE.L hdlgTip(A2),(A0) ; put the HDialogArray record tip in
MOVE.L fidHotRect(A6),A0 ; copy over the HotRect coordinates
MOVE.L hdlgHotRect(A2),(A0)+ ; into the HotRect RectPtr
MOVE.L hdlgHotRect+4(A2),(A0) ; Note: always fill these parameters even if HMSkipItem
;
;
; This is the place to add extraction of new types of Help Messages.
;
; Unfortunately, you have to 'know' how each type is structured so that you can calculate
; the correct offset for disabled, checked, and other message starts.
;
; A2 = address of message data
; D6 = type of message
;
;
@ExtractTheMsg
MOVE fidState(A6),D7 ; put the enabled/disabled/checked flags in D7
CMP #kHMStringItem,D6 ; was it a string?
BEQ.S @Calcthestringaddr ; yes, now see if string enabled/disabled/etc.
MOVE D7,D0 ; copy the flags word
EXT.W D0 ; make it wordy
CMP #kHMStringResItem,D6 ; was it a string res ID?
BEQ.S @Copythelong ; yes, copy over the long sized info
CMP #kHMSkipItem,D6 ; is the item type >= skip?
BGE @UnknownHelpType ; if > then we don't know what this help msg was!
ASL.W #1, D0 ; * 2 for offset (one integer)
MOVE hdlgHelpData(A2,D0),A3 ; put in the integer message (resID)
MOVE.L hdlgOptions(A4),D0 ; get the options into D0
BTST #kBTSTUseSubID,D0 ; do we want to use the resource as a base for a sub ID?
BEQ @RegularResWord ; EQ means no, so, don't add the sub ID
ADD fidResID(A6),A3 ; make it a sub ID driven index
@RegularResWord
MOVE A3,D1
BEQ @fetchhdlgMissingMsg
BRA @Fillitin
@Copythelong
ASL.W #2, D0 ; * 4 for offset (one long)
MOVE.L hdlgHelpData(A2,D0),A3 ; put in the long (STR# resID & index)
MOVE.L A3,D1
MOVE.L hdlgOptions(A4),D0
BTST #kBTSTUseSubID,D0 ; do we want to use the resource as a base?
BEQ.S @RegularResLong
SWAP D1
ADD fidResID(A6),D1 ; add the sub ID driven index to hi word
SWAP D1
@RegularResLong
MOVE.L D1,A3 ; yuck, this sure is messy
TST D1 ; used to: TST.L to check entire word
BEQ @fetchhdlgMissingMsg
BRA.S @Fillitin
@Calcthestringaddr
MOVEQ #0,D0 ; make sure it's clear
CMP #kHMEnabledItem,D7 ; is the item enabled?
BEQ.S @MessageReady ; yes, the msg is ready
ADD.B hdlgHelpData(A2),D0 ; add pstring length (no ADD.B carry prob cuz D0 was 0 at this point)
ADDQ #1,D0 ; add in 1 for the length byte
CMP #kHMDisabledItem,D7 ; was the item disabled?
BEQ.S @MessageReady ; yes, the msg is ready
MOVEQ #0,D1 ; clear MOVE.B adder
MOVE.B hdlgHelpData(A2,D0.W),D1 ; no, skip over the disabled pstring length
ADD D1,D0 ; add it this way to watch overflow
ADDQ #1,D0 ; plus 1 for the length byte
CMP #kHMCheckedItem,D7 ; was the item checked?
BEQ.S @MessageReady ; yes, the msg is ready
MOVE.B hdlgHelpData(A2,D0.W),D1 ; no, add in the checked pstring length
ADD D1,D0 ; add it this way to watch overflow
ADDQ #1,D0 ; plus 1 for the length byte
; so, the item must have been 'other'
; just fall thru
@MessageReady
LEA hdlgHelpData(A2,D0.W),A3 ; compute the address of the message
TST.B (A3) ; was the string NIL?
BEQ.S @fetchhdlgMissingMsg ; yes, just go fetch missing message instead
@Fillitin
SUBQ #2,SP
MOVE D6,-(SP) ; push the help message type
MOVE.L A3,-(SP) ; push some info data to fill in
MOVE.L fidHelpMsg(A6),-(SP) ; push the help message record to fill in
JSR __HMFillInHelpMessage
MOVE (SP)+,D0 ; get result (always noErr for now)
@FillhdlgResult
MOVE D0,fidResult(A6) ; stuff result
@Nohdlg
MOVEM.L (SP)+,D3-D7/A2-A4 ; restore 'em
UNLK A6
MOVE.L (SP)+,A0
ADDA.L #fidParamSize,SP ; or LEA fidParamSize(SP),SP
JMP (A0)
IF HelpMgrTesting THEN
DoDebugSymbols __HMFillInDialogMessage ; label for MacsBug
ENDIF
@skipBalloon
MOVE #hmSkippedBalloon,D0 ; say that the result was a skip
BRA.S @FillhdlgResult ; and stuff and exit
@UnknownHelpType
MOVE #hmUnknownHelpType,D0 ; say that the result was of an unknown message type
BRA.S @FillhdlgResult ; and stuff and exit
@wronghdlgVersion
MOVE #hmWrongVersion,D0 ; say that the result was a skip
BRA.S @FillhdlgResult ; and stuff and exit
ENDP
;---------------------------------------------------------------------------------------------
;
;
; FUNCTION __HMFillInHelpMessage(helpType: INTEGER; info: Ptr;
; VAR aHelpMsg: HMMessageRecord): OsErr;
;
; Enter with helpType and info to be stuffed into the message record
;
__HMFillInHelpMessage PROC EXPORT
SaveRegs REG A2 ; Save these registers
resultsStackFrame
theResult ds.w 1 ; the resulting OsErr part code
parametersStackFrame
theHelpType ds.w 1 ; the type of help message record we're filling out
theInfo ds.l 1 ; ptr to the data to stuff into the msg rec
theMessage ds.l 1 ; the VAR message record we're stuffing
endStackFrame
linkSave SaveRegs ; make a stack frame
MOVE #noErr,theResult(A6) ; set error result (*** always noErr for now)
MOVE.L theMessage(A6),A2 ; this is the ptr to the help record
MOVE theHelpType(A6),D0 ; this is the help type
CMP #kHMStringItem,D0 ; was it a string?
BEQ.S @Copythestring ; copy all of the string bytes + len
CMP #kHMStringResItem,D0 ; was it a string res ID?
BEQ.S @Copythelong ; yes, copy over the long info
; else copy the integer
MOVE theInfo+2(A6),hmmHelpMessage(A2) ; this is integer (not ptr) data
BRA.S @StuffMsgType
@Copythelong
MOVE.L theInfo(A6),hmmHelpMessage(A2) ; stuff the data into the message record
@StuffMsgType
MOVE theHelpType(A6),D0 ; get the Help msg type and stuff it in msg
BRA.S @Yikes
@Copythestring
LEA hmmHelpMessage(A2),A1 ; put the data in the hmmHelpMessage area
MOVE.L theInfo(A6),A0 ; copy all of the data of the string
MOVEQ #0,D0 ; oops! watch out for odd addressing when
MOVE.B (A0),D0 ; copying strings (we used to DBRA loop)!
ADDQ #1,D0 ; includes the length byte too
_BlockMove ; copy string to buffer
MOVE #khmmString,D0 ; say that it was a STR255 type msg
@Yikes
MOVE D0,hmmHelpType(A2) ; stuff the help msg type in message record
restoreUnlinkReturn
IF HelpMgrTesting THEN
DoDebugSymbols __HMFillInHelpMessage ; label for MacsBug
ENDIF
ENDP
;---------------------------------------------------------------------------------------------
;
;
; FUNCTION __HMFillCitationString(origString,stuffString : StringPtr; key: Char) : OsErr;
;
; Searches the origString string for a ^Key char and stuffs the stuffString
;
; Unfortunately, I have no idea how to do this 'internationally'! If you have an idea,
; speak up (and modify the code if you wish).
;
; Returns non-zero if string overflowed
;
__HMFillCitationString PROC EXPORT
SaveRegs REG D3-D6/A2 ; Save these registers
resultsStackFrame
result ds.w 1 ; the resulting INTEGER part code
parametersStackFrame
origString ds.l 1 ; ptr to original string to be searched and stuffed
stuffString ds.l 1 ; ptr to string to stuff into original string
key ds.w 1 ; the citation key to search and stuff at
localsStackFrame
workString ds.w 128 ; space for a STR255 work area
endStackFrame
linkSave SaveRegs ; make a stack frame and save some registers
MOVE #noErr,result(A6) ; assume noErr
@CheckForMoreCarets
MOVE.L origString(A6),A2 ; A2-> string beginning (len byte)
MOVEQ #0,D3 ; clear some hibits
MOVE.B (A2),D3 ; get length
BEQ @ExitFCS ; exit if original string was zero <SM3> CSS
MOVE.B #'^',D0 ; look for citation caret character
LEA 1(A2),A1 ; A1 -> string data
MOVE.L D3,D1 ; D1 = length byte
@ScanMore
CMP.B (A1)+,D0 ; walk string until ^ is found
BEQ.S @FoundCaret ; EQ means we found it
@NotRightKey
SUBQ #1,D1 ; less 1 in string char counter
BNE.S @ScanMore ; if still >0 then there are more chars
; *** someday use a DBRA loop here
BRA.S @ExitFCS ; if EQ then exit w/o doing anything
@FoundCaret
MOVE.B (A1),D2 ; get ^X key
CMP.B key+1(A6),D2 ; was X the key we wanted?
BNE.S @NotRightKey ; no, go check some more characters
;
; OK, we found key
;
LEA 1(A1),A0 ; point just past ^X chars
LEA workString(A6),A1 ; put the sub string in our local space
MOVE.L D3,D5 ; get the original length byte in D5
SUB D1,D5 ; less how many we counted
; this is the offset past string start
MOVE.L D1,D0 ; get the size in D0
MOVE D1,D6 ; D6 has how many to copy to local area
_BlockMove
LEA 1(A2,D5),A1 ; copy the stuff string here
MOVE.L stuffString(A6),A0 ; A0-> to stuff string
MOVE.B (A0)+,D0 ; get the stuff's length
MOVE.L D0,D4 ; save for later
_BlockMove
LEA workString(A6),A0 ; get the working string area for the copy back
ADD D4,D5 ; make offset past the string just stuffed
LEA 1(A2,D5),A1 ; plus it's length byte
MOVE D6,D0 ; restore the working string's length back
_BlockMove ; copy the end back over
ADD D4,D3 ; now, fix up the string's length byte
SUBQ #2,D3 ; less the space taken up by the ^X chars
MOVE.B D3,(A2) ; fill it in
AND #$0F00,D3 ; did we overflow the length byte?
BNE.S @OverflowedLen ; NE means yes, so, max out string and exit
BRA.S @CheckForMoreCarets ; loop until we've filled all ^X carets
@OverflowedLen
MOVE.B #$FF,(A2) ; max out the string
MOVE #1,result(A6) ; return w/ non-zero result
@ExitFCS
restoreUnlinkReturn
IF HelpMgrTesting THEN
DoDebugSymbols FillCitationString ; label for MacsBug
ENDIF
ENDP
;---------------------------------------------------------------------------------------------
;
;
; FUNCTION __HMCallCustomWDEFCalc(v: INTEGER; w: WindowPtr): INTEGER;
;
; This routine calls the WDEF proc in w window to calculate
; the content and structure regions of the window so that we can save the bits behind
; those regions.
;
__HMCallCustomWDEFCalc PROC EXPORT
resultsStackFrame
theResult ds.w 1 ; the resulting INTEGER part code
parametersStackFrame
theVarCode ds.w 1 ; the variant for the window
theWindow ds.l 1 ; the window being calculated
endStackFrame
linkSave ; make a stack frame
SUBQ #4,SP ; make room for WDEF function result
MOVE.W theVarCode(A6),-(SP) ; push variant
MOVE.L theWindow(A6),A0 ; get the window in A0
MOVE.L A0,-(SP) ; push window pointer
MOVE.W #wCalcRgnMsg,-(SP) ; push the message (we want to calc rgns)
CLR.L -(SP) ; NIL param
MOVE.L WindowDef(A0),A0 ; get proc handle
TST.L (A0) ; has the proc been purged?
BNE.S @1 ; if we got it, skip
MOVE.L A0,D0 ; clean the handle (historical)
_StripAddress ; clean the pointer
MOVE.L D0,-(SP) ; better reload the proc
_LoadResource ; via the resource manager
TST.L (A0) ; did we get it this time?
BNE.S @1 ; yup, keep going
MOVE.W #WDEFnFnd,D0 ; get error code <C949/08Nov87> DAF
_SysError ; and croak <C949/08Nov87> DAF
@1
_HLock ; lock the proc handle <C424/18Nov86> DAF
MOVE.L (A0),A0 ; get the proc pointer <C424/18Nov86> DAF
JSR (A0) ; call it
MOVE.L theWindow(A6),A0
MOVE.L WindowDef(A0),A0 ; get the proc handle <C424/18Nov86> DAF
_HUnlock ; free the defproc <C424/18Nov86> DAF
MOVE.W (SP)+,theResult(A6) ; return the result <48> RLC fixed from MOVE.L
restoreUnlinkReturn
IF HelpMgrTesting THEN
DoDebugSymbols __HMCallCustomWDEFCalc ; label for MacsBug
ENDIF
ENDP
;---------------------------------------------------------------------------------------------
;
;
; FUNCTION __HMGetRealWindowHitResult(p: Point; w: WindowPtr): INTEGER;
;
;
__HMGetRealWindowHitResult PROC EXPORT
resultsStackFrame
theResult ds.w 1 ; the resulting INTEGER part code
parametersStackFrame
thePoint ds.l 1 ; the hit point for the window
theWindow ds.l 1 ; the window being hit
endStackFrame
linkSave ; make a stack frame
SUBQ #2,SP ; leave space for variant
MOVE.L theWindow(A6),-(SP) ; push window pointer
_GetWVariant ; get variant code
MOVE (SP)+,D0 ; put in D0
SUBQ #4,SP ; make room for WDEF function result
MOVE.W D0,-(SP)
MOVE.L theWindow(A6),A0 ; get window ptr in A0
MOVE.L A0,-(SP) ; push window pointer
MOVE #WHitMsg,-(SP) ; say that we want a 'hit the window' result
MOVE.L thePoint(A6),-(SP) ; for this point
MOVE.L WindowDef(A0),A0 ; get proc handle
TST.L (A0) ; has the proc been purged?
BNE.S @inMemory ; if we got it, skip
MOVE.L A0,D0 ; clean the handle (historical)
_StripAddress ; clean the pointer
MOVE.L D0,-(SP) ; better reload the proc
_LoadResource ; via the resource manager
TST.L (A0) ; did we get it this time?
BNE.S @inMemory ; yup, keep going
MOVE.W #WDEFnFnd,D0 ; get error code <C949/08Nov87> DAF
_SysError ; and croak <C949/08Nov87> DAF
@inMemory
_HLock ; lock the proc handle <C424/18Nov86> DAF
MOVE.L (A0),A0 ; get the proc pointer <C424/18Nov86> DAF
JSR (A0) ; call it (trashes A0)
MOVE.L theWindow(A6),A0
MOVE.L WindowDef(A0),A0 ; get the proc handle <C424/18Nov86> DAF
_HUnlock ; free the defproc <C424/18Nov86> DAF
MOVE.L (SP)+,D0 ; get the reply
ADDQ #2,D0 ; convert to FindWindow results
MOVE D0,theResult(A6) ; return the result
restoreUnlinkReturn
IF HelpMgrTesting THEN
DoDebugSymbols __HMGetRealWindowHitResult ; label for MacsBug
ENDIF
ENDP
;---------------------------------------------------------------------------------------------
;
;
; PROCEDURE __HMTwitchVarCode(isVariantToRBS: BOOLEAN; FromValue: INTEGER; VAR ToValue: INTEGER);
;
; Destroys pascal register conventions
;
__HMTwitchVarCode PROC EXPORT
cvToValue EQU 8 ; result (ToValue) address
cvFromValue EQU cvToValue+4 ; which variant or RBS
cvIsVToRBS EQU cvFromValue+2 ; flag for direction
cvParamSize EQU cvIsVToRBS+2-8 ; # of bytes of parameters
LINK A6,#0 ; make a stack frame
TST.B cvIsVToRBS(A6)
BEQ.S @wasRBS2Variant
LEA VariantTable,A0 ; point to the variant table
BRA.S @TwitchTime
@wasRBS2Variant
LEA RBSTable,A0
@TwitchTime
MOVE.W cvFromValue(A6),D0 ; get the index in D0
MOVEQ #0,D1
MOVE.B (A0,D0.W),D1
MOVE.L cvToValue(A6),A1 ; get the VAR address for return value
MOVE.W D1,(A1) ; put the table value in the VAR
UNLK A6
MOVE.L (SP)+,A0 ; pop return address
ADDA.L #cvParamSize,SP ; pop params
JMP (A0) ; return to caller
IF HelpMgrTesting THEN
DoDebugSymbols __HMTwitchVarCode ; label for MacsBug
ENDIF
VariantTable
DC.B 6 ; variant 0's RBS Value
DC.B 7 ; variant 1's RBS Value
DC.B 3 ; variant 2's RBS Value
DC.B 2 ; variant 3's RBS Value
DC.B 0 ; variant 4's RBS Value
DC.B 1 ; variant 5's RBS Value
DC.B 5 ; variant 6's RBS Value
DC.B 4 ; variant 7's RBS Value
RBSTable
DC.B 4 ; RBS = 0's variant #
DC.B 5 ; RBS = 1's variant #
DC.B 3 ; RBS = 2's variant #
DC.B 2 ; RBS = 3's variant #
DC.B 7 ; RBS = 4's variant #
DC.B 6 ; RBS = 5's variant #
DC.B 0 ; RBS = 6's variant #
DC.B 1 ; RBS = 7's variant #
ENDP
;---------------------------------------------------------------------------------------------
;
;
; PROCEDURE __HMVarCodeToBiasRecord(varCode: INTEGER; VAR bias: biasRecord);
;
; You MUST pass a varCode between 0 and 7, else die
;
; biasRecord = Record
; hShift : INTEGER;
; vShift : INTEGER;
; hCornerVector : INTEGER;
; vCornerVector : INTEGER;
; hBaseVector : INTEGER;
; vBaseVector : INTEGER;
; END;
;
; Destroys pascal register conventions
;
__HMVarCodeToBiasRecord PROC EXPORT
parametersStackFrame
varCode ds.w 1 ; the varCode to lookup
bias ds.l 1 ; the address of the bias Record
endStackFrame
linkSave ; make a stack frame
lea biasTable,a0
move.w varCode(a6),d0 ; get the index in d0
muls #12,d0 ; shift to get table address
add.w d0,a0 ; make a0 point to the bias record data
move.l bias(A6),a1 ; get the VAR address of bias record in a1
move.l (a0)+,(a1)+ ; copy the data (6 words or 3 longs of data)
move.l (a0)+,(a1)+
move.l (a0)+,(a1)+
restoreUnlinkReturn
IF HelpMgrTesting THEN
DoDebugSymbols __HMVarCodeToBiasRecord ; label for MacsBug
ENDIF
;
; Shift CornerVector BaseVector
; ----- ------------ ----------
biasTable
DC.W 0,-1, -1,0, 1,1 ; variant 0's bias record
DC.W -1,0, 0,-1, 1,1 ; variant 1's bias record
DC.W 1,0, 0,-1, -1,1 ; variant 2's bias record
DC.W 0,-1, 1,0, -1,1 ; variant 3's bias record
DC.W 0,1, 1,0, -1,-1 ; variant 4's bias record
DC.W 1,0, 0,1, -1,-1 ; variant 5's bias record
DC.W -1,0, 0,1, 1,-1 ; variant 6's bias record
DC.W 0,1, -1,0, 1,-1 ; variant 7's bias record
ENDP
;---------------------------------------------------------------------------------------------
;
;
; FUNCTION __HMGetHelpMenuHandle(VAR mh: MenuHandle): OsErr;
;
;
__HMGetHelpMenuHandle PROC EXPORT
SaveRegs REG D4-D5/A2 ; we need these registers saved
resultsStackFrame
result ds.w 1 ; the resulting state word
parametersStackFrame
menuHandle ds.l 1 ; the menu handle to examine
endStackFrame
linkSave SaveRegs
MOVE #hmHelpManagerNotInited,result(A6) ; setup result first
MOVE.L MenuList,D4 ; get the menulist handle
MOVE.L $286,MenuList ; point to the system menulist handle
SUBQ #4,SP ; make some space
MOVE.W #kHMHelpMenuID,-(SP) ; get our help menu in system menulist
_GetMHandle ; get it from the list in MenuList lomem global
MOVE.L (SP)+,D5 ; put it in D5 for later
MOVE.L D4,MenuList ; restore the menulist handle
MOVE.L menuHandle(A6),A2 ; get address of menuhandle VAR in A2
SUBQ #4,SP ; make some space
MOVE.W #kHMHelpMenuID,-(SP) ; get our help menu in application menulist
_GetMHandle ; get it from the list in MenuList lomem global
MOVE.L (SP)+,(A2) ; pop it into the VAR
MOVE #noErr,result(A6) ; return noErr if NE below
CMP.L (A2),D5 ; was the menu in menulist = our global system menu?
BNE.S @GetHelpMHExit ; no, just return the menu in menulist
;
; OK, some application is going to much w/ appending items to the help menu
;
MOVE.L D5,A0 ; make a copy of our global system menu
_HandToHand
MOVE D0,result(A6) ; save off memError result from HandToHand
BNE.S @GetHelpMHExit ; if <>noErr then exit now
; A0 = handle to copy of system menu data
MOVE.L MenuList,A1 ; Get the menulist
MOVE.L (A1),A1 ; dereference
MOVEQ #0,D1
MOVE.W lastMenu(A1),D1 ; count how many menus
@loop
CMP.L menuOH(A1,D1.W),D5 ; is this the place of the menu to stuff
BEQ.S @foundIt
SUBQ #6,D1 ; move to next menu offset
BNE.S @loop ; loop until we find it
MOVE #paramErr,result(A6) ; return error if not in menu list
BRA.S @GetHelpMHExit ; AckWeDidntFindIt!
@foundIt
MOVE.L A0,menuOH(A1,D1.W) ; Slam in the new handle (ugly, but functional)
; and, since this is the first time,
; append a dash to the menu
MOVE.L A0,(A2) ; and return the menu handle in VAR
MOVE.L A0,-(SP) ; push the just made copy to the system menu
PEA DashAddr ; '-' to be appended
_AppendMenu
@GetHelpMHExit
restoreUnlinkReturn
IF HelpMgrTesting THEN
DoDebugSymbols __HMGetHelpMenuHandle ; label for MacsBug
ENDIF
STRING PASCAL
DashAddr DC.B '-' ; this is the text for a dash
ALIGN 2
STRING ASIS
ENDP ; __HMGetHelpMenuHandle
;---------------------------------------------------------------------------------------------
;
;
; PROCEDURE __HMSetGetFontSizeGlobal(setit: INTEGER; VAR fontsize: LongInt);
;
; Gets or Sets the help mgr font in the script mgr globals
;
; set = 1 to set, 0 to get fontsize longword
;
__HMSetGetFontSizeGlobal PROC EXPORT
MOVE.L (SP)+,D2 ; return address
MOVE.L (SP)+,A1 ; VAR fontsize LongInt
WITH SmgrRecord,ScriptRecord
MOVE.L IntlSpec,A0
MOVE smgrSysScript(A0),D0
LSL.W #2,D0
MOVE.L smgrEntry(A0,D0.W),A0
;
; Now we have ScriptRecord pointer in A0
;
MOVE (SP)+,D0 ; set it flag
BEQ.S @wasGetFontSize ; EQ means that we're getting the global
MOVE.L (A1),scriptHelpFondSize(A0)
BRA.S @sgfExit
@wasGetFontSize
MOVE.L scriptHelpFondSize(A0),(A1) ; puts font in hiword, size in loword
@sgfExit
MOVE.L D2,A0 ; put return address in A0
JMP (A0) ; return to caller
ENDP
;---------------------------------------------------------------------------------------------
;
;
; FUNCTION __HMGetMenuItemStatus(mh: MenuHandle; flags: LongInt;
; item: INTEGER): INTEGER;
;
; returns: kHMEnabledItem, kHMDisabledItem, kHMCheckedItem, kHMOtherItem
;
; Follows pascal register trashing conventions
;
__HMGetMenuItemStatus FUNC EXPORT
resultsStackFrame
result ds.w 1 ; the resulting state word
parametersStackFrame
mh ds.l 1 ; the menu handle to examine
flags ds.l 1 ; the menu handle's flags
item ds.w 1 ; which item's state to get
localsStackFrame
markChar ds.w 1 ; a place to put the GetItemMark character
endStackFrame
linkSave
MOVE.W #kHMDisabledItem,result(A6) ; make the default kHMDisabledItem
MOVE.L flags(A6),D1 ; get menu flags
BTST #0,D1 ; is the whole menu disabled?
BEQ.S @GMIDone ; EQ means yes, so exit w/ default condition
MOVE.W item(A6),D0 ; get item (title, if zero)
BNE.S @WasItem
BTST D0,D1 ; test the bit
BEQ.S @GMIDone ; EQ means the title was disabled, so we're done
MOVE.W #kHMEnabledItem,result(A6) ; else make it kHMEnabledItem
BRA.S @GMIDone
@WasItem
CMPI.W #31,D0 ; is the item > 31 ?
BHI.S @CheckMarkChar ; yes, so item must be enabled
BTST D0,D1 ; test the bit
BEQ.S @GMIDone ; EQ means the item or title was disabled
@CheckMarkChar
MOVE #kHMEnabledItem,result(A6) ; make it enabled (assembles to: CLR result(A6))
CLR markChar(A6) ; zero hi bits
MOVE.L mh(A6),-(SP) ; push the menu handle
MOVE.W item(A6),-(SP) ; and the item
PEA markChar(A6) ; put any marking character here
_GetItmMark
CMP #noMark,markChar(A6) ; was the menu item not marked?
BEQ.S @GMIDone ; yes, we're done
CMP #checkMark,markChar(A6) ; was it a checkmark?
BNE.S @MakeOther ; NE means no, so it must be an 'other' mark
MOVE.W #kHMCheckedItem,result(A6) ; say that it was kHMCheckedItem
BRA.S @GMIDone ; we're done
@MakeOther
MOVE.W #kHMOtherItem,result(A6) ; say that it was kHMOtherItem
@GMIDone
restoreUnlinkReturn
IF HelpMgrTesting THEN
DoDebugSymbols __HMGetMenuItemStatus ; label for MacsBug
ENDIF
ENDP
;--------------------------------------------------------------------------------------------
;
;
; PROCEDURE __HMGetTextFontStuff(VAR theFont: INTEGER; VAR theSize: INTEGER);
;
__HMGetTextFontStuff PROC EXPORT
SaveRegs REG A0-A1 ; some registers to save
parametersStackFrame
theFont ds.l 1 ; the font of the port font
theSize ds.l 1 ; the size of the port font
endStackFrame
linkSave SaveRegs
MOVE.L GrafGlobals(A5),A0
MOVE.L thePort(A0),A0 ; get the port in A0
MOVE.L theFont(A6),A1
MOVE.W txFont(A0),(A1)
MOVE.L theSize(A6),A1
MOVE.W txSize(A0),(A1)
restoreUnlinkReturn
ENDP
;--------------------------------------------------------------------------------------------
;
; FUNCTION __HMInvalidateSavedBits(window: WindowPtr): OsErr;
;
__HMInvalidateSavedBits PROC EXPORT
resultsStackFrame
result ds.w 1 ; the resulting OsErr (ignored)
parametersStackFrame
theWindow ds.l 1 ; the window from which painting happened
endStackFrame
linkSave
move.l theWindow(a6),d0 ; get the window ptr in d0
beq.s @noWindow ; if NIL, exit
move.l ExpandMem,a0 ; point to the expand mem ptr
move.l ExpandMemRec.emHelpGlobals(a0),a0 ; A0 = global ptr
move.l hmgSavedBitsHandle(a0),d0 ; do we have any bits to toss?
beq.s @noWindow ; nope, just exit
move.l hmgWindow(a0),d1 ; if no balloon up then don't toss balloon bits
beq.s @noWindow ; if NIL then PaintOne was called for under us
cmp.l theWindow(a6),d1 ; was it our balloon window?
beq.S @noWindow ; yes, ignore balloon window
move.l a0,-(SP)
subq #2,sp ; make some room
move.l d0,-(sp) ; push handle to the bits (maybe its a handle)
_DiscardBits ; call FUNCTION DiscardBits(bits: SavedBits): OSErr;
tst (sp)+ ; toss result
move.l (sp)+,a0
clr.l hmgSavedBitsHandle(a0) ; say that the bits were tossed
@noWindow
restoreUnlinkReturn
IF HelpMgrTesting THEN
DoDebugSymbols __HMInvalidateSavedBits ; label for MacsBug
ENDIF
ENDP
;--------------------------------------------------------------------------------------------
;
; FUNCTION __HMSaveBitsInRect(theRect: Rect): PixMapHandle;
;
__HMSaveBitsInRect PROC EXPORT
resultsStackFrame
pmHandle ds.l 1 ; the resulting pixmap handle
parametersStackFrame
theRect ds.l 1 ; the rectangle of bits to save
endStackFrame
linkSave
subq #2,sp ; make room for error result
move.l theRect(A6),-(SP)
moveq #1,d0 ; <69> lets allow purging (TRUE)
move.b d0,-(sp) ; <69> and pass this to SaveBits()
pea pmHandle(A6)
_SaveBits
tst.w (SP)+ ; ignore error, cuz if it failed then
; appropriate update events will be generated
restoreUnlinkReturn
endproc
;---------------------------------------------------------------------------------------------
;
; PROCEDURE __HMRestoreBitsToRect(thePM: PixMapHandle);
;
;
__HMRestoreBitsToRect PROC EXPORT
MOVE.L (SP)+,A0 ; return address
MOVE.L (SP)+,D0 ; pixmap handle if any
MOVE.L A0,-(SP) ; put return address back on stack
SUBQ #2,SP ; room for result
MOVE.L D0,-(SP) ; push pixmap handle or whatever is here
_RestoreBits
ADDQ.L #2,SP ; ignore result as we just don't care if it worked
RTS ; return to caller
ENDP
;---------------------------------------------------------------------------------------------
;
;
; FUNCTION __HMShiftKey: BOOLEAN; ; we need this code for pascal
;
__HMShiftKey PROC EXPORT
MOVE.L (SP)+,A0 ; get the return address
CLR.W (SP) ; clear the result
BTST #0,KeyMap+7 ; get state of shift key
BEQ.S @notdown
ADDQ.B #1,(SP) ; set the result
@notdown
JMP (A0)
ENDP
;---------------------------------------------------------------------------------------------
;
;
; PROCEDURE __HMStuffWindowInfo(window: WindowPtr; varCode: INTEGER; bounds: Rect);
;
__HMStuffWindowInfo PROC EXPORT
parametersStackFrame
window ds.l 1 ; the window to setup
varCode ds.w 1 ; the window's new varCode
bounds ds.l 1 ; the window's new bounds rectangle
endStackFrame
linkSave a3 ; <59> use a3 for windowptr register
move.l window(a6),a3 ; <59> get window ptr in a1
cmpi.w #$3FFF, ROM85 ; <59> do we have color quickdraw?
bgt.s @useWindowDefProc ; <59> bug in 7.0b3q3 called _GetAuxWin on B & W machines
subq #6,sp ; leave room for result and boolean
move.l a3,-(sp) ; push the windowPtr
pea 6(sp) ; point to the result space
_GetAuxWin ; get the window's auxRec
tst.b (sp)+ ; flush the boolean
beq.s @noAuxRec ; false means no real AuxWinHdl, only the default one
move.l (sp)+,a1 ; get the auxRec handle
move.l (a1),a1 ; get the auxRec ptr
lea awFlags(a1),a1 ; <59> setup the place to stuff the new varcode in a1
bra.s @stuffTheVariant ; <59> branch to the stuffer routine
@noAuxRec
addq #4, sp ; blast handle returned, we don't want it
@useWindowDefProc
lea WindowDef(a3),a1 ; <59> put the pointer to the variant in a1
@stuffTheVariant
move.w varCode(a6),d0 ; <59> get the varCode param in d0 for stuff
andi.w #$000f,d0 ; <59> toss any inappropriate variants (range: [0..15])
move.b d0, (a1) ; <59> set the variant by stuffin it
move.l bounds(a6),a1 ; get the bounds in a1
move.l a3,-(sp) ; <59> push the window, already was in a3
move.l topLeft(a1),-(sp) ; push the topLeft coord point
move.b #0,-(sp) ; select the window (why not?)
_MoveWindow ; move the window
move.l a3,-(sp) ; <59> push the window, already was in a3
move.l bounds(a6),a1 ; get the bounds in a1 again
move.w right(a1),d0 ; get the bounds.right in d0
sub.w left(a1),d0 ; sub bounds.left to get the width
move.w d0,-(sp) ; push the new width of the window
move.w bottom(a1),d0 ; get the bounds.bottom in d0
sub.w top(a1),d0 ; sub bounds.top to get the height
move.w d0,-(sp) ; push the new height of the window
move.b #0,-(sp) ; generate any update events, in case window is visible
_SizeWindow ; resize the window
restoreUnlinkReturn
endproc
;
;
; PROCEDURE __HMStripNullFromProcessName(s: StringPtr);
;
__HMStripNullFromProcessName PROC EXPORT ; <66> add this entire routine
move.l 4(sp),d0 ; <66> string ptr, if any
beq.s @stripExit ; <66> exit now if string ptr was NIL
@lookAgain
move.l d0,a1 ; <66> put a copy of the string ptr in a1
moveq #0,d1 ; <66> clear some hi bits
move.b (a1),d1
beq.s @stripExit
move.b 1(a1),d1 ; <66> check 1st character of string
bne.s @stripExit ; <66> oh, the 1st character wasn't NULL, so exit!
move.b (a1),d1 ; <66> get length byte of string
subq #1,d1 ; <66> make it less 1 so we can toss the NULL char
move.b d1,(a1) ; <66> stuff the new length byte into the pstring
beq.s @stripExit
subq #1,d1 ; <66> set the loop counter to copy chars of the string over
lea 1(a1),a0 ; <66> calculate the destination address of the char copy
lea 2(a1),a1 ; <66> calculate the starting address of the char copy
@moveEveryByte
move.b (a1)+,(a0)+ ; <66> now copy the pstring characters, one byte at a time
dbra d1,@moveEveryByte ; <66> loop until all characters have been copied
bra.s @lookAgain ; <66> now branch to beginning to see if any additional NULLs are in string
@stripExit
move.l (sp)+,a0
addq #4,sp
jmp (a0) ; <66> return to caller
endproc
END