/*===============================
Copyright © 1998-2002 Brian Hall

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*===============================*/
#include "BlugsPrivate.h"
#if !TARGET_RT_MAC_MACHO
#include <Gestalt.h>
#endif

// This module 'owns' the globals
BLGlobals	_blGlobals = {nil,nil,0,0,nil,0,0};


#if __DEBLUG__
	Boolean			gHandlerFlag = false;
	#if TARGET_RT_MAC_MACHO
		const char*	gHandlerFlagDebugMsg =
							"Warning: possible reentrancy issue: ";
	#else
		const unsigned char	gHandlerFlagDebugMsg[] = 
							"\pWarning: possible reentrancy issue.";
	#endif
#endif

//===============================
static Boolean		local_BLIsAppearanceManagerPresent( SInt16* outVersion );


#if !TARGET_API_MAC_CARBON
static Boolean		local_BLIsDragManagerPresent( void );
static Boolean		local_BLIsTranslucentDragsPresent( void );
#endif

#if !TARGET_RT_MAC_MACHO
static Boolean		local_BLIsControlManager2Present( void );
#endif

#if TARGET_API_MAC_CARBON
static Boolean		local_BLIsAquaPresent( void );
#endif
static UInt16		local_BLGetOSVersion( void );

//===============================
// Return codes:
//	notInitErr (-900)					32-bit Quickdraw not installed.
//	memFullErr (-108)					Not enough memory for handler table.

// 11/20/2001 Moses -->1.1
// Call BLSettings *after* all Gestalt checks are made, not before!
// BLSettings chacks bl_Aqua and it's kind crucial to have the correct info!
BL_PROC OSErr BLEnter( UInt32 inSettings )
{
	OSErr	err = noErr;
	
	// Newer policy on checking initialization:
	//	always check to see if initialized, do not return error code
	//	because it isn't a real error.
	if (!bl_Inited)
	{
		SInt16	appearanceVersion;
		Handle	table;
		
		if (local_BLIsAppearanceManagerPresent( &appearanceVersion ))
		{
			bl_Set(_blGlobals.flags,blHasAppearance);
			_blGlobals.appearanceVersion = appearanceVersion;
			// Uncomment this to fake a non-Appearance system.
			//bl_Clear(_blGlobals.flags,blHasAppearance);
			//_blGlobals.appearanceVersion = 0;
		}
		
	#if TARGET_API_MAC_CARBON
		if (local_BLIsAquaPresent()) bl_Set(_blGlobals.flags,blHasAqua);
	#endif
		_blGlobals.osVersion = local_BLGetOSVersion();
	// We can skip over checking for Drag Mgr and its features for Carbon builds.
	#if TARGET_API_MAC_CARBON
		bl_Set(_blGlobals.flags,blHasDragMgr | blHasTranslucentDrags);
	#else
		if (local_BLIsDragManagerPresent())
		{
			bl_Set(_blGlobals.flags,blHasDragMgr);
			if ( local_BLIsTranslucentDragsPresent( ) )
				bl_Set(_blGlobals.flags, blHasTranslucentDrags);
		}
	#endif
	
	#if !TARGET_RT_MAC_MACHO
		if ( local_BLIsControlManager2Present( ) )
	#endif
			bl_Set(_blGlobals.flags, blHasControlMgr2);
		
		// Allocate a hash table for holding content handlers
		table = _BLAllocateHandlerTable();
		if (table)
		{
			_blGlobals.handlerTable = table;
			// Record the fact that initialization succeeded.
			bl_Set(_blGlobals.flags,blInitialized);
		}
		else err = memFullErr;
		BLSettings( inSettings );
	}
	return err;
}

//===============================
BL_PROC void BLSettings( UInt32 inSettings )
{
	// Aqua requires 16-bit GWorlds for DrawThemeButton to work.
	#if TARGET_API_MAC_CARBON
	if (bl_Aqua)
	{
		// If 8, clear and set the next higher.
		if (bl_Test(inSettings,blMax8BitGWorlds))
		{
			bl_Clear(inSettings,blMax8BitGWorlds);
			bl_Set(inSettings,blMax16BitGWorlds);
		}
	}
	#endif
	_blGlobals.userSettings = inSettings;
}

