/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 *
 * The contents of this file are subject to the Netscape Public License
 * Version 1.0 (the "NPL"); you may not use this file except in
 * compliance with the NPL.  You may obtain a copy of the NPL at
 * http://www.mozilla.org/NPL/
 *
 * Software distributed under the NPL is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
 * for the specific language governing rights and limitations under the
 * NPL.
 *
 * The Initial Developer of this code under the NPL is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
 * Reserved.
 */

#include "LTSMSupport.h"
static Boolean 				mHasTextServices = false;
static Boolean				mHasTSMTE = false;
static ScriptCode			mSysScript = smRoman;
static Boolean				mTSMTEisVersion1 = false;
static TSMTEPreUpdateUPP 	mTSMTEPreUpdateUPP = NULL;
static TSMTEPostUpdateUPP 	mTSMTEPostUpdateUPP = NULL;
		

static Boolean TrapAvailable(short theTrap);
static pascal void DefaultTSMTEPreUpdateProc(TEHandle textH, long refCon);

// ---------------------------------------------------------------------------
//	Copy from InlineInputSample.c
// this TSMTEPreUpdateProc only works around a bug in TSMTE 1.0, which has
// been fixed in 1.1. For other possible uses, see technote TE 27.
// ---------------------------------------------------------------------------

static pascal void DefaultTSMTEPreUpdateProc(TEHandle textH, long refCon)
{
	#pragma unused(refCon)

	
	if (mTSMTEisVersion1)		// Modified here for performance 
	{
		ScriptCode keyboardScript;
		short mode;
		TextStyle theStyle;
		
		keyboardScript = ::GetScriptManagerVariable(smKeyScript);
		mode = doFont;
		if (!(::TEContinuousStyle(&mode, &theStyle, textH) &&
				::FontToScript(theStyle.tsFont) == keyboardScript))
		{
			theStyle.tsFont = ::GetScriptVariable(keyboardScript, smScriptAppFond);
			::TESetStyle(doFont, &theStyle, false, textH);
		};
	};
}

// ---------------------------------------------------------------------------
//		¥ Initialization
// ---------------------------------------------------------------------------
//	Default constructor
void LTSMSupport::Initialize()
{
	mSysScript = ::GetScriptManagerVariable(smSysScript); 
	CheckForTextServices();
	BeginTextServices();
	TSMTENewUPP();
}
// ---------------------------------------------------------------------------
//		¥ CheckForTextServices
//		Call by constructor
//		From TE27 Page 4/14
// ---------------------------------------------------------------------------
void LTSMSupport::CheckForTextServices(void)
{
        long gestaltResponse;
        
        if (::TrapAvailable(_Gestalt))
        {
                if ((::Gestalt(gestaltTSMgrVersion, &gestaltResponse) == noErr) &&
                         (gestaltResponse >= 1))
                {
                		mTSMTEisVersion1 = (gestaltResponse == gestaltTSMTE1);
                        mHasTextServices = true;
                        if (::Gestalt(gestaltTSMTEAttr, &gestaltResponse) == noErr)
                                mHasTSMTE = ((gestaltResponse >> gestaltTSMTEPresent) & 1);
                };
        };
}

