/*  Project Tec3270

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

	 OVERVIEW:

    ALFFCursorSelect and ALFFVirtualTerm classes implementation. They are used,
    respectively, to change 3270 cursor format and 3270 terminal screen
    simulation.

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

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

// DEBUG FLAGS
//#define  TRACEKEYBOARD   1
//#define  DEBUG32         1


///////////////////////////////////////////////////////////
// ALFFCursorSelect
// ===========
// Implementation Source
//
ALFFCursorSelect::ALFFCursorSelect (TWindow* parent,
                                    TResId   idDlg,
												nCursorType& nCursor,
												nCursorType& iCursor,
                                    bool& horizLine,
                                    bool& vertLine) :
												ALFFDialog(parent, idDlg),
												normCursor(nCursor),
												insCursor(iCursor),
                                    horizEffect(horizLine),
                                    vertEffect(vertLine)
{
 /* Values of Normal and Insertion Mode Cursor Style Variables on Dialog Start */
 wNormCursor = nCursor;
 wInsCursor  = iCursor;

 pMsgs  = new ALFFMsgs(this);

 /* Normal Mode Cursor Options */
 normalCursorGrp = new TGroupBox(this, IDC_GRPCURSORNORM);
 normalUnder  = new TRadioButton(this, IDC_CURSORNORMLINE, normalCursorGrp);
 normalBlock  = new TRadioButton(this, IDC_CURSORNORMBLOCK, normalCursorGrp);
 normalVert   = new TRadioButton(this, IDC_CURSORNORMVERT, normalCursorGrp);

 /* Insertion Mode Cursor Options */
 insCursorGrp = new TGroupBox(this, IDC_GRPCURSORINSERT);
 insUnder  = new TRadioButton(this, IDC_CURSORINSLINE, insCursorGrp);
 insBlock  = new TRadioButton(this, IDC_CURSORINSBLOCK, insCursorGrp);
 insVert   = new TRadioButton(this, IDC_CURSORINSVERT, insCursorGrp);

 /* Special Effects Cursor Options */
 specHorizLine = new TCheckBox(this, IDC_CURSORHORIZLINE);
 specVertLine  = new TCheckBox(this, IDC_CURSORVERTLINE);
}

ALFFCursorSelect::~ALFFCursorSelect()
{
 /* Normal Mode Cursor Options */
 delete  normalCursorGrp;
 delete  normalUnder;
 delete  normalBlock;
 delete  normalVert;

 /* Insertion Mode Cursor Options */
 delete  insCursorGrp;
 delete  insUnder;
 delete  insBlock;
 delete  insVert;

 /* Special Effects Cursor Options */
 delete  specHorizLine;
 delete  specVertLine;
}

void
ALFFCursorSelect::SetupWindow()
{
 /* Call Base Class Setup Window */
 ALFFDialog::SetupWindow();

 /* Select Current Cursor Style Options */
 switch (wNormCursor)
  {
	case nCursorUNDER : normalUnder->Check();
							  break;
	case nCursorBLOCK : normalBlock->Check();
							  break;
	case nCursorVERT  : normalVert->Check();
							  break;
	default      : pMsgs->Message( IDS_SESSDLGERROR,IDS_ALFFSESSTITLE);
  }

 switch (wInsCursor)
  {
	case nCursorUNDER : insUnder->Check();
							  break;
	case nCursorBLOCK : insBlock->Check();
							  break;
	case nCursorVERT  : insVert->Check();
							  break;
	default      : pMsgs->Message( IDS_SESSDLGERROR,IDS_ALFFSESSTITLE);
  }

 if (horizEffect)
    specHorizLine->Check();
 else specHorizLine->Uncheck();

 if (vertEffect)
    specVertLine->Check();
 else specVertLine->Uncheck();

}

void
ALFFCursorSelect::CmOk()
{
 normCursor = wNormCursor;
 insCursor  = wInsCursor;
 ALFFDialog::CmOk();
}

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

 helpFile->ShowHelp(HH_HELP_CONTEXT, IDH_HELP_CURSOR_SELECT);
}

LRESULT
ALFFCursorSelect::EvCommand(uint controlId, HWND , uint notifyCode)
{
 /*
  * controlId is the control identifier that is related to some
  * option on Connect Dialog.
  */
 switch (controlId)
  {
	/* Connect to PushButton Pressed */
	case			        IDOK: CmOk();
									  break;

	/* Cancel Connect Operation PushButton Pressed */
	case		       IDCANCEL: ALFFDialog::CmCancel();
									  break;

	/* Help to this Dialog Fields */
	case            IDHELP: CmHelp();
									break;

	/* Select Cursor for Normal Mode Text Typing */
	case 	IDC_GRPCURSORNORM: switch(notifyCode)
										{
										  case  IDC_CURSORNORMLINE:  if (notifyCode == BN_CLICKED)
																					wNormCursor=nCursorUNDER;
																				 break;
										  case  IDC_CURSORNORMBLOCK: if (notifyCode == BN_CLICKED)
																					wNormCursor=nCursorBLOCK;
																				 break;
										  case  IDC_CURSORNORMVERT:  if (notifyCode == BN_CLICKED)
																					wNormCursor=nCursorVERT;
																				 break;
										  default      : pMsgs->Message( IDS_SESSDLGERROR,IDS_ALFFSESSTITLE);
															  break;
										}
										break;
	case  IDC_CURSORNORMLINE:  wNormCursor=nCursorUNDER;
										break;
	case  IDC_CURSORNORMBLOCK: wNormCursor=nCursorBLOCK;
										break;
	case  IDC_CURSORNORMVERT:  wNormCursor=nCursorVERT;
										break;

	/* Select Cursor for Insertion Mode Text Typing */
	case 	IDC_GRPCURSORINSERT: switch(notifyCode)
										{
										  case  IDC_CURSORINSLINE:  if (notifyCode == BN_CLICKED)
																					wInsCursor=nCursorUNDER;
																				 break;
										  case  IDC_CURSORINSBLOCK: if (notifyCode == BN_CLICKED)
																					wInsCursor=nCursorBLOCK;
																				 break;
										  case  IDC_CURSORINSVERT:  if (notifyCode == BN_CLICKED)
																					wInsCursor=nCursorVERT;
																				 break;
										  default      : pMsgs->Message( IDS_SESSDLGERROR,IDS_ALFFSESSTITLE);
															  break;
										}
										break;

	case  IDC_CURSORINSLINE:  wInsCursor=nCursorUNDER;
										break;
	case  IDC_CURSORINSBLOCK: wInsCursor=nCursorBLOCK;
										break;
	case  IDC_CURSORINSVERT:  wInsCursor=nCursorVERT;
										break;

   case  IDC_CURSORHORIZLINE: if (horizEffect)
                               {
                                horizEffect = false;
                                specHorizLine->Uncheck();
                               }
                              else
                               {
                                horizEffect = true;
                                specHorizLine->Check();
                               }
                              break;

   case  IDC_CURSORVERTLINE:  if (vertEffect)
                               {
                                vertEffect = false;
                                specVertLine->Uncheck();
                               }
                              else
                               {
                                vertEffect = true;
                                specVertLine->Check();
                               }
                              break;

	default      : pMsgs->Message( IDS_SESSDLGERROR,IDS_ALFFSESSTITLE);
						break;
  }

 return 1L;
}


//{{ALFFVirtualTerm Implementation}}
//
////////////////////////////////////////////////////////////
// Build a response table for all messages/commands handled
// by ALFFVirtualTerm derived from TWindow.
//
DEFINE_RESPONSE_TABLE1(ALFFVirtualTerm, TWindow)
//{{ALFFVirtualTermRSP_TBL_BEGIN}}
	 EV_WM_VSCROLL,
	 EV_WM_HSCROLL,
	 EV_WM_SIZE,
	 EV_WM_SETFOCUS,
	 EV_WM_KILLFOCUS,
	 EV_WM_GETMINMAXINFO,
	 EV_WM_CHAR,
	 EV_WM_KEYDOWN,
	 EV_WM_KEYUP,
	 EV_WM_SYSKEYDOWN,
	 EV_WM_LBUTTONDOWN,
	 EV_WM_LBUTTONDBLCLK,
	 EV_WM_RBUTTONDOWN,
	 EV_WM_MOUSEMOVE,
//{{ALFFVirtualTermRSP_TBL_END}}
END_RESPONSE_TABLE;

//////////////////////////////////////////////////////////
// ALFFVirtualTerm
// =============
// Construction/Destruction handling.
ALFFVirtualTerm::ALFFVirtualTerm (TWindow* parent,
									 const char far* text,
									 TModule* module):
		TWindow(parent, text, module),
		screenBlink(MAXSCRFIELDS/2,0,10),
		field()
{
 tParent = parent;

#ifdef DEBUG32
	MessageBox("ALFFVirtualTerm Constructor starting...","Tec3270 Debug",MB_OK);
#endif
 // Set Scroller Object to get scrolling functions
 Attr.Style |= WS_VSCROLL | WS_HSCROLL;

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

 /* Access Tec3270 Ini File */
 char iniSection[16];
 ALFFIniFile* iniFile = theApp->GetIniFile();

 /* Setup Cursor Styles */
 strcpy(iniSection,"CURSOR STYLES");
 nNormCursor = (nCursorType)iniFile->GetInt(iniSection,"NORMAL MODE",nCursorUNDER);
 nInsCursor  = (nCursorType)iniFile->GetInt(iniSection,"INSERT MODE",nCursorBLOCK);
 horizEffect = (bool)iniFile->GetInt(iniSection,"HORIZ EFFECT",false);
 vertEffect  = (bool)iniFile->GetInt(iniSection,"VERTICAL EFFECT",false);
 nCursor     = nNormCursor;
 firstCursor = true;
 lockedCursor = false;

 // Setup Screen Controls
 terminalInited = false;
 cursorVisible   = false;
 keyboardLocked = false;
 traceOn  = false;
 logOn  = false;
 mode3270 = false;
 screenPos.x = currentPos.x = 0;
 screenPos.y = currentPos.y = 0;
 nvtCursorPos = cursorPos = currentPos;
 scrLineSize = theApp->GetTermLineSize();
 scrNumLines = theApp->GetTermNumLines();
 charSystem = new char[CHARSYSTEMLEN+1];
 strcpy(charSystem,XSYSTEM);

 // Set Screen Font Measures For This Session
 scrFont = NULL;

 screenBlink.Flush();
 blink = false;
 scrType = NOSCREENDEFINED;

 /****************************************************************************
  * For this version of Tec3270 there is no option to use Block              *
  * Mode on Text Selection and for this reason lineBehavior will be always   *
  * true.                                                                    *
  * When next versions arrive and Block Mode become available routines that  *
  * implement Text Selection MUST be updated to admit block mode operation   *
  * (routines SetSelection and RemoveSelection in this class and routines    *
  * that do some work with text like Cut, Paste and Copy as well as auxiliar *
  * routines on 3270 Buffer Class (ALFF3270).                             *
  ****************************************************************************/
 lineBehavior = true;

 /* Set Insert Mode Status to false */
 insertMode = false;
 theApp->SetInsertMode(false);

 unsigned char keyboardState[256];
 ::GetKeyboardState(keyboardState);
 if (keyboardState[VK_INSERT] & 0x01)
  {
   // turn low_order bit off (set system insert mode to false)
   keyboardState[VK_INSERT] &= 0xFE;
   ::SetKeyboardState(keyboardState);
  }

 /* Normally Terminal Will Not Have Remote Echo */
 remoteEcho = false;

#ifdef TRACEKEYBOARD
 scrtrace.open("scrtrace.trc", ios::out|ios::binary);
#endif

#ifdef DEBUG32
	MessageBox("KeyBoard Manager being created...","Tec3270 Debug",MB_OK);
#endif

 /* Creating the Keyboard Manager */
 int keybId;
 strcpy(iniSection,"KEYBOARD");
 keybId = iniFile->GetInt(iniSection,"CONFIG TYPE",KEYBOARDBRPC);

 pKeyboard = new ALFFKeyboard(this,keybId);

 /* Set the Scroller object with initial units and ranges
	 (Ranges will be accurately set on EvSize Function)    */
 const int xUnit = 10;
 const int yUnit = 10;
 const TSize screenRange = theApp->GetFullScreenSize();
 Scroller = new TScroller(this,xUnit,yUnit,screenRange.cx,screenRange.cy);
 /* Set Automatic offset of Client Rect Origin */
 Scroller->AutoOrg = true;

#ifdef DEBUG32
	MessageBox("Creating ALFFMsgs Object ...","Tec3270 Debug",MB_OK);
#endif
 /* Messages and String Resources Object Manager */
 pMsgs = new ALFFMsgs(this);

 /* Text Selection Controls */
 blkMarked = false;
 blkInverse = false;
 markNoBlk = false;

 // Set Initial Timer Control for updating time on status line
 time(&oldTimer);

#ifdef DEBUG32
	MessageBox("ALFFVirtualTerm Constructor: Terminated...","Tec3270 Debug",MB_OK);
#endif
}

ALFFVirtualTerm::~ALFFVirtualTerm ()
{
	 Destroy();

	 /* Save  Cursor Styles */
	 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(), Tec3270App);
	 char cursorSection[16];
	 strcpy(cursorSection,"CURSOR STYLES");
	 ALFFIniFile* iniFile = theApp->GetIniFile();
	 iniFile->WriteInt(cursorSection,"NORMAL MODE",nNormCursor);
	 iniFile->WriteInt(cursorSection,"INSERT MODE",nInsCursor);
    iniFile->WriteInt(cursorSection,"HORIZ EFFECT",horizEffect);
    iniFile->WriteInt(cursorSection,"VERTICAL EFFECT",vertEffect);

    //Delete window scroller set up on constructor
    delete Scroller;

	 delete pKeyboard;
	 delete [] charSystem;

	 if (scrFont)
     delete scrFont;
}

void
ALFFVirtualTerm::SetupWindow()
{
 TWindow::SetupWindow();
#ifdef DEBUG32
	MessageBox("ALFFVirtualTerm:SetupWindow ...","Tec3270 Debug",MB_OK);
#endif
 //hasFocus   = true;

#ifdef DEBUG32
	MessageBox("ALFFVirtualTerm:SetupWindow - SetBkgnColor...","Tec3270 Debug",MB_OK);
#endif
}

