/*************************************************************************\
* "$RCSfile: CPSAppInit.cpp,v $"                                          *
***************************************************************************
* Information by CVS or VSS:                                              *
*     Last check in on: $Date: 2011/10/20 08:09:12 $                      *
*     by                $Author: schluckebier $
*     Revision        : $Revision: 1.56 $                                 *
\*************************************************************************/
/*! \file CPSAppInit.cpp
*	\brief Implementation CPSApp Class
**************************************************************************/

#include "VIC_PS.h"
#include "GBit.h"
#include "Ftp.h"
#include "common.h"
#include "CRegion.h"
#include "CLog.hpp"
#include "CPSApp.hpp"
#include "CFeature.hpp"
#include "CDlg.hpp"
#include "CDlgMain.hpp"
#include "CDlgSaveImage.hpp"
#include "CDlgCam.hpp"
#include "CDlgCamExpert.hpp"
#include "CDlgAppV.hpp"
#include "CDlgTools.hpp"
#include "CDlgDigIO.hpp"
#include "CDlgLog.hpp"
#include "CDlgConfig.hpp"
#include "CDlgPreviewSettings.hpp"
#include "CSmtp.hpp"
#include "CCamFeatures.hpp"

/*************************************************************************/
void CPSApp::ReadAppIni()
/*************************************************************************/
/*! @brief Reads parameters from "APP.INI" to #m_AppIni.
**************************************************************************/
{
	int x, y, w, h;

	m_AppIni = Config::loadFromIni(VIB_Drive[1], "app.ini", "APP_INI");
	m_SkinPath = m_AppIni->getValue("SkinPath", "SKIN", 9);
	m_AppIni->setComment("SkinPath", "Path for Skin elements (Reboot required)");

	// X-Y and size of camera area
	w = m_AppIni->getValue("CamWidth", 1024, 12, 1312);
	m_AppIni->setComment("CamWidth", "[Pixel] (Reboot required)");
	h = m_AppIni->getValue("CamHeight", 1024, 1, 1082);
	m_AppIni->setComment("CamHeight", "[Pixel] (Reboot required)");
	x = m_AppIni->getValue("CamPosX", 0, 0, 1012);
	m_AppIni->setComment("CamPosX", "[Pixel] (Reboot required)");
	y = m_AppIni->getValue("CamPosY", 0, 0, 1023);
	m_AppIni->setComment("CamPosY", "[Pixel] (Reboot required)");
	m_CamReg.NewWH(x, y, w, h);

	m_PVPosX = m_AppIni->getValue("PVPosX", 0);
	m_PVPosY = m_AppIni->getValue("PVPosY", 0); 
	m_PVScale = m_AppIni->getValue("PVScale", 1.0);

	m_CamTimeout = m_AppIni->getValue("GrabTimeout", 0, 0, 10000000);
	m_AppIni->setComment("GrabTimeout", "[µs] set to 0 to disable");
	m_ScreenWidth = m_AppIni->getValue("ScreenWidth", 1024, 600, 1600);
	m_AppIni->setComment("ScreenWidth", "[Pixel] (Reboot required)");
	m_ScreenHeight = m_AppIni->getValue("ScreenHeight", 800, 600, 1200);
	m_AppIni->setComment("ScreenHeight", "[Pixel] (Reboot required)");
	m_UseHalcon = m_AppIni->getValue("UseHalcon", 0, 0, 1);
	m_AppIni->setComment("UseHalcon", " 0 if no Halcon license is installed (Reboot required)");
	m_AppIni->getValue("DetachWindow", 0, 0, 1);
	m_AppIni->setComment("DetachWindow", "0: Window in Web Browser, 1: Detached Window");

	if (VIB_HWInfo.Type != VIB_TYPE_PSC)
		m_CamSerialPort = m_AppIni->getValue("CamSerialPort", 4, 1, 9);
}

