/*  Project Tec3270

	 SUBSYSTEM:    Tec3270.exe (Tec3270 application)
	 FILE:         alffprtn.h
	 AUTHOR:       Alcindo Ferreira Filho

	 OVERVIEW:

    ALFFPrinter, ALFFPrinterSetup, ALFFPrintDialog, ALFFPrintOut,
    Classes Implementation, Tec3270 printing function specific classes.

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

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

////////////////////////////////////////////////
//
// ALFFPrinter Object: TPrinter
//
//
ALFFPrinter::ALFFPrinter (TApplication* appl) : TPrinter(appl)
{
}

ALFFPrinter::~ALFFPrinter()
{
}


////////////////////////////////////////////////
//
// ALFFPrinterSetup Object: ALFFDialog
//
ALFFPrinterSetup::ALFFPrinterSetup (TWindow* parent, const int titleId,
                      ALFFPrinter* pPrt, ALFFPrtData* pData, bool remote)
                      : ALFFDialog(parent, IDD_ALFFPRINTERSETUP),
                        numberOfPrinters(0)
{
  pParent    = parent;
  pPrinter   = pPrt;
  prtData    = pData;
  remotePrinter = remote;

  tPrintData = &pPrinter->GetSetup();
  actualPrinter = new char[MAXPRINTERNAME];
  savedPrinter  = new char[MAXPRINTERNAME];

  // Get the Name Identifier of the Current Selected Printer
  SetPrinterName();
  strcpy(savedPrinter, actualPrinter);
  
  printersInfo = new BYTE[PRINTERINFOBUFFERSIZE];

  /* Create Messages Manager Object */
  pMsgs = new ALFFMsgs(this);

  /* Printer Description           */
  printerName = new TComboBox(this, IDC_ALFFPRINTERNAME);
  printerStatus = new TStatic(this, IDC_ALFFPRINTERSTATUS);
  printerType = new TStatic(this, IDC_ALFFPRINTERTYPE);
  printerLocal = new TStatic(this, IDC_ALFFPRINTERLOCAL);
  printerComments = new TStatic(this, IDC_ALFFPRINTERCOMMENTS);
  printerConfig = new TButton(this, IDC_ALFFPRINTERCONFIG);

  /* Printing Options Objects */
  printToFile = new TCheckBox(this, IDC_ALFFPRINTERTOFILE);
  printToSeparateFiles = new TCheckBox(this, IDC_ALFFPRINTERTOFILESEP);
  printerFileTit  = new TStatic(this, IDC_ALFFPRINTERTOFILETIT);
  printerFileName = new TEdit(this,IDC_ALFFPRINTERTOFILENAME);
  printerFileFind = new TButton(this, IDC_ALFFPRINTERTOFILEFIND);

  /* Temporary Fields to Save on OK button pressed */
  prtFileName = new char[MAXPATH];
  strcpy(prtFileName, prtData->printerFileName);
  prtToFile   = prtData->printToFile;
  prtToSeparateFiles =  prtData->printToSeparateFiles;

  if (titleId)
   {
    char tempTitle[STRINGMSGLEN+1];
    pMsgs->LoadString(titleId, tempTitle, STRINGMSGLEN);
    SetCaption(tempTitle);
   }
}

ALFFPrinterSetup::~ALFFPrinterSetup()
{
 delete [] printersInfo;
 delete [] actualPrinter;
 delete [] savedPrinter;

 delete pMsgs;
 delete printerName;
 delete printerStatus;
 delete printerType;
 delete printerLocal;
 delete printerComments;
 delete printerConfig;
 delete printToFile;
 delete printToSeparateFiles;
 delete printerFileTit;
 delete printerFileName;
 delete printerFileFind;

 // Temporary fields
 delete [] prtFileName;
}

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

 if (!LoadAllPrinters())
   pMsgs->Message(IDS_ALFFPRINTERNOPRINTERS,IDS_ALFFPRTTITLE);

 // Update Actual Printer Complete Info
 SetPrinterInfo();

 // Update Printer Setup Options
 if (prtToFile)
  {
   printToFile->Check();
   printerFileName->SetText(prtFileName);
   printToSeparateFiles->EnableWindow(true);
   printerFileTit->EnableWindow(true);
   printerFileName->EnableWindow(true);
   printerFileFind->EnableWindow(true);
  }
 else
  {
   printToFile->Uncheck();
   printerFileName->Clear();
   printToSeparateFiles->EnableWindow(false);
   printerFileTit->EnableWindow(false);
   printerFileName->EnableWindow(false);
   printerFileFind->EnableWindow(false);
  }
 //
 if (prtToSeparateFiles)
   printToSeparateFiles->Check();
 else printToSeparateFiles->Uncheck();
 //
}

bool
ALFFPrinterSetup::LoadAllPrinters()
{
  ulong   sizeBufferNeeded   = 0;
  numberOfPrinters   = 0;

  // Reset Printer Names ComboBox
  printerName->ClearList();

  // Get All Printers From This System Register
  bool success = ::EnumPrinters(
                   PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
                   NULL,
                   5,    // Common to Win95 and NT. Should try 4 ?
                   printersInfo,
                   PRINTERINFOBUFFERSIZE,
                   &sizeBufferNeeded,
                   &numberOfPrinters);

  // Update Printers Name Combo if they are successfully retrieved
  if (success && numberOfPrinters)
   {
    PRINTER_INFO_5*  prtInfo =  (PRINTER_INFO_5*) printersInfo;
    for (int i = 0; i < numberOfPrinters; i++)
     {
      printerName->AddString(prtInfo->pPrinterName);
      prtInfo++;
     }
    printerName->SetSelString(actualPrinter,0);
    return true;
   }
  else // Put just the initial printer name on ComboBox
   {
    pMsgs->LoadString(IDS_ALFFPRTNOTAVAIL,actualPrinter,MAXPRINTERNAME-1);
    strcpy(savedPrinter,actualPrinter);
    strcpy(actualPrinter,"");
    printerName->AddString(actualPrinter);
    printerName->SetSelIndex(0);
    return false;
   }
}

