Repository for import to local machine

Dependencies:   DMBasicGUI DMSupport

NetworkParameters.cpp

Committer:
jmitc91516
Date:
2017-07-31
Revision:
8:26e49e6955bd
Parent:
1:a5258871b33d

File content as of revision 8:26e49e6955bd:

#include "NetworkParameters.h"
#include "EasyGUITouchAreaIndices.h"
#include "SettingsHandler.h"
#include "GetGCStatusLoop.h"
#include "NumericKeypadPageHandler.h"
#include "EthernetKeypadPageHandler.h"

#include <string.h>

#include <stdio.h>
#include <stdlib.h>



/*
    Displays the specified easyGUI 'structure' (or page, to use a more easily understood term).
    Defined in main.cpp
*/
extern void DisplayEasyGuiStructure(int structureIndex, USBDeviceConnected* usbDevice, USBHostGC* usbHostGC, bool updateEasyGUIVariables = true);


/*
    Draws the background bitmap. It fills the screen, so you do not need to call GuiLib_Clear.
    Defined in main.cpp
*/
extern void DrawBackgroundBitmap(void);
#define USING_BACKGROUND_BITMAP

/*
    Converts three eight-bit colour values to the corresponding 16-bit RGB565 value.
    Defined in main.cpp
*/
GuiConst_INTCOLOR SixteenBitColorValue(GuiConst_INT8U red, GuiConst_INT8U green, GuiConst_INT8U blue); 
/*
    Displays the specified text string at the specified location in the currently-displayed easyGUI page.
    
    Defined in main.cpp - and omits the 'ALLOW_DEBUG_PRINTS' #define
*/
extern void SpecialDebugPrint(char *stuffToPrint, GuiConst_INT16S X, GuiConst_INT16S Y);



/*                      
    Note that this class is a singleton - we do not need or want there to be more than one instance of it
    (we do not want multiple values for the IP address, etc, nor will we show 
    more than one easyGUI 'EthernetParametersPage' to the user at the same time).
*/
NetworkParameters * NetworkParameters::theNetworkParametersInstance = NULL;


/*
    We distinguish the 'active' field - i.e. the one being edited by the user - 
    from the inactive fields, by its background colour
*/
#define EXPERIMENTING_WITH_COLORS
const GuiConst_INTCOLOR NetworkParameters::inactiveFieldBackgroundColour = SixteenBitColorValue(192, 192, 192); // Grey
#ifdef EXPERIMENTING_WITH_COLORS
const GuiConst_INTCOLOR NetworkParameters::activeFieldBackgroundColour   = SixteenBitColorValue(255, 255, 0); // Yellow
#else
const GuiConst_INTCOLOR NetworkParameters::activeFieldBackgroundColour   = SixteenBitColorValue(255, 255, 255); // White
#endif // EXPERIMENTING_WITH_COLORS

//#define USE_BACKGROUND_COLOURS // Else leave them all white
//#define TOUCH_VALUES_DIRECTLY

/*
    Convenient default values
*/
const unsigned int NetworkParameters::defaultPortNumber = 3456;
const unsigned int NetworkParameters::defaultIPAddress[4] = {192, 168, 1, 200};
const unsigned int NetworkParameters::defaultSubnetMask[4] = {255, 255, 255, 0};
const unsigned int NetworkParameters::defaultGatewayAddress[4] = {192, 168, 1, 254};


/*
    Singleton class - return the one and only instance, first creating it if necessary.
*/
NetworkParameters * NetworkParameters::GetInstance(USBDeviceConnected* newUsbDevice, USBHostGC* newUsbHostGC)
{
    if (theNetworkParametersInstance == NULL) {
        theNetworkParametersInstance = new NetworkParameters(newUsbDevice, newUsbHostGC);
    }
    
    return theNetworkParametersInstance;
}

