// DriverSettings.cpp : implementation file
//

#include "stdafx.h"
#include "Ultima_C++Demo.h"
#include "MainSheet.h"
#include "DriverSettings1.h"
#include "DriverSettings2.h"
#include "HoloKotePreview.h"
#include "afxdialogex.h"

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

// CDriverSettings2 dialog
IMPLEMENT_DYNAMIC(CDriverSettings2, CPropertyPage)

CDriverSettings2::CDriverSettings2()
	: CPropertyPage(CDriverSettings2::IDD)
	, DvrAction(0)
{
	Initialised  = FALSE;
	_pPapers	 = NULL;
	_pPaperNames = NULL;
}

CDriverSettings2::~CDriverSettings2()
{
	if (_pPapers)	  delete [] _pPapers;
	if (_pPaperNames) delete [] _pPaperNames;
}

void CDriverSettings2::DoDataExchange(CDataExchange* pDX)
{
	CPropertyPage::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_DRIVERBOX2, Driver2Msg);
	DDX_Radio(pDX, IDC_GETACTIONRADIO_D2, DvrAction);
	DDV_MinMaxInt(pDX, DvrAction, 0, 1);
	DDX_Control(pDX, IDC_DUPLEX_COMBO, Duplex);
	DDX_Control(pDX, IDC_CARDSIZE_COMBO, CardSize);
	DDX_Control(pDX, IDC_COPYCOUNT, CopyCount);
	DDX_Control(pDX, IDC_COPYCOUNT_SPIN, CopyCount_Spin);
	DDX_Control(pDX, IDC_COLOURFORMAT_COMBO, ColourFormat);
	DDX_Control(pDX, IDC_ORIENTATION_COMBO, Orientation);
	DDX_Control(pDX, IDC_OVERCOAT, Overcoat);
	DDX_Control(pDX, IDC_ROTATE, Rotate);
	DDX_Control(pDX, IDC_CARDSETTINGS_SIDE, CardSettings_Side);
	DDX_Control(pDX, IDC_HOLOKOTEIMAGE, HoloKoteImage);
	DDX_Control(pDX, IDC_HOLOKOTEIMAGE_SPIN, HoloKoteImage_Spin);
	DDX_Control(pDX, IDC_HOLOKOTE_ROTATION, HoloKoteRotate);
	DDX_Control(pDX, IDC_HOLOKOTE_SIDE, HoloKote_Side);
	DDX_Control(pDX, IDC_HOLOKOTE_ID_SLOT, HoloKoteIDSlot);
	DDX_Control(pDX, IDC_COLOURAREA_NO, ColourArea_No);
	DDX_Control(pDX, IDC_COLOURAREA_SIDE, ColourArea_Side);
	DDX_Control(pDX, IDC_COLOURAREA_CORRECTION_COMBO, ColourArea_Correction);
	DDX_Control(pDX, IDC_COLOURAREA_LEFT, ColourArea_Left);
	DDX_Control(pDX, IDC_COLOURAREA_WIDTH, ColourArea_Width);
	DDX_Control(pDX, IDC_COLOURAREA_BOTTOM, ColourArea_Bottom);
	DDX_Control(pDX, IDC_COLOURAREA_HEIGHT, ColourArea_Height);
	DDX_Control(pDX, IDC_COLOURAREA_LEFT_SPIN, ColourArea_Left_Spin);
	DDX_Control(pDX, IDC_COLOURAREA_WIDTH_SPIN, ColourArea_Width_Spin);
	DDX_Control(pDX, IDC_COLOURAREA_BOTTOM_SPIN, ColourArea_Bottom_Spin);
	DDX_Control(pDX, IDC_COLOURAREA_HEIGHT_SPIN, ColourArea_Height_Spin);
	DDX_Control(pDX, IDC_COLOURAREA_NO_SPIN, ColourArea_No_Spin);
	DDX_Control(pDX, IDC_CONTRAST, ColAdj_Contrast);
	DDX_Control(pDX, IDC_BRIGHTNESS, ColAdj_Brightness);
	DDX_Control(pDX, IDC_COLOURFUL, ColAdj_Colour);
	DDX_Control(pDX, IDC_TINT, ColAdj_Tint);
	DDX_Control(pDX, IDC_COLOUR_R, ColAdj_Red);
	DDX_Control(pDX, IDC_COLOUR_G, ColAdj_Green);
	DDX_Control(pDX, IDC_COLOUR_B, ColAdj_Blue);
	DDX_Control(pDX, IDC_DARKPICTURE, ColAdj_DarkPic);
	DDX_Control(pDX, IDC_NEGATIVE, ColAdj_Negative);
	DDX_Control(pDX, IDC_ILLUMINANT_COMBO, ColAdj_Illuminant);
	DDX_Control(pDX, IDC_BLACKREF, ColAdj_BlackRef);
	DDX_Control(pDX, IDC_WHITE_REF, ColAdj_WhiteRef);
	DDX_Control(pDX, IDC_CONTRAST_SPIN, ColAdj_Contrast_Spin);
	DDX_Control(pDX, IDC_BRIGHTNESS_SPIN, ColAdj_Brightness_Spin);
	DDX_Control(pDX, IDC_COLOUR_SPIN, ColAdj_Colour_Spin);
	DDX_Control(pDX, IDC_TINT_SPIN, ColAdj_Tint_Spin);
	DDX_Control(pDX, IDC_COLOUR_R_SPIN, ColAdj_Red_Spin);
	DDX_Control(pDX, IDC_COLOUR_G_SPIN, ColAdj_Green_Spin);
	DDX_Control(pDX, IDC_COLOUR_B_SPIN, ColAdj_Blue_Spin);
	DDX_Control(pDX, IDC_BLACKREF_SPIN, ColAdj_BlackRef_Spin);
	DDX_Control(pDX, IDC_WHITEREF_SPIN, ColAdj_WhiteRef_Spin);
	DDX_Control(pDX, IDC_BTN_HOLOKOTEID, HoloKoteIDBtn);
}

