#include <8300lib.h>
#include <8xTcpip.h>
#include <ucos.h>

const unsigned char ProgVersion [16] = "D8370-104";

#define   STATE_MAIN                100
#define   STATE_TAKEDATA            200
#define   STATE_SETTING             300
#define   STATE_NETCONFIG           310

#define   SCANNER_PRIORITY          13                  // Scanner
#define   SCANNER_STK_SIZE          500
OS_STACK  Scanner_Stk [SCANNER_STK_SIZE];

unsigned  char ServerIP [4];
unsigned  int  ServerPort;

struct   NETSTATUS  NetStatus;                          // Net Status
struct   NETCONFIG  NetConfig;                          // Net Config
SOCKET   socket1;                                       // Socket

void  Scanner_Task   (void *);
int   Initialize_Net (void);
int   Open_Net       (void);
void  Close_Net      (int);
void  Send_Net       (char *);

void  Main_Menu      (void);
void  Main_Input     (char);
void  Show_TimeStamp (void);

void  TakeData_Menu  (void);
void  TakeData_Input (char);
void  Process_Data   (void);
void  Query_Item     (void);
void  Update_Qty     (void);

void  Setting_Menu    (void);
void  Setting_Input   (char);
void  NetConfig_Menu  (char);
void  NetConfig_Input (char);
void  NetConfig_Save  (void);

void  Numerical_Input (char);
void  Back_Space      (void);
void  Clear_Line      (void);
void  Display_String  (int, int, char *, int);

int   beep1 [4]  = {16, 5, 0, 0};
int   beep2 [8]  = {30, 10, 0, 5, 30, 10, 0, 0};
int   beep3 [12] = {12, 8, 0, 5, 12, 8, 0, 3, 12, 8, 0, 1};

char  szData [1600];
char  szBuf [50];
char  zTime [16];

char  szNetConfig [20];
char  szItem [20];
char  szName [20];
char  szQty [20];

int   CurX = 5;
int   CurY = 3;

int   nNetConfig = 0;
int   nUpdate = 0;
int   nSelection;
int   nStatus;

unsigned long  msec = 0;

//-------------------------------------------------------------------------//
void main (void *data)
    {
    static int  N, timer=0;
    char   day1, day2, c;
    int    i, k;

    socket1 = -1;
    OSTaskCreate (Scanner_Task, (void *) 0, (void *) Scanner_Stk, SCANNER_STK_SIZE, SCANNER_PRIORITY);

    nSelection = 1;
    Main_Menu ();

    while (1)
        {
        if (socket1 >= 0)                           // if socket existed, test if the connection is OK or not
            {
            if (socket_testfin (socket1) || !socket_isopen (socket1) || (socket_rxstat (socket1) & S_FATAL))
                {
                msec = 0;
                Close_Net (0);                      // close connection immediately
                if (!Open_Net ())
                    {
                    nSelection = 1;
                    Main_Menu ();
                    }
                }
            }

        while ((socket1 >= 0) && socket_hasdata (socket1))
            {
            k = msec = 0;
            *szBuf = *szData = 0;                   // Get data
            if (N = recv (socket1, szData, sizeof (szData), 0))
                {
                for (i=0; i<N; i++)
                    {
                    if (szData [i] == '\r')
                        {
                        szBuf [k] = 0;
                        Process_Data ();            // process the data or command
                        k = 0;
                        }
                    else
                        {
                        szBuf [k] = szData [i];
                        k++;
                        }
                    }
                }
            OSTimeDly (10);
            }

        if ((socket1 >= 0) && (msec > 0))
            {
            if (abs ((int) (sys_msec - msec)) > 600)
                {
                msec = 0;
                on_beeper (beep3);
                InitScanner1 ();
                gotoxy (CurX, CurY);
                SetCursor (CURSOR_ON);
                }
            }

        if (c = getchar())
            {
            switch (nStatus)
                {
                case  STATE_MAIN:                       // Main Menu
                      Main_Input (c);
                      break;

                case  STATE_TAKEDATA:                   // Take Data
                      TakeData_Input (c);
                      break;

                case  STATE_SETTING:                    // Setting
                      Setting_Input (c);
                      break;

                case  STATE_NETCONFIG:                  // Net Config
                      NetConfig_Input (c);
                      break;
                }
            }
        else if (nStatus == STATE_MAIN)                 // Main Menu
            {
            timer++;
            timer %= 5;
            if (timer == 0 || timer == 3) 
                {
                get_time (zTime);
                if (day1 != zTime [6] || day2 != zTime [7])
                    {
                    day1 = zTime [6];
                    day2 = zTime [7];
                    Show_TimeStamp ();
                    }
                else
                    {
                    szBuf [0] = zTime [8];
                    szBuf [1] = zTime [9];
                    szBuf [2] = (timer == 0) ? ':' : ' ';
                    szBuf [3] = zTime [10];
                    szBuf [4] = zTime [11];
                    szBuf [5] = 0;
                    SetFont (1);
                    Display_String (14, 7, szBuf, 0);
                    }
                }
            }

        if (nStatus != STATE_TAKEDATA)
            HaltScanner1 ();

        OSTimeDly (20);
        }
    }