void
ALFFVirtualTerm::SetEchoMode(bool echo)
{
 remoteEcho = echo;
}

void
ALFFVirtualTerm::Connect(bool mode3270, bool justConnect)
{
 if (!justConnect)
	SetMode3270(mode3270);
 SetConnected(true);
}

void
ALFFVirtualTerm::Disconnect()
{
 SetScreen(DEFAULTSCREEN);
 SetMode3270(false);
 SetConnected(false);
}

void
ALFFVirtualTerm::InitTerminal(TWindow* parent,
									ALFF3270* p3270,
									ALFFNvt* pNVT,
									ALFFConnData* cnnData)
{
 tParent  = parent;
 p3270Buf = p3270;
 pNVTBuf  = pNVT;
 connData  = cnnData;
 SetConnected(false);
 terminalInited = true;
}


bool
ALFFVirtualTerm::IdleAction(long idleCount)
{
  TWindow::IdleAction(idleCount);

  // Get Current Time
  time_t timer,result;
  time(&timer);

  result = (timer-oldTimer);
  if (result && IsMode3270() && hasFocus)
   {
     oldTimer = timer;

     // Set Scrolled view
     TClientDC dc(HWindow);
	  if (Scroller)
	   {
	    TRect cRect = GetClientRect();
	    Scroller->BeginView(dc,cRect);
	   }
	  TPoint windowPoint;
	  dc.SelectObject(*scrFont);

     // Update "Blinking" Fields only if 3270 mode is on
     int numFields = screenBlink.GetItemsInContainer();
	  if (numFields && !IsLogOn())
	   {
	    int i;
	    blink = !blink;
	    if (hasFocus && numFields)
		  {
		   for (i=0; i<numFields; i++)
		    {
			  Field fdBlink = screenBlink[i];
		 	  if (blink)
			    fdBlink.fdTextColor = fdBlink.fdBkgdColor;
			  DisplayField(&fdBlink,dc,connData->scrBkgdColor,
							 scrLineSize, 0, scrNumLines-2,
							 fontCharWidth, fontCharHeight);
		    }
		  }
	   }
	  else  dc.SetBkColor(TColor(connData->scrBkgdColor));
   }
 return false;      // era return true;
}

void
ALFFVirtualTerm::SetMenuTraceStat()
{
 HMENU  mainMenu = GetApplication()->GetMainWindow()->GetMenu();
 TMenu* theMenu = new TMenu(mainMenu);
 char* menuMsg = new char[STRINGMSGLEN];
 int menuFlag;
 if (theMenu)
  {
	if (IsTraceOn())
	 {
	  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_TRACESESSION, MF_BYCOMMAND,CM_TRACESESSION,menuMsg);
	bool done = theMenu->CheckMenuItem(CM_TRACESESSION,menuFlag);
	if (done)
      GetApplication()->GetMainWindow()->DrawMenuBar();
  }
 delete [] menuMsg;
}

void
ALFFVirtualTerm::SetLogOn(bool status)
 {
  logOn = status;
  if (status)
   {
 	  KillCursor();
     lockedCursor = true;
   }
  else
   {
     lockedCursor = false;
     SetCursor();
   }
 }

void
ALFFVirtualTerm::EvSetFocus(HWND wnd)
{
 TWindow::EvSetFocus(wnd);
 hasFocus = true;

 /* Update Menu Trace Options For This Session */
 SetMenuTraceStat();

 /* Lock the SSL PadLock */
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);
 theApp->UpdateSSLLock();
 theApp->UpdateTN3270();    // TN3270/TN3270E indicator
 theApp->UpdateTermGadget();
 theApp->UpdateTermNetname();
 theApp->UpdatePrtGadget();
 theApp->UpdatePrtNetname();

 /* Update ScreenFont For This Session */
 SetScreenFont(false);   //Do Not Repaint Screen Here. It will be done ahead.

 /* Set Horizontal and Vertical Scrollers if we need it */
 SetScroll();

 // Get actual insert mode key status
 unsigned char keyboardState[256];
 ::GetKeyboardState(keyboardState);
 // Set last insert mode key status
 if (insertMode)
  {
   nCursor = nInsCursor;
   // set system insert mode to true
   keyboardState[VK_INSERT] |= 0x01;
  }
 else
  {
   nCursor = nNormCursor;
   // set system insert mode to false
   keyboardState[VK_INSERT] &= 0xFE;
  }

 // update system insert mode to current
 ::SetKeyboardState(keyboardState);
 theApp->SetInsertMode(insertMode);

 /* Set Cursor Format and Position */
 if (!logOn)
  {
   lockedCursor = false;
   SetCursor();
  }
}

void
ALFFVirtualTerm::EvKillFocus(HWND wnd)
{
 TWindow::EvKillFocus(wnd);
 if (!logOn)
  {
   KillCursor();
   lockedCursor = true;
  }

 hasFocus = false;
}


void
ALFFVirtualTerm::EvSize(uint /*sizeType*/, TSize& /*size*/)
{
 SetScroll();
 if (IsConnected())
 		PaintScreen(ERASE);
}

void
ALFFVirtualTerm::SetScroll()
{
 /* Only Do It When There Is an Scroller Active */
 if (!Scroller)
  return;

 TRect cRect = GetWindowRect();
 int xVscrol  = GetSystemMetrics(SM_CXVSCROLL);
 int yHscrol  = GetSystemMetrics(SM_CYHSCROLL);

 // Calculating entire window size
 int xFull  = (fontCharWidth*scrLineSize);
 int yFull  = (fontCharHeight*scrNumLines);

 // Calculating and setting new Ranges
 int xRange  = xFull - cRect.Width();
 int yRange  = yFull - cRect.Height();
 int xScroll = 0;
 int yScroll = 0;
 if ((xRange > 2) || (yRange > 2))
  {
	xScroll = (xRange+xVscrol+Scroller->XUnit)/Scroller->XUnit;
	yScroll = (yRange+yHscrol+Scroller->YUnit)/Scroller->YUnit;
  }

 Scroller->SetRange(xScroll,yScroll);
}

void
ALFFVirtualTerm::EvVScroll(uint scrollCode, uint thumbPos, HWND hWndCtl)
{
 TWindow::EvVScroll(scrollCode, thumbPos, hWndCtl);
 PaintScreen(ERASE);
}

void
ALFFVirtualTerm::EvHScroll(uint scrollCode, uint thumbPos, HWND hWndCtl)
{
 TWindow::EvHScroll(scrollCode, thumbPos, hWndCtl);
 PaintScreen(ERASE);
}

void
ALFFVirtualTerm::ResetTimer()
{
 ::PostMessage(Parent->HWindow,MSG_KEYB_MOUSE_ACTIVITY,0,0);
}


void
ALFFVirtualTerm::ChangeCursor()
{
 bool oldHorizEffect = horizEffect;
 bool oldVertEffect  = vertEffect;

 /* Cursor must be hidden while CursorSelect Dialog is active */
 KillCursor();

 if (ALFFCursorSelect(this, IDD_ALFFCURSOR,
							 nNormCursor, nInsCursor,
                      horizEffect, vertEffect).Execute() == IDOK)
 {
  /* Save  Cursor Styles */
  Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(), Tec3270App);
  char cursorSection[16];
  strcpy(cursorSection,"CURSOR STYLES");
  ALFFIniFile* iniFile = theApp->GetIniFile();
  iniFile->WriteInt(cursorSection,"NORMAL MODE",nNormCursor);
  iniFile->WriteInt(cursorSection,"INSERT MODE",nInsCursor);
  iniFile->WriteInt(cursorSection,"HORIZ EFFECT",horizEffect);
  iniFile->WriteInt(cursorSection,"VERTICAL EFFECT",vertEffect);

  /* Set New Cursor Styles */
  if (insertMode)
	nCursor = nInsCursor;
  else nCursor = nNormCursor;
 }

 /* Restore Cursor with new shape */
 SetCursor();
}

void
ALFFVirtualTerm::WriteNVTLine(int resourceId, char* errText)
{
 char* text = new char[MAXLINESIZE+1];
 GetApplication()->LoadString(resourceId,text,MAXLINESIZE);
 if (errText)
  {
	strcat(text," (");
	strcat(text,errText);
	strcat(text,")");
  }
 /* Add Line of Text to Screen Container */
 WriteNVTLine(text);
 delete [] text;
}

void
ALFFVirtualTerm::WriteNVTLine(const char* text)
{
 char CRLF[3] = {CR, LF, NULL};
 char* lineText = new char[1024];
 lineText[0] = NULL;

#ifdef DEBUG32
	MessageBox("WriteNVTLine: Starting...","Tec3270 Debug",MB_OK);
#endif
 // Check For Cursor At Line Beginning
 if (nvtCursorPos.x > 0)
  strcat(lineText,CRLF);

 // Build Text Line
 strcat(lineText,text);
 int lineLen = strlen(lineText);

#ifdef DEBUG32
	MessageBox("WriteNVTLine: pNVT->WriteBuffer...","Tec3270 Debug",MB_OK);
#endif
 // Write Text To NVT
 char* pLineText = lineText;
 int retCode = pNVTBuf->WriteBuffer(&pLineText, lineLen);
 if (retCode)
	pMsgs->Message(IDS_INVNVTORDERCODE,IDS_TITNVTERR);

#ifdef DEBUG32
	MessageBox("WriteNVTLine: pNVT->GetCursorPos...","Tec3270 Debug",MB_OK);
#endif

 delete [] lineText;
 
 // Update Cursor Position
 nvtCursorPos = pNVTBuf->GetCursorPos();
 if (!IsMode3270())
  {
   cursorPos = nvtCursorPos;
#ifdef DEBUG32
	MessageBox("WriteNVTLine: pNVT->PaintScreen...","Tec3270 Debug",MB_OK);
#endif
   // Update Screen To Show Line
   PaintScreen();

#ifdef DEBUG32
	MessageBox("WriteNVTLine: pNVT->  Terminated...","Tec3270 Debug",MB_OK);
#endif
  }
}

bool
ALFFVirtualTerm::ReLoadKeyboard(int keybId)
{
 if (pKeyboard->GetKeyboardId() == keybId)
	return (pKeyboard->LoadKeybFile());
  else return true;
}


void
ALFFVirtualTerm::SetScreenFont(bool redraw)
{
 LOGFONT logFontData;

 /* Access the Application Scope */
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(), Tec3270App);
 Tec3270MainWindow *theAppMainWin =
		TYPESAFE_DOWNCAST(GetApplication()->GetMainWindow(),Tec3270MainWindow);

 /* Get Tec3270 Main Character Font */
 theApp->GetAppFont()->GetObject(logFontData);

 if (theApp->IsAutomaticFontSizing())
	{
	 fontCharWidth  = theApp->SizeFontCharWidth(scrLineSize);
	 fontCharHeight = theApp->SizeFontCharHeight(scrNumLines);

	 logFontData.lfHeight = -(fontCharHeight-1);
	 logFontData.lfWidth  = fontCharWidth;
	 logFontData.lfOutPrecision = OUT_DEVICE_PRECIS;
	 logFontData.lfClipPrecision = CLIP_CHARACTER_PRECIS;
	 logFontData.lfPitchAndFamily = FIXED_PITCH;
	 logFontData.lfQuality = PROOF_QUALITY;

	 /* Try to Create Font with this parameters */
	 if (scrFont)
	  delete scrFont;
	 scrFont = new TFont(&logFontData);

	 /* Check for Actual Char Width */
	 int charWidth[4];
	 TClientDC dc(HWindow);
	 dc.SelectObject(*scrFont);
	 dc.GetCharWidth('A','C',charWidth);

	 /* Set Correct Font Char Width */
	 fontCharWidth = charWidth[1];

	 /* Update Application Data */
	 theApp->SetFontCharWidth(fontCharWidth);
	 theApp->SetFontCharHeight(fontCharHeight);
	 theApp->SetTermLineSize(scrLineSize);
	 theApp->SetTermNumLines(scrNumLines);
	 if (hasFocus && theApp->IsAutomaticWindowSizing())
		 theAppMainWin->ResizeWindow();
 	}
 else
	{
	 if (scrFont)
	  delete scrFont;
	 scrFont = new TFont(&logFontData);
	 fontCharWidth  = theApp->GetFontCharWidth();
	 fontCharHeight = theApp->GetFontCharHeight();
	 if (hasFocus && theApp->IsAutomaticWindowSizing())
		 theAppMainWin->ResizeWindow();
	}

 /* Recalculate Status Line and Time Positions */
 statusLinePos =  ((scrNumLines-1) * fontCharHeight)+2;
 xSystemPos = ((scrLineSize/10)-1) * fontCharWidth;
 timePos = (scrLineSize-TERMTYPELEN-11)*fontCharWidth;

 if (redraw)
	PaintScreen(ERASE);
}