BEGIN_MESSAGE_MAP(CDriverSettings2, CPropertyPage)
	ON_BN_CLICKED(IDC_BTN_DRIVERBOXCLEAR, &CDriverSettings2::OnBnClickedBtnDriverBoxClear)
	ON_BN_CLICKED(IDC_BTN_PRINTSETTINGS, &CDriverSettings2::OnBnClickedBtnPrintSettings)
	ON_BN_CLICKED(IDC_BTN_HOLOKOTE, &CDriverSettings2::OnBnClickedBtnHoloKote)
	ON_BN_CLICKED(IDC_BTN_CARDSETTINGS, &CDriverSettings2::OnBnClickedBtnCardSettings)
	ON_BN_CLICKED(IDC_GETACTIONRADIO_D2, &CDriverSettings2::OnBnClickedGetActionRadio)
	ON_BN_CLICKED(IDC_SETACTIONRADIO_D2, &CDriverSettings2::OnBnClickedSetActionRadio)
	ON_CBN_SELCHANGE(IDC_CARDSETTINGS_SIDE, &CDriverSettings2::OnCbnSelchangeCardSettings)
	ON_CBN_SELCHANGE(IDC_HOLOKOTE_SIDE, &CDriverSettings2::OnCbnSelchangeHoloKote)
	ON_BN_CLICKED(IDC_BTN_COLOURADJUST, &CDriverSettings2::OnBnClickedBtnColourAdjust)
	ON_BN_CLICKED(IDC_BTN_COLOURAREA, &CDriverSettings2::OnBnClickedBtnColourArea)
	ON_EN_CHANGE(IDC_COLOURAREA_NO, &CDriverSettings2::OnEnChangeColourAreaNo)
	ON_CBN_SELCHANGE(IDC_COLOURAREA_SIDE, &CDriverSettings2::OnCbnSelchangeColourArea)
	ON_BN_CLICKED(IDC_BTN_HOLOKOTEID, &CDriverSettings2::OnBnClickedBtnHoloKoteID)
	ON_BN_CLICKED(IDC_BTN_HOLOKOTEPREVIEW, &CDriverSettings2::OnBnClickedBtnHolokotePreview)
END_MESSAGE_MAP()

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

#define PAPERNAME_SIZE 64

// CDriverSettings2 message handlers
BOOL CDriverSettings2::OnInitDialog()
{
	CString temp_string;

	CPropertyPage::OnInitDialog();

	Parent = (CMainSheet *)GetParent();

	//Initialise the Controls on the Property Page...

	//Get Card Sizes from Printer
	_iPaperCount = DeviceCapabilities(DeviceName, NULL, DC_PAPERS, NULL, NULL);
	if (_iPaperCount)
	{
		//Determine size and allocate memory for 'Paper' IDs
		_pPapers = new WORD[_iPaperCount];
		SecureZeroMemory(_pPapers, sizeof(WORD) * _iPaperCount);

		//Get 'Paper' IDs
		DeviceCapabilities(DeviceName, NULL, DC_PAPERS, (LPTSTR)_pPapers, NULL);

		//Determine size and allocate memory for 'Paper' Names
		_pPaperNames = new TCHAR[_iPaperCount * PAPERNAME_SIZE];
		SecureZeroMemory(_pPaperNames, sizeof(TCHAR) * PAPERNAME_SIZE * _iPaperCount);

		//Get 'Paper' Names
		DeviceCapabilities(DeviceName, NULL, DC_PAPERNAMES, (LPTSTR)_pPaperNames, NULL);

		//Load 'Paper' Name strings into the control
		for (int i = 0; i < _iPaperCount; i++)
		{
			temp_string = CString((TCHAR *)&_pPaperNames[i * PAPERNAME_SIZE]);
			CardSize.AddString(temp_string);
		}
	}

	//...Print Settings
	PRINTSET PrintSettings;
	CopyCount_Spin.SetRange(1, 99);
	GetPrintSettings(&PrintSettings);

	//...Card Settings
	CARDSET CardSettings;
	CardSettings_Side.SetCurSel(0);
	GetCardSettings(ID_SIDE_FRONT, &CardSettings);

	//...HoloKote
	HOLOKOTE HoloKote;
	HoloKote_Side.SetCurSel(0);
	HoloKoteImage_Spin.SetRange(1, 10);
	GetHoloKote(ID_SIDE_FRONT, &HoloKote);

    //...HoloKote Identity
	HoloKoteIDSlot.SetCurSel(0);

	//...Colour Area
	COLCORRECT ColCorrect;
	AREA Area;
	ColourArea_Side.SetCurSel(0);
	ColourArea_No.SetWindowText(_T("1"));
	ColourArea_No_Spin.SetRange(1, 5);
	ColourArea_Left_Spin.SetRange(0, Parent->MaxXCoord());
	ColourArea_Width_Spin.SetRange(0, Parent->MaxCardWidth());
	ColourArea_Bottom_Spin.SetRange(0, Parent->MaxYCoord());
	ColourArea_Height_Spin.SetRange(0, Parent->MaxCardHeight());
	GetColourArea(ID_SIDE_FRONT, 1, &Area, &ColCorrect);

	//...Colour Adjust
	ColAdj_Illuminant.SetCurSel(0);
	ColAdj_Contrast_Spin.SetRange(-100, 100);
	ColAdj_Brightness_Spin.SetRange(-100, 100);
	ColAdj_Colour_Spin.SetRange(-100, 100);
	ColAdj_Tint_Spin.SetRange(-100, 100);
	ColAdj_Red_Spin.SetRange32(2500, 65000);
	ColAdj_Green_Spin.SetRange32(2500, 65000);
	ColAdj_Blue_Spin.SetRange32(2500, 65000);
	ColAdj_BlackRef_Spin.SetRange(0, 4000);
	ColAdj_WhiteRef_Spin.SetRange(6000, 10000);

	PCOLORADJUSTMENT pColAdjust = new COLORADJUSTMENT;
	GetColourAdjust(pColAdjust);
	delete pColAdjust;

	Initialised = TRUE;
	EnableGetSetControls(FALSE);
	return TRUE;  // return TRUE  unless you set the focus to a control
}

