//=========================================================================
// CPAKACnf.cpp : implementation of CPA_KeyActionConfiguration class
//
// Version			1.0
// Creation date	21/10/96
// Author:			Philippe Touillaud
//
// Revision date
// Author:          CB : To isolate from CPA project
//
// (c) Ubi Studios 1996
//
//=========================================================================

#include "stdafx.h"

#ifdef ACTIVE_EDITOR
#include "acp_base.h"
#include "itf/CPAKACnf.hpp"
#include "itf/A3dkeybo.hpp"
#include "itf/CPAProj.hpp"

//###########################################################################
// General Keyboard definition

#define C_szKeyboardIniSectionName		"Keyboard"

#define C_szIniCtrl		'^'
#define C_szKeyCtrl     "Ctrl"
#define C_szIniShift	'#'
#define C_szKeyShift    "Shift"
#define C_szTab			'\t'
//CPA2 Corneliu Babiuc (ALT key) 13-05-98
#define C_szIniAlt      '&'
#define C_szKeyAlt		"Alt"
//END CPA2 Corneliu Babiuc (ALT key) 13-05-98

// Status flags
#define C_cStatusNormal	(char)0
#define C_cStatusCombined	(char)1	// used in key combination. ex SHIFT

// Reserved use: these keys can't be chosen by the user, even combinated.
// Moreover, the actions associated to such keys in the ini file can't
// be modified.
#define C_cStatusReserved	(char)2

typedef struct tdstKeyDef_
{
	char            *p_szName;		// name used in INI file
	char			cValue;			// Virtual Key Code
	char	        cStatus;	    // Indicates reserved keys and combination keys (flags)
} tdstKeyDef;

//---------------------------------------------------------------
// Special key names used in INI file, and their Hexa equivalence
//---------------------------------------------------------------
static const tdstKeyDef      C_gs_a_stKeyDefTable[] =
{
	{"BACK",        (char)0x08, C_cStatusNormal},
	{"TAB",         (char)0x09, C_cStatusNormal},
	{"RETURN",      (char)0x0D, C_cStatusReserved},
	{"SHIFT",       (char)0x10, C_cStatusCombined},
	{"CONTROL",     (char)0x11, C_cStatusCombined},
//CPA2 Corneliu Babiuc (ALT key) 13-05-98
	{"ALT",         (char)0x12, C_cStatusCombined | C_cStatusReserved},
//	{"ALT",         0x12, C_cStatusCombined},
//END CPA2 Corneliu Babiuc (ALT key) 13-05-98
	{"PAUSE",       (char)0x13, C_cStatusNormal},
	{"ESCAPE",      (char)0x1B, C_cStatusReserved},
	{"CAPS_LOCK",   (char)0x14, C_cStatusReserved},
	{"VERR_NUM",    (char)0x90, C_cStatusReserved},
	{"SPACE",       (char)0x20, C_cStatusNormal},

	{"INS",         (char)0x2D, C_cStatusNormal},
	{"DEL",         (char)0x2E, C_cStatusNormal},
	{"END",         (char)0x23, C_cStatusNormal},
	{"HOME",        (char)0x24, C_cStatusNormal},
	{"PAGEUP",      (char)0x21, C_cStatusNormal},
	{"PAGEDOWN",    (char)0x22, C_cStatusNormal},

	{"LEFT",        (char)0x25, C_cStatusNormal},
	{"UP",          (char)0x26, C_cStatusNormal},
	{"RIGHT",       (char)0x27, C_cStatusNormal},
	{"DOWN",        (char)0x28, C_cStatusNormal},

	{"NUMPAD0",     (char)0x60, C_cStatusNormal},
	{"NUMPAD1",     (char)0x61, C_cStatusNormal},
	{"NUMPAD2",     (char)0x62, C_cStatusNormal},
	{"NUMPAD3",     (char)0x63, C_cStatusNormal},
	{"NUMPAD4",     (char)0x64, C_cStatusNormal},
	{"NUMPAD5",     (char)0x65, C_cStatusNormal},
	{"NUMPAD6",     (char)0x66, C_cStatusNormal},
	{"NUMPAD7",     (char)0x67, C_cStatusNormal},
	{"NUMPAD8",     (char)0x68, C_cStatusNormal},
	{"NUMPAD9",     (char)0x69, C_cStatusNormal},
	{"NUMPAD*",     (char)0x6A, C_cStatusNormal},
	{"NUMPAD+",     (char)0x6B, C_cStatusNormal},
	{"NUMPAD-",     (char)0x6D, C_cStatusNormal},
	{"NUMPAD.",     (char)0x6E, C_cStatusNormal},
	{"NUMPAD/",     (char)0x6F, C_cStatusNormal},

	{"F1",          (char)0x70, C_cStatusNormal},
	{"F2",          (char)0x71, C_cStatusNormal},
	{"F3",          (char)0x72, C_cStatusNormal},
	{"F4",          (char)0x73, C_cStatusNormal},
	{"F5",          (char)0x74, C_cStatusNormal},
	{"F6",          (char)0x75, C_cStatusNormal},
	{"F7",          (char)0x76, C_cStatusNormal},
	{"F8",          (char)0x77, C_cStatusNormal},
	{"F9",          (char)0x78, C_cStatusNormal},
	{"F10",         (char)0x79, C_cStatusNormal},
	{"F11",         (char)0x7A, C_cStatusNormal},
	{"F12",         (char)0x7B, C_cStatusNormal},

	{"²",           (char)0xDE, C_cStatusNormal},
/*	{"&",           0x31, C_cStatusNormal},	// 1 = "#&", etc...
	{"é",           0x32, C_cStatusNormal},
	{"\"",          0x33, C_cStatusNormal},	// " char
	{"'",           0x34, C_cStatusNormal},
	{"(",           0x35, C_cStatusNormal},
	{"-",           0x36, C_cStatusNormal},
	{"è",           0x37, C_cStatusNormal},
	{"_",           0x38, C_cStatusNormal},
	{"ç",           0x39, C_cStatusNormal},
	{"à",           0x30, C_cStatusNormal},*/
	{"°",           (char)0xDB, C_cStatusNormal},
	{"+",           (char)0xBB, C_cStatusNormal},
	{"^",           (char)0xDD, C_cStatusNormal},
	{"$",           (char)0xBA, C_cStatusNormal},
	{"%",           (char)0xC0, C_cStatusNormal},
	{"*",           (char)0xDC, C_cStatusNormal},
	{"<",           (char)0xE2, C_cStatusNormal},
	{"?",           (char)0xBC, C_cStatusNormal},
	{".",           (char)0xBE, C_cStatusNormal},
	{"/",           (char)0xBF, C_cStatusNormal},
	{"!",           (char)0xDF, C_cStatusNormal},

	{NULL, (char)0, C_cStatusNormal},	// end of the list: DO NOT REMOVE !
};

