/* @(#)Z 1.7 com/src/ui/Arbitrat.cpp, odui, od96nt, odnt9712d 97/03/21 16:48:56 (97/01/15 11:49:15) */
//====START_GENERATED_PROLOG======================================
//
//
//   COMPONENT_NAME: odui
//
//   CLASSES: none
//
//   ORIGINS: 82,27
//
//
//   (C) COPYRIGHT International Business Machines Corp. 1995,1996
//   All Rights Reserved
//   Licensed Materials - Property of IBM
//   US Government Users Restricted Rights - Use, duplication or
//   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//   	
//   IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
//   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//   PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
//   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
//   USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
//   OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
//   OR PERFORMANCE OF THIS SOFTWARE.
//
//====END_GENERATED_PROLOG========================================
//
/*
	File:		Arbitrat.cpp

	Contains:	Implementation of class ODArbitrator, which arbitrates foci.

	Owned by:	Richard Rodseth

	Copyright:	© 1994 - 1995 by Apple Computer, Inc., all rights reserved.

	Change History (most recent first):

		<14>	 10/8/95	TJ		Fixes Recomended by Refball
		<13>	  8/3/95	RR		#1257260: Collapse B classes. Remove
									somInit methods. Don't call IsInitialized
									or SubclassResponsibility
		<12>	 5/26/95	RR		#1251403: Multithreading naming support
		<11>	 5/25/95	jpa		Fixed 'for' loop for ANSI compliance.
									[1253324]
		<10>	 4/13/95	RR		# 1216618 Added ODVolatile
		 <9>	  4/7/95	RR		#1216618 Added SOM_TRY etc.
		 <8>	10/18/94	RR		Removed unused private BRF, CRF, ARF
									methods. Moved selection focus management
									to focus module. Removed assumptions about
									exclusivity by delegating to focus module
									in more places.
		 <7>	  9/2/94	RR		#1184275 Pass transferringFrame and
									newOwner to focusModule::TransferFocus
		 <6>	  9/1/94	CC		RADAR #1181971 - missing factory methods
									(for JBS)
		 <5>	 8/23/94	RR		Move Ref counting into focus module
		 <4>	 8/17/94	jpa		Call DeleteSOMValues on fFocusModules since
									they're SOM objects [1181531]
		 <3>	 6/15/94	RR		Added function prefix
		 <2>	 6/10/94	RR		Update #ifndefs
		 <1>	 6/10/94	RR		first checked in

	To Do:
	In Progress:
		
*/


/*
 *  This file was generated by the SOM Compiler.
 *  Generated using:
 *     SOM incremental update: somc/smmain.c
 */


#define ODArbitrator_Class_Source

#define VARIABLE_MACROS

#include <Arbitrat.xih>

#ifndef _EXCEPT_
#include "Except.h"
#endif

#ifndef _DICTLIST_
#include "DictList.h"
#endif

#ifndef SOM_Module_OpenDoc_Foci_defined
#include "Foci.xh"
#endif

#ifndef SOM_ODFocusSet_xh
#include "FocusSet.xh"
#endif

#ifndef SOM_ODFocusSetIterator_xh
#include "FocusItr.xh"
#endif

#ifndef SOM_ODFocusModule_xh
#include "FocusMod.xh"
#endif

#ifndef SOM_ODExclusiveFocusModule_xh
#include "ExcFocus.xh"
#endif

#ifndef _ODSESSN_
#include "ODSessn.xh"
#endif

#ifndef SOM_ODPart_xh
#include "Part.xh"
#endif

#ifndef SOM_ODFrame_xh
#include "Frame.xh"
#endif

#include "ODUtils.h" 

#include "TempObj.h"

#ifndef SOM_ODWindowIterator_xh
#include "WinIter.xh"
#endif

#ifdef _PLATFORM_OS2_
#include "Window.xh"
#endif
/*
 * prototypes 
 */
#ifdef _PLATFORM_OS2_
SOMEXTERN void SOMLINK EnableApplModal(Environment *ev, ODFrame *frame, ODSession *session, BOOL enable);
#endif