//****************************************************************************

void CDriverSettings2::EnableGetSetControls
(
	BOOL bControl
)
{
	Duplex.EnableWindow(bControl);
	CardSize.EnableWindow(bControl);
	CopyCount.EnableWindow(bControl);
	CopyCount_Spin.EnableWindow(bControl);
	ColourFormat.EnableWindow(bControl);
	Orientation.EnableWindow(bControl);
	Overcoat.EnableWindow(bControl);
	Rotate.EnableWindow(bControl);
	HoloKoteImage.EnableWindow(bControl);
	HoloKoteImage_Spin.EnableWindow(bControl);
	HoloKoteRotate.EnableWindow(bControl);
	
	HoloKoteIDSlot.EnableWindow(!bControl);
	HoloKoteIDBtn.EnableWindow(!bControl);

	ColourArea_Correction.EnableWindow(bControl);
	ColourArea_Left.EnableWindow(bControl);
	ColourArea_Width.EnableWindow(bControl);
	ColourArea_Bottom.EnableWindow(bControl);
	ColourArea_Height.EnableWindow(bControl);
	ColourArea_Left_Spin.EnableWindow(bControl);
	ColourArea_Width_Spin.EnableWindow(bControl);
	ColourArea_Bottom_Spin.EnableWindow(bControl);
	ColourArea_Height_Spin.EnableWindow(bControl);

	ColAdj_Contrast.EnableWindow(bControl);
	ColAdj_Brightness.EnableWindow(bControl);
	ColAdj_Colour.EnableWindow(bControl);
	ColAdj_Tint.EnableWindow(bControl);
	ColAdj_Red.EnableWindow(bControl);
	ColAdj_Green.EnableWindow(bControl);
	ColAdj_Blue.EnableWindow(bControl);
	ColAdj_DarkPic.EnableWindow(bControl);
	ColAdj_Negative.EnableWindow(bControl);
	ColAdj_Illuminant.EnableWindow(bControl);
	ColAdj_BlackRef.EnableWindow(bControl);
	ColAdj_WhiteRef.EnableWindow(bControl);
	ColAdj_Contrast_Spin.EnableWindow(bControl);
	ColAdj_Brightness_Spin.EnableWindow(bControl);
	ColAdj_Colour_Spin.EnableWindow(bControl);
	ColAdj_Tint_Spin.EnableWindow(bControl);
	ColAdj_Red_Spin.EnableWindow(bControl);
	ColAdj_Green_Spin.EnableWindow(bControl);
	ColAdj_Blue_Spin.EnableWindow(bControl);
	ColAdj_BlackRef_Spin.EnableWindow(bControl);
	ColAdj_WhiteRef_Spin.EnableWindow(bControl);
}

void CDriverSettings2::OnBnClickedGetActionRadio()
{
	EnableGetSetControls(FALSE);
}

void CDriverSettings2::OnBnClickedSetActionRadio()
{
	EnableGetSetControls(TRUE);
}

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

CString CDriverSettings2::CardSizeString(int CardSize)
{
	//Get the string description for the given card size
	for (int i = 0; i < _iPaperCount; i++)
	{
		if (_pPapers[i] == CardSize)
			return CString((TCHAR *)&_pPaperNames[i * PAPERNAME_SIZE]);
	}

	return CString(_T("Unknown Card Size"));
}

//****************************************************************************

void CDriverSettings2::PrintSettingsToMsgBox
(
	PPRINTSET    pPrintSettings,
	ID_READWRITE Action
)
{
	//Update the message box for the Print Settings
	CString temp_string;
	CString sep = Parent->Separator(Action);

	switch (pPrintSettings->Duplex)
	{
	case ID_FRONT_ONLY:	temp_string = _T("Front Only");    break;
	case ID_BOTH_SIDES:	temp_string = _T("Both Sides");    break;
	case ID_BACK_ONLY:	temp_string = _T("Back Only");     break;
	default:			temp_string = _T("**Undefined**"); break;
	}
	AddDriverMessage(_T("Duplex") + sep + temp_string);

	AddDriverMessage(_T("Card Size") + sep + CardSizeString(pPrintSettings->CardSize));

	temp_string.Format(_T("%d"), pPrintSettings->CopyCount);
	AddDriverMessage(_T("Copy Count") + sep + temp_string);
	AddDriverMessage(_T(""));
}

//****************************************************************************

void CDriverSettings2::SetPrintSettings(PPRINTSET pPrintSettings)
{
	//Update the controls for the Print Settings
	CString temp_string;
	Duplex.SetCurSel(pPrintSettings->Duplex);
	temp_string.Format(_T("%d"), pPrintSettings->CopyCount);
	CopyCount.SetWindowText(temp_string);

	for (int i = 0; i < _iPaperCount; i++)
	{
		//Set the control to the current setting on the driver
		if (pPrintSettings->CardSize == _pPapers[i])
		{
			CardSize.SetCurSel(i);
		}
	}
}

//****************************************************************************

ID_RETURN CDriverSettings2::GetPrintSettings
(
	PPRINTSET pPrintSettings
)
{
	ID_RETURN SDKReturn = ID_ERROR;

	//Get SDK function address
	PFNIDPRINTSET pFnPrintSettings = (PFNIDPRINTSET)GetProcAddress(Parent->hLib, "ID_PrintSettings");
	if (!pFnPrintSettings)
	{
		FUNCTION_NOT_ACCESSED(GetPrintSettings);
	}

	else
	{
		//Call SDK to read the Print Settings
		SDKReturn = (*pFnPrintSettings)(Parent->hSession, ID_READ, pPrintSettings);
		if (SDKReturn == ID_SUCCESS)
		{
			SetPrintSettings(pPrintSettings);
		}
		else
		{
			DISPLAY_ERROR(GetPrintSettings, SDKReturn);
		}
	}

	return SDKReturn;
}