// System reserved key combinations
static const char *C_gs_a_stReservedKeyDefTable[] =
{
	"^F4",		// Windows "Close"
	"^F6",		// Windows "Next"
//CPA2 Corneliu Babiuc (Alt Key) 14-05-98
	"&F4",		// Close Application
	"&TAB",		// Switch windows
	"&SPACE",	// activate System menu
	"&F",		// activate File menu
	"&E",		// activate Edit menu
	"&D",		// activate Editors menu
	"&T",		// activate Tools menu
	"&V",		// activate 3DView menu
	"&S",		// activate Specific menu
	"&P",		// activate Preference menu
	"&H",		// activate Help menu
//END CPA2 Corneliu Babiuc (Alt Key) 19-05-98
	NULL,	    // end of the list: DO NOT REMOVE !
};


//###########################################################################
// Public functions

/////////////////////////////////////////////////////////////////////////////
// CPA_KeyActionConfiguration construction/destruction
CPA_KeyActionConfiguration::CPA_KeyActionConfiguration
(
    CString                 szFileIni,
    tdstKeyboardActionDef   *p_a_stKeybrdDef
)
{
	m_p_a_stKeybrdDef = p_a_stKeybrdDef;
    m_szFileIniName = szFileIni;
	m_eFileIniNameValid = UNKNOWN;
    M_GetMainApp()->m_lstKeyboard.AddTail(this);
    m_szObjectName = "Undefined Object Name";
    mfn_vUpdateKeyDefListFromIniFile();
}

CPA_KeyActionConfiguration::~CPA_KeyActionConfiguration()
{
    mfn_vRemoveEditorKeyDefList();
}

//===========================================================================
//      Description:    Sets a flag associated to a VK code. (the VK code
//						must be shift or control)
//		Creation date:	19 Jun 96
//		Author:			CB
//---------------------------------------------------------------------------
//		cVKCode			Virtual Key Code
//		p_cFlags		To receive flags
//      Return the flag set in *p_cFlags.
//---------------------------------------------------------------------------
//		Revision date:	21 oct 96
//						(inserted in CPA_KeyActionConfiguration Class)
//		Author:			Philippe Touillaud
//===========================================================================
void CPA_KeyActionConfiguration::mfn_vSetFlag(char cVKCode, char *p_cFlags)
{
	char cUnused;	// for the call only

	if(cVKCode == mfn_cIniStringToKey("SHIFT", &cUnused) )
	{
		mfn_vSetShift(p_cFlags);
	}

	if(cVKCode == mfn_cIniStringToKey("CONTROL", &cUnused) )
	{
		mfn_vSetCtrl(p_cFlags);
	}
//CPA2 Corneliu Babiuc (ALT key) 14-05-98
	if(cVKCode == mfn_cIniStringToKey("ALT", &cUnused) )
	{
		mfn_vSetAlt(p_cFlags);
	}
//END CPA2 Corneliu Babiuc (ALT key) 14-05-98
}