void
ALFFVirtualTerm::SetColors(ALFFConnData* newCnnData)
{

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

 connData->scrCharColor = newCnnData->scrCharColor;
 connData->scrBkgdColor = newCnnData->scrBkgdColor;
 connData->scr3270BkgdColor = newCnnData->scr3270BkgdColor;
 connData->scrNormalUnprotTextColor = newCnnData->scrNormalUnprotTextColor;
 connData->scrHighlightUnprotTextColor = newCnnData->scrHighlightUnprotTextColor;
 connData->scrNormalProtTextColor = newCnnData->scrNormalProtTextColor;
 connData->scrHighlightProtTextColor = newCnnData->scrHighlightProtTextColor;
 connData->neutral = newCnnData->neutral;
 connData->blue = newCnnData->blue;
 connData->red = newCnnData->red;
 connData->pink = newCnnData->pink;
 connData->green = newCnnData->green;
 connData->turquoise = newCnnData->turquoise;
 connData->yellow = newCnnData->yellow;
 connData->inverseNeutral = newCnnData->inverseNeutral;
 connData->black = newCnnData->black;
 connData->deepBlue = newCnnData->deepBlue;
 connData->orange = newCnnData->orange;
 connData->purple = newCnnData->purple;
 connData->paleGreen = newCnnData->paleGreen;
 connData->paleTurquoise = newCnnData->paleTurquoise;
 connData->gray = newCnnData->gray;
 connData->white = newCnnData->white;

 /* Update All Fields On Screen Buffer
 int numFields = screen.GetItemsInContainer();
 for (int i = 0; i < numFields; i++)
  {
	screen[i].fdTextColor = connData->scrCharColor;
	screen[i].fdBkgdColor = connData->scrBkgdColor;
  }
 */

 /* Update Session Colors on its confuguration */
 iniFile->WriteLong(connData->connName,"BKGD3270COLOR",connData->scr3270BkgdColor);
 iniFile->WriteLong(connData->connName,"NORMNPRTTEXT",connData->scrNormalUnprotTextColor);
 iniFile->WriteLong(connData->connName,"HIGHNPRTTEXT",connData->scrHighlightUnprotTextColor);
 iniFile->WriteLong(connData->connName,"NORMPROTTEXT",connData->scrNormalProtTextColor);
 iniFile->WriteLong(connData->connName,"HIGHPROTTEXT",connData->scrHighlightProtTextColor);
 iniFile->WriteLong(connData->connName,"NEUTRAL",connData->neutral);
 iniFile->WriteLong(connData->connName,"BLUE",connData->blue);
 iniFile->WriteLong(connData->connName,"RED",connData->red);
 iniFile->WriteLong(connData->connName,"PINK",connData->pink);
 iniFile->WriteLong(connData->connName,"GREEN",connData->green);
 iniFile->WriteLong(connData->connName,"TURQUOISE",connData->turquoise);
 iniFile->WriteLong(connData->connName,"YELLOW",connData->yellow);
 iniFile->WriteLong(connData->connName,"INVERSENEUTRAL",connData->inverseNeutral);
 iniFile->WriteLong(connData->connName,"BLACK",connData->black);
 iniFile->WriteLong(connData->connName,"DEEPBLUE",connData->deepBlue);
 iniFile->WriteLong(connData->connName,"ORANGE",connData->orange);
 iniFile->WriteLong(connData->connName,"PURPLE",connData->purple);
 iniFile->WriteLong(connData->connName,"PALEGREEN",connData->paleGreen);
 iniFile->WriteLong(connData->connName,"PALETURQUOISE",connData->paleTurquoise);
 iniFile->WriteLong(connData->connName,"GRAY",connData->gray);
 iniFile->WriteLong(connData->connName,"WHITE",connData->white);

 /* Reset Screen BackGround To New Colors */
 ResetScrColor();
}

void
ALFFVirtualTerm::ResetScrColor()
{
 TClientDC dc(HWindow);
 TRect cRect = GetClientRect();
 if (Scroller)
	Scroller->BeginView(dc,cRect);
 //dc.FillRect(cRect, TBrush(connData->scr3270BkgdColor));
 PaintTerminal(dc,cRect,ERASE);
}

#ifdef TRACEKEYBOARD
/*   --------------- DEBUG ------------------------------------------  */
void
ALFFVirtualTerm::LogEv(char* evName, UINT key, BYTE vKey,
							BYTE sCode, bool shift,
							bool ctrl, bool alt,
							UINT command)
{
 char msgString[128];
 TClientDC dc(HWindow);
 if (Scroller)
   {
 	 TRect cRect = GetClientRect();
 	 Scroller->BeginView(dc,cRect);
   }
 TPoint windowPoint;
 int currLine = currentPos.y;
 if (GetKeyState(VK_MENU) < 0)
	 alt = true;
 int intvKey, intSCode;
 intvKey = vKey;
 intSCode = sCode;
 sprintf(msgString,"Tecla: %c   Key=%i, Shift = %i,"
			"Ctrl = %i, Alt = %i, VKey = %i, ScanCode = %i Command = %u",
			 key,key,shift,ctrl,alt,intvKey, intSCode, command);
 strcat(msgString,evName);
 strcat(msgString,"\n");
 scrtrace << msgString;
 windowPoint.x = currentPos.x  * fontCharWidth;
 windowPoint.y = currentPos.y  * fontCharHeight;
 dc.SetTextColor(TColor(connData->scrCharColor));
 dc.TextOut(windowPoint,msgString,strlen(msgString));
 NextLine(currLine, 0, scrNumLines-2);
 currentPos.y = currLine;
}
/*   --------------- DEBUG -------------------------------------------  */
#endif

bool
ALFFVirtualTerm::UpdateScreen(const int fdBegin, const int option,
									const int subOption)
{
  Field* fdRepaint;
  int fromPos = fdBegin;
  /* If protected field then lock the keyboard */
  if (fdBegin < 0)
	{
	 char err[12];
	 if (fdBegin == PROTECTEDFIELD)
		  strcpy(err,PROTECTEDFD);
	 else if (fdBegin == NUMERICFIELD)
				 strcpy(err,NUMERICFD);
	 else strcpy(err,XSYSTEM);
	 LockKeyboard(err);
	 return false;
	}
	else
	 /* else update screen with position changed */
	 {
	  /* Update current cursor position */
	  if (IsMode3270())
		 cursorPos = p3270Buf->GetCursorPos();
	  else
      {
       nvtCursorPos = pNVTBuf->GetCursorPos();
       cursorPos = nvtCursorPos;
      }

	  if (fdBegin < MUSTREPAINT)
		{
		 TClientDC dc(HWindow);
		 if (Scroller)
		  {
			TRect cRect = GetClientRect();
			Scroller->BeginView(dc,cRect);
		  }
		 dc.SelectObject(*scrFont);

		 KillCursor();
       lockedCursor = true;

		 COLORREF bkgdColor;
		 bool firstTime = true;
		 while (fromPos != -1)
		 {
		  if (IsMode3270())
			{
			 /* Set the Correct Bkgd Color */
			 bkgdColor = connData->scr3270BkgdColor;

			 /* Get Just the last position changed */
			 if (firstTime)
			  {
				fdRepaint = p3270Buf->DataToScreen(fromPos,option,subOption);
				firstTime = false;
			  }
			 else fdRepaint = p3270Buf->DataToScreen(fromPos,option,CONTINUE);
			}
		  else
			{
			 /* Set the Correct Bkgd Color */
			 bkgdColor = connData->scrBkgdColor;

			 if (firstTime)
			  {
				fdRepaint = pNVTBuf->DataToScreen(fromPos,option,subOption);
				firstTime = false;
			  }
			 else fdRepaint = pNVTBuf->DataToScreen(fromPos,option,CONTINUE);
			}

		  /* Display The Field Received From DataToScreen */
		  DisplayField(fdRepaint,dc,bkgdColor,
						  scrLineSize, 0, scrNumLines-2,
						  fontCharWidth, fontCharHeight);
		 }
		 WriteCursorPos();

       lockedCursor = false;
		 SetCursor();
		}
	  else PaintScreen();
	  return true;
	 }
}

bool
ALFFVirtualTerm::ProcessCommand(int command, bool ignoreKbLock)
{
 TWindow* wClient;
 char blank = ' ';
 char err[12];
 const char fdMark[2] = {0x1e,0x00};
 const char dupMark[2] = {0x1c,0x00};
 TPoint newPoint;
 int  fdBegin;
 int  bufEndSel;
 int curPos, cursorCol, cursorLine;
 unsigned char keyboardState[256];

 /* Get the Application IniFile Pointer*/
 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(),Tec3270App);

 /* Check For Keyboard Locked And For Commands Processed With Locked Keyb */
 if ( (IsKeyboardLocked() || lockedCursor) && (!ignoreKbLock)
	  &&(command != IDS_RESET)&&(command != IDS_INSERTCHAR)&&(command != IDS_ATTN))
  return false;

 /* If Screen Is Showing Connection Log Do Nothing */
 if (IsLogOn())
	return false;

 /* Notify parent that OIA is changed */
 ::SendMessage(tParent->HWindow,MSG_OIA_CHANGED,0,0);

#ifdef TRACEKEYBOARD
  char charcomando[20];
  itoa(command,charcomando,10);
  char msg[40] = "Comando : ";
  strcat(msg,charcomando);
  MessageBox(msg,"Tec3270 TRACEKEYBOARD",MB_OK);