//-------------------------------------------------------------------------//
void Scanner_Task (void *data)
    {
    while (1)
        {
        OSTimeDly (20);
        if (Decode ())
            {
            on_beeper (beep1);
            set_led (1, 1, 30);                         // on Green LED
            strcpy (szItem, CodeBuf);
            gotoxy (5, 3);
            printf ("%s", szItem);
            gotoxy (0, 5);
            printf ("Name:          ");
            gotoxy (0, 7);
            printf ("Qty :          ");

            nUpdate = 0;
            szBuf [0] = 'I';
            strcpy (szBuf+1, szItem);
            strcat (szBuf, "\r");
            Send_Net ((void *) szBuf);                  // Query Item

            SetCursor (CURSOR_OFF);
            HaltScanner1 ();
            CurX = strlen (szItem) + 5;
            CurY = 3;
            gotoxy (CurX, CurY);
            }
        }
    }

//-------------------------------------------------------------------------//
int Initialize_Net (void)
    {
    SetCursor (CURSOR_OFF);
    SetVideoMode (0);
    SetFont (2);
    clr_scr ();
    gotoxy (0, 1);
    printf ("Initialize...");
    gotoxy (0, 3);
    printf ("Please wait!");

    NetInit (0L);                                         // initialize Net
    while (1)
        {
        GetNetStatus ((void*) &NetStatus);
        if (NetStatus.IPReady)
            break;

        if (getchar () == KEY_ESC)                      // Press ESC Key
            {
            Close_Net (1);                              // Close Net
            return (0);
            }
        OSTimeDly (4);
        }

    GetNetConfig ((void*) &NetConfig);                  // Get Net Config
    return (1);
    }

//-------------------------------------------------------------------------//
int Open_Net (void)
    {
    struct sockaddr_in  sa;
    static char  szIPAddr [20];

    SetCursor (CURSOR_OFF);
    HaltScanner1 ();
    gotoxy (0, 1);
    printf ("No connection  ");

    sprintf (szIPAddr, "%d.%d.%d.%d", ServerIP [0], ServerIP [1], ServerIP [2], ServerIP [3]);
    while(1) {
        memset (&sa, 0, sizeof (sa));
        socket1 = socket (AF_INET, SOCK_STREAM, 0);
        sa.sin_family      = AF_INET;
        sa.sin_port        = htons (ServerPort);
        sa.sin_addr.s_addr = inet_addr (szIPAddr);
        if (connect (socket1, (struct sockaddr *) &sa, sizeof (sa)) >= 0) break;
        Close_Net (0);
        if (getchar () == KEY_ESC)                      // Press ESC Key
           {
            Close_Net (1);                              // Close Net
            return (0);
           }
        OSTimeDly(200);
    }

    socket_keepalive (socket1, 20000UL);

    on_beeper (beep1);
    gotoxy (0, 1);
    printf ("               ");
    gotoxy (0, 1);
    printf ("%d.%d.%d.%d", NetConfig.IpAddr [0], NetConfig.IpAddr [1], NetConfig.IpAddr [2], NetConfig.IpAddr [3]);

    SetCursor (CURSOR_ON);
    gotoxy (CurX, CurY);
    InitScanner1 ();
    return (1);
    }

