/*
==============================================================================
		      WordUp Graphics Toolkit Version 5.0                     
			     Demonstration Program 38                         
									      
 Shows how to use the communications library.          
 WLINK.CFG must contain the correct information before you can use this                                                                              
 program.  You should modify the file to suit your baud rate and com port.
 

 *** PROJECT ***                                                             
 This program requires the file WGT5_WC.LIB and WCOMM_WC.LIB to be linked.                      º
									      
 *** DATA FILES ***                                                          
 WLINK.CFG                                                                       
							   WATCOM C++ VERSION 
==============================================================================
*/

#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <stdarg.h>
#include <wlink.h>
#include <wgt5.h>

/* Multiplater Link data */
int localplayer = -1, remoteplayer = -1;  /* Either 0 or 1 if connected */



/* Text mode routines */

/* Text mode drawing */
#define SCREENPTR       (char*)0xB8000
#define SCREENWIDTH     80
#define SCREENHEIGHT    25

#define BLACK           0
#define BLUE            1
#define GREEN           2
#define CYAN            3
#define RED             4
#define MAGENTA         5
#define BROWN           6
#define LIGHTGRAY       7
#define DARKGRAY        8
#define LIGHTBLUE       9
#define LIGHTGREEN      10
#define LIGHTCYAN       11
#define LIGHTRED        12
#define LIGHTMAGENTA    13
#define YELLOW          14
#define WHITE           15
#define BLINK           128



static char *textptr = SCREENPTR;
static char textcolor = BLACK<<4+LIGHTGRAY;
int cursorx, cursory;
int textscroll = 1;
int linewrap = 1;

/* Sets the current foreground and background colors */
void setcolor (int forecolor, int backcolor)
{
 textcolor = ((backcolor & 0x0F) << 4) + (forecolor & 0x0F);
}


/* Sets the cursor position */
void set_cursor_pos (short x, short y)
{
union REGS r;

 r.h.ah = 2;
 r.h.bh = 0;
 r.h.dh = y;
 r.h.dl = x;
 int386 (0x10, &r, &r);
}

/* Makes a new starting pointer to the text screen */
void gotoxy (int x, int y)
{
 textptr = SCREENPTR + 2*x + 160*y;
 cursorx = x;
 cursory = y;
}

void advance_cursor (void)
{
 cursorx++;
 if ((cursorx == SCREENWIDTH) && (linewrap))
  {
   cursory++;
   cursorx = 0;
  }
}

/* Draws a single character directly to the screen */
void outchar (char c)
{
 switch (c) {
  case 0:
  case 1:
  case 2:
  case 3:
  case 4:
  case 5:
  case 6: break;
  case 7: sound (400);  /* Bell */
	  delay (20);
	  sound (200);
	  delay (20);
	  nosound ();
	  break;
  case 8: if (cursorx > 0)              /* Backspace */
	    gotoxy (cursorx-1, cursory);
	  break;
  case 9: advance_cursor ();    /* Tab */
	  advance_cursor ();  
	  advance_cursor ();
	  advance_cursor ();
	  break;
  case 10: gotoxy (0, cursory+1); /* Line feed */
	   break;
  case 11:
  case 12: break;
  case 13: gotoxy (0, cursory+1);         /* Carriage return */
	   break;
  case 14:
  case 15:
  case 16:
  case 17:
  case 18:
  case 19:
  case 20:
  case 21:
  case 22:
  case 23:
  case 24:
  case 25:
  case 26:
  case 27:
  case 28:
  case 29:
  case 30:
  case 31: break;
  default: *textptr++ = c;
	   *textptr++ = textcolor;
	   advance_cursor ();
	   break;
  }

 /* Scroll the screen if needed */
 if ((cursory >= SCREENHEIGHT) && (textscroll))
  {
   scroll_text_up ();
   textbox (0, 24, 79, 24, ' ');
   gotoxy (0, SCREENHEIGHT-1);
  }

}

/* Draws a character a number of times in a row */
void repchar (char c, int times)
{
 while (--times >= 0)
   {
    *textptr++ = c;
    *textptr++ = textcolor;
    advance_cursor ();
   }
}


/* Draws a string of text */
void outtext (char *string)
{
 while (*string)
   outchar (*string++);
}


/* Scrolls the screen up */
void scroll_text_up (void)
{
char *source;
char *dest;

 gotoxy (0, 0);
 dest = textptr;
 source = textptr + 160;
 memcpy (dest, source, SCREENWIDTH * (SCREENHEIGHT-1) * 2);
}



/* Draws a filled text box */
void textbox (int x1, int y1, int x2, int y2, char c)
{
int width, height;

 width = x2 - x1 + 1;
 height = y2 - y1 + 1;

 while (--height >= 0)
  {
   gotoxy (x1,y1++);
   repchar (c, width);
  }
}

