// Monitor2Dlg.cpp : implementation file
//

#include "stdafx.h"
#include <stdio.h>
#include <process.h>
#include <atlbase.h>

#include "swecoin.h"
#include "Monitor2.h"
#include "config.h"
#include "Monitor2Dlg.h"

#include <AFXPRIV.H>
#include <winspool.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


HANDLE	hPrinter;
TESTPAR	myTestPar;


UINT MyPrintDocument(LPVOID pParam); 
UINT StatusThreadProc(LPVOID pParam);

/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	//{{AFX_DATA(CAboutDlg)
	enum { IDD = IDD_ABOUTBOX };
	//}}AFX_DATA

	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CAboutDlg)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	//}}AFX_VIRTUAL

// Implementation
protected:
	//{{AFX_MSG(CAboutDlg)
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
	//{{AFX_DATA_INIT(CAboutDlg)
	//}}AFX_DATA_INIT
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CAboutDlg)
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
	//{{AFX_MSG_MAP(CAboutDlg)
		// No message handlers
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMonitor2Dlg dialog

CMonitor2Dlg::CMonitor2Dlg(CWnd* pParent /*=NULL*/)
	: CDialog(CMonitor2Dlg::IDD, pParent)
{
	//{{AFX_DATA_INIT(CMonitor2Dlg)
	m_csErrorEvent = _T("");
	m_csPrinter = _T("");
	m_csStatus = _T("");
	m_csStatusEvent = _T("");
	m_csStatusCode = _T("");
	//}}AFX_DATA_INIT
	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CMonitor2Dlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CMonitor2Dlg)
	DDX_Control(pDX, IDC_PRINT, m_cbPrint);
	DDX_Control(pDX, IDC_KILL_PROGRESS, m_cKillStat);
	DDX_Control(pDX, IDC_STATUSCODE_LIST, m_clStatusCode);
	DDX_Control(pDX, IDC_AUTO_STATUS, m_cbAutoStatus);
	DDX_Control(pDX, IDC_STATUS_LIST, m_clStatus);
	DDX_Text(pDX, IDC_ERROR_EVENT, m_csErrorEvent);
	DDX_Text(pDX, IDC_PRN, m_csPrinter);
	DDX_Text(pDX, IDC_Status, m_csStatus);
	DDX_Text(pDX, IDC_STATUS_EVENT, m_csStatusEvent);
	DDX_Text(pDX, IDC_STATUS_CODE, m_csStatusCode);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CMonitor2Dlg, CDialog)
	//{{AFX_MSG_MAP(CMonitor2Dlg)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_BN_CLICKED(IDC_GET_STATUS, OnGetStatus)
	ON_BN_CLICKED(IDC_AUTO_STATUS, OnAutoStatus)
	ON_EN_CHANGE(IDC_Status, OnChangeStatus)
	ON_LBN_SELCHANGE(IDC_STATUS_LIST, OnSelchangeStatusList)
	ON_COMMAND(AFX_ID_BM_CAL, OnIdBmCal)
	ON_COMMAND(AFX_ID_SELECT_PRINTER, OnIdSelectPrinter)
	ON_COMMAND(AFX_ID_SLEEP_TIME, OnIdSleepTime)
	ON_COMMAND(IDC_MENUEXIT, OnMenuexit)
	ON_COMMAND(IDM_ABOUTBOX, OnAboutbox)
	ON_BN_CLICKED(IDC_PRINT, OnPrint)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMonitor2Dlg message handlers
CMonitor2Dlg::~CMonitor2Dlg()
{
	if (m_StatusThread)
	{
		cTi.m_hStatusEventKillThread = TRUE;
		while (cTi.m_hStatusEventKillThread)
			Sleep(500);
	}
	if (m_PrintThread)
	{
		myTestPar.m_hKillThread = TRUE;
		while (myTestPar.m_hKillThread)
			Sleep(500);
	}

	if (cTi.hError)
		CloseHandle(cTi.hError);
	if (cTi.hStatus)
		CloseHandle(cTi.hStatus);
	if (cTi.hPrinter)
		ClosePrinter(cTi.hPrinter);

	if (myTestPar.m_DC)
	{
		myTestPar.m_DC.DeleteDC();
	}
	free(myTestPar.csImage);
}