// Singleton class - private constructor
NetworkParameters::NetworkParameters(USBDeviceConnected* newUsbDevice, USBHostGC* newUsbHostGC)
{
    // Note that we do not use these values here - 
    // but we do need to pass them to the (main.cpp) function DisplayEasyGUIStructure
    usbDevice = newUsbDevice;
    usbHostGC = newUsbHostGC;

    portNumber = defaultPortNumber;

    for (int index = 0; index < 4; ++index) {
        ipAddress[index]      = defaultIPAddress[index];
        subnetMask[index]     = defaultSubnetMask[index];
        gatewayAddress[index] = defaultGatewayAddress[index];
    }
    
    useDHCP = false;
    
    ReadFromQSPISettings();
    
//#define WANT_ETHERNET_DEBUG
#ifdef WANT_ETHERNET_DEBUG
        char dbg[600];
        int dbg1;
        char dbg2[100];
        char dbg3[100];
        char dbg4[100];
        int dbg5;

        dbg1 = GetPortNumber();
        GetIPAddressAsString(dbg2);
        GetSubnetMaskAsString(dbg3);
        GetGatewayAddressAsString(dbg4);
        dbg5 = GetUseDHCP();
        
        sprintf(dbg, "Ethernet port: %d, IP: \"%s\", mask: \"%s\", gateway: \"%s\", useDHCP: %d", dbg1, dbg2, dbg3, dbg4, dbg5);
        SpecialDebugPrint(dbg, 100, 70);
#undef WANT_ETHERNET_DEBUG
#endif // WANT_ETHERNET_DEBUG

    indexOfVariablesCurrentlyBeingEdited = -1;

    variablesForTouchArea[0].touchAreaIndex                    = NETWORK_PARAMS_PORT_VALUE;
    variablesForTouchArea[0].easyGUIVariablePtr                = GuiVar_ethernetPort;
    variablesForTouchArea[0].internalVariablePtr               = &portNumber;
    variablesForTouchArea[0].maxValue                          = 65535;
    variablesForTouchArea[0].easyGUIBackgroundColorVariablePtr = &GuiVar_ethernetPortBackgroundColour;
    strcpy(variablesForTouchArea[0].variableName, "Port");


    variablesForTouchArea[1].touchAreaIndex                    = NETWORK_PARAMS_IP1_VALUE;
    variablesForTouchArea[1].easyGUIVariablePtr                = GuiVar_ethernetIP1;
    variablesForTouchArea[1].internalVariablePtr               = &(ipAddress[0]);
    variablesForTouchArea[1].maxValue                          = 255;
    variablesForTouchArea[1].easyGUIBackgroundColorVariablePtr = &GuiVar_ethernetIP1BackgroundColour;
    strcpy(variablesForTouchArea[1].variableName, "IP Address 1");
    
    variablesForTouchArea[2].touchAreaIndex                    = NETWORK_PARAMS_IP2_VALUE;
    variablesForTouchArea[2].easyGUIVariablePtr                = GuiVar_ethernetIP2;
    variablesForTouchArea[2].internalVariablePtr               = &(ipAddress[1]);
    variablesForTouchArea[2].maxValue                          = 255;
    variablesForTouchArea[2].easyGUIBackgroundColorVariablePtr = &GuiVar_ethernetIP2BackgroundColour;
    strcpy(variablesForTouchArea[2].variableName, "IP Address 2");
    
    variablesForTouchArea[3].touchAreaIndex                    = NETWORK_PARAMS_IP3_VALUE;
    variablesForTouchArea[3].easyGUIVariablePtr                = GuiVar_ethernetIP3;
    variablesForTouchArea[3].internalVariablePtr               = &(ipAddress[2]);
    variablesForTouchArea[3].maxValue                          = 255;
    variablesForTouchArea[3].easyGUIBackgroundColorVariablePtr = &GuiVar_ethernetIP3BackgroundColour;
    strcpy(variablesForTouchArea[3].variableName, "IP Address 3");
    
    variablesForTouchArea[4].touchAreaIndex                    = NETWORK_PARAMS_IP4_VALUE;
    variablesForTouchArea[4].easyGUIVariablePtr                = GuiVar_ethernetIP4;
    variablesForTouchArea[4].internalVariablePtr               = &(ipAddress[3]);
    variablesForTouchArea[4].maxValue                          = 255;
    variablesForTouchArea[4].easyGUIBackgroundColorVariablePtr = &GuiVar_ethernetIP4BackgroundColour;
    strcpy(variablesForTouchArea[4].variableName, "IP Address 4");
    

    variablesForTouchArea[5].touchAreaIndex                    = NETWORK_PARAMS_MASK1_VALUE;
    variablesForTouchArea[5].easyGUIVariablePtr                = GuiVar_ethernetMask1;
    variablesForTouchArea[5].internalVariablePtr               = &(subnetMask[0]);
    variablesForTouchArea[5].maxValue                          = 255;
    variablesForTouchArea[5].easyGUIBackgroundColorVariablePtr = &GuiVar_ethernetMask1BackgroundColour;
    strcpy(variablesForTouchArea[5].variableName, "Subnet mask 1");

    variablesForTouchArea[6].touchAreaIndex                    = NETWORK_PARAMS_MASK2_VALUE;
    variablesForTouchArea[6].easyGUIVariablePtr                = GuiVar_ethernetMask2;
    variablesForTouchArea[6].internalVariablePtr               = &(subnetMask[1]);
    variablesForTouchArea[6].maxValue                          = 255;
    variablesForTouchArea[6].easyGUIBackgroundColorVariablePtr = &GuiVar_ethernetMask2BackgroundColour;
    strcpy(variablesForTouchArea[6].variableName, "Subnet mask 2");

    variablesForTouchArea[7].touchAreaIndex                    = NETWORK_PARAMS_MASK3_VALUE;
    variablesForTouchArea[7].easyGUIVariablePtr                = GuiVar_ethernetMask3;
    variablesForTouchArea[7].internalVariablePtr               = &(subnetMask[2]);
    variablesForTouchArea[7].maxValue                          = 255;
    variablesForTouchArea[7].easyGUIBackgroundColorVariablePtr = &GuiVar_ethernetMask3BackgroundColour;
    strcpy(variablesForTouchArea[7].variableName, "Subnet mask 3");

    variablesForTouchArea[8].touchAreaIndex                    = NETWORK_PARAMS_MASK4_VALUE;
    variablesForTouchArea[8].easyGUIVariablePtr                = GuiVar_ethernetMask4;
    variablesForTouchArea[8].internalVariablePtr               = &(subnetMask[3]);
    variablesForTouchArea[8].maxValue                          = 255;
    variablesForTouchArea[8].easyGUIBackgroundColorVariablePtr = &GuiVar_ethernetMask4BackgroundColour;
    strcpy(variablesForTouchArea[8].variableName, "Subnet mask 4");


    variablesForTouchArea[9].touchAreaIndex                     = NETWORK_PARAMS_GATEWAY1_VALUE;
    variablesForTouchArea[9].easyGUIVariablePtr                 = GuiVar_ethernetGateway1;
    variablesForTouchArea[9].internalVariablePtr                = &(gatewayAddress[0]);
    variablesForTouchArea[9].maxValue                           = 255;
    variablesForTouchArea[9].easyGUIBackgroundColorVariablePtr  = &GuiVar_ethernetGateway1BackgroundColour;
    strcpy(variablesForTouchArea[9].variableName, "Gateway 1");

    variablesForTouchArea[10].touchAreaIndex                    = NETWORK_PARAMS_GATEWAY2_VALUE;
    variablesForTouchArea[10].easyGUIVariablePtr                = GuiVar_ethernetGateway2;
    variablesForTouchArea[10].internalVariablePtr               = &(gatewayAddress[1]);
    variablesForTouchArea[10].maxValue                          = 255;
    variablesForTouchArea[10].easyGUIBackgroundColorVariablePtr = &GuiVar_ethernetGateway2BackgroundColour;
    strcpy(variablesForTouchArea[10].variableName, "Gateway 2");

    variablesForTouchArea[11].touchAreaIndex                    = NETWORK_PARAMS_GATEWAY3_VALUE;
    variablesForTouchArea[11].easyGUIVariablePtr                = GuiVar_ethernetGateway3;
    variablesForTouchArea[11].internalVariablePtr               = &(gatewayAddress[2]);
    variablesForTouchArea[11].maxValue                          = 255;
    variablesForTouchArea[11].easyGUIBackgroundColorVariablePtr = &GuiVar_ethernetGateway3BackgroundColour;
    strcpy(variablesForTouchArea[11].variableName, "Gateway 3");

    variablesForTouchArea[12].touchAreaIndex                    = NETWORK_PARAMS_GATEWAY4_VALUE;
    variablesForTouchArea[12].easyGUIVariablePtr                = GuiVar_ethernetGateway4;
    variablesForTouchArea[12].internalVariablePtr               = &(gatewayAddress[3]);
    variablesForTouchArea[12].maxValue                          = 255;
    variablesForTouchArea[12].easyGUIBackgroundColorVariablePtr = &GuiVar_ethernetGateway4BackgroundColour;
    strcpy(variablesForTouchArea[12].variableName, "Gateway 4");
}

    
// Private destructor also
NetworkParameters::~NetworkParameters()
{
}


