eudora-mac/util.c

1 line
110 KiB
C
Executable File
Raw Permalink Blame History

/* Copyright (c) 2017, Computer History Museum
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted (subject to
the limitations in the disclaimer below) provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of Computer History Museum nor the names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE. */
#include "util.h"
#define FILE_NUM 41
/* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */
/**********************************************************************
* various useful functions
**********************************************************************/
typedef struct SoundEntryStruct SoundEntry, *SoundEntryPtr;
struct SoundEntryStruct
{
SoundEntryPtr next;
Str255 name;
};
#pragma segment Util
#ifdef KERBEROS
#include <krb.h>
#endif
char BitTable[] = {0x1,0x2,0x4,0x8,0x10,0x20,0x40,0x80};
pascal Boolean PasswordFilter(DialogPtr dgPtr,EventRecord *event,short *item);
void CopyPassword(UPtr password);
int ResetPassword(void);
UHandle PwChars=nil;
void NukeMenuItem(MenuHandle mh,short item);
void CompactTempZone(void);
short FindMenuByName(UPtr name);
UPtr GetRStringLo(PStr theString,int theIndex,PersHandle forPers);
void *TempNewHandleGlue(long size,OSErr *err);
void QueueSound(PStr name);
void PlaySystemSound(PStr name);
void AddSoundsToMenuFrom(MenuHandle mh, short vRef, long dirID);
OSErr FindSystemSound(OSType disk,OSType folder,PStr name,FSSpecPtr spec);
// Globals
Movie gSoundMovie;
SoundEntryPtr gSystemSoundList;
GWorldPtr gGWorld;
#if 0
/**********************************************************************
* NeedYield
**********************************************************************/
Boolean NeedYield(void)
{
short numThreads = GetNumBackgroundThreads();
long elapsedTicks = TickCount() - ThreadYieldTicks;
long vicomFactor = (InBG ? 1 : (!VicomIs ? 1 : (GetRLong(VICOM_FACTOR))));
long yieldInterval = (InBG ? GetRLong(BG_YIELD_INTERVAL) : GetRLong(FG_YIELD_INTERVAL)) / ((numThreads ? numThreads : 1) * vicomFactor);
// ASSERT(InBG ? (elapsedTicks < 120) : 1); // are we hogging time somewhere?
if (EventPending() || (elapsedTicks > yieldInterval))
return true;
return false;
}
#endif
/**********************************************************************
* write zeroes over an area of memory
**********************************************************************/
void WriteZero(void *pointer,long size)
{
UPtr u = (UPtr)pointer;
while (size--) *u++ = 0;
}
#ifdef DEBUG
/**********************************************************************
* SetBalloons - help the debugger a bit
**********************************************************************/
void SetBalloons(Boolean on)
{
HMSetBalloons(on);
}
#endif
/**********************************************************************
* initialize all the mac managers
**********************************************************************/
void MacInitialize(int masterCount, long ensureStack)
{
OSErr err;
while (masterCount--) MoreMasters();
FlushEvents (everyEvent - diskMask, 0 );
InitCursor ();
#ifdef THREADING_ON
if (ThreadsAvailable ())
MyInitThreads ();
#endif
if (err=AEObjectInit()) DieWithError(INSTALL_AE,err);
EventPending();
EventPending();
EventPending();
}
/**********************************************************************
* turn a font name into a font id; if the name is not found, use ApplFont
**********************************************************************/
GetFontID(UPtr theName)
{
short theID;
Str255 systemName;
GetFNum(theName,&theID);
if (!theID)
{
GetFontName(0,systemName);
return (StringSame(theName,systemName) ? 0: applFont);
}
else
return (theID);
}
/**********************************************************************
* Check or uncheck a font size in the font menu
**********************************************************************/
void CheckFontSize(int menu,int size,Boolean check)
{
Str255 aString;
Str255 itemString;
MenuHandle mHandle;
short item;
/*
* turn the font size into a string
*/
NumToString((long)size,aString);
/*
* get a copy of the menu handle
*/
mHandle = GetMHandle(menu);
/*
* look for the proper item
*/
for (item = 1; ;item++)
{
GetMenuItemText(mHandle,item,itemString);
if (itemString[1]=='-') break;
if (StringSame(aString,itemString))
{
CheckMenuItem(mHandle,item,check);
break;
}
}
}
/**********************************************************************
* check (or uncheck) a font name in a menu. If check, also outline sizes
**********************************************************************/
void CheckFont(int menu,int fontID,Boolean check)
{
Str255 aString;
Str255 itemString;
MenuHandle mHandle;
short item;
/*
* turn the font id into a font name
*/
GetFontName(fontID,aString);
/*
* get a copy of the menu handle
*/
mHandle = GetMHandle(menu);
/*
* look for the proper item
*/
for (item = 1; ;item++)
{
GetMenuItemText(mHandle,item,itemString);
if (itemString[1]=='-') break; /* skip the sizes */
}
for (item++; ;item++)
{
GetMenuItemText(mHandle,item,itemString);
if (StringSame(aString,itemString))
{
CheckMenuItem(mHandle,item,check);
if (check) OutlineFontSizes(menu,fontID);
break;
}
}
}
/**********************************************************************
* outline sizes of a font in a menu
**********************************************************************/
void OutlineFontSizes(int menu,int fontID)
{
Str255 aString;
MenuHandle mHandle;
short item;
long aSize;
/*
* get a copy of the menu handle
*/
mHandle = GetMHandle(menu);
/*
* outline'em
*/
for (item = 1; ;item++)
{
GetMenuItemText(mHandle,item,aString);
if (aString[1]=='-') break; /* end of sizes? */
/*
* turn text into size
*/
StringToNum(aString,&aSize);
/*
* does it exist?
*/
if (RealFont(fontID,(short)aSize))
SetItemStyle(mHandle,item,outline);
else
SetItemStyle(mHandle,item,nil);
}
}
/**********************************************************************
* figure out the appropriate leading for a font
**********************************************************************/
int GetLeading(int fontID,int fontSize)
{
FMInput fInInfo;
FMOutput *fOutInfo;
/*
* set up the font input struct
*/
fInInfo.family = fontID;
fInInfo.size = fontSize;
fInInfo.face = 0;
fInInfo.needBits = FALSE;
fInInfo.device = 0;
fInInfo.numer.h = fInInfo.numer.v = 1;
fInInfo.denom.h = fInInfo.denom.v = 1;
/*
* get the actual info
*/
fOutInfo = FMSwapFont(&fInInfo);
/*
* yokey-dokey
*/
return(((fOutInfo->leading + fOutInfo->ascent + fOutInfo->descent)*fOutInfo->numer.v)/fOutInfo->denom.v);
}
/**********************************************************************
* find width of largest char in font
**********************************************************************/
int GetWidth(int fontID,int fontSize)
{
#ifdef FONTMGR
FMInput fInInfo;
FMOutput *fOutInfo;
/*
* set up the font input struct
*/
fInInfo.family = fontID;
fInInfo.size = fontSize;
fInInfo.face = 0;
fInInfo.needBits = FALSE;
fInInfo.device = 0;
fInInfo.numer.h = fInInfo.numer.v = 1;
fInInfo.denom.h = fInInfo.denom.v = 1;
/*
* get the actual info
*/
fOutInfo = FMSwapFont(&fInInfo);
/*
* yokey-dokey
*/
return((fOutInfo->widMax * fOutInfo->numer.h)/fOutInfo->denom.h);
#else
GrafPtr oldPort;
GrafPtr aPort;
int width;
GetPort(&oldPort);
MyCreateNewPort(aPort);
TextFont(fontID);
TextSize(fontSize);
width = CharWidth('0');
DisposePort(aPort);
SetPort_(oldPort);
return(width);
#endif
}
/**********************************************************************
* find descent font
**********************************************************************/
int GetDescent(int fontID,int fontSize)
{
FMInput fInInfo;
FMOutput *fOutInfo;
/*
* set up the font input struct
*/
fInInfo.family = fontID;
fInInfo.size = fontSize;
fInInfo.face = 0;
fInInfo.needBits = FALSE;
fInInfo.device = 0;
fInInfo.numer.h = fInInfo.numer.v = 1;
fInInfo.denom.h = fInInfo.denom.v = 1;
/*
* get the actual info
*/
fOutInfo = FMSwapFont(&fInInfo);
/*
* yokey-dokey
*/
return((fOutInfo->descent * fOutInfo->numer.v)/fOutInfo->denom.v);
}
/**********************************************************************
* find ascent font
**********************************************************************/
int GetAscent(int fontID,int fontSize)
{
FMInput fInInfo;
FMOutput *fOutInfo;
/*
* set up the font input struct
*/
fInInfo.family = fontID;
fInInfo.size = fontSize;
fInInfo.face = 0;
fInInfo.needBits = FALSE;
fInInfo.device = 0;
fInInfo.numer.h = fInInfo.numer.v = 1;
fInInfo.denom.h = fInInfo.denom.v = 1;
/*
* get the actual info
*/
fOutInfo = FMSwapFont(&fInInfo);
/*
* yokey-dokey
*/
return((fOutInfo->ascent * fOutInfo->numer.v)/fOutInfo->denom.v);
}
/**********************************************************************
* find fixed-width-ness of font
**********************************************************************/
Boolean IsFixed(int fontID,int fontSize)
{
return(CharWidthInFont('M',fontID,fontSize) == CharWidthInFont('i',fontID,fontSize));
}
/**********************************************************************
* wait for the user to strike a modifier key
**********************************************************************/
void AwaitKey(void)
{
KeyMap kMap;
register long * k;
register long * kEnd;
while (1)
{
GetKeys(&kMap);
for (k= &kMap,kEnd=k+sizeof(KeyMap)/sizeof(long); k<kEnd; k++)
if (*k) return;
}
}
/**********************************************************************
* change or add some data to the current resource file
**********************************************************************/
void ChangePResource(UPtr theData,int theLength,long theType,int theID,UPtr theName)
{
/*
* does the resource exist and reside in the topmost res file?
*/
Zap1Resource(theType,(short)theID);
AddPResource(theData, theLength, theType, theID, theName);
}
/**********************************************************************
* add some data to the current resource file
**********************************************************************/
void AddPResource(UPtr theData,int theLength,long theType,int theID,UPtr theName)
{
Handle aHandle;
/*
* allocate the handle
*/
aHandle = NuHandle((long)theLength);
if (aHandle == nil)
return;
/*
* copy the data
*/
BMD(theData,*aHandle,(long)theLength);
/*
* add it
*/
AddResource_(aHandle,theType,theID,theName);
}
/************************************************************************
* ZapResourceLo - get rid of a resource.
************************************************************************/
OSErr ZapResourceLo(OSType type, short id, Boolean one)
{
Handle resH;
OSErr err=resNotFound;
short refN;
SetResLoad(False);
resH=one ? Get1Resource(type,id) : GetResource_(type,id);
SetResLoad(True);
if (resH)
{
refN = HomeResFile(resH);
RemoveResource(resH);
ZapHandle(resH);
err = ResError();
if (!err && one) ZapResourceLo(type,id,one);
MyUpdateResFile(refN); /* this is very conservative, but it seems necessary
* to avoid duplicate resources on some PPC macs */
}
return(err);
}
/**********************************************************************
* Atoi - replacement for standard C routine
**********************************************************************/
long Atoi(UPtr s)
{
long mul = 1;
long n = 0;
while(IsWhite(*s)) s++;
if (*s=='-') {mul=-1;s++;}
if (*s=='+') s++;
while(isdigit(*s))
{
n = n*10+(*s-'0');
s++;
}
return(n*mul);
}
/**********************************************************************
* AToOSType - ASCII to OSType
**********************************************************************/
OSType AToOSType(UPtr s)
{
long n = 0;
short i;
for (i = 0; i < 4; ++i) {
n <<= 8;
n += *s++;
}
return(n);
}
/**********************************************************************
* ResourceCpy - copy a resource from one resource file to the other
**********************************************************************/
int ResourceCpy(short toRef, short fromRef,long type,int id)
{
int oldRef;
Handle resource;
Str255 name;
short attrs;
oldRef = CurResFile();
UseResFile(toRef);
SetResLoad(false);
resource = GetResource_(type,id); /* no sense loading it if it's wrong */
if (resource!=nil)
{
if (HomeResFile(resource)==toRef)
{
/*
* delete the old one first
*/
SetResLoad(True); RemoveResource(resource); SetResLoad(False);
ZapHandle(resource);
resource = nil;
}
else if (HomeResFile(resource)!=fromRef)
{
ReleaseResource_(resource); /* wrong one */
resource = nil;
}
}
if (resource==nil)
{
/*
* fetch from the proper file
*/
UseResFile(fromRef);
resource = Get1Resource(type,id);
}
SetResLoad(True); /* turn that goodie back on */
if (resource!=nil)
{
attrs = GetResAttrs(resource); /* save attributes */
GetResInfo((Handle)resource,(short*)&id,(ResType*)&type,name);/* get the name */
LoadResource(resource); /* load it in */
HNoPurge_(resource); /* keep it right here */
if (ResError()) goto rErr; /* did that work? */
DetachResource(resource); /* break cnxn with old file */
UseResFile(toRef); /* point at to resource file */
AddResource_(resource,type,id,name); /* stick into new file */
if (ResError()) goto rErr; /* did that work? */
SetResAttrs(resource,attrs); /* restore attributes */
ChangedResource(resource); /* except it's been changed */
HNoPurge(resource); /* don't let anyone purge it */
}
UseResFile(oldRef); /* restore old res file */
if (resource==nil) return(resNotFound);
return(noErr);
rErr:
UseResFile(oldRef);
return(ResError());
}
/**********************************************************************
* DrawTruncString - truncate and draw a string; restores string when done
**********************************************************************/
void DrawTruncString(UPtr string,int len)
{
int sLen = *string;
if (sLen > len)
{
Byte save = string[len];
string[len] = '<EFBFBD>';
*string = len;
DrawString(string);
*string = sLen;
string[len] = save;
}
else
DrawString(string);
}
/**********************************************************************
* CalcTrunc - figure out how much of a string we can print to fit
* in a given width
**********************************************************************/
int CalcTextTrunc(UPtr string,short length, short width,GrafPtr port)
{
short tLen;
int cWidth;
GrafPtr oldPort;
if (width<=0) return(0);
GetPort(&oldPort);
SetPort_(port);
/*
* make an initial estimate
*/
tLen = MIN(width/CharWidth(' '),length);
/*
* if the string fits, ...
*/
cWidth = TextWidth(string,0,tLen);
if (cWidth<width && tLen==length) {SetPort_(oldPort);return(length);}
/*
* if it's too short
*/
if (cWidth<=width)
{
if (tLen<length)
{
tLen++;
while (TextWidth(string,0,tLen)<width && tLen<length) tLen++;
tLen--;
}
}
/*
* too long...
* (we do pretend there is always room for 1 character)
*/
else
do
{
tLen--;
cWidth = TextWidth(string,0,tLen);
}
while (tLen && cWidth>width);
SetPort_(oldPort);
return (tLen ? tLen : 1);
}
/**********************************************************************
* WhiteRect - draw white rectangle with a black border
**********************************************************************/
void WhiteRect(Rect *r)
{
Rect myR = *r;
FrameRect(&myR);
InsetRect(&myR,1,1);
EraseRect(&myR);
}
/************************************************************************
* WannaSave - find out of the user wants to save the contents of a window
************************************************************************/
int WannaSave(MyWindowPtr win)
{
Str255 title;
short res;
MyGetWTitle(GetMyWindowWindowPtr(win),title);
res = ComposeStdAlert(kAlertCautionAlert,SAVE_CHANGES_ASTR+ALRTStringsOnlyStrn,title);
if (res==WANNA_SAVE_CANCEL) res = CANCEL_ITEM;
return(res);
}
/************************************************************************
* GetPassword - read a user's password
************************************************************************/
int GetPassword(PStr personality,PStr userName,PStr serverName,UPtr word, int size, short prompt)
{
Str255 string;
MyWindowPtr dgPtrWin;
DialogPtr dgPtr;
short item;
DECLARE_UPP(PasswordFilter,ModalFilter);
INIT_UPP(PasswordFilter,ModalFilter);
if (!MommyMommy(ATTENTION,nil)) return(PASSWORD_CANCEL);
GetRString(string,prompt);
MyParamText(personality,userName,serverName,string);
if ((dgPtrWin = GetNewMyDialog(PASSWORD_DLOG,nil,nil,InFront))==nil)
{
WarnUser(GENERAL,MemError());
ComposeLogR(LOG_ALRT,nil,ALERT_DISMISSED_ITEM,PASSWORD_CANCEL);
return(PASSWORD_CANCEL);
}
dgPtrWin->noEditMenu = true; // sorry, no copy/paste
dgPtr = GetMyWindowDialogPtr (dgPtrWin);
if (!(CurrentModifiers()&alphaLock)) HideDialogItem(dgPtr,PASSWORD_WARNING);
AutoSizeDialog(dgPtr);
StartMovableModal(dgPtr);
ShowWindow(GetDialogWindow(dgPtr));
HiliteButtonOne(dgPtr);
SetDItemState(dgPtr,PASSWORD_SAVE,PrefIsSet(PREF_SAVE_PASSWORD));
do
{
SetDIText(dgPtr,PASSWORD_WORD,"");
SelectDialogItemText(dgPtr,PASSWORD_WORD,0,REAL_BIG);
if (ResetPassword()) {item=PASSWORD_CANCEL; break;}
PushCursor(arrowCursor);
do
{
MovableModalDialog(dgPtr,PasswordFilterUPP,&item);
if (item==PASSWORD_SAVE) SetDItemState(dgPtr,item,!GetDItemState(dgPtr,item));
}
while (item==PASSWORD_SAVE);
PopCursor();
CopyPassword(string);
}
while (item==PASSWORD_OK && !*string);
if (item==PASSWORD_OK)
SetPref(PREF_SAVE_PASSWORD,GetDItemState(dgPtr,PASSWORD_SAVE) ? YesStr:NoStr);
ComposeLogR(LOG_ALRT,nil,ALERT_DISMISSED_ITEM,item);
EndMovableModal(dgPtr);
DisposDialog_(dgPtr);
InBG = False;
if (item==PASSWORD_OK)
{
if (*string > size-1) *string = size - 1;
PCopy(word,string);
}
return(item!=PASSWORD_OK);
}
/************************************************************************
* GetPassStuff - collect the stuff we need to get a password
************************************************************************/
void GetPassStuff(PStr persName,PStr uName,PStr hName)
{
GetPref(uName,PREF_STUPID_USER);
GetPref(hName,PREF_STUPID_HOST);
PCopy(persName,(*CurPersSafe)->name);
if (!*persName) GetRString(persName,DOMINANT);
}
/************************************************************************
* ResetPassword - get the password routines ready
************************************************************************/
int ResetPassword(void)
{
if (!PwChars)
PwChars = NuHandle(256L);
else if (!*PwChars)
ReallocateHandle(PwChars,256L);
if (!PwChars || !*PwChars) return(MemError());
HNoPurge_(PwChars);
**PwChars = 0;
return(0);
}
/************************************************************************
* InvalidatePasswords - wipe out our memory of passwords
************************************************************************/
void InvalidatePasswords(Boolean pwGood,Boolean auxpwGood,Boolean all)
{
PersHandle old;
if (all)
{
old = CurPers;
for (CurPers=PersList;CurPers;CurPers=(*CurPers)->next)
InvalidateCurrentPasswords(pwGood,auxpwGood);
CurPers = old;
}
else
InvalidateCurrentPasswords(pwGood,auxpwGood);
}
/**********************************************************************
* InvalidatePasswords - wipe out our memory of passwords for the current personality
**********************************************************************/
void InvalidateCurrentPasswords(Boolean pwGood,Boolean auxpwGood)
{
if (!pwGood)
{
Zero((*CurPers)->password);
(*CurPers)->popSecure = 0;
if (PrefIsSet(PREF_SAVE_PASSWORD) && CurPers==PersList)
SetPref(PREF_PASS_TEXT,"");
SetPrefLong(PREF_POP_LAST_AUTH,0);
}
if (!auxpwGood)
{
Zero((*CurPers)->secondPass);
if (PrefIsSet(PREF_SAVE_PASSWORD) && CurPers==PersList)
SetPref(PREF_AUXPW,"");
}
#ifdef HAVE_KEYCHAIN
if (!pwGood && KeychainAvailable() && PrefIsSet(PREF_KEYCHAIN))
DeletePersKCPassword(CurPers);
#endif //HAVE_KEYCHAIN
// force IMAP to reconnect
if (!pwGood && PrefIsSet(PREF_IS_IMAP))
IMAPInvalidatePerConnections(CurPers);
if (!pwGood || !auxpwGood) (*CurPers)->dirty = true;
}
/************************************************************************
* PasswordFilter - a ModalDialog filter for getting passwords
************************************************************************/
pascal Boolean PasswordFilter(DialogPtr dgPtr,EventRecord *event,short *item)
{
if (MiniMainLoop(event))
{
*item = CANCEL_ITEM;
return(True);
}
if (event->what==keyDown || event->what==autoKey)
{
if (event->modifiers & cmdKey)
{
SysBeep(20L);
event->what = nullEvent;
return false;
}
else
{
char key = event->message & charCodeMask;
switch (key)
{
case enterChar:
case returnChar:
*item = 1;
return(True);
break;
case backSpace:
if (**PwChars) --**PwChars;
return(False);
break;
case '.':
if (event->modifiers & cmdKey)
{
*item=2;
return(True);
break;
}
/* fall through */
default:
if (**PwChars < 255 && key != tabChar)
{
PCatC(*PwChars,key);
event->message = ((event->message >> 8)<<8) | bulletChar;
}
else
{
SysBeep(20);
event->what = nullEvent;
}
return(False);
break;
}
}
}
else if (event->what==updateEvt)
{
if (GetDialogFromWindow((WindowPtr)event->message) == dgPtr)
HiliteButtonOne(dgPtr);
else
UpdateMyWindow((WindowPtr)event->message);
}
else
{
if (TickCount()%120<100 && CurrentModifiers()&alphaLock)
ShowDialogItem(dgPtr,PASSWORD_WARNING);
else
HideDialogItem(dgPtr,PASSWORD_WARNING);
}
return(False);
}
/************************************************************************
* CopyPassword - retrieve the password
************************************************************************/
void CopyPassword(UPtr password)
{
BMD(*PwChars,password,**PwChars + 1);
HPurge(PwChars);
}
/************************************************************************
* MyAppendMenu - see that a menu item gets appended to a menu. Avoids
* menu manager meta-characters.
************************************************************************/
void MyAppendMenu(MenuHandle menu, UPtr name)
{
MyInsMenuItem(menu,name,CountMenuItems(menu));
}
/************************************************************************
* GetItemColor - get the color of a menu item
************************************************************************/
RGBColor *GetItemColor(short menu,short item,RGBColor *color)
{
MCEntryPtr mc;
if (!(mc = GetMCEntry(menu,item)))
DEFAULT_COLOR(*color);
else
*color = mc->mctRGB2;
return(color);
}
/************************************************************************
* MyInsMenuItem - see that a menu item gets appended to a menu. Avoids
* menu manager meta-characters.
************************************************************************/
void MyInsMenuItem(MenuHandle menu, UPtr name, short afterItem)
{
Str255 fixName;
PCopy(fixName,"\px");
InsertMenuItem(menu,fixName,afterItem);
if (!IsWordChar[name[1]] && (name[1]<'0' || name[1]>'9'))
{
PCat(fixName,name);
fixName[1] = 0;
}
else PCopy(fixName,name);
SetMenuItemText(menu,afterItem+1,fixName);
}
/**********************************************************************
*
**********************************************************************/
void SetItemR(MenuHandle menu, short item, short id)
{
Str255 itemStr;
GetRString(itemStr,id);
MySetItem(menu,item,itemStr);
}
/**********************************************************************
* MySetItem - set a menu item, avoiding metas
**********************************************************************/
void MySetItem(MenuHandle menu, short item, PStr itemStr)
{
if (!IsWordChar[itemStr[1]] && (itemStr[1]<'0' || itemStr[1]>'9'))
PInsert(itemStr,255,"\p\000",itemStr+1);
SetMenuItemText(menu,item,itemStr);
}
/************************************************************************
* MyGetItem - get the text of a menu item. Strip leading NULL, if any
************************************************************************/
PStr MyGetItem(MenuHandle menu, short item, PStr name)
{
GetMenuItemText(menu,item,name);
if (*name && !name[1])
{
BMD(name+2,name+1,name[0]-1);
name[0]--;
}
return(name);
}
/************************************************************************
* CopyMenuItem - copy a menu item from one menu to another
************************************************************************/
OSErr CopyMenuItem(MenuHandle fromMenu, short fromItem, MenuHandle toMenu, short toItem)
{
Str255 s;
short shortWhatever;
long longWhatever;
Byte byteWhatever;
Handle handleWhatever;
TextEncoding enc;
short n = CountMenuItems(toMenu);
// add the item
InsertMenuItem(toMenu,"\p ",toItem);
if (CountMenuItems(toMenu)!=n+1) return(MemError());
// adjust toItem to be real
if (toItem==0) toItem = 1;
else if (toItem>n) toItem = n+1;
else toItem++;
// now, copy the attributes one at a time
MyGetItem(fromMenu,fromItem,s);
MySetItem(toMenu,toItem,s);
GetItemMark(fromMenu,fromItem,&shortWhatever);
SetItemMark(toMenu,toItem,shortWhatever);
GetItemIcon(fromMenu,fromItem,&shortWhatever);
SetItemIcon(toMenu,toItem,shortWhatever);
GetItemMark(fromMenu,fromItem,&shortWhatever);
SetItemMark(toMenu,toItem,shortWhatever);
GetItemCmd(fromMenu,fromItem,&shortWhatever);
SetItemCmd(toMenu,toItem,shortWhatever);
GetItemStyle(fromMenu,fromItem,&byteWhatever);
SetItemStyle(toMenu,toItem,byteWhatever);
if (!GetMenuItemCommandID(fromMenu,fromItem,&longWhatever))
SetMenuItemCommandID(toMenu,toItem,longWhatever);
if (!GetMenuItemModifiers(fromMenu,fromItem,&byteWhatever))
SetMenuItemModifiers(toMenu,toItem,byteWhatever);
if (!GetMenuItemIconHandle(fromMenu,fromItem,&byteWhatever,&handleWhatever))
SetMenuItemIconHandle(toMenu,toItem,byteWhatever,handleWhatever);
if (!GetMenuItemTextEncoding(fromMenu,fromItem,&enc))
SetMenuItemTextEncoding(toMenu,toItem,enc);
if (!GetMenuItemHierarchicalID(fromMenu,fromItem,&shortWhatever))
SetMenuItemHierarchicalID(toMenu,toItem,shortWhatever);
if (!GetMenuItemFontID(fromMenu,fromItem,&shortWhatever))
SetMenuItemFontID(toMenu,toItem,shortWhatever);
if (!GetMenuItemRefCon(fromMenu,fromItem,&longWhatever))
SetMenuItemRefCon(toMenu,toItem,longWhatever);
if (!GetMenuItemKeyGlyph(fromMenu,fromItem,&shortWhatever))
SetMenuItemKeyGlyph(toMenu,toItem,shortWhatever);
EnableIf(toMenu,toItem,IsEnabled(GetMenuID(fromMenu),fromItem));
return(noErr);
}
/**********************************************************************
* PStr2Handle - copy a PString to a handle
**********************************************************************/
UHandle PStr2Handle(PStr string)
{
UHandle h = NuHandle(*string);
if (h) BMD(string+1,*h,*string);
return(h);
}
/************************************************************************
* SetItemReducedIcon - set a reduced icon for a menu item
************************************************************************/
void SetItemReducedIcon(MenuHandle menu, short item, short iconid)
{
SetItemIcon(menu,item,iconid-256);
SetItemCmd(menu,item,0x1D);
}
/************************************************************************
* FindItemByName - find a named menu item
************************************************************************/
short FindItemByName(MenuHandle menu, UPtr name)
{
short item;
Str255 itemTitle;
for (item=CountMenuItems(menu);item;item--)
{
MyGetItem(menu,item,itemTitle);
if (StringSame(name,itemTitle)) break;
}
return(item);
}
/************************************************************************
* FindMenuByName - find a named menu item
************************************************************************/
short FindMenuByName(UPtr name)
{
Str255 menuTitle;
short i;
MenuHandle m;
Handle h;
static short specialsPro[] = {TABLE_HIER_MENU,REPLY_WITH_HIER_MENU,NEW_WITH_HIER_MENU,FORWARD_TO_HIER_MENU,
NEW_TO_HIER_MENU,REDIST_TO_HIER_MENU,INSERT_TO_HIER_MENU,EMOTICON_HIER_MENU};
static short specialsLight[] = {TABLE_HIER_MENU,FORWARD_TO_HIER_MENU,NEW_TO_HIER_MENU,REDIST_TO_HIER_MENU,INSERT_TO_HIER_MENU};
short num,
*specials;
if (HasFeature (featureStationery)) {
num = sizeof (specialsPro);
specials = specialsPro;
}
else {
num = sizeof (specialsLight);
specials = specialsLight;
}
for (i=0;i<num/sizeof(short);i++)
if (m=GetMHandle(*specials++))
{
GetMenuTitle(m,menuTitle);
if (StringSame(name,menuTitle))
return(GetMenuID(m));
}
for (i=1;h=GetIndResource('MENU',i);i++)
{
PCopy(menuTitle,(*h)+14);
if (StringSame(name,menuTitle))
return(*(short*)*h);
}
return(0);
}
/************************************************************************
* MyUniqueID - get a unique id in the app range
************************************************************************/
short MyUniqueID(ResType type)
{
short id;
for (id=UniqueID(type);id<128;id=UniqueID(type));
return(id);
}
#pragma segment Util2
/**********************************************************************
* OnBatteries - are we running on batteries?
**********************************************************************/
static Boolean OnBatteries9 ( void ) {
long value;
Byte status, power;
if ( noErr != Gestalt (gestaltPowerMgrAttr, &value ))
return false;
if ( value & ( 1 << gestaltPMgrExists )) {
if ( noErr != BatteryStatus ( &status, &power ))
return false;
return ( status & 1 ) == 0;
}
return false;
}
// In Wrappers.cp
extern Boolean OnBatteriesX ( void );
Boolean OnBatteries ( void ) {
static uLong ticks = 0;
static Boolean val;
// Don't check too often
if ( TickCount () - ticks < 60 )
return val;
ticks = TickCount ();
return val = HaveOSX () ? OnBatteriesX () : OnBatteries9 ();
}
/**********************************************************************
* GestaltBits - return the bits for a Gestalt selector. Note that this
* routine cannot distinguish between an error and no bits, so if that's
* important to you, use Gestalt directly.
**********************************************************************/
uLong GestaltBits(OSType selector)
{
uLong value;
if (Gestalt(selector, &value)) value = 0;
return(value);
}
/************************************************************************
* BinFindItemByName - find a named menu item, using binary search
************************************************************************/
short BinFindItemByName(MenuHandle menu, UPtr name)
{
short item;
Str255 itemTitle;
short first,last;
short cmp;
first = 1;
last = CountMenuItems(menu);
for (item=(first+last)/2;first<=last;item=(first+last)/2)
{
MyGetItem(menu,item,itemTitle);
cmp = StringComp(name,itemTitle);
switch (cmp)
{
case -1:
last = item-1;
break;
case 1:
first = item+1;
break;
case 0:
return(item);
}
}
return(0);
}
/************************************************************************
* SpecialKeys - mutate events involving particular keys
************************************************************************/
void SpecialKeys(EventRecord *event)
{
uShort menu,item;
MenuRef mh;
switch(event->message & charCodeMask)
{
case helpChar:
HMSetBalloons(!HMGetBalloons());
event->what = nullEvent;
break;
case homeChar:
case endChar:
case pageUpChar:
case pageDownChar:
event->what = app1Evt;
break;
default:
switch((event->message & keyCodeMask)>>8)
{
case undoKey:
menu = EDIT_MENU;
item = EDIT_UNDO_ITEM;
break;
case cutKey:
menu = EDIT_MENU;
item = EDIT_CUT_ITEM;
break;
case copyKey:
menu = EDIT_MENU;
item = EDIT_COPY_ITEM;
break;
case pasteKey:
menu = EDIT_MENU;
item = EDIT_PASTE_ITEM;
break;
case clearKey:
menu = EDIT_MENU;
item = EDIT_CLEAR_ITEM;
break;
default:
return;
}
EnableMenuItems(False);
Type2SelTicks = 0; /* make sure string gets cleared */
mh = GetMenuHandle(menu);
if (IsMenuItemEnabled(mh,0) && IsMenuItemEnabled(mh,item))
{
short oldMenu = LMGetTheMenu();
HiliteMenu(menu);
DoMenu(FrontWindow_(),(menu<<16)|item,event->modifiers);
if (oldMenu) HiliteMenu(oldMenu);
}
event->what = nullEvent;
break;
}
}
/************************************************************************
* Event2Window - grab a window from an event
************************************************************************/
WindowPtr Event2Window(EventRecord *event)
{
WindowPtr maybe = (WindowPtr)event->message;
WindowPtr is;
#ifdef FLOAT_WIN
for (is=FrontWindow();is;is=GetNextWindow(is))
#else //FLOAT_WIN
for (is=FrontWindow_();is;is=GetNextWindow(is))
#endif //FLOAT_WIN
if (is==maybe) break;
return(is);
}
/**********************************************************************
* FixURLString - undo escaped stuff in URL's
**********************************************************************/
void FixURLString(PStr url)
{
UPtr spot, end;
spot = url+1;
end = url+*url+1;
for (;spot<end;spot++) if (*spot=='%') *spot = lowerDelta;
CaptureHex(url,url);
}
/************************************************************************
* CurrentModifiers - return the current state of the modifers
************************************************************************/
short CurrentModifiers(void)
{
EventRecord theEvent;
OSEventAvail(nil,&theEvent);
return(theEvent.modifiers);
}
/************************************************************************
* AttachHierMenu - attach a hierarchical menu to a menu item
************************************************************************/
void AttachHierMenu(short menu,short item,short hierId)
{
MenuHandle mh = GetMHandle(menu);
if (g16bitSubMenuIDs && hierId > 255)
SetMenuItemHierarchicalID(mh,item,hierId);
else
{
SetItemCmd(mh,item,0x1b);
SetItemMark(mh,item,hierId);
}
}
/************************************************************************
* DirtyKey - does a keystroke cause a window to become dirty?
************************************************************************/
Boolean DirtyKey(long keyAndChar)
{
short charCode = keyAndChar&charCodeMask;
short keyCode = (keyAndChar&keyCodeMask)>>8;
static short safeChars[]={
homeChar,endChar,pageUpChar,pageDownChar,
leftArrowChar,rightArrowChar,upArrowChar,downArrowChar};
short *which;
for (which=safeChars;which<safeChars+sizeof(safeChars)/sizeof(short);which++)
if (charCode==*which) return(False);
return(True);
}
/************************************************************************
* LocalDateTimeStr - return a ctime format date and time,
* but as a pascal string
* <length>Sun Sep 16 01:03:52 1973\015\0
* This is quite purposefully not internationally blessed
************************************************************************/
UPtr LocalDateTimeStr(UPtr string)
{
DateTimeRec dtr;
GetTime(&dtr);
return(ComposeRString(string,DATE_STRING_FMT,
WEEKDAY_STRN+dtr.dayOfWeek,
MONTH_STRN+dtr.month,
dtr.day/10, dtr.day%10,
dtr.hour/10, dtr.hour%10,
dtr.minute/10, dtr.minute%10,
dtr.second/10, dtr.second%10,
dtr.year));
}
/************************************************************************
* WeekDay - get the name of a weekday
************************************************************************/
PStr WeekDay(PStr string,long secs)
{
DateTimeRec dtr;
short itlId;
Str15 **weekNames;
SecondsToDate(secs,&dtr);
itlId = GetScriptVariable(smSystemScript,smScriptDate);
weekNames = GetResource_('itl1',itlId);
if (weekNames)
return(PCopy(string,(*weekNames)[dtr.dayOfWeek-1]));
else
return(GetRString(string,WEEKDAY_STRN+dtr.dayOfWeek));
}
/************************************************************************
* GMTDateTime - return the current seconds
************************************************************************/
uLong GMTDateTime(void)
{
static uLong secs;
static uLong ticks;
if (TickCount()-ticks>30)
{
ticks = TickCount();
GetDateTime(&secs);
secs -= ZoneSecs();
}
return(secs);
}
/************************************************************************
* LocalDateTime - return the current seconds
************************************************************************/
uLong LocalDateTime(void)
{
uLong secs;
GetDateTime(&secs);
return(secs);
}
/************************************************************************
* LocalDateTimeShortStr - return the date/time in a short representation
************************************************************************/
PStr LocalDateTimeShortStr(PStr s)
{
DateTimeRec dtr;
GetTime(&dtr);
ComposeString(s,"\p%d%d%d%d%d%d%d%d",
dtr.month/10, dtr.month%10,
dtr.day/10, dtr.day%10,
dtr.hour/10, dtr.hour%10,
dtr.minute/10, dtr.minute%10);
return(s);
}
/**********************************************************************
* MenuWidth - return the width of a menu
**********************************************************************/
short MenuWidth(MenuHandle mh)
{
CalcMenuSize(mh);
return(GetMenuWidth(mh));
}
/**********************************************************************
* MyTrackDrag - track a drag
**********************************************************************/
OSErr MyTrackDrag(DragReference drag, EventRecord *event, RgnHandle rgn)
{
OSErr err;
PushGWorld();
DragFxxkOff = False;
MightSwitch();
err = TrackDrag(drag,event,rgn);
AfterSwitch();
DragFxxkOff = True;
PopGWorld();
return(err);
}
/**********************************************************************
* HasDragManager - is the pestilent drag manager installed?
**********************************************************************/
Boolean HasDragManager(void)
{
long fxxkingGestalt;
return (!(Gestalt('drag',&fxxkingGestalt) || !(fxxkingGestalt&1)))
#if TARGET_RT_MAC_CFM
&& ((long)InstallTrackingHandler != kUnresolvedCFragSymbolAddress
&& !PrefIsSet(PREF_NO_DRAG))
#endif
;
}
/**********************************************************************
* MyWaitMouseMoved - call WMM but only if we have the drag manager
**********************************************************************/
Boolean MyWaitMouseMoved(Point pt,Boolean honorControl)
{
return(HasDragManager() /*&& (!honorControl || !PrefIsSet(PREF_CONTROL_DRAG) || MainEvent.modifiers&controlKey)*/ && WaitMouseMoved(pt));
}
/**********************************************************************
* MyDragHas - does a drag have a particular type?
**********************************************************************/
Boolean MyDragHas(DragReference drag,short item,OSType type)
{
FlavorFlags flags;
ItemReference ref;
if (GetDragItemReferenceNumber(drag,item,&ref)) return(False);
if (GetFlavorFlags(drag,ref,type,&flags)) return(False);
return (!(flags&flavorSenderOnly));
}
/**********************************************************************
* MyGetDragItemData - dig data out of a drag
**********************************************************************/
OSErr MyGetDragItemData(DragReference drag,short item,OSType type,Handle *data)
{
ItemReference ref;
long len;
OSErr err;
Handle local=nil;
if (data) *data = nil;
err = GetDragItemReferenceNumber(drag,item,&ref);
//Dprintf("\pRef %o %d %d %d;g",type,item,err,ref);
if (err) return(err);
err = GetFlavorDataSize(drag,ref,type,&len);
//Dprintf("\pSiz %o %d %d %d;g",type,item,err,len);
if (err) return(err);
if (!(local = NuHTempBetter(len))) return(err=MemError());
err = GetFlavorData(drag, ref, type, LDRef(local), &len, 0);
//Dprintf("\pDat %o %d %d %p;g",type,item,err,*local);
if (err)
{
ZapHandle(local);
return(err);
}
UL(local);
if (data) *data = local;
else ZapHandle(local);
return (noErr);
}
/**********************************************************************
* MySetDragItemFlavorData - stick data into a flavor
**********************************************************************/
OSErr MySetDragItemFlavorData(DragReference drag,short item,OSType type,void*data,long len)
{
ItemReference ref;
OSErr err;
if (!(err=GetDragItemReferenceNumber(drag,item,&ref)))
err = SetDragItemFlavorData(drag,ref,type,data,len,0);
return (err);
}
/**********************************************************************
*
**********************************************************************/
short DragOrMods(DragReference drag)
{
short m1, m2, m3;
GetDragModifiers(drag,&m1,&m2,&m3);
return(m1|m2|m3);
}
/**********************************************************************
* MyCountDragItems - count the items in a drag
**********************************************************************/
short MyCountDragItems(DragReference drag)
{
short count;
OSErr err = CountDragItems(drag,&count);
if (err) return(0);
return(count);
}
/**********************************************************************
* MyCountDragItemFlavors - count drag item flavors
**********************************************************************/
short MyCountDragItemFlavors(DragReference drag,short item)
{
short count;
ItemReference ref;
if (GetDragItemReferenceNumber(drag,item,&ref)) return(0);
if (CountDragItemFlavors(drag,ref,&count)) return(0);
return(count);
}
/**********************************************************************
* MyGetDragItemFlavorType - get the type of a particular flavor
**********************************************************************/
OSType MyGetDragItemFlavorType(DragReference drag,short item,short flavor)
{
ItemReference ref;
OSType type;
if (GetDragItemReferenceNumber(drag,item,&ref)) return(0);
if (GetFlavorType(drag,ref,flavor,&type)) return(0);
return(type);
}
/**********************************************************************
* MyGetDragItemFlavorFlags
**********************************************************************/
FlavorFlags MyGetDragItemFlavorFlags(DragReference drag,short item,short flavor)
{
FlavorFlags flags;
ItemReference ref;
OSType type;
if (GetDragItemReferenceNumber(drag,item,&ref)) return(0);
if (GetFlavorType(drag,ref,flavor,&type)) return(0);
if (GetFlavorFlags(drag,ref,type,&flags)) return(0);
return(flags);
}
/************************************************************************
* MiniEvents - call WNE, handle a few events, allow cmd-.
************************************************************************/
Boolean MiniEventsLo(long sleepTime,uLong mask)
{
EventRecord event;
Boolean newCommandPeriod = False;
if (NEED_YIELD)
{
#ifndef SLOW_CLOSE
TcpFastFlush(False); /* give lingering connections a chance to die */
#endif
newCommandPeriod = HasCommandPeriod();
if (newCommandPeriod) CommandPeriod = true;
if (WNE(mask,&event,sleepTime)) (void) MiniMainLoop(&event);
}
return(newCommandPeriod);
}
#ifdef DEBUG
/**********************************************************************
* Rude - be rude to memory
**********************************************************************/
void Rude(void)
{
PurgeMem(0x7fffffff);
CompactMem(0x7fffffff);
}
#endif
/************************************************************************
* PlayNamedSound - play a sound with a given name
************************************************************************/
void PlayNamedSound(PStr name)
{
Handle sound = GetNamedResource('snd ',name);
if (sound)
{
HNoPurge(sound);
SndPlay(nil,(void*)sound,False);
HPurge(sound);
}
else
{
// Not sound resource. May be system sound
if (gSoundMovie)
// Busy playing a sound. Queue and try later
QueueSound(name);
else
PlaySystemSound(name);
}
}
/************************************************************************
* PlaySystemSound - play a system sound
************************************************************************/
void PlaySystemSound(PStr name)
{
// Look for file in system sounds folder
FSSpec spec;
if (!FindSystemSound(kUserDomain,kSystemSoundsFolderType,name,&spec) ||
!FindSystemSound(kOnSystemDisk,kSystemSoundsFolderType,name,&spec))
{
short fileRefNum;
OSErr err;
// Make sure QuickTime is inited
if (!QTMoviesInited)
{
if (EnterMovies())
return;
QTMoviesInited = true;
}
// QT movies are attached to a port, even if the movie is just a sound.
// By default, the current port is used. This is bad news if the port
// gets closed, so we specifically assign a port. We use an off screen port.
if (!gGWorld)
{
Rect bounds;
SetRect(&bounds,0,0,16,16);
if (NewGWorld(&gGWorld,0,&bounds,nil,nil,0))
return;
}
if (!OpenMovieFile (&spec, &fileRefNum, fsRdPerm))
{
err = NewMovieFromFile (&gSoundMovie, fileRefNum, 0, nil, newMovieActive, nil);
CloseMovieFile(fileRefNum);
if (!err)
{
SetMovieGWorld(gSoundMovie,gGWorld,nil);
GoToBeginningOfMovie(gSoundMovie);
StartMovie(gSoundMovie);
}
}
}
}
/************************************************************************
* FindSystemSound - look in a particular location for a sound
************************************************************************/
OSErr FindSystemSound(OSType disk,OSType folder,PStr name,FSSpecPtr spec)
{
Str255 suffices;
UPtr spot;
Str31 suffix;
OSErr err = fnfErr;
if (!FindFolder(disk,folder,false,&spec->vRefNum,&spec->parID))
{
PStrCopy(spec->name,name,sizeof(spec->name));
if (err=FSpExists(spec))
{
// This file doesn't exist. Try putting some file extensions on
GetRString(suffices,SOUND_SUFFICES);
spot = suffices+1;
while (PToken(suffices,suffix,&spot,"<EFBFBD>") && *suffix)
{
PCat(spec->name,suffix);
if (!(err=FSpExists(spec)))
break; // This one exists
PStrCopy(spec->name,name,sizeof(spec->name));
}
}
}
return err;
}
/************************************************************************
* PlaySoundIdle - idle function for playing sounds with QuickTime
************************************************************************/
void PlaySoundIdle(void)
{
if (gSoundMovie)
{
MoviesTask(gSoundMovie, 0);
if (IsMovieDone(gSoundMovie))
{
// Done with this movie
DisposeMovie(gSoundMovie);
gSoundMovie = nil;
// Any more sounds to play?
if (gSystemSoundList)
{
SoundEntryPtr next = gSystemSoundList->next;
PlaySystemSound(gSystemSoundList->name);
// Dispose of queue entry
ZapPtr(gSystemSoundList);
gSystemSoundList = next;
}
}
}
else if (gGWorld)
{
// No longer need gworld
DisposeGWorld(gGWorld);
gGWorld = nil;
}
}
/************************************************************************
* QueueSound - queue this system sound to play it later
************************************************************************/
void QueueSound(PStr name)
{
SoundEntryPtr entry;
if (entry = NuPtrClear(sizeof(SoundEntry)))
{
SoundEntryPtr t = gSystemSoundList; \
PCopy(entry->name,name);
// Put at end of queue
if (t) \
{ \
while (t->next)
t = t->next; \
t->next = entry; \
} \
else \
gSystemSoundList = entry; \
}
}
/************************************************************************
* PlaySoundId - play a sound with a given resource id
************************************************************************/
void PlaySoundId(short id)
{
Handle sound = GetResource('snd ',id);
if (sound)
{
HNoPurge(sound);
SndPlay(nil,(void*)sound,False);
HPurge(sound);
}
}
/************************************************************************
* AddSoundsToMenu - add sound names to menu
************************************************************************/
void AddSoundsToMenu(MenuHandle mh)
{
short vRef=0, vRefWas;
long dirID=0, dirIDWas;
// Now add all sounds from system sounds folder
if (!FindFolder(kUserDomain,kSystemSoundsFolderType,false,&vRef,&dirID))
AddSoundsToMenuFrom(mh,vRef,dirID);
dirIDWas = dirID;
vRefWas = vRef;
if (!FindFolder(kOnSystemDisk,kSystemSoundsFolderType,false,&vRef,&dirID))
if (vRef!=vRefWas || dirID!=dirIDWas)
AddSoundsToMenuFrom(mh,vRef,dirID);
}
/************************************************************************
* AddSoundsToMenuFrom - add sound names to menu, from a particular folder
************************************************************************/
void AddSoundsToMenuFrom(MenuHandle mh, short vRef, long dirID)
{
Str32 name;
Str255 suffices;
UPtr spot;
Str31 suffix;
Boolean needsDivider = CountMenuItems(mh) != 0;
CInfoPBRec hfi;
hfi.hFileInfo.ioNamePtr = name;
hfi.hFileInfo.ioFDirIndex = 0;
while (!DirIterate(vRef,dirID,&hfi))
{
// Look for a file extension we can remove
GetRString(suffices,SOUND_SUFFICES);
spot = suffices+1;
while (PToken(suffices,suffix,&spot,"<EFBFBD>") && *suffix)
{
if (EndsWith(name,suffix))
{
// Remove suffix
*name -= *suffix;
break;
}
}
// don't add second item with same name
if (FindItemByName(mh,name)) continue;
// add divider if first sound from this folder
if (needsDivider)
{
AppendMenu(mh,"\p-"); // Divider line
needsDivider = false;
}
// Add to menu
MyAppendMenu(mh,name);
}
}
/************************************************************************
* UnadornKey - unadorn an event message
************************************************************************/
long UnadornKey(long message,short modifiers)
{
Handle curKCHR;
static long state=0;
short key;
curKCHR = GetResource_('KCHR',
GetScriptVariable(GetScriptManagerVariable(smKeyScript),smScriptKeys));
if (curKCHR && (modifiers&optionKey))
{
/*
* get what it would have been without the option key
*/
key = ((message>>8)&0xff) | (modifiers&(~optionKey)&0xff00);
message = KeyTranslate(LDRef(curKCHR),key,&state);
UL(curKCHR);
/*
* now massage this into an event "message"
*/
message = message & 0xff;
}
return(message);
}
extern char checkKey;
/************************************************************************
* MyMenuKey - fix MenuKey to ignore option key
************************************************************************/
long MyMenuKeyLo(EventRecord *event,Boolean enable)
{
long select;
if (enable && event->modifiers&cmdKey) EnableMenuItems(False);
select = MenuEvent(event);
if (select&0xffff0000) return(select);
// STUPID hack.
if (PrefIsSet(PREF_ALTERNATE_CHECK_MAIL_CMD) || !PrefIsSet(PREF_NO_ALTERNATE_ATTACH_CMD))
{
if ((select = STUPIDCheckMailHack(event)) != 0) return (select);
}
// cmd-opt-J - don't strip the opt since it will hit cmd-J
if (JunkPrefSwitchCmdJ() && ((event->message)&0xff)==0xC6)
return(MenuKey(event->message));
return(MenuKey(UnadornMessage(event)));
}
/************************************************************************
* AFPopUpMenuSelect - pop up menu in current font
************************************************************************/
long AFPopUpMenuSelect(MenuHandle mh,short top,short left,short item)
{
short oldSysFont = LMGetSysFontFam();
short oldSysSize = LMGetSysFontSize();
short oldWmgrSize;
short oldCWmgrSize;
long sel;
short i;
GrafPtr wMgrPort, cwMgrPort;
PushGWorld();
GetWMgrPort(&wMgrPort);
SetPort(wMgrPort);
oldWmgrSize = GetPortTextSize(wMgrPort);
TextSize(SmallSysFontID());
if (ThereIsColor)
{
GetCWMgrPort((void*)&cwMgrPort);
SetPort(cwMgrPort);
oldCWmgrSize = GetPortTextSize(cwMgrPort);
TextSize(ScriptVar(smScriptSmallFondSize));
}
PopGWorld();
LMSetSysFontFam(SmallSysFontID());
LMSetSysFontSize(SmallSysFontSize());
LMSetLastSPExtra(-1);
if (item >= 0)
{
for (i=CountMenuItems(mh);i;i--)
if (item==i) SetItemMark(mh,i,diamondChar);
else SetItemMark(mh,i,noMark);
}
else
{
// Don't mess with check marks
item = 0;
}
sel = PopUpMenuSelect(mh,top,left,item);
LMSetSysFontFam(oldSysFont);
LMSetSysFontSize(oldSysSize);
LMSetLastSPExtra(-1);
PushGWorld();
SetPort(wMgrPort);
TextSize(oldWmgrSize);
if (ThereIsColor)
{
SetPort(cwMgrPort);
TextSize(oldCWmgrSize);
}
PopGWorld();
return(sel);
}
/************************************************************************
* SetHiliteMode - Turn on hilite mode
************************************************************************/
void SetHiliteMode(void)
{
Byte mode = LMGetHiliteMode();
BitClr(&mode,pHiliteBit);
LMSetHiliteMode(mode);
}
/************************************************************************
* IsPowerNoVM - is powermac vm turned on?
************************************************************************/
Boolean IsPowerNoVM(void)
{
return(!VM);
}
/************************************************************************
* ChangeStrn - change a string in an Str# resource
************************************************************************/
UPtr ChangeStrn(short resId,short num,UPtr string)
{
Handle resH;
UPtr spot;
short count;
short i;
long hSize;
short diff;
long offset;
SCClear(resId+num);
if (RecountStrn(resId)) Aprintf(OK_ALRT,Caution,FIXED_STRN,resId);
if (!(resH=GetResource_('STR#',resId))) return(nil);
HNoPurge(resH);
spot = LDRef(resH);
hSize = GetHandleSize_(resH);
count = 256*spot[0] + spot[1];
if (num<=count)
{
spot += 2;
for (i=1;i<num;i++) spot += *spot + 1;
diff = *string-*spot;
if (diff<0)
{
diff *= -1;
if (num<count)
BMD(spot+diff,spot,hSize-(spot-*resH)-diff);
SetHandleBig_(resH,hSize-diff);
}
else if (diff>0)
{
offset = spot-*resH;
UL(resH);
SetHandleBig_(resH,hSize+diff);
if (i=MemError()) {WarnUser(MEM_ERR,i);UL(resH);return(nil);}
spot = LDRef(resH) + offset;
if (num<count)
BMD(spot,spot+diff,hSize-offset);
}
}
else
{
UL(resH);
SetHandleBig_(resH,hSize+*string+num-count);
if (i=MemError()) {WarnUser(MEM_ERR,i);return(nil);}
spot = LDRef(resH);
if (num>count+1)
WriteZero(spot+hSize,num-count-1);
spot[0] = num/256;
spot[1] = num%256;
spot += hSize + num-count-1;
}
hSize = GetHandleSize_(resH);
BMD(string,spot,*string+1);
UL(resH);
ChangedResource(resH);
RecountStrn(resId);
return(string);
}
/************************************************************************
* RecountStrn - make sure an STR# resource really has the right number
* of strings
*
* returns True if the resource had to be changed
************************************************************************/
Boolean RecountStrn(short resId)
{
Handle resH = GetResource_('STR#',resId);
UPtr spot,end;
short count;
short realCount=0;
Boolean changed=False;
/*
* no resource?
*/
if (!resH || !*resH) return(False);
spot = *resH;
/*
* does it have a count?
*/
end = spot+GetHandleSize_(resH);
if (end-spot<2) {RemoveResource(resH); ZapHandle(resH); return(True);} // not even two bytes long!
if (end-spot==2 && !spot[0] && !spot[1]) return false; // empty but that's ok
/*
* what's the current count?
*/
count = spot[0]*256 + spot[1];
/*
* count the actual strings, stopping if we go beyond the end of the resource
*/
for (spot+=2;spot+*spot+1<end;spot += *spot+1) realCount++;
/*
* if the last string hits the very end of the resource, we count it, too
*/
if (spot+*spot+1==end)
{
spot += *spot+1;
realCount++;
}
/*
* ok, at this point:
*
* spot points just AFTER the last valid string in the resource
* realCount is the actual count of the strings contained in the resource
*/
/*
* remove extra data from resource
*/
if (spot!=end)
{
SetHandleBig_(resH,spot-*resH);
ChangedResource(resH);
HNoPurge_(resH);
changed = True;
}
/*
* repair the count
*/
if (realCount!=count)
{
spot=*resH;
spot[0] = realCount/256;
spot[1] = realCount%256;
ChangedResource(resH);
HNoPurge_(resH);
changed = True;
}
return(changed);
}
/************************************************************************
* CountStrn - count the strings an STR# resource says it has
************************************************************************/
short CountStrn(short resId)
{
Handle resH = GetResource_('STR#',resId);
return(CountStrnRes(resH));
}
/************************************************************************
*
************************************************************************/
void NukeMenuItemByName(short menuId,UPtr itemName)
{
MenuHandle mh=GetMHandle(menuId);
short itemNum=FindItemByName(mh,itemName);
if (itemNum) NukeMenuItem(mh,itemNum);
}
void NukeMenuItem(MenuHandle mh,short item)
{
if (HasSubmenu(mh,item))
{
short subId,subItem;
MenuHandle subMh;
subId = SubmenuId(mh,item);
subMh=GetMHandle(subId);
for (subItem=CountMenuItems(subMh);subItem;subItem--)
NukeMenuItem(mh,subItem);
}
DeleteMenuItem(mh,item);
}
/************************************************************************
*
************************************************************************/
void RenameItem(short menuId,UPtr oldName,UPtr newName)
{
MenuHandle mh=GetMHandle(menuId);
SetMenuItemText(mh,FindItemByName(mh,oldName),newName);
}
/************************************************************************
*
************************************************************************/
Boolean HasSubmenu(MenuHandle mh, short item)
{
short cmd;
if (g16bitSubMenuIDs)
{
if (GetMenuItemHierarchicalID(mh,item,&cmd)) return false; // error
else return cmd!=0;
}
GetItemCmd(mh,item,&cmd);
return(cmd==0x1b);
}
/************************************************************************
* SubmenuId - return the id of a submenu if an item has one, or zero
************************************************************************/
short SubmenuId(MenuHandle mh, short item)
{
short cmd;
if (g16bitSubMenuIDs)
{
if (GetMenuItemHierarchicalID(mh,item,&cmd)) return 0; // error
else return cmd;
}
else
{
GetItemCmd(mh,item,&cmd);
if (cmd==0x1b)
{
GetItemMark(mh,item,&cmd);
return(cmd);
}
else return(0);
}
}
/************************************************************************
* SetGreyControl - grey a control, if it isn't already
************************************************************************/
Boolean SetGreyControl(ControlHandle cntl, Boolean shdBeGrey)
{
Boolean lifeSucksThanksToOSX =
IsControlActive(cntl)==shdBeGrey && HaveTheDiseaseCalledOSX() && IsControlVisible(cntl);
if (lifeSucksThanksToOSX) SetControlVisibility(cntl,false,false);
ActivateMyControl(cntl,!shdBeGrey);
if (lifeSucksThanksToOSX)
{
Rect r;
SetControlVisibility(cntl,true,false);
GetControlBounds(cntl,&r);
InvalWindowRect(GetControlOwner(cntl),&r);
}
return(shdBeGrey);
}
/************************************************************************
* IsAUX - is A/UX running?
************************************************************************/
Boolean IsAUX(void)
{
return false;
}
/************************************************************************
* ZoneSecs - get the timezone offset, in seconds
************************************************************************/
long ZoneSecs(void)
{
MachineLocation ml;
static long delta;
static uLong ticks;
if (TickCount()-ticks<600) return(delta);
ticks = TickCount();
#define GMTDELTA u.gmtDelta
ReadLocation(&ml);
if (ml.latitude==ml.longitude && ml.GMTDELTA==ml.longitude && ml.GMTDELTA==0)
return(delta = -1);
delta = ml.GMTDELTA&0xffffff;
if ((delta>>23)&1) delta |= 0xff000000;
return(delta);
}
/**********************************************************************
* AddMyResource - add resource, but set Eudora Settings, too
**********************************************************************/
void AddMyResource(Handle h,OSType type,short id,ConstStr255Param name)
{
if (SettingsRefN) UseResFile(SettingsRefN);
AddResource(h,type,id,name);
}
/************************************************************************
* Provide the same benefit as a politician
************************************************************************/
void NOOP(void) {}
/************************************************************************
* RoundDiv - Divide with rounding away from the origin
************************************************************************/
long RoundDiv(long quantity,long unit)
{
if (quantity<0) quantity -= unit-1;
else quantity += unit-1;
return(quantity/unit);
}
/************************************************************************
* TZName2Offset - interpret the time zone with a resource
************************************************************************/
long TZName2Offset(CStr zoneName)
{
UPtr this,end;
Handle tznH = GetResource_('zon#',TZ_NAMES);
long offset = 0;
Str15 psName;
CtoPCpy(psName,zoneName);
TrimWhite(psName);
if (tznH)
{
this = LDRef(tznH);
end = this + GetHandleSize_(tznH);
for (;this<end;this+=*this+1+2*sizeof(short))
if (StringSame(this,psName))
{
short hrs,mins;
this += *this +1;
hrs = this[0]*256+this[1];
mins = this[2]*256+this[3];
offset = hrs*3600 + 60*mins;
break;
}
UL(tznH);
}
return(offset);
}
/************************************************************************
* CenterRectIn - center one rect in another
************************************************************************/
void CenterRectIn(Rect *inner,Rect *outer)
{
OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2,
(outer->top+outer->bottom-inner->top-inner->bottom)/2);
}
/************************************************************************
* TopCenterRectIn - center one rect in (the bottom of) another
************************************************************************/
void TopCenterRectIn(Rect *inner,Rect *outer)
{
OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2,
outer->top-inner->top);
}
/************************************************************************
* BottomCenterRectIn - center one rect in (the bottom of) another
************************************************************************/
void BottomCenterRectIn(Rect *inner,Rect *outer)
{
OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2,
outer->bottom-inner->bottom);
}
/************************************************************************
* ThirdCenterRectIn - center one rect in (the top 1/3 of) another
************************************************************************/
void ThirdCenterRectIn(Rect *inner,Rect *outer)
{
OffsetRect(inner,(outer->left+outer->right-inner->left-inner->right)/2,
outer->top-inner->top +
(outer->bottom-outer->top-inner->bottom+inner->top)/3);
}
/**********************************************************************
* IsEnabled - is a menu item enabled
**********************************************************************/
Boolean IsEnabled(short menu,short item)
{
MenuHandle mh = GetMHandle(menu);
if (!mh) return(False);
if (!IsMenuItemEnabled(mh,0)) return false;
return IsMenuItemEnabled(mh,item);
}
/**********************************************************************
*
**********************************************************************/
void ShowDragRectHilite(DragReference drag, Rect *r, Boolean inside)
{
RgnHandle rgn = NewRgn();
if (rgn)
{
RectRgn(rgn,r);
ShowDragHilite(drag,rgn,inside);
DisposeRgn(rgn);
}
}
/**********************************************************************
* CheckNone - make sure no items are marked in a menu
**********************************************************************/
void CheckNone(MenuHandle mh)
{
short i;
if (mh) for (i=CountMenuItems(mh);i;i--)
if (!HasSubmenu(mh,i)) SetItemMark(mh,i,noMark);
}
/**********************************************************************
* ButtonFit - shrink button to min possibe size
**********************************************************************/
void ButtonFit(ControlHandle button)
{
Str255 title;
short wi, hi;
Rect r,rBtn;
short base;
MyWindowPtr win = GetWindowMyWindowPtr(GetControlOwner(button));
if (ControlIsUgly(button))
{
Zero(r);
GetBestControlRect(button,&r,&base);
GetControlBounds(button,&rBtn);
MoveMyCntl(button,rBtn.left,rBtn.top,RectWi(r),RectHi(r));
}
else
{
GetControlTitle(button,title);
wi = StringWidth(title)+win->hPitch*3;
hi = win->vPitch + 4;
SizeControl(button,wi,hi);
}
}
/**********************************************************************
* return a string from an STR# resource
**********************************************************************/
PStr GetRString(PStr theString,short theIndex)
{
SCPtr start, end;
uLong ticks = TickCount();
uLong oldest = ticks;
short oldSpot;
long n;
Str63 sizeStr;
uLong curPersId = CurThreadGlobals ? (CurPers ? (*CurPers)->persId : 0) : 0;
Boolean dontReadCache = NoDominant || !StringCache || NoProxify;
Boolean dontWriteCache = NoDominant || NoProxify || GrowZoning || (EjectBuckaroo&&!StringCache);
Boolean replaceOld = false;
/*
* find it in the cache
*/
if (!dontReadCache)
{
n = HandleCount(StringCache);
start = *StringCache;
end = start + n;
for (; start<end; start++)
{
if (theIndex==start->id && start->persId==curPersId)
{
PCopy(theString,start->string);
theString[*theString+1] = 0;
start->used = ticks;
return(ProxifyStr(theString,theIndex));
}
else if (oldest)
if (!start->id)
{
oldest = 0;
oldSpot = start-*StringCache;
replaceOld = true; // no need to replace one
}
else if (oldest>start->used)
{
oldest = start->used;
oldSpot = start-*StringCache;
replaceOld = true; // found one we can replace
}
}
}
/*
* not in the cache. Grab it.
*/
GetRStringLo(theString,theIndex,CurPers);
/*
* create cache
*/
if (!StringCache && !dontWriteCache)
{
GetRStringLo(sizeStr,STRING_CACHE,nil);
StringToNum(sizeStr,&n);
StringCache = NuHandleClear(n*sizeof(StringCacheEntry));
oldSpot = 0;
}
/*
* cache string
*/
if (StringCache && !dontWriteCache && replaceOld) // skip the cache just this once
{
PCopy((*StringCache)[oldSpot].string,theString);
(*StringCache)[oldSpot].id = theIndex;
(*StringCache)[oldSpot].used = ticks;
(*StringCache)[oldSpot].persId = curPersId;
}
return(ProxifyStr(theString,theIndex));
}
/**********************************************************************
* SCClear - clear the string cache
**********************************************************************/
void SCClear(short theId)
{
short i;
short n;
if (StringCache)
{
n = HandleCount(StringCache);
for (i=0;i<n;i++)
if (theId==-1 || (*StringCache)[i].id==theId)
{
(*StringCache)[i].id = 0;
//break;
}
}
}
/**********************************************************************
* return a string from an STR# resource
**********************************************************************/
PStr GetRStringLo(PStr theString,int theIndex,PersHandle forPers)
{
StringHandle s;
short oldRes = CurResFile();
if (SettingsRefN) UseResFile(SettingsRefN);
if (theIndex != 1001 &&
(forPers && (s=GetResource(PERS_TYPE('STR ',(*forPers)->resEnd),theIndex)) && HomeResFile(s) ||
(!forPers || forPers!=PersList&&!NoDominant) && (s=GetResource('STR ',theIndex)) && HomeResFile(s)))
{
PCopy(theString,*s);
ReleaseResource_(s);
}
else
{
theString[0] = 0;
if (!NoDominant || CurPers==PersList) GetIndString(theString,100*(theIndex/100),theIndex%100);
}
theString[*theString+1] = 0;
UseResFile(oldRes);
return(theString);
}
/************************************************************************
* FindSTRNIndex - find a string in a resource id
************************************************************************/
short FindSTRNIndex(short resId,PStr string)
{
UHandle resH = GetResource_('STR#',resId);
return(FindSTRNIndexRes(resH,string));
}
/**********************************************************************
* FindSTRNIndexRes - Find a string in an STR# resource
**********************************************************************/
short FindSTRNIndexRes(UHandle resource,PStr string)
{
short n = CountStrnRes(resource);
short i=0;
UPtr p;
if (n && resource && *resource)
{
for (i=1,p=LDRef(resource)+2;i<=n;i++,p+=*p+1)
{
if (StringSame(string,p)) break;
}
UL(resource);
if (i>n) i = 0;
}
return(i);
}
/************************************************************************
* FindSTRNSubIndex - find a substring in a resource id
************************************************************************/
short FindSTRNSubIndex(short resId,PStr string)
{
UHandle resH = GetResource_('STR#',resId);
return(FindSTRNSubIndexRes(resH,string));
}
/**********************************************************************
* FindSTRNSubIndexRes - Find a substring in an STR# resource
**********************************************************************/
short FindSTRNSubIndexRes(UHandle resource,PStr string)
{
short n = CountStrnRes(resource);
short i=0;
UPtr p;
if (n && resource && *resource)
{
for (i=1,p=LDRef(resource)+2;i<=n;i++,p+=*p+1)
{
if (string+1==PPtrFindSub(p,string+1,*string)) break;
}
UL(resource);
if (i>n) i = 0;
}
return(i);
}
/**********************************************************************
* CountStrnRes - count strings in an STR# resource, given the resource
**********************************************************************/
short CountStrnRes(UHandle resH)
{
if (resH && *resH) return((*resH)[0]*256 + (*resH)[1]);
else return(0);
}
/**********************************************************************
* Get a color out of a resource file, and darken for text
**********************************************************************/
RGBColor *GetRTextColor(RGBColor *color,int index)
{
return DarkenColor(GetRColor(color,index),GetRLong(TEXT_DARKER));
}
/**********************************************************************
* Get a color out of a resource file
**********************************************************************/
RGBColor *GetRColor(RGBColor *color,int index)
{
Str255 scratch;
Str31 token;
long aLong;
UPtr spot;
Zero(*color);
if (GetRString(scratch,index))
{
spot = scratch+1;
if (PToken(scratch,token,&spot,","))
{
StringToNum(token,&aLong);
color->red = (short)(aLong&0xffff);
if (PToken(scratch,token,&spot,","))
{
StringToNum(token,&aLong);
color->green = (short)(aLong&0xffff);
if (PToken(scratch,token,&spot,","))
{
StringToNum(token,&aLong);
color->blue = (short)(aLong&0xffff);
return(color);
}
}
}
}
return(nil);
}
/**********************************************************************
* Color2String - convert a color to a string
**********************************************************************/
PStr Color2String(PStr string,RGBColor *color)
{
ComposeString(string,"\p%d,%d,%d",color->red,color->green,color->blue);
return(string);
}
/**********************************************************************
* Get a long out of a resource file
**********************************************************************/
long GetRLong(int index)
{
Str255 scratch;
long aLong;
if (GetRString(scratch,index)==nil)
return(0L);
else
{
StringToNum(scratch,&aLong);
return(aLong);
}
}
/**********************************************************************
* Get an OSType out of a resource file
**********************************************************************/
OSType GetROSType(int index)
{
Str255 scratch;
long len;
OSType theType;
char* src;
char* dst;
long i;
if (GetRString(scratch,index)==nil)
return((OSType)0);
len = *scratch;
if (len > 4)
len = 4;
else if (len < 4)
{
for (i = len, dst = ((char*)&theType) + 3; i < 4; i++)
*dst-- = ' ';
}
for (i = 0, src = scratch + 1, dst = (char*)&theType; i < len; i++)
*dst++ = *src++;
return theType;
}
/************************************************************************
* RemoveChar - remove a char from some text
************************************************************************/
long RemoveChar(Byte c,UPtr text,long size)
{
UPtr from, to, limit;
for (to=text,limit=text+size;to<limit && *to!=c;to++);
if (to<limit)
for (from=to;from<limit;from++) if (*from!=c) *to++ = *from;
return(to-text);
}
/************************************************************************
* RemoveCharHandle - remove a character from a handle
************************************************************************/
long RemoveCharHandle(Byte c,UHandle text)
{
long len = GetHandleSize(text);
long newLen = RemoveChar(c,LDRef(text),len);
UL(text);
if (newLen<len) SetHandleBig(text,newLen);
return(newLen);
}
/**********************************************************************
*
**********************************************************************/
OSErr AddLf(Handle text)
{
UPtr spot, end;
long len = GetHandleSize_(text);
long newLen = len;
end = *text+len;
for (spot=*text;spot<end;spot++) if (*spot=='\015') newLen++;
if (newLen>len)
{
SetHandleBig(text,newLen);
if (MemError()) return(MemError());
end = *text+newLen;
for (spot=*text+len-1;spot>*text;spot--)
{
if (*spot=='\015') *--end = '\012';
*--end = *spot;
}
}
return(noErr);
}
/************************************************************************
* GetRStr - get a string from an 'STR ' resource
************************************************************************/
UPtr GetRStr(UPtr string,short id)
{
Handle strH = GetString(id);
if (strH)
{
PCopy(string,*strH);
ReleaseResource_(strH);
}
else
*string = 0;
return(string);
}
/**********************************************************************
* CountChars - count characters in a handle
**********************************************************************/
long CountChars(Handle text,Byte c)
{
long count = CountCharsPtr(LDRef(text),GetHandleSize(text),c);
UL(text);
return(count);
}
/**********************************************************************
* CountCharsPtr - count characters in a pointer
**********************************************************************/
long CountCharsPtr(UPtr ptr, long size, Byte c)
{
short n = 0;
UPtr end = ptr+size;
while (ptr<end) if (*ptr++==c) n++;
return(n);
}
/**********************************************************************
* HandleLineBreaks - figure out linebreaks in a block of text
**********************************************************************/
OSErr HandleLinebreaks(Handle text,long ***breaks,short inWidth)
{
Fixed width;
short n = 0;
UPtr ptr;
long len;
long textOffset;
long cum=0;
OSErr err;
if ((*breaks=NuHTempBetter(0))==nil) return(MemError());
if (!text || !(len=GetHandleSize(text))) return(noErr);
ptr = LDRef(text);
while(len)
{
width = inWidth<<16;
textOffset = 1;
StyledLineBreak(ptr, len, 0, len, 0, &width, &textOffset);
len -= textOffset;
ptr += textOffset;
cum += textOffset;
if (err=PtrPlusHand_(&cum,*breaks,sizeof(cum)))
return(err);
}
UL(text);
return(noErr);
}
/************************************************************************
* TransLitString - transliaterate with the default viewing table
************************************************************************/
void TransLitString(UPtr string)
{
short id = GetPrefLong(PREF_IN_XLATE);
Handle xlh;
UPtr end;
UPtr table;
if (id!=NO_TABLE && (xlh=GetResource_('taBL',id)))
{
table = LDRef(xlh);
for (end = string+*string;end>string;end--)
*end = table[*end];
UL(xlh);
}
}
/************************************************************************
* TransLitRes - translit, fetching table from a resource
************************************************************************/
void TransLitRes(UPtr string,long len,short resId)
{
Handle res = GetResource_('taBL',resId);
if (res)
{
TransLit(string,len,LDRef(res));
UL(res);
}
}
/************************************************************************
* TransLit - transliterate some chars
************************************************************************/
void TransLit(UPtr string,long len,UPtr table)
{
UPtr end = string+len;
for (end=string+len;string<end;string++)
*string = table[*string];
}
/**********************************************************************
* ScriptVar - return a script variable
**********************************************************************/
long ScriptVar(short selector)
{
long result = GetScriptVariable(smSystemScript,selector);
// apple won't tell us what the small system font is yet
if (!result && selector==smScriptSmallSysFondSize) result = 0x0001000A;
return(result);
}
#define StackSpot(s,n) ((UPtr)*s+sizeof(StackType)+(n)*(*stack)->elSize)
#pragma segment Stack
/**********************************************************************
* StackInit - initialize a stack
* First four bytes are the element size
* Second four bytes are the # of valid elements in the stack
**********************************************************************/
OSErr StackInit(long size,StackHandle *stack)
{
*stack = NuHTempBetter(sizeof(StackType));
if (!*stack) return(MemError());
(**stack)->elSize = size;
(**stack)->elCount = 0;
return(noErr);
}
/**********************************************************************
* StackPush - push an item onto a stack
**********************************************************************/
OSErr StackPush(void *what,StackHandle stack)
{
if (!stack) return fnfErr;
else
{
short nSpace = (GetHandleSize_(stack)-sizeof(StackType))/(*stack)->elSize;
ASSERT(nSpace>=(*stack)->elCount);
if (nSpace==(*stack)->elCount)
{
SetHandleBig_(stack,GetHandleSize_(stack)+20*(*stack)->elSize);
if (MemError()) return(MemError());
}
BMD(what,StackSpot(stack,(*stack)->elCount),(*stack)->elSize);
(*stack)->elCount++;
return(noErr);
}
}
/**********************************************************************
* StackQueue - queue an item onto a bottom of stack
**********************************************************************/
OSErr StackQueue(void *what,StackHandle stack)
{
if (!stack) return fnfErr;
else
{
short nSpace = (GetHandleSize_(stack)-sizeof(StackType))/(*stack)->elSize;
ASSERT(nSpace>=(*stack)->elCount);
if (nSpace==(*stack)->elCount)
{
SetHandleBig_(stack,GetHandleSize_(stack)+20*(*stack)->elSize);
if (MemError()) return(MemError());
}
BMD(StackSpot(stack,0),StackSpot(stack,1),(*stack)->elCount*(*stack)->elSize);
BMD(what,StackSpot(stack,0),(*stack)->elSize);
(*stack)->elCount++;
return(noErr);
}
}
/**********************************************************************
* StackPop - pop an item off a stack
**********************************************************************/
OSErr StackPop(void *into,StackHandle stack)
{
if (!stack || !(*stack)->elCount) return(fnfErr);
(*stack)->elCount--;
if (into) BMD(StackSpot(stack,(*stack)->elCount),into,(*stack)->elSize);
return(noErr);
}
/**********************************************************************
* StackTop - fetch top stack item
**********************************************************************/
OSErr StackTop(void *into,StackHandle stack)
{
if (!stack || !(*stack)->elCount) return(fnfErr);
if (into) BMD(StackSpot(stack,(*stack)->elCount-1),into,(*stack)->elSize);
return(noErr);
}
/**********************************************************************
* StackItem - fetch a stack item
**********************************************************************/
OSErr StackItem(void *into,short item,StackHandle stack)
{
if (!stack || !(*stack)->elCount || item>=(*stack)->elCount) return(fnfErr);
if (into) BMD(StackSpot(stack,item),into,(*stack)->elSize);
return(noErr);
}
/**********************************************************************
* StackCompact - get rid of waste space
**********************************************************************/
void StackCompact(StackHandle stack)
{
if (!stack) return;
SetHandleBig_(stack,(*stack)->elCount*(*stack)->elSize+sizeof(StackType));
}
/**********************************************************************
* StackStringFind - find an item in the stack
**********************************************************************/
short StackStringFind(PStr find,StackHandle stack)
{
Str255 s;
short item;
if (!stack) return -1;
for (item=(*stack)->elCount;item>0;)
{
item--;
StackItem(s,item,stack);
if (StringSame(s,find)) return item;
}
return -1;
}
#pragma segment AssocArray
#define AAElemSize(aa) ((*(aa))->dataSize+(*(aa))->keySize)
#define AAKeySpot(aa,indx) ((UPtr)(*(aa))+sizeof(AssocArray)+((indx)-1)*AAElemSize(aa))
#define AADataSpot(aa,indx) (AAKeySpot(aa,indx)+(*(aa))->keySize)
/************************************************************************
* AANew - create an associative array
************************************************************************/
AAHandle AANew(short keySize, short dataSize)
{
AAHandle aa = NewZHTB(AssocArray);
if (aa)
{
(*aa)->keySize = keySize;
(*aa)->dataSize = dataSize;
}
return(aa);
}
/************************************************************************
* AAAddItem - add an item to an associative array
************************************************************************/
OSErr AAAddItem(AAHandle aa, Boolean replace, PStr key, UPtr data)
{
short count = AACountItems(aa);
short spot = AAFindKey(aa,key);
Str255 lwrKey;
if (spot>0)
{
/* already exists */
if (!replace) return(1);
}
else
{
spot *= -1; /* spot now is the index of the item just after us */
SetHandleBig_(aa,GetHandleSize_(aa)+AAElemSize(aa));
if (MemError()) return(MemError());
if (spot && spot<=count) /* move old data */
BMD(AAKeySpot(aa,spot),AAKeySpot(aa,spot)+AAElemSize(aa),AAElemSize(aa)*(count-spot+1));
}
BMD(data,AADataSpot(aa,spot),(*aa)->dataSize);
PCopy(lwrKey,key); MyLowerStr(lwrKey);
BMD(lwrKey,AAKeySpot(aa,spot),(*aa)->keySize);
return(noErr);
}
/************************************************************************
* AAAddResItem - add an item to an associative array, using a resource for a key
************************************************************************/
OSErr AAAddResItem(AAHandle aa, Boolean replace, short keyId, UPtr data)
{
Str255 key;
GetRString(key,keyId);
return(AAAddItem(aa,replace,key,data));
}
/************************************************************************
* AADeleteKey - delete an item by key
************************************************************************/
OSErr AADeleteKey(AAHandle aa, PStr key)
{
short spot = AAFindKey(aa,key);
if (spot>0)
{
short count = AACountItems(aa);
if (spot<count)
BMD(AAKeySpot(aa,spot+1),AAKeySpot(aa,spot),AAElemSize(aa)*(count-spot));
SetHandleBig_(aa,GetHandleSize_(aa)-AAElemSize(aa));
return(noErr);
}
else
return(1); /* not found */
}
/************************************************************************
* AAFetchData - fetch data from an assoc array, by key
************************************************************************/
OSErr AAFetchData(AAHandle aa, PStr key, UPtr data)
{
short spot = AAFindKey(aa,key);
if (spot>0)
{
BMD(AADataSpot(aa,spot),data,(*aa)->dataSize);
return(noErr);
}
return(1); /* not found */
}
/************************************************************************
* AAFetchResData - fetch data from an assoc array, by a resource key
************************************************************************/
OSErr AAFetchResData(AAHandle aa, short keyId, UPtr data)
{
Str255 key;
return(AAFetchData(aa,GetRString(key,keyId),data));
}
/************************************************************************
* AAFetchIndData - fetch data from an assoc array, by index
************************************************************************/
OSErr AAFetchIndData(AAHandle aa, short index, UPtr data)
{
BMD(AADataSpot(aa,index),data,(*aa)->dataSize);
return(noErr);
}
/************************************************************************
* AAFetchIndKey - fetch key from an assoc array, by index
************************************************************************/
OSErr AAFetchIndKey(AAHandle aa, short index, PStr key)
{
BMD(AAKeySpot(aa,index),key,(*aa)->keySize);
return(noErr);
}
/************************************************************************
* AAFindKey - find a key in an associative array
* returns:
* positive: index of found item
* negative: index of smallest item > current item
************************************************************************/
short AAFindKey(AAHandle aa, PStr key)
{
short count = AACountItems(aa);
short first = 1;
short last = count;
short mid;
short greater = count+1;
short result;
Str255 lwrKey;
PCopy(lwrKey,key);
MyLowerStr(lwrKey);
LDRef(aa);
while (first<=last)
{
mid = (first+last)/2;
result = StringComp(lwrKey,AAKeySpot(aa,mid));
if (result==0)
{
greater = -mid; /* found it! */
break;
}
else if (result<0)
{
greater = mid;
last = mid-1;
}
else
first = mid+1;
}
UL(aa);
return(-greater);
}
/************************************************************************
* AACountItems - count the items in an associative array
************************************************************************/
short AACountItems(AAHandle aa)
{
if (!aa || !*aa) return(-1);
return((GetHandleSize_(aa)-sizeof(AssocArray))/((*aa)->keySize+(*aa)->dataSize));
}
/**********************************************************************
* AccuInit - initialize an accumulator
**********************************************************************/
OSErr AccuInit(AccuPtr a)
{
a->offset = 0;
a->size = 1 K;
a->data = NuHTempBetter(a->size);
return(a->err=MemError());
}
/**********************************************************************
* AccuInitWithHandle - make an accumulator out of an existing handle
**********************************************************************/
void AccuInitWithHandle(AccuPtr a,Handle h)
{
a->size = a->offset = GetHandleSize(h);
a->data = h;
}
/************************************************************************
* AccuWrite - write an accumulator to a file
************************************************************************/
OSErr AccuWrite(AccuPtr a,short refN)
{
long count = a->offset;
OSErr err;
if (!count) return(noErr);
err = AWrite(refN,&count,LDRef(a->data));
UL(a->data);
return(err);
}
/************************************************************************
* AccuFTell - tell the position of the file pointer, assuming that the bytes
* in the accumulator had been written
************************************************************************/
long AccuFTell(AccuPtr a,short refN)
{
long spot;
GetFPos(refN,&spot);
return(spot+a->offset);
}
/************************************************************************
* AccuFSeek - move the pointer back to a given spot
************************************************************************/
OSErr AccuFSeek(AccuPtr a,short refN,long spot)
{
long curSpot = AccuFTell(a,refN);
if (curSpot-spot <= a->offset)
{
a->offset -= curSpot - spot;
return(0);
}
else
{
a->offset = 0;
return(SetFPos(refN,fsFromStart,spot));
}
}
/**********************************************************************
*
**********************************************************************/
void AccuTrim(AccuPtr a)
{
OSErr err;
if (!a->data && (err=AccuInit(a))) return;
#ifdef DEBUG
if (RunType!=Production)
{
if (a->size!=GetHandleSize(a->data) || a->size<a->offset)
{
Dprintf("\po %d s %d hs %d h %x",a->offset,a->size,GetHandleSize(a->data),a->data);
}
}
#endif
SetHandleBig(a->data,a->offset);
a->size = a->offset;
}
/**********************************************************************
*
**********************************************************************/
OSErr AccuAddChar(AccuPtr a,Byte c)
{
return(AccuAddPtr(a,&c,1));
}
/**********************************************************************
*
**********************************************************************/
OSErr AccuAddLong(AccuPtr a,uLong longVal)
{
return(AccuAddPtr(a,&longVal,sizeof(longVal)));
}
/**********************************************************************
* AccuAddPtr64 - add some data, base-64 encoded
**********************************************************************/
OSErr AccuAddPtrB64(AccuPtr a,void *bytes, long len)
{
long newLen = len*4/3+4;
Handle encoded = NuHandle(newLen);
OSErr err;
if (!encoded) return MemError();
Encode64DataPtr(LDRef(encoded),&newLen,bytes,len);
ASSERT(newLen<=len*4/3+4);
err = AccuAddPtr(a,*encoded,newLen);
ZapHandle(encoded);
return err;
}
/**********************************************************************
* AccuAddTrPtr - add to an accumulator, but translate first
**********************************************************************/
OSErr AccuAddTrPtr(AccuPtr a,void *bytes, long len,UPtr from,UPtr to)
{
OSErr err;
// translate
TrLo(bytes,len,from,to);
// add
err = AccuAddPtr(a,bytes,len);
// untranslate
TrLo(bytes,len,to,from);
return err;
}
/**********************************************************************
*
**********************************************************************/
OSErr AccuAddPtr(AccuPtr a,void *bytes, long len)
{
OSErr err;
if (!a->data && (err=AccuInit(a))) return(err);
#ifdef DEBUG
if (RunType!=Production)
{
if (a->size!=GetHandleSize(a->data) || a->size<a->offset)
{
Dprintf("\po %d s %d hs %d h %x",a->offset,a->size,GetHandleSize(a->data),a->data);
}
}
#endif
if (a->offset+len>a->size)
{
a->size += len + 4 K;
SetHandleBig_(a->data,a->size);
if (MemError()) return(a->err=MemError());
}
BMD(bytes,*a->data+a->offset,len);
a->offset += len;
return(noErr);
}
/**********************************************************************
* AccuAddSortedLong - add a long to an accumulator, but keep it sorted
**********************************************************************/
OSErr AccuAddSortedLong(AccuPtr a,long addVal)
{
OSErr err = AccuAddPtr(a,&addVal,sizeof(addVal));
if (!err)
{
long *start = *a->data; // start of data
long *spot = *a->data+a->offset-sizeof(addVal); // spot we added addVal
long *newSpot = spot-1; // spot addVal really belongs
// if the value before us is bigger than we are, we'll need to move
if (newSpot>=start && *newSpot > addVal)
{
// keep going until the value we're looking at is
// not greater than the value we're putting in
while (newSpot>=start && *newSpot>addVal) newSpot--;
// Note: if we wanted to eliminate duplicates, here is the spot
// if (newSpot>=start && *newSpot==addVal)
// {
// a->offset -= sizeof(addVal);
// return noErr;
// }
// newSpot now points one BEFORE the proper spot; increment
newSpot++;
// move everything above us to make room
BMD(newSpot,newSpot+1,sizeof(addVal)*(spot-newSpot));
// and put us into place
*newSpot = addVal;
}
}
return err;
}
/**********************************************************************
*
**********************************************************************/
OSErr AccuAddRes(AccuPtr a,short res)
{
Str255 s;
GetRString(s,res);
return(AccuAddStr(a,s));
}
/**********************************************************************
* AccuAddHandleToPtr - copy some data into a handle and add the handle to the accumulator
**********************************************************************/
OSErr AccuAddHandleToPtr(AccuPtr a,UPtr data,long size)
{
Handle h = NuDHTempBetter(data,size);
OSErr err;
if (h)
{
err = AccuAddPtr(a,(void*)&h,sizeof(h));
if (err) ZapHandle(h);
}
else err = MemError();
return(err);
}
/**********************************************************************
* AccuAddTrHandle - add a translated handle
**********************************************************************/
OSErr AccuAddTrHandle(AccuPtr a,Handle data,UPtr from, UPtr to)
{
OSErr err;
Tr(data,from,to);
err = AccuAddHandle(a,data);
Tr(data,to,from);
return err;
}
/**********************************************************************
*
**********************************************************************/
OSErr AccuAddHandle(AccuPtr a,Handle data)
{
OSErr err;
long len;
if (!a->data && (err=AccuInit(a))) return(err);
ASSERT(data);
if (!data) return noErr;
#ifdef DEBUG
if (RunType!=Production)
{
if (a->size!=GetHandleSize(a->data) || a->size<a->offset)
{
Dprintf("\po %d s %d hs %d h %x",a->offset,a->size,GetHandleSize(a->data),a->data);
}
}
#endif
len = GetHandleSize(data);
if (a->offset+len>a->size)
{
a->size += len + 4 K;
SetHandleBig_(a->data,a->size);
if (MemError()) return(a->err=MemError());
}
BMD(*data,*a->data+a->offset,len);
a->offset += len;
return(noErr);
}
/**********************************************************************
*
**********************************************************************/
OSErr AccuAddFromHandle(AccuPtr a,Handle data,long offset,long len)
{
OSErr err;
if (!a->data && (err=AccuInit(a))) return(err);
if(len < 0) len = GetHandleSize(data);
if(len < 0) return len;
#ifdef DEBUG
if (RunType!=Production)
{
if (a->size!=GetHandleSize(a->data) || a->size<a->offset)
{
Dprintf("\po %d s %d hs %d h %x",a->offset,a->size,GetHandleSize(a->data),a->data);
}
}
#endif
if (a->offset+len>a->size)
{
a->size += len + 4 K;
SetHandleBig_(a->data,a->size);
if (MemError()) return(a->err=MemError());
}
BMD(*data + offset,*a->data+a->offset,len);
a->offset += len;
return(noErr);
}
/************************************************************************
* AccuFindPtr - find a pointer in an accumulator
************************************************************************/
long AccuFindPtr(AccuPtr a, UPtr stuff, short len)
{
UPtr spot;
UPtr end;
if (!a->data || !len) return -1;
spot = *a->data;
end = spot+a->offset-len;
for (;spot<=end;spot+=len)
if (!memcmp(spot,stuff,len)) return spot-*a->data;
return -1;
}
/************************************************************************
* AccuFindLong - find a long in an accumulator; returns an index
************************************************************************/
long AccuFindLong(AccuPtr a, uLong theLong)
{
uLong *spot;
uLong *end;
if (!a->data) return -1;
spot = (uLong*)*a->data;
end = (uLong*)spot+(a->offset-sizeof(uLong))/sizeof(uLong);
for (;spot<=end;spot++)
if (*spot==theLong) return spot-(uLong*)*a->data;
return -1;
}
/************************************************************************
* DecodeB64Accu - decode a base64 accumulator
************************************************************************/
short DecodeB64Accu(AccuPtr a,Boolean isText)
{
Dec64 d64;
Handle data = NuHandle((3*a->offset)/4+4);
long len;
long result;
if (!data) return MemError();
if (!a->offset) return noErr;
Zero(d64);
result = Decode64(LDRef(a->data),a->offset,LDRef(data),&len,&d64,isText);
if ((d64.decoderState+d64.padCount)%4) result++;
if (!result)
{
a->offset = len;
BMD(*data,*a->data,len);
}
ZapHandle(data);
UL(a->data);
return(result);
}
/**********************************************************************
*
**********************************************************************/
OSErr AccuInsertChar(AccuPtr a,Byte c,long offset)
{
return(AccuInsertPtr(a,&c,1,offset));
}
/**********************************************************************
*
**********************************************************************/
OSErr AccuInsertPtr(AccuPtr a,UPtr bytes, long len, long offset)
{
OSErr err;
if (!a->data && (err=AccuInit(a))) return(err);
#ifdef DEBUG
if (RunType!=Production)
{
if (a->size!=GetHandleSize(a->data) || a->size<a->offset)
{
Dprintf("\po %d s %d hs %d h %x",a->offset,a->size,GetHandleSize(a->data),a->data);
}
}
#endif
if (a->offset+len>a->size)
{
a->size += len + 4 K;
SetHandleBig_(a->data,a->size);
if (MemError()) return(a->err=MemError());
}
BMD(*a->data+offset,*a->data+offset+len,a->offset-offset);
BMD(bytes,*a->data+offset,len);
a->offset += len;
return(noErr);
}
/**********************************************************************
* Strip 'n' bytes off of the end of an accumulator
**********************************************************************/
OSErr AccuStrip (AccuPtr a, long num)
{
OSErr theError;
if (!a->data && (theError=AccuInit(a))) return(theError);
a->offset = a->offset > num ? a->offset - num : 0;
return (noErr);
}
/************************************************************************
* Long2Hex - write a long in 8 hex bytes
************************************************************************/
PStr Long2Hex(PStr hex, long aLong)
{
Bytes2Hex((void*)&aLong,sizeof(aLong),(void*)(hex+1));
*hex = 8;
return(hex);
}
char *hexdig = "0123456789ABCDEF";
/************************************************************************
* Bytes2Hex - encode some bytes in hex
************************************************************************/
UPtr Bytes2Hex(UPtr bytes, long size,UPtr hex)
{
Byte c;
UPtr spot = hex;
while (size--)
{
c = *bytes++;
*spot++ = hexdig[(c>>4)&0xf];
*spot++ = hexdig[c&0xf];
}
return(hex);
}
/************************************************************************
* IsHexDig - is a char a hex digit?
************************************************************************/
Boolean IsHexDig(Byte c)
{
if (islower(c)) c = toupper(c);
return ('0'<=c && c<='9' || 'A'<=c && c<='F');
}
#define Hex2Nyb(c) (c<='9'?c-'0':(c>='a'?c-'a'+10:c-'A'+10))
/************************************************************************
* Hex2Bytes - decode some bytes from hex
************************************************************************/
OSErr Hex2Bytes(UPtr hex,long size,UPtr bytes)
{
Byte hi, lo;
while (size>=2)
{
hi = Hex2Nyb(*hex);
hex++;
lo = Hex2Nyb(*hex);
hex++;
*bytes++ = (hi<<4) | lo;
size -= 2;
}
return(noErr);
}
#pragma segment Main
/************************************************************************
* MyOSEventAvail - OSEventAvail with resource chain protection
************************************************************************/
#undef OSEventAvail
Boolean MyOSEventAvail(short mask,EventRecord *event)
{
Boolean result;
MightSwitch();
result = EventAvail(mask,event);
AfterSwitch();
return (result);
}
#define OSEventAvail MyOSEventAvail
/************************************************************************
* SafeToAllocate - is it safe to allocate this much memory?
************************************************************************/
Boolean SafeToAllocate(long size)
{
static uLong allocated;
if (size > 4 K || allocated+50 K > LastContigSpace)
{
allocated = 0;
PurgeSpace(&LastTotalSpace,&LastContigSpace);
}
allocated += size;
if (LastContigSpace && size+1 K K > LastContigSpace) return(False);
if (!MemLastFailed) return(True);
if (size>MemLastFailed) return(False);
return(True);
}
/************************************************************************
* NuHTempOK - New Handle, prefer my heap but temp mem ok
************************************************************************/
void *NuHTempOK(long size)
{
Handle h;
RANDOM_FAILURE;
if (!SafeToAllocate(size) || !(h=NuHandle(size))) h = NuHTempBetter(size);
return(h);
}
/**********************************************************************
* NuDHTempBetter - allocate a handle and copy data into it
**********************************************************************/
void *NuDHTempBetter(void *data, long size)
{
Handle h;
RANDOM_FAILURE;
h = NuHTempBetter(size);
if (h) BMD(data,*h,size);
return(h);
}
/**********************************************************************
* NuDHTempOK - allocate a handle and copy data into it
**********************************************************************/
void *NuDHTempOK(void *data, long size)
{
Handle h;
RANDOM_FAILURE;
h = NuHTempOK(size);
if (h) BMD(data,*h,size);
return(h);
}
/************************************************************************
* NuHTempBetter - New Handle, prefer temp mem
************************************************************************/
void *NuHTempBetter(long size)
{
Handle theMem;
OSErr err;
RANDOM_FAILURE;
#ifdef DEBUG
if (BUG9) return(NuHandle(size));
#endif
if (size>1 K) CompactTempZone();
theMem = TempNewHandleGlue(size,&err);
if (!theMem) theMem = NuHandle(size);
else if (size>1 K) MoveHHi(theMem);
return(theMem);
}
/**********************************************************************
*
**********************************************************************/
void *TempNewHandleGlue(long size,OSErr *err)
{
return(TempNewHandle(size,err));
}
/**********************************************************************
* ZeroHandle - clear the contents of a handle
**********************************************************************/
void *ZeroHandle(void*hand)
{
Handle h=hand;
long len;
if (h && *h)
{
len = GetHandleSize(h);
WriteZero(LDRef(h),len);
UL(h);
}
return(h);
}
/************************************************************************
* CompactTempZone - compact the temp memory zone
************************************************************************/
void CompactTempZone(void)
{
}
/************************************************************************
* NewIOBHandle - New IO buffer, Handle
************************************************************************/
Handle NewIOBHandle(long min,long max)
{
Handle theMem;
CompactTempZone();
do
{
theMem = NuHTempOK(max);
max/=2;
}
while (!theMem && max>=min);
if (theMem) MoveHHi(theMem);
return(theMem);
}
/************************************************************************
* GetTableCName - get the canonical name of a table
************************************************************************/
Boolean GetTableCName(short tid,PStr name)
{
UHandle res;
short spot, end;
short idFromResource;
short rIndex;
for (rIndex=1;res=GetIndResource_('euTM',rIndex);rIndex++)
{
HNoPurge_(res);
end = GetHandleSize_(res);
spot = 0;
for (spot=0;spot<end;spot+=(*res)[spot+2]+3)
{
idFromResource = (*res)[spot]*256 + (*res)[spot+1]; /* read id */
if (idFromResource==tid) /* found it */
{
PCopy(name,(*res)+spot+2); /* copy name */
HPurge(res);
return(True);
}
}
HPurge(res);
}
return(False);
}
/************************************************************************
* GetTableID - get the id of a named table
************************************************************************/
Boolean GetTableID(PStr name,short *tid)
{
UHandle res;
short spot, end;
Str63 nameFromResource;
short rIndex;
for (rIndex=1;res=GetIndResource_('euTM',rIndex);rIndex++)
{
HNoPurge_(res);
end = GetHandleSize_(res);
spot = 0;
for (spot=0;spot<end;spot+=(*res)[spot+2]+3)
{
PCopy(nameFromResource,(*res)+spot+2);
if (StringSame(nameFromResource,name))
{
*tid = (*res)[spot]*256 + (*res)[spot+1]; /* read id */
HPurge(res);
return(True);
}
}
HPurge(res);
}
return(False);
}
#pragma segment Main
/************************************************************************
* EventPending - is an event waiting for us?
************************************************************************/
Boolean EventPending(void)
{
EventRecord event;
static uLong ticks;
if (TickCount()-ticks <= 8) return(False);
else
{
ticks = TickCount();
return(OSEventAvail(mUpMask|mDownMask|keyDownMask|updateMask|activMask|osMask,&event));
}
}
#ifdef DEBUG
#undef UseResFile
void MyUseResFile(short refN)
{
FSSpec oldSpec, newSpec;
short oldRefN;
if (BUG8)
{
oldRefN = CurResFile();
if (oldRefN!=refN)
{
Zero(oldSpec);
Zero(newSpec);
GetFileByRef(refN,&newSpec);
GetFileByRef(oldRefN,&oldSpec);
Dprintf("\pUseResFile <20>%p<> -> <20>%p<>;g",oldSpec.name,newSpec.name);
}
}
UseResFile(refN);
}
/************************************************************************
* RESCHK - verify that a resource is a resource
************************************************************************/
void RESCHK(OSType type, short resId);
void RESCHK(OSType type, short resId)
{
Handle resH = GetResource_(type,resId);
short flags;
if (resH)
{
flags = HGetState(resH);
ASSERT(flags & 32);
}
}
#endif
#define gestaltGatewayExternal 'VIGE'
/************************************************************************
* IsVICOM - return true if VICOM Internet gateway is running
************************************************************************/
Boolean IsVICOM(void)
{
long interfaceVICOM = 0;
if (Gestalt(gestaltGatewayExternal, &interfaceVICOM) == noErr) return (interfaceVICOM!=0);
else return (false);
}
/************************************************************************
* MyRemoveResource - fix bug in RemoveResource:
* it doesn't work if CurResFile is not set to the resource's resource file
************************************************************************/
#undef RemoveResource
OSErr MyRemoveResource(Handle h)
{
short useFile,saveFile = CurResFile();
OSErr err = noErr;
if (h)
{
useFile = HomeResFile(h);
if (!(err = ResError()))
{
UseResFile(useFile);
RemoveResource(h);
err = ResError();
UseResFile(saveFile);
}
}
return err;
}
/************************************************************************
* FinderDragVoodoo - hack around a Finder 8.1 (at least) bug
************************************************************************/
OSErr FinderDragVoodoo(DragReference drag)
{
// This magic incantation seems to avoid a bug in (at least) the 8.1 finder
// which seems to sometimes go boom if the first drag it sees is non-TEXT,
// promised, sender-only, and not saved.
return(AddDragItemFlavor(drag, 1L, 'xyzy', "", 0, flavorNotSaved));
}
/**********************************************************************
* ShortCompare - compare two shorts, return 0 if equal, -1 if value1 < value2, 1 if value1 2 value2
**********************************************************************/
short ShortCompare(short value1,short value2)
{
if (value1 == value2) return 0;
if (value1 < value2) return -1;
return 1;
}
/************************************************************************
* DateCompare - compare two dates
* return 0 if equal, -1 if date1 < date2, 1 if date1 2 date2
* Doesn't compare time portion of DateTimeRec
************************************************************************/
short DateCompare(DateTimeRec *date1,DateTimeRec *date2)
{
short result;
if (!(result=ShortCompare(date1->year,date2->year)))
if (!(result=ShortCompare(date1->month,date2->month)))
result=ShortCompare(date1->day,date2->day);
return result;
}
/************************************************************************
* TimeCompare - compare two dates including time
* return 0 if equal, -1 if date1 < date2, 1 if date1 2 date2
************************************************************************/
short TimeCompare(DateTimeRec *date1,DateTimeRec *date2)
{
short result;
if (!(result=DateCompare(date1,date2)))
if (!(result=ShortCompare(date1->hour,date2->hour)))
if (!(result=ShortCompare(date1->minute,date2->minute)))
result=ShortCompare(date1->second,date2->second);
return result;
}
//#define IsColorWin(win) \
// (ThereIsColor && \
// (((GrafPtr)(win))->portBits.rowBytes & 0xC000) && \
// ((**((CGrafPtr)(win))->portPixMap).pixelSize > 1))
Boolean IsColorWin(WindowPtr winWP)
{
MyWindowPtr win = GetWindowMyWindowPtr (winWP);
CGrafPtr thePort = GetWindowPort (winWP);
Boolean isThere; // well?
isThere = false;
if (ThereIsColor && thePort)
isThere = GetPortPixelDepth(thePort) > 1;
return (isThere);
}
/************************************************************************
* GetOSVersion - get OS version in BCD format: 9.01 = 0x0901
************************************************************************/
short GetOSVersion(void)
{
static short sysVers;
long result;
if (!sysVers)
{
if (!Gestalt(gestaltSystemVersion, &result))
sysVers = result;
}
return (sysVers);
}
/************************************************************************
* HaveOSX - are we running Mac OS X or bettter
************************************************************************/
Boolean HaveOSX(void)
{
return GetOSVersion() >= 0x1000;
}
#ifdef DEBUG
#undef GetResource
#undef Get1Resource
#undef GetNamedResource
#undef Get1NamedResource
#undef GetMenu
#undef Get1IndResource
#undef GetIndResource
Handle NoSLGetResource(OSType type,short id) {Handle h;SLDisable();h=GetResource(type,id);SLEnable();return h;}
Handle NoSLGet1Resource(OSType type,short id) {Handle h;SLDisable();h=Get1Resource(type,id);SLEnable();return h;}
Handle NoSLGet1IndResource(OSType type,short ind) {Handle h;SLDisable();h=Get1IndResource(type,ind);SLEnable();return h;}
Handle NoSLGetIndResource(OSType type,short ind) {Handle h;SLDisable();h=GetIndResource(type,ind);SLEnable();return h;}
Handle NoSLGetNamedResource(OSType type,PStr name) {Handle h;SLDisable();h=GetNamedResource(type,name);SLEnable();return h;}
Handle NoSLGet1NamedResource(OSType type,PStr name) {Handle h;SLDisable();h=Get1NamedResource(type,name);SLEnable();return h;}
MenuHandle NoSLGetMenu(short id) {MenuHandle h;SLDisable();h=GetMenu(id);SLEnable();return h;}
MenuHandle NoSLGetMHandle(short id) {MenuHandle h;SLDisable();h=GetMenuHandle(id);SLEnable();return h;}
#endif