/*  Project Tec3270

	 SUBSYSTEM:    Tec3270.exe (Tec3270 application)
	 FILE:         alffnprt.cpp
	 AUTHOR:       Alcindo Ferreira Filho

	 OVERVIEW:

    ALFFRemotePrinter Class Implementation, the Tec3270 remote printer
    session class. Sessions are childs of class ALFFMDIClient,
    the MDI manager.

    COPYRIGHT:    © 1998-2007
                  Alcindo Ferreira Filho
                  <alcindo@inttec.com.br>

    LICENSE:      Tec3270_License (docs/Tec3270_License.txt)
*/
#include "alffnall.h"

// Controls For Printer Session Simulation On Debugging
//=============================================================
//      #define  DEBUG32    1
//      #define  ALFFRemotePrtDebug  1
//      #define  DEBUG_LU3PRT 1
//#define DEBUG_QUERYREPLYLU1 1
//#define DEBUG_QUERYREPLYLU1TN3270 1
//#define DEBUG_QUERYREPLYLU3 1
//#define DEBUG_QUERYREPLYLU3TN3270 1
//#define  DEBUG_NVT
//      #define  DEBUG_PRT  1
//=============================================================


//{{ALFFRemotePrinter Implementation}}
//
// Build a response table for all messages/commands handled
// by ALFFRemotePrinter derived from TWindow
//
DEFINE_RESPONSE_TABLE1(ALFFRemotePrinter, TWindow)
//{{ALFFRemotePrinterRSP_TBL_BEGIN}}
	 EV_MESSAGE(MSG_CLUSTER_NOTIFY, DoClusterNotification),
	 EV_MESSAGE(MSG_LINE_NOTIFY, DoLineNotification),
	 EV_MESSAGE(MSG_NET_INPUT_NOTIFY, DoNetInputProcess),
    EV_MESSAGE(MSG_NET_INPUT_LU1_NOTIFY, DoNetInputLU1Process),
    EV_MESSAGE(MSG_NET_END_OF_PRINTING_NOTIFY, DoPrinterBeginEndOfJob),
	 EV_MESSAGE(MSG_OUTPUT_NOTIFY, DoNetOutputProcess),
	 EV_MESSAGE(MSG_OUTPUT_ECHO, DoNetOutputEcho),
    EV_MESSAGE(MSG_START_TLS, EvStartTLS),

	 /* Session Menu Command Handlers */
	 EV_COMMAND(CM_CONNECTREMPRT, CmConnect),
	 EV_COMMAND_ENABLE(CM_CONNECTREMPRT, CmConnectEnable),
	 EV_COMMAND(CM_DISCONNECTREMPRT, CmDisconnect),
	 EV_COMMAND_ENABLE(CM_DISCONNECTREMPRT, CmDisconnectEnable),
    EV_COMMAND(CM_CHANGEREMPRTSESS,CmChangePrtSess),
	 EV_COMMAND_ENABLE(CM_CHANGEREMPRTSESS, CmConnectEnable),
    EV_COMMAND(CM_CHOOSEREMPRTFONT,CmChoosePrtFont),
	 EV_COMMAND_ENABLE(CM_CHOOSEREMPRTFONT, CmConnectEnable),
	 EV_COMMAND(CM_ALFFREMPRTSETUP, CmPrinterSetup),
    EV_COMMAND_ENABLE(CM_ALFFREMPRTSETUP, CmPrinterEnable),
    EV_COMMAND(CM_ALFFREMPRTEXIT, CmCloseWindow),

    /* Security Menu Command Handlers */
    EV_COMMAND(CM_ALFFREMPRTCERTIFICATE, CmShowCertificate),
    EV_COMMAND_ENABLE(CM_ALFFREMPRTCERTIFICATE,CmShowCertificateEnable),

	 /* Options Menu Command Handlers */
	 EV_COMMAND(CM_TRACEREMPRT, CmTraceSession),
	 EV_COMMAND_ENABLE(CM_TRACEREMPRT, CmTraceSessionEnable),

    /* Menu Select  Command Processing */
    EV_WM_MENUSELECT,

    /* SSL Padlock Draw Message */
    EV_WM_DRAWITEM,

    /* Mouse Clicked on Status Bar */
    EV_WM_SETCURSOR,

    /* Mouse Clicked  ....         */
    EV_WM_NCHITTEST,

//{{ALFFRemotePrinterRSP_TBL_END}}
END_RESPONSE_TABLE;


//////////////////////////////////////////////////////////
// ALFFRemotePrinter
// ====================
// Construction/Destruction handling.
ALFFRemotePrinter::ALFFRemotePrinter (TWindow* parent,
                                  ALFFDate::DateFormat fmt,
											 ALFFConnData* cnnData,
											 int sessionId):
											 ALFFDialog(parent, IDD_ALFFREMPRT,
                                             parent->GetModule(), true /*center dialog*/),
											 nLineState(nIdle),
											 dataSent(true),
                                  sslLockRect(0,0,0,0),
                                  mousePos(0,0)
{
    // Printer parent
	 myParent = parent;

	 /* Get the Application IniFile Pointer*/
	 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
    dateFormat = fmt;
    
	 // Set Connection Data Up
    connData = new ALFFConnData();
	 strcpy(connData->connName,cnnData->connName);
	 strcpy(connData->sessTitle,cnnData->sessTitle);
	 strcpy(connData->hostName,cnnData->hostName);
	 connData->portNumber = cnnData->portNumber;
    connData->securityMethod   = cnnData->securityMethod;
	 connData->connLog = false;
	 connData->connReconn = cnnData->connReconn;
	 connData->connExit  = cnnData->connExit;
	 connData->connDoNothing = cnnData->connDoNothing;
	 connData->actOption = NO_TIMER;   //No session timeout;
	 connData->intvTime = 0;			  //No time specified
	 connData->pressKey  = 0;          //Enter key;
	 connData->bringTop = false;
	 connData->soundAlm = cnnData->soundAlm;
	 connData->actYale = false;		  //No Yale Nulls Processing
	 connData->monTime =  -1;			  //No Monitoring session;
	 connData->termType = cnnData->termType;
    strcpy(connData->terminalNetName,cnnData->terminalNetName);
	 connData->codePage = 0;      	  //Assume EBCDIC Code Page 037

    /* Set colors from terminal session defines */
    connData->scrCharColor = cnnData->scrCharColor;
 	 connData->scrBkgdColor = cnnData->scrBkgdColor;
 	 connData->scr3270BkgdColor = cnnData->scr3270BkgdColor;
 	 connData->scrNormalUnprotTextColor = cnnData->scrNormalUnprotTextColor;
 	 connData->scrHighlightUnprotTextColor = cnnData->scrHighlightUnprotTextColor;
 	 connData->scrNormalProtTextColor = cnnData->scrNormalProtTextColor;
 	 connData->scrHighlightProtTextColor = cnnData->scrHighlightProtTextColor;
 	 connData->neutral = cnnData->neutral;
 	 connData->blue = cnnData->blue;
 	 connData->red = cnnData->red;
 	 connData->pink = cnnData->pink;
 	 connData->green = cnnData->green;
  	 connData->turquoise = cnnData->turquoise;
 	 connData->yellow = cnnData->yellow;
 	 connData->inverseNeutral = cnnData->inverseNeutral;
 	 connData->black = cnnData->black;
 	 connData->deepBlue = cnnData->deepBlue;
 	 connData->orange = cnnData->orange;
 	 connData->purple = cnnData->purple;
 	 connData->paleGreen = cnnData->paleGreen;
 	 connData->paleTurquoise = cnnData->paleTurquoise;
 	 connData->gray = cnnData->gray;
    connData->white = cnnData->white;

  	 /* Remote Printer Session Config Info   */
    strcpy(connData->printerNetName,cnnData->printerNetName);
    connData->printerAssociated = cnnData->printerAssociated;  // Remote Printer Associated to terminal
    connData->printerOnly   = cnnData->printerOnly;    // Must use Printer Netname supplied
	 connData->printerInact = cnnData->printerInact;
	 connData->printerOnColor = cnnData->printerOnColor;
	 connData->printerDimen =  cnnData->printerDimen;
	 connData->printerIgnoreFF = cnnData->printerIgnoreFF;
	 connData->printerBreakLine = cnnData->printerBreakLine;
	 connData->printerTabWidth =  cnnData->printerTabWidth;
	 connData->printerCharPerInch = cnnData->printerCharPerInch;
	 connData->printerLinePerInch =  cnnData->printerLinePerInch; // (SLD)
	 connData->printerCharPerLine = cnnData->printerCharPerLine;  //(MPP)
	 connData->printerLinePerPage =  cnnData->printerLinePerPage; //(MPL)
	 connData->printerTimeInact =   cnnData->printerTimeInact;
	 connData->printerTimeConcat =  cnnData->printerTimeConcat;
	 connData->printerTimeEnd =  cnnData->printerTimeEnd;
	 connData->printerNullLine = cnnData->printerNullLine;
	 connData->printerNullAsSpace = cnnData->printerNullAsSpace;
	 connData->printerIgnoreAttr =  cnnData->printerIgnoreAttr;
	 connData->printerFFAsSpace =   cnnData->printerFFAsSpace;
	 connData->printerFFAnyPos =  cnnData->printerFFAnyPos;
	 connData->printerEndLineNL = cnnData->printerEndLineNL;
	 connData->printerEndLineCR = cnnData->printerEndLineCR;
	 connData->printerSCSErr =   cnnData->printerSCSErr;
	 connData->printerInheritParm = cnnData->printerInheritParm;
    /*--------------------------------------------------------*/

	 connData->scriptOn = false;       //Assume No Script File;
  	 connData->scriptFile[0] = NULL;

	 div_t res;
	 if (sessionId>0)
		 res = div(sessionId-1,MAXCHILDPERTIME);
	  else res = div(1,MAXCHILDPERTIME);
	 connNumber = res.rem+1;
	 connShift  = res.quot;

	 // Setup ALFF Messages Object
	 pMsgs = new ALFFMsgs(this);

	 // Make Initial Printer Title
	 char prtHdr[STRINGMSGLEN];

	 // Generate a title for the Remote Printer window.
    pMsgs->LoadString(IDS_LINESTATNOTCONNECTED, prtHdr, STRINGMSGLEN-1);
    connInitialTitle = prtHdr;
    connStatusTitle = connInitialTitle;

	 connTextTitle = "";
	 connTraceTitle = "";

#ifdef DEBUG32
	MessageBox("Creating Buffers...","Tec3270 Remote Prt Debug",MB_OK);
#endif

	 // Create Ring Buffers For Send & Receive Data
	 pLineInBuf   = new ALFFBuffer(5*BUFSIZE);
	 pLineOutBuf  = new ALFFBuffer(5*BUFSIZE);
	 pNetInBuf  = new ALFFBuffer(5*BUFSIZE);
	 pNetOutBuf = new ALFFBuffer(5*BUFSIZE);
    pOOBData   = new ALFFBuffer(BUFSIZE/2);

#ifdef DEBUG32
	MessageBox("Creating Tec3270CommLine...","Tec3270 Remote Prt Debug",MB_OK);
#endif

	 // Create Line Communication Object
	 pLineComm = new ALFFCommLine(this, theApp->GetSecurityObj(), dateFormat);

    // Use Asynchronous Line Mode
    pLineComm->StartLineNotification();

#ifdef DEBUG32
	MessageBox("Creating ALFFNvt...","Tec3270 Remote Prt Debug",MB_OK);
#endif
#define PRINTERBUFFER true
	 // Create NVT Object for processing Basic Terminal stream
	 pNVTBuf = new ALFFNvt(connData, PRINTERBUFFER);

#ifdef DEBUG32
	MessageBox("Creating ALFF3270...","Tec3270 Remote Prt Debug",MB_OK);
#endif
	 // Create Terminal 3270 Object for processing 3270 stream
#define  ISPRINTER  true
	 p3270Buf = new ALFF3270(connData, ISPRINTER);
	 termBufferInitialized = false;

#ifdef DEBUG32
	MessageBox("Creating ALFFTelnet...","Tec3270 Remote Prt Debug",MB_OK);
#endif
	 // Create Telnet Object for processing Telnet Data
	 pTelnet = new ALFFTelnet(this, connData, true /*printerLine*/);

	 // Setup Event driven Process Controls
	 netInputProcessing = false;
	 netInputQueue      = 0;
    dataTypeQueue    = new WPARAM[32];
	 receiving = false;
	 recvQueue = 0;
	 sending = false;
	 sendQueue = 0;

	 // Setup Log Data Trace Status Off
	 traceON = false;
	 SetScrLogOn(false);
	 pTrcFile = NULL;
	 pConnLog = NULL;

	 autoConnect = false;
	 numReconnTries = 0;
    disconnectedByHost = false;

    /* SSL Controls */
    connectPendingForReadWrite = false;
    receiveDataPendingForReadWrite = false;
    sendDataPendingForReadWrite    = false;
    disconnectPendingForReadWrite = false;

	 /* Initialize Printer Objects  */
	 Printer = 0;
	 Printing = false;
    printerBuf = 0;
    totalReportsQuantity = 0;
    totalReportsLines    = 0;
    thisReportLines      = 0;

	 ALFFIniFile* iniFile = theApp->GetIniFile();
    char iniSection[21];

    // Create and Load Printer Device Descriptors */
    prtData = new ALFFPrtData();

    //
    strcpy(iniSection,"REMOTE PRINTER DEVICE");
    iniFile->GetString(iniSection,"DRIVER", "", prtData->prtDriver, 64);
    iniFile->GetString(iniSection,"DEVICE", "", prtData->prtDevice, 128);
    iniFile->GetString(iniSection,"OUTPUT", "", prtData->prtOutput, 128);
    prtData->defaultPrt = iniFile->GetInt(iniSection,"DEFAULT",0);

	 /*
	  * Get Remote Printer Font From INI File and Calculate its size.
	  *  Relies on MM_LOENGLISH map mode.
	  */
    TScreenDC dc;
	 prtFontName = new char[256];
	 iniFile->GetString(iniSection,"FONTNAME","Courier New",
								  prtFontName,255);
	 prtCharHeight = iniFile->GetInt(iniSection,"FONTHEIGHT",12);
	 prtCharWidth  = iniFile->GetInt(iniSection,"FONTWIDTH",8);
	 prtFontSize  = iniFile->GetInt(iniSection,"FONTSIZE",11);
	 int fontHeight  =
			 -MulDiv(prtFontSize,dc.GetDeviceCaps(LOGPIXELSY),72);
	 prtFontWeight = iniFile->GetInt(iniSection,"FONTWEIGHT",0);
	 prtFontItalic = iniFile->GetInt(iniSection,"FONTITALIC",0);
	 prtFontCharset = iniFile->GetInt(iniSection,"FONTCHARSET",0);
	 prtFont = new TFont(prtFontName,fontHeight,0,0,0,prtFontWeight,
								DEFAULT_PITCH|FF_DONTCARE,prtFontItalic,0,0,
								prtFontCharset);

	 /* Update ALFFPrtData Structure with printer font */
    prtData->currPrtFont = prtFont;

    /* Remote Printer Status Indicators */
    prtHostName = new TStatic(this,IDC_REMPRTHOSTNAME);
    prtHostPc = new ALFFStatic(this,IDC_REMPRTHOSTPCCONN,NULL,TColor(255,0,0));
    prtPCName = new TStatic(this,IDC_REMPRTPCNAME);
    prtPCPrinter = new ALFFStatic(this,IDC_REMPRTPCPRINTERCONN,NULL,TColor(255,0,0));
    prtPrinterName = new TStatic(this,IDC_REMPRTPRINTERNAME);

    /* Query Reply List Codes For Read Partition Query List */
    queryReplyList = NULL;

    /* Begin/End of Print Job Controls */
    beginEndOfJobStrFd = false;
    beginOfPrintJob = false;
    endOfPrintJob = false;

    /* LU1 Format Controls */
    memset (horizontalFmt,0x00,256);
    memset (verticalFmt,0x00,256);
    memset (channels1_12,0x00,12);
}

ALFFRemotePrinter::~ALFFRemotePrinter ()
{
 Destroy();
 delete pLineComm;
 delete pTelnet;
 delete p3270Buf;
 delete pNVTBuf;
 delete pLineInBuf;
 delete pLineOutBuf;
 delete pNetInBuf;
 delete pNetOutBuf;
 delete pMsgs;
 delete [] dataTypeQueue;

 /* Remote Printer Status Indicators */
 delete prtHostName;
 delete prtHostPc;
 delete prtPCName;
 delete prtPCPrinter;
 delete prtPrinterName;

 /* Printer Device Descriptors */
 delete prtData;

 /* Delete Printer Font controls */
 delete prtFont;
 delete [] prtFontName;

 /* Delete Printer if exists one */
 if (Printer)
 	  delete Printer;
 if (printerBuf)
     delete printerBuf;
     
 if (prtMenu)
    delete prtMenu;

 /* Delete Connection Data Parameters */
 delete connData;

 if (pTrcFile)
  {
	pTrcFile->LogText(IDS_ALFFSESSTRACEEND, GetApplication()->GetInstance());
	delete pTrcFile;
  }

 if (pConnLog)
  {
	pConnLog->LogText(IDS_ALFFSESSTRCLOGEND, GetApplication()->GetInstance());
	delete pConnLog;
  }

  if (queryReplyList)
   delete [] queryReplyList;

  if (statParts)
   delete [] statParts;
}

void
ALFFRemotePrinter::CmCloseWindow()
{
 Show(SW_HIDE);
}

void
ALFFRemotePrinter::SetWindowTitle()
{
 string wTitle;
 if (strlen(connData->sessTitle))
    wTitle = connData->sessTitle;
 else wTitle = connData->connName;
 if (connTraceTitle.length() > 0)
   wTitle = wTitle + connTraceTitle;
 else
  {
   wTitle.append(" - ");
   wTitle = wTitle + connStatusTitle + connSSLStatus;
  }
 SetCaption(wTitle.c_str());
}

void
ALFFRemotePrinter::SetupWindow()
{
 ALFFDialog::SetupWindow();

 SetWindowTitle();

#ifdef DEBUG32
	MessageBox("ALFFRemotePrinter:SetupWindow - Starting...","Tec3270 Remote Prt Debug",MB_OK);
#endif

 // Set Session Menu
 prtMenu = new TMenuDescr(IDM_ALFFRPRT);
 SetMenu(prtMenu->GetHandle());


 //Rem Prt Dialog Status Bar
 RECT rcClient;
 prtStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE,
                                   " ",
                                   this->Handle,
                                   IDC_ALFFREMPRTSTATBAR);

 ::EnableWindow (prtStatusBar, true);

 ::GetClientRect(this->Handle, &rcClient);
 int sslWidth = 24;
 int nWidth = (rcClient.right-sslWidth) / (PRTSTATBARPARTS-1);
 int centralAdjust = nWidth / 20;
 statParts = new int[PRTSTATBARPARTS];
 statParts[0] = nWidth-centralAdjust;
 statParts[1] = (nWidth*2)+centralAdjust;
 statParts[2] = nWidth*3;
 statParts[3] = nWidth*3+sslWidth;

 ::SendMessage(prtStatusBar,
               SB_SETPARTS,
               (WPARAM) PRTSTATBARPARTS,
               (LPARAM) statParts);

 /* Set Initial status bar printing controls */
 SetStatusBar();

 // Do Not Need an EvInitTerminal ....MUST CONFIRM IT !
 InitTerminalBuffer(NVTMODE);

 /* Set Host Server info */
 SetHostInfo();

 /* At this Time PC is Not Connected to Host */
 SetHostStatus();


 /* Set PC Info ...*/
 char msgText[128];
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
 strcpy(msgText, theApp->GetComputerName());
 strcat(msgText, "\r\nIP : ");
 strcat(msgText, theApp->GetComputerAddress());
 prtPCName->Clear();
 prtPCName->SetText(msgText);

 /* Create the Printer Device depending upon saved options */
 CreatePrinter(prtData->prtDriver, prtData->prtDevice, prtData->prtOutput);

 /* Set PC to Printer Conn Status */
 SetPrinterStatus(GetPrinterStatus());

 /* Set Printer Info .... */
 SetPrinterName();

#ifdef DEBUG_PRT
   CmTraceSession();
#endif

 // Try to connect the printer to host
 Connect();
}

void
ALFFRemotePrinter::SetHostInfo()
{
 char msgText[128];
 char tempText[STRINGMSGLEN+1];
 char port[10];

 pMsgs->LoadString(IDS_ATHOST,tempText,STRINGMSGLEN);
 strcpy(msgText, tempText);
 strcat(msgText, connData->hostName);
 strcat(msgText,"\r\n");
 pMsgs->LoadString(IDS_ATPORT,tempText,STRINGMSGLEN);
 strcat(msgText,&tempText[3]);
 itoa(connData->portNumber, port, 10);
 strcat(msgText, port);
 strcat(msgText,"\r\n");
 strcat(msgText,pTelnet->GetPrinterNetname());
 prtHostName->Clear();
 prtHostName->SetText(msgText);

}
void
ALFFRemotePrinter::SetHostStatus()
{
 if (IsConnected() || IsSSLConnected())
   prtHostPc->SetBkgdColor(RGB(0,255,0));
 else prtHostPc->SetBkgdColor(RGB(255,0,0));
}

void
ALFFRemotePrinter::SetPrinterStatus(int printerStatus)
{
 if (printerStatus == NO_DEVICE_ERROR)
   prtPCPrinter->SetBkgdColor(RGB(0,255,0));
 else prtPCPrinter->SetBkgdColor(RGB(255,0,0));
}

void
ALFFRemotePrinter::SavePrinterParms()
{
 const DEVNAMES* prtNames = Printer->GetData()->GetDevNames();
 if (prtNames)
  {
   strcpy(prtData->prtDriver, (const char*)prtNames+prtNames->wDriverOffset);
   strcpy(prtData->prtDevice, (const char*)prtNames+prtNames->wDeviceOffset);
   strcpy(prtData->prtOutput, (const char*)prtNames+prtNames->wOutputOffset);
   if (prtNames->wDefault & DN_DEFAULTPRN)
      prtData->defaultPrt = 1;
   else prtData->defaultPrt = 0;
  }
 else
  {
   strcpy(prtData->prtDriver, "");
   strcpy(prtData->prtDevice, "");
   strcpy(prtData->prtOutput, "");
   prtData->defaultPrt = 0;
  }
 /* Save Actual Printer DEVICE To INI File */
 char iniSection[21];
 strcpy(iniSection,"REMOTE PRINTER DEVICE");

 /* Get the Application IniFile Pointer*/
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
 ALFFIniFile* iniFile = theApp->GetIniFile();

 iniFile->WriteString(iniSection,"DRIVER",prtData->prtDriver);
 iniFile->WriteString(iniSection,"DEVICE",prtData->prtDevice);
 iniFile->WriteString(iniSection,"OUTPUT",prtData->prtOutput);
 iniFile->WriteInt(iniSection,"DEFAULT",prtData->defaultPrt);
}

void
ALFFRemotePrinter::SetPrinterName()
{
#define MAXPRTNAMESIZE  37
  string prtName;
  char tempChar[STRINGMSGLEN];
  string temp;
  prtName = "";
  if (Printer->GetData()->GetDevNames())
   {
    temp = prtData->prtDevice;
    if (temp.contains("\\")  ||  temp.contains("/"))
      {
        int slashPos = temp.find_last_of("\\");
        if (slashPos == NPOS)
            slashPos = temp.find_last_of("/");
        if (slashPos > MAXPRTNAMESIZE)
          {
           prtName = temp.substr(0,MAXPRTNAMESIZE).c_str();
           prtName += "...";
          }
        else prtName = temp.substr(0,slashPos).c_str();
        prtName += "\r\n";
        prtName += temp.substr(slashPos+1).c_str();
      }
    else prtName = temp.c_str();

    /* Next Line */
    prtName += "\r\n";

    if (!prtData->printToFile)
     {
      temp = prtData->prtOutput;
      if (temp.contains("\\")  ||  temp.contains("/"))
       {
        int slashPos = temp.find_last_of("\\");
        if (slashPos == NPOS)
            slashPos = temp.find_last_of("/");
        prtName += temp.substr(slashPos+1).c_str();
       }
      else prtName += temp.c_str();

      if (prtData->defaultPrt)
       {
        pMsgs->LoadString(IDS_ALFFPRTDEFAULTPRINTER, tempChar, STRINGMSGLEN);
        prtName += tempChar;
       }
     }
    else
     {
      // Printing to File ...
      pMsgs->LoadString(IDS_ALFFPRTPRINTTOFILE, tempChar, STRINGMSGLEN);
      prtName += tempChar;
      prtName += " : \r\n";
      temp    =  prtData->printerFileName;
      bool  endReplace = false;
      int   slashPos = temp.find_first_of("\\");
      while (!endReplace)
       {
        if  (slashPos != NPOS)
         {
          temp.replace(slashPos,1,"/");
          slashPos = temp.find("\\",slashPos+2);
         }
        else endReplace = true;
       }
      prtName += temp;
     }
   }
  else
   {
     pMsgs->LoadString(IDS_ALFFPRTNOTAVAIL, tempChar, STRINGMSGLEN);
     prtName = tempChar;
   }

  prtPrinterName->SetText(prtName.c_str());
}

void
ALFFRemotePrinter::SetStatusBar()
{
  char barText[STRINGMSGLEN+1];
  char temp[STRINGMSGLEN+1];

  /* Reset Status Bar from previous use */
  strcpy(barText," ");
  ::SendMessage(prtStatusBar,SB_SETTEXT,255,(LPARAM)(LPSTR)&barText[0]);

  /* Load Printed Reports Quantity Descriptor */
  pMsgs->LoadString(IDS_REMPRTTOTREPORTQTY, temp, STRINGMSGLEN);
  sprintf(barText, temp, totalReportsQuantity);
  ::SendMessage(prtStatusBar,SB_SETTEXT, 0, (LPARAM)(LPSTR)&barText[0]);

  /* Load Printed Reports Total Lines Quantity */
  pMsgs->LoadString(IDS_REMPRTTOTREPORTLINES, temp, STRINGMSGLEN);
  sprintf(barText, temp, totalReportsLines);
  ::SendMessage(prtStatusBar,SB_SETTEXT, 1, (LPARAM)(LPSTR)&barText[0]);

  /* Load Current/Last Report Lines Quantity   */
  pMsgs->LoadString(IDS_REMPRTTHISREPORTLINES, temp, STRINGMSGLEN);
  sprintf(barText, temp, thisReportLines);
  ::SendMessage(prtStatusBar,SB_SETTEXT, 2, (LPARAM)(LPSTR)&barText[0]);

  if (IsSSLConnected())
   strcpy(barText," SSL");
  else strcpy(barText," ");
  ::SendMessage(prtStatusBar, SB_SETTEXT, 3|SBT_OWNERDRAW, (LPARAM) IDB_REMPRTSSLLOCK );
}