SOM_Scope ODBoolean  SOMLINK ODArbitratorRequestFocusSet(ODArbitrator *somSelf, Environment *ev,
		ODFocusSet* focusSet,
		ODFrame* requestingFrame)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","RequestFocusSet");

	ODFocusSetIterator* iter = kODNULL; ODVolatile(iter);
	ODBoolean allRegistered = kODTrue;
	ODBoolean allWilling = kODTrue;
	ODTypeToken lastFocus;
	ODBoolean success = kODFalse;
	
	SOM_TRY

		iter = focusSet->CreateIterator(ev);
		
		// First check if any foci are not registered
		ODTypeToken focus;
		for (focus = iter->First(ev); allRegistered && iter->IsNotComplete(ev);focus = iter->Next(ev))
		{
			allRegistered = somSelf->GetFocusModule(ev,focus) && allRegistered;
		}
		if (!allRegistered)
			THROW(kODErrFocusNotRegistered);
		
		// Now check if existing owners are willing to relinquish each focus
		// Non-exclusive foci aren't checked
		
		for (focus = iter->First(ev); allWilling && iter->IsNotComplete(ev);focus = iter->Next(ev))
		{
			ODFocusModule* focusModule = somSelf->GetFocusModule(ev,focus);
			
			if (focusModule && (!focusModule->BeginRelinquishFocus(ev,focus, requestingFrame)))
				allWilling = kODFalse;
			
			lastFocus = focus;
		}
	
		// Now commit or abort all requests
		
		if (allWilling)
		{
			for (ODTypeToken focus = iter->First(ev); iter->IsNotComplete(ev);focus = iter->Next(ev))
			{
				ODFocusModule* focusModule = somSelf->GetFocusModule(ev, focus);
				
				focusModule->CommitRelinquishFocus(ev, focus, requestingFrame);
				focusModule->SetFocusOwnership(ev, focus, requestingFrame);
				
			}
			success = kODTrue;
		}
		else
		{
			for (ODTypeToken focus = iter->First(ev); (focus != lastFocus) && iter->IsNotComplete(ev);focus = iter->Next(ev))
			{
				ODFocusModule* focusModule = somSelf->GetFocusModule(ev, focus);
					
				focusModule->AbortRelinquishFocus(ev, focus, requestingFrame);
			}
			success = kODFalse;
		}	
		ODDeleteObject(iter);
		
	SOM_CATCH_ALL
	
		ODDeleteObject(iter);
			
	SOM_ENDTRY
	
	return success;
}

SOM_Scope ODBoolean  SOMLINK ODArbitratorRequestFocus(ODArbitrator *somSelf, Environment *ev,
		ODTypeToken focus,
		ODFrame* requestingFrame)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","RequestFocus");
    
    ODBoolean succeeded = kODFalse;

	SOM_TRY
	
		ODFocusModule* focusModule = somSelf->GetFocusModule(ev,focus);
		
		if (focusModule)
		{
			succeeded = focusModule->BeginRelinquishFocus(ev, focus, requestingFrame);
			if (succeeded)
			{
				focusModule->CommitRelinquishFocus(ev, focus, requestingFrame);
				focusModule->SetFocusOwnership(ev, focus, requestingFrame);
#ifdef _PLATFORM_OS2_
                                ODTypeToken modalFocus  = _fSession->Tokenize(ev, kODModalFocus);
                                if (focus == modalFocus) {

                                   // OS/2 has no application modality.  We have to fake it here, by
                                   // disabling mouse and keyboard inputs
                                   // to all the OD windows except the window that is going to own
                                   // the modal focus.dialog. 

                                   EnableApplModal(ev, requestingFrame, _fSession, FALSE);
                                }
#endif // _PLATFORM_OS2_
			}
			else	
				focusModule->AbortRelinquishFocus(ev, focus, requestingFrame);
		}
		else
		{
			succeeded = kODFalse;
			THROW(kODErrFocusNotRegistered);
		}

	SOM_CATCH_ALL
	
		succeeded = kODFalse;
			
	SOM_ENDTRY
	
	return succeeded;
}