/*
    Saves the current parameter values to QSPI settings,
    so they are maintained even when the user powers off
    
    No arguments, no return value
*/
void NetworkParameters::SaveToQSPISettings(void)
{
    // Put values to QSPI settings, using SettingsHandler member functions

    SettingsHandler::PutIntegerValueToQSPISettings("PortNumber", portNumber);

    SettingsHandler::PutIntegerValueToQSPISettings("IPAddress0", ipAddress[0]);
    SettingsHandler::PutIntegerValueToQSPISettings("IPAddress1", ipAddress[1]);
    SettingsHandler::PutIntegerValueToQSPISettings("IPAddress2", ipAddress[2]);
    SettingsHandler::PutIntegerValueToQSPISettings("IPAddress3", ipAddress[3]);

    SettingsHandler::PutIntegerValueToQSPISettings("SubnetMask0", subnetMask[0]);
    SettingsHandler::PutIntegerValueToQSPISettings("SubnetMask1", subnetMask[1]);
    SettingsHandler::PutIntegerValueToQSPISettings("SubnetMask2", subnetMask[2]);
    SettingsHandler::PutIntegerValueToQSPISettings("SubnetMask3", subnetMask[3]);

    SettingsHandler::PutIntegerValueToQSPISettings("GatewayAddress0", gatewayAddress[0]);
    SettingsHandler::PutIntegerValueToQSPISettings("GatewayAddress1", gatewayAddress[1]);
    SettingsHandler::PutIntegerValueToQSPISettings("GatewayAddress2", gatewayAddress[2]);
    SettingsHandler::PutIntegerValueToQSPISettings("GatewayAddress3", gatewayAddress[3]);

    SettingsHandler::PutIntegerValueToQSPISettings("UseDHCP", (useDHCP ? 1 : 0) );
}


/*
    Reads the current parameter values from QSPI settings,
    so they are maintained even when the user powers off
    
    No arguments, no return value
*/
void NetworkParameters::ReadFromQSPISettings(void)
{
    // Get values from QSPI settings, using SettingsHandler member functions
    
    portNumber = SettingsHandler::GetIntegerValueFromQSPISettings("PortNumber", defaultPortNumber);
    
    ipAddress[0] = SettingsHandler::GetIntegerValueFromQSPISettings("IPAddress0", defaultIPAddress[0]);
    ipAddress[1] = SettingsHandler::GetIntegerValueFromQSPISettings("IPAddress1", defaultIPAddress[1]);
    ipAddress[2] = SettingsHandler::GetIntegerValueFromQSPISettings("IPAddress2", defaultIPAddress[2]);
    ipAddress[3] = SettingsHandler::GetIntegerValueFromQSPISettings("IPAddress3", defaultIPAddress[3]);
    
    subnetMask[0] = SettingsHandler::GetIntegerValueFromQSPISettings("SubnetMask0", defaultSubnetMask[0]);
    subnetMask[1] = SettingsHandler::GetIntegerValueFromQSPISettings("SubnetMask1", defaultSubnetMask[1]);
    subnetMask[2] = SettingsHandler::GetIntegerValueFromQSPISettings("SubnetMask2", defaultSubnetMask[2]);
    subnetMask[3] = SettingsHandler::GetIntegerValueFromQSPISettings("SubnetMask3", defaultSubnetMask[3]);

    gatewayAddress[0] = SettingsHandler::GetIntegerValueFromQSPISettings("GatewayAddress0", defaultGatewayAddress[0]);
    gatewayAddress[1] = SettingsHandler::GetIntegerValueFromQSPISettings("GatewayAddress1", defaultGatewayAddress[1]);
    gatewayAddress[2] = SettingsHandler::GetIntegerValueFromQSPISettings("GatewayAddress2", defaultGatewayAddress[2]);
    gatewayAddress[3] = SettingsHandler::GetIntegerValueFromQSPISettings("GatewayAddress3", defaultGatewayAddress[3]);
    
    useDHCP = (SettingsHandler::GetIntegerValueFromQSPISettings("UseDHCP", 0) != 0); // Default to false
}

/*
    Gets the current parameters - i.e. the values we are actually using 
    for the Ethernet link - from the specified EthernetInterface instance, 
    and saves them as the "real" values, so that we can restore them 
    (a) on entering the page (called from TouchCallback in main.cpp), 
    and (b) when the user presses Cancel.
    
    Args: a pointer to the EthernetInterface instance
    
    No return code
*/
void NetworkParameters::SaveRealValues(EthernetInterface *eth)
{
    realPortNumber = portNumber;

    SetIPAddressFromString(eth->getIPAddress());
    SetSubnetMaskFromString(eth->getNetworkMask());
    SetGatewayAddressFromString(eth->getGateway());

    for (int index = 0; index < 4; ++index) {
        realIPAddress[index]      = ipAddress[index];
        realSubnetMask[index]     = subnetMask[index];
        realGatewayAddress[index] = gatewayAddress[index];
    }
}


/*
    Restores the current parameter values to the 'real' values.
    It is up the caller to display these to the user.
    ************************************************
    
    No arguments, no return code
*/
void NetworkParameters::RestoreRealValues(void)
{
    portNumber = realPortNumber;

    for (int index = 0; index < 4; ++index) {
        ipAddress[index]      = realIPAddress[index];
        subnetMask[index]     = realSubnetMask[index];
        gatewayAddress[index] = realGatewayAddress[index];
    }
}


/*
    Sets the background colours of all 'editable' fields to the 'inactive' colour.
    
    No arguments, no return code
*/
void NetworkParameters::SetAllFieldBackgroundColoursToInactive(void)
{
    GuiVar_ethernetPortBackgroundColour = inactiveFieldBackgroundColour;

    GuiVar_ethernetIP1BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_ethernetIP2BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_ethernetIP3BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_ethernetIP4BackgroundColour = inactiveFieldBackgroundColour;

    GuiVar_ethernetMask1BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_ethernetMask2BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_ethernetMask3BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_ethernetMask4BackgroundColour = inactiveFieldBackgroundColour;

    GuiVar_ethernetGateway1BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_ethernetGateway2BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_ethernetGateway3BackgroundColour = inactiveFieldBackgroundColour;
    GuiVar_ethernetGateway4BackgroundColour = inactiveFieldBackgroundColour;
}

/*
    Sets the background colours of all 'editable' fields to the 'inactive' colour.
    
    No arguments, no return code
*/
void NetworkParameters::SetAllFieldBackgroundColoursToWhite(void)
{
    GuiVar_ethernetPortBackgroundColour = 0xFFFF;

    GuiVar_ethernetIP1BackgroundColour = 0xFFFF;
    GuiVar_ethernetIP2BackgroundColour = 0xFFFF;
    GuiVar_ethernetIP3BackgroundColour = 0xFFFF;
    GuiVar_ethernetIP4BackgroundColour = 0xFFFF;

    GuiVar_ethernetMask1BackgroundColour = 0xFFFF;
    GuiVar_ethernetMask2BackgroundColour = 0xFFFF;
    GuiVar_ethernetMask3BackgroundColour = 0xFFFF;
    GuiVar_ethernetMask4BackgroundColour = 0xFFFF;

    GuiVar_ethernetGateway1BackgroundColour = 0xFFFF;
    GuiVar_ethernetGateway2BackgroundColour = 0xFFFF;
    GuiVar_ethernetGateway3BackgroundColour = 0xFFFF;
    GuiVar_ethernetGateway4BackgroundColour = 0xFFFF;
}