//-------------------------------------------------------------------------//
void Close_Net (int nClose)
    {
	socket_noblock(socket1);
    shutdown (socket1, 2);                              // close connection immediately
    closesocket (socket1);
    socket1 = -1;
    if (nClose)  NetClose ();                           // Close Net
    }

//-------------------------------------------------------------------------//
void Send_Net (char *str)
    {
    if (socket_cansend (socket1, strlen (str)))
        {
        socket_push (socket1);
        send (socket1, str, strlen (str), 0);
        SetCursor (CURSOR_OFF);
        msec = sys_msec;
        }
    }

//-------------------------------------------------------------------------//
void Main_Menu (void)
    {
    SetCursor (CURSOR_OFF);
    SetVideoMode (0);
    dis_alpha ();
    clr_scr ();

    SetFont (1);
    gotoxy (0, 0);
    GetNetConfig ((void*) &NetConfig);                  // Get Net Config
    printf ("IP: %d.%d.%d.%d", NetConfig.IpAddr [0], NetConfig.IpAddr [1], NetConfig.IpAddr [2], NetConfig.IpAddr [3]);

    SetFont (2);
    Display_String (0, 3, (char *) "1. Take data   ", (nSelection == 1) ? 1 : 0);
    Display_String (0, 5, (char *) "2. Configure   ", (nSelection == 2) ? 1 : 0);

    Show_TimeStamp ();
    nStatus = STATE_MAIN;
    }

//-------------------------------------------------------------------------//
void Main_Input (char c)
    {
    switch (c)
        {
        case KEY_UP:
             if (nSelection > 1)  nSelection--;
             else                 nSelection = 2;
             Main_Menu ();
             break;

        case KEY_DOWN:
             if (nSelection < 2)  nSelection++;
             else                 nSelection = 1;
             Main_Menu ();
             break;

        case KEY_CR:
             Main_Input ((char) nSelection+'0');
             break;

        case '1':                                       // Take Data
             if (!Initialize_Net ())                    // Initialize Net
                 {
                 nSelection = 1;
                 Main_Menu ();
                 break;
                 }
             if (!Open_Net ())                          // Open Net
                 {
                 nSelection = 1;
                 Main_Menu ();
                 break;
                 }
             TakeData_Menu ();
             break;

        case '2':                                       // Setting
             nSelection = 1;
             Setting_Menu ();
             break;

        default:
             break;
        }
    }

//-------------------------------------------------------------------------//
void Show_TimeStamp (void)
    {
    int  month;

    get_time (zTime);
    month = (zTime [4] - '0') * 10 + zTime [5] - '0';   // month
    switch (month)
        {
        case  1: strcpy (szBuf, "JAN ");     break;
        case  2: strcpy (szBuf, "FEB ");     break;
        case  3: strcpy (szBuf, "MAR ");     break;
        case  4: strcpy (szBuf, "APR ");     break;
        case  5: strcpy (szBuf, "MAY ");     break;
        case  6: strcpy (szBuf, "JUN ");     break;
        case  7: strcpy (szBuf, "JUL ");     break;
        case  8: strcpy (szBuf, "AUG ");     break;
        case  9: strcpy (szBuf, "SEP ");     break;
        case 10: strcpy (szBuf, "OCT ");     break;
        case 11: strcpy (szBuf, "NOV ");     break;
        case 12: strcpy (szBuf, "DEC ");     break;
        }
    szBuf [4] = zTime [6];                              // day
    szBuf [5] = zTime [7];
    szBuf [6] = ',';
    szBuf [7] = ' ';
    szBuf [8] = zTime [0];                              // year
    szBuf [9] = zTime [1];
    szBuf [10] = zTime [2];
    szBuf [11] = zTime [3];
    szBuf [12] = ' ';
    szBuf [13] = ' ';
    szBuf [14] = zTime [8];                             // hour
    szBuf [15] = zTime [9];
    szBuf [16] = ':';
    szBuf [17] = zTime [10];                            // minute
    szBuf [18] = zTime [11];
    szBuf [19] = ' ';
    szBuf [20] = 0;
    SetFont (1);
    Display_String (0, 7, szBuf, 0);
    }