#endif
 cursorCol = cursorPos.x;
 cursorLine = cursorPos.y;
 switch (command)
  {
	case  IDS_CURSORRIGHT:  /* Cursor Right movement */
									if (!NextCol(cursorCol, scrLineSize))
										NextLine(cursorLine, 0, scrNumLines-2);
									cursorPos.x = cursorCol;
									cursorPos.y = cursorLine;
									UpdateCursor();
									break;

	case     IDS_SELRIGHT:  /* Select Text To Right */
									if (!NextCol(cursorCol, scrLineSize))
										NextLine(cursorLine, 0, scrNumLines-2);
									newPoint.x = cursorCol;
									newPoint.y = cursorLine;
									SetSelection(newPoint);
									cursorPos = newPoint;
									UpdateCursor(false); //Do Note Remove Selection
									break;

	case    IDS_FASTRIGHT:  /* Cursor Right fast movement */
									if (!NextCol(cursorCol, scrLineSize, 2))
										NextLine(cursorLine, 0, scrNumLines-2);
									cursorPos.x = cursorCol;
									cursorPos.y = cursorLine;
									UpdateCursor();
									break;

	case   IDS_CURSORLEFT:  /* Cursor Left  movement */
									if (!PrevCol(cursorCol, scrLineSize))
										PrevLine(cursorLine, 0, scrNumLines-2);
									cursorPos.x = cursorCol;
									cursorPos.y = cursorLine;
									UpdateCursor();
									break;

	case      IDS_SELLEFT:  /* Select Text To Left */
									if (!PrevCol(cursorCol, scrLineSize))
										PrevLine(cursorLine, 0, scrNumLines-2);
									newPoint.x = cursorCol;
									newPoint.y = cursorLine;
									SetSelection(newPoint);
									cursorPos = newPoint;
									UpdateCursor(false); //Do Note Remove Selection
									break;

	case     IDS_FASTLEFT:  /* Cursor Left  fast movement */
									if (!PrevCol(cursorCol, scrLineSize, 2))
										PrevLine(cursorLine, 0, scrNumLines-2);
									cursorPos.x = cursorCol;
									cursorPos.y = cursorLine;
									UpdateCursor();
									break;

	case     IDS_CURSORUP:  /* Cursor Up movement */
									PrevLine(cursorLine, 0, scrNumLines-2);
									cursorPos.y = cursorLine;
									UpdateCursor();
									break;

	case        IDS_SELUP:  /* Select Text Up */
									PrevLine(cursorLine, 0, scrNumLines-2);
									newPoint.y = cursorLine;
                           newPoint.x = cursorCol;
									SetSelection(newPoint);
									cursorPos = newPoint;
									UpdateCursor(false); //Do Note Remove Selection
									break;

	case       IDS_FASTUP:  /* Cursor Up fast movement */
									PrevLine(cursorLine, 0, scrNumLines-2, 2);
									cursorPos.y = cursorLine;
									UpdateCursor();
									break;

	case   IDS_CURSORDOWN:  /* Cursor Down movement */
									NextLine(cursorLine, 0, scrNumLines-2);
									cursorPos.y = cursorLine;
									UpdateCursor();
									break;

	case      IDS_SELDOWN:  /* Select Text Down */
									NextLine(cursorLine, 0, scrNumLines-2);
									newPoint.y = cursorLine;
                           newPoint.x = cursorCol;
									SetSelection(newPoint);
									cursorPos = newPoint;
									UpdateCursor(false); //Do Note Remove Selection
									break;

	case     IDS_FASTDOWN:  /* Cursor Down fast movement */
									NextLine(cursorLine,0, scrNumLines-2, 2);
									cursorPos.y = cursorLine;
									UpdateCursor();
									break;

	case   IDS_CURSORHOME:  /* Cursor Home movement */
									if (lineBehavior)
									 {
									  /* Move Cursor to First Line Position */
									  cursorPos.x = 0;
									 }
									 else
									  {
										if (IsMode3270())
										  cursorPos = p3270Buf->GetBeginOfField(GetCursorPos());
										else cursorPos = pNVTBuf->GetBeginOfField(GetCursorPos());
									  }
									UpdateCursor();
									break;

	case      IDS_SELHOME:  /* Select Text into Home */
									if (lineBehavior)
									 {
									  /* Move Cursor to First Line Position */
									  newPoint.x = 0;
                             newPoint.y = cursorLine;
									 }
									 else
									  {
										if (IsMode3270())
										  newPoint = p3270Buf->GetBeginOfField(GetCursorPos());
										else newPoint = pNVTBuf->GetBeginOfField(GetCursorPos());
									  }
									SetSelection(newPoint);
									cursorPos = newPoint;
									UpdateCursor(false); //Do Note Remove Selection
									break;

	case    IDS_CURSOREND: /* Cursor End Movement  */
								  if (lineBehavior)
									{
									 /* Move Cursor to Last Line Position */
									 cursorPos.x = scrLineSize-1;
									}
									else
									 /* Move Cursor to End of Current Field */
									  {
										if (IsMode3270())
										  cursorPos = p3270Buf->GetEndOfField(GetCursorPos());
										else cursorPos = pNVTBuf->GetEndOfField(GetCursorPos());
									  }
								  UpdateCursor();
								  break;

	case       IDS_SELEND: /* Select Text into End */
								  if (lineBehavior)
									{
									 /* Move Cursor to 1st Pos of Next Line Position */
									 cursorCol = 0;
									 NextLine(cursorLine, 0, scrNumLines-2);
									}
									else
									 {
									  /* Move Cursor to Next Pos after End of Field */
									  if (IsMode3270())
										  newPoint = p3270Buf->GetEndOfField(GetCursorPos());
									  else newPoint = pNVTBuf->GetEndOfField(GetCursorPos());
									  cursorCol = newPoint.x;
									  cursorLine = newPoint.y;
									  if (!NextCol(cursorCol, scrLineSize, 2))
										 NextLine(cursorLine, 0, scrNumLines-2);
									 }
									newPoint.x = cursorCol;
									newPoint.y = cursorLine;
									SetSelection(newPoint);
									cursorPos = newPoint;
									UpdateCursor(false); //Do Note Remove Selection
									break;

	case    IDS_BACKSPDEL: /* BackSpace one character removing it */

								  /* First of All Selection Must Be Removed */
								  RemoveSelection(true,false,false);
								  if (IsMode3270())
									  fdBegin = p3270Buf->DataFromKeyboard(&blank, 1, false);
								  else
									 {
									  /* If NVT is in Remote Echo Mode Must send BS to SERVER */
									  if (remoteEcho)
										{
										 ::SendMessage(tParent->HWindow,MSG_OUTPUT_ECHO,BS,0);
										 return true;
										}
									  else fdBegin = pNVTBuf->DataFromKeyboard(&blank, 1, false);
									 }
								  /* Update Terminal Screen */
								  if (UpdateScreen(fdBegin,LASTUPDATED,CHARUPDATED))
									{
									 cursorPos.x = cursorCol;
									 cursorPos.y = cursorLine;
									}
								  else return false;
								  /* For completing operation Normal BackSpace should be done */

	case    IDS_BACKSPACE: /* BackSpace one character */
								  if (!PrevCol(cursorCol, scrLineSize))
										PrevLine(cursorLine, 0, scrNumLines-2);
								  cursorPos.x = cursorCol;
								  cursorPos.y = cursorLine;
								  UpdateCursor();
								  break;

	case        IDS_RESET: /* Reset Keyboard */
                          KillCursor();
								  ::GetKeyboardState(keyboardState);
                          if (keyboardState[VK_INSERT] & 0x01)
                           {
                            keyboardState[VK_INSERT] &= 0xFE;  // turn low_order bit off
                            ::SetKeyboardState(keyboardState);
                            theApp->SetInsertMode(false);
									 insertMode = false;
									 nCursor = nNormCursor;
									}
								  SetCursor();
                          UnlockKeyboard();
								  break;

	case    IDS_NEXTFIELD: /* Get Next Unprotected field */
								  if (IsMode3270())
									 cursorPos = p3270Buf->GetNextUnprotField(GetCursorPos());
								  else cursorPos = pNVTBuf->GetNextUnprotField(GetCursorPos());
								  UpdateCursor();
								  break;

	case    IDS_PREVFIELD: /* Get Previous Unprotected field */
								  if (IsMode3270())
									  cursorPos = p3270Buf->GetPrevUnprotField(GetCursorPos());
								  else cursorPos = pNVTBuf->GetPrevUnprotField(GetCursorPos());
								  UpdateCursor();
								  break;

	case        IDS_CLEAR: /* Clear Function do some preliminary procedures */
								  if (IsMode3270())
									{
									 p3270Buf->ClearBuf();
									 cursorPos = p3270Buf->GetCursorPos();
									}
								  else
									{
									 pNVTBuf->ClearBuf();
									 cursorPos = pNVTBuf->GetCursorPos();
									}
								  RemoveSelection(true,false,false);
								  PaintScreen();
								  LockKeyboard();
								  if (IsMode3270())
									 p3270Buf->CommandKey(Parent->HWindow,command);
								  else pNVTBuf->CommandKey(Parent->HWindow,command);
								  break;

	case IDS_ENTERCOMMAND: /* AID Functional Command Pressed */
	case IDS_PF1         :
	case IDS_PF2         :
	case IDS_PF3         :
	case IDS_PF4         :
	case IDS_PF5         :
	case IDS_PF6         :
	case IDS_PF7         :
	case IDS_PF8         :
	case IDS_PF9         :
	case IDS_PF10        :
	case IDS_PF11        :
	case IDS_PF12        :
	case IDS_PF13        :
	case IDS_PF14        :
	case IDS_PF15        :
	case IDS_PF16        :
	case IDS_PF17        :
	case IDS_PF18        :
	case IDS_PF19        :
	case IDS_PF20        :
	case IDS_PF21        :
	case IDS_PF22        :
	case IDS_PF23        :
	case IDS_PF24        :
	case IDS_PA1         :
	case IDS_PA2         :
	case IDS_PA3         :
	case IDS_SYSREQ      : /* System Request:  Has no meaning on TELNET */
	case IDS_ATTN			: /* Function Keys: Should be processed in 3270/NVT  Object */
								  RemoveSelection(true,false,false);
								  LockKeyboard();
								  if (IsMode3270())
									 p3270Buf->CommandKey(Parent->HWindow,command);
								  else pNVTBuf->CommandKey(Parent->HWindow,command);
								  break;
	case IDS_PRINTSCREEN	: /*
									* This is a normal Print Command: Should be
									* processed as it was activated from Tec3270 Menu.
									*/
								  wClient = GetApplication()->GetMainWindow()->
												GetClientWindow();
								  if (wClient)
									 wClient->SendMessage(WM_COMMAND, CM_ALFFPRINT, 0);

								  break;
	case IDS_PREVWORD		: /* Get Previous word begin (It not depends upon
									  Field Start and do wrap around the screen) */
								  if (IsMode3270())
									 cursorPos = p3270Buf->GetPrevWord(GetCursorPos());
								  else cursorPos = pNVTBuf->GetPrevWord(GetCursorPos());
								  UpdateCursor();
								  break;
	case IDS_NEXTWORD		: /* Get Next word begin (It not depends upon
									  Field Start and do wrap around the screen) */
								  if (IsMode3270())
									 cursorPos = p3270Buf->GetNextWord(GetCursorPos());
								  else cursorPos = pNVTBuf->GetNextWord(GetCursorPos());
								  UpdateCursor();
								  break;
	case IDS_NEWLINE		: /* Moves the Cursor to the 1st position of Next Line */
								  cursorPos.x = 0;
								  NextLine(cursorLine, 0, scrNumLines-2);
                          cursorPos.y = cursorLine;
								  UpdateCursor();
								  break;

	case IDS_INSERTCHAR	: /* Turn Insertion Mode On/Off */
   							  KillCursor();
                          ::GetKeyboardState(keyboardState);
                          if (keyboardState[VK_INSERT] & 0x01)
                           {
                            insertMode = true;
									 nCursor = nInsCursor;
									}
                          else
                           {
                            insertMode=false;
									 nCursor = nNormCursor;
                           }
                          theApp->SetInsertMode(insertMode);
								  SetCursor();
								  break;

	case IDS_FIELDMARK	: /* Insert a Field Mark (0x1e-EBCDIC) on current
									  buffer position and advance cursor to next
									  unprotected buffer position. Insertion Mode
									  is ignored to perform this operation. */
								  if (IsMode3270())
									{
									 /* First of All Selection Must Be Removed */
									 RemoveSelection(true,false,false);

									 /* Insert Field Mark */
									 fdBegin = p3270Buf->DataFromKeyboard(fdMark, 1, false);

									 /* Update Terminal Screen */
									 return (UpdateScreen(fdBegin,LASTUPDATED,CHARUPDATED));
									}
								  break;

	case IDS_FIELDEND		: /* Move Cursor to End of Current Field */
								  if (IsMode3270())
									 cursorPos = p3270Buf->GetEndOfField(GetCursorPos());
								  else cursorPos = pNVTBuf->GetEndOfField(GetCursorPos());
								  UpdateCursor();
								  break;

	case IDS_ERASINPUT	: /* Erase All Unprotected Fields on Screen */
								  if (IsMode3270())
									{
									 cursorPos = p3270Buf->EraseAllUnprot();
									 UpdateCursor();
									 PaintScreen(); //Invalidate();
									}
                          // else has no meaning on NVT Mode: ignored
								  break;

	case IDS_ERASEOF		: /* Erase from cursor position to end of field */
								  if (IsMode3270())
									  fdBegin = p3270Buf->DelBufferChar(DELTOPOSITION,ENDOFFIELD);
								  else fdBegin = pNVTBuf->DelBufferChar(DELTOPOSITION,ENDOFFIELD);
								  /* Update Terminal Screen */
								  return (UpdateScreen(fdBegin,LASTUPDATED,TOENDOFFIELD));

	case IDS_DUP			: /* Insert a Dup Mark (0x1c-EBCDIC) on current
									  buffer position and advance cursor to next
									  unprotected buffer position. Insertion Mode
									  is ignored to perform this operation. */
								  if (IsMode3270())
									{
									 /* First of All Selection Must Be Removed */
									 RemoveSelection(true,false,false);

									 /* Insert Dup Mark */
									 fdBegin = p3270Buf->DataFromKeyboard(dupMark, 1, false);

									 /* Update Terminal Screen */
									 if (UpdateScreen(fdBegin,LASTUPDATED,CHARUPDATED))
									  {
										/* Dup Key needs an Tab operation after entering its
										  code on 3270 buffer */
										cursorPos = p3270Buf->GetNextUnprotField(GetCursorPos());
										UpdateCursor();
										return true;
									  }
									  else return false;
									}
                          // else has no meaning on NVT Mode: ignored
								  break;

	case IDS_DELWORD		: /* Delete current word (cursor must be under word that
									  doesn't begin  or end outside line boundaries */
								  if (IsMode3270())
									  fdBegin = p3270Buf->DelWord();
								  else fdBegin = pNVTBuf->DelWord();

								  if (fdBegin >= 0)
									{
									 /* Update Terminal Screen */
									 return (UpdateScreen(fdBegin,LASTUPDATED,TOENDOFFIELD));
									}
								  else
                           {
                            switch(fdBegin)
										  {
											case PROTECTEDFIELD: strcpy(err,PROTECTEDFD);
																		LockKeyboard(err);
																		break;
											case WORDNOTFOUNDTHISLINE: pMsgs->Message(IDS_WORDNOTFOUNDTHISLINE,IDS_ALFFSESSTITLE);
																				break;
											default: pMsgs->Message(IDS_WORDUNEXPECTEDERR,IDS_ALFFSESSTITLE);
										  }
								    return false;
                           }

	case IDS_DEL			: /* If there is no Text Selected
									*   Delete Current Cursor Position on 3270 Buffer
									*  else Delete Selected Text
									*/
								  if (!blkMarked)
									{
									 if (IsMode3270())
										fdBegin = p3270Buf->DelBufferChar();
									 else fdBegin = pNVTBuf->DelBufferChar();
									}
								  else
									{
									 if (!blkInverse)
									  {
										cursorPos = startSel;
										bufEndSel = endSel.y*scrLineSize+endSel.x;
									  }
									 else
									  {
										cursorPos = endSel;
										bufEndSel = startSel.y*scrLineSize+startSel.x;
									  }

									 /* Remove All Screen Selection with no updates */
									 RemoveSelection(false,false,false);

									 /* Update 3270 Buffer Cursor Position */
									 curPos = (cursorPos.y*scrLineSize)+cursorPos.x;

									 if (IsMode3270())
									  {
										p3270Buf->SetCursorPos(curPos);
										/* Delete Buffer From Cursor to end of selection
										  (Not Included)*/
										fdBegin = p3270Buf->DelBufferChar(DELTOPOSITION,bufEndSel);
									  }
									 else
									  {
										pNVTBuf->SetCursorPos(curPos);
										/* Delete Buffer From Cursor to end of selection
										  (Not Included)*/
										fdBegin = pNVTBuf->DelBufferChar(DELTOPOSITION,bufEndSel);
									  }

									}

								  /* Check For Unsuccessful Operation */
								  if (fdBegin == PROTECTEDFIELD)
									{
									 strcpy(err,PROTECTEDFD);
									 LockKeyboard(err);
									 return false;
									}

								  /* Del Operation was done: Update Terminal Screen */
								  PaintScreen();
								  return true;

	case IDS_DECIMALPOINT: /* This command will supply the decimal signal (.) */
								  /* First of All, Selection Must Be Removed */
								  RemoveSelection(true,false,false);

								  if (IsMode3270())
									 fdBegin = p3270Buf->DataFromKeyboard(".", 1, insertMode);
								  else fdBegin = pNVTBuf->DataFromKeyboard(".", 1, insertMode);

								  /* Update Terminal Screen */
								  //If insertMode == true then it means TOENDOFFIELD(1=true)
								  //   else it means CHARUPDATED(0=false)
								  return (UpdateScreen(fdBegin,LASTUPDATED, insertMode));

	case IDS_CURSEL		: /* Cursor Style Selection */
								  ChangeCursor();
								  break;

	case IDS_CBPASTE		: /* ClipBoard Paste Operations */
								  if (tParent && !IsKeyboardLocked() && IsConnected() && !lockedCursor)
									{
									 if (::OpenClipboard(HWindow))
									  {
										if (::GetClipboardData(CF_TEXT))
                               {
                                 ::CloseClipboard();
								   		tParent->SendMessage(WM_COMMAND,CM_ALFFEDITPASTE,0);
                                 // cursorPos wiil be updated on UpdateScreen() method
                                 // called from parent.
                               }
                              else ::CloseClipboard();
									  }
									}
								  break;

	case IDS_CBCUT		   : /* ClipBoard Cut Operation */
								  if (tParent && IsTextSelected() && IsConnected())
									 tParent->SendMessage(WM_COMMAND,CM_ALFFEDITCUT,0);
								  break;

	case IDS_CBCOPY		: /* ClipBoard Copy Operation */
								  if (tParent && IsTextSelected()&& IsConnected())
									 tParent->SendMessage(WM_COMMAND,CM_ALFFEDITCOPY,0);
								  break;

	case IDS_DIVIDEOPER	: /* This command will supply the divide signal (/) */

								  /* First of All, Selection Must Be Removed */
								  RemoveSelection(true,false,false);
								  if (IsMode3270())
									 fdBegin = p3270Buf->DataFromKeyboard("/", 1, insertMode);
								  else fdBegin = pNVTBuf->DataFromKeyboard("/", 1, insertMode);

								  /* Update Terminal Screen */
								  //If insertMode == true then it means TOENDOFFIELD(1=true)
								  //   else it means CHARUPDATED(0=false)
								  return (UpdateScreen(fdBegin,LASTUPDATED, insertMode));


	case IDS_TIMES			: /* This command will supply the times signal (*) */

								  /* First of All, Selection Must Be Removed */
								  RemoveSelection(true,false,false);
								  if (IsMode3270())
									  fdBegin = p3270Buf->DataFromKeyboard("*", 1, insertMode);
								  else fdBegin = pNVTBuf->DataFromKeyboard("*", 1, insertMode);

								  /* Update Terminal Screen */
								  //If insertMode == true then it means TOENDOFFIELD(1=true)
								  //   else it means CHARUPDATED(0=false)
								  return (UpdateScreen(fdBegin,LASTUPDATED, insertMode));


	case IDS_PLUS			: /* This command will supply the plus signal (+) */

								  /* First of All, Selection Must Be Removed */
								  RemoveSelection(true,false,false);
								  if (IsMode3270())
									  fdBegin = p3270Buf->DataFromKeyboard("+", 1, insertMode);
								  else fdBegin = pNVTBuf->DataFromKeyboard("+", 1, insertMode);

								  /* Update Terminal Screen */
								  //If insertMode == true then it means TOENDOFFIELD(1=true)
								  //   else it means CHARUPDATED(0=false)
								  return (UpdateScreen(fdBegin,LASTUPDATED, insertMode));


	case IDS_SUBTRACTOPER: /* This command will supply the subtract signal (-) */

								  /* First of All, Selection Must Be Removed */
								  RemoveSelection(true,false,false);
								  if (IsMode3270())
									 fdBegin = p3270Buf->DataFromKeyboard("-", 1, insertMode);
								  else fdBegin = pNVTBuf->DataFromKeyboard("-", 1, insertMode);

								  /* Update Terminal Screen */
								  //If insertMode == true then it means TOENDOFFIELD(1=true)
								  //   else it means CHARUPDATED(0=false)
								  return (UpdateScreen(fdBegin,LASTUPDATED, insertMode));


	case IDS_CENT			: /* This command will supply the cent signal (¢) */

								  /* First of All, Selection Must Be Removed */
								  RemoveSelection(true,false,false);
								  if (IsMode3270())
									 fdBegin = p3270Buf->DataFromKeyboard("¢", 1, insertMode);
								  else fdBegin = pNVTBuf->DataFromKeyboard("¢", 1, insertMode);

								  /* Update Terminal Screen */
								  //If insertMode == true then it means TOENDOFFIELD(1=true)
								  //   else it means CHARUPDATED(0=false)
								  return (UpdateScreen(fdBegin,LASTUPDATED, insertMode));

	default              : /* Do not process commands not available */
								  return false;
  }
 return true;
}

