/* @(#)Z 1.4 com/src/storage/TransDlg.cpp, oddataxfer, od96nt, odnt9712d 97/03/21 16:46:45 (96/10/29 09:31:59) */
//====START_GENERATED_PROLOG======================================
//
//
//   COMPONENT_NAME: oddataxfer
//
//   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:		TransDlg.cpp

	Contains:	C++ Implementation for Translation Dialog class.

	Owned by:	Craig Carper

	Copyright:	© 1993-95 by Apple Computer, Inc., all rights reserved.

	Change History (most recent first):

		<30>	10/16/95	CC		GM 1291441: InitialEditorSetup: Translation
									disabled if only one translate-kind
									possible.
									GM 1292157: Removed static function
									GetEditorFromList; call
									GetThisEditorFromList instead.
		<29>	 10/3/95	eeh		1284995: new default param to
									SetDialogTextStyle
		<28>	 9/12/95	DM		1280020 FB1 part trans dlg mem leaks
		<27>	  9/7/95	CG		#1229981 FB2:No Trans dlg when no
									translators are installed.
		<26>	 8/30/95	EL		1279451: Translation dialog problem if
									exception thrown.
		<25>	 8/25/95	eeh		1230007: new param to DrawITextInDlogBox
		<24>	 8/24/95	CC		1242669,1279966,1279963: Fixes to
									ShowTranslationDialog.
		<23>	 8/23/95	CC		1242581: ShowTranslateDialog: Copy selected
									editor on return if OK button pressed.
		<22>	 7/28/95	CC		1258538: Remove declaration of
									GetFromAndToKinds.
		<21>	 7/26/95	DM		#1270320: Memory leak fixes.
		<20>	 6/21/95	CC		1260937: BB: ODTypeListIterator must return
									copies of ODType values.
		<19>	 6/16/95	CC		1258538: ShowTranslateDialog: Release kind
									and editor menu resources; also check
									GetMenu result; Added TRY block.
									Added GetOrderedCollectionElement.
									Removed GetFromAndToKinds.
									1259356: ShowPartTranslateDialog:
									ChangeKind or externalize before attempting
									translation.
									1259719: ShowPartTranslateDialog: Use
									ChangeKindAndEditor.
									Added #includes of OrdColl.h and
									StdTypIO.h.
		<18>	  6/7/95	jpa		Fixed EndUsingLibRsrcs calls. [1255369]
		<17>	  6/7/95	CC		1236299: Moved CUsingLibraryResources call
									from ShowPartTranslateDialog to
									ShowTranslateDialog.  Wrapped other uses of
									resource manager with
									BeginUsingLibraryResources and
									EndUsingLibraryResources.
		<16>	  6/2/95	CC		1236617: Use CreateTypeList factory method.
		<15>	 5/26/95	VL		1251403: Multithreading naming support.
		<14>	 5/18/95	CG		#1249263 BB: BndNSUtl.cpp does not compile
									standalone.
		<13>	  5/1/95	CG		#1240845	BB: Kinds popups need to include
									all kinds that an editor can edit.
		<12>	 4/25/95	CC		1242555: $5 entered as bug 1242666.
									1242555: ShowTranslateDialog: $5 entered as
									bug 1242669.
		<11>	 4/14/95	T‚		#1235279 BB: InfoUtil & StdTypIO functions
									should take Environment* and SU* when
									possible
		<10>	 3/28/95	CC		1229640: Added forPaste parameter to
									ShowTranslateDialog.
									DrawEditorName calls DrawITextInDlogBox
									utility.
		 <9>	 3/28/95	CC		1233117: Removed unused ODStorageUnit
									parameter from  ShowPartTranslateDialog.
									1232850: Fixed bug causing crash.
		 <8>	 3/27/95	CC		1229640: Split ShowTranslateDialog() into
									two methods: ShowPartTranslateDialog() and
									ShowPartTranslateDialog().  Many changes to
									support display from Paste As dialog.
		 <7>	  3/6/95	jpa		Use dialog utilities (ODGetNewDialog,
									ODDialogFilterProc) to make dlogs movable.
									[1218957]
		 <6>	 1/12/95	jpa		Don't use obsolete Toolbox names [1211211]
		 <5>	 1/10/95	CG		1197870: If no Part is root and TransDlg is
									dismissed, close document.
		 <4>	12/23/94	JBS		1186869: hide ODPartWrapper from public
									API; 1192557: ODPartWrapper realPart access
		 <3>	12/20/94	CG		#1207346: Switching editors was crashing.
		 <2>	12/13/94	CG		#1187128: Added StorageUnit and PartWrapper
									parameters to ShowTranslateDialog().
		 <1>	11/17/94	CG		first checked in
	To Do:
	In Progress:
		