BOOL CMonitor2Dlg::OnInitDialog()
{
	USES_CONVERSION;

	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.
	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

	// TODO: Add extra initialization here
	DWORD	dRet, dType, dNeeded;
	PRINTER_DEFAULTS pd;
	BOOL	bRet;
	LPTSTR cTmp;
	char *mbstr;

	// get the default printer and try setting it in the TTPMonitor Wrapper
	CPrintDialog dlg (FALSE);
	dlg.GetDefaults();
	if (myTestPar.m_DC!=NULL)
		myTestPar.m_DC.DeleteDC();
	myTestPar.m_DC.Attach( dlg.GetPrinterDC());
	m_csPrinter = dlg.GetDeviceName( );

	// global printer handle to be used later
	hPrinter = NULL;
	// Sleep time for the Auto Status
	dSleepTime = 10000;

	myTestPar.csImage = (LPTSTR)malloc(MAX_PATH+15);
	if (myTestPar.csImage)
	{
		GetCurrentDirectory(MAX_PATH, myTestPar.csImage);
		sprintf(myTestPar.csImage, "%s\\SWCUSLogo.bmp", myTestPar.csImage);
	}
	myTestPar.myHwnd = this->m_hWnd;
	myTestPar.iLineCount = 30;
	myTestPar.iPageCount = 1;
	myTestPar.iOrientation = 0;
	myTestPar.dSleepTime = dSleepTime;
	bPrint = FALSE;
	m_PrintThread = NULL;

	// 1. Step in the TTP Language Monitor Implementation guide
	// Open the printer for later use
	ZeroMemory(&pd, sizeof(pd));
	pd.DesiredAccess = PRINTER_ALL_ACCESS;
	bRet = OpenPrinter(m_csPrinter.GetBuffer(1), &hPrinter, &pd);
	if (!bRet || (hPrinter==NULL))
	{
		dRet = GetLastError();
		MessageBox("Error opening printer!","",MB_OK);
	}
	m_csPrinter.ReleaseBuffer();
	cTi.hPrinter = hPrinter;
	myTestPar.hPrinter = hPrinter;

	
	// still 1. Step in the TTP Language Monitor Implementation guide
	// get the event names
	cTmp = (LPTSTR)malloc(100);
	if ((dRet = GetPrinterData(hPrinter, "ErrorEventName", &dType, (LPBYTE)cTmp, 100, &dNeeded))!=ERROR_SUCCESS)
	{
		MessageBox("Error Event name error.","",MB_OK);
	}
	else
	{
		mbstr = m_csErrorEvent.GetBuffer(200);
		wcstombs( mbstr, (wchar_t *)cTmp, dNeeded);
 		m_csErrorEvent.ReleaseBuffer();
	}

	if ((dRet = GetPrinterData(hPrinter, "StatusEventName", &dType, (LPBYTE)cTmp, 100, &dNeeded))!=ERROR_SUCCESS)
	{
		MessageBox("Status Event name error.","",MB_OK);
	}
	else
	{
		mbstr = m_csStatusEvent.GetBuffer(200);
		wcstombs( mbstr, (wchar_t *)cTmp, dNeeded);
		m_csStatusEvent.ReleaseBuffer();
	}
	free(cTmp);

	// 2. Step in the TTP Language Monitor Implementation guide
	if ((cTi.hError = OpenEvent(SYNCHRONIZE, TRUE, m_csErrorEvent))==NULL)
	{
		dRet = GetLastError();
		MessageBox("Error Event open error.","",MB_OK);
	}
	myTestPar.hError = cTi.hError; 

	if ((cTi.hStatus = OpenEvent(SYNCHRONIZE, TRUE, m_csStatusEvent))==NULL)
	{
		dRet = GetLastError();
		MessageBox("Status Event open error.","",MB_OK);
	}
	myTestPar.hStatus = cTi.hStatus; 

	// Set the Status list box with current values
	m_csStatusCode = "3";
	for (int i=0; i<14; i++)
		m_clStatusCode.AddString(prnkey[i].name);

	// prepare the variables for the Status thread
	bStatus = FALSE;
	m_StatusThread = NULL;
	cTi.myHwnd = this->m_hWnd;
	cTi.dSleepTime = dSleepTime;
	cTi.m_hStatusEventKillThread = FALSE;

	UpdateData(FALSE);

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CMonitor2Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CMonitor2Dlg::OnPaint() 
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CMonitor2Dlg::OnQueryDragIcon()
{
	return (HCURSOR) m_hIcon;
}

void CMonitor2Dlg::OnGetStatus() 
{
	// TODO: Add your control notification handler code here
	int	iStatusCode;
	DWORD	dRet, dType, dNeeded, dTmp;

	UpdateData(TRUE);

	iStatusCode = m_clStatusCode.GetCurSel();

	if (prnkey[iStatusCode].type == REG_DWORD)
	{
		if ((dRet = GetPrinterData(hPrinter, prnkey[iStatusCode].name, &dType, (LPBYTE)&dTmp, sizeof(DWORD), &dNeeded))!=ERROR_SUCCESS)
		{
			MessageBox("Status error.","",MB_OK);
		}
		else
		{
			char *cTmp = m_csStatus.GetBuffer(100);
			sprintf(cTmp,"Status %08X", dTmp);
			m_csStatus.ReleaseBuffer();
		}
	}
	else
	{
		if (prnkey[iStatusCode].type == REG_BINARY)
		{
			char cbTmp[200];
			if ((dRet = GetPrinterData(hPrinter, prnkey[iStatusCode].name, &dType, (LPBYTE)cbTmp, 200, &dNeeded))!=ERROR_SUCCESS)
			{
				MessageBox("Status error.","",MB_OK);
			}
			else
			{
				char *cTmp = (char*)malloc(4*dNeeded);
				sprintf(cTmp,"%s ", prnkey[iStatusCode].name);
				for (DWORD i=0; i<dNeeded; i++)
					sprintf(cTmp,"%s %02X", cTmp, cbTmp[i]);
				m_csStatus = cTmp;
			}
		}
		else
		{
			if (prnkey[iStatusCode].type == REG_SZ)
			{
				LPTSTR cTmp;
				char *mbstr;
				cTmp = (LPTSTR)malloc(100);
				if ((dRet = GetPrinterData(hPrinter, prnkey[iStatusCode].name, &dType, (LPBYTE)cTmp, 100, &dNeeded))!=ERROR_SUCCESS)
				{
					MessageBox("Status error.","",MB_OK);
				}
				else
				{
					mbstr = m_csStatus.GetBuffer(200);
					wcstombs( mbstr, (wchar_t *)cTmp, dNeeded);
 					m_csStatus.ReleaseBuffer();
				}
				free(cTmp);
			}
		}
	}

	UpdateData(FALSE);
}

UINT StatusThreadProc( LPVOID pParam)
{
	CStatusThreadInfo* pInfo = (CStatusThreadInfo*)pParam;
	long dwResult=0, dwRet=0;
	char str[50];
	HANDLE myHandle[2];
	DWORD	dType, dNeeded;

    if (pInfo == NULL)
	{
		OutputDebugStringA("### entering Status Poll thread Failed!\n");
		return 1;   // if pObject is not valid
	}

	// 4. Step in the TTP Language Monitor Implementation guide
	// fill the event handles in an array of handles to be used with the 
	// WaitForMultipleObjects() function
	myHandle[0] = pInfo->hError;
	myHandle[1] = pInfo->hStatus;

	OutputDebugStringA("### entering Status Poll thread...\n");

	// 5. Step in the TTP Language Monitor Implementation guide
	// start the monitoring loop
	for ( ; ; )
	{
		if (pInfo->m_hStatusEventKillThread)
		{
			OutputDebugStringA("### [Thread msg.] Kill thread...\n");
			pInfo->m_hStatusEventKillThread = FALSE;
			AfxEndThread( 1 );
			return 1;
		}
		// wait for an event
		if ((dwRet = WaitForMultipleObjects(2, myHandle, FALSE, pInfo->dSleepTime))!=WAIT_FAILED)
		{
			// when an event occured
			if (dwRet==WAIT_OBJECT_0 || dwRet==WAIT_OBJECT_0+1)
			{
				// get the status with GetPrinterData
				if ((dwRet = GetPrinterData(hPrinter, "ERROR", &dType, (LPBYTE)&dwResult, sizeof(dwResult), &dNeeded))!=ERROR_SUCCESS)
				{
					sprintf( str, "### [Status Thread error %d] read [%08X]\n", dwRet, dwResult);
					OutputDebugStringA(str);
				}
				sprintf( str, "### [Status Thread] read [%08X]\n", dwResult);
				OutputDebugStringA(str);
				SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)(str));
				// then decode the status accordingly
				if (dwResult & 0x00000000)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_OK"));
				if (dwResult & PRINTER_STATUS_ERROR)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_ERROR"));
				if (dwResult & PRINTER_STATUS_PENDING_DELETION)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_PENDING_DELETION"));
				if (dwResult & PRINTER_STATUS_PAPER_JAM)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_PAPER_JAM"));
				if (dwResult & PRINTER_STATUS_PAPER_OUT)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_PAPER_OUT"));
				if (dwResult & PRINTER_STATUS_PAPER_PROBLEM)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_PAPER_PROBLEM"));
				if (dwResult & PRINTER_STATUS_OFFLINE)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_OFFLINE"));
				if (dwResult & PRINTER_STATUS_IO_ACTIVE)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_IO_ACTIVE"));
				if (dwResult & PRINTER_STATUS_BUSY)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_BUSY"));
				if (dwResult & PRINTER_STATUS_PRINTING)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_PRINTING"));
				if (dwResult & PRINTER_STATUS_OUTPUT_BIN_FULL)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_OUTPUT_BIN_FULL"));
				if (dwResult & PRINTER_STATUS_PROCESSING)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_PROCESSING"));
				if (dwResult & PRINTER_STATUS_USER_INTERVENTION)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_USER_INTERVENTION"));
				if (dwResult & PRINTER_STATUS_DOOR_OPEN)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_DOOR_OPEN"));
				
				if (dwResult & PRINTER_STATUS_PAPER_NEAR_END)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_PAPER_NEAR_END"));
				if (dwResult & PRINTER_STATUS_PAPER_WEEKEND)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_PAPER_WEEKEND"));
				if (dwResult & PRINTER_STATUS_PAPER_PRESENTER)
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_PAPER_PRESENTER"));
				if (dwResult & PRINTER_STATUS_EXTERNAL_ERROR)
				{
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("PRINTER_STATUS_EXTERNAL_ERROR"));
					if ((dwRet = GetPrinterData(hPrinter, "EXTERNALERROR", &dType, (LPBYTE)dwResult, sizeof(dwResult), &dNeeded))!=ERROR_SUCCESS)
					{
						sprintf( str, "### [Status Thread error %d] read [%08X]\n", dwRet, dwResult);
						OutputDebugStringA(str);
					}
					sprintf( str, "### [Status Thread External Error] read [%08X]\n", dwResult);
					OutputDebugStringA(str);
					SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)(str));
				}
			}
			else
				SendMessage(GetDlgItem((HWND)pInfo->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)("Timeout"));
		}
		else
		{
			dwRet = GetLastError();
			sprintf( str, "### Wait function failed! [%d]\n", dwRet);
			OutputDebugStringA(str);
		}
	}
	return 1;
}

