/* 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;i<NSpare;i++) MakeGrow(SPARE_SIZE,i); 			/* reserve some memory for emergencies */
	SetGrowZone(NewGrowZoneUPP(MyGrowZone));			/* let the mac know it's there */
	DoMonitor = True;
	ThereIsColor = utl_HaveColor();
	if (!ModernSystem()) DieWithError(OLD_SYSTEM,0);
	if (!(MousePen = NewRgn())) DieWithError(MEM_ERR,MemError());
	if ((err = InitUnicode()) != noErr) DieWithError(MEM_ERR,err);

	InitCarbonUtil();	//	Set up Carbon utilities

	RegisterProFeatures ();	// (jp) Added to register each of the features supported in Pro
	
	#ifdef USECMM
	gHasCMM = HaveCMM();
	if( gHasCMM && InitContextualMenus() )
		gHasCMM = false;
	#endif

	InitIntScript();
	OpenPlugIns();
	
#ifdef TWO
	Splash();
#endif
	InitLDEF(ICON_LDEF,SettingsListDef);
	InitLDEF(TLATE_LDEF,TlateListDef);
#ifdef FANCY_FILT_LDEF
	InitLDEF(FILT_LDEF,FiltListDef);
#endif
	InitLDEF(FEATURE_LDEF,FeatureListDef);
	InitCDEF(APP_CDEF,AppCdef);
	InitCDEF(COL_CDEF,ColCdef);
	InitCDEF(LIST_CDEF,ListCdef);
#ifdef DEBUG
	InitCDEF(DEBUG_CDEF,DebugCdef);
#endif
	InitLDEF(LISTVIEW_LDEF,ListViewListDef);
#ifdef TASK_PROGRESS_ON
	InitLDEF(TASK_LDEF,ListItemDef);
#endif
	
	INIT_UPP(DlgFilter,ModalFilter);

	//	Remember any plugins in the system (or extensions) folder.
	//	This must be called before PETEInit which installs all the
	//	components including the plug-ins. (ALB)
	ETLGetSystemPlugins();
	// Register for PETE and EMSAPI
	RegisterEudoraComponentFiles();
#ifdef PEE
	/*
	 * initialize editor
	 */
	if (err=PETEInit(&PETE,GraphicHandlers))
		DieWithError(err==invalidComponentID ? NO_PETE:(err==afpBadVersNum?BAD_PETE:PETE_ERR),err);
	PETESetMemFail(PETE,&MemCanFail);
#ifdef DEBUG
	PETEDebugMode(PETE,RunType!=Production);
#endif
	Pslh = NewZH(PETEStyleEntry);
	PETESetCallback(PETE,nil,PeteCalled,peHasBeenCalled);
	PETESetLabelCopyMask(PETE,LABEL_COPY_MASK);
#endif

	ScanPrefs();

	/* MJN *//* initialize LDAP and the LDAP utilities */
#ifdef LDAP_ENABLED
	err = InitLDAP();
	if (err)
		DieWithError(LDAP_INIT_ERR, err);
#endif

	/* MJN *//* initialize the nickname watcher */
	err = InitNicknameWatcher();
	if (err)
		DieWithError(NICK_WATCHER_LOAD_ERR, err);

	if (err=AEObjectInit()) DieWithError(INSTALL_AE,err);	
	InstallAE();
	if (HasDragManager())
	{
		DECLARE_UPP(PantyTrack,DragTrackingHandler);
		DECLARE_UPP(PantyReceive,DragReceiveHandler);

		INIT_UPP(PantyTrack,DragTrackingHandler);
		INIT_UPP(PantyReceive,DragReceiveHandler);
		
		InstallTrackingHandler(PantyTrackUPP,nil,nil);
		InstallReceiveHandler(PantyReceiveUPP,nil,nil);
	}
	MakeWordChars();
	
	OTIs = HaveOT();

	OptiMEMIs = HaveOptiMEM();

	VicomIs = IsVICOM();
	
	// The mailbox rename stack
	if (!StackInit(sizeof(MBRenameProcPtr),&MBRenameStack))
	{
		MBRenameProcPtr proc;
		
		proc = TellFiltMBRename; StackQueue(&proc,MBRenameStack);
		proc = TellToolMBRename; StackQueue(&proc,MBRenameStack);
	}

#ifdef	DEMO
	TimeBomb();
#endif

	//LOGLINE;
	AwaitStartupAE();						/* wait for the Finder to tell us what to do */
	//LOGLINE;

	UpdateFeatureUsage (gFeatureList);

#ifdef NAG
	if (nagState)
		CheckNagging ((*nagState)->state);
#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)<PREF_SIGFILE-100)
	{
		if (PrefIsSet(PREF_SIG)) SetPrefLong(PREF_SIGFILE,SIG_STANDARD);
		else SetPrefLong(PREF_SIGFILE,SIG_NONE);
	}
}