bool
ALFFPrinterSetup::SetPrinterInfo(char* newPrinterName)
{
#define MAXPRTLOCALINFO    50
 HANDLE prtHandle = 0;
 bool success = false;
 char text[STRINGMSGLEN+1];

 // Get Actual Printer Setup Info
 //tPrintData = &pPrinter->GetSetup();

 // If there is an new printer try to open it, else try the old one
 if (newPrinterName)
   success = ::OpenPrinter(newPrinterName, &prtHandle, 0);
 else success = ::OpenPrinter(actualPrinter, &prtHandle, 0);

 // If the Printer cannot be opened, set it not available ....
 if (!success)
  {
   // Set Actual Printer Info already available on TPrintDialog::Data
   pMsgs->LoadString(IDS_ALFFPRINTERNOTREADY, text, STRINGMSGLEN);

   // Set The New Printer Setup to no printer .......
   tPrintData->SetDevNames("","","");

   printerStatus->SetText(text);
   printerType->Clear();
   printerLocal->Clear();
   printerComments->Clear();
   return false;
  }

 // 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;

   // Set The New Printer Setup    .......
   tPrintData->SetDevNames(prtInfo2->pDriverName,prtInfo2->pPrinterName,
                           prtInfo2->pPortName);
   pPrinter->SetData(tPrintData);

   // Update the actual Printer Name to the New one
   strcpy(actualPrinter, prtInfo2->pPrinterName);

   // Update Printer Setup Dialog With New Info
   if (prtInfo2->Status == 0)
     pMsgs->LoadString(IDS_ALFFPRINTERREADY, text, STRINGMSGLEN);
   else pMsgs->LoadString(IDS_ALFFPRINTERNOTREADY, text, STRINGMSGLEN);
   printerStatus->SetText(text);
   printerType->SetText(prtInfo2->pDriverName);
   SetPrinterLocalInfo(prtInfo2->pPortName, MAXPRTLOCALINFO);
   printerComments->SetText(prtInfo2->pComment);

   // Return Successfully updated
   success = true;
  }
 else
  {
   // Not Ok:  Get Data from old printer ....
   pMsgs->LoadString(IDS_ALFFPRINTERNOTREADY, text, STRINGMSGLEN);
   printerStatus->SetText(text);
   if (!newPrinterName)
    {
     const DEVNAMES* prtNames = tPrintData->GetDevNames();
     if (prtNames)
      {
       LPTSTR pPrinterDriver = (LPTSTR) prtNames+prtNames->wDriverOffset;
       LPTSTR pPrinterPort = (LPTSTR) prtNames+prtNames->wOutputOffset;
       printerType->SetText(pPrinterDriver);
       SetPrinterLocalInfo(pPrinterPort, MAXPRTLOCALINFO);
      }
     else
      {
       printerType->SetText("");
       SetPrinterLocalInfo("", MAXPRTLOCALINFO);
      }
     printerComments->Clear();
    }
   else
    {
     strcpy(actualPrinter, newPrinterName);
     printerType->Clear();
     printerLocal->Clear();
     printerComments->Clear();
    }
   success = false;
  }

 return success;
}

bool
ALFFPrinterSetup::SetPrinterLocalInfo(char* lName, int maxLen)
{
 string temp = lName;
 char*   localName;
 localName = new char[maxLen+4];
 int nameLen = strlen(lName);
 bool reduced;
 if (nameLen > maxLen)
  {
   strcpy (localName, temp.substr(0,maxLen).c_str());
   strcat (localName, "...");
   reduced = true;
  }
 else
  {
   strcpy (localName, lName);
   reduced = false;
  }
 printerLocal->SetText(localName);
 delete [] localName;

 return reduced;
}