/*
    Caller is telling us it is about to display the easyGUI 'EthernetParametersPage',
    and that we should do whatever we have to do to get it ready,
    before the caller displays it.
    
    No arguments, no return code
*/
void NetworkParameters::DisplayingEasyGUIPage(bool updateEasyGUIVariables)
{
    if(updateEasyGUIVariables) {
        UpdateEasyGUIVariablesFromInternalValues();
    }

#ifdef USE_BACKGROUND_COLOURS
    SetAllFieldBackgroundColoursToInactive();
#else
    SetAllFieldBackgroundColoursToWhite();
#endif

    indexOfVariablesCurrentlyBeingEdited = -1; 
    
//    UpdateEasyGUIPage();
}


/*
    Outputs the port number as a null-terminated string, in the form of an integer
    with 1-5 digits. If the value is zero, it will be returned as "0", not as an empty string.
    
    Args: a pointer to a buffer to contain the string.
          It is up to the caller to make sure this is long enough, i.e. at least 6 bytes long
                                                                        **********************
    No return code
*/
void NetworkParameters::GetPortNumberAsString(char *portBuffer)
{
    if(portNumber == 0) {
        portBuffer[0] = '0';
        portBuffer[1] = '\0';
        
        return;
    }
    
    if(portNumber >= 65535) {
        portBuffer[0] = '6';
        portBuffer[1] = '5';
        portBuffer[2] = '5';
        portBuffer[3] = '3';
        portBuffer[4] = '5';
        portBuffer[5] = '\0';
        
        return;
    }
    
    // 'else' - value is between 0 and 65535
    sprintf(portBuffer, "%5u", portNumber);
    return;
    
}


/*
    Set the port number from a null-terminated string
    
    Args: a pointer to a buffer that contains the string.

    No return code
*/
void NetworkParameters::SetPortNumberFromString(char *portBuffer)
{
    unsigned int temp;
    sscanf(portBuffer, "%u", &temp);
    
    // 'temp' is unsigned, so cannot be less than zero
    if(temp > 65535) {
        portNumber = 65535;
        return;
    }
    
    // 'else'
    portNumber = temp;
}


/*
    Outputs the specified field of the IP address as a null-terminated string, in the form of an integer
    with 1-3 digits. If the value is zero, it will be returned as "0", not as an empty string.
    
    Args: the index to the field (value 0 through 3)
          a pointer to a buffer to contain the string.
          It is up to the caller to make sure this is long enough, i.e. at least 4 bytes long
                                                                        **********************
    No return code
*/
void NetworkParameters::GetIPAddressFieldAsString(int fieldIndex, char *ipAddressBuffer, bool wantLeadingSpaces)
{
    // By default, we pad the field with leading spaces,
    // to try and keep it a constant width
    if((fieldIndex >= 0) && (fieldIndex < 4)) {
        if(ipAddress[fieldIndex] == 0) {
            if(wantLeadingSpaces) {
                ipAddressBuffer[0] = ' ';
                ipAddressBuffer[1] = ' ';
                ipAddressBuffer[2] = '0';
                ipAddressBuffer[3] = '\0';
            } else {
                ipAddressBuffer[0] = '0';
                ipAddressBuffer[1] = '\0';
            }
                        
            return;
        }
        
        if(ipAddress[fieldIndex] >= 255) {
            ipAddressBuffer[0] = '2';
            ipAddressBuffer[1] = '5';
            ipAddressBuffer[2] = '5';
            ipAddressBuffer[3] = '\0';
            
            return;
        }
        
        // 'else' - value is between 0 and 255
        if(wantLeadingSpaces) {
            sprintf(ipAddressBuffer, "%3u", ipAddress[fieldIndex]);
        } else {
            sprintf(ipAddressBuffer, "%u", ipAddress[fieldIndex]);
        }            
        return;
    }
    
    // 'else' - invalid index
    ipAddressBuffer[0] = '\0';
}


/*
    Sets the specified field of the IP address from a null-terminated string
    
    Args: the index to the field (value 0 through 3)
          a pointer to a buffer that contains the string.

    No return code
*/
void NetworkParameters::SetIPAddressFieldFromString(int fieldIndex, char *ipAddressBuffer)
{
    if((fieldIndex >= 0) && (fieldIndex < 4)) {
        unsigned int temp;
        sscanf(ipAddressBuffer, "%u", &temp);
        
        // 'temp' is unsigned, so cannot be less than zero
        if(temp > 255) {
            ipAddress[fieldIndex] = 255;
            return;
        }
        
        // 'else'
        ipAddress[fieldIndex] = temp;
    }
}


/*
    Outputs the specified field of the subnet mask as a null-terminated string, in the form of an integer
    with 1-3 digits. If the value is zero, it will be returned as "0", not as an empty string.
    
    Args: the index to the field (value 0 through 3)
          a pointer to a buffer to contain the string.
          It is up to the caller to make sure this is long enough, i.e. at least 4 bytes long
                                                                        **********************
    No return code
*/
void NetworkParameters::GetSubnetMaskFieldAsString(int fieldIndex, char *subnetMaskBuffer, bool wantLeadingSpaces)
{
    // By default, we pad the field with leading spaces,
    // to try and keep it a constant width
    if((fieldIndex >= 0) && (fieldIndex < 4)) {
        if(subnetMask[fieldIndex] == 0) {
            if(wantLeadingSpaces) {
                subnetMaskBuffer[0] = ' ';
                subnetMaskBuffer[1] = ' ';
                subnetMaskBuffer[2] = '0';
                subnetMaskBuffer[3] = '\0';
            } else {
                subnetMaskBuffer[0] = '0';
                subnetMaskBuffer[1] = '\0';
            }            
            return;
        }
        
        if(subnetMask[fieldIndex] >= 255) {
            subnetMaskBuffer[0] = '2';
            subnetMaskBuffer[1] = '5';
            subnetMaskBuffer[2] = '5';
            subnetMaskBuffer[3] = '\0';
            
            return;
        }
        
        // 'else' - value is between 0 and 255
        if(wantLeadingSpaces) {
            sprintf(subnetMaskBuffer, "%3u", subnetMask[fieldIndex]);
        } else {
            sprintf(subnetMaskBuffer, "%u", subnetMask[fieldIndex]);
        }
        return;
    }
    
    // 'else' - invalid index
    subnetMaskBuffer[0] = '\0';    
}


/*
    Sets the specified field of the subnet mask from a null-terminated string
    
    Args: the index to the field (value 0 through 3)
          a pointer to a buffer that contains the string.

    No return code
*/
void NetworkParameters::SetSubnetMaskFieldFromString(int fieldIndex, char *subnetMaskBuffer)
{
    if((fieldIndex >= 0) && (fieldIndex < 4)) {
        unsigned int temp;
        sscanf(subnetMaskBuffer, "%u", &temp);
        
        // 'temp' is unsigned, so cannot be less than zero
        if(temp > 255) {
            subnetMask[fieldIndex] = 255;
            return;
        }
        
        // 'else'
        subnetMask[fieldIndex] = temp;
    }
}


