#include <windows.h>
#include <stdio.h>
#include <bncs_string.h>
#include <bncs_config.h>
#include "NamesEditor.h"

#define HOME_PAGE 1
#define NAME_EDIT 2
#define PACKAGE_EDIT 3

#define TIMER_SETUP	1
#define TIMER_UPDATE 2

#define TIMEOUT_COUNT 20

#define SOURCE_MAP_OFFSET 0		// Source button maps start at page 1 
#define DEST_MAP_OFFSET 100		// Destination button maps start at page 101
#define SRCGRP_MAP_OFFSET 200	// Mapping of source groups start at page 201
#define DESTGRP_MAP_OFFSET 250	// Mapping of destination groups starts at page 251

// ============================================================== //
// This little macro makes our class visible to the outside world //
// ============================================================== //
EXPORT_BNCS_SCRIPT( NamesEditor )

// ++++++++++++++++++++++++++++++++++++++++++++ //
// constructor - equivalent to ApplCore STARTUP //
// ++++++++++++++++++++++++++++++++++++++++++++ //
NamesEditor::NamesEditor( bncs_client_callback * parent, const char * path ) : bncs_script_helper( parent, path )
{
	// Initialize local variables to "safe" starting values.
	cta_sdi_id = 0;				// CTA SDI router BNCS device ID
	cta_audio_id = 0;			// CTA audio router BNCS device ID
	cta_tc_id = 0;				// CTA timecode router BNCS device ID
	cta_camstat_id = 0;			// CTA camera status router BNCS device ID
	cta_spare_id = 0;			// Spare half of timecode router
	sta_pal_id = 0;				// Studio A PAL matrix id
	cta_pkg_id = 0;				// CTA BNCS packager device id
	cta_pkg_src_info_id = 0;	// CTA BNCS packager source content infodriver
	cta_pkg_dst_info_id = 0;	// CTA BNCS packager destination content infodriver

	current_mtx = 0;
	current_dbase = 0;
	edit_index = 0;

	timer_enabled = false;		// Save edit timeout not active
	elementsEnabled = true;		// Initially the element selection buttons on PACKA_EDIT panel are active
	edit_active = false;		// Package content edit not active
	pkg_update_enable = false;	// The update button on the package content panel is not active

	curLevel = None;

	// Get the matrix ids from the Instances file
	getDev("CTA SDI Router", &cta_sdi_id);
	getDev("CTA Audio Router", &cta_audio_id);
	getDev("CTA Timecode Router", &cta_tc_id);
	getDev("CTA Cam Status Router", &cta_camstat_id);
	getDev("CTA BNCS Packager", &cta_pkg_id);
	getDev("CTA Spare Audio Router", &cta_spare_id);
	getDev("StA PAL Router", &sta_pal_id);

	// Initialise panels to enable them to receive data before they are displayed
	panelInit(HOME_PAGE, "FrontPage.bncs_ui");				// Edit function selctor
	panelInit(NAME_EDIT, "NameEdit.bncs_ui");				// Individual names editor
	panelInit(PACKAGE_EDIT, "packageedit.bncs_ui");			// Package contents editor
	
	// Disable the keyboard on the editor panel
	controlHide(NAME_EDIT, "KB");

	// Disable the Update and Restore buttons on the package edit panel
	controlDisable(PACKAGE_EDIT, "Update");
	controlDisable(PACKAGE_EDIT, "Restore");
	pkg_update_enable = false;

	// Show the home page
	panelShow(HOME_PAGE, "FrontPage.bncs_ui");

	// We need to have the device numbers for the combiner infodrivers. Whilst these are likely to be the combiner_ID +1, +2, and +3
	// it could be dangerous to make such an assumption. So we can use the windows library functions to read a token from an ini file.
	// First we need to build the file name of the INI file to be checked.
	myTemp = "%CC_ROOT%\\%CC_SYSTEM%\\config\\system\\DEV_%1.INI";	// Point to the basic file storage area
	myTemp = myTemp.arg(cta_pkg_id);								// Replace the %1 by id of packager
	ExpandEnvironmentStrings(myTemp, myFile, sizeof(myFile));		// Convert environment variable names into actual paths
	cta_pkg_src_info_id = GetPrivateProfileInt("Combiner", "SrcePkgInfoId", 0, myFile);	// Get the driver id of the Source Package infodriver
	cta_pkg_dst_info_id = GetPrivateProfileInt("Combiner", "DestPkgInfoId", 0, myFile);	// Get the driver id of the Source Package infodriver

	// Register for revertives from the CTA BNCS PACKAGER Source and Destination package infodrivers
	infoRegister(cta_pkg_src_info_id, 1, getRouterSize(cta_pkg_id, 0));
	infoRegister(cta_pkg_dst_info_id, 1, getRouterSize(cta_pkg_id, 1));

}	// End of function NamesEditor( bncs_client_callback * parent, const char * path )


// +++++++++++++++++++++++++++++++++++++++++++++ //
// Destructor - equivalent to ApplCore CLOSEDOWN //
// +++++++++++++++++++++++++++++++++++++++++++++ //
NamesEditor::~NamesEditor()
{
	if (timer_enabled)
	{
		timerStop(TIMER_UPDATE);
		timer_enabled = false;
	}

	infoUnregister(cta_pkg_src_info_id);
	infoUnregister(cta_pkg_dst_info_id);
}


// +++++++++++++++++++++++++++++++++++++++++++++ //
// All button pushes and notifications come here //
// +++++++++++++++++++++++++++++++++++++++++++++ //
void NamesEditor::buttonCallback( buttonNotify *b )
{
	switch (b->panel())
	{
		case HOME_PAGE:
			MatrixSelector(b);
			break;

		case NAME_EDIT:
			EditButtonProcess(b);
			break;

		case PACKAGE_EDIT:
			pkgEditProcess(b);
			break;
	}
	
}