//===========================================================================
//		Description:	Checks if a key is currently used in the Key Def list
//						by the current editor.
//      Creation date:  30 oct 96
//      Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
BOOL CPA_KeyActionConfiguration::mfn_bKeyIsUsed(char cKey, char cFlags)
{
	return ( ( mfn_uwKeyToAction(cKey, cFlags) != 0) );
}

//===========================================================================
//		Description:	Checks if a key is used, excluding the application key
//						list: pre-defined windows keys, accelerator...
//						by the current editor.
//      Creation date:  30 oct 96
//      Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
BOOL CPA_KeyActionConfiguration::mfn_bKeyIsUsedOutside(char cKey, char cFlags)
{
	short   wIndex = 0;
	char	cRKey;
	char	cRFlags;

    while(C_gs_a_stReservedKeyDefTable[wIndex])
    {
		cRKey = mfn_cIniStringToKey(C_gs_a_stReservedKeyDefTable[wIndex], &cRFlags);
    	if((cRKey == cKey) && (cRFlags == cFlags))
		{
			return TRUE;
		}
		wIndex++;
    }

	return FALSE;
}

//===========================================================================
//		Description:	Checks if a key is reserved (in C_gs_a_stKeyDefTable)
//						If the key isn't in the table, it's considered as a
//						normal key (returns FALSE)
//      Creation date:  30 oct 96
//      Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
BOOL CPA_KeyActionConfiguration::mfn_bIsReserved(char cKey)
{
	short   wIndex = 0;

	// Searches the key
    while(C_gs_a_stKeyDefTable[wIndex].p_szName)
    {
    	if( cKey == C_gs_a_stKeyDefTable[wIndex].cValue )
		{
			// flag discrimination
    		return ( (C_gs_a_stKeyDefTable[wIndex].cStatus & C_cStatusReserved) != 0);
		}
		wIndex++;
    }

	return FALSE;
}

//===========================================================================
//		Description:	Checks if a key is a combination key (in
//						C_gs_a_stKeyDefTable)
//						If the key isn't in the table, it's considered as a
//						normal key (returns FALSE)
//      Creation date:  30 oct 96
//      Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
BOOL CPA_KeyActionConfiguration::mfn_bIsCombined(char cKey)
{
	short   wIndex = 0;

	// Searches the key
    while(C_gs_a_stKeyDefTable[wIndex].p_szName)
    {
    	if( cKey == C_gs_a_stKeyDefTable[wIndex].cValue )
		{
			// flag discrimination
    		return ( (C_gs_a_stKeyDefTable[wIndex].cStatus & C_cStatusCombined) != 0);
		}
		wIndex++;
    }

	return FALSE;
}

//===========================================================================
//      Description:    saves the current key list definition in the INI file,
//						using the correct strings (overwrites the existing).
//		Creation date:	24 oct 96
//		Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//		Revision date:
//		Author:
//===========================================================================
void CPA_KeyActionConfiguration::mfn_vUpdateIniFileFromKeyDefList(void)
{
    POSITION            stPos;
    CPA_KeyDefinition   *p_oCurrent;

	stPos = m_lstKeyDefinition.GetHeadPosition();
    while(stPos != NULL)
	{
    	p_oCurrent = m_lstKeyDefinition.GetAt(stPos);
 		mfn_bWriteProfileString
            (
				(LPCTSTR) mfn_oActionToIniString(p_oCurrent->m_uwAction),
				(LPCTSTR) mfn_oKeyToIniString(p_oCurrent->m_cKey, p_oCurrent->m_cFlags)
			);
    	m_lstKeyDefinition.GetNext(stPos);
    }
}

//===========================================================================
// To configure keyboard with a dialog.
//===========================================================================
void CPA_KeyActionConfiguration::mfn_vDialog(CWnd *pParent, CString szName)
{
    A3d_KeyboardConfDlg     oKeyConfDlg(pParent, szName);
	CList<CString, CString> oKeyStringList;

	mfn_vBuildStringList(&oKeyStringList);
	oKeyConfDlg.mfn_vSetStringList(&oKeyStringList);
	oKeyConfDlg.mfn_vSetKAConf(this);
	if(oKeyConfDlg.DoModal() == IDOK)
	{
		// Update key def list in memory
		mfn_vUpdateKeyDefListFromStringList(&oKeyStringList);
		// save changes to ini file
		mfn_vUpdateIniFileFromKeyDefList();
	}
}