/************************************************************************
 * VersString - get the version number
 ************************************************************************/
PStr VersString(PStr versionString)
{
	Handle version;
	
	if (version = GetResource_(CREATOR,2))
	{
		PCopy(versionString,*version);
		ReleaseResource_(version);
	}
	else
		*versionString = 0;
		
#ifdef NEVER
	if (PETE)
	{
		Str31 editor;
		ComposeString(editor,"\p/Editor %d.%d",GetComponentVersion(PETE)>>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<EstimatePartitionSize(false)) MemoryWarning();
	if (EjectBuckaroo) {Cleanup();ExitToShell();}
	TOCList = nil;							/* no open TOC's yet */
	MessList = nil; 						/* no open messages yet */
	SetSendQueue(); 						/* set SendQueue if there are queued messages */
	EnableMenus(nil,False); 					/* enable appropriate items */
	GenAliasList();							/* figure out where the alias lists are */
	WrapWrong = CountResources('Rong') > 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)<PREF_FURRIN_SORT-100)
	{
		SetPref(PREF_TOOLBAR,YesStr);
		SetPref(PREF_TB_VARIATION,"\p1");
		SetPref(PREF_3D,YesStr);
		SetPref(PREF_FURRIN_SORT,NoStr);
	}
	
	if (!GetPrefLong(PREF_POP_MODE)) SetPrefLong(PREF_POP_MODE,popRUIDL);
	
	switch (GetPref(scratch,PREF_NO_LINES)[1])
	{
		case 'y': SetPrefLong(PREF_NO_LINES,3); break;
		case '\0': SetPrefLong(PREF_NO_LINES,2); break;
	}
	
	switch (GetPref(scratch,PREF_SEND_STYLE)[1])
	{
		case 'y': SetPrefLong(PREF_SEND_STYLE,1); break;
		case 'n': case '\0': SetPrefLong(PREF_SEND_STYLE,0); break;
	}
	
	switch (GetPref(scratch,PREF_NICK_GEN_OPTIONS)[1])
	{
		case 'y': SetPrefLong(PREF_NICK_GEN_OPTIONS,1); break;
		case 'n': case '\0': SetPrefLong(PREF_NICK_GEN_OPTIONS,0); break;
	}
		
	/*
	 * colors
	 */
	PeteSetupTextColors(nil,false);
	
	/*
	 * Is the attachment folder ok?
	 */
	CheckAttachFolder();
	
	/*
	 * fix old recip menus
	 */
	FixRecipMenu();
	
	/*
	 * fix arrow settings
	 */
	GetPref(scratch,PREF_SWITCH_MODIFIERS);
	if (scratch[1]=='y' || scratch[1]=='n' || !*scratch)
		SetPrefLong(PREF_SWITCH_MODIFIERS,cmdKey);
	
	/*
	 * fix connection hours weekend thing
	 */
	aLong = GetPrefLong(PREF_CHECK_HOURS);
	if (!(aLong&(kHourAlwaysWeekendMask|kHourNeverWeekendMask|kHourUseWeekendMask)))
		SetPrefLong(PREF_CHECK_HOURS,aLong|kHourAlwaysWeekendMask);

	/*
	 * install help for transfer menu
	 */
	TransferMenuHelp(TFER_HMNU);
	
#ifdef WINTERTREE
	// Spelling options
	if (HasFeature (featureSpellChecking))
		WinterTreeOptions = GetPrefLong(PREF_WINTERTREE_OPTS);
#endif
			
	/*
	 * fix stupid new user settings
	 */
	if (*GetPref(scratch,PREF_POP_SIGH) && !*GetPref(scratch,PREF_STUPID_USER))
	{
		for (CurPers=PersList;CurPers;CurPers=(*CurPers)->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;i<sizeof(badIndices)/sizeof(short);i++)
	  GetRString(badNames[i],badIndices[i]);
	  
	// Now, go through the root folder, moving as we go
	Zero(hfi);
	hfi.hFileInfo.ioNamePtr = name;
	for (hfi.hFileInfo.ioFDirIndex=i=0;
			 !DirIterate(Root.vRef,Root.dirId,&hfi);
			 hfi.hFileInfo.ioFDirIndex=++i)
	{
		SimpleMakeFSSpec(Root.vRef,Root.dirId,name,&spec);
		if (HFIIsFolderOrAlias(&hfi) || hfi.hFileInfo.ioFlFndrInfo.fdType==MAILBOX_TYPE || hfi.hFileInfo.ioFlFndrInfo.fdType==TOC_TYPE)
		{
			for (bad=0;bad<sizeof(badIndices)/sizeof(short);bad++)
				if (StringSame(badNames[bad],name)) break;
			if (bad==sizeof(badIndices)/sizeof(short))
			{
				// move it!
				if (err = HMove(Root.vRef,Root.dirId,name,MailRoot.dirId,nil))
				{
					FileSystemError(MOVING_MAILBOXES,name,err);
					if (CommandPeriod) break;
				}
				else i--;
			}
		}
	}
}