void
ALFFPrinterSetup::CmOk()
{
 const DEVNAMES* prtNames = pPrinter->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 Printer to File Options */
 strcpy(prtData->printerFileName, prtFileName);
 prtData->printToFile = prtToFile;
 prtData->printToSeparateFiles = prtToSeparateFiles;

 /* Save Actual Printer Options To INI File */
 char iniSection[21];
 if (remotePrinter)
     strcpy(iniSection,"REMOTE PRINTER DEVICE");
 else strcpy(iniSection,"SCREEN 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);
 iniFile->WriteString(iniSection,"PRINTERFILENAME",prtData->printerFileName);
 iniFile->WriteInt(iniSection,"PRINTTOFILE",prtData->printToFile);
 iniFile->WriteInt(iniSection,"PRINTTOSEPARATEFILES",prtData->printToSeparateFiles);

 ALFFDialog::CmOk();
}

void
ALFFPrinterSetup::CmCancel()
{
 SetPrinterInfo(savedPrinter);
 ALFFDialog::CmCancel();
}

void
ALFFPrinterSetup::CmHelp()
{
 /* Get the Application IniFile Pointer  */
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
 ALFFHelp* helpFile = theApp->GetHelpFile();
 HWND helpWin = helpFile->ShowHelp(HH_HELP_CONTEXT, IDH_HELP_PRINT_SETUP, IDH_POPUP_WINDOW);
 if (!helpWin)
   pMsgs->Message(IDS_ALFFHELPNOTAVAIL, IDS_ALFFSESSTITLE);
}

void
ALFFPrinterSetup::SetPrinterName()
{
 const DEVNAMES* prtNames = tPrintData->GetDevNames();
 if (prtNames)
   strcpy(actualPrinter, (LPTSTR) prtNames+prtNames->wDeviceOffset);
 else strcpy(actualPrinter, "");
}

LRESULT
ALFFPrinterSetup::EvCommand(uint controlId, HWND , uint notifyCode)
{
 /*
  * controlId is the control identifier that is related to some
  * option on Print Dialog.
  */
 int   selIndex = -1;
 WIN32_FIND_DATA  fileInfo;
 char* openPrtFileTitle;
 char  prtFName[STRINGMSGLEN+1];
 char  prtFExt[STRINGMSGLEN+1];
 char  newPrtName[MAXPRINTERNAME];

 switch (controlId)
  {
	case			             IDOK: CmOk();
									        break;

	case		            IDCANCEL: CmCancel();
									       break;

	case                   IDHELP: CmHelp();
									       break;

   case      IDC_ALFFPRINTERNAME: if (notifyCode == CBN_SELCHANGE)
                                   {
                                    selIndex = printerName->GetSelIndex();
                                    printerName->GetString(newPrtName,selIndex);
                                    SetPrinterInfo(newPrtName);
                                   }
											 break;

	case    IDC_ALFFPRINTERCONFIG: pPrinter->Setup(this);
                                  tPrintData = &pPrinter->GetSetup();
                                  SetPrinterName();
									       SetPrinterInfo(actualPrinter);
                                  printerName->SetSelString(actualPrinter,0);
									       break;

	case    IDC_ALFFPRINTERTOFILE: if (prtToFile)
											  {
											   printToFile->Uncheck();
											   prtToFile = false;
                                    printerFileName->Clear();
                                    printToSeparateFiles->EnableWindow(false);
                                    printerFileTit->EnableWindow(false);
                                    printerFileName->EnableWindow(false);
                                    printerFileFind->EnableWindow(false);
											  }
											 else
											  {
												printToFile->Check();
												prtToFile = true;
                                    printToSeparateFiles->EnableWindow(true);
                                    printerFileTit->EnableWindow(true);
                                    printerFileFind->EnableWindow(true);
												if (strlen(prtFileName))
												 {
												  printerFileName->Clear();
												  printerFileName->Insert(prtFileName);
												 }
                                    printerFileName->EnableWindow(true);                                     
											  }
                                  break;//    CheckBox

	case IDC_ALFFPRINTERTOFILENAME:if (notifyCode == EN_KILLFOCUS)
											  {
												printerFileName->GetText(prtFileName,MAXPATH-1);
                                    if (strlen(prtFileName))
                                     {
												   if (FindFirstFile (prtFileName,&fileInfo) !=  INVALID_HANDLE_VALUE)
												    {
												     /* The Printer File Name is already on disk */
												     if (pMsgs->Message(IDS_ALFFPRINTERTOFILEEXIST,
																	  IDS_ALFFPRTTITLE,true) == IDOK)
													      printerFileName->SetFocus();
													  else
													   {
														 prtFileName[0]=NULL;
														 printerFileName->Clear();
													   }
                                        }
												 }
                                    else
                                     {
                                      if (pMsgs->Message(IDS_ALFFPRINTERBADFILENAME,
																	  IDS_ALFFPRTTITLE,true) == IDCANCEL)
                                       printerFileName->SetFocus();
                                      else
													   {
														 prtFileName[0]=NULL;
														 printerFileName->Clear();
													   }
                                     }
											  }
                                  break; //   Nome do Arquivo Printer

	case IDC_ALFFPRINTERTOFILESEP: if (prtToSeparateFiles)
											  {
											   printToSeparateFiles->Uncheck();
											   prtToSeparateFiles = false;
											  }
											 else
											  {
												printToSeparateFiles->Check();
												prtToSeparateFiles = true;
											  }
                                  break; // CheckBox
                                  
	case IDC_ALFFPRINTERTOFILEFIND:if (notifyCode == BN_CLICKED)
											 {
											  openPrtFileTitle = new char[STRINGMSGLEN];
											  pMsgs->LoadString(IDS_ALFFPRINTERFILE,prtFName,STRINGMSGLEN);
											  pMsgs->LoadString(IDS_ALFFPRINTERFILEEXT,prtFExt,STRINGMSGLEN);
											  TOpenSaveDialog::TData
											  fileData(OFN_HIDEREADONLY | OFN_SHOWHELP,
														  prtFName,
														  0,0,
														  prtFExt);
											  pMsgs->LoadString(IDS_ALFFPRTTITLE,
																	  openPrtFileTitle,STRINGMSGLEN-1);
											  if (TFileOpenDialog(this, fileData,0,
														  openPrtFileTitle).Execute() == IDOK)
												{
													if (fileData.FileName[0])
													 {
													  /* Printer File Supplied */
													  strcpy(prtFileName,fileData.FileName);
													  printerFileName->Clear();
													  printerFileName->Insert(prtFileName);
													 }
												}
                                   delete [] openPrtFileTitle;
											 }

                                  break;//   Procurar Arquivo

	default             : char msgString[128];
								 sprintf(msgString,"ID = %i,  COD = %i",
														 controlId, notifyCode);
								 pMsgs->StrMessage(msgString,IDS_ALFFPRTINVOPTION,IDS_ALFFPRTTITLE);
								 break;
  }

 return 1L;
}


////////////////////////////////////////////////
//
// ALFFPrintDialog Object: ALFFDialog
//
//
ALFFPrintDialog::ALFFPrintDialog(TWindow* Parent,
											ALFFPrinter* pPrt,
											ALFFPrtData* prtDta,
											TResId resId)
			: ALFFDialog(Parent, resId)
{
  pdParent   = Parent;
  tPrintData = &pPrt->GetSetup();
  pPrinter   = pPrt;
  prtData    = prtDta;

  /* Create Messages Manager Object */
  pMsgs = new ALFFMsgs(this);

  /* Printing Range Objects        */
  prtRngGroup = new TGroupBox(this, IDC_ALFFPRTRNGGROUP);
  prtAllPg = new TRadioButton(this, IDC_ALFFPRTALLPG,  prtRngGroup);
  prtSelPg = new TRadioButton(this, IDC_ALFFPRTSELPG,  prtRngGroup);
  prtFromPg = new TEdit(this, IDC_ALFFPRTFROMPAGE);
  prtFromPg->SetValidator(new TFilterValidator("0-9"));
  prtToPg   = new TEdit(this, IDC_ALFFPRTTOPAGE);
  prtToPg->SetValidator(new TFilterValidator("0-9"));
  txtFromPg = new TStatic(this,IDC_ALFFPRTTXTFROM);
  txtToPg   = new TStatic(this,IDC_ALFFPRTTXTTO);

  /* Printer Description           */
  printerName = new TStatic(this, IDC_ALFFPRTPRINTER);

  /* Print Selection Group Objects */
  printGroup = new TGroupBox(this, IDC_ALFFSELGROUP);
  prtScreen  = new TRadioButton(this, IDC_ALFFPRTALLSCR,  printGroup);
  prtSelTxt  = new TRadioButton(this, IDC_ALFFPRTSELTXT,  printGroup);

  /* Print Page  Group Objects     */
  pageGroup = new TGroupBox(this, IDC_ALFFPRTPAGE);
  oneScrPage = new TRadioButton(this, IDC_ALFFPRTONESCR,  pageGroup);
  maxScrPage = new TRadioButton(this, IDC_ALFFPRTMAXSCR,  pageGroup);

  /* Print/Store Group Objects     */
  prtStorGroup = new TGroupBox(this, IDC_ALFFPRTOPTIONS);
  storeScr  = new TRadioButton(this, IDC_ALFFPRTSTORE,  prtStorGroup);
  printStor = new TRadioButton(this, IDC_ALFFPRTIMMSTOR,  prtStorGroup);
  printScr  = new TRadioButton(this, IDC_ALFFPRTIMMED,  prtStorGroup);
  printClr  = new TRadioButton(this, IDC_ALFFPRTCLEAR,  prtStorGroup);

  /* Printing Options Objects      */
  hdrPage    = new TCheckBox(this,IDC_ALFFPRTHDR);
  hdrShowText = new TStatic(this,IDC_ALFFPRTHDRTEXT);
  prtColor    = new TCheckBox(this,IDC_ALFFPRTCOLOR);
  numCopies  = new TEdit(this,IDC_ALFFPRTCOPIES);
  numCopies->SetValidator(new TFilterValidator("0-9"));
}

ALFFPrintDialog::~ALFFPrintDialog()
{
 delete prtRngGroup;
 delete prtAllPg;
 delete prtSelPg;
 delete prtFromPg;
 delete prtToPg;
 delete txtFromPg;
 delete txtToPg;
 delete printerName;
 delete printGroup;
 delete prtScreen;
 delete prtSelTxt;
 delete pageGroup;
 delete oneScrPage;
 delete maxScrPage;
 delete prtStorGroup;

 delete storeScr;
 delete printStor;
 delete printScr;
 delete printClr;

 delete hdrPage;
 delete hdrShowText;
 delete prtColor;
 delete numCopies;

 delete pMsgs;
}

void
ALFFPrintDialog::SetupWindow()
{
  ALFFDialog::SetupWindow();
  SetPrinterName();

  /* Set Last used Initial and Final Pages */
  char text[6];
  itoa(prtData->FromPage,text,10);
  prtFromPg->Insert(text);
  itoa(prtData->ToPage,text,10);
  prtToPg->Insert(text);

  /* Set Last used Options */
  if (prtData->printAllPages)
	 prtAllPg->Check();
	else prtSelPg->Check();
  if (prtData->printWholeScr)
	 prtScreen->Check();
	else prtSelTxt->Check();
  if (prtData->oneScrPerPage)
	 oneScrPage->Check();
	else maxScrPage->Check();

  switch (prtData->printOption)
  {
	case    PO_STORESCR:  storeScr->Check();
								 break;
	case PO_PRINTSTORED:  printStor->Check();
								 break;
	case    PO_PRINTSCR:	 printScr->Check();
								 break;
	case PO_CLEARSTORED:  printClr->Check();
								 break;
					default:  printScr->Check();
								 break;
	}
  if (prtData->hdrText)
	 {
	  hdrActive = true;
	  hdrShowText->SetText(prtData->hdrText);
	  hdrPage->Check();
	 }
	 else
	  {
      hdrActive = false;
		hdrShowText->Clear();
		hdrPage->Uncheck();
	  }
  numCopies->Clear();
  if (!tPrintData->Copies)
	  tPrintData->Copies = 1;
  char txtCopies[16];
  itoa(tPrintData->Copies, txtCopies, 10);
  numCopies->Insert(txtCopies);

  if (prtData->printOnColor)
	 prtColor->Check();
  else prtColor->Uncheck();

}

bool
ALFFPrintDialog::SetPrinterLocalInfo(char* prtOutInfo, const char* lName, int maxLen)
{
 string temp = lName;
 char*   localName;
 localName = new char[maxLen+4];
 int nameLen = strlen(lName);
 bool reduced;
 if (nameLen > maxLen)
  {
   strcpy (localName, temp.substr(0,maxLen).c_str());
   strcat (localName, "...");
   strcpy(prtOutInfo,localName);
   reduced = true;
  }
 else
  {
   strcpy (prtOutInfo, lName);
   reduced = false;
  }
 delete [] localName;

 return reduced;
}

void
ALFFPrintDialog::SetPrinterName()
{
#define MAXPRTNAMESIZE  35
  char prtName[256];
  char tempChar[STRINGMSGLEN];
  string temp;
  prtName[0] = NULL;
  if (prtData)
   {
    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)
          {
           strcpy (prtName, temp.substr(0,MAXPRTNAMESIZE).c_str());
           strcat (prtName, "...");
          }
        else strcpy (prtName, temp.substr(0,slashPos).c_str());
        strcat (prtName, "\r\n");
        strcat (prtName, temp.substr(slashPos+1).c_str());
      }
    else strcpy(prtName, temp.c_str());

    /* Next Line */
    strcat(prtName,"\r\n");

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

    if (prtData->defaultPrt)
     {
      strcat(prtName,"\r\n");
      pMsgs->LoadString(IDS_ALFFPRTDEFAULTPRINTER, tempChar, STRINGMSGLEN);
      strcat(prtName,tempChar);
     }
   }
  else pMsgs->LoadString(IDS_ALFFPRTNOTAVAIL, prtName, STRINGMSGLEN);

  printerName->SetText(prtName);
}