void
ALFFRemotePrinter::EvDrawItem(uint /*ctrlId*/, DRAWITEMSTRUCT far& drawInfo)
{
 TRect rcItem = drawInfo.rcItem;

 sslLockRect = rcItem;

 TClientDC statBarDC(drawInfo.hwndItem);
 if (IsSSLConnected())
  {
   TBitmap sslLock(*GetModule(), IDB_REMPRTSSLLOCK);
   TMemoryDC memDC;
   memDC.SelectObject(sslLock);
   int bitmapX = sslLock.Width();
   int bitmapY = sslLock.Height();
   statBarDC.BitBlt(rcItem.left, rcItem.top, bitmapX,
                     bitmapY, memDC, 0, 0, SRCCOPY);
  }
 else statBarDC.FillRect(sslLockRect, TBrush(TColor::Sys3dFace));
}

void
ALFFRemotePrinter::EvMenuSelect(uint menuItemId, uint flags, HMENU /*hMenu*/)
{
 char menuHelp[STRINGMSGLEN];

 /* Check for Menu Index of drop-down submenu */
 if ((menuItemId < IDS_ALFFREMPRT) && (flags & MF_POPUP) && (flags != 65535) )
   menuItemId += IDS_ALFFREMPRT;

 int length = pMsgs->LoadString(menuItemId,menuHelp,STRINGMSGLEN);
 if (length)
   ::SendMessage(prtStatusBar, SB_SETTEXT, 255,(LPARAM)(LPSTR)&menuHelp[0]);
 else SetStatusBar();
}

bool
ALFFRemotePrinter::EvSetCursor(HWND hWndCursor, uint /*hitTest*/, uint mouseMsg)
{
 TPoint mousePos;
 ::GetCursorPos(&mousePos);
 ::ScreenToClient(prtStatusBar, &mousePos);
 if ((mouseMsg == WM_LBUTTONDOWN) && (hWndCursor == prtStatusBar))
  {
   if (IsSSLConnected() && sslLockRect.Contains(mousePos))
    {
     CmShowCertificate();
     return true;
    }
   else return false;
  }
 else return false;
}

void
ALFFRemotePrinter::SessionMessage(const int errorId)
{
 WPARAM wParam = MAKEWPARAM(errorId,0);
 myParent->SendMessage(MSG_REMPRT_NOTIFY, wParam, 0);
}

void
ALFFRemotePrinter::SessionMessage(const char* errorMsg)
{
 LPARAM lParam = (LPARAM) errorMsg;
 myParent->SendMessage(MSG_REMPRT_NOTIFY, 0, lParam);
}

void
ALFFRemotePrinter::TimeMessage()
{
 /* Register Date and Time at what connection was ended */
 char text[STRINGMSGLEN];
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
 theApp->GetTimeStamp(text);

 SessionMessage(text);
}

void
ALFFRemotePrinter::LineError(int cError)
{
	char stringError[STRINGMSGLEN];
	char msgError[STRINGMSGLEN*2];

	if (cError == INVALID_CONNECTION_STATE)
		{ pMsgs->Message(IDS_ALFFINVSESSSTATE, IDS_ALFFSESSTITLE); }
	else
		{
		 pMsgs->LoadString(IDS_ALFFCOMMCLUSTERERR,stringError,STRINGMSGLEN);
		 sprintf(msgError,stringError,cError);
		 strncpy(stringError,
					  ALFFLineError(cError).ReportError(),
					  LINE_STRING_ERROR_LENGTH);
		 strcat(msgError,"\n");
		 strcat(msgError,stringError);
		 pMsgs->StrMessage(msgError,0,IDS_ALFFSESSTITLE);
		}
	  /* Log Error on Terminal Session Screen */
	  SessionMessage(stringError);

	  /* Register the error message and Disconnect Session */
	  SessionMessage(IDS_LINECLOSEDBYERROR);
	  Disconnect();
}

LRESULT
ALFFRemotePrinter::DoClusterNotification(WPARAM, LPARAM lParam)
{
	int cError;
	cError = pLineComm->DoClusterNotification(lParam);

	if (cError)
	 { LineError(cError); }
	 else
	  {
		//  This call of LineConnect need no parameters because
		//   previous call was passed them.
		//  At this point LineConnect MUST be in waitingforhostaddress
		//   state.
		cError = pLineComm->LineConnect("  ","  ");
		if (cError)
        { LineError(cError); }
	  }
	return 1L;
}

void
ALFFRemotePrinter::ActivateConnection()
{
   char sessMsg[STRINGMSGLEN];
   int  statusId;

   // The session was disconnect by host, so do the session cleanup
   if (disconnectedByHost)
    {
     DisconnectedByHost();
     return;
    }

	// Update Child Caption To Reflect Connection Status
   if (IsSSLConnecting())
    {
     SetSSLConnectedState();
     statusId = IDS_LINESTATSECURECONNECTED;
    }
   else if (IsConnecting())
    {
     SetConnectedState();
     statusId =  IDS_LINESTATCONNECTED;
    }
   else
    {
      pMsgs->StrMessage("ActivateConnection",IDS_ALFFINVSESSSTATE, IDS_ALFFSESSTITLE);
      CloseTerminal();
    }

	pMsgs->LoadString(statusId, sessMsg, STRINGMSGLEN-1);

   // Verify message length for not exceeding sessMsg LENGTH !!
   if (strlen(connData->sessTitle))
       strcat(sessMsg, connData->sessTitle);
   else strcat(sessMsg, connData->connName);


	/* Log Connection status on Screen and Log File if it is active*/
	SessionMessage(sessMsg);

	/* Register Date and Time at what connection begins */
	TimeMessage();

	// Update Child Caption To Reflect Connection Status
   strcpy(sessMsg," - ");
   connStatusTitle = sessMsg;

	/* Update Connection Window caption and icon */
	SetWindowTitle();

   // Must show the printer window.
   Show(SW_HIDE);

   /* Further will we receive telnet commands from telnet server
    * through an Line_Read notification on DoLineNotification
    * method that is in following
    */
}

LRESULT
ALFFRemotePrinter::DoLineNotification(WPARAM, LPARAM lParam)
{
	int nEvent = LOWORD(lParam);
	int lError = HIWORD(lParam);
	char stringError[LINE_STRING_ERROR_LENGTH];
	//char text[STRINGMSGLEN];

	if (!lError)
	 nEvent = pLineComm->DoLineNotification(nEvent);

	//--------------------------TRACE---------------------------------
	#ifdef Tec3270Trace
	char message[50];
	char evento [10];
	switch (nEvent)
	 {
	  case LINE_CONNECT  : strcpy(evento,"LINE_CONNECT");
								  break;
	  case LINE_READ     : strcpy(evento,"LINE_READ");
								  break;
	  case LINE_WRITE    : strcpy(evento,"LINE_WRITE");
								  break;
	  case LINE_CLOSE    : strcpy(evento,"LINE_CLOSE  ");
								  break;
	  case LINE_ACCEPT   : strcpy(evento,"LINE_ACCEPT ");
								  break;
	  case LINE_OOB      : strcpy(evento,"LINE_OOB");
								  break;
	  default            : strcpy(evento,"UNKNOW ");
								  break;
	 }
	sprintf(message,"Line Notification Received : Event %s",evento);
	MessageBox(message,
				  "Tec3270 Trace Info",
				  MB_OK | MB_ICONEXCLAMATION);
	#endif
	//----------------------------------------------------------------

	/* Process line event */
	if (nEvent == LINE_WRITE)
	 {
     ///////////////////////////  Event LINE_WRITE /////////////////////////////
	  if ( (connectPendingForReadWrite)   // Connect  	Pending Read/Write  (SSL)
        ||(sendDataPendingForReadWrite)  // SendData 	Pending Read/Write  (SSL)
        ||(receiveDataPendingForReadWrite) // ReceiveData Pending Read/Write(SSL)
        ||(!dataSent) )
	  {
		if(lError)
		 {
			stringError[0]=NULL;
			strncpy(stringError,
					  ALFFLineError(lError).ReportError(),
					  LINE_STRING_ERROR_LENGTH);
			pMsgs->StrMessage(stringError,0,IDS_ALFFSESSTITLE);

			/* Log Error on Screen and Log File if is active*/
			SessionMessage(stringError);
		 }
      else if ( IsConnecting() )
         // It would never occurs, but if it comes, advise user as an error
         pMsgs->StrMessage("LINE_WRITE/IsConnecting",IDS_ALFFINVSESSSTATE,IDS_ALFFSESSTITLE);

		else if (IsSSLConnecting())    //(nEvent == LINE_WRITE)
       {
        if (connectPendingForReadWrite)
         {
          connectPendingForReadWrite = false;
          // Re-Initiate SSL Negotiation
          int rc = ConnectSecurity();
          if (rc == SSL_CONNECTION_OK)
			    ActivateConnection();
         }
       }
      else if (IsSSLConnected() || IsConnected())
       {
        if (receiveDataPendingForReadWrite)
         {
			 // receiveDataPendingForReading = false;  (will be done on following method)
          ReceiveDataEnqueued();
         }

        else if (sendDataPendingForReadWrite)
         {
          sendDataPendingForReadWrite = false;
           // Redo writing of data !!
			 SendData();
         }
       }
		else if (IsSSLDisconnecting())    //(nEvent == LINE_WRITE)
       {
        if (disconnectPendingForReadWrite)
         // Re-Initiate SSL Disconnecting ....
         Disconnect();
        //else ignore LINE_WRITE event
       }

      else if (IsIdle())
       {
			// Ignore event:  Nothing to do !!
       }
      else pMsgs->StrMessage("Unknow", IDS_ALFFINVSESSSTATE,IDS_ALFFSESSTITLE);
	  }
     /////////////////////////// End Event LINE_WRITE //////////////////////////
	 }
	else if(nEvent == LINE_READ)
	 {
     /////////////////////////// Event LINE_READ ///////////////////////////////
	  if(lError)
		 {
			stringError[0]=NULL;
			strncpy(stringError,
					  ALFFLineError(lError).ReportError(),
					  LINE_STRING_ERROR_LENGTH);
			pMsgs->StrMessage(stringError,0,IDS_ALFFSESSTITLE);

			/* Log Error on Log File if it is active*/
			SessionMessage(stringError);

		 }
      else if ( IsConnecting() )
       {
#ifdef ALFFRemotePrtDebug
          ReceiveDataEnqueued();
#else
         // It would never occurs, but if it comes, advise user as an error
         pMsgs->StrMessage("LINE_READ/IsConnecting",IDS_ALFFINVSESSSTATE,IDS_ALFFSESSTITLE);
#endif         
       }
		else if (IsSSLConnecting())    //(nEvent == LINE_READ)
       {
        if (connectPendingForReadWrite)
         {
          connectPendingForReadWrite = false;
          // Re-Initiate SSL Negotiation
          int rc = ConnectSecurity();
          if (rc == SSL_CONNECTION_OK)
			    ActivateConnection();
         }
       }
      else if ( IsConnected() || IsSSLConnected() )
		 {
        if (sendDataPendingForReadWrite)
         {
          sendDataPendingForReadWrite = false;
          // Redo writing of data !!
          SendData();
         }
        else
          // At this state we must have sendData or Receive Data being
          //  enqueued waiting for LINE_READ, so if it is not sendDataPendingForReadWrite
          //  it must be receiveDataPendingForReadWrite
          ReceiveDataEnqueued();
		 }
		else if (IsSSLDisconnecting())    //(nEvent == LINE_READ)
       {
        if (disconnectPendingForReadWrite)
         {
          disconnectPendingForReadWrite = false;
          // Re-Initiate SSL Disconnecting ....
          Disconnect();
         }
       }

      else if (IsIdle())
       {
			// Ignore event:  Nothing to do !!
       }

      else pMsgs->StrMessage("Unknow", IDS_ALFFINVSESSSTATE,IDS_ALFFSESSTITLE);

      ///////////////////////////  End Event LINE_READ /////////////////////////
	  }

	else if(nEvent == LINE_OOBDATA)
	 {
      //////////////////// Event LINE_OOBDATA (Read) ///////////////////////////

		/////////////////////////////////////////////////////////////////////////
		//   VERIFICAR:    DEVE PREVER O SSL ?????????????
		/////////////////////////////////////////////////////////////////////////
		if(lError)
		 {
			stringError[0]=NULL;
			strncpy(stringError,
					  ALFFLineError(lError).ReportError(),
					  LINE_STRING_ERROR_LENGTH);
			pMsgs->StrMessage(stringError,0,IDS_ALFFSESSTITLE);

			/* Log Error on Log File if it is active*/
			SessionMessage(stringError);
		 }
		else
		 {
        ReceiveDataEnqueued(URGENT);
		 }
      //////////////////// End of Event LINE_OOBDATA (Read) ////////////////////
    }
	else if(nEvent == LINE_CONNECT && IsConnecting() )
	 {
      //////////////////// Event LINE_CONNECT //////////////////////////////////
		if(lError)
		  {
			strncpy(stringError,
					  ALFFLineError(lError).ReportError(),
					  LINE_STRING_ERROR_LENGTH);
			pMsgs->StrMessage(stringError,IDS_ALFFLINECONNERR,
													IDS_ALFFSESSTITLE);

			/* Log Error on Log File if it is active*/
			SessionMessage(stringError);

			/* Inform Date and Time when connection error ocurred
				and reset all session status to Idle  */
			SessionMessage(IDS_LINECLOSEDBYERROR);
			Disconnect();
		  }
		else if (IsConnecting())
		  {
         // Check for SSL connections
         if (connData->securityMethod != ALFFSSLComm::ALFFNONE)
          {
           // Initiate SSL-TLS  Negotiation
           SetSSLConnectingState();

           int rc = ConnectSecurity();
           if (rc == SSL_CONNECTION_OK)
     				ActivateConnection();
          }
         else ActivateConnection();
		  }
      else // Any other state is invalid
        {
         char stateNumber[10];
         sprintf (stateNumber, "< %i >", nLineState);
         pMsgs->StrMessage(stateNumber, IDS_ALFFINVSESSSTATE,IDS_ALFFSESSTITLE);
        }
      //////////////////// End of Event LINE_CONNECT ///////////////////////////
	 }  // nEvent == LINE_CONNECT

	else if (nEvent == LINE_CLOSE)
	 {
      //////////////////// Event LINE_CLOSE ////////////////////////////////////
		if(lError)
		 {
		  stringError[0]=NULL;
		  strncpy(stringError,
					 ALFFLineError(lError).ReportError(),
					 LINE_STRING_ERROR_LENGTH);
		  pMsgs->StrMessage(stringError,0,IDS_ALFFSESSTITLE);

		  /* Log Error on Log File if it is active*/
		  SessionMessage(stringError);

 		  SessionMessage(IDS_LINECLOSEDBYERROR);

		  CloseTerminal();

		  /* Register Date and Time at what connection was ended */
		  TimeMessage();

	     /* If connection remains active set initial state */
  	     SetIdleState();
		 }
      else if ( IsConnecting() || IsConnected() || IsSSLConnected() )
       {
         DisconnectedByHost();
       }
      else if ( IsSSLConnecting() || IsSSLDisconnecting() )
       {
         // register host disconnection for further processing
         //  on SSL routines.
         disconnectedByHost = true;
       }
       // else ignore this event as we are in SSL Disconnecting process.
      //////////////////// End of Event LINE_CLOSE /////////////////////////////
	  }

   //////////////////// INTERNAL ERROR ////////////////////////////////////////
	else
    {
     char eventErr[128];
     sprintf (eventErr,"[ %i ]",nEvent);
     pMsgs->StrMessage(eventErr,IDS_SESSNETEVENTUNKNOW,IDS_ALFFSESSTITLE);
    }

	return 1L;
}

void
ALFFRemotePrinter::ReceiveDataEnqueued(bool /*urgent*/)
{
 // This method enqueues all  LINE_READ / LINE_WRITE events
 //  that must be directed to ReceiveData method.
 //
 // Note that SSL Connections may want read or write in read or
 // write data operations, because SSL protocol may want to renegotiate
 // encryption keys on any operation.
 //
 // All variables are global for having its scope available for each
 // operation that may be called from.
 //
 recvQueue++;
 if (!receiving)
  {
   receiving=true;
   while (recvQueue)
    {
     receiveDataPendingForReadWrite=false;
     ReceiveData();
	  recvQueue-=1;
    }
   receiving=false;
  }
}

void
ALFFRemotePrinter::DisconnectedByHost()
{
  // The session was disconnect by host, so do the session cleanup

  // Clear Flag for SSL Routines, because we are trueing disconnecting
  disconnectedByHost = false;

  SessionMessage(IDS_LINECLOSEDBYHOST);
  CloseTerminal();

  /* Register Date and Time at what connection was ended */
  TimeMessage();

  /* If connection remains active set initial state */
  SetIdleState();
}

bool
ALFFRemotePrinter::UpdateSecurityOptions(bool verifyCert, bool verifyRevoked)
{
 if (IsSSLConnected() || IsSSLConnecting())
  {
   pLineComm->UpdateCertVerifyOptions(verifyCert ,verifyRevoked);
   return true;
  }
 else return false;
}

int
ALFFRemotePrinter::ConnectSecurity()
{
   // The session was disconnect by host, so do the session cleanup
   if (disconnectedByHost)
    {
     DisconnectedByHost();
     return SSL_CONNECTION_ERROR;
    }

	/* Access the Application Scope */
	Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(), Tec3270App);

   // Initiate Application Security Lib
   if (theApp->GetSecurityObj())
    {
      if (!theApp->GetSecurityObj()->IsSecurityOn())
        	theApp->SetSecurityOn();
    }
   else throw ALFFSecurityException();

   char iniSection[24] = "SECURITY OPTIONS";

   /* Get the Application IniFile Pointer  */
   ALFFIniFile* iniFile = theApp->GetIniFile();

   /*******************************************************
   * Getting Secure Connection Options previous defined   *
   *******************************************************/
   bool verify_server_cert = false;
   bool verify_revoked = false;

   connectPendingForReadWrite = false;

   // Start (or Re-Start) the Secured connection
   int rc = pLineComm->SSLLineConnect(connData->securityMethod,
                                      verify_server_cert,
                                      verify_revoked);
   if ((rc == SSL_WANT_READ) || (rc == SSL_WANT_WRITE))
      connectPendingForReadWrite = true;
   else if (rc == SSL_CONNECTION_ERROR)
    {
      bool hasError = false;
      string sslErrMsg = pLineComm->GetSSLErrors(hasError);
      int msgId;
      if (hasError)
        msgId = IDS_ALFFSSLERROR;
      else if (disconnectedByHost)
        msgId = IDS_LINECLOSEDBYHOST;
      else  msgId = IDS_LINECLOSEDBYTIMEOUT;

      pMsgs->StrMessage(connData->hostName,msgId,IDS_ALFFSESSTITLE);

      if (hasError)
       {
         /* Log Error on Screen and Log File if is active*/
         SessionMessage(sslErrMsg.c_str());
         SessionMessage(IDS_LINECLOSEDBYERROR);
       }
      else if (!disconnectedByHost)
         SessionMessage(msgId);

      /* Inform Date and Time when connection error ocurred
         and reset all session status to Idle  */
      Disconnect();
    }
  return rc;
}

LRESULT
ALFFRemotePrinter::EvStartTLS(WPARAM, LPARAM)
{
 char iniSection[24] = "SECURITY OPTIONS";

 /* Get the Application IniFile Pointer  */
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
 ALFFIniFile* iniFile = theApp->GetIniFile();

 /*******************************************************
 * Getting TLS Connection Method previous defined      *
 *******************************************************/
 connData->securityMethod =
         iniFile->GetInt(iniSection,"TLSMETHOD",ALFFSSLComm::ALFFSSLV3);

 // Initiate SSL-TLS  Negotiation
 SetSSLConnectingState();

 int rc = ConnectSecurity();
 if (rc == SSL_CONNECTION_OK)
		ActivateConnection();

 return 1L;
}

LRESULT
ALFFRemotePrinter::DoNetInputLU1Process(WPARAM dataType, LPARAM messageCtrl)
// LU1 Printer: "messageCtrl" is the TN3270E message header, except dataType.
//                   Byte     Ctrl
//                    0        requestFlag
//                    1        responseFlag
//                   2-3       sequence number
// These values have meaning when  RESPONSE function was active, otherwise is zero.
{
 /*
  * This method is "posted" by the "MessageRecv" method of
  *  ALFFTelnet class that knows from what kind of LU
  *  (LU1 or LU3) is the printing data format.
  * It is the method responsable for processing LU1 printing data.
  */
 int  netLength, retCode, index;
 char err3270[12] = {"X PROGxxx "};
 int  errorId, titleId;
 bool nvtMode = false;
 int  printerStatus = DEVICE_READY;
 bool needResponse = false;
 int senseCode;

 netInputQueue++;
 dataTypeQueue[netInputQueue-1] = dataType; 
 if (!netInputProcessing)
  {
	netInputProcessing = true;
   index = 0;
	while (netInputQueue)
	 {
	  /*
		* Is There any data to terminal screen ?
		*/
     WPARAM dtaType = dataTypeQueue[index++];
     printerStatus = DEVICE_READY;

	  netLength = pNetInBuf->ring_full_consecutive();
	  if ( /*(pTelnet->EorReceived()) &&*/ (netLength) )
		{
       /* Checking for TN3270E switching from NVTMode to 3270Mode and vice-versa */
       if (dtaType & 0x80)
        {
          dtaType &= 0x7F;
          if (dtaType == T3270_DATA)
           {
            /*
             * Do not need to Clear 3270 Buffer, because on LU1 printers it is
             * not necessary, as all received data is stored on PrinterBuffer
             * that is always flushed before processing any message !!
             */
            //p3270Buf->ClearBuf();
           }
          else if (dtaType == NVT_DATA)
           {
             nvtMode = true;
            pNVTBuf->ClearBuf();
           }
          else pMsgs->StrMessage("ALFFRemotePrinter::DoNetInputProcess",IDS_UNEXPECTED3270ERROR,IDS_TITTELNETERR);
        }

		 /*
        * Process printing data directly from net input buffer
        *  because there is no buffer for formatting ....
		  */
		 if (pTelnet->Is3270Mode() && !nvtMode)
		  {
			retCode = LU1DataFromNetwork(pNetInBuf);
			titleId = IDS_TIT3270PRTERR;
		  }
		 else
		  {
         /* If it is an NVT Message, store it on NVT Buffer */
			retCode = pNVTBuf->DataFromNetwork(pNetInBuf);
			titleId = IDS_TITNVTPRTERR;
 		  }

		 if (retCode < 0)  // Error when receiving data or Read Command or QUERY REPLY
		  {
			switch (retCode)
			 {
           /* Invalid SCS_SVF State - Internal Error */
           case INVALIDSVFDATASTATE:
             {
              errorId = IDS_INVALIDSVFDATASTATE;
              strcpy(err3270,PROG401);
              break;
             }

           /* Invalid SCS_SVF parameter - Error */
           case INVALIDSVFSEQUENCE:
             {
              errorId = IDS_INVALIDSVFSEQUENCE;
              strcpy(err3270,PROG401);
              break;
             }

           /* Invalid SCS_SPD parameter - Error */
           case INVALIDSPDSEQUENCE:
             {
              errorId = IDS_INVALIDSPDSEQUENCE;
              strcpy(err3270,PROG401);
              break;
             }

           /* Invalid SCS_SLD parameter - Error */
           case INVALIDSLDSEQUENCE:
             {
              errorId = IDS_INVALIDSLDSEQUENCE;
              strcpy(err3270,PROG401);
              break;
             }

           /* Invalid SCS_SHF parameter - Error */
           case INVALIDSHFSEQUENCE:
             {
              errorId = IDS_INVALIDSHFSEQUENCE;
              strcpy(err3270,PROG401);
              break;
             }

           /* Invalid SCS_SHF State - Internal Error */
           case INVALIDSHFDATASTATE:
             {
              errorId = IDS_INVALIDSHFDATASTATE;
              strcpy(err3270,PROG401);
              break;
             }

           /* Invalid SCS Data State - Internal Error */
           case INVALIDSCSDATASTATE:
             {
              errorId = IDS_INVALIDSCSDATASTATE;
              strcpy(err3270,PROG401);
              break;
             }

			  /* (INVALIDCOMMAND) Invalid 3270 Or NVT COMMAND Code */
			  /* Error Valid Exclusively For 3270 Terminal State */
			  case INVALIDCOMMAND:
				 {
				  /* Must Reject With Sense X'1003' */
				  errorId = IDS_INV3270COMMCODE;
				  strcpy(err3270,PROG401);
				  break;
				 }

			  /* (INVALIDREADPARTYPE) Invalid Read Partition Type Code */
			  case INVALIDREADPARTYPE:
				 {
				  /* Must Reject With Sense X'1003' */
				  errorId = IDS_INVREADPARTYPE;
				  strcpy(err3270,PROG401);
				  break;
				 }

			  /* (INVALIDSTRFIELD) Invalid Structured Field (Format) */
			  case INVALIDSTRFIELD:
				 {
				  /* Must Reject With Sense X'1003' */
				  errorId = IDS_UNSUPPSTRFIELD;
				  strcpy(err3270,PROG401);
				  break;
				 }

			  /* (UNSUPPORTEDSTRFIELD) Unsupported Structured Field (Code) */
			  case UNSUPPORTEDSTRFIELD:
				 {
				  /* Must Reject With Sense X'1003' */
				  errorId = IDS_UNSUPPSTRFIELD;
				  strcpy(err3270,PROG401);
				  break;
				 }

			  /* (DATAFOLLOWEAUREAD) Invalid Data Follows READ PARTITION */
			  case DATAFOLLOWEAUREAD:
				 {
				  /* Must Reject With Sense X'1003' */
				  errorId = IDS_DATAFOLLOWREAD;
				  strcpy(err3270,PROG403);
				  break;
				 }
			  /* (QUERY REPLY ) Structured Fields */
			  case QUERYREPLY:
			  case QUERYREPLYLIST:
				 {
				  /* Must Reject With Sense X'1003' */
				  /* Valid Only For 3270 Mode (LU1) */
				  if (pTelnet->Is3270Mode() && !nvtMode)
					  retCode = DataToNetwork(pNetOutBuf,LU1,queryReplyList);
				  else retCode = IDS_DATANOTSENT;
				  if ( retCode == DATASENT)
					{
					 if (pTelnet->MessageSend(pLineOutBuf,pNetOutBuf))
					  {
						SendData();
						errorId = 0;
					  }
					 else errorId = IDS_DATANOTSENT ;
					}
				  else errorId = retCode;
				  break;
				 }

			  /* Something Wrong: Unexpected Return Code */
			  default:
				 {
				  if (pTelnet->Is3270Mode() && !nvtMode)
					  errorId = IDS_UNEXPECTED3270ERROR;
				  else errorId = IDS_UNEXPECTEDNVTERROR;
				  strcpy(err3270,PROG999);
				  break;
				 }

			 } // end switch

			/* Check for any error on command processing */
			if (errorId)
			 {
			  /* Shows Error Message Dialog With Error Message Selected */
			  pNetOutBuf->ring_reset();
			  pMsgs->Message(errorId,titleId);

			  /* if Log connection option active */
			  if (connData->connLog)
				{
				 pConnLog->LogText(errorId, GetApplication()->GetInstance(), &err3270[1]);
				 if (pTelnet->Is3270Mode() && !nvtMode)
				  {
					pConnLog->LogData('R',
										  p3270Buf->GetLastStream3270(),
										  p3270Buf->GetLastStreamSize(),
										  false,
										  true,
										  p3270Buf->GetTabEbcAsc());
				  }
				 else
				  {
					pConnLog->LogData('R',
										  pNVTBuf->GetLastStreamNVT(),
										  pNVTBuf->GetLastStreamSize(),
										  false,
										  false,
										  NULL);
				  }
				}

           // Set printer status on error for sending back to the server
           printerStatus = DEVICE_NOT_READY;
           senseCode = GetLU1SenseCode(retCode);
			 }
         else
          {
           printerStatus = DEVICE_READY;
           senseCode = NO_DEVICE_ERROR;
          }
		  }
		 else // (retCode >= 0)
		  {
         /* Verify if printer job was began and if not do begin it */
         if ((!beginEndOfJobStrFd) && (!beginOfPrintJob))
				DoPrinterBeginEndOfJob(0,0);

         /* Print out the data that we just received */
         bool printerError = false;

         if (!retCode)  // & STARTPRINTING) // wcc bit 4 was on
          {
           if (!nvtMode)
  			    printerError = PrintBuffer(LU1);
           else
  			    printerError = PrintBuffer(NVT);
          }

         if (!printerError)
          {
            printerStatus = DEVICE_READY;
            senseCode     = NO_DEVICE_ERROR;
          }
         else
          {
           // Set printer status for sending back to the server
           printerStatus = DEVICE_NOT_READY;
           senseCode = GetPrinterStatus();
           // If printer is already ok, do not send error notification
           if (senseCode == NO_DEVICE_ERROR)
             printerStatus = DEVICE_READY;
          }

		  } // (if retCode ......)

       // Set Actual Printer Status on printer window
       SetPrinterStatus(GetPrinterStatus());

       // If session is TN3270E and RESPONSE function is active we must check
       //  for needing of an response.
       if (pTelnet->Is3270EMode())
        {
         needResponse = pTelnet->SetNeededResponse(pNetOutBuf, messageCtrl,
                                              printerStatus, senseCode);
        }
       // If this an printer at TN3270 Mode we must sent back
       //  the printer status message for receiving more data
       else if (pTelnet->Is3270Mode())
        {
         needResponse = BuildTN3270PrtStatus(pNetOutBuf, printerStatus, retCode);
         if (!needResponse)
            pMsgs->Message(IDS_DATANOTSENT,titleId);
        }
       //else this is an NVT printer so, nothing todo ...

      }  // end if ( pTelnet->....)
     else if (pTelnet->Is3270EMode())
         needResponse = pTelnet->SetNeededResponse(pNetOutBuf, messageCtrl,
                                                   DEVICE_READY,
                                                   NO_DEVICE_ERROR);
     // Sending back the response message if it is needed
     if (needResponse)
      {
       //  true == no TN3270E Header: needed hdr was set before
       //                             on SetNeededResponse method
       if (pTelnet->MessageSend(pLineOutBuf,pNetOutBuf, true ))
           SendData();
       else  pMsgs->Message(IDS_DATANOTSENT,titleId);
      }

	  netInputQueue--;

	 } // end while (....)

	netInputProcessing = false;

  }  // end if (!netInput...)

 pTelnet->ResetEor();
 return 1L;
}