void CMonitor2Dlg::OnAutoStatus() 
{
	// TODO: Add your control notification handler code here

	if (bStatus)
	{
		// stopping the monitoring thread
		bStatus = FALSE;
		cTi.m_hStatusEventKillThread = TRUE;
		if (m_StatusThread)
		{
			m_cKillStat.SetRange(0, 255);
			m_cKillStat.ShowWindow(SW_SHOW);
			while (cTi.m_hStatusEventKillThread)
			{
				m_cKillStat.StepIt();
				UpdateData(FALSE);
				Sleep(500);
			}
			MessageBox("Status Thread killed!", "", MB_OK);
			m_StatusThread = NULL;
			m_cbAutoStatus.SetWindowText("Auto Status");
			m_cKillStat.ShowWindow(SW_HIDE);
			m_StatusThread = FALSE;
		}
	}
	else
	{
	// 3. Step in the TTP Language Monitor Implementation guide
	// Starting the monitoring thread.
		bStatus = TRUE;
		m_StatusThread = AfxBeginThread( StatusThreadProc, &cTi, THREAD_PRIORITY_NORMAL,0,0,NULL);
		if (m_StatusThread)
		{
			m_cbAutoStatus.SetWindowText("Stop Auto Status");
		}

	}

}

void CMonitor2Dlg::OnChangeStatus() 
{
	// TODO: If this is a RICHEDIT control, the control will not
	// send this notification unless you override the CDialog::OnInitDialog()
	// function and call CRichEditCtrl().SetEventMask()
	// with the ENM_CHANGE flag ORed into the mask.
	
	// TODO: Add your control notification handler code here
	int iSel;
	UpdateData(TRUE);
	m_clStatus.AddString(m_csStatus);
	iSel = m_clStatus.GetCount();
	m_clStatus.SetCurSel(iSel-1);
	UpdateData(FALSE);
	
}