LRESULT
ALFFPrintDialog::EvCommand(uint controlId, HWND , uint notifyCode)
{
 char nCopies[8];
 char pgNum[8];
 char *hdrPrompt;
 char *hdrTitle;
 char msgString[128];
 /*
  * controlId is the control identifier that is related to some
  * option on Print Dialog.
  */

 switch (controlId)
  {
	case			      IDOK: CmOk();
									break;

	case		     IDCANCEL: ALFFDialog::CmCancel();
									break;

	case 		     IDCONFIG: ALFFPrinterSetup(GetApplication()->GetMainWindow(),
                              IDS_ALFFPRINTOUTTITLE,
                              pPrinter, prtData, false).Execute();
									SetPrinterName();
									break;

	case            IDHELP: CmHelp();
									break;

	/* Selecting Print All Pages or just Selected Pages */
	case  IDC_ALFFPRTRNGGROUP: switch(notifyCode)
										{
										  case  IDC_ALFFPRTALLPG: prtData->printAllPages = true;
																		  prtToPg->EnableWindow(false);
																		  txtToPg->EnableWindow(false);
																		  prtFromPg->EnableWindow(false);
																		  txtFromPg->EnableWindow(false);
																		  break;
										  case  IDC_ALFFPRTSELPG: prtData->printAllPages = false;
																		  prtToPg->EnableWindow(true);
																		  txtToPg->EnableWindow(true);
																		  prtFromPg->EnableWindow(true);
																		  txtFromPg->EnableWindow(true);
																		  break;
										  default      : pMsgs->Message(IDS_ALFFPRTERROR,IDS_ALFFPRTTITLE);
															  break;
										}
										break;


	/* Selecting Print All Screen or just Selected Text */
	case  IDC_ALFFSELGROUP: switch(notifyCode)
									{
									 case IDC_ALFFPRTALLSCR: prtData->printWholeScr = true;
																	 break;
									 case IDC_ALFFPRTSELTXT: prtData->printWholeScr = false;
																	 break;
									 default      : pMsgs->Message(IDS_ALFFPRTERROR,IDS_ALFFPRTTITLE);
														 break;
									}
									break;

	/* Selecting one or two screens per page */
	case   IDC_ALFFPRTPAGE: switch(notifyCode)
									{
									 case IDC_ALFFPRTONESCR: prtData->oneScrPerPage = true;
																	 break;
									 case IDC_ALFFPRTMAXSCR: prtData->oneScrPerPage = false;
																	 break;
									 default      : pMsgs->Message(IDS_ALFFPRTERROR,IDS_ALFFPRTTITLE);
														 break;
									}
									break;

	/* Selecting one of the four printing options */
	case   IDC_ALFFPRTOPTIONS: switch(notifyCode)
										{
										 case  IDC_ALFFPRTSTORE: prtData->printOption
																				= PO_STORESCR;
																		 break;
										 case  IDC_ALFFPRTIMMSTOR: prtData->printOption
																				= PO_PRINTSTORED;
																		 break;
										 case  IDC_ALFFPRTIMMED: prtData->printOption
																				= PO_PRINTSCR;
																		 break;
										 case  IDC_ALFFPRTCLEAR: prtData->printOption
																				= PO_CLEARSTORED;
																		 break;
										default      : pMsgs->Message(IDS_ALFFPRTERROR,IDS_ALFFPRTTITLE);
															break;
										}
										break;

	/* Print Range Group Commands                    */
	case IDC_ALFFPRTALLPG : prtData->printAllPages = true;
									prtToPg->EnableWindow(false);
									txtToPg->EnableWindow(false);
									prtFromPg->EnableWindow(false);
									txtFromPg->EnableWindow(false);
									break;
	case IDC_ALFFPRTSELPG : prtData->printAllPages = false;
									prtToPg->EnableWindow(true);
									txtToPg->EnableWindow(true);
									prtFromPg->EnableWindow(true);
									txtFromPg->EnableWindow(true);
									break;
	case IDC_ALFFPRTFROMPAGE: if (notifyCode == EN_KILLFOCUS)
										{
										 prtFromPg->GetText(pgNum,6);
										 prtData->FromPage = atoi(pgNum);
										}
									  break;
	case   IDC_ALFFPRTTOPAGE: if (notifyCode == EN_KILLFOCUS)
										{
										 prtToPg->GetText(pgNum,6);
										 prtData->ToPage = atoi(pgNum);
										}
									  break;

	case IDC_ALFFPRTALLSCR: prtData->printWholeScr = true;
									break;
	case IDC_ALFFPRTSELTXT: prtData->printWholeScr = false;
									break;

	case IDC_ALFFPRTONESCR: prtData->oneScrPerPage = true;
									break;
	case IDC_ALFFPRTMAXSCR: prtData->oneScrPerPage = false;
									break;

	case  IDC_ALFFPRTSTORE: prtData->printOption	= PO_STORESCR;
									break;

	case  IDC_ALFFPRTIMMSTOR: prtData->printOption = PO_PRINTSTORED;
									  break;

	case  IDC_ALFFPRTIMMED: prtData->printOption	= PO_PRINTSCR;
									break;

	case  IDC_ALFFPRTCLEAR: prtData->printOption	= PO_CLEARSTORED;
									break;

	case    IDC_ALFFPRTHDR: if (!hdrActive)
									 {
									  if (!prtData->hdrText)
										{
										 prtData->hdrText = new char[HDRTEXTLEN+1];
										 prtData->hdrText[0] = NULL;
										}
									  hdrPrompt = new char[STRINGMSGLEN];
									  hdrTitle = new char[TITLELEN];
									  pMsgs->LoadString(IDS_ALFFPRTHDRPROMPT, hdrPrompt, STRINGMSGLEN-1);
									  pMsgs->LoadString(IDS_ALFFPRTHDRTITLE, hdrTitle, STRINGMSGLEN-1);
									  if (ALFFInputDialog(this, hdrTitle, hdrPrompt,
															 prtData->hdrText, HDRTEXTLEN).Execute()
										  != IDOK)
										{
										 hdrPage->Uncheck();
										}
										else
										  {
											hdrShowText->SetText(prtData->hdrText);
											hdrActive = true;
										  }
									  delete [] hdrPrompt;
									  delete [] hdrTitle;
									 }
									 else
									  {
										hdrShowText->Clear();
                              hdrActive = false;
									  }
									break;

	case   IDC_ALFFPRTCOLOR: /* Use colors on printing screens */
                           if (prtData->printOnColor)
                            {
                              prtData->printOnColor = false;
                              prtColor->Uncheck();
                            }
                           else
                            {
                              prtData->printOnColor = true;
                              prtColor->Check();
                            }
									break;

	case IDC_ALFFPRTCOPIES: numCopies->GetText(nCopies,6);
									prtData->Copies = atoi(nCopies);
									break;

	default             : sprintf(msgString,"ID = %i,  COD = %i",
														 controlId, notifyCode);
								 pMsgs->StrMessage(msgString,IDS_ALFFPRTINVOPTION,IDS_ALFFPRTTITLE);
								 break;
  }

 return 1L;
}

