    // ------------------------------- //
    // -------- Start of File -------- //
    // ------------------------------- //
    // ----------------------------------------------------------- //
    // C++ Source Code File Name: testprog.cpp
    // C++ Compiler Used: MSVC, BCC32, GCC, HPUX aCC, SOLARIS CC
    // Produced By: DataReel Software Development Team
    // File Creation Date: 03/21/1997
    // Date Last Modified: 06/17/2016
    // Copyright (c) 2001-2024 DataReel Software Development
    // ----------------------------------------------------------- //
    // ------------- Program Description and Details ------------- //
    // ----------------------------------------------------------- //
    /*
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
    USA

    This is a test program for the terminal interface class.
    */
    // ----------------------------------------------------------- //
    #include "gxdlcode.h"

    // This directive must be defined to use the terminal I/O class
    #if !defined (__USE_TERMINAL_IO__)
    int main() { return 0; } // No test for native types
    #else

    #include <ctype.h>
    #include <string.h>
    #include "terminal.h"

    #ifdef __MSVC_DEBUG__
    #include "leaktest.h"
    #endif

    const int selections = 10;
    const int functions = 10;
    typedef void (*MF)(); // Function pointer to menu functions

    void Exit();
    void CursorPositionTest(); // Full screen cursor test
    void Dialogs();            // User interface functions
    void InputFunctions();     // Test input functions
    void StatusLine();         // Status line function
    void Justification();      // Test right, left, and center justification
    void VideoTest();          // Test video attributes
    void KBWait();             // Test KBWait function
    void ScanCodes();          // Display keyboard scan codes
    void GetTerm();            // Get the terminal type

    const char *MainMenu[selections] = {
      "(0) - To exit this program",
      "(1) - Cursor position test",
      "(2) - Standard dialog test",
      "(3) - Input function test",
      "(4) - Status line test",
      "(5) - Line justification test",
      "(6) - Video attributes test",
      "(7) - Key board wait test",
      "(8) - Display keyboard scancodes",
      "(9) - Get the terminal type"
    };

    MF MMFunctions[functions] = {
      &Exit,
      &CursorPositionTest, // Full screen cursor test
      &Dialogs,            // User interface functions
      &InputFunctions,     // Test input functions
      &StatusLine,         // Status line function
      &Justification,      // Test right, left, and center justification
      &VideoTest,          // Test video attributes
      &KBWait,             // Test KBWait function
      &ScanCodes,          // Display keyboard scan codes
      &GetTerm             // Get the terminal type
    };

    void Menu()
    {
      const char *title = "TERMINAL CLASS TEST PROGRAM'S MAIN MENU" ;

      Coords *p = new Coords(0, 0);
      p->SetX(terminal->Center(title));
      p->SetY(terminal->ScreenCenter(selections));
      terminal->ClearScreen();
      terminal->Write(title, p->XPos(), p->YPrev());

      for(int i = 0; i < selections; i++)
        terminal->Write(MainMenu[i], p->XPos(), p->YOffset(1));

      terminal->Write((char *)"Press the number of your selection >",
    		  p->XPos(), p->YOffset(2));
      delete p;
    }

    void ProcessArgs()
    {
      int c;
      while(1) {
        Menu();
        c = terminal->GetChar();
        switch(tolower(c)) {
          case '0':
    	(*MMFunctions[0]) (); // Call the appropriate menu function
    	return;
          case '1':
    	(*MMFunctions[1]) (); // Call the appropriate menu function
    	break;
          case '2':
    	(*MMFunctions[2]) (); // Call the appropriate menu function
    	break;
          case '3':
    	(*MMFunctions[3]) (); // Call the appropriate menu function
    	break;
          case '4':
    	(*MMFunctions[4]) (); // Call the appropriate menu function
    	break;
          case '5':
    	(*MMFunctions[5]) (); // Call the appropriate menu function
    	break;
          case '6':
    	(*MMFunctions[6]) (); // Call the appropriate menu function
    	break;
          case '7':
    	(*MMFunctions[7]) (); // Call the appropriate menu function
    	break;
          case '8':
    	(*MMFunctions[8]) (); // Call the appropriate menu function
    	break;
          case '9':
    	(*MMFunctions[9]) (); // Call the appropriate menu function
    	break;
          default:
    	break;
        }
      }
    }

    int main()
    {
    #ifdef __MSVC_DEBUG__
      InitLeakTest();
    #endif

      terminal->init();   // Initialize the terminal

      ProcessArgs();      // Enter main communications loop

      terminal->ClearScreen();
      terminal->finish(); // Restore the terminal before exiting
      return 0;
    }

    void ScanCodes()
    {
      char c; int x, y;
      terminal->ClearScreen();
      x = y = 0;
      terminal->Write((char *)"Displaying keyboard scan codes...", x, y);
      y = y+2;
      terminal->Write((char *)"Type keys. Press Esc when finished",x ,y);
      y = y+2;
      terminal->MoveCursor(x, y);
      while ((c = terminal->GetChar()) != termEscapeKey) {
        y = y+1;
        terminal->Write((char *)"The ", x, y);
        terminal->Write(c);
        terminal->Write((char *)" key value is: ");
        terminal->Write((int)c & 255);
        if(y > terminal->MaxLines()-1) {
          terminal->ClearScreen();
          terminal->Write((char *)"Type keys. Press Esc when finished",0 ,0);
          y = 2;
          terminal->MoveCursor(x, y);
        }
      }
      terminal->ClearScreen();
    }

    void CursorPositionTest()
    {
      terminal->ClearScreen();

      const char Pop = '*';     // Display cursor position character
      short x = 0, y = 0;
      unsigned char lastc = 0;
      unsigned char c = 0;
      char *sl = "U-up, D-down, L-left, R-right, Esc to quit...";
      int len = strlen(sl);

      while (c != termEscapeKey) {
        terminal->StatusLine(sl);
        terminal->Write((char *)"x: ", len + 5, terminal->MaxLines()-1);
        terminal->Write(x);
        terminal->Write((char *)" y: ");
        terminal->Write(y);
        terminal->MoveCursor(x, y);
        c = terminal->GetChar();
        switch (tolower(c))	{
          case ' ': case '\r':
    	terminal->Write(Pop, x, y);
    	terminal->PutBack(lastc);
    	break;
          case 'u': // up cursor
    	if (y-- == 0) y = terminal->MaxLines()-1;
    	lastc = c;
    	break;
          case 'd': // down cursor
    	if (++y == terminal->MaxLines()-1) y = 0; // Avoid  status line
    	lastc = c;
    	break;
          case 'l': // left cursor
    	if (x-- == 0) x = terminal->MaxCols()-1;
    	lastc = c;
    	break;
          case 'r': //  right cursor
    	if (++x == terminal->MaxCols()) x = 0;
    	lastc = c;
    	break;
          default:
    	break;
        }
      }
      terminal->ClearScreen();
    }

    void VideoTest()
    {
      int x, y;
      x = y = 0;
      terminal->ClearScreen();
      terminal->Write((char *)"Testing video attributes...", x, y);
      y = y+2;
      terminal->StandOut((char *)"Stand Out video mode", x, y);
      y = y+2;
      terminal->Write((char *)"Normal text", x, y);
      y = y+2;
      terminal->AnyKey(x, y);
      terminal->ClearScreen();
    }

    void Justification()
    {
      terminal->ClearScreen();
      terminal->Write((char *)"Testing left, center, and right justification", 0, 0);
      char *fox = "This quick brown fox jumps over the lazy dog";
      char *nums = "0123456789";
      char *alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

      terminal->Write(nums, 0, 2);
      terminal->Write(nums, terminal->Center(nums), 4);
      terminal->Write(nums, terminal->Right(nums), 6);

      terminal->Write(alpha, 0, 8);
      terminal->Write(alpha, terminal->Center(alpha), 10);
      terminal->Write(alpha, terminal->Right(alpha), 12);

      terminal->Write(fox, 0, 14);
      terminal->Write(fox, terminal->Center(fox), 16);
      terminal->Write(fox, terminal->Right(fox), 18);

      terminal->AnyKey(0, 20);
      terminal->ClearScreen();
    }

    void InputFunctions()
    {
      terminal->ClearScreen();
      Coords *pos = new Coords(0, 0);
      terminal->Write((char *)"Testing input functions...", pos->XPos(), pos->YPos());

      terminal->Write((char *)"Enter a string: ", pos->XPos(), pos->YOffset(2));
      char buf[81];
      terminal->GetString(buf);
      terminal->Write((char *)"You entered: ", pos->XPos(), pos->YOffset(2));
      terminal->Write(buf);

      terminal->Write((char *)"Enter a password: ", pos->XPos(), pos->YOffset(2));
      terminal->GetPassword(buf);
      terminal->Write((char *)"You entered: ", pos->XPos(), pos->YOffset(2));
      terminal->Write(buf);

      terminal->Write((char *)"Enter a number: ", pos->XPos(), pos->YOffset(2));
      int num = terminal->GetInt();
      terminal->Write((char *)"You entered: ", pos->XPos(), pos->YOffset(2));
      terminal->Write(num);

      terminal->Write((char *)"Enter a floating point number: ",
    		  pos->XPos(), pos->YOffset(2));
      double fp = terminal->GetFloat();
      terminal->Write((char *)"You entered: ", pos->XPos(), pos->YOffset(2));
      terminal->Write(fp);

      terminal->AnyKey(pos->XPos(), pos->YOffset(2));
      terminal->ClearScreen();
      delete pos;
    }

    void KBWait()
    {
      terminal->ClearScreen();
      terminal->Write((char *)"Testing KBWait() function...", 0, 0);
      terminal->AnyKey(0, 1);

      int i, j = 0;
      for(;;) { // Continue processing until any key is pressed
        for(i = 0; i < terminal->MaxCols(); i++) {
          terminal->Write('*', i, j);
        }
        j++;
        if(terminal->KBWait()) break;
      }
      terminal->ClearScreen();
    }

    void Dialogs()
    {
      Coords *pos = new Coords(0, 0);
      terminal->ClearScreen();
      terminal->Write((char *)"Testing standard dialogs functions...",
    		  pos->XPos(), pos->YPos());

      int yn = terminal->YesNo(pos->XPos(), pos->YOffset(2));
      if(yn)
        terminal->Write((char *)"You pressed \'y\' to continue",
    		    pos->XPos(), pos->YOffset(2));

      terminal->MoveCursor(pos->XPos(), pos->YOffset(2));
      yn = terminal->YesNo();
      if(!yn)
        terminal->Write((char *)"You pressed \'n\' not to continue",
    		    pos->XPos(), pos->YOffset(2));

      terminal->AnyKey(pos->XPos(), pos->YOffset(2));

      terminal->ClearScreen();
      delete pos;
    }

    void StatusLine()
    {
      terminal->ClearScreen();
      terminal->Write((char *)"Testing status line functions...",0, 0);
      terminal->StatusLine((char *)"Normal mode bottom, left justified status line");
      terminal->AnyKey(0, 2);
      terminal->ClearScreen();
    }

    void GetTerm()
    {
      terminal->ClearScreen();
      if(getenv("TERM")) {
        terminal->Write((char *)"The TERM variable is set: ", 0, 0);
        terminal->Write(terminal->GetTerm());
      }
      else
        terminal->Write((char *)"The TERM variable is not set.", 0, 0);

      terminal->Write((char *)"The maximum number of lines = ", 0, 1);
      terminal->Write(terminal->MaxLines());
      terminal->Write((char *)"The maximum number of columns = ", 0, 2);
      terminal->Write(terminal->MaxCols());
      terminal->AnyKey(0, 4);
      terminal->ClearScreen();
    }

    void Exit()
    {
      return;
    }

    #endif // __USE_TERMINAL_IO__
    // ----------------------------------------------------------- //
    // ------------------------------- //
    // --------- End of File --------- //
    // ------------------------------- //