//-------------------------------------------------------------------------//
void TakeData_Menu (void)
    {
    SetVideoMode (0);
    SetFont (2);
    clr_scr ();

    gotoxy (0, 1);
    if (socket1 < 0)  printf ("No connection  ");
    else              printf ("%d.%d.%d.%d", NetConfig.IpAddr [0], NetConfig.IpAddr [1],
                                             NetConfig.IpAddr [2], NetConfig.IpAddr [3]);
    gotoxy (0, 3);
    printf ("Item:          ");
    gotoxy (0, 5);
    printf ("Name:          ");
    gotoxy (0, 7);
    printf ("Qty :          ");
    nStatus = STATE_TAKEDATA;

    SetCursor (CURSOR_ON);
    InitScanner1 ();
    CurX = 5;
    CurY = 3;
    gotoxy (CurX, CurY);
    }

//-------------------------------------------------------------------------//
void TakeData_Input (char c)
    {
    switch (c)
        {
        case KEY_UP:
             if (CurY == 7)
                 {
                 CurX = strlen (szItem) + 5;
                 CurY = 3;
                 gotoxy (CurX, CurY);
                 }
             break;

        case KEY_BS:
             Back_Space ();
             break;

        case KEY_CLEAR:
             Clear_Line ();
             break;

        case KEY_ESC:
             Close_Net (1);                             // Close Net
             nSelection = 1;
             Main_Menu ();
             break;

        case KEY_DOWN:
        case KEY_LEFT:
        case KEY_RIGHT:
        case KEY_F1:
        case KEY_F2:
        case KEY_F3:
        case KEY_F4:
        case KEY_F5:
        case KEY_F6:
        case KEY_F7:
        case KEY_F8:
        case KEY_F9:
             break;

        case KEY_CR:
             if (CurX > 5 && CurY == 3)
                 {
                 Query_Item ();
                 }
             else if (CurX > 5 && CurY == 7)
                 {
                 if (nUpdate)
                     Update_Qty ();
                 TakeData_Menu ();
                 }
             break;

        default:
             Numerical_Input (c);
             break;
        }
    }

//-------------------------------------------------------------------------//
void Process_Data (void)
    {
    char   c;
    int    i, len;

    if (nStatus != STATE_TAKEDATA)
        {
        on_beeper (beep1);
        return;
        }

    switch (szBuf [0])
        {
        case 'D':                                       // got the answer
             nUpdate = 1;
             on_beeper (beep1);
             len = strlen (szBuf);
             i = 1;
             while (i < len)
                 {
                 if (szBuf [i] == ',')
                     break;
                 i++;
                 }

             strncpy (szName, szBuf+1, i-1);            // Name
             szName [i-1] = 0;
             strcpy (szQty, szBuf+i+1);                 // Qty
             gotoxy (5, 5);
             printf ("%s", szName);
             gotoxy (5, 7);
             printf ("%s", szQty);

             SetCursor (CURSOR_ON);
             CurX = strlen (szQty) + 5;
             CurY = 7;
             gotoxy (CurX, CurY);
             break;

        case 'N':                                       // data not found
             strcpy (szName, "**********");
             gotoxy (5, 5);
             printf ("%s", szName);
             gotoxy (5, 7);
             printf ("          ");

             SetCursor (CURSOR_ON);
             CurX = 5;
             CurY = 7;
             gotoxy (CurX, CurY);
             break;

        case 'U':                                       // update ok
             on_beeper (beep2);
             TakeData_Menu ();
             break;

        default:
             return;
        }
    }