//****************************************************************************

void CDriverSettings2::OnBnClickedBtnPrintSettings()
{
	PRINTSET PrintSettings = {};
	CWaitCursor wait;
	CString temp_string;

	if (ActionIsGet())
	{
		//Get Print Settings
		if (GetPrintSettings(&PrintSettings) == ID_SUCCESS)
		{
			//Update the display
			PrintSettingsToMsgBox(&PrintSettings, ID_READ);
		}
	}

	else
	{
		//Get SDK function address
		PFNIDPRINTSET pFnSetPrintSettings = (PFNIDPRINTSET)GetProcAddress(Parent->hLib, "ID_PrintSettings");
		if (!pFnSetPrintSettings)
		{
			FUNCTION_NOT_ACCESSED(SetPrintSettings);
		}

		else
		{
			//Get Print Settings values from controls
			PrintSettings.Duplex = (ID_PRINTSIDES)Duplex.GetCurSel();
			PrintSettings.CardSize = _pPapers[CardSize.GetCurSel()];
			CopyCount.GetWindowText(temp_string);
			PrintSettings.CopyCount = _ttoi(temp_string);

			//Call the SDK to write to the driver
			ID_RETURN SDKReturn = (*pFnSetPrintSettings)(Parent->hSession, ID_WRITE, &PrintSettings);
			if (SDKReturn != ID_SUCCESS)
			{
				DISPLAY_ERROR(SetPrintSettings, SDKReturn);
			}

			else
			{
				//Update the message box
				PrintSettingsToMsgBox(&PrintSettings, ID_WRITE);
			}
		}
	}
}

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

void CDriverSettings2::OnCbnSelchangeCardSettings()
{
	//Card Settings selections have changed
	CARDSET CardSettings = {};

	//get the card settings from the driver
	if (GetCardSettings((ID_SIDE)CardSettings_Side.GetCurSel(),
						&CardSettings) == ID_SUCCESS)
	{
		//Update the display
		SetCardSettings(&CardSettings);
	}
}

//****************************************************************************

void CDriverSettings2::CardSettingsToMsgBox
(
	ID_SIDE      Side,
	PCARDSET     pCardSettings,
	ID_READWRITE Action
)
{
	//Update the message box for the Card Settings
	CString temp_string;
	CString sep = Parent->Separator(Action);

	AddDriverMessage(_T("CardSettings (")  + Parent->SideString(CardSettings_Side.GetCurSel()) + _T(")"));

	switch (pCardSettings->ColourFormat)
	{
	case ID_COLOURFORMAT_YMC:  temp_string = _T("YMC");		      break;
	case ID_COLOURFORMAT_YMCK: temp_string = _T("YMCK");		  break;
	case ID_COLOURFORMAT_K:    temp_string = _T("Resin Only");    break;
	default:                   temp_string = _T("**Undefined**"); break;
	}
	AddDriverMessage(_T("Colour Format") + sep + temp_string);

	AddDriverMessage(_T("Overcoat") + sep + Parent->OnOffString(pCardSettings->Overcoat));

	switch (pCardSettings->Orientation)
	{
	case ID_ORIENTATION_LANDSCAPE: temp_string = _T("Landscape");     break;
	case ID_ORIENTATION_PORTRAIT:  temp_string = _T("Portrait");      break;
	default:					   temp_string = _T("**Undefined**"); break;
	}
	AddDriverMessage(_T("Orientation") + sep + temp_string);

	AddDriverMessage(_T("Rotation") + sep + Parent->OnOffString(pCardSettings->Rotation));
	AddDriverMessage(_T(""));
}

//****************************************************************************

void CDriverSettings2::SetCardSettings(PCARDSET pCardSettings)
{
	//Update the controls for the Card Settings
	ColourFormat.SetCurSel(pCardSettings->ColourFormat);
	Orientation.SetCurSel(pCardSettings->Orientation);
	Overcoat.SetCheck(pCardSettings->Overcoat);
	Rotate.SetCheck(pCardSettings->Rotation);
}

//****************************************************************************

ID_RETURN CDriverSettings2::GetCardSettings
(
	ID_SIDE		Side,
	PCARDSET	pCardSettings
)
{
	ID_RETURN SDKReturn = ID_ERROR;

	//Get SDK function address
	PFNIDCARDSET pFnCardSettings = (PFNIDCARDSET)GetProcAddress(Parent->hLib, "ID_CardSettings");
	if (!pFnCardSettings)
	{
		FUNCTION_NOT_ACCESSED(GetCardSettings);
	}

	else
	{
		//Call SDK to read the Card Settings
		SDKReturn = (*pFnCardSettings)(Parent->hSession, ID_READ, Side, pCardSettings);
		if (SDKReturn == ID_SUCCESS)
		{
			SetCardSettings(pCardSettings);
		}
		else
		{
			DISPLAY_ERROR(GetCardSettings, SDKReturn);
		}
	}

	return SDKReturn;
}

//****************************************************************************