void
ALFFPrintDialog::CmOk()
{
 bool dlgError = false;
 if ((!prtData->printAllPages)
  && ((prtData->FromPage < prtData->MinPage)
  || (prtData->ToPage > prtData->MaxPage)
  || (prtData->FromPage > prtData->ToPage)))
  dlgError = true;
 if (!dlgError)
  {
	if (prtData->printToFile)
	  tPrintData->Flags |= PD_PRINTTOFILE;
	 else tPrintData->Flags &= ~PD_PRINTTOFILE;
	if (prtData->printAllPages)
	 {
	  tPrintData->Flags |= PD_NOPAGENUMS;
	  tPrintData->Flags |= PD_ALLPAGES;
	 }
	 else
	  {
		tPrintData->Flags |= PD_PAGENUMS;
		tPrintData->Flags &= ~PD_ALLPAGES;
	  }
	tPrintData->MaxPage  = prtData->MaxPage;
	tPrintData->MinPage  = prtData->MinPage;
	tPrintData->FromPage = prtData->FromPage;
	tPrintData->ToPage = prtData->ToPage;
	tPrintData->Copies = prtData->Copies;

	/* Setup prtData->hdrText according hdr is or not active */
	if (!hdrActive && prtData->hdrText)
	 {
		delete [] prtData->hdrText;
		prtData->hdrText = NULL;
	 }

	ALFFDialog::CmOk();
  }
  else
	{
	 pMsgs->Message(IDS_ALFFPRTSELPGERR,IDS_ALFFPRTTITLE);
	 prtFromPg->SetFocus();
	}
}

void
ALFFPrintDialog::CmHelp()
{
 /* Get the Application IniFile Pointer  */
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
 ALFFHelp* helpFile = theApp->GetHelpFile();

 HWND helpWin = helpFile->ShowHelp(HH_HELP_CONTEXT, IDH_HELP_PRINT_SCREEN, IDH_POPUP_WINDOW);
 if (!helpWin)
   pMsgs->Message(IDS_ALFFHELPNOTAVAIL, IDS_ALFFSESSTITLE);

}


////////////////////////////////////////////////
//
// ALFFPrintOut Object: TPrintout
//
//
/* PrintOut Constructor */
ALFFPrintOut::ALFFPrintOut (ALFFPrinter *printer,
                            ALFFPrinterBuffer* prtBuf,
									 const char far *title,
									 TWindow* window,
									 ALFFPrtData* prtDta,
                            ALFFConnData* cnnData,
									 bool scale ) : TPrintout(title)
{
  /* Initialize some printout controls */
  Printer = printer;
  printerBuf = prtBuf;
  Window = window;
  Scale = scale;
  prtData  = prtDta;
  connData = cnnData;
  MapMode = MM_LOENGLISH;
  hFont = NULL;

  remotePrtFont = NULL;
  printedLines = 0;
}

ALFFPrintOut::~ALFFPrintOut()
{
  if (remotePrtFont != NULL)
     delete remotePrtFont;
}

void
ALFFPrintOut::SetPrintParams(TPrintDC* dc, TSize pageSize)
{
  TPrintout::SetPrintParams(dc, pageSize);
}