//-------------------------------------------------------------------------//
void Query_Item (void)
    {
    SetCursor (CURSOR_OFF);
    HaltScanner1 ();
    gotoxy (0, 5);
    printf ("Name:          ");
    gotoxy (0, 7);
    printf ("Qty :          ");

    nUpdate = 0;
    szItem [CurX-5] = 0;
    szBuf [0] = 'I';
    strcpy (szBuf+1, szItem);
    strcat (szBuf, "\r");
    Send_Net ((void *) szBuf);                          // Query Item
    }

//-------------------------------------------------------------------------//
void Update_Qty (void)
    {
    szQty [CurX-5] = 0;
    szBuf [0] = 'Q';
    strcpy (szBuf+1, szItem);
    strcat (szBuf, ",");
    strcat (szBuf, szQty);
    strcat (szBuf, "\r");
    Send_Net ((void *) szBuf);                          // Update Qty
    }

//-------------------------------------------------------------------------//
void Setting_Menu (void)
    {
    nStatus = STATE_SETTING;
    SetCursor (CURSOR_OFF);
    SetVideoMode (0);
    SetFont (1);
    clr_scr ();
    Display_String (0, 0, (char *) "=== Setting Menu ===", 0);
    Display_String (0, 1, (char *) "1. Sub Net Mask     ", (nSelection == 1) ? 1 : 0);
    Display_String (0, 2, (char *) "2. Local IP Address ", (nSelection == 2) ? 1 : 0);
    Display_String (0, 3, (char *) "3. Default Gateway  ", (nSelection == 3) ? 1 : 0);
    Display_String (0, 4, (char *) "4. DNS Server       ", (nSelection == 4) ? 1 : 0);
    Display_String (0, 5, (char *) "5. SS ID            ", (nSelection == 5) ? 1 : 0);
    Display_String (0, 6, (char *) "6. Server IP        ", (nSelection == 6) ? 1 : 0);
    Display_String (0, 7, (char *) "7. Server Port      ", (nSelection == 7) ? 1 : 0);
    }

//-------------------------------------------------------------------------//
void Setting_Input (char c)
    {
    switch (c)
        {
        case KEY_UP:
             if (nSelection > 1)  nSelection--;
             else                 nSelection = 7;
             Setting_Menu ();
             return;

        case KEY_DOWN:
             if (nSelection < 7)  nSelection++;
             else                 nSelection = 1;
             Setting_Menu ();
             return;

        case KEY_CR:
             Setting_Input ((char) nSelection+'0');
             return;

        case '1':                                       // Subnet Mask
        case '2':                                       // IP Address
        case '3':                                       // Default Gateway
        case '4':                                       // DNS Server
        case '5':                                       // SSID
        case '6':                                       // Server IP
        case '7':                                       // Server Port
             nSelection = c - '0';
             NetConfig_Menu (c);
             break;

        case KEY_ESC:
             SetNetConfig ((void*) &NetConfig);         // Set NetConfig
             nSelection = 2;
             Main_Menu ();
             break;

        default:
             return;
        }
    }

