LUCA: Reusable Communications Code
by Bennett M. Griffin

Listing One
// We define our own Terminal Port here as a subclass of LUCA's Vport
// class.  active() is called from the main loop as often as possible
// to send characters out the port.

class TermPort : public Vport
{
public:
       TermPort(char *link_identifier, char esc_char); // create link
  int  active(); // while it's active, do something else
private:
  int  is_active;
  char escape;
  // overloaded event handlers
  void OnCONNECT();
  void OnDISCONNECT();
  void OnCANREAD();
  void OnNONSTD();
  void OnERROR();
};
int main(int argc, char **argv)
{
  char link_identifier[255];
  TermPort *port;
  cout << "To use this simple terminal example, you have to enter " << endl;
  cout << "a LUCA Link Identifier." << endl << endl;

  // Get a new link identifier from the user or command line.
  if (argc == 1) { 
    cout << "Link Identifier (enter 'quit' to exit):"
    cin >> link_identifier;
  }
  else strcpy(link_identifier, argv[1]);

  // Main loop for communication.  0x1b is the ESC key.
  port = new TermPort(link_identifier, 0x1b);
  while (port->active()) Sleep(50);
  delete port;

  cout << "Press any key to return to the operating system." << endl << flush;
  char c = getch();
  return 0;
}

Listing Two
TermPort::TermPort(char *link_identifier, char esc_char)
{
  char errorstr[255];

  // Tell the user how to disconnect

  escape = esc_char;
  cout << "Terminal mode.  Hit"
  if (escape < 32) {
    if (escape == 0x1b)
       cout << "ESC";
    else
       cout << "Ctrl-" << (char)(escape+"@");
    }
  else
    cout << escape;
  cout << " to disconnect." << endl;
  cout << "Wait for connect..." << endl;
  if ((Vopen(link_identifier)) < 0) {
    // oops, it failed.
    Verror(errorstr);
    cout << "No connection: " << errorstr << endl;
    is_active = 0;
  } else {
    is_active = 1;
  }
}


Listing Three
int TermPort::active()
{
  // Try and fetch a character from the keyboard and sent it to port.

  if (is_active) {
    if (kbhit()) {
      char c = getch();
      if (c == escape) {
        is_active = 0;
        cout << "Closing connection." << endl;
        Vclose();
      } else if Vwrite(&c, 1) < 0) {
        cout << "Write Error" << endl;
        is_active = 0;
      }
    }
  }
  return is_active;
}


Listing Four
void TermPort::OnCANREAD()
{
  // If we can read, we'll send all data to the console screen.
  unsigned char buffer[8192];

  int n = Vread(buffer, sizeof(buffer));
  if (n > 0) {
    buffer[n] = '\0';
    cout << buffer << flush;
  } else if (n == 0) {
    cout << "Read EOF" << endl << flush;
  } else {
    cout << "Read Error" << endl << flush;
  }
}


Listing Five
void TermPort::OnDISCONNECT()
{
  // The connection was lost.  Inform the user what happened and print
  // all communications parameters that were used on this connection.
  char param[256];
  char value[256];
  int n;

  cout << "The following parameters were used:" << endl;

  n = Vgetpar("", param);
  while (n > 0) {
    Vgetpar(param, value);
    cout << "        " << param << " = " << value << endl;
    n = getpar("+", param);
  }
  cout << "Disconnected." << endl << flush;


Listing Six
void TermPort::OnCONNECT()
{
  // everything went well
  cout << "Connected." << endl << flush;
}
void TermPort::OnNONSTD()
{
  // something extra came up -- print it.
  char eventname[255];
  if (Vgetpar("NONSTD", eventname) >= 0) {
    cout << "Non Standard Event: " << eventname << endl << flush;
  }
}
void TermPort::OnERROR()
{
  // Something else went wrong.  Close down for good measure.
  char err[255];

  Verror(err);
  cout << "Error! " << err << endl << flush;
  is_active = 0;
  Vclose();
}