/*
    Outputs the specified field of the gateway address as a null-terminated string, in the form of an integer
    with 1-3 digits. If the value is zero, it will be returned as "0", not as an empty string.
    
    Args: the index to the field (value 0 through 3)
          a pointer to a buffer to contain the string.
          It is up to the caller to make sure this is long enough, i.e. at least 4 bytes long
                                                                        **********************
    No return code
*/
void NetworkParameters::GetGatewayAddressFieldAsString(int fieldIndex, char *gatewayAddressBuffer, bool wantLeadingSpaces)
{
    // By default, we pad the field with leading spaces,
    // to try and keep it a constant width
    if((fieldIndex >= 0) && (fieldIndex < 4)) {
        if(gatewayAddress[fieldIndex] == 0) {
            if(wantLeadingSpaces) {
                gatewayAddressBuffer[0] = ' ';
                gatewayAddressBuffer[1] = ' ';
                gatewayAddressBuffer[2] = '0';
                gatewayAddressBuffer[3] = '\0';
            } else {
                gatewayAddressBuffer[0] = '0';
                gatewayAddressBuffer[1] = '\0';
            }            
            return;
        }
        
        if(gatewayAddress[fieldIndex] >= 255) {
            gatewayAddressBuffer[0] = '2';
            gatewayAddressBuffer[1] = '5';
            gatewayAddressBuffer[2] = '5';
            gatewayAddressBuffer[3] = '\0';
            
            return;
        }
        
        // 'else' - value is between 0 and 255
        if(wantLeadingSpaces) {
            sprintf(gatewayAddressBuffer, "%3u", gatewayAddress[fieldIndex]);
        } else {
            sprintf(gatewayAddressBuffer, "%u", gatewayAddress[fieldIndex]);
        }
        return;
    }
    
    // 'else' - invalid index
    gatewayAddressBuffer[0] = '\0';    
}
    

/*
    Sets the specified field of the gateway address from a null-terminated string
    
    Args: the index to the field (value 0 through 3)
          a pointer to a buffer that contains the string.

    No return code
*/
void NetworkParameters::SetGatewayAddressFieldFromString(int fieldIndex, char *gatewayAddressBuffer)
{
    if((fieldIndex >= 0) && (fieldIndex < 4)) {
        unsigned int temp;
        sscanf(gatewayAddressBuffer, "%u", &temp);
        
        // 'temp' is unsigned, so cannot be less than zero
        if(temp > 255) {
            gatewayAddress[fieldIndex] = 255;
            return;
        }
        
        // 'else'
        gatewayAddress[fieldIndex] = temp;
    }
}


/*
    Outputs the IP address as a null-terminated string, in the conventional form,
    i.e. as four integers, each of which can be 1-3 digits, separated by dots, e.g. "123.456.789.123".
    If any of the values is zero, it will appear as "0", not as an empty string - but other than that,
    there will be no leading zeroes.
    
    Args: a pointer to a buffer to contain the string.
          It is up to the caller to make sure this is long enough, i.e. at least 16 bytes long
                                                                        **********************
    No return code
*/
void NetworkParameters::GetIPAddressAsString(char *ipAddressBuffer)
{
    char ipAddressField0[10];
    char ipAddressField1[10];
    char ipAddressField2[10];
    char ipAddressField3[10];
    
    GetIPAddressFieldAsString(0, ipAddressField0, false);
    GetIPAddressFieldAsString(1, ipAddressField1, false);
    GetIPAddressFieldAsString(2, ipAddressField2, false);
    GetIPAddressFieldAsString(3, ipAddressField3, false);
    
    sprintf(ipAddressBuffer, "%s.%s.%s.%s", ipAddressField0, ipAddressField1, ipAddressField2, ipAddressField3);
}

/*
    Sets our IP address from the string passed to it, which we expect to be in the conventional form,
    i.e. as four integers, each of which can be 1-3 digits, separated by dots, e.g. "123.456.789.123".

    Args: a pointer to a buffer which contains the string.

    No return code
*/
void NetworkParameters::SetIPAddressFromString(char *ipAddressBuffer)
{
    char fieldBuff[20];
    int fieldBuffIndex;
    int ipAddressBufferIndex;
    
    ipAddressBufferIndex = 0;
    for (int ipAddressIndex = 0; ipAddressIndex < 4; ++ipAddressIndex) {
        fieldBuffIndex = 0;
        while((ipAddressBuffer[ipAddressBufferIndex] != '\0') && (ipAddressBuffer[ipAddressBufferIndex] != '.')){
            fieldBuff[fieldBuffIndex++] = ipAddressBuffer[ipAddressBufferIndex++];
        }
        fieldBuff[fieldBuffIndex] = '\0';
        
        SetIPAddressFieldFromString(ipAddressIndex, fieldBuff);
        
        if(ipAddressBuffer[ipAddressBufferIndex] == '\0') break;
        
        ++ipAddressBufferIndex; // Point to next field
    }
}


/*
    Outputs the subnet mask as a null-terminated string, in the conventional form,
    i.e. as four integers, each of which can be 1-3 digits, separated by dots, e.g. "123.456.789.123".
    If any of the values is zero, it will appear as "0", not as an empty string - but other than that,
    there will be no leading zeroes.
    
    Args: a pointer to a buffer to contain the string.
          It is up to the caller to make sure this is long enough, i.e. at least 16 bytes long
                                                                        **********************
    No return code
*/
void NetworkParameters::GetSubnetMaskAsString(char *subnetMaskBuffer)
{
    char subnetMaskField0[10];
    char subnetMaskField1[10];
    char subnetMaskField2[10];
    char subnetMaskField3[10];
    
    GetSubnetMaskFieldAsString(0, subnetMaskField0, false);
    GetSubnetMaskFieldAsString(1, subnetMaskField1, false);
    GetSubnetMaskFieldAsString(2, subnetMaskField2, false);
    GetSubnetMaskFieldAsString(3, subnetMaskField3, false);
    
    sprintf(subnetMaskBuffer, "%s.%s.%s.%s", subnetMaskField0, subnetMaskField1, subnetMaskField2, subnetMaskField3);
}

/*
    Sets our subnet mask from the string passed to it, which we expect to be in the conventional form,
    i.e. as four integers, each of which can be 1-3 digits, separated by dots, e.g. "123.456.789.123".

    Args: a pointer to a buffer which contains the string.

    No return code
*/
void NetworkParameters::SetSubnetMaskFromString(char *subnetMaskBuffer)
{
    char fieldBuff[20];
    int fieldBuffIndex;
    int subnetMaskBufferIndex;
    
    subnetMaskBufferIndex = 0;
    for (int subnetMaskIndex = 0; subnetMaskIndex < 4; ++subnetMaskIndex) {
        fieldBuffIndex = 0;
        while((subnetMaskBuffer[subnetMaskBufferIndex] != '\0') && (subnetMaskBuffer[subnetMaskBufferIndex] != '.')){
            fieldBuff[fieldBuffIndex++] = subnetMaskBuffer[subnetMaskBufferIndex++];
        }
        fieldBuff[fieldBuffIndex] = '\0';
        
        SetSubnetMaskFieldFromString(subnetMaskIndex, fieldBuff);
        
        if(subnetMaskBuffer[subnetMaskBufferIndex] == '\0') break;
        
        ++subnetMaskBufferIndex; // Point to next field
    }
}