SOM_Scope void  SOMLINK ODArbitratorRelinquishFocusSet(ODArbitrator *somSelf, Environment *ev,
		ODFocusSet* focusSet,
		ODFrame* relinquishingFrame)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","RelinquishFocusSet");

	ODFocusSetIterator* iter = kODNULL; ODVolatile(iter);
	
	SOM_TRY
	
		iter = focusSet->CreateIterator(ev);
	
		for (ODTypeToken focus = iter->First(ev); iter->IsNotComplete(ev);focus = iter->Next(ev))
		{
	
			ODFocusModule* focusModule = somSelf->GetFocusModule(ev,focus);
			
			if (focusModule)
			{
				focusModule->UnsetFocusOwnership(ev, focus, relinquishingFrame);
			}
			else
				THROW(kODErrFocusNotRegistered);
		}
		ODDeleteObject(iter);
		
	SOM_CATCH_ALL
	
		ODDeleteObject(iter);
		
	SOM_ENDTRY
}

SOM_Scope void  SOMLINK ODArbitratorRelinquishFocus(ODArbitrator *somSelf, Environment *ev,
		ODTypeToken focus,
		ODFrame* relinquishingFrame)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","RelinquishFocus");

	SOM_TRY

		ODFocusModule* focusModule = somSelf->GetFocusModule(ev, focus);
		
		if (focusModule)
		{
			focusModule->UnsetFocusOwnership(ev, focus, relinquishingFrame);
		}
		else
			THROW(kODErrFocusNotRegistered);
#ifdef _PLATFORM_OS2_
                ODTypeToken modalFocus  = _fSession->Tokenize(ev, kODModalFocus);
                if (focus == modalFocus) {
                   EnableApplModal(ev, kODNULL, _fSession, TRUE);
                }
#endif

	SOM_CATCH_ALL
	SOM_ENDTRY
}

SOM_Scope void  SOMLINK ODArbitratorTransferFocus(ODArbitrator *somSelf, Environment *ev,
		ODTypeToken focus,
		ODFrame* transferringFrame,
		ODFrame* newOwner)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","TransferFocus");

	SOM_TRY

		ODFocusModule* focusModule = somSelf->GetFocusModule(ev, focus);
		if (focusModule)
			focusModule->TransferFocusOwnership(ev, focus,transferringFrame, newOwner);
#ifdef _PLATFORM_OS2_
                ODTypeToken modalFocus  = _fSession->Tokenize(ev, kODModalFocus);
                if (focus == modalFocus) {
                   EnableApplModal(ev, newOwner, _fSession, TRUE);
                   if(newOwner)
                      EnableApplModal(ev, newOwner, _fSession, FALSE);
                }
#endif

	SOM_CATCH_ALL
	SOM_ENDTRY
}

SOM_Scope void  SOMLINK ODArbitratorTransferFocusSet(ODArbitrator *somSelf, Environment *ev,
		ODFocusSet* focusSet,
		ODFrame* transferringFrame,
		ODFrame* newOwner)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","TransferFocusSet");

	ODFocusModule* focusModule = kODNULL;
	ODFocusSetIterator* iter = kODNULL; ODVolatile(iter);

	SOM_TRY
	
		iter = focusSet->CreateIterator(ev);
	
		for (ODTypeToken focus = iter->First(ev); iter->IsNotComplete(ev);focus = iter->Next(ev))
		{
			focusModule = somSelf->GetFocusModule(ev, focus);
			if (focusModule)
				focusModule->TransferFocusOwnership(ev, focus,transferringFrame, newOwner);
		}
		ODDeleteObject(iter);

	SOM_CATCH_ALL
	
		ODDeleteObject(iter);
		
	SOM_ENDTRY
}

SOM_Scope ODFrame*  SOMLINK ODArbitratorAcquireFocusOwner(ODArbitrator *somSelf, Environment *ev,
		ODTypeToken focus)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","AcquireFocusOwner");

	ODFrame* focusOwner = kODNULL;
	ODFocusModule* focusModule = kODNULL;
		
	SOM_TRY
	
		focusModule = somSelf->GetFocusModule(ev, focus);
		if (focusModule) 
//#ifdef _PLATFORM_OS2_
//                {
//                      if(!focusModule->IsFocusExclusive(ev, focus)) // [107837]
//                            THROW(kODErrFocusIsNonExclusive);
//#endif
			focusOwner = focusModule->AcquireFocusOwner(ev, focus);