void CMonitor2Dlg::OnSelchangeStatusList() 
{
	// TODO: Add your control notification handler code here
	int iSel;
	UpdateData(TRUE);
	iSel = m_clStatus.GetCount();
//	m_clStatus.SetCurSel(iSel-1);
	UpdateData(FALSE);
}

void CMonitor2Dlg::OnIdBmCal() 
{
	// TODO: Add your command handler code here
	USES_CONVERSION;
//	MessageBox("Black Mark Calibration","",MB_OK);
	char cCmd[3];
	DWORD dRet;

	CString csTmp;
	int iCnt=0;

	cCmd[0] = 0x1b;
	cCmd[1] = 0x23;
	if ((dRet=WriteEscapeToPrinter(cCmd, 2))!=ERROR_SUCCESS)
	{
		DisplayLastError(dRet);
	}

	if (MessageBox("Printer Calibrated!\nDo you want to save the new value?", "Black Mark Calibration", MB_YESNO)==IDYES)
	{
		cCmd[0] = 0x1b;
		cCmd[1] = 0x26;
		cCmd[2] = 0x04;
		if ((dRet=WriteEscapeToPrinter(cCmd, 3))!=ERROR_SUCCESS)
		{
			DisplayLastError(dRet);
		}
	}
}

void CMonitor2Dlg::OnIdSelectPrinter() 
{
	USES_CONVERSION;
	// TODO: Add your command handler code here
	DWORD fMode = 0, dRet, dNeeded, dType;
	BOOL	bRet;
	PRINTER_DEFAULTS pd;
	LPTSTR cTmp;
	char *mbstr;

	CPrintDialog dlg (FALSE);

	if (dlg.DoModal() == IDOK)
	{
		if (myTestPar.m_DC)
		{
			myTestPar.m_DC.DeleteDC();
		}
		myTestPar.m_DC.Attach( dlg.GetPrinterDC());
		m_csPrinter = dlg.GetDeviceName( );
		
		if (hPrinter)
		{
			ClosePrinter(hPrinter);
			hPrinter = NULL;
		}
		// open printer handle

		ZeroMemory(&pd, sizeof(pd));
		pd.DesiredAccess = PRINTER_ALL_ACCESS;
		bRet = OpenPrinter(m_csPrinter.GetBuffer(1), &hPrinter, &pd);
		m_csPrinter.ReleaseBuffer();

		if(hPrinter == NULL)
		{
			MessageBox("Open printer error.","",MB_OK|MB_ICONERROR|MB_SYSTEMMODAL);
			return;
		}

		if (m_csPrinter.GetLength()!=0)
		{
			cTi.hPrinter = hPrinter;
			myTestPar.hPrinter = hPrinter;
			if (cTi.hError)
			{
				CloseHandle(cTi.hError);
				cTi.hError = NULL;
			}
			if (cTi.hStatus)
			{
				CloseHandle(cTi.hStatus);
				cTi.hStatus = NULL;
			}
			// get the event names
			cTmp = (LPTSTR)malloc(100);
			if ((dRet = GetPrinterData(hPrinter, "ErrorEventName", &dType, (LPBYTE)cTmp, 100, &dNeeded))!=ERROR_SUCCESS)
			{
				MessageBox("Error Event name error.","",MB_OK);
			}
			else
			{
				mbstr = m_csErrorEvent.GetBuffer(200);
				wcstombs( mbstr, (wchar_t *)cTmp, dNeeded);
 				m_csErrorEvent.ReleaseBuffer();
			}

			if ((dRet = GetPrinterData(hPrinter, "StatusEventName", &dType, (LPBYTE)cTmp, 100, &dNeeded))!=ERROR_SUCCESS)
			{
				MessageBox("Status Event name error.","",MB_OK);
			}
			else
			{
				mbstr = m_csStatusEvent.GetBuffer(200);
				wcstombs( mbstr, (wchar_t *)cTmp, dNeeded);
				m_csStatusEvent.ReleaseBuffer();
			}
			free(cTmp);


			if ((cTi.hError = OpenEvent(SYNCHRONIZE, TRUE, m_csErrorEvent))==NULL)
			{
				dRet = GetLastError();
				MessageBox("Error Event open error.","",MB_OK);
			}
			myTestPar.hError = cTi.hError; 

			if ((cTi.hStatus = OpenEvent(SYNCHRONIZE, TRUE, m_csStatusEvent))==NULL)
			{
				dRet = GetLastError();
				MessageBox("Status Event open error.","",MB_OK);
			}
			myTestPar.hStatus = cTi.hStatus; 

		}
	}
	UpdateData(FALSE);
}