void
ALFFRemotePrinter::ResetPrinterFormats(const int fmt)
{
  switch (fmt)
   {
     case  HORZFMT:
                    connData->printerCharPerLine = DEFAULTMPP;
                    prtData->leftMargin = DEFAULTLEFTMARGIN;
                    prtData->rightMargin = connData->printerCharPerLine;
                    memset(horizontalFmt,0x00,256);
                    break;
     case  VERTFMT:
                    connData->printerLinePerPage = DEFAULTMPL;
                    prtData->topMargin = DEFAULTTOPMARGIN;
                    prtData->bottomMargin = connData->printerLinePerPage;
                    memset(verticalFmt,0x00,256);
                    memset(channels1_12,0x00,256);
                    break;
     case  BOTHFMT:
                    ResetPrinterFormats(HORZFMT);
                    ResetPrinterFormats(VERTFMT);
                    break;

          default : break;
   }
}

LRESULT
ALFFRemotePrinter::DoPrinterBeginEndOfJob(WPARAM printEOJ, LPARAM endOfJob)  // LU1,LU3 Printer End Of Job
{
 // LU1 or LU3 Printer End Of Job: (Called from ALFFTelnet
 //                                 via MSG_NET_END_OF_PRINTING_NOTIFY message
 //                                 or, from LU1DataFromNetwork method placed
 //                                 at the end of this class code.

 /*
  *  When Begin or End Of File Str Fields are used with
  *  TN3270E PRINT-EOJ command or with Terminate Time, they
  *  take precedence over these (PRINT-EOJ or Terminate Time)
  *  in determining when a print job begins or ends.
  */

 if (printEOJ && beginEndOfJobStrFd)
   return 1L;

 if (endOfJob)
  {
   // Do the printer end_of_Job only if it was began !
   if (beginOfPrintJob)
    {
     	beginOfPrintJob = false;
     	endOfPrintJob = true;
     	totalReportsQuantity += 1;
     	totalReportsLines += thisReportLines;

      if (!connData->printerInheritParm)
       {
        /* PrtData Formats */
        ResetPrinterFormats(BOTHFMT);

        // Reset Printing Parms to its session defined values
        Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
        ALFFIniFile* iniFile = theApp->GetIniFile();
        /* -----------  Remote Printer Session Config Info -------------------  */
  		  connData->printerCharPerInch = iniFile->GetInt(connData->connName,"PRINTERCHARPERINCH",10);
	 	  connData->printerLinePerInch =  iniFile->GetInt(connData->connName,"PRINTERLINEPERINCH",6);
	 	  connData->printerCharPerLine = iniFile->GetInt(connData->connName,"PRINTERCHARPERLINE",132);
	 	  connData->printerLinePerPage =  iniFile->GetInt(connData->connName,"PRINTERLINEPERPAGE",66);
       }
    }
  //else (!beginOfPrintJob)
      // Cannot terminate what hasn't began
  }
 else //(!endOfJob == beginOfJob)
  {
    // Begin the job only if it wasn't began
     if (!beginOfPrintJob)
      {
       beginOfPrintJob = true;
       endOfPrintJob = false;
       thisReportLines = 0;
      }
  }

 // Update Remote Printer Status Bar
 SetStatusBar();

 return 1L;
}


LRESULT
ALFFRemotePrinter::DoNetInputProcess(WPARAM dataType, LPARAM messageCtrl)
// LU3 Printer: "messageCtrl" is the TN3270E message header, except dataType.
//                   Byte     Ctrl
//                    0        requestFlag
//                    1        responseFlag
//                   2-3       sequence number
// These values have meaning when  RESPONSE function was active, otherwise is zero.
{
 /*
  * This method is "posted" by the "MessageRecv" method of
  *  ALFFTelnet class that knows from what kind of LU
  *  (LU1 or LU3) is the printing data format.
  * It is the method responsable for processing    LU2 / LU3
  *  data stream formatted buffer.
  */
 int  netLength, retCode, index;
 char err3270[12] = {"X PROGxxx "};
 int  errorId, titleId;
 bool nvtMode = false;
 int  printerStatus = DEVICE_READY;
 bool needResponse = false;
 int  senseCode;

 netInputQueue++;
 dataTypeQueue[netInputQueue-1] = dataType;

 if (!netInputProcessing)
  {
	netInputProcessing = true;
   index = 0;
	while (netInputQueue)
	 {
	  /*
		* Is There any data to terminal screen ?
		*/
     WPARAM dtaType = dataTypeQueue[index++];
     printerStatus = DEVICE_READY;

	  netLength = pNetInBuf->ring_full_consecutive();
	  if (netLength)
		{

       /* Checking for TN3270E switching from NVTMode to 3270Mode and vice-versa */
       if (dataType & 0x80)  // Means TELNET Mode Switched
        {
          dataType &= 0x7F;
          if (dataType == T3270_DATA)
           {
             p3270Buf->ClearBuf();
           }
          else if (dataType == NVT_DATA)
           {
             pNVTBuf->ClearBuf();
            nvtMode = true;
           }
          else pMsgs->StrMessage("ALFFRemotePrinter::DoNetInputProcess",IDS_UNEXPECTED3270ERROR,IDS_TITTELNETERR);
        }

   	 /* Update 3270Printer or NVT Buffer Cursor Position from Screen cursor
		  * position and do receiving operation
		  */
		 if (pTelnet->Is3270Mode() && !nvtMode)
		  {
			retCode = p3270Buf->DataFromNetwork(pNetInBuf);
			titleId = IDS_TIT3270PRTERR;
		  }
		 else
		  {
			retCode = pNVTBuf->DataFromNetwork(pNetInBuf);
			titleId = IDS_TITNVTPRTERR;
		  }

		 if (retCode < 0)  // Error when receiving data or Read Command or QUERY REPLY
		  {
			switch (retCode)
			 {
			  /* (INVALIDCOMMAND) Invalid 3270 Or NVT COMMAND Code */
			  /* Error Valid Exclusively For 3270 Terminal State */
			  case INVALIDCOMMAND:
				 {
				  /* Must Reject With Sense X'1003' */
				  errorId = IDS_INV3270COMMCODE;
				  strcpy(err3270,PROG401);
				  break;
				 }

			  /* (INVALIDOUT3270CMND) Invalid OutBound 3270DS COMMAND Code */
			  /* Error Valid Exclusively For 3270 Terminal State */
			  case INVALIDOUT3270CMND:
				 {
				  /* Must Reject With Sense X'1003' */
				  errorId = IDS_INVOUT3270DSCOMMCODE;
				  strcpy(err3270,PROG401);
				  break;
				 }

			  /* (INVALIDREADPARTYPE) Invalid Read Partition Type Code */
			  /* Error Valid Exclusively For 3270 Terminal State */
			  case INVALIDREADPARTYPE:
				 {
				  /* Must Reject With Sense X'1003' */
				  errorId = IDS_INVREADPARTYPE;
				  strcpy(err3270,PROG401);
				  break;
				 }

			  /* (INVALIDRPLYMODE) Invalid Reply Mode Code */
			  /* Error Valid For NVT or 3270 Terminal State */
			  case INVALIDREPLYMODE:
				 {
				  /* Must Reject With Sense X'1003' */
				  errorId = IDS_INVALIDREPLYMODE;
				  strcpy(err3270,PROG401);
				  break;
				 }

			  /* (UNSUPPORTEDSTRFIELD) Invalid Read Partition Type Code */
			  /* Error Valid Exclusively For 3270 Terminal State */
			  case UNSUPPORTEDSTRFIELD:
				 {
				  /* Must Reject With Sense X'1003' */
				  errorId = IDS_UNSUPPSTRFIELD;
				  strcpy(err3270,PROG401);
				  break;
				 }

			  /* (DATAFOLLOWEAUREAD) Invalid Data Follows READ or EAU COMMAND */
			  /* Error Valid Exclusively For 3270 Terminal State */
			  case DATAFOLLOWEAUREAD:
				 {
				  /* Must Reject With Sense X'1003' */
				  errorId = IDS_DATAFOLLOWREAD;
				  strcpy(err3270,PROG403);
				  break;
				 }

			  /* (INVALIDORDER) Invalid 3270 or NVT ORDER Code */
			  /* Error Valid For NVT or 3270 Terminal State */
			  case   INVALIDORDER:
				 {
				  /* Must Reject With Sense X'1003' */
				  if (pTelnet->Is3270Mode() && !nvtMode)
					 errorId = IDS_INV3270ORDERCODE;
				  else errorId = IDS_INVNVTORDERCODE;
				  strcpy(err3270,PROG404);
				  break;
				 }

			  /* (INVALIDBUFADDR) Invalid Buffer Address */
			  /* Error Valid Exclusively For 3270 Terminal State */
			  case INVALIDBUFADDR:
				 {
				  /* Must Reject With Sense X'1005' */
				  errorId = IDS_INVBUFFERADDR;
				  strcpy(err3270,PROG402);
				  break;
				 }

			  /* (INVALIDATTRTYPE) Invalid Attribute Type */
			  /* Error Valid Exclusively For 3270 Terminal State */
			  case INVALIDATTRTYPE:
				 {
				  /* Must Reject With Sense X'1005' */
				  errorId = IDS_INVATTRTYPE;
				  strcpy(err3270,PROG406);
				  break;
				 }

			  /* (INVALIDATTRVALUE) Invalid Attribute Value */
			  /* Error Valid Exclusively For 3270 Terminal State */
			  case INVALIDATTRVALUE:
				 {
				  /* Must Reject With Sense X'1003' */
				  errorId = IDS_INVATTRVALUE;
				  strcpy(err3270,PROG406);
				  break;
				 }

			  /* (BUFFERNOTAVAIL) 3270 Buffer Not Available */
			  /* Error Valid For NVT or 3270 Terminal State */
			  case   BUFFERNOTAVAIL:
				 {
				  if (pTelnet->Is3270Mode() && !nvtMode)
					 errorId = IDS_BUFNOTAVAIL;
				  else errorId = IDS_NVTBUFNOTAVAIL;
				  break;
				 }

			  /* Read Modified Command (Read Modified Fields and Send to Host) */
			  case READMODIFIEDCOMMAND:
				 {
				  /* Valid Only For 3270 Mode */
				  if (pTelnet->Is3270Mode() && nvtMode)
					  retCode = p3270Buf->DataToNetwork(pNetOutBuf,MODIFIED);
				  else retCode = IDS_DATANOTSENT;

				  if ( retCode == DATASENT)
					{
					 if (pTelnet->MessageSend(pLineOutBuf,pNetOutBuf))
					  {
						SendData();
						errorId = 0;
					  }
					 else errorId = IDS_DATANOTSENT ;
					}
				  else errorId = retCode;
				  break;
				 }

			  /* Read Buffer Command (Read Entire Buffer and Send to Host) */
			  case READBUFFERCOMMAND:
				 {
				  /* Valid Only For 3270 Mode */
				  if (pTelnet->Is3270Mode() && !nvtMode)
					  retCode = p3270Buf->DataToNetwork(pNetOutBuf,ALLBUFFER);
				  else retCode = IDS_DATANOTSENT;

				  if ( retCode == DATASENT)
					{
					 if (pTelnet->MessageSend(pLineOutBuf,pNetOutBuf))
					  {
						SendData();
						errorId = 0;
					  }
					 else errorId = IDS_DATANOTSENT;
					}
				  else errorId = retCode;
				  break;
				 }

			  /* (QUERY REPLY ) Structured Fields */
			  case QUERYREPLYLIST:
        	  case QUERYREPLY:
				 {
				  /* Valid Only For 3270 LU3 printer */
				  if (pTelnet->Is3270Mode() && !nvtMode)
					  retCode = DataToNetwork(pNetOutBuf,LU3,p3270Buf->GetQueryReplyList());
				  else retCode = IDS_DATANOTSENT;
				  if ( retCode == DATASENT)
					{
					 if (pTelnet->MessageSend(pLineOutBuf,pNetOutBuf))
					  {
						SendData();
						errorId = 0;
					  }
					 else errorId = IDS_DATANOTSENT ;
					}
				  else errorId = retCode;
				  break;
				 }

			  /* Something Wrong: Unexpected Return Code */
			  default:
				 {
				  if (pTelnet->Is3270Mode() && !nvtMode)
					  errorId = IDS_UNEXPECTED3270ERROR;
				  else errorId = IDS_UNEXPECTEDNVTERROR;
				  strcpy(err3270,PROG999);
				  break;
				 }

			 } // end switch

			/* Check for any error on command processing */
			if (errorId)
			 {
			  /* Shows Error Message Dialog With Error Message Selected */
			  pNetOutBuf->ring_reset();
			  pMsgs->Message(errorId,titleId);

			  /* if Log connection option active */
			  if (connData->connLog)
				{
				 pConnLog->LogText(errorId, GetApplication()->GetInstance(), &err3270[1]);
				 if (pTelnet->Is3270Mode() && !nvtMode)
				  {
					pConnLog->LogData('R',
										  p3270Buf->GetLastStream3270(),
										  p3270Buf->GetLastStreamSize(),
										  false,
										  true,
										  p3270Buf->GetTabEbcAsc());
				  }
				 else
				  {
					pConnLog->LogData('R',
										  pNVTBuf->GetLastStreamNVT(),
										  pNVTBuf->GetLastStreamSize(),
										  false,
										  false,
										  NULL);
				  }
				}

           // Set printer status on error for sending back to the server
           printerStatus = DEVICE_NOT_READY;
           senseCode = p3270Buf->Get3270SenseCode(retCode);
			 }
         else
          {
            printerStatus = DEVICE_READY;
            senseCode =   NO_DEVICE_ERROR;
          }
 		  } // end (if retCode < 0)
		 else
		  {
         /* Verify Printer End of Job received on an str field */
         if (retCode & END_OF_FILE)
           DoPrinterBeginEndOfJob(0, 1);
			else if (retCode & BEGIN_OF_FILE)
           DoPrinterBeginEndOfJob(0, 0);
         else
            /* Verify if printer job was began and if not do begin it */
            if ((!beginEndOfJobStrFd) && (!beginOfPrintJob))
				   DoPrinterBeginEndOfJob(0, 0);

         /* Print out 3270 buffer or NVT Buffer that we just received */
         bool printerError = false;
         if (retCode & STARTPRINTING) // wcc bit 4 was on
          {
           if (nvtMode)
			    printerError = PrintBuffer(NVT);
           else printerError = PrintBuffer();  // LU3
          }

         // If this is an TN3270E session  and RESPONSE function was
         // negotiated we must sent back the device status message
         // depending upon RESPONSE_FLAG
         if (!printerError)
          {
           printerStatus = DEVICE_READY;
           senseCode     = NO_DEVICE_ERROR;
          }
         else
          {
           // Set printer status for sending back to the server
           printerStatus = DEVICE_NOT_READY;
           senseCode = GetPrinterStatus();
           // If printer is already ok, do not send error notification
           if (senseCode == NO_DEVICE_ERROR)
             printerStatus = DEVICE_READY;
          }

		  } // (if retCode ......)

       // Set Actual Printer Status on printer window
       SetPrinterStatus(GetPrinterStatus());

       // If session is TN3270E and RESPONSE function is active we must check
       //  for needing of an response.
       if (pTelnet->Is3270EMode())
        {
         needResponse = pTelnet->SetNeededResponse(pNetOutBuf, messageCtrl,
                                                   printerStatus, senseCode);
        }
       // If this an printer at TN3270 Mode we must sent back
       //  the printer status message for receiving more data
       else if (pTelnet->Is3270Mode())
        {
         needResponse = BuildTN3270PrtStatus(pNetOutBuf, printerStatus, retCode);
         if (!needResponse)
            pMsgs->Message(IDS_DATANOTSENT,titleId);
        }
       //else this is an NVT printer so, nothing todo ...

		}  // end if ( pTelnet->....)
     else if (pTelnet->Is3270EMode())
         needResponse = pTelnet->SetNeededResponse(pNetOutBuf, messageCtrl,
                                                   DEVICE_READY,
                                                   NO_DEVICE_ERROR);
     // Sending back the response message if it is needed
     if (needResponse)
      {
       //  true == no TN3270E Header: needed hdr was set before
       //                             on SetNeededResponse method
       if (pTelnet->MessageSend(pLineOutBuf,pNetOutBuf, true ))
           SendData();
       else  pMsgs->Message(IDS_DATANOTSENT,titleId);
      }

	  netInputQueue--;

	 } // end while (....)

	netInputProcessing = false;

  }  // end if (!netInput...)

 pTelnet->ResetEor();
 return 1L;
}

unsigned char
ALFFRemotePrinter::GetLU1SenseCode(int retCode)
{
     unsigned char byteError;
     switch (retCode)
      {
       case INVALIDCOMMAND:
       case INVALIDORDER:
       case UNSUPPORTEDSTRFIELD:
       case INVALIDOUT3270CMND:
       case INVALIDREADPARTYPE:
       case INVALIDSVFSEQUENCE:
       case INVALIDSPDSEQUENCE:
       case INVALIDSLDSEQUENCE:
       case INVALIDSHFSEQUENCE:
       case COMMAND_REJECTED: byteError =  COMMAND_REJECT;
                              break;
       case INTERVENTION_REQ: byteError =  INTERV_REQD;
                              break;
       case BUFFERNOTAVAIL:
       case COMP_DISCONNECTED:byteError =  COMPONENT_DISCONN;
                              break;
       case INVALIDATTRTYPE:
       case INVALIDATTRVALUE:
       case INVALIDBUFADDR:
       case DATAFOLLOWEAUREAD:
       case INVALIDREPLYMODE:
       case INVALIDSCSDATASTATE:
       case INVALIDSVFDATASTATE:
       case INVALIDSHFDATASTATE:
       case  OPERATION_CHECK: byteError =  OPERATION_CHECK;
                              break;
                    default : byteError =  COMMAND_REJECT;
                              break;
      }
    return byteError;
}

bool
ALFFRemotePrinter::BuildTN3270PrtStatus(LPALFFBUF pNetOutBuf, int status, int errorCode)
{
 /* Printer Status Message Must be sent every time
  *  the TN3270 Server sends an End-Of-Record(EOR)
  *  indicator to the TN3270 Client, or when an
  *  error occurs at the Client.
  *  Format is:  SOH % R S1 S2 IAC EOR
  *
  *              SOH = 0x01
  *                % = 0x6C
  *                R = 0xD9
  *               S1 = Status/Sense Byte 0
  *               S2 = Status/Sense Byte 1
  *              IAC = Telnet IAC Character
  *              EOR = Telnet EOR Character
  */
   /* Printer Status Message Format  - 5 bytes  */
#define PRINTERSTATUSLENGTH    5
 char printerStatus[] = { 0x01, 0x6C, 0xD9,
                          0x00,   // S1
                          0x00    // S2
                        };
 char statusMessage[5];
 memcpy (&statusMessage[0], &printerStatus[0], PRINTERSTATUSLENGTH);
 if (status == DEVICE_READY)
   memset(&statusMessage[3],0x02,1);  // Device End
 else
  {
    memset(&statusMessage[3],0x02,1);  // Unit Specify
    switch (errorCode)
     {
      case INVALIDCOMMAND:
      case INVALIDORDER:
      case UNSUPPORTEDSTRFIELD:
      case INVALIDOUT3270CMND:
      case INVALIDREADPARTYPE:
      case COMMAND_REJECTED:  memset(&statusMessage[4],0x20,1);
                              break;
      case INTERVENTION_REQ:  memset(&statusMessage[4],0x10,1);
                              break;
      case BUFFERNOTAVAIL:
      case COMP_DISCONNECTED: memset(&statusMessage[4],0x08,1);
                              break;
      case        DATA_CHECK: memset(&statusMessage[4],0x04,1);
                              break;
      case INVALIDATTRTYPE:
      case INVALIDATTRVALUE:
      case INVALIDBUFADDR:
      case DATAFOLLOWEAUREAD:
      case INVALIDREPLYMODE:
      case   OPERATION_CHECK: memset(&statusMessage[4],0x01,1);
                              break;
      default : break;
     }
   }

 char* netOutBuf = pNetOutBuf->supply;
 int maxDataLen = pNetOutBuf->ring_empty_consecutive();
 if (PRINTERSTATUSLENGTH <= maxDataLen)
  {
   memcpy (netOutBuf, statusMessage, PRINTERSTATUSLENGTH);
   pNetOutBuf->ring_supplied(PRINTERSTATUSLENGTH);
   return true;
  }
 else
  {
   pMsgs->Message(IDS_REMPRTSTATUSOUTOFMEM,IDS_TIT3270PRTERR);
   return false;
  }
}

LRESULT
ALFFRemotePrinter::DoNetOutputProcess(WPARAM command, LPARAM)
{
#ifdef Tec3270Debug
 char destString[32];
 GetApplication()->LoadString(command, destString, 31);
 char msgString[256];
 sprintf(msgString,"Session%i : %s Key Pressed",connNumber,destString);
 MessageBox(msgString,"Tec3270 Remote Prt Debug", MB_OK | MB_ICONEXCLAMATION);
#endif
 int retCode;
 int titleId;

 int readType;
 if (pTelnet->Is3270Mode())
  {
	/* Check For 3270 Special Commands */
	if ( (command == IDS_CLEAR) || (command == IDS_PA1)
	  ||(command == IDS_PA2  ) || (command == IDS_PA3)
	  ||(command == IDS_ATTN ) || (command == IDS_SYSREQ) )
	 {
	  if (command == IDS_ATTN)
		{
		 pTelnet->SendControl(pLineOutBuf,IDS_ATTN);
		 SendData();
		 return 1L;
		}
	  else if (command == IDS_SYSREQ)
		{
		 pTelnet->SendControl(pLineOutBuf,IP);
		 SendData();
		 pTelnet->SendControl(pLineOutBuf,SYNC);
		 SendData();
		 pTelnet->SendControl(pLineOutBuf,IDS_SYSREQ);
		 SendData();
		 return 1L;
		}
	  else 	readType = SHORTREAD;
	 }
	else readType = MODIFIED;

	/* Send Data To NetWork Output Buffer */
	titleId = IDS_TIT3270PRTERR;
	retCode = p3270Buf->DataToNetwork(pNetOutBuf,readType);
  }
 else
  {
	/* Check For NVT Special Commands */
	if (command == IDS_ATTN)
	 {
	  pTelnet->SendControl(pLineOutBuf,IDS_ATTN);
	  SendData();
	  return 1L;
	 }

	/* Send Data To NetWork Output Buffer */
	titleId = IDS_TITNVTPRTERR;
	retCode = pNVTBuf->DataToNetwork(pNetOutBuf,MODIFIED);
  }

 if (retCode == DATASENT)
	 {
	  if (pTelnet->MessageSend(pLineOutBuf,pNetOutBuf))
		 SendData();
	  else pMsgs->Message(IDS_DATANOTSENT,titleId);
	 }
 else pMsgs->Message(IDS_DATANOTSENT,titleId);

 return 1L;
}