*/

#ifndef _TRANSDLG_
#include "TransDlg.h"
#endif

#ifndef _TRNDLGDF_
#include <TrnDlgDf.h>
#endif

#ifndef _USERSRCM_
#include <UseRsrcM.h>
#endif

#ifndef __DIALOGS__
#include <Dialogs.h>
#endif

#ifndef SOM_ODSession_xh
#include <ODSessn.xh>
#endif

#ifndef SOM_ODPart_xh
#include <Part.xh>
#endif

#ifndef SOM_ODStorageSystem_xh
#include <ODStor.xh>
#endif

#ifndef SOM_ODStorageUnit_xh
#include <StorageU.xh>
#endif

#ifndef SOM_ODTypeList_xh
#include <TypeList.xh>
#endif

#ifndef SOM_ODTypeListIterator_xh
#include <TypLsItr.xh>
#endif

#ifndef _BINDNGH_
#include <BindngH.h>
#endif

#ifndef _BNDNSUTL_
#include <BndNSUtl.h>
#endif

#ifndef _ODUTILS_
#include <ODUtils.h>
#endif

#ifndef _PASCLSTR_
#include <PasclStr.h>
#endif

#ifndef _DLOGUTIL_
#include <DlogUtil.h>
#endif

#ifndef SOM_ODFrame_xh
#include <Frame.xh>
#endif

#ifndef SOM_ODWindowState_xh
#include <WinStat.xh>
#endif

#ifndef SOM_Module_OpenDoc_StdProps_defined
#include <StdProps.xh>
#endif

#ifndef SOM_Module_OpenDoc_StdTypes_defined
#include <StdTypes.xh>
#endif

#ifndef SOM_ODTranslation_xh
#include <Translt.xh>
#endif

#ifndef _EDITRSET_
#include <EditrSet.h>
#endif

#ifndef SOM_ODPartWrapper_xh
#include <PartWrap.xh>
#endif

#include <somcls.xh>
#include <somcm.xh>

#ifndef _ODMEMORY_
#include <ODMemory.h>
#endif

#ifndef __TEXTUTILS__
#include <TextUtils.h>
#endif

#ifndef _INFOUTIL_
#include <InfoUtil.h>
#endif

#ifndef _TRANSUTL_
#include <TransUtl.h>
#endif

#ifndef _ORDCOLL_
#include "OrdColl.h"
#endif

#ifndef _STDTYPIO_
#include "StdTypIO.h"
#endif

#ifndef _TEMPOBJ_
#include <TempObj.h>
#endif

#ifndef _ISOSTR_
#include <ISOStr.h>
#endif

#pragma segment TransDlg

//==============================================================================
// Constants
//==============================================================================

const Boolean kNoDefaultButton = kODFalse;

const short kControlInactive = 255;
const short kControlActive = 0;

//==============================================================================
// Scalar Types
//==============================================================================

//==============================================================================
// Local Classes
//==============================================================================

//==============================================================================
// Global Variables
//==============================================================================

// Use a global to pass the editor name to DrawEditorName
ODStatic ODName* gEditorName = kODNULL;

//==============================================================================
// Function Prototype
//==============================================================================
ODStatic void DisposeGlobalODNameAndZeroPtr(ODName** name);

ODStatic pascal void DrawEditorName(DialogPtr dialog, SInt16 item);