/*************************************************************************/
void CPSApp::OpenCameraLink(int LineCamCheck)
/*************************************************************************/
/*! @brief Opens camera link receiver and channel.

	The mode for CL Receiver and CL Channel is taken from #m_CamPixelFormat.
	@param LineCamCheck Check for line camera mode
**************************************************************************/
{
	int r1, r2;
	int AqMode;

	if (LineCamCheck)
	{
		AqMode = CCamFeatures::GetInstance()->m_pLineCamMode->GetValue() ? CL_LINECAM : CL_AREACAM;
		if (VIB_HWInfo.Type != VIB_TYPE_PSC)
			AqMode |= CL_KEEP_FPGA;
	}
	else
		AqMode = CL_AREACAM;

	switch (m_CamPixelFormat)
	{
	case CamMode::_1TAP_8BIT:	// For Frontend D1024-40
		r1 = VIB_ClInSetupReceiver(&m_ClInReceiver, -1, 0, CL_FORMAT8 | AqMode);
		r2 = VIB_ClInOpenChannel(&m_ClInChannel, &m_ClInReceiver, 0, 0, 0, GetCamWidth(), GetCamHeight(), 0);
		break;
	case CamMode::_1TAP_10BIT:	// For Frontend D1024-40
	case CamMode::_1TAP_12BIT:
		r1 = VIB_ClInSetupReceiver(&m_ClInReceiver, -1, 0, CL_FORMAT16 | AqMode);
		r2 = VIB_ClInOpenChannel(&m_ClInChannel, &m_ClInReceiver, 0, 0, 0, GetCamWidth(), GetCamHeight(), 0);
		break;
	case CamMode::_2TAP_8BIT:	// For Frontend D1024-80
		r1 = VIB_ClInSetupReceiver(&m_ClInReceiver, -1, 0, CL_FORMAT16 | AqMode);
		r2 = VIB_ClInOpenChannel(&m_ClInChannel, &m_ClInReceiver, 0, 0, 0, GetCamWidth()/2, GetCamHeight(), 0);
		break;
	case CamMode::_2TAP_10BIT:	// For Frontend D1024-80
	case CamMode::_2TAP_12BIT:
		r1 = VIB_ClInSetupReceiver(&m_ClInReceiver, -1, 0, CL_FORMAT12 | AqMode);
		r2 = VIB_ClInOpenChannel(&m_ClInChannel, &m_ClInReceiver, 0, 0, 0, GetCamWidth(), GetCamHeight(), 0);
		break;
	default:
		r1 = r2 = 0;
		break;
	}

	if (r1)
		CLog::Print("OpenCamera: VIB_ClInSetupReceiver()\n");
	if (r2)
		CLog::Print("OpenCamera: VIB_ClInOpenChannel()\n");
}

/*************************************************************************/
void CPSApp::OpenPflib()
/*************************************************************************/
/*! @brief Opens Photonfocus library for handling of the camera module.
**************************************************************************/
{
	int NumOfPorts, Error, BaudRate, mBytes, nBytes, Version, Type;
	char Manu[32], Name[32];

	m_pCamImage = NULL;

	if (VIB_HWInfo.Type == VIB_TYPE_PSC)
	{
		m_CamSerialPort = 2;
		VIB_SetReg(DIO_ADDRESS, 0xFF00);
	}

	pfPortInit(&NumOfPorts);
	pfPortInfo(m_CamSerialPort, Manu, &mBytes, Name, &nBytes, &Version, &Type);
	CLog::Print("Manu: %s, %s, mBytes %d, nBytes %d, ver %d, type %d\n",
				 Manu, Name, mBytes, nBytes, Version, Type);
	// Open camera port
	Error = pfDeviceOpen(m_CamSerialPort);
	if (Error != 0)
	{
		CLog::Print("pfDeviceOpen: %d\n", Error);
		printf("pfDeviceOpen: %d\n", Error);
		m_bCameraPresent = false;
		m_CamTimeout = 1000;
	}
	else
	{
		// Get current baud rate
		pfGetBaudRate(m_CamSerialPort, &BaudRate);
	//	CLog.Print("Baud rate: %d\n", BaudRate);
	//	printf("Baud rate: %d\n", BaudRate);

		Error = pfIsBaudRateSupported(m_CamSerialPort, 115200);
		if (Error == 1)
		{
			// Set baud rate to 115200
			Error = pfSetBaudRate(m_CamSerialPort, 115200);
			if (Error != 0)
			{
				CLog::Print("Error baud rate 115200: %d\n", Error);
				printf("Error baud rate 115200: %d\n", Error);
			}
		}
		else
		{
			// Set baud rate to 57600
			Error = pfSetBaudRate(m_CamSerialPort, 57600);
			if (Error != 0)
			{
				CLog::Print("Error baud rate: %d\n", Error);
				printf("Error baud rate: %d\n", Error);
			}
		}
		m_bCameraPresent = true;

		// Get current baud rate
		pfGetBaudRate(m_CamSerialPort, &BaudRate);
	//	printf("Baud rate: %d\n", BaudRate);
	//	CLog.Print("Baud rate: %d\n", BaudRate);

		// Reset camera
		SetPropertyInt(m_CamSerialPort, "Reset", 1);
	}

	// Set TriggerAndStrobe
	m_TriggerSourceNStrobeOut = 0x00;

	// *** Get some properties of the camera for the GUI ***
	CCamFeatures::CreateInstance();
}