LRESULT
ALFFRemotePrinter::DoNetOutputEcho(WPARAM key, LPARAM)
{
 /*
  * This Method is used only by NVT sessions with Echo              
  */
 unsigned char byte = LOBYTE(key);
 if (pTelnet->SendEcho(pLineOutBuf,(char*)&byte))
	 SendData();
 else pMsgs->Message(IDS_DATANOTSENT,IDS_TITNVTPRTERR);

 return 1L;
}


void
ALFFRemotePrinter::CmTraceSessionEnable(TCommandEnabler &ce)
{
 ce.Enable(true);
}

void
ALFFRemotePrinter::CmTraceSession()
{
  int rcOpenTrace;
  if (!traceON)
	{
	 pTrcFile = new ALFFLogFile(this);
	 rcOpenTrace = pTrcFile->OpenTrace();
	 if (rcOpenTrace == SUCCESSFULOPEN)
	  {
		string wFileName(pTrcFile->GetFileName());
		char traceText[STRINGMSGLEN];
		traceText[0] = NULL;
		pMsgs->LoadString(IDS_ALFFTRACETIT,traceText,STRINGMSGLEN-1);
		connTraceTitle = traceText + wFileName + ")";
		SetWindowTitle();
		traceON = true;
		/*
		 * Setup Log File Title For Identifying What IS Going On
		 */
		char trcHeader[STRINGMSGLEN];
		char msgHeader[STRINGMSGLEN];
		pMsgs->LoadString(IDS_ALFFSESSTRACEHDR, trcHeader,STRINGMSGLEN);
		sprintf(msgHeader,trcHeader,connNumber);
		pTrcFile->SetLogTitle(msgHeader, dateFormat);
	  }
	  else if (rcOpenTrace == INVALIDOPEN)
			  pMsgs->Message(IDS_ALFFTRACEOPENERR,IDS_ALFFSESSTITLE);
	  else if (rcOpenTrace == NOFILENAME)
			  pMsgs->Message(IDS_ALFFTRACEFILENAMERR,IDS_ALFFSESSTITLE);
	}
	else
	 {
	  pTrcFile->LogText(IDS_ALFFSESSTRACEEND, GetApplication()->GetInstance());
	  delete pTrcFile;
	  pTrcFile = 0;
	  traceON = false;
	  connTraceTitle = "";
	  SetWindowTitle();
	 }
 SetMenuTraceStat();    
}

void
ALFFRemotePrinter::SetMenuTraceStat()
{
 HMENU  prtMenu = GetMenu();
 TMenu* theMenu = new TMenu(prtMenu);
 char* menuMsg = new char[STRINGMSGLEN];
 int menuFlag;
 if (theMenu)
  {
	if (traceON)
	 {
	  pMsgs->LoadString(IDS_ALFFTRACEON,menuMsg,STRINGMSGLEN);
	  menuFlag = MF_BYCOMMAND | MF_CHECKED;
	 }
	else
	 {
	  pMsgs->LoadString(IDS_ALFFTRACEOFF,menuMsg,STRINGMSGLEN);
	  menuFlag = MF_BYCOMMAND | MF_UNCHECKED;
	 }
	theMenu->ModifyMenu(CM_TRACEREMPRT, MF_BYCOMMAND,CM_TRACEREMPRT,menuMsg);
	theMenu->CheckMenuItem(CM_TRACEREMPRT,menuFlag);
   DrawMenuBar();
  }
 delete [] menuMsg;
}

void
ALFFRemotePrinter::CmToolsLogScreenEnable(TCommandEnabler &ce)
{
 ce.Enable( IsConnected() );
}

void
ALFFRemotePrinter::SetLogScreenMenu()
{
 HMENU  prtMenu = GetMenu();
 TMenu* theMenu = new TMenu(prtMenu);
 char* menuMsg = new char[STRINGMSGLEN];
 int menuFlag;
 if (theMenu)
  {
	if (GetScrLogOn())
	 {
	  pMsgs->LoadString(IDS_ALFFLOGON,menuMsg,STRINGMSGLEN);
	  menuFlag = MF_BYCOMMAND | MF_CHECKED;
	 }
	else
	 {
	  pMsgs->LoadString(IDS_ALFFLOGOFF,menuMsg,STRINGMSGLEN);
	  menuFlag = MF_BYCOMMAND | MF_UNCHECKED;
	 }
	theMenu->ModifyMenu(CM_TOOLSLOGSCREEN, MF_BYCOMMAND,CM_TOOLSLOGSCREEN,menuMsg);
	theMenu->CheckMenuItem(CM_TOOLSLOGSCREEN,menuFlag);
	DrawMenuBar();
  }
 delete [] menuMsg;
}

/* Security menu command handlers  */
void
ALFFRemotePrinter::CmShowCertificateEnable(TCommandEnabler &ce)
{
 if (IsSSLConnected())
   ce.Enable(true);
 else ce.Enable(false);
}

void
ALFFRemotePrinter::CmShowCertificate()
{
 char title[STRINGMSGLEN];
 pMsgs->LoadString(IDS_REMPRTHEADER, title, STRINGMSGLEN-1);
 pLineComm->ShowSSLCertificate(title);
}

void
ALFFRemotePrinter::CmConnectEnable(TCommandEnabler &ce)
{
 if (IsConnected() || IsConnecting()
   || IsSSLConnecting() || IsSSLConnected() )
	ce.Enable(false);
  else
	ce.Enable(true);
}

void
ALFFRemotePrinter::CmConnect()
{
	if(nLineState == nIdle)
     Connect();
}



void
ALFFRemotePrinter::Connect()
{
	char text[STRINGMSGLEN];
	char portNumber[10];

#ifdef DEBUG_PRT
	MessageBox("ALFFRemotePrinter::Connect: Starting...","Tec3270 Remote Prt Debug",MB_OK);
#endif

	autoConnect = false;

#ifdef DEBUG_PRT
	MessageBox("ALFFRemotePrinter::Connect: SetConnectingState...","Tec3270 Remote Prt Debug",MB_OK);
#endif

	// Set Connection State:
	SetConnectingState();

	// If Connection Log File then create it
	if (connData->connLog)
	 {
	  if (!pConnLog)
		{
		 char logName[MAXPATH];
		 wsprintf(logName,"Sess%03i_prt.log",connNumber);
		 pConnLog = new ALFFLogFile(this);
		 int rcOpenLog = pConnLog->OpenLog(logName);
		 if (rcOpenLog == SUCCESSFULOPEN)
		  {
			char logHeader[STRINGMSGLEN];
			char msgHeader[STRINGMSGLEN];
			pMsgs->LoadString(IDS_ALFFSESSLOGHDR, logHeader,STRINGMSGLEN);
			wsprintf(msgHeader,logHeader,connNumber);
			pConnLog->SetLogTitle(msgHeader, dateFormat);
		  }
		  else if (rcOpenLog == INVALIDOPEN)
			 pMsgs->Message(IDS_ALFFSESSLOGOPENERR,IDS_ALFFSESSTITLE);
		  else if (rcOpenLog == NOFILENAME)
			 pMsgs->Message(IDS_ALFFSESSLOGFILENAMERR,IDS_ALFFSESSTITLE);
		}
	 }

	// Setup Connection IP Address and Port and Update Title
	connHostAddress = connData->hostName;
	itoa(connData->portNumber, portNumber, 10);
	connPortAddress = portNumber;
	GetApplication()->LoadString(IDS_LINESTATCONNECTING, text, STRINGMSGLEN-1);
   connStatusTitle = text;
   connStatusTitle.append(" ");
	connTextTitle = connHostAddress + " : " + connPortAddress;

   // if this an secure connection inform ssl method
   if (connData->securityMethod == ALFFSSLComm::ALFFSSLV23)
      connSSLStatus = " (SSLV2/SSLV3)";
   else if (connData->securityMethod == ALFFSSLComm::ALFFSSLV2)
      connSSLStatus = " (SSLV2)";
   else if (connData->securityMethod == ALFFSSLComm::ALFFSSLV3)
      connSSLStatus = " (SSLV3)";
   else connSSLStatus = " ";

   // Verificar tamanho do campo "text" para conter todo o texto abaixo !!!
	strcpy(text, connStatusTitle.c_str());
   int titLen;
   int sessTitLen = strlen (connData->sessTitle);
   if (sessTitLen)
     titLen = sessTitLen;
   else titLen = strlen(connData->connName);
   
   if ((strlen(text) + titLen) < (STRINGMSGLEN-2))
    {
     if (sessTitLen)
	      strcat(text, connData->sessTitle);
     else strcat(text, connData->connName);
	  strcat(text, " (");
    }
   if ((strlen(text) + strlen(connTextTitle.c_str())) < (STRINGMSGLEN-2))
    {
     strcat(text, connTextTitle.c_str());
	  strcat(text,")");
    }
   if ((strlen(text) + strlen(connSSLStatus.c_str())) < (STRINGMSGLEN-2))
     strcat(text,connSSLStatus.c_str());

#ifdef DEBUG_PRT
	MessageBox("ALFFRemotePrinter::Connect: SessionMessage...","Tec3270 Remote Prt Debug",MB_OK);
#endif
	/* Log Begin on Screen and Log File if is active*/
	SessionMessage(text);

#ifdef DEBUG_PRT
	MessageBox("ALFFRemotePrinter::Connect: TimeMessage...","Tec3270 Remote Prt Debug",MB_OK);
#endif

	/* Register Date and Time at what connection begins */
	TimeMessage();

#ifdef DEBUG_PRT
	MessageBox("ALFFRemotePrinter::Connect: SetWindowTitle ...","Tec3270 Remote Prt Debug",MB_OK);
#endif
	/* Update Connection Window Title */
	SetWindowTitle();

#ifndef ALFFRemotePrtDebug
	int pError;
	char stringError[LINE_STRING_ERROR_LENGTH];

	pError = pLineComm->LineConnect(connData->hostName, portNumber);
	if (pError)
	 {
	  if (pError == INVALID_CONNECTION_STATE)
		 pMsgs->Message(IDS_ALFFINVSESSSTATE, IDS_ALFFSESSTITLE);
		else
		{
		 strncpy(stringError,
					ALFFLineError(pError).ReportError(),LINE_STRING_ERROR_LENGTH);
		 pMsgs->StrMessage(stringError,0,IDS_ALFFSESSTITLE);

		 /* Log Error on Screen and Log File if it is active */
		 SessionMessage(stringError);

		 /* Inform Date and Time when connection error ocurred */
		 SessionMessage(IDS_LINECLOSEDBYERROR);
		 Disconnect();
		}
	  return;
	 }
   /* further, we will receive LINE_CONNECT Event */
#endif

//--------------------------TRACE---------------------------------
#ifdef Tec3270Trace
	MessageBox("ALFFRemotePrinter::Connect: Connection Ok ........", "Tec3270 Trace Info", MB_OK);
#endif
//---------------------------------------------------------------


//----------------------Tec3270 Remote Prt Debug Starts Here ----------------//
#ifdef ALFFRemotePrtDebug
	int nEvent = LINE_READ;
	int lError = 0;
	WPARAM wParam = 0;
	LPARAM lParam = MAKELONG(nEvent,lError);

	/* Test for Close After and IDLE TIME  Events
	if ((connData->actOption != NO_TIMER)&&(connData->intvTime))
		  {
			timerType = connData->actOption;
			timerOn = true;
			ResetTimer(true);  //Force Timer To Be Set
		  }*/
//--------------- Tec3270 DEBUG Starts Here -----------------//
#ifdef DEBUG_LU1PRT
   // LU1 Printer Data for testing LU1 processing
   //---------------------------------------------------------
	//
	// Telnet Session Initialization - Valid For 3270 Terminal Types
	//
	/* IAC DO TN3270E */
	unsigned char wBuf1[] = {IAC, DO, TN3270E};
	pLineInBuf->ring_supply_data((char*)wBuf1, 3);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	/* IAC, SB, TN3270E, SEND, DEVICE-TYPE, IAC, SE */
	unsigned char wBuf2[] = { IAC, SB, TN3270E, SEND_E, DEVICE_TYPE, IAC, SE};
	pLineInBuf->ring_supply_data((char*)wBuf2, 7);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);


   /* IAC SB TN3270E DEVICE-TYPE IS IBM-3287-1 CONNECT GWI00130 IAC SE */
	unsigned char wBuf3[] = {IAC, SB, TN3270E, DEVICE_TYPE, IS_E,
                            'I','B','M','-','3','2','8','7','-','1',
                            CONNECT,
                            'G','W','I','0','0','1','3','0',
                            IAC, SE};
	pLineInBuf->ring_supply_data((char*)wBuf3, 26);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	/* IAC SB TN3270E FUNCTIONS IS_E DATA_STREAM_CTL RESPONSES IAC SE */
	unsigned char wBuf4[] = {IAC, SB, TN3270E, FUNCTIONS, IS_E, DATA_STREAM_CTL,
                                                               SCS_CTL_CODES, IAC, SE };
	pLineInBuf->ring_supply_data((char*)wBuf4, 9);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

   // LU1 Data Stream
   // 1920 bytes
	unsigned char wBuf5[] =
   {SCS_DATA,0x00,0x00,0x00,0x00,SCS_FMT,SVF,0x05,0x42,0x03,0x00,0x05,
    SCS_FMT,SHF,0x08,0x50,0x03,0x00,0x0B,0x1F,0x33,0x47
   }


   pLineInBuf->ring_supply_data((char*)wBuf5, 1920);  //*
  	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);



   
   
   ////////////////////   END OF LU1 Data Stream   ///////////
#elif defined DEBUG_LU3PRT
   // LU3 Printer Data for testing LU3 processing
   //---------------------------------------------------------
	//
	// Telnet Session Initialization - Valid For 3270 Terminal Types
	//
	/* IAC DO TN3270E */
	unsigned char wBuf1[] = {IAC, DO, TN3270E};
	pLineInBuf->ring_supply_data((char*)wBuf1, 3);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	/* IAC, SB, TN3270E, SEND, DEVICE-TYPE, IAC, SE */
	unsigned char wBuf2[] = { IAC, SB, TN3270E, SEND_E, DEVICE_TYPE, IAC, SE};
	pLineInBuf->ring_supply_data((char*)wBuf2, 7);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);


   /* IAC SB TN3270E DEVICE-TYPE IS IBM-3287-1 CONNECT GWI00130 IAC SE */
	unsigned char wBuf3[] = {IAC, SB, TN3270E, DEVICE_TYPE, IS_E,
                            'I','B','M','-','3','2','8','7','-','1',
                            CONNECT,
                            'G','W','I','0','0','1','3','0',
                            IAC, SE};

   //Force Netname....
   //strcpy(connData->printerNetName, "GWI00130");

	pLineInBuf->ring_supply_data((char*)wBuf3, 26);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);


	/* IAC SB TN3270E FUNCTIONS IS_E DATA_STREAM_CTL RESPONSES IAC SE */
	unsigned char wBuf4[] = {IAC, SB, TN3270E, FUNCTIONS, IS_E, DATA_STREAM_CTL,
                                                               SCS_CTL_CODES,
                                                               RESPONSES,
                                                               IAC, SE };
	pLineInBuf->ring_supply_data((char*)wBuf4, 10);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	//
	unsigned char wBuf5[1920];
	memset ((char*)wBuf5,0xC1,1520);

   // TN3270E  Header
   memset ((char*)wBuf5,T3270_DATA,1);  //DATA-TYPE
   memset ((char*)wBuf5+1,0x00,1);      //REQUEST-FLAG
   memset ((char*)wBuf5+2,ALWAYS_RESPONSE,1);      //RESPONSE-FLAG
   memset ((char*)wBuf5+3,0x00,2);      //SEQ-NUMBER

   // LU3 3270 Data Stream
	memset ((char*)wBuf5+5,ERASEWRITEREM,1);  //Operation Code
	memset ((char*)wBuf5+6,0xCC,1);           //WCC era 0xC7
   pLineInBuf->ring_supply_data((char*)wBuf5, 7);  //*

//
// Standard Screen For 3270 Attributes Testing  */
//*
	unsigned char wBuf6[1365] =     
	{0x40,0x40,0x11,0x40,0x4b,0x1d,0xe8,0x28,0x42,0xf4,0xc4,0x40,
	 0x81,0x40,0xa3,0x40,0x81,0x40,0x40,0xc9,0x40,0x95,0x40,0xa3,
	 0x40,0x85,0x40,0x99,0x40,0x86,0x40,0x81,0x40,0x83,0x40,0x85,
	 0x40,0x40,0x28,0x42,0xf5,0xe3,0x40,0xd5,0x40,0xf3,0x40,0xf2,
	 0x40,0xf7,0x40,0xf0,0x40,0xc5,0x28,0x42,0xf4,0x40,0x40,0xe2,
	 0x40,0x85,0x40,0x99,0x40,0xa5,0x40,0x85,0x40,0x99,0x28,0x42,
	 0x00,0x11,0xc1,0xe3,0x1d,0xe0,0xe4,0x95,0x97,0x99,0x96,0xa3,
	 0x85,0x83,0xa3,0x85,0x84,0x40,0x86,0x89,0x85,0x93,0x84,0xa2,
	 0x7a,0x1d,0xc0,0xd9,0x85,0x87,0xa4,0x93,0x81,0x99,0x40,0x40,
	 0x1d,0xc8,0xc9,0x95,0xa3,0x85,0x95,0xa2,0x85,0x11,0xc2,0xf5,
	 0x1d,0xe0,0xd7,0x99,0x96,0xa3,0x85,0x83,0xa3,0x85,0x84,0x40,
	 0x86,0x89,0x85,0x93,0x84,0xa2,0x7a,0x1d,0xe0,0xd9,0x85,0x87,
	 0xa4,0x93,0x81,0x99,0x40,0x40,0x1d,0xe8,0xc9,0x95,0xa3,0x85,
	 0x95,0xa2,0x85,0x11,0x5d,0x4a,0x1d,0xe8,0x28,0x42,0xf4,0xc8,
	 0x89,0xa3,0x40,0x28,0x42,0xf5,0xc5,0xd5,0xe3,0xc5,0xd9,0x28,
	 0x42,0xf4,0x40,0xa3,0x96,0x40,0x99,0x85,0xa3,0xa4,0x99,0x95,
	 0x40,0xa3,0x96,0x40,0x94,0x85,0x95,0xa4,0x11,0xc5,0xc9,0x1d,
	 0xe8,0x28,0x41,0x00,0x40,0xc4,0xc5,0xc6,0xc1,0xe4,0xd3,0xe3,
	 0x40,0x11,0xc5,0x5f,0x28,0x41,0xf1,0x40,0x40,0xc2,0xd3,0xc9,
	 0xd5,0xd2,0x40,0x40,0x11,0xc5,0xf1,0x28,0x41,0xf2,0x40,0xd9,
	 0xc5,0xe5,0xc5,0xd9,0xe2,0xc5,0x40,0x11,0xc6,0xc5,0x28,0x41,
	 0xf4,0xe4,0xd5,0xc4,0xc5,0xd9,0xd3,0xc9,0xd5,0xc5,0x11,0xc6,
	 0x5a,0x28,0x41,0x00,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,
	 0x60,0x11,0xc6,0x6f,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,
	 0x60,0x11,0xc7,0xc1,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,
	 0x60,0x11,0xc7,0xd5,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,
	 0x60,0x11,0xc7,0x60,0x1d,0xe0,0x28,0x42,0x00,0xd5,0xd6,0xd9,
	 0xd4,0xc1,0xd3,0x11,0xc7,0x6a,0x28,0x41,0x00,0x40,0xc4,0x85,
	 0x86,0x81,0xa4,0x93,0xa3,0x40,0x11,0xc7,0x7f,0x28,0x41,0xf1,
	 0x40,0xc4,0x85,0x86,0x81,0xa4,0x93,0xa3,0x40,0x11,0xc8,0xd1,
	 0x28,0x41,0xf2,0x40,0xc4,0x85,0x86,0x81,0xa4,0x93,0xa3,0x40,
	 0x11,0xc8,0xe5,0x28,0x41,0xf4,0x40,0xc4,0x85,0x86,0x81,0xa4,
	 0x93,0xa3,0x40,0x11,0xc8,0x7a,0x28,0x42,0xf1,0x28,0x41,0x00,
	 0x40,0x40,0xc2,0x93,0xa4,0x85,0x40,0x40,0x40,0x11,0xc9,0x4f,
	 0x28,0x41,0xf1,0x40,0x40,0xc2,0x93,0xa4,0x85,0x40,0x40,0x40,
	 0x11,0xc9,0x61,0x28,0x41,0xf2,0x40,0x40,0xc2,0x93,0xa4,0x85,
	 0x40,0x40,0x40,0x11,0xc9,0xf5,0x28,0x41,0xf4,0x40,0x40,0xc2,
	 0x93,0xa4,0x85,0x40,0x40,0x40,0x11,0x4a,0x4a,0x28,0x42,0xf2,
	 0x28,0x41,0x00,0x40,0x40,0x40,0xd9,0x85,0x84,0x40,0x40,0x40,
	 0x11,0x4a,0x5f,0x28,0x41,0xf1,0x40,0x40,0x40,0xd9,0x85,0x84,
	 0x40,0x40,0x40,0x11,0x4a,0xf1,0x28,0x41,0xf2,0x40,0x40,0x40,
	 0xd9,0x85,0x84,0x40,0x40,0x40,0x11,0x4b,0xc5,0x28,0x41,0xf4,
	 0x40,0x40,0x40,0xd9,0x85,0x84,0x40,0x40,0x40,0x11,0x4b,0x5a,
	 0x28,0x42,0xf3,0x28,0x41,0x00,0x40,0x40,0xd7,0x89,0x95,0x92,
	 0x40,0x40,0x40,0x11,0x4b,0x6f,0x28,0x41,0xf1,0x40,0x40,0xd7,
	 0x89,0x95,0x92,0x40,0x40,0x40,0x11,0x4c,0xc1,0x28,0x41,0xf2,
	 0x40,0x40,0xd7,0x89,0x95,0x92,0x40,0x40,0x40,0x11,0x4c,0xd5,
	 0x28,0x41,0xf4,0x40,0x40,0xd7,0x89,0x95,0x92,0x40,0x40,0x40,
	 0x11,0x4c,0x6a,0x28,0x42,0xf4,0x28,0x41,0x00,0x40,0x40,0xc7,
	 0x99,0x85,0x85,0x95,0x40,0x40,0x11,0x4c,0x7f,0x28,0x41,0xf1,
	 0x40,0x40,0xc7,0x99,0x85,0x85,0x95,0x40,0x40,0x11,0x4d,0xd1,
	 0x28,0x41,0xf2,0x40,0x40,0xc7,0x99,0x85,0x85,0x95,0x40,0x40,
	 0x11,0x4d,0xe5,0x28,0x41,0xf4,0x40,0x40,0xc7,0x99,0x85,0x85,
	 0x95,0x40,0x40,0x11,0x4d,0x7a,0x28,0x42,0xf5,0x28,0x41,0x00,
	 0xe3,0xa4,0x99,0x98,0xa4,0x96,0x89,0xa2,0x85,0x11,0x4e,0x4f,
	 0x28,0x41,0xf1,0xe3,0xa4,0x99,0x98,0xa4,0x96,0x89,0xa2,0x85,
	 0x11,0x4e,0x61,0x28,0x41,0xf2,0xe3,0xa4,0x99,0x98,0xa4,0x96,
	 0x89,0xa2,0x85,0x11,0x4e,0xf5,0x28,0x41,0xf4,0xe3,0xa4,0x99,
	 0x98,0xa4,0x96,0x89,0xa2,0x85,0x11,0x4f,0x4a,0x28,0x42,0xf6,
	 0x28,0x41,0x00,0x40,0xe8,0x85,0x93,0x93,0x96,0xa6,0x40,0x40,
	 0x11,0x4f,0x5f,0x28,0x41,0xf1,0x40,0xe8,0x85,0x93,0x93,0x96,
	 0xa6,0x40,0x40,0x11,0x4f,0xf1,0x28,0x41,0xf2,0x40,0xe8,0x85,
	 0x93,0x93,0x96,0xa6,0x40,0x40,0x11,0x50,0xc5,0x28,0x41,0xf4,
	 0x40,0xe8,0x85,0x93,0x93,0x96,0xa6,0x40,0x40,0x11,0x50,0x5a,
	 0x28,0x42,0xf7,0x28,0x41,0x00,0x40,0x40,0xe6,0x88,0x89,0xa3,
	 0x85,0x40,0x40,0x11,0x50,0x6f,0x28,0x41,0xf1,0x40,0x40,0xe6,
	 0x88,0x89,0xa3,0x85,0x40,0x40,0x11,0xd1,0xc1,0x28,0x41,0xf2,
	 0x40,0x40,0xe6,0x88,0x89,0xa3,0x85,0x40,0x40,0x11,0xd1,0xd5,
	 0x28,0x41,0xf4,0x40,0x40,0xe6,0x88,0x89,0xa3,0x85,0x40,NL,NL,NL,
	 0x11,0xd1,0x60,0x1d,0xe8,0x28,0x42,0x00,0x28,0x41,0x00,0xc9,
	 0xd5,0xe3,0xc5,0xd5,0xe2,0xc5,0x11,0xd1,0x6a,0x28,0x41,0x00,
	 0x40,0xc4,0x85,0x86,0x81,0xa4,0x93,0xa3,0x40,0x11,0xd1,0x7f,
	 0x28,0x41,0xf1,0x40,0xc4,0x85,0x86,0x81,0xa4,0x93,0xa3,0x40,
	 0x11,0xd2,0xd1,0x28,0x41,0xf2,0x40,0xc4,0x85,0x86,0x81,0xa4,
	 0x93,0xa3,0x40,0x11,0xd2,0xe5,0x28,0x41,0xf4,0x40,0xc4,0x85,
	 0x86,0x81,0xa4,0x93,0xa3,0x40,0x11,0xd2,0x7a,0x28,0x42,0xf1,
	 0x28,0x41,0x00,0x40,0x40,0xc2,0x93,0xa4,0x85,0x40,0x40,0x40,
	 0x11,0xd3,0x4f,0x28,0x41,0xf1,0x40,0x40,0xc2,0x93,0xa4,0x85,
	 0x40,0x40,0x40,0x11,0xd3,0x61,0x28,0x41,0xf2,0x40,0x40,0xc2,
	 0x93,0xa4,0x85,0x40,0x40,0x40,0x11,0xd3,0xf5,0x28,0x41,0xf4,
	 0x40,0x40,0xc2,0x93,0xa4,0x85,0x40,0x40,0x40,0x11,0xd4,
	 0x4a,0x28,0x42,0xf2,0x28,0x41,0x00,0x40,0x40,0x40,0xd9,0x85,
	 0x84,0x40,0x40,0x40,0x11,0xd4,0x5f,0x28,0x41,0xf1,0x40,0x40,
	 0x40,0xd9,0x85,0x84,0x40,0x40,0x40,0x11,0xd4,0xf1,0x28,0x41,
	 0xf2,0x40,0x40,0x40,0xd9,0x85,0x84,0x40,0x40,0x40,0x11,0xd5,
	 0xc5,0x28,0x41,0xf4,0x40,0x40,0x40,0xd9,0x85,0x84,0x40,0x40,
	 0x40,0x11,0xd5,0x5a,0x28,0x42,0xf3,0x28,0x41,0x00,0x40,0x40,
	 0xd7,0x89,0x95,0x92,0x40,0x40,0x40,0x11,0xd5,0x6f,0x28,0x41,
	 0xf1,0x40,0x40,0xd7,0x89,0x95,0x92,0x40,0x40,0x40,0x11,0xd6,
	 0xc1,0x28,0x41,0xf2,0x40,0x40,0xd7,0x89,0x95,0x92,0x40,0x40,
	 0x40,0x11,0xd6,0xd5,0x28,0x41,0xf4,0x40,0x40,0xd7,0x89,0x95,
	 0x92,0x40,0x40,0x40,0x11,0xd6,0x6a,0x28,0x42,0xf4,0x28,0x41,
	 0x00,0x40,0x40,0xc7,0x99,0x85,0x85,0x95,0x40,0x40,0x11,0xd6,
	 0x7f,0x28,0x41,0xf1,0x40,0x40,0xc7,0x99,0x85,0x85,0x95,0x40,
	 0x40,0x11,0xd7,0xd1,0x28,0x41,0xf2,0x40,0x40,0xc7,0x99,0x85,
	 0x85,0x95,0x40,0x40,0x11,0xd7,0xe5,0x28,0x41,0xf4,0x40,0x40,
	 0xc7,0x99,0x85,0x85,0x95,0x40,0x40,0x11,0xd7,0x7a,0x28,0x42,
	 0xf5,0x28,0x41,0x00,0xe3,0xa4,0x99,0x98,0xa4,0x96,0x89,0xa2,
	 0x85,0x11,0xd8,0x4f,0x28,0x41,0xf1,0xe3,0xa4,0x99,0x98,0xa4,
	 0x96,0x89,0xa2,0x85,0x11,0xd8,0x61,0x28,0x41,0xf2,0xe3,0xa4,
	 0x99,0x98,0xa4,0x96,0x89,0xa2,0x85,0x11,0xd8,0xf5,0x28,0x41,
	 0xf4,0xe3,0xa4,0x99,0x98,0xa4,0x96,0x89,0xa2,0x85,0x11,0xd9,
	 0x4a,0x28,0x42,0xf6,0x28,0x41,0x00,0x40,0xe8,0x85,0x93,0x93,
	 0x96,0xa6,0x40,0x40,0x11,0xd9,0x5f,0x28,0x41,0xf1,0x40,0xe8,
	 0x85,0x93,0x93,0x96,0xa6,0x40,0x40,0x11,0xd9,0xf1,0x28,0x41,
	 0xf2,0x40,0xe8,0x85,0x93,0x93,0x96,0xa6,0x40,0x40,0x11,0x5a,
	 0xc5,0x28,0x41,0xf4,0x40,0xe8,0x85,0x93,0x93,0x96,0xa6,0x40,
	 0x40,0x11,0x5a,0x5a,0x28,0x42,0xf7,0x28,0x41,0x00,0x40,0x40,
	 0xe6,0x88,0x89,0xa3,0x85,0x40,0x40,0x11,0x5a,0x6f,0x28,0x41,
	 0xf1,0x40,0x40,0xe6,0x88,0x89,0xa3,0x85,0x40,0x40,0x11,0x5b,
	 0xc1,0x28,0x41,0xf2,0x40,0x40,0xe6,0x88,0x89,0xa3,0x85,0x40,
	 0x40,0x11,0x5b,0xd5,0x28,0x41,0xf4,0x40,0x40,0xe6,0x88,0x89,
	 0xa3,0x85,0x40,NL,0xe6,0x88,0x89,0xa3,0x85,0x40,CR,0xe6,0x88,
    0x89,0xa3,0x85,0x40,EPM,0xff,0xef};
	pLineInBuf->ring_supply_data((char*)wBuf6, 1365);  //era 1352
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);
   ////////////////////   END OF LU3 Data Stream   ////////////////////