/*
    Outputs the gateway address as a null-terminated string, in the conventional form,
    i.e. as four integers, each of which can be 1-3 digits, separated by dots, e.g. "123.456.789.123".
    If any of the values is zero, it will appear as "0", not as an empty string - but other than that,
    there will be no leading zeroes.
    
    Args: a pointer to a buffer to contain the string.
          It is up to the caller to make sure this is long enough, i.e. at least 16 bytes long
                                                                        **********************
    No return code
*/
void NetworkParameters::GetGatewayAddressAsString(char *gatewayAddressBuffer)
{
    char gatewayAddressField0[10];
    char gatewayAddressField1[10];
    char gatewayAddressField2[10];
    char gatewayAddressField3[10];
    
    GetGatewayAddressFieldAsString(0, gatewayAddressField0, false);
    GetGatewayAddressFieldAsString(1, gatewayAddressField1, false);
    GetGatewayAddressFieldAsString(2, gatewayAddressField2, false);
    GetGatewayAddressFieldAsString(3, gatewayAddressField3, false);
    
    sprintf(gatewayAddressBuffer, "%s.%s.%s.%s", gatewayAddressField0, gatewayAddressField1, gatewayAddressField2, gatewayAddressField3);
}

/*
    Sets our gateway address from the string passed to it, which we expect to be in the conventional form,
    i.e. as four integers, each of which can be 1-3 digits, separated by dots, e.g. "123.456.789.123".

    Args: a pointer to a buffer which contains the string.

    No return code
*/
void NetworkParameters::SetGatewayAddressFromString(char *gatewayAddressBuffer)
{
    char fieldBuff[20];
    int fieldBuffIndex;
    int gatewayAddressBufferIndex;
    
    gatewayAddressBufferIndex = 0;
    for (int gatewayAddressIndex = 0; gatewayAddressIndex < 4; ++gatewayAddressIndex) {
        fieldBuffIndex = 0;
        while((gatewayAddressBuffer[gatewayAddressBufferIndex] != '\0') && (gatewayAddressBuffer[gatewayAddressBufferIndex] != '.')){
            fieldBuff[fieldBuffIndex++] = gatewayAddressBuffer[gatewayAddressBufferIndex++];
        }
        fieldBuff[fieldBuffIndex] = '\0';
        
        SetGatewayAddressFieldFromString(gatewayAddressIndex, fieldBuff);
        
        if(gatewayAddressBuffer[gatewayAddressBufferIndex] == '\0') break;
        
        ++gatewayAddressBufferIndex; // Point to next field
    }
}


/*
    Tells the caller whether or not the specified touch index is on the easyGUI 'EthernetParametersPage',
    and therefore needs to be handled by this class.
    
    Args: the touch area index in question
    
    Return code: true if the touch area represents a network parameter, false if not
*/
bool NetworkParameters::TouchAreaIsNetworkParameter(int touchAreaIndex)
{
    if((touchAreaIndex >= MIN_NETWORK_PARAM) && (touchAreaIndex <= MAX_NETWORK_PARAM)) {
        return true;
    }
    
    // 'else'...
    return false;
}


/*
    Tells the caller if the specified touch area corresponds to a value the user can edit
    on the easyGUI 'EthernetParametersPage', and if so, which one.
    
    Args: the touch area index in question
    
    Returns the index of the corresponding entry in our 'variablesForTouchArea' array,
    or -1 if there is no such entry. It is up to the caller to check for -1
                                     **************************************
*/
int NetworkParameters::GetIndexOfVariablesToEditForTouchArea(int touchAreaIndex)
{
    for (int index = 0; index < COUNT_OF_VARIABLES_FOR_TOUCH_AREAS; ++index) {
        if(variablesForTouchArea[index].touchAreaIndex == touchAreaIndex) {
            return index;
        }
    }
    
    // 'else' no Network Parameters variable corresponds to the specified touch area
    return -1;
}


/*
    If the specified touch area represents a key or field on the easyGUI 'EthernetParametersPage',
    this function performs whatever action is appropriate for it. Provided so that the caller
    can (in effect) say "if this is one of yours, deal with it", without needing to know 
    anything about what this class does, or how it handles the keys on that easyGUI page.

    Args: the touch area index in question
    
    Returns true if it dealt with the touch area (so the caller need not do anything else 
    with the value), or false if it did not deal with the touch area (implying that it 
    was not a touch area on the easyGUI 'EthernetParametersPage', and so the caller
    must deal with it some other way).
*/
bool NetworkParameters::DealWithTouch(int touchAreaIndex)
{
    if(TouchAreaIsNetworkParameter(touchAreaIndex)) {
    
#ifdef TOUCH_VALUES_DIRECTLY
        // Has the user selected a field to edit - 
        // if so, we will have an entry in our 'variablesForTouchArea' array that corresponds with this touch area
        int indexOfVariablesToEdit = GetIndexOfVariablesToEditForTouchArea(touchAreaIndex);
        if(indexOfVariablesToEdit != -1) {        
            // User has selected a field to edit
            indexOfVariablesCurrentlyBeingEdited = indexOfVariablesToEdit;
            NumericKeypadPageHandler* numericKeypadPageHandler = NumericKeypadPageHandler::GetInstance(usbDevice, usbHostGC);
            if(numericKeypadPageHandler != NULL) {
                
                numericKeypadPageHandler->StartEditing(variablesForTouchArea[indexOfVariablesCurrentlyBeingEdited].easyGUIVariablePtr);
                
                // We need the numeric keypad to update the easyGUI variable *and* our internal variable - they must always match
                numericKeypadPageHandler->SetEasyGUIVariableToEdit(variablesForTouchArea[indexOfVariablesCurrentlyBeingEdited].easyGUIVariablePtr);
                numericKeypadPageHandler->SetInternalVariableToEdit(variablesForTouchArea[indexOfVariablesCurrentlyBeingEdited].internalVariablePtr);
                
                numericKeypadPageHandler->SetEasyGUICallingPage(GuiStruct_EthernetParametersPage_50);
                numericKeypadPageHandler->SetEditVariableRange(0, variablesForTouchArea[indexOfVariablesCurrentlyBeingEdited].maxValue);
                numericKeypadPageHandler->SetEditVariableName(variablesForTouchArea[indexOfVariablesCurrentlyBeingEdited].variableName);
                
                numericKeypadPageHandler->DisplayEasyGUIPage();
            }
            return true;
        } 
#endif // TOUCH_VALUES_DIRECTLY

        if(touchAreaIndex == NETWORK_PARAMS_PORT_EDIT) {
            indexOfVariablesCurrentlyBeingEdited = 0; // Port
            NumericKeypadPageHandler* numericKeypadPageHandler = NumericKeypadPageHandler::GetInstance(usbDevice, usbHostGC);
            if(numericKeypadPageHandler != NULL) {
                
                numericKeypadPageHandler->StartEditing(variablesForTouchArea[indexOfVariablesCurrentlyBeingEdited].easyGUIVariablePtr);
                
                // We need the numeric keypad to update the easyGUI variable *and* our internal variable - they must always match
                numericKeypadPageHandler->SetEasyGUIVariableToEdit(variablesForTouchArea[indexOfVariablesCurrentlyBeingEdited].easyGUIVariablePtr);                
                numericKeypadPageHandler->SetInternalVariableToEdit(variablesForTouchArea[indexOfVariablesCurrentlyBeingEdited].internalVariablePtr);
                
                numericKeypadPageHandler->SetEasyGUICallingPage(GuiStruct_EthernetParametersPage_50);
                numericKeypadPageHandler->SetEditVariableRange(0, variablesForTouchArea[indexOfVariablesCurrentlyBeingEdited].maxValue);
                numericKeypadPageHandler->SetEditVariableName(variablesForTouchArea[indexOfVariablesCurrentlyBeingEdited].variableName);
                
                numericKeypadPageHandler->DisplayEasyGUIPage();
            }
            return true;
        }
        
        // 'else'...
        
        if(DealWithIPEditButton(touchAreaIndex)) {
            return true;
        }
        
        // 'else'...
        
        if(DealWithMaskEditButton(touchAreaIndex)) {
            return true;
        }
        
        // 'else'...
        
        if(DealWithGatewayEditButton(touchAreaIndex)) {
            return true;
        }
            
        // 'else'...
        
        if(DealWithCancelButton(touchAreaIndex)) {
            return true;
        }
            
        // 'else'...
        
        if(DealWithApplyButton(touchAreaIndex)) {
            return true;
        }
            
        // 'else'...
        
        if(DealWithUseDHCPButton(touchAreaIndex)) {
            return true;
        }

        return false; // Not dealt with touch area
    }
    
    // 'else' not one of our touch areas...
    return false;
}


