
#include "vt.h"
#include "user.h"

#include <String.h>

User::User (char* termtype, char* hostname) :
       os(cout),
/* pshuang: replaced
       userWindow(stdscr)
*/
       userWindow()

//       userWindow(userWindow.lines(), userWindow.cols(), 0, 0)
{
  TermHd.userWindow = &userWindow;

  lessThan25 = (userWindow.lines() < 25);

//  isVT100 =  (fcompare(termtype,"vt100")==0) ? 1 : 0;

  isVT100 = 1;

/* pshuang: replaced with below fragment, no refernce to dont_...
  if(isVT100) dont_process_output =1;
  else        pTerm = & TermHd;
*/
  pTerm = &TermVT; // pshuang: default terminal

  readFD.Assign_fd(0);
  readFD.Param_add(CBREAK);
  readFD.Param_remove(ECHO);
  readFD.NonBlocking();
}

fd_set User::readfds ()
{
  fd_set fdset;
  FD_ZERO(&fdset);
  FD_SET(0,&fdset);
  return fdset;
}

/* pshuang: commented out and replaced 6-13-91 8:30pm

   int User::read (char* buf, int nchars)
   {
     return ::read(0,buf,nchars);
   }

*/

// pshuang: code now checks with curses to see if cursor is on
// the correct row for input from BARTON before permitting any input
// Note: possibility for confusion -- curses uses 0,0 as home position
// for the window, but 1,1 for the physical screen?
// Note2: this change may not be very necessary, as User::read only
// gets called when the telnet object returns nothing when read, which
// usually only happens when GEAC is ready to accept input or when the
// network is *VERY* busy.
// Note3: added check to make sure we're using Barton
// Note4: permitted y>BARTON_INPUT_LINE for some of GEAC's help screens

#define BARTON_INPUT_LINE 21

int User::read (char* buf, int nchars)
{
  extern bool InteractWithLibrary;

  if ((pTerm==&TermVTbart) && (InteractWithLibrary))
    {
      int x, y;
      userWindow.getyx(y,x);

      if ((y==BARTON_INPUT_LINE) || ((y>BARTON_INPUT_LINE) && (x<=1)))
	{
	  userWindow.refresh();
	  return ::read(0,buf,nchars);
	}
      else
	{
	  ::read(0,buf,nchars);
            // throw away whatever is in the input buffer;
            // should work since telnet.cc calls upon filedesc.cc
            // to implement non-blocking on inputs.
	  return 0;
            // counting on while loop in Interface::Service to
            // to handle errors in read correctly
	}
    }
  else return ::read(0,buf,nchars);
}


int User::write (char* buf, int nchars)
{
/* pshuang: why not go through Term___ for all cases? Replaced with below code
  if (pTerm != &TermVTbart)
    for (int i = 0; i < nchars; i++) userWindow.addch(buf[i]);
  else
    pTerm->write(buf, nchars);
  receivedSomething += 1;
*/
  pTerm->write(buf,nchars);
  receivedSomething +=1;
}

void User::write_ClearScreen()
{
  userWindow.clear();
  userWindow.move(0, 0);
  userWindow.touchwin();
  userWindow.refresh();

  workingMessageShown = 0;
}

void User::working_message()
{
  // pshuang: modified to only do anything with Barton in VT100

  if (pTerm==&TermVTbart)
    {
      int x, y;
      userWindow.getyx(y, x);
    
      userWindow.move(userWindow.lines() - 1, 0);
      userWindow.clrtoeol();
/* pshuang: commented out for below code
      userWindow.move(userWindow.lines() - 1, userWindow.cols() / 2 - 5);
      userWindow.addstr("working...");
*/
      // pshuang: modified 6-18-91
      userWindow.move(23, userWindow.cols() / 2 - 20);
      userWindow.standout();
      userWindow.addstr("(Working, please be patient...)");
      userWindow.standend();
    
      userWindow.move(y, x);
      userWindow.refresh();

      workingMessageShown = 1;
      receivedSomething = 0;
    }

}

void User::flush ()
{
  // pshuang: modified to only do anything with Barton in VT100

  if (workingMessageShown) {
/* pshuang: 6-20-91 replaced with below code
    if (receivedSomething > 25)
*/
#define WAIT_AFTER_WORKING 80
    if (receivedSomething > WAIT_AFTER_WORKING)
      // pshuang: increased number in hopes of forcing the refresh
      // to wait until cursor is already moved away from input line

      {
	if (pTerm==&TermVTbart)
	  {
	    int x, y;
	    
	    // save the current cursor position
	    userWindow.getyx(y, x);
	    
	    // move to the last line and clear it
	    userWindow.move(userWindow.lines() - 1, 0);
	    userWindow.clrtoeol();
	    
	    // restore saved cursor position
	    userWindow.move(y, x);
	  }
	
	// remember that the message is now not displayed
	workingMessageShown = 0;
      }
  }
  
  // flush Curses window to the user for viewing
  userWindow.refresh();
}

void User::redraw ()
{
  userWindow.refresh();
}

/* pshuang: too convoluted, replaced
void User::Person_is_VT100 (bool yes)
{
  isVT100 =yes;
  dont_process_output =0;
  if(isVT100) {
    if(receivingVT100) {
      if(receivingBarton && VTBartonHack_enabled) pTerm = &TermVTbart;
      else dont_process_output =1;
    }
    else dont_process_output =1; 
  }
  else {
    if(receivingVT100) {
      if(receivingBarton) pTerm = &TermHdbart;
      else                pTerm = &TermHd;
    }
    else dont_process_output =1;
  }
}
*/

void User::Person_is_VT100 (bool isVT100)
{
  // pshuang: eliminated all references to dont_process_output,
  // since there are no other references in code

  status_Person_is_VT100 = isVT100;

  if ((isVT100) && (receivingVT100))
    {
      if (receivingBarton)
	pTerm=&TermVTbart;
      else
	pTerm=&TermVT;
    }
  else
    {
      if (receivingBarton)
	pTerm=&TermHdbart;
      else
	pTerm=&TermHd;
    }

  pTerm->userWindow = &userWindow; // pshuang: added
}

void User::Library_is_VT100 (bool yes)
{
  receivingVT100 = yes;
  Person_is_VT100(isVT100);
}
void User::Now_using_BARTON (bool p)
{
  receivingBarton =p;
  Person_is_VT100(isVT100);
}

void User::VTBartonHack_Enable (bool p)
{
  VTBartonHack_enabled = p;
  Person_is_VT100(isVT100);
}