void CMonitor2Dlg::OnIdSleepTime() 
{
	// TODO: Add your command handler code here
//	MessageBox("Set Sleep Time","",MB_OK);
	CConfig dlg;
	int iLen;
	LPTSTR csTmp;

	dlg.m_dSleepTime = dSleepTime;
	iLen = strlen(myTestPar.csImage);
	csTmp = dlg.m_csImage.GetBuffer(iLen);
	strcpy(csTmp, myTestPar.csImage);
	dlg.m_csImage.ReleaseBuffer();
	dlg.m_iLineCnt = myTestPar.iLineCount;
	dlg.m_iPgCnt = myTestPar.iPageCount;

	int nResponse = dlg.DoModal();
	if (nResponse == IDOK)
	{
		// TODO: Place code here to handle when the dialog is
		//  dismissed with OK
		dSleepTime = dlg.m_dSleepTime;
		strcpy(myTestPar.csImage,dlg.m_csImage);
		myTestPar.iLineCount = dlg.m_iLineCnt;
		myTestPar.iPageCount = dlg.m_iPgCnt;
		myTestPar.dSleepTime = dSleepTime;
		cTi.dSleepTime = dSleepTime;
	}

}

void CMonitor2Dlg::OnMenuexit() 
{
	// TODO: Add your command handler code here
	OnOK();
}


void CMonitor2Dlg::OnAboutbox() 
{
	// TODO: Add your command handler code here
	CAboutDlg dlgAbout;
	dlgAbout.DoModal();
	
}