//===============================
BL_PROC UInt32 BLEnvironment( void )
{
	return _blGlobals.flags;
}

//===============================
BL_PROC SInt16	BLAppearanceVersion( void )
{
	SInt16	version;
	
#if TARGET_API_MAC_CARBON
	version = _blGlobals.appearanceVersion;
#else
	if (bl_Appearance) version = _blGlobals.appearanceVersion;
	else version = 0;
#endif
	return version;
}

//===============================
void _BLLoadCursors( void )
{
	CursHandle	curs = nil;
	
	curs = GetCursor( blRowResizeCURS );
	if (curs)
	{
		DetachResource( (Handle)curs );
		_blGlobals.rowResizeCursHdl = curs;
	}
	curs = GetCursor( blColResizeCURS );
	if (curs)
	{
		DetachResource( (Handle)curs );
		_blGlobals.colResizeCursHdl = curs;
	}
}

//===================================
static Boolean local_BLIsAppearanceManagerPresent( SInt16* outVersion )
{
	SInt32		response;
	OSErr		err;
	SInt16		version = 0x0000;
	Boolean		hasAppearance = false;
	
	err = Gestalt( gestaltAppearanceAttr, &response );
	if (!err)
	{
		SInt32		versResponse;
		
		err = Gestalt( gestaltAppearanceVersion, &versResponse );
		if (err) version = 0x0100;
		else version = LoWord( versResponse );
		if (response & (1 << gestaltAppearanceExists))
		//if (bl_Test(response,(1 << gestaltAppearanceExists)))
		if ((Ptr)RegisterAppearanceClient != (Ptr)kUnresolvedCFragSymbolAddress)
		hasAppearance = true;
	}
	*outVersion = version;
	return hasAppearance;
}

// We only need to check for Drag Mgr & features in pre-Carbon builds.
#if !TARGET_API_MAC_CARBON
//===================================
static Boolean local_BLIsDragManagerPresent( void )
{
	OSErr	err;
	SInt32	response;
	
	err = Gestalt( gestaltDragMgrAttr, &response );
	if (!err)
	{
		if (response & (1 << gestaltDragMgrPresent))
		{
			#if TARGET_RT_MAC_CFM
				if (response & (1 << gestaltPPCDragLibPresent))
				{
					if ((Ptr)NewDrag != (Ptr)kUnresolvedCFragSymbolAddress) return true;
				}
				//return false; //Moses was here. This seems unnecessary.
			#else
				return true;
			#endif
		}
	}
	return false;
}

//===================================
static Boolean local_BLIsTranslucentDragsPresent( void )
{
	OSErr	err;
	SInt32	response = 0L;
	
	err = Gestalt( gestaltDragMgrAttr, &response );
	if (!err)
		if (response & (1 << gestaltDragMgrHasImageSupport)) return true;
	return false;
}
#endif //!TARGET_API_MAC_CARBON

#if !TARGET_RT_MAC_MACHO
//===================================
static Boolean local_BLIsControlManager2Present( void )
{
	OSErr	err;
	SInt32	response = 0L;
	
	err = Gestalt( gestaltControlMgrAttr, &response );
	if ((err == noErr) && (response & gestaltControlMgrPresent))
#if TARGET_RT_MAC_CFM
		if ( (UInt32)SetControlViewSize != kUnresolvedCFragSymbolAddress )
#endif
			return true;
	return false;
}
#endif

#if TARGET_API_MAC_CARBON
//===================================
static Boolean local_BLIsAquaPresent( void )
{
	OSErr	err;
	SInt32	response = 0L;
	
	err = Gestalt( gestaltMenuMgrAttr, &response );
	if ((err == noErr) && (response & gestaltMenuMgrAquaLayoutMask)) return true;
	return false;
}
#endif

//===================================
static UInt16 local_BLGetOSVersion( void )
{
	OSErr	err;
	SInt32	response = 0L;
	UInt16	version = 0;
	
	err = Gestalt( gestaltSystemVersion, &response );
	if (!err) version = LoWord( response );
	return version;
}