/*************************************************************************/
void CPSApp::ClosePflib()
/*************************************************************************/
/*! @brief Closes Photonfocus lib.
**************************************************************************/
{
	if (m_bCameraPresent)
		pfDeviceClose(m_CamSerialPort);
	CCamFeatures::DisposeInstance();
}

/*************************************************************************/
void CPSApp::InitNetwork()
/*************************************************************************/
/*! @brief Initializes network connection.
**************************************************************************/
{
	CSmtp *pMail;
	int i;
	GBIT_INITDATA InitData;
	char *pUsername, *pPassword;
	char Hostname[32];
	char txt1[32], txt2[32];

	m_EthernetIni = Config::loadFromIni(VIB_Drive[1], "ethernet.ini", "ETHERNET_INI");

	InitData.IpAddress    = m_EthernetIni->getValue("IPAddress", "0.0.0.0");
	InitData.IpSubnetMask = m_EthernetIni->getValue("IpSubnetMask", "255.255.255.0");
	InitData.IpDefaultGw  = m_EthernetIni->getValue("IpDefaultGw", "192.168.1.1");
	InitData.IpDNSServer  = m_EthernetIni->getValue("IpDNSServer", "0.0.0.0");
	InitData.HostName     = m_EthernetIni->getValue("HostName", m_SerialNumber);
	InitData.DomainName   = m_EthernetIni->getValue("DomainName", "imago");

	m_NetShowLinks        = m_EthernetIni->getValue("ShowLinks", 1);
	m_NetAutoRedraw       = m_EthernetIni->getValue("AutoRedraw", 1);
	m_TcpDisplayPort      = m_EthernetIni->getValue("TcpDisplayPort", 2001);
	m_XmlPort             = m_EthernetIni->getValue("XmlPort", 2222);
	m_XmlAllowed          = m_EthernetIni->getValue("XmlAllowed", 1);

	m_IP_Adr[0] = '\0';
	m_EthError = (GBIT_Init(-1, &InitData) < 0) ? -2: 0;

	if (m_EthError)
	{
		CLog::Print("%s\nS/N: %s\n", m_LibVersion, m_SerialNumber);
		return;
	}

	fdOpenSession(TSK_self());

	// *** Get IP-Address via DHCP ***
	if (!strcmp(InitData.IpAddress, "0.0.0.0"))
	{
		for (i = 0; i < 20; i++)
		{
			VIB_WaitBios(500);
			gethostname(Hostname, 32);
			if (strlen(Hostname) > 0)
				break;
		}
		if (i < 20)
		{
			char HostEntBuf[256];
			HOSTENT *pHostEnt = (HOSTENT*)HostEntBuf;

			printf("Hostname:   '%s'\n", Hostname);
			gethostbyname(Hostname, HostEntBuf, 256);
			if (pHostEnt->h_addrtype == AF_INET)
				sprintf(m_IP_Adr, "%s", inet_ntoa(*(LPIN_ADDR)pHostEnt->h_addr));
		}
	}
	else
	{
		strcpy(m_IP_Adr, InitData.IpAddress);
	}

	// *** Start message ***
	CLog::Print("%s\n"
				"S/N: %s\n"
				"IP address: %s\n",
				m_LibVersion, m_SerialNumber, m_IP_Adr);
	printf("IP address: '%s'\n", m_IP_Adr);

	// *** Start FTP-Server ***
	m_pFtp = new Ftp();
	m_pFtp->setMaxConnections(m_EthernetIni->getValue("ftpMaxConnections", (int)10));
	pUsername = m_EthernetIni->getValue("ftpUsername", "username");
	pPassword = m_EthernetIni->getValue("ftpPassword", "password");
	m_pFtp->addUser(pUsername, pPassword, 5, 120);
	m_pFtp->addUser("supervisor", "968672", 5, 120);
	m_pFtp->addUser("anonymous", "", 5, 120);

	// *** SD-Card ***
	sprintf(txt1, "%s:/", VIB_GetDeviceName(VIB_Drive[1]));
	m_pFtp->addVirtualDir(pUsername, txt1, "/", "LRW");
	m_pFtp->addVirtualDir("supervisor", txt1, "/", "LRW");
	m_pFtp->addVirtualDir("anonymous", txt1, "/", "L");

	// *** Internal Flash ***
	sprintf(txt1, "%s:/", VIB_GetDeviceName(VIB_Drive[0]));
	sprintf(txt2, "/%s", VIB_GetDeviceName(VIB_Drive[0]));
	m_pFtp->addVirtualDir(pUsername, txt1, txt2, "LR");
	m_pFtp->addVirtualDir("supervisor", txt1, txt2, "LRW");

	m_pFtp->start();

	// *** Start Mail-Server ***
	char *pSAdr = m_EthernetIni->getValue("MailserverAdr", "192.168.1.1");
	int Port = m_EthernetIni->getValue("MailserverPort", 25);
	char *pFrom = m_EthernetIni->getValue("MailFrom", "info@imago-technologies.com");
	char *pTo = m_EthernetIni->getValue("MailTo", "example@imago-technologies.com");
	int Ena = m_EthernetIni->getValue("StatusEmailsVerbosity", 0, 0, 10);
	pMail = CSmtp::CreateInstance();
	pMail->SetMailServer(pSAdr, Port);
	pMail->SetMailAddress(pFrom);
	pMail->SetRecepientAddress(pTo);
	pMail->SetEnable(Ena);
}