#elif defined(DEBUG_QUERYREPLYLU1)
	//
	// Telnet Session Initialization - Valid For 3270 Terminal Types
	//
	/* IAC DO TN3270E */
	unsigned char wBuf1[] = {IAC, DO, TN3270E};
	pLineInBuf->ring_supply_data((char*)wBuf1, 3);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	/* IAC, SB, TN3270E, SEND, DEVICE-TYPE, IAC, SE */
	unsigned char wBuf2[] = { IAC, SB, TN3270E, SEND_E, DEVICE_TYPE, IAC, SE};
	pLineInBuf->ring_supply_data((char*)wBuf2, 7);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);


   /* IAC SB TN3270E DEVICE-TYPE IS IBM-3287-1 CONNECT GWI00130 IAC SE */
	unsigned char wBuf3[] = {IAC, SB, TN3270E, DEVICE_TYPE, IS_E,
                            'I','B','M','-','3','2','8','7','-','1',
                            CONNECT,
                            'G','W','I','0','0','1','4','4',
                            IAC, SE};
	pLineInBuf->ring_supply_data((char*)wBuf3, 26);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	/* IAC SB TN3270E FUNCTIONS IS_E DATA_STREAM_CTL RESPONSES IAC SE */
	unsigned char wBuf4[] = {IAC, SB, TN3270E, FUNCTIONS, IS_E,
                                     DATA_STREAM_CTL,
                                     SCS_CTL_CODES,
                                     IAC, SE };
	pLineInBuf->ring_supply_data((char*)wBuf4, 9);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	// 3270 LU3 Printer Query replies
	unsigned char wBuf5[23];

   // TN3270E  Header
   memset ((char*)wBuf5,SCS_DATA,1);  //DATA-TYPE
   memset ((char*)wBuf5+1,0x00,1);      //REQUEST-FLAG
   memset ((char*)wBuf5+2,0x00,1);      //RESPONSE-FLAG
   memset ((char*)wBuf5+3,0x00,2);      //SEQ-NUMBER (Bytes 3 e 4)

   // LU1 outbound FMH-1 Header for Structured Fields
	memset ((char*)wBuf5+5,0x06,1);  //Operation Code
   memset ((char*)wBuf5+6,0x01,1);  //Operation Code
   memset ((char*)wBuf5+7,0x00,1);  //Operation Code
   memset ((char*)wBuf5+8,0x0B,1);  //Operation Code
   memset ((char*)wBuf5+9,0x60,1);  //Operation Code
   memset ((char*)wBuf5+10,0x00,1);  //Operation Code

   // Read Partition Structured Field
	memset ((char*)wBuf5+11,0x00,1);     //STR Length Byte 0
  	memset ((char*)wBuf5+12,0x09,1);     //STR Length Byte 1 -0x05(Query Reply)
	memset ((char*)wBuf5+13,0x01,1);     //Read Partition
   memset ((char*)wBuf5+14,0xFF,1);     //PID (0xff for Query)
   memset ((char*)wBuf5+15,0xFF,1);     //PID (0xff must be sent 2 times)
	memset ((char*)wBuf5+16,0x03,1);     //Type: 0x02-Query 0x03-QueryList
	memset ((char*)wBuf5+17,0x40,1);     //ReqType: Present only for QueryList
	memset ((char*)wBuf5+18,0x81,1);     //QCODEs:  For Type 0x03-QueryList
	memset ((char*)wBuf5+19,0xA6,1);     //QCODEs:  For Type 0x03-QueryList
	memset ((char*)wBuf5+20,0x81,1);     //QCODEs:  Duplicate Query Code
   memset ((char*)wBuf5+21,IAC,1);      //IAC
   memset ((char*)wBuf5+22,EOR,1);      //EOR

   pLineInBuf->ring_supply_data((char*)wBuf5, 23);  //* Type 0x02-Query
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

#elif defined(DEBUG_QUERYREPLYLU1TN3270)
	//
	// Telnet Session Initialization - Valid For 3270 Terminal Types
	//
	/* IAC DO TN3270E */
	unsigned char wBuf1[] = {IAC, WILL, TN_SUPPRESS_GA,
                            IAC, DO, TN_TERMINAL_TYPE
                            };
	pLineInBuf->ring_supply_data((char*)wBuf1, 6);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	/* IAC, SB, TN3270E, SEND, DEVICE-TYPE, IAC, SE */
	unsigned char wBuf2[] = { IAC, SB, TN_TERMINAL_TYPE, SEND, IAC, SE};
	pLineInBuf->ring_supply_data((char*)wBuf2, 6);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);


   /* IAC SB TN3270E DEVICE-TYPE IS IBM-3287-1 CONNECT GWI00130 IAC SE */
	unsigned char wBuf3[] = {IAC, DO, TN_EOR,
                            IAC, WILL, TN_EOR,
                            IAC, DO, TN_TRANSMIT_BINARY,
                            IAC, WILL, TN_TRANSMIT_BINARY
                            };

	pLineInBuf->ring_supply_data((char*)wBuf3, 12);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	// TN3270 LU1 Printer Query replies
	unsigned char wBuf5[23];

   // TN3270 LU1 Header
   memset ((char*)wBuf5,0x00,1);    //0x00 in first byte means LU1 SCS_DATA

   // LU1 outbound FMH-1 Header for Structured Fields
	memset ((char*)wBuf5+1,0x06,1);  //Operation Code
   memset ((char*)wBuf5+2,0x01,1);  //Operation Code
   memset ((char*)wBuf5+3,0x00,1);  //Operation Code
   memset ((char*)wBuf5+4,0x0B,1);  //Operation Code
   memset ((char*)wBuf5+5,0x60,1);  //Operation Code
   memset ((char*)wBuf5+6,0x00,1);  //Operation Code
   // Read Partition Structured Field
	memset ((char*)wBuf5+7,0x00,1);     //STR Length Byte 0
  	memset ((char*)wBuf5+8,0x09,1);     //STR Length Byte 1 -0x05(Query Reply)
	memset ((char*)wBuf5+9,0x01,1);     //Read Partition
   memset ((char*)wBuf5+10,0xFF,1);    //PID (0xff for Query)
   memset ((char*)wBuf5+11,0xFF,1);    //PID (0xff must be sent 2 times)
	memset ((char*)wBuf5+12,0x03,1);    //Type: 0x02-Query 0x03-QueryList
	memset ((char*)wBuf5+13,0x40,1);    //ReqType: Present only for QueryList
	memset ((char*)wBuf5+14,0x81,1);    //QCODEs:  For Type 0x03-QueryList
	memset ((char*)wBuf5+15,0xA6,1);    //QCODEs:  For Type 0x03-QueryList
	memset ((char*)wBuf5+16,0x81,1);    //QCODEs:  Duplicate Query Code
   memset ((char*)wBuf5+17,IAC,1);     //IAC
   memset ((char*)wBuf5+18,EOR,1);     //EOR

   pLineInBuf->ring_supply_data((char*)wBuf5, 19);  //* Type 0x02-Query
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);


#elif defined(DEBUG_QUERYREPLYLU3)
	//
	// Telnet Session Initialization - Valid For 3270 Terminal Types
	//
	/* IAC DO TN3270E */
	unsigned char wBuf1[] = {IAC, DO, TN3270E};
	pLineInBuf->ring_supply_data((char*)wBuf1, 3);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	/* IAC, SB, TN3270E, SEND, DEVICE-TYPE, IAC, SE */
	unsigned char wBuf2[] = { IAC, SB, TN3270E, SEND_E, DEVICE_TYPE, IAC, SE};
	pLineInBuf->ring_supply_data((char*)wBuf2, 7);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);


   /* IAC SB TN3270E DEVICE-TYPE IS IBM-3287-1 CONNECT GWI00130 IAC SE */
	unsigned char wBuf3[] = {IAC, SB, TN3270E, DEVICE_TYPE, IS_E,
                            'I','B','M','-','3','2','8','7','-','1',
                            CONNECT,
                            'G','W','I','0','0','1','4','4',
                            IAC, SE};
	pLineInBuf->ring_supply_data((char*)wBuf3, 26);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	/* IAC SB TN3270E FUNCTIONS IS_E DATA_STREAM_CTL RESPONSES IAC SE */
	unsigned char wBuf4[] = {IAC, SB, TN3270E, FUNCTIONS, IS_E,
                                     DATA_STREAM_CTL,
                                     SCS_CTL_CODES,
                                     IAC, SE };
	pLineInBuf->ring_supply_data((char*)wBuf4, 9);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	// 3270 LU3 Printer Query replies
	unsigned char wBuf5[18];

   // TN3270E  Header
   memset ((char*)wBuf5,T3270_DATA,1);  //DATA-TYPE
   memset ((char*)wBuf5+1,0x00,1);      //REQUEST-FLAG
   memset ((char*)wBuf5+2,0x00,1);      //RESPONSE-FLAG
   memset ((char*)wBuf5+3,0x00,2);      //SEQ-NUMBER (Bytes 3 e 4)

   // LU3 3270 Data Stream
	memset ((char*)wBuf5+5,WRITESTRFIELD,1);  //Operation Code
	memset ((char*)wBuf5+6,0x00,1);           //STR Length Byte 0
  	memset ((char*)wBuf5+7,0x09,1);           //STR Length Byte 1 -0x05(Query Reply)
	memset ((char*)wBuf5+8,0x01,1);           //Read Partition
   memset ((char*)wBuf5+9,0xFF,1);           //PID (0xff for Query)
   memset ((char*)wBuf5+10,0xFF,1);          //PID (0xff must be sent 2 times)
	memset ((char*)wBuf5+11,0x03,1);          //Type: 0x02-Query 0x03-QueryList
	memset ((char*)wBuf5+12,0x40,1);          //ReqType: Present only for QueryList
	memset ((char*)wBuf5+13,0x81,1);          //QCODEs:  For Type 0x03-QueryList
	memset ((char*)wBuf5+14,0xA6,1);          //QCODEs:  For Type 0x03-QueryList
	memset ((char*)wBuf5+15,0x81,1);          //QCODEs:  Duplicate Query Code
   memset ((char*)wBuf5+16,IAC,1);           //IAC
   memset ((char*)wBuf5+17,EOR,1);           //IAC

   pLineInBuf->ring_supply_data((char*)wBuf5, 18);  //* Type 0x02-Query
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

#elif defined(DEBUG_QUERYREPLYLU3TN3270)
	//
	// Telnet Session Initialization - Valid For 3270 Terminal Types
	//
	/* IAC DO TN3270E */
	unsigned char wBuf1[] = {IAC, WILL, TN_SUPPRESS_GA,
                            IAC, DO, TN_TERMINAL_TYPE
                            };
	pLineInBuf->ring_supply_data((char*)wBuf1, 6);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	/* IAC, SB, TN3270E, SEND, DEVICE-TYPE, IAC, SE */
	unsigned char wBuf2[] = { IAC, SB, TN_TERMINAL_TYPE, SEND, IAC, SE};
	pLineInBuf->ring_supply_data((char*)wBuf2, 6);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);


   /* IAC SB TN3270E DEVICE-TYPE IS IBM-3287-1 CONNECT GWI00130 IAC SE */
	unsigned char wBuf3[] = {IAC, DO, TN_EOR,
                            IAC, WILL, TN_EOR,
                            IAC, DO, TN_TRANSMIT_BINARY,
                            IAC, WILL, TN_TRANSMIT_BINARY
                            };

	pLineInBuf->ring_supply_data((char*)wBuf3, 12);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	// TN3270 LU1 Printer Query replies
	unsigned char wBuf5[23];

   // LU3 Write Structured Field Command
  	memset ((char*)wBuf5,WRITESTRFIELD,1);  //Operation Code

   // Read Partition Structured Field
	memset ((char*)wBuf5+1,0x00,1);     //STR Length Byte 0
  	memset ((char*)wBuf5+2,0x09,1);     //STR Length Byte 1 -0x05(Query Reply)
	memset ((char*)wBuf5+3,0x01,1);     //Read Partition
   memset ((char*)wBuf5+4,0xFF,1);    //PID (0xff for Query)
   memset ((char*)wBuf5+5,0xFF,1);    //PID (0xff must be sent 2 times)
	memset ((char*)wBuf5+6,0x03,1);    //Type: 0x02-Query 0x03-QueryList
	memset ((char*)wBuf5+7,0x40,1);    //ReqType: Present only for QueryList
	memset ((char*)wBuf5+8,0x81,1);    //QCODEs:  For Type 0x03-QueryList
	memset ((char*)wBuf5+9,0xA6,1);    //QCODEs:  For Type 0x03-QueryList
	memset ((char*)wBuf5+10,0x81,1);    //QCODEs:  Duplicate Query Code
   memset ((char*)wBuf5+11,IAC,1);     //IAC
   memset ((char*)wBuf5+12,EOR,1);     //EOR

   pLineInBuf->ring_supply_data((char*)wBuf5, 13);  //* Type 0x02-Query
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

//--------------- Tec3270 3270 DEBUG Ends Here -----------------//

#elif defined(DEBUG_NVT)

//--------------- Tec3270 NVT DEBUG Starts Here ----------------//
	//
	// Telnet Session Initialization - Valid For NVT Terminal Type
	//
	/* IAC WILL TN_ECHO */
	unsigned char wBuf1[] = {IAC, WILL, TN_ECHO};
	pLineInBuf->ring_supply_data((char*)wBuf1, 3);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	/* IAC WILL TN_SUPRESS_GA */
	unsigned char wBuf2[] = {IAC, WILL, TN_SUPPRESS_GA};
	pLineInBuf->ring_supply_data((char*)wBuf2, 3);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	/* IAC, DO, TN_TERMINAL_TYPE */
	unsigned char wBuf3[] = { IAC, DO, TN_TERMINAL_TYPE};
	pLineInBuf->ring_supply_data((char*)wBuf3, 3);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

	/* IAC, DO, TN_NEG_ABOUT_WIN_SIZ */
	unsigned char wBuf4[] = { IAC, DO, TN_NEG_ABOUT_WIN_SIZ};
	pLineInBuf->ring_supply_data((char*)wBuf4, 3);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

//
// Standard Screen For NVT Testing  */
//
	unsigned char wBuf5[370] =
	{0x43,0x43,0x0d,0x0a,
	 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
	 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
	 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
	 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
	 0x23,0x23,0x23,0x0d,0x0a,
	 0x23,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
	 0x20,0x20,0x20,0x20,0x20,0x53,0x20,0x45,0x20,0x52,0x20,0x50,
	 0x20,0x52,0x20,0x20,0x4f,0x20,0x2d,0x20,0x53,0x20,0x50,0x20,
	 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
	 0x20,0x20,0x23,0x0d,0x0a,
	 0x23,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x45,0x71,0x75,
	 0x69,0x70,0x61,0x6d,0x65,0x6e,0x74,0x6f,0x3a,0x20,0x43,0x69,
	 0x73,0x63,0x6f,0x20,0x37,0x35,0x31,0x33,0x20,0x23,0x20,0x32,
	 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
	 0x20,0x20,0x23,0x0d,0x0a,
	 0x23,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x4c,0x6f,0x63,
	 0x61,0x6c,0x69,0x7a,0x61,0x63,0x61,0x6f,0x3a,0x20,0x52,0x45,
	 0x47,0x49,0x4f,0x4e,0x41,0x4c,0x20,0x53,0x41,0x4f,0x20,0x50,
	 0x41,0x55,0x4c,0x4f,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
	 0x20,0x20,0x23,0x0d,0x0a,
	 0x23,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x43,0x6f,0x6e,
	 0x74,0x61,0x74,0x6f,0x3a,0x20,0x28,0x30,0x31,0x31,0x29,0x20,
	 0x35,0x32,0x35,0x2d,0x31,0x35,0x32,0x36,0x20,0x2d,0x20,0x43,
	 0x47,0x52,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,
	 0x20,0x20,0x23,0x0d,0x0a,
	 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
	 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
	 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
	 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
	 0x23,0x23,0x23,0x0d,0x0a,
	 0x60,0x0d,0x0a,0x0d,0x0a,
	 0x55,0x73,0x65,0x72,0x20,0x41,0x63,0x63,0x65,0x73,0x73,0x20,
	 0x56,0x65,0x72,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,
	 0x0d,0x0a,0x0d,0x0a,
	 0x28,0x74,0x61,0x63,0x29,0x55,0x73,0x65,0x72,0x6e,0x61,0x6d,
	 0x65,0x3a,0x20};
	pLineInBuf->ring_supply_data((char*)wBuf5, 370);
	SendMessage(MSG_LINE_NOTIFY,wParam,lParam);

#endif  //ifdef DEBUG_NVT
//--------------- Tec3270 NVT DEBUG Ends Here -----------------//

#endif  //ifdef ALFFRemotePrtDebug
//----------------------Tec3270 Remote Prt Debug Ends Here -----------------//
}

void
ALFFRemotePrinter::CmDisconnectEnable(TCommandEnabler &ce)
{
 if (IsConnected() || IsConnecting()
   || IsSSLConnecting() || IsSSLConnected() )
	ce.Enable(true);
  else
	ce.Enable(false);
}

void
ALFFRemotePrinter::CmDisconnect()
{
 SessionMessage(IDS_LINECLOSEDBYUSER);
 Disconnect();  //true = Check Exit on Closing
}

bool
ALFFRemotePrinter::Disconnect()
{
 int pError;
 char stringError[LINE_STRING_ERROR_LENGTH];

 if (IsConnecting())
  {
   // Nothing to do: just reset the connection
   // and put it on Idle State()
   // See procedures that follow "if" structure
  }
 else if (IsConnected())
  {
	pError = pLineComm->LineDisconnect();
	if(pError)
	 {
	  stringError[0]=NULL;
	  strncpy(stringError,
				 ALFFLineError(pError).ReportError(),
				 LINE_STRING_ERROR_LENGTH);
	  pMsgs->StrMessage(stringError,0,IDS_ALFFSESSTITLE);

	  /* Log Error on Screen and Log File if is active*/
	  SessionMessage(stringError);
	 }
  }
 else if ( IsSSLConnected() || IsSSLConnecting()
        || IsSSLDisconnecting() )
   {
   // If the session was disconnect by host, so do the session cleanup
   if (disconnectedByHost)
    {
     DisconnectedByHost();
     return true;
    }

    /* Set Disconnecting SSL State */
    SetSSLDisconnectingState();
    disconnectPendingForReadWrite = false;

    // try to disconnect
	 pError = pLineComm->LineDisconnect();
    if (pError != SSL_CONNECTION_CLOSED)  // Something wrong has happened !!
     {
      string sslErrMsg;
      switch (pError)
       {
        case SSL_WANT_READ:
        case SSL_WANT_WRITE:
			     {
        		  	// Need to do nothing: further we will receive FD_READ
        			//  or FD_WRITE from socket
      			disconnectPendingForReadWrite = true;
       		   return false;
              }
        case SSL_DISCONNECT_ERROR:
       		  {
        			bool hasError = false;
        			sslErrMsg = pLineComm->GetSSLErrors(hasError);
        			if (hasError)
                {
          			pMsgs->StrMessage(sslErrMsg.c_str(),0,IDS_ALFFSESSTITLE);
          			/* Log Error on Screen and Log File if is active*/
          			SessionMessage(sslErrMsg.c_str());
         		 }
               break;
       		  }
        case INVALID_CONNECTION_STATE:
              {
               pMsgs->StrMessage("SSLComm-Disconnect",IDS_ALFFINVSESSSTATE ,IDS_ALFFSESSTITLE);
               break;
              }
        default:
              {
               pMsgs->StrMessage("SSLComm-Disconnect", IDS_ALFFSSLERROR, IDS_ALFFSESSTITLE);
               break;
              }
       }

     }
    //final cleanup else's is ahead ....

   }
 else if (IsIdle())
         return true;

 else pMsgs->StrMessage("Disconnect", IDS_ALFFINVSESSSTATE, IDS_ALFFSESSTITLE);

 /* Register Date/Time of event */
 TimeMessage();

 /* Reset All conditions to initial state */
 //if ( IsConnected() || IsSSLConnected() || IsSSLDisconnecting() )
 CloseTerminal();

 /* Update Connection window title */
 connStatusTitle = connInitialTitle;
 connSSLStatus = " ";
 SetWindowTitle();

 SetIdleState();

 return true;
}

