;__________________________________________________________________________________________________ ; 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): ; ; 10/22/92 CSS Change some branch short instructions to word branches. ; <72> 5/14/92 KST #1027497 : #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 #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 #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 #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 Change include of BalloonPACKEqu to BalloonsPriv.a. ; <62> 1/14/91 RLC 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 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 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 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 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 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 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 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 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 ... @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 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 DAF _SysError ; and croak DAF @1 _HLock ; lock the proc handle DAF MOVE.L (A0),A0 ; get the proc pointer DAF JSR (A0) ; call it MOVE.L theWindow(A6),A0 MOVE.L WindowDef(A0),A0 ; get the proc handle DAF _HUnlock ; free the defproc 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 DAF _SysError ; and croak DAF @inMemory _HLock ; lock the proc handle DAF MOVE.L (A0),A0 ; get the proc pointer DAF JSR (A0) ; call it (trashes A0) MOVE.L theWindow(A6),A0 MOVE.L WindowDef(A0),A0 ; get the proc handle DAF _HUnlock ; free the defproc 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