// ++++++++++++++++++++++++ //
// All revertives come here //
// ++++++++++++++++++++++++ //
int NamesEditor::revertiveCallback( revertiveNotify * r )
{

	if (r->device() == cta_pkg_src_info_id)
	{
		// Source package Infodriver data is returned here. The string is a comma delimited string with - instead of zero for unused levels.
		// Only need to process revertive if the index matches the pkg edit index and the database is source and editing is enabled.
		if ((r->index() == pkg_index) && (pkg_dbase == 0) && edit_active)
		{
			elements = r->sInfo();				// Copy reply into a stringlist item
			src_v = elements[0].toInt();		// Split into the 4 elements we are interested in
			src_a = elements[1].toInt();
			src_k = elements[2].toInt();
			src_t = elements[3].toInt();

			idx_v = src_v;						// Load working memories with extracted data
			idx_a = src_a;
			idx_k = src_k;
			idx_t = src_t;

			textPut("text", src_v, PACKAGE_EDIT, "sdi_id");			// Display the data
			textPut("text", src_a, PACKAGE_EDIT, "audio_id");
			textPut("text", src_k, PACKAGE_EDIT, "key_id");
			textPut("text", src_t, PACKAGE_EDIT, "tc_id");
			routerName(cta_sdi_id, 0, src_v, myTemp);				// Get the name of the video element
			textPut("text", myTemp, PACKAGE_EDIT, "sdi_name");
			routerName(cta_audio_id, 0, src_a, myTemp);				// Get the name of the audio element
			textPut("text", myTemp, PACKAGE_EDIT, "audio_name");
			routerName(cta_sdi_id, 0, src_k, myTemp);				// Get the name of the key element
			textPut("text", myTemp, PACKAGE_EDIT, "key_name");
			routerName(cta_tc_id, 0, src_t, myTemp);				// Get the name of the timecode element
			textPut("text", myTemp, PACKAGE_EDIT, "tc_name");
		}

		return 0;
	}

	if (r->device() == cta_pkg_dst_info_id)
	{
		// Destination package Infodriver data is returned here. The string is a comma delimited string with - instead of zero for unused levels.
		// Only need to process revertive if the index matches the pkg edit index and the database is destinations and editing is enabled.
		if ((r->index() == pkg_index) && (pkg_dbase == 1) && edit_active)
		{
			elements = r->sInfo();				// Copy reply into a stringlist item
			dst_v = elements[0].toInt();		// Extract the 4 levels of interest
			dst_a = elements[1].toInt();
			dst_k = elements[2].toInt();
			dst_t = elements[3].toInt();

			idx_v = dst_v;						// Load working memories
			idx_a = dst_a;
			idx_k = dst_k;
			idx_t = dst_t;

			textPut("text", dst_v, PACKAGE_EDIT, "sdi_id");			// Display the data
			textPut("text", dst_a, PACKAGE_EDIT, "audio_id");
			textPut("text", dst_k, PACKAGE_EDIT, "key_id");
			textPut("text", dst_t, PACKAGE_EDIT, "tc_id");
			routerName(cta_sdi_id, 1, dst_v, myTemp);				// Get the name of the video element
			textPut("text", myTemp, PACKAGE_EDIT, "sdi_name");
			routerName(cta_audio_id, 1, dst_a, myTemp);				// Get the name of the audio element
			textPut("text", myTemp, PACKAGE_EDIT, "audio_name");
			routerName(cta_sdi_id, 1, dst_k, myTemp);				// Get the name of the key element
			textPut("text", myTemp, PACKAGE_EDIT, "key_name");
			routerName(cta_tc_id, 1, dst_t, myTemp);				// Get the name of the timecode element
			textPut("text", myTemp, PACKAGE_EDIT, "tc_name");
		}
		return 0;
	}

	return 0;	// Catch all return
}


// ++++++++++++++++++++++++++++++++++++++++ //
// All database name changes come back here //
// ++++++++++++++++++++++++++++++++++++++++ //
void NamesEditor::databaseCallback( revertiveNotify * r )
{
}


// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
// All parent notifications come here i.e. when this script is just one   //
// component of another dialog then our host might want to tell us things //
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
bncs_string NamesEditor::parentCallback( parentNotify *p )
{
	if( p->command() == "return" )
	{
		if( p->value() == "all" )
		{	// Persisting values for bncs_vis_ed
			bncs_stringlist sl;
			
			sl << bncs_string( "myParam=%1" ).arg( m_myParam );
			
			return sl.toString( '\n' );
		}

		else if( p->value() == "myParam" )
		{	// Specific value being asked for by a textGet
			return( bncs_string( "%1=%2" ).arg( p->value() ).arg( m_myParam ) );
		}

	}
	else if( p->command() == "instance" && p->value() != m_instance )
	{	// Our instance is being set/changed
		m_instance = p->value();
		//Do something instance-change related here
	}

	else if( p->command() == "myParam" )
	{	// Persisted value or 'Command' being set here
		m_myParam = p->value();
	}

	// ***** CONNECTIONS EVENTS HELPER LIST *****
	else if( p->command() == "_events" )
	{	// Helper-list of everything in this component generated by hostNotify's
		bncs_stringlist sl;

		sl << "notify=*";		
		
		return sl.toString( '\n' );
	}

	// ***** CONNECTIONS COMMANDS HELPER LIST *****
	else if( p->command() == "_commands" )
	{	// Helper-list of any commands/parameters you might want to set at run-time
		bncs_stringlist sl;
		
		sl << "myParam=[value]";
		
		return sl.toString( '\n' );
	}

	return "";
}