DWORD CMonitor2Dlg::WriteEscapeToPrinter( 	char* pBuf,  // array that contains printer data
											DWORD cbBuf)  // size, in bytes, of array
{
	DWORD dwRetBytes = 0;
	DWORD dRet;
	DWORD hJob;
	DOC_INFO_1 docinfo;

	docinfo.pDocName = "Black Mark Calibration";
	docinfo.pOutputFile = "";
	docinfo.pDatatype = NULL;
	hJob = StartDocPrinter(hPrinter,1,(BYTE *)&docinfo);
	if(!hJob)
	{
		return GetLastError();
	}
	if ((dRet=StartPagePrinter(hPrinter))==0)
	{	
		return GetLastError();
	}

	if (!WritePrinter(hPrinter,pBuf, cbBuf,&dwRetBytes))
		dRet = GetLastError();
	else
		dRet = ERROR_SUCCESS;
	if(!EndPagePrinter(hPrinter))
	{	
		return GetLastError();
	}
	if (!EndDocPrinter((HANDLE)hPrinter))
	{	
		return GetLastError();
	}

	return dRet;
}

void CMonitor2Dlg::DisplayLastError(DWORD LastError)
{
	LPVOID lpMsgBuf;
	CString csError;		

	DWORD dwBufferSize = 
		FormatMessage( 
		FORMAT_MESSAGE_ALLOCATE_BUFFER | 
		FORMAT_MESSAGE_FROM_SYSTEM | 
		FORMAT_MESSAGE_IGNORE_INSERTS,
		NULL,
		LastError,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
		(LPTSTR) &lpMsgBuf,
		0,
		NULL 
		);
	if (lpMsgBuf)
	{
		MessageBox( (const char *)lpMsgBuf, "Last Error", MB_OK);
		LocalFree( lpMsgBuf );
	}
	else
	{
		sprintf(csError.GetBuffer(200), "Error %d", LastError);
		csError.ReleaseBuffer();
		MessageBox(csError, "LastError", MB_OK);
	}
}

void CMonitor2Dlg::OnPrint() 
{
	UpdateData(TRUE);
	if (bPrint)
	{
		bPrint = FALSE;
		myTestPar.m_hKillThread = TRUE;
		if (m_PrintThread)
		{
			m_cKillStat.SetRange(0, 255);
			m_cKillStat.ShowWindow(SW_SHOW);
			while (myTestPar.m_hKillThread)
			{
				m_cKillStat.StepIt();
				UpdateData(FALSE);
				Sleep(500);
			}
//			MessageBox("Print Thread killed!", "", MB_OK);
			m_StatusThread = NULL;
			m_cbPrint.SetWindowText("Print");
			m_cKillStat.ShowWindow(SW_HIDE);
			m_PrintThread = NULL;
		}
	}
	else
	{
		bPrint = TRUE;
		myTestPar.dPrintCnt = 0;
		
		m_PrintThread = AfxBeginThread( MyPrintDocument, &myTestPar, THREAD_PRIORITY_NORMAL,0,0,NULL);
		if (m_PrintThread)
		{
			m_cbPrint.SetWindowText("Stop Print");
		}

	}
}

