/* 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 #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 len) { Byte save = string[len]; string[len] = 'É'; *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 (cWidthwidth); 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;imessage & 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 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;whichSun 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,"¥") && *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,"¥") && *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;i0) { 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 (numcount+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>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 (;thisleft+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 (; startid && 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;iresEnd),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;tolen) { 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 (ptrstring;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;stringelSize) #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 (spot0) { 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->sizeoffset) { 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->sizeoffset) { 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->sizeoffset) { 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->sizeoffset) { 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->sizeoffset) { 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 Ò%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