/**********************************************************************
 * LogPlugins - log the resources in open files
 **********************************************************************/
OSErr LogPlugins(void)
{
	short refN;
	FSSpec spec;
	Str31 volName;
	Handle r;
	OSType type;
	Str255 rName;
	short id;
	short typeCount;
	short resCount;

	for (GetTopResourceFile(&refN); refN!=AppResFile; GetNextResourceFile(refN,&refN))
	{
		if (GetFileByRef(refN,&spec)) break;
		GetDirName(nil,spec.vRefNum,spec.parID,volName);
		ComposeLogS(LOG_PLUG,nil,"\p%p:%p",volName,spec.name);
		
		UseResFile(refN);
		for (typeCount = Count1Types(); typeCount; typeCount--)
		{
			Get1IndType(&type,typeCount);
			for (resCount = Count1Resources(type); resCount; resCount--)
			{
				SetResLoad(False);
				r = Get1IndResource(type,resCount);
				SetResLoad(True);
				if (r)
				{
					GetResInfo(r,&id,&type,rName);
					UseResFile(SettingsRefN);
					ComposeLogS(LOG_PLUG,nil,"\p  %O %d %p",type,id,rName);
					UseResFile(refN);
				}
			}
		}
	}
	UseResFile(SettingsRefN);
	return noErr;
}

/**********************************************************************
 * CheckAttachFolder - check to see if the user's real attachment folder exists
 **********************************************************************/
void CheckAttachFolder(void)
{
	Str127 pref, volname;
	long dirID;
	
	GetPref(pref,PREF_AUTOHEX_VOLPATH);
	if (*pref && !GetVolpath(pref,volname,&dirID))
	{
		switch (ComposeStdAlert(kAlertNoteAlert,NO_ATTACH_FOLDER))
		{
			case kAlertStdAlertOKButton:
				SetPref(PREF_AUTOHEX_VOLPATH,"");
				SetPref(PREF_AUTOHEX_NAME,"");
				break;
			case kAlertStdAlertOtherButton:
				if (GetHexPath(volname,pref))
				{
					SetPref(PREF_AUTOHEX_NAME,volname);
					SetPref(PREF_AUTOHEX_VOLPATH,pref);
				}
				break;
			default:;	// leave it for next time
		}
	}
}

/************************************************************************
 * GenAliasList - find the alias list
 ************************************************************************/
void GenAliasList(void)
{
	Str31 name;
	FSSpec folderSpec;
	AliasDesc ad;
	
	/*
	 * clear out the old, allocate empty handle for new
	 */
	if (Aliases) ZapHandle(Aliases);
	if (!(Aliases=NuHandle(0L))) DieWithError(MEM_ERR,MemError());

#ifdef VCARD
	/*
	 * add the Personal Nicknames file (we do this whether or not the feature is turned on)
	 */
	if (HasFeature (featureVCard)) {
		Zero(ad);
		ad.type = personalAddressBook;
		FSMakeFSSpec(Root.vRef,Root.dirId,GetRString(name,PERSONAL_ALIAS_FILE),&ad.spec);
		if (PtrPlusHand_(&ad,Aliases,sizeof(ad))) DieWithError(MEM_ERR,MemError());
	}
#endif
	
	/*
	 * add the Eudora Nicknames file
	 */
	Zero(ad);
	ad.type = eudoraAddressBook;
	FSMakeFSSpec(Root.vRef,Root.dirId,GetRString(name,ALIAS_FILE),&ad.spec);
	if (PtrPlusHand_(&ad,Aliases,sizeof(ad))) DieWithError(MEM_ERR,MemError());
	
#ifdef TWO
	/*
	 * is there a nicknames folder?
	 */
	if (HasFeature (featureMultipleNicknameFiles) && !SubFolderSpec(NICK_FOLDER,&folderSpec))
		ReadNickFileList (&folderSpec, regularAddressBook, false);

	/*
	 * add the Eudora Nicknames Cache file
	 */
	if (HasFeature (featureNicknameWatching)) {
		Zero(ad);
		ad.type = historyAddressBook;
		FSMakeFSSpec(Root.vRef,Root.dirId,GetRString(name,CACHE_ALIAS_FILE),&ad.spec);
		if (PtrPlusHand_(&ad,Aliases,sizeof(ad))) DieWithError(MEM_ERR,MemError());
	}
	ReadPluginNickFiles(false);
#endif
}

/************************************************************************
 * UsingNewTables - are we using the new translit table scheme?
 ************************************************************************/
