mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2025-01-04 01:29:22 +00:00
0ba83392d4
Resource forks are included only for .rsrc files. These are DeRezzed into their data fork. 'ckid' resources, from the Projector VCS, are not included. The Tools directory, containing mostly junk, is also excluded.
581 lines
15 KiB
C
581 lines
15 KiB
C
/*
|
|
File: CommToolboxUtilityRoutines.c
|
|
|
|
Contains: Various routines
|
|
|
|
Written by: Byron Han
|
|
Alex Kazim
|
|
|
|
Copyright: © 1990, 1992 by Apple Computer, Inc., all rights reserved.
|
|
|
|
|
|
Change History (most recent first):
|
|
|
|
<16> 11/13/92 JDR Updated QuickDraw.h to not use the dangerous pattern type.
|
|
<15> 5/29/92 DCL Included TextUtils.h and Script.h. EqualString and GetScript
|
|
moved for the New Inside Mac.
|
|
<14> 2/8/91 JNG kaz,#82584:Getflst needs to make sure the system file is in the
|
|
resource chain before calling GetIndFlst.
|
|
<13> 8/19/90 kaz Fixed gray OK outline to check for ColorQD and a color port.
|
|
<12> 8/15/90 kaz Added PlaceWindow() routine to perform 2/3rds centering.
|
|
<11> 8/6/90 kaz Added grayOutline button routine, HaveColorQD() macro.
|
|
<10> 7/2/90 kaz GetIndflst will compensate for odd font names.
|
|
<9> 5/24/90 kaz Combined GetIndfinf & GetIndflst; Added Getflst()
|
|
<8> 5/22/90 kaz Renamed Parse_finf, Parse_flst. Using new TextState data struct.
|
|
Adding GetTextState, SetTextState
|
|
<7> 4/18/90 kaz DoTheIcon() now uses only 1 BitMap
|
|
<6> 4/11/90 kaz Added International CmdPeriod() from TechNotes
|
|
<5> 3/20/90 kaz Merging utility routines from 1.0
|
|
- Fetch QD Globals
|
|
- Get just the DITL ItemRect
|
|
- Set the UserItem Proc
|
|
- PCopyString instead of Pascal aStr := bStr
|
|
<4> 3/16/90 BBH added MIN and MAX routines
|
|
<3> 3/16/90 BBH change GetDitem to GetDItem
|
|
<2> 3/16/90 BBH added DoTheIcon, parse_finf, parse_flst, FindMenuItem,
|
|
GoodDrawOutlineButton
|
|
<1> 3/14/90 BBH first checked in
|
|
|
|
To Do:
|
|
*/
|
|
|
|
// These are utility routines used by CommToolboxCore.c and the various managers
|
|
|
|
// this routine returns the first resource of the given type from the
|
|
// tool with the procID specified. This makes no assumptions about the
|
|
// tool already being in the resource chain
|
|
|
|
#include <Menus.h>
|
|
#include <Dialogs.h>
|
|
#include <QuickDraw.h>
|
|
#include <Fonts.h>
|
|
#include <SysEqu.h>
|
|
#include <TextUtils.h>
|
|
#include <Script.h>
|
|
|
|
#include "CTBUtilities.h"
|
|
#include "CommResources.h"
|
|
#include "CommToolboxPriv.h"
|
|
|
|
/* For CmdPeriod() */
|
|
#define kMaskModifiers 0xFE00 // strip the cmd key
|
|
#define kMaskVirtualKey 0x0000FF00 // virtual key from event
|
|
#define kUpKeyMask 0x0080
|
|
#define kShiftWord 8 // virtual key -> keycode
|
|
#define kMaskASCII1 0x00FF0000 // getting the key
|
|
#define kMaskASCII2 0x000000FF
|
|
#define kPeriod 0x2E // ascii for a '.'
|
|
|
|
#define HaveCQD() ((*(unsigned short *) ROM85) <= 0x3FFF)
|
|
|
|
pascal long MIN(a, b)
|
|
long a, b;
|
|
{
|
|
return( a < b ? a : b);
|
|
}
|
|
|
|
pascal long MAX(a, b)
|
|
long a, b;
|
|
{
|
|
return( a > b ? a : b);
|
|
}
|
|
|
|
pascal Handle CRMGetAResource(theType, procID)
|
|
ResType theType;
|
|
short procID;
|
|
{
|
|
CRMToolContext theContext;
|
|
short cur;
|
|
Handle theHandle;
|
|
|
|
CRMToolPreflight(procID, &theContext);
|
|
cur = CurResFile();
|
|
UseResFile(procID);
|
|
theHandle = CRMGet1IndResource(theType, 1);
|
|
UseResFile(cur);
|
|
CRMToolPostflight(&theContext);
|
|
|
|
return(theHandle);
|
|
}
|
|
|
|
pascal void DoTheIcon(theIcon, destRect, selected)
|
|
Ptr theIcon;
|
|
const Rect *destRect;
|
|
Boolean selected;
|
|
{
|
|
|
|
#define ICONSIZE 32
|
|
|
|
typedef struct IconsRecord {
|
|
long icon[ICONSIZE];
|
|
long mask[ICONSIZE];
|
|
} IconsRecord, *IconsRecordPtr;
|
|
|
|
BitMap mBitMap;
|
|
GrafPtr myPort;
|
|
IconsRecordPtr iP;
|
|
|
|
GetPort(&myPort);
|
|
|
|
SetRect(&mBitMap.bounds, 0, 0, ICONSIZE, ICONSIZE);
|
|
mBitMap.rowBytes = 4;
|
|
|
|
iP = (IconsRecordPtr) theIcon;
|
|
|
|
mBitMap.baseAddr = (Ptr) &iP->mask;
|
|
CopyBits(&mBitMap, &myPort->portBits, &mBitMap.bounds, destRect, selected ? srcOr : srcBic, nil);
|
|
|
|
mBitMap.baseAddr = (Ptr) &iP->icon;
|
|
CopyBits(&mBitMap, &myPort->portBits, &mBitMap.bounds, destRect, srcXor, nil);
|
|
}
|
|
|
|
|
|
/*************************************************************
|
|
DoSolidOutline - Draws a solid outline
|
|
Used for default buttons.
|
|
|
|
pDialog - Where we are
|
|
theItem - The DITL item #
|
|
**************************************************************/
|
|
pascal void DoSolidOutline(DialogPtr pDialog, short theItem)
|
|
{
|
|
Rect itemRect;
|
|
PenState ps;
|
|
|
|
GetPenState(&ps);
|
|
PenNormal();
|
|
PenSize(3,3);
|
|
GetItemRect(pDialog, theItem, &itemRect);
|
|
FrameRoundRect(&itemRect, 16, 16);
|
|
SetPenState(&ps);
|
|
}
|
|
|
|
/*************************************************************
|
|
DoGrayOutline - Draws a gray outline
|
|
Used for default buttons.
|
|
|
|
pDialog - Where we are
|
|
theItem - The DITL item #
|
|
**************************************************************/
|
|
pascal void DoGrayOutline(DialogPtr pDialog, short theItem)
|
|
{
|
|
Rect itemRect;
|
|
PenState ps;
|
|
GrafWorldPtr qdWorld;
|
|
PixPatHandle myPix = nil;
|
|
RGBColor oldFore,
|
|
oldAft;
|
|
|
|
GetPenState(&ps);
|
|
PenNormal();
|
|
PenSize(3,3);
|
|
GetItemRect(pDialog, theItem, &itemRect);
|
|
|
|
if (HaveCQD())
|
|
if (((CGrafPtr) pDialog)->portVersion & 0xC000) {
|
|
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;
|
|
|
|
myPix = NewPixPat();
|
|
|
|
if (myPix != nil) {
|
|
MakeRGBPat(myPix,&oldFore);
|
|
PenPixPat(myPix);
|
|
}
|
|
}
|
|
|
|
|
|
if (myPix == nil) {
|
|
qdWorld = GetQDGlobals();
|
|
PenPat((ConstPatternParam)&(qdWorld->gray));
|
|
}
|
|
|
|
FrameRoundRect(&itemRect, 16, 16);
|
|
|
|
if (myPix != nil)
|
|
DisposPixPat(myPix);
|
|
|
|
SetPenState(&ps);
|
|
}
|
|
|
|
|
|
/*************************************************************
|
|
GetIndflst - Walks the font info template ('finf' or
|
|
'flst' and tries to get the request
|
|
|
|
hInfo - A handle to the data from GetResource
|
|
oldStyle - True if a 'finf', else 'flst'
|
|
index - Which font info do you want
|
|
finfInfo - Info to return
|
|
|
|
returns - -1 if it didn't work
|
|
**************************************************************/
|
|
|
|
pascal OSErr GetIndflst(hInfo, oldStyle, index, finfInfo)
|
|
Handle hInfo;
|
|
Boolean oldStyle;
|
|
short index;
|
|
TextState *finfInfo;
|
|
{
|
|
short numEntries;
|
|
long offset;
|
|
Str255 fontName;
|
|
short i;
|
|
short aFont;
|
|
|
|
finfInfo->theFont = 0; // resort to defaults
|
|
finfInfo->theSize = 0;
|
|
finfInfo->theFace = 0;
|
|
finfInfo->theMode = srcOr;
|
|
|
|
numEntries = *((short *) (*hInfo));
|
|
offset = (long) (*hInfo) + sizeof(numEntries);
|
|
|
|
/* Have to walk this 'cuz 'flst' is variable length */
|
|
for (i = 1; i <= numEntries; i++) {
|
|
if (oldStyle) {
|
|
aFont = *((short *) offset);
|
|
offset += sizeof(short);
|
|
}
|
|
else {
|
|
BlockMove((Ptr) offset, fontName, *((unsigned char *) offset) + 1);
|
|
offset += Length(fontName) + 1; // add length + length-byte
|
|
if (offset & 0x0001) // even it out
|
|
offset++;
|
|
}
|
|
|
|
/* Grab the rest of the data */
|
|
if (i == index) {
|
|
if (oldStyle)
|
|
finfInfo->theFont = aFont;
|
|
else
|
|
GetFNum(fontName, &finfInfo->theFont);
|
|
finfInfo->theFace = *((short *) offset);
|
|
offset += sizeof(short);
|
|
finfInfo->theSize = *((short *) offset);
|
|
offset += sizeof(short);
|
|
if (! oldStyle) // mode does not exist in 'finf'
|
|
finfInfo->theMode = *((short *) offset);
|
|
return(noErr);
|
|
}
|
|
|
|
offset += sizeof(short); // face
|
|
offset += sizeof(short); // size
|
|
if (! oldStyle)
|
|
offset += sizeof(short); // mode
|
|
}
|
|
return(-1);
|
|
}
|
|
|
|
|
|
/*************************************************************
|
|
Getflst - Tries to get the 'flst' resource from the
|
|
specified file, then tries to get a 'finf',
|
|
finally resorts to System 'flst'. Assumes that
|
|
the resource will exist in the System.
|
|
|
|
procID - The file to get it from
|
|
resourceID - yes
|
|
finfIndex - Index to get
|
|
finfInfo - Info to return
|
|
|
|
**************************************************************/
|
|
|
|
#define toolFINF 1
|
|
#define sysFLST 2
|
|
|
|
pascal void Getflst(procID, resourceID, finfIndex, finfInfo)
|
|
short procID;
|
|
short resourceID;
|
|
short finfIndex;
|
|
TextState *finfInfo;
|
|
{
|
|
short savedResRef;
|
|
Handle theResource;
|
|
short tries;
|
|
ResType theType;
|
|
|
|
savedResRef = CurResFile();
|
|
|
|
|
|
for (tries = 0; tries < 3; tries++) {
|
|
|
|
|
|
theType = 'flst';
|
|
if (tries == toolFINF) // we try the 'finf' to maintain compatibility
|
|
theType = 'finf';
|
|
|
|
if (tries == sysFLST)
|
|
UseResFile(0);
|
|
else
|
|
UseResFile(procID);
|
|
|
|
theResource = Get1Resource(theType, resourceID);
|
|
|
|
if (theResource == nil)
|
|
continue;
|
|
|
|
UseResFile(0); // Needs to be the system so GetIndflst can find font names
|
|
|
|
if (GetIndflst(theResource, (tries == toolFINF), finfIndex, finfInfo) == noErr)
|
|
break;
|
|
}
|
|
|
|
UseResFile(savedResRef);
|
|
}
|
|
|
|
|
|
|
|
/*************************************************************
|
|
GetTextState - Loads the current grafport text info
|
|
|
|
txState - Like penState
|
|
**************************************************************/
|
|
|
|
pascal 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
|
|
**************************************************************/
|
|
|
|
pascal void SetTextState(TextState *txState)
|
|
{
|
|
TextFont(txState->theFont);
|
|
TextSize(txState->theSize);
|
|
TextFace(txState->theFace);
|
|
TextMode(txState->theMode);
|
|
}
|
|
|
|
|
|
|
|
pascal short FindMenuItem(hMenu, theItem)
|
|
MenuHandle hMenu;
|
|
const Str255 theItem;
|
|
{
|
|
short i;
|
|
Str255 theString;
|
|
short limit;
|
|
|
|
limit = CountMItems(hMenu);
|
|
for (i = 1; i <= limit; i++) {
|
|
GetItem(hMenu, i, &theString);
|
|
if (EqualString(theString, theItem, false, true) )
|
|
return(i);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
/*************************************************************
|
|
GetQDGlobals - Gets a pointer to the start of
|
|
the QD Globals given that A5 is valid
|
|
|
|
oneWorld - The stuff we need
|
|
|
|
**************************************************************/
|
|
|
|
pascal GrafWorldPtr GetQDGlobals()
|
|
{
|
|
GrafWorldPtr oneWorld;
|
|
|
|
/* A5 points to thePort of QD Global structure, so we add */
|
|
/* the GrafPtr to make oneWorld point past the bottom */
|
|
/* Then we make oneWorld point to the top */
|
|
|
|
oneWorld = (GrafWorldPtr) ((**((long **) CurrentA5)) + sizeof(GrafPtr));
|
|
return(--oneWorld);
|
|
}
|
|
|
|
|
|
/*************************************************************
|
|
GetItemRect - Gets a rectangle for a dialog item
|
|
so I don't have to pass all those damn
|
|
parameters all the time.
|
|
|
|
theDialog - The place
|
|
theItem - The DITL number
|
|
theRect - Thar she blows
|
|
|
|
**************************************************************/
|
|
|
|
pascal void GetItemRect(DialogPtr theDialog, short theItem, Rect *theRect)
|
|
{
|
|
short itemKind;
|
|
Handle itemHandle;
|
|
|
|
GetDItem(theDialog, theItem, &itemKind, &itemHandle, theRect);
|
|
}
|
|
|
|
|
|
/*************************************************************
|
|
SetUserItemProc - Sets the DITL user Item Proc
|
|
|
|
theDialog - The place
|
|
theItem - The DITL number
|
|
theProc - What to set it to
|
|
|
|
**************************************************************/
|
|
|
|
pascal void SetUserItemProc(DialogPtr theDialog, short theItem, ProcPtr theProc)
|
|
{
|
|
short itemKind;
|
|
Handle itemHandle;
|
|
Rect itemRect;
|
|
|
|
GetDItem(theDialog, theItem, &itemKind, &itemHandle, &itemRect);
|
|
SetDItem(theDialog, theItem, itemKind, (Handle) theProc, &itemRect);
|
|
}
|
|
|
|
/*************************************************************
|
|
PCopyString - Copies the Pascal string using
|
|
BlockMove src -> dest
|
|
|
|
srcStr - The source & scourge
|
|
destStr - Unsuspecting bystander
|
|
|
|
**************************************************************/
|
|
|
|
pascal void PCopyString(Str255 srcStr, Str255 destStr)
|
|
{
|
|
BlockMove((Ptr) srcStr,(Ptr) destStr,Length(srcStr) + 1);
|
|
}
|
|
|
|
/*************************************************************
|
|
CmdPeriod - Determines if the cmd-. was hit in an
|
|
international friendly way
|
|
|
|
theEvent - what to look at; not a VAR param
|
|
|
|
**************************************************************/
|
|
|
|
pascal Boolean CmdPeriod(EventRecord *theEvent)
|
|
{
|
|
Boolean fTimeToQuit;
|
|
short keyCode;
|
|
long virtualKey, keyInfo, lowChar,
|
|
highChar, state, keyCId;
|
|
Handle hKCHR;
|
|
|
|
fTimeToQuit = false;
|
|
|
|
if ((theEvent->what == keyDown) || (theEvent->what == autoKey)) {
|
|
|
|
/* If CmdKey is down, get the ascii equiv of the keydown */
|
|
if (theEvent->modifiers & cmdKey) {
|
|
virtualKey = (theEvent->message & kMaskVirtualKey) >> kShiftWord;
|
|
|
|
/* get rid of the cmd key and add the virtual */
|
|
keyCode = (theEvent->modifiers & kMaskModifiers) | virtualKey;
|
|
state = 0;
|
|
|
|
keyCId = GetScript(GetEnvirons(smKeyScript), smScriptKeys);
|
|
hKCHR = GetResource('KCHR', keyCId);
|
|
|
|
if (hKCHR != nil) {
|
|
keyInfo = KeyTrans(*hKCHR, keyCode, &state);
|
|
ReleaseResource(hKCHR);
|
|
}
|
|
else
|
|
keyInfo = theEvent->message;
|
|
|
|
lowChar = keyInfo & kMaskASCII2;
|
|
highChar = (keyInfo & kMaskASCII1) >> 16;
|
|
|
|
if ((lowChar == kPeriod) || (highChar == kPeriod))
|
|
fTimeToQuit = true;
|
|
} // cmdKey down
|
|
|
|
} // keyEvent
|
|
|
|
return(fTimeToQuit);
|
|
}
|
|
|
|
/****************************************************************************
|
|
* PlaceWindow - Determines where to put the topLeft corner
|
|
* of a window given a relative window
|
|
*
|
|
* Inputs:
|
|
* theParent - place the child relative to it
|
|
* childHeight - the size of the child window. We use a rect 'cuz the
|
|
* childWidth - dialog may be opened/closed by a ROM routine (SFGetFile)
|
|
******************************************************************************/
|
|
pascal Point PlaceWindow(WindowPtr theParent,short childHeight,short childWidth)
|
|
{
|
|
GDHandle theScreen,
|
|
maxScreen; // How many faces
|
|
RgnHandle screenRgn;
|
|
long areaTaken,
|
|
maxAreaTaken = 0; // The amt the parent occupies per screen
|
|
Point offset; // Relative to the GDevice
|
|
Rect screenRect;
|
|
Boolean addMenu = false;
|
|
Point returnVal;
|
|
|
|
if (! HaveCQD()) { // old fashioned way
|
|
screenRect = (**(GetGrayRgn())).rgnBBox;
|
|
goto setLoc;
|
|
}
|
|
|
|
if (theParent == nil) { // Put it on the main screen
|
|
screenRect = (**(GetMainDevice())).gdRect;
|
|
addMenu = true;
|
|
goto setLoc;
|
|
}
|
|
// Put it on that screen
|
|
screenRgn = NewRgn();
|
|
|
|
/* We will walk the screen list to decide which one */
|
|
/* the parent window is most on. */
|
|
|
|
theScreen = GetDeviceList(); // Scan thru the GDevices
|
|
maxScreen = theScreen;
|
|
maxAreaTaken = 0;
|
|
|
|
while (theScreen != nil) {
|
|
RectRgn(screenRgn,&(**theScreen).gdRect);
|
|
SectRgn(screenRgn,((WindowPeek) theParent)->contRgn,screenRgn);
|
|
|
|
screenRect = (**screenRgn).rgnBBox;
|
|
areaTaken = (screenRect.right - screenRect.left) *
|
|
(screenRect.bottom - screenRect.top);
|
|
|
|
if (areaTaken > maxAreaTaken) { // This be the big one
|
|
maxScreen = theScreen;
|
|
maxAreaTaken = areaTaken;
|
|
}
|
|
|
|
theScreen = GetNextDevice(theScreen); // NeXT, please
|
|
} // in the list
|
|
|
|
DisposeRgn(screenRgn);
|
|
|
|
screenRect = (**maxScreen).gdRect;
|
|
addMenu = (maxScreen == GetMainDevice());
|
|
|
|
setLoc:
|
|
offset.h = ((screenRect.right - screenRect.left) - childWidth) >> 1;
|
|
offset.v = ((screenRect.bottom - screenRect.top) - childHeight) / 3;
|
|
SetPt(&returnVal, screenRect.left + offset.h, screenRect.top + offset.v);
|
|
if (addMenu)
|
|
returnVal.v += (GetMBarHeight() << 1) / 3;
|
|
|
|
return(returnVal);
|
|
} |