/* Prints a string with formatting */
void tprintf (char *fmt, ...)
{
va_list  argptr;                     /* Argument list pointer*/
char str[251];                       /* Buffer to build string into*/

 va_start (argptr, fmt);              /* Initialize va_ functions*/

 vsprintf (str, fmt, argptr);         /* prints string to buffer*/
 outtext (str);
 /* Send string in graphics mode */

 va_end (argptr);                     /* Close va_ functions*/
}


/* End of text mode routines */

/* Reads the modem configuration from a file */
void read_config (char *filename)
{
char line[257];
short length;
FILE *config;
short i;
unsigned char *vectorptr;
unsigned long lnum;

 /* Set up the initial values */
 link_info.baud_rate = -1;
 link_info.com_port  = -1;
 link_info.irq_num   = -1;
 link_info.uart      = -1;
 link_info.vector    = -1;

 if ((config = fopen (filename, "r")) == NULL)
  {
   printf ("Could not open wlink.cfg file.");
   exit(1);
  }

 /* Read the modem initialation string */
 fgets (line, 256, config);
 strcpy (link_info.modem_init, line);
 length = strlen (link_info.modem_init) - 1;
 if (link_info.modem_init [length] == '\n')
     link_info.modem_init [length] = '\0';

 /* Read the modem hangup string */
 fgets (line, 256, config);
 strcpy (link_info.modem_hangup, line);
 length = strlen (link_info.modem_hangup) - 1;
 if (link_info.modem_hangup [length] == '\n')
     link_info.modem_hangup [length] = '\0';

/* Read the baud rate */
 fgets (line, 256, config);
 sscanf (line, "%lu", &link_info.baud_rate);
 if (link_info.baud_rate != 9600  && link_info.baud_rate != 14400 &&
     link_info.baud_rate != 19200 && link_info.baud_rate != 38400 &&
     link_info.baud_rate != 57600 && link_info.baud_rate != 115200)
	link_info.baud_rate = 9600;
 /* Default to 9600 baud */

 /* Read the com port */
 fgets (line, 256, config);
 sscanf (line, "%hi", &link_info.com_port);
 printf ("read %hi\n", link_info.com_port);
 if (link_info.com_port < 1 || link_info.com_port > 4)
     link_info.com_port = 1;

 /* Read the IRQ */
 fgets (line, 256, config);
 sscanf (line, "%hi", &link_info.irq_num);

 fclose (config);

 /* If the IRQ or the uart is not known yet, search for it */
 if ((link_info.irq_num == -1) || (link_info.uart == -1))
    wlink_getuart ();
 printf ("Found UART at port 0x%x, irq %d...\n\n",link_info.uart,link_info.irq_num);

 /* Search for the interrupt vector if it wasn't set */
 if (link_info.vector == -1)
    wlink_getvector ();

 if (link_info.vector == WLINK_NOVECTOR)
   {
    printf ("Warning: no NULL or iret interrupt vectors were found in the 0x60 to 0x66\nrange.  Aborting.\n");
    exit (1);
   }

}


/* Print all the communications data for debugging */
void print_link_config (void)
{
 setcolor (WHITE, BLUE);
 textbox (0, 0, 79, 24, ' ');

 gotoxy (30, 0);
 tprintf ("WGT Communications Demo");
 gotoxy (2, 2);
 tprintf("\n\n\n");
 tprintf("MODEM INIT STRING  : %s\n", link_info.modem_init);
 tprintf("MODEM HANGUP STRING: %s\n", link_info.modem_hangup);
 tprintf("BAUD RATE:           %lu\n",link_info.baud_rate);
 tprintf("COM PORT:            %i\n", link_info.com_port);
 tprintf("IRQ NUMBER:          %i\n", link_info.irq_num);
 tprintf("UART:                %i\n", link_info.uart);
 tprintf("VECTOR:              %i\n", link_info.vector);
}


void print_main_menu (void)
{
 gotoxy (0, 15);
 tprintf ("1. Call (Modem)\n");
 tprintf ("2. Answer (Modem)\n");
 tprintf ("3. Call (Direct)\n");
 tprintf ("4. Answer (Direct)\n");
 tprintf ("5. Quit\n");
 tprintf ("Selection:");
 set_cursor_pos (10, 20);
}


/* Send anything typed on the keyboard, and show anything received on the
   screen */
void terminal_mode (void)
{
int c;
char inkey;

 linewrap = 0;
 textbox (0, 0, 79, 24, ' ');
 gotoxy (0, 0);
 tprintf ("Terminal mode...  Press ESC to quit");
 gotoxy (0, 2);
 while (1)
  {
   /* Check for keypress */
   if (_bios_keybrd (1))
    {
     if ((inkey = _bios_keybrd (0) & 0xff) == 27)
     {
      /* ESC key -- Exit terminal mode -- Flush both sides */
      while (wlink_read_byte () != -1);
      while (_bios_keybrd (1))
	 _bios_keybrd (0);
      printf ("\n\n");
      return;
     }
    wlink_write_buffer (&(unsigned char)inkey, 1);
   }
  /* Check for received byte */
 c = wlink_read_byte ();

 if (c != -1)
   outchar (c);

 }
}