bool
ALFFRemotePrinter::InitTerminalBuffer(bool nvt)
{
 int defScrLineSize, defScrNumLines,
	  altScrLineSize, altScrNumLines;
 bool colorTerminal, extendedAttribute;

 if (!nvt)
  {
	char *pType, *pModel;
	pType  = pTelnet->GetTerminalType();
	pModel = pTelnet->GetTerminalModel();

	/*
	 * STRCMP returns 0 (false) when strings to
	 * compare are equal
	 */
	if (!(strcmp(pType,IBM3278))
	  || !(strcmp(pType,IBM3279))
     || !(strcmp(pType,IBM3287)) )
	 {
	  /* Set Printer Color  Characteristics */
	  if (!strcmp(pType,IBM3279) )
		 colorTerminal = true;
	  else colorTerminal = false;

	  /* Set Terminal Highlighting Characteristics */
	  if (!(strcmp(pModel,MODEL2E))
		 || !(strcmp(pModel,MODEL3E))
		 || !(strcmp(pModel,MODEL4E))
		 || !(strcmp(pModel,MODEL5E)) )
		 extendedAttribute = true;
	  else extendedAttribute = false;

	  /* Set Terminal Default and Alternate Screen Format */
	  if  ( !(strcmp(pModel,MODEL1)) )
			{
			 defScrLineSize = 80;
			 defScrNumLines = 24;
			 altScrLineSize = connData->printerCharPerLine;
			 altScrNumLines = connData->printerLinePerPage;
			}
	  else if (!(strcmp(pModel,MODEL3))
				 || !(strcmp(pModel,MODEL3E)))
					{
					 defScrLineSize = 80;
					 defScrNumLines = 24;
					 altScrLineSize = 80;
					 altScrNumLines = 32;
					}
	  else if (!(strcmp(pModel,MODEL4))
				 || !(strcmp(pModel,MODEL4E)))
					{
					 defScrLineSize = 80;
					 defScrNumLines = 24;
					 altScrLineSize = 80;
					 altScrNumLines = 43;
					}

	  else if (!(strcmp(pModel,MODEL5))
				 || !(strcmp(pModel,MODEL5E)))
					{
					 defScrLineSize = 80;
					 defScrNumLines = 24;
					 altScrLineSize = 132;
					 altScrNumLines = 27;
					}

	  else      {
					 defScrLineSize = 80;
					 defScrNumLines = 24;
					 altScrLineSize = 80;
					 altScrNumLines = 24;
					}

	  /* Initialize 3270 Buffer with Default and Alternate Screens Parms */
	  p3270Buf->InitBuf(defScrNumLines,defScrLineSize,
							  altScrNumLines,altScrLineSize,
							  colorTerminal, extendedAttribute);

     /* Update Remote Printer Window Caption */
     connStatusTitle = pTelnet->GetPrinterNetname();
     SetWindowTitle();

	 }
	 else
	 {
	  /* Included for preparing to other terminal
		* types in the future ....
		*/
	  if (!(strcmp(pType,TELNETNVT)))
		{
		 /* Returning To NVT Terminal Mode */
		 defScrLineSize = 80;
		 defScrNumLines = 24;
		 altScrLineSize = 80;
		 altScrNumLines = 24;
		 }
	  else
		 {
		  /* Unknow Terminal Type */
        pMsgs->StrMessage(pType,IDS_ALFFSESSTERMERR,IDS_TITNVTPRTERR);
		  return false;
		 }
	 }
  }
 else
  {
	/* This is an NVT Session Initialization*/
	defScrLineSize = 80;
	defScrNumLines = 24;
	altScrLineSize = 80;
	altScrNumLines = 24;
	colorTerminal = false;
	extendedAttribute = false;

	/* Initialize NVT Buffer with Default and Alternate Screens Parms */
	pNVTBuf->InitBuf(defScrNumLines,defScrLineSize,
						  altScrNumLines,altScrLineSize,
						  colorTerminal, extendedAttribute);
  }

 /* Update Host Info on TN3270E */
 SetHostInfo();

 /* Update Tec3270 Status Bar */
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
 theApp->UpdatePrtGadget();
 theApp->UpdatePrtNetname();

 return true;
}

bool
ALFFRemotePrinter::CloseTerminal()
{
 pTelnet->CloseAll();
 if (pTelnet->Is3270Mode())
  {
	p3270Buf->ClearBuf();
	p3270Buf->ResetAll();
  }
 else	pNVTBuf->Reset();

 termBufferInitialized = false;

 /* Reset Communications Line */
 pLineComm->LineDisconnect();

 /* Reset All Connection Buffers */
 pLineInBuf->ring_reset();
 pLineOutBuf->ring_reset();
 pNetInBuf->ring_reset();
 pNetOutBuf->ring_reset();

 /* Reset Structured Field Query Reply */
 if (queryReplyList)
	{
	 delete queryReplyList;
	 queryReplyList = NULL;
	}

 return true;
}


void
ALFFRemotePrinter::ReceiveData()
{
 int  readLength = 0,
#ifndef ALFFRemotePrtDebug
		maxReadLength,
#endif
		retOOBLen;
 char *lastRead   = 0;

 //--------------------------TRACE---------------------------------
#ifdef Tec3270Trace
	MessageBox("Starting line read ...",
						 "Tec3270 Trace Info", MB_OK);
#endif
 //-------------------------DEBUG----------------------------------
#ifdef ALFFRemotePrtDebug
 int lError = 0;
 readLength = pLineInBuf->ring_full_consecutive();
 lastRead = pLineInBuf->consume;
#else
 //----------- Normal Processing - Read Line ----------------------

 int lError;
 char stringError[LINE_STRING_ERROR_LENGTH];

 maxReadLength = readLength = pLineInBuf->ring_empty_consecutive();
 lError = pLineComm->LineRecvData(pLineInBuf->supply, (int&)readLength);

 // Is there some bytes on ringbuffer to process ?
 if (!readLength)
   // Nothing to do !!
   return;

 if (lError != 0)
  {
   if (IsConnected())  // Not an SSL Connection
    {
	  stringError[0]=NULL;
	  strncpy(stringError,
			  ALFFLineError(lError).ReportError(),
			  LINE_STRING_ERROR_LENGTH);
	  pMsgs->StrMessage(stringError,0,IDS_ALFFSESSTITLE);

     /* Log Error on Screen and Log File if is active*/
     SessionMessage(stringError);
    }
   else if (IsSSLConnected() )
    {
     if ((lError == SSL_WANT_READ) || (lError == SSL_WANT_WRITE) )
      {
       //Nothing to do: wait until next FD_READ  (LINE_READ)
       receiveDataPendingForReadWrite = true;
       return;
      }
     else if (lError == SSL_CONNECTION_CLOSED)
      {
	    pMsgs->Message(IDS_ALFFSSLCONNCLOSED,IDS_ALFFSESSTITLE);
	    SessionMessage(IDS_LINECLOSEDBYERROR);
	    Disconnect();
       return;
      }
     else  //SSL_CONNECTION_ERROR
      {
       bool hasError = false;
       string sslErrMsg = pLineComm->GetSSLErrors(hasError);
       if (hasError)
        {
         pMsgs->StrMessage(sslErrMsg.c_str(),0,IDS_ALFFSESSTITLE);
         /* Log Error on Screen and Log File if is active*/
         SessionMessage(sslErrMsg.c_str());
        }
      }
    }
   else pMsgs->StrMessage("ReceiveData",IDS_ALFFINVSESSSTATE, IDS_ALFFSESSTITLE);

	#ifndef ALFFRemotePrtDebug
	return;
	#endif
  }
  else
  {
   receiveDataPendingForReadWrite = false;
	if (readLength > maxReadLength)
	  pMsgs->Message(IDS_ALFFSESSRECVERR,IDS_ALFFSESSTITLE);
	else
	 {
	  pLineInBuf->ring_supplied(readLength);
	  lastRead = pLineInBuf->consume;
    }
  }
#endif

 //--------------------------TRACE---------------------------------
#ifdef Tec3270Trace
 char tBuf[128];
 char message[256];
 memcpy(tBuf,lastRead,(readLength > sizeof tBuf ?
				 sizeof tBuf : (size_t)readLength));
 tBuf[126] = NULL;
 wsprintf(message,"Read Data (Char) -> %s",tBuf);
 MessageBox(message,
			  "Tec3270 Trace Info", MB_OK | MB_ICONEXCLAMATION);
#endif

 //--------------------------DEBUG---------------------------------
 if (traceON)
  if (pTelnet->Is3270Mode())
	 /* Convert EBCDIC to ASCII */
	 pTrcFile->LogData('R',lastRead, readLength, false, true,
							  p3270Buf->GetTabEbcAsc());
  else
	 /* Need no Conversion */
	 pTrcFile->LogData('R',lastRead, readLength, false);

 /*
  * Process TelNet Data:
  *
  *   Take message available for consuming in NetInBuf and parse it for
  *   separating Terminal Input Data (TermInBuf) from Protocol Options
  *   Negotiations data and give correct responses for them (OOBData).
  */

 /* Do Not Process OOB Data on separate mode in this version */
 int telnetError = pTelnet->MessageRecv(pLineInBuf,pNetInBuf,pOOBData);

 //
 // Is There OOBDATA to send ??
 //
 lError = 0;
 retOOBLen = pOOBData->ring_full_consecutive();
 if (retOOBLen)
  {
	//--------------------------TRACE-----------------------------
	#ifdef Tec3270Trace
	MessageBox("Sending OOB Data ...",
				  "Tec3270 Remote Prt Debug Info", MB_OK | MB_ICONEXCLAMATION);
	#endif
	//------------------------------------------------------------
	//
	if ((pLineOutBuf->ring_empty_consecutive()) > retOOBLen)
	 {
	  pTelnet->SetOOBData(true);
     //  true == no TN3270E Header
	  if (pTelnet->MessageSend(pLineOutBuf,pOOBData,true))
		{
		 SendData();
		 if (pTelnet->TermTypeChanged())
		  {
			if (InitTerminalBuffer())
			 termBufferInitialized = true;
			else lError = IDS_ALFFSESSTERMERR;
		  }
       else
        {
         /* Update Tec3270 Status Bar */
         Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
         theApp->UpdatePrtGadget();
         theApp->UpdatePrtNetname();
        }
		}
		else lError = IDS_ALFFSESSPROTERR;
	  pTelnet->SetOOBData(false);
	 }
	 else lError = IDS_ALFFSESSOUTBUFERR;
  }
 else if (!telnetError)
  {
	 if (pTelnet->TermTypeChanged())
	  {
		if (InitTerminalBuffer())
		 termBufferInitialized = true;
		else lError = IDS_ALFFSESSTERMERR;
	  }
  }
 if (lError || telnetError)
  {
   if (telnetError)
      lError = telnetError;
   ::SendMessage(myParent->HWindow, MSG_REMPRT_NOTIFY,
                 IDS_TERMINALTYPEERROR, 0);
   SessionMessage(IDS_LINECLOSEDBYERROR);
   Disconnect();
  }
}

void
ALFFRemotePrinter::SendData()
{
 int  lError;
 char *sendBuf;
 int nCharsToSend;
 char stringError[LINE_STRING_ERROR_LENGTH];
 /*
  * if it is sending data put the new request on a queue...
  */
 sendQueue++;
 if (!sending)
 {
  while (sendQueue)
	{
	 sending=true;
	 //--------------------------TRACE---------------------------------
	 #ifdef Tec3270Trace
	 MessageBox("Sending Data ...",
					"Tec3270 Remote Prt Debug Info", MB_OK | MB_ICONEXCLAMATION);
	 #endif
	 //----------------------------------------------------------------
	 nCharsToSend = pLineOutBuf->ring_full_consecutive();
	 if (nCharsToSend)
	 {
	  sendBuf = pLineOutBuf->consume;
#ifndef ALFFRemotePrtDebug
	  lError = pLineComm->LineSendData(sendBuf, nCharsToSend, false);
#else
     lError = 0;
#endif
     if(lError != 0)
      {
		 dataSent = false;
       if (IsConnected())  // Not an SSL Connection
        {
		   stringError[0]=NULL;
		   strncpy(stringError,
					ALFFLineError(lError).ReportError(),
					LINE_STRING_ERROR_LENGTH);
		   pMsgs->StrMessage(stringError,0,IDS_ALFFSESSTITLE);

		   /* Log Error on Screen and Log File if is active*/
		   SessionMessage(stringError);
		   TimeMessage();
        }
       else if (IsSSLConnected() )
        {
         if ((lError == SSL_WANT_READ) || (lError == SSL_WANT_WRITE) )
          {
           //Nothing to do: wait until next FD_READ  (LINE_READ)
           sendDataPendingForReadWrite = true;
           return;
          }
         else if (lError == SSL_CONNECTION_CLOSED)
          {
	        pMsgs->Message(IDS_ALFFSSLCONNCLOSED,IDS_ALFFSESSTITLE);
	        SessionMessage(IDS_LINECLOSEDBYERROR);
	        Disconnect();  
           return;
          }
         else  //SSL_CONNECTION_ERROR
          {
           bool hasError = false;
           string sslErrMsg = pLineComm->GetSSLErrors(hasError);
           if (hasError)
            {
             pMsgs->StrMessage(sslErrMsg.c_str(),0,IDS_ALFFSESSTITLE);
             /* Log Error on Screen and Log File if is active*/
             SessionMessage(sslErrMsg.c_str());
            }
          }
        }
       else pMsgs->StrMessage("SendData",IDS_ALFFINVSESSSTATE, IDS_ALFFSESSTITLE);
#ifndef ALFFRemotePrtDebug
		 return;
#else
		 pLineOutBuf->ring_consumed(nCharsToSend);
#endif
      }
	  else
      {
       sendDataPendingForReadWrite = false;
       pLineOutBuf->ring_consumed(nCharsToSend);
      }
    }
	if (pLineOutBuf->ring_full_count())
	  dataSent = false;
	 else dataSent = true;

	//
	// Trace Send Text to Trace File if Trace Option was selected
	//
	if (traceON)
	 if (pTelnet->Is3270Mode())
		/* Convert EBCDIC to ASCII */
		pTrcFile->LogData('S',sendBuf, nCharsToSend, false, true,
								p3270Buf->GetTabEbcAsc());
	 else
		/* Need no Conversion */
		pTrcFile->LogData('S', sendBuf, nCharsToSend);
	 sendQueue-=1;

	} // end while
  sending=false;
 }
}

void
ALFFRemotePrinter::SetIdleState()
{
 // Line Closed by host or any line error before
 //  reset  dataSent & xxxxxxxPendingForReadWrite
 connectPendingForReadWrite = false;
 receiveDataPendingForReadWrite = false;
 sendDataPendingForReadWrite    = false;
 disconnectPendingForReadWrite = false;
 dataSent = true;
 nLineState = nIdle;

 /* Update Status Bar for showing ssl status */
 SetStatusBar();

 /* Update link to Host Status */
 SetHostInfo();
 SetHostStatus();

 /* Update the Printer Gadgets */
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
 theApp->UpdatePrtGadget();
 theApp->UpdatePrtNetname();
}

void
ALFFRemotePrinter::SetConnectedState()
{
 nLineState = nConnected;

/* Update Status Bar for showing ssl status */
 SetStatusBar();

 /* Update link to Host Status */
 SetHostStatus();

 /* Update Tec3270 Status Bar */
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
 theApp->UpdatePrtGadget();
 theApp->UpdatePrtNetname();
}

void
ALFFRemotePrinter::SetSSLConnectedState()
{
 nLineState = nSSLConnected;

 /* Update Status Bar for showing ssl status */
 SetStatusBar();

 /* Update link to Host Status */
 SetHostStatus();

 /* Update Tec3270 Status Bar */
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
 theApp->UpdatePrtGadget();
 theApp->UpdatePrtNetname();
}

bool
ALFFRemotePrinter::CanClose()
{
 CmCloseWindow();
 return false;
}

// Menu enabler used by Print & Print Setup
void
ALFFRemotePrinter::CmPrinterEnable (TCommandEnabler &tce)
{
     tce.Enable(true);
}

int
ALFFRemotePrinter::GetPrinterStatus()
{
 HANDLE prtHandle = 0;
 const DEVNAMES* prtNames = tPrintData->GetDevNames();

 // try to open the printer
 bool success = ::OpenPrinter(prtData->prtDevice, &prtHandle, 0);

 // If the Printer cannot be opened, set it not available ....
 if (!success)
  return COMPONENT_DISCONN;

 BYTE* printersInfo =  new BYTE[PRINTERINFOBUFFERSIZE];
 int   senseCode;
 // If New Printer Opened Ok, then Get the New Printer Info (PRINTER_INFO_2)
 DWORD sizeNeeded = 0;
 if (::GetPrinter(prtHandle,  2, printersInfo,
                  PRINTERINFOBUFFERSIZE,  &sizeNeeded))
  {
   // Ok: The new printer is available ...
   PRINTER_INFO_2* prtInfo2 = (PRINTER_INFO_2*) printersInfo;

   // Return printer senseCode
   if (prtInfo2->Status == 0)
     senseCode = NO_DEVICE_ERROR;
   else senseCode = INTERV_REQD;
  }
 else senseCode = INTERV_REQD;

 delete [] printersInfo;
 return senseCode;

////////////////// PRINTER STATUS on prtInfo2->Status:  /////////////
/*
Status

Specifies the printer status. This member can be one of the following values:

Windows NT:

PRINTER_STATUS_PAUSED
PRINTER_STATUS_PENDING_DELETION

Windows 95:

PRINTER_STATUS_BUSY
PRINTER_STATUS_DOOR_OPEN
PRINTER_STATUS_ERROR
PRINTER_STATUS_INITIALIZING
PRINTER_STATUS_IO_ACTIVE
PRINTER_STATUS_MANUAL_FEED
PRINTER_STATUS_NO_TONER
PRINTER_STATUS_NOT_AVAILABLE
PRINTER_STATUS_OFFLINE
PRINTER_STATUS_OUT_OF_MEMORY
PRINTER_STATUS_OUTPUT_BIN_FULL
PRINTER_STATUS_PAGE_PUNT
PRINTER_STATUS_PAPER_JAM
PRINTER_STATUS_PAPER_OUT
PRINTER_STATUS_PAPER_PROBLEM
PRINTER_STATUS_PAUSED
PRINTER_STATUS_PENDING_DELETION
PRINTER_STATUS_PRINTING
PRINTER_STATUS_PROCESSING
PRINTER_STATUS_TONER_LOW
PRINTER_STATUS_UNAVAILABLE
PRINTER_STATUS_USER_INTERVENTION
PRINTER_STATUS_WAITING
PRINTER_STATUS_WARMING_UP

Remarks

Windows 95: The PRINTER_STATUS_PAGE_PUNT value specifies that the page is being "punted" (that is, not printed) because it is too complex for the printer to print.
////////////////////////////////////////////////////////////////////
*/
}

bool
ALFFRemotePrinter::CreatePrinter(char* prtDriver, char* prtDevice, char* prtOutput)
{
 /*
  *   if defaultPrt, Printer is associated to Windows default printer
  */
  char barTitle[STRINGMSGLEN+1];
  pMsgs->LoadString(IDS_REMPRTBARTITLE, barTitle, STRINGMSGLEN);
  ALFFProgressBar* pBar = new ALFFProgressBar(this,barTitle,20);
  pBar->Create();
  pBar->ShowWindow(SW_SHOW);

  if (!Printer)
   {
	try{
	  Printer = new ALFFPrinter(GetApplication());
     if (!prtData->defaultPrt)
       Printer->InitPrinter(prtDriver, prtDevice, prtOutput);
     SavePrinterParms();
	 }
	catch (TXOwl* erro)
	 {
	  pMsgs->Message(IDS_OUTOFMEMORY, IDS_ALFFPRINTOUTTITLE);
     delete pBar;
	  return false;
	 }
	}

 pBar->SetPosition(100);

 // Wait for 1 second and delete the progress bar
 long tickCount = ::GetTickCount();
 long tickNovo = tickCount;
 while ((tickNovo-tickCount)<1000)
    tickNovo = ::GetTickCount();

 delete pBar;

 // Get Printer Options
 tPrintData = &Printer->GetSetup();
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);

 // Update Remote Printer Options
 ALFFIniFile* iniFile = theApp->GetIniFile();
 char iniSection[21];

 strcpy(iniSection,"REMOTE PRINTER DEVICE");
 iniFile->GetString(iniSection,"PRINTERFILENAME", "", prtData->printerFileName, MAXPATH);
 prtData->printToFile = iniFile->GetInt(iniSection,"PRINTTOFILE",0);
 prtData->printToSeparateFiles = iniFile->GetInt(iniSection,"PRINTTOSEPARATEFILES",0);
 strcpy(prtData->prtDriver, prtDriver);
 strcpy(prtData->prtDevice, prtDevice);
 strcpy(prtData->prtOutput, prtOutput);

 return true;
}

// Menu File Print Setup command
void
ALFFRemotePrinter::CmPrinterSetup ()
{

  if (!Printer)
	 CreatePrinter();

#ifdef DEBUG_PRT
	MessageBox("CmPrintSetup: Starting Dialog...","Tec3270 Remote Prt Debug",MB_OK);
#endif
  /* Bring up the Print Setup dialog. */
  ALFFPrinterSetup*  setupDlg = new ALFFPrinterSetup(this, IDS_ALFFRPRTSETUPTIT,
                                                     Printer, prtData);
  bool endSetup = false;
  while (!endSetup)
   {
    setupDlg->Execute();
    if (Printer->GetSetup().Error)
	  {
       tPrintData = &Printer->GetSetup();
       const char* printerName = tPrintData->GetOutputName();
       int button = -1;
       if (printerName)
	         button = pMsgs->StrMessage(printerName,
                         IDS_ALFFPRTNOTAVAIL,IDS_TIT3270PRTERR, true);
       else button = pMsgs->StrMessage("??????",
                         IDS_ALFFPRTNOTAVAIL,IDS_TIT3270PRTERR, true);
       /* Let User change the printer */
       if (button == IDOK)
         endSetup = true;
	  }
    else endSetup = true;
   }

  // Update printer name even if it is not available,
  //  because some printer may be inherited from old
  //  parms and must be reset.....
  SetPrinterName();

  // Update printer status gadget ....
  SetPrinterStatus(GetPrinterStatus());

  delete setupDlg;
}

void
ALFFRemotePrinter::SetPrtFont(LOGFONT logFont)
{
 TScreenDC pdc;   // Must be checked if TPrintDC could be used instead of TScreenDC...
                  // TPrintDC(HDC handle, TAutoDelete autoDelete = NoAutoDelete);
 if (prtFont)
	  delete prtFont;
 strcpy(prtFontName, logFont.lfFaceName);
 prtFontSize = MulDiv(-logFont.lfHeight,72,pdc.GetDeviceCaps(LOGPIXELSY));
 prtFontWeight = logFont.lfWeight;
 prtFontItalic = logFont.lfItalic;
 prtFontCharset = logFont.lfCharSet;
 int fontHeight  =
			-MulDiv(prtFontSize,pdc.GetDeviceCaps(LOGPIXELSY),72);
 prtFont = new TFont(prtFontName,fontHeight,0,0,0,prtFontWeight,
							DEFAULT_PITCH|FF_DONTCARE,prtFontItalic,0,0,
							prtFontCharset);
 /* Update ALFFPrtData Structure with printer font */
 prtData->currPrtFont = prtFont;
}

// Change Remote Printer Session Options
void
ALFFRemotePrinter::CmChangePrtSess()
{
 int option = ALFFRemotePrinterDlg(this,connData).Execute();
 if (option == IDOK)
  {
     /* -----------  Remote Printer Session Config Info -------------------
      ----------DO NOT SAVE REMOTE CHANGED PRINTER PARAMETERS ----------
      ----------------- THEY ARE VALID JUST FOR THIS SESSION !!
      ---------------------------------------------------------------------*/
  }
}

// Choose Printer Font to any fixedpitch font available on Printer
void
ALFFRemotePrinter::CmChoosePrtFont()
{
 TFont* actualFont;
 TScreenDC pdc;
 char fontDlgTitle[TITLELEN+1];

 /* Load Tec3270 Choose Printer Font Dialog Title */
 pMsgs->LoadString(IDS_ALFFCHOOSEREMPRTFONT,fontDlgTitle, TITLELEN);

 /* Access Tec3270App Application */
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(), Tec3270App);
 actualFont = prtFont;

 // Declare common dialog data structure
 ALFFChooseFontDialog::TData fontData;

 // Flags - Allow no color or effects
 fontData.Flags = CF_FORCEFONTEXIST | CF_TTONLY | CF_SCREENFONTS
						| CF_LIMITSIZE | CF_FIXEDPITCHONLY;

 // The following are not used
 fontData.PointSize = 11;
 fontData.Style = 0;
 fontData.FontType = 0;
 fontData.SizeMin = 6;
 fontData.SizeMax = 16;
 fontData.Color = 0;

 // If we already have a font, initialise the dialog with it.
 if (actualFont)
  {
	actualFont->GetObject(fontData.LogFont);
	// Tell the dialog to go initialise itself
	fontData.Flags |= CF_INITTOLOGFONTSTRUCT;
  }

 fontData.PointSize =
		 MulDiv(-fontData.LogFont.lfHeight,72,pdc.GetDeviceCaps(LOGPIXELSY));
 fontData.DC = (HDC)pdc;

 ALFFChooseFontDialog chooseFont(this, fontData, fontDlgTitle);
 if (chooseFont.Execute() == IDOK)
  {
	 /* Process and Set up new font */
	 SetPrtFont(fontData.LogFont);

    /* Save Actual Printer Font To INI File */
    char iniSection[21];
    strcpy(iniSection,"REMOTE PRINTER DEVICE");

    /* Get the Application IniFile Pointer*/
    Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
    ALFFIniFile* iniFile = theApp->GetIniFile();

    iniFile->WriteString(iniSection,"FONTNAME",prtFontName);
    iniFile->WriteInt(iniSection,"FONTHEIGHT",prtCharHeight);
    iniFile->WriteInt(iniSection,"FONTWIDTH",prtCharWidth);
    iniFile->WriteInt(iniSection,"FONTSIZE",prtFontSize);
    iniFile->WriteInt(iniSection,"FONTWEIGHT",prtFontWeight);
    iniFile->WriteInt(iniSection,"FONTITALIC",prtFontItalic);
    iniFile->WriteInt(iniSection,"FONTCHARSET",prtFontCharset);
  }   // end if IDOK
}

bool
ALFFRemotePrinter::PrintBuffer(int luType)
{
 /*
  * Verify if printer buffer is already available.
  * If it is not available then it will be created just here
  */
  // When luType is LU1 printer Buffer is already filled.
  if ((luType == LU3) || (luType == NVT))
   {
    if (!printerBuf)
	  {
#ifdef DEBUG32
	MessageBox("ALFFRemotePrinter:PrintBuffer: Creating Printer Buffer...","Tec3270 Debug",MB_OK);
#endif
	   try {
	    printerBuf = new ALFFPrinterBuffer(6*MAXSCRFIELDS,0,MAXSCRFIELDS);
	   }
	  catch (xalloc)
	   {
		 pMsgs->StrMessage("New Printer Buffer",IDS_OUTOFMEMORY, IDS_ALFFPRINTOUTTITLE);
		 return false;
	   }
	  }
    else printerBuf->Flush();
   }

  ////////////////////////////////////////////////////////////////////////////

#ifdef DEBUG32
	MessageBox("ALFFRemotePrinter:PrintBuffer: Creating ALFFPrintOut...","Tec3270 Debug",MB_OK);
#endif

  ALFFPrintOut* printout;
  try {
		printout = new ALFFPrintOut(Printer,
                                  printerBuf,
                                  connData->printerNetName, this,
											 prtData, connData, true);
		}
  catch (TXOwl* erro)
		{
		 pMsgs->Message(IDS_OUTOFMEMORY, IDS_ALFFPRINTOUTTITLE);
		 return false;
		}


 /////////////////////////////////////////////////////////////////////////////
 // When luType is NVT or LU3 we need to fill the printer Buffer
 if ((luType == NVT) || (luType == LU3))
  {
   /* Retrieve all print fields from printer buffer */
   int rc;
   if (luType == LU3)
     rc = p3270Buf->DataToPrinter(printerBuf);
   else rc = pNVTBuf->DataToPrinter(printerBuf);
   if (rc != 0)
    {
     char xallocMsg [80];
	  sprintf(xallocMsg,"DataToPrinter RC = %i",rc);
	  pMsgs->StrMessage(xallocMsg,IDS_OUTOFMEMORY, IDS_ALFFPRINTOUTTITLE);
	  return false;
    }
  }

  /* Do need to call ALFFPrintout Paginate method  for updating page number
   * in printer buffer, because it needed on print routine for having the
   * correct page number.
   */
#ifdef DEBUG32
	MessageBox("ALFFRemotePrinter:PrintBuffer: Printout paging...","Tec3270 Debug",MB_OK);
#endif
  printout->Paginate();
  prtData->FromPage = prtData->MinPage;
  prtData->ToPage   = prtData->MaxPage;

  /* Set the print option to PO_PRINTSTORED,
   *  because the entire buffer was stored
   *  and there is no screens
   */
  prtData->printOption = PO_PRINTSTORED;

  /* Now it's time to print entire
   * printer buffer !!
   */
  bool printerError = false;

  if (prtData->printToFile)
    printerBuf->PrintToFile(this, prtData, pMsgs);
  else printerError = Printer->Print(this, *printout, false);

  int printedLines = printout->GetPrintedLines();

  //ALFFPrintout object is no more needed
  delete printout;

  if (!printerError)
   {
    thisReportLines += printedLines;
    SetStatusBar();
    return true;
   }
  else return false;
}