void CDriverSettings2::OnBnClickedBtnCardSettings()
{
	CARDSET CardSettings = {};
	CWaitCursor wait;

	ID_SIDE Side = (ID_SIDE)CardSettings_Side.GetCurSel();

	if (ActionIsGet())
	{
		//Get Card Settings
		if (GetCardSettings(Side, &CardSettings) == ID_SUCCESS)
		{
			//Update the display
			CardSettingsToMsgBox(Side, &CardSettings, ID_READ);
		}
	}

	else
	{
		//Get SDK function address
		PFNIDCARDSET pFnSetCardSettings = (PFNIDCARDSET)GetProcAddress(Parent->hLib, "ID_CardSettings");
		if (!pFnSetCardSettings)
		{
			FUNCTION_NOT_ACCESSED(SetCardSettings);
		}

		else
		{
			//Get Card Settings values from controls
			CardSettings.ColourFormat = (ID_COLOURFORMAT)ColourFormat.GetCurSel();
			CardSettings.Orientation  = (Orientation.GetCurSel() ? ID_ORIENTATION_LANDSCAPE : ID_ORIENTATION_PORTRAIT);
			CardSettings.Overcoat     = (Overcoat.GetCheck() == BST_CHECKED);
			CardSettings.Rotation     = (Rotate.GetCheck() == BST_CHECKED);

			//Call the SDK to write to the driver
			ID_RETURN SDKReturn = (*pFnSetCardSettings)(Parent->hSession, ID_WRITE, Side, &CardSettings);
			if (SDKReturn != ID_SUCCESS)
			{
				DISPLAY_ERROR(SetCardSettings, SDKReturn);
			}

			else
			{
				//Update the message box
				CardSettingsToMsgBox(Side, &CardSettings, ID_WRITE);
			}
		}
	}
}

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

void CDriverSettings2::OnCbnSelchangeHoloKote()
{
	//HoloKote settings have changed
	HOLOKOTE HoloKote = {};

	//Get the HoloKote Settings
	if (GetHoloKote((ID_SIDE)HoloKote_Side.GetCurSel(), &HoloKote) == ID_SUCCESS)
	{
		//Update the display
		SetHoloKote(&HoloKote);
	}
}

//****************************************************************************

void CDriverSettings2::HoloKoteToMsgBox
(
	ID_SIDE      Side,
	PHOLOKOTE    pHoloKote,
	ID_READWRITE Action
)
{
	//Update the message box for the HoloKote settings
	CString temp_string;
	CString sep = Parent->Separator(Action);

	if (pHoloKote->ImageID == 0)
	{
		AddDriverMessage(_T("HoloKote (") + Parent->SideString(Side) + _T(")") + sep + _T("Disabled"));
	}
	else
	{
		AddDriverMessage(_T("HoloKote (") + Parent->SideString(Side) + _T(")"));
		temp_string.Format(_T("%d"), pHoloKote->ImageID);
		AddDriverMessage(_T("ImageID") + sep + temp_string);

		switch (pHoloKote->Rotation)
		{
		case ID_ROTATION_NONE: temp_string = _T("None");          break;
		case ID_ROTATION_90:   temp_string = _T("90 Degrees");    break;
		case ID_ROTATION_180:  temp_string = _T("180 Degrees");   break;
		case ID_ROTATION_270:  temp_string = _T("270 Degrees");   break;
		default:			   temp_string = _T("**Undefined**"); break;
		}
		AddDriverMessage(_T("Rotation") + sep + temp_string);
	}
	AddDriverMessage(_T(""));
}

//****************************************************************************

void CDriverSettings2::SetHoloKote
(
	PHOLOKOTE pHoloKote
)
{
	//Update the controls for the HoloKote settings
	CString temp_string;
	temp_string.Format(_T("%d"), pHoloKote->ImageID);
	HoloKoteImage.SetWindowText(temp_string);

	switch(pHoloKote->Rotation)
	{
	//Only 0 and 180 degree rotations are valid for Ultima
	case ID_ROTATION_NONE: HoloKoteRotate.SetCurSel(0); break;
	case ID_ROTATION_180:  HoloKoteRotate.SetCurSel(1); break;
	default:
		MessageBox(_T("HoloKote Error - Invalid Rotation"), MSGBOX_TITLE, MB_OK | MB_ICONSTOP);
		break;
	}
}

//****************************************************************************

ID_RETURN CDriverSettings2::GetHoloKote
(
	ID_SIDE		Side,
	PHOLOKOTE	pHoloKote
)
{
	ID_RETURN SDKReturn = ID_ERROR;

	//Get SDK function address
	PFNIDHOLOKOTE pFnHoloKote = (PFNIDHOLOKOTE)GetProcAddress(Parent->hLib, "ID_HoloKote");
	if (!pFnHoloKote)
	{
		FUNCTION_NOT_ACCESSED(GetHoloKote);
	}

	else
	{
		//Call SDK to read the HoloKote settings
		SDKReturn = (*pFnHoloKote)(Parent->hSession, ID_READ, Side, pHoloKote);
		if (SDKReturn == ID_SUCCESS)
		{
			SetHoloKote(pHoloKote);
		}
		else
		{
			DISPLAY_ERROR(GetHoloKote, SDKReturn);
		}
	}

	return SDKReturn;
}

//****************************************************************************

void CDriverSettings2::OnBnClickedBtnHoloKote()
{
	HOLOKOTE HoloKote = {};
	CWaitCursor wait;
	CString temp_string;
	ID_SIDE Side = (ID_SIDE)HoloKote_Side.GetCurSel();

	if (ActionIsGet())
	{
		//Get HoloKote Settings
		if (GetHoloKote(Side, &HoloKote) == ID_SUCCESS)
		{
			//Update the display
			HoloKoteToMsgBox(Side, &HoloKote, ID_READ);
		}
	}

	else
	{
		//Get SDK function address
		PFNIDHOLOKOTE pFnSetHoloKote = (PFNIDHOLOKOTE)GetProcAddress(Parent->hLib, "ID_HoloKote");
		if (!pFnSetHoloKote)
		{
			FUNCTION_NOT_ACCESSED(SetHoloKote);
		}

		else
		{
			//Get HoloKote settings from controls
			HoloKoteImage.GetWindowText(temp_string);
			HoloKote.ImageID = _ttoi(temp_string);
			HoloKote.Rotation = (ID_ROTATION)HoloKoteRotate.GetCurSel();

			//Call the SDK to write to the driver
			int SDKReturn = (*pFnSetHoloKote)(Parent->hSession, ID_WRITE, Side, &HoloKote);
			if (SDKReturn != ID_SUCCESS)
			{
				DISPLAY_ERROR(SetHoloKote, SDKReturn);
			}

			else
			{
				//Update the message box
				HoloKoteToMsgBox(Side, &HoloKote, ID_WRITE);
			}
		}
	}
}

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