// Do not enable page range in the print dialog since only one page is
// available to be printed
//
void
ALFFPrintOut::GetDialogInfo (int& minPage, int& maxPage, int& selFromPage, int& selToPage)
{
  minPage = prtData->MinPage;
  maxPage = prtData->MaxPage;
  selFromPage = prtData->FromPage;
  selToPage = prtData->ToPage;
}

void
ALFFPrintOut::BeginPrinting ()
{
	 /* Repaginate Printer Buffer to Get Correct Page Layout */
	 //Paginate();

	 /* Update TPrintDialog::TData from prtData struct */
	 TPrintDialog::TData& printerData = Printer->GetSetup();
	 printerData.FromPage = prtData->FromPage;
	 printerData.ToPage = prtData->ToPage;
	 printerData.MinPage = prtData->MinPage;
	 printerData.MaxPage = prtData->MaxPage;
	 printerData.Copies  = prtData->Copies;

    /* Set the DC to the Correct Map Mode */
	 SetMappingMode(*DC);
}

void
ALFFPrintOut::EndPrinting()
{
 DC->RestoreFont();
}

void
ALFFPrintOut::PrintPage (int page, TRect&, unsigned)
{
    // Lines from left
    int xOffset = prtData->leftMargin;
    // Lines from top
    int yOffset = prtData->topMargin;

    bool printError = false;

	 /* Get and Set the Printer Font */
    if (remotePrtFont)
     {
      DC->SelectObject(*remotePrtFont);
     }
    else DC->SelectObject(*prtData->currPrtFont);

	 /* Set Printer Font Metrics */
	 TEXTMETRIC tm;
	 DC->GetTextMetrics(tm);
	 int fCharHeight = tm.tmHeight + tm.tmExternalLeading;
	 int  interScrSpace = prtData->interScrSpace;


	 TPrintDialog::TData& printerData = Printer->GetSetup();
	 int fromPg = printerData.FromPage;
	 int toPg = printerData.ToPage;

	 printerData.FromPage = page;
	 printerData.ToPage = page;


    /* Set color printing option */
    bool printerOnColor;
    if (connData)
     printerOnColor = connData->printerOnColor;
    else printerOnColor = prtData->printOnColor;

	 /*
	  * Print the Current Page with corresponding screens
	  */

	 /* If there is any header text then print it  */
	 if (!remotePrtFont && (prtData->fdHdr))
	  {
      bool Error = false;

		/* Some auxiliary variables to facilitate access to header text*/
		char* hdrText = prtData->fdHdr->fdText;
		int   hdrLen  = strlen(hdrText);
		int   hdrLineSize = prtData->fdHdr->scrLineSize;
		int   hdrSize;

		PrtField* fdPag;
		fdPag = new PrtField();

		/* Format Page Number Text */
		fdPag->fdText      = new char[PAGETEXTLEN+1];
		sprintf(fdPag->fdText,"Página: %i",page);
		fdPag->fdFormatted = false;
		fdPag->fdPosition.x  = hdrLineSize + 2;
		fdPag->fdPosition.y  = 0;     // Skip one line from top
      if (!printerOnColor)
       {
		  fdPag->fdTextColor = prtData->fdHdr->fdTextColor;
		  fdPag->fdBkgdColor = prtData->fdHdr->fdBkgdColor;
       }
      else
       {
		  fdPag->fdTextColor = prtData->fdHdr->fdTextColor = TColor(0,0,200); //Blue
		  fdPag->fdBkgdColor = prtData->fdHdr->fdBkgdColor = TColor::White;
       }

		/* Page Sub Field */
		fdPag->scrLineSize = hdrLineSize + PAGETEXTLEN + 1;
		fdPag->scrPrtBegLine  = 0;
		fdPag->scrPrtEndLine = 0;
		fdPag->scrNumber   = 0;


		if (hdrLen < hdrLineSize)
		  hdrSize = hdrLineSize;
		else hdrSize = hdrLen;

		/* Create an Header Image for building its lines for printing */
		char* hdrImage = new char[hdrSize+PAGETEXTLEN+2];
		memset(hdrImage,' ',hdrSize+PAGETEXTLEN+2);


      /* Header Print Field */
		printError = PrintField(*DC,
									  prtData->fdHdr,
									  TColor::White,
									  prtData->fdHdr->scrLineSize,
									  prtData->fdHdr->scrPrtBegLine,
									  prtData->fdHdr->scrPrtEndLine,
				                 xOffset,
				                 yOffset);

      if (!printError)
       {
		  /* Print Page Number Text */
		  printError = PrintField(*DC,
										  fdPag,
										  TColor::White,
										  fdPag->scrLineSize,
										  fdPag->scrPrtBegLine,
										  fdPag->scrPrtEndLine,
					                 xOffset,
					                 yOffset);
       }
      /* Update yOffset to consider Header lines and 1 line of space between
       *  the header and first screen - Valid only for Printing Screens
       * Remote Printers does not have Header Lines nor Page Numbers managed
       * by this program.
       */
      if (hdrLen > hdrLineSize)
        yOffset += 3;
      else
        yOffset += 2;

		delete fdPag;
		delete [] hdrImage;
	  }

	 /* Print Field direct displaying */
	 int scrNum = 0;
	 bool endPrinting = false;

	 /* Printing all selected fields */
	 int numFields = printerBuf->GetItemsInContainer();
	 int i = 0;
    int scrPageOffset = 0;
    int firstPrintedLine = -1;

	 bool printField;
	 while (!endPrinting && !printError)
	 {
	  /*
		* Get a field from Printer Buffer
		*/
	  if (i < numFields)
		{
		 printField = false;
		 fdPrint = &(*printerBuf)[i++];
		 if (prtData->printOption == PO_PRINTSCR)
		  {
			if (fdPrint->scrNumber == prtData->numScreens)
			  printField = true;
		  }
		 else if (fdPrint->prtPageNumber == page)
				  printField = true;

       // PRINTBUFFER's field to field printing
       if (printField)
        {
         /* Set first printed line */
         if (firstPrintedLine == -1)
           firstPrintedLine = fdPrint->fdPosition.y;
         else if (firstPrintedLine > fdPrint->fdPosition.y)
           firstPrintedLine = fdPrint->fdPosition.y;
			/* Print Field direct displaying it */
			scrPageOffset = prtData->scrPageOffset + fdPrint->scrPrtPageOffset;
         if (!printerOnColor)
          {
			  fdPrint->fdTextColor = TColor::Black;
			  fdPrint->fdBkgdColor = TColor::White;
          }
			printError = PrintField(*DC,
											  fdPrint,
											  TColor::White,
											  fdPrint->scrLineSize,
											  fdPrint->scrPrtBegLine,
											  fdPrint->scrPrtEndLine,
					                    xOffset,
											  scrPageOffset+yOffset);
        }

		}
	  else endPrinting = true;

	 } // while (!endPrinting)

    // Number of printed Lines
    printedLines += fdPrint->fdPosition.y - firstPrintedLine + 1;
    firstPrintedLine = -1;

	 printerData.FromPage = fromPg;
	 printerData.ToPage = toPg;

	 /* if any error ocurred it should be reported */
	 if (printError)
		throw TXPrinter();
}

