Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
Utilities.c
/*------------------------------------------------------------------------------ |
* |
* Apple Developer Technical Support |
* |
* |
* |
* Program: AEObject-Edition Sample |
* File: Utilities.c -C Source |
* |
* by: C.K. Haun <TR> |
* |
* Copyright © 1990-1992 Apple Computer, Inc. |
* All rights reserved. |
* |
*------------------------------------------------------------------------------ |
* This file contains some of our window handling routines. I created it |
* primarily to take some of the clutter out of the main.c file. |
* It also contains the clipboard handlers |
*----------------------------------------------------------------------------*/ |
#define __GUTILS__ |
#include "Sampdefines.h" |
#pragma segment Utils |
/* standardDialogFilter is _new_ and dispatches to the System 7 */ |
/* standard dialog filter. Please see tech note #304 */ |
/* for details on how this works, and why I am checking */ |
/* for update events in this thing */ |
/* Look right below for one for Alerts */ |
pascal Boolean standardDialogFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit) |
{ |
if (theEvent->what == updateEvt && theEvent->message != theDialog ){ |
WindowPtr theWindow = (WindowPtr)theEvent->message; |
/* draw my window if it's really mine */ |
if(IsMyWindow(theWindow)){ |
DrawIt((WindowPtr)theWindow); |
*itemHit = 0; |
return(false); /* tell the dialog manager I handled this event */ |
} |
} else { |
ModalFilterUPP stdProc; |
GetStdFilterProc(&stdProc); |
return CallModalFilterProc(stdProc, theDialog, theEvent, itemHit); |
} |
} /* end standardDialogFilter */ |
pascal Boolean standardAlertFilter(DialogPtr theDialog, EventRecord *theEvent, short *itemHit) |
{ |
Boolean returnVal = false; |
if(theEvent->what == updateEvt && theEvent->message != theDialog ){ |
WindowPtr theWindow = (WindowPtr)theEvent->message; |
/* draw my window if it's really mine */ |
if(IsMyWindow(theWindow)){ |
DrawIt((WindowPtr)theWindow); |
*itemHit = 0; |
returnVal = false; |
} |
} else { |
/* for alerts we have to check for keys ourselves, since we didn't have a chance to */ |
/* call SetDialogCancel or anything */ |
if ((theEvent->what == keyDown) || (theEvent->what == autoKey)) { |
short tempItem; Handle tempHandle; |
Rect tempRect; |
char theKey = theEvent->message & charCodeMask; |
switch (theKey) { |
long tilticks; |
case kReturnKey: |
case kEnterKey: /* enter key */ |
/* This filters for Return or Enter as item 1, and Esc as item 2 */ |
*itemHit = 1; /* change whatever the current item is to the OK item */ |
/* now we need to invert the button */ |
GetDialogItem(theDialog, 1, &tempItem, &tempHandle, &tempRect); |
if(tempItem == ctrlItem){ |
/* double check for the unlikely event that this is _not_ a button */ |
HiliteControl(SnatchHandle(theDialog, ok), inButton); |
Delay(8, &tilticks); /* wait about 8 ticks so they can see it */ |
HiliteControl(SnatchHandle(theDialog, ok), false); |
returnVal = true; |
} |
break; |
/* This filters the escape key as the same as item 2 (the canx button, usually ) */ |
case kEscKey: |
*itemHit = 2; |
if(tempItem == ctrlItem){ |
/* much more likely that this may not be a button */ |
HiliteControl(SnatchHandle(theDialog, cancel), inButton); |
Delay(8, &tilticks); /* wait about 8 ticks so they can see it */ |
HiliteControl(SnatchHandle(theDialog, cancel), false); |
returnVal = true; |
} |
break; |
} |
} |
} |
return(returnVal); |
} /* end standardDialogFilter */ |
/* Gets the ControlHandle for the item you want in the dialog box thebox. */ |
/* Handy for setting checkboxes and radio buttons */ |
ControlHandle SnatchHandle(DialogPtr thebox, short theGetItem) |
{ |
short itemtype; |
Rect itemrect; |
Handle thandle; |
GetDialogItem(thebox, theGetItem, &itemtype, &thandle, &itemrect); |
return((ControlHandle)thandle); |
} /* end SnatchHandle */ |
/* MakeRect converts two points into a rect. */ |
/* it also insures that the rect is not reversed */ |
void MakeRect(Point *aPoint, Point *bPoint, Rect *putRect) |
{ |
short temp; |
putRect->top = aPoint->v; |
putRect->left = aPoint->h; |
putRect->bottom = bPoint->v; |
putRect->right = bPoint->h; |
if (putRect->top > putRect->bottom) { |
temp = putRect->bottom; |
putRect->bottom = putRect->top; |
putRect->top = temp; |
} |
if (putRect->left > putRect->right) { |
temp = putRect->right; |
putRect->right = putRect->left; |
putRect->left = temp; |
} |
if (putRect->right == putRect->left) |
putRect->left++; |
if (putRect->bottom == putRect->top) |
putRect->bottom++; |
} /* end MakeRect */ |
/* ties two P strings together. Haven't we all written this at one time or another???? */ |
void AppendString(Str255 target, Str255 appendIt) |
{ |
BlockMove((Ptr)(appendIt + 1), (Ptr)(target + (target[0])+1), appendIt[0]); |
target[0] += appendIt[0]; |
} /* end AppendString */ |
/* PureCursor checks to see if the last keystroke was a 'pure' cursor */ |
/* moving keystroke. This is important for setting Undo for text typing, */ |
/* if I had put that in */ |
Boolean PureCursor(char theKey) |
{ |
register qq; |
char curChars[4] = { |
kLeftArrow, kRightArrow, kUpArrow, kDownArrow |
}; |
Boolean result = false; |
for (qq = 0; qq < 4; qq++) { |
if (theKey == curChars[qq]) |
result = true; |
} |
return(result); |
} /* end PureCursor */ |
/* This tries as hard as it can to resize a handle, avoiding the problem SetHandleSize */ |
/* has when a block is surrounded by locked stuff. */ |
/* Of course if you use this, you can only have one copy of the handle around and you */ |
/* always must reference that handle, since the master pointer contained within it */ |
/* can change during the ReallocateHandle call. But you should be doing that anyway (nag nag nag) */ |
OSErr MySetHandleSize(Handle theHandle, Size theSize) |
{ |
OSErr memErr; |
Handle tempHand = theHandle; |
SetHandleSize(theHandle, theSize); |
memErr = MemError(); |
if (!memErr) |
return(noErr); |
/* could not resize the handle. Why? */ |
if (memErr != memFullErr) |
return(memErr); /* not something we can deal with */ |
/* either the memory is really not available, or there is a locked pointer |
* above the handle we're resizing. We'll try seeing if the memory |
* is actually there first. */ |
ShowMe("\p mem err", memErr, __LINE__); |
if (!(CompactMem(theSize) >= theSize)) |
return(MemError()); /* memory really is full, bail */ |
/* OK, memory is available somewhere. Find it */ |
HandToHand(&tempHand); /* copy the handle */ |
ReallocateHandle(theHandle, theSize); /* resize by reallocation */ |
HLock(tempHand); |
HLock(theHandle); |
BlockMove(*tempHand, *theHandle, GetHandleSize(theHandle)); /* only move the size of the target */ |
HUnlock(theHandle); |
DisposeHandle(tempHand); |
} /* end MySetHandleSize */ |
/* ShowMe is just a handy place to display a string and a number. */ |
/* ¥¥¥ NOTE: That I'm calling AEInteractWithUser here, instead */ |
/* of just blasting up an alert */ |
void ShowMe(Str255 in, OSErr aevtErr, short lineNo) |
{ |
NMRec myNotification; |
Str255 nmWords; |
Str32 theGuy; |
Str32 theLine; |
OSErr myErr; |
myNotification.qType =nmType ; |
myNotification.nmMark = nil; |
myNotification.nmIcon = nil; |
myNotification.nmSound = (Handle)-1; |
myNotification.nmStr =&nmWords ; |
myNotification.nmResp =nil ; |
GetIndString(&nmWords,kGeneralStrings,kErrorToSay); |
myErr = AEInteractWithUser(kAEDefaultTimeout, &myNotification, gCommonIdleFunctionUPP); |
if(myErr != errAENoUserInteraction ) { |
ModalFilterUPP upp = NewModalFilterProc(standardAlertFilter); |
InitCursor(); |
NumToString((long)aevtErr, theGuy); |
NumToString((long)lineNo, theLine); |
ParamText(in, theGuy, theLine, ""); |
Alert(129, upp); |
DisposeRoutineDescriptor(upp); |
} |
} /* end ShowMe */ |
/* DoDiskEvents just checks the error code from the disk mount, */ |
/* and puts up the 'Format' dialog (through DIBadMount) if need be */ |
/* You can do much more here if you care about what disks are */ |
/* in the drive */ |
void DoDiskEvents(long dinfo) /* hi word is error code, lo word is drive number */ |
{ |
short hival, loval, tommy; |
Point fredpoint = { |
40, 40 |
}; |
hival = HiWord(dinfo); |
loval = LoWord(dinfo); |
if (hival != noErr) /* something happened */ { |
tommy = DIBadMount(fredpoint, dinfo); |
} |
} /* end DoDiskEvents */ |
/* CommonDStart is here just because I'm tired of typing GetNewDialog and */ |
/* typing the d*mned (WindowPtr)-1 all the time. */ |
/* It also sets up our default and cancel items, as expalined in TN #304 */ |
DialogPtr CommonDStart(short DNumber, short set1, short set2) |
{ |
DialogPtr tdial = GetNewDialog(DNumber, nil, (WindowPtr)-1); |
if (set1) |
SetControlValue(SnatchHandle(tdial, set1), true); |
if (set2) |
SetControlValue(SnatchHandle(tdial, set2), true); |
SetDialogDefaultItem(tdial, ok); |
SetDialogCancelItem(tdial, cancel); |
return(tdial); |
} /* end CommonDStart */ |
/* PullRect either drags a rect around the screen (for subscribers) or pulls a rect */ |
/* rubber-band wise for anything else. I'm not using DragGryRgn because I have to check some */ |
/* intersections along the way */ |
/* And since an Oval has the same calling conventions as a Rect, it calls this too */ |
void PullRect(windowCHandle theWind, Rect *startRect, Boolean isOval, Boolean useRect, Boolean onlyCorner) |
{ |
WindowPtr theWindow = FrontWindow(); |
Rect oldRect; |
Point endPoint, thePoint; |
Boolean hreversed = false; |
Boolean vreversed = false; |
/* set up */ |
if (useRect) { |
oldRect = *startRect; |
} else { |
oldRect.top = startRect->top = oldRect.bottom = startRect->bottom = gERecord.where.v; |
oldRect.right = startRect->right = oldRect.left = startRect->left = gERecord.where.h; |
} |
PenMode(srcXor); /* So we can rubberband */ |
/* see if we're dragging the whole rect, or just pulling a corner out */ |
if (onlyCorner) { |
while (StillDown()) { /* Keep doing this as long as the */ |
/* user keeps the mouse down */ |
GetMouse(&endPoint); /* Current mouse position in local */ |
if (hreversed) { |
/* see if it flipped first */ |
if (endPoint.h > startRect->right) { |
/* they flipped back */ |
hreversed = false; /* and ignore this move */ |
} else { |
/* still reversed */ |
startRect->left = endPoint.h; |
} |
} else { |
if (endPoint.h < startRect->left) { |
hreversed = true; |
} else { |
startRect->right = endPoint.h; |
} |
} |
if (vreversed) { |
/* see if it flipped first */ |
if (endPoint.v > startRect->bottom) { |
/* they flipped back */ |
vreversed = false; /* and ignore this move */ |
} else { |
/* still reversed */ |
startRect->top = endPoint.v; |
} |
} else { |
if (endPoint.v < startRect->top) { |
vreversed = true; |
} else { |
startRect->bottom = endPoint.v; |
} |
} |
/* make sure we're not intersecting a text box */ |
if (!InTextBox(theWind, startRect)) { |
if (*startRect != oldRect) { /* redraw the rect only if the mouse moved */ |
if (isOval) { |
FrameOval(&oldRect); |
FrameOval(startRect); |
} else { |
FrameRect(&oldRect); |
FrameRect(startRect); /* draw the new rect */ |
} |
oldRect = *startRect; |
} |
} else { |
*startRect = oldRect; |
} |
} |
} else { |
/* We're dragging the whole rectangle here */ |
GetMouse(&thePoint); |
while (StillDown()) { /* keep doing it until they release the mouse */ |
PenMode(patXor); |
if (!EqualRect(startRect, &oldRect)) { |
FrameRect(startRect); /* nasty way to put up a flashing border for the drag */ |
FrameRect(startRect); |
} |
GetMouse(&endPoint); |
/* keep inside the window please, don't let them drag the */ |
/* rectangle outside the window bounds */ |
if ((PtInRect(endPoint, &(FrontWindow()->portRect)))) { |
if (endPoint != thePoint) { |
oldRect = *startRect; |
OffsetRect(startRect, endPoint.h - thePoint.h, endPoint.v - thePoint.v); |
if (!InTextBox(theWind, startRect)) { |
thePoint = endPoint; |
} else { |
*startRect = oldRect; |
FrameRect(startRect); /* nasty way to put up a flashing border for the drag */ |
FrameRect(startRect); |
} |
} |
} |
} |
PenMode(normal); |
} |
PenMode(srcCopy); |
} /* end PullRect */ |
/* DoAnts draws the marque box for the current selection. */ |
/* Please note: No one else in the known universe does marching ants */ |
/* like this but me. I happen to like this */ |
void DoAnts(Rect *theRect) |
{ |
static short nowPat = 0; |
static long timeToMarch = 0; |
WindowPtr theWind = FrontWindow(); |
Pattern thePat; |
if(TickCount() > timeToMarch || timeToMarch == 0){ |
if (theWind) { |
windowCHandle tempWC = (windowCHandle)GetWRefCon(theWind); |
if ((*tempWC)->hasSelection || theRect) { |
GetIndPattern(&thePat, 128, nowPat); |
nowPat++; |
if (nowPat == 8) |
nowPat = 0; |
PenMode(patXor); |
PenPat(&thePat); |
if (theRect) |
FrameRect(theRect); |
else |
FrameRect(&(*tempWC)->selectionRect); |
PenMode(normal); |
PenPat(&qd.black); |
} |
} |
timeToMarch = TickCount() + kMarchTime; |
} |
} /* end DoAnts */ |
/* AdjustCursor change the cursor's shape, depending on its position. This also calculates |
the region where the current cursor resides (for WaitNextEvent). If the |
mouse is ever outside of that region, an event would be generated, causing |
this routine to be called, allowing us to change the region to the region |
the mouse is currently in. |
*/ |
void AdjustCursor(Point mouse, RgnHandle region) |
{ |
WindowPtr window; |
RgnHandle specialRgn; |
RgnHandle tbRgn; |
Rect textRect; |
Rect globalPortRect; |
windowCHandle shortName; |
window = FrontWindow(); /* we only adjust the cursor when we are in front */ |
if (!window){ |
SetEmptyRgn(region); |
return; /* ignore also if we have no open doc windows */ |
} |
if (((WindowPeek)window)->windowKind == kClipboardWindow || ((WindowPeek)window)->windowKind == kAEStatusWindow) { |
InitCursor(); |
SetEmptyRgn(region); /* don't care if a doc window not frontmost */ |
return; |
} |
if ((!gInBackground) && (IsMyWindow(window))) { |
specialRgn = NewRgn(); |
shortName = (windowCHandle)GetWRefCon(window); |
/* calculate specialRgn */ |
globalPortRect = window->portRect; |
LocalToGlobal((Point *)&globalPortRect); |
LocalToGlobal((Point *)&globalPortRect.bottom); |
RectRgn(specialRgn, &globalPortRect); |
if((*shortName)->boxHandle){ |
textRect = (*shortName)->textBox; |
LocalToGlobal((Point *)&textRect); |
LocalToGlobal((Point *)&textRect.bottom); |
tbRgn = NewRgn(); |
OpenRgn(); |
FrameRect(&textRect); |
CloseRgn(tbRgn); |
DiffRgn(specialRgn,tbRgn,specialRgn); |
DisposeRgn(tbRgn); |
} |
/* change the cursor and the region parameter */ |
if (PtInRect(mouse, &globalPortRect)) { |
short temp; |
temp = actsToIDs[(*shortName)->currentAction]; |
SetMyCursor(temp); |
/* if textbox then poke hole for text box */ |
if((*shortName)->boxHandle){ |
textRect = (*shortName)->textBox; |
LocalToGlobal((Point *)&textRect); |
LocalToGlobal((Point *)&textRect.bottom); |
if(PtInRect(mouse, &textRect)){ |
InitCursor(); |
RectRgn(specialRgn, &textRect); |
} |
} |
CopyRgn(specialRgn, region); |
} else { /* outside */ |
InitCursor(); |
/* make a region that's everything _but_ our windows vis region */ |
/* Uhhh, I was asking for the gray region here, but that doesn't */ |
/* include the menu bar, so you really do need to go full open */ |
SetRectRgn(region, kExtremeNeg, kExtremeNeg, |
kExtremePos, kExtremePos); |
DiffRgn(region, specialRgn, region); |
} |
/* get rid of our local regions */ |
DisposeRgn(specialRgn); |
} |
} |
/* end AdjustCursor*/ |
Boolean CompareFSSpecs(FSSpecPtr spec1,FSSpecPtr spec2) |
{ |
Boolean returnVal = false; |
if((spec1->vRefNum == spec2->vRefNum) && (spec1->parID == spec2->parID) && (EqualString(&spec1->name,&spec2->name,false,false))) |
returnVal = true; |
return(returnVal); |
} |
void SpinCursor(void) |
{ |
static short cID = kBaseMadFred; |
SetCursor(*GetCursor(cID)); |
cID++; |
if(cID > 137)cID = kBaseMadFred; |
} |
Boolean IsMyWindow(WindowPtr theWind) |
{ |
return((((WindowPeek)theWind)->windowKind == kAEStatusWindow) || (((WindowPeek)theWind)->windowKind == kClipboardWindow) || (((WindowPeek)theWind)->windowKind == kDocumentWindow)); |
} |
Boolean IsModalFront(void) |
{ |
Boolean retVal = false; |
WindowPtr theWindow = FrontWindow(); |
#define peekit ((WindowPeek)theWindow)->windowKind |
if(peekit == plainDBox || peekit == altDBoxProc || peekit == movableDBoxProc) |
retVal = true; |
#undef peekit |
return(retVal); |
} |
#undef __GUTILS__ |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-01-14