//###########################################################################
//	Private functions
//###########################################################################


//===========================================================================
//      Description:    Defines all keyboard actions from the INI file.
//		Creation date:	24 oct 96
//		Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//		Revision date:
//		Author:
//===========================================================================
void CPA_KeyActionConfiguration::mfn_vUpdateKeyDefListFromIniFile(void)
{
    short   wIndex = 0;

	ASSERT(m_p_a_stKeybrdDef != NULL);

	// Add every entry
    while(m_p_a_stKeybrdDef[wIndex].p_szIniName)
    {
    	mfn_vAddKeyDefFromIniFile
            (
                m_p_a_stKeybrdDef[wIndex].p_szIniName,
				m_p_a_stKeybrdDef[wIndex].uwAction
			);
		wIndex++;
    }
}

//===========================================================================
//      Description:    Adds INI kAction definition to m_lstKeyDefinition.
//						(reads the entry in ini.file)
//      Creation date:  19 Jun 96
//      Author:         CB
//---------------------------------------------------------------------------
//      p_szDes         Reference in .INI file
//      uwAction        Action to associate with key
//      Return void
//---------------------------------------------------------------------------
//      Revision date:  21 oct 96
//							(inserted in CPA_KeyActionConfiguration Class)
//      Author:			Philippe Touillaud
//===========================================================================
void CPA_KeyActionConfiguration::mfn_vAddKeyDefFromIniFile(LPCTSTR p_szDes,unsigned short uwAction)
{
    CString         oValue;
    char            cValue;
    char            cFlags;
	WIN32_FIND_DATA stFileInfo;
    char			szPath[MAX_PATH];	


	if (m_eFileIniNameValid == INVALID)
		return;

	// look if the file exist somewhere...
	// and set the m_szFileIniName
	// normal search
	if (m_eFileIniNameValid == UNKNOWN)
	{
		sprintf(szPath, "%s", (LPCTSTR) m_szFileIniName);
		if (FindFirstFile(szPath,&stFileInfo) != INVALID_HANDLE_VALUE)
		{
			m_szFileIniName = szPath;
			m_eFileIniNameValid = VALID;
		}
	}
	
    // Search in current directory
	if (m_eFileIniNameValid == UNKNOWN)
	{
		sprintf(szPath, ".\\%s", (LPCTSTR) m_szFileIniName);
		if (FindFirstFile(szPath,&stFileInfo) != INVALID_HANDLE_VALUE)
		{
			m_szFileIniName = szPath;
			m_eFileIniNameValid = VALID;
		}
	}
	
    // Search in editor data directory
	if (m_eFileIniNameValid == UNKNOWN)
	{
		sprintf(szPath, "EDT_Data\\%s", (LPCTSTR) m_szFileIniName);
		if (FindFirstFile(szPath,&stFileInfo) != INVALID_HANDLE_VALUE)
		{
			m_szFileIniName = szPath;
			m_eFileIniNameValid = VALID;
		}
	}
	
    // Search in editor objects dll directory
	if (m_eFileIniNameValid == UNKNOWN)
	{
		sprintf(szPath, "EDT_Data\\Objects\\%s", (LPCTSTR) m_szFileIniName);
		if (FindFirstFile(szPath,&stFileInfo) != INVALID_HANDLE_VALUE)
		{
			m_szFileIniName = szPath;
			m_eFileIniNameValid = VALID;
		}
	}
	
    // Search in editor tools dll directory
	if (m_eFileIniNameValid == UNKNOWN)
	{
		sprintf(szPath, "EDT_Data\\Tools\\%s", (LPCTSTR) m_szFileIniName);
		if (FindFirstFile(szPath,&stFileInfo) != INVALID_HANDLE_VALUE)
		{
			m_szFileIniName = szPath;
			m_eFileIniNameValid = VALID;
		}
	}
	
	// Search in data directory
	if (m_eFileIniNameValid == UNKNOWN)
	{
		sprintf(szPath, "Data\\%s", (LPCTSTR) m_szFileIniName);
		if (FindFirstFile(szPath,&stFileInfo) != INVALID_HANDLE_VALUE)
		{
			m_szFileIniName = szPath;
			m_eFileIniNameValid = VALID;
		}
	}

	if (m_eFileIniNameValid == UNKNOWN)
	{
		sprintf (szPath,"Unable to find ini file ' %s '...",m_szFileIniName);
		AfxMessageBox(szPath,MB_ICONEXCLAMATION | MB_OK);
		m_eFileIniNameValid = INVALID;
		return;
	}

	// here, m_szFileIniName contains the path and file name to reach the ini file


	// Search key
    oValue = mfn_oGetProfileString(p_szDes);
	
    if(oValue == "")	// If string not found
        return;
	
    cValue = mfn_cIniStringToKey(oValue, &cFlags);
    ASSERT(cValue != 0);	// test whether the string in entry is valid
	
	m_lstKeyDefinition.AddTail(new CPA_KeyDefinition(cValue, cFlags, uwAction));
}