UINT MyPrintDocument(LPVOID pParam) 
{
	USES_CONVERSION;
	// TODO: Add your control notification handler code here
	int		CurrentX=0, CurrentY=0;
	int		TextHeigth=0, TextWidth=0;

	char *args[4], prog[80], par[80];
	args[1] = NULL;
	args[2] = NULL;
	args[3] = NULL;

	time_t	myTime_t;
	struct	tm *ptm;

	DOCINFO di;
	int nJobID;

	CFont	fntCurrentFont, fntCurrentFontBold, fntCurrentFontItalics, fntCurrentFontItalicsBold, fntCurrentFontUPCBarcode;
	CSize	m_Size;
	CRect	m_Rect;

	HDC		hDCbmp;
	HBITMAP hBitmap;
	BITMAP  mBmp;

	char sCurDir[MAX_PATH];
	char sSysDir[MAX_PATH];
	char str[50];
	DWORD	dRet=0, dwResult=0,dwResult1=0, dType, dNeeded;

	int iCnt;


	TESTPAR* myTestPar = (TESTPAR*)pParam;
    if (myTestPar == NULL)
	{
		OutputDebugStringA("### entering Status Poll thread Failed!\n");
		AfxEndThread( 0 );
		return 0;
	}
	
	if (myTestPar->m_DC == NULL)
		AfxEndThread(0);

	if ( !fntCurrentFont.CreateFont( 
//			30, 0, 0, 0, FW_BOLD, 0, 0, 0,
			30, 0, 0, 0, FW_NORMAL, 0, 0, 0,
			ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
			DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
//			"Comic Sans MS") )
//			"Courier New") )
			"Monospac821 BT") )
		AfxEndThread( 0 );
	
	if ( !fntCurrentFontBold.CreateFont( 
			30, 15, 0, 0, FW_BOLD, 0, 0, 0,
			ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
			DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
			"Monospac821 BT") )
		AfxEndThread( 0 );

	if ( !fntCurrentFontItalics.CreateFont( 
			30, 0, 0, 0, FW_NORMAL, 1, 0, 0,
			ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
			DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
			"Monospac821 BT") )
		AfxEndThread( 0 );

	if ( !fntCurrentFontItalicsBold.CreateFont( 
			30, 15, 0, 0, FW_BOLD, 1, 0, 0,
			ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
			DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
			"Monospac821 BT") )
		AfxEndThread( 0 );


	GetCurrentDirectory(MAX_PATH, sCurDir);
	GetSystemDirectory(sSysDir, MAX_PATH);

	di.cbSize      = sizeof(DOCINFO);
	di.lpszDocName = "Receipt Printer Test";
	di.lpszOutput  = NULL;
//	di.lpszOutput  = "test.prn";
	di.lpszDatatype= NULL;

	for (;;)
	{
		if (myTestPar->m_hKillThread)
		{
			OutputDebugStringA("### [Thread msg.] Kill thread...\n");
			
			fntCurrentFont.DeleteObject();
			fntCurrentFontBold.DeleteObject();
			fntCurrentFontItalics.DeleteObject();
			fntCurrentFontItalicsBold.DeleteObject();
			
			myTestPar->m_hKillThread = FALSE;
			AfxEndThread( 1 );
			return 1;
		}

		iCnt = 0;
		if ((dRet = GetPrinterData(hPrinter, "ERROR", &dType, (LPBYTE)&dwResult, sizeof(dwResult), &dNeeded))!=ERROR_SUCCESS)
		{
			sprintf( str, "### [Print Thread error %d] read [%08X]\n", dRet, dwResult);
			OutputDebugStringA(str);
		}
		
		if (dwResult & 0x1FFFFFFF)
		{
			sprintf(str, "### Error: %08X", dwResult);
			OutputDebugStringA(str);
			SendMessage(GetDlgItem((HWND)myTestPar->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)(str));
			if (dwResult1!= dwResult)
			{
				dwResult1 = dwResult;
				sprintf(prog, "%s\\WScript.exe", sSysDir);
				sprintf(par, "\"%s\\PaperError.vbs\"", sCurDir);
				args[0] = prog;
				args[1] = par;
				sprintf( str, "\"Status [%08X]\"",dwResult);
				if (_spawnl(_P_WAIT, prog, "//Nologo", par, str, NULL)==-1)
				{
					sprintf(prog, "Error runing VB script: errno = %d\n", errno);
					OutputDebugStringA(prog);
				}
			}
			if (dwResult & 0x10000000)
			{
				if ((dRet = GetPrinterData(hPrinter, "EXTERNALERROR", &dType, (LPBYTE)dwResult, sizeof(dwResult), &dNeeded))!=ERROR_SUCCESS)
				{
					sprintf( str, "### [Print Thread error %d] read [%08X]\n", dRet, dwResult);
					OutputDebugStringA(str);
				}
				sprintf(str, "### External Error: %08X", dwResult);
				OutputDebugStringA(str);
				SendMessage(GetDlgItem((HWND)myTestPar->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)(str));
			}

		
		}
		else
		{
			sprintf(str, "### Status: %08X", dwResult);
			OutputDebugStringA(str);
			SendMessage(GetDlgItem((HWND)myTestPar->myHwnd, IDC_Status), WM_SETTEXT, 0, (LPARAM)(str));
			if (dwResult1!= dwResult)
			{
				dwResult1= dwResult;
				if (dwResult & 0x20000000)
				{
					sprintf(prog, "%s\\WScript.exe", sSysDir);
					sprintf(par, "\"%s\\Paperlow.vbs\"", sCurDir);
					sprintf( str, "\"Status [%08X]\"",dwResult);
					if (_spawnl(_P_WAIT, prog, "//Nologo", par, str, NULL)==-1)
					{
						sprintf(prog, "Error runing VB script: errno = %d\n", errno);
						OutputDebugStringA(prog);
					}
				}
			}
			// Starting Page definition 
			nJobID = myTestPar->m_DC.StartDoc(&di);
			if (nJobID<=0)
			{
				sprintf(str, "### Error in StartDoc %d", GetLastError());
				OutputDebugStringA(str);
			}
			else
			{
				myTestPar->dPrintCnt ++;
				for (int cnt = 0; cnt<myTestPar->iPageCount; cnt++)
				{
					myTestPar->m_DC.StartPage();

					m_Size.cx = myTestPar->m_DC.GetDeviceCaps( HORZRES);
					m_Size.cy = myTestPar->m_DC.GetDeviceCaps( VERTRES);

					if (strlen(myTestPar->csImage))
					{
						hBitmap = (HBITMAP)LoadImage(
									NULL,   // handle of the instance containing the image
									myTestPar->csImage,  // name or identifier of image
									IMAGE_BITMAP,        // type of image
									0,     // desired width
									0,     // desired height
									LR_DEFAULTSIZE|LR_LOADFROMFILE|LR_MONOCHROME        // load flags
								   );
						if (hBitmap)
						{
							GetObject(hBitmap, sizeof(BITMAP), &mBmp);
							hDCbmp = CreateCompatibleDC( myTestPar->m_DC.m_hDC );
							SelectObject(hDCbmp, hBitmap);
							BitBlt( myTestPar->m_DC.m_hDC, ((m_Size.cx - mBmp.bmWidth)/2), 10, mBmp.bmWidth, mBmp.bmHeight, hDCbmp, 0, 0, SRCCOPY );
							DeleteObject(hBitmap);
							DeleteDC(hDCbmp);
							CurrentY = mBmp.bmHeight+10;
							CurrentX = mBmp.bmWidth;
						}
						else
							CurrentY = 0;
					}
					else
						CurrentY = 0;

					CurrentX = 0;

					if ((myTestPar->iOrientation+1)==DMORIENT_LANDSCAPE)
					{
						OutputDebugStringA("Can't print Landscape!");
					}
					else
					{
						myTestPar->m_DC.SelectObject(&fntCurrentFont);
						TextHeigth = myTestPar->m_DC.GetTextExtent("A", 1).cy;
						myTestPar->m_DC.SetTextAlign(TA_CENTER);
						m_Rect.bottom = CurrentY + TextHeigth;
						m_Rect.left = CurrentX;
						m_Rect.top = CurrentY;
						m_Rect.right = m_Size.cx;
						myTestPar->m_DC.TextOut ( m_Size.cx/2, CurrentY, "----------------------------------------", strlen("----------------------------------------"));
						CurrentY += 2 * TextHeigth;
						m_Rect.bottom = CurrentY + TextHeigth;
						m_Rect.left = CurrentX;
						m_Rect.top = CurrentY;
						myTestPar->m_DC.SelectObject(&fntCurrentFontBold);
						myTestPar->m_DC.TextOut ( m_Size.cx/2, CurrentY, "Welcome to Swecoin's Printer Test!", strlen("Welcome to Swecoin's Printer Test!"));
						CurrentY += 2 * TextHeigth;
						myTestPar->m_DC.TextOut ( m_Size.cx/2, CurrentY, "Swecoin Printer Test", strlen("Swecoin Printer Test"));
						CurrentY += TextHeigth;
						myTestPar->m_DC.TextOut ( m_Size.cx/2, CurrentY, "1037 Aquidneck Ave", strlen("1037 Aquidneck Ave"));
						CurrentY += TextHeigth;
						myTestPar->m_DC.TextOut ( m_Size.cx/2, CurrentY, "Middletown, RI - 02842", strlen("Middletown, RI - 02842"));
						CurrentY += TextHeigth;

						time(&myTime_t);
						ptm=localtime(&myTime_t);
						if (ptm)
						{
							sprintf(str, "%02d-%02d-%04d %02d:%02d:%02d", ptm->tm_mday,
											ptm->tm_mon+1, ptm->tm_year+1900, ptm->tm_hour,
											ptm->tm_min, ptm->tm_sec);
						}
						myTestPar->m_DC.SetTextAlign(TA_LEFT);
						myTestPar->m_DC.TextOut (CurrentX, CurrentY, str, strlen(str));
						CurrentY += 2 * TextHeigth;
						myTestPar->m_DC.SelectObject(&fntCurrentFontBold);
						myTestPar->m_DC.TextOut ( CurrentX, CurrentY, "----------------------------------------", strlen("----------------------------------------"));
						CurrentY +=  TextHeigth;

					}

					for(int nCompt = 0; nCompt < myTestPar->iLineCount; nCompt++)
					{
						sprintf(str, "%d Line printing test ########################", nCompt);

						if ((myTestPar->iOrientation+1)==DMORIENT_LANDSCAPE)
						{
							if ((nCompt>0) && ((nCompt % 10)==0))
							{
								TextWidth	 = myTestPar->m_DC.GetTextExtent( str, strlen(str)).cx;
								CurrentX += (TextWidth + 20);
								CurrentY = 0;
							}
						}
						myTestPar->m_DC.SelectObject(&fntCurrentFont);
						if (nCompt%3)
							myTestPar->m_DC.SelectObject(&fntCurrentFontBold);
						else
							if (nCompt%5)
								myTestPar->m_DC.SelectObject(&fntCurrentFontItalics);
							else
							if (nCompt%7)
								myTestPar->m_DC.SelectObject(&fntCurrentFontItalicsBold);

						myTestPar->m_DC.TextOut ( CurrentX, CurrentY, str, strlen(str));
						CurrentY += TextHeigth;
					}
					// Print the text
					myTestPar->m_DC.EndPage();
				}
				myTestPar->m_DC.EndDoc();
			}
		}
		Sleep(myTestPar->dSleepTime);
	}

}