bool
ALFFPrintOut::HasPage (int pageNumber)
{
 TPrintDialog::TData &printerData = Printer->GetSetup();
 return (pageNumber >= printerData.MinPage)
			&& (pageNumber <= printerData.MaxPage);
}

void
ALFFPrintOut::SetMappingMode(TDC& dc)
{
 dc.SetMapMode(MM_LOENGLISH);
 dc.SetMapMode(MM_ANISOTROPIC);
 TSize ext = dc.GetWindowExt();
 ext.cy = -ext.cy;
 dc.SetWindowExt(ext);
}

void
ALFFPrintOut::Paginate()
{
 LOGFONT logFontData;
 TEXTMETRIC tm;


 Tec3270App *theApp = TYPESAFE_DOWNCAST(Window->GetApplication(), Tec3270App);

 TPrintDialog::TData& data = Printer->GetSetup();

 /*
  * Create the printer DC. If it fails, let the print dialog report the
  * error for us and allow the user to sort it out.
  */
 try
	{
	 TIC prnDC(data.GetDriverName(),
				  data.GetDeviceName(),
				  data.GetOutputName(),
				  data.GetDevMode());

	 /* Set the Map Mode for the printer DC */
	 SetMappingMode(prnDC);

    /* Set up phisical page height and width */
	 int pageHeight = (prnDC.GetDeviceCaps(VERTSIZE) / 0.254);
	 int pageWidth = (prnDC.GetDeviceCaps(HORZSIZE) / 0.254);

	 /* Reset the Remote Printer Font to none */
    if (remotePrtFont)
     {
      delete remotePrtFont;
      remotePrtFont = 0;
     }

    /* Set up  char font metrics */
    if (connData)
     {
       prtData->currPrtFont->GetObject(logFontData);
       if (connData->printerDimen)
        {
         if (connData->printerLinePerPage && connData->printerCharPerLine)
          {
           logFontData.lfHeight = -((pageHeight / connData->printerLinePerPage));
           logFontData.lfWidth  = (pageWidth / connData->printerCharPerLine);
           remotePrtFont = new TFont(&logFontData);
           prnDC.SelectObject(*remotePrtFont);
          }
         else prnDC.SelectObject(*prtData->currPrtFont);
        }
       else if ((connData->printerLinePerInch != 0) &&
                (connData->printerCharPerInch != 0) )
             {
        		  logFontData.lfHeight = -((72/connData->printerLinePerInch)+1);
      		  logFontData.lfWidth  = 	 (72/connData->printerCharPerInch)+1;
              remotePrtFont = new TFont(&logFontData);
              prnDC.SelectObject(*remotePrtFont);
             }
       else prnDC.SelectObject(*prtData->currPrtFont);
     }
    else prnDC.SelectObject(*prtData->currPrtFont);


    /* Get Actual Font Metrics */
  	 prnDC.GetTextMetrics(tm);

	 fCharWidth = tm.tmAveCharWidth;
	 fCharHeight = tm.tmHeight+tm.tmExternalLeading;

    // Calculate Actual Page Height
    pageHeight -= (prtData->topMargin*fCharHeight);

	 /* Calculate number of font lines per page */
	 int linesPerPage = pageHeight/fCharHeight;

    if (remotePrtFont)
     {
      /* Checking pageHeight with MPL */
      if (connData->printerLinePerPage < linesPerPage )
       linesPerPage = connData->printerLinePerPage;
     }

    // Bottom margin must be respected.
    if (linesPerPage >  prtData->bottomMargin )
      linesPerPage = prtData->bottomMargin;

	 int interScrSpace = prtData->interScrSpace;
	 /*
	  * If there is an printerBuf available then
	  * Do calculate printer page number of each screen on printer buffer
	  * Remember that each screen could have different lines quantity
	  */

	 int pageNum = 1;

	 if (printerBuf)
	  {
      int itemsInContainer = printerBuf->GetItemsInContainer();
      if (itemsInContainer)
       {
        PrtField* fdPrint = &(*printerBuf)[0];
		  int scrNum = fdPrint->scrNumber;
        int scrPageOffset = 0;
        int pageLines = fdPrint->scrPrtEndLine;

        //----------------------------------------------------//
		  for (int i = 0;i < itemsInContainer;i++)
		  {
         fdPrint = &(*printerBuf)[i];
         if (!connData)   // if is printing screens
         {
          // adjust screen position on page to have maximum per page
		    if (fdPrint->scrNumber != scrNum)  //
		     {
 	         scrNum = fdPrint->scrNumber;
            if (prtData->oneScrPerPage)
             {
              pageNum++;
			     pageLines = fdPrint->scrPrtEndLine;
			     scrPageOffset = 0;
             }
            else
             {
		        scrPageOffset += pageLines + interScrSpace;
		        pageLines = scrPageOffset + fdPrint->scrPrtEndLine;
		        if (pageLines > linesPerPage)
			      {
			       pageNum++;
			       pageLines = fdPrint->scrPrtEndLine;
			       scrPageOffset = 0;
               }
			    }
           }
		    }
         // else is remote printing
         else
          {
           if (fdPrint->prtPageNumber != pageNum)
             pageNum = fdPrint->prtPageNumber;
          }
		   fdPrint->prtPageNumber = pageNum;
         // Points from top :
		   fdPrint->scrPrtPageOffset = scrPageOffset;
		  }
       //----------------------------------------------------//
       }
      else
       {
        pageNum = 1;
       }
	 }
	 /* Save Last Page Number: It is the Max Page Number */
	 prtData->MinPage = 1;
	 prtData->MaxPage = pageNum;
  }
 catch (TGdiBase::TXGdi)
  {
	TPrintDialog(Window,data).Execute();
	return;
  }
}


bool
ALFFPrintOut::NextLine(int& line, const int begLine,
								const int endLine, const int offset)
{
 line+=offset;
 if (line > endLine)
  {
	line = begLine;
	return false;
  }
  else return true;
}

bool
ALFFPrintOut::NextCol(int& col, const int lineSize, const int offset)
{
 col+=offset;
 if (col > (lineSize-1))
  {
	col = 0;
	return false;
  }
  else return true;
}