/*
The VkKeyScan function:
======================
UINT VkKeyScan(uChar)
---------------------

UINT uChar;	/* character to translate

It translates a Windows character to the corresponding
virtual-key code and shift state for the current keyboard.

Parameter	Description
---------   -----------
uChar	      Specifies the character to be translated to a
				virtual-key code.

Returns
-------

The return value is the virtual-key code and shift state,
if the function is successful. The low-order byte contains
the virtual-key code; the high-order byte contains the shift
state, which can be one of the following:

Value		Meaning
-----		-------
1			Character is shifted.
2			Character is a control character.
3-5		Shift-key combination that is not used for characters.
6			Character is generated by the CTRL+ALT key combination.
7			Character is generated by the SHIFT+CTRL+ALT key combination.

If no key is found that translates to the passed Windows code,
the return value is -1.

Comments
--------
Translations for the numeric keypad (VK_NUMPAD0 through
VK_DIVIDE) are ignored. This function is intended to
force a translation for the main keyboard only.
*/


void
ALFFVirtualTerm::EvChar(UINT key, UINT, UINT
#ifdef TRACEKEYBOARD
	 flags
#endif
)
{
 if (IsConnected() && !IsKeyboardLocked() && !IsLogOn() && !lockedCursor)
  {
	char chCharCode = (TCHAR)key;    // character code
#ifdef TRACEKEYBOARD
	BYTE sCode;
	UINT vKey;
	bool shift;
	bool ctrl;
	if (GetKeyState(VK_SHIFT) < 0)
	  shift = true;
	if (GetKeyState(VK_CONTROL) < 0)
	  ctrl = true;
	sCode = LOBYTE(flags);
	vKey = VkKeyScan(chCharCode);
	LogEv("<EvChar>",key,LOBYTE(vKey), sCode,shift,ctrl,false); //DEBUG
#endif
	if (key >= VK_SPACE)
	 {
	  RemoveSelection(true,false,false);  //Do Not Update Cursor Position
	  char byte = chCharCode; // & 0x7f;
	  int fdBegin;

	  if (IsMode3270())
		{
		 fdBegin = p3270Buf->DataFromKeyboard(&byte, 1, insertMode);
		 /* Update Terminal Screen */
		 //If insertMode == true then it means TOENDOFFIELD(1=true)
		 //   else it means CHARUPDATED(0=false)
		 UpdateScreen(fdBegin,LASTUPDATED,insertMode);
		}
	  else
		{
		 if (!remoteEcho)
		  {
			fdBegin = pNVTBuf->DataFromKeyboard(&byte, 1, insertMode);
			/* Update Terminal Screen */
			//If insertMode == true then it means TOENDOFFIELD(1=true)
			//   else it means CHARUPDATED(0=false)
			UpdateScreen(fdBegin,LASTUPDATED,insertMode);
		  }
		 else ::SendMessage(tParent->HWindow,MSG_OUTPUT_ECHO,key,0);
		}
	 }
  }
}

void
ALFFVirtualTerm::EvKeyDown(UINT vkey, UINT, /*repeatCount*/
								 UINT
#ifdef TRACEKEYBOARD
					flags
#endif
)
{
 unsigned int command;
 bool shift = false;
 bool ctrl = false;
 bool altgr = false;
 char* keyText;
 char* scptFileName;
 int fdBegin;

 if (IsConnected())
  {
	ResetTimer();
	if (GetKeyState(VK_SHIFT) < 0)
	 shift = true;
	if (GetKeyState(VK_CONTROL) < 0)
	 ctrl = true;
	if (shift && ctrl)
	 {
	  shift = false;
	  ctrl  = false;
	  altgr = true;
	 }
	command = pKeyboard->GetCommand(vkey,shift,ctrl,false,altgr);
#ifdef TRACEKEYBOARD
	BYTE sCode;
	sCode = LOBYTE(flags);
	// On eventkeydown key is the virtual key
	LogEv("<EvKeyDown>",vkey,vkey,sCode,shift,ctrl,false,command); //DEBUG
#endif
	if (command > IDS_COMMBASE)
	 {
	  /* This is an Function Keyboard Command */
	  ProcessCommand(command);
	 }
	else if (command > IDS_KEYBASE)
			{
			 /* First of All, Selection Must Be Removed */
			 RemoveSelection(true,false,false);
			 /* This is an Remapped Key */
			 char byte = HEX(command-IDS_KEYBASE);
			 if (IsMode3270())
				fdBegin = p3270Buf->DataFromKeyboard(&byte, 1, insertMode);
			 else fdBegin = pNVTBuf->DataFromKeyboard(&byte, 1, insertMode);

			 /* Update Terminal Screen */
			 //If insertMode == true then it means TOENDOFFIELD(1=true)
			 //   else it means CHARUPDATED(0=false)
			 UpdateScreen(fdBegin,LASTUPDATED,insertMode);
			}
	else if (command == TEXTKEY)
			{
			 keyText = pKeyboard->GetKeyText(vkey,shift,ctrl,false,altgr);
			 if (keyText)
			  {
				/* First of All, Selection Must Be Removed */
				RemoveSelection(true,false,false);
				if (IsMode3270())
				  fdBegin = p3270Buf->DataFromKeyboard(keyText, strlen(keyText), insertMode);
				else fdBegin = pNVTBuf->DataFromKeyboard(keyText, strlen(keyText), insertMode);

				/* Update Terminal Screen */
				if (fdBegin >= 0)
					PaintScreen();
				else
				  {
					 char err[12];
					 if (fdBegin == PROTECTEDFIELD)
						  strcpy(err,PROTECTEDFD);
					 else if (fdBegin == NUMERICFIELD)
							  strcpy(err,NUMERICFD);
					 else strcpy(err,XSYSTEM);
					 LockKeyboard(err);
				  }
			  }
			}
	else if (command == SCPTKEY)
			{
			 scptFileName = pKeyboard->GetKeyText(vkey,shift,ctrl,false,altgr);
			 if (scptFileName)
			  {
				/* This option is not yet implemented.
             * It will be available on future versions. */
			  }
			}
	else return;
  }
}

void
ALFFVirtualTerm::EvKeyUp(UINT /*vkey*/, UINT, /*repeatCount*/
											  UINT /*flags*/ )
{
 return;
}

/*
 * Process WM_SYSKEYDOWN that is generated when VK_MENU is
 *  pressed (generally Alt Key). key contains the key pressed
 *  simultaneously with VK_MENU key.
 */
void
ALFFVirtualTerm::EvSysKeyDown(UINT vkey, UINT, UINT
#ifdef TRACEKEYBOARD
  flags
#endif
)
{
 int command, fdBegin;
 bool shift = false;
 bool ctrl  = false;
 bool alt   = false;
 char* keyText;
 char* scptFileName;

 if (IsConnected() && !IsKeyboardLocked() && !lockedCursor)
  {
	ResetTimer();
	if (GetKeyState(VK_SHIFT) < 0)
	  shift = true;
	if (GetKeyState(VK_CONTROL) < 0)
	  ctrl = true;
	if (GetKeyState(VK_MENU) < 0)
	  alt = true;
#ifdef TRACEKEYBOARD
	BYTE sCode;
	sCode = LOBYTE(flags);
	// On eventsyskeydown key is the virtual key
	LogEv("<EvSysKeyDown>",vkey,vkey,sCode,shift,ctrl,alt); //DEBUG
#endif
	command = pKeyboard->GetCommand(vkey,shift,ctrl,alt,false);
	if (command > IDS_COMMBASE)
	 {
	  /* This is an Function Keyboard Command */
	  ProcessCommand(command);
	 }
	else if (command > IDS_KEYBASE)
			{
			 /* First of All, Selection Must Be Removed */
			 RemoveSelection(true,false,false);

			 /* This is an Remapped Key */
			 char byte = HEX(command-IDS_KEYBASE);
			 if (IsMode3270())
				fdBegin = p3270Buf->DataFromKeyboard(&byte, 1, insertMode);
			 else fdBegin = pNVTBuf->DataFromKeyboard(&byte, 1, insertMode);

			 /* Update Terminal Screen */
			 //If insertMode == true then it means TOENDOFFIELD(1=true)
			 //   else it means CHARUPDATED(0=false)
			 UpdateScreen(fdBegin,LASTUPDATED,insertMode);
			}
	else if (command == TEXTKEY)
			{
			 keyText = pKeyboard->GetKeyText(vkey,shift,ctrl,alt,false);
			 if (keyText)
			  {
				/* First of All, Selection Must Be Removed */
				RemoveSelection(true,false,false);
				if (IsMode3270())
				  fdBegin = p3270Buf->DataFromKeyboard(keyText, strlen(keyText), insertMode);
				else fdBegin = pNVTBuf->DataFromKeyboard(keyText, strlen(keyText), insertMode);

				/* Update Terminal Screen */
				if (fdBegin >= 0)
					PaintScreen();
				 else
				  {
					 char err[12];
					 if (fdBegin == PROTECTEDFIELD)
						  strcpy(err,PROTECTEDFD);
					 else if (fdBegin == NUMERICFIELD)
							  strcpy(err,NUMERICFD);
					 else strcpy(err,XSYSTEM);
					 LockKeyboard(err);
				  }
			  }
			}
	else if (command == SCPTKEY)
			{
			 scptFileName = pKeyboard->GetKeyText(vkey,shift,ctrl,alt,false);
			 if (scptFileName)
			  {
				/* This option is not yet implemented.
             * It will be available on future versions. */
			  }
			}
	else return;
  }
}

void
ALFFVirtualTerm::EvLButtonDown(uint /*modKeys*/, TPoint& point)
{
 if (cursorVisible && IsConnected())
  {
	if (!IsKeyboardLocked() && !lockedCursor)
	 {
	  ResetTimer();
	  TPoint wPoint = point;
	  TPoint newPos;
	  UpdateScroll(wPoint,false);
	  newPos.x = wPoint.x / fontCharWidth;
	  newPos.y = wPoint.y / fontCharHeight;
	  if ((newPos.y < (scrNumLines-1))
		 &&(newPos.x < scrLineSize))
		{
       if ( (blkMarked) && (newPos == endSel) )
        { SetSelection(newPos); }
       else
        {
		   cursorPos = newPos;
		   UpdateCursor(true);
        }
		}
	 }
  }
}

void
ALFFVirtualTerm::EvLButtonDblClk(uint /*modKeys*/, TPoint& /*point*/)
{
 /* At this version Mouse Left Button DoubleClick Does Nothing !! */
 ResetTimer();
}

void
ALFFVirtualTerm::EvRButtonDown(uint /*modKeys*/, TPoint& point)
{
 /* This Version provides a popup menu with utilities functions */
 if (cursorVisible && IsConnected())
  {
   TMenu baseMenu(GetApplication()->GetInstance(),(TResId)IDM_ALFFPOPUP);
   TPopupMenu popUpMenu(baseMenu);
   popUpMenu.TrackPopupMenu(TPM_LEFTALIGN, point.x, point.y,
                          0, tParent->HWindow);
  }
}

/*
MK_CONTROL	Set if CTRL key is down.
MK_LBUTTON	Set if left button is down.
MK_MBUTTON	Set if middle button is down.
MK_RBUTTON	Set if right button is down.
MK_SHIFT	Set if SHIFT key is down.
*/
void
ALFFVirtualTerm::EvMouseMove(uint modKeys, TPoint& point)
{
 TPoint charPoint;
 TPoint wPoint = point;
 ResetTimer();
 if ((modKeys & MK_LBUTTON)&& IsMode3270() && !IsLogOn())
  {
	UpdateScroll(wPoint,false);
	charPoint.y = wPoint.y/fontCharHeight;
	charPoint.x = wPoint.x/fontCharWidth;
	if (charPoint.y < (scrNumLines-1)
	 &&(charPoint != cursorPos))
	  SetSelection(charPoint);
  }
}

