mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-29 20:49:19 +00:00
3481 lines
114 KiB
OpenEdge ABL
3481 lines
114 KiB
OpenEdge ABL
{__________________________________________________________________________________________________
|
||
File: BalloonPACK.p
|
||
|
||
Contains: Pascal support routines for _Pack14 (HelpMgr)
|
||
|
||
Written by: Randy Carr
|
||
|
||
Copyright: © 1989-1992 by Apple Computer, Inc., all rights reserved.
|
||
|
||
Change History (most recent first):
|
||
|
||
<SM3> 2/17/93 kc Allocate pictures in the System Heap because they persist longer
|
||
than the application heap.
|
||
<81> 6/2/92 KST #1030643 <JH>: We have only 1 default message for the floating
|
||
window instead of two (floating windows are all active).
|
||
<80> 5/14/92 KST #1027497 <JH>: #1025797,#1027497: In '__HMGetWindowPartCode',
|
||
defined 2 new window parts when mouse is over a floating window.
|
||
Provided default message so that Balloon help can work when
|
||
mouse is over a floating window.
|
||
<79> 4/23/92 JH #1027497,<YK>: CubeE adds a IMlayer for use by floating windows
|
||
that input windows need. Unfortunately, the Help mgr doesn't
|
||
know anything about this new layer. So I'm changing
|
||
__HMGetWindowPartCode to call the TSM call FindServiceWindow
|
||
before calling FindWindow. If FindServiceWindow returns a part
|
||
code in a real window we use GetParent to find IMlayer. Swap
|
||
that layer in, let the help mgr do its thing, and then swap the
|
||
old layer back.
|
||
<78> 4/4/92 csd #1017165,<BBM>: In HMShowWindowPartBalloon, set the port to the
|
||
BalloonWindow before calling ReplaceText since ReplaceText uses
|
||
the current port’s font and script information.
|
||
<77> 3/23/92 JSM OSEvents.p is obsolete, use Events.p.
|
||
<76> 11/21/91 csd #83334: Used a single string with ReplaceText instead a two
|
||
strings with Concat to build "This window belongs to the
|
||
application “xxx”. To make this window active, click in it."
|
||
<75> 11/3/91 KSM In theFuture, we should not arbitrarily limit the size of
|
||
balloons (per Randy).
|
||
<74> 4/1/91 RLC vl, #85955- FIx bug that wasn't respecting current process when
|
||
tracking dialogs that contain a help item in the DITL handle.
|
||
<73> 3/19/91 RLC ksm,#BH-TCA-0083 - FIx bug that wasn't passing window method
|
||
parameter to HMShowBalloon() for 'hdlg' & 'hrct' resources.
|
||
<72> 3/13/91 RLC ksm,#84586 - Change reset of help msgs using a text edit handle
|
||
that are passed to HMShowBalloon to force the text edit handle
|
||
to the help mgr font.
|
||
<71> 2/20/91 RLC ksm,#BBSLostItsMind - Add a bracket back in that somehow got
|
||
left out of a comment in the HMSelectBestVariant routine.
|
||
<70> 2/20/91 RLC ksm,#82854 - Add a check in HMScanTemplateItems that makes sure
|
||
that the window we're examining is a dialog if the type if
|
||
kHMDialogResType. The call to FindDItem in HMSameItemState can
|
||
otherwise be made on a non-Dialog window (i.e. Crash!).
|
||
<69> 2/19/91 RLC ksm,#81544 Fix balloon positioner to make sure all variants are
|
||
tried when initial variant does not fit. This fixes the clipped
|
||
balloon for Empty Trash and KeyCaps. GO5 approved.
|
||
<68> 2/8/91 RLC <ksm> #82161 Add a call to strip the null character from the
|
||
processes that are desk accessories. This causes text edit to
|
||
word break the process name leaving beginning and ending quotes
|
||
on different lines of the balloon. <BHTCA0080> = force grayed
|
||
controls to get the HMDisabled state in all cases.
|
||
<67> 1/24/91 RLC <gbm> #81591 Change __HMFillInDialogMessage() calls to pass the
|
||
resource file refnum from HMScanTemplateItems(). Those routines
|
||
will call GetResource() for file refnum<>-1 otherwise call
|
||
Get1Resource() [which means specifically search a resource file
|
||
for a help resource]. Also changed occurrances of hmmPic to
|
||
hmmPict as per Scott Boyd's changes to Balloons.p.
|
||
<66> 1/22/91 RLC <dc> #81592 Fix bug that leaves a balloon up if the mouse
|
||
moves from a system tracked balloon to the menubar and remove
|
||
the extraneous tip parameter from HMShowTitleBalloon() routine.
|
||
<65> 1/10/91 RLC <stb> Change the code for HMTrackModalItems and
|
||
HMScanTemplateItems to not set the hmgLastItem and
|
||
hmgLastItemState when the 'hdlg' resource that we're tracking
|
||
returns a hmSkippedBalloon for an item's message. This makes
|
||
sure that the 'hdlg' resource indicated by the HMSetDialogResID
|
||
setting gets checked in case the resource comes later in the
|
||
resource map.
|
||
<64> 1/10/91 RLC <ksm> Fix __HMPinTipAndAltRect routine to do the right thing if
|
||
tip is outside screenbounds and after correction is still
|
||
outside altRect.
|
||
<63> 12/17/90 RLC <ksm> Change HMSetBalloons to always remove the balloon before
|
||
disposing of the layer when balloon help is turned off else we
|
||
risk orphaning the balloon window in a non-existent layer.
|
||
<62> 12/14/90 RLC <ngk> Add check to __HMShowWindowPartBalloon so that unhilited
|
||
windows that are behind a movable modal get the right balloon.
|
||
(i.e. you can switch to another layer, but you cannot bring an
|
||
inactive window to the front) Remove HMNewBestWorld conditional
|
||
and the older positioning code that was excluded by it. Change
|
||
giant case statement into table driven HMVarCodeToBias() asm
|
||
routine (saves 238 bytes). Changed kHMFinderOnly to
|
||
kHMActiveApplOther to support menu items in Process menu that
|
||
are marked. Make HMCountDITLHelpItems external so that Standard
|
||
file can call it from the private interface.
|
||
<61> 12/14/90 dba <JDR> get rid of LongIntPtr, now in Types.p
|
||
<60> 12/3/90 RLC <ksm> Add check to __HMShowWindowPartBalloon so that unhilited
|
||
windows that are behind a movable modal get the right balloon.
|
||
(i.e. you can switch to another layer, but you cannot bring an
|
||
inactive window to the front.
|
||
<59> 11/16/90 RLC <ksm> Always call HMFillInMenuMessage when a modal dialog is up
|
||
so that the disabled AppleMenu items get the right help string.
|
||
Fix bug that would not clear the pic VAR if HMCalculateBalloon
|
||
was called too frequently and not enough time elapsed. Roll in
|
||
new HMBestWorld calculation to fix all those agonizing balloons
|
||
that hang offscreen bugs. The new routine is simpler, smaller,
|
||
and tries more ways to get the balloon to fit.
|
||
<58> 10/4/90 RLC <ksm> Fix mem leak that wasn't always disposing of the picture
|
||
handles. The bug was that if the mouse was moving quickly
|
||
enough to cause HMCalculateBalloon to abort its calculation,
|
||
HMCalculateBalloon would return hmBalloonAborted, but with a
|
||
valid picHandle. In this case, the caller must dispose of
|
||
the picture by calling KillPicture. Remove references to
|
||
hmgContentWindow and hmgOurBalloon variables as these were
|
||
internal to the .a code of which is now calling the external
|
||
routine HMScanTemplateItems. Fixed bug in HMScanTemplate that
|
||
wasn't obeying the hmAbsoluteCoords option in the resource.
|
||
Change code that handles picture resources or picHandles when
|
||
showing a balloon: we don't copy the picture data, we just use
|
||
the pic as is and stuff it in the windowPic field. Call
|
||
DisposeWindow instead of CloseWindow for custom balloon winds.
|
||
<57> 9/30/90 RLC Change hits in the 'inGrow' message of a window to be
|
||
'inContent'. Reduce more redundant code in TrackModalHelp
|
||
routines by consolidating some code into:__HMSameItemState (this
|
||
saved >370 bytes).
|
||
<56> 9/26/90 RLC Make a change to the automatically generated window part
|
||
balloons to allow non-front windows that are hilighted to get
|
||
'front window' balloons. (This will allow windoids and other
|
||
palette windows that respect the window record's hilited boolean
|
||
to work correctly).
|
||
<55> 9/25/90 RLC Consolidate by having HMExtractHelpMsg call HMGetIndHelpMsg
|
||
instead of having separate (duplicate) code (saves >370 bytes).
|
||
Change HMShowMenuBalloon call to only call HMRemoveBalloon if a
|
||
new balloon is about to be displayed and add a call to
|
||
HMRemoveBalloon if HMSavedBits… is called.
|
||
<54> 9/21/90 RLC Add code to the HMGetBalloons toggle to create both help window
|
||
and layer when the flag goes true and tear down the window &
|
||
layer for false. This means that the help layer won't be
|
||
burdening the window list hierarchy unless balloon help is on.
|
||
<53> 9/16/90 RLC (KSM also) Utilize itemReserved longword in HMShowMenuBalloon
|
||
routine to draw that string instead of fetching a help message
|
||
from the 'hmnu' resource.
|
||
<52> 9/15/90 RLC Repair positioner code in HMBestWorld that was calculating
|
||
balloon tip position incorrectly for balloons that failed to fit
|
||
on screen after 2 re-fits.
|
||
<51> 9/13/90 RLC Change references to our global handle (HMGlobalHandle) into
|
||
references to a global ptr (HMGlobalPtr), rename all routines
|
||
in this package to have __HM in front so that Balloons.p can
|
||
be part of uses statement, remove all multiple derefs to use
|
||
a single with as we don't have to worry about relocation of
|
||
handle's ptr.
|
||
<50> 8/31/90 RLC Remove duplicate and extraneous equates.
|
||
<49> 8/20/90 RLC Fix offscreen balloons bug that allows a balloon to hang off the
|
||
edge.
|
||
<48> 8/20/90 RLC Repair Philip's merge of the old file.
|
||
<46> 7/17/90 RLC Fix HMExtract calling conventions & styled text edit balloon
|
||
bugs.
|
||
<45> 7/16/90 RLC Change format of Styled-Text edit.
|
||
<44> 7/13/90 RLC Just about every interface routine got changed. Improved speed
|
||
of WDEF calc routines. Shortened code for everything. Made
|
||
multiple helpItems in dialogs work, fixed offset as well.
|
||
<43> 7/6/90 RLC Repair skip items in modal dialog to really be skipped instead
|
||
of always removing balloons.
|
||
<42> 7/5/90 RLC Fix multiple 'hdlg' occurrances.
|
||
<41> 7/2/90 RLC Some short changes
|
||
<40> 6/19/90 RLC More correction in variant central.
|
||
<39> 6/18/90 RLC Repair pinning algo again & add variant sensitivity/
|
||
<38> 6/14/90 RLC Include BalloonDefs.p for HMGlobalRecord.
|
||
<37> 6/8/90 KSM Update for new IsFrontWindowModal.
|
||
<36> 6/7/90 RLC Optimize a bit, fix misc positioning bugs.
|
||
<35> 6/5/90 RLC Fix HMSetDialogResID & system menu title balloon tip.
|
||
<34> 6/1/90 RLC Update global record
|
||
<33> 5/31/90 RLC Fix possible address error for 68K machines in HMShowBalloon.
|
||
<32> 5/29/90 RLC Add support routines for new HMGetHelpMenu selector.
|
||
<31> 5/4/90 RLC Patches CONST changes.
|
||
<30> 5/3/90 RLC Fix bugs in modal dialog balloons, launching, etc.
|
||
<29> 4/19/90 RLC Add scriptmgr help font & size to HMSet & HMGet font calls.
|
||
<28> 4/17/90 RLC Add reference to new utility routine: HMFillCitationString.
|
||
<27> 4/10/90 KSM New constants for system menu patch.
|
||
<26> 4/5/90 RLC Add support for the 'hovr' resource.
|
||
<25> 4/3/90 RLC Fix Modal Dialog tracking
|
||
<24> 4/2/90 RLC Reconnect HMSetDialogResID & HMSetMenuResID.
|
||
<23> 3/30/90 RLC Make sure MF rect is in line with MultiFinder.
|
||
<23> 3/28/90 RLC Add support for appends to the help menu.
|
||
<21> 3/26/90 RLC Fix global lasts for menus AND saveBits options.
|
||
<20> 3/22/90 RLC Remove hardcoded strings except for testing.
|
||
<19> 3/19/90 RLC Bug Fixes galore (58881 thru 62272).
|
||
<18> 3/15/90 RLC Fix all error return codes, abort remove if point is in our help
|
||
balloon.
|
||
<17> 3/7/90 RLC Fix the pt not in current layer stuff.
|
||
<16> 2/23/90 RLC Repair HMSetMenuResID for Pascal3.1 & add other layer support.
|
||
<15> 2/22/90 dnf Per RLC's instructions: Comment out code in HMSetMenuResID
|
||
Function
|
||
<14> 2/8/90 RLC Fix scanning of window parts to always return the correct
|
||
windowpart balloon.
|
||
<13> 2/7/90 RLC Add in change to respect tip & hotRect parameters in 'hdlg'
|
||
resources.
|
||
<12> 2/5/90 RLC Add support for delay in balloon drawing.
|
||
<11> 1/31/90 RLC Revise HMGlobalRecord again.
|
||
<10> 1/26/90 RLC Increase Performance.
|
||
<9> 1/26/90 RLC Update hmgGlobalRecord and support for a modal condition
|
||
(again).
|
||
<8> 1/25/90 RLC Change shape of Balloon look.
|
||
<7> 1/19/90 RLC Update selectors and error codes.
|
||
<6> 1/11/90 RLC Change mechanism for controlling how system balloons appear.
|
||
<5> 1/9/90 RLC Add support for new resource format.
|
||
<4> 1/3/90 RLC Fix to remove balloons in a modal dialog case where the mouse
|
||
leaves the dialog.
|
||
<3> 1/3/90 RC Change hdlgSaveBits option to only save bits if on.
|
||
<2> 12/20/89 RC Add change to support Menu title balloons better.
|
||
<4.1> 12/15/89 RLC Added TipProc, theProc, & variant support.
|
||
<4.0> 12/6/89 RLC Tweak tip when horizontal balloon crosses hotRect.
|
||
<3.9> 12/1/89 RLC Fix HMScanTemplate routine check to see if dialog is a modal
|
||
dialog before setting flag.
|
||
<3.8> 11/30/89 RLC Fixed bug in HMTrackTemplate code that couldn't handle HMSkip
|
||
types & updated HMGlobalsRecord
|
||
<3.7> 11/21/89 RLC Temp fix for bug in _DrawPicture & remember to TEDispose the
|
||
TENew.
|
||
<3.6> 11/20/89 RLC Update routines that find the helpItem parameter in a 'DITL'
|
||
template handle.
|
||
<3.5> 11/16/89 RLC Change parameter interface to HMTrackTemplateHelpItems.
|
||
<3.4> 11/15/89 RLC Change 'hdlg' support to correctly handle local offsets.
|
||
<3.3> 11/13/89 RLC Changed dialog tracking routines, window parts tracker.
|
||
<3.2> 11/9/89 RLC Fix bug in window part balloons for grow box.
|
||
<3.1> 11/7/89 RLC Add support for window parts tracking.
|
||
<3.0> 11/2/89 RLC Removed all non-PACK14 routines.
|
||
<2.9> 10/27/89 RLC Fix bug when displaying khmmPict and PicHandle types that didn't
|
||
set origin correctly.
|
||
<2.8> 10/1/89 RLC Added new routine HMGetStyledTE & Updated HMBalloonRect for
|
||
HelpMsg types: StyledTE & STR.
|
||
<2.7> 9/28/89 RLC Fixed bug that didn't correct the Balloon tip if on GDevice
|
||
monitors.
|
||
<2.6> 9/27/89 RLC Fixed positioner for Balloons in ModalDialogs.
|
||
<2.5> 9/25/89 RLC Added more support for MultiFinder appl icon.
|
||
<2.4> 9/22/89 RLC Fixed bug in HMGetGDevice & potential dangling pointer bug in
|
||
HMSaveBalloonBits
|
||
<2.3> 9/21/89 RLC Changed Balloon WDEF ID to 126.
|
||
<2.2> 9/21/89 RLC Added better error checking on message passing to HMBalloonRect
|
||
& HMCalcBalloon routines.
|
||
<2.1> 9/20/89 RLC Bug Fixes, change hmnu scanning routines to make sure
|
||
HMSkipItems never display balloons.
|
||
<2.0> 9/19/89 RLC Bug Fix in ShowMenuTitle.
|
||
<1.9> 9/19/89 RLC Added support for Multifinder Balloons.
|
||
<1.8> 9/18/89 RLC Dialog Template scan routines changed.
|
||
<1.7> 9/15/89 RLC Changed Modal Dialog Tracking to use PopupMenu instead of ICON.'
|
||
<1.6> 9/15/89 RLC Changed Debuggers to Assert calls.
|
||
<1.5> 9/13/89 RLC Repaired Balloon Calculation routines, made MenuTitle Balloons
|
||
better.
|
||
<1.4> 8/29/89 RLC Changed HMCalc & Changed all Balloon routines to use new calling
|
||
convention.
|
||
8/22/89 RCarr Rewrite nearly every interface!
|
||
<1.3> 8/10/89 RLC Added code for autocontents & added patch to _InitWindows
|
||
8/8/89 RCarr Optimize by preallocating Help Layer @ _InitWindows time, fix
|
||
bug that was calling _KillPicture twice when calling
|
||
_DisposeWindow.
|
||
7/31/89 RCarr Added support for autocontents patches for help mgr.
|
||
<1.2> 7/20/89 RLC Added patchcode to support help menu & move HMBalloonRect from C
|
||
to Pascal.
|
||
7/20/89 RCarr Added tons of support stuff & Help Menu
|
||
<1.1> 7/13/89 RLC Add HMBalloonRect to pack
|
||
<1.0> 6/29/89 RLC Created Today.
|
||
5/22/89 RCarr New Today!
|
||
__________________________________________________________________________________________________}
|
||
|
||
|
||
{$ifc UNDEFINED HelpMgrTesting}
|
||
{$setc HelpMgrTesting = false}
|
||
{$endc}
|
||
|
||
|
||
{$setc AllowCloseViewChanges = false}
|
||
|
||
{$ifc HelpMgrTesting}
|
||
{$D+}
|
||
{$INIT+}
|
||
{$elsec}
|
||
{$D-}
|
||
{$INIT-}
|
||
{$endc}
|
||
|
||
UNIT BalloonPack;
|
||
|
||
INTERFACE
|
||
|
||
USES
|
||
Types, QuickDraw, ToolUtils, Fonts, Events, Controls,
|
||
Windows, Dialogs, Files, Menus, Desk, Traps, OSUtils, GestaltEqu,
|
||
Resources, Memory, Packages, FixMath, Errors, Layers, Processes, MFPrivate, MenuMgrPriv, DialogsPriv, Balloons,
|
||
TextServices; {<79>}
|
||
|
||
CONST
|
||
{ Start of internal CONST }
|
||
|
||
hmGetNextHelpItem = -873;
|
||
hmWasAppleMenu = -874;
|
||
|
||
{System STR# resource indexes}
|
||
kHMMenuTitleIndex = 1;
|
||
kHMAboutHelpIndex = 2;
|
||
kHMAboutHelpDisabled = 3;
|
||
kHMReserved = 4;
|
||
kHMWhatIsHide = 5;
|
||
kHMInDragIndex = 6;
|
||
kHMInGrowIndex = 7;
|
||
kHMInGoAwayIndex = 8;
|
||
kHMInZoomIndex = 9;
|
||
kHMMultiFinderIndex = 10;
|
||
kHMInScrollBar = 11;
|
||
kHMInDisabledScrollBar = 12;
|
||
kHMInOtherWindow = 13;
|
||
kHMInLayerPreamble = 14;
|
||
kHMInLayerBody = 15;
|
||
kHMOutsideModalWindow = 16;
|
||
kHMAppleMenuTitle = 17;
|
||
kHMShowHideEnabled = 18;
|
||
kHMHideOthersEnabled = 19;
|
||
kHMShowAllEnabled = 20;
|
||
kHMShowHideDisabled = 21;
|
||
kHMHideOthersDisabled = 22;
|
||
kHMShowAllDisabled = 23;
|
||
kHMEasy1Access = 24;
|
||
kHMEasy2Access = 25;
|
||
kHMEasy3Access = 26;
|
||
kHMActiveApplEnabled = 27;
|
||
kHMActiveApplDisabled = 28;
|
||
kHMActiveApplChecked = 29;
|
||
kHMActiveApplOther = 30;
|
||
kHMActiveApplDisabledTitle = 31;
|
||
kHMActiveApplDisabledItem = 32;
|
||
kHMInFrontFloatingWindow = 33; { for IM, mouse is over a floating window }
|
||
|
||
|
||
|
||
kHMDelayTix = 5;
|
||
|
||
{Dialog item template type}
|
||
kHelpItem = 1;
|
||
|
||
{Dialog item template offsets}
|
||
kHelpItemType = 1; {new, allows the helpItem to contain more than just a resID}
|
||
kHelpItemData = 3; {offset in HelpItem array item in DITL to read ResID}
|
||
kHelpItemOffset = 5; {offset to reach overriding append offset for hdlg}
|
||
|
||
{helpItem type constants}
|
||
kScanhdlg = 1;
|
||
kScanhrct = 2;
|
||
kScanAppendhdlg = 8; { <58> for some reason, this was a 3 in previous, sync up w/ Types.r }
|
||
|
||
|
||
{ internal balloon creation consts (Tweak these values until we die) }
|
||
DicksOffsetPixels = 9; {was 9+3 for Dick's design}
|
||
HMMenuOffsetPixels = 8;
|
||
kHMFrameThickness = 6;
|
||
|
||
kHMVertContentMargin = 13;
|
||
kHMHorizContentMargin = 13;
|
||
kHMScreenBorder = 20;
|
||
kHMCornerDiameter = 16;
|
||
kHMPointerSize = 18;
|
||
kHMBottomMargin = 50;
|
||
|
||
kHMShadowThickness = 2;
|
||
|
||
kHMVertFrameMargin = (kHMPointerSize + (kHMShadowThickness * 4));
|
||
kHMHorizFrameMargin = (kHMPointerSize + (kHMShadowThickness * 4));
|
||
|
||
kHMMiscMargin = 5;
|
||
|
||
maxTETextArea = 50 * 340; {50 lines @ 340 pixels/line}
|
||
MBarHeight = $BAA;
|
||
UnImplementedTrap = $9F;
|
||
|
||
wasWindow = 0;
|
||
wasMenu = 1;
|
||
|
||
kTitleType = 1;
|
||
kDialogType = 2;
|
||
kMenuType = 3;
|
||
kRectType = 4;
|
||
kEAType = 5;
|
||
kWindPartType = 6;
|
||
|
||
{hmgMenuID flag values}
|
||
kwasMultiFinder = -2;
|
||
kwasWindowPart = -3;
|
||
kwasMenuTitle = -4;
|
||
kwasCleared = -5;
|
||
kwasEasyAccess = -6;
|
||
|
||
kGetFont = 0;
|
||
kSetFont = 1;
|
||
|
||
kVariantToRBS = true;
|
||
kRBSToVariant = false;
|
||
|
||
kShiftBit = 0;
|
||
kBottomBit = 1;
|
||
kRightBit = 2;
|
||
|
||
TYPE
|
||
EventRecPtr = ^EventRecord;
|
||
|
||
RBSRecord = Packed RECORD { this is it boys! }
|
||
CASE INTEGER OF
|
||
0: (
|
||
Filler1 : 0..8191;
|
||
rightValue : 0..1; { if 1 then balloon is hanging right }
|
||
bottomValue : 0..1; { if 1 then balloon is hanging down }
|
||
shiftValue : 0..1; { if 1 then balloon has vertical tip }
|
||
);
|
||
1: (
|
||
Whole : INTEGER;
|
||
);
|
||
END;
|
||
|
||
biasRecord = Packed RECORD
|
||
hShift : INTEGER;
|
||
vShift : INTEGER;
|
||
hCornerVector : INTEGER;
|
||
vCornerVector : INTEGER;
|
||
hBaseVector : INTEGER;
|
||
vBaseVector : INTEGER;
|
||
END;
|
||
|
||
|
||
{$I BalloonDefs.p}
|
||
|
||
|
||
FUNCTION __HMShowBalloon(aHelpMsg: HMMessageRecord;
|
||
tip: Point;
|
||
alternateRect: RectPtr;
|
||
tipProc: Ptr;
|
||
theProc,variant: INTEGER;
|
||
method: INTEGER): OsErr;
|
||
FUNCTION __HMRemoveBalloon: OsErr;
|
||
FUNCTION __HMGetBalloons: BOOLEAN;
|
||
FUNCTION __HMSetBalloons(flag: BOOLEAN): OsErr;
|
||
FUNCTION __HMShowMenuBalloon(itemNum,itemMenuID: INTEGER;
|
||
itemFlags,itemReserved: LongInt;
|
||
tip: Point; alternateRect: RectPtr; tipProc: Ptr;
|
||
theProc,variant: INTEGER): OsErr;
|
||
FUNCTION __HMIsBalloon: BOOLEAN;
|
||
FUNCTION __HMSetFont(font: INTEGER): OsErr;
|
||
FUNCTION __HMSetFontSize(fontSize: INTEGER): OsErr;
|
||
FUNCTION __HMGetFont(VAR font: INTEGER): OsErr;
|
||
FUNCTION __HMGetFontSize(VAR fontSize: INTEGER): OsErr;
|
||
FUNCTION __HMSetDialogResID(theResID: INTEGER): OsErr;
|
||
FUNCTION __HMGetDialogResID(VAR theResID: INTEGER): OsErr;
|
||
FUNCTION __HMSetMenuResID(theMenuID,theResID: INTEGER): OsErr;
|
||
FUNCTION __HMGetMenuResID(theMenuID: INTEGER; VAR theResID: INTEGER): OsErr;
|
||
FUNCTION __HMBalloonRect(aHelpMsg: HMMessageRecord; VAR coolRect: Rect): OsErr;
|
||
FUNCTION __HMBalloonPict(aHelpMsg: HMMessageRecord; VAR coolPict: PicHandle): OsErr;
|
||
FUNCTION __HMScanTemplateItems(whichID,whichResFile: INTEGER; whichType: ResType): OsErr;
|
||
FUNCTION __HMGetBalloonWindow(VAR window: WindowPtr): OsErr;
|
||
|
||
{private calls}
|
||
FUNCTION __HMCountDITLHelpItems(d: DialogPtr): INTEGER;
|
||
FUNCTION __HMModalDialogMenuSetup(ModalDialogComingUp: BOOLEAN): OsErr;
|
||
FUNCTION __HMTrackModalHelpItems: OsErr; { tracks items in modal dialogs and alerts }
|
||
|
||
FUNCTION __HMDrawBalloonFrame(rgn: RgnHandle): OsErr;
|
||
FUNCTION __HMSetupBalloonRgns( varCode: INTEGER;
|
||
VAR structRgn: RgnHandle;
|
||
VAR contentRgn: RgnHandle;
|
||
VAR bounds: Rect): OsErr;
|
||
|
||
PROCEDURE __HMShowEasyAccessBalloon;
|
||
PROCEDURE __HMShowTitleBalloon(menuID: INTEGER; flags: LongInt);
|
||
FUNCTION __HMShowContentBalloon(tip: Point; alternateRect: Rect;
|
||
theProc,variant: INTEGER;
|
||
aHelpMsg: HMMessageRecord; options: LongInt): OsErr;
|
||
|
||
FUNCTION __HMGetWindowPartCode(VAR window: WindowPtr): INTEGER;
|
||
FUNCTION __HMShowWindowPartBalloon(window: WindowPtr; windowCode: INTEGER): BOOLEAN;
|
||
FUNCTION __HMFillFrontProcessString(s: StringPtr): OsErr;
|
||
FUNCTION __HMExtractHelpMsg(whichType: ResType;
|
||
whichResID, whichMsg, whichState: INTEGER;
|
||
VAR aHelpMsg: HMMessageRecord): OsErr;
|
||
|
||
|
||
IMPLEMENTATION
|
||
|
||
|
||
FUNCTION __HMGetScreenGDevice(pt: Point): GDHandle; FORWARD;
|
||
FUNCTION __HMSaveBalloonBits(aHelpMsg: HMMessageRecord;
|
||
tip: Point;
|
||
alternateRect: RectPtr;
|
||
tipProc: Ptr;
|
||
variant: INTEGER;
|
||
balloonType: INTEGER): OsErr; FORWARD;
|
||
FUNCTION __HMCalculateBalloon( aHelpMsg: HMMessageRecord;
|
||
tip: Point;
|
||
alternateRect: RectPtr;
|
||
VAR varCode: INTEGER;
|
||
VAR bounds: Rect; VAR pic: PicHandle;
|
||
balloonType: INTEGER;
|
||
abortable: BOOLEAN): OsErr; FORWARD;
|
||
|
||
PROCEDURE __HMTwitchVarCode(isVariantToRBS: BOOLEAN;
|
||
FromValue: INTEGER; VAR ToValue: INTEGER); EXTERNAL;
|
||
PROCEDURE __HMVarCodeToBiasRecord(varCode: INTEGER; VAR bias: biasRecord); EXTERNAL;
|
||
FUNCTION __HMSlopMouse(tip: Point): BOOLEAN; EXTERNAL;
|
||
FUNCTION __HMCallTipProc(tipProc: Ptr;
|
||
tip: Point;
|
||
structure: RgnHandle;
|
||
VAR bounds: Rect;
|
||
VAR varCode: INTEGER): OsErr; EXTERNAL;
|
||
PROCEDURE __HMSetGetFontSizeGlobal(setit: INTEGER; VAR fontsize: LongInt); EXTERNAL;
|
||
FUNCTION __HMSaveBitsInRect(theRect: Rect): PixMapHandle; EXTERNAL;
|
||
PROCEDURE __HMRestoreBitsToRect(thePM: PixMapHandle); EXTERNAL;
|
||
FUNCTION __HMFillCitationString(origString,stuffString: StringPtr;
|
||
key: Char) : OsErr; EXTERNAL;
|
||
FUNCTION __HMCallCustomWDEFCalc(v: INTEGER; w: WindowPtr): INTEGER; EXTERNAL;
|
||
|
||
FUNCTION __HMGetIndHelpMsg(whichType: ResType;
|
||
whichResID, whichMsg, whichState: INTEGER;
|
||
VAR options: LongInt;
|
||
VAR tip: Point;
|
||
altRect: RectPtr;
|
||
VAR theProc: INTEGER; VAR variant: INTEGER;
|
||
VAR aHelpMsg: HMMessageRecord;
|
||
VAR count: INTEGER): OsErr; EXTERNAL;
|
||
FUNCTION __HMBalloonBulk: OsErr; EXTERNAL;
|
||
FUNCTION __HMFillInMenuMessage(menuID,item,resID: INTEGER; flags: LongInt;
|
||
VAR variant: INTEGER;
|
||
VAR aHelpMsg: HMMessageRecord): OsErr; EXTERNAL;
|
||
|
||
FUNCTION __HMFillInDialogMessage( resID,item,whichHelpItem,
|
||
totalHelpItems,state,offset: INTEGER;
|
||
resFile: INTEGER;
|
||
VAR options: LongInt;
|
||
VAR tip: Point; altRect: RectPtr;
|
||
VAR theProc: INTEGER; VAR variant: INTEGER;
|
||
VAR aHelpMsg: HMMessageRecord): OsErr; EXTERNAL;
|
||
|
||
FUNCTION __HMScanHRCTResource(whichWindow: WindowPtr; whichResID: INTEGER; whichPt: Point;
|
||
VAR whichMsg: INTEGER): OsErr; EXTERNAL;
|
||
|
||
FUNCTION __HMGetMenuItemStatus(mh: MenuHandle; flags: LongInt;
|
||
item: INTEGER): INTEGER; EXTERNAL;
|
||
|
||
FUNCTION __HMGetHelpGlobal: HMGlobalPtr; EXTERNAL;
|
||
FUNCTION __HMGetRealWindowHitResult(p: Point; w: WindowPtr): INTEGER; EXTERNAL;
|
||
FUNCTION __HMGetGlobalMouse: Point; EXTERNAL;
|
||
PROCEDURE __HMGetTextFontStuff(VAR theFont: INTEGER; VAR theSize: INTEGER); EXTERNAL;
|
||
FUNCTION __HMShiftKey: BOOLEAN; EXTERNAL;
|
||
PROCEDURE __HMStuffWindowInfo(window: WindowPtr; varCode: INTEGER; bounds: Rect); EXTERNAL;
|
||
PROCEDURE __HMStripNullFromProcessName(s: StringPtr); EXTERNAL;
|
||
|
||
|
||
|
||
{$ifc HelpMgrTesting}
|
||
PROCEDURE Assert(b: BOOLEAN; s: STR255);
|
||
BEGIN
|
||
if b then DebugStr(s);
|
||
END;
|
||
{$endc}
|
||
|
||
PROCEDURE __HMDisposeRgn(r: RgnHandle);
|
||
BEGIN
|
||
if r<>NIL then
|
||
DisposeRgn(r);
|
||
END;
|
||
|
||
FUNCTION __HMCanPictureBeKilled(kind: INTEGER): BOOLEAN; { <59> Code saver }
|
||
BEGIN
|
||
__HMCanPictureBeKilled := (kind <> khmmPict) and (kind <> khmmPictHandle);
|
||
END;
|
||
|
||
FUNCTION __HMIsThisAModalDialog: BOOLEAN;
|
||
VAR class : INTEGER;
|
||
BEGIN
|
||
__HMIsThisAModalDialog := false;
|
||
if GetFrontWindowModalClass(class) = noErr then
|
||
__HMIsThisAModalDialog := (class = dBoxProc);
|
||
END;
|
||
|
||
FUNCTION __HMFillFrontProcessString(s: StringPtr): OsErr;
|
||
VAR PSN : ProcessSerialNumber;
|
||
info : ProcessInfoRec;
|
||
result : OsErr;
|
||
BEGIN
|
||
result := GetFrontProcess(PSN);
|
||
|
||
if result=noErr then
|
||
begin
|
||
with info do
|
||
begin
|
||
processInfoLength := Sizeof(ProcessInfoRec);
|
||
processName := s;
|
||
processAppSpec := NIL;
|
||
end;
|
||
result := GetProcessInformation(PSN,info);
|
||
end;
|
||
|
||
__HMFillFrontProcessString := result;
|
||
END;
|
||
|
||
|
||
FUNCTION __HMGetStyledHandleResource( textRect: Rect;
|
||
textResType: ResType;
|
||
textID: INTEGER): TEHandle;
|
||
VAR hTE : TEHandle;
|
||
hStyl : Handle;
|
||
hText : Handle;
|
||
BEGIN
|
||
__HMGetStyledHandleResource := NIL; { assume that we didn't get it }
|
||
if LongInt(textResType) = LongInt(kHMTETextResType) then
|
||
begin
|
||
hTE := TEStylNew(textRect,textRect);
|
||
if hTE<>NIL then
|
||
begin
|
||
hText := GetResource(kHMTETextResType,textID); { we hope this is purgeable! }
|
||
|
||
if hText<>NIL then { set up the TEHandle w the char data }
|
||
begin
|
||
hStyl := GetResource(kHMTEStyleResType,textID);
|
||
|
||
HLock(hText);
|
||
TESetText(Ptr(hText^),GetHandleSize(hText),hTE);
|
||
HUnlock(hText);
|
||
|
||
if hStyl<>NIL then
|
||
SetStylScrap(0,$7FF,stScrpHandle(hStyl),false,hTE);
|
||
end else
|
||
begin
|
||
if hTE<>NIL then
|
||
TEDispose(hTE);
|
||
hTE := NIL;
|
||
end;
|
||
end;
|
||
__HMGetStyledHandleResource := hTE;
|
||
end;
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMBalloonPict(aHelpMsg: HMMessageRecord; VAR coolPict: PicHandle): OsErr;
|
||
VAR tip : Point;
|
||
bounds : Rect;
|
||
varCode : INTEGER;
|
||
BEGIN
|
||
LongInt(tip) := 0;
|
||
varCode := 0;
|
||
__HMBalloonPict := __HMCalculateBalloon(aHelpMsg,tip,NIL,
|
||
varCode,bounds,coolPict,wasWindow,false {can't abort balloon if mouse is moving});
|
||
END;
|
||
|
||
|
||
FUNCTION __HMBalloonRect(aHelpMsg: HMMessageRecord; VAR coolRect: Rect): OsErr;
|
||
VAR aTE : TEHandle;
|
||
fInfo : FontInfo;
|
||
lineHeight : LongInt;
|
||
ph : PicHandle;
|
||
textH : Handle;
|
||
textArea : LongInt;
|
||
ht,wd : LongInt;
|
||
numLines : LongInt;
|
||
r,rp : LongInt;
|
||
tempstr : STR255;
|
||
tempRect : Rect;
|
||
result : INTEGER;
|
||
resizeAble : BOOLEAN;
|
||
tempFont : INTEGER;
|
||
tempSize : INTEGER;
|
||
|
||
|
||
FUNCTION FastSQRT(val: LongInt): LongInt;
|
||
BEGIN
|
||
FastSQRT := BSR(FracSqrt(Fract(val)),15);
|
||
|
||
{ in C: FastSQRT = (long) FracSqrt((Fract)val) >> 15;}
|
||
END;
|
||
|
||
PROCEDURE ResizeTE(teh: TEHandle; width, height: INTEGER);
|
||
VAR ter : Rect;
|
||
BEGIN
|
||
with teh^^ do
|
||
begin
|
||
ter := destRect;
|
||
with ter do
|
||
begin
|
||
bottom := top + height;
|
||
right := left + width;
|
||
end;
|
||
destRect := ter;
|
||
viewRect := ter;
|
||
end;
|
||
TECalText(teh);
|
||
END;
|
||
|
||
|
||
BEGIN
|
||
GetFontInfo(fInfo);
|
||
with fInfo do
|
||
lineHeight := ascent + descent + leading;
|
||
|
||
__HMBalloonRect := noErr;
|
||
|
||
wd := 0;
|
||
ht := 0;
|
||
|
||
aTE := NIL;
|
||
result := noErr;
|
||
resizeAble := false;
|
||
|
||
SetRect(tempRect,5,5,100,100); { Start with this rect initially }
|
||
|
||
case aHelpMsg.hmmHelpType of
|
||
|
||
khmmString,khmmStringRes,khmmSTRRes:
|
||
begin
|
||
with aHelpMsg do
|
||
begin
|
||
tempstr := ''; { zero for failures }
|
||
|
||
if hmmHelpType = khmmString then
|
||
tempstr := hmmString
|
||
|
||
else if hmmHelpType = khmmSTRRes then
|
||
begin
|
||
textH := Handle(GetString(hmmSTRRes));
|
||
if textH<>NIL then
|
||
tempstr := StringHandle(textH)^^;
|
||
end else
|
||
GetIndString(tempstr,hmmStringRes.hmmResID,
|
||
hmmStringRes.hmmIndex);
|
||
|
||
if length(tempstr) > 0 then
|
||
begin
|
||
aTE := TENew(tempRect,tempRect);
|
||
|
||
{$ifc HelpMgrTesting}
|
||
Assert(aTE=NIL,'HMBalloonRect[X]: a te handle was NIL');
|
||
{$endc}
|
||
|
||
if aTE<>NIL then
|
||
begin
|
||
TESetText(pointer(ord(@tempstr)+1),
|
||
length(tempstr),aTE);
|
||
textArea := lineHeight * StringWidth(tempstr);
|
||
|
||
end else result := memFullErr;
|
||
|
||
end else result := paramErr;
|
||
end;
|
||
end;
|
||
|
||
khmmPict,khmmPictHandle:
|
||
begin
|
||
if aHelpMsg.hmmHelpType = khmmPict then
|
||
ph := PicHandle(GetResource('PICT',aHelpMsg.hmmPict))
|
||
else ph := aHelpMsg.hmmPictHandle;
|
||
|
||
if ph<>NIL then
|
||
begin
|
||
with ph^^.picFrame do
|
||
begin
|
||
wd := right-left;
|
||
ht := bottom-top;
|
||
end;
|
||
|
||
end else
|
||
if aHelpMsg.hmmHelpType = khmmPict then
|
||
result := resNotFound
|
||
else result := paramErr;
|
||
|
||
{$ifc HelpMgrTesting}
|
||
Assert(ph=NIL,'HMBalloonRect[2]: a pic handle was NIL');
|
||
{$endc}
|
||
end;
|
||
|
||
khmmTEHandle,khmmTERes:
|
||
begin
|
||
if (aHelpMsg.hmmHelpType = khmmTERes) then
|
||
aTE := __HMGetStyledHandleResource(tempRect,kHMTETextResType,aHelpMsg.hmmTERes)
|
||
else aTE := aHelpMsg.hmmTEHandle;
|
||
|
||
if aTE<>NIL then
|
||
begin
|
||
resizeAble := (aTE^^.txSize<>-1);
|
||
|
||
textH := aTE^^.hText;
|
||
HLock(textH);
|
||
|
||
if resizeAble then
|
||
with aTE^^ do
|
||
begin
|
||
{ <72> don't need these anymore
|
||
tempFont := txFont;
|
||
tempSize := txSize;
|
||
}
|
||
__HMGetTextFontStuff(txFont,txSize);
|
||
{ *** how do we reset the old TEHandle's font & size helpmgr font here? }
|
||
|
||
GetFontInfo(fInfo);
|
||
with fInfo do
|
||
lineHeight := ascent + descent + leading;
|
||
|
||
end else
|
||
lineHeight := TEGetHeight(0,$7FF,aTE) div aTE^^.nLines;
|
||
|
||
textArea := lineHeight * TextWidth(textH^, 0, aTE^^.teLength);
|
||
HUnlock(textH);
|
||
{$IFC NOT theFuture} {<75>}
|
||
if textArea > maxTETextArea then
|
||
result := paramErr;
|
||
{$ENDC}
|
||
end else result := paramErr;
|
||
end;
|
||
|
||
otherwise
|
||
begin
|
||
{$ifc HelpMgrTesting}
|
||
NumToString(aHelpMsg.hmmHelpType,tempstr);
|
||
DebugStr(concat('Bad HelpType (',tempstr,') passed to HMBalloonRect'));
|
||
{$endc}
|
||
|
||
__HMBalloonRect := hmUnknownHelpType;
|
||
Exit(__HMBalloonRect);
|
||
end;
|
||
end;
|
||
|
||
if result<>noErr then
|
||
begin
|
||
__HMBalloonRect := result;
|
||
Exit(__HMBalloonRect);
|
||
end;
|
||
|
||
if aTE<>NIL then { for khmmPict or khmmPictHandle case, don't do resizing}
|
||
begin
|
||
|
||
if textArea=0 then
|
||
r := 0 else
|
||
r := FastSQRT(textArea);
|
||
|
||
ht := (r * 1000) div 1272; {(1272/1000)**2 approx golden ratio}
|
||
|
||
{ make height a multiple of line height }
|
||
rp := ht mod lineHeight;
|
||
if (rp <> 0) then
|
||
ht := ht + lineHeight - rp;
|
||
|
||
numLines := ht div lineHeight;
|
||
|
||
wd := textArea div ht;
|
||
|
||
{ *** make sure longest word fits, someday! }
|
||
|
||
ResizeTE(aTE, wd, ht);
|
||
|
||
while (TEGetHeight(0,$7FF,aTE)>ht) do {loop until the # of lines fits in bounds}
|
||
begin
|
||
if (TEGetHeight(0,$7FF,aTE)>ht) then
|
||
begin
|
||
wd := (ht * 3236) div 2000;
|
||
ResizeTE(aTE, wd, ht);
|
||
end;
|
||
|
||
if (TEGetHeight(0,$7FF,aTE)>ht) then
|
||
begin
|
||
wd := ((ht + lineHeight) * 3236) div 2000;
|
||
ResizeTE(aTE, wd, ht);
|
||
end;
|
||
|
||
if (TEGetHeight(0,$7FF,aTE)>ht) then
|
||
begin
|
||
wd := (ht * 3236) div 2000;
|
||
ht := ht + lineHeight;
|
||
ResizeTE(aTE, wd, ht);
|
||
end;
|
||
end;
|
||
|
||
if (TEGetHeight(0,$7FF,aTE)<ht) then
|
||
begin
|
||
ht := TEGetHeight(0,$7FF,aTE);
|
||
ResizeTE(aTE, wd, ht); {resize again so HMCalc won't have to also}
|
||
end;
|
||
|
||
{ <72> don't reset the font and size of the text edit handle passed, as we've just calculated
|
||
the balloon for this text edit handle using the help mgr font
|
||
if resizeAble then
|
||
begin
|
||
with aTE^^ do
|
||
begin
|
||
txFont := tempFont;
|
||
txSize := tempSize;
|
||
end;
|
||
end;
|
||
}
|
||
|
||
with __HMGetHelpGlobal^ do
|
||
if hmgKeepTEHandle then
|
||
hmgTEHandle := aTE else
|
||
if aHelpMsg.hmmHelpType <> khmmTEHandle then {don't toss the supplied handle in khmmTEHandle case}
|
||
TEDispose(aTE);
|
||
end;
|
||
|
||
SetRect(coolRect,0,0,wd,ht);
|
||
END;
|
||
|
||
|
||
FUNCTION __HMGetBalloons: BOOLEAN;
|
||
|
||
BEGIN
|
||
|
||
__HMGetBalloons := __HMGetHelpGlobal^.hmgWhatIs;
|
||
END;
|
||
|
||
{$ifc AllowCloseViewChanges}
|
||
FUNCTION __HMIsCloseViewActive: BOOLEAN;
|
||
VAR result : LongInt;
|
||
BEGIN
|
||
__HMIsCloseViewActive := true;
|
||
(*
|
||
__HMIsCloseViewActive := false;
|
||
if Gestalt('BSDa',result) = noErr then
|
||
__HMIsCloseViewActive := (result <> 0);
|
||
*)
|
||
END;
|
||
{$endc}
|
||
|
||
FUNCTION __HMRemoveBalloon: OsErr;
|
||
VAR window : WindowPtr;
|
||
windowPic : PicHandle;
|
||
oldPort : GrafPtr;
|
||
wPort : GrafPtr;
|
||
oldLayer : LayerPtr;
|
||
floatLayer : LayerPtr;
|
||
bounds : Rect;
|
||
refcon : LongInt;
|
||
balloonDown : BOOLEAN;
|
||
pt : Point;
|
||
windowCode : INTEGER;
|
||
floatwindowCode : INTEGER;
|
||
ignoreErr : OSErr;
|
||
BEGIN
|
||
with __HMGetHelpGlobal^ do
|
||
begin
|
||
{$ifc AllowCloseViewChanges}
|
||
if __HMIsBalloon then
|
||
if __HMIsCloseViewActive then
|
||
if __HMShiftKey then
|
||
begin
|
||
hmgCloseViewCount := 1 {means remove current balloon when the shift key goes up};
|
||
|
||
__HMRemoveBalloon := hmCloseViewActive;
|
||
exit(__HMRemoveBalloon);
|
||
end;
|
||
{$endc}
|
||
|
||
|
||
|
||
if not hmgWhatIs then
|
||
__HMRemoveBalloon := hmHelpDisabled;
|
||
|
||
window := hmgWindow;
|
||
balloonDown := false; { assume that a balloon wasn't removed }
|
||
|
||
|
||
if (window<>NIL) then
|
||
begin
|
||
if hmgLayer<>NIL then
|
||
oldLayer := SwapCurLayer(hmgLayer);
|
||
|
||
windowPic := GetWindowPic(window); { <59> call toolbox instead of WindowPeeking record }
|
||
refcon := GetWRefCon(window); { <59> call toolbox instead of WindowPeeking record }
|
||
|
||
if windowPic<>NIL then { <58> make sure picture was actually there! }
|
||
if __HMCanPictureBeKilled(refcon) then { <59> don't 'kill' a resource! }
|
||
KillPicture(windowPic); { <54> but be sure to kill the picture }
|
||
|
||
SetWindowPic(window,NIL); { <59> call toolbox instead of WindowPeeking record }
|
||
|
||
if window = hmgHelpWindow then { we don't toss our window <54> }
|
||
begin
|
||
SetWRefCon(window,0); { <59> call toolbox instead of WindowPeeking record }
|
||
HideWindow(window); { just hide it <54> }
|
||
end else
|
||
DisposeWindow(window); { this does a KillPicture(windowPic) automagically! }
|
||
|
||
if hmgLayer<>NIL then
|
||
SetCurLayer(oldLayer);
|
||
|
||
hmgWindow := NIL;
|
||
hmgTitleBalloon := 0; { clear the flag that says that a menu title balloon is up }
|
||
hmgItemNum := -1;
|
||
|
||
balloonDown := true;
|
||
end;
|
||
|
||
if hmgSavedBitsHandle<>NIL then { <57> we don't need to set wmgrport anymore }
|
||
begin
|
||
__HMRestoreBitsToRect(hmgSavedBitsHandle);
|
||
|
||
hmgSavedBitsHandle := NIL; { zero the handle [flag] }
|
||
hmgItemNum := -1; { force new balloon to get shown }
|
||
balloonDown := true;
|
||
end;
|
||
|
||
with hmgSlopRect do
|
||
begin
|
||
LongInt(topLeft) := 0;
|
||
LongInt(botRight):= 0;
|
||
end;
|
||
|
||
with hmgItemRect do
|
||
begin
|
||
LongInt(topLeft) := 0;
|
||
LongInt(botRight):= 0;
|
||
end;
|
||
|
||
hmgLastPartCode := 0;
|
||
hmgLastWindowPtr := NIL;
|
||
|
||
hmgLastMenuID := -1;
|
||
hmgLastEnabled := 0;
|
||
hmgLastItem := 0;
|
||
|
||
hmgState := -1;
|
||
hmgMenuID := kwasCleared;
|
||
|
||
{$ifc AllowCloseViewChanges}
|
||
if balloonDown then
|
||
hmgCloseViewCount := 0;
|
||
{$endc}
|
||
|
||
end; { with __HMGetHelpGlobal^ }
|
||
|
||
{ do this nonsense 'cuz the WindowMgr clips the WmgrPort to menubar,
|
||
the result is that the pulldown menus get drawn w/o being erased first! }
|
||
SetRect(bounds,-32768, -32768, 32767,32767);
|
||
GetPort(oldPort);
|
||
GetWMgrPort(wPort);
|
||
SetPort(wPort);
|
||
ClipRect(bounds);
|
||
SetPort(oldport);
|
||
|
||
if balloonDown then
|
||
__HMRemoveBalloon := noErr
|
||
else __HMRemoveBalloon := hmNoBalloonUp;
|
||
END;
|
||
|
||
|
||
FUNCTION __HMIsBalloon: BOOLEAN;
|
||
BEGIN
|
||
with __HMGetHelpGlobal^ do
|
||
__HMIsBalloon := (hmgWindow<>NIL) | (hmgSavedBitsHandle<>NIL);
|
||
END;
|
||
|
||
|
||
FUNCTION __HMSetBalloons(flag: BOOLEAN): OsErr; { the entire routine was rewritten <54> RLC }
|
||
VAR aLayer : LayerPtr;
|
||
fontAndSize : HMFontRecord;
|
||
gp : HMGlobalPtr;
|
||
oldLayer : LayerPtr;
|
||
oldZone : THz;
|
||
bounds : Rect;
|
||
chain : WindowPeek;
|
||
aMenu : MenuHandle;
|
||
result : OsErr;
|
||
BEGIN
|
||
__HMSetBalloons := noErr; { in case we're exiting early }
|
||
|
||
gp := __HMGetHelpGlobal;
|
||
if gp<>NIL then
|
||
with gp^ do
|
||
begin
|
||
if hmgWhatIs = flag then exit(__HMSetBalloons); { the state is already setup so exit now }
|
||
|
||
{ reset the script info again }
|
||
LongInt(fontAndSize) := GetScript(INTEGER(GetEnvirons(smSysScript)), smScriptHelpFondSize);
|
||
LongInt(hmgFontAndSize) := LongInt(fontAndSize); { all this LongInt stuff is a code saver }
|
||
|
||
if flag then { let's create the layer and window now! }
|
||
begin
|
||
chain := LayerPeek(GetRootLayer)^.subWindows; { get the first children of root }
|
||
if chain<>NIL then { there is a child }
|
||
begin
|
||
{ *** Assert if the child is our help layer then everything is set already (how could this happen?) }
|
||
{$ifc HelpMgrTesting}
|
||
Assert(chain = WindowPeek(hmgLayer),'HMSetBalloons: Help layer was not deallocated!');
|
||
|
||
{walk the children of the root, looking for our help layer}
|
||
repeat
|
||
chain := chain^.nextWindow;
|
||
until (chain = NIL) | (chain = WindowPeek(hmgLayer));
|
||
|
||
Assert(chain<>NIL,'HMSetBalloons: Help layer was still in layer chain!');
|
||
{$endc}
|
||
|
||
{ get and set the rootlayer }
|
||
oldLayer := SwapCurLayer(GetRootLayer);
|
||
|
||
oldZone := GetZone; { get the current heap zone }
|
||
SetZone(SystemZone); { point at the system heap }
|
||
|
||
aLayer := NIL;
|
||
|
||
{ create the help layer, having its rgns in sys heap }
|
||
result := NewLayer(aLayer,true{visible},true{neveractive},
|
||
pointer(-1){infront},LongInt($BADFACE){refcon});
|
||
|
||
if result<>noErr then
|
||
begin
|
||
{$ifc HelpMgrTesting}
|
||
DebugStr('HMSetBalloons: Unable to create a help layer');
|
||
{$endc}
|
||
|
||
aLayer := NIL; { this seems to be garbage sometimes when there isn't the memory }
|
||
end else
|
||
begin
|
||
SetCurLayer(aLayer);
|
||
|
||
SetRect(bounds,0,0,100,100);
|
||
hmgHelpWindow := NewWindow(@hmgHelpWRecord,bounds,'Balloon',
|
||
false,(16 * kBalloonWDEFID) + 0 {default varCode},pointer(-1),false,0);
|
||
end;
|
||
|
||
SetZone(oldZone); { restore the heap zone }
|
||
hmgLayer := aLayer; { make our globals have that layer }
|
||
SetCurLayer(oldLayer); { restore the current layer }
|
||
|
||
end; { else there wasn't any root layer (how can this happen?) }
|
||
end else
|
||
begin { tear down the layer and window }
|
||
{$ifc HelpMgrTesting}
|
||
if hmgHelpWindow = NIL then
|
||
begin
|
||
DebugStr('HMSetBalloons: we tried to deallocate the help window twice!');
|
||
exit(__HMSetBalloons);
|
||
end;
|
||
|
||
if hmgLayer = NIL then
|
||
begin
|
||
DebugStr('HMSetBalloons: we tried to deallocate the help layer twice!');
|
||
exit(__HMSetBalloons);
|
||
end;
|
||
{$endc}
|
||
|
||
if __HMRemoveBalloon=noErr then; { <63> always hide the balloons if help is turned off }
|
||
|
||
oldLayer := SwapCurLayer(hmgLayer);
|
||
|
||
CloseWindow(hmgHelpWindow); { close the window because we've got our own storage for the wRecord }
|
||
hmgHelpWindow := NIL;
|
||
DisposeWindow(hmgLayer); { dispose window because we allocated it in the System heap via NIL }
|
||
hmgLayer := NIL;
|
||
|
||
SetCurLayer(oldLayer); { restore the current layer }
|
||
end;
|
||
|
||
hmgWhatIs := flag; { Set the HMGetBalloons global flag }
|
||
end;
|
||
|
||
__HMSetBalloons := noErr;
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMShowBalloon(aHelpMsg: HMMessageRecord;
|
||
tip: Point;
|
||
alternateRect: RectPtr;
|
||
tipProc: Ptr;
|
||
theProc,variant: INTEGER;
|
||
method: INTEGER): OsErr;
|
||
|
||
VAR oldPort : GrafPtr;
|
||
oldZone : THz;
|
||
bounds : Rect;
|
||
wBounds : Rect;
|
||
temprect : Rect;
|
||
gp : HMGlobalPtr;
|
||
pic : PicHandle;
|
||
window : WindowPtr;
|
||
oldLayer : LayerPtr;
|
||
initialWindowPtr: WindowPtr;
|
||
initialPartCode : INTEGER;
|
||
procID : INTEGER;
|
||
varCode : INTEGER;
|
||
wVarCode : INTEGER;
|
||
result : OsErr;
|
||
oldState : SignedByte;
|
||
|
||
PROCEDURE __HMSetLastGlobals;
|
||
BEGIN
|
||
with gp^ do
|
||
begin
|
||
if alternateRect<>NIL then
|
||
hmgSlopRect := alternateRect^ else
|
||
SetRect(hmgSlopRect,0,0,0,0);
|
||
|
||
hmgLastPartCode := initialPartCode;
|
||
hmgLastWindowPtr := initialWindowPtr;
|
||
|
||
if hmgLastWindowPtr<>NIL then
|
||
begin
|
||
if BAnd($C000,CGrafPtr(hmgLastWindowPtr)^.portVersion)<>0 then
|
||
temprect := CGrafPtr(hmgLastWindowPtr)^.portPixMap^^.bounds
|
||
else temprect := hmgLastWindowPtr^.portBits.bounds;
|
||
|
||
with hmgLastWindowPtr^.portRect do
|
||
begin
|
||
hmgLastWidth := (right-left);
|
||
hmgLastHeight := (bottom-top);
|
||
hmgLastLeft := temprect.left - left;
|
||
hmgLastTop := temprect.top - top;
|
||
end;
|
||
end else
|
||
begin
|
||
hmgLastWidth := 0;
|
||
hmgLastHeight := 0;
|
||
hmgLastLeft := 0;
|
||
hmgLastTop := 0;
|
||
end;
|
||
|
||
|
||
end;
|
||
END;
|
||
BEGIN
|
||
gp := __HMGetHelpGlobal;
|
||
|
||
if __HMGetBalloons
|
||
{$ifc AllowCloseViewChanges}
|
||
& (gp^.hmgCloseViewCount = 0) {CloseView is active, shift key was down, & balloon was up}
|
||
{$endc} then
|
||
begin
|
||
__HMShowBalloon := hmBalloonAborted;
|
||
|
||
|
||
|
||
if __HMRemoveBalloon=noErr then;
|
||
|
||
initialPartCode := __HMGetWindowPartCode(initialWindowPtr);
|
||
|
||
method := BAnd($0007,method); { strip off hi bits of method }
|
||
|
||
{ *** we currently support only:
|
||
kHMRegularWindow = 0; Create a regular window floating above all windows
|
||
kHMSaveBitsNoWindow = 1; Just save the bits and draw (for MDEF calls
|
||
kHMSaveBitsWindow = 2; Regular window, save bits behind, AND generate update event
|
||
}
|
||
|
||
if method = kHMSaveBitsNoWindow then
|
||
begin
|
||
if theProc<>0 then {only support proc 0 when saving bits}
|
||
__HMShowBalloon := hmOperationUnsupported else
|
||
begin
|
||
result := __HMSaveBalloonBits(aHelpMsg,tip,alternateRect,
|
||
tipProc,variant,wasWindow);
|
||
|
||
if result=noErr then
|
||
__HMSetLastGlobals;
|
||
|
||
__HMShowBalloon := result;
|
||
end;
|
||
end else
|
||
begin { it must have been a kHMRegularWindow or kHMSaveBitsWindow method }
|
||
GetPort(oldPort);
|
||
|
||
with gp^ do
|
||
if hmgLayer<>NIL then
|
||
oldLayer := SwapCurLayer(hmgLayer);
|
||
|
||
varCode := variant;
|
||
result := __HMCalculateBalloon(aHelpMsg,tip,alternateRect,
|
||
varCode,bounds,pic,wasWindow,true { will abort balloon if mouse moves });
|
||
if result = noErr then
|
||
begin
|
||
if theProc<>0 then
|
||
begin
|
||
procID := theProc;
|
||
varCode := variant; { override just calculated varCode in __HMCalculateBalloon
|
||
as we have our own defProc whose variant could be different }
|
||
|
||
if GetResource('WDEF',theProc)=NIL then { we couldn't load the custom 'WDEF' }
|
||
result := resNotFound;
|
||
end else
|
||
procID := kBalloonWDEFID; { use our balloon 'WDEF' }
|
||
|
||
if result = noErr then
|
||
with gp^ do
|
||
begin
|
||
if theProc<>0 then
|
||
begin
|
||
oldZone := GetZone; { get the current heap zone }
|
||
SetZone(SystemZone); { point at the system heap }
|
||
|
||
{ only call new window if theProc isn't our balloon definition <54> }
|
||
window := NewWindow(NIL,bounds,'appBalloon',false,(16 * procID) + varCode,
|
||
pointer(-1),false,0);
|
||
|
||
SetZone(oldZone);
|
||
end else
|
||
begin
|
||
{ change our balloon window's defproc variant to be the new one <54> }
|
||
__HMStuffWindowInfo(hmgHelpWindow,varCode,bounds);
|
||
|
||
{ make the showwindow call recalculate the window's regions <54> }
|
||
with WindowPeek(hmgHelpWindow)^ do
|
||
begin
|
||
SetEmptyRgn(strucRgn);
|
||
SetEmptyRgn(contRgn);
|
||
end;
|
||
|
||
{ make the current balloon our window <54> }
|
||
window := hmgHelpWindow;
|
||
end;
|
||
|
||
if window<>NIL then
|
||
begin
|
||
SetPort(window);
|
||
|
||
if (method = kHMSaveBitsWindow) | (tipProc<>NIL) then { <58> check tip procedure too }
|
||
begin
|
||
if __HMCallCustomWDEFCalc(wCalcRgns,window)=noErr then;
|
||
|
||
if tipProc<>NIL then { <58> give the caller a chance to abort }
|
||
begin
|
||
with WindowPeek(window)^ do { <58> using the balloon window information… }
|
||
begin
|
||
wBounds := bounds;
|
||
wVarCode := varCode;
|
||
|
||
result := __HMCallTipProc(tipProc,tip,strucRgn,wBounds,wVarCode); { <58> see if caller doesn't like balloon }
|
||
|
||
if result = noErr then { <58> balloon might have changed a bit, so update info }
|
||
if (wVarCode<>varCode) |
|
||
(LongInt(wBounds.topLeft)<>LongInt(bounds.topLeft)) |
|
||
(LongInt(wBounds.botRight)<>LongInt(bounds.botRight)) then
|
||
begin
|
||
bounds := wBounds;
|
||
varCode := wVarCode;
|
||
|
||
__HMStuffWindowInfo(window,varCode,bounds); { <58> restuff the window info }
|
||
|
||
SetEmptyRgn(strucRgn); { <58> will cause window to recalc when visible }
|
||
SetEmptyRgn(contRgn);
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
if result = noErr then { <58> either there wasn't a tip proc or caller didn't abort }
|
||
if (method = kHMSaveBitsWindow) then
|
||
with WindowPeek(window)^ do
|
||
begin
|
||
wBounds := strucRgn^^.rgnBBox;
|
||
hmgSavedBitsHandle := __HMSaveBitsInRect(wBounds); { save bits behind window b4 putting up window }
|
||
|
||
{ make the ShowWindow() call recalculate the window's regions }
|
||
SetEmptyRgn(strucRgn);
|
||
SetEmptyRgn(contRgn);
|
||
end;
|
||
end;
|
||
|
||
if result = noErr then
|
||
begin
|
||
SetWindowPic(window,pic); { <59> Call toolbox instead of WindowPeeking record }
|
||
SetWRefCon(window,aHelpMsg.hmmHelpType); { <59> Call toolbox instead of WindowPeeking record }
|
||
ShowWindow(window);
|
||
|
||
{ The code below makes the balloon contents appear immediately
|
||
instead of waiting for the window manager to draw the picture }
|
||
|
||
BeginUpdate(window);
|
||
|
||
if pic^ = NIL then { <58> the pic was really a resource that was purged }
|
||
LoadResource(Handle(pic));
|
||
|
||
if pic^ <> NIL then { <58> the pic was successfully reloaded (if purged) }
|
||
begin
|
||
oldState := HGetState(Handle(pic)); { <58> remember pic handle's state }
|
||
HNoPurge(Handle(pic)); { <58> keep it around (if resource) }
|
||
|
||
with pic^^.picFrame do
|
||
SetRect(bounds,0,0,right-left,bottom-top); { <58> force picture to window coords }
|
||
|
||
DrawPicture(pic,bounds);
|
||
HSetState(Handle(pic),oldState);
|
||
end;
|
||
|
||
EndUpdate(window);
|
||
|
||
hmgWindow := window;
|
||
|
||
end else { there was an abort returned from calling tip proc, so toss the window }
|
||
begin
|
||
if window <> hmgHelpWindow then
|
||
begin
|
||
DisposeWindow(window); { <58> Dispose the wind if the window was custom }
|
||
pic := NIL; { *** } { <59> NIL picHandle, DisposeWindow() kills the pic automatically }
|
||
end;
|
||
|
||
if (hmgSavedBitsHandle <> NIL) then
|
||
begin
|
||
if DiscardBits(LongInt(hmgSavedBitsHandle))=noErr then;
|
||
hmgSavedBitsHandle := NIL; { <58> NIL this in case someone calls HMRemoveBalloon() }
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
end;
|
||
end;
|
||
|
||
if result <> noErr then { some sort of error or abort occurred, so toss the picture (if any) }
|
||
if pic <> NIL then
|
||
if __HMCanPictureBeKilled(aHelpMsg.hmmHelpType) then { <59> KillPicture if type wasn't resource based }
|
||
KillPicture(pic);
|
||
|
||
__HMShowBalloon := result;
|
||
|
||
with gp^ do
|
||
if (hmgLayer<>NIL) then
|
||
SetCurLayer(oldLayer);
|
||
|
||
SetPort(oldPort);
|
||
|
||
__HMSetLastGlobals;
|
||
end;
|
||
|
||
end else __HMShowBalloon := hmHelpDisabled;
|
||
END;
|
||
|
||
|
||
|
||
|
||
PROCEDURE __HMShowTitleBalloon(menuID: INTEGER; flags: LongInt);
|
||
VAR aHelpMsg : HMMessageRecord;
|
||
altRect : Rect;
|
||
pt : Point;
|
||
width : INTEGER;
|
||
variant : INTEGER;
|
||
resID : INTEGER;
|
||
result : OsErr;
|
||
gp : HMGlobalPtr;
|
||
BEGIN
|
||
gp := __HMGetHelpGlobal;
|
||
|
||
with gp^ do
|
||
if (hmgItemNum = 0) then if (menuID = hmgMenuID) then
|
||
Exit(__HMShowTitleBalloon);
|
||
|
||
if __HMGetMenuResID(menuID,resID)<>noErr then
|
||
resID := -1;
|
||
|
||
variant := 0; { default in the case of the Apple Menu }
|
||
|
||
if __HMFillInMenuMessage(menuID,0,resID,flags,variant,aHelpMsg)<>noErr then
|
||
Exit(__HMShowTitleBalloon);
|
||
|
||
if GetMenuTitleRect(menuID,altRect)=noErr then;
|
||
with altRect do
|
||
begin
|
||
width := right-left;
|
||
pt.h := left + BSR(width,1);
|
||
pt.v := IntegerPtr(MBarHeight)^;
|
||
|
||
top := top - 1;
|
||
bottom := top + pt.v;
|
||
end;
|
||
|
||
result := __HMShowBalloon(aHelpMsg,pt,@altRect,NIL,0,variant,2);
|
||
|
||
if result=noErr then
|
||
with gp^ do
|
||
begin
|
||
hmgLastMenuID := menuID;
|
||
hmgLastEnabled := flags;
|
||
hmgLastItem := 0;
|
||
|
||
hmgItemNum := 0;
|
||
hmgMenuID := menuID;
|
||
hmgTitleBalloon := 1; { when this is non-zero, the show hide patch won't toss this balloon }
|
||
end;
|
||
END;
|
||
|
||
|
||
|
||
|
||
|
||
FUNCTION __HMShowMenuBalloon(itemNum,itemMenuID: INTEGER;
|
||
itemFlags,itemReserved: LongInt;
|
||
tip: Point; alternateRect: RectPtr; tipProc: Ptr;
|
||
theProc,variant: INTEGER): OsErr;
|
||
VAR aHelpMsg : HMMessageRecord;
|
||
menuBarRect : Rect;
|
||
menuHeight : INTEGER;
|
||
overVariant : INTEGER;
|
||
gp : HMGlobalPtr;
|
||
pt : Point;
|
||
result : OsErr;
|
||
resID : INTEGER;
|
||
BEGIN
|
||
gp := __HMGetHelpGlobal;
|
||
|
||
__HMShowMenuBalloon := hmSameAsLastBalloon; {assume that it's already displayed}
|
||
|
||
if __HMGetBalloons
|
||
|
||
{$ifc AllowCloseViewChanges}
|
||
& (gp^.hmgCloseViewCount = 0) {CloseView is active, shift key was down, & balloon was up}
|
||
{$endc}
|
||
then
|
||
with gp^ do
|
||
begin
|
||
if (hmgLastItem = itemNum) then
|
||
if (hmgLastMenuID = itemMenuID) then
|
||
if (hmgLastEnabled = itemFlags) then EXIT(__HMShowMenuBalloon);
|
||
|
||
if itemNum <= 0 then { if 0 then mouse was in a title, if -1 then it was a dash }
|
||
begin
|
||
if __HMRemoveBalloon=noErr then; { toss any existing Balloons, if 0 or -1 }
|
||
Exit(__HMShowMenuBalloon);
|
||
end;
|
||
|
||
if __HMGetMenuResID(itemMenuID,resID)<>noErr then
|
||
resID := -1;
|
||
|
||
if alternateRect<>NIL then
|
||
hmgItemRect := alternateRect^;
|
||
|
||
hmgItemNum := itemNum;
|
||
hmgMenuID := itemMenuID;
|
||
|
||
overVariant := variant;
|
||
|
||
{ <59> Ignore itemReserved parameter menu or item is disabled }
|
||
if (itemReserved <> 0) then
|
||
begin
|
||
IF not BTST(itemFlags,0) THEN { The whole menu is disabled }
|
||
itemReserved := 0
|
||
ELSE IF (itemNum <= 31) THEN { The item has a flag bit }
|
||
IF NOT BTST(itemFlags,itemNum) THEN { That item is disabled }
|
||
itemReserved := 0;
|
||
end;
|
||
|
||
if (itemReserved = 0) or (ODD(itemReserved)) then { we need to fetch the msg out of the 'hmnu' resource }
|
||
begin
|
||
result := __HMFillInMenuMessage(itemMenuID,itemNum,resID,itemFlags,overVariant,aHelpMsg);
|
||
|
||
if result<>noErr then { we didn't find anything in the 'hmnu' or the 'hmnu' was missing }
|
||
begin
|
||
__HMShowMenuBalloon := result;
|
||
exit(__HMShowMenuBalloon);
|
||
end;
|
||
|
||
end else { let's assume that itemReserved is a StringHandle to the message string }
|
||
with aHelpMsg do
|
||
begin
|
||
hmmHelpType := khmmString;
|
||
hmmString := StringHandle(itemReserved)^^; { copy the string data }
|
||
result := noErr;
|
||
end;
|
||
|
||
with aHelpMsg do
|
||
if hmmHelpType = khmmString then
|
||
if length(hmmString)=0 then
|
||
begin
|
||
__HMShowMenuBalloon := paramErr;
|
||
exit(__HMShowMenuBalloon);
|
||
end;
|
||
|
||
if overVariant<>0 then
|
||
variant := overVariant;
|
||
|
||
result := __HMSaveBalloonBits(aHelpMsg,tip,alternateRect,tipProc,variant,wasMenu);
|
||
|
||
if result=noErr then
|
||
begin
|
||
if alternateRect<>NIL then
|
||
hmgSlopRect := alternateRect^
|
||
else SetRect(hmgSlopRect,0,0,0,0);
|
||
|
||
hmgLastItem := itemNum;
|
||
hmgLastMenuID := itemMenuID;
|
||
hmgLastEnabled := itemFlags;
|
||
end;
|
||
|
||
end else
|
||
result := hmHelpDisabled;
|
||
|
||
__HMShowMenuBalloon := result;
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMSetFont(font: INTEGER): OsErr;
|
||
VAR fontlong : LongInt;
|
||
BEGIN
|
||
__HMSetGetFontSizeGlobal(kGetFont,fontlong);
|
||
with __HMGetHelpGlobal^ do
|
||
begin
|
||
hmgFontAndSize.hmgFont := font;
|
||
__HMSetGetFontSizeGlobal(kSetFont,LongInt(hmgFontAndSize));
|
||
end;
|
||
__HMSetFont := noErr;
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMSetFontSize(fontSize: INTEGER): OsErr;
|
||
VAR fontlong : LongInt;
|
||
BEGIN
|
||
__HMSetGetFontSizeGlobal(kGetFont,fontlong);
|
||
with __HMGetHelpGlobal^ do
|
||
begin
|
||
hmgFontAndSize.hmgFontSize := fontSize;
|
||
__HMSetGetFontSizeGlobal(kSetFont,LongInt(hmgFontAndSize));
|
||
end;
|
||
__HMSetFontSize := noErr;
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMGetFont(VAR font: INTEGER): OsErr;
|
||
BEGIN
|
||
font := __HMGetHelpGlobal^.hmgFontAndSize.hmgFont;
|
||
__HMGetFont := noErr;
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMGetFontSize(VAR fontSize: INTEGER): OsErr;
|
||
BEGIN
|
||
fontSize := __HMGetHelpGlobal^.hmgFontAndSize.hmgFontSize;
|
||
__HMGetFontSize := noErr;
|
||
END;
|
||
|
||
|
||
{ <58> HMFind now will find BOTH menu & dialog PSN driven indices in open apps }
|
||
FUNCTION __HMFind(queue: HHMHelpQueueRecord; theMenuID: INTEGER;
|
||
VAR index: INTEGER; PSN: ProcessSerialNumber): INTEGER;
|
||
VAR i : INTEGER;
|
||
count : INTEGER;
|
||
BEGIN
|
||
__HMFind := -1; { say we didn't find it in the array }
|
||
|
||
if queue<>NIL then
|
||
begin
|
||
count := queue^^.queueCount;
|
||
for i := 1 to count do
|
||
with queue^^.queueRecords[i] do
|
||
begin
|
||
if (theMenuID = slotID) then { theMenuID will always be equal when searching the dialog queue }
|
||
if (PSN.lowLongOfPSN = slotPID.lowLongOfPSN) then
|
||
if (PSN.highLongOfPSN = slotPID.highLongOfPSN) then
|
||
begin
|
||
__HMFind := slotResID;
|
||
index := i;
|
||
leave;
|
||
end;
|
||
end;
|
||
end;
|
||
END;
|
||
|
||
|
||
FUNCTION __HMSetDialogResID(theResID: INTEGER): OsErr; { <58> rewritten to work with the current PSN instead of just one index }
|
||
VAR i : INTEGER;
|
||
result : OsErr;
|
||
offset : LongInt;
|
||
p : LongInt;
|
||
queue : HHMHelpQueueRecord;
|
||
PSN : ProcessSerialNumber;
|
||
BEGIN
|
||
result := GetCurrentProcess(PSN); { <58> make this work for the current process who is assigning the res ID }
|
||
|
||
if result=noErr then { <58> only use Process IDs that are good }
|
||
begin
|
||
queue := __HMGetHelpGlobal^.hmgDialogQueue; { <58> use the dialog queue }
|
||
|
||
if __HMFind(queue,0 {allow only 1 entry in dialogs},i,PSN)<>-1 then { <58> we found a setup index, just replace the record's data }
|
||
begin
|
||
if theResID = -1 then { <58> remove this record from our queue }
|
||
begin
|
||
{believe it or not, the calculation below IS 32 bit clean}
|
||
|
||
p := ord4(@queue^^.queueRecords[i]); { <58> }
|
||
offset := p - ord4(queue^); { <58> }
|
||
|
||
{ <58> this does a SetHandleSize smaller so it should always (gulp!) succeed }
|
||
if Munger(Handle(queue),offset,NIL,SIZEOF(HMHelpSlot),Ptr(-1),0)=0 then; { <58> }
|
||
|
||
with queue^^ do
|
||
queueCount := queueCount - 1; { <58> }
|
||
|
||
{ *** <58> do we need to hide any currently displayed balloon here? }
|
||
|
||
end else
|
||
queue^^.queueRecords[i].slotResID := theResID; { <58> }
|
||
|
||
end else { <58> the ID returned from HMFind was -1 which means add a new element to the queue }
|
||
begin
|
||
SetHandleSize(Handle(queue), GetHandleSize(Handle(queue)) + SIZEOF(HMHelpSlot)); { <58> }
|
||
|
||
result := memError; { <58> }
|
||
|
||
if result=noErr then { <58> }
|
||
begin
|
||
with queue^^ do { <58> }
|
||
begin
|
||
queueCount := queueCount + 1;
|
||
with queueRecords[queueCount] do { <58> }
|
||
begin
|
||
{queueRecords[queueCount].}slotPID := PSN; { <58> }
|
||
{queueRecords[queueCount].}slotResID := theResID; { <58> }
|
||
{queueRecords[queueCount].}slotID := 0; { <58> }
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
__HMSetDialogResID := result; { <58> }
|
||
END;
|
||
|
||
|
||
FUNCTION __HMGetDialogResID(VAR theResID: INTEGER): OsErr;
|
||
VAR i : INTEGER;
|
||
PSN : ProcessSerialNumber;
|
||
BEGIN
|
||
__HMGetDialogResID := resNotFound; { <58> assume that we didn't find any dialog res id assignment }
|
||
|
||
with __HMGetHelpGlobal^ do
|
||
begin
|
||
if hmgDialogQueue^^.queueCount > 0 then { <58> quick check to see if anybody has ever overridden any dialog res ID }
|
||
if GetCurrentProcess(PSN)=noErr then { <58> only use Process IDs that are good }
|
||
begin
|
||
theResID := __HMFind(hmgDialogQueue,0,i,PSN); { <58> returns assigned res id for the PSN's dialog override }
|
||
if theResID<>-1 then
|
||
__HMGetDialogResID := noErr; { <58> return noErr if we found an assignment }
|
||
end;
|
||
end;
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMSetMenuResID(theMenuID,theResID: INTEGER): OsErr; { <58> now can return ProcessMgr error by calling GetCurrentProcess }
|
||
VAR i : INTEGER;
|
||
result : OsErr;
|
||
offset : LongInt;
|
||
p : LongInt;
|
||
queue : HHMHelpQueueRecord;
|
||
PSN : ProcessSerialNumber;
|
||
BEGIN
|
||
result := GetCurrentProcess(PSN);
|
||
if result=noErr then { only use Process IDs that are good }
|
||
begin
|
||
__HMSetMenuResID := noErr;
|
||
|
||
queue := __HMGetHelpGlobal^.hmgMenuQueue;
|
||
|
||
if __HMFind(queue,theMenuID,i,PSN)<>-1 then { we found this theMenuID in the list already, returns found index in i for array }
|
||
begin
|
||
if theResID = -1 then { remove this record }
|
||
begin
|
||
{believe it or not, the calculation below IS 32 bit clean}
|
||
p := ord4(@queue^^.queueRecords[i]); {ord(Handle(queue^^.queueRecords[i])^);}
|
||
offset := p - ord4(queue^);
|
||
|
||
{ the following routine will remove the data at the given offset:
|
||
offset := p - ord(queue^);
|
||
count to remove := SIZEOF(record); (size of our record HMHelpSlot)
|
||
|
||
the trick to munger in this case below is that the last parameter must be zero
|
||
as we're not replacing anything & munger calls SetHandleSize for us!
|
||
and since this is a delete (SetHandleSize smaller), it will always (gulp!) succeed… }
|
||
|
||
if Munger(Handle(queue),offset,NIL,SIZEOF(HMHelpSlot),Ptr(-1),0)=0 then;
|
||
|
||
with queue^^ do
|
||
queueCount := queueCount - 1;
|
||
|
||
end else
|
||
queue^^.queueRecords[i].slotResID := theResID;
|
||
|
||
end else { the ID was -1 which means add a new record }
|
||
begin
|
||
SetHandleSize(Handle(queue), GetHandleSize(Handle(queue)) + SIZEOF(HMHelpSlot));
|
||
|
||
result := memError;
|
||
|
||
if result=noErr then
|
||
begin
|
||
with queue^^ do
|
||
begin
|
||
queueCount := queueCount + 1;
|
||
with queueRecords[queueCount] do
|
||
begin
|
||
{queueRecords[queueCount].}slotPID := PSN;
|
||
{queueRecords[queueCount].}slotResID := theResID;
|
||
{queueRecords[queueCount].}slotID := theMenuID;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
__HMSetMenuResID := result;
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMGetMenuResID(theMenuID: INTEGER; VAR theResID: INTEGER): OsErr;
|
||
VAR i : INTEGER;
|
||
PSN : ProcessSerialNumber;
|
||
BEGIN
|
||
__HMGetMenuResID := resNotFound; { assume that we didn't find any resource }
|
||
|
||
{ <58> note: don't bother with quick check that HMGetDialogResID does by checking the queueCount field
|
||
in the menu queue. Finder always overrides the hmnu res id's when it is launched, so, there
|
||
is always something in the queue }
|
||
|
||
if GetCurrentProcess(PSN)=noErr then { only use Process IDs that are good }
|
||
begin
|
||
theResID := __HMFind(__HMGetHelpGlobal^.hmgMenuQueue,theMenuID,i,PSN); { <58> pass the queue now }
|
||
if theResID<>-1 then
|
||
__HMGetMenuResID := noErr;
|
||
end;
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMModalDialogMenuSetup(ModalDialogComingUp: BOOLEAN): OsErr;
|
||
VAR mh : MenuHandle;
|
||
i : INTEGER;
|
||
BEGIN
|
||
__HMModalDialogMenuSetup := noErr;
|
||
mh := GetMHandle(kHMHelpMenuID);
|
||
if (mh<>NIL) then
|
||
begin
|
||
for i := 1 to CountMItems(mh) do
|
||
begin
|
||
if (i<>kHMShowBalloonsItem) then
|
||
if (ModalDialogComingUp) then
|
||
DisableItem(mh,i) else
|
||
EnableItem(mh,i);
|
||
end;
|
||
end else
|
||
__HMModalDialogMenuSetup := hmHelpManagerNotInited;
|
||
END;
|
||
|
||
FUNCTION __HMGetScreenGDevice(pt: Point): GDHandle;
|
||
VAR gh : GDHandle;
|
||
BEGIN
|
||
gh := GetDeviceList;
|
||
while gh<>NIL do
|
||
begin
|
||
if TestDeviceAttribute(gh,screenDevice) then
|
||
if TestDeviceAttribute(gh,screenActive) then
|
||
if PtInRect(pt,gh^^.gdRect) then
|
||
leave;
|
||
gh := GetNextDevice(gh); { *** faster if we use: gh^^.gdNextGD }
|
||
end;
|
||
__HMGetScreenGDevice := gh;
|
||
END;
|
||
|
||
|
||
|
||
PROCEDURE __HMGetVariantRect(rbs: RBSRecord; VAR fullRect: Rect); { Returns the rect that can encompass the balloon }
|
||
VAR theword : IntegerPtr;
|
||
BEGIN
|
||
with fullRect do
|
||
begin
|
||
theword := @right;
|
||
if BTST(rbs.whole, kShiftBit) then
|
||
theword := @bottom;
|
||
end;
|
||
theword^ := theword^ + kHMPointerSize;
|
||
END;
|
||
|
||
|
||
|
||
|
||
|
||
PROCEDURE __HMSelectProperVariant( balloonBounds: Rect; { bounds of balloon w/o tip }
|
||
altRect: Rect; { alternate rectangle }
|
||
screenRect: Rect; { bounds of monitor we're about to display on }
|
||
VAR rbs: RBSRecord; { balloon's variant word, right, bottom, shift values }
|
||
VAR tip: Point { balloon's initial tip position }
|
||
);
|
||
|
||
CONST
|
||
horizontal = 0;
|
||
vertical = 1;
|
||
|
||
VAR dL : INTEGER;
|
||
dR : INTEGER;
|
||
dT : INTEGER;
|
||
dB : INTEGER;
|
||
retries : INTEGER;
|
||
|
||
width : INTEGER;
|
||
height : INTEGER;
|
||
border : INTEGER;
|
||
|
||
deltaH : INTEGER;
|
||
deltaV : INTEGER;
|
||
|
||
whichAxis : INTEGER;
|
||
axisCount : INTEGER;
|
||
|
||
hangRight : INTEGER; { 1 if balloon hangs right }
|
||
hangDown : INTEGER; { 1 if balloon hangs down }
|
||
hangShift : INTEGER; { 1 if balloon has a vertical tip }
|
||
|
||
bestRight : INTEGER;
|
||
bestDown : INTEGER;
|
||
bestShift : INTEGER;
|
||
bestTip : Point;
|
||
|
||
bestArea : LongInt;
|
||
|
||
area : LongInt;
|
||
areaH : LongInt;
|
||
areaV : LongInt;
|
||
|
||
destRect : Rect;
|
||
areaRect : Rect;
|
||
|
||
{ • First: See if tip's position delegates having a vertical (shift = 1) tip.
|
||
|
||
• Second: Try the horizontal position of the balloon to see if it fits with the
|
||
original tip and variant. The routine below is written to calculate balloons
|
||
in a specific order. Instead of just computing a balloon that fits, we walk
|
||
thru choices of variants to produce what appears better rather than what is
|
||
just mathematically appropriate.
|
||
|
||
Every second time that a variant is changed, the balloon
|
||
shift (whether or not a vertical tip is used) is toggled. This ensures that
|
||
every variant is tried in order to get the balloon to fit without clipping.
|
||
|
||
• Third: Try the vertical position.
|
||
|
||
• Fourth: If all variants have been tried then use the best balloon that we had calculated
|
||
along the way. The best balloon is the one with the most area.
|
||
|
||
}
|
||
|
||
BEGIN
|
||
border := IntegerPtr(MBarHeight)^ + 2; { compute the menubar's height plus room for the line & 1 pix }
|
||
|
||
hangRight := rbs.rightValue; { get right hang direction in local (if hangRight = 1 then the balloon hangs right) }
|
||
hangDown := rbs.bottomValue; { get downward hang direction in local (if hangDown = 1 then the balloon hangs down) }
|
||
hangShift := rbs.shiftValue; { get shift value in local (if hangShift = 1 then the balloon has a vertical tip) }
|
||
|
||
if hangShift = 0 then
|
||
with screenRect do
|
||
if (tip.v < top + border) or
|
||
(tip.v > bottom - border) then { the balloon tip is in menubar area or near very bottom of screen bounds }
|
||
begin
|
||
hangShift := 1; { force a vertical tip as we're near the top or bottom of screen }
|
||
end;
|
||
|
||
whichAxis := horizontal; { start with the horizontal axis first }
|
||
axisCount := 0; { reset the counter for keeping track of how many times we've tried either horizontal or vertically }
|
||
bestArea := -1; { initialize the bestArea local that keeps track of the balloon with the greatest area }
|
||
|
||
for retries := 1 to 8 do { keep computing until we tried 8 times }
|
||
begin
|
||
destRect := balloonBounds; { reset destination rect to be the balloon bounds EACH time thru the loop }
|
||
with destRect do { recalculate the dimensions of the balloon }
|
||
begin
|
||
if hangShift = 0 then
|
||
right := right + kHMPointerSize
|
||
else bottom := bottom + kHMPointerSize; { include space for tip dimensions }
|
||
|
||
width := right - left + kHMHorizFrameMargin; { include balloon horizontal margin }
|
||
height := bottom - top + kHMVertFrameMargin; { include balloon vertical margin }
|
||
end;
|
||
|
||
with screenRect do
|
||
begin
|
||
dR := (right - tip.h); { compute the space between the tip and the right edge of the screen bounds }
|
||
dL := (tip.h - left); { compute the space between the tip and the left edge of the screen bounds }
|
||
|
||
dB := (bottom - tip.v); { compute the space between the tip and the bottom edge of the screen bounds }
|
||
dT := (tip.v - (top + border)); { compute the space between the tip and the top edge of the screen bounds (minus border) }
|
||
end;
|
||
|
||
deltaH := dR; { Assume balloon hangs right so use deltaH for right }
|
||
if hangRight = 0 then { T => Nope, it hangs left, so use left deltaH }
|
||
deltaH := dL;
|
||
areaH := width; { remember this balloon's width so that if no balloons fit, we }
|
||
if width > deltaH then { can use the 'best' balloon as a last resort… }
|
||
areaH := deltaH;
|
||
|
||
deltaV := dB; { Assume balloon hangs down so use deltaV for bottom }
|
||
if hangDown = 0 then { T => Nope, it hangs up, so use top deltaV }
|
||
deltaV := dT;
|
||
areaV := height; { remember this balloon's height so that if no balloons fit, we }
|
||
if height > deltaV then { can use the 'best' balloon as a last resort… }
|
||
areaV := deltaV;
|
||
|
||
area := areaV * areaH; { compute this balloons area in case all balloons fail to fit }
|
||
if area > bestArea then { this balloon's area was larger than the last, so copy the balloon's params }
|
||
begin
|
||
bestRight := hangRight;
|
||
bestDown := hangDown;
|
||
bestShift := hangShift;
|
||
bestTip := tip;
|
||
bestArea := area; { and save the bestArea for the next go 'round }
|
||
end;
|
||
|
||
|
||
case whichAxis of
|
||
horizontal:
|
||
begin
|
||
if (width > deltaH) then { the balloon was too wide to fit, try tweeking the tip &/or variant }
|
||
begin
|
||
axisCount := axisCount + 1; { increment the counter for walking thru the balloon variants }
|
||
|
||
if axisCount <> 4 then { don't move the tip the 4th time we've checked the horiz size }
|
||
begin
|
||
tip.h := altRect.left + (altRect.right - tip.h); { move tip to the opposite side of the altRect }
|
||
end else
|
||
hangShift := 1 - hangShift; { change from a vertical tip to a horizontal one or horiz to vertical }
|
||
|
||
hangRight := 1 - hangRight; { change the balloon hanging right to hanging left or left to right }
|
||
end else
|
||
begin { we successfully fit horizontally }
|
||
whichAxis := vertical; { so now try the vertical }
|
||
axisCount := 0; { reset the counter }
|
||
cycle; { to the next for retries }
|
||
end;
|
||
end;
|
||
|
||
vertical:
|
||
begin
|
||
if (height > deltaV) then { the balloon was too tall to fit, try tweeking the tip &/or variant }
|
||
begin
|
||
axisCount := axisCount + 1; { increment the counter for walking thru the balloon variants }
|
||
|
||
if axisCount <> 4 then { don't move the tip the 4th time we've checked the vertical size }
|
||
begin
|
||
tip.v := altRect.top + (altRect.bottom - tip.v); { move tip to the opposite side of the altRect }
|
||
end else
|
||
hangShift := 1 - hangShift; { change from a vertical tip to a horizontal one or horiz to vertical }
|
||
|
||
hangDown := 1 - hangDown; { change the balloon hanging down to hanging up or down to up }
|
||
end else
|
||
begin
|
||
leave; { both the horizontal and vertical fit so exit now }
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
if retries >= 8 then { balloon didn't fit, use the which one was best }
|
||
begin
|
||
hangRight := bestRight;
|
||
hangDown := bestDown;
|
||
hangShift := bestShift;
|
||
tip := bestTip;
|
||
|
||
leave;
|
||
end
|
||
else if (axisCount mod 2) = 0 then { every second try, change the shift factor }
|
||
begin
|
||
hangShift := 1 - hangShift; { change from a vertical tip to a horizontal one or horiz to vertical }
|
||
end;
|
||
end;
|
||
|
||
rbs.rightValue := hangRight; { reset the rbs value to use the just tweaked (possibly) hanging values }
|
||
rbs.bottomValue := hangDown;
|
||
rbs.shiftValue := hangShift;
|
||
END;
|
||
|
||
|
||
FUNCTION __HMPinTipAndAltRect(screenBounds: Rect; VAR tip: Point; VAR altRect: Rect): BOOLEAN; { Returns false if no intersection }
|
||
VAR deltaLeft : LongInt;
|
||
deltaTop : LongInt;
|
||
width,height : LongInt;
|
||
newAltRect : Rect;
|
||
insideScreenBounds : BOOLEAN;
|
||
BEGIN
|
||
{ see if the altRect is really in the screen bounds (and clip it to the screen bounds at the same time) }
|
||
insideScreenBounds := SectRect(screenBounds,altRect,newAltRect);
|
||
|
||
if insideScreenBounds then { at least part of the altRect is visible }
|
||
begin
|
||
if not EqualRect(altRect,newAltRect) then { if part of the altRect is clipped, then use the ratio for the tip inside the altRect }
|
||
begin
|
||
{ use the original altRect to determine the tip deltas between the right & left, top & bottom with respect to the tip }
|
||
with altRect do
|
||
begin
|
||
deltaLeft := (tip.h - left); { this is the space between the right edge of the altRect and the horizontal part of the tip }
|
||
deltaTop := (tip.v - top);
|
||
|
||
width := right - left; { get old altRect width and height }
|
||
height := bottom - top;
|
||
|
||
end;
|
||
|
||
if width = 0 then width := 1; { make sure were not zero }
|
||
if height = 0 then height := 1;
|
||
|
||
with newAltRect do
|
||
begin
|
||
tip.h := left + (ORD4((right - left) * deltaLeft) div width); { compute ratio of tip within rect }
|
||
tip.v := top + (ORD4((bottom - top) * deltaTop) div height);
|
||
end;
|
||
|
||
altRect := newAltRect;
|
||
LongInt(tip) := PinRect(altRect,tip); { always repin the tip to the new altRect }
|
||
end;
|
||
end;
|
||
|
||
__HMPinTipAndAltRect := insideScreenBounds;
|
||
END;
|
||
|
||
|
||
FUNCTION __HMBestWorld(worldBounds: Rect; tip: Point; areaRect: Rect; balloonType: INTEGER;
|
||
VAR balloonBounds: Rect; VAR variant: INTEGER): OsErr;
|
||
VAR rbs : RBSRecord;
|
||
i,j : INTEGER;
|
||
deltaL : INTEGER;
|
||
deltaR : INTEGER;
|
||
deltaT : INTEGER;
|
||
deltaB : INTEGER;
|
||
result : INTEGER;
|
||
boundsWidth : INTEGER;
|
||
boundsHeight : INTEGER;
|
||
tweek : INTEGER;
|
||
moveValue : Point;
|
||
destRect : Rect;
|
||
offset : Point;
|
||
rbsOK : BOOLEAN;
|
||
oldPort : GrafPtr;
|
||
|
||
BEGIN
|
||
rbsOK := false;
|
||
|
||
__HMTwitchVarCode(kVariantToRBS,variant,rbs.whole);
|
||
|
||
{ Compute the 'best' rbs that will fit the balloon in the worldBounds }
|
||
__HMSelectProperVariant(balloonBounds, areaRect, worldBounds, rbs, tip);
|
||
|
||
destRect := balloonBounds; { start with the balloon bounds }
|
||
__HMGetVariantRect(rbs,destRect); { tweak the bounds to take in account the tip placement }
|
||
|
||
with balloonBounds do
|
||
begin
|
||
boundsWidth := right - left;
|
||
boundsHeight := bottom - top;
|
||
|
||
left := tip.h - ((1-rbs.rightValue) * (destRect.right - destRect.left));
|
||
top := tip.v - ((1-rbs.bottomValue) * (destRect.bottom - destRect.top));
|
||
right := left + boundsWidth;
|
||
bottom := top + boundsHeight;
|
||
end;
|
||
|
||
LongInt(offset) := 0;
|
||
|
||
if BTST(rbs.whole,kShiftBit) then
|
||
offset.v := kHMPointerSize * rbs.bottomValue
|
||
else
|
||
offset.h := kHMPointerSize * rbs.rightValue;
|
||
|
||
offset.h := offset.h + (rbs.rightValue * kHMFrameThickness) - ((1-rbs.rightValue) * kHMPointerSize);
|
||
offset.v := offset.v + (rbs.bottomValue * kHMFrameThickness) - ((1-rbs.bottomValue) * kHMPointerSize);
|
||
|
||
OffsetRect(balloonBounds,offset.h,offset.v);
|
||
|
||
__HMTwitchVarCode(kRBSToVariant,INTEGER(rbs),variant);
|
||
|
||
__HMBestWorld := noErr;
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMCalculateBalloon( aHelpMsg: HMMessageRecord;
|
||
tip: Point;
|
||
alternateRect: RectPtr;
|
||
VAR varCode: INTEGER;
|
||
VAR bounds: Rect; VAR pic: PicHandle;
|
||
balloonType: INTEGER;
|
||
abortable: BOOLEAN): OsErr;
|
||
|
||
VAR gp : HMGlobalPtr;
|
||
screenBounds : Rect;
|
||
areaRect : Rect;
|
||
visibleRect : Rect;
|
||
gh : GDHandle;
|
||
oldDevice : GDHandle;
|
||
oldPort : GrafPtr;
|
||
tPort : GrafPtr;
|
||
picPort : GrafPort;
|
||
err : INTEGER;
|
||
pt : Point;
|
||
slopTip : Point;
|
||
aTE : TEHandle;
|
||
tix : LongInt;
|
||
sloppy : BOOLEAN;
|
||
hasColorQD : BOOLEAN;
|
||
oldZone : THz; { <SM2> }
|
||
|
||
BEGIN
|
||
__HMCalculateBalloon := hmBalloonAborted; { make default case aborted }
|
||
gp := __HMGetHelpGlobal;
|
||
pic := NIL; { <59> make sure pic is NIL in case we exit early }
|
||
|
||
if abortable then
|
||
begin
|
||
tix := Tickcount;
|
||
with gp^ do
|
||
begin
|
||
if (hmgDelay - (tix - hmgTix)) > 0 then
|
||
exit(__HMCalculateBalloon); { exit if not enough time has elapsed }
|
||
hmgTix := tix;
|
||
end;
|
||
end;
|
||
|
||
oldDevice := NIL;
|
||
sloppy := false;
|
||
slopTip := __HMGetGlobalMouse;
|
||
hasColorQD := gp^.hmgHasColorQD;
|
||
|
||
if hasColorQD then
|
||
begin
|
||
{ *** do we want to use the tip's GDevice or the mouse point's ? }
|
||
gh := __HMGetScreenGDevice(slopTip); { use the mouse's GDevice }
|
||
if gh<>NIL then
|
||
begin
|
||
screenBounds := gh^^.gdRect;
|
||
oldDevice := GetGDevice;
|
||
SetGDevice(gh);
|
||
end else
|
||
exit(__HMCalculateBalloon); { how could the mouse be offscreen? }
|
||
end else
|
||
begin
|
||
screenBounds := GetGrayRgn^^.rgnBBox;
|
||
screenBounds.top := 0;
|
||
end;
|
||
|
||
if alternateRect<>NIL then
|
||
begin
|
||
areaRect := alternateRect^;
|
||
if not __HMPinTipAndAltRect(screenBounds,tip,areaRect) then
|
||
begin
|
||
if oldDevice<>NIL then { =NIL for non-color ports }
|
||
SetGDevice(oldDevice);
|
||
|
||
exit(__HMCalculateBalloon);
|
||
end;
|
||
end else
|
||
begin
|
||
LongInt(tip) := PinRect(screenBounds,tip);
|
||
with areaRect do
|
||
begin
|
||
topLeft := tip;
|
||
bottom := tip.v + 1;
|
||
right := tip.h + 1;
|
||
end;
|
||
end;
|
||
|
||
|
||
{$ifc HelpMgrTesting}
|
||
Assert(EmptyRect(areaRect),'HMCalculateBalloon: Empty area Rect!');
|
||
{$endc}
|
||
|
||
GetPort(oldPort);
|
||
|
||
{if hasColorQD then
|
||
OpenCPort(@picPort)
|
||
else }OpenPort(@picPort);
|
||
|
||
SetPort(@picPort);
|
||
|
||
with gp^ do
|
||
begin
|
||
TextFont(hmgFontAndSize.hmgFont);
|
||
TextSize(hmgFontAndSize.hmgFontSize);
|
||
|
||
hmgKeepTEHandle := true; {we don't want the __HMBalloonRect() call to toss the TEHandle (if any)}
|
||
hmgTEHandle := NIL; {in case __HMBalloonRect fails}
|
||
end;
|
||
|
||
SetRect(bounds,0,0,0,0);
|
||
err := __HMBalloonRect(aHelpMsg,bounds);
|
||
|
||
__HMCalculateBalloon := err;
|
||
|
||
if err=noErr then
|
||
begin
|
||
err := __HMBestWorld(screenBounds,tip,areaRect,balloonType,bounds,varCode);
|
||
|
||
{$ifc HelpMgrTesting}
|
||
if err<>noErr then
|
||
DebugStr('Unable to fit balloon on screen…');
|
||
{$endc}
|
||
end;
|
||
|
||
if err<>noErr then
|
||
begin
|
||
{if hasColorQD then
|
||
CloseCPort(@picPort)
|
||
else} ClosePort(@picPort);
|
||
|
||
SetPort(oldPort);
|
||
|
||
if oldDevice<>NIL then { always NIL for non-color ports }
|
||
SetGDevice(oldDevice);
|
||
exit(__HMCalculateBalloon);
|
||
end;
|
||
|
||
with bounds do
|
||
begin
|
||
SetRect(visibleRect,0,0,right-left,bottom-top);
|
||
|
||
right := right + kHMHorizContentMargin;
|
||
bottom := bottom + kHMVertContentMargin;
|
||
end;
|
||
|
||
aTE := gp^.hmgTEHandle;
|
||
|
||
if not __HMSlopMouse(slopTip) or not abortable then
|
||
begin
|
||
with aHelpMsg do
|
||
case hmmHelpType of
|
||
khmmPict,khmmPictHandle:
|
||
if hmmHelpType = khmmPict then
|
||
pic := PicHandle(GetResource('PICT',hmmPict))
|
||
else pic := hmmPictHandle;
|
||
|
||
khmmTEHandle:
|
||
begin
|
||
aTE := hmmTEHandle;
|
||
if aTE<>NIL then
|
||
begin
|
||
with aTE^^ do
|
||
begin
|
||
tPort := inPort;
|
||
inPort := @picPort;
|
||
end;
|
||
|
||
oldZone := GetZone; { get the current heap zone } { <SM2> }
|
||
SetZone(SystemZone); { point at the system heap } { <SM2> }
|
||
{ <SM2> }
|
||
pic := OpenPicture(visibleRect);
|
||
TEUpdate(visibleRect,aTE);
|
||
ClosePicture;
|
||
|
||
SetZone(oldZone); { <SM2> }
|
||
{ <SM2> }
|
||
with aTE^^ do
|
||
inPort := tPort;
|
||
end;
|
||
end;
|
||
|
||
otherwise
|
||
if aTE<>NIL then
|
||
begin
|
||
oldZone := GetZone; { get the current heap zone } { <SM2> }
|
||
SetZone(SystemZone); { point at the system heap } { <SM2> }
|
||
{ <SM2> }
|
||
pic := OpenPicture(visibleRect);
|
||
TEUpdate(visibleRect,aTE);
|
||
ClosePicture;
|
||
{ <SM2> }
|
||
SetZone(oldZone); { <SM2> }
|
||
{ <SM2> }
|
||
end;
|
||
end;
|
||
|
||
end else Sloppy := true;
|
||
|
||
if aHelpMsg.hmmHelpType<>khmmTEHandle then
|
||
if aTE<>NIL then
|
||
TEDispose(aTE);
|
||
|
||
with gp^ do
|
||
begin
|
||
hmgTEHandle := NIL;
|
||
hmgKeepTEHandle := false;
|
||
end;
|
||
|
||
{if hasColorQD then
|
||
CloseCPort(@picPort)
|
||
else} ClosePort(@picPort);
|
||
|
||
SetPort(oldPort);
|
||
|
||
if oldDevice<>NIL then {=NIL for non-color ports}
|
||
SetGDevice(oldDevice);
|
||
|
||
if Sloppy | (pic = NIL) then
|
||
begin
|
||
gp^.hmgItemNum := -1;
|
||
|
||
__HMCalculateBalloon := memFullErr;
|
||
|
||
if pic<>NIL then
|
||
begin
|
||
if __HMCanPictureBeKilled(aHelpMsg.hmmHelpType) then { <59> Kill picture if it wasn't resource based }
|
||
KillPicture(pic);
|
||
pic := NIL;
|
||
end;
|
||
|
||
if Sloppy then
|
||
__HMCalculateBalloon := hmBalloonAborted;
|
||
|
||
exit(__HMCalculateBalloon);
|
||
end;
|
||
|
||
{ <58> the third call to HMSlopMouse below means that HMCalculate can return w/ an error
|
||
but still return (in VAR pic) a valid picture handle, the calling code must call
|
||
KillPicture() to dispose of it in this case!! Memory leak bug in 7.0b1 }
|
||
|
||
if (abortable and __HMSlopMouse(slopTip)) or EmptyRect(bounds) then { <58> add abortable }
|
||
__HMCalculateBalloon := hmBalloonAborted;
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMSetupBalloonRgns( varCode: INTEGER;
|
||
VAR structRgn: RgnHandle;
|
||
VAR contentRgn: RgnHandle;
|
||
VAR bounds: Rect): OsErr;
|
||
|
||
{ Balloon Tip Variants
|
||
|
||
The diagram below relates the varcode parameter value to the bubble
|
||
tip position and orientation. The table below shows the Unit
|
||
Vectors which are used to draw the tip.
|
||
|
||
1 2
|
||
|
||
* *
|
||
|\ /|
|
||
| \ / | NOTES
|
||
0 *---------------------* 3
|
||
\ | | / a. The 8 asterisks indicate the 8
|
||
\| |/ bubble tips.
|
||
| Bubble |
|
||
| Structure | b. The digits are the varcode values for each
|
||
| Rectangle | bubble tip.
|
||
/| |\
|
||
/ | | \
|
||
7 *---------------------* 4 c. The hCorner,vCorner columns below are a unit vector from
|
||
| / \ | the corner to the bubble tip.
|
||
|/ \|
|
||
* * d. The hBase,vBase columns are a unit vector from the
|
||
bubble tip to the base of the diagonal.
|
||
6 5
|
||
|
||
Pointing
|
||
varcode Hotspot Location Direction hCorner vCorner hBase vBase
|
||
------- ---------------- --------- ------ ------- ------- -------
|
||
0 Top, Left Left -1 0 1 1
|
||
1 Top, Left Up 0 -1 1 1
|
||
2 Top, Right Up 0 -1 -1 1
|
||
3 Top, Right Right 1 0 -1 1
|
||
4 Bottom, Right Right 1 0 -1 -1
|
||
5 Bottom, Right Down 0 1 -1 -1
|
||
6 Bottom, Left Down 0 1 1 -1
|
||
7 Bottom, Left Left -1 0 1 -1
|
||
}
|
||
|
||
VAR frame : Rect;
|
||
originalFrame : Rect;
|
||
tempRgn : RgnHandle;
|
||
bias : biasRecord;
|
||
BEGIN
|
||
RectRgn(contentRgn, bounds);
|
||
|
||
frame := bounds;
|
||
InsetRect(frame,-kHMFrameThickness,-kHMFrameThickness);
|
||
|
||
originalFrame := frame;
|
||
|
||
varCode := BAnd($0007,varCode); { strip off hi bits of varCode, in case the varCode is out of range }
|
||
|
||
with frame.topleft do
|
||
begin
|
||
if varCode >= 4 then
|
||
v := frame.bottom;
|
||
|
||
if (varCode >= 2) then if (varCode <= 5) then
|
||
h := frame.right;
|
||
|
||
__HMVarCodeToBiasRecord(varCode,bias);
|
||
|
||
with bias do
|
||
begin
|
||
h := h + (kHMPointerSize * hCornerVector);
|
||
v := v + (kHMPointerSize * vCornerVector);
|
||
|
||
OpenRgn;
|
||
FrameRoundRect(originalFrame, kHMCornerDiameter, kHMCornerDiameter);
|
||
|
||
MoveTo(h,v);
|
||
Line(hBaseVector * kHMPointerSize,VBaseVector * kHMPointerSize);
|
||
Line(DicksOffsetPixels * hShift, DicksOffsetPixels * vShift);
|
||
LineTo(h,v);
|
||
CloseRgn(structRgn);
|
||
end;
|
||
end;
|
||
|
||
tempRgn := GetGrayRgn;
|
||
SectRgn(tempRgn, structRgn, structRgn);
|
||
SectRgn(tempRgn, contentRgn, contentRgn);
|
||
|
||
__HMSetupBalloonRgns := noErr;
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMDrawBalloonFrame(rgn: RgnHandle): OsErr;
|
||
VAR oldClip : RgnHandle;
|
||
BEGIN
|
||
oldClip := NewRgn;
|
||
|
||
{$ifc HelpMgrTesting}
|
||
Assert(oldClip=NIL,'HMDrawBalloonFrame[1]: NIL Region for NewRgn call');
|
||
{$endc}
|
||
|
||
GetClip(oldClip);
|
||
|
||
EraseRgn(rgn);
|
||
FrameRgn(rgn);
|
||
SetClip(rgn);
|
||
OffsetRgn(rgn, -1, -1);
|
||
FrameRgn(rgn);
|
||
OffsetRgn(rgn, 1, 1);
|
||
|
||
SetClip(oldClip);
|
||
__HMDisposeRgn(oldClip);
|
||
|
||
__HMDrawBalloonFrame := noErr;
|
||
END;
|
||
|
||
|
||
FUNCTION __HMSaveBalloonBits(aHelpMsg: HMMessageRecord;
|
||
tip: Point;
|
||
alternateRect: RectPtr;
|
||
tipProc: Ptr;
|
||
variant: INTEGER;
|
||
balloonType: INTEGER): OsErr;
|
||
VAR bounds : Rect;
|
||
bitsbounds : Rect;
|
||
oldBounds : Rect;
|
||
pic : PicHandle;
|
||
result : OsErr;
|
||
varCode : INTEGER;
|
||
wVarCode : INTEGER;
|
||
wBounds : Rect;
|
||
oldPort : GrafPtr;
|
||
wPort : GrafPtr;
|
||
oldClipRgn : RgnHandle;
|
||
wideOpenRgn : RgnHandle;
|
||
aStructRgn : RgnHandle;
|
||
aContentRgn : RgnHandle;
|
||
oldState : SignedByte;
|
||
BEGIN
|
||
GetPort(oldPort);
|
||
GetWMgrPort(wPort);
|
||
SetPort(wPort);
|
||
|
||
oldClipRgn := NewRgn;
|
||
|
||
if oldClipRgn<>NIL then
|
||
begin
|
||
GetClip(oldClipRgn);
|
||
|
||
wideOpenRgn := NewRgn;
|
||
|
||
if wideOpenRgn<>NIL then
|
||
begin
|
||
SetRectRgn(wideOpenRgn,-32768,-32768,32767,32767);
|
||
SetClip(wideOpenRgn);
|
||
__HMDisposeRgn(wideOpenRgn);
|
||
end;
|
||
|
||
varCode := variant;
|
||
|
||
result := __HMCalculateBalloon(aHelpMsg,tip,alternateRect,varCode,bounds,pic,balloonType,true{can be aborted});
|
||
if result = noErr then { we can display a balloon }
|
||
begin
|
||
if __HMRemoveBalloon=noErr then; { toss any existing Balloons, if we get this far }
|
||
|
||
aStructRgn := NewRgn;
|
||
aContentRgn := NewRgn;
|
||
|
||
result := __HMSetupBalloonRgns(varCode,aStructRgn,aContentRgn,bounds);
|
||
|
||
if tipProc<>NIL then
|
||
begin
|
||
wBounds := bounds;
|
||
wVarCode := varCode;
|
||
|
||
result := __HMCallTipProc(tipProc,tip,aStructRgn,wBounds,wVarCode); { <58> give the caller a chance to abort }
|
||
|
||
if result = noErr then { <58> balloon might have changed a bit, so update info }
|
||
if (wVarCode<>varCode) |
|
||
(LongInt(wBounds.topLeft)<>LongInt(bounds.topLeft)) |
|
||
(LongInt(wBounds.botRight)<>LongInt(bounds.botRight)) then
|
||
begin
|
||
bounds := wBounds;
|
||
varCode := wVarCode;
|
||
|
||
if __HMSetupBalloonRgns(varCode,aStructRgn,aContentRgn,bounds)=noErr then; { <58> recalculate the balloon's regions }
|
||
end;
|
||
|
||
end else
|
||
result := noErr;
|
||
|
||
if result = noErr then
|
||
with __HMGetHelpGlobal^ do
|
||
begin
|
||
bitsbounds := aStructRgn^^.rgnBBox;
|
||
hmgSavedBitsHandle := __HMSaveBitsInRect(bitsbounds);
|
||
|
||
if hmgSavedBitsHandle<>NIL then
|
||
begin
|
||
if __HMDrawBalloonFrame(aStructRgn)=noErr then;
|
||
|
||
if pic<>NIL then
|
||
begin
|
||
SetClip(aContentRgn);
|
||
|
||
if pic^ = NIL then { <58> the pic was really a resource that was purged }
|
||
LoadResource(Handle(pic));
|
||
|
||
if pic^ <> NIL then { <58> the pic was successfully reloaded (if purged) }
|
||
begin
|
||
oldState := HGetState(Handle(pic)); { <58> remember pic handle's state }
|
||
HNoPurge(Handle(pic)); { <58> keep it around (if resource) }
|
||
|
||
oldBounds := pic^^.picFrame; { <58> keep old picture bounds as we're offsetting the frame }
|
||
|
||
with pic^^.picFrame do
|
||
begin
|
||
bounds.right := bounds.left + (right-left);
|
||
bounds.bottom := bounds.top + (bottom-top);
|
||
end;
|
||
|
||
DrawPicture(pic,bounds);
|
||
pic^^.picFrame := oldBounds; { <58> restore old picture bounds }
|
||
|
||
HSetState(Handle(pic),oldState); { <58> restore picture handle state }
|
||
end;
|
||
end;
|
||
end else
|
||
result := memFullErr;
|
||
end;
|
||
|
||
__HMDisposeRgn(aStructRgn);
|
||
__HMDisposeRgn(aContentRgn);
|
||
end;
|
||
|
||
if (pic<>NIL) then
|
||
if __HMCanPictureBeKilled(aHelpMsg.hmmHelpType) then { <59> Kill picture if it wasn't resource based }
|
||
KillPicture(pic); { bug before <58> [used to be before DisposeRgn(aStructRgn) above] }
|
||
|
||
SetClip(oldClipRgn);
|
||
DisposeRgn(oldClipRgn); { we don't need to NIL check handle here }
|
||
|
||
end else
|
||
result := memFullErr;
|
||
|
||
SetPort(oldPort);
|
||
|
||
__HMSaveBalloonBits := result;
|
||
END;
|
||
|
||
|
||
FUNCTION __HMGetHelpItemResID(d: DialogPtr; whichOne: INTEGER; VAR kind: INTEGER; VAR offset: INTEGER): INTEGER;
|
||
VAR numItems : INTEGER;
|
||
dataSize : INTEGER;
|
||
i : INTEGER;
|
||
hItems : hItemList;
|
||
pItem : pDITLItem;
|
||
USB : SByteArray;
|
||
count : INTEGER;
|
||
BEGIN
|
||
__HMGetHelpItemResID := -1;
|
||
|
||
count := 1;
|
||
hItems := hItemList(DialogPeek(d)^.items);
|
||
numItems := hItems^^.dlgMaxIndex + 1;
|
||
pItem := @hItems^^.DITLItems;
|
||
|
||
for i := 1 to numItems do { code below is handle safe! }
|
||
begin
|
||
USB.Int := 0;
|
||
USB.SBArray[1] := pItem^.itmData[0];
|
||
|
||
with pItem^ do
|
||
if BAnd(itmType,$7F)=kHelpItem then
|
||
if count = whichOne then
|
||
begin
|
||
kind := IntegerPtr(@itmdata[kHelpItemType])^;
|
||
|
||
{ always check the ranges we know in case in the future we use HelpItem for something else }
|
||
if (kind = kScanhdlg) or (kind = kScanhrct) or (kind = kScanAppendhdlg) then
|
||
begin
|
||
__HMGetHelpItemResID := IntegerPtr(@itmdata[kHelpItemData])^;
|
||
offset := 0;
|
||
|
||
if kind = kScanAppendhdlg then
|
||
offset := IntegerPtr(@itmdata[kHelpItemOffset])^;
|
||
end;
|
||
leave;
|
||
end else
|
||
count := count + 1;
|
||
|
||
dataSize := BAnd(USB.Int + 1, $FFFE);
|
||
pItem := pDITLItem(ptr(ord4(@pItem^) + datasize + sizeof(DITLItem)));
|
||
end;
|
||
END;
|
||
|
||
FUNCTION __HMCountDITLHelpItems(d: DialogPtr): INTEGER;
|
||
VAR numItems : INTEGER;
|
||
i : INTEGER;
|
||
itemType : INTEGER;
|
||
itemHandle : Handle;
|
||
itemRect : Rect;
|
||
count : INTEGER;
|
||
BEGIN
|
||
count := 0;
|
||
numItems := hItemList(DialogPeek(d)^.items)^^.dlgMaxIndex + 1;
|
||
for i := 1 to numItems do
|
||
begin
|
||
GetDItem(d,i,itemType,itemHandle,itemRect);
|
||
|
||
if BAnd(itemType,$7F)=kHelpItem then
|
||
count := count + 1;
|
||
end;
|
||
__HMCountDITLHelpItems := count;
|
||
END;
|
||
|
||
|
||
FUNCTION __HMSameItemState(theDialog: DialogPtr; thePoint: Point;
|
||
VAR item: INTEGER; VAR state: INTEGER; VAR itemRect: Rect): BOOLEAN;
|
||
{ Finds an item in theDialog at thePoint and returns true if the item & state were the same, therefore,
|
||
no balloon needs to be redrawn. It returns the item & state as VAR params.
|
||
}
|
||
VAR value : INTEGER;
|
||
itemType : INTEGER;
|
||
itemHandle : Handle;
|
||
BEGIN
|
||
__HMSameItemState := false; { say that we need to redraw the balloon }
|
||
item := FindDItem(theDialog,thePoint);
|
||
|
||
if item >= 0 then
|
||
begin
|
||
item := item + 1; { convert to GetDItem offset (always 1 based) }
|
||
|
||
GetDItem(theDialog,item,itemType,itemHandle,itemRect); { get the item's info }
|
||
|
||
if BAnd(itemType,$80)<>0 then { item was disabled }
|
||
state := kHMDisabledItem else
|
||
state := kHMEnabledItem; { otherwise it was enabled }
|
||
|
||
value := BAnd(itemType,$7F); { toss item's disabled bit }
|
||
|
||
if (value >= ctrlItem + btnCtrl) then
|
||
if (value <= ctrlItem + resCtrl) then { if item is a button, checkbox, or 'CNTL' then… }
|
||
with ControlHandle(itemHandle)^^ do { convert it's state to it's value }
|
||
begin
|
||
if contrlHilite = 255 then { the item's control was gray, make it a disabled item }
|
||
state := kHMDisabledItem;
|
||
|
||
if value = ctrlItem + btnCtrl then
|
||
begin
|
||
if GetCtlMax(ControlHandle(itemHandle))>1 then
|
||
if state = kHMEnabledItem then
|
||
state := kHMCheckedItem
|
||
else state := kHMOtherItem;
|
||
end else
|
||
if state = kHMEnabledItem then { <68> BHTCA0080, check for 'checked' or 'other' only if enabled }
|
||
begin
|
||
if contrlValue = 1 then { the item's control value was 1, make it a checked item }
|
||
state := kHMCheckedItem
|
||
else if contrlValue > 1 then { the item's control value was >1, make it an 'other' item }
|
||
state := kHMOtherItem;
|
||
end;
|
||
end;
|
||
|
||
with __HMGetHelpGlobal^ do { return true if item & state were the same as last time }
|
||
__HMSameItemState := (hmgState = state) and (hmgItemNum = item);
|
||
end;
|
||
END;
|
||
|
||
FUNCTION __HMTrackModalHelpItems: OsErr;
|
||
VAR d : DialogPtr;
|
||
result : OsErr;
|
||
itemRect : Rect;
|
||
helpTemplateID : INTEGER;
|
||
founditem : INTEGER;
|
||
eachHelpItem : INTEGER;
|
||
state : INTEGER;
|
||
theProc : INTEGER;
|
||
variant : INTEGER;
|
||
index : INTEGER;
|
||
altRect : Rect;
|
||
pt : Point;
|
||
err : OsErr;
|
||
i : INTEGER;
|
||
aHelpMsg : HMMessageRecord;
|
||
gp : HMGlobalPtr;
|
||
oldPort : GrafPtr;
|
||
options : LongInt;
|
||
helpItemCount : INTEGER;
|
||
kind : INTEGER;
|
||
offset : INTEGER;
|
||
count : INTEGER;
|
||
method : LongInt;
|
||
currentPSN : ProcessSerialNumber;
|
||
frontPSN : ProcessSerialNumber;
|
||
sameResult : BOOLEAN;
|
||
|
||
BEGIN
|
||
if __HMGetHelpGlobal^.hmgOurDialog then { if our dialog is in front then call bulk once to kick menuselect }
|
||
if __HMBalloonBulk=noErr then;
|
||
|
||
__HMTrackModalHelpItems := noErr;
|
||
|
||
{ we already checked to see if Balloon Help mode was on }
|
||
d := FrontWindow;
|
||
|
||
if d=NIL then exit(__HMTrackModalHelpItems);
|
||
|
||
{ quik check to see if the front window is truely a dialog }
|
||
if WindowPeek(d)^.windowKind<>DialogKind then exit(__HMTrackModalHelpItems);
|
||
|
||
{ <74> now make sure that we're being executed from the frontmost process, otherwise exit }
|
||
err := GetCurrentProcess(currentPSN); { <74> }
|
||
if err = noErr then { <74> }
|
||
begin { <74> }
|
||
err := GetFrontProcess(frontPSN); { <74> }
|
||
if err = noErr then { <74> }
|
||
err := SameProcess(currentPSN,frontPSN,sameResult); { <74> }
|
||
end; { <74> }
|
||
if not sameResult or (err <> noErr) then { <74> }
|
||
exit(__HMTrackModalHelpItems); { <74> }
|
||
|
||
helpItemCount := __HMCountDITLHelpItems(d); { returns how many help items are in the dialog's item list }
|
||
|
||
if helpItemCount>0 then { there weren't any help items in the dialog so scram! }
|
||
begin
|
||
GetPort(oldPort);
|
||
SetPort(d);
|
||
GetMouse(pt);
|
||
|
||
if PtInRect(pt,d^.portrect) then { make sure local mouse is in window portrect }
|
||
begin
|
||
result := -1;
|
||
gp := __HMGetHelpGlobal;
|
||
|
||
if __HMSameItemState(d,pt,foundItem,state,itemRect) then
|
||
begin
|
||
SetPort(oldPort);
|
||
Exit(__HMTrackModalHelpItems);
|
||
end;
|
||
|
||
for eachHelpItem := 1 to helpItemCount do { check each help item present in the dialog item list }
|
||
begin
|
||
helpTemplateID := __HMGetHelpItemResID(d,eachHelpItem,kind,offset);
|
||
if helpTemplateID <> -1 then
|
||
begin
|
||
if (kind = kScanhrct) then
|
||
begin
|
||
result := __HMScanHRCTResource(WindowPtr(d),helpTemplateID,pt,index);
|
||
if result = noErr then
|
||
begin
|
||
with gp^ do { check to see if these were the same as last time, if so, exit! }
|
||
if (helpTemplateID = hmgState) then if (index = hmgItemNum) then
|
||
begin
|
||
SetPort(oldPort);
|
||
Exit(__HMTrackModalHelpItems);
|
||
end;
|
||
|
||
result := __HMGetIndHelpMsg(kHMRectListResType,helpTemplateID,
|
||
index,kHMEnabledItem,options,pt,@itemRect,
|
||
theProc,variant,aHelpMsg,count);
|
||
|
||
if result = noErr then
|
||
begin
|
||
state := helpTemplateID;
|
||
founditem := index;
|
||
end;
|
||
end;
|
||
end else
|
||
begin
|
||
if founditem >= 0 then
|
||
result := __HMFillInDialogMessage( helpTemplateID,founditem,
|
||
eachHelpItem,helpItemCount,
|
||
state,offset,-1{current resfile},options,pt,@altRect,
|
||
theProc,variant,aHelpMsg);
|
||
|
||
if result = noErr then
|
||
with itemRect do { correct the dialog item's hot rect [<59> always add in altRect params] }
|
||
begin
|
||
left := left + altRect.left;
|
||
top := top + altRect.top;
|
||
right := right + altRect.right;
|
||
bottom := bottom + altRect.bottom;
|
||
end;
|
||
end;
|
||
|
||
case result of
|
||
noErr,hmSkippedBalloon:
|
||
leave;
|
||
|
||
otherwise { including hmGetNextHelpItem }
|
||
cycle;
|
||
|
||
end; { case }
|
||
|
||
end else { end helpTemplateID=-1 }
|
||
{$ifc HelpMgrTesting}
|
||
DebugStr('HMGetHelpItemResID returned a -1 for a hdlg resource ID');
|
||
{$endc}
|
||
|
||
end; { end of for loop }
|
||
|
||
if result = noErr then { we hit something; either an hdlg driven item or hrct driven rect }
|
||
begin
|
||
altRect := itemRect;
|
||
|
||
with altRect do
|
||
begin
|
||
LocalToGlobal(topLeft); { note: the port is set already }
|
||
LocalToGlobal(botRight);
|
||
|
||
if LongInt(pt)=0 then
|
||
begin
|
||
pt := botRight;
|
||
pt.h := pt.h - 10;
|
||
pt.v := pt.v - 10;
|
||
end else { setup the tip as it wasn't the special 'EmptyPt' case }
|
||
if (kind <> kScanhrct) then
|
||
begin
|
||
pt.h := pt.h + left; { for 'hdlg's move the tip relative to the item's rect }
|
||
pt.v := pt.v + top;
|
||
end else
|
||
LocalToGlobal(pt); { for 'hrct's just convert the tip to global coords }
|
||
end;
|
||
|
||
method := BSR(BAnd(options,$0000000C),2);
|
||
result := __HMShowBalloon(aHelpMsg,pt,@altRect,
|
||
NIL,theProc,variant,method);
|
||
|
||
if result = noErr then
|
||
with gp^ do
|
||
begin
|
||
hmgLastWindowPtr := d;
|
||
hmgItemNum := founditem;
|
||
hmgState := state;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
SetPort(oldPort);
|
||
|
||
end; { helpItemCount>0 }
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMShowContentBalloon( tip: Point; alternateRect: Rect;
|
||
theProc,variant: INTEGER;
|
||
aHelpMsg: HMMessageRecord; options: LongInt): OsErr;
|
||
BEGIN
|
||
{Note: port is already set, and front window cannot be NIL!}
|
||
|
||
LocalToGlobal(tip); {yucko!}
|
||
LocalToGlobal(alternateRect.topLeft);
|
||
LocalToGlobal(alternateRect.botRight);
|
||
|
||
if BTst(options,kBTSTAbsoluteCoords) then
|
||
with FrontWindow^.portrect,tip do
|
||
begin
|
||
{tip.}h := {tip.}h + left;
|
||
{tip.}v := {tip.}v + top;
|
||
|
||
OffsetRect(alternateRect,left,top);
|
||
end;
|
||
|
||
__HMShowContentBalloon := __HMShowBalloon(aHelpMsg,tip,@alternateRect,NIL,theProc,variant,0);
|
||
|
||
{ hmgLastBalloon information is set in BalloonPack.a, when a balloon comes up }
|
||
END;
|
||
|
||
|
||
PROCEDURE __HMShowEasyAccessBalloon;
|
||
VAR aHelpMsg : HMMessageRecord;
|
||
altRect : Rect;
|
||
pt : Point;
|
||
result : LongInt;
|
||
BEGIN
|
||
if Gestalt(gestaltEasyAccessAttr,result) = noErr then { Easy Access is installed }
|
||
if GetMBARRect(altRect)=noErr then
|
||
begin
|
||
altRect.left := altRect.right-10;
|
||
|
||
if PtInRect(__HMGetGlobalMouse,altRect) then
|
||
with __HMGetHelpGlobal^ do
|
||
begin
|
||
result := BAnd($0007,result); { toss hi bits so that Don Brady can use the call for somethin' else }
|
||
|
||
if (hmgMenuID = kwasEasyAccess) then if (hmgItemNum = result) then
|
||
Exit(__HMShowEasyAccessBalloon);
|
||
|
||
if (result = 0) then
|
||
begin
|
||
if __HMIsBalloon then
|
||
if __HMRemoveBalloon=noErr then;
|
||
exit(__HMShowEasyAccessBalloon);
|
||
end;
|
||
|
||
with aHelpMsg do
|
||
begin
|
||
hmmHelpType := khmmString;
|
||
GetIndString(hmmString,kHMHelpID,kHMEasy1Access-1+result);
|
||
|
||
if length(hmmString)=0 then
|
||
exit(__HMShowEasyAccessBalloon);
|
||
end;
|
||
|
||
pt.h := altRect.left + 5;
|
||
pt.v := altRect.bottom;
|
||
|
||
if __HMShowBalloon(aHelpMsg,pt,@altRect,NIL,0,2,0)=noErr then
|
||
begin
|
||
hmgItemNum := result;
|
||
hmgMenuID := kwasEasyAccess;
|
||
hmgTitleBalloon := 1; { treat this balloon as if it was a menu title balloon }
|
||
end;
|
||
end;
|
||
end;
|
||
END;
|
||
|
||
|
||
FUNCTION __HMGetWindowPartCode(VAR window: WindowPtr): INTEGER;
|
||
{ returns the typical FindWindow result codes:
|
||
inDesk = 0;
|
||
inMenuBar = 1;
|
||
inSysWindow = 2;
|
||
inContent = 3;
|
||
inDrag = 4;
|
||
inGrow = 5;
|
||
inGoAway = 6;
|
||
inZoomIn = 7;
|
||
inZoomOut = 8;
|
||
|
||
Note: Don't call this unless curLayer == applicationLayer
|
||
}
|
||
|
||
VAR layer : LayerPtr;
|
||
saveLayer : LayerPtr;
|
||
pt : Point;
|
||
windowCode : INTEGER;
|
||
variant : INTEGER;
|
||
err : OsErr;
|
||
PSN : ProcessSerialNumber;
|
||
info : ProcessInfoRec;
|
||
modalClass : INTEGER;
|
||
windowIsFloater : BOOLEAN;
|
||
gp : HMGlobalPtr;
|
||
|
||
BEGIN
|
||
pt := __HMGetGlobalMouse;
|
||
|
||
|
||
{
|
||
look in the IMlayer first, and explicitly set savelayer to NIL
|
||
}
|
||
saveLayer := NIL;
|
||
windowIsFloater := false;
|
||
windowCode := FindServiceWindow(pt,window);
|
||
|
||
if ( windowCode <> inDesk ) and ( windowCode <> inMenuBar ) then { appears that we have something in the IMlayer }
|
||
begin
|
||
saveLayer := SwapCurLayer(LayerPtr(GetParent(window)));
|
||
windowIsFloater := true;
|
||
end else
|
||
windowCode := FindWindow(pt,window);
|
||
|
||
if windowCode = inSysWindow then
|
||
windowCode := __HMGetRealWindowHitResult(pt,window);
|
||
|
||
case windowCode of
|
||
inGrow:
|
||
windowCode := inContent;
|
||
{ *** someday, figure out whether the grow box is really visible!
|
||
the code below doesn't work correctly as developers really
|
||
don't use the correct type of window for their applications!
|
||
begin
|
||
variant := GetWVariant(window);
|
||
if variant <> documentProc then
|
||
windowCode := inContent;
|
||
end;
|
||
}
|
||
|
||
inZoomOut:
|
||
windowCode := inZoomIn;
|
||
end;
|
||
|
||
if (windowCode = inDesk) and (window<>FrontWindow) then { we're in the desk or in another layer's window }
|
||
begin
|
||
saveLayer := SwapCurLayer(NIL); {set curLayer to RootLayer}
|
||
windowCode := FindWindow(pt,window);
|
||
SetCurLayer(saveLayer);
|
||
saveLayer := NIL; {<79> set this to NIL so we can test below}
|
||
|
||
if (GetFrontWindowModalClass(modalClass) = noErr) and (modalClass = dBoxProc) then { <60> don't put up a balloon for window areas outside a modal dialog }
|
||
windowCode := kHMOutsideModalWindow;
|
||
|
||
with __HMGetHelpGlobal^ do
|
||
begin
|
||
if (window=hmgLayer) or (window=hmgWindow) then
|
||
begin
|
||
windowCode := hmgLastPartCode;
|
||
window := hmgLastWindowPtr;
|
||
end else
|
||
if (windowCode <> inDesk) and (windowCode <> kHMOutsideModalWindow) then { <61> and if code isnt kHMOutsideModalWindow }
|
||
begin
|
||
if GetProcessFromLayer(PSN,window)=noErr then { works w/ WindowPtrs }
|
||
begin
|
||
with info do
|
||
begin
|
||
processInfoLength := Sizeof(ProcessInfoRec);
|
||
processName := @hmgProcessName;
|
||
processAppSpec := NIL;
|
||
end;
|
||
|
||
if GetProcessInformation(PSN,info)=noErr then
|
||
begin
|
||
windowCode := kHMInLayerPreamble;
|
||
__HMStripNullFromProcessName(@hmgProcessName);
|
||
end;
|
||
|
||
end else windowCode := kHMInOtherWindow;
|
||
end else
|
||
begin
|
||
{ *** the window code was inDesk (probably the Finder desktop), so lets do somethin' }
|
||
end;
|
||
end;
|
||
end else
|
||
begin
|
||
{ if (window<>NIL) then if (ORD(WindowPeek(window)^.hilited) = ORD(false)) and ( NOT windowIsFloater) then } { mouse isn't in a hilited window and it isn't a floater }
|
||
|
||
if (window<>NIL) then
|
||
if (ORD(WindowPeek(window)^.hilited) = ORD(false)) then { mouse isn't in a hilited window }
|
||
begin
|
||
if ( windowIsFloater ) then { it is a floater }
|
||
begin
|
||
if ( windowCode = inContent ) then { and the mouse is in content region }
|
||
windowCode := kHMInFrontFloatingWindow; { special Balloon for frontmost floater }
|
||
end
|
||
else { not a floater }
|
||
begin
|
||
windowCode := kHMInOtherWindow;
|
||
|
||
if (GetFrontWindowModalClass(modalClass) = noErr) then
|
||
if (modalClass = movableDBoxProc) or (modalClass = dBoxProc) then { <60> don't put up a balloon for window areas outside a modal dialog }
|
||
windowCode := kHMOutsideModalWindow;
|
||
end
|
||
end;
|
||
end;
|
||
|
||
__HMGetWindowPartCode := windowCode;
|
||
|
||
if saveLayer <> NIL then { <79> if we are in the IMlayer restore to the saved layer }
|
||
SetCurLayer(saveLayer);
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMShowWindowPartBalloon(window: WindowPtr; windowCode: INTEGER): BOOLEAN;
|
||
{ returns true if a Balloon was shown }
|
||
|
||
VAR aHelpMsg : HMMessageRecord;
|
||
w : WindowPtr;
|
||
pt : Point;
|
||
i : INTEGER;
|
||
thisFile : INTEGER;
|
||
count : INTEGER;
|
||
aID : INTEGER;
|
||
mapCode : INTEGER;
|
||
balloonProc : INTEGER;
|
||
balloonVariant : INTEGER;
|
||
aType : ResType;
|
||
overrideH : Handle;
|
||
tempstr : STR255;
|
||
overridden : BOOLEAN;
|
||
tempBaseStr : Handle; {<76>}
|
||
tempSubstituteStr : Handle; {<76>}
|
||
anErr : INTEGER; {<76>}
|
||
savedPort : GrafPtr; {<78>}
|
||
|
||
BEGIN
|
||
__HMShowWindowPartBalloon := false;
|
||
|
||
balloonProc := 0;
|
||
balloonVariant := 0;
|
||
|
||
overridden := false;
|
||
|
||
count := CountResources('hovr');
|
||
if count>0 then
|
||
begin
|
||
thisFile := CurResFile;
|
||
for i := 1 to count do
|
||
begin
|
||
overrideH := GetIndResource('hovr',i);
|
||
if HomeResFile(overrideH)=thisFile then
|
||
begin
|
||
GetResInfo(overrideH,aID,aType,tempstr);
|
||
|
||
with HMhfdrRecordHdl(overrideH)^^ do
|
||
begin
|
||
balloonProc := theProc;
|
||
balloonVariant := variant;
|
||
end;
|
||
|
||
{ Remember that FindWindow returns:
|
||
inDrag = 4;
|
||
inGrow = 5;
|
||
inGoAway = 6;
|
||
inZoomIn = 7;
|
||
inZoomOut = 8;
|
||
}
|
||
|
||
case windowCode of
|
||
inDrag..inZoomIn: mapCode := windowCode - 3; { convert to our indexes }
|
||
|
||
kHMInOtherWindow :
|
||
mapCode := 5;
|
||
kHMInLayerPreamble..kHMInLayerBody:
|
||
mapCode := 6;
|
||
kHMOutsideModalWindow:
|
||
mapCode := 7;
|
||
otherwise mapCode := windowCode;
|
||
end;
|
||
|
||
overridden := __HMExtractHelpMsg(aType,aID,mapCode,0,aHelpMsg)=noErr;
|
||
if overridden then
|
||
leave;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
if not overridden then
|
||
with aHelpMsg do
|
||
begin
|
||
hmmHelpType := khmmString;
|
||
|
||
case windowCode of
|
||
kHMInOtherWindow..kHMOutsideModalWindow:
|
||
begin
|
||
GetIndString(hmmString,kHMHelpID,windowCode);
|
||
if windowCode=kHMInLayerPreamble then
|
||
begin
|
||
GetPort(savedPort); {<78>}
|
||
w := __HMGetHelpGlobal^.hmgHelpWindow; {<78>}
|
||
IF w <> NIL THEN {<78>}
|
||
SetPort(w); {<78>}
|
||
tempBaseStr := NewHandle(Length(hmmString)); {<76>}
|
||
tempSubstituteStr := NewHandle(Length(__HMGetHelpGlobal^.hmgProcessName)); {<76>}
|
||
IF (tempBaseStr <> NIL) AND (tempSubstituteStr <> NIL) THEN BEGIN {<76>}
|
||
BlockMove(@hmmString[1], tempBaseStr^, Length(hmmString)); {<76>}
|
||
with __HMGetHelpGlobal^ do {<76>}
|
||
BlockMove(@hmgProcessName[1], tempSubstituteStr^, Length(hmgProcessName)); {<76>}
|
||
anErr := ReplaceText(tempBaseStr, tempSubstituteStr, '^0'); {<76>}
|
||
hmmString[0] := Chr(GetHandleSize(tempBaseStr)); {<76>}
|
||
BlockMove(tempBaseStr^, @hmmString[1], Ord(hmmString[0])); {<76>}
|
||
END; {<76>}
|
||
DisposeHandle(tempBaseStr); {<76>}
|
||
DisposeHandle(tempSubstituteStr); {<76>}
|
||
SetPort(savedPort); {<78>}
|
||
end;
|
||
end;
|
||
|
||
kHMInFrontFloatingWindow: {<80>}
|
||
begin {<80>}
|
||
GetIndString(hmmString, kHMHelpID, windowCode); {<80>}
|
||
end; {<80>}
|
||
|
||
otherwise
|
||
GetIndString(hmmString,kHMHelpID,windowCode+(kHMInDragIndex-inDrag));
|
||
end;
|
||
|
||
if length(hmmString)=0 then { yikes! what happened to our string resource? }
|
||
{$ifc HelpMgrTesting}
|
||
hmmString := 'The window parts help resource was not found…';
|
||
{$elsec}
|
||
Exit(__HMShowWindowPartBalloon);
|
||
{$endc}
|
||
end;
|
||
|
||
if __HMShowBalloon(aHelpMsg,__HMGetGlobalMouse,NIL,NIL,balloonProc,balloonVariant,0) = noErr then
|
||
with __HMGetHelpGlobal^ do
|
||
begin
|
||
hmgItemNum := windowCode;
|
||
hmgMenuID := kwasWindowPart;
|
||
|
||
__HMShowWindowPartBalloon := true;
|
||
end;
|
||
END;
|
||
|
||
|
||
|
||
FUNCTION __HMGetBalloonWindow(VAR window: WindowPtr): OsErr;
|
||
BEGIN
|
||
window := __HMGetHelpGlobal^.hmgWindow;
|
||
__HMGetBalloonWindow := noErr;
|
||
END;
|
||
|
||
|
||
FUNCTION __HMScanTemplateItems(whichID,whichResFile: INTEGER; whichType: ResType): OsErr;
|
||
VAR d : DialogPtr;
|
||
result : OsErr;
|
||
founditem : INTEGER;
|
||
state : INTEGER;
|
||
theProc : INTEGER;
|
||
variant : INTEGER;
|
||
oldResFile : INTEGER;
|
||
count : INTEGER;
|
||
index : INTEGER;
|
||
itemRect : Rect;
|
||
altRect : Rect;
|
||
pt : Point;
|
||
err : OsErr;
|
||
aHelpMsg : HMMessageRecord;
|
||
gp : HMGlobalPtr;
|
||
oldPort : GrafPtr;
|
||
options : LongInt;
|
||
|
||
BEGIN
|
||
__HMScanTemplateItems := paramErr;
|
||
|
||
d := FrontWindow;
|
||
if d=NIL then exit(__HMScanTemplateItems);
|
||
|
||
if (LongInt(whichType) = LongInt(kHMDialogResType)) or (LongInt(whichType) = LongInt(kHMRectListResType)) then
|
||
begin
|
||
__HMScanTemplateItems := hmSameAsLastBalloon; { assume that it's already displayed }
|
||
|
||
GetPort(oldPort);
|
||
SetPort(d);
|
||
GetMouse(pt);
|
||
|
||
if PtInRect(pt,d^.portrect) then { make sure local mouse is in window portrect }
|
||
begin
|
||
gp := __HMGetHelpGlobal;
|
||
|
||
if (LongInt(whichType) = LongInt(kHMDialogResType)) then { see if the mouse is in any of the dialog item rects }
|
||
begin
|
||
{ <67> the following check MUST be short circuit! }
|
||
if (WindowPeek(d)^.windowKind<>DialogKind) | (__HMSameItemState(d,pt,foundItem,state,itemRect)) then begin
|
||
SetPort(oldPort);
|
||
Exit(__HMScanTemplateItems);
|
||
end;
|
||
|
||
if whichResFile<>-1 then
|
||
begin
|
||
oldResFile := CurResFile;
|
||
UseResFile(whichResFile);
|
||
end;
|
||
|
||
result := __HMFillInDialogMessage(whichID,founditem,0,0,state,0{offset},whichResFile,options,
|
||
pt,@altRect,theProc,variant,aHelpMsg);
|
||
|
||
if result = noErr then
|
||
with itemRect do { correct the dialog item's “hot” rect [<59> always add in altRect params] }
|
||
begin
|
||
left := left + altRect.left;
|
||
top := top + altRect.top;
|
||
right := right + altRect.right;
|
||
bottom := bottom + altRect.bottom;
|
||
end;
|
||
|
||
end else { it must have been an hrct resource that we wanted to scan }
|
||
begin
|
||
if whichResFile<>-1 then
|
||
begin
|
||
oldResFile := CurResFile;
|
||
UseResFile(whichResFile);
|
||
end;
|
||
|
||
result := __HMScanHRCTResource(WindowPtr(d),whichID,pt,index);
|
||
if result = noErr then
|
||
begin
|
||
with gp^ do { check to see if these were the same as last time, if so, exit! }
|
||
if (hmgState = whichID) then if (hmgItemNum = index) then
|
||
begin
|
||
if whichResFile<>-1 then
|
||
UseResFile(oldResFile);
|
||
|
||
SetPort(oldPort);
|
||
Exit(__HMScanTemplateItems);
|
||
end;
|
||
|
||
result := __HMGetIndHelpMsg(kHMRectListResType,whichID,
|
||
index,kHMEnabledItem,options,pt,@itemRect,
|
||
theProc,variant,aHelpMsg,count);
|
||
|
||
if result = noErr then
|
||
begin
|
||
state := whichID;
|
||
founditem := index;
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
if result <> noErr then
|
||
begin
|
||
if whichResFile<>-1 then
|
||
UseResFile(oldResFile);
|
||
|
||
SetPort(oldPort);
|
||
|
||
__HMScanTemplateItems := result;
|
||
exit(__HMScanTemplateItems);
|
||
end;
|
||
|
||
altRect := itemRect;
|
||
with altRect do
|
||
begin
|
||
LocalToGlobal(topLeft); { watch the port! Make sure it is set! }
|
||
LocalToGlobal(botRight);
|
||
|
||
if LongInt(pt)=0 then
|
||
begin
|
||
pt := botRight;
|
||
pt.h := pt.h - 10;
|
||
pt.v := pt.v - 10;
|
||
end else { setup the tip as it wasn't the special 'EmptyPt' case }
|
||
if (LongInt(whichType) = LongInt(kHMDialogResType)) then
|
||
begin
|
||
pt.h := pt.h + left; { for 'hdlg's move the tip relative to the item's rect }
|
||
pt.v := pt.v + top;
|
||
end else
|
||
LocalToGlobal(pt); { for 'hrct's just convert the tip to global coords }
|
||
end;
|
||
|
||
if BTst(options,kBTSTAbsoluteCoords) then
|
||
with WindowPtr(d)^.portrect,pt do
|
||
begin
|
||
{pt.}h := {pt.}h + left;
|
||
{pt.}v := {pt.}v + top;
|
||
|
||
OffsetRect(altRect,left,top);
|
||
end;
|
||
|
||
result := __HMShowBalloon(aHelpMsg,pt,@altRect,
|
||
NIL,theProc,variant,BSR(BAnd(options,$0000000C),2) { convert hmSaveBitsNoWindow & hmSaveBitsWindow to method parameter });
|
||
|
||
if whichResFile<>-1 then
|
||
UseResFile(oldResFile);
|
||
|
||
if result = noErr then
|
||
with gp^ do
|
||
begin
|
||
hmgItemNum := founditem;
|
||
hmgState := state;
|
||
end;
|
||
|
||
__HMScanTemplateItems := result;
|
||
|
||
end else { mouse wasn't in window's port rect so return hmBalloonAborted }
|
||
__HMScanTemplateItems := hmBalloonAborted;
|
||
|
||
SetPort(oldPort);
|
||
end;
|
||
END;
|
||
|
||
|
||
FUNCTION __HMExtractHelpMsg( whichType: ResType;
|
||
whichResID, whichMsg, whichState: INTEGER;
|
||
VAR aHelpMsg: HMMessageRecord): OsErr;
|
||
VAR options : LongInt;
|
||
tip : Point;
|
||
altRect : Rect;
|
||
theProc : INTEGER;
|
||
variant : INTEGER;
|
||
count : INTEGER;
|
||
BEGIN
|
||
__HMExtractHelpMsg := __HMGetIndHelpMsg(whichType,whichResID,whichMsg,whichState,
|
||
options,tip,@altRect,theProc,variant,aHelpMsg,count);
|
||
END;
|
||
|
||
|
||
END.
|