bool
ALFFPrintOut::PrintField(TDC&  dc,
								 const Field* field,
								 const TColor bgColor,
								 const int lineSize,
								 const int scrBegLine,
								 const int scrEndLine,
                         const int xOffset,
								 const int yOffset)
{
 TPoint windowPoint, currentPos, devicePos;
 int textLen, outLen, currentCol, currentLine;
 char* outText;
 bool underLined = false;
 bool penNotRestored;
 bool Error = false;
 TFont* boldFont = NULL;

  /*
	* If could get a field show it on real screen
	*/
  if (field)
  {
	/* Set Printer Font Metrics */
	TEXTMETRIC tm;
	dc.GetTextMetrics(tm);
	int fCharWidth = tm.tmAveCharWidth;
	int fCharHeight = tm.tmHeight + tm.tmExternalLeading;

	/* Display The Field */
	outText = field->fdText;
	textLen = strlen(outText);
	currentCol  = field->fdPosition.x;
	currentLine  = field->fdPosition.y;

	/* Should Display Field Attributte as Blank Char with last Field Attr */
	if (field->fdFormatted)
	 {
	  windowPoint.x = (currentCol + xOffset) * fCharWidth;
	  windowPoint.y = (currentLine + yOffset) * fCharHeight;
	  dc.SetTextColor(bgColor);
	  dc.SetBkColor(bgColor);
	  Error = !dc.TextOut(windowPoint," ",1);
     if (Error)
      return true;  // Something wrong has happened !!
	  if (!NextCol(currentCol, lineSize))
		 NextLine(currentLine, scrBegLine, scrEndLine);
	 }


 	/*--------------------------------------------------------------------*
	 * Only "3270 Extended HighLight" effect was implemented.             *
	 * On new versions we should implement Field Background Transparency, *
	 *    Field Outlining, and Field Validation (on keyboard input)       *
	 *--------------------------------------------------------------------*/

	/* Initialize Field "Special" Effects removing Highlight Flag*/
   unsigned char fdEffects = field->fdEffects & 0xf7;
	switch (fdEffects)
	 {
	  case EHREVERSE: /* Reverse Color Field */
							dc.SetBkColor(field->fdTextColor);
							dc.SetTextColor(bgColor);
							break;

	  case   EHBLINK: /* Blinking Field */
                     dc.SetTextColor(field->fdTextColor);
                     dc.SetBkColor(bgColor);
							break;

	  case EHUNDERSC: /* Field with Underlined Characteres */
							dc.SetTextColor(field->fdTextColor);
							dc.SetBkColor(bgColor);
							underLined = true;
							break;
 				default: /* Normal Screen Display */
							dc.SetBkColor(bgColor);
							dc.SetTextColor(field->fdTextColor);
							break;
	 }

   /* Verify if field color must be intensified */
   if (field->fdEffects & EHHIGHLIGHT)
    {
     /* Highlight Fields should be printed as bold */
     LOGFONT logFont;
     if (remotePrtFont)
       remotePrtFont->GetObject(logFont);
     else prtData->currPrtFont->GetObject(logFont);
     logFont.lfWeight = FW_SEMIBOLD; //it was FW_BOLD;
     boldFont = new TFont(&logFont);
     dc.SelectObject(*boldFont);
    }

   // Do print the field
	while(textLen)
	 {
	  windowPoint.x = (currentCol + xOffset) * fCharWidth;
	  windowPoint.y = (currentLine  + yOffset) * fCharHeight;
	  if (textLen > lineSize)
		{
		 if (currentCol > 0)
			{
			 outLen = lineSize - currentCol;
			 Error = !dc.TextOut(windowPoint,outText,outLen);
          if (Error)
           break;
			 if (underLined)
			  {
				TPen pen(field->fdTextColor);
				dc.SelectObject(pen);
            penNotRestored = true;
				Error = !dc.MoveTo(windowPoint.x, windowPoint.y+fCharHeight-1);
            if (Error)
             break;
				Error = !dc.LineTo(windowPoint.x+(outLen*fCharWidth),
							         windowPoint.y+fCharHeight-1);
            if (Error)
             break;
				dc.RestorePen();
            penNotRestored = false;
			  }
			 outText+=outLen;
			 textLen-=outLen;
			 currentCol = 0;
			 NextLine(currentLine, scrBegLine, scrEndLine);
			}
		  else
			{
			 Error = !dc.TextOut(windowPoint,outText,lineSize);
          if (Error)
           break;
			 if (underLined)
			  {
				TPen pen(field->fdTextColor);
				dc.SelectObject(pen);
            penNotRestored = true;
				Error = !dc.MoveTo(windowPoint.x, windowPoint.y+fCharHeight-1);
            if (Error)
             break;
				Error = !dc.LineTo(windowPoint.x+(lineSize*fCharWidth),
										 windowPoint.y+fCharHeight-1);
            if (Error)
             break;
				dc.RestorePen();
            penNotRestored = false;
			  }
			 outText+=lineSize;
			 textLen-=lineSize;
			 NextLine(currentLine, scrBegLine, scrEndLine);
			}
		}
	  else
		{
		 if ((currentCol+textLen) > lineSize)
		  {
			  outLen = lineSize-currentCol;
			  Error = !dc.TextOut(windowPoint,outText,outLen);
           if (Error)
            break;
			  if (underLined)
				{
				 TPen pen(field->fdTextColor);
				 dc.SelectObject(pen);
             penNotRestored = true;
				 Error = !dc.MoveTo(windowPoint.x, windowPoint.y+fCharHeight-1);
             if (Error)
              break;

				 Error = !dc.LineTo(windowPoint.x+(outLen*fCharWidth),
							  				windowPoint.y+fCharHeight-1);
             if (Error)
              break;
				 dc.RestorePen();
             penNotRestored = false;
				}
			  outText+=outLen;
			  textLen-=outLen;
			  currentCol = 0;
			  NextLine(currentLine, scrBegLine, scrEndLine);
			 }
			else
			 {
			  dc.TextOut(windowPoint,outText,textLen);
			  if (underLined)
				{
				 TPen pen(field->fdTextColor);
				 dc.SelectObject(pen);
             penNotRestored = true;
				 Error = !dc.MoveTo(windowPoint.x, windowPoint.y+fCharHeight-1);
             if (Error)
              break;
				 Error = !dc.LineTo(windowPoint.x+(textLen*fCharWidth),
							  				windowPoint.y+fCharHeight-1);
             if (Error)
               break;
        		 dc.RestorePen();
             penNotRestored = false;
				}
			  outText+=textLen;
			  textLen-=textLen;
			 }
		} // else (if textLen > scrLineSize)

	 }  // while (textLen)

   if (boldFont)
    {
     delete boldFont;
     boldFont = NULL;
     if (remotePrtFont)
		dc.SelectObject(*remotePrtFont);
     else dc.SelectObject(*prtData->currPrtFont);
    }
   if (Error)
    {
     if (penNotRestored)
       dc.RestorePen();
     return true;
    }
   else return false;
  }  // if (field)
 else return true; // Error !! - There is no field !!
}