/*************************************************************************/
void CPSApp::SetColors()
/*************************************************************************/
/*! @brief Reads the GUI color set from CPSApp::m_Colini.
**************************************************************************/
{
	m_GradCol[0].R = m_ColIni->getValue("Grad0R", rgbGradBlue[0].R);
	m_GradCol[0].G = m_ColIni->getValue("Grad0G", rgbGradBlue[0].G);
	m_GradCol[0].B = m_ColIni->getValue("Grad0B", rgbGradBlue[0].B);

	m_GradCol[1].R = m_ColIni->getValue("Grad1R", rgbGradBlue[1].R);
	m_GradCol[1].G = m_ColIni->getValue("Grad1G", rgbGradBlue[1].G);
	m_GradCol[1].B = m_ColIni->getValue("Grad1B", rgbGradBlue[1].B);

	m_GradCol[2].R = m_ColIni->getValue("Grad2R", rgbGradBlue[2].R);
	m_GradCol[2].G = m_ColIni->getValue("Grad2G", rgbGradBlue[2].G);
	m_GradCol[2].B = m_ColIni->getValue("Grad2B", rgbGradBlue[2].B);

	m_GradCol[3].R = m_ColIni->getValue("Grad3R", rgbGradBlue[3].R);
	m_GradCol[3].G = m_ColIni->getValue("Grad3G", rgbGradBlue[3].G);
	m_GradCol[3].B = m_ColIni->getValue("Grad4B", rgbGradBlue[3].B);

	m_ColBack.R = m_ColIni->getValue("ColBackR", rgbCoolBlue.R);
	m_ColBack.G = m_ColIni->getValue("ColBackG", rgbCoolBlue.G);
	m_ColBack.B = m_ColIni->getValue("ColBackB", rgbCoolBlue.B);

	m_ColText.R = m_ColIni->getValue("ColTextR", rgbWhite.R);
	m_ColText.G = m_ColIni->getValue("ColTextG", rgbWhite.G);
	m_ColText.B = m_ColIni->getValue("ColTextB", rgbWhite.B);
}