ODStatic ODType GetTypeListItem(ODTypeList* typeList, ODUShort index);

ODStatic ODUShort GetOrderedCollectionElement(OrderedCollection* collection, ODUShort index);

//==============================================================================
// Local Functions
//==============================================================================

//------------------------------------------------------------------------------
// DisposeGlobalODNameAndZeroPtr
//------------------------------------------------------------------------------
ODStatic void DisposeGlobalODNameAndZeroPtr(ODName** name)
{
	if (*name)
	{
		// simple way to force deletion of old name value without knowing
		// that DisposeIText is the right way to destroy an ODName:
		TempODName tempName = *name;
		*name = kODNULL;
	}
}

//------------------------------------------------------------------------------
// DrawEditorName
//------------------------------------------------------------------------------

ODStatic pascal void DrawEditorName(DialogPtr dialog, SInt16 item)
{
	short			itemType;
	Handle			itemHandle;
	Rect			itemRect;

	GetDialogItem(dialog, item, &itemType, &itemHandle, &itemRect);

	if ( gEditorName )
		DrawITextInDlogBox(gEditorName, &itemRect, dialog, kODTrue);
}

//------------------------------------------------------------------------------
// GetTypeListItem 
//------------------------------------------------------------------------------

ODStatic ODType GetTypeListItem(ODTypeList* typeList, ODUShort index)
{
	Environment* ev = somGetGlobalEnvironment();
	ODType theType = kODNULL;

	if ( index > 0 )
	{
		ODTypeListIterator* typeIter = typeList->CreateTypeListIterator(ev);
	
		for (theType = typeIter->First(ev);
			 (typeIter->IsNotComplete(ev)) && (index > 1);
			 theType = typeIter->Next(ev), --index)
		{
			ODDisposePtr(theType);
		}
	
		delete typeIter;
	}
	
	return theType;
}

//------------------------------------------------------------------------------
// GetOrderedCollectionElement
//------------------------------------------------------------------------------

ODStatic ODUShort GetOrderedCollectionElement(OrderedCollection* collection, ODUShort index)
{
	OrderedCollectionIterator* oci = collection->CreateIterator();

	ODUShort elem = 0;

	for (	elem = (ODUShort) oci->First();
			oci->IsNotComplete(); 
			elem = (ODUShort) oci->Next() )
	{
		if ( --index == 0 )
			break;
	}

	ODDeleteObject(oci);

	return elem;
}

//------------------------------------------------------------------------------
// InitialEditorSetup
//------------------------------------------------------------------------------
// On entry, kindIndex identifies the preferred kind in kindList.
// Returns in kindIndex the index into kindList of a type for which editors are
// available.  If none are available, kindIndex is unchanged, and the returned
// editor set is empty.
ODStatic EditorSet* InitialEditorSetup(
						ODTypeList*		kindList,
						ODUShort*		kindIndex,
						MenuHandle		editorMenu, 
						ControlHandle	popupCtlHndl, 
						ODSession*		session)
{
	// Create an empty editor list
	EditorSet* editorList = new EditorSet;
	editorList->InitEditorSet();

	Environment* ev = somGetGlobalEnvironment();

	ODUShort kindItems = kindList->Count(ev);

	if ( (*kindIndex > 0) && (*kindIndex <= kindItems) )
	{
	 	TempODType initialKind = GetTypeListItem(kindList, *kindIndex);
	 	if ( initialKind )
			SetupEditorMenu(initialKind, editorList, editorMenu, popupCtlHndl, session);
	 }

	// If the initial kind is supported by at least one editor, 
	// or there is no other kind, return
	if ( (editorList->GetEditorCount() > 0) || (kindItems < 2) )
		return editorList;

	ODUShort index = 1;
	ODTypeListIterator* iter = kindList->CreateTypeListIterator(ev);

	TempODType kind = kODNULL;
	for (kind = iter->First(ev);
		 iter->IsNotComplete(ev);
		 kind = iter->Next(ev))
	{
		if ( SetupEditorMenu(kind, editorList, editorMenu, popupCtlHndl, session) )
		{
			*kindIndex = index;
			break;
		}
		ODDisposePtr(kind);
		kind = kODNULL;
		++index;
	}
	delete iter;

	return editorList;
}	