// ++++++++++++++++++++++++++ //
// All timer events come here //
// ++++++++++++++++++++++++++ //
void NamesEditor::timerCallback( int id )
{
	switch( id )
	{
		case TIMER_SETUP:
			timerStop(id);
			break;

		case TIMER_UPDATE:					// Used by the Update/Restore system on the name edit panel
			timeout_counter--;				// Decrement the timeout counter
			if (timeout_counter != 0)
			{
				// Toggle the highlights on the UPDATE and RESTORE buttons
				if (timeout_counter & 1)	// Find if the counter is Odd or Even
				{
					textPut("statesheet=WN_TakeLow", NAME_EDIT, "Update");
					textPut("statesheet=WN_TakeHigh", NAME_EDIT, "Restore");
				}
				else
				{
					textPut("statesheet=WN_TakeHigh", NAME_EDIT, "Update");
					textPut("statesheet=WN_TakeLow", NAME_EDIT, "Restore");
				}
			}
			else
			{
				// Terminate the count sequence and tidy the buttons. Execute a default RESTORE
				timerStop(TIMER_UPDATE);
				textPut("statesheet=WNSourceDeselected", NAME_EDIT, "Update");
				textPut("statesheet=WNSourceDeselected", NAME_EDIT, "Restore");
				// Do the restore actions
				controlDisable(NAME_EDIT, "Update");
				controlDisable(NAME_EDIT, "Restore");
				controlEnable(NAME_EDIT, "ShortName");
				controlEnable(NAME_EDIT, "LongName");
				textPut("text", "", NAME_EDIT, "Edited");			// Clear the text edited display
				controlEnable(NAME_EDIT, "BtnPage");
				controlEnable(NAME_EDIT, "BtnID");
				controlEnable(NAME_EDIT, "Home");
			}
			break;

		default:	// Unhandled timer event
			timerStop(id);
			break;
	}
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////// Callbacks above - Methods below ///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////

// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
// Function MatrixSelector(buttonNotify *b) handles button pushes on the //
// edit type (home) selection panel.                                     //
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
void NamesEditor::MatrixSelector(buttonNotify *b)
{
	// This function is called to select and configure the required editor screen.
	// All of the buttons on the homepage  have numeric IDs, so we can use a switch
	// statement to select between them.

	switch (b->id())
	{
		case 1:
			// Edit CTA SDI Source names
			current_mtx = cta_sdi_id;			// Using CTA SDI Router 
			current_dbase = 0;					// Sources database
			edit_index = 0;

			textPut("text", "CTA SDI Router", NAME_EDIT, "MatrixName");	// Put router data into editor controls
			
			SetEditButtons();							// Load the values for the matrix smart display buttons BtnPage mapdb offset page

			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 2:
			// Edit CTA Audio Source names
			current_mtx = cta_audio_id;			// Using CTA SDI Router
			current_dbase = 0;					// Sources database
			edit_index = 0;

			textPut("text", "CTA Audio Router", NAME_EDIT, "MatrixName");	// Put router data into editor controls

			SetEditButtons();							// Load the values for the matrix smart display buttons BtnPage mapdb offset page
			
			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 3:
			// Edit CTA Timecode Source names
			current_mtx = cta_tc_id;			// Using CTA SDI Router
			current_dbase = 0;					// Sources database
			edit_index = 0;

			textPut("text", "CTA Timecode Router", NAME_EDIT, "MatrixName");	// Put router data into editor controls

			SetEditButtons();					// Load the values for the matrix smart display buttons BtnPage mapdb offset page

			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 4:
			// Edit Studio A PAL router Source names
			current_mtx = sta_pal_id;			// Using CTA SDI Router
			current_dbase = 0;					// Sources database
			edit_index = 0;

			textPut("text", "Studio A PAL Router", NAME_EDIT, "MatrixName");	// Put router data into editor controls

			SetEditButtons();					// Load the values for the matrix smart display buttons BtnPage mapdb offset page

			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 5:
			// Edit CTA Camera Status Source names
			current_mtx = cta_camstat_id;		// Using CTA SDI Router
			current_dbase = 0;					// Sources database
			edit_index = 0;

			textPut("text", "CTA Camera Status", NAME_EDIT, "MatrixName");	// Put router data into editor controls

			SetEditButtons();					// Load the values for the matrix smart display buttons BtnPage mapdb offset page

			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 6:
			// Edit CTA Spare Audio Source names
			current_mtx = cta_spare_id;			// Using CTA SDI Router
			current_dbase = 0;					// Sources database
			edit_index = 0;

			textPut("text", "CTA Spare Audio", NAME_EDIT, "MatrixName");	// Put router data into editor controls

			SetEditButtons();					// Load the values for the matrix smart display buttons BtnPage mapdb offset page

			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 11:
			// Edit CTA SDI Destination names
			current_mtx = cta_sdi_id;			// Using CTA SDI Router
			current_dbase = 1;					// Destinations database
			edit_index = 0;

			textPut("text", "CTA SDI Router", NAME_EDIT, "MatrixName");	// Put router data into editor controls

			SetEditButtons();					// Load the values for the matrix smart display buttons BtnPage mapdb offset page

			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 12:
			// Edit CTA Audio Destination names
			current_mtx = cta_audio_id;			// Using CTA SDI Router
			current_dbase = 1;					// Destinations database
			edit_index = 0;

			textPut("text", "CTA Audio Router", NAME_EDIT, "MatrixName");	// Put router data into editor controls

			SetEditButtons();					// Load the values for the matrix smart display buttons BtnPage mapdb offset page

			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 13:
			// Edit CTA Timecode Destination names
			current_mtx = cta_tc_id;			// Using CTA SDI Router
			current_dbase = 1;					// Destinations database
			edit_index = 0;

			textPut("text", "CTA Timecode Router", NAME_EDIT, "MatrixName");	// Put router data into editor controls

			SetEditButtons();					// Load the values for the matrix smart display buttons BtnPage mapdb offset page

			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 14:
			// Edit Studio A PAL Destination names
			current_mtx = sta_pal_id;			// Using CTA SDI Router
			current_dbase = 0;					// Destinations database
			edit_index = 0;

			textPut("text", "Studio A PAL Router", NAME_EDIT, "MatrixName");	// Put router data into editor controls

			SetEditButtons();					// Load the values for the matrix smart display buttons BtnPage mapdb offset page

			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 15:
			// Edit CTA Camera Status Destination names
			current_mtx = cta_camstat_id;		// Using CTA SDI Router
			current_dbase = 1;					// Destinations database
			edit_index = 0;

			textPut("text", "CTA Camera Status", NAME_EDIT, "MatrixName");	// Put router data into editor controls

			SetEditButtons();					// Load the values for the matrix smart display buttons BtnPage mapdb offset page

			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 16:
			// Edit CTA Spare audio Destination names
			current_mtx = cta_spare_id;			// Using CTA SDI Router
			current_dbase = 0;					// Destinations database
			edit_index = 0;

			textPut("text", "CTA Spare Audio", NAME_EDIT, "MatrixName");	// Put router data into editor controls

			SetEditButtons();					// Load the values for the matrix smart display buttons BtnPage mapdb offset page

			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 21:
			// Edit CTA Packager Source names
			current_mtx = cta_pkg_id;			// Using CTA SDI Router
			current_dbase = 0;					// Sources database
			edit_index = 0;

			textPut("text", "CTA BNCS Package Router", NAME_EDIT, "MatrixName");	// Put router data into editor controls

			SetEditButtons();					// Load the values for the matrix smart display buttons BtnPage mapdb offset page

			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 22:
			// Edit CTA Packager Destination names
			current_mtx = cta_pkg_id;			// Using CTA SDI Router
			current_dbase = 1;					// Sources database
			edit_index = 0;

			textPut("text", "CTA BNCS Package Router", NAME_EDIT, "MatrixName");	// Put router data into editor controls

			SetEditButtons();					// Load the values for the matrix smart display buttons BtnPage mapdb offset page

			panelRemove(HOME_PAGE);						// Remove the home page panel
			panelShow(NAME_EDIT, "nameedit.bncs_ui");	// Display the edit panel
			break;

		case 23:		
			// Edit CTA Packager Source Contents
			hideElementSelector();											// Hide the element selector panel
			disableElementChose();											// Disable level seletion/edit buttons
			pkg_dbase = 0;													// Select source operations
			textPut("pixmap", "EditSource.png", PACKAGE_EDIT, "BG3");		// Select the required background panel for elements selector
			textPut("namesdb=4", PACKAGE_EDIT, "BtnPage");					// Select the source group names
			textPut("mapoffset", SRCGRP_MAP_OFFSET, PACKAGE_EDIT, "BtnPage");
			textPut("namesdb=0", PACKAGE_EDIT, "BtnID");					// Select source names
			textPut("mapoffset", SOURCE_MAP_OFFSET, PACKAGE_EDIT, "BtnID");
			textPut("button.001=released", PACKAGE_EDIT, "BtnPage");		// Select the first page of names
			
			panelRemove(HOME_PAGE);											// Remove the home page panel
			panelShow(PACKAGE_EDIT, "packageedit.bncs_ui");					// Display the edit panel
			break;

		case 24:
			// Edit CTA Packager Destination Contents
			hideElementSelector();											// Hide the element selector panel
			disableElementChose();											// Disable level seletion/edit buttons
			pkg_dbase = 1;													// Select destination operations
			textPut("pixmap", "EditDestination.png", PACKAGE_EDIT, "BG3");
			textPut("namesdb=5", PACKAGE_EDIT, "BtnPage");					// Select the destination group names
			textPut("mapoffset", DESTGRP_MAP_OFFSET, PACKAGE_EDIT, "BtnPage");
			textPut("namesdb=1", PACKAGE_EDIT, "BtnID");					// Select destination names
			textPut("mapoffset", DEST_MAP_OFFSET, PACKAGE_EDIT, "BtnID");
			textPut("button.001=released", PACKAGE_EDIT, "BtnPage");		// Select the first page of names

			panelRemove(HOME_PAGE);											// Remove the home page panel
			panelShow(PACKAGE_EDIT, "packageedit.bncs_ui");					// Display the edit panel
			break;

		case 25:
			// End the edit process
			// This may not be possible in version 4.5
			break;

		default:
			break;
	}
}


// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
// functionEditButtonProcess(buttonNotify *b) is called to action button //
// presses on the names editing functions.                               //
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
void NamesEditor::EditButtonProcess(buttonNotify *b)
{
	if (b->id() == "BtnPage")								// Request to change page?
	{
		textPut("page", b->value(), NAME_EDIT, "BtnID");	// Set the new page
		textPut("index=0", NAME_EDIT, "BtnID");				// Deselct any button on the name grid
		edit_index = 0;
		textPut("text", "---", NAME_EDIT, "ShortName");		// Blank the short name display
		textPut("text", "---", NAME_EDIT, "LongName");		// Blank the long name display

		return;
	}

	if (b->id() == "BtnID")
	{
		edit_index = b->value().toInt();								// Get the mapped button index
		routerName(current_mtx, current_dbase, edit_index, myTemp);		// Get the "Long" name from database 0 or 1
		textPut("text", myTemp, NAME_EDIT, "LongName");					// Show long name
		routerName(current_mtx, current_dbase+2, edit_index, myTemp);	// Get the "Short" name from database 2 or 3
		textPut("text", myTemp, NAME_EDIT, "ShortName");				// Show short name
		return;
	}

	if (b->id() == "Home")
	{
		panelRemove(NAME_EDIT);
		panelShow(HOME_PAGE, "FrontPage.bncs_ui");
		return;
	}

	if (b->id() == "ShortName")
	{
		if (edit_index != 0)		// Only edit if there is a selected button
		{
			// Initiate the edit process for a short name (database 2 or 3)
			controlDisable(NAME_EDIT, "Home");						// Disable the "Home" button

			textGet("text", NAME_EDIT, "ShortName", RestoreName);	// Read the current name setting
			textPut("text", RestoreName, NAME_EDIT, "KB");			// Put it in the keyboard
			controlDisable(NAME_EDIT, "BtnPage");					// Disable the group selector
			controlDisable(NAME_EDIT, "BtnID");						// Disable the item selector
			controlDisable(NAME_EDIT, "ShortName");
			controlDisable(NAME_EDIT, "LongName");
			maxlength = 8;
			dbase_offset = current_dbase + 2;						// Identify the short source/destination database
			returnBtnID = "ShortName";
			controlShow(NAME_EDIT, "KB");							// Show the keyboard 
			textPut("setFocus", NAME_EDIT, "KB");					// Give it focus ready for text input from an external keyboard
		}

		return;
	}

	if (b->id() == "LongName")
	{
		if (edit_index != 0)		// Only edit if there is a selected button
		{
			// Initiate the edit process for a long name (database 0 or 1)
			controlDisable(NAME_EDIT, "Home");						// Disable the "Home" button

			textGet("text", NAME_EDIT, "LongName", RestoreName);	// Read the current name setting
			textPut("text", RestoreName, NAME_EDIT, "KB");			// Put it in the keyboard
			controlDisable(NAME_EDIT, "BtnPage");					// Disable the group selector
			controlDisable(NAME_EDIT, "BtnID");						// Disable the item selector
			controlDisable(NAME_EDIT, "ShortName");
			controlDisable(NAME_EDIT, "LongName");
			maxlength = 16;
			dbase_offset = current_dbase;							// Identify the long source/destination database
			returnBtnID = "LongName";
			controlShow(NAME_EDIT, "KB");							// Show the keyboard 
			textPut("setFocus", NAME_EDIT, "KB");					// Give it focus ready for text input from an external keyboard
		}

		return;
	}

	if (b->id() == "KB")
	{
		// Process the returns from the keyboard. This includes both the letter being pressed and the return key
		// To process the data we need to know the text string
		if (b->sub(0) == "return")
		{
			// Return has been pressed - end the edit. We know that the string is not overlength because the else clause
			// of this if statement would have caught and corrected the length problem.
			textGet("text", NAME_EDIT, "KB", editedName);			// Read the current name from the keyboard
			textPut("text", editedName, NAME_EDIT, "Edited");		// Put the name in the relevant control
			textPut("text", "", NAME_EDIT, "KB");					// Clear keyboard text buffer
			controlHide(NAME_EDIT, "KB");
			controlEnable(NAME_EDIT, "Update");
			controlEnable(NAME_EDIT, "Restore");
			textPut("statesheet=WN_TakeHigh", NAME_EDIT, "Update");
			textPut("statesheet=WN_TakeLow", NAME_EDIT, "Restore");
			timeout_counter = TIMEOUT_COUNT;
			timerStart(TIMER_UPDATE, 500);
			timer_enabled = true;
		}
		else
		{
			// Read the text and validate the length. If too long, truncate the string
			textGet("text", NAME_EDIT, "KB", myTemp);
			if (myTemp.length() > (unsigned)maxlength)
			{
				myTemp = myTemp.left(maxlength);
				textPut("text", myTemp, NAME_EDIT, "KB");
			}
		}
		return;
	}

	if (b->id() == "Restore")
	{
		if (timer_enabled)
		{
			timerStop(TIMER_UPDATE);
			timer_enabled = false;
		}
		// Essentially an "Abandon this edit" button
		controlDisable(NAME_EDIT, "Update");				// So disable the Update button
		controlDisable(NAME_EDIT, "Restore");				// Disable the Restore button (ie the buttonpushed to activate this code)
		controlEnable(NAME_EDIT, "ShortName");
		controlEnable(NAME_EDIT, "LongName");
		textPut("text", "", NAME_EDIT, "Edited");			// Clear the text edited display
		controlEnable(NAME_EDIT, "BtnPage");
		controlEnable(NAME_EDIT, "BtnID");
		controlEnable(NAME_EDIT, "Home");

		return;
	}

	if (b->id() == "Update")
	{
		if (timer_enabled)
		{
			timerStop(TIMER_UPDATE);
			timer_enabled = false;
		}
		// Disable the action pushes
		controlDisable(NAME_EDIT, "Update");
		controlDisable(NAME_EDIT, "Restore");
		// Send the edited name to the network
		textPut("text", editedName, NAME_EDIT, returnBtnID);
		routerModify(current_mtx, dbase_offset, edit_index, editedName, false);		// Update the network, do NOT do a full dump of matrix.
		// Enable normal edit selector buttons
		controlEnable(NAME_EDIT, "ShortName");
		controlEnable(NAME_EDIT, "LongName");
		textPut("text", "", NAME_EDIT, "Edited");			// Clear the text edited display
		controlEnable(NAME_EDIT, "BtnPage");
		controlEnable(NAME_EDIT, "BtnID");
		controlEnable(NAME_EDIT, "Home");
		 
		return;
	}

}


// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
// pkgEditProcess(buttonNotify *b) is called to process actions for any buttons //
// pushed on the edit package content panel.                                    //
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
void NamesEditor::pkgEditProcess(buttonNotify *b)
{
	// This function handles the button pushes on the package contents editor
	
	if (b->id() == "BtnPage")		// Request to change page?
	{
		textPut("page", b->value(), PACKAGE_EDIT, "BtnID");				// Set the new page
		pkg_index = 0;
		textPut("index=0", PACKAGE_EDIT, "BtnID");						// Deselect any button on the name grid
		
		textPut("text", bncs_string(pkg_index), PACKAGE_EDIT, "PkgID");	// Put Page number into ID info box
		routerName(cta_pkg_id, (4 + pkg_dbase) , b->value(), myTemp);	// Get the group name
		sep_posn = myTemp.find('|');									// Check for a line break character
		if (sep_posn != -1)
		{
			// Line seperator found. If the previous character is a '/' just delete line seperator, else replace line seperator by a space
			myTemp.replace("|", " ");
			myTemp.replace("/ ", "/");
		}
		
		textPut("text", myTemp, PACKAGE_EDIT, "PkgGroup");				// Show the package group name in info box
		textPut("text", "---", PACKAGE_EDIT, "PkgName");				// Blank the package name display (as we have just forced no active package

		disableElementChose();
		return;
	}

	if (b->id() == "BtnID")
	{
		pkg_index = b->value().toInt();									// Get the mapped button index
		textPut("text", bncs_string(pkg_index), PACKAGE_EDIT, "PkgID");	// Put Page number into ID info box
		routerName(cta_pkg_id, pkg_dbase, pkg_index, myTemp);			// Get the "Long" name from database 0 or 1
		textPut("text", myTemp, PACKAGE_EDIT, "PkgName");				// Show long name

		if (pkg_index <= 0)
		{
			disableElementChose();			// Blank and disable the element selection panel
			hideElementSelector();
		}
		else
		{
			edit_active = true;											// Show that we are actively editing
			enableElementChose();										// Enable the element selector
			if (pkg_dbase == 0)
			{
				infoPoll(cta_pkg_src_info_id, pkg_index, pkg_index);	// Get source package string
			}
			if (pkg_dbase == 1)
			{
				infoPoll(cta_pkg_dst_info_id, pkg_index, pkg_index);	// Get destination package string
			}
			showElementSelector();
			controlDisable(PACKAGE_EDIT, "Home");						// Disable Home button
			controlDisable(PACKAGE_EDIT, "BtnPage");					// Disable Source group selection
			controlDisable(PACKAGE_EDIT, "BtnID");						// Disable indivdual source selector
			controlEnable(PACKAGE_EDIT, "Restore");
		}

		return;
	}

	if ((b->id() == "sdi_id") || (b->id() == "sdi_name"))
	{
		// Request to edit sdi level. Inhibit all other buttons
		use_level(Video);			// Display the sdi selector panel.
		if (!pkg_update_enable)
		{
			pkg_update_enable = true;
			controlEnable(PACKAGE_EDIT, "Update");
		}
		return;
	}

	// sdi_id sdi_name use_level(editLevels myLevel)
	if((b->id() == "audio_id") || (b->id() == "audio_name"))
	{
		// User pushed one of Audio id or Audio name buttons
		use_level(Audio);			// Display the audio selection panels
		if (!pkg_update_enable)
		{
			pkg_update_enable = true;
			controlEnable(PACKAGE_EDIT, "Update");
		}
		return;
	}

	if ((b->id() == "key_id") || (b->id() == "key_name"))
	{
		// User pushed one of Key id or Key name buttons
		use_level(Key);				// Display the SDI selector
		if (!pkg_update_enable)
		{
			pkg_update_enable = true;
			controlEnable(PACKAGE_EDIT, "Update");
		}
		return;
	}

	
	if ((b->id() == "tc_id") || (b->id() == "tc_name"))
	{
		// User pushed one of timecode id or timecode name buttons
		use_level(Timecode);		// Set up timecode selector panel
		if (!pkg_update_enable)
		{
			pkg_update_enable = true;
			controlEnable(PACKAGE_EDIT, "Update");
		}
		return;
	}


	if (b->id() == "sdiUsed")
	{
		no_element_selected();
		idx_v = 0;
		textPut("text", "0", PACKAGE_EDIT, "sdi_id");
		textPut("text", "---", PACKAGE_EDIT, "sdi_name");
		if (!pkg_update_enable)
		{
			pkg_update_enable = true;
			controlEnable(PACKAGE_EDIT, "Update");
		}
	}

	if (b->id() == "audioUsed")
	{
		no_element_selected();
		idx_a = 0;
		textPut("text", "0", PACKAGE_EDIT, "audio_id");
		textPut("text", "---", PACKAGE_EDIT, "audio_name");
		if (!pkg_update_enable)
		{
			pkg_update_enable = true;
			controlEnable(PACKAGE_EDIT, "Update");
		}
	}

	if (b->id() == "keyUsed")
	{
		no_element_selected();
		idx_k = 0;
		textPut("text", "0", PACKAGE_EDIT, "key_id");
		textPut("text", "---", PACKAGE_EDIT, "key_name");
		if (!pkg_update_enable)
		{
			pkg_update_enable = true;
			controlEnable(PACKAGE_EDIT, "Update");
		}
	}

	if (b->id() == "tcUsed")
	{
		no_element_selected();
		idx_t = 0;
		textPut("text", "0", PACKAGE_EDIT, "tc_id");
		textPut("text", "---", PACKAGE_EDIT, "tc_name");
		if (!pkg_update_enable)
		{
			pkg_update_enable = true;
			controlEnable(PACKAGE_EDIT, "Update");
		}
	}


	if (b->id() == "ElementGrp")
	{
		// Copy returned index into page property of ElementID
		textPut("page", b->value(), PACKAGE_EDIT, "ElementID");
		textPut("index=0", PACKAGE_EDIT, "ElementID");
		return;
	}

	if (b->id() == "ElementID")
	{
		// Action depends on the current active level held in variable curLevel. b->value() gives the index of the element

		switch (curLevel)
		{
			case None:
				break;

			case Video:
				if (b->value() > 0)
				{
					idx_v = b->value();										// Note the index reported
					textPut("text", idx_v, PACKAGE_EDIT, "sdi_id");			// Update the index for the video level
					routerName(cta_sdi_id, pkg_dbase, idx_v, myTemp);		// Look up the name
					textPut("text", myTemp, PACKAGE_EDIT, "sdi_name");		// Display the name
				}
				break;

			case Audio:
				if (b->value() > 0)
				{
					idx_a = b->value();										// Note the index reported
					textPut("text", idx_a, PACKAGE_EDIT, "audio_id");		// Update the index for the video level
					routerName(cta_audio_id, pkg_dbase, idx_a, myTemp);		// Look up the name
					textPut("text", myTemp, PACKAGE_EDIT, "audio_name");	// Display the name
				}
				break;

			case Key:
				if (b->value() > 0)
				{
					idx_k = b->value();										// Note the index reported
					textPut("text", idx_k, PACKAGE_EDIT, "key_id");			// Update the index for the video level
					routerName(cta_sdi_id, pkg_dbase, idx_k, myTemp);		// Look up the name
					textPut("text", myTemp, PACKAGE_EDIT, "key_name");		// Display the name
				}
				break;

			case Timecode:
				if (b->value() > 0)
				{
					idx_t = b->value();										// Note the index reported
					textPut("text", idx_t, PACKAGE_EDIT, "tc_id");			// Update the index for the video level
					routerName(cta_tc_id, pkg_dbase, idx_t, myTemp);		// Look up the name
					textPut("text", myTemp, PACKAGE_EDIT, "tc_name");		// Display the name
				}
				break;
		}

		return;
	}

	if (b->id() == "Restore")
	{
		//	Do not store any updated values, hide the element selector, clear and disable the level select pads
		no_element_selected();
		hideElementSelector();
		disableElementChose();
		controlEnable(PACKAGE_EDIT, "BtnPage");
		controlEnable(PACKAGE_EDIT, "BtnID");
		textPut("index=0", PACKAGE_EDIT, "BtnID");
		textPut("text=0", PACKAGE_EDIT, "PkgID");
		textPut("text","---", PACKAGE_EDIT, "PkgName");
		edit_active = false;
		pkg_update_enable = false;
		controlDisable(PACKAGE_EDIT, "Update");
		controlDisable(PACKAGE_EDIT, "Restore");
		controlEnable(PACKAGE_EDIT, "Home");								// Enable the return to home page
	}

	if (b->id() == "Update")
	{
		// Need to form a string from the selected level data, and send to the relevant infodriver slot.
		// We can then set the panel ready for more editing.

		newPkg = (idx_v == 0) ? "-," : bncs_string("%1,").arg(idx_v);		// Build output string with '-' in place of 0
		newPkg += (idx_a == 0) ? "-," : bncs_string("%1,").arg(idx_a);
		newPkg += (idx_k == 0) ? "-," : bncs_string("%1,").arg(idx_k);
		newPkg += (idx_t == 0) ? "-," : bncs_string("%1,").arg(idx_t);

		no_element_selected();
		hideElementSelector();
		disableElementChose();
		controlEnable(PACKAGE_EDIT, "BtnPage");
		controlEnable(PACKAGE_EDIT, "BtnID");
		textPut("index=0", PACKAGE_EDIT, "BtnID");
		textPut("text=0", PACKAGE_EDIT, "PkgID");
		textPut("text", "---", PACKAGE_EDIT, "PkgName");
		edit_active = false;
		pkg_update_enable = false;
		controlDisable(PACKAGE_EDIT, "Update");
		controlDisable(PACKAGE_EDIT, "Restore");
		controlEnable(PACKAGE_EDIT, "Home");								// Enable the return to home page

		// Send new string to relevant infodriver
		if (pkg_dbase == 0)	infoWrite(cta_pkg_src_info_id, newPkg, pkg_index, true);	// Send new source package string
		if (pkg_dbase == 1)	infoWrite(cta_pkg_dst_info_id, newPkg, pkg_index, true);	// Send new destination package string
	}


	if (b->id() == "Home")
	{
		panelRemove(PACKAGE_EDIT);
		panelShow(HOME_PAGE, "FrontPage.bncs_ui");
		return;
	}

	return;
}	// Endo of function EditButtonProcess()


// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
// SetEditButtons() is called to set the matrix data displays //
// required in name edit processes.                           //
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
void NamesEditor::SetEditButtons(void)
{
	// Before calling this function, the local variables current_mtx and current_dbase (source=0, 1=destination) must be set to target values

	textPut("text", current_mtx, NAME_EDIT, "DeviceID");				// Display the matrix properties
	textPut("text", current_dbase, NAME_EDIT, "DB_Index");				// on the top of the edit panel
	textPut("text", "---", NAME_EDIT, "ShortName");						// Clear the long and short names
	textPut("text", "---", NAME_EDIT, "LongName");

	// Group selection panel
	textPut("device", current_mtx, NAME_EDIT, "BtnPage");				// Tell the smart group selector which matrix data to use
	textPut("device.map", current_mtx, NAME_EDIT, "BtnPage");
	textPut("namesdb", current_dbase + 4, NAME_EDIT, "BtnPage");		// Select the source or destination group names
	textPut("mapdb", "8", NAME_EDIT, "BtnPage");
	textPut("mapoffset", 200 + (50 * current_dbase), NAME_EDIT, "BtnPage");
	textPut("page", "1", NAME_EDIT, "BtnPage");

	// Item selection panel
	textPut("device", current_mtx, NAME_EDIT, "BtnID");					// Tell the source selector which matrix data to show
	textPut("device.map", current_mtx, NAME_EDIT, "BtnID");
	textPut("namesdb", current_dbase, NAME_EDIT, "BtnID");				// Choose database for names display
	textPut("mapdb", "8", NAME_EDIT, "BtnID");							// Use database 8 for the mapping operations
	textPut("mapoffset", 100 * current_dbase, NAME_EDIT, "BtnID");		// Set offset to either 0 (sources) or 100 (destinations)
	textPut("page", "1", NAME_EDIT, "BtnID");							// Select page 1
	textPut("index=0", NAME_EDIT, "BtnID");								// Ensure no button is pressed

	textPut("button.001=released", NAME_EDIT, "BtnPage");				// Select page 1 of button array by pushing the button
	controlDisable(NAME_EDIT, "Update");
	controlDisable(NAME_EDIT, "Restore");
}	// End of function SetEditButtons()


// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
// function hideElementSelector() hides the group and name selector //
// panels used during package editing.                              //
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
void NamesEditor::hideElementSelector(void)
{
	// Disable the element selectors on the package edit page
	controlHide(PACKAGE_EDIT, "BG2");
	controlHide(PACKAGE_EDIT, "ElementGrp");
	controlHide(PACKAGE_EDIT, "ElementID");
}	// End of function hideElementSelector()


// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
// function showElementSelector() displays the group and name selector //
// panels used during package editing.                                 //
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
void NamesEditor::showElementSelector(void)
{
	// Disable the element selctors on the package edit page
	controlShow(PACKAGE_EDIT, "BG2");
	controlShow(PACKAGE_EDIT, "ElementGrp");
	controlShow(PACKAGE_EDIT, "ElementID");
}	// End of function showElementSelector()


// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
// function disableElementChoose() disables the element selector //
// panel used during package editing.                            //
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
void NamesEditor::disableElementChose(void)
{
	textPut("text", "-", PACKAGE_EDIT, "sdi_id");
	textPut("text", "-", PACKAGE_EDIT, "audio_id");
	textPut("text", "-", PACKAGE_EDIT, "key_id");
	textPut("text", "-", PACKAGE_EDIT, "tc_id");
	textPut("text", "---", PACKAGE_EDIT, "sdi_name");
	textPut("text", "---", PACKAGE_EDIT, "audio_name");
	textPut("text", "---", PACKAGE_EDIT, "key_name");
	textPut("text", "---", PACKAGE_EDIT, "tc_name");
	controlDisable(PACKAGE_EDIT, "sdiUsed");
	controlDisable(PACKAGE_EDIT, "audioUsed"); 
	controlDisable(PACKAGE_EDIT, "keyUsed"); 
	controlDisable(PACKAGE_EDIT, "tcUsed"); 
	controlDisable(PACKAGE_EDIT, "sdi_id");
	controlDisable(PACKAGE_EDIT, "audio_id");
	controlDisable(PACKAGE_EDIT, "key_id");
	controlDisable(PACKAGE_EDIT, "tc_id");
	controlDisable(PACKAGE_EDIT, "sdi_name");
	controlDisable(PACKAGE_EDIT, "audio_name");
	controlDisable(PACKAGE_EDIT, "key_name");
	controlDisable(PACKAGE_EDIT, "tc_name");
	elementsEnabled = false;
}	// End of function disableElementChose()


// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
// function enableElementChoose() enables the element selector //
// panel used during package editing.                          //
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
void NamesEditor::enableElementChose(void)
{
	controlEnable(PACKAGE_EDIT, "sdiUsed");
	controlEnable(PACKAGE_EDIT, "audioUsed");
	controlEnable(PACKAGE_EDIT, "keyUsed");
	controlEnable(PACKAGE_EDIT, "tcUsed");
	controlEnable(PACKAGE_EDIT, "sdi_id");
	controlEnable(PACKAGE_EDIT, "audio_id");
	controlEnable(PACKAGE_EDIT, "key_id");
	controlEnable(PACKAGE_EDIT, "tc_id");
	controlEnable(PACKAGE_EDIT, "sdi_name");
	controlEnable(PACKAGE_EDIT, "audio_name");
	controlEnable(PACKAGE_EDIT, "key_name");
	controlEnable(PACKAGE_EDIT, "tc_name");
	elementsEnabled = true;
}	// End of function enableElementChose()


// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
// function use_level(newlevel) is called to set the selector buttons //
// and record the new level for other functions.                      //
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
void NamesEditor::use_level(editLevels myLevel)
{
	// This function is called to inhibit the selector buttons for all but the level passed as a parameter
	// Configure the Element select buttons to show the relevent matrix data

	switch (myLevel)					// Need to know which matrix to use
	{
		case None:
			break;

		case Video:
			mtxid = cta_sdi_id;
			break;

		case Key:	
			mtxid = cta_sdi_id;			// Key is also an SDI signal
			break;

		case Audio:
			mtxid = cta_audio_id;
			break;

		case Timecode:
			mtxid = cta_tc_id;
			break;
	}

	if (myLevel == None)
	{
		curLevel = None;
		no_element_selected();
	}
	else
	{
		curLevel = myLevel;												// Keep a record of which level is in use
		textPut("device", mtxid, PACKAGE_EDIT, "ElementGrp");			// Set the matrix to use for names/ids
		textPut("device.map", mtxid, PACKAGE_EDIT, "ElementGrp");		// Set the matrix to use for names/ids
		textPut("namesdb", 4 + pkg_dbase, PACKAGE_EDIT, "ElementGrp");	// Set the database to use for names/ids (4 or 5)
		textPut("namesoffset", 0, PACKAGE_EDIT, "ElementGrp");
		textPut("mapoffset", 200 + (50 * pkg_dbase), PACKAGE_EDIT, "ElementGrp");
		textPut("device", mtxid, PACKAGE_EDIT, "ElementID");
		textPut("device.map", mtxid, PACKAGE_EDIT, "ElementID");
		textPut("namesdb", pkg_dbase, PACKAGE_EDIT, "ElementID");
		textPut("namesoffset", 0, PACKAGE_EDIT, "ElementID");
		textPut("mapoffset", 100 * pkg_dbase, PACKAGE_EDIT, "ElementID");
		textPut("button.001=released", PACKAGE_EDIT, "ElementGrp");	// Select the first group
	}
}	// End of function use_level()


// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
// function no_element_selected() is called to set the group and      //
// individual buttons of the element selector to blank.               //
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
void NamesEditor::no_element_selected(void)
{
	// This function is called to select no active matrix in the element selector.
	// This process is effected by selecting a silly set of mapping parameters that do not exist
	curLevel = None;												// No level active
	mtxid = 1;
	textPut("device", mtxid, PACKAGE_EDIT, "ElementGrp");
	textPut("device.map", mtxid, PACKAGE_EDIT, "ElementGrp");
	textPut("namesdb", 4 + pkg_dbase, PACKAGE_EDIT, "ElementGrp");
	textPut("namesoffset", 9999, PACKAGE_EDIT, "ElementGrp");
	textPut("mapoffset", 9999, PACKAGE_EDIT, "ElementGrp");
	textPut("device", mtxid, PACKAGE_EDIT, "ElementID");
	textPut("device.map", mtxid, PACKAGE_EDIT, "ElementID");
	textPut("namesdb", pkg_dbase, PACKAGE_EDIT, "ElementID");
	textPut("namesoffset", 9999, PACKAGE_EDIT, "ElementID");
	textPut("mapoffset", 9999, PACKAGE_EDIT, "ElementID");
}	// End of function no_element_selected()