Boolean UsingNewTables(void)
{
	Boolean found=False;
	Handle table;
	short ind=0;
	Str255 name;
	short id;
	ResType type;
	
	SetResLoad(False);
	while (table=GetIndResource_('taBL',++ind))
	{
		GetResInfo(table,&id,&type,&name);
		if (found=(id<1001||id>1003)&&*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;menu<MENU_LIMIT;menu++)
		{
			if (mHandle=GetMHandle(menu)) ReleaseResource_(mHandle);
		}
		if (!HMGetHelpMenuHandle(&mHandle) && mHandle) /* the check for nil is needed courtesy of Norton Utilities, crap that it is */
			if (HaveTheDiseaseCalledOSX())
			{
				// destroy the entire menu
				HMGetHelpMenuHandle(nil);
				ReleaseResource_(mHandle);
			}
			else
				// kill our items only
				TrashMenu(mHandle,OriginalHelpCount+1);
		ClearMenuBar();
		ZapAliases();
		ZapHandle(Aliases);
		ZapHistoriesList(true);
		ZapFilters();
		ZapHandle(Filters);
		ConConDispose();
#ifdef	IMAP
	 	DisposePersIMAPMailboxTrees();
#endif
		DisposePersonalities();
		ProxyZap();
	}
	AmQuitting = False;
	//if (ToolbarShowing()) OpenToolbar();

	/*
	 * Now, point us at the right directory
	 */
	
	(void) IsAlias(spec,spec);
	Root.vRef = spec->vRefNum;
	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;i<sizeof(baaaadPlaces)/sizeof(OSType);i++)
		if (!FindFolder(spec->vRefNum,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) && where<bestWhere)
					{
						bestWhere = where;
						SimpleMakeFSSpec(vRef,dirId,date,&spec);
						if (!where) break;
					}
		  }
	  }
		if (bestWhere<REAL_BIG) OpenOtherDoc(&spec,false,false,nil);
	  return(true);
	}

	return(false);
}

#ifdef TWO
#pragma segment Main
pascal void FMSError(PStr s);
pascal void FMSError(PStr s)
{
	AlertStr(OK_ALRT,Caution,s);
}
pascal void FMSFilter(EventRecord *event);
pascal void FMSFilter(EventRecord *event)
{
	MiniMainLoop(event);
}
#pragma segment Ends
#endif

/**********************************************************************
 * PutUpMenus - set up the menu bar
 **********************************************************************/