/*
    If the specified touch area represents the Apply button on the easyGUI 'EthernetParametersPage',
    this function will apply the current values on that page. In theory, this should mean closing 
    the current Ethernet connection, if any, and setting up a new one with the new values. However,
    in practice the EthernetInterface class does not seem to be able to do this (while the first 
    call to the EthernetInterface 'init' method succeeds, subsequent calls crash). So we write 
    our current values to QSPI memory, and then force the entire application to restart, 
    knowing that when it does so, GetGCStatusLoop::MainLoopWithEthernet will call us back 
    to get the new Ethernet parameters from QSPI memory before calling the EthernetInterface 'init' method.

    Args: the touch area index in question
    
    Returns true if the specified touch area is the Apply button, false if not
    (we are just telling the caller whether it needs to do anything else with this value)
*/
bool NetworkParameters::DealWithApplyButton(int touchAreaIndex)
{
    if(touchAreaIndex == NETWORK_PARAMS_APPLY_BUTTON) {
        
        useDHCP = false;
        
        UpdateInternalValuesFromEasyGUIVariables();
        
        SaveToQSPISettings();
        
        GetGCStatusLoop* getGCStatusLoop = GetGCStatusLoop::GetInstance();
        if(getGCStatusLoop != NULL) {
            getGCStatusLoop->ForceRestart(); // This is the only way to make the new values take effect
        }

        return true;
    }
    
    // 'else' not the Apply button
    return false;
}


/*
    If the specified touch area represents the Cancel button on the easyGUI 'EthernetParametersPage',
    this function will reset the current values on that page to the 'real' values -
    i.e. the ones we are actually using for the Ethernet link.

    Args: the touch area index in question
    
    Returns true if the specified touch area is the Cancel button, false if not
    (we are just telling the caller whether it needs to do anything else with this value)
*/
bool NetworkParameters::DealWithCancelButton(int touchAreaIndex)
{
    if(touchAreaIndex == NETWORK_PARAMS_CANCEL_BUTTON) {
        
        RestoreRealValues();
        UpdateEasyGUIVariablesFromInternalValues();

#ifdef USE_BACKGROUND_COLOURS
        SetAllFieldBackgroundColoursToInactive();
#else
        SetAllFieldBackgroundColoursToWhite();
#endif

        indexOfVariablesCurrentlyBeingEdited = -1; 
        
        UpdateEasyGUIPage();

        return true;
    }
    
    // 'else' not the Cancel button
    return false;
}


/*
    If the specified touch area represents the "Use DHCP" button on the easyGUI 'EthernetParametersPage',
    this function will restart the Ethernet connection using DHCP to obtain the IP address, etc, values, 
    instead of using the explicit ones shown on this page. In theory, this should mean closing 
    the current Ethernet connection, if any, and setting up a new one with the new values. However,
    in practice the EthernetInterface class does not seem to be able to do this (while the first 
    call to the EthernetInterface 'init' method succeeds, subsequent calls crash). So we write 
    "UseDHCP = true" to QSPI memory, and then force the entire application to restart, 
    knowing that when it does so, GetGCStatusLoop::MainLoopWithEthernet will call us back 
    to get the new Ethernet parameters from QSPI memory, see that "UseDHCP" is set true,
    and call the appropriate EthernetInterface 'init' method.

    Args: the touch area index in question
    
    Returns true if the specified touch area is the "Use DHCP" button, false if not
    (we are just telling the caller whether it needs to do anything else with this value)
*/
bool NetworkParameters::DealWithUseDHCPButton(int touchAreaIndex)
{
    if(touchAreaIndex == NETWORK_PARAMS_DHCP_BUTTON) {
        
        useDHCP = true;
        
        UpdateInternalValuesFromEasyGUIVariables();
        
        SaveToQSPISettings();
        
        GetGCStatusLoop* getGCStatusLoop = GetGCStatusLoop::GetInstance();
        if(getGCStatusLoop != NULL) {
            getGCStatusLoop->ForceRestart(); // This is the only way to make the new values take effect
        }

        return true;
    }
    
    // 'else' not the Apply button
    return false;
}