//#ifdef _PLATFORM_OS2_
//                }
//#endif
		else
			focusOwner = kODNULL;
		
	SOM_CATCH_ALL
	SOM_ENDTRY
	
	return focusOwner;
}

SOM_Scope ODFocusOwnerIterator*  SOMLINK ODArbitratorCreateOwnerIterator(ODArbitrator *somSelf, Environment *ev,
		ODTypeToken focus)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","CreateOwnerIterator");

	ODFocusOwnerIterator* ownerIterator = kODNULL;
	ODFocusModule* focusModule = kODNULL;
	
	SOM_TRY

		focusModule = somSelf->GetFocusModule(ev, focus);
		if (focusModule)
			ownerIterator = focusModule->CreateOwnerIterator(ev, focus);
		else
			THROW(kODErrFocusNotRegistered);

	SOM_CATCH_ALL
	SOM_ENDTRY
	
	return ownerIterator;
}

SOM_Scope void  SOMLINK ODArbitratorRegisterFocus(ODArbitrator *somSelf, Environment *ev,
		ODTypeToken focus,
		ODFocusModule* focusModule)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","RegisterFocus");

	ODFocusModule* existingModule = kODNULL;
	ODFocusModule* newModule = kODNULL; ODVolatile(newModule);

	SOM_TRY

		existingModule = (ODFocusModule*) _fFocusModules->ValueAtKey((KeyType) focus);
		if (existingModule)
			THROW(kODErrFocusAlreadyRegistered);
		else
		{
			newModule = focusModule;
			if (newModule == kODNULL)
			{
				newModule = new ODExclusiveFocusModule();
    			THROW_IF_NULL(newModule);	// new doesn't THROW for SOM objects
				((ODExclusiveFocusModule*) newModule)->InitExclusiveFocusModule(ev, _fSession);
			}
	
			_fFocusModules->AddPair((KeyType) focus, (ValueType) newModule);
		}

	SOM_CATCH_ALL
	
		ODDeleteObject(newModule);
		
	SOM_ENDTRY
}

SOM_Scope void  SOMLINK ODArbitratorUnregisterFocus(ODArbitrator *somSelf, Environment *ev,
		ODTypeToken focus)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","UnregisterFocus");

	SOM_TRY

		if (_fFocusModules->ContainsKey((KeyType) focus))
			_fFocusModules->RemoveKey((KeyType) focus);
		else
			THROW(kODErrFocusNotRegistered);

	SOM_CATCH_ALL
	SOM_ENDTRY
}

SOM_Scope ODBoolean  SOMLINK ODArbitratorIsFocusRegistered(ODArbitrator *somSelf, Environment *ev,
		ODTypeToken focus)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","IsFocusRegistered");

	ODBoolean isRegistered = kODFalse;
	
	SOM_TRY

		ODFocusModule* focusModule = somSelf->GetFocusModule(ev, focus);
		isRegistered = (focusModule != kODNULL);
		
	SOM_CATCH_ALL
	SOM_ENDTRY
	
	return isRegistered;
}

SOM_Scope ODBoolean  SOMLINK ODArbitratorIsFocusExclusive(ODArbitrator *somSelf, Environment *ev,
		ODTypeToken focus)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","IsFocusExclusive");

	ODBoolean isExclusive = kODFalse;
	ODFocusModule* focusModule = kODNULL;
		
	SOM_TRY

		focusModule = somSelf->GetFocusModule(ev, focus);
		if (focusModule)
			isExclusive = focusModule->IsFocusExclusive(ev, focus);
		else
			THROW(kODErrFocusNotRegistered);
			
	SOM_CATCH_ALL
	SOM_ENDTRY
	
	return isExclusive;
}