//===========================================================================
//		Description:    Returns action associated to a key (with flags)
//		Creation date:  23 oct 96
//		Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//		cKey            Key to test
//		cFlags          Associated flags
//		Return action (unsigned short) (0 if no action found)
//---------------------------------------------------------------------------
//		Revision date:
//		Author:
//===========================================================================
unsigned short CPA_KeyActionConfiguration::mfn_uwKeyToAction(char cKey)
{
    char    cFlags;

    cFlags = GetAsyncKeyState(VK_SHIFT) & 0x8000 ? C_KeybSHIFT : 0;
    cFlags |= GetAsyncKeyState(VK_CONTROL) & 0x8000 ? C_KeybCTRL : 0;
//CPA2 Corneliu Babiuc (ALT key) 14-05-98
	cFlags |= GetAsyncKeyState(VK_MENU) & 0x8000 ? C_KeybALT : 0;
//END CPA2 Corneliu Babiuc (ALT key) 14-05-98

    if((cKey == VK_SHIFT) || (cKey == VK_CONTROL))
        cFlags = 0;

    return mfn_uwKeyToAction(cKey, cFlags);
}

unsigned short CPA_KeyActionConfiguration::mfn_uwKeyToAction(char cKey, char cFlags)
{
    POSITION            stPos;
    CPA_KeyDefinition   *p_oCurrent;

	stPos = m_lstKeyDefinition.GetHeadPosition();
    while(stPos != NULL)
	{
    	p_oCurrent = m_lstKeyDefinition.GetAt(stPos);
    	if
            (
    		    (p_oCurrent->m_cKey == cKey)
    		&&  (p_oCurrent->m_cFlags == cFlags)
    		)
    	{
    		return p_oCurrent->m_uwAction;
    	}
    	m_lstKeyDefinition.GetNext(stPos);
    }
    return 0;
}

//===========================================================================
//		Description:    Returns key (with flags) associated to an action
//		Creation date:  23 oct 96
//		Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//		uwAction        Action to test
//		p_cFlags        returns flags associated with key
//		Return key (char) (0 if no key found) and flags through p_cFlags
//---------------------------------------------------------------------------
//		Revision date:
//		Author:
//===========================================================================
char CPA_KeyActionConfiguration::mfn_cActionToKey
(
    unsigned short  uwAction,
    char            *p_cFlags
)
{
    POSITION            stPos;
    CPA_KeyDefinition   *p_oCurrent;

	ASSERT(p_cFlags != NULL);
	*p_cFlags = 0;

	stPos = m_lstKeyDefinition.GetHeadPosition();
    while(stPos != NULL)
	{
    	p_oCurrent = m_lstKeyDefinition.GetAt(stPos);
    	if(p_oCurrent->m_uwAction == uwAction)
    	{
			*p_cFlags = p_oCurrent->m_cFlags;
    		return p_oCurrent->m_cKey;
    	}
    	m_lstKeyDefinition.GetNext(stPos);
    }
    return (char)(0);
}

//===========================================================================
//      Description:    Searches an entry in an INI file linked to the editor.
//      Creation date:  16 Sep 96
//      Author:         CB
//---------------------------------------------------------------------------
//      p_szDes         Reference in .INI file
//      Return CString associated with entry (empty string if entry not found)
//---------------------------------------------------------------------------
//      Revision date:  21 oct 96
//							(inserted in CPA_KeyActionConfiguration Class)
//      Author:			Philippe Touillaud
//===========================================================================
#define M_vGetProfile()\
    ::GetPrivateProfileString\
    (\
        C_szKeyboardIniSectionName,\
        p_szDes,\
        "",\
        oValue.GetBuffer(100),\
        100,\
	    m_szFileIniName\
    );

CString CPA_KeyActionConfiguration::mfn_oGetProfileString(LPCTSTR p_szDes)
{
    CString                 oValue;
	char					szTemp[255];

	ASSERT(p_szDes != NULL);

    M_vGetProfile();
    if(oValue != "")
        return oValue;

	sprintf (szTemp,"Unable to find the key ' %s '...",p_szDes);
	AfxMessageBox(szTemp,MB_ICONEXCLAMATION | MB_OK);

    return oValue;
}