void CDriverSettings2::OnBnClickedBtnHoloKoteID()
{
	//Get SDK function address
	PFNIDHKIDENTITY pFnHKIdentity = (PFNIDHKIDENTITY)GetProcAddress(Parent->hLib, IDFN_HOLOKOTEIDENTITY);
	if (!pFnHKIdentity)
	{
		FUNCTION_NOT_ACCESSED(HoloKoteID);
	}

	else
	{
		DWORD BufferSize = 0;

		//Call the SDK to get the buffer size
		int SDKReturn = (*pFnHKIdentity)(Parent->hSession, HoloKoteIDSlot.GetCurSel(), NULL, &BufferSize);
		
		LPTSTR pBuffer = new TCHAR[BufferSize];
		SDKReturn = (*pFnHKIdentity)(Parent->hSession, HoloKoteIDSlot.GetCurSel(), pBuffer, &BufferSize);
		if (SDKReturn != ID_SUCCESS)
		{
			DISPLAY_ERROR(HoloKoteIDs, SDKReturn);
		}
		else
		{
			CString temp_string = pBuffer;
			if (HoloKoteIDSlot.GetCurSel() == 0)
			{
				AddDriverMessage(_T("HoloKote IDs: "));
				
				int curPos = 0;
				int i = 1;
				CString token = temp_string.Tokenize(_T(","), curPos);
				while (token != _T(""))
				{
					CString slotno;
					slotno.Format(_T("%d"), i++);
				    AddDriverMessage(slotno + _T(": ") + token);
				    token = temp_string.Tokenize(_T(","), curPos);
				}
			}
			else
			{
				temp_string.Format(_T("%d"), HoloKoteIDSlot.GetCurSel());
				AddDriverMessage(_T("HoloKote ID ") + temp_string + _T(": ") + CString(pBuffer, BufferSize));
			}
			AddDriverMessage(_T(""));
		}

		delete[] pBuffer;
	}
}

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

CString CDriverSettings2::IlluminantString
(
	int Illuminant
)
{
	//Return the string corresponding to the given Illuminant value
	switch (Illuminant)
	{
	case ILLUMINANT_DEVICE_DEFAULT: return _T("Device Default");
	case ILLUMINANT_A:              return _T("Tungsten Lamp");
	case ILLUMINANT_B:              return _T("Noon Sunlight");
	case ILLUMINANT_C:              return _T("NTSC Sunlight");
	case ILLUMINANT_D50:            return _T("Normal Print");
	case ILLUMINANT_D55:            return _T("Bond Paper Print");
	case ILLUMINANT_D65:	        return _T("Standard Daylight");
	case ILLUMINANT_D75:	        return _T("Northern Daylight");
	case ILLUMINANT_F2:	            return _T("Cool White Lamp");
	default:                        return _T("**Undefined**");
	}
}

//****************************************************************************

void CDriverSettings2::ColourAdjToMsgBox
(
	PCOLORADJUSTMENT pca,
	ID_READWRITE     Action
)
{
	CString sep = Parent->Separator(Action);

	//Update the message box with the IP Settings status
	CString temp_string;
	temp_string.Format(_T("%d"), pca->caContrast);
	AddDriverMessage(_T("Contrast: ") + sep + temp_string);
	temp_string.Format(_T("%d"), pca->caBrightness);
	AddDriverMessage(_T("Brightness: ") + sep + temp_string);
	temp_string.Format(_T("%d"), pca->caColorfulness);
	AddDriverMessage(_T("Colorfulness: ") + sep + temp_string);
	temp_string.Format(_T("%d"), pca->caRedGreenTint);
	AddDriverMessage(_T("RedGreenTint: ") + sep + temp_string);
	temp_string.Format(_T("%d"), pca->caRedGamma);
	AddDriverMessage(_T("RedGamma: ") + sep + temp_string);
	temp_string.Format(_T("%d"), pca->caGreenGamma);
	AddDriverMessage(_T("GreenGamma: ") + sep + temp_string);
	temp_string.Format(_T("%d"), pca->caBlueGamma);
	AddDriverMessage(_T("BlueGamma: ") + sep + temp_string);
	temp_string.Format(_T("%d"), pca->caReferenceBlack);
 	AddDriverMessage(_T("IlluminantIndex: ") + sep + IlluminantString(pca->caIlluminantIndex));
 	AddDriverMessage(_T("Dark Picture: ") + sep + Parent->OnOffString(pca->caFlags & CA_LOG_FILTER));
 	AddDriverMessage(_T("Negative: ") + sep + Parent->OnOffString(pca->caFlags & CA_NEGATIVE));
	AddDriverMessage(_T("ReferenceBlack: ") + sep + temp_string);
	temp_string.Format(_T("%d"), pca->caReferenceWhite);
	AddDriverMessage(_T("ReferenceWhite: ") + sep + temp_string);

	AddDriverMessage(_T(""));
}

//****************************************************************************

