Intercepting data before it reaches the terminal

To intercept data before it reaches the terminal can be a useful technique to control what is seen to the users.  Nonprintable characters can be converted to readable hex values, data coming in from the com port can be parsed and displayed in a more usable format. 

The TAdTerminal component will automatically attempt to find a port (either a TApdComPort or a TApdWinsockPort) when it is created.  To control what data is being displayed on the terminal, we need to break this link.

Fortunately, this is an easy thing to do.  You will want to set the ComPort property to nil.  This can be done before or after the port has been opened.  It is probably best to null out the ComPort property before opening the port.

Delphi
  AdTerminal1.ComPort := nil;
  ApdWinsockPort1.Open := True;
C++ Builder
  AdTerminal1->ComPort = NULL;
  ApdWinsockPort1->Open;

Once this is done, the terminal will no longer respond to data coming in from the port, nor will it send keystrokes from the user to the port.  It is necessary to rebuild the links to the port.  To get data from the com port to the terminal, you will need to manually send it to the terminal on the portís OnTriggerAvail event.

Delphi
procedure TForm1.ApdWinsockPort1TriggerAvail(CP: TObject; Count: Word);
var
  i : Integer;
begin
  for i := 1 to Count do begin
    AdTerminal1.WriteChar (ApdWinsockPort1.GetChar);
end;
C++ Builder
void __fastcall TForm1::ApdWinsockPort1TriggerAvail(TObject *CP,
      WORD Count)
{
  for (int i = 0; i < Count; i++)
    AdTerminal1->WriteChar (ApdWinsockPort1->GetChar()); 
}

To send keystrokes from the terminal back to the port, you will need to manually send them to the port from one of the terminalís OnKeyxxx events.  If you want the terminal to be read only, you will not need to do this.

If you set the terminalís HalfDuplex property to false, you will need to handle displaying the characters that user types.  This can be a useful technique for controlling what the terminal displays in reaction to the userís keystrokes.

Delphi
procedure TForm1.AdTerminal1KeyPress(Sender: TObject; var Key: Char);
begin
  ApdWinsockPort1.PutChar (Key);
  AdTerminal1.WriteChar (Key);
end;
C++ Builder
void __fastcall TForm1::AdTerminal1KeyPress(TObject *Sender, char &Key)
{
  ApdWinsockPort1->PutChar (Key);
  AdTerminal1->WriteChar (Key);        
}

At this point we now have a terminal that responds as if it was really connected to the port, but with easy access to the data flowing back and forth to the terminal.  If we wanted to convert non printable characters coming in from the port to a more readable form, we could do something like the following in the portís OnTriggerAvail event.

Delphi

 

procedure TForm1.ApdWinsockPort1TriggerAvail(CP: TObject; Count: Word);
var
  i : Integer;
  c : Char;
begin
  for i := 1 to Count do begin
    c := ApdWinsockPort1.GetChar;
    if (c < #$20) or (c > #$7e) then
      AdTerminal1.WriteString ('[' + 
                               IntToHex (Ord (c), 2) + 
                               ']')
    else
      AdTerminal1.WriteChar (c);
  end;
end;
C++ Builder
void __fastcall TForm1::ApdWinsockPort1TriggerAvail(TObject *CP,
      WORD Count)
{
  char c;
  for (int i = 0; i < Count; i++) {
    c = ApdWinsockPort1->GetChar ();
    if (c < 0x20 || c > 0x7e)
      AdTerminal1->WriteString (Format ("[%02.2x]",
                                        ARRAYOFCONST (((int) c))));
    else
      AdTerminal1->WriteChar (c);
  }
}

 

We can do the same thing in the Terminalís OnKeyxxx event to cause any non printable characters typed (like Escape) on the terminal to be displayed in hex.

Delphi
procedure TForm1.AdTerminal1KeyPress(Sender: TObject; var Key: Char);
begin
  ApdWinsockPort1.PutChar (Key);
  if (Key < #$20) or (Key > #$7e) then
    AdTerminal1.WriteString ('[' + IntToHex (Ord (Key), 2) + ']')
  else
    AdTerminal1.WriteChar (Key);
end;
C++ Builder
void __fastcall TForm1::AdTerminal1KeyPress(TObject *Sender, char &Key)
{
  ApdWinsockPort1->PutChar (Key);
  if (Key < 0x20 || Key > 0x7e)
    AdTerminal1->WriteString (Format ("[%02.2x]",
                                      ARRAYOFCONST (((int) Key))));
  else
    AdTerminal1->WriteChar (Key);
}

Another way this technique can be used is to color characters coming in from the port one color and those being typed from the user.  For this, you will need a TAdVT100Emulator component to intercept ANSI escape sequences for color control.

To do this, when you receive characters from the port, you will want to first write the escape sequence to set the color, and then write the character to the terminal.  On the OnKeyxxx event, write the escape sequence to set the color and then the character.

Delphi
procedure TForm1.ApdWinsockPort1TriggerAvail(CP: TObject; Count: Word);
var
  i : Integer;
begin
  AdTerminal1.WriteString (#$1b'[1;32m');
  for i := 1 to Count do 
    AdTerminal1.WriteChar (ApdWinsockPort1.GetChar);
end;
 
procedure TForm1.AdTerminal1KeyPress(Sender: TObject; var Key: Char);
begin
  ApdWinsockPort1.PutChar (Key);
  AdTerminal1.WriteString (#$1b'[1;34m');
  AdTerminal1.WriteChar (Key);
end;
C++ Builder
void __fastcall TForm1::AdTerminal1KeyPress(TObject *Sender, char &Key)
{
  ApdWinsockPort1->PutChar (Key);
  AdTerminal1->WriteString (0x1b + "[1;34m");
  AdTerminal1->WriteChar (Key);
}
 
void __fastcall TForm1::ApdWinsockPort1TriggerAvail(TObject *CP,
      WORD Count)
{
  AdTerminal1->WriteString (0x1b + "[1;32m");
  for (int i = 0; i < Count; i++)
    AdTerminal1->WriteChar (ApdWinsockPort1 -> GetChar ());
}

This technique can be taken further.  It is not necessary to have a port associated with a terminal.  Terminals without ports can be used as consoles to applications, debugging displays for applications, and a host of other uses (I can even imagine a multiline editor with syntax highlighting)

This site is not affiliated, endorsed, or otherwise associated with the entity formerly known as TurboPower Software. The owners and maintainers of Aprozilla.com were merely meager employees of the aforementioned organization, providing this site out of the pure goodness of their collective hearts. SourceForge.net Logo

Last updated: July 22, 2003.