/* Split screen chat */
void talk_mode (void)
{
int c;
char inkey;
int rx, ry, lx, ly;

 linewrap = 1;
 setcolor (WHITE, BLUE);
 textbox (0, 0, 79, 24, ' ');
 setcolor (CYAN, BLUE);
 textbox (0, 0, 79, 0, ' ');
 textbox (0, 12, 79, 13, ' ');
 
 gotoxy (0, 1);
 repchar ('²', 80);
 gotoxy (0, 12);
 repchar ('Í', 80);
 gotoxy (0, 14);
 repchar ('²', 80);
 
 gotoxy (34, 0);
 tprintf ("Remote User");
 gotoxy (34, 13);
 tprintf ("Local User");
 
 setcolor (WHITE, BLUE);
 
 lx = 0;        /* Local cursor coordinates */
 ly = 15;
 rx = 0;        /* Remote cursor coordinates */
 ry = 2;
 set_cursor_pos (lx, ly);
 textscroll = 0;  /* turn off text scrolling */

 while (1)
  {
   /* Check for keypress */
   if (_bios_keybrd (1))
    {
     if ((inkey = _bios_keybrd (0) & 0xff) == 27)
     {
      /* ESC key -- Exit terminal mode -- Flush both sides */
      while (wlink_read_byte () != -1);
      while (_bios_keybrd (1))
	 _bios_keybrd (0);
      printf ("\n\n");
      return;
     }
    wlink_write_buffer (&(unsigned char)inkey, 1);
    
    gotoxy (lx, ly);    /* Set the local coordinates */
    outchar (inkey);        /* show the character you typed */
    lx = cursorx;       /* Get the new cursor coords */
    ly = cursory;
    if (ly == SCREENHEIGHT)
      ly = 15;
    if (lx == 0)       /* Erase the line that was previously here */
       textbox (0, ly, 79, ly, ' ');
    set_cursor_pos (lx, ly);
   }
  /* Check for received byte */
 c = wlink_read_byte ();

 if (c != -1)
  {  
   gotoxy (rx, ry);    /* Set the remote coordinates */
   outchar (c);        /* show the character you typed */
   rx = cursorx;       /* Get the new cursor coords */
   ry = cursory;
   if (ry == 12)
      ry = 2;
   if (rx == 0)        /* Erase the line that was previously here */
     textbox (0, ry, 79, ry, ' ');
     
  }
   
 }

 textscroll = 1;  /* Turn text scrolling back on */

}

void dial_number (void)
{
char dialstring[80];

 textbox (0, 0, 79, 24, ' ');
 gotoxy (0, 0);
 tprintf ("Enter the number to dial:");
 set_cursor_pos (26, 0);
 scanf ("%s", dialstring);

 if (wlink_dial (dialstring))
  {  /* connected */
   localplayer = 0;
   remoteplayer = 1;
  }
}


void wait_for_call (void)
{
 textbox (0, 0, 79, 24, ' ');
 gotoxy (0, 0);
 tprintf ("Waiting for call...");

 if (wlink_answer ())
  {  /* connected */
   localplayer = 1;
   remoteplayer = 0;
  }
}


void process_main_menu (void)
{
char c;
int quit;

  quit = 0;

  do {
   c = getch ();

   if (c == '1')
    {
     dial_number ();
     terminal_mode ();
     quit = 1;
    }
   else if (c == '2')
    {
     wait_for_call ();
     terminal_mode ();
     quit = 1;
    }
   else if (c == '3')
    {
     talk_mode ();
     quit = 1;
    }
   else if (c == '4')
    {
     talk_mode ();
     quit = 1;
    }
   else if (c == '5')
    {
     
     quit = 1;
    }


 } while (quit == 0);
}




/* A simple terminal program */
void main (void)
{
 printf ("WGT Example #38\n\n");
 printf ("Uses the communications library to either call a BBS or talk\n");
 printf ("directly across a null modem connection.  For a null modem connection\n");
 printf ("both computers should be running the program and one person will\n");
 printf ("dial while the other answers.\n");
 printf ("** You must modify WLINK.CFG before running this program **\n");
 printf ("\n\nPress any key to continue.\n");
 getch ();

 
 read_config ("wlink.cfg");
 wlink_initport ();

 print_link_config ();
 
 if (link_info.uarttype == WLINK_16550_UART)
   tprintf ("UART is a 16550");
 else
   tprintf ("UART is an 8250");
 
 print_main_menu ();
 process_main_menu ();

 wlink_shutdownport ();
 wsetmode (3);
}