//===========================================================================
//      Description:    Writes an entry in the INI file linked to the editor.
//						. if the reference doesn't exist, it is created.
//						. if the reference exists, it is overwrited.
//      Creation date:	21 oct 96
//      Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//      p_szDes         Reference in .INI file
//		p_oValue		key string definition to set for the reference
//		returns True if successful, False if not.
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
BOOL CPA_KeyActionConfiguration::mfn_bWriteProfileString
(
    LPCTSTR p_szDes,
    LPCTSTR p_szValue
)
{
	BOOL					bTemoinSucces;

	ASSERT(p_szDes != NULL);

	// writes the entry in the C_szKeyboardIniSectionName section
    bTemoinSucces = ::WritePrivateProfileString
        (
            C_szKeyboardIniSectionName,
            p_szDes,
            p_szValue,
            m_szFileIniName
        );
    return bTemoinSucces;
}

//===========================================================================
//      Description:    Converts an action in the Ini string as defined in
//						m_p_a_stKeybrdDef (after keyboard configuration)
//      Creation date:	21 oct 96
//      Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//		uwAction			KAction
//		returns the string associated ("" if no string associated)
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
CString CPA_KeyActionConfiguration::mfn_oActionToIniString(unsigned short uwAction)
{
	CString oResultat;
    short   wIndex = 0;

	ASSERT(m_p_a_stKeybrdDef != NULL);	// keyboard must be configured

	// search in the table
    while( m_p_a_stKeybrdDef[wIndex].p_szIniName )
    {
    	if ( m_p_a_stKeybrdDef[wIndex].uwAction == uwAction)
		{
			oResultat = m_p_a_stKeybrdDef[wIndex].p_szIniName;
			return oResultat;
		}
		wIndex++;
    }

	return oResultat;	// no entry found
}

//===========================================================================
//      Description:    Converts an Ini string in the action as defined in
//						m_p_a_stKeybrdDef (after configuration)
//      Creation date:	21 oct 96
//      Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//		p_oIniString		Ini string
//		returns the action associated (0 if no action asssociated)
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
unsigned short CPA_KeyActionConfiguration::mfn_uwIniStringToAction(const CString *p_oIniString)
{
	unsigned short  uwAction;
    short           wIndex = 0;

	ASSERT(m_p_a_stKeybrdDef != NULL);	// keyboard must be configured

	// search in the table
    while( m_p_a_stKeybrdDef[wIndex].p_szIniName )
    {
		if ( !p_oIniString->Compare(m_p_a_stKeybrdDef[wIndex].p_szIniName) )
		{
			uwAction = m_p_a_stKeybrdDef[wIndex].uwAction;
			return uwAction;
		}
		wIndex++;
    }

	return 0;	// no entry found
}

//===========================================================================
//      Description:    Converts an INI string to a keyboard reference.
//		Creation date:	19 Jun 96
//		Author:			CB
//---------------------------------------------------------------------------
//		p_szDes			Description of key
//		p_cFlags		To receive flags
//      Return char that is the keyboard reference (and the flags in
//		*p_cFlags), or 0 if error.
//---------------------------------------------------------------------------
//		Revision date:	21 oct 96
//						(inserted in CPA_KeyActionConfiguration Class)
//		Author:			Philippe Touillaud
//===========================================================================
char CPA_KeyActionConfiguration::mfn_cIniStringToKey(LPCTSTR p_szDes, char *p_cFlags)
{
    short   wIndex = 0;

    ASSERT(p_szDes != NULL);
	ASSERT(p_cFlags != NULL);

    // Flags
    *p_cFlags = (char)(0);

	// Look for possible Ctrl or Shift
	if(strlen(p_szDes) > 1)
    {
    	switch(*p_szDes)
    	{
    	case C_szIniCtrl:
			mfn_vSetCtrl(p_cFlags);
    		p_szDes++;
    		break;

    	case C_szIniShift:
			mfn_vSetShift(p_cFlags);
    		p_szDes++;
    		break;

//CPA2 Corneliu Babiuc (ALT key) 14-05-98
		case C_szIniAlt:
			mfn_vSetAlt(p_cFlags);
			p_szDes++;
			break;
//END CPA2 Corneliu Babiuc (ALT key) 14-05-98

    	case '~':
			p_szDes++;
    		break;
    	}
    }

	// Search if it's a special key
    while(C_gs_a_stKeyDefTable[wIndex].p_szName)
    {
    	// if the strings are identical (strcmpi returns 0)
		if(!strcmpi(C_gs_a_stKeyDefTable[wIndex].p_szName, p_szDes))
		{
    		return C_gs_a_stKeyDefTable[wIndex].cValue;
		}
		wIndex++;
    }

	// Uppercase
    return toupper(*p_szDes);
}