//-------------------------------------------------------------------------//
void NetConfig_Menu (char c)
    {
    nStatus = STATE_NETCONFIG;
    SetCursor (CURSOR_ON);

    clr_scr ();
    Display_String (0, 1, (char *) " Current :          ", 0);
    Display_String (0, 3, (char *) " New :              ", 0);
    Display_String (0, 6, (char *) "[ Enter ] to select ", 0);
    Display_String (0, 7, (char *) "[ ESC ]   to cancel ", 0);

    nNetConfig = 0;
    GetNetConfig ((void*) &NetConfig);

    switch (c)
        {
        case '1':
             Display_String (0, 0, (char *) "    SubNet Mask     ", 0);
             gotoxy (4, 2);
             printf ("%d.%d.%d.%d", NetConfig.SubnetMask [0], NetConfig.SubnetMask [1],
                                    NetConfig.SubnetMask [2], NetConfig.SubnetMask [3]);
             break;

        case '2':
             Display_String (0, 0, (char *) "  Local IP Address  ", 0);
             gotoxy (4, 2);
             printf ("%d.%d.%d.%d", NetConfig.IpAddr [0], NetConfig.IpAddr [1],
                                    NetConfig.IpAddr [2], NetConfig.IpAddr [3]);
             break;

        case '3':
             Display_String (0, 0, (char *) "   Default Gateway  ", 0);
             gotoxy (4, 2);
             printf ("%d.%d.%d.%d", NetConfig.DefaultGateway [0], NetConfig.DefaultGateway [1],
                                    NetConfig.DefaultGateway [2], NetConfig.DefaultGateway [3]);
             break;

        case '4':
             Display_String (0, 0, (char *) "     DNS Server     ", 0);
             gotoxy (4, 2);
             printf ("%d.%d.%d.%d", NetConfig.DnsServer [0], NetConfig.DnsServer [1],
                                    NetConfig.DnsServer [2], NetConfig.DnsServer [3]);
             break;

        case '5':
             Display_String (0, 0, (char *) "        SSID        ", 0);
             gotoxy (4, 2);
             printf ("%s", NetConfig.SSID);
             en_alpha (ALPHA_FIXED);
             break;

        case '6':
             Display_String (0, 0, (char *) "    Server IP       ", 0);
             gotoxy (4, 2);
             printf ("%d.%d.%d.%d", ServerIP [0], ServerIP [1], ServerIP [2], ServerIP [3]);
             break;

        case '7':
             Display_String (0, 0, (char *) "    Server Port     ", 0);
             gotoxy (4, 2);
             printf ("%d", ServerPort);
             break;
        }

    gotoxy (4, 4);
    CurX = 4;
    CurY = 4;
    }

//-------------------------------------------------------------------------//
void NetConfig_Input (char c)
    {
    switch (c)
        {
        case KEY_CR:
             NetConfig_Save ();
             if (nNetConfig)                            // Set Net Config
                 SetNetConfig ((void*) &NetConfig);

        case KEY_ESC:
             Setting_Menu ();
             return;

        case KEY_BS:
             Back_Space ();
             break;

        case KEY_CLEAR:
             Clear_Line ();
             break;

        case KEY_UP:
        case KEY_DOWN:
        case KEY_LEFT:
        case KEY_RIGHT:
        case KEY_F1:
        case KEY_F2:
        case KEY_F3:
        case KEY_F4:
        case KEY_F5:
        case KEY_F6:
        case KEY_F7:
        case KEY_F8:
        case KEY_F9:
             break;

        default:
             Numerical_Input (c);
             break;
        }
    }

//-------------------------------------------------------------------------//
void NetConfig_Save (void)
    {
    char  szSet [20];
    int   len, n, i;
    int   j=0, k=0;

    szNetConfig [CurX-4] = 0;
    len = strlen (szNetConfig);
    if (!len && nSelection != 5)                        // empty and not SSID input
        return;

    nNetConfig = 1;
    if (nSelection == 5)                                // SS ID
        {
        strcpy ((char *) NetConfig.SSID, szNetConfig);
        return;
        }
    else if (nSelection == 7)                           // Server Port
        {
        ServerPort = atoi (szNetConfig);
        return;
        }

    for (i=0; i<len; i++)
        {
        if (szNetConfig [i] == '.')
            {
            szSet [j] = 0;
            n = atoi (szSet);
            if (n > 255)  n = 255;

            if (nSelection == 1)       NetConfig.SubnetMask [k++]     = (unsigned char) n;
            else if (nSelection == 2)  NetConfig.IpAddr [k++]         = (unsigned char) n;
            else if (nSelection == 3)  NetConfig.DefaultGateway [k++] = (unsigned char) n;
            else if (nSelection == 4)  NetConfig.DnsServer [k++]      = (unsigned char) n;
            else if (nSelection == 6)  ServerIP [k++]                 = (unsigned char) n;
            j = 0;
            }
        else
            {
            szSet [j++] = szNetConfig [i];
            }
        }

    if (i >= len && k > 0)
        {
        szSet [j] = 0;
        n = atoi (szSet);
        if (n > 255)  n = 255;

        if (nSelection == 1)       NetConfig.SubnetMask [k++]     = (unsigned char) n;
        else if (nSelection == 2)  NetConfig.IpAddr [k++]         = (unsigned char) n;
        else if (nSelection == 3)  NetConfig.DefaultGateway [k++] = (unsigned char) n;
        else if (nSelection == 4)  NetConfig.DnsServer [k++]      = (unsigned char) n;
        else if (nSelection == 6)  ServerIP [k++]                 = (unsigned char) n;
        }
    }