//------------------------------------------------------------------------------
// IndexOfSupportedKind
//------------------------------------------------------------------------------
// On entry, kindIndex identifies the preferred kind in kindList.
// Returns in kindIndex the index into kindList of a type for which editors are
// available.  If no editor is available for any kind, kindIndex is unchanged
// and false is returned.
ODStatic ODBoolean IndexOfSupportedKind(
						ODTypeList*			kindList,
						ODUShort*			kindIndex,
						ODEditor			editorID,
						ODNameSpaceManager*	nsm)
{
	Environment* ev = somGetGlobalEnvironment();

	ODUShort kindItems = kindList->Count(ev);

	if ( (*kindIndex > 1) && (*kindIndex <= kindItems) )
	{
	 	TempODType initialKind = GetTypeListItem(kindList, *kindIndex);
	 	if ( EditorSupportsKind(nsm, editorID, initialKind) )
	 		return kODTrue;
	 }

	ODBoolean result = kODFalse;
	ODUShort index = 1;
	ODTypeListIterator* iter = kindList->CreateTypeListIterator(ev);

	TempODType kind = kODNULL;
	for (kind = iter->First(ev);
		 iter->IsNotComplete(ev);
		 kind = iter->Next(ev))
	{
	 	if ( EditorSupportsKind(nsm, editorID, kind) )
		{
			*kindIndex = index;
			result = kODTrue;
			break;
		}
		ODDisposePtr(kind);
		kind = kODNULL;
		++index;
	}
	delete iter;

	return result;
}	

//==============================================================================
// Class TranslationDialog
//==============================================================================

//------------------------------------------------------------------------------
// TranslationDialog::TranslationDialog
//------------------------------------------------------------------------------
TranslationDialog::TranslationDialog()
{
	fSession = kODNULL;
}

//------------------------------------------------------------------------------
// TranslationDialog::~TranslationDialog
//------------------------------------------------------------------------------
TranslationDialog::~TranslationDialog()
{
}

//------------------------------------------------------------------------------
// TranslationDialog::InitTranslationDialog
//------------------------------------------------------------------------------
void TranslationDialog::InitTranslationDialog(ODSession* session)
{
	fSession = session;
}