bool
ALFFVirtualTerm::NextLine(int& line, int begLine,int endLine, int offset)
{
 line+=offset;
 if (line > endLine)  //(scrNumLines-2))
  {
	line = begLine;
	return false;
  }
  else return true;
}

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

bool
ALFFVirtualTerm::PrevLine(int& line, int begLine, int endLine, int offset)
{
 line-=offset;
 if (line < begLine)
  {
	line = endLine;     //scrNumLines-2;
	return false;
  }
  else return true;
}

bool
ALFFVirtualTerm::PrevCol(int& col, int lineSize, int offset)
{
 col-=offset;
 if (col < 0)
  {
	col = lineSize-1; //scrLineSize-1;
	return false;
  }
  else return true;
}


void
ALFFVirtualTerm::PaintScreen(bool erase)
{
 TClientDC dc(HWindow);
 TRect cRect = GetClientRect();
 if (Scroller)
	Scroller->BeginView(dc,cRect);
#ifdef DEBUG32
	MessageBox("PaintScreen: PaintTerminal...","Tec3270 Debug",MB_OK);
#endif
 PaintTerminal(dc, cRect, erase);
}

void
ALFFVirtualTerm::SetScrLineSize(const int defLSize, const int altLSize)
{
 scrLineSize = defLSize;
 defScrLineSize = defLSize;
 altScrLineSize = altLSize;
}

void
ALFFVirtualTerm::SetScrNumLines(const int defNLines, const int altNLines)
{
 scrNumLines = defNLines+1;
 defScrNumLines = defNLines+1;
 altScrNumLines = altNLines+1;
}

bool
ALFFVirtualTerm::SetScreen(const int newScrType)
{
 if (newScrType != scrType)
  {
   /* Remove Selection Block From Screen and Buffers */
	RemoveSelection(true,false,false);

	/* Temporarily Hide the Cursor */
	KillCursor();
   lockedCursor = true;

	/* New Screen Type Isn't The Same As Anterior Type */
	if (newScrType == DEFAULTSCREEN)
	 {
	  scrLineSize = defScrLineSize;
	  scrNumLines = defScrNumLines;
	 }
	else if (newScrType == ALTERNATESCREEN)
		 {
		  scrLineSize = altScrLineSize;
		  scrNumLines = altScrNumLines;
		 }
	else return false;
	/* Save New Scr Type For Further Updates */
	scrType = newScrType;

	/* Recalculate Screen Font Measures To Fit on Screen Size */
	SetScreenFont();

	/* Reset Screen To New Size */
	TClientDC dc(HWindow);
	TRect cRect = GetClientRect();
	if (Scroller)
	 {
	  Scroller->BeginView(dc,cRect);
	  SetScroll();
	 }

	dc.FillRect(cRect, TBrush(connData->scr3270BkgdColor));
   firstCursor = true;

	/* Restore Cursor On New Screen Size */
   lockedCursor = false;
	SetCursor();

	return true;
  }
  else return false;
}

void
ALFFVirtualTerm::SetCursorPos(const int newCursorPos, bool setCursor)
{
 /* If there is any cursor active we must deactivate it before
  * changing its position.
  */
 bool cursorKilled = false;
 if (setCursor && !lockedCursor)
  {
   KillCursor();
   cursorKilled = true;
  }

 /* Set cursor coordinates */
 cursorPos.y = newCursorPos/scrLineSize;
 cursorPos.x = newCursorPos-(cursorPos.y*scrLineSize);
 if (!IsMode3270())
   nvtCursorPos = cursorPos;

 if (setCursor && cursorKilled)
	SetCursor();
}

void
ALFFVirtualTerm::SetCursorPos(const TPoint newCursorPos, bool setCursor)
{
 /* If there is any cursor active we must deactivate it before
  * changing its position.
  */
 bool cursorKilled = false;
 if (setCursor && !lockedCursor)
  {
   KillCursor();
   cursorKilled = true;
  }

 /* Set cursor coordinates */
 cursorPos.x = newCursorPos.x;
 cursorPos.y = newCursorPos.y;
 if (!IsMode3270())
   nvtCursorPos = cursorPos;

 if (setCursor && cursorKilled)
	SetCursor();
}

unsigned int
ALFFVirtualTerm::GetCursorPos()
{
 /* Set cursor pos relative to zero */
 unsigned int curPos = ((cursorPos.y*scrLineSize)+cursorPos.x);
 curPos += 1;
 curPos -= 1;
 return curPos;
}

void
ALFFVirtualTerm::ClearScr(COLORREF bkgdColor)
{
 /* Remove Selection Block From Screen and Buffers */
 RemoveSelection(true,false,false);

 if (!logOn)
  {
   KillCursor();
   lockedCursor = true;
  }

 /* Reset Screen BackGround To Mode Colors */
 TClientDC dc(HWindow);
 TRect cRect = GetClientRect();
 if (Scroller)
	  Scroller->BeginView(dc,cRect);

 dc.FillRect(cRect, TBrush(TColor(bkgdColor)));
 firstCursor = true;

 if (!logOn)
  {
   lockedCursor = false;
   SetCursor();
  }
}

void
ALFFVirtualTerm::SetMode3270(bool mode)
{
 /* Remove Selection Block From Screen and Buffers */
 RemoveSelection(true,false,false);

 KillCursor();

 lockedCursor = true;

 /* Reset Screen BackGround To Mode Colors */
 TClientDC dc(HWindow);
 TRect cRect = GetClientRect();
 if (Scroller)
	  Scroller->BeginView(dc,cRect);

 if (mode)  // 3270 Mode On
  {
   if (terminalInited)
    {
	  dc.FillRect(cRect, TBrush(connData->scr3270BkgdColor));
     firstCursor = true;
	  mode3270=true;
     SetCursor();
    }
   else mode3270 = false;
  }
 else   // NVT Mode (3270 Mode Off)
  {
    if (IsConnected())
     {
      dc.FillRect(cRect, TBrush(connData->scrBkgdColor));
      firstCursor = true;
      SetCursor();
     }

    mode3270 = false;
    // returning to NVT Mode must assure correct cursor position.
    cursorPos = nvtCursorPos;
  }

 lockedCursor = false;
}

void
ALFFVirtualTerm::UpdateCursor(bool removeSel)
{
 if (removeSel)
	 RemoveSelection(true,false,false); //Reset 3270 or NVT Buffer and Do not reset cursor//

 KillCursor();
 lockedCursor = true;

 int curPos;
 curPos = (cursorPos.y*scrLineSize)+cursorPos.x;
 if (IsMode3270())
	 p3270Buf->SetCursorPos(curPos);
 else
  {
    pNVTBuf->SetCursorPos(curPos);
    nvtCursorPos = cursorPos;
  }
 WriteCursorPos();

 lockedCursor = false;
 SetCursor();
}

void
ALFFVirtualTerm::WriteCursorPos()
{
  TClientDC dc(HWindow);
  if (Scroller)
	{
	 TRect cRect = GetClientRect();
	 Scroller->BeginView(dc,cRect);
	}
  int statCurLine, statCurCol;
  int colCursor, lineCursor;
  char cursorPosString [10];
  dc.SelectObject(*scrFont);
  dc.SetTextColor((connData->scrCharColor));
  if (IsMode3270())
	 dc.SetBkColor(TColor(connData->scr3270BkgdColor));
  else dc.SetBkColor(TColor(connData->scrBkgdColor));
  statCurCol = (((scrLineSize/2)-4) * fontCharWidth);
  statCurLine= statusLinePos;
  colCursor = cursorPos.x+1;
  lineCursor = cursorPos.y+1;
#if (PORTUGUES==1)
  sprintf(cursorPosString,"L:%i C:%i",lineCursor,colCursor);
#elif (ENGLISH==1)
  sprintf(cursorPosString,"R:%i C:%i",lineCursor,colCursor);
#else
#error (ALFFNTSC.CPP) - PORTUGUES or ENGLISH must be defined for using localized resources.
#endif
  dc.TextOut(statCurCol,statCurLine,"            ",12);
  dc.TextOut(statCurCol,statCurLine,cursorPosString,strlen(cursorPosString));
  statCurCol += INSERTPOS*fontCharWidth;
  dc.TextOut(statCurCol,statCurLine,"     ",5);
}

bool
ALFFVirtualTerm::IsKeyboardLocked()
{
 return keyboardLocked;
}

void
ALFFVirtualTerm::UnlockKeyboard()
{
 /* erase "System" in Terminal Status Line */
 TClientDC dc(HWindow);
 if (Scroller)
  {
	TRect cRect = GetClientRect();
	Scroller->BeginView(dc,cRect);
  }
 dc.SelectObject(*scrFont);
 TPoint windowPoint;
 strcpy(charSystem,XSYSTEM);
 char* charBlank = new char[CHARSYSTEMLEN+1];
 memset(charBlank,' ',CHARSYSTEMLEN);
 dc.SetTextColor(TColor(connData->scrCharColor));
 if (IsMode3270())
	dc.SetBkColor(TColor(connData->scr3270BkgdColor));
 else dc.SetBkColor(TColor(connData->scrBkgdColor));
 windowPoint.x = xSystemPos;
 windowPoint.y = statusLinePos;
 dc.TextOut(windowPoint,CLEARSYSTEM,CHARSYSTEMLEN);

 keyboardLocked = false;
 
 delete [] charBlank;
}

void
ALFFVirtualTerm::LockKeyboard(char* err3270)
{
 keyboardLocked = true;
 /* write  "System"  in Terminal Status Line */
 TClientDC dc(HWindow);
 if (Scroller)
  {
	TRect cRect = GetClientRect();
	Scroller->BeginView(dc,cRect);
  }
 dc.SelectObject(*scrFont);
 TPoint windowPoint;
 if (err3270)
	strcpy(charSystem,err3270);
 dc.SetTextColor(TColor(connData->scrCharColor));
 if (IsMode3270())
	dc.SetBkColor(TColor(connData->scr3270BkgdColor));
 else dc.SetBkColor(TColor(connData->scrBkgdColor));
 windowPoint.x = xSystemPos;
 windowPoint.y = statusLinePos;
 dc.TextOut(windowPoint,charSystem,CHARSYSTEMLEN);
}

void
ALFFVirtualTerm::DisplayField(const Field* field, TDC& dc,
									 const COLORREF bgColor,
									 const int lineSize,
									 const int scrBegLine,
									 const int scrEndLine,
									 const int fCharWidth,
									 const int fCharHeight,
									 bool  eraseLine)
{
 TPoint windowPoint;
 int textLen, outLen,currentLine, currentCol;
 char* outText;
 bool underLined = false;
 Field blkField;
 TFont* boldFont = NULL;

  /*
	* If could get a field show it on real screen
	*/
  if (field)
  {
	/* Display The Field */
	outText = field->fdText;
	textLen = strlen(outText);
	currentCol   = field->fdPosition.x;
	currentLine  = field->fdPosition.y;

	/* If asked for do erase all field line */
	if (eraseLine)
	 {
	  char erasedLine[MAXLINESIZE];
	  memset(erasedLine,' ',lineSize);
	  windowPoint.x = 0;
	  windowPoint.y = (currentLine * fCharHeight);
	  dc.SetBkColor(TColor(bgColor));
	  dc.SetTextColor(TColor(bgColor));
	  dc.TextOut(windowPoint,erasedLine,lineSize);
	 }


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

	/*--------------------------------------------------------------------*
	 * Only "3270 Extended HighLight" 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(TColor(field->fdTextColor));
							dc.SetTextColor(TColor(field->fdBkgdColor));
							break;

	  case   EHBLINK: /* Blinking Field */
							dc.SetTextColor(TColor(field->fdTextColor));
							dc.SetBkColor(TColor(field->fdBkgdColor));
							blkField = *field;
							blkField.fdEffects = EHDEFAULT;
                     if (field->fdEffects & EHHIGHLIGHT)
                      blkField.fdEffects |= EHHIGHLIGHT;
							screenBlink.Add(blkField);
							break;

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

   /* Verify if field color must be intensified */
   if (field->fdEffects & EHHIGHLIGHT)
    {
      uint red,redInc, green,greenInc, blue,blueInc;

      /* Increase color intensity */
      red = GetRValue(field->fdTextColor);
      green = GetGValue(field->fdTextColor);
      blue = GetBValue(field->fdTextColor);

      // RED
      redInc = (red * 4)/10;
      if ((red + redInc) > 255)
      red = 255;
      else red += redInc;
      // GREEN
      greenInc = (green * 4)/10;
      if ((green + greenInc) > 255)
      green = 255;
      else green += greenInc;
      // BLUE
      blueInc = (blue * 4)/10;
      if ((blue + blueInc) > 255)
         blue = 255;
      else blue += blueInc;
      if (fdEffects != EHREVERSE)
         dc.SetTextColor(TColor(red,green,blue));
      else dc.SetBkColor(TColor(red,green,blue));
    }

   // Do display the field
	while(textLen)
	 {
	  windowPoint.x = (currentCol  * fCharWidth);
	  windowPoint.y = (currentLine * fCharHeight);
	  if (textLen > lineSize)
		{
		 if (currentCol > 0)
			{
			 outLen = lineSize - currentCol;
			 dc.TextOut(windowPoint,outText,outLen);
			 if (underLined)
			  {
				TPen pen(TColor(field->fdTextColor));
				dc.SelectObject(pen);
				dc.MoveTo(windowPoint.x, windowPoint.y+fCharHeight-2);
				dc.LineTo(windowPoint.x+(outLen*fCharWidth),
							 windowPoint.y+fCharHeight-2);
				dc.RestorePen();
			  }
			 outText+=outLen;
			 textLen-=outLen;
			 currentCol = 0;
			 NextLine(currentLine, scrBegLine, scrEndLine);
			}
		  else
			{
			 dc.TextOut(windowPoint,outText,lineSize);
			 if (underLined)
			  {
				TPen pen(TColor(field->fdTextColor));
				dc.SelectObject(pen);
				dc.MoveTo(windowPoint.x, windowPoint.y+fCharHeight-2);
				dc.LineTo(windowPoint.x+(lineSize*fCharWidth),
							 windowPoint.y+fCharHeight-2);
				dc.RestorePen();
			  }
			 outText+=lineSize;
			 textLen-=lineSize;
			 NextLine(currentLine, scrBegLine, scrEndLine);
			}
		}
	  else
		{
		 if ((currentCol+textLen) > lineSize)
		  {
			  outLen = lineSize-currentCol;
			  dc.TextOut(windowPoint,outText,outLen);
			  if (underLined)
				{
				 TPen pen(TColor(field->fdTextColor));
				 dc.SelectObject(pen);
				 dc.MoveTo(windowPoint.x, windowPoint.y+fCharHeight-2);
				 dc.LineTo(windowPoint.x+(outLen*fCharWidth),
							  windowPoint.y+fCharHeight-2);
				 dc.RestorePen();
				}

			  outText+=outLen;
			  textLen-=outLen;
			  currentCol = 0;
			  NextLine(currentLine, scrBegLine, scrEndLine);
			 }
			else
			 {
			  dc.TextOut(windowPoint,outText,textLen);
			  if (underLined)
				{
				 TPen pen(TColor(field->fdTextColor));
				 dc.SelectObject(pen);
				 dc.MoveTo(windowPoint.x, windowPoint.y+fCharHeight-2);
				 dc.LineTo(windowPoint.x+(textLen*fCharWidth),
							  windowPoint.y+fCharHeight-2);
				 dc.RestorePen();
				}

			  outText+=textLen;
			  textLen-=textLen;
			 }
		} // else (if textLen > scrLineSize)

	 }  // while (textLen)

   // Restore actual font after using bold font
   if (boldFont)
    {
     delete boldFont;
     boldFont = NULL;
     dc.SelectObject(*scrFont);
    }

  }  // if (field)
}

