mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 01:29:20 +00:00
1685 lines
54 KiB
C
1685 lines
54 KiB
C
|
/*
|
|||
|
File: PopupCDEF.c
|
|||
|
|
|||
|
Contains: Source code for Popup Menu CDEF
|
|||
|
|
|||
|
Written by: Byron Han
|
|||
|
|
|||
|
Copyright: <EFBFBD> 1987-1992 by Apple Computer, Inc., all rights reserved.
|
|||
|
|
|||
|
Change History (most recent first):
|
|||
|
|
|||
|
<SM4> 11/19/92 RB Set ROMMapInsert to mapTRue to look for resources in ROM first.
|
|||
|
<43> 11/13/92 JDR Updated QuickDraw.h to not use the dangerous pattern type.
|
|||
|
<42> 11/7/92 JDR Removed the PopupPrivateData record, which is now a public
|
|||
|
structure. Change occurances of the usage too,
|
|||
|
<41> 11/3/92 DTY Strip out unnecessary includes.
|
|||
|
<40> 5/21/92 gbm #1030284,<dty>: Stop leaving the menu handle in the menu list
|
|||
|
all the time. This causes conflicts if two popups have the same
|
|||
|
ID.
|
|||
|
<39> 5/10/92 BH some applications stuff the window manager and color window
|
|||
|
manager ports with text size 12 (font is still set to 0).
|
|||
|
normally, these values are 0 and 0 - this causes the menu
|
|||
|
manager to barf since it tries to draw using the font and size
|
|||
|
of the window mgr ports. if a non zero value is specified in
|
|||
|
these ports, the appropriate values in sysFontFam and
|
|||
|
sysFontSize are not used (which is where we stuff the
|
|||
|
appropriate owning window's font and size information.
|
|||
|
|
|||
|
this is the infamous geneva 12 popup problem.
|
|||
|
|
|||
|
and I solved it. (Byronus Maximus)
|
|||
|
|
|||
|
we use the routines SaveAndResetWMPorts() and RestoreWMPorts()
|
|||
|
[see mods in PopupCdef.h]
|
|||
|
|
|||
|
All under the TheFuture conditional
|
|||
|
<EFBFBD> REALPOPUP() when saving port state, also save and reset the
|
|||
|
window manager port and color port font and size to 0, 0
|
|||
|
<EFBFBD> DoDraw() fix bug where triangles for items after the 31st in
|
|||
|
the menu would be dimmed
|
|||
|
<EFBFBD> DoUseWFont() fix bug where if the owning window font was the
|
|||
|
system font we would not set the size for the control properly.
|
|||
|
<EFBFBD> DoUseWFont() always invalidate the font manager cache (was
|
|||
|
checking to see if it was 0, 0 but it may be different because
|
|||
|
of window manager port/color port may have been set to 0, C
|
|||
|
instead) [fontfam, fontsize]
|
|||
|
<EFBFBD> SaveAndResetWMPorts() added
|
|||
|
<EFBFBD> RestoreWMPorts() added
|
|||
|
<38> 2/19/92 BH fixed comments for <37>
|
|||
|
<37> 1/24/92 BH Fixed problem with triangles for items after item 31 were always
|
|||
|
dimmed. Also fixed the infamous 12 point geneva popup (now
|
|||
|
always invalidate font mgr cache when changing system font and
|
|||
|
size)
|
|||
|
<36> 8/22/91 KSM PKE,#85693-Bruges: Don't use hard-coded bullet char for menu.
|
|||
|
Don't use sysFontFam=0, get smSysScript.
|
|||
|
<35> 4/5/91 JDR dba, DTY, kaz, BRC#86187: If the menu has been disposed and then
|
|||
|
re-added to the menu list, call GetMHandle to refresh the menu
|
|||
|
handle in the control's data storage.
|
|||
|
<34> 4/3/91 DTY ngk, kaz, #SIAC: The preflighting calls _HNoPurge on the menu
|
|||
|
handle for all messages except for initCntlMsg. In low memory
|
|||
|
conditions, the menu can get purged inside of CalcAndDrawMenu
|
|||
|
which is called via ResizeControl which in turn is called during
|
|||
|
the initCntlMsg. Add lines to _HNoPurge the menu for the
|
|||
|
initCtlMsg case also.
|
|||
|
<33> 3/27/91 kaz jng, AEK-038: Fix last fix <EFBFBD> dispCntl will dispose what dataP
|
|||
|
points to, so dataP->theMenu is an unknown. Instead we check the
|
|||
|
menuList w/ _GetMHandle to see if the menu is still around &
|
|||
|
then restore the state.
|
|||
|
<32> 3/27/91 DFH JWM,WS#DFH-910320a: Fixed so that we don't try to HSetState the
|
|||
|
menu handle if the menu has been disposed.
|
|||
|
<31> 3/20/91 VL DFH, WS#DFH-910320a: theMenu is made non-purgeable during the
|
|||
|
CDEF routines. This fixes many problems with PopupCDEF during
|
|||
|
low-memory situations.
|
|||
|
<30> 3/15/91 kaz jng, b6-ngk-002: Fixing bug in _TestControl <EFBFBD> removing -2 fudge
|
|||
|
factor from rectangle test
|
|||
|
<29> 2/7/91 kaz BBH, #81082: ResizeControl() - if the popup gets too big and
|
|||
|
only the triangle is showing (Views CDEV - size menu), we will
|
|||
|
draw the frame at the contrlRect boundary.
|
|||
|
<28> 2/4/91 kaz jng, #74915: DrawTriangle() will dim the triangle if the control
|
|||
|
is dimmed, the whole menu is dimmed, or the menuItem is dimmed.
|
|||
|
<27> 1/23/91 kaz <jng>,#81486,#81487: Fix ResEdit crash by exiting from the CDEF
|
|||
|
if the MENU is really gone. If the menu is not preloaded, use
|
|||
|
the contrlMin field as a 'MENU' resID and get the new menuID
|
|||
|
after GetMenu(resID).
|
|||
|
<26> 1/16/91 kaz Fixing Script Mgr bug: DoUseWFont() will not stuff SysFontFam if
|
|||
|
txFont is systemFont or applFont.
|
|||
|
<25> 1/14/91 kaz <jng> Fixing DrawTitle for B&W classic machines.
|
|||
|
<24> 12/13/90 kaz Copying the pnVis field if we have to create a color port. <jng>
|
|||
|
<23> 12/7/90 kaz Hierarchial Menu support: added popupResult field to private
|
|||
|
record to save the last value of PopupMenuSelect. Won't check
|
|||
|
hierarchial items, and draws the unpopped item without hier
|
|||
|
arrow. Added FindHMenu() to return the parent if a hier menu
|
|||
|
item is tracked; Fixed bug in right just of title: not sign
|
|||
|
extending. <jng>
|
|||
|
<22> 11/12/90 kaz Added StandardFile support: draws the box pinned to the
|
|||
|
contrlRect if needed; Shrinks the box width to be the current
|
|||
|
itemwidth. Smarter drawing: only redraws the control if heights
|
|||
|
or widths have changed, the control has moved, etc. Some
|
|||
|
cleanup. <jng>
|
|||
|
<21> 10/30/90 kaz Triangle is now drawn using _FillPoly instead of _DrawPicture;
|
|||
|
Will only dehilite the title if the user tracks the same value;
|
|||
|
Removed PaintMyGrayRect(). <BBH>
|
|||
|
<20> 9/22/90 gbm (with kaz) Changing DoDraw to properly dispose of PixPats (by
|
|||
|
calling PenNormal!) instead of leaving them around in the app
|
|||
|
heap
|
|||
|
<19> 9/16/90 PWD Grays the title on classic machines properly. <kaz>
|
|||
|
<18> 9/15/90 PWD Reimplemented AddResMenu variant; popupUseCQD is now reserved.
|
|||
|
<kaz> <crz>
|
|||
|
<17> 9/14/90 kaz Always tries to use CQD; Clips properly, even if we roll our own
|
|||
|
color port; Erase control if the new menu item height < old (for
|
|||
|
icons).
|
|||
|
<16> 9/13/90 kaz DoDraw(): no longer calls _DisposPixPat after _PenPixPat (let QD
|
|||
|
dispose it when we reset the PenState); calls _PenPixPat after
|
|||
|
sending drawItemMsg in case MDEF has changed it.
|
|||
|
<15> 9/11/90 kaz If the menu is cleared after InitMsg, we reload it and delete it
|
|||
|
at the end.
|
|||
|
<14> 9/5/90 kaz Properly bracketing calls for BeginGray/EndGray
|
|||
|
<13> 9/4/90 kaz Changing gray text _PenMode to _TextMode.
|
|||
|
<12> 8/5/90 kaz Added new graying algorithm; Spun out DrawTitle().
|
|||
|
<11> 8/2/90 kaz Fixed shadow dimensions. Moved triangle in a little, and center
|
|||
|
it for popups with not enough space. Only erases the old
|
|||
|
location if the control has moved. Only redraws the title when
|
|||
|
mouse hit. Fixed right justified bugs. Temporary gray algorithm.
|
|||
|
More code shrinkage.
|
|||
|
<10> 7/10/90 dba get rid of C warnings
|
|||
|
<9> 6/12/90 kaz Mega changes to decrease code size. JustLeft is now the default.
|
|||
|
Does not grow the contrlRect. Clips to conrtlRect. Draws the
|
|||
|
popup nicely if the menu is empty. ItemMark will be a checkmark
|
|||
|
if the useWFont is a SystemFont.
|
|||
|
<8> 6/4/90 kaz Temporarily removed the min/max FixedWidth stuff as Finder uses
|
|||
|
the refCon. Resort to old fixedWidth. Locks theData before
|
|||
|
calling ResizeControl() from DoInit().
|
|||
|
<7> 6/4/90 kaz Control is now vertically centered; Will not normally change the
|
|||
|
control rectangle, except to grow it. Will center the control if
|
|||
|
titleWidth == 0 and titleJust = center (for Standard File).
|
|||
|
FixedWidth will calc a minimum width from the refCon, and
|
|||
|
maxWidth from the controlRect. AddResMenu temporarily #ifdef'ed.
|
|||
|
<6> 5/31/90 kaz popupFixedWidth expands the menu in DoTrack() if the menuWidth <
|
|||
|
boxWidth.
|
|||
|
<5> 5/29/90 kaz Title textFace is set to grafPort's for useWFont; Removed SKANKY
|
|||
|
#ifdef; Tweaked traingle drawing.
|
|||
|
<4> 3/20/90 EMT Changed CQDLives() function to HaveCQD() macro used by
|
|||
|
Notification and Layer managers (to save code).
|
|||
|
<3> 3/16/90 BBH removed code that checked if mdefproc bailed on the
|
|||
|
mCalcItemMsg; also stopped diddling with the wmgrport and
|
|||
|
wmgrcport's font and fontsize since we are already diddling with
|
|||
|
sysFontFam and sysFontSize
|
|||
|
<2> 3/5/90 BBH fix problem with drawing the popup label in right justification
|
|||
|
mode
|
|||
|
<1> 3/5/90 BBH first checked in to BBS
|
|||
|
|
|||
|
To Do:
|
|||
|
<EFBFBD> Add our own truncString for < System 7
|
|||
|
|
|||
|
*/
|
|||
|
|
|||
|
// Pre-BBS Modification History
|
|||
|
// WHEN WHO WHAT
|
|||
|
// 2/6/90 BBH Changed drawing of triangle via polygon to use a pict
|
|||
|
// renamed hasColor to hasCQD in myData data structure
|
|||
|
// renamed color to useCQD in myData data structure
|
|||
|
//
|
|||
|
// 12/7/89 BBH Fixed calculation of size for reduced icons
|
|||
|
// Now tries to use mdef to calculate item size and
|
|||
|
// standard message for drawing an item.
|
|||
|
//
|
|||
|
// 12/6/89 BBH Finished port to C
|
|||
|
// Better accuray in redraw, smaller code
|
|||
|
// 12/5/89 BBH Started
|
|||
|
//////////Ported to C
|
|||
|
/* old revision notes
|
|||
|
12/4/89 BBH Use two custom MDEF's
|
|||
|
One that calls the mdef and widens the width
|
|||
|
Other really isn't an MDEF - just handles mDrawMsg
|
|||
|
differently (draws item in whichItem in the
|
|||
|
rectangle provided) - but handles icons,
|
|||
|
sicns, and reduced icons
|
|||
|
Added triangle support
|
|||
|
Consolidation of calculation routines
|
|||
|
11/30/89 BBH Trying to get it up
|
|||
|
10/4/89 BBH Minimum safe title width is 1 pixel. We now check.
|
|||
|
10/3/89 BBH If menu preexists in the menu list, we do not a GetMenu, InsertMenu
|
|||
|
upon creation, and a DeleteMenu, DisposMenu upon disposal
|
|||
|
(SAFEMENUS set to TRUE for this feature)
|
|||
|
Fixed bug in TruncateString if space given is insufficient for even
|
|||
|
an ellipsis caused infinite loop in truncation.
|
|||
|
TruncateString routine has been modified to return empty string
|
|||
|
if there is insuffient space for 1 character (can be multibyte)
|
|||
|
plus the ellipsis.
|
|||
|
7/25/89 BBH Always recalculate the height regardless of popupFixedWidth bit.
|
|||
|
6/19/89 BBH Added checks for the popup menu trap and the script manager trap.
|
|||
|
If the popup menu trap is NOT available, then draw
|
|||
|
the control as if disabled and do not perform tracking.
|
|||
|
If the script manager trap is NOT available, then truncate the
|
|||
|
string one byte at a time (do not test for multibute chars)
|
|||
|
6/18/89 BBH Instead of setting clip to the control rectangle, set to the intersection
|
|||
|
of the existing clipRgn and the control rectangle.
|
|||
|
Removed scripts field from private data structure. Was not being used.
|
|||
|
Reformatted modification history. Added more generous comments.
|
|||
|
Also use CTBUtils.p pascal interface file for the variant code
|
|||
|
constants.
|
|||
|
Removed some dead code. Did a personal review of the code.
|
|||
|
6/16/89 BBH TruncateString is now script manager compatible - uses CharByte.
|
|||
|
Also, when drawing the control, we clip to the control rectangle.
|
|||
|
This prevents a problem with descenders in geneva 9pt, shadow being
|
|||
|
drawing outside of the control rectangle.
|
|||
|
6/14/89 BBH Added support for calcCntlRgn and calcThumbRgn messages for System 7.0
|
|||
|
compatibility. See TN 212
|
|||
|
6/8/89 BBH Fixed bug that Rich Hoiberg was having that if you have a control
|
|||
|
attached to a dialog item list and after creating the dialog
|
|||
|
(and hence creating the control) you change the dialog font and
|
|||
|
dialog size, the height of the popup is not recalculated properly.
|
|||
|
fixed by calling GetFontInfo in DoResize and manually adjusting
|
|||
|
the control height if the variation code for fixed size is not being
|
|||
|
used.
|
|||
|
Removed info: FontInfo and height: INTEGER from myData data structure
|
|||
|
6/7/89 BBH Changed EraseRect of the control rectangle to a EraseControl call
|
|||
|
which will only erase the parts of the control that get drawn
|
|||
|
which means if the window is filled with a pattern, no annoying
|
|||
|
whitespace gets left behind.
|
|||
|
6/4/89 BBH PreflightFont is called after resetting the window manager ports
|
|||
|
in DoResize.
|
|||
|
5/31/89 BBH popup value has the justification stored as a signed Byte
|
|||
|
in the low byte and stores the popup title style in
|
|||
|
the high byte if the high bit is clear
|
|||
|
Defined new constants in CTBUtils.r, .p, and .h
|
|||
|
If high bit of the popup value is set, ignore style (this is for
|
|||
|
backwards compatibility with old CNTL templates which use -1 for
|
|||
|
the popup title justification)
|
|||
|
5/3/89 BBH Changed HLock and HUnlock of the control handle to HGetState,
|
|||
|
HLock, HSetState
|
|||
|
4/26/89 BBH Changed all BitAnd's to BANDs
|
|||
|
Changed drawing to not subtract 3. This fixes shifting of quiescent and
|
|||
|
active menu items with system 6.0.4
|
|||
|
3/22/89 BBH use checkmark if using system font
|
|||
|
use <EFBFBD> if using window font instead of checkMark
|
|||
|
we now call preflightFont to load in font info if using window font
|
|||
|
prior to calling CalcMenuSize in the DoResize routine.
|
|||
|
Also indentation when drawing popup box is using the max char width
|
|||
|
of the font minus two.
|
|||
|
3/21/89 kaz in DoTrack() check to see if variant is UseWFont
|
|||
|
then save the old WMgrPort text info, set it to the
|
|||
|
current window text info, then reset it. This
|
|||
|
should paint the menus in the right font/size
|
|||
|
Changed Pop-up to use a bullet mark <EFBFBD> for the
|
|||
|
checked menu item instead of a checkmark
|
|||
|
3/14/89 BBH use System Font size 0.
|
|||
|
also added support for variant codes.
|
|||
|
moved refcon/AddResMenu stuff to variant code 4.
|
|||
|
added color quickdraw stuff with support for mctb.
|
|||
|
opens a CGrafPort is necessary.
|
|||
|
added support for sys just of teJustRight to draw
|
|||
|
title to the RIGHT of the pop up box.
|
|||
|
12/23/88 BBH Drawing of the ow done with TextBox. Is using GetSysJust
|
|||
|
Also, instead of using System Font size 12, we get font and
|
|||
|
size information from window manager port.
|
|||
|
The test routine will return 0 or myPartCode which is 1.
|
|||
|
Caveats
|
|||
|
The CDEF installs and deinstalls the menu from the menu list
|
|||
|
when the control is created/destroyed.
|
|||
|
If the menu does not exist, you are at your own risk.
|
|||
|
12/22/88 BBH value is justification of the popup menu title. It is
|
|||
|
reset to min after control creation
|
|||
|
application must reset the value then.
|
|||
|
|
|||
|
9/88 BBH Second major rewrite to add AddResMenu capability
|
|||
|
refCon is NIL - nothing
|
|||
|
refCon is NOT nil - do a AddResMenu(ResType(refcon));
|
|||
|
menuID is MIN
|
|||
|
popuptitlewidth is MAX
|
|||
|
7/88 BBH First major rewrite. Use refCon to specify menuID and popup title
|
|||
|
width. Use flag bit in refCon to determine if application
|
|||
|
is performing InsertMenu/DeleteMenu.
|
|||
|
Refcon values
|
|||
|
HiWord contains ID of menu
|
|||
|
LoWord contains width of popup title
|
|||
|
If the hi bit of the low word of the refcon is set, then the calling
|
|||
|
applciation must install/deinstall the menu from the menu list.
|
|||
|
Rect is rect.
|
|||
|
11/2/87 BBH Second version
|
|||
|
10/20/87 BBH First version
|
|||
|
|
|||
|
Things to be done:
|
|||
|
TruncateString should be internationalized. Test it.
|
|||
|
Why does TrackControl always return non zero even if we track out of the control?
|
|||
|
|
|||
|
Make popup return different part codes
|
|||
|
*/
|
|||
|
|
|||
|
#include <Types.h>
|
|||
|
#include <Controls.h>
|
|||
|
#include <Fonts.h>
|
|||
|
#include <Memory.h>
|
|||
|
#include <Menus.h>
|
|||
|
#include <QuickDraw.h>
|
|||
|
#include <QuickDrawText.h>
|
|||
|
#include <Resources.h>
|
|||
|
#include <Script.h>
|
|||
|
#include <SysEqu.h>
|
|||
|
#include <TextEdit.h>
|
|||
|
#include <ToolUtils.h>
|
|||
|
|
|||
|
#include "PopupCDEF.h"
|
|||
|
|
|||
|
#define HaveCQD() ((*(unsigned short *) ROM85) <= 0x3FFF)
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
REALPOPUP - DefProc control
|
|||
|
|
|||
|
hControl - the popup
|
|||
|
theVar - CDEF variant
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
pascal long REALPOPUP(short theVar, ControlHandle hControl, short msg, long theParam)
|
|||
|
{
|
|||
|
PenState savedPen;
|
|||
|
TextState savedText,
|
|||
|
myText;
|
|||
|
WMPortState savedWMPortState;
|
|||
|
|
|||
|
GrafPtr savedPort;
|
|||
|
unsigned char savedState;
|
|||
|
long rval = 0; // return value
|
|||
|
GrafPtr owner;
|
|||
|
myDataP dataP; // moved this declaration out from if-statement <31>
|
|||
|
unsigned char menuSavedState; // state for theMenu <31>
|
|||
|
|
|||
|
GetPort(&savedPort); // set to the owner
|
|||
|
owner = (**hControl).contrlOwner;
|
|||
|
SetPort(owner);
|
|||
|
|
|||
|
savedState = HGetState((Handle) hControl);
|
|||
|
HLock((Handle) hControl); // lock the control down
|
|||
|
|
|||
|
/* We need to lock theData 'cuz we use dangling ptrs to save space */
|
|||
|
/* It's NIL at init time, but HLock doesn't care, so we don't either */
|
|||
|
HLock((Handle) (**hControl).contrlData);
|
|||
|
|
|||
|
GetTextState(&savedText);
|
|||
|
GetPenState(&savedPen);
|
|||
|
SaveAndResetWMPorts(&savedWMPortState);
|
|||
|
|
|||
|
PenNormal();
|
|||
|
if ( !(theVar & popupUseWFont) ) {
|
|||
|
myText.theFont = systemFont;
|
|||
|
myText.theSize = 0;
|
|||
|
myText.theFace = 0;
|
|||
|
myText.theMode = srcOr;
|
|||
|
SetTextState(&myText);
|
|||
|
}
|
|||
|
|
|||
|
dataP = *((myDataH) (**hControl).contrlData); // moved this from the if-statement below <31>
|
|||
|
|
|||
|
// if the menu's gone, reload it & mark it for deletion later
|
|||
|
if (msg != initCntl) {
|
|||
|
dataP->public.mHandle = GetMHandle(dataP->public.mID); // <35>
|
|||
|
if (dataP->public.mHandle == nil) {
|
|||
|
dataP->preinstalled = false; // delete at dispose time
|
|||
|
dataP->public.mHandle = GetMenu(dataP->resID);
|
|||
|
if (dataP->public.mHandle == nil)
|
|||
|
goto restoreState; // if it doesn't work, get out
|
|||
|
dataP->public.mID = (**dataP->public.mHandle).menuID;
|
|||
|
InsertMenu(dataP->public.mHandle, hierMenu);
|
|||
|
|
|||
|
menuSavedState = HGetState((Handle) dataP->public.mHandle);
|
|||
|
HNoPurge((Handle) dataP->public.mHandle);
|
|||
|
} else
|
|||
|
dataP->preinstalled = true;
|
|||
|
|
|||
|
// <31> The following segment of code is added to ensure that the menu is not purgeable
|
|||
|
// during the course of PopupCDEF routines.
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
switch (msg) {
|
|||
|
case drawCntl:
|
|||
|
if ( (**hControl).contrlVis )
|
|||
|
rval = DoDraw(hControl, theVar, (short) theParam);
|
|||
|
break;
|
|||
|
|
|||
|
case testCntl:
|
|||
|
rval = DoTest(hControl, theParam);
|
|||
|
break;
|
|||
|
|
|||
|
case calcCRgns:
|
|||
|
#ifdef calcCntlRgn
|
|||
|
case calcCntlRgn:
|
|||
|
#endif calcCntlRgn
|
|||
|
#ifdef calcThumbRgn
|
|||
|
case calcThumbRgn:
|
|||
|
#endif calcThumbRgn
|
|||
|
DoCalc(hControl, theVar, &theParam);
|
|||
|
break;
|
|||
|
|
|||
|
case initCntl:
|
|||
|
DoInit(hControl, theVar);
|
|||
|
break;
|
|||
|
|
|||
|
case dispCntl:
|
|||
|
DoDispose(hControl);
|
|||
|
break;
|
|||
|
|
|||
|
case autoTrack:
|
|||
|
rval = DoTrack(hControl, theVar);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
// <31> The following line is used to restore the state of public.mHandle so that public.mHandle can
|
|||
|
// become purgeable again. (maybe)
|
|||
|
// we inserted the menu in the list on entry, and now we<77>re taking it out again
|
|||
|
if ((msg != initCntl) && (msg !=dispCntl)) {
|
|||
|
if (!dataP->preinstalled) {
|
|||
|
DeleteMenu( dataP->public.mID );
|
|||
|
HSetState((Handle)dataP->public.mHandle, menuSavedState );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
restoreState:
|
|||
|
SetTextState(&savedText);
|
|||
|
SetPenState(&savedPen); // restore control handle
|
|||
|
RestoreWMPorts(&savedWMPortState);
|
|||
|
|
|||
|
HUnlock((Handle) (**hControl).contrlData);
|
|||
|
HSetState((Handle) hControl, savedState);
|
|||
|
|
|||
|
SetPort(savedPort);
|
|||
|
return(rval); // bye bye
|
|||
|
}
|
|||
|
|
|||
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
DoInit - Gets the values from the control record,
|
|||
|
and puts them in our private data struct
|
|||
|
|
|||
|
hControl - the popup
|
|||
|
theVar - CDEF variant
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void DoInit(ControlHandle hControl, short theVar)
|
|||
|
{
|
|||
|
myDataP dataP;
|
|||
|
ControlPtr controlP;
|
|||
|
myDataH theData;
|
|||
|
MenuHandle hMenu;
|
|||
|
unsigned char menuSavedState; // Save the state of the menu handle <34>
|
|||
|
|
|||
|
controlP = *hControl;
|
|||
|
|
|||
|
theData = (myDataH) NewHandleClear(sizeof(myData));
|
|||
|
controlP->contrlData = (Handle) theData;
|
|||
|
if (theData == nil)
|
|||
|
goto error;
|
|||
|
|
|||
|
HLock((Handle) theData); // will be unlocked in REALPOPUP
|
|||
|
|
|||
|
dataP = *theData; // ptr for smaller code
|
|||
|
|
|||
|
// deal with environment
|
|||
|
dataP->useColor = HaveCQD(); // always try to use CQD
|
|||
|
if (dataP->useColor)
|
|||
|
dataP->makeCPort = ((dataP->useColor) &&
|
|||
|
(!(controlP->contrlOwner->portBits.rowBytes & cGrafSignature)));
|
|||
|
|
|||
|
// deal with creation parameters
|
|||
|
dataP->resID = dataP->public.mID = controlP->contrlMin; // get the menu ID
|
|||
|
|
|||
|
if (controlP->contrlMax > 1)
|
|||
|
dataP->titleWidth = controlP->contrlMax;
|
|||
|
|
|||
|
dataP->titleJust = (char) (controlP->contrlValue & popupTitleJustMask);
|
|||
|
if (!(controlP->contrlValue & popupTitleNoStyle))
|
|||
|
dataP->titleStyle = (Style) ((controlP->contrlValue & popupTitleStyleMask ) >> 8);
|
|||
|
|
|||
|
// Add the grafport's style if useWFont
|
|||
|
if (theVar & popupUseWFont)
|
|||
|
dataP->titleStyle |= controlP->contrlOwner->txFace;
|
|||
|
|
|||
|
// get the menu; if it isn't pre-installed, then we need to build it
|
|||
|
hMenu = GetMHandle(dataP->public.mID);
|
|||
|
dataP->preinstalled = (hMenu != nil);
|
|||
|
if (! dataP->preinstalled) {
|
|||
|
hMenu = GetMenu(dataP->resID);
|
|||
|
if (hMenu == nil)
|
|||
|
goto error;
|
|||
|
menuSavedState = HGetState((Handle) hMenu); // Save the state <34>
|
|||
|
HNoPurge((Handle) hMenu); // Make it non-purgeable <34>
|
|||
|
dataP->public.mID = (**hMenu).menuID;
|
|||
|
InsertMenu(hMenu, hierMenu); // stick it in
|
|||
|
}
|
|||
|
dataP->public.mHandle = hMenu;
|
|||
|
|
|||
|
// Use the refCon as the resource type to add
|
|||
|
if ( (theVar & popupUseAddResMenu) )
|
|||
|
AddResMenu(hMenu, (ResType) controlP->contrlRfCon);
|
|||
|
|
|||
|
// Get the widths for fixedWidth controls. Note that if the refCon = 0, this is
|
|||
|
// the old fixedWidth control setting to maintain compatibility w/ 1.0
|
|||
|
dataP->maxWidth = controlP->contrlRect.right - controlP->contrlRect.left;
|
|||
|
|
|||
|
if (theVar & popupFixedWidth)
|
|||
|
dataP->minWidth = dataP->maxWidth;
|
|||
|
|
|||
|
// set up max/min/val
|
|||
|
controlP->contrlMin = 1;
|
|||
|
controlP->contrlMax = CountMItems(hMenu);
|
|||
|
if (controlP->contrlMax == 0 )
|
|||
|
controlP->contrlMin = 0; // nothing around
|
|||
|
controlP->contrlValue = controlP->contrlMin;
|
|||
|
|
|||
|
dataP->popupResult = (dataP->public.mID << 16) + controlP->contrlValue;
|
|||
|
|
|||
|
dataP->oldContrlRect = controlP->contrlRect;
|
|||
|
dataP->oldMax = controlP->contrlMax;
|
|||
|
dataP->changedVal = true; // forces a draw of the control
|
|||
|
|
|||
|
ResizeControl(hControl, theVar); // calculate dynamic values
|
|||
|
|
|||
|
controlP->contrlAction = (ProcPtr) (-1); // handle own autotrack
|
|||
|
if (!dataP->preinstalled) { // take this back out of the menu list when <gbm>
|
|||
|
DeleteMenu(dataP->public.mID); // we<77>re done, but only if we put it in there <gbm>
|
|||
|
HSetState((Handle) dataP->public.mHandle, menuSavedState); // Restore the state <34>
|
|||
|
}
|
|||
|
goto exit;
|
|||
|
error: // clean up
|
|||
|
DoDispose(hControl);
|
|||
|
controlP->contrlData = nil; // nil it out please
|
|||
|
|
|||
|
exit:
|
|||
|
;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
DoDraw - Draws the entire popup control
|
|||
|
|
|||
|
hControl - the popup
|
|||
|
theVar - CDEF variant
|
|||
|
theParam - part code to draw:
|
|||
|
0 => all parts
|
|||
|
myPartCode => control hasn't moved
|
|||
|
129 => control has moved
|
|||
|
returns - 0
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
long DoDraw(ControlHandle hControl, short theVar, short theParam)
|
|||
|
{
|
|||
|
myDataP dataP;
|
|||
|
ControlPtr controlP;
|
|||
|
CGrafPtr myCPort = nil;
|
|||
|
GrafPtr owner; // owner of control
|
|||
|
Rect boxRect,
|
|||
|
theRect;
|
|||
|
RgnHandle savedClip,
|
|||
|
newClip; // for setting clip to control frame
|
|||
|
RGBColor oldCQDFore, // CQD variables
|
|||
|
oldCQDBack;
|
|||
|
Boolean dimmedOut;
|
|||
|
Boolean useColor;
|
|||
|
PixPatHandle myPixPat = nil;
|
|||
|
long oldFlags;
|
|||
|
Boolean majorClean = false;
|
|||
|
short cmdChar = 0,
|
|||
|
markChar = 0;
|
|||
|
|
|||
|
controlP = *hControl;
|
|||
|
dataP = *((myDataH) controlP->contrlData);
|
|||
|
|
|||
|
useColor = dataP->useColor; // local vars for smaller code
|
|||
|
owner = controlP->contrlOwner;
|
|||
|
|
|||
|
// We dim the control if the hilite is set, or the menu is empty
|
|||
|
dimmedOut = ((controlP->contrlHilite == 255) ||
|
|||
|
((**dataP->public.mHandle).menuWidth == 0));
|
|||
|
|
|||
|
// get new menu item height
|
|||
|
SetRect(&theRect, 0, 0, 0, 0);
|
|||
|
CalcAndDrawItem(hControl, theVar, mCalcItemMsg, &theRect); // theRect.top = 0 => ignore it
|
|||
|
GetItemCmd(dataP->public.mHandle,controlP->contrlValue,&cmdChar);
|
|||
|
GetItemMark(dataP->public.mHandle,controlP->contrlValue,&markChar);
|
|||
|
|
|||
|
majorClean = ((theParam == movedPartCode) ||
|
|||
|
(controlP->contrlMax != dataP->oldMax) ||
|
|||
|
(theRect.bottom != dataP->oldHeight) ||
|
|||
|
(cmdChar == 0x001A) ||
|
|||
|
(dataP->oldWidth != (**dataP->public.mHandle).menuWidth) ||
|
|||
|
(! EqualRect(&dataP->oldContrlRect, &controlP->contrlRect)));
|
|||
|
|
|||
|
if (majorClean) {
|
|||
|
dataP->oldMax = controlP->contrlMax;
|
|||
|
dataP->oldHeight = theRect.bottom; // update flags
|
|||
|
dataP->oldWidth = (**dataP->public.mHandle).menuWidth;
|
|||
|
dataP->oldContrlRect = controlP->contrlRect;
|
|||
|
|
|||
|
EraseRect(&dataP->myCtlRect);
|
|||
|
ResizeControl(hControl, theVar); // recalc & erase new loc
|
|||
|
EraseRect(&dataP->myCtlRect);
|
|||
|
}
|
|||
|
|
|||
|
// If the value has changed, we just need to dehilite the title
|
|||
|
if (! dataP->changedVal)
|
|||
|
if (! majorClean)
|
|||
|
if (dataP->titleWidth <= 0)
|
|||
|
goto done;
|
|||
|
|
|||
|
PortNClip:
|
|||
|
if (dataP->makeCPort)
|
|||
|
myCPort = MakeColorPort(owner);
|
|||
|
// save off color quickdraw stuff
|
|||
|
if (useColor) {
|
|||
|
GetForeColor(&oldCQDFore);
|
|||
|
GetBackColor(&oldCQDBack);
|
|||
|
}
|
|||
|
|
|||
|
savedClip = NewRgn();
|
|||
|
newClip = NewRgn();
|
|||
|
GetClip(savedClip);
|
|||
|
RectRgn(newClip, &controlP->contrlRect);
|
|||
|
SectRgn(newClip, savedClip, newClip);
|
|||
|
SetClip(newClip);
|
|||
|
|
|||
|
if (dataP->titleWidth > 0) {
|
|||
|
DrawTitle(controlP, dataP);
|
|||
|
|
|||
|
if (! dataP->changedVal)
|
|||
|
if (! majorClean)
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
// Don't need to redraw the following for hilited state as
|
|||
|
// menu will popup on top and save bits behind
|
|||
|
if ((controlP->contrlHilite == myPartCode) && (! majorClean))
|
|||
|
goto cleanup;
|
|||
|
|
|||
|
// now erase the popup box if CQD to get colors right
|
|||
|
CalcBoxArea(dataP, &boxRect);
|
|||
|
if (useColor) {
|
|||
|
SetColors(dataP->public.mID, controlP->contrlValue, false);
|
|||
|
EraseRect(&boxRect);
|
|||
|
}
|
|||
|
|
|||
|
// Draw the Menu Item
|
|||
|
// If we're dimmed, we trick the Menu Mgr into dimming for us
|
|||
|
// Also, we don't want any check marks, hier arrows drawn for us, so we zap 'em
|
|||
|
CalcMenuArea(dataP, &theRect);
|
|||
|
if (dimmedOut) {
|
|||
|
oldFlags = (**dataP->public.mHandle).enableFlags;
|
|||
|
if (controlP->contrlValue <= 31)
|
|||
|
DisableItem(dataP->public.mHandle, controlP->contrlValue);
|
|||
|
}
|
|||
|
if (cmdChar == 0x001B)
|
|||
|
SetItemCmd(dataP->public.mHandle,controlP->contrlValue,0);
|
|||
|
SetItemMark(dataP->public.mHandle,controlP->contrlValue,0);
|
|||
|
|
|||
|
CalcAndDrawItem(hControl, theVar, mDrawItemMsg, &theRect);
|
|||
|
|
|||
|
// Now put everything back
|
|||
|
SetItemCmd(dataP->public.mHandle,controlP->contrlValue,cmdChar);
|
|||
|
SetItemMark(dataP->public.mHandle,controlP->contrlValue,markChar);
|
|||
|
if (dimmedOut)
|
|||
|
(**dataP->public.mHandle).enableFlags = oldFlags;
|
|||
|
|
|||
|
// Triangle will be dimmed if control is dimmed OR the menu OR current item is dimmed
|
|||
|
// so we reuse oldFlags to see if the menu is dimmed, else if the item is dimmed
|
|||
|
|
|||
|
oldFlags = (**dataP->public.mHandle).enableFlags & 1; // bit 0 -- whole menu is dimmed
|
|||
|
#if CubeE
|
|||
|
if (oldFlags == 1)
|
|||
|
oldFlags = (**dataP->public.mHandle).enableFlags & (1 << controlP->contrlValue);
|
|||
|
#endif
|
|||
|
#if TheFuture
|
|||
|
if (oldFlags == 1) {
|
|||
|
if (controlP->contrlValue <= 31) // <37>
|
|||
|
oldFlags = (**dataP->public.mHandle).enableFlags & (1 << controlP->contrlValue);
|
|||
|
}
|
|||
|
#endif
|
|||
|
DrawTriangle(dataP,(dimmedOut || (oldFlags == 0)));
|
|||
|
|
|||
|
if (useColor)
|
|||
|
SetColors(dataP->public.mID, -1, false); // reset to default colors
|
|||
|
|
|||
|
// set it in case menu mgr changed it
|
|||
|
if (dimmedOut)
|
|||
|
myPixPat = BeginMyGray(dataP);
|
|||
|
|
|||
|
// Frame & Shadow
|
|||
|
FrameRect(&boxRect);
|
|||
|
CalcShadowArea(dataP, &boxRect);
|
|||
|
MoveTo(--boxRect.right, boxRect.top); // move the pen INSIDE the rect
|
|||
|
LineTo(boxRect.right, --boxRect.bottom);
|
|||
|
LineTo(boxRect.left, boxRect.bottom);
|
|||
|
|
|||
|
// Graying over the triangle
|
|||
|
if (dimmedOut)
|
|||
|
if (myPixPat == nil) { // gray the title if no color avail.
|
|||
|
CalcTitleArea(dataP, &theRect);
|
|||
|
PenMode(patBic);
|
|||
|
PaintRect(&theRect);
|
|||
|
}
|
|||
|
|
|||
|
PenNormal();
|
|||
|
if (myPixPat != nil)
|
|||
|
DisposPixPat(myPixPat);
|
|||
|
|
|||
|
cleanup:
|
|||
|
// _SetPenState will be reset it main
|
|||
|
|
|||
|
if (useColor) {
|
|||
|
RGBForeColor(&oldCQDFore);
|
|||
|
RGBBackColor(&oldCQDBack);
|
|||
|
}
|
|||
|
|
|||
|
SetClip(savedClip);
|
|||
|
DisposeRgn(savedClip);
|
|||
|
DisposeRgn(newClip);
|
|||
|
|
|||
|
if (myCPort != nil) {
|
|||
|
CloseCPort(myCPort);
|
|||
|
DisposPtr((Ptr) myCPort);
|
|||
|
SetPort(owner);
|
|||
|
}
|
|||
|
|
|||
|
done:
|
|||
|
dataP->changedVal = true;
|
|||
|
return(0);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
DoTest - Determines if a point is in my control
|
|||
|
and returns which part.
|
|||
|
|
|||
|
hControl - the popup
|
|||
|
theParam - point location
|
|||
|
|
|||
|
returns - control part code
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
long DoTest(ControlHandle hControl, long theParam)
|
|||
|
{
|
|||
|
myDataP dataP;
|
|||
|
Point thePoint;
|
|||
|
long rval = 0;
|
|||
|
Rect theRect;
|
|||
|
|
|||
|
*((long *) &thePoint) = theParam;
|
|||
|
|
|||
|
dataP = *((myDataH) (**hControl).contrlData);
|
|||
|
|
|||
|
theRect = dataP->myCtlRect;
|
|||
|
|
|||
|
if (PtInRect(thePoint, &theRect))
|
|||
|
if (((**hControl).contrlHilite != 255) &&
|
|||
|
((**dataP->public.mHandle).menuWidth != 0))
|
|||
|
rval = myPartCode;
|
|||
|
|
|||
|
return (rval);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
DoDispose - Returns the control area as a region
|
|||
|
for Control Mgr calculations
|
|||
|
|
|||
|
hControl - the popup
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void DoDispose(ControlHandle hControl)
|
|||
|
{
|
|||
|
myDataH theData;
|
|||
|
|
|||
|
theData = (myDataH) (**hControl).contrlData;
|
|||
|
if (theData != nil) {
|
|||
|
if (!(**theData).preinstalled) {
|
|||
|
DeleteMenu( (**theData).public.mID);
|
|||
|
DisposeMenu( (**theData).public.mHandle );
|
|||
|
(**theData).public.mHandle = nil;
|
|||
|
}
|
|||
|
|
|||
|
DisposHandle((Handle) theData);
|
|||
|
(**hControl).contrlData = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
DoCalc - Returns the control area as a region
|
|||
|
for Control Mgr calculations
|
|||
|
|
|||
|
hControl - the popup
|
|||
|
theVar - CDEF variant
|
|||
|
theParam - a VAR RgnHandle to return
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void DoCalc(ControlHandle hControl, short theVar, long* theParam)
|
|||
|
{
|
|||
|
ResizeControl(hControl, theVar);
|
|||
|
RectRgn((RgnHandle) (*theParam), &((**((myDataH) (**hControl).contrlData)).myCtlRect));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
DoTrack - Gets the SpandexMDEF if necessary, and
|
|||
|
calls _PopUpMenuSelect.
|
|||
|
|
|||
|
hControl - the popup
|
|||
|
theVar - CDEF variant
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
long DoTrack(ControlHandle hControl, short theVar)
|
|||
|
{
|
|||
|
myDataP dataP;
|
|||
|
MenuHandle hMenu;
|
|||
|
TextState savedInfo; // saved wmgr/cwmgr port font/size
|
|||
|
SpandexH theHandle = nil;
|
|||
|
Rect theRect;
|
|||
|
Point thePoint;
|
|||
|
Boolean useSpandex = true;
|
|||
|
short growWidth;
|
|||
|
short curWidth;
|
|||
|
char myMark;
|
|||
|
long rval = 0;
|
|||
|
short cmdChar = 0;
|
|||
|
short thisMenuID;
|
|||
|
|
|||
|
dataP = *((myDataH) (**hControl).contrlData);
|
|||
|
|
|||
|
hMenu = dataP->public.mHandle;
|
|||
|
|
|||
|
CalcBoxArea(dataP, &theRect);
|
|||
|
thePoint.h = ++theRect.left;
|
|||
|
thePoint.v = ++theRect.top;
|
|||
|
LocalToGlobal(&thePoint);
|
|||
|
|
|||
|
if (theVar & popupUseWFont)
|
|||
|
DoUseWFont(&savedInfo,(**hControl).contrlOwner,true);
|
|||
|
|
|||
|
/* We want to check the current item but won't for StdFile ($1A) or Hier ($1B) */
|
|||
|
/* Also, use checkmark unless we're not using System Font */
|
|||
|
GetItemCmd(hMenu,(**hControl).contrlValue,&cmdChar);
|
|||
|
if ((cmdChar != 0x001A) && (cmdChar != 0x001B)) {
|
|||
|
myMark = (char) checkMark;
|
|||
|
if (theVar & popupUseWFont)
|
|||
|
{
|
|||
|
short sysFont = (*((short *) SysFontFam));
|
|||
|
if (sysFont != GetScript(GetEnvirons(smSysScript), smScriptSysFond))
|
|||
|
myMark = GetIntlTokenChar(tokenCenterDot, Font2Script(sysFont), BulletMark); // no checkmark available
|
|||
|
}
|
|||
|
SetItemMark(hMenu, (**hControl).contrlValue, myMark);
|
|||
|
}
|
|||
|
|
|||
|
/* We want to grow the menu for non-fixed width and for */
|
|||
|
/* fixed width where the menuWidth < controlWidth */
|
|||
|
CalcBoxArea(dataP, &theRect);
|
|||
|
// +1 for the shadow
|
|||
|
growWidth = theRect.right - theRect.left - (**hMenu).menuWidth - popupSlop + 1;
|
|||
|
useSpandex = (growWidth > 0);
|
|||
|
|
|||
|
if (useSpandex) { // invoke spandex MDEF
|
|||
|
*(short*) RomMapInsert = mapTrue; // <SM4> rb
|
|||
|
theHandle = (SpandexH) GetResource(SpandexResType, SpandexMDEF); // <SM4> rb
|
|||
|
if (theHandle != nil) { // load in spandex MDEF
|
|||
|
LoadResource( (Handle) theHandle ); // load in case of purged -- now unpurgeable so remove this
|
|||
|
HLock( (Handle) theHandle );
|
|||
|
if ( * (Handle) theHandle == nil) // was it loaded properly?
|
|||
|
theHandle = nil; // nope
|
|||
|
}
|
|||
|
|
|||
|
if (theHandle != nil) { // splice old mdef into spandex
|
|||
|
(**theHandle).defProc = (**hMenu).menuProc; // store old mdefproc
|
|||
|
|
|||
|
/* If the menu is in a fixed state, then we expand to the max */
|
|||
|
/* otherwise we just grow to the triangle size */
|
|||
|
|
|||
|
curWidth = dataP->myCtlRect.right - dataP->myCtlRect.left;
|
|||
|
if (!((theVar & popupFixedWidth) &&
|
|||
|
((curWidth == dataP->minWidth) ||
|
|||
|
(curWidth == dataP->maxWidth))))
|
|||
|
growWidth = dataP->info.widMax;
|
|||
|
|
|||
|
(**theHandle).dH = growWidth; // amount to widen by...
|
|||
|
|
|||
|
(**hMenu).menuProc = (Handle) theHandle; // splice it in
|
|||
|
CalcMenuSize(hMenu); // recalculate the menu width
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
rval = PopUpMenuSelect(hMenu, thePoint.v, thePoint.h, (**hControl).contrlValue);
|
|||
|
|
|||
|
dataP->popupResult = rval; // track menuID & value for hier menus
|
|||
|
|
|||
|
if (useSpandex) // take off spandex
|
|||
|
if (theHandle != nil) {
|
|||
|
(**hMenu).menuProc = (**theHandle).defProc; // restore mdefproc
|
|||
|
HUnlock( (Handle) theHandle );
|
|||
|
}
|
|||
|
|
|||
|
if ((cmdChar != 0x001A) && (cmdChar != 0x001B))
|
|||
|
CheckItem(hMenu, (**hControl).contrlValue, false); // uncheck the item
|
|||
|
|
|||
|
if ((theVar & popupUseWFont))
|
|||
|
DoUseWFont(&savedInfo,nil,false);
|
|||
|
|
|||
|
dataP->changedVal = false;
|
|||
|
|
|||
|
/*
|
|||
|
To determine the control value we normally check the low word of rval.
|
|||
|
For hierarchial menus, the ctl value should be the parent item of the selected item.
|
|||
|
We match the menuHandles instead of the menu IDs, 'cuz MacApp adds a menuHandle
|
|||
|
from their 'cmnu' stuff
|
|||
|
*/
|
|||
|
|
|||
|
thisMenuID = (rval & 0xFFFF0000) >> 16;
|
|||
|
if (thisMenuID == 0)
|
|||
|
rval = 0;
|
|||
|
else {
|
|||
|
if (GetMHandle(thisMenuID) != dataP->public.mHandle)
|
|||
|
rval = FindHItem(dataP->public.mHandle,thisMenuID);
|
|||
|
else
|
|||
|
rval &= 0x0000FFFF;
|
|||
|
// set the flag for changed val
|
|||
|
dataP->changedVal = ((**hControl).contrlValue != rval);
|
|||
|
(**hControl).contrlValue = rval;
|
|||
|
|
|||
|
rval = myPartCode; // useless as DoTrack is a void()
|
|||
|
}
|
|||
|
|
|||
|
return(rval);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
ResizeControl - Calculates the Rect to draw in.
|
|||
|
Grows contrlRect if needed.
|
|||
|
|
|||
|
hControl - the popup
|
|||
|
theVar - CDEF variant
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void ResizeControl(hControl, theVar)
|
|||
|
ControlHandle hControl;
|
|||
|
short theVar;
|
|||
|
{
|
|||
|
myDataP dataP;
|
|||
|
myDataH theData;
|
|||
|
TextState savedInfo;
|
|||
|
MenuHandle hMenu;
|
|||
|
short height; // also used for menu width
|
|||
|
Rect theRect;
|
|||
|
short curWidth;
|
|||
|
short lineHeight;
|
|||
|
short cmdChar = 0; // for StdFile presence
|
|||
|
short limit;
|
|||
|
Rect controlRect,
|
|||
|
mRect;
|
|||
|
|
|||
|
theData = (myDataH) (**hControl).contrlData;
|
|||
|
|
|||
|
dataP = *theData;
|
|||
|
hMenu = dataP->public.mHandle;
|
|||
|
|
|||
|
// recalculate dynamic properties
|
|||
|
dataP->sysJust = GetSysJust();
|
|||
|
|
|||
|
if ((theVar & popupUseWFont))
|
|||
|
DoUseWFont(&savedInfo,(**hControl).contrlOwner,true);
|
|||
|
|
|||
|
CalcMenuSize(hMenu); // recalculate menusize
|
|||
|
GetFontInfo(&dataP->info); // get font information
|
|||
|
|
|||
|
// Set my control area
|
|||
|
controlRect = (**hControl).contrlRect;
|
|||
|
dataP->myCtlRect = controlRect;
|
|||
|
|
|||
|
// calculate height of the control
|
|||
|
SetRect(&theRect, 0, 0, 0, 0);
|
|||
|
CalcAndDrawItem(hControl, theVar, mCalcItemMsg, &theRect);
|
|||
|
dataP->oldHeight = theRect.bottom;
|
|||
|
dataP->oldWidth = (**hMenu).menuWidth;
|
|||
|
|
|||
|
// If the menu is empty, get the height from the font info
|
|||
|
lineHeight = theRect.bottom; // - top, but top == 0
|
|||
|
if (lineHeight == 0)
|
|||
|
lineHeight = dataP->info.ascent + dataP->info.descent + dataP->info.leading;
|
|||
|
|
|||
|
// We now center the control on the height
|
|||
|
height = ((controlRect.bottom - controlRect.top) - lineHeight - popupSlopV) >> 1;
|
|||
|
dataP->myCtlRect.top += height;
|
|||
|
dataP->myCtlRect.bottom = dataP->myCtlRect.top + lineHeight + popupSlopV;
|
|||
|
|
|||
|
// If the box gets too tall, we shorten the popup to the controlRect for 2 cases:
|
|||
|
// StandardFile and the case where only the triangle is displayed
|
|||
|
|
|||
|
GetItemCmd(hMenu,(**hControl).contrlValue,&cmdChar);
|
|||
|
CalcMenuArea(dataP, &mRect);
|
|||
|
// small menurect => no menuitem drawn
|
|||
|
if ((cmdChar == 0x001A) || ((mRect.right - mRect.left) <= (popupSlop << 1))) {
|
|||
|
limit = controlRect.top;
|
|||
|
if (dataP->myCtlRect.top < limit)
|
|||
|
dataP->myCtlRect.top = limit;
|
|||
|
limit = controlRect.bottom;
|
|||
|
if (dataP->myCtlRect.bottom > limit)
|
|||
|
dataP->myCtlRect.bottom = limit;
|
|||
|
}
|
|||
|
|
|||
|
// Calc the width of the control. If the menu's empty, we set to the max width
|
|||
|
// If StandardFile, the width is the current item, otherwise use menuWidth
|
|||
|
if ((**hMenu).menuWidth == 0)
|
|||
|
height = dataP->maxWidth;
|
|||
|
else {
|
|||
|
height = dataP->info.widMax + dataP->titleWidth + popupSlop;
|
|||
|
if (cmdChar == 0x001A)
|
|||
|
height += theRect.right;
|
|||
|
else
|
|||
|
height += (**hMenu).menuWidth;
|
|||
|
}
|
|||
|
|
|||
|
// Sanity check for new fixed width, both min & max
|
|||
|
if (height > dataP->maxWidth)
|
|||
|
height = dataP->maxWidth;
|
|||
|
|
|||
|
if (height < dataP->minWidth)
|
|||
|
height = dataP->minWidth;
|
|||
|
|
|||
|
/* For popups w/ no title (i.e. StandardFile), we can center the control */
|
|||
|
if ((dataP->titleWidth == 0) &&
|
|||
|
(dataP->titleJust == popupTitleCenterJust)) {
|
|||
|
curWidth = controlRect.right - controlRect.left;
|
|||
|
dataP->myCtlRect.left -= (height - curWidth) >> 1;
|
|||
|
dataP->myCtlRect.right = dataP->myCtlRect.left + height;
|
|||
|
}
|
|||
|
else if (dataP->sysJust == teJustRight)
|
|||
|
dataP->myCtlRect.left = dataP->myCtlRect.right - height;
|
|||
|
else
|
|||
|
dataP->myCtlRect.right = dataP->myCtlRect.left + height;
|
|||
|
|
|||
|
// restore font information
|
|||
|
if ((theVar & popupUseWFont))
|
|||
|
DoUseWFont(&savedInfo,nil,false);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
// Drawing Routines
|
|||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
DrawTriangle - Draws the popup triangle
|
|||
|
|
|||
|
dataP - control info
|
|||
|
dimmed - gray the triangle using fore & back blend
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void DrawTriangle(myDataP dataP, Boolean dimmed)
|
|||
|
{
|
|||
|
short tWidth; // width of triangle
|
|||
|
short tHeight; // height of triangle
|
|||
|
short sWidth; // width of rectangle
|
|||
|
short sHeight; // height of tectangle
|
|||
|
Rect trigRect,
|
|||
|
boxRect;
|
|||
|
short theWidth; // max width of the triangle
|
|||
|
PolyHandle trigPoly;
|
|||
|
PixPatHandle myPixPat = nil;
|
|||
|
|
|||
|
if (dimmed)
|
|||
|
myPixPat = BeginMyGray(dataP);
|
|||
|
|
|||
|
CalcTriangleRect(dataP, &trigRect);
|
|||
|
CalcBoxArea(dataP, &boxRect);
|
|||
|
|
|||
|
theWidth = dataP->info.widMax;
|
|||
|
sWidth = boxRect.right - boxRect.left;
|
|||
|
sHeight = trigRect.bottom - trigRect.top;
|
|||
|
|
|||
|
// We need a width that's 75% of original and even
|
|||
|
tWidth = theWidth;
|
|||
|
tWidth -= (tWidth >> 2);
|
|||
|
if (tWidth & 0x0001)
|
|||
|
tWidth++;
|
|||
|
|
|||
|
// Minimum size sanity checking
|
|||
|
if (tWidth < 6) {
|
|||
|
tWidth = 6;
|
|||
|
if (tWidth > theWidth) {
|
|||
|
if (theWidth < 4)
|
|||
|
return;
|
|||
|
tWidth = 4;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
tHeight = tWidth >> 1;
|
|||
|
|
|||
|
/* Horizontally center the triangle if the control */
|
|||
|
/* isn't wide enough for the menu item */
|
|||
|
if (sWidth < (theWidth + (popupSlop << 1)))
|
|||
|
trigRect.left = boxRect.left + ((sWidth - tWidth) >> 1);
|
|||
|
else if (dataP->sysJust == teJustRight)
|
|||
|
trigRect.left = trigRect.right - tWidth;
|
|||
|
|
|||
|
trigRect.right = trigRect.left + tWidth;
|
|||
|
trigRect.top += ((sHeight - tHeight) >> 1); // move top by half of vertical whitespace
|
|||
|
trigRect.bottom = trigRect.top + tHeight;
|
|||
|
|
|||
|
trigPoly = OpenPoly();
|
|||
|
MoveTo(trigRect.left, trigRect.top);
|
|||
|
LineTo(trigRect.right, trigRect.top);
|
|||
|
LineTo((trigRect.right + trigRect.left) >> 1, trigRect.bottom);
|
|||
|
LineTo(trigRect.left, trigRect.top);
|
|||
|
ClosePoly();
|
|||
|
|
|||
|
PaintPoly(trigPoly);
|
|||
|
KillPoly(trigPoly);
|
|||
|
|
|||
|
PenNormal();
|
|||
|
if (myPixPat != nil)
|
|||
|
DisposPixPat(myPixPat);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
DrawTitle - Draws the popup title
|
|||
|
|
|||
|
controlP - control
|
|||
|
dataP - control info
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void DrawTitle(ControlPtr controlP, myDataP dataP)
|
|||
|
{
|
|||
|
Rect titleRect,
|
|||
|
theRect;
|
|||
|
Style oldStyle;
|
|||
|
short oldMode;
|
|||
|
Str255 theString;
|
|||
|
short width;
|
|||
|
|
|||
|
CalcTitleArea(dataP, &titleRect);
|
|||
|
InsetRect(&titleRect,0,1);
|
|||
|
|
|||
|
// Erase the title & swap colors for color inverse
|
|||
|
if (dataP->useColor)
|
|||
|
SetColors(dataP->public.mID, 0, (controlP->contrlHilite == myPartCode)); // use menu table
|
|||
|
|
|||
|
EraseRect(&titleRect);
|
|||
|
|
|||
|
oldStyle = (controlP->contrlOwner)->txFace;
|
|||
|
oldMode = (controlP->contrlOwner)->txMode;
|
|||
|
TextFace(dataP->titleStyle);
|
|||
|
|
|||
|
// We dim the control if the hilite is set, or the menu is empty
|
|||
|
if ((controlP->contrlHilite == 255) ||
|
|||
|
((**dataP->public.mHandle).menuWidth == 0))
|
|||
|
TextMode(grayishTextOr);
|
|||
|
|
|||
|
BlockMove((Ptr) controlP->contrlTitle, (Ptr) theString,
|
|||
|
Length(controlP->contrlTitle) + 1);
|
|||
|
|
|||
|
// textbox rect
|
|||
|
theRect = titleRect;
|
|||
|
InsetRect(&theRect, popupSlop, 0);
|
|||
|
|
|||
|
// turn on condensing if we can't fit
|
|||
|
width = theRect.right - theRect.left - 1; // 1 is for indent
|
|||
|
if (StringWidth(theString) > width) {
|
|||
|
TextFace(dataP->titleStyle | condense);
|
|||
|
TruncString(width, theString, smTruncEnd);
|
|||
|
}
|
|||
|
TextBox((Ptr) (theString + 1), Length(theString), &theRect, dataP->titleJust );
|
|||
|
TextFace(oldStyle);
|
|||
|
TextMode(oldMode);
|
|||
|
|
|||
|
// now hilite the title if necessary and if not CQD (CQD already done above)
|
|||
|
if (controlP->contrlHilite == myPartCode)
|
|||
|
if (! dataP->useColor)
|
|||
|
InvertRect(&titleRect);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
MakeColorPort - Returns a color grafport
|
|||
|
|
|||
|
owner - where this will reside
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
CGrafPtr MakeColorPort(GrafPtr owner)
|
|||
|
{
|
|||
|
Rect theRect;
|
|||
|
Point tempPt;
|
|||
|
TextState myText;
|
|||
|
CGrafPtr myCPort;
|
|||
|
|
|||
|
myCPort = (CGrafPtr) NewPtr(sizeof(CGrafPort)); // create color graf port
|
|||
|
if (myCPort != nil) {
|
|||
|
theRect = owner->portRect;
|
|||
|
|
|||
|
tempPt.h = theRect.left;
|
|||
|
tempPt.v = theRect.top;
|
|||
|
|
|||
|
LocalToGlobal(&tempPt);
|
|||
|
OpenCPort(myCPort); // initialize the port (and set to it)
|
|||
|
MovePortTo(tempPt.h, tempPt.v); // and size it properly
|
|||
|
PortSize( theRect.right - theRect.left, theRect.bottom - theRect.top);
|
|||
|
|
|||
|
// now copy quickdraw stuff
|
|||
|
myText.theFont = owner->txFont;
|
|||
|
myText.theSize = owner->txSize;
|
|||
|
myText.theFace = owner->txFace;
|
|||
|
myText.theMode = owner->txMode;
|
|||
|
SetTextState(&myText);
|
|||
|
|
|||
|
PenNormal(); // Isn't this done for us?
|
|||
|
CopyRgn(owner->clipRgn, myCPort->clipRgn);
|
|||
|
CopyRgn(owner->visRgn, myCPort->visRgn);
|
|||
|
if (owner->pnVis < 0)
|
|||
|
HidePen();
|
|||
|
}
|
|||
|
|
|||
|
return(myCPort);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
SetColors - Sets the RGB Fore & Back colors to
|
|||
|
the appropriate values
|
|||
|
|
|||
|
menuID - for the menu color table entry
|
|||
|
menuItem - > 0 --> item color table entry
|
|||
|
= 0 --> use menu CT
|
|||
|
= -1 --> set to default colors
|
|||
|
isHilited - reverse the colors if we're hilited
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void SetColors(short menuID, short menuItem, Boolean isHilited)
|
|||
|
{
|
|||
|
RGBColor newCQDFore, newCQDBack,
|
|||
|
*foreCP, *backCP;
|
|||
|
MCEntryPtr theMenuColor;
|
|||
|
|
|||
|
newCQDFore.red = // load up initial values
|
|||
|
newCQDFore.green =
|
|||
|
newCQDFore.blue = 0;
|
|||
|
|
|||
|
newCQDBack.red =
|
|||
|
newCQDBack.green =
|
|||
|
newCQDBack.blue = 0xFFFF;
|
|||
|
|
|||
|
/* We try to get the colors asked for. */
|
|||
|
/* Failing that, we keep trying 'till default mctb */
|
|||
|
|
|||
|
if (menuItem == -1) // just set to default color
|
|||
|
goto setColor;
|
|||
|
|
|||
|
if (menuItem == 0) // default item color
|
|||
|
goto getMenuColor;
|
|||
|
|
|||
|
/* We have to make local copies of the menu colors, 'cuz the */
|
|||
|
/* table is relocatable, and RGBForColor may move it */
|
|||
|
|
|||
|
// use mctb for menu/item
|
|||
|
if ((theMenuColor = GetMCEntry(menuID,menuItem)) != nil) {
|
|||
|
newCQDFore = theMenuColor->mctRGB2; // item color
|
|||
|
newCQDBack = theMenuColor->mctRGB4; // item background color
|
|||
|
goto setColor;
|
|||
|
}
|
|||
|
|
|||
|
getMenuColor: // use mctb for menu
|
|||
|
if ((theMenuColor = GetMCEntry(menuID,0)) != nil) {
|
|||
|
newCQDFore = theMenuColor->mctRGB3; // default item color
|
|||
|
newCQDBack = theMenuColor->mctRGB4; // default item background color
|
|||
|
goto setColor;
|
|||
|
}
|
|||
|
|
|||
|
getSystemColor: // use default mctb
|
|||
|
if ((theMenuColor = GetMCEntry(0,0)) != nil) {
|
|||
|
newCQDFore = theMenuColor->mctRGB3; // default title color
|
|||
|
newCQDBack = theMenuColor->mctRGB2; // default menubar background color
|
|||
|
}
|
|||
|
|
|||
|
setColor:
|
|||
|
foreCP = &newCQDFore; // ptrs for easy swap & small size
|
|||
|
backCP = &newCQDBack;
|
|||
|
|
|||
|
if (isHilited) {
|
|||
|
foreCP = &newCQDBack; // swap values if we're highlighted
|
|||
|
backCP = &newCQDFore;
|
|||
|
}
|
|||
|
|
|||
|
RGBForeColor(foreCP);
|
|||
|
RGBBackColor(backCP);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
// Calculation Routines
|
|||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
CalcAndDrawItem - passes mCalcMsg or mDrawMsg to the
|
|||
|
menu defProc
|
|||
|
|
|||
|
hControl - the popup
|
|||
|
theVar - CDEF variant
|
|||
|
theRect - what to return
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void CalcAndDrawItem(ControlHandle hControl, short theVar, short theMsg, Rect* theRect)
|
|||
|
{
|
|||
|
myDataH theData;
|
|||
|
MDEFHandle theHandle;
|
|||
|
short whichItem;
|
|||
|
TextState savedInfo;
|
|||
|
unsigned char theState;
|
|||
|
|
|||
|
theData = (myDataH) (**hControl).contrlData;
|
|||
|
|
|||
|
theHandle = (MDEFHandle) (**((**theData).public.mHandle)).menuProc;
|
|||
|
if (theHandle == nil)
|
|||
|
return;
|
|||
|
|
|||
|
LoadResource((Handle) theHandle);
|
|||
|
if (*((Handle) theHandle) == nil)
|
|||
|
return;
|
|||
|
|
|||
|
// Set up the grafport info
|
|||
|
if (theVar & popupUseWFont)
|
|||
|
DoUseWFont(&savedInfo,(**hControl).contrlOwner,true);
|
|||
|
|
|||
|
whichItem = (**hControl).contrlValue;
|
|||
|
|
|||
|
// Is the lock really needed??
|
|||
|
theState = HGetState( (Handle) theHandle);
|
|||
|
HLock((Handle) theHandle);
|
|||
|
(**theHandle) (theMsg, (**theData).public.mHandle, theRect, * (Point*) theRect, &whichItem);
|
|||
|
HSetState((Handle) theHandle, theState);
|
|||
|
|
|||
|
// Reset the grafport info
|
|||
|
if (theVar & popupUseWFont)
|
|||
|
DoUseWFont(&savedInfo,nil,false);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
CalcTriangleRect - Calcs triangle rect for pict
|
|||
|
|
|||
|
dataP - the popup
|
|||
|
theRect - what to return
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void CalcTriangleRect(myDataP dataP, Rect *theRect)
|
|||
|
{
|
|||
|
short tWidth;
|
|||
|
|
|||
|
CalcBoxArea(dataP, theRect);
|
|||
|
|
|||
|
tWidth = dataP->info.widMax + popupSlop;
|
|||
|
|
|||
|
InsetRect(theRect,1,1);
|
|||
|
if (dataP->sysJust == teJustRight)
|
|||
|
theRect->right = theRect->left + tWidth;
|
|||
|
else
|
|||
|
theRect->left = theRect->right - tWidth;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
CalcTitleArea - Calcs enclosing title rect
|
|||
|
|
|||
|
dataP - the popup
|
|||
|
theRect - what to return
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void CalcTitleArea(myDataP dataP,Rect *theRect)
|
|||
|
{
|
|||
|
short tWidth;
|
|||
|
|
|||
|
*theRect = dataP->myCtlRect;
|
|||
|
tWidth = dataP->titleWidth;
|
|||
|
|
|||
|
if (dataP->sysJust == teJustRight)
|
|||
|
theRect->left = theRect->right - tWidth;
|
|||
|
else
|
|||
|
theRect->right = theRect->left + tWidth;
|
|||
|
|
|||
|
--theRect->bottom;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
CalcBoxArea - Calcs popup box without shadow
|
|||
|
|
|||
|
dataP - the popup
|
|||
|
theRect - what to return
|
|||
|
**************************************************************/
|
|||
|
void CalcBoxArea(myDataP dataP, Rect *theRect)
|
|||
|
{
|
|||
|
short tWidth;
|
|||
|
|
|||
|
*theRect = dataP->myCtlRect;
|
|||
|
tWidth = dataP->titleWidth;
|
|||
|
|
|||
|
if (dataP->sysJust == teJustRight)
|
|||
|
theRect->right -= tWidth;
|
|||
|
else
|
|||
|
theRect->left += tWidth;
|
|||
|
|
|||
|
--theRect->bottom;
|
|||
|
--theRect->right;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
CalcMenuArea - Calcs popup box without shadow, triangle
|
|||
|
|
|||
|
dataP - the popup
|
|||
|
theRect - what to return
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void CalcMenuArea(myDataP dataP, Rect *theRect)
|
|||
|
{
|
|||
|
short tWidth;
|
|||
|
|
|||
|
tWidth = dataP->info.widMax + popupSlop;
|
|||
|
CalcBoxArea(dataP, theRect);
|
|||
|
|
|||
|
if (dataP->sysJust == teJustRight) {
|
|||
|
theRect->left += tWidth;
|
|||
|
--theRect->right;
|
|||
|
}
|
|||
|
else {
|
|||
|
theRect->right -= tWidth;
|
|||
|
++theRect->left;
|
|||
|
}
|
|||
|
|
|||
|
++theRect->top;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
CalcShadowArea - Calc rect for popup shadow
|
|||
|
|
|||
|
dataP - the popup
|
|||
|
theRect - what to return
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void CalcShadowArea(myDataP dataP, Rect *theRect)
|
|||
|
{
|
|||
|
CalcBoxArea(dataP, theRect);
|
|||
|
theRect->left += shadowLeft;
|
|||
|
theRect->top += shadowTop;
|
|||
|
++theRect->right;
|
|||
|
++theRect->bottom;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
GetTextState - Loads the current grafport text info
|
|||
|
|
|||
|
txState - Like penState
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void GetTextState(TextState *txState)
|
|||
|
{
|
|||
|
GrafPtr thePort;
|
|||
|
|
|||
|
GetPort(&thePort);
|
|||
|
|
|||
|
txState->theFont = thePort->txFont;
|
|||
|
txState->theFace = thePort->txFace;
|
|||
|
txState->theSize = thePort->txSize;
|
|||
|
txState->theMode = thePort->txMode;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
SetTextState - Sets the current grafport text info
|
|||
|
|
|||
|
txState - Like penState
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void SetTextState(TextState *txState)
|
|||
|
{
|
|||
|
TextFont(txState->theFont);
|
|||
|
TextSize(txState->theSize);
|
|||
|
TextFace(txState->theFace);
|
|||
|
TextMode(txState->theMode);
|
|||
|
}
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
SaveAndResetWMPorts -
|
|||
|
saves font and size for window manager
|
|||
|
port and color window manager port
|
|||
|
then sets them to zero
|
|||
|
WMPortState - Like penState
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void
|
|||
|
SaveAndResetWMPorts(WMPortState *pWMPortState)
|
|||
|
{
|
|||
|
GrafPtr tempPort;
|
|||
|
CGrafPtr tempCPort;
|
|||
|
|
|||
|
tempPort = * (GrafPtr *) WMgrPort;
|
|||
|
pWMPortState->savedFont = tempPort->txFont;
|
|||
|
pWMPortState->savedSize = tempPort->txSize;
|
|||
|
tempPort->txFont = tempPort->txSize = 0;
|
|||
|
|
|||
|
if (HaveCQD()) {
|
|||
|
tempCPort = * (CGrafPtr *) WMgrCPort;
|
|||
|
pWMPortState->savedCFont = tempCPort->txFont;
|
|||
|
pWMPortState->savedCSize = tempCPort->txSize;
|
|||
|
tempCPort->txFont = tempCPort->txSize = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
RestoreWMPorts - sets the wmgr and color wmgr ports
|
|||
|
WMPortState - Like penState
|
|||
|
**************************************************************/
|
|||
|
void
|
|||
|
RestoreWMPorts(WMPortState *pWMPortState)
|
|||
|
{
|
|||
|
GrafPtr tempPort;
|
|||
|
CGrafPtr tempCPort;
|
|||
|
|
|||
|
tempPort = * (GrafPtr *) WMgrPort;
|
|||
|
tempPort->txFont = pWMPortState->savedFont;
|
|||
|
tempPort->txSize = pWMPortState->savedSize;
|
|||
|
|
|||
|
if (HaveCQD()) {
|
|||
|
tempCPort = * (CGrafPtr *) WMgrCPort;
|
|||
|
tempCPort->txFont = pWMPortState->savedCFont;
|
|||
|
tempCPort->txSize = pWMPortState->savedCSize;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
DoUseWFont - Sets the font mgr low mem globals so
|
|||
|
we can have Geneva 9 popups
|
|||
|
|
|||
|
savedInfo - Fills it in if saveIt = true, else
|
|||
|
it sets the port to those values
|
|||
|
owner - Where to get the original values
|
|||
|
saveIt - true at the start of the
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
void DoUseWFont(TextState *savedInfo, WindowPtr owner, Boolean saveIt)
|
|||
|
{
|
|||
|
TextState myState,
|
|||
|
*theState;
|
|||
|
short aFont;
|
|||
|
|
|||
|
theState = savedInfo;
|
|||
|
|
|||
|
if (saveIt) {
|
|||
|
savedInfo->theFont = *((short *) SysFontFam); // save low memory globals
|
|||
|
savedInfo->theSize = *((short *) SysFontSize);
|
|||
|
|
|||
|
myState.theFont = owner->txFont;
|
|||
|
myState.theSize = owner->txSize;
|
|||
|
theState = &myState;
|
|||
|
|
|||
|
// if we stuff systemFont, it will screw up Script Mgr
|
|||
|
if (owner->txFont == systemFont)
|
|||
|
goto dosizestuff;
|
|||
|
}
|
|||
|
|
|||
|
// if we stuff applFont, this will also screw up Script Mgr
|
|||
|
// instead we get the actual font
|
|||
|
|
|||
|
aFont = theState->theFont;
|
|||
|
if (saveIt)
|
|||
|
if (owner->txFont == applFont)
|
|||
|
aFont = *((short *) ApFontID);
|
|||
|
*((short *) SysFontFam) = aFont; // set/restore low memory globals
|
|||
|
|
|||
|
dosizestuff:
|
|||
|
*((short *) SysFontSize) = theState->theSize;
|
|||
|
|
|||
|
*((long *) CurFMInput) = 0xFFFFFFFF;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
BeginMyGray - Sets up the pen, etc for disabled
|
|||
|
drawing
|
|||
|
|
|||
|
returns - A colorQD pattern
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
PixPatHandle BeginMyGray(myDataP dataP)
|
|||
|
{
|
|||
|
Pattern pat;
|
|||
|
RGBColor oldFore, oldAft;
|
|||
|
PixPatHandle myPixPat = nil;
|
|||
|
|
|||
|
if (dataP->useColor) {
|
|||
|
// do color QD stuff here
|
|||
|
GetForeColor(&oldFore);
|
|||
|
GetBackColor(&oldAft);
|
|||
|
|
|||
|
// gimme average RGB. Why does MenuMgr do a ROXR instead of an ASR??
|
|||
|
oldFore.red = (oldFore.red + oldAft.red) >> 1;
|
|||
|
oldFore.green = (oldFore.green + oldAft.green) >> 1;
|
|||
|
oldFore.blue = (oldFore.blue + oldAft.blue) >> 1;
|
|||
|
|
|||
|
myPixPat = NewPixPat();
|
|||
|
|
|||
|
if (myPixPat != nil) {
|
|||
|
MakeRGBPat(myPixPat,&oldFore);
|
|||
|
PenPixPat(myPixPat);
|
|||
|
}
|
|||
|
|
|||
|
TextMode(grayishTextOr); //grayish text copy
|
|||
|
}
|
|||
|
|
|||
|
if (myPixPat == nil) {
|
|||
|
GetIndPattern(&pat,sysPatListID,grayPatternID);
|
|||
|
PenPat(&pat);
|
|||
|
}
|
|||
|
|
|||
|
return(myPixPat);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
FindHItem - Tries to find a hierarchial item in the
|
|||
|
menu with the given hier menu id
|
|||
|
|
|||
|
returns - The parent item number
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
short FindHItem(MenuHandle hMenu, short hMenuID)
|
|||
|
{
|
|||
|
short i;
|
|||
|
short cmdChar = 0,
|
|||
|
markChar = 0;
|
|||
|
|
|||
|
for (i = 1;i <= CountMItems(hMenu);i++) {
|
|||
|
GetItemCmd(hMenu, i, &cmdChar);
|
|||
|
if (cmdChar == 0x001B) {
|
|||
|
GetItemMark(hMenu, i, &markChar);
|
|||
|
if (markChar == hMenuID)
|
|||
|
return(i);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return(1);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/*************************************************************
|
|||
|
GetIntlTokenChar - Get the token for the given script
|
|||
|
|
|||
|
returns - The token or the default if error
|
|||
|
**************************************************************/
|
|||
|
|
|||
|
char GetIntlTokenChar(short whichToken, short whichScript, char defaultChar)
|
|||
|
{
|
|||
|
Handle itl4H;
|
|||
|
long offset, len;
|
|||
|
|
|||
|
// Look up the untoken table -- bail if we can<61>t get it
|
|||
|
IUGetItlTable(whichScript, iuUnTokenTable, &itl4H, &offset, &len);
|
|||
|
if (itl4H && (offset > 0) && (len >= 0))
|
|||
|
{
|
|||
|
char *sp = (*itl4H + offset); // Point to start of untoken table
|
|||
|
if (whichToken <= ((short *)sp)[1]) // Check if token has valid index
|
|||
|
{
|
|||
|
sp += ((short *)sp)[2+whichToken]; // Add the string offset and voli<6C>!
|
|||
|
if (*sp == 1) defaultChar = sp[1]; // Might be 2-byte, so check length byte
|
|||
|
}
|
|||
|
}
|
|||
|
return(defaultChar);
|
|||
|
}
|