int
ALFFRemotePrinter::LU1DataFromNetwork(LPALFFBUF pNetInBuf)
{
 nStateLU1  nLU1State;
 register unsigned char byte;
 register int streamSize;
 int   retCode;
 unsigned char* streamLU1;
 int   saveStreamSize;

 /*
  * Verify if printer buffer is already available.
  * If it is not available then it will be created just here
  */
 if (!printerBuf)
  {
#ifdef DEBUG32
	MessageBox("ALFFRemotePrinter:LU1DataFromNetwork: Creating Printer Buffer...","Tec3270 Debug",MB_OK);
#endif
	  try {
	    printerBuf = new ALFFPrinterBuffer(6*MAXSCRFIELDS,0,MAXSCRFIELDS);
	  }
	  catch (xalloc)
	  {
		pMsgs->StrMessage("New Printer Buffer",IDS_OUTOFMEMORY, IDS_ALFFPRINTOUTTITLE);
		return false;
	  }
  }
 else printerBuf->Flush();

 /*-----------------------------------------------------------------------*/
 #define  OUTFMH1LENGTH     6
 unsigned char outboundFMH1[6]  = {0x06,0x01,0x00,0x0b,0x60,0x00};
 /*-----------------------------------------------------------------------*/

 saveStreamSize = streamSize = pNetInBuf->ring_full_consecutive();
 streamLU1 = (unsigned char*)pNetInBuf->consume;
 nLU1State = nLU1_IDLE;

 /*
  * Scan Data Received for parsing LU1 / SCS controls
  */
 while ((streamSize) && (streamLU1[0] != EM))
 {
  switch (nLU1State)
	{
    case nLU1_IDLE: /* Initial Status */
      {
       /*
        * Scan Data Received for parsing LU1 SCS controls
        */
       if (!memcmp(streamLU1,outboundFMH1,OUTFMH1LENGTH)) //Is it an FMH-1 ??
        {
         nLU1State = nLU1_STRUCTFLD;
         streamLU1 += 6;   //Skip FMH1
         streamSize -= 6;
        }
       else  nLU1State = nLU1_SCSDATA;
       break;
      }

	 case nLU1_SCSDATA: /* SCS DATA: Execute printing */
		{
        retCode = ProcessSCSData(&streamLU1, streamSize);
        nLU1State = nLU1_IDLE;
        if (retCode)
         {
          pNetInBuf->ring_consumed(saveStreamSize);
		    return retCode;
         }
        break;
      }

    /* LU1 Structured Fields: Process Only SAA Compatibility Fields */
    case nLU1_STRUCTFLD:
      {
		 while (streamSize)
		 {
		  /* Structured Fields Implemented Just for SAA Compatibility */
		  short strfSize = 0;
        unsigned char cmnd;

		  /* Build Str Field Length */
		  memcpy(&strfSize+1,&*streamLU1++,1);
		  memcpy(&strfSize,&*streamLU1++,1);
		  streamSize -= 2;
    	  strfSize -= 2;

		  /* Get Str Field ID (SFID) */;
		  byte = *streamLU1++;
        streamSize--; strfSize--;

		  /* Handle Str Order and Process All Acceptable */
		  switch (byte)
			{
			 case        SCSDATA:  /* This is Printing Data to be printed */
                              {
                                /* Skip reserved byte 3 on Str Field */
                                streamLU1++; streamSize--; strfSize--;

                                // Process SCS Data:
                                int printSize = strfSize;
                                retCode = ProcessSCSData(&streamLU1, printSize);
                                if (retCode)
                                 {
                                  pNetInBuf->ring_consumed(saveStreamSize);
											 nLU1State = nLU1_IDLE;
											 return retCode;
                                 }
                                else streamSize -= strfSize;
										  break;
                              }
			 case  READPARTITION:  /* SKIP Partition ID: It Must be 0xFF for
											  Queries  or 00-7E for Read Operations */
                               {
										  streamLU1++; streamSize--; strfSize--;

										  /* Get ReadPartition Type: */
										  cmnd = *streamLU1++;
										  streamSize--;  strfSize--;
										  switch (cmnd)
											{
											 /* Query Reply All Supported Functions */
											 case   READQRYREPLY:
												  {
													if (*streamLU1 == EM)
													 {
													  pNetInBuf->ring_consumed(saveStreamSize);
													  return QUERYREPLY;
													 }
													else
													 {
													  nLU1State = nLU1_IDLE;
													  pNetInBuf->ring_consumed(saveStreamSize);
													  return DATAFOLLOWEAUREAD;
													 }
												  }

											 /* Query Reply Listed Functions */
											 case READQRYREPLYLIST:
												  {
													/* Create Query Reply list Preceded By ReqType */
                                       if (queryReplyList)
                                         delete [] queryReplyList;
													queryReplyList = new char[strfSize*2];

													/* Store REQTYP at first Query List Byte      */
													memcpy(queryReplyList,streamLU1,strfSize);

													/* Terminate Query Reply List */
													memset(queryReplyList+strfSize,0xFF,2);

													/* Skip To First Byte After Struct Field */
													streamSize -= strfSize;
													streamLU1 += strfSize;
													nLU1State = nLU1_IDLE;
 												   pNetInBuf->ring_consumed(saveStreamSize);
													if (*streamLU1 == EM)
													  return QUERYREPLYLIST;
													else return DATAFOLLOWEAUREAD;
												  }

											 default: /* Invalid Read Partition Type */
													 {
													  nLU1State = nLU1_IDLE;
													  pNetInBuf->ring_consumed(saveStreamSize);
													  return INVALIDREADPARTYPE;
													 }
											}
                               }
			 case   EXTENDEDSTRFD:  /* This is an extended  structured field */
                               {
                                /* For this version processing BEGIN/END
                                 * of Printer JOB, just for printers, obviously.
                                 */
										  if (*streamLU1 == BEGINENDFILE)
											{
											 /* This is an Begin/End of File STR Field */
                                  streamLU1 += 2;  // Skip identifier and PID
                                  streamSize -=2;
                                  /* Check Begin/End of File Flag */
                                  if ((*streamLU1 & BEGIN_OF_FILE)
                                   &&(!*streamLU1 & END_OF_FILE ) )
                                   {
                                    // BEGIN OF PRINTER JOB
                                    DoPrinterBeginEndOfJob(0,0);
                                   }
                                  if (!(*streamLU1 & BEGIN_OF_FILE)
                                   &&(*streamLU1 & END_OF_FILE ) )
                                   {
                                    // END OF PRINTER JOB
                                    DoPrinterBeginEndOfJob(0,1);
                                   }
                                  else
                                   {
											   /* Incorrect Begin/End of File STR Field */
                                    pNetInBuf->ring_consumed(saveStreamSize);
                                    return INVALIDSTRFIELD;
                                   }
											}
										  else
											{
											 /* Unsupported (other then BEGINENDFILE)
                                   *  STR Field                              */
                                  pNetInBuf->ring_consumed(saveStreamSize);
                                  return UNSUPPORTEDSTRFIELD;
											}

                                // Must skip Flag1 and Flag 2 of BeginEnd Str Fd
										  streamLU1 += 2;
                                streamSize -= 2; strfSize -= 2;
										  break;
                               }
			 default: /* Structured Field Function Not Supported */
										  {
											nLU1State = nLU1_IDLE;
											pNetInBuf->ring_consumed(saveStreamSize);
											return UNSUPPORTEDSTRFIELD;
										  }
			}
		  /* Check for end of structured field message before end of
			  entire message */
		  if (*streamLU1 == EM)
			{
			 streamLU1++;
			 streamSize--;
			 break;
			}
		 }
		 nLU1State = nLU1_IDLE;
       break;
		}
    default:
      {
         break;
      }
   } // end of "switch (nLU1State)"

 } // end of "while (streamSize)"

 /* Termination of LU1 SCS data stream processing */
 if (streamSize > 0)
  {
   // We must leave the next message on buffer for further processing
   //  but excluding EndOfMessage Char (EM)
   saveStreamSize -= streamSize-1;
  }

 pNetInBuf->ring_consumed(saveStreamSize);
 pNetInBuf->ring_clear_mark();

 nLU1State = nLU1_IDLE;

 return 0;
}

int
ALFFRemotePrinter::ProcessSCSData(unsigned char** streamLU1, int& streamSize)
{
 register unsigned char byte = 0x00;
 char posChar;
 int  subComm, cnt;
 int  addRC;
 int  fmtCount, fmtState;
 nStateLU1  nLU1State = nLU1_SCSDATA;

 /* Store All Printing Data in an Printer Field */
 PrtField fdStore;

 // Relative Page Number (for processing FF command) and
 // set for every SCS Data Stream received, as it is imediatelly printed
 // after being processed
 int  currentPage = 1, currentCol = 0, currentLine = 0;

 char  *fieldText = NULL;
 char  *fieldTextBeg = NULL;

 /* Create Text Field To Store Buffer Characters */
 fieldTextBeg = new char[connData->printerCharPerLine+1]; // Printer Max Line Size
 memset(fieldTextBeg,NULL,connData->printerCharPerLine+1);

 /* First Field must be set here */
 fieldText = fieldTextBeg;

 // Do Process SCS Data:
 while ((streamSize) && (*streamLU1[0] != EM))
  {
   /* Get SCS Command or printing data */;
   posChar = **streamLU1;
   byte = **streamLU1++; streamSize--;

   switch (nLU1State)
	 {
     case nLU1_SCSDATA:
      {
		  /* Handle Printing Data or SCS Command */
		  switch (byte)
			{
          case   SCS_SI:
          case   SCS_SO: /* Shift In and Shift Out:
                          * Commands for switching between SBCS and DBCS
                          * In this program version only SBCS is supported.
                          * These command codes are ignored as they not take
                          * an character position.
                          */
                         break;

          case	 SCS_VCS: /* Vertical Channel Select */
                         {
                          /* Close the current field in every case
                           * and insert it on Buffer. */
                          *fieldText = NULL;   // it ends the field
                          addRC = CloseAndStorePrtField(fdStore, fieldTextBeg,
                                                        currentPage,
                                                        currentCol, currentLine);
                          if (addRC)  // IDS_ALFFPRTNOROOM
                              return addRC;

                          // Start an new field with the new position
                          fieldText = fieldTextBeg;
                          //fdStore.Reset();
                          fdStore.fdFormatted = false;

                          /* Get Channel Id */
                          byte = **streamLU1++; streamSize--;

                          /* Get the channel array index */
                          byte &= 0x0F;

                          /* This is the channel Line */
                          int channelLine = channels1_12[byte-1];
                          if (channelLine == 0)
                           {
                            // VCS is treated as an LF
                            currentLine += 1;
                            if (currentLine > prtData->bottomMargin)
                             {
                              currentPage += 1;
                              currentLine = 0;
                             }
                           }
                          else if (channelLine < currentLine)
                           {
                            // In this case it's needed to get next page
                            currentPage += 1;
                            currentLine = channelLine;
                           }
                          else currentLine =  channelLine;
                          break;
                         }

          case   SCS_HT: /* 				 Horizontal Tab          */
                         {
                          int nextCol = currentCol;
                          /* Get Next available horizontal Tab */
                          for (int i=currentCol+1; i<prtData->rightMargin; i++)
                           {
                            if (horizontalFmt[i] == SCS_HT)
                              {
                                nextCol = i;
                                break;
                              }
                           }
                          // if there is an tab mark ahead end current field:
                          if (nextCol > currentCol)
                           {
                            // Terminate current field and insert it on Buffer
                            *fieldText = NULL;   // it ends the field
                            addRC = CloseAndStorePrtField(fdStore, fieldTextBeg,
                                                        currentPage,
                                                        currentCol, currentLine);
                            if (addRC)  // IDS_ALFFPRTNOROOM
                              return addRC;

                            // Start an new field with the new position
                            fieldText = fieldTextBeg;
                            fdStore.fdFormatted = false;

                            // Set New field position;
                            currentCol = nextCol;

                            break;
                           }
                          // else HT will result in a space
                          if (currentCol > prtData->rightMargin)
                           {
                            /* End of Printer Line  and End Of Field */
                            *fieldText = NULL;   // it ends the field
                            addRC = CloseAndStorePrtField(fdStore, fieldTextBeg,
                                                          currentPage,
                                                          currentCol, currentLine);
                            if (addRC)  // IDS_ALFFPRTNOROOM
                               return addRC;

                            // ReInit the line text field
                            fieldText = fieldTextBeg;

                            // Set Next Line position
                            currentCol = 0;
                            currentLine += 1;

                            //  Maximum Page Length                (M P L)
                            if (currentLine > connData->printerLinePerPage)
                             {
                              currentPage += 1;
                              currentLine = 0;
                              currentCol  = 0;
                             }
                           }
                          *fieldText++ = ASCIIBLANK;
                          currentCol += 1;
                          break;
                         }
          case   SCS_GE: /*             Graphic Escape          */
                         {
                          // Not supported in this version - Ignored
                          break;
                         }
          case   SCS_VT: /*             Vertical Tab            */
                         {
                          int nextLine = currentLine;
                          /* Get Next available Vertical Tab */
                          for (int i=currentLine+1; i < prtData->bottomMargin; i++)
                           {
                             if (verticalFmt[i] == SCS_VT)
                              {
                                nextLine = i;
                                break;
                              }
                           }

                          // if there is an tab mark ahead, end current field:
                          if (nextLine > currentLine)
                           {
                            // Terminate current field and insert it on Buffer
                            *fieldText = NULL;   // it ends the field
                            addRC = CloseAndStorePrtField(fdStore, fieldTextBeg,
                                                        currentPage,
                                                        currentCol, currentLine);
                            if (addRC)  // IDS_ALFFPRTNOROOM
                              return addRC;

                            // Start an new field with the new position
                            fieldText = fieldTextBeg;
                            fdStore.fdFormatted = false;

                            // Set New field position;
                            currentLine = nextLine;

                            break;
                           }
                          // else VT will result in an LineFeed(LF)
                          /* End of Printer Line  and End Of Field */
                          *fieldText = NULL;   // it ends the field
                          addRC = CloseAndStorePrtField(fdStore, fieldTextBeg,
                                                          currentPage,
                                                          currentCol, currentLine);
                          if (addRC)  // IDS_ALFFPRTNOROOM
                               return addRC;

                          // ReInit the line text field
                          fieldText = fieldTextBeg;

                          currentLine++;
                          if (currentLine > prtData->bottomMargin)
                           {
                            currentPage += 1;
                            currentLine = 0;
                            currentCol  = 0;
                           }
                          }
                         break;
          case   SCS_FF: /*             Form Feed               */
                         {
                          // Terminate current field and insert it on Buffer
                          *fieldText = NULL;   // it ends the field
                          addRC = CloseAndStorePrtField(fdStore, fieldTextBeg,
                                                        currentPage,
                                                        currentCol, currentLine);
                          if (addRC)  // IDS_ALFFPRTNOROOM
                              return addRC;

                          // Start an new field with the new position
                          fieldText = fieldTextBeg;
                          fdStore.fdFormatted = false;

                          // Set Next Page position
                          currentPage +=1;
                          currentCol = 0;
                          currentLine = 0;

                         }
          case   SCS_CR: /*             Carriage Return         */
                         {
                          // Moves the presentation position horizontally
                          // to the left margin. If it is at first column
                          // CR is ignored.
                          if (currentCol > 0)
                           {
                            // Terminate current field and insert it on Buffer
                            *fieldText = NULL;   // it ends the field
                            addRC = CloseAndStorePrtField(fdStore, fieldTextBeg,
                                                          currentPage,
                                                          currentCol, currentLine);
                            if (addRC)  // IDS_ALFFPRTNOROOM
                                return addRC;

                            // Start an new field with the new position
                            fieldText = fieldTextBeg;
                            fdStore.fdFormatted = false;

                            // This new field will overlap the old one
                            currentCol = 0;

                            // If next char is an LF control, process it now
                            if (HEX(**streamLU1) == SCS_LF)
                             {
                              currentLine += 1;
                              //  Maximum Page Length                (M P L)
                              if (currentLine > connData->printerLinePerPage)
                               {
                                currentPage += 1;
                                currentLine = 0;
                               }
                              *streamLU1+=1; streamSize--;
                             }
                           }
                          break;
                         }
                         
          case  SCS_ENP:
          case  SCS_INP:
          case     NULL: /* Inhibit Presentation, and
                          * Enable Presentation are
                          * Handled as NUL : No Operation
                          */
                         {
                          break;
                         }

          case  SCS_IRS: /*             Interchange Record Sep            */
          case   SCS_NL: /*             New Line                          */
                         {
                          // Terminate current field and insert it on Buffer
                          *fieldText = NULL;   // it ends the field
                          addRC = CloseAndStorePrtField(fdStore, fieldTextBeg,
                                                        currentPage,
                                                        currentCol, currentLine);
                          if (addRC)  // IDS_ALFFPRTNOROOM
                              return addRC;

                          // Start an new field with the new position
                          fieldText = fieldTextBeg;
                          fdStore.fdFormatted = false;

                          // Set Next Line position
                          currentCol = 0;
                          currentLine += 1;
                          //  Maximum Page Length                (M P L)
                          if (currentLine > connData->printerLinePerPage)
                           {
                             currentPage += 1;
                             currentLine = 0;
                           }
                          break;
                         }

          case   SCS_BS: /*             BackSpace                         */
                         {
                          // Moves the presentation position horizontally
                          // one position to left. If it is at first column
                          // BS is ignored.
                          if (currentCol > 0)
                           {
                            // Terminate current field and insert it on Buffer
                            *fieldText = NULL;   // it ends the field
                            addRC = CloseAndStorePrtField(fdStore, fieldTextBeg,
                                                          currentPage,
                                                          currentCol, currentLine);
                            if (addRC)  // IDS_ALFFPRTNOROOM
                                return addRC;

                            // Start an new field with the new position
                            fieldText = fieldTextBeg;
                            fdStore.fdFormatted = false;

                            // This new field will overlap the old one
                            currentCol -=1;
                           }
                          break;
                         }
          case  SCS_WUS: /*             Word Underscore         */
                         // Not available on this program version: ignored.
                         break;


          case   SCS_LF: /*             Line Feed                         */
                          // Terminate current field and insert it on Buffer
                          *fieldText = NULL;   // it ends the field
                          addRC = CloseAndStorePrtField(fdStore, fieldTextBeg,
                                                        currentPage,
                                                        currentCol, currentLine);
                          if (addRC)  // IDS_ALFFPRTNOROOM
                              return addRC;

                          // Start an new field with the new position
                          fieldText = fieldTextBeg;
                          fdStore.fdFormatted = false;

                          // Set Next Line position
                          currentLine += 1;
                          //  Maximum Page Length                (M P L)
                          if (currentLine > prtData->bottomMargin)
                           {
                             currentPage += 1;
                             currentLine = 0;
                           }

          case   SCS_SA: /*             Set Attribute                     */
                         {
                          // Terminate current field and insert it on Buffer
                          *fieldText = NULL;   // it ends the field
                          addRC = CloseAndStorePrtField(fdStore, fieldTextBeg,
                                                        currentPage,
                                                        currentCol, currentLine);
                          if (addRC)  // IDS_ALFFPRTNOROOM
                              return addRC;

                          // Start an new field with the new position
                          fieldText = fieldTextBeg;

                          fdStore.fdFormatted = false;

                          // If next char is TYPE/VALUE pair, so process it now
                          // Reset All Attributes
                          if (HEX(**streamLU1) == ALLATTR)
                           {
                             // Reset Type/Value
                             *streamLU1 += 1; streamSize--;
                             if (HEX(**streamLU1) == RESETALL)
                                fdStore.fdEffects = EHDEFAULT;
                             *streamLU1 += 1; streamSize--;
                           }
                          // Extended Highlighting
                          else if (HEX(**streamLU1) == EH)
                           {
                             // Highlighting Type/Value
                             *streamLU1 += 1; streamSize--;
                             byte = **streamLU1;
                             if ( (byte == EHDEFAULT) || (byte == EHNORMAL)
                                ||(byte == EHBLINK) || (byte == EHREVERSE)
                                ||(byte == EHUNDERSC) )
                                fdStore.fdEffects = byte;
                             *streamLU1 += 1; streamSize--;
                           }
                          else
                           {
                            // Character Set and Grid Attribute (DBCS) are not
                            // supported in this version. They will be ignored.
                            *streamLU1 += 2; streamSize -=2;
                           }

                         }
          case  SCS_FMT: /*             Format                            */
                         {
                          nLU1State = nLU1_SCS_FMT;
                          break;
                         }

          case  SCS_BEL: /*             Bell Control Code                */
                         {
                          if (connData->soundAlm)
                            ::MessageBeep(MB_ICONEXCLAMATION);
                          break;
                         }

          case  SCS_TRN: /* Transparent Mode */
            {
             // Get transparent Characters Count
             int trnCount = byte = **streamLU1++; streamSize--;

             // Initially count must be decreased by one for discounting itself
             // The valid minimum value of count is 1(one) when there is no
             // data following it.
             trnCount--;
             while (trnCount)
              {
               // Check for reaching right margin
               if (currentCol > prtData->rightMargin)
                {
                 /* End of Printer Line  and End Of Field */
                 *fieldText = NULL;   // it ends the field
                 addRC = CloseAndStorePrtField(fdStore, fieldTextBeg,
                                               currentPage,
                                               currentCol, currentLine);
                 if (addRC)  // IDS_ALFFPRTNOROOM
                   return addRC;

                 // ReInit the line text field
                 fieldText = fieldTextBeg;

                 // Set Next Line position
                 currentCol = 0;
                 currentLine += 1;
                 //  Maximum Page Length         (M P L)
                 if (currentLine > prtData->bottomMargin)
                  {
                   currentPage += 1;
                   currentLine = 0;
                   currentCol  = 0;
                  }
                }

               *fieldText++ = posChar; // no EBCDIC->ASCII translation;
               currentCol += 1;
               trnCount--;
              }
             break;
            }

          default:  /* Formating Data Fields and Inserting on Printer Buffer */
            {
              // Check for reaching right margin
              if (connData->printerBreakLine)
               {
                if (currentCol > prtData->rightMargin)
                 {
                  /* End of Printer Line  and End Of Field */
                  *fieldText = NULL;   // it ends the field
                  addRC = CloseAndStorePrtField(fdStore, fieldTextBeg,
                                              currentPage,
                                              currentCol, currentLine);
                  if (addRC)  // IDS_ALFFPRTNOROOM
                   return addRC;

                  // ReInit the line text field
                  fieldText = fieldTextBeg;

                  // Set Next Line position
                  currentCol = 0;
                  currentLine += 1;
                  //  Maximum Page Length         (M P L)
                  if (currentLine > prtData->bottomMargin)
                   {
                    currentPage += 1;
                    currentLine = 0;
                    currentCol  = 0;
                   }
                 }
               }
              // Translate to Ascii and put on field
              *fieldText++ = p3270Buf->ConvertToAscii(posChar);
              currentCol += 1;
              break;
             }
         }
		 break;
      }

     case nLU1_SCS_FMT: /* SCS Format Command        */
      {
       /* Get SCS Format Sub Command */;
		 byte = **streamLU1++; streamSize--;

       /* Handle SCS Format Command (SCS_FMT) */
		 switch (byte)
		  {
         case    SHF: /* Set Horizontal Format    */
          {
           // Get SHF Count
           fmtCount = byte = **streamLU1++; streamSize--;

           if ((connData->printerDimen)
             ||(connData->printerCharPerInch == 0))
            {
             /* ignore SCS SHF command */
             *streamLU1 += fmtCount-1;
             streamSize -= fmtCount-1;
             break;
            }
           // Set all horizontal format controls to its defaults
           ResetPrinterFormats(HORZFMT);

           // First state is MPP processing
           fmtState = SHF_MPP;
           // Initially count must be decreased by one for discounting itself
           // The valid minimum value of count is 1(one) when SHF is used to
           // reset horizontal format controls to its defaults.
           while (--fmtCount)
            {
              // Get SHF parms until shfCount
              byte = **streamLU1++; streamSize--;
              switch (fmtState)
               {
                case SHF_MPP: /* Maximum Presentation Position (MPP)
                               * Default -->  connData->printerCharPerLine
                               */
					               if (byte > 0x00)
                                connData->printerCharPerLine = byte;
                              // else use default value
                              fmtState = SHF_LM;
                              break;

                 case SHF_LM: /* Left Margin Column Position
                               * Default -->  prtData->leftMargin
                               */
					               if (byte > 0x00)
                               {
                                if (byte <= connData->printerCharPerLine)
                                 {
                                  horizontalFmt[byte] = SCS_HT;
                                  prtData->leftMargin = byte;
                                 }
                                else return INVALIDSHFSEQUENCE;
                               }
                              fmtState = SHF_RM;
                              break;
                 case SHF_RM: /* Right Margin Column Position
                               * Default -->  prtData->rightMargin
                               */
					               if (byte > 0x00)
                               {
                                if (byte >= prtData->rightMargin)
                                   prtData->rightMargin = byte;
                                else  return INVALIDSHFSEQUENCE;
                               }
                              fmtState = SHF_TAB;
                              break;

                 case SHF_TAB:/* Horixontal TAB Positions
                               * Default -->  horizontalFmt array
                               */
					               if (byte > 0x00)
                               {
                                if ((byte >= prtData->leftMargin)
                                  &&(byte <= prtData->rightMargin) )
                                 {
                                  horizontalFmt[byte] = SCS_HT;
                                 }
                                else  return INVALIDSHFSEQUENCE;
                               }
                              fmtState = SHF_TAB;
                              break;

                    default : /* Invalid SCS_SHF State - Internal Error */
                              return INVALIDSHFDATASTATE;
               }  //  end switch
            } // end while
           nLU1State = nLU1_SCSDATA;
           break;
          }

         case    SVF: /* Set Vertical   Format    */
          {
           // Get SVF Count
           fmtCount = byte = **streamLU1++; streamSize--;

           if ((connData->printerDimen)
             ||(connData->printerLinePerInch == 0) )
            {
             /* ignore SCS SVF command */
             *streamLU1 += fmtCount-1;
             streamSize -= fmtCount-1;
             break;
            }

           // Set all vertical format controls to its defaults
           ResetPrinterFormats(VERTFMT);

           // First state is MPL processing
           fmtState = SVF_MPL;

           int channelIndex = 0;  // first valid channel 2-12
           // Initially count must be decreased by one for discounting itself
           // The valid minimum value of count is 1(one) when SVF is used to
           // reset vertical format controls to its defaults.
           while (fmtCount)
            {
              // Get SHF parms until shfCount
              byte = **streamLU1++; streamSize--;
              switch (fmtState)
               {
                case SVF_MPL: /* Maximum Presentation Line (MPL)
                               * Default -->  connData->printerLinePerPage
                               */
					               if (byte > 0x00)
                                connData->printerLinePerPage = byte;
                              // else use default value
                              fmtState = SVF_TM;
                              break;

                 case SVF_TM: /* Top Margin Line Position
                               * Default -->  prtData->topMargin
                               */
					               if (byte > 0x00)
                               {
                                if (byte <= connData->printerLinePerPage)
                                 {
                                  verticalFmt[byte] = SCS_VT;
                                  prtData->topMargin = byte;
                                  // Set channel 1 to TM
                                  channels1_12[channelIndex++] = byte;
                                 }
                                else return INVALIDSVFSEQUENCE;
                               }
                              fmtState = SVF_BM;
                              break;
                 case SVF_BM: /* Bottom Margin Line Position
                               * Default -->  prtData->bottomMargin
                               */
					               if (byte > 0x00)
                               {
                                if ((byte >= prtData->topMargin)
                                  &&(byte <= connData->printerLinePerPage) )
                                   prtData->bottomMargin = byte;
                                else  return INVALIDSVFSEQUENCE;
                               }
                              fmtState = SVF_TAB;
                              break;

                 case SVF_TAB:/* Vertical TAB Positions
                               * Default -->  verticalFmt array
                               */
					               if (byte > 0x00)
                               {
                                if ((byte >= prtData->topMargin)
                                  &&(byte <= prtData->bottomMargin) )
                                 {
                                  verticalFmt[byte] = SCS_VT;
                                  // Channels 1-12 are 0-11 channelIndex
                                  if (channelIndex < 12)
                                   channels1_12[channelIndex] = byte;
                                 }
                                else  return INVALIDSVFSEQUENCE;
                               }
                              fmtState = SVF_TAB;
                              break;

                    default : /* Invalid SCS_SHF State - Internal Error */
                              return INVALIDSVFDATASTATE;
               }  //  end switch
            } // end while

           nLU1State = nLU1_SCSDATA;
           break;
          }

         case    SLD: /* Set Line Density         */
          {
           /* When SLD is received line density is set to its default value
            * before doing any analisys. */
           connData->printerLinePerInch =  DEFAULTLINEDENSITY;

           /* getting sldCount */
           byte = **streamLU1++; streamSize--;
           if ((byte != 1) || (byte != 2))
             return INVALIDSLDSEQUENCE;

           // if there is any info after sldCount do process it
           if (byte == 2)
            {
             /* getting sldPoints */
             byte = **streamLU1++; streamSize--;
             if ((byte > 0) && (byte <= 72))
              {
               connData->printerLinePerInch = 72/byte;
              }
            }

           nLU1State = nLU1_SCSDATA;
           break;
          }

         case    STO: /* Set Text Orientation     */
          {
           nLU1State = nLU1_SCSDATA;
           break;
          }

         case SPDPPM: /* SPD or PPM control       */
          {
           nLU1State = nLU1_SCS_FMT_SPDPPM;
           break;
          }

         default: /* Unsupported Control */
                  nLU1State = nLU1_SCSDATA;
                  break;
        }
       break;
      }

     case nLU1_SCS_FMT_SPDPPM: /* SPD or PPM format control subcommand */
       {
        /* Handle SPD or PPM Format Sub Command */
		  cnt = HEX (**streamLU1++); streamSize--;
        subComm = HEX (**streamLU1++);
        switch (subComm)
         {
          case SPD: /* Set Print Density */
                    if (cnt == 4)  // cnt=1byte + 29/SPD=1byte + charperinch=2bytes
                     {
                      /* When SPD is received the print density is set to
                       * its default value before doing any analisys. */
                      connData->printerCharPerInch =  DEFAULTPRINTDENSITY;

                      short charDensity;
                      /* Build Char Density field from data stream */
		  					 memcpy(&charDensity+1,&*streamLU1++,1);
		  					 memcpy(&charDensity,&*streamLU1++,1);
                      streamSize -= 2;
                      
                      if (charDensity > 0)
                       connData->printerCharPerInch = charDensity;
                      // else retain default value
                     }
                    // else retain default value
                    break;

          case PPM: /* Sub Command Not implemented */
                    break;
          default:  /* Unsupported Format SubCommand */
                    nLU1State = nLU1_SCSDATA;
                    break;
         }
        nLU1State = nLU1_SCSDATA;
        break;
       }
     default: /* Invalid State */
              return INVALIDSCSDATASTATE;

   }  // switch ...
  } // while (streamSize) ....

 delete [] fieldTextBeg;

 return 0;
}