void PutUpMenus()
{
	int menu;
	MenuHandle mHandle;
	Str63 scratch;
	short key;
	
	/*
	 * add the standard ones
	 */
	for (menu=APPLE_MENU;menu<MENU_LIMIT;menu++)
	{
		if (mHandle=GetMHandle(menu)) ReleaseResource_(mHandle);
		mHandle = GetMenu(menu+1000);
		if (mHandle==nil)
			DieWithError(GET_MENU,MemError());
		InsertMenu(mHandle,0);
		if (menu==FILE_MENU)
		{
			SInt32	result;
			Gestalt(gestaltMenuMgrAttr,&result);
			if (result&gestaltMenuMgrAquaLayoutMask)
			{
				//	No File->Quit 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))<CHANGE_TABLE_ITEM)
		{
			AppendMenu(GetMHandle(CHANGE_HIER_MENU),GetMenuTitle(mHandle,scratch));
		}
		AttachHierMenu(CHANGE_HIER_MENU,CHANGE_TABLE_ITEM,TABLE_HIER_MENU);
		InsertMenu(mHandle,-1);
	}
	
	// Adjust command keys
	mHandle = GetMHandle(EDIT_MENU);
	GetItemCmd(mHandle,EDIT_PASTE_ITEM,&key);
	if (key)
	{
		SetItemCmd(mHandle,EDIT_QUOTE_ITEM,key);
		SetMenuItemModifiers(mHandle,EDIT_QUOTE_ITEM,kMenuOptionModifier);
	}

	mHandle = GetMHandle(TEXT_HIER_MENU);
	GetItemCmd(mHandle,tmQuote,&key);
	if (key)
	{
		SetItemCmd(mHandle,tmUnquote,key);
		SetMenuItemModifiers(mHandle,tmUnquote,kMenuOptionModifier);
	}

	AdjustStupidCommandKeys();
	
	AddCustomSortItems();

	if (HasFeature (featureStyleMargin))
		BuildMarginMenu();

#ifdef TWO
#ifdef ETL

	ETLInit();
#endif
#endif

	BuildSearchMenu();

	/*
	 * add the help menus
	 */
	AddHelpMenuItems();
	
	/*
	 * add finder menu items
	 */
	RefreshLabelsMenu();
	
	/*
	 * add the Word Services menus
	 */

	AddWSMenuItems();

	// Scripts menu
	BuildScriptMenu();

	ChangeCmdKeys();

	InitSharedMenus((void*)FMSError,(void*)FMSFilter);					/* Frontier menusharing */

	/*
	 * draw the menu bar
	 */
	gMenuBarIsSetup = true;
	EnableMenus(nil,false);
	
}

/************************************************************************
 * AddCustomSortItems - add custom sorts
 ************************************************************************/
void AddCustomSortItems(void)
{
	Str255 s;
	Str63 menuItem;
	short i;
	MenuHandle mh = GetMHandle(SORT_HIER_MENU);
	
	if (mh)
		for (i=1;*GetRString(s,SortsStrn+i);i++)
		{
			if (i==1) AppendMenu(mh,"\p-");
			if (!InterpretSortString(s,nil,nil,menuItem))
				MyAppendMenu(mh,menuItem);
			else MyAppendMenu(mh,s);
		}
}

/************************************************************************
 * GetAndInsertHier - get a menu and insert it
 ************************************************************************/
void GetAndInsertHier(short menu)
{
	MenuHandle mHandle;
	
	ZapResMenu(menu);
	mHandle = GetMenu(menu+1000);
	if (mHandle==nil) DieWithError(GET_MENU,menu);
	InsertMenu(mHandle,-1);
}

/************************************************************************
 * AddFinderItems - add the items from the Finder's label menu
 ************************************************************************/
void AddFinderItems(MenuHandle mh)
{
	short item;
	Str255 string;
	RGBColor color;
	Handle suite;
	short mItem;
	
	if (mh)
	{
		mItem = CountMenuItems(mh);
		for (item=1;item<=15;item++)
		{
			if (item==8)
			{
				AppendMenu(mh,"\p-");
				DisableItem(mh,CountMenuItems(mh));
				mItem++;
			}
			MyGetLabel(item,&color,string);
			if (!*string) PCatC(string,item);
			MyAppendMenu(mh,string);
			mItem++;
#ifdef LABEL_ICONS
			RefreshLabelIcon(item,&color);
			if (!GetIconSuite(&suite,LABEL_SICN_BASE+item-1,svAllSmallData))
				SetMenuItemIconHandle(mh,mItem,kMenuIconSuiteType,suite);
#endif
			if (!BlackWhite(&color))
			{
				SetMenuColor(mh,mItem,&color);
			}
		}
	}
}

/************************************************************************
 * RefreshLabelIcon - refresh the icon for a label
 ************************************************************************/
#ifdef LABEL_ICONS
OSErr RefreshLabelIcon(short item,RGBColor *color)
{
	Boolean changed;
	OSErr err = RefreshRGBIcon(LABEL_SICN_BASE+item-1,color,LABEL_SICN_TEMPLATE,&changed);
	if (changed) UpdateLabelControls();	
	return(err);
}

/************************************************************************
 * UpdateLabelControls - update label controls in windows
 ************************************************************************/
void UpdateLabelControls(void)
{
	TBarHasChanged = True;
}

#endif

/************************************************************************
 * AddIconsToColorMenu - add icons to the color menu
 ************************************************************************/
OSErr AddIconsToColorMenu(MenuHandle mh)
{
	short item;
	RGBColor color;
	OSErr err = noErr;
	MCEntryPtr mc;
	Handle suite;
	
	ASSERT(mh);
	
	for (item=CountMenuItems(mh);!err && item;item--)
	{
		if (mc = GetMCEntry(COLOR_HIER_MENU,item))
		{
			color = mc->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; r++)
			if ((resH=GetResource_('TEXT',r)) || (resH=GetResource_('PICT',r)))
				AddRes2HelpMenu(hm,resH);
				
		for (r = 1;(resH=GetIndResource_('TEXT',r)) || (resH=GetIndResource_('PICT',r));r++)
		{
			GetResInfo(resH,&id,&type,name);
			if (id>=HELP_PICT_BASE+50 && id<HELP_PICT_BASE+1000)
				AddRes2HelpMenu(hm,resH);
		}
		SetResLoad(True);
		
		AppendMenu(hm,"\p-");DisableItem(hm,CountMenuItems(hm));

#ifndef DEATH_BUILD
#ifdef NAG
		// Append the "Payment & RegistrationÉ" menu item
		AppendMenu (hm, GetRString (name, PAY_AND_REGISTER));
/*
		// Append the "Enter Registration CodeÉ" menu item
		if (!RegisteredUser ((*nagState)->state))
			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;i<bfd->badCount;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;item<count;item++)
		{
			if ((*names)[item].isDir || (*names)[item].skipIt) continue;
			thisOne = (*names)[item];
			MyAppendMenu(menus[MAILBOX],thisOne.spec.name);
			GetRString(thisOne.spec.name,TRANSFER_PREFIX);
			PCat(thisOne.spec.name,(*names)[item].spec.name);
			MyAppendMenu(menus[TRANSFER],thisOne.spec.name);
			if (thisOne.hasUnread)
				MarkHavingUnread(menus[MAILBOX],CountMenuItems(menus[MAILBOX]));
			CycleBalls();
		}
	}
	
	for (item=0;item<count;item++)
	{
		IMAPMailboxAttributes att;
		
		if (!(*names)[item].isDir || (*names)[item].skipIt) continue;
		thisOne = (*names)[item];
			
		MyAppendMenu(menus[MAILBOX],thisOne.spec.name);
		if (isIMAPDir && thisOne.hasUnread) MarkHavingUnread(menus[MAILBOX],CountMenuItems(menus[MAILBOX]));	
		GetRString(thisOne.spec.name,TRANSFER_PREFIX);
		PCat(thisOne.spec.name,(*names)[item].spec.name);
		MyAppendMenu(menus[TRANSFER],thisOne.spec.name);
		thisOne = (*names)[item];
		
		// Special cases when not to stick a submenu onto this guy
		if (isIMAPDir && MailboxAttributes(&thisOne.spec,&att))
		{
			// no submenu on mailboxes that can't have children
			if (att.noInferiors) continue;
			
			// no submenu on mailboxes with messages but no children
			if (!att.noSelect && !att.hasChildren) continue;
		}
		
		for (i=0;i<MENU_ARRAY_LIMIT;i++)
		{
			dirItem = i*MAX_BOX_LEVELS+bfd->level+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;i<sizeof(badIndices)/sizeof(short);i++)
	  GetRString(badNames[i],badIndices[i]);
	GetRString(bfd.newText,NEW_ITEM_TEXT);
#ifdef TWO
	GetRString(bfd.otherText,OTHER_ITEM_TEXT);
#ifdef	IMAP
	GetRString(bfd.thisBoxText,IMAP_THIS_MAILBOX_NAME);	
	GetRString(bfd.enclosingFolderName,MAIL_FOLDER_NAME);
#endif
#endif
			
	/*
	 * stick them into the proper menus
	 */
	menus[MAILBOX] = GetMHandle(MAILBOX_MENU);
	menus[TRANSFER] = GetMHandle(TRANSFER_MENU);
	
	/*
	 * rename a few
	 */
	{
		short aliases[] = {FILE_ALIAS_IN,FILE_ALIAS_OUT,FILE_ALIAS_JUNK,FILE_ALIAS_TRASH,0};
		Str63 name;
		Str15 prefix;
		
		GetRString(prefix,TRANSFER_PREFIX);
		for (i=0;aliases[i];i++)
		{
			GetRString(name,aliases[i]);
			SetMenuItemText(menus[MAILBOX],i+1,name);
			PInsert(name,sizeof(name),prefix,name+1);
			SetMenuItemText(menus[TRANSFER],i+1,name);
		}
	}
			
	/*
	 * now, do the recursive thing
	 */
	BoxFolder(MailRoot.vRef,MailRoot.dirId,menus,&bfd,&anyUnread,false,false);
#ifdef IMAP
	if (IMAPExists())
	{
		bfd.level++;
		BoxFolder(IMAPMailRoot.vRef,IMAPMailRoot.dirId,menus,&bfd,&anyUnread,true,true);
	}
#endif
#ifdef NEVER
	if (HasHelp) MakeHmnusPurge();
#endif
	BuildBoxCount();
#ifdef DEBUG
	Log(LOG_TPUT,"\pBuildBoxMenus end");
#endif
}

/************************************************************************
 * RemoveBoxMenus - get a clean slate
 ************************************************************************/
void RemoveBoxMenus(void)
{
	ZapHandle(BoxMap); BoxMap = nil;
#ifdef NEVER
	TrashHmnu();
#endif
	CheckBox(nil,False);
#ifdef TWO
	TrashMenu(GetMHandle(MAILBOX_MENU),MAILBOX_NEW_ITEM);
#else
	TrashMenu(GetMHandle(MAILBOX_MENU),MAILBOX_FIRST_USER_ITEM);
#endif
	TrashMenu(GetMHandle(TRANSFER_MENU),TRANSFER_NEW_ITEM);
}

/**********************************************************************
 * BuildStationMenu - build the stationery menu
 **********************************************************************/
void BuildStationMenu(void)
{
	MenuHandle mhReply,mhNew;
	Str255 string;
	FSSpec folderSpec;
	CInfoPBRec hfi;
	long newDirId;
	
	if (!HasFeature (featureStationery))
		return;
		
	/*
	 * create the folder
	 */
	DirCreate(Root.vRef,Root.dirId,GetRString(string,STATION_FOLDER),&newDirId);
	
	/*
	 * wipe out the old menu
	 */
	if (mhReply=GetMHandle(REPLY_WITH_HIER_MENU)) {DeleteMenu(REPLY_WITH_HIER_MENU); DisposeMenu(mhReply);}
	if (mhNew=GetMHandle(NEW_WITH_HIER_MENU)) {DeleteMenu(NEW_WITH_HIER_MENU); DisposeMenu(mhNew);}
	
	/*
	 * is there a folder?
	 */
	if (!SubFolderSpec(STATION_FOLDER,&folderSpec))
	{
		StationVRef = folderSpec.vRefNum;
		StationDirId = folderSpec.parID;
		
		/*
		 * attach the menu
		 */
		AttachHierMenu(MESSAGE_MENU,MESSAGE_REPLY_WITH_ITEM,REPLY_WITH_HIER_MENU);
		AttachHierMenu(MESSAGE_MENU,MESSAGE_NEW_WITH_ITEM,NEW_WITH_HIER_MENU);
	
		/*
		 * create the new menu
		 */
		MyGetItem(GetMHandle(MESSAGE_MENU),MESSAGE_REPLY_WITH_ITEM,string);
		if (mhReply = NewMenu(REPLY_WITH_HIER_MENU,string))
		if (mhNew = NewMenu(NEW_WITH_HIER_MENU,GetRString(string,NEW_MESSAGE_WITH)))
		{
			InsertMenu(mhReply,-1);
			InsertMenu(mhNew,-1);
			
			/*
			 * iterate through all the files, adding them to the list
			 */
			hfi.hFileInfo.ioNamePtr = string;
			hfi.hFileInfo.ioFDirIndex = 0;
			while (!DirIterate(folderSpec.vRefNum,folderSpec.parID,&hfi))
				if (hfi.hFileInfo.ioFlFndrInfo.fdType==STATIONERY_TYPE)
				{
					MyAppendMenu(mhReply,string);
					MyAppendMenu(mhNew,string);
				}
			
			if (!CountMenuItems(mhReply))
			{
				MyAppendMenu(mhReply,GetRString(string,NO_STATIONERY));
				DisableItem(mhReply,1);
				SetItemStyle(mhReply,1,italic);
				MyAppendMenu(mhNew,string);
				DisableItem(mhNew,1);
				SetItemStyle(mhNew,1,italic);
			}
		}
	}
}

/**********************************************************************
 * BuildPersMenu - build the personality menu
 **********************************************************************/
void BuildPersMenu(void)
{
	MenuHandle mh;
	Str255 string;
	PersHandle pers;
	
	if (!HasFeature (featureMultiplePersonalities))
		return;

	/*
	 * wipe out the old menu
	 */
	if (mh=GetMHandle(PERS_HIER_MENU)) {DeleteMenu(PERS_HIER_MENU); ReleaseResource_(mh);}
	
	/*
	 * grab the menu
	 */
	GetAndInsertHier(PERS_HIER_MENU);
	
	if (mh=GetMHandle(PERS_HIER_MENU))
	{
		for (pers=(*PersList)->next;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<BoxLinesLimit-1)
	{
		RemoveResource(strn); strn = nil;
		strn = GetResource_('STR#',BoxLinesStrn);
		count = *((short *)*strn);
		SetPref(TOC_INVERSION_MATRIX,"");
	}
	
	if (!BoxWidths) BoxWidths = NuHandle(count*sizeof(short));
	if (BoxWidths==nil) DieWithError(MEM_ERR,MemError());
	
	for(i=0;i<count;i++)
	{
		StringToNum(GetRString(scratch,BoxLinesStrn+i+1),&rightSide);
		(*BoxWidths)[i] = rightSide;
	}
	
	BoxInversionSetup();
}


/************************************************************************
 * SetupInsurancePort - create a grafport for use when others are unavailable
 ************************************************************************/
void SetupInsurancePort(void)
{
	if (!InsurancePort)
	{
		MyCreateNewPort(InsurancePort);
		if (!InsurancePort) DieWithError(MEM_ERR,MemError());
	}
	SetPort_(InsurancePort);
	TextFont(FontID);
	TextSize(FontSize);
}

/************************************************************************
 * ModernSystem - is the system 7 or better?
 ************************************************************************/
Boolean ModernSystem(void)
{
	long resp;
	long sysVers;

	HasHelp = !Gestalt(gestaltHelpMgrAttr,&resp) &&
										resp&(1L<<gestaltHelpMgrPresent);
	HasPM = !Gestalt(gestaltOSAttr,&resp) && resp&(1L<<gestaltLaunchControl);
	if (HasPM && !Gestalt(gestaltAUXVersion, &resp))
		HasPM = (resp>>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)<sizeof(dv)) dv.id = 0;
			ReleaseResource_(dvh);
			RecallWindow(&dv);
		}
		MonitorGrow(True);
		FloatingWinIdle();	// fix any layering problems we might have
	}

	for (theWindow = GetWindowList (); theWindow; theWindow = GetNextWindow (theWindow))
	{
		Rect	rContent;
		Point o;	
		
		SetPort(GetWindowPort(theWindow));
		GetContentRgnBounds(theWindow,&rContent);
		o.h = o.v = 0;
		GlobalToLocal(&o);
		OffsetRect(&rContent,o.h,o.v);
		InvalWindowRect(theWindow,&rContent);
		if (IsKnownWindowMyWindow(theWindow)) UpdateMyWindow(theWindow);
	}

	if (IsAdwareMode()) OpenAdWindow();
}

/************************************************************************
 * FolderSniffer - look for a folder in various places, and give a shout
 *  for each one found.  Similar to OpenPlugins, but general-purpose.
 *  OpenPlugins left alone for now, for backward compatibility
 ************************************************************************/
void FolderSniffer(short subfolderID,FolderSnifferFunc sniffer,uLong refCon)
{
	Str31 subfolderName;
	
	GetRString(subfolderName,subfolderID);
	FolderSnifferStr(subfolderName,sniffer,refCon);
}

void FolderSnifferStr(PStr subfolderName,FolderSnifferFunc sniffer,uLong refCon)
{
	FSSpec spec;
	Str31 name;
	FSSpec appSpec;
	OSErr err;

	/*
	 * in folder with Eudora
	 */
	if (!GetFileByRef(AppResFile,&spec))
	{
		appSpec = spec;
		
		// right next to Eudora
		if (!FSMakeFSSpec(spec.vRefNum,spec.parID,subfolderName,&spec))
		{
			IsAlias(&spec,&spec);
			spec.parID = SpecDirId(&spec);
			sniffer(spec.vRefNum,spec.parID,refCon);
		}
	
		// subfolder of Eudora Stuff folder
		if (!FSMakeFSSpec(spec.vRefNum,spec.parID,GetRString(name,STUFF_FOLDER),&spec))
		{
			IsAlias(&spec,&spec);
			if (!(err=FSMakeFSSpec(spec.vRefNum,SpecDirId(&spec),subfolderName,&spec)))
			{
				IsAlias(&spec,&spec);
				spec.parID = SpecDirId(&spec);
				sniffer(spec.vRefNum,spec.parID,refCon);
			}
		}
		
		/*
		 * if we're packaged, in Eudora Stuff 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,STUFF_FOLDER),&spec)))
		{
			IsAlias(&spec,&spec);
			if (!(err=FSMakeFSSpec(spec.vRefNum,spec.parID,subfolderName,&spec)))
			{
				IsAlias(&spec,&spec);
				spec.parID = SpecDirId(&spec);
				sniffer(spec.vRefNum,spec.parID,refCon);
			}
		}
	}
	
	/*
	 * 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 (!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()<giveUp)
	{
		//LOGLINE;
		if (WaitNextEvent(highLevelEventMask,&event,10,nil))
		{
			//LOGLINE;
			(void) AEProcessAppleEvent(&event);
			if (!SettingsRefN) SystemEudoraFolder();
		}
		else
			CyclePendulum();
	}
	//LOGLINE;
	
	/*
	 * did we get setup?  If not, open the standard folder
	 */
	if (!SettingsRefN) SystemEudoraFolder();
}

/************************************************************************
 * InitIntScript - make and use a local copy of 'itl2' in case system resource can't be loaded later
 ************************************************************************/
static void InitIntScript(void)
{
	Handle	hIntl0,hMyIntl0;
	GrafPtr	port;
	short		saveFont;
	OSErr err = noErr;
		
	//	Make sure we're using system script by setting textfont of current port to 0
	GetPort(&port);
	if (!port)
	{
		//	Oops, nothing set. Use WMgrPort
		GetWMgrPort(&port);
		SetPort(port);
	}
	saveFont = GetPortTextFont(port);
	TextFont(0);
	
	if ((hIntl0 = GetIntlResource(2)) &&
		(hMyIntl0 = GetResource('itl2',kMyIntl0)))
	{
		char saveState = HGetState(hIntl0);
		
		HNoPurge(hIntl0);
		HLock(hIntl0);
		SetHandleSize(hMyIntl0,0);
		if (!HandAndHand(hIntl0, hMyIntl0))
		{
			ChangedResource(hMyIntl0);	//	Resource is protected so it won't get written
		}
		else err = MemError();
		HSetState(hIntl0,saveState);
	}
	else err = ResError();
	TextFont(saveFont);
	if (err) DieWithError(INTERNATIONAL_FAILURE,err);
}

/************************************************************************
 * PrefillSettings - process initial settings from a text file
 ************************************************************************/
static void PrefillSettings(void)
{
	FSSpec	spec;
	Handle	text;
	Str255 s;
	Ptr	queryPtr;
	long	queryLen;

	if (!FindMyFile(&spec,kStuffFolderBit,SETTINGS_PREFILL_FILE))
	if (!Snarf(&spec,&text,0))
	{
		Ptr	p = LDRef(text);	
		while (*p)
		{
			//	Line must start with <x-eudora-setting
			if (*p=='<')
			{
				Ptr	pStart = ++p;
				while (*p && *p!='>' && *p!=0x0d && *p!=0x0a) p++;
				if (*p=='>')
				{
					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));	
	}
}