void
ALFFVirtualTerm::DisplayStatusLine(TDC& dc)
{
 TPoint windowPoint, beginStatusLine, endStatusLine;

 /* Trace Status Line Separator */
 TPen pen(TColor(connData->scrCharColor));
 dc.SelectObject(pen);
 beginStatusLine.x = 0;
 beginStatusLine.y = statusLinePos-1;
 //beginStatusLine.y = (scrNumLines-1) * fontCharHeight;
 dc.MoveTo(beginStatusLine);
 endStatusLine.x = scrLineSize * fontCharWidth;
 endStatusLine.y = statusLinePos-1;
 //endStatusLine.y = (scrNumLines-1) * fontCharHeight;
 dc.LineTo(endStatusLine);
 dc.RestorePen();

 /* Write Comm line active indicator */
 windowPoint.x = 0;
 windowPoint.y = statusLinePos;

 if (IsMode3270() && !IsLogOn())
  {
	dc.SetTextColor(TColor(connData->scr3270BkgdColor));
	dc.SetBkColor(TColor(connData->scrCharColor));
	dc.TextOut(windowPoint,"4 A",3);
	dc.SetTextColor(TColor(connData->scrCharColor));
	dc.SetBkColor(TColor(connData->scr3270BkgdColor));
	dc.TextOut(windowPoint.x+(1*fontCharWidth), windowPoint.y,"-",1);
  }
 else
  {
	dc.SetTextColor(TColor(connData->scrCharColor));
	dc.SetBkColor(TColor(connData->scrBkgdColor));
	dc.TextOut(windowPoint,"NVT",3);
  }

 /* If Keyboard is Locked then show "X SYSTEM" */
 if (keyboardLocked)
  {
	windowPoint.x = xSystemPos;
	dc.TextOut(windowPoint,charSystem,CHARSYSTEMLEN);
  }

 /* Update Cursor Position  */
 if (!IsLogOn())
	WriteCursorPos();

 /* Display Terminal Model */
 char terModel[STRINGMSGLEN];
 char termText[STRINGMSGLEN];
 if (IsMode3270())
	pMsgs->LoadString(IDS_ALFFTERMBASE+connData->termType+1,terModel,STRINGMSGLEN);
 else
	{
	 pMsgs->LoadString(IDS_ALFFTERMBASE+1,terModel,STRINGMSGLEN);
	 memset(&terModel[15],NULL,1);
	}
 strcpy(termText,"<");
 strcat(termText,terModel);
 strcat(termText,">");
 windowPoint.x = (scrLineSize-strlen(termText))*fontCharWidth;
 dc.TextOut(windowPoint,termText,strlen(termText));
}

void
ALFFVirtualTerm::Paint(TDC& dc, bool erase, TRect& pRect)
{
  PaintTerminal(dc,pRect, erase);
}

void
ALFFVirtualTerm::PaintTerminal(TDC& dc, TRect& pRect, bool /*erase*/)
{
 TPoint windowPoint;
 TRect  clipRect;
 TRect  invRect;

 int fromPos = 0;
 Field* fdPaint;

#ifdef DEBUG32
	MessageBox("PaintTerminal: Starting...","Tec3270 Debug",MB_OK);
#endif
 if (!terminalInited)
   return;
 /*
  * For repainting all screen we should do some housekeeping ...
  */
 KillCursor();

 /* Set the Screen Background */
 if (IsMode3270() && !IsLogOn())
  {
#ifdef DEBUG32
	MessageBox("PaintTerminal: IsMode3270 & !GetLogon..","Tec3270 Debug",MB_OK);
#endif
	/* If in 3270 mode should get data from 3270 buffer .. */
	SetBkgndColor(TColor(connData->scr3270BkgdColor));
	dc.SetTextColor(TColor(connData->scrCharColor));
	dc.SetBkColor(TColor(connData->scr3270BkgdColor));
//	if (erase || blkMarked)
//    {
	  dc.FillRect(pRect, TBrush(connData->scr3270BkgdColor));
     firstCursor = true;
//    }
  }
  else
	{
#ifdef DEBUG32
	MessageBox("PaintTerminal: !IsMode3270...","Tec3270 Debug",MB_OK);
#endif
	   /* Else should get data from NVT buffer ... */
	   SetBkgndColor(TColor(connData->scrBkgdColor));
	   dc.SetTextColor(TColor(connData->scrCharColor));
	   dc.SetBkColor(TColor(connData->scrBkgdColor));
	   dc.FillRect(pRect, TBrush(TColor(connData->scrBkgdColor)));
      firstCursor = true;
	}

  /* Reset "Blinking" Fields Container */
 screenBlink.Flush();
 blink = false;

 /* Set Screen  Font */
 dc.SelectObject(*scrFont);

 bool endPainting = false;
 bool firsTime = true;
 int  firstFd = -1;
#ifdef DEBUG32
	MessageBox("PaintTerminal: while(!endPainting),..","Tec3270 Debug",MB_OK);
#endif

 while (!endPainting)
 {
  /*
	* Get a field from 3270 Screen Buffer if in 3270 Mode
	* or get a field from terminal screen container if not
	*/
  if (IsMode3270() && !IsLogOn())
	{
     // 3270 Mode (TN3270 or TN3270E connection)
#ifdef DEBUG32
	MessageBox("PaintTerminal-while(endPainting): IsMode3270 & !GetLogon..","Tec3270 Debug",MB_OK);
#endif
	  /* This Connection is connected in a 3270 Mode */
	  fdPaint = p3270Buf->DataToScreen(fromPos,REGULARFIELD); //suboption doesn't matter;
	  if (firsTime)
		{
		 firsTime = false;
		 firstFd  = (fdPaint->fdPosition.y*scrLineSize)+fdPaint->fdPosition.x;
		}
	  DisplayField(fdPaint,dc,connData->scr3270BkgdColor,
						scrLineSize, 0, scrNumLines-2,
						fontCharWidth, fontCharHeight);
	  if (fromPos == firstFd)
		{
		 /* Show the 3270 Status Line */
		 DisplayStatusLine(dc);

		 /* If there is any selected text show it ! */
		 if (blkMarked)
			InvertScrColor(dc,startSel,endSel,true);

		 endPainting = true;
		}
	}
  else // NVT Mode (Connected or not)
	{
#ifdef DEBUG32
	MessageBox("PaintTerminal-while(endPainting): NotConnected or NVT Mode...","Tec3270 Debug",MB_OK);
#endif
	  /* This Connection Ins't connected or in NVT Mode */
	  fdPaint = pNVTBuf->DataToScreen(fromPos,REGULARFIELD); //suboption doesn't matter;
	  int fdPos =  (fdPaint->fdPosition.y*scrLineSize)+fdPaint->fdPosition.x;

	  /* Change Field Colors To Current Session Colors */
	  fdPaint->fdTextColor = connData->scrCharColor;
	  fdPaint->fdBkgdColor = connData->scrBkgdColor;

	  if (firsTime)
		{
#ifdef DEBUG32
	MessageBox("PaintTerminal-while(endPainting): firsTime...","Tec3270 Debug",MB_OK);
#endif
		 firsTime = false;
		 firstFd  = fdPos;
		 DisplayField(fdPaint,dc,connData->scrBkgdColor,
						  scrLineSize, 0, scrNumLines-2,
						  fontCharWidth, fontCharHeight);
		}
	  /* Show the NVT Status Line and selected text only if it is connected */
	  else
		{
#ifdef DEBUG32
	MessageBox("PaintTerminal-while(endPainting): Not firsTime...","Tec3270 Debug",MB_OK);
#endif
		 if (fdPos == firstFd)
		  {
#ifdef DEBUG32
	MessageBox("PaintTerminal-while(endPainting): (fdPos==firstFd)","Tec3270 Debug",MB_OK);
#endif
			if (IsConnected())
			 {
#ifdef DEBUG32
	MessageBox("PaintTerminal-while(endPainting): DisplayStatusLine","Tec3270 Debug",MB_OK);
#endif
			  DisplayStatusLine(dc);
			  /* If there is any selected text show it ! */
			  if (blkMarked)
				 InvertScrColor(dc,startSel,endSel,true);
			 }
#ifdef DEBUG32
	MessageBox("PaintTerminal-while(endPainting): endPainting=true","Tec3270 Debug",MB_OK);
#endif
			endPainting = true;
		  }
		  else DisplayField(fdPaint,dc,connData->scrBkgdColor,
								  scrLineSize, 0, scrNumLines-2,
								  fontCharWidth, fontCharHeight);
		}
	}
 } // while (!endPainting)

#ifdef DEBUG32
 MessageBox("PaintTerminal: SetCursor","Tec3270 Debug",MB_OK);
#endif
 SetCursor();

#ifdef DEBUG32
 MessageBox("PaintTerminal: dc.RestoreFont","Tec3270 Debug",MB_OK);
#endif
 dc.RestoreFont();
}

void
ALFFVirtualTerm::UpdateScroll(TPoint& winPos, bool convertToScrolled)
{
 long xScrollOffset = 0;
 long yScrollOffset = 0;
 if (Scroller)
  {
	yScrollOffset = Scroller->YPos * Scroller->YUnit;
	xScrollOffset = Scroller->XPos * Scroller->XUnit;
  }
 if (convertToScrolled)
  {
	winPos.x -= (int)xScrollOffset;
	winPos.y -= (int)yScrollOffset;
  }
 else
  {
	winPos.x += (int)xScrollOffset;
	winPos.y += (int)yScrollOffset;
  }
}

void
ALFFVirtualTerm::BuildCursor(TPoint cursorPos)
{
 TPoint winCursorPos;
 TPoint cursorUnderPos;
 TClientDC dc(HWindow);

 /* Calculate Cursor Window Absolute Coordinates */
 winCursorPos.x = (cursorPos.x * fontCharWidth)-1;
 winCursorPos.y = ((cursorPos.y+1) * fontCharHeight);

 /* Update Cursor Position Relative to Scrolled Window */
 if (Scroller)
   {
 	 TRect cRect = GetClientRect();
 	 Scroller->BeginView(dc,cRect);
   }

 if (horizEffect)
   {
     int xOffset = scrLineSize*fontCharWidth;
     dc.InvertRect(0,winCursorPos.y-1, xOffset, winCursorPos.y);
   }
 if (vertEffect)
   {
    int yOffset = (scrNumLines-1)*fontCharHeight;
    dc.InvertRect(winCursorPos.x,0, winCursorPos.x+1,yOffset);
   }
 firstCursor = false;

 /* Update Window Coordinates to Scrolled Position */
 UpdateScroll(winCursorPos, true);
 SetCaretPos(winCursorPos);
}

void
ALFFVirtualTerm::SetCursor()
{
 if (IsConnected() && !cursorVisible && !lockedCursor)
  {
#ifdef DEBUG32
	MessageBox("SetCursor: MakeCursor...","Tec3270 Debug",MB_OK);
#endif
	switch (nCursor)
    {
	  case nCursorBLOCK: CreateCaret(false,fontCharWidth,-fontCharHeight);
							 break;

	  case nCursorUNDER: CreateCaret(false,fontCharWidth,-2);
							 break;

	  case nCursorVERT : CreateCaret(false,1,-fontCharHeight);
							 break;
    }
   BuildCursor(cursorPos);
   ShowCaret();

	cursorVisible = true;
  }
}

void
ALFFVirtualTerm::KillCursor()
{
 if (IsConnected() && cursorVisible && !lockedCursor)
  {
   TClientDC dc(HWindow);

   /* Save Old Cursor Position for using on Special Effects */
   TPoint oldCursorPos;
   GetCaretPos(oldCursorPos);

   /* Update Cursor Position Relative to Scrolled Window */
   UpdateScroll(oldCursorPos,false);
 	TRect cRect = GetClientRect();
   if (Scroller)
   {
 	 Scroller->BeginView(dc,cRect);
   }

   if (horizEffect)
    {
     int xOffset = scrLineSize*fontCharWidth;
     if (!firstCursor)
        dc.InvertRect(0,oldCursorPos.y-1, xOffset, oldCursorPos.y);
    }
   if (vertEffect)
    {
    int yOffset = ((scrNumLines-1)*fontCharHeight);
    if (!firstCursor)
       dc.InvertRect(oldCursorPos.x,0, oldCursorPos.x+1,yOffset);
    }

	DestroyCaret();
	cursorVisible = false;
  }
}