void CDriverSettings2::SetColourAdjust(PCOLORADJUSTMENT pca)
{
	CString temp_string;
	temp_string.Format(_T("%d"), pca->caRedGamma);
	ColAdj_Red.SetWindowText(temp_string);
	temp_string.Format(_T("%d"), pca->caGreenGamma);
	ColAdj_Green.SetWindowText(temp_string);
	temp_string.Format(_T("%d"), pca->caBlueGamma);
	ColAdj_Blue.SetWindowText(temp_string);
	temp_string.Format(_T("%d"), pca->caReferenceBlack);
	ColAdj_BlackRef.SetWindowText(temp_string);
	temp_string.Format(_T("%d"), pca->caReferenceWhite);
	ColAdj_WhiteRef.SetWindowText(temp_string);
	temp_string.Format(_T("%d"), pca->caContrast);
	ColAdj_Contrast.SetWindowText(temp_string);
	temp_string.Format(_T("%d"), pca->caBrightness);
	ColAdj_Brightness.SetWindowText(temp_string);
	temp_string.Format(_T("%d"), pca->caColorfulness);
	ColAdj_Colour.SetWindowText(temp_string);
	temp_string.Format(_T("%d"), pca->caRedGreenTint);
	ColAdj_Tint.SetWindowText(temp_string);

	ColAdj_Negative.SetCheck(pca->caFlags & CA_NEGATIVE);
	ColAdj_DarkPic.SetCheck(pca->caFlags & CA_LOG_FILTER);

	ColAdj_Illuminant.SetCurSel(pca->caIlluminantIndex);
}

//****************************************************************************

ID_RETURN CDriverSettings2::GetColourAdjust
(
	PCOLORADJUSTMENT pca
)
{
	ID_RETURN SDKReturn = ID_ERROR;

	PFNIDCOLADJ pFnColAdjust = (PFNIDCOLADJ)GetProcAddress(Parent->hLib, "ID_ColourAdjust");
	if (!pFnColAdjust)
	{
		FUNCTION_NOT_ACCESSED(ColourAdjust);
	}

	else
	{
		SDKReturn = (*pFnColAdjust)(Parent->hSession, ID_READ, pca);
		if (SDKReturn == ID_SUCCESS)
		{
			SetColourAdjust(pca);
		}
		else
		{
			DISPLAY_ERROR(GetColourAdjust, SDKReturn);
		}
	}

	return SDKReturn;
}

//****************************************************************************

void CDriverSettings2::OnBnClickedBtnColourAdjust()
{
	CWaitCursor wait;

	PCOLORADJUSTMENT pColAdjust = new COLORADJUSTMENT;

	if (ActionIsGet())
	{
		if (GetColourAdjust(pColAdjust) == ID_SUCCESS)
		{
			//Update the display
			ColourAdjToMsgBox(pColAdjust, ID_READ);
		}
	}

	else
	{
		PFNIDCOLADJ pFnColAdjust = (PFNIDCOLADJ)GetProcAddress(Parent->hLib, "ID_ColourAdjust");
		if (!pFnColAdjust)
		{
			FUNCTION_NOT_ACCESSED(ColourAdjust);
		}

		else
		{
			//Get Colour Adjust settings from controls
			CString temp_string;

			memset(pColAdjust, 0, sizeof(COLORADJUSTMENT));
			pColAdjust->caSize = sizeof(COLORADJUSTMENT);

			ColAdj_Contrast.GetWindowText(temp_string);
			pColAdjust->caContrast = _ttoi(temp_string);
			ColAdj_Brightness.GetWindowText(temp_string);
			pColAdjust->caBrightness = _ttoi(temp_string);
			ColAdj_Colour.GetWindowText(temp_string);
			pColAdjust->caColorfulness = _ttoi(temp_string);
			ColAdj_Tint.GetWindowText(temp_string);
			pColAdjust->caRedGreenTint = _ttoi(temp_string);
			ColAdj_Red.GetWindowText(temp_string);
			pColAdjust->caRedGamma = _ttoi(temp_string);
			ColAdj_Green.GetWindowText(temp_string);
			pColAdjust->caGreenGamma = _ttoi(temp_string);
			ColAdj_Blue.GetWindowText(temp_string);
			pColAdjust->caBlueGamma = _ttoi(temp_string);
			if (ColAdj_Negative.GetCheck()) pColAdjust->caFlags |= CA_NEGATIVE;
			if (ColAdj_DarkPic.GetCheck())  pColAdjust->caFlags |= CA_LOG_FILTER;
			pColAdjust->caIlluminantIndex = (COLCORRECT)ColAdj_Illuminant.GetCurSel();
			ColAdj_BlackRef.GetWindowText(temp_string);
			pColAdjust->caReferenceBlack = _ttoi(temp_string);
			ColAdj_WhiteRef.GetWindowText(temp_string);
			pColAdjust->caReferenceWhite = _ttoi(temp_string);

			//Call the SDK to write to the driver
			int SDKReturn = (*pFnColAdjust)(Parent->hSession, ID_WRITE, pColAdjust);
			if (SDKReturn != ID_SUCCESS)
			{
				DISPLAY_ERROR(SetColourAdjust, SDKReturn);
			}

			else
			{
				//Update the message box
				ColourAdjToMsgBox(pColAdjust, ID_WRITE);
			}
		}
	}

	delete pColAdjust;
}

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

void CDriverSettings2::OnEnChangeColourAreaNo()
{
	if (Initialised)
	{
		//Colour Area Number has been changed
		OnCbnSelchangeColourArea();
	}
}

//****************************************************************************

void CDriverSettings2::OnCbnSelchangeColourArea()
{
	AREA Area = {0};
	CString temp_string;

	//Colour Area settings have been changed
	ColourArea_No.GetWindowText(temp_string);
	int AreaNo = _ttoi(temp_string);
	COLCORRECT Correction;

	if (GetColourArea((ID_SIDE)ColourArea_Side.GetCurSel(), AreaNo, &Area, &Correction) == ID_SUCCESS)
	{
		SetColourArea(&Area, Correction);
	}
}

//****************************************************************************