/*
    If the specified touch area represents the "Edit IP address" button on the easyGUI 'EthernetParametersPage',
    this function invokes the EthernetKeypadPageHandler to do that.

    Args: the touch area index in question
    
    Returns true if the specified touch area is the "Edit IP address" button, false if not
    (we are just telling the caller whether it needs to do anything else with this value)
*/
bool NetworkParameters::DealWithIPEditButton(int touchAreaIndex)
{
    if(touchAreaIndex == NETWORK_PARAMS_IP_EDIT) {
        
        EthernetKeypadPageHandler* ethernetKeypadPageHandler = EthernetKeypadPageHandler::GetInstance(usbDevice, usbHostGC);
        if(ethernetKeypadPageHandler != NULL) {
                
            ethernetKeypadPageHandler->SetEasyGUIOctetVariablesToEdit(GuiVar_ethernetIP1, GuiVar_ethernetIP2, GuiVar_ethernetIP3, GuiVar_ethernetIP4);
            ethernetKeypadPageHandler->SetInternalOctetVariablesToEdit(&(ipAddress[0]), &(ipAddress[1]), &(ipAddress[2]), &(ipAddress[3]));
            
            ethernetKeypadPageHandler->StartEditing("IP Address");
        }

        return true;
    }
    
    // 'else'...
    return false;
}


/*
    If the specified touch area represents the "Edit subnet mask" button on the easyGUI 'EthernetParametersPage',
    this function invokes the EthernetKeypadPageHandler to do that.

    Args: the touch area index in question
    
    Returns true if the specified touch area is the "Edit subnet mask" button, false if not
    (we are just telling the caller whether it needs to do anything else with this value)
*/
bool NetworkParameters::DealWithMaskEditButton(int touchAreaIndex)
{
    if(touchAreaIndex == NETWORK_PARAMS_MASK_EDIT) {
        
        EthernetKeypadPageHandler* ethernetKeypadPageHandler = EthernetKeypadPageHandler::GetInstance(usbDevice, usbHostGC);
        if(ethernetKeypadPageHandler != NULL) {
                
            ethernetKeypadPageHandler->SetEasyGUIOctetVariablesToEdit(GuiVar_ethernetMask1, GuiVar_ethernetMask2, GuiVar_ethernetMask3, GuiVar_ethernetMask4);
            ethernetKeypadPageHandler->SetInternalOctetVariablesToEdit(&(subnetMask[0]), &(subnetMask[1]), &(subnetMask[2]), &(subnetMask[3]));
            
            ethernetKeypadPageHandler->StartEditing("Subnet Mask");
        }

        return true;
    }
    
    // 'else'...
    return false;
}


/*
    If the specified touch area represents the "Edit gateway" button on the easyGUI 'EthernetParametersPage',
    this function invokes the EthernetKeypadPageHandler to do that.

    Args: the touch area index in question
    
    Returns true if the specified touch area is the "Edit gateway" button, false if not
    (we are just telling the caller whether it needs to do anything else with this value)
*/
bool NetworkParameters::DealWithGatewayEditButton(int touchAreaIndex)
{
    if(touchAreaIndex == NETWORK_PARAMS_GATEWAY_EDIT) {
        
        EthernetKeypadPageHandler* ethernetKeypadPageHandler = EthernetKeypadPageHandler::GetInstance(usbDevice, usbHostGC);
        if(ethernetKeypadPageHandler != NULL) {

            ethernetKeypadPageHandler->SetEasyGUIOctetVariablesToEdit(GuiVar_ethernetGateway1, GuiVar_ethernetGateway2, GuiVar_ethernetGateway3, GuiVar_ethernetGateway4);
            ethernetKeypadPageHandler->SetInternalOctetVariablesToEdit(&(gatewayAddress[0]), &(gatewayAddress[1]), &(gatewayAddress[2]), &(gatewayAddress[3]));
            
            ethernetKeypadPageHandler->StartEditing("Gateway");
        }

        return true;
    }
    
    return false;
}


/*
    For each of our internal (private) variables, make it equal to the value
    of the corresponding easyGUI variable (the value displayed to the user)
    
    No arguments, no return code
*/
void NetworkParameters::UpdateInternalValuesFromEasyGUIVariables(void)
{
    SetPortNumberFromString(GuiVar_ethernetPort);
    
    SetIPAddressFieldFromString(0, GuiVar_ethernetIP1);
    SetIPAddressFieldFromString(1, GuiVar_ethernetIP2);
    SetIPAddressFieldFromString(2, GuiVar_ethernetIP3);
    SetIPAddressFieldFromString(3, GuiVar_ethernetIP4);
    
    SetSubnetMaskFieldFromString(0, GuiVar_ethernetMask1);
    SetSubnetMaskFieldFromString(1, GuiVar_ethernetMask2);
    SetSubnetMaskFieldFromString(2, GuiVar_ethernetMask3);
    SetSubnetMaskFieldFromString(3, GuiVar_ethernetMask4);

    SetGatewayAddressFieldFromString(0, GuiVar_ethernetGateway1);
    SetGatewayAddressFieldFromString(1, GuiVar_ethernetGateway2);
    SetGatewayAddressFieldFromString(2, GuiVar_ethernetGateway3);
    SetGatewayAddressFieldFromString(3, GuiVar_ethernetGateway4);
}


/*
    For each of our internal (private) variables, copy its value
    to the corresponding easyGUI variable (the value displayed to the user)
    
    No arguments, no return code
*/
void NetworkParameters::UpdateEasyGUIVariablesFromInternalValues(void)
{
    GetPortNumberAsString(GuiVar_ethernetPort);
    
    GetIPAddressFieldAsString(0, GuiVar_ethernetIP1);
    GetIPAddressFieldAsString(1, GuiVar_ethernetIP2);
    GetIPAddressFieldAsString(2, GuiVar_ethernetIP3);
    GetIPAddressFieldAsString(3, GuiVar_ethernetIP4);
    
    GetSubnetMaskFieldAsString(0, GuiVar_ethernetMask1);
    GetSubnetMaskFieldAsString(1, GuiVar_ethernetMask2);
    GetSubnetMaskFieldAsString(2, GuiVar_ethernetMask3);
    GetSubnetMaskFieldAsString(3, GuiVar_ethernetMask4);

    GetGatewayAddressFieldAsString(0, GuiVar_ethernetGateway1);
    GetGatewayAddressFieldAsString(1, GuiVar_ethernetGateway2);
    GetGatewayAddressFieldAsString(2, GuiVar_ethernetGateway3);
    GetGatewayAddressFieldAsString(3, GuiVar_ethernetGateway4);
}


/*
    (Re)display the easyGUI 'EthernetParametersPage' -
    e.g. after the caller has updated one or more of the easyGUI variables
    included in the page, and wants to display the new value to the user.
    
    No arguments, no return code
*/
void NetworkParameters::UpdateEasyGUIPage(void)
{
#define WANT_GUILIB_CLEAR
#ifdef WANT_GUILIB_CLEAR
#ifdef USING_BACKGROUND_BITMAP
    DrawBackgroundBitmap();
#else
    GuiLib_Clear();
#endif
#undef WANT_GUILIB_CLEAR
#endif
    GuiLib_ShowScreen(GuiStruct_EthernetParametersPage_50, GuiLib_NO_CURSOR, GuiLib_RESET_AUTO_REDRAW);

    GuiLib_Refresh();    
}