/*
 * This Event is called by ALFFPRTN to discover maximum number of
 * points on window to be printed...
 */
void ALFFVirtualTerm::EvGetMinMaxInfo (MINMAXINFO far& minmaxinfo)
{
	 Tec3270App *theApp = TYPESAFE_DOWNCAST(GetApplication(), Tec3270App);
	 if (theApp)
	  {
		  if (theApp->Printing)
		  {
				minmaxinfo.ptMaxSize = TPoint(32000, 32000);
				minmaxinfo.ptMaxTrackSize = TPoint(32000, 32000);
				return;
		  }
	 }
	 TWindow::EvGetMinMaxInfo(minmaxinfo);
}

/**************************************************************************
* WhithinRange: Test for Point position within specified Range.           *
**-----------------------------------------------------------------------**
* Input   : X,Y   = Column,Row of cursor reference                        *
*           XT,YT = Column,Row of Upper Left Coordenades of test range    *
*           XB,YB = Column,Row of Lower Right Coordenades of test range   *
* Returns : True if cursor is whithin coordinates, otherwise False        *
**************************************************************************/
bool
ALFFVirtualTerm::WithinRange(const TPoint chkPoint,
								  const TPoint topPoint,
								  const TPoint botPoint)
{
 int X = chkPoint.x; int Y = chkPoint.y;
 int XT = topPoint.x; int YT = topPoint.y;
 int XB = botPoint.x; int YB = botPoint.y;

 if ((Y >= YT) && (Y <= YB))
  {
	if (YT == YB)
	 {
		if ((X >= XT)
		  &&(X <= XB))
		  return true;
		else return false;
	 }
	 else
	 {
	  if (Y == YT)
		{
		 if (X < XT)
			 return false;
		  else return true;
		}
		else
		 {
		  if (Y == YB)
			{
			 if (X <= XB)
				 return true;
			  else return false;
			}
			else return true;
		 }
	 }
  }
  else return false;
}

/**************************************************************************
* SetSelection: Sets Text Selection Range                                 *
**-----------------------------------------------------------------------**
* Input   : newPoint -> New Point to end the selection                    *
* Process : Calculate the New Selection Range and Update Screen for       *
*           showing new selection Range.                                  *
* Returns : Nothing.                                                      *
**************************************************************************/
void
ALFFVirtualTerm::SetSelection(TPoint newPoint)
{
 /* Note: UpdateScrSel is a method that invert pixel colors within the
			 interval frompoint,topoint and is used either to invert bg and
			 text colors or to restore original colors.

 /* If there is no selection before this method is called then initialize
  * selection controls and save initial position */
 if (!blkMarked)
  {
	blkMarked = true;
	blkInverse = false;
	startSel = cursorPos;
	endSel = cursorPos;
  }
 if (blkInverse)
  {
	/* Selection Positions is inversed: end is less than start */
	if (WithinRange(newPoint,endSel,startSel))
	 {
	  /* Selection is being reduced from the end point and we need to
		  restore from endSel to newPoint (reinvert Colors)         */
	  UpdateScrSel(endSel,newPoint,true); //true=Cursor Coordinates//
	 }
	else
	 {
	  if (WithinRange(newPoint,TPoint(0,0),endSel))
		{
		 /* Selection Block is being extended in inverse mode and we need
			 to extend the selection from endsel to newpoint (invert colors) */
		 UpdateScrSel(newPoint,endSel,true); //true=Cursor Coordinates//
		}
		else
		 {
		 /* Selection Block is changing to Direct Mode */
		  blkInverse = false;
		  /* Restore Old selection to original colors */
		  UpdateScrSel(endSel,startSel,true); //true=Cursor Coordinates//
		  /* Set new selection, inverting bg and text colors */
		  UpdateScrSel(startSel,newPoint,true); //true=Cursor Coordinates//
		 }
	 }
  }
  else
	{
	 /* Selection Positions is direct: end is greater then start */
	if (WithinRange(newPoint,startSel,endSel))
	 {
	  /* Selection is being reduced from the end point and that interval
		  must be removed (reinverted)  */
	  UpdateScrSel(newPoint,endSel,true); //true=Cursor Coordinates//
	 }
	else
	 {
	  if (WithinRange(newPoint,TPoint(0,0),startSel))
		{
		 /* Selection Block is changing to Inverse Mode */
		 blkInverse = true;
		 /* Restore Old selection to original colors */
		 UpdateScrSel(startSel,endSel,true);   //true=Cursor Coordinates//
		 /* Set new selection, inverting bg and text colors */
		 UpdateScrSel(newPoint,startSel,true);   //true=Cursor Coordinates//
		}
	  else  //newPoint is after endSel //
		{
		 /* Selection Block is being extended in direct mode and we need
			 to extend selection to newPoint */
		 UpdateScrSel(endSel,newPoint,true);   //true=Cursor Coordinates//
		}
	 }
	}
 endSel = newPoint;

 /* Update NVT or 3270 Buffer selection */
 if (IsMode3270())
  {
	if (!blkInverse)
	  p3270Buf->SetSelection(startSel,endSel);
	else p3270Buf->SetSelection(endSel,startSel);
  }
 else
  {
	if (!blkInverse)
	  pNVTBuf->SetSelection(startSel,endSel);
	else pNVTBuf->SetSelection(endSel,startSel);
  }

}

/**************************************************************************
* RemoveSelection: Remove Text Selection Range From Screen                *
**-----------------------------------------------------------------------**
* Input   : resetBuf -> true if 3270 Buffer Selection must be reset       *
* Process : Do the same process to set the text selection depending upon  *
*           line or block behavior (InvertRect) because it will return    *
*           screens colors to its original style                          *
* Returns : Nothing.                                                      *
**************************************************************************/
void
ALFFVirtualTerm::RemoveSelection(bool resetBuf, bool up, bool updateCursor)
{
 /* If there is no Selection Active, there is nothing to do */
 if (!blkMarked)
  return;

 KillCursor();
 lockedCursor = true;

 blkMarked = false;
 TClientDC dc(HWindow);
 if (Scroller)
  {
 	TRect cRect = GetClientRect();
 	Scroller->BeginView(dc,cRect);
  }

 /* Return to Normal Screen Colors */
 if (!blkInverse)
	  InvertScrColor(dc,startSel,endSel,true); //true=Cursor Coordinates//
 else InvertScrColor(dc,endSel,startSel,true); //true=Cursor Coordinates//

 /* Set No selection active */
 blkInverse = false;

 if (updateCursor)
  {
	/* Set Cursor Position for next Search Operation */
	if (!up)
	  cursorPos = endSel = startSel;
	 else cursorPos = startSel = endSel;

	/* Update Cursor Position on 3270 Buffer */
	int curPos;
	curPos = (cursorPos.y*scrLineSize)+cursorPos.x;
	if (IsMode3270())
		p3270Buf->SetCursorPos(curPos);
	else
    {
      pNVTBuf->SetCursorPos(curPos);
      nvtCursorPos = cursorPos;
    }
  }

 /* Reset 3270 Buffer Selection if asked for */
 if (resetBuf)
  {
	if (IsMode3270())
	  p3270Buf->SetSelection(-1,-1); //Remove 3270 Buffer Selection
	else pNVTBuf->SetSelection(-1,-1); //Remove NVT Buffer Selection
  }

 lockedCursor = false;
 SetCursor();
}

/**************************************************************************
* InvertScrColor: Invert The Screen Color On Specified Range              *
**-----------------------------------------------------------------------**
* Input   : fromPos, toPos (3270 Buffer Reference of Begin and End of     *
*                           Selected Text)                                *
* Process : Calculate Screen Coordinates and Restore the color of each    *
*           line, verifying selection range on the same line, on several  *
*           lines and inverted ranges (end less than begin).              *
* Returns : Nothing.                                                      *
**************************************************************************/
void
ALFFVirtualTerm::InvertScrColor(TDC& dc,
									  const TPoint fromPoint, const TPoint toPoint,
									  bool convertToScreen)
{
 TPoint scrFromPoint;
 TPoint scrToPoint;
 TPoint xMinMax;

 /* Set Maximun and Minimum Line x Coordinates */
 xMinMax.x = 0;
 xMinMax.y = scrLineSize*fontCharWidth; //xFull//

 if (convertToScreen)
  {
	/* Get Initial Position Referred To Char Positions (Cursor) */
	scrFromPoint.y = fromPoint.y*fontCharHeight;
	scrFromPoint.x = fromPoint.x*fontCharWidth;

	/* Get End Position Referred To Char Positions (Cursor) */
	scrToPoint.y = toPoint.y*fontCharHeight;
	scrToPoint.x = toPoint.x*fontCharWidth;
  }
  else
	{
	 /* Get Initial Position Referred To Screen Positions (Coordinates) */
	 scrFromPoint.y = fromPoint.y;
	 scrFromPoint.x = fromPoint.x;

	 /* Get End Position Referred To Screen Positions (Coordinates) */
	 scrToPoint.y = toPoint.y;
	 scrToPoint.x = toPoint.x;
	}


 /* Check For Line or Block Mode Behavior */
 if (lineBehavior)
  {
	if (scrToPoint.y > scrFromPoint.y)
	 {
	  /* Begin and End of Selected Text are in different lines and the bottom
		  Line is Under the Top Line */

	  /* Select the first line of selected block */
	  dc.InvertRect(scrFromPoint.x, scrFromPoint.y,
						 xMinMax.y, scrFromPoint.y+fontCharHeight);

	  /* Select the lines inside the block selection */
	  for ( int line=scrFromPoint.y+fontCharHeight;
			  line<scrToPoint.y; line+=fontCharHeight )
		{
		 dc.InvertRect(xMinMax.x,line,
							scrLineSize*fontCharWidth,line+fontCharHeight);
		}
	  /* Select the last line of selected block */
	  dc.InvertRect(xMinMax.x,scrToPoint.y,
						 scrToPoint.x,scrToPoint.y+fontCharHeight);
	 }

	 /* Begin and End of Selected Text are in the same line */
	 else if (scrToPoint.y == scrFromPoint.y)
			 dc.InvertRect(scrFromPoint.x,scrFromPoint.y,
								scrToPoint.x,scrToPoint.y+fontCharHeight);

	 else  /* scrToPoint.y < scrFromPoint.y */
	  {
		/* Begin and End of Selected Text are in different lines and the bottom
			Line is Above the Top Line */

		/* Select the first line of selected block */
		dc.InvertRect(scrToPoint.x, scrToPoint.y,
						  xMinMax.y, scrToPoint.y+fontCharHeight);

	  /* Select the lines inside the block selection */
		for (int line=scrToPoint.y+fontCharHeight; line<scrFromPoint.y; line+=fontCharHeight)
		 {
		  dc.InvertRect(xMinMax.x,line,
							 xMinMax.y,line+fontCharHeight);
		 }

		/* Select the last line of selected block */
		dc.InvertRect(xMinMax.x,scrFromPoint.y,
						  scrFromPoint.x,scrFromPoint.y+fontCharHeight);
	  }
  }
  else /* It is BlockMode and so Selection MUST be an Rectangle */
		dc.InvertRect(scrFromPoint.x, scrFromPoint.y,
						  scrToPoint.x, scrToPoint.y+fontCharHeight);

}

/**************************************************************************
* UpdateScrSel: Set Text Selection Range On Screen                        *
**-----------------------------------------------------------------------**
* Input   : fromPos, toPos (3270 Buffer Reference of Begin and End of     *
*                           Selected Text)                                *
* Process : Calculate Screen Coordinates and Inverts the color of each    *
*           line, verifying selection range on the same line, on several  *
*           lines and inverted ranges (end less than begin).              *
* Returns : Nothing.                                                      *
**************************************************************************/
void
ALFFVirtualTerm::UpdateScrSel(const uint fromPos, const uint toPos)
{
 TPoint scrFromPoint;
 TPoint scrToPoint;

 /* Get Initial Position Referred To Char Positions (Cursor) */
 scrFromPoint.y = fromPos/scrLineSize;
 scrFromPoint.x = fromPos - scrFromPoint.y*scrLineSize;
 startSel = scrFromPoint;

 /* Transform them into screen coordinates */
 scrFromPoint.y = scrFromPoint.y*fontCharHeight;
 scrFromPoint.x = scrFromPoint.x*fontCharWidth;

 /* Get End Position Referred To Char Positions (Cursor) */
 scrToPoint.y = toPos/scrLineSize;
 scrToPoint.x = toPos - scrToPoint.y*scrLineSize;
 endSel = scrToPoint;

 /* Transform them into screen coordinates */
 scrToPoint.y = scrToPoint.y*fontCharHeight;
 scrToPoint.x = scrToPoint.x*fontCharWidth;

 TClientDC dc(HWindow);
 if (Scroller)
  {
	TRect cRect = GetClientRect();
	Scroller->BeginView(dc,cRect);
  }

 KillCursor();
 lockedCursor = true;

 /* Invert Screen BackGround and Text Colors */
 InvertScrColor(dc,scrFromPoint,scrToPoint, false); //false=Screen Coordinates//

 lockedCursor = false;
 SetCursor();

 /* Set Active Text Selection (May Be Line or Block Behavior) */
 blkMarked = true;
}


void
ALFFVirtualTerm::UpdateScrSel(const TPoint fromPoint,
									const TPoint toPoint,
									bool  convertToScreen)
{
 TClientDC dc(HWindow);
 if (Scroller)
  {
 	TRect cRect = GetClientRect();
 	Scroller->BeginView(dc,cRect);
  }

 KillCursor();
 lockedCursor = true;

 /* Invert Screen BackGround and Text Colors */
 InvertScrColor(dc, fromPoint,toPoint,convertToScreen);

 lockedCursor = false;
 SetCursor();

 /* Set Active Text Selection (May Be Line or Block Behavior) */
 blkMarked = true;
}