void CDriverSettings2::ColourAreaToMsgBox
(
	ID_SIDE      Side,
	int          AreaNo,
	PAREA        pArea,
	ID_READWRITE Action,
	COLCORRECT   Correction
)
{
	//Update the message box with the Resin Area settings
	CString temp_string;
	CString sep = Parent->Separator(Action);

	temp_string.Format(_T("Colour Area %s %d"), Parent->SideString(Side), AreaNo);
	AddDriverMessage(temp_string);
	temp_string.Format(_T("%d"), pArea->Left);
	AddDriverMessage(_T("Left") + sep + temp_string);
	temp_string.Format(_T("%d"), pArea->Width);
	AddDriverMessage(_T("Width") + sep + temp_string);
	temp_string.Format(_T("%d"), pArea->Bottom);
	AddDriverMessage(_T("Bottom") + sep + temp_string);
	temp_string.Format(_T("%d"), pArea->Height);
	AddDriverMessage(_T("Height") + sep + temp_string);
	AddDriverMessage(_T("Correction") + sep + Parent->CorrectionString(Correction));
	AddDriverMessage(_T(""));
}

//****************************************************************************

void CDriverSettings2::SetColourArea(PAREA pArea, COLCORRECT Correction)
{
	//Update the Colour Area controls
	CString temp_string;
	temp_string.Format(_T("%d"), pArea->Left);
	ColourArea_Left.SetWindowText(temp_string);
	temp_string.Format(_T("%d"), pArea->Width);
	ColourArea_Width.SetWindowText(temp_string);
	temp_string.Format(_T("%d"), pArea->Bottom);
	ColourArea_Bottom.SetWindowText(temp_string);
	temp_string.Format(_T("%d"), pArea->Height);
	ColourArea_Height.SetWindowText(temp_string);
	ColourArea_Correction.SetCurSel(Correction);
}

//****************************************************************************

ID_RETURN CDriverSettings2::GetColourArea
(
	ID_SIDE     Side,
	int		    AreaNo,
	PAREA	    pArea,
	PCOLCORRECT pCorrection
)
{
	ID_RETURN SDKReturn = ID_ERROR;

	//Get SDK function address
	PFNIDCOLOURAREA pFnColourArea = (PFNIDCOLOURAREA)GetProcAddress(Parent->hLib, "ID_ColourArea");
	if (!pFnColourArea)
	{
		FUNCTION_NOT_ACCESSED(GetColourArea);
	}

	else
	{
		//Call SDK to read the Resin Area setting
		SDKReturn = (*pFnColourArea)(Parent->hSession,
								     ID_READ,
									 Side,
									 AreaNo,
									 pArea,
									 pCorrection);
		if (SDKReturn == ID_SUCCESS)
		{
			SetColourArea(pArea, *pCorrection);
		}
		else
		{
			DISPLAY_ERROR(GetColourArea, SDKReturn);
		}
	}

	return SDKReturn;
}

//****************************************************************************

void CDriverSettings2::OnBnClickedBtnColourArea()
{
	AREA Area = {0};
	CWaitCursor wait;
	CString temp_string;

	ColourArea_No.GetWindowText(temp_string);
	int AreaNo = _ttoi(temp_string);
	ID_SIDE Side = (ID_SIDE)ColourArea_Side.GetCurSel();
	COLCORRECT Correction;

	if (ActionIsGet())
	{
		//Get the Resin Area settings
		if (GetColourArea(Side, AreaNo, &Area, &Correction) == ID_SUCCESS)
		{
			ColourAreaToMsgBox(Side, AreaNo, &Area, ID_READ, Correction);
		}
	}

	else
	{
		//Get SDK function address
		PFNIDCOLOURAREA pFnSetColourArea = (PFNIDCOLOURAREA)GetProcAddress(Parent->hLib, "ID_ColourArea");
		if (!pFnSetColourArea)
		{
			FUNCTION_NOT_ACCESSED(SetColourArea);
		}

		else
		{
			//Get the selected Colour Area settings
			ColourArea_Left.GetWindowText(temp_string);
			Area.Left = _ttoi(temp_string);
			ColourArea_Width.GetWindowText(temp_string);
			Area.Width = _ttoi(temp_string);
			ColourArea_Bottom.GetWindowText(temp_string);
			Area.Bottom = _ttoi(temp_string);
			ColourArea_Height.GetWindowText(temp_string);
			Area.Height = _ttoi(temp_string);
			Correction = (COLCORRECT)ColourArea_Correction.GetCurSel();

			//Call the SDK to write to the driver
			ID_RETURN SDKReturn = (*pFnSetColourArea)(Parent->hSession,
											          ID_WRITE,
											          Side,
											          AreaNo,
											          &Area,
													  &Correction);
			if (SDKReturn != ID_SUCCESS)
			{
				DISPLAY_ERROR(SetColourArea, SDKReturn);
			}

			else
			{
				//Update the message box
				ColourAreaToMsgBox(Side, AreaNo, &Area, ID_WRITE, Correction);
			}

		}
	}
}

//****************************************************************************

void CDriverSettings2::OnBnClickedBtnHolokotePreview()
{
	PFNIDHKTPREVIEW pFnHoloKotePreview = (PFNIDHKTPREVIEW)GetProcAddress(Parent->hLib, "ID_HoloKotePreview");
	PFNIDHKTCOUNT pFnHoloKoteCount = (PFNIDHKTCOUNT)GetProcAddress(Parent->hLib, "ID_HoloKoteCount");
	if (!pFnHoloKotePreview
	|| !pFnHoloKoteCount)
	{
		FUNCTION_NOT_ACCESSED(HoloKotePreview);
	}

	else
	{
		CWaitCursor wait;
		
		//Get the holokote count
		DWORD slotCount = (*pFnHoloKoteCount)(Parent->hSession);
		
		//multiply by the size of a holokote preview structure
		DWORD cbNeeded = sizeof(HKPREVIEW) * slotCount;

		//Allocate the memory
		char *buff = new char[cbNeeded];

		ID_RETURN SDKReturn = (*pFnHoloKotePreview)(Parent->hSession,
								                    (PHKPREVIEW)buff,
								                    &cbNeeded);
		if (SDKReturn != ID_SUCCESS)
		{
			DISPLAY_ERROR(HolokotePreview, SDKReturn);
		}
		else
		{
			CHoloKotePreview preview(buff, slotCount, this);
			preview.DoModal();
		}

		delete[] buff;
	}
}
