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

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

3530 lines
132 KiB
Plaintext

;__________________________________________________________________________________________________
; 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 couldnÕt 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