//-------------------------------------------------------------------------//
void Numerical_Input (char c)
    {
    int  a, b;

    wherexy (&a, &b);
    if (nStatus == STATE_TAKEDATA)
        {
        if (CurY == 3)                                  // Item
            {
            putchar (c);
            szItem [CurX-5] = c;
            if (CurX < 14)  CurX++;
            else            gotoxy (a, b);              // else stay in the same place
            }
        else                                            // Qty
            {
            if (c < '0' || c > '9')
                return;
            putchar (c);
            szQty [CurX-5] = c;
            if (CurX < 9)   CurX++;
            else            gotoxy (a, b);              // else stay in the same place
            }
        }
    else if (nStatus == STATE_NETCONFIG)
        {
        if (nSelection == 5)                            // SS ID
            {
            putchar (c);
            szNetConfig [CurX-4] = c;
            if (CurX < 19)   CurX++;
            else             gotoxy (a, b);
            }
        else
            {
            if (c < '.' || c > '9')
                return;
            putchar (c);
            szNetConfig [CurX-4] = c;
            if (CurX < 19)   CurX++;
            else             gotoxy (a, b);
            }
        }
    }

//-------------------------------------------------------------------------//
static void Back_Space (void)
    {
    int  a, b;

    wherexy (&a, &b);
    if (nStatus == STATE_TAKEDATA)
        {
        if (CurY == 3)                                  // Item
            {
            if (CurX > 5)
                {
                CurX--;
                szItem [CurX-5] = 0;
                putchar (' ');
                gotoxy (--a, b);
                putchar (' ');
                }
            }
        else                                            // Qty
            {
            if (CurX > 5)
                {
                CurX--;
                szQty [CurX-5] = 0;
                putchar (' ');
                gotoxy (--a, b);
                putchar (' ');
                }
            }
        }
    else if (nStatus == STATE_NETCONFIG)
        {
        if (CurX > 4)
            {
            CurX--;
            szNetConfig [CurX-4] = 0;
            putchar (' ');
            gotoxy (--a, b);
            putchar (' ');
            }
        }
    gotoxy (a, b);
    }

//-------------------------------------------------------------------------//
static void Clear_Line (void)
    {
    if (nStatus == STATE_TAKEDATA)
        {
        if (CurY == 3)                                  // Item
            {
            gotoxy (0, 3);
            printf ("Item:          ");
            gotoxy (CurX=5, CurY=3);
            }
        else                                            // Qty
            {
            gotoxy (0, 7);
            printf ("Qty :          ");
            gotoxy (CurX=5, CurY=7);
            }
        }
    else if (nStatus == STATE_NETCONFIG)
        {
        gotoxy (4, 4);
        printf ("               ");
        gotoxy (CurX=4, CurY=4);
        }
    }

//-------------------------------------------------------------------------//
void Display_String (int x, int y, char *str, int mode)
    {
    SetVideoMode (mode);
    gotoxy (x, y);
    printf ("%s", str);
    }

//-------------------------------------------------------------------------//