/*************************************************************************/
void CPSApp::InitDisplay()
/*************************************************************************/
/*! @brief Initializes GUI, text parameters, colors and Ethernet display.
**************************************************************************/
{
	int Error = 0;
	TSK_Attrs TskAttrs = TSK_ATTRS;

	if (m_EthError == 0)
	{
		m_VIBDisplay.width = m_ScreenWidth;
		m_VIBDisplay.height = m_ScreenHeight;
		m_GUIDisplay = GUI_NewDisplay();
		GUI_DisplayAddDevice(&m_GUIDisplay, &m_VIBDisplay, 0, 0);
		Error =
			(GBIT_InitDisplay(m_ScreenWidth, m_ScreenHeight, m_TcpDisplayPort, &m_VIBDisplay) < 0);
	}
	else	// No Ethernet
	{
		VIB_DISPLAYDEVICE display;

		if (VIB_InitDisplay(&m_VIBDisplay, &display) >= 0)
		{
			m_ScreenWidth = m_VIBDisplay.width;
			m_ScreenHeight = m_VIBDisplay.height;
		}
		else
		{
			Error = 1;
		}
	}
	if (Error)
	{
		printf("No display!\n");
		exit(0);
	}

	GUI_Init();
	m_Image = GUI_CImage(NULL, NULL, NULL, m_ScreenWidth, m_ScreenHeight);
	GUI_Language = GUI_ENGLISH;

	if (m_EthError == 0)
	{
		if (m_EthernetIni->getValue("JPEG_Mode", 0, 0, 1))
			JPEG_SetGBitMode();
		else if (m_EthernetIni->getValue("PNG_Mode", 0, 0, 1))
			PNG_SetGBitMode();

		GUI_DlgGetCoord = GBIT_GetKoord;

		GUI_SetActiveDisplay(&m_GUIDisplay);

		InitIndexHtml();

		// *** Create task to redraw on connect ***
		TskAttrs.priority  = TSK_getpri(TSK_self());
		TskAttrs.stack     = 0;
		TskAttrs.stacksize = 0x2000;
		TskAttrs.stackseg  = SDRAM1;
		TskAttrs.environ   = 0;
		TskAttrs.name      = "TaskDisplay1";
		TskAttrs.exitflag  = 0;
		TskAttrs.initstackflag = TRUE;

		if (m_NetAutoRedraw)
			TSK_create((Fxn)TaskDisplay, &TskAttrs, (CPSApp*)this);
	}
	else
	{
		m_pDisplayImage = &m_Image;
	}

	InitBackground();
	PrintInit("Start...");
	//Display();

	m_fKB = fopen("VIB:KEYB", "r");

	GUI_InitTxtParam(&m_TPSet[0]); // Normal
	GUI_InitTxtParam(&m_TPSet[1]); // Error
	GUI_InitTxtParam(&m_TPSet[2]); // OK
	GUI_InitTxtParam(&m_TPSet[3]); // Bold
	GUI_InitTxtParam(&m_TPSet[4]); // Shadow & opaque
	GUI_InitTxtParam(&m_TPSet[5]); // Monospace
	m_TPSet[TextStyle::NORMAL].BackCol = m_ColBack;
	m_TPSet[TextStyle::NORMAL].FrontCol = m_ColText;

	m_TPSet[TextStyle::ERROR].BackCol = rgbRed;
	m_TPSet[TextStyle::ERROR].FrontCol = m_ColText;

	m_TPSet[TextStyle::OK].FrontCol = rgbGreen;
	m_TPSet[TextStyle::OK].Back = 0;

	m_TPSet[TextStyle::BOLD].BackCol = m_ColBack;
	m_TPSet[TextStyle::BOLD].FrontCol = m_ColText;
	m_TPSet[TextStyle::BOLD].Style = GUI_FSBOLD;

	m_TPSet[TextStyle::SHADOW].Back = 0;
	m_TPSet[TextStyle::SHADOW].FrontCol = m_ColText;
	m_TPSet[TextStyle::SHADOW].Style = GUI_FSSHADOW;

	m_TPSet[TextStyle::MONOSPACE].BackCol = m_ColBack;
	m_TPSet[TextStyle::MONOSPACE].FrontCol = m_ColText;

	GUI_SetTxtParamSet(m_TPSet, 6);	// Assign text parameter list

#if (USE_FREETYPE == 1)
	void *fFont = NULL, *fFontB = NULL, *fFontM = NULL;

	fFont = GUI_FTFont(GUI_FTVera, GUI_FTVeraSize, 16, 16, 0);
	fFontB = GUI_FTFontBold(GUI_FTVera, GUI_FTVeraSize, 16, 16, 1, 40);
	fFontM = GUI_FTFont(GUI_FTVeraMono, GUI_FTVeraMonoSize, 16, 16, 1);

	if (fFont)
	{
		GUI_SetTxtFTFontParam(fFont, &m_TPSet[TextStyle::NORMAL]);
		GUI_SetTxtFTFontParam(fFont, &m_TPSet[TextStyle::SHADOW]);
	}
	if (fFontB)
	{
		GUI_SetTxtFTFontParam(fFontB, &m_TPSet[TextStyle::BOLD]);
		m_TPSet[TextStyle::BOLD].Style = GUI_FSNORMAL;
	}
	if (fFontM)
	{
		GUI_SetTxtFTFontParam(fFontM, &m_TPSet[TextStyle::MONOSPACE]);
		m_TPSet[TextStyle::MONOSPACE].CharWidth = 8;
	}
	SetTP(TextStyle::NORMAL);
#endif

	GUI_SetTxtStyle(GUI_FSEXTEND);
	GUI_SetTxtFrontCol(m_ColText);
	GUI_SetTxtBackCol(m_ColBack);
	GUI_MBGradient = 1;

	GUI_SetWndTitleStyle(&m_TPSet[TextStyle::NORMAL], 0);
	GUI_SetWndTitleStyle(&m_TPSet[TextStyle::SHADOW], 1);

	VIB_ChDir(VIB_Drive[1], m_SkinPath);
	m_Icon[IconId::OK]    = CDlg::ReadIcon("B_OK.PNG", 98, 98);
	m_Icon[IconId::CANCEL]= CDlg::ReadIcon("B_CANCEL.PNG", 98, 98);
	m_Icon[IconId::BACK]  = CDlg::ReadIcon("B_BACK.PNG", 98, 98);
	m_Icon[IconId::SAVE]  = CDlg::ReadIcon("B_SAVE.PNG", 98, 98);
	m_Icon[IconId::SAVEA] = CDlg::ReadIcon("B_SAVEA.PNG", 98, 98);
	m_Icon[IconId::APP]   = CDlg::ReadIcon("B_APP.PNG", 98, 98);
	VIB_ChDir(VIB_Drive[1], "..");
}

