sys7.1-doc-wip/Toolbox/ControlMgr/PopupCDEF.c
2020-04-26 16:46:44 +08:00

1695 lines
54 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
Hacks to match MacOS (most recent first):
<Sys7.1> 8/3/92 Reverted <SM4> expectation of finding the menu-widening "wrapper" MDEF
(really a proc resource) in ROM -- probably a bug, because the defproc
resource needs to be writeable. Reverted <43> to use the old array
definition of Pattern.
9/2/94 SuperMario ROM source dump (header preserved below)
*/
/*
File: PopupCDEF.c
Contains: Source code for Popup Menu CDEF
Written by: Byron Han
Copyright: © 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
• REALPOPUP() when saving port state, also save and reset the
window manager port and color port font and size to 0, 0
• DoDraw() fix bug where triangles for items after the 31st in
the menu would be dimmed
• DoUseWFont() fix bug where if the owning window font was the
system font we would not set the size for the control properly.
• 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]
• SaveAndResetWMPorts() added
• 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 — 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 — 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:
• 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 • 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 • 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
*/
#define dangerousPattern // ex<43> <Sys7.1>
#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 were 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); // were 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
theHandle = (SpandexH) GetResource(SpandexResType, SpandexMDEF); // <SM4> rb <Sys7.1>
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 cant 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á!
if (*sp == 1) defaultChar = sp[1]; // Might be 2-byte, so check length byte
}
}
return(defaultChar);
}