//------------------------------------------------------------------------------
// TranslationDialog::ShowPartTranslateDialog
//------------------------------------------------------------------------------
ODBoolean  TranslationDialog::ShowPartTranslateDialog(ODPartWrapper* partWrapper)
{
	Environment *ev = somGetGlobalEnvironment();
	ODTypeList*	kindList = kODNULL;
	ODTypeList*	translateToList = kODNULL;
	OrderedCollection* translateFromList = kODNULL;
	
	ODVolatile(kindList);
	ODVolatile(translateToList);
	ODVolatile(translateFromList);

	ODBoolean translationSuccessful = kODFalse;

	TRY
		ODBinding* binding = fSession->GetBinding(ev);
		ODNameSpaceManager* nsm = fSession->GetNameSpaceManager(ev);
		ODStorageUnit* storageUnit = partWrapper->GetStorageUnit(ev);
		
		// Create the list of kinds and translations
		kindList = fSession->GetStorageSystem(ev)->CreateTypeList(ev, (ODTypeList*) kODNULL);
		
		ContentValueTypes(storageUnit, kindList);

		{ TempODEditor tempEditor = GetCurrentEditorForPart(partWrapper);
		  GetAllKindsForEditor(nsm, kindList, tempEditor);
		}

		translateToList = fSession->GetStorageSystem(ev)->CreateTypeList(ev, (ODTypeList*) kODNULL);
		
		translateFromList = new OrderedCollection;
		
		GetDestinationKindsList(kindList, translateToList, translateFromList, fSession);
		
		if (translateToList->Count(ev) == 0)
		{
			TempODName 		partName	= ODGetPOName(ev, partWrapper,0);
			Str255	 partNameString = "\p";
			GetITextPString( partName, partNameString );

			ParamText(partNameString, "\p", "\p", "\p");
	
			fSession->GetWindowState(ev)->DeactivateFrontWindows(ev);
			ShowAlert(ev, kODNoTransAlert, GetODButtonKeyFilterProc(), fSession);
			fSession->GetWindowState(ev)->ActivateFrontWindows(ev);
		}
		else
		{
			fSession->GetWindowState(ev)->DeactivateFrontWindows(ev);
		
			ODUShort selectedKind = 0;
			ODEditor editorID = kODNULL;
			ODBoolean result = this->ShowTranslateDialog(translateToList, 
															&selectedKind, 
															&editorID,
															kODTrue,
															kODFalse);
		
			TempODEditor tempEditorID = editorID; // make sure it is deleted eventually
			
			fSession->GetWindowState(ev)->ActivateFrontWindows(ev);
		
			if ( result )
			{
				TempODType toKind = GetTypeListItem(translateToList, selectedKind);
				TempODType fromKind = GetTypeListItem(kindList, GetOrderedCollectionElement(translateFromList, selectedKind));
	
				if ( fromKind && toKind )
				{
					// If fromKind does not yet exist, force part to change to that kind.
					// Otherwise, force the part to externalize any changes to its storage unit.
					if ( !storageUnit->Exists(ev, kODPropContents, fromKind, 0) )
						partWrapper->ChangeKind(ev, fromKind);
					else
						partWrapper->Externalize(ev);
	
					storageUnit->Focus(ev, kODPropContents, kODPosUndefined, fromKind, 0, kODPosUndefined);
					TempODStorageUnitView fromView = storageUnit->CreateView(ev);
					
					storageUnit->Focus(ev, kODPropContents, kODPosAll, kODTypeAll, 0, kODPosUndefined);
	
					storageUnit->AddValue( ev, toKind );
					TempODStorageUnitView toView = storageUnit->CreateView(ev);
					
					ODTranslation* translation = fSession->GetTranslation(ev);
			
					translation->TranslateView(ev, fromView, toView);
					
					ChangeKindAndEditor(ev, partWrapper, toKind, editorID, nsm);
	
					translationSuccessful = kODTrue;
				}
			}
		}
	
	CATCH_ALL
		WARN("ShowPartTranslateDialog caught exception %d\n", ErrorCode());
		ODDeleteObject(kindList);
		ODDeleteObject(translateToList);
		ODDeleteObject(translateFromList);
		RERAISE;
	ENDTRY

	delete kindList;
	delete translateToList;
	delete translateFromList;

	return translationSuccessful;
}