int
ALFFRemotePrinter::CloseAndStorePrtField(PrtField& fdStore,
                                            char* text, int currentPage,
                                            int currentCol, int currentLine)
{
  int textLen = strlen(text)+1;
  if (textLen)
   {
    fdStore.fdText = new char[textLen];
    strcpy(fdStore.fdText,text);
    fdStore.fdPosition.x = currentCol;
    fdStore.fdPosition.y = currentLine;
    fdStore.scrLineSize = connData->printerCharPerLine; //(MPP)
    fdStore.scrPrtEndLine  = connData->printerLinePerPage; //(MPL)
    fdStore.prtPageNumber = currentPage;
    int addRC = printerBuf->StorePrtField(&fdStore);
    // It would be return printerBuf......
    //  but I prefer to document its return codes !
    if (addRC)  // IDS_ALFFPRTNOROOM
      return addRC;
    else return 0;
   }
  else return 0;  // Should be modified to return an error code !!
}

int
ALFFRemotePrinter::DataToNetwork(LPALFFBUF pNetOutBuf, int luType, const char* qReplyList)
{
 int netCount=0, netOutMax=0, rCode=0;
 char *netBufPtr, *netBufSave;

 /*
  *  Set Network Output Buffer Controls
  */
 netBufSave = netBufPtr = pNetOutBuf->supply;
 netOutMax = pNetOutBuf->ring_empty_consecutive();
 netBufSave = netBufSave;
 netCount = 0;

 /* Query Reply Data as Answer of Read Partition */
 /* Check For Query Reply or Query Reply List */
 if (!qReplyList)
  {
   rCode = SendQueryReply(&netBufPtr, &netCount, netOutMax, luType, QUERYREPLY);
   if (rCode != DATASENT)
    return rCode;
  }
 else
  {
   /* This an Query Reply List: Check REQTYP on 1st
 		  queryReplyList Byte */
   if (!(*qReplyList & 0xc0))   // Test for B'00' ReqType
    {
     // QCODE List - List of Query Replies to send
     int qCount = 0;
     bool alreadySent = false;
     char qReplySent[128];
     qReplyList++;
     rCode = SendQueryReply(&netBufPtr, &netCount, netOutMax, luType, QUERYREPLYHDR);
     while ((*qReplyList != 0xFF) && (rCode == DATASENT))
      {
       // Verify if query reply has already sent
       for (int i=0; i < qCount; i++)
        {
         if (*qReplyList == qReplySent[i])
          {
           alreadySent = true;
           break;
          }
        }
       // if it was not yet sent try to send it .....
       if (!alreadySent)
        {
         rCode = SendQueryReply(&netBufPtr, &netCount, netOutMax, luType, *qReplyList);
         if (rCode == DATASENT)
          {
           qReplySent[qCount] = *qReplyList;
           qCount++;
           qReplyList++;
          }
        }
       else
        {
         alreadySent = false;
         qReplyList++;
        }
      } // while ///

     if (qCount == 0)
      rCode = SendQueryReply(&netBufPtr, &netCount, netOutMax, luType, QUERYREPLYNULL);

     if (rCode != DATASENT)
      return rCode;
    }
   else if ((*qReplyList & 0x40) // Test for B'01' ReqType - // EQUIVALENT - Same as Query Reply
         ||(*qReplyList & 0x80)) // Test for B'10' ReqType - // ALL - All query replies supported
    {
     // EQUIVALENT - Same as Query Reply
     rCode = SendQueryReply(&netBufPtr, &netCount, netOutMax, luType, QUERYREPLY);
     if (rCode != DATASENT)
      return rCode;
    }
   else
    {
     rCode = SendQueryReply(&netBufPtr, &netCount, netOutMax, luType, QUERYREPLYNULL);
     if (rCode != DATASENT)
        return rCode;
    }
  }

 /* Update Buffer With Network Stream Data To Send */
 pNetOutBuf->ring_supplied(netCount);
 return DATASENT;
}

int
ALFFRemotePrinter::SendQueryReply(char** netBufPtr, int* netCount, const int netOutMax,
                                     const int luType, const int qCode)
{
/*-----------------------------------------------------------------------*/
 unsigned char replySummary_LU1printer[10] =
 {
  /*Summary (Query Reply Codes Accepted)
							 Summary (SAA Support)
							 |    Usable Area (SAA Support)
							 |	  	|    Character Sets (SAA Support)
							 |	   |    |
							 |    |    |    HighLighting
							 |		| 	  |    |	  Begin/End of File
				Summary   |    |    |    |	   |	 Device Characteristics
				|         |    |    |    |    |    |
  Length    |      	 |		|    |    |	   |	  |
  |			|			 |		|    |    |    |    |	                       */
  0x00,0x0A,0x81,0x80,0x80,0x81,0x85,0x87,0x9F,0xA0
  };
 unsigned char replySummary_LU3printer[11] =
 {
  /*Summary (Query Reply Codes Accepted)
							 Summary (SAA Support)
							 |    Usable Area (SAA Support)
							 |	  	|    Character Sets (SAA Support)
							 |	   |    |
							 |    |    |    HighLighting
							 |		| 	  |    |	   Reply Modes
				QueryReply|    |    |    |	   |
				|         |    |    |    |    |    Begin/End Of File
  Length    |      	 |		|    |    |	   |	  |
  |			|			 |		|    |    |    |    |	  Implicit Partitions (SAA Support) */
  0x00,0x0B,0x81,0x80,0x80,0x81,0x85,0x87,0x88,0x9F,0xA6
  };

  /*-----------------------------------------------------------------------*/
  unsigned char replyUsable_LU1printer[23] =
  {
  /* Usable Area Query Reply Base
									Flag                     Units
							 Flag |A   |Area     |Area     |A
	 						 |    |l   |Width    |Height   |l   Points
							 |    |w   |(+6)     |(+8)     |w   |Al
				Usable    |    |a   |(MPP)    |(MPL)    |a   | wa
  Length    Area      |    |y   |         |         |y   |   ys
  |         |         |    |s   |         |         |s   |         */
  0x00,0x17,0x81,0x81,0x1f,0x00,0x00,0x50,0x00,0x18,0x00,0x00,0x01,

  /*                                      BuffSize
  |  Cell Points Sizes...     | Cell Cell | Always
  |     A l                   | X    Y    | 0x00, 0x00
  |          w a              | UnitsUnits| LU1 has no Buffer
  |               y s         | |    |    |                            */
  0x00,0x78,0x00,0x01,0x00,0x48,0x0D,0x1C,0x00,0x00
  };

  unsigned char replyUsable_LU3printer[23] =
  {
  /* Usable Area Query Reply Base
									Flag                     Units
							 Flag |A   |Area     |Area     |A
							 |12  |l   |Width    |Height   |l   Points
							 |-   |w   |         |         |w   |Al
				Usable    |14  |a   |         |         |a   | wa
  Length    Area      |Bit |y   |         |         |y   |   ys
  |         |         |Adr |s   |         |         |s   |         */
  0x00,0x17,0x81,0x81,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
  /*                                      BuffSize (+21)
  |  Cell Points Sizes...     | Cell Cell | Mod2 (24*80)  = 0x07,0x80
  |     A l                   | X    Y    | Mod3 (32*80)  = 0x0a,0x00
  |          w a              | UnitsUnits| Mod4 (43*80)  = 0x0d,0x07
  |               y s         | |    |    | Mod5 (27*132) = 0x0d,0xec  */
  0x00,0x78,0x00,0x01,0x00,0x48,0x0D,0x1C,0x07,0x80
  };

  /*-----------------------------------------------------------------------*/
  unsigned char replyCharSet_LU1LU3printer[20] =
  {
  /*        Character Sets      Default Char Slot
  Length    |      	 Flags     |    Height
  |			|			 |no GE    |Width    |FORM               DL
  |         |         |CGCSGID  |         |                   |     */
  0x00,0x14,0x81,0x85,0x02,0x00,0x09,0x0C,0x00,0x00,0x00,0x00,0x07,
  /*           *      |
               *      This version does not support Graphic Escape (GE)
               *      as it is indicated on Flags field above.
               *      When support to GE is added the Flag value MUST be
               *      changed from '0x02,0x00' to '0x82,0x00'.
               *      Its implementation is under evaluation as GE codepoints
               *      refers to APL symbols,as stated on page
               *      http://x3270.bgp.nu/Charset.html
               *      May be on version 4 it will be available.
               */
  /*   Flag      | ---- CGCSGID ---- |
  Set  |    LCID |CECP     |Code Page
  | Id |    |    |695      |1140 (Old CP037 + Euro Sign)            */
  0x00,0x00,0x00,0x02,0xb7,0x04,0x74
  /* On next version, when GE is ready to be accepted, we must supply
   * following descriptor for APL Character Set:
   *
   *     Flag      | ---- CGCSGID ---- |
    Set  |    LCID |CECP     |Code Page
    | Id |    |    |963      | 310 (APL)
    0x01,0x00,0xF1,0x03,0xc3,0x01,0x36                            */
  };

  /*-----------------------------------------------------------------------*/
  unsigned char replyHighLight_LU1LU3printer[13] =
  {
  /* HighLighting Supported Query Reply
							 List |- E f f e c t s ...
							 |L   | A  E    |         |         |
							 |e   | c  f    |         |         |
							 |n   | c  f    |         |         |
							 |g   | e  e    |         |         |
  Length    HighLght  |t   | p  c    |A   E    |A   E    |A   E
  |         |         |h   | t  t    |c   f    |c   f    |c   f     */
  0x00,0x0d,0x81,0x87,0x04,0x00,0xf0,0xf1,0xf1,0xf2,0xf2,0xf4,0xf4
  };

  /*-----------------------------------------------------------------------*/
  unsigned char replyModes_LU3printer[6] =
  {
  /* Reply Modes
									Extended Field Mode
				Summary        |
  Length    |      	 Field|      Character Mode
  |			|			 |Mode|      |                             */
  0x00,0x06,0x81,0x88,0x00,0x01 //,0x02,
  };

  /*-----------------------------------------------------------------------*/
  unsigned char replyBeginEndFile_LU1LU3printer[5] =
  {
  /* Begin/End of File

				QueryReply
  Length    |      Begin/End   Reserved
  |			|	    | of File	 |                                        */
  0x00,0x05,0x81,  0x9F,       0x00
  };

  /*-----------------------------------------------------------------------*/
  unsigned char replyDeviceCharacteristics_LU1printer[40] =
  {
  /*        Query
  Length    |Reply    Length    |HDP           |CPI=10   |CPI=12   |CPI=17.1
  |			| Device  |of HDP   |Descript |SPD |MPP=80   |MPP=96   |MPP=137
  |         | Char    |descri-  |ID       |Sup |         |         |
  |         |         | ptor    |         |    |         |         |     */
  0x00,0x28,0x81,0xa0,0x00,0x0b,0xff,0x01,0x80,0x0a,0x50,0x0c,0x60,0x11,0x89, /*
  |Length   |VDP      |SLD
  |of VDP   |Descript |Sup |LPI=2    |LPI=3    |LPI=4    |LPI=6    |LPI=8
  |Descript |ID       |    |MPL=127  |MPL=127  |MPL=127  |MPL=127  |MPL=127 */
  0x00,0x0f,0xFF,0x02,0x80,0x24,0x7F,0x18,0x7F,0x12,0x7F,0x0c,0x7f,0x0a,0x7f, /*
  |Length   |PPM      |No  |Length   |STO      |No
  |of PPM   |Descript |PPM |of STO   |Descript |STO
  |Descript |ID       |    |Descript |ID       |      */
  0x00,0x05,0xff,0x03,0x00,0x00,0x05,0xff,0x04,0x00
  };

  /*-----------------------------------------------------------------------*/
  unsigned char replyImplicitPart_LU3printer[17] =
  {
  /*        Implicit            Self-Defining Parameter
  Length    |Parti-   Flags     |    For  |F   |- Default Printer-|
  |			| tion	 |Always   |    Part |l   |  Buffer          |
  |         |         |Zeroes   |    Size |a   |  Size            |
  |         |         |         |    |    |g   | (80 x 24)        |	*/
  0x00,0x11,0x81,0xa6,0x00,0x00,0x0b,0x03,0x00,0x00,0x00,0x07,0x80,  /*
  |- Altern. Printer|
  |   Buffer Size   |
  |  (27 * 132)     | */
  0x00,0x00,0x0d,0xec
  };

  /*-----------------------------------------------------------------------*/
  unsigned char replyNull[4] =
  {
  /*        Field Validation
  Length    |
  |			|
  |         |    |  Null (No features queried supported)  */
  0x00,0x04,0x81,0xFF
  };

 /*-----------------------------------------------------------------------*/
 unsigned char inboundFMH1[6]  = {0x06,0x01,0x00,0x8b,0x60,0x00};
 /*-----------------------------------------------------------------------*/

#define QUERYREPLYLU1LENGTH    111     // =  10+23+20+13+5+40
#define QUERYREPLYLU3LENGTH     95     // =  11+23+20+13+6+5+17

 /* Set Query Reply Length depending upon LU type */
 int queryReplyLen;
 if (luType == LU1)
   queryReplyLen = 6+QUERYREPLYLU1LENGTH;  //(inbound FMH1 length = 6)
 else queryReplyLen = QUERYREPLYLU3LENGTH;

 switch (qCode)
  {
    case QUERYREPLY:
      {
       if (netOutMax > queryReplyLen)
        {
         if (luType == LU1)
          {
		     /* Set Structured Field Reply inbound FMH-1 */
		     memcpy(*netBufPtr,inboundFMH1,6);
           *netBufPtr+=6;
		     *netCount+=6;

		     /* Send LU1 Query Reply Summary Structured Field */
		     memcpy(*netBufPtr,replySummary_LU1printer,10);
		     *netBufPtr+=10;
		     *netCount+=10;

		     /* Send LU1 Query Reply Usable Area Structured Field */
		     memcpy(*netBufPtr,replyUsable_LU1printer,23);
		     *netBufPtr+=23;
		     *netCount+=23;

		     /* Send Query Reply Character Set (SAA Support) */
		     memcpy(*netBufPtr,replyCharSet_LU1LU3printer,20);
		     *netBufPtr+=20;
		     *netCount+=20;

		     /* Send Query Reply HighLight Structured Field */
		     memcpy(*netBufPtr,replyHighLight_LU1LU3printer,13);
		     *netBufPtr+=13;
		     *netCount+=13;

		     /* Send Query Reply Begin/End of File Field */
		     memcpy(*netBufPtr,replyBeginEndFile_LU1LU3printer,5);
		     *netBufPtr+=5;
		     *netCount+=5;

		     /* Send Query Reply Device Characteristics Field */
		     memcpy(*netBufPtr,replyDeviceCharacteristics_LU1printer,40);
		     *netBufPtr+=40;
		     *netCount+=40;
          }
         else if (luType == LU3)
          {
		     /* Set Structured Field Reply AID */
		     **netBufPtr = AIDSTRFIELD;
           *netBufPtr +=1;
		     *netCount+=1;

		     /* Send LU3 Query Reply Summary Structured Field */
		     memcpy(*netBufPtr,replySummary_LU3printer,11);
		     *netBufPtr+=11;
		     *netCount+=11;

		     /* Send LU3 Query Reply Usable Area Structured Field */
		     memcpy(*netBufPtr,replyUsable_LU3printer,23);
		     *netBufPtr+=23;
		     *netCount+=23;

		     /* Send Query Reply Character Set (SAA Support) */
		     memcpy(*netBufPtr,replyCharSet_LU1LU3printer,20);
		     *netBufPtr+=20;
		     *netCount+=20;

		     /* Send Query Reply HighLight Structured Field */
		     memcpy(*netBufPtr,replyHighLight_LU1LU3printer,13);
		     *netBufPtr+=13;
		     *netCount+=13;

		     /* Send Query Reply Modes Structured Field */
		     memcpy(*netBufPtr,replyModes_LU3printer,6);
		     *netBufPtr+=6;
		     *netCount+=6;

		     /* Send Query Reply Begin/End of File Field */
		     memcpy(*netBufPtr,replyBeginEndFile_LU1LU3printer,5);
		     *netBufPtr+=5;
		     *netCount+=5;

		     /* Send Query Reply Implicit Partition Structured Field */
 		     memcpy(*netBufPtr,replyImplicitPart_LU3printer,17);
		     *netBufPtr+=17;
		     *netCount+=17;
		    }
          beginEndOfJobStrFd = true;
          break;
        }
	    else return IDS_RINGBUFFERFULL;
      }

    case QUERYREPLYHDR:
     {
      if (luType == LU1)
       {
		  /* Set Structured Field Reply inbound FMH-1 */
		  memcpy(*netBufPtr,inboundFMH1,6);
        *netBufPtr+=6;
		  *netCount+=6;
        break;
       }
      else if (luType == LU3)
       {
		  /* Set Structured Field Reply AID */
	     **netBufPtr = AIDSTRFIELD;
        *netBufPtr +=1;
		  *netCount+=1;
        break;
       }
      else return INVALIDLUTYPE;
     }

    case QUERYSUMMARY:
     {
      if (luType == LU1)
       {
        /* Send LU1 Query Reply Summary Structured Field */
		  memcpy(*netBufPtr,replySummary_LU1printer,10);
		  *netBufPtr+=10;
		  *netCount+=10;
        beginEndOfJobStrFd = true;
        break;
       }
      else if (luType == LU3)
       {
	     /* Send LU3 Query Reply Summary Structured Field */
	     memcpy(*netBufPtr,replySummary_LU3printer,11);
	     *netBufPtr+=11;
	     *netCount+=11;
        beginEndOfJobStrFd = true;
        break;
       }
      else return INVALIDLUTYPE;
     }

    case QUERYUSABLE:
     {
      if (luType == LU1)
       {
		  /* Send LU1 Query Reply Usable Area Structured Field */
		  memcpy(*netBufPtr,replyUsable_LU1printer,23);
		  *netBufPtr+=23;
		  *netCount+=23;
        break;
       }
      else if (luType == LU3)
       {
		  /* Send LU3 Query Reply Usable Area Structured Field */
		  memcpy(*netBufPtr,replyUsable_LU3printer,23);
		  *netBufPtr+=23;
		  *netCount+=23;
        break;
       }
      else return INVALIDLUTYPE;
     }

    case QUERYCHARACTERSET:  // Same for LU1 and LU3
     {
      if ((luType == LU1) || (luType == LU3))
       {
	     /* Send Query Reply Character Set (SAA Support) */
	     memcpy(*netBufPtr,replyCharSet_LU1LU3printer,20);
	     *netBufPtr+=20;
	     *netCount+=20;
        break;
       }
      else return INVALIDLUTYPE;
     }

    case QUERYHIGHLIGHTING:  // Same for LU1 and LU3
     {
      if ((luType == LU1) || (luType == LU3))
       {
		  /* Send Query Reply HighLight Structured Field */
		  memcpy(*netBufPtr,replyHighLight_LU1LU3printer,13);
		  *netBufPtr+=13;
		  *netCount+=13;
        break;
       }
      else return INVALIDLUTYPE;
     }

    case QUERYREPLYMODES:  // LU3 Only
     {
      if (luType == LU3)
       {
		  /* Send Query Reply Modes Structured Field */
		  memcpy(*netBufPtr,replyModes_LU3printer,6);
		  *netBufPtr+=6;
		  *netCount+=6;
        break;
       }
      else return INVALIDLUTYPE;
     }

    case QUERYBEGINENDFILE:    // Same for LU1 and LU3
     {
      if ((luType == LU1) || (luType == LU3))
       {
		  /* Send Query Reply Begin/End of File Field */
		  memcpy(*netBufPtr,replyBeginEndFile_LU1LU3printer,5);
		  *netBufPtr+=5;
		  *netCount+=5;
        beginEndOfJobStrFd = true;
        break;
       }
      else return INVALIDLUTYPE;
     }

    case QUERYDEVICECHARACT:  // Only For LU1
     {
      if (luType == LU1)
       {
		  /* Send Query Reply Device Characteristics Field */
		  memcpy(*netBufPtr,replyDeviceCharacteristics_LU1printer,40);
		  *netBufPtr+=40;
		  *netCount+=40;
        break;
       }
      else return INVALIDLUTYPE;
     }

    case QUERYIMPLICITPART:  // LU3 Only
     {
      if (luType == LU3)
       {
		  /* Send Query Reply Implicit Partition Structured Field */
 		  memcpy(*netBufPtr,replyImplicitPart_LU3printer,17);
		  *netBufPtr+=17;
		  *netCount+=17;
        break;
       }
      else return INVALIDLUTYPE;
     }

    case QUERYREPLYNULL:
      {
       /*  Send Query Reply Null */
       memcpy(*netBufPtr,replyNull,4);
       netBufPtr+=4;
       netCount+=4;
       break;
      }

    default:  return DATANOTSENT;
  }
 return DATASENT;
}