// ---------------------------------------------------------------------------
//		¥ TSMTENewUPP
//		Modified from InlineInputSample.c
// ---------------------------------------------------------------------------
void LTSMSupport::TSMTENewUPP()
{
	if(mHasTSMTE) {
		if(mTSMTEPreUpdateUPP == NULL )
			mTSMTEPreUpdateUPP = NewTSMTEPreUpdateProc(DefaultTSMTEPreUpdateProc);
	}
}
// ---------------------------------------------------------------------------
//		¥ BeginTextServices
//		Call by constructor
//		From TE27 Page 4/14
// ---------------------------------------------------------------------------
void LTSMSupport::BeginTextServices()
{
	if (!(mHasTSMTE && ::InitTSMAwareApplication() == noErr))
	{
	        // if this happens, just move on without text services
	        mHasTextServices = false;
	        mHasTSMTE = false;
	};
}
// ---------------------------------------------------------------------------
//		¥ DoQuit
//		Called by DoQuit()
//		From TE27 Page 4/14
// ---------------------------------------------------------------------------
void LTSMSupport::DoQuit(Int32	inSaveOption)
{
	if (mHasTextServices)
        (void) ::CloseTSMAwareApplication();
}
// ---------------------------------------------------------------------------
//		¥ IntlTSMEvent
//		From TE27 Page 11/14
// ---------------------------------------------------------------------------
Boolean
LTSMSupport::TSMEvent(const EventRecord &inMacEvent)
{
        short oldFont;
        ScriptCode keyboardScript;
        
        if(mHasTextServices)
        {
	        // make sure we have a port and it's not the Window Manager port
//	        if (qd.thePort != nil && ::FrontWindow() != nil)
//	        {
//	                oldFont = qd.thePort->txFont;
//	                keyboardScript = ::GetScriptManagerVariable(smKeyScript);
//	                if (::FontToScript(oldFont) != keyboardScript)
//	                        ::TextFont(GetScriptVariable(keyboardScript, smScriptAppFond));
//	        };
	        return ::TSMEvent((EventRecord *)&inMacEvent);
	    }
	    else
	    {
	    	return false;
	    }
}
// ---------------------------------------------------------------------------
//		¥ IntlTSMEvent
//		From TE27 Page 11/14
// ---------------------------------------------------------------------------
Boolean	LTSMSupport::SetTSMCursor(Point mousePos)
{
	if(mHasTextServices)
		return ::SetTSMCursor(mousePos);
	else
		return false;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
Boolean	LTSMSupport::HasTextServices()
{
	return mHasTextServices;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
Boolean	LTSMSupport::HasTSMTE()
{
	return mHasTSMTE;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------

TSMTEPreUpdateUPP	LTSMSupport::GetDefaultTSMTEPreUpdateUPP()
{
	return mTSMTEPreUpdateUPP;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
TSMTEPostUpdateUPP	LTSMSupport::GetDefaultTSMTEPostUpdateUPP()
{
	return mTSMTEPostUpdateUPP;
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void LTSMSupport::StartFontScriptLimit()
{
	//short theFontScript = ::FontScript();
	//StartFontScriptLimit(theFontScript);
}

// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void LTSMSupport::StartFontScriptLimit(  ScriptCode scriptcode)
{
	//	We want to disable all the script except: Roman and the Font script
	//  1. we have set the system script to the font script
	//	2. disable all the script except Roman and System script by calling 
	//			KeyScript(smDisablKybds);
	//  3. Should we also switch input method to the font script ?
	//	4. restore the system script.
	//if(mSysScript != scriptcode)
	//{
	//	::SetScriptManagerVariable(smSysScript, scriptcode);		
	//}
	//if(scriptcode != ::GetScriptManagerVariable(smKeyScript))
	//{
	//	::KeyScript(scriptcode);
	//}
//	::KeyScript(smKeyDisableKybds);
//	::SetScriptManagerVariable(smSysScript, mSysScript);		
}
// ---------------------------------------------------------------------------
//
// ---------------------------------------------------------------------------
void LTSMSupport::EndFontScriptLimit()
{
	// Re-enable all the script
	//::KeyScript(smKeyEnableKybds);
	//::SetScriptManagerVariable(smSysScript, mSysScript);		
}
// ---------------------------------------------------------------------------
// check to see if a given trap is implemented. We follow IM VI-3-8.
// ---------------------------------------------------------------------------
static 
Boolean TrapAvailable(short theTrap)
{
	TrapType theTrapType;
	short numToolboxTraps;
	
	if ((theTrap & 0x0800) > 0)
		theTrapType = ToolTrap;
	else
		theTrapType = OSTrap;

	if (theTrapType == ToolTrap)
	{
		theTrap = theTrap & 0x07ff;
		if (NGetTrapAddress(_InitGraf, ToolTrap) == NGetTrapAddress(0xaa6e, ToolTrap))
			numToolboxTraps = 0x0200;
		else
			numToolboxTraps = 0x0400;
		if (theTrap >= numToolboxTraps)
			theTrap = _Unimplemented;
	};

	return (NGetTrapAddress(theTrap, theTrapType) != NGetTrapAddress(_Unimplemented, ToolTrap));
}