//------------------------------------------------------------------------------
// TranslationDialog::ShowTranslateDialog
//------------------------------------------------------------------------------
ODBoolean  TranslationDialog::ShowTranslateDialog(
				ODTypeList*	translateToList,
				ODUShort*	selectedKind,
				ODEditor*	editor,
				ODBoolean	canChangeEditor,
				ODBoolean	forPaste)
{
	short      		itemHit = kODTransCancelBtn;
	short			itemType;
	Handle			itemHandle;
	ControlHandle	kindPopupControlHandle;
	ControlHandle	editorPopupControlHandle;
	Rect			itemRect;
	Rect			editorPopupRect;
	ODBoolean		translationSuccessful = kODFalse;
	Environment 	*ev = somGetGlobalEnvironment();
	ODUShort		selectedEditor = 0;
	ODSLong			refSaved;
	OSErr			resErr;
	ODUShort		kindIndex = ( *selectedKind > 0 ? *selectedKind : 1);

	DialogPtr  		dlg;						ODVolatile(dlg);
	WindowPtr		savePort;					ODVolatile(savePort);
	UserItemUPP		DrawEditorNameUPP = kODNULL;ODVolatile(DrawEditorNameUPP);
	EditorSet*		editorList = kODNULL;		ODVolatile(editorList);
	MenuHandle		kindMenu = kODNULL;			ODVolatile(kindMenu);
	MenuHandle		editorMenu = kODNULL;		ODVolatile(editorMenu);
	
	{
		CUsingLibraryResources r;
		dlg  = ODGetNewDialog(ev, (forPaste ? kODTransDlgID : kODPartTransDlgID), fSession, kNoDefaultButton);
	}

	if (dlg)
	{
		GetPort(&savePort);
		TRY
			SetPort(dlg);
	
			{ CUsingLibraryResources r;
				SetDialogTextStyle(dlg, (forPaste ? kODTransDlgID : kODPartTransDlgID),
						smCurrentScript);
			}
	
			// Initialize control handles
			GetDialogItem(dlg, kODTransKindPopup, &itemType, (Handle*) &kindPopupControlHandle, &itemRect);
			GetDialogItem(dlg, kODTransEditorPopup, &itemType, (Handle*) &editorPopupControlHandle, &editorPopupRect);
	
			// Set the draw routine for the default button outline item
			GetDialogItem(dlg, kODTransDefaultButtonOutline, &itemType, &itemHandle, &itemRect);
			SetDialogItem(dlg, kODTransDefaultButtonOutline, itemType, (Handle)GetODOutlineDefaultButtonDrawProc(), &itemRect);
	
			// Set up Kind Menu
			refSaved = BeginUsingLibraryResources();
			kindMenu = GetMenu(kODTransKindMenu);
			resErr = ResError();
			EndUsingLibraryResources(refSaved);
			THROW_IF_NULL(kindMenu, resErr ? resErr : resNotFound);
	
			if (translateToList->Count(ev) == 0 )
			{
				AppendMenu(kindMenu, "\p");
				HiliteControl(kindPopupControlHandle, kControlInactive);
			}
			else
			{
				AddTypesToMenu(translateToList, kindMenu, fSession);
				if ( !canChangeEditor )
					EnableTypesInMenu(translateToList, kindMenu, *editor, fSession->GetNameSpaceManager(ev));
			}
			SetControlMinimum(kindPopupControlHandle, 1);
			SetControlMaximum(kindPopupControlHandle, translateToList->Count(ev));
	
			// Set up Editor Menu
			refSaved = BeginUsingLibraryResources();
			editorMenu = GetMenu(kODTransEditorMenu);
			resErr = ResError();
			EndUsingLibraryResources(refSaved);
			THROW_IF_NULL(editorMenu, resErr ? resErr : resNotFound);
	
			// If an editor was specified, display that editor as static text in place
			// of the popup, and disable translation kinds not supported by the editor
			if ( canChangeEditor )
			{
				// Pick a supported kind and create the editor list
				editorList = InitialEditorSetup(
									translateToList,
									&kindIndex,
									editorMenu, 
									editorPopupControlHandle, 
									fSession);

				ODBoolean anyEditor = (editorList->GetEditorCount() > 0);
				EnableOkButton(dlg, anyEditor);

				if ( anyEditor )
				{
					if ( *editor != kODNULL )
						selectedEditor = IndexOfEditorInList(editorList, *editor);
					if ( selectedEditor == 0 )
						selectedEditor = 1;
		
					SetControlValue(editorPopupControlHandle, selectedEditor);
						
					HideDialogItem(dlg, kODTransEditorLabel);
					HideDialogItem(dlg, kODTransEditorText);
					HideDialogItem(dlg, kODTransNoEditorText);
				}
				else
				{
					HideDialogItem(dlg, kODTransEditorPopup);
					HideDialogItem(dlg, kODTransEditorText);
				}
			}
			else
			{
				// Pick a supported kind
				ODBoolean anyKindSupported = IndexOfSupportedKind(
									translateToList, 
									&kindIndex, 
									*editor, 
									fSession->GetNameSpaceManager(ev));
				
				EnableOkButton(dlg, anyKindSupported);

				// Set text of static editor item
				DisposeGlobalODNameAndZeroPtr(&gEditorName);
				if ( GetUserEditorFromEditor(fSession->GetNameSpaceManager(ev), *editor, &gEditorName) )
				{
					GetDialogItem(dlg, kODTransEditorText, &itemType, &itemHandle, &itemRect);
					DrawEditorNameUPP = NewUserItemProc(DrawEditorName);
					SetDialogItem(dlg, kODTransEditorText, userItem+itemDisable, (Handle) DrawEditorNameUPP, &itemRect);
				}
	
				HideDialogItem(dlg, kODTransEditorPopup);
				HideDialogItem(dlg, kODTransNoEditorText);
			}
	
			SetControlValue(kindPopupControlHandle, kindIndex);

			ShowWindow(dlg);

			do {
				refSaved = BeginUsingLibraryResources();
				ModalDialog(GetODButtonKeyFilterProc(), &itemHit);
				EndUsingLibraryResources(refSaved);
	
				switch (itemHit)
				{
					case kODTransKindPopup:
						ODSShort kindItem = (ODUShort) GetControlValue(kindPopupControlHandle);
						if (kindItem != kindIndex)
						{
							if ( canChangeEditor )
							{
								TempODEditor selectedEditorID = GetThisEditorFromList(selectedEditor, editorList);

								editorList->RemoveAllEditors();
								TempODType toKind = GetTypeListItem(translateToList, kindItem);
								ODBoolean anyEditors = SetupEditorMenu(
															toKind,
															editorList, 
															editorMenu, 
															editorPopupControlHandle, 
															fSession);
								EnableOkButton(dlg, anyEditors);
								
								ODUShort newEditor = (ODUShort) GetControlValue(editorPopupControlHandle);
								ODSShort selectedEditor = IndexOfEditorInList(editorList, selectedEditorID);

								if ( (selectedEditor != 0 ) && (newEditor != selectedEditor) )
								{
									CUsingLibraryResources r;
									SetControlValue(editorPopupControlHandle, selectedEditor);
								}
								else
								{
									selectedEditor = newEditor;
									SetPort(dlg);
									InvalRect(&editorPopupRect);	// Redraw the popup
								}
							}
							kindIndex = kindItem;
						}
						break;
	
					case kODTransEditorPopup:
						selectedEditor = (ODUShort) GetControlValue(editorPopupControlHandle);
						break;
	
					default:
						break;
				}
			} while ( (itemHit != kODTransOKBtn) && (itemHit != kODTransCancelBtn) );
	
			if ( itemHit == kODTransOKBtn ) 
			{
				*selectedKind = kindIndex;
				if ( canChangeEditor )
				{
					ODEditor newEditor = GetThisEditorFromList(selectedEditor, editorList);
					if ( newEditor )
					{
						ODDisposePtr((ODPtr) *editor);
						*editor = newEditor;
					}
				}
			}
	
		CATCH_ALL
			ODDeleteObject(editorList);
		
			ODDisposeRoutineDescriptor(DrawEditorNameUPP);
	
			refSaved = BeginUsingLibraryResources();
			if ( kindMenu )
			{
				DeleteMenu(kODTransKindMenu);
				ReleaseResource((Handle) kindMenu);
			}
			if ( editorMenu )
			{
				DeleteMenu(kODTransEditorMenu);
				ReleaseResource((Handle) editorMenu);
			}
			DisposeDialog(dlg);
			EndUsingLibraryResources(refSaved);

			DisposeGlobalODNameAndZeroPtr(&gEditorName);

			SetPort(savePort);
			RERAISE;
		ENDTRY

		ODDeleteObject(editorList);
	
		ODDisposeRoutineDescriptor(DrawEditorNameUPP);

		refSaved = BeginUsingLibraryResources();
		if ( kindMenu )
		{
			DeleteMenu(kODTransKindMenu);
			ReleaseResource((Handle) kindMenu);
		}
		if ( editorMenu )
		{
			DeleteMenu(kODTransEditorMenu);
			ReleaseResource((Handle) editorMenu);
		}
		DisposeDialog(dlg);
		EndUsingLibraryResources(refSaved);
	
		DisposeGlobalODNameAndZeroPtr(&gEditorName);

		SetPort(savePort);
	}

	return (itemHit == kODTransOKBtn);
}