//===========================================================================
//		Description:	Converts a keyboard reference to an INI string.
//		The function tests whether the key is special only with the
//		predefined table C_gs_a_stKeyDefTable. If the use of the key
//		is effectively special, it must be in this table.
//      Creation date:  21 oct 96
//      Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//      cKey			Keyboard reference
//      p_cFlags		Flags associated
//      Return INI Description of key.
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
CString CPA_KeyActionConfiguration::mfn_oKeyToIniString(char cKey, char cFlags)
{
    short   wIndex = 0;
	CString szIniKey;

	// begins with specific char for Ctrl or Shift.
	if(mfn_bIsCtrlSet(cFlags))
	{
    	szIniKey += C_szIniCtrl;
	}

	if (mfn_bIsShiftSet(cFlags))
	{
    	szIniKey += C_szIniShift;
	}

//CPA2 Corneliu Babiuc (ALT key) 14-05-98
	//and now we search for ALT flag
	if (mfn_bIsAltSet(cFlags))
	{
    	szIniKey += C_szIniAlt;
	}
//CPA2 Corneliu Babiuc (ALT key) 14-05-98

	// Searches if it's a special key.
    while(C_gs_a_stKeyDefTable[wIndex].p_szName)
    {
		if(cKey == C_gs_a_stKeyDefTable[wIndex].cValue)
		{
    		szIniKey += C_gs_a_stKeyDefTable[wIndex].p_szName;
			return szIniKey;
		}
    	wIndex++;
    }

	// It's a normal key: add it uppercase
	szIniKey += (char)toupper(cKey);
    return szIniKey;
}

//===========================================================================
//      Description:    Converts a keyboard reference to an KEY string.
//		The function tests whether the key is special only with the
//		predefined table C_gs_a_stKeyDefTable. If the use of the key
//		is effectively special, it must be in this table.
//      Creation date:  29 jan 97
//      Author:         Marc Trabucato
//---------------------------------------------------------------------------
//      cKey			Keyboard reference
//      p_cFlags		Flags associated
//      Return KEY Description of key.
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
CString CPA_KeyActionConfiguration::mfn_oKeyToKeyString(char cKey, char cFlags)
{
    short   wIndex = 0;
    CString szKey;

	// begins with specific char for Ctrl or Shift.
	if(mfn_bIsCtrlSet(cFlags))
	{
        szKey += CString(C_szKeyCtrl) + "+";
	}

	if (mfn_bIsShiftSet(cFlags))
	{
        szKey += CString(C_szKeyShift) + "+";
	}

//CPA2 Corneliu Babiuc (ALT key) 14-05-98
	//and now we search for ALT flag
	if (mfn_bIsAltSet(cFlags))
	{
    	szKey += CString(C_szKeyAlt) + "+";
	}
//CPA2 Corneliu Babiuc (ALT key) 14-05-98

	// Searches if it's a special key.
    while(C_gs_a_stKeyDefTable[wIndex].p_szName)
    {
		if(cKey == C_gs_a_stKeyDefTable[wIndex].cValue)
		{
            szKey += C_gs_a_stKeyDefTable[wIndex].p_szName;
            return szKey;
		}
    	wIndex++;
    }

	// It's a normal key: add it uppercase
    szKey += (char)toupper(cKey);
    return szKey;
}

//===========================================================================
//      Description:    Build a list to be used by a graphic interface.
//		Creation date:	24 oct 96
//		Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//		p_oKeyStringList	Empty list to fill
//---------------------------------------------------------------------------
//		Revision date:
//		Author:
//===========================================================================
void CPA_KeyActionConfiguration::mfn_vBuildStringList
(
    CList<CString, CString> *p_oKeyStringList
)
{
    POSITION            stPos;
    CPA_KeyDefinition   *p_oCurrent;
	CString				oKeyString;

	ASSERT(p_oKeyStringList != NULL);

	stPos = m_lstKeyDefinition.GetHeadPosition();
    while(stPos != NULL)
	{
    	p_oCurrent = m_lstKeyDefinition.GetAt(stPos);
        oKeyString = mfn_oConvertKeyDefInString
            (
                p_oCurrent->m_cKey,
                p_oCurrent->m_cFlags,
                p_oCurrent->m_uwAction
            );
		p_oKeyStringList->AddTail(oKeyString);
    	m_lstKeyDefinition.GetNext(stPos);
    }
}

