/* 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 "ends.h" #include "buildversion.h" #define FILE_NUM 12 /* Copyright (c) 1990-1992 by the University of Illinois Board of Trustees */ /********************************************************************** * initialization and cleanup **********************************************************************/ #pragma segment Ends typedef struct { Str31 *badNames; short badCount; Str31 newText; #ifdef TWO Str31 otherText; #endif #ifdef IMAP Str31 thisBoxText; #endif short level; CInfoPBRec hfi; Str63 hfi_namePtr; #ifdef IMAP Str63 enclosingFolderName; #endif } BoxFolderDesc, *BoxFolderDescPtr; #ifdef IMAP typedef struct {FSSpec spec; Boolean isDir; Boolean hasUnread; Boolean skipIt; Boolean isIMAPpers; Boolean moveToTop; long imapAttributes;} NameType; #else typedef struct {FSSpec spec; Boolean isDir; Boolean hasUnread; Boolean skipIt;} NameType; #endif void ZapResMenu(short id); Boolean HaveOptiMEM(void); void doInitDEF(short resId,UniversalProcPtr upp,OSType type); void SettingsInit(FSSpecPtr spec,Boolean system,Boolean changeUserState); void OpenSettingsFile(FSSpecPtr spec); void PutUpMenus(void); void CreateBoxes(void); void SetupInsurancePort(void); void SetRunType(void); Boolean ModernSystem(void); void BoxFolder(short vRef,long dirId,MenuHandle *menus,BoxFolderDescPtr bfd,Boolean *anyUnread,Boolean appending,Boolean isIMAP); void RemoveBoxMenus(void); void BuildMarginMenu(void); #ifdef NEVER void MakeHmnusPurge(void); void TrashHmnu(void); #endif void OpenPlugIns(void); void MarkHavingUnread(MenuHandle mh, short item); Boolean UsingNewTables(void); void AwaitStartupAE(void); void AddHelpMenuItems(void); void AddWSMenuItems(void); void Splash(void); void MakeWordChars(void); void ConvertSignature(void); short PlugInDir(short vRef,long dirId); void GenAliasList(void); void BoxNamesSort(NameType **names); int NameCompare(NameType *n1, NameType *n2); void NameSwap(NameType *n1, NameType *n2); void MakeUserFindSettings(FSSpecPtr spec); Boolean MakeUserFindSettingsStd(FSSpecPtr spec); void GetAndInsertHier(short menu); #ifdef IMAP Boolean InferUnread(CInfoPBRec *hfi, Boolean imap); #else Boolean InferUnread(CInfoPBRec *hfi); #endif void CheckAttachFolder(void); void AddRes2HelpMenu(MenuHandle hm,Handle resH); OSErr AddIconsToColorMenu(MenuHandle mh); OSErr LogPlugins(void); void SaneSettings(FSSpecPtr spec); void HuntSpellswell(void); Boolean HaveOT(void); void CreateItemsFolder(void); void CreateSpoolfolder(void); void CreateMailFolder(void); void CreatePartsfolder(void); void CreateCachefolder(void); #ifdef BATCH_DELIVERY_ON void CreateDeliveryfolder(void); #endif OSErr LocalizeFiles(void); void MoveMailboxesToMailFolder(void); void ReloadStdSizes(void); #ifdef LABEL_ICONS OSErr RefreshLabelIcon(short item,RGBColor *color); void UpdateLabelControls(void); #endif #ifdef USECMM Boolean HaveCMM(); #endif Boolean HaveVM(void); Boolean FallbackSettings(FSSpecPtr spec); OSErr LocalizeRename(FSSpecPtr spec,short id); static void InitIntScript(void); void ScanPrefs(void); OSErr RegisterEudoraComponentFiles(void); // In peteglue.c void AddCustomSortItems(void); void InitCDEF(short resId,ControlDefProcPtr proc); void InitLDEF(short resId,ListDefProcPtr proc); pascal OSStatus ControlCNTLToCollection (Rect *bounds, SInt16 value, Boolean visible, SInt16 max, SInt16 min, SInt16 procID, SInt32 refCon, ConstStr255Param title, Collection collection); #pragma segment Main pascal void PeteCalled(Boolean entry); pascal void PeteCalled(Boolean entry) {MemCanFail = entry;} Boolean OkSettingsFileSpot(FSSpecPtr spec); static void PrefillSettings(void); static OSErr FindEudoraFolder(FSSpecPtr spec,StringPtr folder,short vRefNum,OSType folderType); ModalFilterUPP DlgFilterUPP; PETEGraphicHandlerProcPtr GraphicHandlers[] = { PersGraphic, FileGraphic, HorizRuleGraphic, TableGraphic, nil }; #pragma segment Ends /********************************************************************** * Initialize - set up my stuff as well as the Mac managers **********************************************************************/ void Initialize(void) { SInt32 gestaltResult; #ifdef PEE OSErr err; short i; #endif VM = HaveVM(); MacInitialize(20,40 K); /* initialize mac managers */ SetQDGlobalsRandomSeed(LocalDateTime()); // Check for Appearance Extension if (err = Gestalt(gestaltAppearanceAttr, &gestaltResult)) DieWithError(NO_APPEARANCE, err); /* MJN *//* make sure the library is REALLY loaded and linked */ if ((long)RegisterAppearanceClient == kUnresolvedCFragSymbolAddress) DieWithError(NO_APPEARANCE, cfragNoSymbolErr); gAppearanceIsLoaded = true; // Okay, so we didn't die on loading AM gGoodAppearance = !Gestalt(gestaltAppearanceVersion,&gestaltResult); g16bitSubMenuIDs = gestaltResult >= 0x0110; gBetterAppearance = gestaltResult >= 0x0110; gBestAppearance = gestaltResult >= 0x0114; gMaxBoxLevels = g16bitSubMenuIDs ? (BOX_MENU_LIMIT-BOX_MENU_START)/2 : OLD_MAX_BOX_LEVELS; gHave85MenuMgr = !Gestalt(gestaltMenuMgrAttr,&gestaltResult) && gestaltResult&gestaltMenuMgrPresent && (long)EnableMenuItem != kUnresolvedCFragSymbolAddress; SetRunType(); /* figure out what kind of run this is */ for (i=0;istate); #endif if (!JunkPrefDeadPluginsWarning() && ETLCountTranslatorsLo(EMSF_JUNK_MAIL,EMS_ModePaid)>ETLCountTranslators(EMSF_JUNK_MAIL)) JunkDownDialog(); } /************************************************************************ * ScanPrefs - scan the prefs folder for "interesting" items ************************************************************************/ void ScanPrefs(void) { Str63 name; CInfoPBRec hfi; short vRef; long dirId; Zero(hfi); hfi.hFileInfo.ioNamePtr = name; hfi.hFileInfo.ioFDirIndex = 0; if (!FindFolder(kOnSystemDisk,kPreferencesFolderType,False,&vRef,&dirId)) // keep going until we run out of files or find everything #ifdef SPEECH_ENABLED while((!AutoDoubler || !PrefsPlugIns || !*TCPprefFileSpec.name || !*PPPprefFileSpec.name || !*SpeechPrefFileSpec.name) && !DirIterate(vRef,dirId,&hfi)) #else while((!AutoDoubler || !PrefsPlugIns || !*TCPprefFileSpec.name || !*PPPprefFileSpec.name) && !DirIterate(vRef,dirId,&hfi)) #endif switch(hfi.hFileInfo.ioFlFndrInfo.fdCreator) { case TCP_PREF_FILE_CREATOR: // ot tcp prefs file if (hfi.hFileInfo.ioFlFndrInfo.fdType == TCP_PREF_FILE_TYPE) SimpleMakeFSSpec(vRef,dirId,name,&TCPprefFileSpec); break; case PPP_PREF_FILE_CREATOR: if (hfi.hFileInfo.ioFlFndrInfo.fdType == PPP_PREF_FILE_TYPE) SimpleMakeFSSpec(vRef,dirId,name,&PPPprefFileSpec); break; case CREATOR: // one of ours PrefsPlugIns = True; break; case 'DDAP': // Autodoubler if (hfi.hFileInfo.ioFlFndrInfo.fdType=='ADDA') AutoDoubler = SyncRW = True; break; #ifdef SPEECH_ENABLED case SPEECH_PREF_FILE_CREATOR: // Speech Preferences if (hfi.hFileInfo.ioFlFndrInfo.fdType == SPEECH_PREF_FILE_TYPE) SimpleMakeFSSpec (vRef, dirId, name, &SpeechPrefFileSpec); break; #endif } } /************************************************************************ * ReloadStdSizes - reload standard font size array ************************************************************************/ void ReloadStdSizes(void) { short size; short i; short narml = FontSize; short finnarml = FixedSize; ZapHandle(StdSizes); ZapHandle(FixedSizes); StdSizes = NuHandle(0); if (!StdSizes) DieWithError(MEM_ERR,MemError()); // yeah, right FixedSizes = NuHandle(0); if (!FixedSizes) DieWithError(MEM_ERR,MemError()); // yeah, right for (i=1;;i++) if (size=GetRLong(StdSizesStrn+i)) { if (size==narml) narml = 0; if (size==finnarml) finnarml = 0; if (size>narml && narml) { PtrPlusHand(&narml,(Handle)StdSizes,sizeof(short)); narml = 0; } if (size>finnarml && finnarml) { PtrPlusHand(&finnarml,(Handle)FixedSizes,sizeof(short)); finnarml = 0; } PtrPlusHand(&size,(Handle)StdSizes,sizeof(short)); PtrPlusHand(&size,(Handle)FixedSizes,sizeof(short)); } else break; } #ifdef USECMM /********************************************************************** * HaveCMM - do we have the contextual memory manager? **********************************************************************/ Boolean HaveCMM() { #if !TARGET_RT_MAC_CFM return true; #else return (InitContextualMenus != (void *)kUnresolvedCFragSymbolAddress) && (IsShowContextualMenuClick != (void *)kUnresolvedCFragSymbolAddress) && (ContextualMenuSelect != (void *)kUnresolvedCFragSymbolAddress) && (ProcessIsContextualMenuClient != (void *)kUnresolvedCFragSymbolAddress); #endif } #endif /********************************************************************** * HaveVM - do we have VM? **********************************************************************/ Boolean HaveVM(void) { long value; if (Gestalt(gestaltVMAttr, &value)) return(False); return((value&1)!=0); } /********************************************************************** * HaveOT - OpenTransport is lurking **********************************************************************/ Boolean HaveOT(void) { long result; OSErr err = Gestalt(gestaltOpenTpt, &result); return(!err && (result & gestaltOpenTptPresentMask) && (result & gestaltOpenTptTCPPresentMask)); } /********************************************************************** * HaveOptiMEM - OptiMEM is lurking **********************************************************************/ Boolean HaveOptiMEM(void) { long result; OSErr err = Gestalt('xMe0', &result); return(!err); } /************************************************************************ * MakeWordChars - set the IsWordChar array ************************************************************************/ void MakeWordChars(void) { short i; for (i=0;i<256;i++) IsWordChar[i] = (CharacterType(((Ptr)&i)+1,0,nil)&0xf)!=0; } #ifdef TWO DialogPtr DBSplash; void ChangeTEFont(TEHandle teh,short font,short size); /************************************************************************ * Splash - show the splash box ************************************************************************/ void Splash(void) { MyWindowPtr dgWin; DialogPtr dg; Str255 versionString, regInfo; Handle h; short t; Rect r,portR; VersString(versionString); AboutRegisterString(regInfo); MyParamText(versionString,regInfo,"",""); SetDialogFont(SmallSysFontID()); dgWin = GetNewMyDialog(ABOUT_ALRT,nil,nil,InFront); ConfigFontSetup(dgWin); SetDialogFont(0); if (dgWin) { dg = GetMyWindowDialogPtr (dgWin); DBSplash = (void*)dg; for (t=CountDITL(dg)-1;t>=12;t--) HideDialogItem(dg,t); GetDialogItem(dg,5,&t,&h,&r); GetPortBounds(GetDialogPort(dg),&portR); SizeWindow(GetDialogWindow(dg),portR.right-portR.left,r.bottom+1,False); ShowWindow(GetDialogWindow(dg)); UpdateMyWindow(GetDialogWindow(dg)); } } #endif /************************************************************************ * ConvertSignature - move signature from Eudora Settings to external file ************************************************************************/ void ConvertSignature(void) { Str31 s; FSSpec spec; Handle sig; long newDirId; if (!DirCreate(Root.vRef,Root.dirId,GetRString(s,SIG_FOLDER),&newDirId)) { /* * created directory; read old sig */ GetRString(s,SETTINGS_FILE); FSMakeFSSpec(Root.vRef,Root.dirId,s,&spec); if (Snarf(&spec,&sig,0)) sig = NuHandle(0); /* * create new sig file */ FSMakeFSSpec(Root.vRef,newDirId,GetRString(s,SIGNATURE),&spec); Blat(&spec,sig,False); #ifdef TWO FSMakeFSSpec(Root.vRef,newDirId,GetRString(s,ALT_SIG),&spec); SetHandleBig_(sig,0); Blat(&spec,sig,False); #endif ZapHandle(sig); } else { if (fnfErr==SigSpec(&spec,0)) FSpCreate(&spec,CREATOR,'TEXT',smSystemScript); #ifdef TWO if (fnfErr==SigSpec(&spec,1)) FSpCreate(&spec,CREATOR,'TEXT',smSystemScript); #endif } // Convert old sig preference if (CountStrn(PREF2_STRN)>16,GetComponentVersion(PETE)&0xffff); PCat(versionString,editor); } #endif return(versionString); } /************************************************************************ * SettingsInit - Initialize with a settings file ************************************************************************/ void SettingsInit(FSSpecPtr spec,Boolean system,Boolean changeUserState) { #ifdef NAG InitNagResultType initNagResult; #endif Str255 scratch; uLong aLong; OSErr err; StartingUp = true; DateWarning(true); // annoy the user about his timezone SubFolderSpec(0,nil); // clear the subfolder cache MailRoot = Root; // until we create the mail folder ZapHandle(CompactStack); StackInit(sizeof(FSSpec),&CompactStack); /* * install other AE handlers */ InstallAERest(); if (EjectBuckaroo) {Cleanup();ExitToShell();} ZapHandle(StringCache); OpenSettingsFile(spec); /* open our settings file */ AuditStartup(kMyPlatformCode,MAJOR_VERSION*100+MINOR_VERSION*10+INC_VERSION,BUILD_VERSION); /* * Check out our ... anal */ AnalFindMine(); VicomFactor=GetRLong(VICOM_FACTOR); BgYieldInterval=GetRLong(BG_YIELD_INTERVAL); FgYieldInterval=GetRLong(FG_YIELD_INTERVAL); ASSERT(Count1Resources(TOC_TYPE)==0); InitPersonalities(); ProxyInit(); BuildSigList(); OTInitOpenTransport(); InitAppearanceMgr(); // Register Appearance and Live Scrolling PrefillSettings(); #ifdef NAG initNagResult = InitNagging (); #endif SwapQDTextFlags(PrefIsSet(PREF_QD_TEXT_ROUTINES) ? kQDUseTrueTypeScalerGlyphs : kQDUseCGTextRendering|kQDUseCGTextMetrics); PETELiveScroll(PETE, PrefIsSet(PREF_LIVE_SCROLL)); HesiodKill(); FurrinSort = PrefIsSet(PREF_FURRIN_SORT); SyncRW = AutoDoubler || PrefIsSet(PREF_SYNC_IO); Offline = PrefIsSet(PREF_OFFLINE); UseCTB = PrefIsSet(PREF_TRANS_METHOD); CurTrans = GetTCPTrans(); UnreadStyle = GetRLong(UNREAD_STYLE); NewTables = UsingNewTables(); NoPreflight = PrefIsSet(PREF_NO_CHECK_MEM); LogLevel = GetPrefLong(PREF_LOG); // start logging LocalizeFiles(); ConvertSignature(); CreateMailFolder(); /* make the mail folder and move stuff in it */ // do this before creating other folders & crap #ifdef IMAP CreateIMAPMailFolder(); /* make the folder for the IMAP cache */ RebuildAllIMAPMailboxTrees(); /* and build the personalities IMAP trees. */ #endif CreateItemsFolder(); /* create folder for misc items */ CreateSpoolfolder(); /* create folder for outgoing spools */ #ifdef BATCH_DELIVERY_ON CreateDeliveryfolder(); #endif CreatePartsfolder(); /* create folder for mhmtl parts */ CreateCachefolder(); /* create folder for downloading html images */ FigureOutFont(True); /* figure out what font && size to use */ CreateBoxes(); /* create In and Out boxes, for later use */ GetAttFolderSpecLo(&AttFolderSpec); PutUpMenus(); /* menus */ if (err=ConConInit()) DieWithError(COULDNT_INIT_CONCON,err); // ContentConcentrator #ifdef IMAP // make sure all the personalities have cache folders CreateNewPersCaches(); // initialize the string we'll pass back IMAP errors with. gIMAPErrorString[0] = 0; #endif if (!OptiMEMIs && CurrentSize()+10 K 0; Toshiba = PrefIsSet(PREF_TOSHIBA_FLUSH); FakeTabs = PrefIsSet(PREF_TAB_IN_TEXT); gNeedRemind = FindRemindLink(); /* see if the user needs to be reminded about any missed links */ D3 = ThereIsColor && PrefIsSet(PREF_3D); if (!PrefIsSet(PREF_SAVE_PASSWORD)) SetPref(PREF_PASS_TEXT,""); // Since SCNetworkCheckReachabilityByName is a piece of crap in 10.3 and before // we make sure that we don't call it unless the user has explicitly enabled it. if ( HaveTheDiseaseCalledOSX ()) if ( !*GetPref ( scratch, PREF_IGNORE_PPP )) SetPref ( PREF_IGNORE_PPP, YesStr ); if (!*GetPref(scratch,PREF_AUTO_CHECK)) SetPref(PREF_AUTO_CHECK,GetPrefLong(PREF_INTERVAL)?YesStr:NoStr); PersSetAutoCheck(); PETEAllowIntelligentEdit(PETE,!PrefIsSet(PREF_DUMB_PASTE)); PETEAnchoredSelection(PETE,PrefIsSet(PREF_ANCHORED_SELECTION)); OutgoingMIDListLoad(); GetRString(Re,REPLY_INTRO); GetRString(Fwd,FWD_PREFIX); GetRString(OFwd,OUTLOOK_FW_PREFIX); TrimWhite(Re); TrimWhite(Fwd); TrimWhite(OFwd); GetRString(NewLine,UseCTB ? CTB_NEWLINE : NEWLINE); /* * saved password? */ { PersHandle old = CurPers; for (CurPers=PersList;CurPers;CurPers=(*CurPers)->next) { if(!PrefIsSet(PREF_SAVE_PASSWORD)) InvalidateCurrentPasswords(False,False); else if(CurPers==PersList) { GetPref(scratch,PREF_PASS_TEXT); PCopy((*CurPers)->password,scratch); GetPref(scratch,PREF_AUXPW); PCopy((*CurPers)->secondPass,scratch); } } CurPers = old; } #ifdef HAVE_KEYCHAIN if (KeychainAvailable() && !*GetPref(scratch,PREF_KEYCHAIN)) { if (ComposeStdAlert(Normal,KEYCHAIN_WANNA)==1) KeychainConvert(); else SetPref(PREF_KEYCHAIN,NoStr); } #endif //HAVE_KEYCHAIN /* * fix up some older settings */ ASSERT(resNotFound==Zap1Resource('STR ',973)); Zap1Resource('STR ',973); if (!*GetPref(scratch,PREF_NEWMAIL_SOUND)) SetPref(PREF_ERROR_SOUND,GetResName(scratch,'snd ',ATTENTION_SND)); if (!*GetPref(scratch,PREF_NEWMAIL_SOUND)) SetPref(PREF_NEWMAIL_SOUND,GetResName(scratch,'snd ',NEW_MAIL_SND)); if (!PrefIsSet(PREF_BINHEX) && !PrefIsSet(PREF_DOUBLE) && !PrefIsSet(PREF_SINGLE) && !PrefIsSet(PREF_UUENCODE)) { GetPref(scratch,PREF_ATT_TYPE); if (!*scratch) scratch[1] = '0'; switch(scratch[1]) { default: SetPref(PREF_DOUBLE,YesStr);break; case atmSingle: SetPref(PREF_SINGLE,YesStr);break; case atmUU: SetPref(PREF_UUENCODE,YesStr);break; case atmHQX: SetPref(PREF_BINHEX,YesStr);break; } } GetPref(scratch,PREF_NO_EZ_OPEN); if (!*scratch || scratch[1]=='n') SetPref(PREF_NO_EZ_OPEN,"\p2"); else if (scratch[1]=='y') SetPref(PREF_NO_EZ_OPEN,"\p0"); if (GetPref(scratch,PREF_NO_PREVIEW_READ)[1]=='y') SetPrefLong(PREF_NO_PREVIEW_READ,1); if (LogLevel & LOG_PLUG) LogPlugins(); if (CountStrn(900)next) SetStupidStuff(); } CurPers = PersList; /* * OS X AddressBook sync */ OSXAddressBookSync(); InitWazoos(); #ifdef LDAP_ENABLED RefreshLDAPSettings(); #endif RefreshNicknameWatcherGlobals (false); #ifdef IMAP /* * Set Offline if shift was pressed before now. */ if (NoInitialCheck) SetPref(PREF_OFFLINE,YesStr); #endif // Initialize emoticons before we open any windows EmoInit(); /* * Upen the toolbar */ if (ToolbarShowing()) OpenToolbar(); if (PrefIsSet(PREF_TOOLBAR)) OpenToolbar(); /* * start measuring face time */ FMBMain = NewFaceMeasure(); FaceMeasureBegin(FMBMain); // start recording stats InitStats(); /* * Start showing ads */ OpenAdWindow(); /* * Bring Out Yer Dead! */ if (!EjectBuckaroo) RecallOpenWindows(); /* * run initial check */ #ifndef IMAP //Too late, we could be opening and resyncing IMAP windows already if (NoInitialCheck) SetPref(PREF_OFFLINE,YesStr); #endif if (!EjectBuckaroo && PersCheckTicks() && AutoCheckOK()) CheckNow = True; /* * filter messages that were left behind */ #ifdef THREADING_ON CleanRealOutTOC(); CleanTempOutTOC(); SetNeedToFilterOut(); NeedToFilterIn = 1; // make sure we check for delivery stuff if (!PrefIsSet(PREF_FOREGROUND_IMAP_FILTERING)) NeedToFilterIMAP = 1; gSkipIMAPBoxes = true; // we can skip any IMAP mailboxes for this first filter pass. FilterXferMessages(); gSkipIMAPBoxes = false; #endif // // Swap command keys with manual filtering if (JunkPrefSwitchCmdJAsked()) { if (JunkPrefSwitchCmdJ()) JunkReassignKeys(true); } else if (!HaveManualFilters() || kAlertStdAlertOKButton==ComposeStdAlert(Note,USE_CMD_J_FOR_JUNK)) { JunkReassignKeys(true); } else { JunkReassignKeys(false); } SetPrefBit(PREF_JUNK_MAILBOX,bJunkPrefSwitchCmdJAsked); if (GetCurrentPayMode()==EMS_ModePaid) ClearPrefBit(PREF_JUNK_MAILBOX,bJunkPrefDeadPluginsWarning); /* * send the audit record? */ if (!NoInitialCheck) RandomSendAudit(); #ifdef NAG if (initNagResult) DoPendingNagDialog (initNagResult); #endif StartingUp = false; } #ifdef HAVE_KEYCHAIN /********************************************************************** * KeychainConvert - setup personalities to do the keychain **********************************************************************/ void KeychainConvert(void) { PushPers(PersList); for (CurPers=PersList;CurPers;CurPers=(*CurPers)->next) { InvalidateCurrentPasswords(False,False); SetPref(PREF_SAVE_PASSWORD,YesStr); } SetPref(PREF_KEYCHAIN,YesStr); PopPers(); } #endif //HAVE_KEYCHAIN /********************************************************************** * CleanTempFolder - get rid of our stuff in the temp folder **********************************************************************/ void CleanTempFolder(void) { short vRef; long dirId; CInfoPBRec hfi; Str63 name; FindFolder(Root.vRef,kTemporaryFolderType,True,&vRef,&dirId); hfi.hFileInfo.ioNamePtr = name; hfi.hFileInfo.ioFDirIndex = 0; while (!DirIterate(vRef,dirId,&hfi)) if (hfi.hFileInfo.ioFlFndrInfo.fdCreator==CREATOR) { OSErr err; err = HDelete(vRef,dirId,name); if (!err) hfi.hFileInfo.ioFDirIndex--; // Don't skip next entry } } /********************************************************************** * **********************************************************************/ OSErr LocalizeFiles(void) { FSSpec spec, tocSpec; short rootfiles[] = { USA_NICKNAME_FOLDER, NICK_FOLDER, USA_EUDORA_NICKNAMES, ALIAS_FILE, USA_CACHE_ALIAS_FILE, CACHE_ALIAS_FILE, USA_PERSONAL_ALIAS_FILE, PERSONAL_ALIAS_FILE, USA_STATISTICS_FILE, STATISTICS_FILE, USA_ATTACHMENTS_FOLDER, ATTACH_FOLDER, USA_SIG_FOLDER, SIG_FOLDER, USA_STATION_FOLDER, STATION_FOLDER, USA_SPOOL_FOLDER, SPOOL_FOLDER, #ifdef BATCH_DELIVERY_ON USA_DELIVERY_FOLDER, DELIVERY_FOLDER, #endif USA_MISPLACED_FOLDER, MISPLACED_FOLDER, 0,0}; short mailfiles[] = { USA_IN, IN, USA_OUT, OUT, USA_TRASH, TRASH, 0,0}; OSErr err = noErr; short *file; spec.vRefNum = Root.vRef; spec.parID = Root.dirId; for (file=rootfiles;*file;file+=2) { if (!EqualStrRes(GetRString(spec.name,file[1]),file[0])) LocalizeRename(&spec,file[0]); } spec.vRefNum = MailRoot.vRef; spec.parID = MailRoot.dirId; for (file=mailfiles;*file;file+=2) { if (!EqualStrRes(GetRString(spec.name,file[1]),file[0])) { LocalizeRename(&spec,file[0]); Box2TOCSpec(&spec,&tocSpec); // usa .toc name in tocSpec GetRString(spec.name,file[1]); Box2TOCSpec(&spec,&spec); // local .toc name in spec FSpRename(&tocSpec,&spec.name); // will fail if local .toc exists; ok } } /* * a few files in subfolders */ if (!(err=SubFolderSpec(NICK_FOLDER,&spec))) { GetRString(spec.name, PHOTO_FOLDER); LocalizeRename(&spec, USA_PHOTO_FOLDER); #ifdef VCARD GetRString(spec.name, VCARD_FOLDER); LocalizeRename(&spec, USA_VCARD_FOLDER); #endif } if (!(err=SubFolderSpec(STATION_FOLDER,&spec))) { GetRString(spec.name,DEFAULT); LocalizeRename(&spec,USA_DEFAULT); } if (!(err=SubFolderSpec(SIG_FOLDER,&spec))) { GetRString(spec.name,SIGNATURE); LocalizeRename(&spec,USA_SIGNATURE); GetRString(spec.name,ALT_SIG); LocalizeRename(&spec,USA_ALTERNATE); } return err; } /********************************************************************** * **********************************************************************/ OSErr LocalizeRename(FSSpecPtr spec,short id) { Str63 newName; FSSpec origSpec = *spec; PCopy(newName,spec->name); GetRString(origSpec.name,id); return(FSpRename(&origSpec,&newName)); } /********************************************************************** * CreateItemsFolder - make the Eudora Items folder **********************************************************************/ void CreateItemsFolder(void) { FSSpec spec; Str63 folder; long junk; CInfoPBRec hfi; short pluginsVRefNum; long pluginsDirID; // Make Eudora Items folder FSMakeFSSpec(Root.vRef,Root.dirId,GetRString(folder,ITEMS_FOLDER),&spec); FSpDirCreate(&spec,smSystemScript,&junk); AFSpGetCatInfo(&spec,&spec,&hfi); IsAlias(&spec,&spec); ItemsFolder.dirId = SpecDirId(&spec); ItemsFolder.vRef = spec.vRefNum; // Make Plugins folder for plugin preferences FSMakeFSSpec(ItemsFolder.vRef,ItemsFolder.dirId,GetRString(folder,PLUGINS_FOLDER),&spec); IsAlias(&spec,&spec); FSpDirCreate(&spec,smSystemScript,&junk); pluginsVRefNum = spec.vRefNum; pluginsDirID = SpecDirId(&spec); // Make plugin Filter and Nicknames folders inside plugin folder FSMakeFSSpec(pluginsVRefNum,pluginsDirID,GetRString(folder,PLUGIN_FILTERS),&spec); FSpDirCreate(&spec,smSystemScript,&junk); FSMakeFSSpec(pluginsVRefNum,pluginsDirID,GetRString(folder,PLUGIN_NICKNAMES),&spec); FSpDirCreate(&spec,smSystemScript,&junk); } /********************************************************************** * CreateSpoolfolder - make the user's spool folder **********************************************************************/ void CreateSpoolfolder(void) { FSSpec spec; Str63 folder; long junk; FSMakeFSSpec(Root.vRef,Root.dirId,GetRString(folder,SPOOL_FOLDER),&spec); FSpDirCreate(&spec,smSystemScript,&junk); } #ifdef BATCH_DELIVERY_ON /********************************************************************** * CreateDeliveryfolder - make the user's delivery folder **********************************************************************/ void CreateDeliveryfolder(void) { FSSpec spec; Str63 folder; long junk; FSMakeFSSpec(Root.vRef,Root.dirId,GetRString(folder,DELIVERY_FOLDER),&spec); FSpDirCreate(&spec,smSystemScript,&junk); } #endif /********************************************************************** * CreatePartsfolder - make the user's part folder **********************************************************************/ void CreatePartsfolder(void) { FSSpec spec; Str63 folder; long junk; OSErr err; Boolean isFolder, boolJunk; Boolean created; err=FSMakeFSSpec(Root.vRef,Root.dirId,GetRString(folder,PARTS_FOLDER),&spec); if (created = err==fnfErr) err = FSpDirCreate(&spec,smSystemScript,&junk); if (!err) { err = ResolveAliasFile(&spec,True,&isFolder,&boolJunk); if (!err && !folder) err = fnfErr; } } /********************************************************************** * CreateCachefolder - make the user's part folder **********************************************************************/ void CreateCachefolder(void) { FSSpec spec; Str63 folder; long junk; OSErr err; err=FSMakeFSSpec(Root.vRef,Root.dirId,GetRString(folder,CACHE_FOLDER),&spec); if (err==fnfErr) FSpDirCreate(&spec,smSystemScript,&junk); } /********************************************************************** * CreateMailFolder - make the user's mail folder **********************************************************************/ void CreateMailFolder(void) { FSSpec spec; Str63 folder; long junk; OSErr err; Boolean isFolder, boolJunk; Boolean created; err=FSMakeFSSpec(Root.vRef,Root.dirId,GetRString(folder,MAIL_FOLDER_NAME),&spec); if (created = err==fnfErr) err = FSpDirCreate(&spec,smSystemScript,&junk); if (!err) { err = ResolveAliasFile(&spec,True,&isFolder,&boolJunk); if (!err && !folder) err = fnfErr; } if (err) DieWithError(MAIL_FOLDER,err); MailRoot.vRef = spec.vRefNum; MailRoot.dirId = SpecDirId(&spec); if (created) MoveMailboxesToMailFolder(); } /************************************************************************ * MoveMailboxesToMailFolder - move things to the mail folder ************************************************************************/ void MoveMailboxesToMailFolder(void) { #ifdef BATCH_DELIVERY_ON short badIndices[] = {ALIAS_FILE,CACHE_ALIAS_FILE,PERSONAL_ALIAS_FILE,LOG_NAME,OLD_LOG,FILTERS_NAME,SIG_FOLDER,NICK_FOLDER,PHOTO_FOLDER,ATTACH_FOLDER,STATION_FOLDER,SPOOL_FOLDER,ITEMS_FOLDER,MAIL_FOLDER_NAME,IMAP_MAIL_FOLDER_NAME,CACHE_FOLDER,PARTS_FOLDER,LINK_HISTORY_FOLDER,AUDIT_FILE,DELIVERY_FOLDER}; #else short badIndices[] = {ALIAS_FILE,CACHE_ALIAS_FILE,PERSONAL_ALIAS_FILE,LOG_NAME,OLD_LOG,FILTERS_NAME,SIG_FOLDER,NICK_FOLDER,PHOTO_FOLDER,ATTACH_FOLDER,STATION_FOLDER,SPOOL_FOLDER,ITEMS_FOLDER.MAIL_FOLDER_NAME,IMAP_MAIL_FOLDER_NAME,CACHE_FOLDER,PARTS_FOLDER,LINK_HISTORY_FOLDER,AUDIT_FILE}; #endif Str31 badNames[sizeof(badIndices)/sizeof(short)]; short i,bad; CInfoPBRec hfi; Str31 name; OSErr err; FSSpec spec; // load up the list of names we don't like for (i=0;i1003)&&*name) break; } SetResLoad(True); return(found); } /************************************************************************ * OpenNewSettings - open a new settings file, closing things out * properly first * * (10/4/99 jp) Modified a bit for adware to save the settings FSSpec so * we can pass it back in on a relaunch. ************************************************************************/ void OpenNewSettings(FSSpecPtr spec, Boolean changeUserState, UserStateType newState) { short menu; MenuHandle mHandle; if (!OkSettingsFileSpot(spec)) { if (SettingsRefN) return; Cleanup(); ExitToShell(); } if (SettingsRefN) { /* * a simulated Quit */ DoQuit(changeUserState); if (changeUserState) (*nagState)->state = newState; if (!AmQuitting) return; Done = False; /* * let's get rid of some stuff */ KillWazoos(); RemoveBoxMenus(); #ifdef TWO NukeXfUndo(); #endif CloseAdWindow(); if (mHandle=GetMHandle(LABEL_HIER_MENU)) TrashMenu(mHandle,3); // kill it to get rid of icon suites ZapResMenu(COLOR_HIER_MENU); ZapResMenu(SIG_HIER_MENU); ZapResMenu(SORT_HIER_MENU); ZapResMenu(FONT_HIER_MENU); ZapResMenu(MARGIN_HIER_MENU); ZapResMenu(TEXT_HIER_MENU); if (HasFeature (featureMultiplePersonalities)) ZapResMenu(PERS_HIER_MENU); ZapResMenu(TEXT_SIZE_HIER_MENU); ZapResMenu(SERVER_HIER_MENU); #ifdef WINTERTREE if (HasFeature (featureSpellChecking)) ZapResMenu(SPELL_HIER_MENU); #endif for (menu=APPLE_MENU;menuvRefNum; Root.dirId = spec->parID; SettingsFileSpec = *spec; /* * keep yer fingers crossed... */ SettingsInit(spec,False,changeUserState); } /************************************************************************ * OkSettingsFileSpot - does this look like a good spot for Eudora Settings? ************************************************************************/ Boolean OkSettingsFileSpot(FSSpecPtr spec) { Str31 name; Str31 otherName; short vRef; long dirID; short i; static OSType baaaadPlaces[] = {kAppleMenuFolderType,kControlPanelFolderType,kDesktopFolderType, kExtensionFolderType,kFontsFolderType,kPreferencesFolderType,kPrintMonitorDocsFolderType, kStartupFolderType,kSystemFolderType,kTemporaryFolderType,kTrashFolderType,kWhereToEmptyTrashFolderType}; FSSpec otherSpec; // we may need the name GetDirName(nil,spec->vRefNum,spec->parID,name); // root volumes no good if (spec->parID==2) { ComposeStdAlert(Stop,NO_EF_DESKTOP,name); return(False); } // special folders no good for (i=0;ivRefNum,baaaadPlaces[i],false,&vRef,&dirID)) if (spec->vRefNum==vRef && spec->parID==dirID) { ComposeStdAlert(Stop,NO_EF_DESKTOP,name); return(False); } if (!FSMakeFSSpec(spec->vRefNum,spec->parID,GetRString(otherName,MAIL_FOLDER_NAME),&otherSpec)) return (True); // we like it! if (FSMakeFSSpec(spec->vRefNum,spec->parID,GetRString(otherName,IN),&otherSpec) || FSMakeFSSpec(spec->vRefNum,spec->parID,GetRString(otherName,OUT),&otherSpec)) return(ComposeStdAlert(Caution,EF_WARNING,name,name)==kAlertStdAlertOKButton); return(True); } /********************************************************************** * **********************************************************************/ void ZapResMenu(short id) { MenuHandle mHandle; if (mHandle=GetMHandle(id)) { DeleteMenu(id); ReleaseResource_(mHandle); } } /************************************************************************ * SetRunType - figure out from the name of the app whether we're prod- * uction, testing, or my private version. This is a HACK. ************************************************************************/ void SetRunType(void) { #ifdef DEBUG FSSpec appSpec; #endif AppResFile = HomeResFile(GetIndResource(CREATOR, 1)); #ifdef DEBUG GetFileByRef(AppResFile,&appSpec); switch (appSpec.name[1]) { case 'P': RunType=Steve;break; case 'e': RunType=Debugging;break; case 'l': RunType=Debugging;break; default: RunType=Production;break; } #else RunType=Production; #endif DEBUG } /********************************************************************** * do what we need before exiting functions **********************************************************************/ void Cleanup() { #ifdef ETL ETLCleanup(); #endif #ifdef THREADING_ON KillThreads (); #endif #ifdef IMAP if (KerberosWasUsed() && PrefIsSet(PREF_DIE_DOG)) KerbDestroy(); if (KerberosWasUsed() && PrefIsSet(PREF_DIE_DOG_USER)) KerbDestroyUser(); #else if (PrefIsSet(PREF_KERBEROS) && PrefIsSet(PREF_DIE_DOG)) KerbDestroy(); if (PrefIsSet(PREF_KERBEROS) && PrefIsSet(PREF_DIE_DOG_USER)) KerbDestroyUser(); #endif #ifdef MENUSTATS NoteMenuSelection(-1); #endif #ifndef SLOW_CLOSE TcpFastFlush(True); #endif OTCleanUpAfterOpenTransport(); SaveFeaturesWithExtemeProfanity (gFeatureList); if (SettingsRefN) {short refN=SettingsRefN; SettingsRefN=0; CloseResFile(refN);} // fool closeresfile, because it's ok to close settings here CloseLog(); FlushVol(nil,Root.vRef); FlushVol(nil,MailRoot.vRef); if (PETE) PETECleanup(PETE); if (TBTurnedOnBalloons) {TBTurnedOnBalloons = False; HMSetBalloons(False);} CleanupUnicode(); OSXAddressBookSyncCleanup(false); } /************************************************************************/ /* d o i n i t l d e f - initialize LDEF resource. **/ /************************************************************************/ void doInitDEF(short resId,UniversalProcPtr upp,OSType type) { #pragma options align=mac68k struct AbsJMP { /* See the LDEF 1001 resource (stub) in Muslin.r for an explanation */ long LEA; short MOVEA; short JMP; Ptr theAddr; }; #pragma options align=reset typedef struct AbsJMP AbsJMP; Handle theResource; AbsJMP *theJMP; /* Lifted from some DTS code. The LDEF resource is a stub into which we write the address of the "real" LDEF (in the application.) The toolbox calls this stub, which in turn jumps to our LDEF. This technique not only allows us to debug the LDEF more easily (and give it access to the program's globals under 68K), it also simplifies working with Mixed Mode (see below) */ theResource = GetResource(type,resId); theJMP = (AbsJMP*)(*theResource); theJMP->theAddr = (Ptr)upp; } /* end of doInitLDEF */ /************************************************************************/ /* InitCDEF - setup a CDEF /************************************************************************/ void InitCDEF(short resId,ControlDefProcPtr proc) { // Register this resId so we will automatically use our CDEF ControlDefSpec cdefSpec; static ControlCNTLToCollectionUPP conversionProc; cdefSpec.defType = kControlDefProcPtr; cdefSpec.u.defProc = NewControlDefUPP(proc); if (!conversionProc) conversionProc = NewControlCNTLToCollectionUPP(ControlCNTLToCollection); RegisterControlDefinition(resId,&cdefSpec,conversionProc); } /************************************************************************/ /* ControlCNTLToCollection - put control values into collection for CDEF /************************************************************************/ pascal OSStatus ControlCNTLToCollection (Rect *bounds, SInt16 value, Boolean visible, SInt16 max, SInt16 min, SInt16 procID, SInt32 refCon, ConstStr255Param title, Collection collection) { OSErr err; if (!(err = AddCollectionItem(collection,kControlCollectionTagBounds,0,sizeof(Rect),bounds))) if (!(err = AddCollectionItem(collection,kControlCollectionTagValue,0, sizeof (value), &value))) if (!(err = AddCollectionItem(collection,kControlCollectionTagMinimum,0,sizeof (min), &min))) if (!(err = AddCollectionItem(collection,kControlCollectionTagMaximum,0, sizeof (max), &max))) if (!(err = AddCollectionItem(collection,kControlCollectionTagVisibility,0,sizeof(visible),&visible))) if (!(err = AddCollectionItem(collection,kControlCollectionTagRefCon,0, sizeof (refCon), &refCon))) err = AddCollectionItem(collection,kControlCollectionTagTitle,0,title[0],title+1); return err; } /************************************************************************/ /* InitLDEF - setup an LDEF /************************************************************************/ void InitLDEF(short resId,ListDefProcPtr proc) { // Register this resId so we will automatically use our LDEF if (RegisterListDefinition) { ListDefSpec ldefSpec; ldefSpec.defType = kListDefUserProcType; ldefSpec.u.userProc = NewListDefUPP(proc); RegisterListDefinition(resId,&ldefSpec); } } /********************************************************************** * figure out what font and size to use **********************************************************************/ void FigureOutFont(Boolean peteToo) { Str255 fontName; PETEDefaultFontEntry defaultFont; int i; /* * which font? */ if (EqualStrRes(GetPref(fontName,PREF_FONT_NAME),APPL_FONT)) FontID = 1; else FontID = GetFontID(fontName); /* * which fixed font? */ GetRString(fontName,FIXED_FONT); if((FixedID = GetFontID(fontName)) == applFont) FixedID = HiWord(ScriptVar(smScriptMonoFondSize)); /* * how big? */ FontSize = GetPrefLong(PREF_FONT_SIZE); if (!FontSize) FontSize = LoWord(ScriptVar(smScriptAppFondSize)); FixedSize = GetRLong(DEF_FIXED_SIZE); if (!FixedSize) FixedSize = LoWord(ScriptVar(smScriptMonoFondSize)); normFonts[0].fontID = FontID; normFonts[0].fontSize = FontSize; printNormFonts[0].fontID = GetFontID(GetPref(fontName,PREF_PRINT_FONT)); printNormFonts[0].fontSize = GetPrefLong(PREF_PRINT_FONT_SIZE); if (!printNormFonts[0].fontID) printNormFonts[0].fontID = FontID; if (!printNormFonts[0].fontSize) printNormFonts[0].fontSize = FontSize; printMonoFonts[0].fontID = monoFonts[0].fontID = FixedID; monoFonts[0].fontSize = FixedSize; printMonoFonts[0].fontSize = GetPrefLong(PREF_PRINT_FONT_SIZE); if (!printMonoFonts[0].fontSize) printNormFonts[0].fontSize = FixedSize; /* Get from the international font settings; will override above if available */ for(i = 32; --i >= 0; ) { short normID = 0, printNormID = 0, monoID = 0, printMonoID = 0; long normSize = 0, printNormSize = 0, monoSize = 0, printMonoSize = 0; GetRString(fontName, IntlFontsStrn+i+1); if(fontName[0]) { unsigned char delims[3] = {',',':',0}; UPtr spotP = &fontName[1]; PToken(fontName, GlobalTemp, &spotP, delims); if(*GlobalTemp) StringToNum(GlobalTemp, &normSize); PToken(fontName, GlobalTemp, &spotP, delims); if(*GlobalTemp) GetFNum(GlobalTemp, &normID); PToken(fontName, GlobalTemp, &spotP, delims); if(*GlobalTemp) StringToNum(GlobalTemp, &monoSize); PToken(fontName, GlobalTemp, &spotP, delims); if(*GlobalTemp) GetFNum(GlobalTemp, &monoID); PToken(fontName, GlobalTemp, &spotP, delims); if(*GlobalTemp) StringToNum(GlobalTemp, &printNormSize); PToken(fontName, GlobalTemp, &spotP, delims); if(*GlobalTemp) GetFNum(GlobalTemp, &printNormID); PToken(fontName, GlobalTemp, &spotP, delims); if(*GlobalTemp) StringToNum(GlobalTemp, &printMonoSize); PToken(fontName, GlobalTemp, &spotP, delims); if(*GlobalTemp) GetFNum(GlobalTemp, &printMonoID); } if(i != 0) { long normVal, monoVal; normVal = GetScriptVariable(i, smScriptAppFondSize); monoVal = GetScriptVariable(i, smScriptMonoFondSize); normFonts[i].fontSize = normSize ? normSize : LoWord(normVal); normFonts[i].fontID = normID ? normID : HiWord(normVal); monoFonts[i].fontSize = monoSize ? monoSize : LoWord(monoVal); monoFonts[i].fontID = monoID ? monoID : HiWord(monoVal); printNormFonts[i].fontSize = printNormSize ? printNormSize : normFonts[i].fontSize; printNormFonts[i].fontID = printNormID ? printNormID : normFonts[i].fontID; printMonoFonts[i].fontSize = printMonoSize ? printMonoSize : monoFonts[i].fontSize; printMonoFonts[i].fontID = printMonoID ? printMonoID : monoFonts[i].fontID; } else { if(normSize) FontSize = normFonts[i].fontSize = normSize; if(normID) FontID = normFonts[i].fontID = normID; if(monoSize) FixedSize = monoFonts[i].fontSize = monoSize; if(monoID) FixedID = monoFonts[i].fontID = monoID; if(printNormSize) printNormFonts[i].fontSize = printNormSize; if(printNormID) printNormFonts[i].fontID = printNormID; if(printMonoSize) printMonoFonts[i].fontSize = printMonoSize; if(printMonoID) printMonoFonts[i].fontID = printMonoID; } } /* * create a spare port for necessities */ SetupInsurancePort(); /* * and how big is big? */ FontWidth = GetWidth(FontID,FontSize); FontLead = GetLeading(FontID,FontSize); FontDescent = GetDescent(FontID,FontSize); FontAscent = GetAscent(FontID,FontSize); FontIsFixed = IsFixed(FontID,FontSize); /* * and get the widths of boxes */ GetBoxLines(); /* * notify pete */ if (peteToo) { // save these, because utf8 stuff uses them short saveNormFont = normFonts[0].fontID; short saveNormFontSize = normFonts[0].fontSize; // handle the new prefs for text region // font and size if (*GetPref(fontName,PREF_TEXT_FONT)) { short id=0; GetFNum(fontName,&id); if (id) normFonts[0].fontID = id; } { short size = GetPrefLong(PREF_TEXT_SIZE); if (size) normFonts[0].fontSize = size; } for(i = 32; --i >= 0; ) { Zero(defaultFont); defaultFont.pdFont = normFonts[i].fontID; defaultFont.pdSize = normFonts[i].fontSize; PETESetDefaultFont(PETE,nil,&defaultFont); Zero(defaultFont); defaultFont.pdFont = printNormFonts[i].fontID; defaultFont.pdSize = printNormFonts[i].fontSize; defaultFont.pdPrint = True; PETESetDefaultFont(PETE,nil,&defaultFont); #ifdef USEFIXEDDEFAULTFONT Zero(defaultFont); defaultFont.pdFont = monoFonts[i].fontID; defaultFont.pdSize = monoFonts[i].fontSize; defaultFont.pdFixed = True; PETESetDefaultFont(PETE,nil,&defaultFont); Zero(defaultFont); defaultFont.pdFont = printMonoFonts[i].fontID; defaultFont.pdSize = printMonoFonts[i].fontSize; defaultFont.pdFixed = True; defaultFont.pdPrint = True; PETESetDefaultFont(PETE,nil,&defaultFont); #endif } // restore these, because utf8 stuff uses them normFonts[0].fontID = saveNormFont; normFonts[0].fontSize = saveNormFontSize; } ReloadStdSizes(); } /********************************************************************** * open (or create) the settings file **********************************************************************/ void OpenSettingsFile(FSSpecPtr spec) { Str255 settingsName; Handle appVersion; Handle prefVersion; int err; FInfo info; FSSpec appSpec; static short copyMe[] = {PREF2_STRN,PREF3_STRN,PREF4_STRN,RegValStrn,RecentDirServStrn,0}; short *copyPtr; Boolean newSettingsFile; enum { kAppVersionNum = MAJOR_VERSION*10000+MINOR_VERSION*100+INC_VERSION }; FSSpec theSpec; NoMenus = true; /* * close it if it's open */ if (SettingsRefN) { // CloseResFile won't close the settings file without anger; fool it short refN = SettingsRefN; SettingsRefN = 0; CloseResFile(refN); Zero(SettingsSpec); } /* * and any plug-ins in its directory */ if (PrefPlugEnd) while (CurResFile()!=PrefPlugEnd) CloseResFile(CurResFile()); /* * we'll create it before we open it, to avoid the PMSP */ if (spec && spec->name && !FSpGetFInfo(spec,&info) && info.fdType==SETTINGS_TYPE && info.fdCreator==CREATOR) PCopy(settingsName,spec->name); else { if (!spec) spec = &theSpec; GetRString(settingsName,SETTINGS_FILE); PSCopy(spec->name,settingsName); spec->vRefNum = Root.vRef; spec->parID = Root.dirId; LocalizeRename(spec,USA_SETTINGS); } FSpCreateResFile(spec,CREATOR,SETTINGS_TYPE,smSystemScript); /* * is it sane? */ SaneSettings(spec); SimpleMakeFSSpec (Root.vRef, Root.dirId, settingsName, &SettingsFileSpec); /* * grab some stuff from the application resource file first */ if ((appVersion = GetResource_(CREATOR,1))==nil) DieWithError(READ_SETTINGS,ResError()); HNoPurge(appVersion); /* * if there are plug-ins in the Eudora Folder, open them, too */ GetFileByRef(AppResFile,&appSpec); if (appSpec.vRefNum!=Root.vRef || appSpec.parID!=Root.dirId) (void) PlugInDir(Root.vRef,Root.dirId); /* * now, open the preferences file */ if ((SettingsRefN=FSpOpenResFile(spec,fsRdWrPerm))==-1) { err = ResError(); DieWithError(err==opWrErr ? SETTINGS_BUSY : OPEN_SETTINGS,err); } // keep track of this little puppy SettingsSpec = *spec; /* * copy the preferences into it if need be * "need be" means either the resources aren't now there, * or the program version has changed since last time the * preferences file was written. */ if ((prefVersion = GetResource_(CREATOR,1))==nil) DieWithError(READ_SETTINGS,ResError()); HNoPurge(prefVersion); newSettingsFile = HomeResFile(prefVersion)!=SettingsRefN; // No version resource. Most likely a new settings file if (newSettingsFile || !StringSame(*prefVersion,*appVersion)) { ReleaseResource_(prefVersion); ReleaseResource_(appVersion); if (err=ResourceCpy(SettingsRefN,AppResFile,CREATOR,1)) DieWithError(WRITE_SETTINGS,err); if (err=ResourceCpy(SettingsRefN,AppResFile,'STR#',PREF_STRN)) DieWithError(WRITE_SETTINGS,err); MyUpdateResFile(SettingsRefN); if (ResError()) DieWithError(WRITE_SETTINGS,ResError()); } else { ReleaseResource_(prefVersion); ReleaseResource_(appVersion); } for (copyPtr=copyMe;*copyPtr;copyPtr++) if (!(prefVersion=Get1Resource('STR#',*copyPtr)) || HomeResFile(prefVersion)!=SettingsRefN) { if (err=ResourceCpy(SettingsRefN,AppResFile,'STR#',*copyPtr)) DieWithError(WRITE_SETTINGS,err); } // previous versions copied this in, we don't really want it if (prefVersion=Get1Resource('STR#',CmdKeyStrn)) if (GetHandleSize(prefVersion)==2) Zap1Resource('STR#',CmdKeyStrn); // Copy over default wazoos for new settings file or if // settings file has never been opened with version 4.0.0 or higher if (newSettingsFile || GetPrefLong(PREF_HIGHEST_APP_VERSION) < 4*10000) { if (!Count1Resources(kWazooListResType)) { ResourceCpy(SettingsRefN,AppResFile,kWazooListResType,kWazooRes1); ResourceCpy(SettingsRefN,AppResFile,kWazooListResType,kWazooRes2); } /* set default prefs for nickname type-ahead and nickname hiliting */ SetDefaultNicknameWatcherPrefs(); } // Copy over default LIGHT wazoos for new settings file or if // settings file has never been opened with version 4.3.0 or higher if (newSettingsFile || GetPrefLong(PREF_HIGHEST_APP_VERSION) < 403*100) { if (!Count1Resources(kFreeWazooListResType)) { ResourceCpy(SettingsRefN,AppResFile,kFreeWazooListResType,kWazooRes1); ResourceCpy(SettingsRefN,AppResFile,kFreeWazooListResType,kWazooRes2); } } for (copyPtr=copyMe;*copyPtr;copyPtr++) if (RecountStrn(*copyPtr)) Aprintf(OK_ALRT,Caution,FIXED_STRN,*copyPtr); // For new settings files, do not give the preexisting junk mailbox warning if (newSettingsFile) SetPrefLong(PREF_JUNK_MAILBOX,GetPrefLong(PREF_JUNK_MAILBOX)|bJunkPrefBoxExistWarning|bJunkPrefNeedIntro); // Update application version preferences SetPrefLong(PREF_LAST_APP_VERSION,kAppVersionNum); if ((gHighestAppVersionAtLaunch = GetPrefLong(PREF_HIGHEST_APP_VERSION)) < kAppVersionNum) SetPrefLong(PREF_HIGHEST_APP_VERSION,kAppVersionNum); } /********************************************************************** * SaneSettings - make sure a settings file is sane, and then backup **********************************************************************/ void SaneSettings(FSSpecPtr spec) { Boolean sane; FSSpec bkup; OSErr err; if ((err=utl_RFSanity(spec,&sane)) || !sane) if (!FallbackSettings(spec)) DieWithError(SETTINGS_BAD,err?err:1); /* * is sane. make backup */ bkup = *spec; if (*bkup.name > 26) *bkup.name = 26; PSCat(bkup.name,"\p.bkup"); FSpDupFile(&bkup,spec,True,False); } /********************************************************************** * **********************************************************************/ Boolean FallbackSettings(FSSpecPtr spec) { FSSpec backup; Boolean sane; OSErr err; backup = *spec; if (*backup.name > 26) *backup.name = 26; PSCat(backup.name,"\p.bkup"); if (!FSpExists(&backup) && !utl_RFSanity(&backup,&sane) && sane) { if (ReallyDoAnAlert(USE_BACKUP_ALRT,Note)==1) { err = FSpExchangeFiles(spec,&backup); if (!err) PSCat(spec->name,"\p.bad"); if (!err) FSpDelete(spec); if (!err) err = FSpRename(&backup,spec->name); if (err) FileSystemError(READ_SETTINGS,spec->name,err); else return(True); } } return(False); } /********************************************************************** * SystemEudoraFolder - find the directory for us in the system folder. * If it doesn't exist, create it. * * Actually, we now do this: * - Look for the folder in the system folder * - Look for the folder in the documents folder * - Create it in the documents folder * - With OSX will also look in the classic folders **********************************************************************/ void SystemEudoraFolder(void) { CInfoPBRec hfi; int err=0; FSSpec spec; Str31 folder,scratch; Boolean system = True; /* * now, look for our directory */ #ifdef DEBUG GetRString(folder,RunType==Steve ? STEVE_FOLDER : FOLDER_NAME); #else GetRString(folder,FOLDER_NAME); #endif DEBUG /* * try system folder */ err = FindEudoraFolder(&spec,folder,kOnSystemDisk,kSystemFolderType); /* * if system folder failed, try documents folder */ if (err) err = FindEudoraFolder(&spec,folder,kOnSystemDisk,kDocumentsFolderType); if (err && HaveOSX()) { // Search classic folders // Try system folder err = FindEudoraFolder(&spec,folder,kClassicDomain,kSystemFolderType); // Try documents folder if (err) err = FindEudoraFolder(&spec,folder,kClassicDomain,kDocumentsFolderType); if (err) { // Finding the classic documents folder current doesn't work (OS X 10.1.3). Let's try // to find it ourselves. err = FindFolder(kClassicDomain,kSystemFolderType,False,&spec.vRefNum,&spec.parID); if (!err) { FSMakeFSSpec(spec.vRefNum,spec.parID,nil,&spec); // system folder err = FSMakeFSSpec(spec.vRefNum,spec.parID,GetRString(scratch,USA_DOCUMENTS),&spec); // documents folder Root.vRef = spec.vRefNum; Root.dirId = SpecDirId(&spec); err = FSMakeFSSpec(Root.vRef,Root.dirId,folder,&spec); if (err==fnfErr) err = LocalizeRename(&spec,USA_EUDORA_FOLDER); } } // Need to end with OS X documents folder if (err) err = FindEudoraFolder(&spec,folder,kOnSystemDisk,kDocumentsFolderType); } /* * now we are pointed where we think the folder should go. Create it, so that it will * exist if we can make it */ FSpDirCreate(&spec,smSystemScript,&Root.dirId); /* * Get info, and possibly resolve alias */ err = AFSpGetCatInfo(&spec,&spec,&hfi); /* * it exists. Is it a folder? */ if (!err && hfi.hFileInfo.ioFlAttrib&0x10) { Root.vRef = spec.vRefNum; spec.parID = Root.dirId = hfi.hFileInfo.ioDirID; GetRString(spec.name,SETTINGS_FILE); LocalizeRename(&spec,USA_SETTINGS); } else if (!err) { MakeUserFindSettings(&spec); system = False; } if (err) DieWithError(MAIL_FOLDER,err); SettingsInit(&spec,system,false); } /************************************************************************ * FindEudoraFolder - see if Eudora Folder is at specified location, set up FSSpec ************************************************************************/ static OSErr FindEudoraFolder(FSSpecPtr spec,StringPtr folder,short vRefNum,OSType folderType) { OSErr err; if (!(err = FindFolder(vRefNum,folderType,False,&Root.vRef,&Root.dirId))) { err = FSMakeFSSpec(Root.vRef,Root.dirId,folder,spec); if (err==fnfErr) err = LocalizeRename(spec,USA_EUDORA_FOLDER); } return err; } /************************************************************************ * MakeUserFindSettings - force the user to find a Eudora Settings file ************************************************************************/ void MakeUserFindSettings(FSSpecPtr spec) { Boolean justQuit; justQuit = true; if (ReallyDoAnAlert(INSIST_SETTINGS_ALRT,Stop)==1) { justQuit = MakeUserFindSettingsNav (spec); } if (justQuit) { Cleanup(); ExitToShell(); } } /************************************************************************ * DateWarning - warn the user about the date, if need be. Returns true * if date not set ************************************************************************/ Boolean DateWarning(Boolean uiOK) { short vRef; long dirId; Str63 date; CInfoPBRec hfi; FSSpec spec; short where = -1; short bestWhere = REAL_BIG; BuildDateHeader(date,0); if (!*date) { if (uiOK) { WarnUser(USE_MAP,0); if (!FindFolder(kOnSystemDisk,kControlPanelFolderType,False,&vRef,&dirId)) { hfi.hFileInfo.ioNamePtr = date; hfi.hFileInfo.ioFDirIndex = 0; while(!DirIterate(vRef,dirId,&hfi)) if (TypeIsOnListWhere(hfi.hFileInfo.ioFlFndrInfo.fdCreator,DATELOC_TYPE,&where) && whereQuit menu item under aqua DeleteMenuItem(mHandle,FILE_QUIT_ITEM); DeleteMenuItem(mHandle,FILE_QUIT_ITEM-1); } } else if (menu==SPECIAL_MENU) { extern short gDeletedSpecialItem; if ( !PrefIsSet ( PREF_SHOW_CHANGE_PASSWORD )) { DeleteMenuItem ( mHandle, SPECIAL_CHANGE_ITEM ); gDeletedSpecialItem = SPECIAL_CHANGE_ITEM; } } } if (mHandle=GetMHandle(WINDOW_MENU)) ReleaseResource_(mHandle); mHandle = GetMenu(WINDOW_MENU+1000); if (mHandle==nil) DieWithError(GET_MENU,MemError()); InsertMenu(mHandle,0); #ifdef DEBUG if (RunType!=Production) { InsertMenu(GetMenu(DEBUG_MENU+1000),0); AttachHierMenu(DEBUG_MENU,dbAds,AD_SELECT_HIER_MENU); GetAndInsertHier(AD_SELECT_HIER_MENU); } #endif /* * take care of special menus */ BuildBoxMenus(); /* build the menus that refer to Mailboxes */ /* * the user menus */ AttachHierMenu(EDIT_MENU,EDIT_TEXT_ITEM,TEXT_HIER_MENU); #ifdef WINTERTREE if (HasFeature (featureSpellChecking)) { AttachHierMenu(EDIT_MENU,EDIT_ISPELL_HOOK_ITEM,SPELL_HIER_MENU); GetAndInsertHier(SPELL_HIER_MENU); } #endif GetAndInsertHier(TEXT_HIER_MENU); GetAndInsertHier(SIG_HIER_MENU); GetAndInsertHier(SERVER_HIER_MENU); GetAndInsertHier(ATTACH_MENU); GetAndInsertHier(TEXT_SIZE_HIER_MENU); AttachHierMenu(TEXT_HIER_MENU,tmFont,FONT_HIER_MENU); AttachHierMenu(TEXT_HIER_MENU,tmColor,COLOR_HIER_MENU); AttachHierMenu(TEXT_HIER_MENU,tmMargin,MARGIN_HIER_MENU); #ifdef NEVER AttachHierMenu(CHANGE_HIER_MENU,CHANGE_STATUS_ITEM,STATE_HIER_MENU); #endif SetupRecipMenus(); if (HasFeature (featureStationery)) BuildStationMenu(); if (HasFeature (featureMultiplePersonalities)) BuildPersMenu(); /* * hier menus */ GetAndInsertHier(FIND_HIER_MENU); GetAndInsertHier(SORT_HIER_MENU); GetAndInsertHier(CHANGE_HIER_MENU); GetAndInsertHier(COLOR_HIER_MENU); AddIconsToColorMenu(GetMHandle(COLOR_HIER_MENU)); MightSwitch(); GetAndInsertHier(FONT_HIER_MENU); AppendResMenu(GetMHandle(FONT_HIER_MENU),'FONT'); AfterSwitch(); GetAndInsertHier(MARGIN_HIER_MENU); GetAndInsertHier(TLATE_SEL_HIER_MENU); GetAndInsertHier(TLATE_SET_HIER_MENU); GetAndInsertHier(TLATE_ATT_HIER_MENU); #ifdef TWO GetAndInsertHier(STATE_HIER_MENU); #endif GetAndInsertHier(PRIOR_HIER_MENU); GetAndInsertHier(LABEL_HIER_MENU); { Byte type; Handle suite=nil; if ((mHandle=GetMHandle(LABEL_HIER_MENU)) && (GetMenuItemIconHandle(mHandle,1,&type,&suite) || !suite)) { GetIconSuite(&suite,NO_LABEL_SICN,svAllSmallData); SetMenuItemIconHandle(mHandle,1,kMenuIconSuiteType,suite); } } #ifdef DEBUG if (RunType!=Production) { GetAndInsertHier(WIND_PROP_HIER_MENU); AttachHierMenu(WINDOW_MENU,WIN_PROPERTIES_ITEM,WIND_PROP_HIER_MENU); } #endif if (NewTables) { mHandle = GetMenu(TABLE_HIER_MENU+1000); if (CountMenuItems(GetMHandle(CHANGE_HIER_MENU))mctRGB2; if (!BlackWhite(&color)) { err = RefreshRGBIcon(COLORS_MENU_ICON_BASE+item-1,&color,COLORS_MENU_ICON_TEMPLATE,nil); if (!GetIconSuite(&suite,COLORS_MENU_ICON_BASE+item-1,svAllSmallData)) SetMenuItemIconHandle(mh,item,kMenuIconSuiteType,suite); } ASSERT(!err); } } return(err); } /************************************************************************ * AddHelpMenuItems - add items to the help menu ************************************************************************/ void AddHelpMenuItems(void) { Handle resH; short r; short id; OSType type; Str255 name; MenuHandle hm; if (!HMGetHelpMenuHandle(&hm) && hm) /* the check for nil is needed courtesy of Norton Utilities, crap that it is */ { OriginalHelpCount = CountMenuItems(hm); SetResLoad(False); for (r = HELP_PICT_BASE; r=HELP_PICT_BASE+50 && idstate)) AppendMenu (hm, GetRString (name, ENTER_REG_CODE)); // Append the "Try Full FeaturesÉ" menu item if (LightUser ((*nagState)->state)) AppendMenu (hm, GetRString (name, TRY_FULL_FEATURES)); */ #else AppendMenu(hm,GetRString(name,PURCHASE_EUDORA)); if (GetPrefLong(PREF_REGISTER)!=0x0fffffff) AppendMenu(hm,GetRString(name,REGISTER_EUDORA)); #endif #endif AppendMenu(hm,GetRString(name,INSERT_CONFIGURATION)); AppendMenu(hm,GetRString(name,HELP_SUGGEST_MTEXT)); AppendMenu(hm,GetRString(name,HELP_BUG_MTEXT)); EndHelpCount = CountMenuItems(hm); } } /********************************************************************** * **********************************************************************/ void AddRes2HelpMenu(MenuHandle hm,Handle resH) { short id; OSType type; Str255 name; GetResInfo(resH,&id,&type,name); if (*name) MyAppendMenu(hm,name); else {AppendMenu(hm,"\p-");DisableItem(hm,CountMenuItems(hm));} ReleaseResource_(resH); } /************************************************************************ * AddWSMenuItems - add Word Services ************************************************************************/ void AddWSMenuItems(void) { Handle resH; short r; short id; OSType type; Str255 name; MenuHandle mh; if (mh = GetMHandle(EDIT_MENU)) { SetResLoad(False); for (r = 1;resH=GetIndResource_(WS_ALIAS_TYPE,r);r++) { GetResInfo(resH,&id,&type,name); MyAppendMenu(mh,name); } SetResLoad(True); } WordServices = NuHandle((r-1)*sizeof(**WordServices)); if (WordServices) { WriteZero(LDRef(WordServices),GetHandleSize_(WordServices)); UL(WordServices); } } /********************************************************************** * HuntSpellswell - find & install spellswell, if not there already **********************************************************************/ void HuntSpellswell(void) { OSType creator = FetchOSType(SPELLSWELL_CREATOR); FSSpec spec; OSErr err; short dtRef; short vRef; if (!(err = GetFileByRef(AppResFile,&spec))) { vRef = spec.vRefNum; if (!(err = DTRef(vRef,&dtRef))) { if (!(err = DTGetAppl(vRef,dtRef,creator,&spec))) { if (FileCreatorOf(&spec)==creator) { InstallSpeller(&spec); } } } } } /********************************************************************** * InferUnread - figure out if a mailbox has unread mail from its label * label 0xe means unread * if there is an age limit, and mailbox is older, remove label * * - Added imap parameter to do special things to IMAP mail folders **********************************************************************/ Boolean InferUnread(CInfoPBRec *hfi, Boolean imap) { CInfoPBRec *info = hfi; CInfoPBRec mailboxFileInfo; // if we're looking at an IMAP mailbox, peek inside the folder at the mailbox file. if (imap) { Zero(mailboxFileInfo); if (noErr==HGetCatInfo(info->hFileInfo.ioVRefNum,info->hFileInfo.ioDirID,info->hFileInfo.ioNamePtr,&mailboxFileInfo)) info = &mailboxFileInfo; } if ((info->hFileInfo.ioFlFndrInfo.fdFlags&0xe)==0xe) { uLong minDate; FSSpec spec; uLong curDate; minDate = GetRLong(UNREAD_LIMIT)*24*3600; if (minDate) { minDate = LocalDateTime()-minDate; if (PrefIsSet(PREF_NEW_TOC)) curDate = info->hFileInfo.ioFlMdDat; else { SimpleMakeFSSpec(info->hFileInfo.ioVRefNum,info->hFileInfo.ioFlParID,info->hFileInfo.ioNamePtr,&spec); Box2TOCSpec(&spec,&spec); curDate = FSpModDate(&spec); } if (curDate < minDate) { info->hFileInfo.ioFlFndrInfo.fdFlags &= ~0xe; HSetFInfo(info->hFileInfo.ioVRefNum,info->hFileInfo.ioFlParID,info->hFileInfo.ioNamePtr,&info->hFileInfo.ioFlFndrInfo); return(False); /* too old to have really unread mail */ } } return(True); /* label set to 1 and no min date or min date ok */ } return(False); /* label not set to 1 */ } /********************************************************************** * BoxFolder - build the mailbox menus according to the files in * a mailbox folder. * * - heavily uglified to add IMAP cache folders to menus **********************************************************************/ void BoxFolder(short vRef,long dirId,MenuHandle *menus,BoxFolderDescPtr bfd, Boolean *anyUnread, Boolean appending,Boolean isIMAP) { NameType thisOne; NameType **names=nil; short count=0,i,item,dirItem; MenuHandle newMenus[MENU_ARRAY_LIMIT]; Str15 suffix; Str15 tmpsuffix; Str32 s; Boolean localAnyUnread=False; Boolean isIMAPDir = false; // set to true once we know we're processing an IMAP cache directory Boolean isSelectable = false; Boolean haveIMAPpers = false; Boolean isRoot = vRef==MailRoot.vRef && dirId==MailRoot.dirId; Boolean junkIsSpecial = isRoot && JunkPrefBoxNoUnread(); uLong notAgain = 0; /* * make sure we're kosher */ if (bfd->level>MAX_BOX_LEVELS) DieWithError(TOO_MANY_LEVELS,bfd->level); AddBoxMap(vRef,dirId); /* * get started */ if ((names=NuHandle(0L))==nil) DieWithError(ALLO_MBOX_LIST,MemError()); if (!PrefIsSet(PREF_NEW_TOC)) GetRString(suffix,TOC_SUFFIX); else *suffix = 0; GetRString(tmpsuffix,TEMP_SUFFIX); /* * read names of mailbox files */ for (bfd->hfi.hFileInfo.ioFDirIndex=0;!DirIterate(vRef,dirId,&bfd->hfi);) { if (HaveOSX() && bfd->hfi.hFileInfo.ioNamePtr[0] && bfd->hfi.hFileInfo.ioNamePtr[1]=='.') // On OS X, files beginning with "." are invisible goto nextfile; /* * make an FSSpec out of the info */ SimpleMakeFSSpec(vRef,dirId,bfd->hfi.hFileInfo.ioNamePtr,&thisOne.spec); /* * aliases at the root level that are marked with the stationery bit * mean they were temporary mailboxes and should be cleaned up next * time Eudora is launched on this mail folder */ if (StartingUp && isRoot && (bfd->hfi.hFileInfo.ioFlFndrInfo.fdFlags&(kIsStationery|kIsAlias))==(kIsStationery|kIsAlias)) { if (notAgain != Hash(thisOne.spec.name)) { notAgain = Hash(thisOne.spec.name); if (!FSpDelete(&thisOne.spec)) { bfd->hfi.hFileInfo.ioFDirIndex--; continue; } } } /* * is it a special name? */ if (IsRoot(&thisOne.spec)) for (i=0;ibadCount;i++) if (StringSame(bfd->badNames[i],bfd->hfi.hFileInfo.ioNamePtr)) { if (i<3 && InferUnread(&bfd->hfi, false)) MarkHavingUnread(menus[MAILBOX],i+1); goto nextfile; } /* * is this a special name, IMAP-ly speaking? */ if (IsSpecialIMAPName(bfd->hfi.hFileInfo.ioNamePtr, NULL)) { isIMAPDir = true; goto nextfile; } /* * Is this another IMAP cache folder? */ if (IsFreeMode() && IsIMAPSubPers(&thisOne.spec)) { isIMAPDir = true; goto nextfile; } /* * read the IMAP info from this box, ONLY if it's an IMAP mailbox. */ if (bfd->hfi.hFileInfo.ioFlFndrInfo.fdType == IMAP_MAILBOX_TYPE) if (ReadIMAPMailboxAttributes(&thisOne.spec, &thisOne.imapAttributes)==noErr) isIMAPDir = true; /* * does this mailbox have the same name as the enclosing folder, and is it an IMAP folder? */ if (isIMAPDir && StringSame(bfd->enclosingFolderName,bfd->hfi.hFileInfo.ioNamePtr) && IsIMAPMailboxFile(&thisOne.spec)) { if (!(thisOne.imapAttributes&LATT_NOSELECT)) // we're building a menu to list mailboxes within a selectable mailbox isSelectable = true; goto nextfile; } thisOne.skipIt = false; thisOne.isIMAPpers = false; thisOne.moveToTop = isIMAP && StringSame(thisOne.spec.name,GetRString(s,IMAP_INBOX_NAME)); // is this file a folder? thisOne.isDir = HFIIsFolderOrAlias(&bfd->hfi); if (!thisOne.isDir) { if ((bfd->hfi.hFileInfo.ioFlFndrInfo.fdType!=MAILBOX_TYPE) && (bfd->hfi.hFileInfo.ioFlFndrInfo.fdType!=IMAP_MAILBOX_TYPE)) continue; if (*bfd->hfi.hFileInfo.ioNamePtr>*tmpsuffix && EndsWith(bfd->hfi.hFileInfo.ioNamePtr,tmpsuffix)) TempWarning(bfd->hfi.hFileInfo.ioNamePtr); if (*bfd->hfi.hFileInfo.ioNamePtr>31-*suffix) { TooLong(bfd->hfi.hFileInfo.ioNamePtr); continue; } if (!junkIsSpecial || !SpecIsJunkSpec(&thisOne.spec)) { if (thisOne.hasUnread = InferUnread(&bfd->hfi,false)) localAnyUnread = True; } } else { FSSpec tempSpec; // look inside all IMAP mailboxes and folders to see if they contain unread messages if (isIMAP) { if (thisOne.hasUnread = InferUnread(&bfd->hfi, true)) localAnyUnread = True; } else thisOne.hasUnread = false; if (IsAlias(&thisOne.spec,&tempSpec)) /* resolve alias */ { if (!(thisOne.skipIt=SameSpec(&thisOne.spec,&tempSpec))) { thisOne.spec.parID = SpecDirId(&tempSpec); /* get dirid of folder */ thisOne.spec.vRefNum = tempSpec.vRefNum; if (tempSpec.parID == IMAPMailRoot.dirId) { thisOne.isIMAPpers = true; haveIMAPpers = true; } } } else thisOne.spec.parID = bfd->hfi.hFileInfo.ioDirID; } PtrPlusHand_ (&thisOne,names,sizeof(thisOne)); if (MemError()) DieWithError(ALLO_MBOX_LIST,MemError()); count++; nextfile:; } /* * sort them */ BoxNamesSort(names); /* * add the New item */ if (!appending) { AppendMenu(menus[TRANSFER],bfd->newText); #ifdef TWO AppendMenu(menus[MAILBOX],bfd->newText); } if (isIMAPDir == false && !appending) { AppendMenu(menus[MAILBOX],bfd->otherText); AppendMenu(menus[TRANSFER],bfd->otherText); } else if (isSelectable == true) // this menu represents the contents of a SELECTable IMAP mailbox { AppendMenu(menus[MAILBOX],bfd->thisBoxText); AppendMenu(menus[TRANSFER],bfd->thisBoxText); } else // this menu represents the contents of a non-SELECTable mailbox - a folder. { AppendMenu(menus[MAILBOX],"\p-"); AppendMenu(menus[TRANSFER],"\p-"); } #endif /* * stick them into the proper menus */ { for (item=0;itemlevel+1; if (!(newMenus[i] = NewMenu(dirItem,thisOne.spec.name))) DieWithError(ALLO_MBOX_LIST,MemError()); AttachHierMenu(GetMenuID(menus[i]),CountMenuItems(menus[i]),dirItem); InsertMenu(newMenus[i],-1); #ifdef NEVER if (HasHelp && !isRoot && !Get1Resource('hmnu',dirItem)) { Handle mHand=GetResource_('hmnu',i*MAX_BOX_LEVELS+1); Handle newHand=mHand; if (mHand && !HandToHand_(&newHand)) { AddResource_(newHand,'hmnu',dirItem,""); SetResAttrs(newHand,resChanged|resPurgeable); } } #endif } bfd->level++; PCopy(bfd->enclosingFolderName,thisOne.spec.name); BoxFolder(thisOne.spec.vRefNum,thisOne.spec.parID,newMenus,bfd,&thisOne.hasUnread,false,isIMAP); if (MemError()) DieWithError(ALLO_MBOX_LIST,MemError()); if (thisOne.hasUnread) { localAnyUnread = True; MarkHavingUnread(menus[MAILBOX],CountMenuItems(menus[MAILBOX])); } } // If MacOS 8.5 (Appearance 1.1) or greater, make sure // menu items 32+ are enabled using menu manager if (gHave85MenuMgr) { count = CountMenuItems(menus[MAILBOX]); for (item=32;item<=count;item++) { EnableMenuItem(menus[MAILBOX],item); EnableMenuItem(menus[TRANSFER],item); } } ZapHandle(names); *anyUnread = localAnyUnread || *anyUnread; } /************************************************************************ * MarkHavingUnread - mark a mailbox as having unread messages ************************************************************************/ void MarkHavingUnread(MenuHandle mh, short item) { SetItemStyle(mh,item,UnreadStyle); } /************************************************************************ * BoxNamesSort - sort mailbox names ************************************************************************/ void BoxNamesSort(NameType **names) { NameType last; short n = GetHandleSize_(names)/sizeof(last); Zero(last); InfiniteString(last.spec.name,sizeof(last.spec.name)); PtrPlusHand_(&last,names,sizeof(last)); QuickSort((void*)LDRef(names),sizeof(last),0,n-1,(void*)NameCompare,(void*)NameSwap); UL(names); SetHandleBig_(names,n*sizeof(last)); } /************************************************************************ * NameCompare - compare two names ************************************************************************/ int NameCompare(NameType *n1, NameType *n2) { #ifdef IMAP if (n1->moveToTop != n2->moveToTop) return n1->moveToTop ? -1 : 1; #endif return(StringComp(n1->spec.name,n2->spec.name)); } /************************************************************************ * NameSwap - swap two names ************************************************************************/ void NameSwap(NameType *n1, NameType *n2) { NameType temp = *n2; *n2 = *n1; *n1 = temp; } /************************************************************************ * TempWarning - warn the user about a temp file in his mailbox structure ************************************************************************/ void TempWarning(UPtr filename) { Str255 msg; GetRString(msg,TEMP_WARNING); MyParamText(msg,filename,"",""); ReallyDoAnAlert(OK_ALRT,Caution); } /********************************************************************** * BuildBoxMenus - build the mailbox menus according to the files in * our mailbox folder. **********************************************************************/ void BuildBoxMenus() { BoxFolderDesc bfd; short badIndices[] = {IN,OUT,JUNK,TRASH}; // 1st 3 must be in,out,trash Str31 badNames[sizeof(badIndices)/sizeof(short)]; MenuHandle menus[MENU_ARRAY_LIMIT]; short i; Boolean anyUnread; #ifdef DEBUG Log(LOG_TPUT,"\pBuildBoxMenus begin"); #endif /* * this may mess with the head of the filters. * trash them if we dare */ if (Filters && !FiltersRefCount) ZapFilters(); /* * set up descriptor (saves stack space, parameter shuffling) */ bfd.badNames = badNames; bfd.badCount = sizeof(badIndices)/sizeof(short); bfd.level = g16bitSubMenuIDs ? BOX_MENU_START-1: 0; Zero(bfd.hfi); bfd.hfi.hFileInfo.ioNamePtr = bfd.hfi_namePtr; if (BoxMap!=nil) RemoveBoxMenus(); if ((BoxMap=NuHandle(0L))==nil) DieWithError(ALLO_MBOX_LIST,MemError()); for (i=0;inext;pers;pers=(*pers)->next) MyAppendMenu(mh,PCopy(string,(*pers)->name)); } } /********************************************************************** * BuildMarginMenu - build the margin menu **********************************************************************/ void BuildMarginMenu(void) { MenuHandle mh; Str255 scratch; Str255 name; short i; if (mh=GetMHandle(MARGIN_HIER_MENU)) {TrashMenu(mh,3);} for (i=1;*GetRString(scratch,MarginStrn+i);i++) { if (!Ascii2Margin(scratch,name,nil)) { if (*name==1 && name[1]=='-') AppendMenu(mh,name); else MyAppendMenu(mh,name); } else AppendMenu(mh,"\p-"); } GetRString(scratch,ADD_BULLETS); AppendMenu(mh,scratch); } #ifdef NEVER /************************************************************************ * TrashHmnu - get rid of the help resources for subfolders ************************************************************************/ void TrashHmnu(void) { short i,n; Handle hHand; n = GetHandleSize_(BoxMap)/sizeof(long); for (i=2;i<=n;i++) { ZapSettingsResource('hmnu',i); ZapSettingsResource('hmnu',i+MAX_BOX_LEVELS); } MyUpdateResFile(CurResFile()); } /************************************************************************ * MakeHmnusPurge - make sure we can purge the Hmnus ************************************************************************/ void MakeHmnusPurge(void) { short i,n; Handle hHand; /* * first off, get them written out */ MyUpdateResFile(CurResFile()); /* * trash 'em */ n = GetHandleSize_(BoxMap)/sizeof(long); SetResLoad(False); for (i=1;i<=n;i++) { if (hHand=Get1Resource('hmnu',i)) ReleaseResource_(hHand); if (hHand=Get1Resource('hmnu',i+MAX_BOX_LEVELS)) ReleaseResource_(hHand); } SetResLoad(True); } #endif #ifdef THREADING_ON void CreateTempBox(short which) { Str63 name; int err; FSSpec spec, spool; if (err=SubFolderSpec(SPOOL_FOLDER,&spool)) DieWithError(CREATING_MAILBOX,err); // or some other error // create temporary mailbox GetRString(name,which); if (FSMakeFSSpec(spool.vRefNum,spool.parID,name,&spec)) if (err=MakeResFile(name,spool.vRefNum,spool.parID,CREATOR,MAILBOX_TYPE)) DieWithError(CREATING_MAILBOX,err); } #endif THREADING_ON /********************************************************************** * CreateBoxes - Create the "In" and "Out" mailboxes if need be **********************************************************************/ void CreateBoxes() { Str63 name; int err; FSSpec spec; #ifdef THREADING_ON CreateTempBox(IN_TEMP); CreateTempBox(OUT_TEMP); #endif THREADING_ON GetRString(name,IN); if (FSMakeFSSpec(MailRoot.vRef,MailRoot.dirId,name,&spec)) if (err=MakeResFile(name,MailRoot.vRef,MailRoot.dirId,CREATOR,MAILBOX_TYPE)) DieWithError(CREATING_MAILBOX,err); GetRString(name,OUT); if (FSMakeFSSpec(MailRoot.vRef,MailRoot.dirId,name,&spec)) if (err=MakeResFile(name,MailRoot.vRef,MailRoot.dirId,CREATOR,MAILBOX_TYPE)) DieWithError(CREATING_MAILBOX,err); GetRString(name,TRASH); if (FSMakeFSSpec(MailRoot.vRef,MailRoot.dirId,name,&spec)) if (err=MakeResFile(name,MailRoot.vRef,MailRoot.dirId,CREATOR,MAILBOX_TYPE)) DieWithError(CREATING_MAILBOX,err); if (JunkPrefNeedIntro()) JunkIntro(); GetRString(name,JUNK); if (FSMakeFSSpec(MailRoot.vRef,MailRoot.dirId,name,&spec)) { if (err=MakeResFile(name,MailRoot.vRef,MailRoot.dirId,CREATOR,MAILBOX_TYPE)) DieWithError(CREATING_MAILBOX,err); // we made it, we don't need to warn about it SetPrefLong(PREF_JUNK_MAILBOX,GetPrefLong(PREF_JUNK_MAILBOX)|bJunkPrefBoxExistWarning); } else if (FSpIsItAFolder(&spec) || JunkPrefBoxExistWarning()) PreexistingJunkWarning(&spec); GetRString(name,ALIAS_FILE); if (FSMakeFSSpec(Root.vRef,Root.dirId,name,&spec)) if (err=MakeResFile(name,Root.vRef,Root.dirId,CREATOR,'TEXT')) DieWithError(CREATING_ALIAS,err); if (HasFeature (featureNicknameWatching)) { GetRString(name,CACHE_ALIAS_FILE); if (FSMakeFSSpec(Root.vRef,Root.dirId,name,&spec)) (void) MakeResFile(name,Root.vRef,Root.dirId,CREATOR,'TEXT'); // No error check, we just won't cache addresses } #ifdef VCARD if (IsVCardAvailable ()) { GetRString(name,PERSONAL_ALIAS_FILE); if (FSMakeFSSpec(Root.vRef,Root.dirId,name,&spec)) if (err=MakeResFile(name,Root.vRef,Root.dirId,CREATOR,'TEXT')) DieWithError(CREATING_PERSONAL_ALIAS,err); } #endif GetRString(name,LINK_HISTORY_FILE); if (FSMakeFSSpec(Root.vRef,Root.dirId,name,&spec)) if (err=MakeResFile(name,Root.vRef,Root.dirId,CREATOR,'TEXT')) DieWithError(CREATING_LINK_HISTORY,err); } /********************************************************************** * GetBoxLines - read the horizontal widths of the various mailbox * data areas. **********************************************************************/ void GetBoxLines(void) { Handle strn; int count; Str255 scratch; long rightSide; short last=0; short offset=0; short i; strn=GetResource_('STR#',BoxLinesStrn); if (strn==nil) DieWithError(GENERAL,ResError()); count = *((short *)*strn); if (count>8)>=3; if (Gestalt(gestaltComponentMgr,&resp)) DieWithError(NEED_COMPONENT_MGR,0); return !Gestalt(gestaltSystemVersion, &sysVers) ? sysVers >= 0x0700 : false; } void RememberOpenWindows(void) { DejaVuHandle dvh; DejaVu dv; short ind; WindowPtr theWindow; if (!SettingsRefN) return; else UseResFile(SettingsRefN); /* * out with the old */ SetResLoad(False); while (dvh=(DejaVuHandle)Get1IndResource(DEJA_VU_TYPE,1)) { SetResLoad(True); RemoveResource((Handle)dvh); SetResLoad(False); DisposeHandle((Handle)dvh); } SetResLoad(True); /* * save each window */ ind = 1000; for (theWindow = GetWindowList (); theWindow; theWindow = GetNextWindow (theWindow)) if (IsKnownWindowMyWindow(theWindow) && IsWindowVisible(theWindow)) if (RememberWindow(theWindow,&dv)) if (dvh=NuHandle(sizeof(dv))) { BMD(&dv,*dvh,sizeof(dv)); AddMyResource_(dvh,DEJA_VU_TYPE,++ind,""); ReleaseResource_(dvh); } UpdateResFile(SettingsRefN); WashMe = false; } /************************************************************************ * RecallOpenWindows - reopen windows there when we quit ************************************************************************/ void RecallOpenWindows(void) { short ind; DejaVuHandle dvh; DejaVu dv; WindowPtr theWindow; #ifdef TWO if (DBSplash != nil) { DisposDialog_(DBSplash); /* splash screen */ DBSplash = nil; } FlushEvents(everyEvent,0); #endif UseResFile(SettingsRefN); for (ind=1000+Count1Resources(DEJA_VU_TYPE);!EjectBuckaroo && ind>1000;ind--) { CycleBalls(); UseResFile(SettingsRefN); if (dvh=(DejaVuHandle)Get1Resource(DEJA_VU_TYPE,ind)) { ActivateMyWindow(FrontWindow(),False); dv = **dvh; if (GetHandleSize_(dvh)0) if (!FindSubFolderSpec(domains[n],kApplicationSupportFolderType,EUDORA_EUDORA,false,&spec)) if (!SameSpec(&spec,&oldSpec)) { oldSpec = spec; if (!SubFolderSpecOfStr(&spec,subfolderName,false,&spec)) sniffer(spec.vRefNum,spec.parID,refCon); } } } /************************************************************************ * OpenPlugIns - open extra Eudora resource files ************************************************************************/ void OpenPlugIns(void) { FSSpec spec; Str31 name; short vRef; long dirId; FSSpec appSpec; OSErr err; /* * in folder with Eudora */ if (!GetFileByRef(AppResFile,&spec)) { appSpec = spec; PlugInDir(spec.vRefNum,spec.parID); /* * in Eudora Stuff folder */ if (!FSMakeFSSpec(spec.vRefNum,spec.parID,GetRString(name,STUFF_FOLDER),&spec)) { IsAlias(&spec,&spec); spec.parID = SpecDirId(&spec); PlugInDir(spec.vRefNum,spec.parID); } /* * if we're packaged, in plugins folder up and over */ if (!(err=ParentSpec(&appSpec,&spec))) if (!(err=FSMakeFSSpec(spec.vRefNum,spec.parID,GetRString(name,PACKAGE_MACOS_FOLDER),&spec))) if (!(err=FSMakeFSSpec(spec.vRefNum,spec.parID,GetRString(name,PACKAGE_PLUGINS_FOLDER),&spec))) { IsAlias(&spec,&spec); spec.parID = SpecDirId(&spec); PlugInDir(spec.vRefNum,spec.parID); } } /* * in system prefs folder */ if (PrefsPlugIns && !FindFolder(kOnSystemDisk,kPreferencesFolderType,False,&vRef,&dirId)) PrefPlugEnd = PlugInDir(vRef,dirId); /* * various application support folders/Eudora */ { long domains[]={kUserDomain,kLocalDomain,kSystemDomain,kNetworkDomain}; FSSpec spec, oldSpec; short n = sizeof(domains)/sizeof(domains[0]); Zero(oldSpec); while (n-->0) if (!FindSubFolderSpec(domains[n],kApplicationSupportFolderType,EUDORA_EUDORA,false,&spec)) if (!SameSpec(&spec,&oldSpec)) { oldSpec = spec; if (!SubFolderSpecOf(&spec,PACKAGE_PLUGINS_FOLDER,false,&spec)) PlugInDir(spec.vRefNum,spec.parID); } } } /************************************************************************ * PlugInDir - open plug-ins in a directory ************************************************************************/ short PlugInDir(short vRef,long dirId) { CInfoPBRec hfi; Str31 name; short refN; short lastRefN = CurResFile(); FSSpec spec; hfi.hFileInfo.ioNamePtr = name; hfi.hFileInfo.ioFDirIndex = 0; while(!DirIterate(vRef,dirId,&hfi)) if ((hfi.hFileInfo.ioFlFndrInfo.fdType==PLUG_TYPE || hfi.hFileInfo.ioFlFndrInfo.fdType==HELP_TYPE) && hfi.hFileInfo.ioFlFndrInfo.fdCreator==CREATOR) { FSMakeFSSpec(vRef,dirId,name,&spec); ResolveAliasNoMount(&spec,&spec,nil); if ((refN=FSpOpenResFile(&spec, fsRdPerm))==-1) FileSystemError(OPEN_SETTINGS,name,ResError()); else { lastRefN = refN; if (hfi.hFileInfo.ioFlFndrInfo.fdType==HELP_TYPE && !HelpResFile) HelpResFile = refN; } } return(lastRefN); } /************************************************************************ * AwaitStartupAE - wait for our startup AE. If it doesn't come, die. ************************************************************************/ void AwaitStartupAE(void) { EventRecord event; uLong giveUp = TickCount() + 60*GetRLong(AE_INITIAL_TIMEOUT_SECS); /* * wait for the AE handlers to work their magic, and find us a folder * if they don't, just use the standard folder */ while (!SettingsRefN && TickCount()') { if (!(ParseURLPtr(pStart,p-pStart,s,nil,&queryPtr,&queryLen))) if (FindSTRNIndex(ProtocolStrn,s) == proSetting) { Ptr spot = queryPtr; if (PTokenPtr(queryPtr,queryLen,s,&spot,"=")) { long num; StringToNum(s,&num); if (PTokenPtr(queryPtr,queryLen,s,&spot,"")) SetPref(num,s); } } } } // Next line while (*p && *p!=0x0d && *p!=0x0a) p++; while (*p && (*p==0x0d || *p==0x0a)) p++; } // Rename file so we don't process it again FSpRename(&spec,GetRString(s,SETTINGS_PREFILL_PROCESSED)); } }