SOM_Scope void  SOMLINK ODArbitratorInitArbitrator(ODArbitrator *somSelf, Environment *ev,
		ODSession* session)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","InitArbitrator");

	DictionaryList* focusModules = kODNULL; ODVolatile(focusModules);
	

	SOM_TRY
	
		/* Moved from somInit. SOM itself sets fields to zero
		_fSession = kODNULL;
		_fFocusModules = kODNULL;
		*/
		
		somSelf->InitObject(ev);
		_fSession = session;
		focusModules = new DictionaryList(); // "new" THROWS for non-SOM objects
		_fFocusModules = focusModules;
		
	SOM_CATCH_ALL
	
		ODDeleteObject(focusModules);
		
	SOM_ENDTRY
}


SOM_Scope ODFocusModule*  SOMLINK ODArbitratorGetFocusModule(ODArbitrator *somSelf, Environment *ev,
		ODTypeToken focus)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","GetFocusModule");

	ODFocusModule* module = kODNULL;
	
	SOM_TRY
	
        if(_fFocusModules)
		module = (ODFocusModule*) _fFocusModules->ValueAtKey((KeyType) focus);
	else
                return((ODFocusModule*)kODNULL);	

	SOM_CATCH_ALL
	SOM_ENDTRY
	
	return module;
}

SOM_Scope ODFocusSet*  SOMLINK ODArbitratorCreateFocusSet(ODArbitrator *somSelf, Environment *ev)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","CreateFocusSet");

    ODFocusSet* focusSet = kODNULL;  ODVolatile(focusSet);

 	SOM_TRY
 	       
    	focusSet = new ODFocusSet;
    	THROW_IF_NULL(focusSet);	// new doesn't THROW for SOM objects
    	focusSet->InitFocusSet(ev);
    
    SOM_CATCH_ALL
    
    	ODDeleteObject(focusSet);
    	
    SOM_ENDTRY
    
    return focusSet;
}

SOM_Scope void  SOMLINK ODArbitratorsomUninit(ODArbitrator *somSelf)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","somUninit");

	if (_fFocusModules)
	{
		TRY
			_fFocusModules->DeleteSOMValues(); // Delete the Focus Modules
			ODDeleteObject(_fFocusModules);
		CATCH_ALL
			// Ignore exceptions
		ENDTRY
	}

    parent_somUninit(somSelf);
}

SOM_Scope ODSize  SOMLINK ODArbitratorPurge(ODArbitrator *somSelf, Environment *ev,
		ODSize size)
{
    ODArbitratorData *somThis = ODArbitratorGetData(somSelf);
    ODArbitratorMethodDebug("ODArbitrator","Purge");
    
    ODSize purgeSize = 0;

 	SOM_TRY

   		 purgeSize = parent_Purge(somSelf,ev,size);
   		 
    SOM_CATCH_ALL
    SOM_ENDTRY
    
    return purgeSize;
}

#ifdef _PLATFORM_OS2_
//------------------------------------------------------------------------------
// EnableApplModal - Simulates application modality by disabling/enabling
//                   all the OD windows except the window which owns the dialog.
//------------------------------------------------------------------------------
SOMEXTERN void SOMLINK EnableApplModal(Environment *ev, ODFrame* frame, ODSession* session, BOOL enable)
{
    ODWindowIterator *iter = kODNULL;
    ODWindow         *curWindow;

    try
    {
        // Disable/Enable mouse and keyboard input to all the OD windows 
        // except the one which is going to own the display dialog.
	//
	// Note: The window which is going to own the display dialog is
	//       disable/enable by the system.
	ODWindowState *windowState = session->GetWindowState(ev);
	if (windowState)
	{
                HWND hwnd = NULL;
                TempODWindow Window = kODNULL;
                if(frame)
                   Window = frame->AcquireWindow(ev);
                if(Window)
                   hwnd = Window->GetPlatformWindow(ev);

		iter = windowState->CreateWindowIterator(ev);
		for (curWindow = iter->First(ev); iter->IsNotComplete(ev); 
		     curWindow = iter->Next(ev))
	        {
	            HWND platformWindow = curWindow->GetPlatformWindow(ev);
	            if (platformWindow != hwnd)
	               WinEnableWindow(platformWindow, enable);
	        }
	        ODDeleteObject(iter);
	}

    }
    catch (ODException _exception)
    {
//        LOG("OpenDoc exception occured in EnableApplModal.\n");
        ODDeleteObject(iter);
        throw;
    }
}

#endif // _PLATFORM_OS2_