//===========================================================================
//      Description:    Changes the keyboard configuration, using the string
//						list (modified in the dialog interface).
//		Creation date:	24 oct 96
//		Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//		p_oKeyStringList	string list to decode
//---------------------------------------------------------------------------
//		Revision date:
//		Author:
//===========================================================================
void CPA_KeyActionConfiguration::mfn_vUpdateKeyDefListFromStringList
(
    CList<CString, CString> *p_oKeyStringList
)
{
    POSITION	    stPos;
 	CString		    oKeyString;
	char		    cKey;
	char		    cFlags;
	unsigned short	uwAction;

	ASSERT(p_oKeyStringList != NULL);

	// removes the definitions
	mfn_vRemoveEditorKeyDefList();

	// adds the new definitions
	stPos = p_oKeyStringList->GetHeadPosition();
    while(stPos != NULL)
	{
    	oKeyString = p_oKeyStringList->GetAt(stPos);
		cKey = mfn_cConvertStringInKeyDef(&oKeyString, &cFlags, &uwAction);
		m_lstKeyDefinition.AddTail(new CPA_KeyDefinition(cKey, cFlags, uwAction));
		p_oKeyStringList->GetNext(stPos);
    }
}

//===========================================================================
//      Description:    Converts a key Def in a string for the dialog interface
//      Creation date:	21 oct 96
//      Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//		cKey
//		cFlags
//		uwAction	key definition:(key, flags, and action linked)
//		returns the string "<Ini String>tab<Key String>"
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
CString CPA_KeyActionConfiguration::mfn_oConvertKeyDefInString
(
    char            cKey,
    char            cFlags,
    unsigned short  uwAction
)
{
	CString oResultat;

	oResultat = mfn_oActionToIniString(uwAction); // Ini String
	oResultat += C_szTab;		// tab
	oResultat += mfn_oKeyToIniString(cKey, cFlags);
	return oResultat;
}

//===========================================================================
//      Description:    Converts a string from the dialog interface in a
//							key definition
//      Creation date:	21 oct 96
//      Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//		p_oKeyString		string "<ini string>tab<keyString>"
//
//		p_cFlags			pointer to return flags
//		uwAction			pointer to return action
//		returns the key code, and the flags and action through pointers.
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
char CPA_KeyActionConfiguration::mfn_cConvertStringInKeyDef
(
    const CString   *p_oKeyString,
    char            *p_cFlags,
    unsigned short  *p_uwAction
)
{
	char	cKey;
	short	wIndexLeft;
	short	wIndexRight;
	CString	oIntermedString;

	ASSERT(p_oKeyString != 0);
	ASSERT(p_cFlags != 0);
	ASSERT(p_uwAction != 0);

	// cut the string, discarding the tab char
	wIndexLeft = p_oKeyString->Find(C_szTab);
	wIndexRight = p_oKeyString->GetLength() - wIndexLeft -1;

	// extracts the informations
	oIntermedString = p_oKeyString->Right(wIndexRight);
	cKey		    = mfn_cIniStringToKey(oIntermedString, p_cFlags);

	oIntermedString = p_oKeyString->Left(wIndexLeft);
	*p_uwAction	= mfn_uwIniStringToAction((const CString *) &oIntermedString);

	return cKey;
}

//===========================================================================
//      Description:    Removes all editor's CPA_KeyDefinitions in the list
//						m_lstKeyDefinition
//      Creation date:	21 oct 96
//      Author:			Philippe Touillaud
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
void CPA_KeyActionConfiguration::mfn_vRemoveEditorKeyDefList(void)
{
    POSITION            stPos;
    CPA_KeyDefinition   *p_oCurrent;

	stPos = m_lstKeyDefinition.GetHeadPosition();
    while(stPos != NULL)
	{
    	p_oCurrent = m_lstKeyDefinition.GetAt(stPos);
		delete p_oCurrent;
		m_lstKeyDefinition.RemoveAt(stPos);
		stPos = m_lstKeyDefinition.GetHeadPosition();
    }
}

//===========================================================================
//      Description:    Converts an INI string to a Key string
//      Creation date:  39 jan 97
//      Author:         Marc Trabucato
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//      Revision date:
//      Author:
//===========================================================================
CString CPA_KeyActionConfiguration::mfn_oConvertIniStringToKeyString
(
    const CString   *p_oIniString
)
{
    unsigned short  uwAction;
    char            cFlags;
    char            cKey;

    uwAction = mfn_uwIniStringToAction(p_oIniString);
    if( uwAction == 0 )
    {
        // action not founded
        return CString("");
    }
    cKey = mfn_cActionToKey(uwAction,&cFlags);

    return mfn_oKeyToKeyString(cKey,cFlags);
}

//###########################################################################

#endif // ACTIVE_EDITOR