/*************************************************************************/
void CPSApp::InitBackground()
/*************************************************************************/
/*! @brief Initializes #m_Image with the company logo.
**************************************************************************/
{
	const int Width  = m_Image.Width;
	const int Height = m_Image.Height;
	const int xo = (Width - (Width / 180) * 180) / 2 + 12;
	const int yo = (Height- (Height / 140) * 140) / 2 + 18;

	GUI_Fill(&m_Image, &rgbDkBlue);
	for (int i = yo; i < Height - 110; i += 140)
	{
		for (int j = xo; j < Width - 160; j += 180)
			GUI_DrawILogo(&m_Image, j, i, 1);
	}
}

/*************************************************************************/
void CPSApp::InitIndexHtml()
/*************************************************************************/
/*! @brief Creates index file for display via GBit Ethernet. (\p index.html)
**************************************************************************/
{
	int DetachWindow;
	int Width, Height;
	char *pFileBuffer;
	char Text[256];

	pFileBuffer = (char*)VIB_MemAlloc(8 * 1024);

	DetachWindow = m_AppIni->getValue("DetachWindow", 0, 0, 1);
	if (DetachWindow && VIB_FindFile2(VIB_Drive[0], "TcpDisp.jar") > 0)
	{
		Width = 300;
		Height = 20;
	}
	else
	{
		Width = m_ScreenWidth;
		Height = m_ScreenHeight;
	}

	strcpy(pFileBuffer, "<HTML>\n<HEAD>\n<TITLE>IMAGO + Photonfocus</TITLE> </HEAD>\n"
						"<BODY bgcolor=\"#324B64\" link=\"#FFFFFF\" vlink=\"#FFFFFF\" alink=\"#FFFF00\" text=\"#FFFFFF\">\n");
	sprintf(Text, "<center>\n<applet code=\"TcpDisplay.class\" archive=\"TcpDisplay.jar\" width=%d height=%d>\n"
				  "<param name=\"port\" value=\"%d\">\n"
				  "<param name=\"DetachWindow\" value=\"%d\">\n",
				  Width, Height, m_TcpDisplayPort, DetachWindow);
	strcat(pFileBuffer, Text);
	if (VIB_FindFile2(VIB_Drive[0], "TcpDisp.jar") > 0)
		strcat(pFileBuffer, "<param name=\"jnlp_href\" value=\"TcpDisplay.jnlp\">\n");
	strcat(pFileBuffer, "<param name=\"draggable\" value=\"true\">\n"
						"alt=\"Your browser understands the &lt;APPLET&gt; tag but isn't running the applet, for some reason.\""
						"Your browser is completely ignoring the &lt;APPLET&gt; tag!\n</applet>\n</center>\n");

	if (m_NetShowLinks)
	{
		if (m_IP_Adr[0] != 0)
		{
			strcat(pFileBuffer, "<table style=\"font-family:Helvetica; border:1px solid; font-size:12px;\">");
			sprintf(Text, "<tr><td><a href=\"ftp://%s\" target=\"_clean\">ftp://%s</a></td></tr>", m_IP_Adr, m_IP_Adr);
			strcat(pFileBuffer, Text);
			sprintf(Text, "<tr><td><a href=\"help.html\" target=\"_clean\">Help</a></td></tr>");
			strcat(pFileBuffer, Text);
			strcat(pFileBuffer, "</table>");
		}
	}
	strcat(pFileBuffer, "</BODY>\n</HTML>\n");
	GBIT_AddWebFile("index.html", (unsigned char*)pFileBuffer, (unsigned int)strlen(pFileBuffer));

	// Create "TcpDisplay.jnlp"
	if (m_IP_Adr[0] != 0)
	{
		strcpy(pFileBuffer, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
		sprintf(Text, "<jnlp spec=\"1.0+\" codebase=\"http://%s/\" href=\"TcpDisplay.jnlp\">\n", m_IP_Adr);
		strcat(pFileBuffer, Text);
		strcat(pFileBuffer, "<information>\n");
		sprintf(Text, "<title>TcpDisplay (%s)</title>\n", m_IP_Adr);
		strcat(pFileBuffer, Text);
		strcat(pFileBuffer, "<vendor>IMAGO Technologies</vendor>\n"
							"<description kind=\"short\">\n"
							"This Applet enables access to the VisionBox GUI by using a TCP connection.\n"
							"</description>\n"
							"<icon kind=\"shortcut\" href=\"jar:TcpDisplay.jar!/images/strampe.png\"/>\n"
							"<offline-allowed/>\n"
							"<shortcut online=\"false\">\n<desktop />\n</shortcut>\n"
							"</information>\n"
							"<security>\n<all-permissions/>\n</security>\n"
							"<resources><j2se version=\"1.5+\"/><jar href=\"TcpDisplay.jar\"/>\n</resources>\n");
		sprintf(Text, "<applet-desc main-class=\"TcpDisplay\" name=\"TcpDisplay\" width=\"%d\" height=\"%d\"/>\n</jnlp>\n", 
			Width, Height);
		strcat(pFileBuffer, Text);
		GBIT_AddWebFile("TcpDisplay.jnlp", (unsigned char*)pFileBuffer, (unsigned int)strlen(pFileBuffer));
	}

	sprintf(pFileBuffer, "<HTML>\n<HEAD>\n<TITLE>Vision Box - %s</TITLE> </HEAD>\n", m_SerialNumber);
	strcat(pFileBuffer, "<BODY bgcolor=\"#324B64\" link=\"#FFFFFF\" vlink=\"#FFFFFF\" alink=\"#FFFF00\" text=\"#FFFFFF\">\n"
		"<center style=\"font-family:Helvetica; border:1px solid; font-size:12px;\">"
		"See <tt>'VisionCamPS.chm'</tt> for more information about this program.</center>\n"
		"</BODY>\n</HTML>\n");
	GBIT_AddWebFile("help.html", (unsigned char*)pFileBuffer, (unsigned int)strlen(pFileBuffer));

	VIB_MemFree(pFileBuffer);
}

/*************************************************************************/
void CPSApp::TaskDisplay()
/*************************************************************************/
/*! @brief <b>Task:</b> Update Ethernet display.

	#m_Image is displayed on new connections.\n
	This code looks for a new connected client and updates the screen.
**************************************************************************/
{
	CSmtp *pMail = CSmtp::GetInstance();
	int DisplayStatus, OldDisplayStatus = 0;
	char Text[256];
	time_t tTime;
	tm *sTime;

	fdOpenSession(TSK_self());

	while (1)
	{
		DisplayStatus = GBIT_DisplayStatus(m_pThis->GetVIBDisplayDev());
		if (DisplayStatus == 2 || (DisplayStatus && !OldDisplayStatus))
		{
			m_pThis->Display();
			CDlgMain::GetInstance()->ForceRedraw();
			CDlgSaveImage::GetInstance()->ForceRedraw();
			CDlgPreviewSettings::GetInstance()->ForceRedraw();
			CDlgCamExpert::GetInstance()->ForceRedraw();
			CDlgCam::GetInstance()->ForceRedraw();
			pDlgApp->ForceRedraw();
			CDlgTools::GetInstance()->ForceRedraw();
			CDlgDigIO::GetInstance()->ForceRedraw();

			VIB_time(&tTime);
			sTime = localtime(&tTime);
			sprintf(Text, "Ethernet display connected at %02d:%02d:%02d\n",
				sTime->tm_hour, sTime->tm_min, sTime->tm_sec);
			pMail->Send(Text);
		}
		if (!DisplayStatus && OldDisplayStatus)
		{
			VIB_time(&tTime);
			sTime = localtime(&tTime);
			sprintf(Text, "Ethernet display disconnected at %02d:%02d:%02d\n",
				sTime->tm_hour, sTime->tm_min, sTime->tm_sec);
			pMail->Send(Text);
		}
		OldDisplayStatus = DisplayStatus;
		VIB_WaitBios(100);
	}
}

/*************************************************************************/
void CPSApp::InitStringTable()
/*************************************************************************/
/*! @brief Reads string table from \p "VIC_PS_S.INI" to #m_VicPsStrings.
**************************************************************************/
{
	if (m_VicPsStrings == NULL)
		m_VicPsStrings = Config::loadFromIni(VIB_Drive[1], "vic_ps_s.ini", "VIC_PS_STRINGS_INI");
	m_Str[StringTable::YES] = m_VicPsStrings->getValue("Yes", "_Yes");
	m_Str[StringTable::NO] = m_VicPsStrings->getValue("No", "_No");
	m_Str[StringTable::BACK] = m_VicPsStrings->getValue("Back", "_Back");
	m_Str[StringTable::CANCEL] = m_VicPsStrings->getValue("Cancel", "_Cancel");
	m_Str[StringTable::TEMPERATURE] = m_VicPsStrings->getValue("Temperature", "Temperature");
	m_Str[StringTable::CPU_LOAD] = m_VicPsStrings->getValue("CPULoad", "CPU Load");
	m_Str[StringTable::FRAMERATE] = m_VicPsStrings->getValue("Framerate", "Framerate");
	m_Str[StringTable::CAM_INFO] = m_VicPsStrings->getValue("CameraInfo", "Info");
	m_Str[StringTable::HISTOGRAM] = m_VicPsStrings->getValue("Histogram", "Histogram");
	m_Str[StringTable::HISTOGRAM_LOG] = m_VicPsStrings->getValue("HistogramLogarithm", "Histogram [Log]");
	m_Str[StringTable::FILE_EXISTS] = m_VicPsStrings->getValue("FileExists", "File exists!");
	m_Str[StringTable::OVERWRITE] = m_VicPsStrings->getValue("Overwrite", "Overwrite?");
}

/*************************************************************************/
void CPSApp::PrintInit(const char *pText)
/*************************************************************************/
/*! @brief Prints initialization string.
**************************************************************************/
{
	static int s_Pos = 4;

	GUI_TextOut(&m_Image, 4, s_Pos, pText);
	Display();
	s_Pos += 20;
}

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