mirror of
https://github.com/elliotnunn/mac-rom.git
synced 2024-12-28 01:29:20 +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.
333 lines
7.6 KiB
C
333 lines
7.6 KiB
C
/*
|
|
File: Utilities.c
|
|
|
|
Contains: Utility routines that could be recoded in assembler for performance
|
|
|
|
Written by: Phil Goldman
|
|
|
|
Copyright: © 1986-1992 by Apple Computer, Inc., all rights reserved.
|
|
|
|
Change History (most recent first):
|
|
|
|
<5> 3/23/92 JSM OSEvents.h is obsolete, use Events.h instead.
|
|
<4> 1/10/91 DFH Updated copyright years.
|
|
<3> 11/1/90 DFH Correct prototyping for DebuggerMsg().
|
|
<2> 10/31/90 DFH Got rid of warnings.
|
|
<1> 10/22/90 DFH First checked in.
|
|
<0> 12/15/86 PYG New Today.
|
|
|
|
*/
|
|
|
|
#include <types.h>
|
|
#include <quickdraw.h>
|
|
#include <memory.h>
|
|
#include <resources.h>
|
|
#include <toolutils.h>
|
|
#include <events.h>
|
|
|
|
#include "Glue.h"
|
|
#include "Lomem.h"
|
|
#include "Data.h"
|
|
|
|
#pragma segment kernel_segment
|
|
|
|
Handle GetRsrcHdlMatchingFirstLongword(long, long);
|
|
|
|
#ifdef MSWORKS_FIX
|
|
/* Set up app patch addr.
|
|
* NOTE: Assumes a5 == PROCESSMGRGLOBALS.
|
|
*/
|
|
ProcPtr
|
|
SetOverlayRecoverHandle(ProcPtr apptrap)
|
|
{
|
|
void OverlayRecoverHandle(void);
|
|
|
|
(*pCurrentProcess->p_pcb)->appRecoverHandlePatch = apptrap;
|
|
return ((ProcPtr) OverlayRecoverHandle);
|
|
}
|
|
|
|
ProcPtr
|
|
GetOverlayRecoverHandleOldTrap(void)
|
|
{
|
|
unsigned long olda5;
|
|
ProcPtr appRecoverHandlePatch;
|
|
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
appRecoverHandlePatch = (*pCurrentProcess->p_pcb)->appRecoverHandlePatch;
|
|
A5SimpleRestore(olda5);
|
|
|
|
return appRecoverHandlePatch;
|
|
}
|
|
#endif MSWORKS_FIX
|
|
|
|
/* MemClear. Two-bit routine to clear 'bytes' bytes starting at *'ptr' */
|
|
void
|
|
MemClear(register Ptr ptr, register unsigned long bytes)
|
|
{
|
|
do
|
|
{
|
|
*ptr++ = (char) 0x00;
|
|
}
|
|
while (--bytes != 0);
|
|
|
|
}
|
|
|
|
/* StripLeadingNulls. Can you guess what it does?
|
|
* NOTE: It sets the last leading NULL to the length of the rest of the string,
|
|
* thereby altering the original string. Be careful! But you CAN restore
|
|
* the string by storing a NULL byte through the function result.
|
|
*/
|
|
StringPtr
|
|
StripLeadingNulls(StringPtr pString)
|
|
{
|
|
register Ptr pChar;
|
|
register unsigned char strSize;
|
|
|
|
strSize = Length(pString);
|
|
pChar = &StringByte(pString, 0);
|
|
while ((strSize != 0) && (*pChar == NULL))
|
|
{
|
|
--strSize;
|
|
pChar++;
|
|
}
|
|
|
|
if (strSize != Length(pString))
|
|
{
|
|
pString = (StringPtr) (--pChar);
|
|
Length(pString) = strSize;
|
|
}
|
|
|
|
return(pString);
|
|
}
|
|
|
|
/* NewMungedString. Copy pProtoStr into a NewString, and replace the 0th
|
|
* parameter substring with pSubStr.
|
|
*/
|
|
Handle
|
|
NewMungedString(StringPtr pSubStr, StringPtr pProtoStr)
|
|
{
|
|
unsigned long ParamZeroStr = TWO_CHAR_STRING('^','0');
|
|
StringPtr ptr1, ptr2;
|
|
unsigned long len1,len2;
|
|
StringHandle retVal;
|
|
|
|
if ((retVal = NewString(pProtoStr)) != nil)
|
|
{
|
|
ptr1 = (StringPtr) &ParamZeroStr;
|
|
len1 = (unsigned long) Length(ptr1);
|
|
ptr1 = &StringByte(ptr1, 0);
|
|
len2 = (long) Length(pSubStr);
|
|
ptr2 = &StringByte(pSubStr, 0);
|
|
(void)Munger(retVal,0,ptr1,len1,ptr2,len2);
|
|
if (MEMERROR == noErr)
|
|
Length((*retVal)) += len2 - len1;
|
|
else
|
|
{
|
|
DisposHandle(retVal);
|
|
retVal = nil;
|
|
}
|
|
}
|
|
return (retVal);
|
|
}
|
|
|
|
/* StrInStrList. Use specified function to check whether the specified string is
|
|
* "in" the specified list of strings.
|
|
*/
|
|
StringPtr
|
|
StrInStrList(Ptr strPtr, Ptr strListPtr, short cStrings, RelStringGluePtr relStringGluePtr)
|
|
{
|
|
while (--cStrings >= 0)
|
|
{
|
|
if ((*relStringGluePtr)(strListPtr, strPtr) == 0)
|
|
return(strListPtr);
|
|
strListPtr += Length(strListPtr) + 1;
|
|
}
|
|
|
|
return(nil);
|
|
}
|
|
|
|
/* GetRsrcHdlMatchingFirstLongword. Find the first resource of specified type that
|
|
* has the given value in its first long word. Scope is the entire resource chain.
|
|
*/
|
|
Handle
|
|
GetRsrcHdlMatchingFirstLongword(long resType, long firstLong)
|
|
{
|
|
Handle hdl;
|
|
short resIndex, resLast;
|
|
|
|
resLast = CountResources(resType);
|
|
for (resIndex = 1; resIndex <= resLast; resIndex++)
|
|
{
|
|
hdl = GetIndResource(resType, resIndex);
|
|
if (hdl != nil)
|
|
{
|
|
if (**((long **) hdl) == firstLong)
|
|
return (hdl);
|
|
ReleaseResource(hdl);
|
|
}
|
|
}
|
|
|
|
return (nil);
|
|
}
|
|
|
|
/* GetIconIDFromBundle. Figure out the icon family resource ID for the given type and
|
|
* creator. Starts at the current resource map. Uses the same search path that Finder
|
|
* does (FREF -> BNDL -> icon resource).
|
|
*/
|
|
short
|
|
GetIconIDFromBundle(OSType theType, unsigned long theCreator)
|
|
{
|
|
Ptr pRsrc;
|
|
short typeIndex, icnIndex;
|
|
Handle rsrcHdl;
|
|
short localID, globalID;
|
|
|
|
/* Find the FREF of the type */
|
|
rsrcHdl = GetRsrcHdlMatchingFirstLongword('FREF', theType);
|
|
if (rsrcHdl == nil)
|
|
return(0);
|
|
|
|
pRsrc = *rsrcHdl + 4;
|
|
localID = *((short *) pRsrc);
|
|
ReleaseResource(rsrcHdl);
|
|
|
|
/* Get the BNDL */
|
|
rsrcHdl = GetRsrcHdlMatchingFirstLongword('BNDL', theCreator);
|
|
if (rsrcHdl == nil)
|
|
return(0);
|
|
|
|
pRsrc = *rsrcHdl + 6;
|
|
|
|
/* Major loop -- find global id of icon in bundle */
|
|
globalID = 0;
|
|
for (typeIndex = *((short *) pRsrc)++; typeIndex >= 0; typeIndex--)
|
|
{
|
|
/* Is this type ICN# ? */
|
|
if (*((long *) pRsrc)++ == 'ICN#')
|
|
{
|
|
/* Minor loop - find a match for our given local ID and get it */
|
|
for (icnIndex = *((short *) pRsrc)++; icnIndex >= 0; icnIndex--)
|
|
{
|
|
if (*((short *) pRsrc)++ == localID)
|
|
{
|
|
/* Found it! */
|
|
globalID = *((short *) pRsrc);
|
|
break;
|
|
}
|
|
|
|
pRsrc += 2;
|
|
}
|
|
|
|
/* Either we found it or we looked at all icons */
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
/* Skip over all of this type's resources, carefully because count
|
|
* is zero-based.
|
|
*/
|
|
((long *) pRsrc) += *((short *) pRsrc)++;
|
|
((long *) pRsrc)++;
|
|
}
|
|
}
|
|
|
|
/* Clean up and go */
|
|
ReleaseResource(rsrcHdl);
|
|
return(globalID);
|
|
}
|
|
|
|
/* OptionKeyIsDown. Figure out if the option-key is depressed. */
|
|
Boolean
|
|
OptionKeyIsDown(void)
|
|
{
|
|
EventRecord evtRecord;
|
|
|
|
(void) GetOSEvent(0, &evtRecord);
|
|
return((evtRecord.modifiers & optionKey) != 0);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
/* DebuggerMsg. Append message to file name and line number to and pass to debugger */
|
|
void
|
|
DebuggerMsg(char *cFileString, int debugLine, char *cMsgString)
|
|
{
|
|
register char *pch, *pch2;
|
|
Str255 totalMsgString;
|
|
static char assertFailureString[] = "Assertion Failure";
|
|
int len;
|
|
unsigned long olda5;
|
|
|
|
if (*((short *)0xF0) == 0x4E4F) /* 'NO' debugging */
|
|
return;
|
|
|
|
if (PROCESSMGRGLOBALS != (Ptr)(-1))
|
|
olda5 = ProcessMgrA5SimpleSetup();
|
|
|
|
/* Normalize C file string */
|
|
if (PROCESSMGRGLOBALS != (Ptr)(-1))
|
|
cFileString += ((long)PROCESSMGRGLOBALS - (long)olda5); /* Normalize this puppy (HAAAAAAACCK) */
|
|
|
|
/* Find length of file name (C string) */
|
|
len = 0;
|
|
pch = cFileString;
|
|
while (*pch++)
|
|
len++;
|
|
|
|
/* Stick it in buffer (P string) */
|
|
pch = &totalMsgString;
|
|
*pch++ = (char) (len + 5);
|
|
BlockMove(cFileString, pch, len);
|
|
pch += len;
|
|
*pch++ = '+';
|
|
|
|
/* Stick in the line number */
|
|
|
|
if (*pch = debugLine/1000)
|
|
{
|
|
debugLine -= (*pch)*1000;
|
|
*pch++ += '0';
|
|
Length(&totalMsgString)++;
|
|
}
|
|
|
|
if (*pch = debugLine/100)
|
|
{
|
|
debugLine -= (*pch)*100;
|
|
*pch++ += '0';
|
|
Length(&totalMsgString)++;
|
|
}
|
|
*pch = debugLine/10;
|
|
debugLine -= (*pch)*10;
|
|
*pch++ += '0';
|
|
*pch++ = debugLine + '0';
|
|
*pch++ = ':';
|
|
*pch++ = ' ';
|
|
|
|
/* Move in the old message */
|
|
if (cMsgString != NO_MESSAGE_ID)
|
|
{
|
|
if (cMsgString == ASSERTION_FAILURE_ID)
|
|
cMsgString = assertFailureString;
|
|
else
|
|
if (PROCESSMGRGLOBALS != (Ptr)(-1))
|
|
cMsgString += ((long)PROCESSMGRGLOBALS - (long)olda5); /* Normalize this puppy (HAAAAAAACCK) */
|
|
|
|
/* Find length of msg (C string) */
|
|
len = 0;
|
|
pch2 = cMsgString;
|
|
while (*pch2++)
|
|
len++;
|
|
|
|
/* Move it on in */
|
|
BlockMove(cMsgString, pch, len);
|
|
Length(&totalMsgString) += len;
|
|
}
|
|
|
|
/* Restore A5 */
|
|
if (PROCESSMGRGLOBALS != (Ptr)(-1))
|
|
A5SimpleRestore(olda5);
|
|
|
|
/* Call the trap (keep at end of routine so we can jump right back in flow of things) */
|
|
debugger(&totalMsgString);
|
|
}
|
|
#endif DEBUG
|