// keep these at the top!
#define COM_SCRIPT_VERSION                      1.97
#define COM_SCRIPT_NAME                         "CommonUtilities.inc"

/***************************************************************************************************************************
*
*   Copyright © 2001-2005 Creo Inc. All rights reserved.
*
*   File: CommonUtilities.inc
*
*   Purpose:
*   This file defines all common routines on MPE/MCE devices for:                                      
*       - device I/O communication (commands, parameters),
*       - file I/O,
*       - user CANCEL detection,
*       - debug information display in SPT Terminal.log,
*       - common plot and calibration routines.
*
*   Note: this is an "include#" file, not a stand alone script.
****************************************************************************************************************************
* Version   Date            Author          Description
*---------------------------------------------------------------------------------------------------------------------------
* 1.97      May/10/2006     K.Dyck          Added support for TH1.x V2.00
* 1.96      Mar/06/2006     J.FLORES        Added GMCE support to COM_ResetTheDevice(), COM_EraseBoardNVS() and created 
                                            COM_PutGMCEIntoBootMode(), COM_TestAndWaitForGMCEPrompt(), COM_EraseMPENVS(), 
                                            COM_EraseGMCENVS(), COM_TestAndWaitForGMCEPrompt(). Also modified COM_Output().
* 1.95      Feb/16/2006     G.Brown         Removed COM_OpenFile() made changes to account for splot 4.83
* 1.94      Feb/16/2006     G.Brown         Fixed TFX bugs in COM_GetHeadFWVersion() and COM_TestForTFX()
* 1.93      Feb/14/2006     G.Brown         Updated COM_ResetTheDevice() and removed function declerations
* 1.92      Feb/03/2006     G.Brown         Changed function name and contents COM_GetServiceShellClientVersionOnHostMachine()
* 1.91      Jan/30/2006     G.Brown         Added COM_IsMCE3244() and COM_GetRegistryValue()
* 1.90      Jan/13/2006     G.Brown         Modified COM_CopyDirectory to copy empty folders as well
* 1.89      Dec/16/2005     G.Brown         Updated COM_CheckIfNewspaperOrAutoloader()
* 1.88      Oct/28/2005     G.Brown         Added GMCE support more functions.  Added COM_RenameFile() & 
                                            COM_ExtractExtensionFromPath()
* 1.87      Oct/13/2005     G.Brown         Added GMCE support to some commonly used functions
* 1.86      Sep/01/2005     G.Brown         Added GMCE to COM_GetFWType()
* 1.85      Jun/17/2005     G.Brown         Updated COM_TestForTFX() and COM_TestForTH2() - the MPE support needed rework
* 1.84      Jun/17/2005     G.Brown         Fixed a bug in COM_GetHeadFWVersion()
* 1.83      Jun/16/2005     G.Brown         Enhanced file updating Modified: COM_UpdateFileRefFileAndFilesReferencedInIt()
                                                                             COM_CheckVersionUpdateFile()
                                                                             COM_UpdateFilesInReferenceFile()
* 1.82      May/30/2005     G.Brown         Added COM_ConvertFWVersionToBuildVersionInt() and modified 
*                                           COM_UpdateFilesInReferenceFile()
* 1.81      May/25/2005     G.Brown         Added COM_ScriptUpdatedMustEndDialog(), COM_UpdateFileRefFileAndFilesReferencedInIt() 
                                            and COM_UpdateFilesInReferenceFile()
* 1.80      Mar/16/2005     G.Brown         Added COM_GetStringFromFile()
* 1.79      Mar/03/2005     G.Brown         Changed the name COM_CheckIfNewspaperOrAutoloader(), added COM_GetMCEFirmwareVersion()
                                            and modified COM_GetFirmwareVersion()
* 1.78      Feb/21/2005     G.Brown         Modified COM_BreakStringIntoChunksAndTrasmit() and Removed COM_ReplaceBackSlash()
                                            Modified COM_GetHeadFWVersion() and made all device debug go directly to the SS log file
                                            Modified COM_Output()
* 1.77      Feb/17/2005     G.Brown         Fixed a bug in COM_VerifyNVS()
* 1.76      Jan/26/2005     G.Brown         Fixed some bugs in COM_TestForTFX()
* 1.75      Jan/26/2005     G.Brown         Added connection types and modified COM_GetConnectionType()
* 1.74      Jan/25/2005     G.Brown         Added MCE_OREN_TURBO_MCE device, added a check for "GRAV" in COM_GetDeviceTYpe()
* 1.73      Jan/11/2005     G.Brown         Fixed a bug in COM_CheckForServiceShellPath()
* 1.72      Jan/06/2005     G.Brown         Created COM_BreakStringIntoChunksAndTrasmit() and enhanced COM_Output()
* 1.71      Jan/06/2005     G.Brown         Need to spawn an update.
* 1.70      Jan/05/2005     G.Brown         Added COM_GetModelType() and enhanced COM_Output()
* 1.69      Nov/03/2004     G.Brown         Modified COM_GetDeviceIntoGoodStartingPoint() and COM_CheckForDualMCE()
* 1.68      Nov/01/2004     G.Brown         Added COM_GetServiceShellClientVersion()
* 1.67      Nov/01/2004     G.Brown         Added NO_SUSPEND_IN_COMMON_UTL in COM_Output()
* 1.66      Oct/20/2004     G.Brown         Modified COM_GetDeviceIntoGoodStartingPoint() and Modified COM_GetDeviceType()
*                                           to try to get fw simulators to work.
* 1.65      Oct/19/2004     G.Brown         Fixed a bug in COM_CopyDirectory()
* 1.64      Oct/06/2004     G.Brown         Modified COM_EraseBoardNVS()
* 1.63      Oct/06/2004     G.Brown         Fixed a bug in COM_EraseBoardNVS() and added functionality to COM_EraseBoardNVS()
* 1.62      Sep/02/2004     G.Brown         Added COM_CovertCharHexStringToDecimal()
* 1.61      Sep/01/2004     G.Brown         Added LMCE support
* 1.60      Aug/30/2004     G.Brown         Modified COM_EraseNVS()
* 1.59      Aug/27/2004     G.Brown         Added COM_PutMCEIntoBootMode()
* 1.58      Aug/17/2004     G.Brown         Updated COM_GetDeviceType()
* 1.57      Aug/12/2004     G.Brown         Updated COM_ResetTheDevice()
* 1.56      Jul/29/2004     G.Brown         Modified COM_EraseBoardNVS()
* 1.55      Jul/28/2004     G.Brown         Modified COM_EraseBoardNVS()
* 1.54      Jul/26/2004     G.Brown         Added COM_CheckForNewspaper() &COM_CheckForSANewspaper()
* 1.53      Jul/19/2004     G.Brown         Fixed a bug in COM_TestForTH2()
* 1.52      Jul/12/2004     G.Brown         Added COM_IsMPE3244(), COM_EraseBoardNVS() and COM_GetMPEDeviceTypeFromUser()
* 1.51      Jun/14/2004     G.Brown         Added COM_CheckVersionUpdateFile, added to COM_Output()
* 1.50      Jun/14/2004     G.Brown         Added Dual and single head TSC devices
* 1.49      Jun/02/2004     G.Brown         Added #ifndef NODEBUG and changed some printfs to COM_Output
* 1.48      May/28/2004     G.Brown         I added to device types QUANTUM and 2630
* 1.47      May/21/2004     G.Brown         Added COM_GetDeviceTypeConfiguredInHost() and modified COM_CopyAndOverwriteFile()
* 1.46      Mar/24/2004     G.Brown         Fixed a minor bug with COM_GetDeviceType()
* 1.45      Mar/23/2004     G.Brown         Added model defines
* 1.44      Mar/23/2004     G.Brown         Added COM_ReplaceSpace(deviceType) to COM_GetDeviceType()
* 1.43      Mar/15/2004     G.Brown         Modified COM_GetDeviceType()
* 1.42      Mar/11/2004     A.Siewierski    Added COM_ReplaceCharacter(), COM_GetSystemDate(), COM_GetSystemTime(), COM_LCase(),
*                                           COM_UCase(),
* 1.41      Mar/11/2004     G.Brown         Updated COM_GetSSWorkingDirectory()
* 1.40      Feb/27/2004     G.Brown         Added UPDATE_LOCATION and COM_CopyDirectory()
* 1.39      Feb/13/2004     A.Siewierski    Added drum media status check to COM_LoadPlate() and flag bUnloadFirst, added
*                                           COM_UnloadPlate(), modified COM_GetAllMediaNames() to allow proofs or plates only,
*                                           added COM_GetCurrentMediaInfo(), COM_SelectMediaByName(), COM_HeadCalculateExposure(),
*                                           modified COM_CalibrateFocus() to return FAILURE if sr outside of range. 
*                                           updated COM_FileDelete(), fixes to error msg extraction, removed error constants.
* 1.38      Feb/17/2004     G.Brown         Added COM_TestForTFX().
* 1.37      Feb/10/2004     G.Brown         Updated COM_CopyAndOverwriteFile and COM_CopyAndOverwriteFileNoCheck
* 1.36      Feb/10/2004     G.Brown         Updated my functions with COM_.
* 1.35      Feb/10/2004     G.Brown         Updated GetHeadType() and GetHeadFWVersion().
* 1.34      Feb/10/2004     A.Siewierski    Added COM_FileAppend(), removed all debug info from all file handling procedures.
* 1.33      Feb/10/2004     G.Brown         Modified GetSSWorkingDirectory()
* 1.32      Feb/09/2004     A.Siewierski    Added COM_LoadPlate(), COM_TSAL_ForceLoadRamp(), modified COM_GetAllMediaNames()
* 1.31      Feb/05/2004     A.Siewierski    Fixed COM_RemoveStringArtifacts(), replaced all references to COM_ExitScript() with 
*                                           return nRC, 
* 1.30      Feb/05/2004     A.Siewierski    Added (again) COM_GetFocus(), COM_FindPlateEdge(), COM_CalibrateFocus(), 
*                                           #include <errors.inc>, COM_GetRandomNumber(), COM_GetDeviceSN(), FW error msg retrieval,
*                                           fixed string retrieval in COM_ExtractStringWithinQuotes(), added COM_GetDeviceSN(),
*                                           added COM_GetDeviceType(), COM_GetHeadType(), COM_GetAllMediaNames()
* 1.29      Feb/04/2004     G.Brown         Updated GetSSWorkingDirectory()  and CheckForServiceShellPath() to remove bin if 
*                                           found install path under bin.
* 1.28      Feb/03/2004     G.Brown         Updated GetFileFromAnyLocation() and GetFileFromAnyLocationNoCheck() del "\"%s\""
* 1.27      Jan/28/2004     G.Brown         Updated GetSSWorkingDirectory() and added STR_LEN and CheckForServiceShellPath()
* 1.26      Jan/28/2004     G.Brown         Added GetSSWorkingDirectory() and modified GetFileLocationsForHost(),
*                                           OpenSSDataFile and WriteToSSDataFile()
* 1.25      Jan/13/2004     G.Brown         Modified GetFirmwareVersion() so VLFAL does not take long if FW is greater than 
*                                           3.00.  I also move some #define for MPE, MCE, MCE2
*                                           Added OpenSSDataFile() & WriteToSSDataFile().
* 1.24      Jan/13/2004     G.Brown         Modified CopyFileToExternalLocation()
* 1.23      Jan/13/2004     G.Brown         Modified CreateFolder()
* 1.22      Dec/11/2003     G.Brown         Added GetScriptVersion() and UpdateFile()
* 1.21      Dec/08/2003     G.Brown         Made a fix for detecting the MPE TSSA and TSSB devices.  
* 1.20      Dec/08/2003     G.Brown         Added MPE proofsetter as a device type and modified GetDeviceIntoGoodStartingPoint()         
* 1.19      Dec/04/2003     G.Brown         Removed suspend from IsSpectrum()         
* 1.18      Oct/08/2003     G.Brown         Added GetServiceHostVersion()         
* 1.17      Oct/26/2003     G.Brown         Added GetFileFromAnyLocationNoCheck()
* 1.16      Sep/23t/2003    G.Brown         Modified TesAndWaitForPrompt()
* 1.15      Sep/16t/2003    G.Brown         Added IsSpectrum()
* 1.14      Sep/11t/2003    G.Brown         CheckHostConfigForMCE2()
* 1.13      Sep/09t/2003    G.Brown         Removed this: Updated GetOwnerName() to capture '-' in a name
* 1.12      Sep/08t/2003    G.Brown         I updated RemoveCharactersFromString()
* 1.11      Sep/05t/2003    G.Brown         Changed SignOn(), Updated GetOwnerName() to capture '-' in a name
* 1.10      Aug/13/2003     G.Brown         Transferred more functions to this file.  Added functions for head 1.91 upgrades 
* 1.09      Aug/13/2003     G.Brown         Transferred some functions to this file.  Updated CheckForPrompt()
* 1.08      Aug/13/2003     G.Brown         Added - RemoveCharactersFromString
* 1.07      Aug/11/2003     G.Brown         Updated client path to return capitals for drive letter.
* 1.06      Jan/31/2003     G.Brown         Added GetDeviceInfo()
* 1.05      Jan/29/2003     G.Brown         Removed #define RESTORE_NVS 4
* 1.04      Jan/29/2003     G.Brown         Added CheckAndWaitForMCEPrompt
* 1.03      Jan/29/2003     G.Brown         Added functions created by G.Brown
* 1.02      Jan/29/2003     A.Siewierski    Added boolean parameters retrieval. Tested with MCE.
* 1.01      Jan/28/2003     A.Siewierski    Lite demo version.
* 1.00      May/31/2001     A.Siewierski    Original, MPE only version.
****************************************************************************************************************************/

//Errors
#include <errors.inc>

// Return codes for COM_SendCommand().
#define SEND_CMD_TIMEOUT                        1
#define SEND_CMD_ERROR                          2
#define SEND_CMD_ERROR_RESUME                   3
#define SEND_CMD_ERROR_CLEAR                    4
#define SEND_CMD_ERROR_ABORT                    5
#define SEND_CMD_ERROR_RESUME_CLEAR             6
#define SEND_CMD_ERROR_RESUME_ABORT             7
#define SEND_CMD_ERROR_RESUME_CLEAR_ABORT       8
#define SEND_CMD_CANCELLED                      9
#define SEND_CMD_UNSUPPORTED                    10
#define SEND_CMD_INVALID                        11
#define SEND_CMD_PARM_INVALID                   12
#define SEND_CMD_PARM_OUT_OF_RANGE              13

// SPlot waitreg() expressions
#define GMCE_DEVICE_TYPE                        "[A-Za-z0-9\+\_ ]*>"
#define MCE_DEVICE_TYPE                         "[A-Za-z0-9\+\_ ]*>"
#define NUMERIC_VALUE                           "-*[0-9]+[\\.]*[0-9]*[^0-9]"
#define STRING_VALUE                            "\"[^\"]*\""
#define NON_NUMERIC_VALUE                       "[^0-9]+"
#define ANYCHAR_TO_EOL_VALUE                    "[^\r]+\r"                       // Any character(s) to end of line. If there is a better name out there, tell me;)
#define BOOLEAN_VALUE                           "[^fFtT]+[fFtT]+[aArR]+[lLuU]+[sSeE]+[eE ]+"      // false or true, upper, lower or mixed case
#define FW_ERROR                                "\\*\\*\\*[^0-9]+[0-9]*): code [0-9]+[^0-9]+"
#define FW_ERROR_DESCRIPTION                    "\[[^\]]*\]"
#define FW_ERROR_CODE                           "): code"
#define FW_ERROR_EXPECTED_SUSPEND_RESPONSE      "expected SUSPEND responses"
#define FW_ERROR_RESUME_EXPECTED                "RESUME[^\r]+\r"
#define FW_ERROR_CLEAR_EXPECTED                 "CLEAR[^\r]+\r"
#define FW_ERROR_ABORT_EXPECTED                 "ABORT[^\r]+\r"
#define FW_ERROR_RESUME_CLEAR_EXPECTED          "RESUME[\ ]+CLEAR[^\r]+\r"
#define FW_ERROR_RESUME_ABORT_EXPECTED          "RESUME[\ ]+ABORT[^\r]+\r"
#define FW_ERROR_RESUME_CLEAR_ABORT_EXPECTED    "RESUME[\ ]+CLEAR[\ ]+ABORT[^\r]+\r"
#define FW_ERROR_RESUME_ABORT_CLEAR_EXPECTED    "RESUME[\ ]+ABORT[\ ]+CLEAR[^\r]+\r"  //"RESUME or ABORT or CLEAR"
#define FW_TIMEOUT                              "Timeout sending command!"
#define FW_PARM_OUT_OF_RANGE                    "out of range"
#define FW_PARM_INVALID                         "Invalid parameter, unable to set parameter in device!"
#define FW_CMD_INVALID                          "Invalid command"
#define FW_CMD_UNSUPPORTED                      "Command not supported"
#define FW_CMD_CANCELLED                        "Command Cancelled"
#define FW_CMD_HEAD_CANCELLED                   "Exposure Head unsolicited message:"

// FW parameters types
#define PARM_NUMERIC                      1     // Float, double or int:  -123.456
#define PARM_STRING                       2     // "device name"
#define PARM_BOOLEAN                      3     // True False
#define PARM_ANYCHAR_TO_EOL               4     // Any alphanumeric character(s) until the End Of Line

// FW value types
#define ACTIVE                            1
#define SAVED                             2
#define DEFAULT                           3


// Command send/receive
#define STR_LEN         256      // Standard length of a string
#define STR_LEN_LONG    512      // Non Standard length of a string

// File I/O
#define INPUT_FILENAME                    "VBtoSPT.txt"
#define OUTPUT_FILENAME                   "SPTtoVB.txt"

#define ALL_NVS_FILENAME                  "AllNVS.txt"
#define TA_NVS_FILENAME                   "TANVS.txt"
#define SCRIPT_NVS_FILENAME               "ScriptNVS.txt"

#define MODE_READ_ONLY                    "r"
#define MODE_WRITE                        "w"
#define MODE_APPEND                       "a"

#define PATH_SERVICE_SHELL_LOGS             1

// Script Exit constants
#define EXIT_SUCCESS    1
#define EXIT_CANCEL     2
#define EXIT_FATAL      3
#define EXIT_CRITICAL   4
#define EXIT_ERROR      5
#define EXIT_FAILURE    6

// Script Restore bit flags
#define RESTORE_NONE            1
#define RESTORE_DEVICE_IDLE     2
#define RESTORE_ALL             RESTORE_NONE | RESTORE_DEVICE_IDLE | RESTORE_NVS            

// Misc
#define SUCCESS         0
#define FAILURE         1
#define TRUE            1
#define FALSE           0
#define SINGLE_QUOTE    "\""
#define OFF             0
#define ON              1
#define NONE            0
#define LINE_80         "________________________________________________________________________________"
#define LINE_40         "________________________________________"

#ifndef VERSIONNAME_CommonUtilities
#define VERSIONNAME_CommonUtilities "Common Utilities Version 1.0"

// Location to check for new script version updates
#define UPDATE_LOCATION "\\\\MASTER\\SOFTWARE\\BETA\\Controlled_Releases\\CreoAutoScriptUpdateFolder\\"

#define WAIT_TIME 3 

#define INFORMATIVE 0 
#define TERMINAL_DEBUG 1
#define TERMINAL 2 
#define SUSPEND_BOX 3 
#define TERMINAL_RESTORE_PARAMETERS 4 
#define TERMINAL_RESTORE_PARAMETERS_CATCH_CALLED 5 
#define INFO_DIALOG_BOX 7
#define INFORMATIVE_MPE_REPLACE_BACKSLASH 8
#define SUSPEND_BOX_YES_NO 9

#define GMCENAME "GMCE"
#define MCENAME "MCE"
#define MCE2NAME "MCE2"                                 
#define MPENAME "MPE"
#define TFXNAME "TFX"
#define TH3NAME "TH3"
#define SSDIAG "srvshell"

// connection types

#define NOT_CONNECTED "NC"
#define LOCAL_CONNECTION "Local"
#define REMOTE_CONNECTION "Remote"

// head types
#define HEAD_UNKNOWN    999
#define TH10            0
#define TH17            1
#define TFX             2
#define TH2             3
#define TH3             4
#define MAX_HEAD_TYPE   5   // Must be last value

// Device type definitions
#define DEVICE_UNKNOWN        1000
#define PS                    1
#define TS                    2
#define VLFPS                 3
#define VLFTS                 4
#define TSAL                  5
#define VLFTSAL               6
#define TS2637                7     // TS 2637 (Newspaper)
#define SPEC                  8     // Proofsetter
#define TSSPEC                9     // TS Spectrum
#define VLFPOST               10    // VLF Postsetter
#define FLEXO                 11    // Thermoflex

// MCE devices
#define TS_II                 12    
#define TS_II_SPEC            13
#define TS_II_PROOF           14
#define TS_II_AL              15
#define TS_II_CL              16
#define TS_II_CL_SP           17
#define TS_II_AL_SP           18
#define TS_NEWS               19     
#define TS_NEWS_SA            20     
#define TS_NEWS_200           21     
#define TSC                   22     
#define MAGNUS_VLF            23
#define MAGNUS_VLF_AL         24
#define MAGNUS_VLF_CL         25
#define FLEXO_WIDE_II         26
#define GRAVURE               27
#define FLAT_PANEL            28

#define MPE_3244_PLATESETTER        "T324"
#define MPE_TRENDSETTER_A           "TTSA"
#define MPE_TRENDSETTER_B           "TTSB"
#define MPE_VLF_PLATESETTER         "TVLF"
#define MPE_VLF_TRENDSETTER         "TVTS"
#define MPE_TRENDSETTER_AL          "TTSL"
#define MPE_VLF_AL                  "TVAL"
#define MPE_NEWS                    "TTSN"
#define MPE_TRENDSETTER_SP          "TTSS"
#define MPE_PROOFSETTER             "TTSS-P"
#define MPE_THERMOFLEX_WIDEI        "TFTS"

#define MCE_TRENDSETTER             "TS"
#define MCE_TRENDSETTER_AL          "TSAL"
#define MCE_TRENDSETTER_SP          "TSSP"
#define MCE_TRENDSETTER_CL          "TSCL"
#define MCE_TRENDSETTER_CL_SP       "TSCLSP"
#define MCE_TRENDSETTER_AL_SP       "TSALSP" 
#define MCE_MAGNUS_VLF              "Magnus-VLF"
#define MCE_MAGNUS_VLF_AL           "Magnus-VLF-AL"
#define MCE_MAGNUS_VLF_CL           "Magnus-VLF-CL"
#define MCE_NEWS                    "NEWS"
#define MCE_NEWS_SA                 "NEWS-SA"
#define MCE_FUGU                    "TSC"
#define MCE_GRAVURE                 "GRAVURE"
#define MCE_THINK                   "THINK"
#define MCE_THERMOFLEX_WIDEII       "Flexo"
#define MCE_SLAVE                   "MSFW"
#define MCE_QUANTUM                 "QUANTUM"
#define MCE_LMCE                    "LMCE"
#define MCE_2630                    "2630"
#define MCE_OREN_TURBO_MCE          "OTMCE"

#define UNKNOWN_DEVICE              "ZZZZ"
#define UNKNOWN_MODEL               "Unknown Model"
#define NO_FIRMWARE_ON_DEVICE       "XXXX"

#define READ "r"
#define WRITE "w"

#define MCE 1
#define MPE 1
#define MCE2 2
#define GMCE 1
#define GMCE2 2

#define PLATFORM_UNKNOWN    1001
#define PLATFORM_MPE        1
#define PLATFORM_MCE        2
#define PLATFORM_MCE_2      3
#define MAX_PLATFORM        4           // Must be last value

#define SYSTEM_PATH_FILE "path.txt"

// SPlot constants
#define DIALOG_CLOSE            -2      // dialog() return code
#define LIST_ITEM_SEPARATOR     "\n"    // PICKBOX list items separator
#define LIST_DEFAULT_ITEM       "\r"    // PICKBOX list items default item separator/indicator


// state plate_loc d status <value>
#define DRUM_STATUS_EMPTY                               0
#define DRUM_STATUS_PLATE_LOADED                        1
#define DRUM_STATUS_PLATE_LOADED_NON_ACTIVE             2
#define DRUM_STATUS_REJECTED_PLATE                      3
#define DRUM_STATUS_FLYOFF_TRIPPED                      4
#define DRUM_STATUS_PLATE_IN_CONVEYOR_ERROR             5
#define DRUM_STATUS_PLATE_IN_CONVEYOR_STATUS_UNKNOWN    6
#define DRUM_STATUS_DOUBLE_THICKNESS                    7

#define DRUM_STATUS_CARRIER_LOADED              1
#define DRUM_STATUS_RECEIVER_LOADED             2
#define DRUM_STATUS_DONOR_LOADED                3

// Units of measure
#define UNIT_MJ_CM2             "mJ/cm2"
#define UNIT_WATTS              "Watts"
#define UNIT_AMPS               "Amps"
#define UNIT_RPM                "rpm"
#define UNIT_PIXELS             "pixels"
#define UNIT_DPI                "dpi"
#define UNIT_MILIMETERS         "mm"
#define UNIT_MICRONS            "µm"
#define UNIT_MILS               "mils"
#define UNIT_TEMP_CELC          "°C"
#define UNIT_TIME_HOURS         "hours"
#define UNIT_DATE_DAYS          "days"

// file update definitions
#define VERSION_ID "Version:"
#define MAX_NUM_OF_FILES_TO_UPDATE 30 // max number of files that can be in a reference update file
#define MAX_NUM_OF_VERSION_INFO_LINES 10  // max number of lines (non file path lines) that will be kept when the reference file is copied.

// svsh registry query types
#define REG_STRING "REG_SZ"
#define REG_DWORD "REG_DWORD"

#define SERVICE_SHELL_CLIENT_REG_KEY "software\\creo\\serviceshell\\ServiceClientCurrentVersion"


// Public structs
struct tm
{
    int tm_sec;        // seconds (0 - 59)
    int tm_min;        // minutes (0 - 59)
    int tm_hour;       // hours   (0 - 23)
    int tm_mday;       // day of month (1-31)
    int tm_mon;        // month (0 - 11, Jan = 0)
    int tm_year;       // year - 1900
    int tm_wday;       // day of week 0 - 6, Sun = 0)
    int tm_yday;       // day of year 0 - 354)
    int tm_isdst;      // >0 if daylight savings, 0 if not, < 0 unknown
};

// *** Private variables ***
int m_bAllowAutoTermination = FALSE;
int m_bDateTimeStampDebugOutput = TRUE;
int m_bEnableDebug = TRUE;

/************************************************************************
*  Description:
*     Print debug info to SPlot terminal.
*
*  Input:
*     *sMsg - debug message.
************************************************************************/
void Debug(char *sMsg)
{
  char sDebugMsg[3*STR_LEN+2+26];           // 2 char's for "; " + 26 char's for [Thu Jan 10 11:48:24 2002]

  if (m_bEnableDebug == FALSE)
  {
    return;
  }

  // Display debug info
  sleep(200);                             // To prevent SPT buffer overrun
  
  if (m_bDateTimeStampDebugOutput == TRUE)
  {
    sprintf(sDebugMsg, "; [%s] %s", ctime(time()), sMsg);       
  }
  else
  {
    sprintf(sDebugMsg, "; %s", sMsg);       
  }

  transmit(sDebugMsg);
  
  //transmit(";"," ");                    // This was causing loss of characters
  //transmit(sMsg);                       // when a script was run over a network
  
  sleep(200);                             // To prevent SPT buffer overrun

  return;
}


/************************************************************************
*  Description:
*     Passes script's info to SPlot terminal.
*
*  Input:
* dScriptVersion - current script version
* sScriptName    - current script filename
************************************************************************/
void COM_PassScriptsInfo(double dScriptVersion, char *sScriptName)
{
  char sTmp[STR_LEN];
  
  sprintf(sTmp, "Script %s version %.2f", sScriptName, dScriptVersion);
  Debug(sTmp);

  return;
}


/*******************************************************************************
*  Description:
*       Clean script exit. Can inlcude generic script cleanup or restore procedures here.
*
*  Input:
*       nFlag_ExitSeverity - determines action(s) required before the script can exit:
*               EXIT_FATAL      - when an error occured, "fatal|critical|error: error_no - description"
*               EXIT_CRITICAL     script must provide error number & can provide extra info
*               EXIT_ERROR      
*               EXIT_CANCEL     - when the script was canceled, "exit: 0 - cancel"
*               EXIT_SUCCESS    - when the script was successfull, "exit: 0 - success"
*               EXIT_FAILURE    - when the script failed, but we want to exit without error prompt
*
*       nFlag_CleanUp - determines cleanup procedure for given exit severity type
*               RESTORE_NONE
*               RESTORE_DEVICE_IDLE
*               RESTORE_NVS
*               RESTORE_ALL
*
*       nErrorNo - (optional - default value 0) error number
*       sExtraInfo - (optional - default value "") additional error information
*
*   NOTE: (optional) parms don't exist in SPlot. Must submit default value.
*
*******************************************************************************/
void COM_ExitScript(int nExitSeverity, int nFlag_CleanUp, int nErrorNo, char *sExtraInfo)
{
  int nRC = SUCCESS;
  char sMsg[STR_LEN];


  // *** Send Exit message to TA ***//
  switch(nExitSeverity)
  {
    case EXIT_SUCCESS:
        Debug("exit: 0 - success");
        break;

    case EXIT_ERROR:
        sprintf(sMsg, "error: %d - %s", nErrorNo, sExtraInfo);
        Debug(sMsg);
        break;

    case EXIT_CRITICAL:
        sprintf(sMsg, "critical: %d - %s", nErrorNo, sExtraInfo);
        Debug(sMsg);
        break;

    case EXIT_FATAL:
        sprintf(sMsg, "fatal: %d - %s", nErrorNo, sExtraInfo);
        Debug(sMsg);
        break;

    case EXIT_CANCEL:
        Debug("exit: 0 - cancel");
        break;

    case EXIT_FAILURE:
        sprintf(sMsg, "exit: %d - %s", nErrorNo, sExtraInfo);
        Debug(sMsg);
        break;

    default:
        sprintf(sMsg, "error: %d - %s %d", ERR_PARM_OUT_OF_RANGE, "Invalid Exit Code Number", nExitSeverity);
        Debug(sMsg);
        break;
  }

  // Quit SPlot
  exit(0);
}


/****************************************************************************************************
*  Description:
*     Sends a command to the device, then returns the device response, e.g.
*     nRC=COM_SendCommand("head install on", "Head command ([0-9]+) Complete", sRetStr, 10, 2);
*
*  Input:
*     *sCommand    - command send to the device.
*     *sParseStr   - expected device response string to parse.
*     nWaitTime    - command timeout in seconds.
*     nNoOfRetries - how many times the command should be auto-retried.
*
*  Output:
*     *sReturnStr  - contains the command response, which may be the expected string or
*                    TIMEOUT, Command Canceled, ERROR or other response.
*
*  Return:
*     SUCCESS if expected device response received. Check 'return codes for COM_SendCommand()' above.
*
*  Warning! *sParseStr can not point to an empty string - SPlot will blow up.
****************************************************************************************************/
int COM_SendCommand(char *sCommand, char *sParseStr, char *sReturnStr,
                    int nWaitTime, int nNoOfRetries)
{
  int i;
  int nError = 0;
  char sDevResponse[STR_LEN];
  char sTmp[STR_LEN];
  int nRC=FAILURE;

  // Auto-retry the command for nNoOfRetries
  for (i = 0; i < nNoOfRetries; i++)
  {
    // check for cancel in between repeats
    // Not done...     

    // This is to allign SPlot comm buffer
    transmit("");
    waitfor(">>", 1);
    transmit(sCommand);
    // WARNING !!! REGULAR EXPRESSIONS IN WAITREG() ARE LIMITED TO 10.

    if (waitreg(sParseStr, sDevResponse, nWaitTime,
        FW_ERROR,
        FW_CMD_CANCELLED,
        FW_CMD_UNSUPPORTED,
        FW_CMD_INVALID,
        FW_PARM_INVALID,
        FW_PARM_OUT_OF_RANGE,
        FW_ERROR_EXPECTED_SUSPEND_RESPONSE,
        FW_CMD_HEAD_CANCELLED) != SUCCESS)
    {
      // Command timeout, auto-repeat if necessary
      nError = SEND_CMD_TIMEOUT;
      sprintf(sDevResponse, FW_TIMEOUT);
    }
    else
    {
      if (strcmp(sDevResponse, FW_CMD_CANCELLED) == SUCCESS)
      {
        // Error condition, command was canceled by the fw
        nError = SEND_CMD_CANCELLED;
      }
      else if (strcmp(sDevResponse, FW_CMD_HEAD_CANCELLED) == SUCCESS)
      {
        // Error condition, command was canceled by the head fw
        nError = SEND_CMD_CANCELLED;
      }
      else if (strcmp(sDevResponse, FW_CMD_UNSUPPORTED) == SUCCESS)
      {
        // Error condition, command not supported by fw
        nError = SEND_CMD_UNSUPPORTED;
      }
      else if (strcmp(sDevResponse, FW_CMD_INVALID) == SUCCESS)
      {
        // Error condition, invalid command
        nError = SEND_CMD_INVALID;
      }
      else if (strcmp(sDevResponse, FW_PARM_INVALID) == SUCCESS)
      {
        // Error condition, invalid parameter
        nError = SEND_CMD_PARM_INVALID;
      }
      else if (strcmp(sDevResponse, FW_PARM_OUT_OF_RANGE) == SUCCESS)
      {
        // Error condition, parameter is out of the range
        nError = SEND_CMD_PARM_OUT_OF_RANGE;
      }
      else if (strcmp(sDevResponse, FW_ERROR_EXPECTED_SUSPEND_RESPONSE) == SUCCESS)
      {
        //Debug("response first");
        // Error condition, FW send expected suspend state responses BEFORE the error message (it happens)
        nError = SEND_CMD_ERROR;

        // Get the FW expected response
        COM_GetFWErrorExpectedResponse(&nError);
        //   sprintf(sTmp, "Response first: nRC=%d, nError=%d", nRC, nError);
        //   Debug(sTmp);

        // Get the error #

        // TODO:

        // Get the error description, which follows the error code
        COM_GetFWErrorMsg(sTmp);

        strcpy(sDevResponse, sTmp);      // Err msg
      }
      else if (strstr(sDevResponse, FW_ERROR_CODE) != NULL)
      {
         // TODO: extract error #
         // Error condition, error code received
         nError = SEND_CMD_ERROR;
         
         // Get the error description, which follows the error code
         COM_GetFWErrorMsg(sTmp);

         strcpy(sDevResponse, sTmp);      // for now...

         // Get the FW expected response
         COM_GetFWErrorExpectedResponse(&nError);
         //   sprintf(sTmp, "Error first: nRC=%d, nError=%d", nRC, nError);
         //   Debug(sTmp);

      }
      else
      {
         // Expected device response received. Matching string found.
         nError = SUCCESS;
      }

      // Break out of the loop
      i=nNoOfRetries;
    }
    // End of the loop
  }

  // TODO: Debug info, remove.
  // sprintf(sTmp,"log: SendCommand nError:%d, sDevResponse=%s", nError, sDevResponse);
  // Debug(sTmp);

  // Debug(sDevResponse);
  strcpy(sReturnStr, sDevResponse);             // Return the device response
  //                              // Check for cancel from Windows Application at the end of the command
  // COM_SPLOT_BUG_NO_1523_FIX_WrongResponse();    // Fix for SPlot bug # 1523

  // Debug(sCommand);
  // Debug(sParseStr);
  // Debug(sReturnStr);

  if ((m_bAllowAutoTermination == TRUE) && (nError != SUCCESS))
  {
    Debug("AutoTermination enabled");
    return nError;   // COM_ExitScript(EXIT_CRITICAL, RESTORE_NONE, nError, sDevResponse);
  }

  return nError;
}


/************************************************************************
*  Description:
*     Used when FW error was detected in COM_SendCommand() to retrieve
*     the FW error message.
*     Must be called as soon as the error is detected.
*
*  Input:
*     none.
*
*  Output:
*     *sErrorMsg - FW error message.
*
*  Return:
*     SUCCESS if FW error message was received.
************************************************************************/
int COM_GetFWErrorMsg(char *sErrorMsg)
{

  /* Error example:

  Al cmd  : ALE expected SUSPEND responses:
  RESUME  CLEAR  ABORT
  *** Autoloader suspend error (ALE command 28): code 15251
  [  plate not detected on load ramp                   ]
  *** waiting for RESUME or ABORT or CLEAR
  Al cmd  : ALE expected SUSPEND responses:
  RESUME  CLEAR  ABORT

  */

  int nMaxErrLines = 3;      // Max no of lines an error message may have
  int nCnt;
  char sErrorMsgLine[STR_LEN];
  char sBuffer[3*STR_LEN];

  strcpy(sErrorMsgLine, "");

  for (nCnt=0; nCnt < nMaxErrLines; nCnt++)
  {
    // Get the error description, which follows the error code
    if (waitreg(FW_ERROR_DESCRIPTION, sErrorMsgLine, 10, "\\*\\*\\* waiting") == SUCCESS)
    {
      if (strcmp(sErrorMsgLine, "*** waiting") == SUCCESS)
      {
           // End of error message
           strcpy(sErrorMsg, sBuffer);
           // Get the remaining garbage containing FALSE information about RESUME/ABORT/CLEAR
           waitreg(ANYCHAR_TO_EOL_VALUE, sBuffer, 5);
           return SUCCESS;
      }
      else
      {
           // Got a single line of an error description
           // Append error msg line, CRLF and ";" - in case it will be displayed using Debug()
           strcat(sBuffer, sErrorMsgLine);
           sprintf(sBuffer, "%s\r\n;", sBuffer);
      }
    }
    else
    {
      // If we were able to receive at least 1 line of error msg (safety net)
      if (nCnt > 0)
      {
         strcpy(sErrorMsg, sBuffer);
         // Get the remaining garbage containing FALSE information about RESUME/ABORT/CLEAR
         waitfor("\\*\\*\\* waiting", 5);
         waitreg(ANYCHAR_TO_EOL_VALUE, sBuffer, 5);
         return SUCCESS;
      }
      else
      {
         Debug("Unable to get the error description.");
         return FAILURE;
      }
    }
  }

  // Return error msg
  strcpy(sErrorMsg,sBuffer);
  return SUCCESS;
}


/************************************************************************
*  Description:
*     Used when FW error was detected in COM_SendCommand() to retrieve
*     the expected FW responses to a particular error.
*     Must be called as soon as the error is detected.
*
*  Input:
*     none.
*
*  Output:
*     *nFWExpectedResponses - int indicating the expected FW responses,
*                             as defined# above.
*
*  Return:
*     SUCCESS if expected SUSPEND state FW device response received.
************************************************************************/
int COM_GetFWErrorExpectedResponse(int *nFWExpectedResponse)
{

  char sDevResponse[STR_LEN];

  // Get the expected SUSPEND response
  if (waitreg(FW_ERROR_RESUME_CLEAR_ABORT_EXPECTED, sDevResponse, 10,
              FW_ERROR_RESUME_ABORT_CLEAR_EXPECTED,
              FW_ERROR_RESUME_CLEAR_EXPECTED,
              FW_ERROR_RESUME_ABORT_EXPECTED,
              FW_ERROR_ABORT_EXPECTED,
              FW_ERROR_CLEAR_EXPECTED,
              FW_ERROR_RESUME_EXPECTED) == SUCCESS)
    {
     //Debug(sDevResponse);
     if (strstr(sDevResponse, "RESUME") != NULL &&
         strstr(sDevResponse, "CLEAR") != NULL &&
         strstr(sDevResponse, "ABORT") != NULL)
     {
       // Error condition, FW expecting RESUME or ABORT or CLEAR
       *nFWExpectedResponse = SEND_CMD_ERROR_RESUME_CLEAR_ABORT;
     }
     else if (strstr(sDevResponse, "RESUME") != NULL &&
              strstr(sDevResponse, "CLEAR") != NULL)
     {
       // Error condition, FW expecting RESUME or CLEAR
       *nFWExpectedResponse = SEND_CMD_ERROR_RESUME_CLEAR;
     }
     else if (strstr(sDevResponse, "RESUME") != NULL &&
              strstr(sDevResponse, "ABORT") != NULL)
     {
       // Error condition, FW expecting RESUME or ABORT
       *nFWExpectedResponse = SEND_CMD_ERROR_RESUME_ABORT;
     }
     else if (strstr(sDevResponse, "ABORT") != NULL)
     {
       // Error condition, FW expecting ABORT
       *nFWExpectedResponse = SEND_CMD_ERROR_ABORT;
     }
     else if (strstr(sDevResponse, "CLEAR") != NULL)
     {
       // Error condition, FW expecting CLEAR
       *nFWExpectedResponse = SEND_CMD_ERROR_CLEAR;
     }
     else if (strstr(sDevResponse, "RESUME") != NULL)
     {
        // Error condition, FW expecting RESUME
       *nFWExpectedResponse = SEND_CMD_ERROR_RESUME;
     }
  }
  else
  {
     // Unable to get the response
     Debug("Unable to get the expected SUSPEND responses.");
     return FAILURE;
  }

  return SUCCESS;
}


/****************************************************************************************************
*  Description:
*     Gets a value from the device (parameter or description, etc), e.g.
*     To retrieves the ACTIVE value:
*     nRC=COM_GetParm("set hdm 1 sd", "surface_depth", sRetStr, PARM_NUMERIC, nWaitTime, nNoOfRetries);
*     To retrieves the SAVED value:
*     nRC=COM_GetParm("set hdm 1 sd", "Saved", sRetStr, PARM_NUMERIC, nWaitTime, nNoOfRetries);
*     To retrieves the DEFAULT value:
*     nRC=COM_GetParm("set hdm 1 sd", "Default", sRetStr, PARM_NUMERIC, nWaitTime, nNoOfRetries);
*     To retrieves the other values:
*     nRC=COM_GetParm("laser", "Thermal head type", sRetStr, PARM_NUMERIC, nWaitTime, nNoOfRetries);
*     This calibrates the focus reflectivity and retrieves the sr value. Note, the increased timeout:
*     nRC=COM_GetParm("focus cal reflect", "Reflectivity", sRetStr, PARM_NUMERIC, nWaitTime*3, nNoOfRetries);
*     This retrieves string parameter:
*     nRC=COM_GetParm("set config serial", "serialno", sRetStr, PARM_STRING, nWaitTime, nNoOfRetries);
*
*  Input:
*     *sCommand    - command send to the device.
*     *sParmName   - expected device response string to parse.
*     nParmType    - type of parameter as specified above (string, numeric, boolean).
*     nWaitTime    - command timeout in seconds.
*     nNoOfRetries - how many times the command should be auto-retried.
*
*  Output:
*     *sParmRetValue - contains the command response, which may be the expected string or
*                      TIMEOUT, Command Canceled, ERROR or other response.
*
*  Return:
*     SUCCESS if expected device response received. Check 'return codes for COM_SendCommand()' above.
*     BRUCE - For now can always assume SUCCESS return code
*             as this function exits the script if a failure occurs.
****************************************************************************************************/
int COM_GetParm(char *sCommand, char *sParmName, char *sParmRetValue, int nParmType, int nWaitTime, int nNoOfRetries)
{
  int nRC = SUCCESS;
  char sTmp[STR_LEN];
  char sParmValue[STR_LEN];
  int nCnt = 0;
  char sErrorMsg[STR_LEN];

  // Call appropriate function, depence on the type of value being received.
  switch(nParmType)
  {
      case PARM_NUMERIC:
           // Get numeric value
           nRC=COM_GetNumericParm(sCommand, sParmName, sParmRetValue, nWaitTime, nNoOfRetries);
           // Check FW Bug Cases here:
           if (nRC != SUCCESS)
           {
               // bug 1: This affects the Thermal software ver below 2.58 and
               //                         Head firmware ver below 1.70:
               //        sd and sr parameters have been moved to the hdm slot but one can't see them there.
               //        They still exist in media slot with (rx) attached.
               if (strcmp(sParmName, "surface_reflectivity") == SUCCESS)
               {
                  nRC=COM_GetNumericParm(sCommand, "surface_reflectivity (r2)", sParmRetValue, nWaitTime, nNoOfRetries);
               }
               else if (strcmp(sParmName, "surface_depth") == SUCCESS)
               {
                  nRC=COM_GetNumericParm(sCommand, "surface_depth (r3)", sParmRetValue, nWaitTime, nNoOfRetries);
               }
           }
           break;

      case PARM_STRING:
           // Get string value
           nRC=COM_GetStringParm(sCommand, sParmName, sParmRetValue, nWaitTime, nNoOfRetries);
           break;

      case PARM_ANYCHAR_TO_EOL:
           // Get strings of alphanumeric characters until the End Of Line
           nRC=COM_GetAnyCharToEOLParm(sCommand, sParmName, sParmRetValue, nWaitTime, nNoOfRetries);
           break;

      case PARM_BOOLEAN:
           nRC=COM_GetBooleanParm(sCommand, sParmName, sParmRetValue, nWaitTime, nNoOfRetries);
           break;

      default:
           nRC=FAILURE;
  }

  // BRUCE - for now let's stop the script with a critical error if cannot read an NVS parameter.
  if ((m_bAllowAutoTermination == TRUE) && (nRC != SUCCESS))
  {
      sprintf(sErrorMsg, "Unable to read an NVS parameter: %s (parameter name: %s)", sCommand, sParmName);
      //COM_ExitScript(EXIT_CRITICAL, RESTORE_ALL, ERR_CANT_RW_PARM, sErrorMsg);
  }

  return nRC;
}


/************************************************************************
*  Description:
*     Retrieve any numeric NVS parameter value (float or integer).
*
*  Input:
*     *sCommand    - command send to the device.
*     *sParmName   - expected device response string to parse.
*     nWaitTime    - command timeout in seconds.
*     nNoOfRetries - how many times the command should be auto-retried.
*
*  Output:
*     *sReturnStr  - contains the command response, which may be the expected string or
*                    TIMEOUT, Command Canceled, ERROR or other response.
*
*  Return:
*     SUCCESS if expected device response received. Check 'return codes for COM_SendCommand()' above.
************************************************************************/
int COM_GetNumericParm(char *sCommand, char *sParmName, char *sReturnStr, int nWaitTime, int nNoOfRetries)
{
  int nRC = SUCCESS;
  char sNewParseStr[STR_LEN];
  char sParmValue[STR_LEN];
  int nCnt = 0;

  // Auto-retry the command for nNoOfRetries
  for (nCnt=0; nCnt<nNoOfRetries; nCnt++)
  {
      // Get the parameter value
      sprintf(sNewParseStr, "%s%s%s", sParmName, NON_NUMERIC_VALUE, NUMERIC_VALUE);
      nRC=COM_SendCommand(sCommand, sNewParseStr, sReturnStr, nWaitTime, 1);
      // If value not found, increment Wait Time x 2.
      if (nRC != SUCCESS)
      {
         nWaitTime *= 2;
      }
      else
      {
         break;
      }
  }

  if (nRC == SUCCESS)
  {
    // Parse the value from the string received from the device
    nRC=COM_ParseNumericValue(sReturnStr,sParmValue);
    if (nRC == SUCCESS)
       strcpy(sReturnStr, sParmValue);
  }

  return nRC;
}



/************************************************************************
*  Description:
*     Retrieve any numeric NVS parameter value (float or integer).
*
*  Input:
*     *sCommand    - command send to the device.
*     *sParmName   - expected device response string to parse.
*     nWaitTime    - command timeout in seconds.
*     nNoOfRetries - how many times the command should be auto-retried.
*
*  Output:
*     *sReturnStr  - contains the command response, which may be the expected string or
*                    TIMEOUT, Command Canceled, ERROR or other response.
*
*  Return:
*     SUCCESS if expected device response received. Check 'return codes for COM_SendCommand()' above.
************************************************************************/
int COM_GetBooleanParm(char *sCommand, char *sParmName, char *sReturnStr, int nWaitTime, int nNoOfRetries)
{
  int nRC = SUCCESS;
  char sNewParseStr[STR_LEN];
  char sParmValue[STR_LEN];
  int nCnt = 0;

  // Auto-retry the command for nNoOfRetries
  for (nCnt=0; nCnt<nNoOfRetries; nCnt++)
  {
      
      // Get the parameter value
      sprintf(sNewParseStr, "%s%s", sParmName, BOOLEAN_VALUE);
      nRC=COM_SendCommand(sCommand, sNewParseStr, sReturnStr, nWaitTime, 1);

      // If value not found, increment Wait Time x 2.
      if (nRC == SUCCESS)
      {
         // Parse the value from the string received from the device &
         // remove parenthesis & artifacts from the return string
         nRC=COM_ParseBooleanValue(sReturnStr, sParmName, sParmValue);
         if (nRC == SUCCESS)
         {
            // Return clean string or originally retrieved string to calling function
            strcpy(sReturnStr, sParmValue);
         }
         break;
      }
      else
      {
         // If value still not found, increment Wait Time x 2.
         nWaitTime *= 2;
      }
  }

  return nRC;
}

/************************************************************************
*  Description:
*     Retrieve any string NVS parameter value. This includes strings in ""
*     as well as strings without "". Only the string contents is returned.
*     If there were no "", everything until EOL is returned.
*     Also the artifacts are removed (e.g. =, :, empty spaces).
*
*  Input:
*     *sCommand    - command send to the device.
*     *sParmName   - expected device response string to parse.
*     nWaitTime    - command timeout in seconds.
*     nNoOfRetries - how many times the command should be auto-retried.
*
*  Output:
*     *sReturnStr  - contains the command response, which may be the expected string or
*                    TIMEOUT, Command Canceled, ERROR or other response.
*
*  Return:
*     SUCCESS if expected device response received. Check 'return codes for COM_SendCommand()' above.
************************************************************************/
int COM_GetStringParm(char *sCommand, char *sParmName, char *sReturnStr, int nWaitTime, int nNoOfRetries)
{
  int nRC = SUCCESS;
  char sParmValue[STR_LEN];
  char sNewParseStr[STR_LEN];
  int nCnt = 0;


  // String to parse consists of parameter name + any characters until EOL
  sprintf(sNewParseStr, "%s%s", sParmName, ANYCHAR_TO_EOL_VALUE);

  // Auto-retry the command for nNoOfRetries
  for (nCnt=0; nCnt<nNoOfRetries; nCnt++)
  {
      // Get string of alphanumeric characters until the End Of Line
      nRC=COM_SendCommand(sCommand, sNewParseStr, sReturnStr, nWaitTime, 1);

      if (nRC == SUCCESS)
      {
         // Parse the value from the string received from the device &
         // remove parenthesis & artifacts from the return string
         nRC=COM_ParseStringValue(sReturnStr, sParmName, sParmValue);
         if (nRC == SUCCESS)
         {
            // Return clean string or originally retrieved string to calling function
            strcpy(sReturnStr, sParmValue);
         }
         break;
      }
      else
      {
         // If value still not found, increment Wait Time x 2.
         nWaitTime *= 2;
      }
  }


  return nRC;
}




/************************************************************************
*  Description:
*     Retrieve any alphanumeric value until the End Of Line.
*
*  Input:
*     *sCommand    - command send to the device.
*     *sParmName   - expected device response string to parse.
*     nWaitTime    - command timeout in seconds.
*     nNoOfRetries - how many times the command should be auto-retried.
*
*  Output:
*     *sReturnStr  - contains the command response, which may be the expected string or
*                    TIMEOUT, Command Canceled, ERROR or other response.
*
*  Return:
*     SUCCESS if expected device response received. Check 'return codes for COM_SendCommand()' above.
************************************************************************/
int COM_GetAnyCharToEOLParm(char *sCommand, char *sParmName, char *sReturnStr, int nWaitTime, int nNoOfRetries)
{
  int nRC = SUCCESS;
  char sParmValue[STR_LEN];
  char sNewParseStr[STR_LEN];
  int nCnt = 0;

  // Auto-retry the command for nNoOfRetries
  for (nCnt=0; nCnt<nNoOfRetries; nCnt++)
  {
      // Get the string parameter value
      sprintf(sNewParseStr, "%s%s", sParmName, ANYCHAR_TO_EOL_VALUE);
      nRC=COM_SendCommand(sCommand, sNewParseStr, sReturnStr, nWaitTime, 1);
      // If value still not found, increment Wait Time x 2.
      if (nRC != SUCCESS)
      {
         nWaitTime *= 2;
      }
      else
      {
         break;
      }
  }

  if (nRC == SUCCESS)
  {
    // Parse the value from the string received from the device
    strcpy(sParmValue, sReturnStr + strlen(sParmName));
    strcpy(sReturnStr, sParmValue);
  }

  return nRC;
}


/************************************************************************
*  Description:
*     Set any type of NVS parameter, e.g.
*     Set string parameter:
*     nRC=COM_SetParm("set config serial \"12345 ABC\" ", "serialno", sRetStr);
*     Set parameter to an empty string:
*     nRC=COM_SetParm("set config owner \"\" ", "ownername", sRetStr);
*     Set numeric parameter:
*     nRC=COM_SetParm("set hdm 1 sd -1", "surface_depth", sRetStr);
*
*  Input:
*     *sCommand    - command send to the device.
*     *sParmName   - expected device response string to parse.
*
*  Output:
*     *sReturnStr  - contains the command response, which may be the expected string or
*                    TIMEOUT, Command Canceled, ERROR or other response.
*
*  Return:
*     SUCCESS if device parameter successfully set. For full set of
*     return codes, check 'return codes for COM_SendCommand()' above.
*     BRUCE - For now can always assume SUCCESS return code
*             as this function exits the script if a failure occurs.
************************************************************************/
int COM_SetParm(char *sCommand, char *sParmName, char *sReturnStr)
{
  int nRC = SUCCESS;
  int nWaitTime = 10;                  // Default command timeout in seconds
  int nNoOfRetries = 2;                // Default no of retries
  char sNewParseStr[STR_LEN];
  char sErrorMsg[STR_LEN];

  sprintf(sNewParseStr, "%s = ", sParmName);  // MPE only
  sprintf(sNewParseStr, "%s", sParmName); // MPE + MCE
  nRC=COM_SendCommand(sCommand, sNewParseStr, sReturnStr, nWaitTime, nNoOfRetries);

  // FW Bug Cases here:
  if (nRC != SUCCESS)
  {
     // FW bug case 1: explained in COM_GetParm() above.
     if (strcmp(sParmName, "surface_reflectivity") == SUCCESS)
     {
         sprintf(sNewParseStr, "%s = ", "surface_reflectivity (r2)");
         nRC=COM_SendCommand(sCommand, sNewParseStr, sReturnStr, nWaitTime, nNoOfRetries);
     }
     else if (strcmp(sParmName, "surface_depth") == SUCCESS)
     {
         sprintf(sNewParseStr, "%s = ", "surface_depth (r3)");
         nRC=COM_SendCommand(sCommand, sNewParseStr, sReturnStr, nWaitTime, nNoOfRetries);
     }
  }

  if ((m_bAllowAutoTermination == TRUE) && (nRC != SUCCESS))
  {
        sprintf(sErrorMsg, "Unable to set an NVS parameter: %s (parameter name: %s)", sCommand, sParmName);
      return nRC;   // COM_ExitScript(EXIT_CRITICAL, RESTORE_NONE, ERR_CANT_RW_PARM, sErrorMsg);
  }

  return nRC;
}


/************************************************************************
*  Description:
*     Parse the NVS numeric parameter value from the string returned by the device.
*
*  Input:
*     *sParseStr - device response. Holds the parameter and the value
*
*  Output:
*     *sValue - parameter value. Works for float numbers, including "-".
*
*  Return:
*     SUCCESS if the value was parsed.
************************************************************************/
int COM_ParseNumericValue(char *sParseStr, char *sValue)
{
  int n;
  int nStrLen;

  nStrLen=strlen(sParseStr)-1;   // Strings begin at 0.
  // Sometimes SPlot leaves an extra, non-numeric character at the end.
  // Remove it from the string. E.g. Thermal head type: 40W
  // Search from the end of the string
  for (n=nStrLen; n>=0; n--)
  {
     // Find first valid numerical characters in the string: -123.456
     if (isdigit(sParseStr[n]))
     {
        strncat(sValue, sParseStr, n + 1);
        strcpy(sParseStr, sValue);
        break;  // Break out of the loop
     }

     // keep searching for valid number until all characters were checked
     if (n == 0)
        return FAILURE;        // No valid floating point value was found
  }

  nStrLen=strlen(sParseStr)-1; // Strings begin at 0.
  // Search from the end of the string
  for (n=nStrLen; n>=0; n--)
  {
     // Check for invalid characters in the numerical string: -123.456
     if (!(isdigit(sParseStr[n])) && \
         (sParseStr[n] != '-') && \
         (sParseStr[n] != '.'))
     {
        strcpy(sValue, sParseStr + n + 1);
        return SUCCESS;
     }

     // keep searching, character is still a valid part of the number
  }

  return FAILURE;
}


/************************************************************************
*  Description:
*     Parse the string NVS parameter value from the string returned by the device.
*
*  Input:
*     *sParseStr - device response. Holds the parameter and the value
*     *sParmName - parameter name.
*
*  Output:
*     *sValue - parameter value. String without quotes, empty spaces, etc. 
*
*  Return:
*     SUCCESS if the value was parsed.
*     NOTE: parm = "value".The returned value has quotes stripped off.
************************************************************************/
int COM_ParseStringValue(char *sParseStr, char *sParmName, char *sValue)
{
   int nRC=FAILURE;
   char sTmp[STR_LEN];

   // For strings contained within "", e.g.
   // > set media x name
   // > media_type_name = "Kodak IR"  Saved = "Kodak IR"  Default =
   nRC=COM_ExtractStringWithinQuotes(sParseStr, sValue);
   if (nRC == SUCCESS)
   {
      // No need to further clean the string, string within quotes was extracted
      return nRC;
   }
   // For strings without "", e.g.

   // Remove the parm name if exists, e.g. (where parm name = MPE Firmware Version)
   // > list version
   // > MPE Firmware Version 1.60
   strcpy(sTmp, sParseStr + strlen(sParmName));
   strcpy(sParseStr, sTmp);

   // > ws "cd"
   // > Product   = TSVLF
   // Remove other characters, like " = ", " : ", etc
   COM_RemoveStringArtifacts(sParseStr, sValue);

   return SUCCESS;


}

/************************************************************************
*  Description:
*     Parse the boolean NVS parameter value from the string returned by the device.
*
*  Input:
*     *sParseStr - device response. Holds the parameter and the value
*     *sParmName - parameter name.
*
*  Output:
*     *sValue - parameter value. Boolean value True or False, original case.
*
*  Return:
*     SUCCESS if the value was parsed.
*     NOTE: parm = "value".The returned value without empty spaces, etc.
************************************************************************/
int COM_ParseBooleanValue(char *sParseStr, char *sParmName, char *sValue)
{
   int nRC=FAILURE;
   char sTmp[STR_LEN];

   // Remove the parm name if exists, 
   strcpy(sTmp, sParseStr + strlen(sParmName));

   // Remove other characters, like " = ", " : ", spaces, etc
   COM_RemoveStringArtifacts(sTmp, sValue);

   return SUCCESS;

}

/************************************************************************
*  Description:
*     Strip the string off the quotes.
*
*  Input:
*     *sParseStr - input string
*
*  Output:
*     *sValue - output string without quotes
*
*  Return:
*     SUCCESS if the input string was parsed.
*     FAILURE if there were no quotes to parse.
************************************************************************/
int COM_ExtractStringWithinQuotes(char *sParseStr, char *sValue)
{
  int nQuotePosition;
  char sTmp[STR_LEN];
  char *psQuote;


    // Find first quote
    psQuote = strstr(sParseStr, SINGLE_QUOTE);
    if (psQuote == NULL)
        return FAILURE;

    
    // Position of the first "
    nQuotePosition = strlen(sParseStr) - strlen(psQuote) + 1;


    strcpy(sTmp, sParseStr + nQuotePosition);

    // Find second quote
    psQuote = strstr(sTmp, SINGLE_QUOTE);
    if (psQuote == NULL)
        return FAILURE;

    // Position of the second "
    nQuotePosition = strlen(sTmp) - strlen(psQuote) + 1;


    // Copy the contents of the string without the quotes, to sValue only if the string is not empty
    if ((nQuotePosition - 1) > 0)
        strncat(sValue, sTmp, nQuotePosition - 1);
    else
        strcpy(sValue, "");

    return SUCCESS;
}


/************************************************************************
*  Description:
*     Removes string artifacts & leading spaces from output string.
*     Artifacts include: mystr = ABC, mystr: ABC, mystr=   ABC.
*     This function returns ABC only.
*
*  Input:
*     *sParseStr - string to clean.
*
*  Output:
*     *sValue - cleaned string.
*
*  Return:
*     None. Cleaned string or origininal string if there were no artifacts.
************************************************************************/
void COM_RemoveStringArtifacts(char *sParseStr, char *sValue)
{
  int nCharPosition;
  char sTmp[STR_LEN];
  char *psCharFound;


  // Find & remove artifact
  psCharFound = strstr(sParseStr, "=");
  if (psCharFound != NULL)
  {
      // Position of the character sought 
      nCharPosition = strlen(psCharFound) + 1 - strlen(sParseStr);
      strcpy(sTmp, sParseStr + nCharPosition);
      strcpy(sParseStr, sTmp);
  }

  // Find & remove artifact
  psCharFound = strstr(sParseStr, ":");
  if (psCharFound != NULL)
  {
      // Position of the character sought
      nCharPosition = strlen(psCharFound) + 1 - strlen(sParseStr);
      strcpy(sTmp, sParseStr + nCharPosition);
      strcpy(sParseStr, sTmp);
  }

  // Remove empty spaces from beginning of the string.
  // For now, just leave empty spaces (if any) at the end of string.

  for (nCharPosition = 0; nCharPosition < strlen(sParseStr)-1; nCharPosition++)
  {
      if (sParseStr[nCharPosition] != ' ')
      {
         // sprintf(sTmp,"Found char at pos:%d", nCharPosition);
         // Debug(sTmp);
         // Found first non empty char
         strcpy(sTmp, sParseStr + nCharPosition);
         strcpy(sParseStr, sTmp);
         break;
      }
  }

  // Return clean string
  strcpy(sValue, sParseStr);

  return;
}

/************************************************************************
*  Description:
*     This overrides the automatic script exiting by common.inc functions.
*
*  Input:
*     bAllowAutoTermination - TRUE to enable the automatic script exiting,
*                             FALSE to disable the automatic script exiting
*
************************************************************************/
void COM_EnableAutoScriptTermination(int bAllowAutoTermination)
{
   m_bAllowAutoTermination = bAllowAutoTermination;
}

/************************************************************************
*  Description:
*     This overrides the automatic date/time stamping of debug info.
*
*  Input:
*     bAllowDebugDateTimeStamp - TRUE to auto-stamp with date/time,
*                                FALSE to disable the date/time stamp
*
************************************************************************/
void COM_EnableDebugDateTimeStamp(int bAllowDebugDateTimeStamp)
{
   m_bDateTimeStampDebugOutput = bAllowDebugDateTimeStamp;
}

/************************************************************************
*  Description:
*     This overrides the automatic debug output for all scripts.
*
*  Input:
*     bAllowDebugOutput - TRUE to enable the automatic debug output (default),
*                         FALSE to disable the automatic debug output
*
************************************************************************/
void COM_EnableDebugOutput(int bAllowDebugOutput)
{
   m_bEnableDebug = bAllowDebugOutput;
}


/************************************************************************
*  Description:
*       Opens file in specified mode.
*       - Define file pointer is script like this: 
*           FILE *fpMyFile = NULL;
*       - Make procedure call like this:
*           COM_FileOpen("path\\filename", MODE, &fpMyFile);    
*
*  Input:
*       *sFileName - path & filename of the file to open (note, use \\ or / as dir separators - SPlot requirement).
*       *sMode     - file open mode (defined# above)
*
*  Output:
*       **fpFile   - pointer to the opened file
*
*  Return:
*       SUCCESS if the file was opened.
*************************************************************************/
int COM_FileOpen(char *sFileName, char *sMode, FILE **fpFile)
{
    int nRC = SUCCESS;
    char sTransmitline[STR_LEN];

    // Close opened file first
    if (*fpFile != NULL)
        COM_FileClose(fpFile);

    // Open file
    *fpFile = fopen(sFileName, sMode);
    if (*fpFile == NULL)
    {
      sprintf(sTransmitline, "Cannot open file: %s...", sFileName);
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
      nRC = FAILURE;
    }
    else
    {
      sprintf(sTransmitline, "Opening file: %s...", sFileName);
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
    }

    return nRC;
}


/************************************************************************
*  Description:
*       Closes opened file. Sets the file pointer explicitly to NULL.
*       - Define file pointer is script like this: 
*           FILE *fpMyFile = NULL;
*       - Make procedure call like this:
*           COM_FileClose(&fpMyFile);    
*
*  Input:
*       **fpFile - pointer to a file.
*
*  Return:
*       SUCCESS if the file was opened, or may terminate the script otherwise.
************************************************************************/
void COM_FileClose(FILE **fpFile)
{
    int nRC = SUCCESS;

    if (*fpFile != NULL)
    {
        // Close file
        nRC=fclose(*fpFile);
        if (nRC == 0)
            *fpFile = NULL;
        else
            nRC = FAILURE;
    }

    return nRC;
}


/************************************************************************
*  Description:
*     Deletes specified file.
*
*  Input:
*     *sFileName - name of the file to delete.
*
*  Return:
*     SUCCESS if the file was deleted.
************************************************************************/
int COM_FileDelete(char *sFileName)
{
    int nRC = SUCCESS;
    FILE *fFile = NULL;
    char sTmp[STR_LEN];

    // check if the file exists (otherwise NT's cmd window will display if the file to delete doesn't exist!)
    fFile = fopen(sFileName, MODE_READ_ONLY);
    if (fFile != NULL)
    {
        nRC=fclose(fFile);
        // verified the file exists so now delete it. NOTE: If your path is not in quotes and the file path has a space in it will not be deleted.
        sprintf(sTmp, "del \"%s\" > null", sFileName);
        nRC=system(sTmp);
        if (nRC != 0)
            nRC = FAILURE;
    }

    return nRC;
}


/************************************************************************
*  Description:
*       Appends message to txt file (note, file must be already open).
*       - Define file pointer is script like this: 
*           FILE *fpMyFile = NULL;
*       - Make procedure call like this:
*           COM_FileAppend(&fpMyFile, "message");    
*
*  Input:
*       **fpFile - pointer to an open file.
*       *sMsg    - message to append.
*
*  Return:
*       SUCCESS if message appended.
************************************************************************/
int COM_FileAppend(FILE **fpFile, char *sMsg)
{
    int nRC = SUCCESS;
    
    fprintf(*fpFile,"%s\n",sMsg);
    nRC=fflush(*fpFile);
    if (nRC == 0)
        nRC = SUCCESS;
    else
        nRC = FAILURE;
    return nRC;
}


/************************************************************************
*  Description:
*       Returns specified path. 
*
*  Input:
*       nPathType - as #defined above
*
*   Output:
*       sPath - path found in SPlot format or empty string.
*
*  Return:
*       SUCCESS if message appended.
************************************************************************/
int COM_FileGetPath(int nPathType, char *sPath)
{

    char sTmp[STR_LEN];
    char sTmpFile[STR_LEN];
    char sEnvVarName[STR_LEN];
    char sServiceShellPath[STR_LEN];
    int nRC = SUCCESS;
    
    switch (nPathType)
    {
        case PATH_SERVICE_SHELL_LOGS:
            strcpy(sServiceShellPath, "D:\\ServiceShell\\Logs");
            nRC=chdir(sServiceShellPath);
            if (nRC != SUCCESS)
            {
                strcpy(sServiceShellPath, "C:\\ServiceShell\\Logs");
                nRC=chdir(sServiceShellPath);
                if (nRC == SUCCESS)
                {
                    strcpy(sPath, sServiceShellPath);
                }    
            }
            else
            {
                strcpy(sPath, sServiceShellPath);
            }
            break;
    
        default:
            Debug("Unable to retrieve specified path info.");
            nRC = FAILURE;
            break;
    }
    
    return nRC;
}


/************************************************************************
*  Description:
*     Return no of lines in a text file.
*
*  Input:
*     *sFilename - input file.
*
*  Return:
*     No of lines counted or 0.
*
*  Notes:
*     If the specified file is empty or doesn't exist, this function
*     returns without error (it returns 0 lines count).
*
************************************************************************/
int COM_FileGetNoOfLines(char *sFilename)
{
  char sLine[STR_LEN];              // Single line
  char *sRC = NULL;                 // fgets() return char
  FILE *fpNVS = NULL;               // NVS backup file pointer
  int nRC = FAILURE;
  int nLinesCnt = 0;

   
  nRC=COM_FileOpen(sFilename, MODE_READ_ONLY, &fpNVS);
   
  if (nRC != SUCCESS)
  {
    // The file doesn't exist, it was not created in the first place, meaning, that
    // there were no parameters to restore anyway. This is to allow scripts that don't
    // create the NVS file, to still use the COM_ExitScript() function.
    return (nLinesCnt);
  }

  // Get the initial line
  sRC=fgets(sLine, STR_LEN, fpNVS);

  // Loop until EOF
  while (sRC != NULL)
  {
    // Increment line counter
    nLinesCnt++;
    // Get the initial command line
    sRC=fgets(sLine, STR_LEN, fpNVS);
  }

  COM_FileClose(&fpNVS);

  return (nLinesCnt);

}

/*******************************************************************************
*  Description:
*     Gets the head focus readings for sum and error. Uses "head install on".
*
*  Output:
*     *nFocusSum   - focus sum.
*     *nFocusError - focus error.
*
*  Return:
*     SUCCESS if focus values were retrieved.
*     BRUCE - For now can always assume SUCCESS return code 
*             as this function exits the script if a failure occurs.
*******************************************************************************/
int COM_GetFocus(int *nFocusSum, int *nFocusError)
{
  int nRC = SUCCESS;             // Function return code
  char sRetStr[STR_LEN];         // Function return string, if any.
  int nWaitTime = 10;            // Command complete wait time
  int nNoOfRetries = 2;          // No of retries for a command issued
  int nDrumEdgePos = 0;          // Drum edge position
  int i;
  char sTmp[STR_LEN];
  int nDrumInitPos = 0;
  int nCarriageInitPos = 0;
  int EDGE_OFFSET = 1000;     // Min offset from the edge where sr is calibrated. 
  
      // Move carriage and drum to plate edge position
    nRC=COM_SendCommand("plot edge", "Plot command ([0-9]+) Complete", sRetStr, 15 * nWaitTime, nNoOfRetries);
    if (nRC != SUCCESS)
        return nRC;

    nRC=COM_SendCommand("drum edge", "Drum command ([0-9]+) Complete", sRetStr, 4 * nWaitTime, nNoOfRetries);
    
    // Initialize variables
    COM_GetParm("carriage", "Current Position", sRetStr, PARM_NUMERIC, nWaitTime, nNoOfRetries);
    // waitreg("Carriage command ([0-9]+) Complete", sTmp, 5);
    nCarriageInitPos = atoi(sRetStr);

    COM_GetParm("drum", "Drum position", sRetStr, PARM_NUMERIC, nWaitTime, nNoOfRetries);
    // waitreg("Drum command ([0-9]+) Complete", sTmp, 5);
    nDrumInitPos = atoi(sRetStr);

    COM_GetRandomNumber(100,1000, TRUE);    // Seed random no generator

    sprintf(sTmp, "carriage moveto %d", nCarriageInitPos + EDGE_OFFSET + COM_GetRandomNumber(100,3000, FALSE));
    nRC=COM_SendCommand(sTmp, "Carriage command ([0-9]+) Complete", sRetStr, 15 * nWaitTime, nNoOfRetries);
    if (nRC != SUCCESS)
        return nRC;

    // Offset drum, away from the edge
    sprintf(sTmp, "drum moveto %d h", nDrumInitPos + EDGE_OFFSET + COM_GetRandomNumber(100,3000, FALSE));
    nRC=COM_SendCommand(sTmp, "Drum command ([0-9]+) Complete", sRetStr, 2 * nWaitTime, nNoOfRetries);
    sleep(1000);  // Drum needs to stabilize
    nRC=COM_SendCommand("drum soft", "Drum command ([0-9]+) Complete", sRetStr, nWaitTime, nNoOfRetries);
    // sleep(1000);  // Drum needs to stabilize
 
  
  
  // Retrieve the baseline focus sum and error values
  nRC=COM_SendCommand("head install on", "Head command ([0-9]+) Complete", sRetStr, nWaitTime, nNoOfRetries);
  if (nRC != SUCCESS)
  {
    //COM_ExitScript(TRUE, "fatal: 1027 - Unable to retrieve focus reading from head.");
  return nRC;   // COM_ExitScript(EXIT_FATAL, RESTORE_ALL, ERR_HEAD_FOCUS_READ_FAILED, "Unable to retrieve focus reading from head.");
  }

  // Skip first few readings, may not be accurate
  for( i=0; i < 5; i++)
    waitreg("s", sRetStr, nWaitTime);

  // COM_EnableAutoScriptTermination(FALSE);

  // Retrieve the baseline focus sum
  nRC=COM_GetParm("", "s", sRetStr, PARM_NUMERIC, nWaitTime, nNoOfRetries);
  if (nRC != SUCCESS)
  {
    //COM_ExitScript(TRUE, "fatal: 1027 - Unable to retrieve focus reading from head.");
  return nRC;   // COM_ExitScript(EXIT_FATAL, RESTORE_ALL, ERR_HEAD_FOCUS_READ_FAILED, "Unable to retrieve focus reading from head.");
  }
  *nFocusSum = atoi(sRetStr);

  // Retrieve the baseline focus error
  nRC=COM_GetParm("", "e", sRetStr, PARM_NUMERIC, nWaitTime, nNoOfRetries);
  if (nRC != SUCCESS)
  {
    //COM_ExitScript(TRUE, "fatal: 1027 - Unable to retrieve focus reading from head.");
  return nRC;   // COM_ExitScript(EXIT_FATAL, RESTORE_ALL, ERR_HEAD_FOCUS_READ_FAILED, "Unable to retrieve focus reading from head.");
  }
  *nFocusError = atoi(sRetStr);

  // COM_EnableAutoScriptTermination(TRUE);

  // Turn the head focus readings off
  nRC=COM_SendCommand("head install off", "Head command ([0-9]+) Complete", sRetStr, nWaitTime, nNoOfRetries);
  if (nRC != SUCCESS)
  {
    //COM_ExitScript(TRUE, "fatal: 1027 - Unable to retrieve focus reading from head.");
  return nRC;   // COM_ExitScript(EXIT_FATAL, RESTORE_ALL, ERR_HEAD_FOCUS_READ_FAILED, "Unable to retrieve focus reading from head.");
  }

  return nRC;
}


/************************************************************************
*  Description:
*     Finds plate edge position.
*
*  Input:
*     nModeNo  - current mode number.
*
*  Return:
*     SUCCESS if plate edge was found.
*     BRUCE - For now can always assume SUCCESS return code 
*             as this function exits the script if a failure occurs.
************************************************************************/
int COM_FindPlateEdge(int nNoOfEdgeFindAttempts, int *nActualAttemptsCnt, double *dEdgePosMin, double *dEdgePosMax)
{
    int nEdgeFindAttemptsCnt = 0;
    int nModeNo;
    int bLoop = TRUE;
    double dEdgePos = 0;
    char sRetStr[STR_LEN];     // Function return string, if any.
    int nRC = SUCCESS;         // Function return code.
    int nWaitTime = 10;         // Command complete wait time
    int nNoOfRetries = 2;      // No of retries for a command issued
    int nModeEdgeBkp = 0;      // Original edge detect mode parameter (set mode x edge)
    char sTmp[STR_LEN];


    // Get current resolution mode
    COM_GetParm("mode", "Current Mode", sRetStr, PARM_NUMERIC, 5, 3);
    nModeNo = atoi(sRetStr);

   
    // Get mode x edge parameter
    sprintf(sTmp, "set mode %d edge", nModeNo);
    COM_GetParm(sTmp, "find_edge", sRetStr, PARM_NUMERIC, nWaitTime, nNoOfRetries);
    nModeEdgeBkp = atoi(sRetStr);

    // Check if edge detection is turned off
    if (nModeEdgeBkp != ON)
    {
        sprintf(sTmp, "set mode %d edge %d", nModeNo, ON);
        COM_SetParm(sTmp, "find_edge", sRetStr);
    }

    // Initialize focus
    nRC=COM_SendCommand("focus init", "Stroke command ([0-9]+) Complete", sRetStr, nWaitTime, nNoOfRetries);
    if (nRC != SUCCESS)
    {
        Debug("focus init failed");
        return nRC;
    }

    // Find plate edge
    *nActualAttemptsCnt = 0;
    
    for (nEdgeFindAttemptsCnt = 1; nEdgeFindAttemptsCnt <= nNoOfEdgeFindAttempts; nEdgeFindAttemptsCnt++)
    { 
        bLoop = TRUE;
        transmit("plot edge");
        while (bLoop == TRUE)
        {
            if (waitreg("Verified edge at time", sRetStr, 150, "Edge detect attempt",FW_ERROR) != SUCCESS)
            {
                // Command timeout, auto-repeat if necessary
                nRC = SEND_CMD_TIMEOUT;
                bLoop = FALSE;
            }
            else
            {
                if (strcmp(sRetStr, "Edge detect attempt") == SUCCESS)
                {
                    // Increment attempt count
                    *nActualAttemptsCnt = *nActualAttemptsCnt + 1;
                }       
                else if (strcmp(sRetStr, "Verified edge at time") == SUCCESS)
                {
                    // Found edge, get position
                    // Get remaining command complete
                    COM_SendCommand("", "Plot command ([0-9]+) Complete", sRetStr, nWaitTime, 1);
                    // waitreg(NUMERIC_VALUE, sRetStr, 3);
                    // COM_ParseNumericValue(sRetStr,sTmp);
                    COM_GetParm("set state plate_loc d epos", "edge_position", sRetStr, PARM_NUMERIC, 3, 2);
                    dEdgePos = atof(sRetStr);
                    //  Update min/max
                    if (*dEdgePosMin == 0 && *dEdgePosMax == 0)
                    {
                        *dEdgePosMin = dEdgePos;
                        *dEdgePosMax = dEdgePos;
                    }
                    else 
                    {
                        if (*dEdgePosMin > dEdgePos) 
                           *dEdgePosMin = dEdgePos;
                        if (*dEdgePosMax < dEdgePos)
                           *dEdgePosMax = dEdgePos;
                    }
                    // Clean up
                    nRC = SUCCESS;
                    bLoop = FALSE;
                }       
                else
                {
                    // Error - Exit
                    nRC = SEND_CMD_ERROR;
                    bLoop = FALSE;
                }       
            }
        }
    }    
    
 /*
   nRC=COM_SendCommand("plot edge", "Verified edge at time", sRetStr, 15 * nWaitTime, nNoOfRetries);
   if (nRC != SUCCESS)
   {
      //COM_ExitScript(TRUE, "critical: 1023 - Unable to find the edge of the plate.");
      // return nRC;   // COM_ExitScript(EXIT_CRITICAL, RESTORE_ALL, ERR_PLATE_EDGE_DETECTION_FAILURE, "Unable to find the edge of the plate.");
      Debug("Failed edge detection");
      return nRC;
   }
*/
   //Debug("Passed edge detection");
   // Get remaining command complete
   // nRC=COM_SendCommand("", "Plot command ([0-9]+) Complete", sRetStr, nWaitTime, 1);

   // Restore original mode x edge. Mode x edge was only changed if it wasn't turned on.
   if (nModeEdgeBkp != ON)
   {
      sprintf(sTmp, "set mode %d edge %d", nModeNo, nModeEdgeBkp);
      COM_SetParm(sTmp, "find_edge", sRetStr);
   }

   return nRC;
}


/************************************************************************
*  Description:
*     Calibrates focus sr value. This function returns:
*     the original sr if calibrated sr < min
*     error message if calibrated sr > max
*
*  Input:
*     dMinSr      - minimum sr allowed
*     dMaxSr      - maximum sr allowed
*
*  Output:
*     *dCalibratedSr - calibrated surface reflectivity value
*
*  Return:
*     SUCCESS if sr was calibrated.
************************************************************************/
int COM_CalibrateFocus(double *dOriginalSr, double *dCalibratedSr, double dMinSr, double dMaxSr)
{
  int nNoOfSamples = 3;
  int nRC = SUCCESS;          // Function return code
  char sRetStr[STR_LEN];      // Function return string, if any.
  int EDGE_OFFSET = 3000;     // Min offset from the edge where sr is calibrated. 
  int nWaitTime = 10;         // Command complete wait time
  int nNoOfRetries = 2;       // No of retries for a command issued
  int n = 0;
  double d = 0.0;
  char sTmp[STR_LEN];
  int nMediaNo = 0;         // Current media no  
  // double dOriginalSr = 0;       // Original SR value 
  double dSampleSR[nNoOfSamples];     // Array holding SR readings 
  int nSampleNo = 0;
  double dSRSum = 0;
  int nCarriageInitPos = 0;       // Carriage initial position
  int nDrumInitPos = 0;         // Drum initial position 


    Debug("Calibrating focus...");
    
    // Get current media type
    COM_GetParm("mode", "Current Media Type", sRetStr, PARM_NUMERIC, 5, 3);
    nMediaNo = atoi(sRetStr);
  
    sprintf(sTmp, "set hdm %d sr", nMediaNo);
    COM_GetParm(sTmp, "surface_reflectivity", sRetStr, PARM_NUMERIC, 5, 3);
    *dOriginalSr = atof(sRetStr);



    // Move carriage and drum to plate edge position
    nRC=COM_SendCommand("plot edge", "Plot command ([0-9]+) Complete", sRetStr, 15 * nWaitTime, nNoOfRetries);
    if (nRC != SUCCESS)
    {
  //COM_ExitScript(TRUE, "critical: 1023 - Unable to find the edge of the plate.");
      //COM_ExitScript(EXIT_CRITICAL, RESTORE_ALL, ERR_PLATE_EDGE_DETECTION_FAILURE, "Unable to find the edge of the plate.");
        return nRC;
    }

    nRC=COM_SendCommand("drum edge", "Drum command ([0-9]+) Complete", sRetStr, 4 * nWaitTime, nNoOfRetries);
    
    // Initialize variables
    COM_GetParm("carriage", "Current Position", sRetStr, PARM_NUMERIC, nWaitTime, nNoOfRetries);
    waitreg("Carriage command ([0-9]+) Complete", sTmp, 5);
    nCarriageInitPos = atoi(sRetStr);

    COM_GetParm("drum", "Drum position", sRetStr, PARM_NUMERIC, nWaitTime, nNoOfRetries);
    waitreg("Drum command ([0-9]+) Complete", sTmp, 5);
    nDrumInitPos = atoi(sRetStr);

    COM_GetRandomNumber(100,1000, TRUE);    // Seed random no generator
    

    // Get specified number of samples for averaging
    for (nSampleNo = 0; nSampleNo < nNoOfSamples ; nSampleNo++)
    {

          // Initialize the focus
          nRC=COM_SendCommand("focus init", "Stroke command ([0-9]+) Complete", sRetStr, nWaitTime, nNoOfRetries);
          if (nRC != SUCCESS)
          {
                return nRC;
                //COM_ExitScript(EXIT_CRITICAL, RESTORE_ALL, ERR_HEAD_INITIALIZATION_FAILED, "'focus init' command failed.");
            }
    
          // Position the focus laser on the plate, away from the plate edges
          // Offset carriage on the plate, away from the edge
          sprintf(sTmp, "carriage moveto %d", nCarriageInitPos + EDGE_OFFSET + COM_GetRandomNumber(100,3000, FALSE));
          nRC=COM_SendCommand(sTmp, "Carriage command ([0-9]+) Complete", sRetStr, 15 * nWaitTime, nNoOfRetries);
          if (nRC != SUCCESS)
          {
              return nRC;
                // COM_ExitScript(EXIT_CRITICAL, RESTORE_ALL, ERR_CARRIAGE_FAILURE, "Carriage 'moveto' command failed.");
          }

          // Offset drum, away from the edge
          sprintf(sTmp, "drum moveto %d h", nDrumInitPos + EDGE_OFFSET + COM_GetRandomNumber(100,3000, FALSE));
          nRC=COM_SendCommand(sTmp, "Drum command ([0-9]+) Complete", sRetStr, 2 * nWaitTime, nNoOfRetries);
          sleep(1000);  // Drum needs to stabilize
          nRC=COM_SendCommand("drum soft", "Drum command ([0-9]+) Complete", sRetStr, nWaitTime, nNoOfRetries);
          sleep(1000);  // Drum needs to stabilize

          // Calibrate surface reflectivity
          COM_GetParm("focus cal reflect", "Reflectivity", sRetStr, PARM_NUMERIC, 2 * nWaitTime, nNoOfRetries);
          //*dCalibratedSr = atof(sRetStr);
          dSampleSR[nSampleNo] = atof(sRetStr);

          // Debug the info
          sprintf(sTmp, "log: Calibrated sr=%.3f Min=%.3f, Max=%.3f, Original sr=%.3f", dSampleSR[nSampleNo], dMinSr, dMaxSr, *dOriginalSr);
          Debug(sTmp);
          // COM_SendTAMsg(sTmp);

    }

    // Calculate average SR
    for (nSampleNo = 0; nSampleNo < nNoOfSamples ; nSampleNo++)
    {
        dSRSum += dSampleSR[nSampleNo];
    }


    *dCalibratedSr = dSRSum / nNoOfSamples;
    sprintf(sTmp, "log: Average Calibrated sr=%.3f Min=%.3f, Max=%.3f, Original sr=%.3f",*dCalibratedSr, dMinSr, dMaxSr, *dOriginalSr);
    Debug(sTmp);
    // COM_SendTAMsg(sTmp);


  // Validate sr range
  // sr < min ?
  if (*dCalibratedSr < dMinSr)
  {
      Debug("Using original sr value. sr < MIN");
      // Use original sr value if sr < min
      // *dCalibratedSr = dOriginalSr;
      return FAILURE;
  }

  // sr > max ?
  if (*dCalibratedSr > dMaxSr)
  {
     // sr > max. Most likely the plate is loaded backwards.
     Debug("Error: sr > MAX");
     return FAILURE;
  }

    return SUCCESS;
}


/************************************************************************
*  Description:
*     Basic random number generator. Need error checking for min/max.
*
*  Input:
*     nMin - min random number range
*     nMax - max random number range
*     bInitialize - seeds the random number generator
*
*   Return:
*     Random int between nMin and nMax.
************************************************************************/
int COM_GetRandomNumber(int nMin, int nMax, int bInitialize)
{
    int nSeed = 0;
    int nRandomNumber = 0;
    int bFound = FALSE;

    char sTmp[STR_LEN];

    if (bInitialize == TRUE)
    {
        // Re-seed the random number generator
        time(&nSeed);
        srand(nSeed);
    }


    // TODO: range checking, see rand() values.
    do
    {
          // Generate random number between Min & Max
          nRandomNumber = rand();
          nRandomNumber += nMin;
          if (nRandomNumber <= nMax)
          {
              bFound = TRUE;
          }
    }
    while (bFound == FALSE);
    

    sprintf(sTmp, "Range=%d to %d, Seed=%d, RandomNo=%d", nMin, nMax, nSeed, nRandomNumber);
    Debug(sTmp);
    return nRandomNumber;

}


/************************************************************************
*   Description:    
*       Returns current system date.
*
*   Input:          
* 
* 
*   Output:         
*       *nYear  - year
*       *nMonth - month
*       *nDay   - day
*
*   Return:         
*       Empty value for information unable to retrieve.
************************************************************************/
void COM_GetSystemDate(int *nYear, int *nMonth, int *nDay)
{
    struct tm *tmDate;
    
    tmDate = localtime(time());
    *nDay = tmDate->tm_mday;
    *nMonth = tmDate->tm_mon + 1;
    *nYear = tmDate->tm_year + 1900;

    return;
}


/************************************************************************
*   Description:    
*       Returns current system time.
*
*   Input:          
* 
* 
*   Output:         
*       *nHour   - hour
*       *nMinute - minute
*       *nSecond - second
*
*   Return:         
*       Empty value for information unable to retrieve.
************************************************************************/
void COM_GetSystemTime(int *nHour, int *nMinute, int *nSecond)
{
    struct tm *tmTime;
    
    tmTime = localtime(time());
    *nHour = tmTime->tm_hour;
    *nMinute = tmTime->tm_min;
    *nSecond = tmTime->tm_sec;

    return;
}


/************************************************************************
*   Description:    
*       Retrieves device sn, head sn and owner name. MPE only.
*
*   Input:          
* 
* 
*   Output:         
*       sHeadSN   - head sn 
*       sDeviceSN - device sn 
*       sOwner    - owner name
*
*   Return:         
*       Empty value for information unable to retrieve.
************************************************************************/
void COM_GetDeviceSN(char *sHeadSN, char *sDeviceSN, char *sOwner)
{
    int nHeadSN = 0;
    int nRC = SUCCESS;          // Function return code
    char sRetStr[STR_LEN];      // Function return string
    char sMsg[STR_LEN];

    // Get device SN. "sys sn" is integer 0-65535
    nRC=COM_GetParm("set sys sn", "serial_number", sRetStr, PARM_NUMERIC, 5, 3);
    if (strcmp(sRetStr,"0") == 0)
    {
        // "config serial" is string
        nRC=COM_GetParm("set config serial", "serialno", sRetStr, PARM_STRING, 5, 3);
    }

    if (sRetStr[0] != '\0')
    {
       strcpy(sDeviceSN, sRetStr);
    }
    
    // Get head SN
    nRC=COM_GetParm("set head sn", "serial_number", sRetStr, PARM_NUMERIC, 5, 3);
    if (strcmp(sRetStr,"0") != 0)
    {
        strcpy(sHeadSN, sRetStr);
    }
    

    // Get owner name
    nRC=COM_GetParm("set config owner", "ownername", sRetStr, PARM_STRING, 5, 3);
    if (sRetStr[0] != '\0')
    {
        strcpy(sOwner, sRetStr);
    }


    return;

 }


/************************************************************************
*  Description:
*       Finds the type of CTP device being used. MPE only.
*
*  Input:
*
*  Output:
*       nDeviceTypeID   - Device type definition ID - Print Console compatible
*       sDeviceTypeName - Device type full name
*       nPlatform       - MPE, MCE, MCE2
*
*  Return:
*       FAILURE if unable to detect device type        
************************************************************************/
int COM_GetDeviceTypeMPE(int *nDeviceTypeID, char *sDeviceTypeName, int *nPlatform)
{
    
    int nRC = SUCCESS;          // Function return code
    char sRetStr[STR_LEN];      // Function return string
  
    // Get device type 
    nRC=COM_GetParm("ws \"cd\"", "Product   = ", sRetStr, PARM_ANYCHAR_TO_EOL, 5, 3);
    if (nRC != SUCCESS)
        return;
    else
        *nPlatform = PLATFORM_MPE;

    if (strcmp(sRetStr, "PS") == 0)
        *nDeviceTypeID = PS;
    else if (strcmp(sRetStr, "TS") == 0)
        *nDeviceTypeID = TS;
    else if (strcmp(sRetStr, "VLFPS") == 0)
        *nDeviceTypeID = VLFPS;
    else if (strcmp(sRetStr, "VLFTS") == 0)
        *nDeviceTypeID = VLFTS;
    else if (strcmp(sRetStr, "TSAL") == 0)
        *nDeviceTypeID = TSAL;
    else if (strcmp(sRetStr, "VLFTSAL") == 0)
        *nDeviceTypeID = VLFTSAL;
    else if (strcmp(sRetStr, "TS2637") == 0)
        *nDeviceTypeID = TS2637;                    // TS 2637 (Newspaper)
    else if (strcmp(sRetStr, "TSSPEC") == 0)
        *nDeviceTypeID = TSSPEC;                    // TS Spectrum
    else if (strcmp(sRetStr, "SPEC") == 0)
        *nDeviceTypeID = SPEC;                      // Proofsetter
    else if (strcmp(sRetStr, "VLFPOST") == 0)
        *nDeviceTypeID = VLFPOST;                    // VLF Postsetter
    else if (strcmp(sRetStr, "FLEXO") == 0)
        *nDeviceTypeID = FLEXO;                     // Thermoflex
    else
    {
        // Unknown device type
        *nDeviceTypeID = DEVICE_UNKNOWN;
        nRC = FAILURE;
        return nRC;
    }

    // Get device full name from FW
    nRC=COM_GetParm("list version", "Thermal", sRetStr, PARM_ANYCHAR_TO_EOL, 5, 3);
    if (nRC != SUCCESS)
        return;

    sprintf(sDeviceTypeName,"Thermal%s",sRetStr);

    // TODO: Get device platform. FOr now, just detect if it's MPE
    // #define PLATFORM_MPE    1
    // #define PLATFORM_MCE    2
    // #define PLATFORM_MCE_2  3

    return nRC;
}


/************************************************************************
*  Description:
*       Finds the type of thermal head being used. MPE only.
*
*  Input:
*
*  Output:
*       nHeadTypeID - Head type definition ID - FW defined
*       sHeadTypeName - Head type full name
*
*  Return:
*       FAILURE if unable to detect head type.  
************************************************************************/
int COM_GetHeadTypeMPE(int *nHeadTypeID, char *sHeadTypeName)
{
    
    int nRC = SUCCESS;          // Function return code
    char sRetStr[STR_LEN];      // Function return string
  
    // Get device type 
    nRC=COM_GetParm("set head type", "head_type", sRetStr, PARM_NUMERIC, 5, 3);
    if (nRC == SUCCESS)
        *nHeadTypeID = atoi(sRetStr);
    else
        return nRC; 
    
    switch(*nHeadTypeID)
    {
        case TH10:
            strcpy(sHeadTypeName,"Thermal 1.0");
            break;
        case TH17:
            strcpy(sHeadTypeName,"Thermal 1.7");        
            break;
        case TFX:
            strcpy(sHeadTypeName,"Thermal TFX");        
            break;
        case TH2:
            strcpy(sHeadTypeName,"Thermal 2.0");        
            break;
        case TH3:
            strcpy(sHeadTypeName,"Thermal 3.0");        
            break;
        default:
            *nHeadTypeID = HEAD_UNKNOWN;
            nRC = FAILURE;
            break;
    }
    
     return nRC;
}


/************************************************************************
*  Description:
*       Returns all media names and colors from NVS.
*
*  Input:
*       bIncludeColor - flag indicating whether media color should be
*                       included with the media name.
*
*  Output:
*       sMediaNames - list of all available media names as defined in NVS.
*                     Names are pre-formatted for dialog() display. Each
*                     name is separated with "\n".       
*
*  Return:
*       SUCCESS if all media names were retrieved.
************************************************************************/
int COM_GetAllMediaNames(char *sMediaNames, char *sDefaultMediaName, int *nDefaultMediaIndex, int bPlatesOnly, int bProofsOnly) // plates only
{

    char sMediaName[STR_LEN];
    char sMediaColor[STR_LEN];
    int nMediaSlotIndex = 0;
    int nRC = SUCCESS;          // Function return code
    char sRetStr[STR_LEN];      // Function return string
    char sMsg[STR_LEN];
    char sCmd[STR_LEN];
    int bAddMediaToList = TRUE;
    int nCnt = 0;
     
    // Initialize
    *nDefaultMediaIndex = 0;
    strcpy(sMediaNames,"");
    
    // Preserve default media name and index
    if (*nDefaultMediaIndex == 0) 
    {
        nRC=COM_GetParm("mode", "Current Media Type", sDefaultMediaName, PARM_STRING, 5, 2);
        nRC=COM_GetParm("mode", "Current Media Type", sRetStr, PARM_NUMERIC, 5, 2);        
        *nDefaultMediaIndex = atoi(sRetStr);
        // sprintf(sMsg,"default media:%s,idx:%d",sDefaultMediaName,*nDefaultMediaIndex);
        // Debug(sMsg);
    }
    
    // COM_GetCurrentMediaInfo(, nMediaSlotIndex,
    
    // Loop through 16 media slots
    for (nMediaSlotIndex=1; nMediaSlotIndex<=16; nMediaSlotIndex++)
    {
        // Read the media name from each media/hdm slot
        sprintf(sCmd, "set media %d name", nMediaSlotIndex);
        nRC=COM_GetParm(sCmd, "media_type_name", sMediaName, PARM_STRING, 5, 2);
        // sprintf(sMsg,"COM_GetParm rc=%d",nRC);
        // Debug(sMsg);
        // Some FW versions support only 8 media slots
        if (nRC == SEND_CMD_PARM_OUT_OF_RANGE)
        {
            // FW supports only 8 media slots
            Debug("FW supports only 8 media slots.");
            nRC = SUCCESS;
            break;
        }
        else if (nRC != SUCCESS)
        {
            // Unable to receive device response
            sprintf(sMsg, "Unable to read an NVS parameter: %s ", sCmd);
            Debug(sMsg);
            return FAILURE;
        }
        else if (strlen(sMediaName) > 0)
        {            
            
            // Append media color
            bAddMediaToList = TRUE;
            sprintf(sCmd, "set media %d colour", nMediaSlotIndex);
            nRC=COM_GetParm(sCmd, "proofer_colour", sMediaColor, PARM_STRING, 5, 2);
            if (nRC != SUCCESS && bPlatesOnly == FALSE)
            {
                // Unable to retrieve color
                return FAILURE;
            }
            else if (strlen(sMediaColor) > 0)
            {
                // Proof
                if (bPlatesOnly == TRUE)
                {
                    bAddMediaToList = FALSE;
                }
                else
                {
                    sprintf(sMediaName,"%s %s",sMediaName,sMediaColor);
                }
            }
            else
            {
                // Plate, film
                if (bProofsOnly == TRUE)
                {
                    bAddMediaToList = FALSE;
                }
            }    
        
            // Append next media name to final string        
            if (bAddMediaToList == TRUE)
            {
                // Add default media as first item in the list. DON'T USE SPLOT "\r" - causes display of 1 blank list item in the list. Also, problems when returning item selection. The workaround is to plate the default item as first and use "\n" as items separator.
                if (*nDefaultMediaIndex == nMediaSlotIndex) 
                {
                    if (strlen(sMediaNames) == 0)
                        sprintf(sMediaNames,"%s",sMediaName);                                       // List empty, "default_item"
                    else
                        sprintf(sMediaNames,"%s%s%s",sMediaName, LIST_ITEM_SEPARATOR, sMediaNames); // List not empty, "default_item\nnext_item..."
                }
                else
                {
                    if (strlen(sMediaNames) == 0)
                        sprintf(sMediaNames,"%s",sMediaName);                                       // List empty, "first_item"
                    else
                        sprintf(sMediaNames,"%s%s%s",sMediaNames, LIST_ITEM_SEPARATOR,sMediaName);  // List not empty, "list_items\nnext_item..."
                }
                strcpy(sMediaName,"");
            }
        }
    }
    
    return SUCCESS;
}


/************************************************************************
*  Description:
*       Gets the current media information from the device.
*
*  Output:
*       
*       *sMediaManufacturer - media manufacturer
*       *sMediaColor        - media color
*       *nMediaType         - media type, plate, proof, etc.
*   *nSlotIndex         - media slot index in NVS
*
*   Return:
*       SUCCESS if media information was retrieved.
************************************************************************/
int COM_GetCurrentMediaInfo(char *sMediaManufacturer, char *sMediaColor, int *nMediaType, int *nSlotIndex)
{
    char sRetStr[STR_LEN];
    char sCommand[STR_LEN];
    int nRC = SUCCESS;                  // Function return code

    // Get media NVS index
    nRC=COM_GetParm("mode", "Current Media Type", sRetStr, PARM_NUMERIC, 5, 3);
    if (nRC == SUCCESS)
        *nSlotIndex = atoi(sRetStr);
    else
        return FAILURE;

    // Determine media manufacturer from media name
    sprintf(sCommand, "set media %d name", *nSlotIndex);
    nRC=COM_GetParm(sCommand, "media_type_name", sRetStr, PARM_STRING, 5, 3);
    if (nRC == SUCCESS)
        strcpy(sMediaManufacturer,sRetStr);
    else
        return FAILURE;

    // Determine media type from media name
    sprintf(sCommand, "set media %d mcode", *nSlotIndex);
    nRC=COM_GetParm(sCommand, "media_code", sRetStr, PARM_NUMERIC, 5, 3);
    if (nRC == SUCCESS)
        *nMediaType = atoi(sRetStr);
    else
        return FAILURE;

    // Determine media color constant
    sprintf(sCommand, "set media %d colour", *nSlotIndex);
    COM_GetParm(sCommand, "proofer_colour", sRetStr, PARM_STRING, 5, 3);
    if (nRC == SUCCESS)
        strcpy(sMediaColor,sRetStr);
    else
        return FAILURE;

    // int *nSlotIndex, int *nMediaManufacturer, int *nMediaColor, int *nMediaType)
    // sprintf(sCommand, "log: MediaNo:%d, Manufacturer:%d, Color:%d, MediaType:%d", *nSlotIndex, *nMediaManufacturer, *nMediaColor, *nMediaType);
    // Debug(sCommand);

    return nRC;

}


/************************************************************************
*  Description:
*       Selects media in device based on supplied media name.
*
*  Input:
*       *sMediaName - media name to switch to
*
*   Return:
*       SUCCESS if device mode was switched to supplied media name.
************************************************************************/
int COM_SelectMediaByName(char *sMediaName)
{
    char sCurrentMediaName[STR_LEN];
    char sMediaColor[STR_LEN];
    int nMediaSlotIndex = 0;
    int nNewMediaSlotIndex = 0;
    int nRC = SUCCESS;          // Function return code
    char sRetStr[STR_LEN];      // Function return string
    char sMsg[STR_LEN];
    char sCmd[STR_LEN];

   // Loop through 16 media slots
    for (nMediaSlotIndex=1; nMediaSlotIndex<=16; nMediaSlotIndex++)
    {
        // Read the media name from each media/hdm slot
        sprintf(sCmd, "set media %d name", nMediaSlotIndex);
        nRC=COM_GetParm(sCmd, "media_type_name", sCurrentMediaName, PARM_STRING, 5, 2);
        if (strcmp(sMediaName, sCurrentMediaName) == 0)
        {
            // Found match
            sprintf(sCmd, "mode media %d",nMediaSlotIndex);
            nRC=COM_GetParm(sCmd, "Current Media Type", sRetStr, PARM_NUMERIC, 5, 2);
            if (nRC == SUCCESS)
            {
                nNewMediaSlotIndex=atoi(sRetStr);
                if (nNewMediaSlotIndex != nMediaSlotIndex)
                    nRC=FAILURE;
            }
            return nRC;        
        }
   }
   
   return nRC;
} 


/*****************************************************************************
*  Description:
*     Loads the plate on drum.
*     For Platesetters, user is required to load the plate in the bay first.
*     For TS AL and Newssetter, a manual load is performed.
*
*  Input:
*     nDeviceType  - type of device as defined in common.inc
*     nPlateHeight - plate height in mm
*     nPlateWidth  - plate width in mm
*     nPlateThk    - plate thickness in microns
*     nLoadBayNo   - loading bay no, for automatic loading only
*     bUnloadFirst - flag, if TRUE, media aready loaded is unloaded first,
*                    if FALSE, media already loaded is left on drum.
*
*  Output:
*     *sErrorMsg   - error message
*
*  Return:
*     SUCCESS if plate loading was complete.
*****************************************************************************/
int COM_LoadPlate(int nDeviceType, int nPlateHeight, int nPlateWidth, \
              int nPlateThk, int nLoadBayNo, char *sErrorMsg, int bUnloadFirst)
{
  int nRC = SUCCESS;          // Function return code
  int nWaitTime = 10;         // Command timeout   TODO: change to nCmdTimeOut
  int nNoOfRetries = 1;       // No of retries for command issued
  char sTmp[STR_LEN];
  int nPlateStatus = DRUM_STATUS_EMPTY;


  // Initialize  
  strcpy(sTmp,"Getting ready to load plate, please wait for further instructions...");
  dialog(" ", 1, 1, sTmp,CTEXT | 1);

   // Verify that the drum is empty
  COM_GetParm("set state plate_loc d status", "status", sErrorMsg, PARM_NUMERIC, 5, 2);
  nPlateStatus = atoi(sErrorMsg);
  if (nPlateStatus != DRUM_STATUS_EMPTY)
  {

     if (bUnloadFirst == TRUE)
     {
        // iF UnloadFirst flag set, unload loaded plate first
        nRC=COM_UnloadPlate(nDeviceType);
        if (nRC != SUCCESS)
        {
            sprintf(sErrorMsg, "critical: %d - An error occurred while unloading the media.", ERR_PLATE_UNLOAD_FAILED);
            dialog(" ", 1, 1, sErrorMsg, CTEXT | 1);
            return FAILURE;
        }
     }
     else
     {
        // Skip plate loading, use existing plate
        strcpy(sErrorMsg, "A plate is already loaded. Skipping plate loading");
        dialog(" ", 1, 1, sErrorMsg, CTEXT | 1);
        return SUCCESS;
     }
  }


  switch(nDeviceType)
  {
    case PS:
      // Same as VLFPS below

    case VLFPS:
      Debug("log: Using Platesetter load sequence.");

      // Part 1 - operator must load the plate into a bay
      sprintf(sTmp, "cb %d load", nLoadBayNo);

      // Get device acknowledgement, that bay loading has started
      nRC=COM_SendCommand(sTmp, "loading", sErrorMsg, 3 * nWaitTime, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         strcpy(sErrorMsg, "critical: 1020 - An error occurred while loading the bay.");
         return FAILURE;
      }

      sprintf(sTmp, "Load the plate into bay %d  %s", nLoadBayNo, "and hold the door closed until it locks.");
      dialog(" ", 1, 1, sTmp,CTEXT | 1);

      // Get device acknowledgement, that bay loading has finished successfully
      nRC=COM_SendCommand("", "ALE command ([0-9]+) Complete", sErrorMsg, nWaitTime * 30, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         strcpy(sErrorMsg, "critical: 1020 - An error occurred while loading the bay.");
         return FAILURE;
      }

      // Set plate size in the bay
      sprintf(sTmp, "set state bay %d msz %d", nLoadBayNo, nPlateHeight);
      COM_SetParm(sTmp, "Default", sErrorMsg);
      sprintf(sTmp, "set state bay %d ssz %d", nLoadBayNo, nPlateWidth);
      COM_SetParm(sTmp, "Default", sErrorMsg);

      // Part 2 - pick the plate from the bay
      strcpy(sTmp,"Picking plate out of load bay...");
      dialog(" ", 1, 1, sTmp,CTEXT | 1);
      sprintf(sTmp, "pick %d", nLoadBayNo);
      nRC=COM_SendCommand(sTmp,"command ([0-9]+) Pick Complete", sErrorMsg, nWaitTime * 18, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         strcpy(sErrorMsg, "critical: 1020 - An error occurred while picking up the plate.");
         return FAILURE;
      }

      // Part 3 - load the plate on drum
      strcpy(sTmp, "Loading the plate onto drum...");
      dialog(" ", 1, 1, sTmp,CTEXT | 1);
      transmit("load");
      nRC=COM_SendCommand("load", "command ([0-9]+) Load Complete", sErrorMsg, nWaitTime * 18, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         strcpy(sErrorMsg, "critical: 1019 - An error occurred while loading the plate");
         return FAILURE;
      }
      break;

    case TS:
      // Same as SPEC below

    case SPEC:
    case TSSPEC:
      Debug("log: Using Trendsetter load sequence.");

      // Part 1 - operator must press the load button.
      sprintf(sTmp, "load %d %d", nPlateHeight, nPlateWidth);
      nRC=COM_SendCommand(sTmp, "Waiting for the button to be pressed", sErrorMsg, nWaitTime * 12, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         strcpy(sErrorMsg, "critical: 1019 - An error occurred while loading the plate");
         return FAILURE;
      }

      strcpy(sTmp,"Place the plate on the load ramp and press the CTP device load button.");
      dialog(" ", 1, 1, sTmp,CTEXT | 1);

      // Part 2 - wait for the load to complete.
      nRC=COM_SendCommand("", "command ([0-9]+) Load Complete", sErrorMsg, nWaitTime * 18, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         strcpy(sErrorMsg, "critical: 1019 - An error occurred while loading the plate");
         return FAILURE;
      }
      break;

    case VLFTSAL:
      Debug("log: Using VLF Trendsetter AL manual load sequence.");

      // Part 1 - operator must press the load button.
      sprintf(sTmp, "load %d %d", nPlateHeight, nPlateWidth);
      nRC=COM_SendCommand(sTmp, "button when you are ready to continue", sErrorMsg, nWaitTime * 18, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         strcpy(sErrorMsg, "critical: 1019 - An error occurred while loading the plate");
         return FAILURE;
      }

      strcpy(sTmp,"Place the plate on the load table, close the gate and press the CTP device load button.");
      dialog(" ", 1, 1, sTmp,CTEXT | 1);
      
      // Part 2 - wait for the load to complete.
      nRC=COM_SendCommand("", "command ([0-9]+) Load Complete", sErrorMsg, nWaitTime * 18, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         strcpy(sErrorMsg, "critical: 1019 - An error occurred while loading the plate");
         return FAILURE;
      }
      break;

    case VLFTS:
      Debug("log: Using VLF Trendsetter load sequence.");

      sprintf(sTmp, "load %d %d", nPlateHeight, nPlateWidth);
      nRC=COM_SendCommand(sTmp, "to continue", sErrorMsg, nWaitTime * 20, nNoOfRetries);
      // nRC=COM_SendCommand(sTmp, "ALE command ([0-9]+) Load Started", sErrorMsg, nWaitTime * 5, nNoOfRetries);

      // Part 1 - operator must press the load button.
      if (nRC != SUCCESS)
      {
         strcpy(sErrorMsg, "critical: 1019 - The load sequence could not progress.");
         return FAILURE;
      }

      strcpy(sTmp,"Place plate on the load table and press the CTP device load button.");
      dialog(" ", 1, 1, sTmp,CTEXT | 1);

      // Part 2 - operator must lift the table up
      nRC=COM_SendCommand("", "upright position", sErrorMsg, nWaitTime * 20, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         strcpy(sErrorMsg, "critical: 1019 - An error occurred while loading the plate.");
         return FAILURE;
      }

      strcpy(sTmp,"Lift the load table to the fully upright position.");
      dialog(" ", 1, 1, sTmp,CTEXT | 1);

      // Part 3 - wait for the load to complete
      nRC=COM_SendCommand("", "command ([0-9]+) Load Complete", sErrorMsg, nWaitTime * 18, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         strcpy(sTmp, "Lower the table all the way down and remove the plate from the table.");
         dialog(" ", 1, 1, sTmp,CTEXT | 1);
         strcpy(sErrorMsg, "critical: 1019 - An error occurred while loading the plate");
         return FAILURE;
      }
      break;

    case TSAL:
      // Same as TS237 below

    case TS2637:
      Debug("log: Using Trendsetter AL manual load sequence.");

      // Part 1 - load ramp must be in manual bypass position.
      nRC=COM_TSAL_ForceLoadRamp(TRUE);

      // Part 2 - operator must press the load button
      sprintf(sTmp, "mload %d %d", nPlateHeight, nPlateWidth);
      nRC=COM_SendCommand(sTmp, "Waiting for the button to be pressed", sErrorMsg, nWaitTime * 12, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         strcpy(sErrorMsg, "critical: 1019 - An error occurred while loading the plate.");
         return FAILURE;
      }

      strcpy(sTmp, "Place the plate on the load ramp and press the CTP device load button.");
      dialog(" ", 1, 1, sTmp,CTEXT | 1);
      
      // Part 3 - wait for the load to complete
      nRC=COM_SendCommand("", "command ([0-9]+) Load Complete", sErrorMsg, nWaitTime * 18, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         strcpy(sErrorMsg, "critical: 1019 - An error occurred while loading the plate");
         return FAILURE;
      }
      break;

    default:
      break;
  }

  // Set the plate thickness
  sprintf(sTmp, "set state plate_loc d thk %d", nPlateThk);
  COM_SetParm(sTmp, "plate_thickness", sErrorMsg);

  return SUCCESS;
}


/*******************************************************************************************
*  Description:
*     Forces the user to switch the TSAL device to manual or automatic
*     load/unload position.
*
*  Input:
*     nFlag_ManualLoadPosition - flag indicating which mode is desired.
*                                TRUE if manual load/unload on TSAL
*                                FALSE if automatic load/unload (plate cover closed).
*
*  Return:
*     SUCCESS if device was switched by the user to desired mode.
*
*  Note:
*     The only way out of this function is to cancel the TA or switch to desired mode.
*******************************************************************************************/
int COM_TSAL_ForceLoadRamp(int nFlag_ManualLoadPosition)
{
   char sCommandResponse[STR_LEN];     // Function return string
   int nRC = SUCCESS;                  // Function return code
   int nWaitTime = 5;                  // Command timeout   TODO: change to nCmdTimeOut
   int nNoOfRetries = 2;               // No of retries for command issued
   char sTmp[STR_LEN];

   if (nFlag_ManualLoadPosition == TRUE)
   {
      // Load ramp must be in manual bypass position.
      // Check the plate cover position (3 states: True, False, Disabled
      // State 1 - manual load/unload position
      nRC=COM_SendCommand("picker", "cover closed sensor=False", sCommandResponse, nWaitTime, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         nRC=COM_SendCommand("picker", "cover closed sensor=True", sCommandResponse, nWaitTime, nNoOfRetries);
         if (nRC == SUCCESS)
         {
            // State 2 - device is in automatic position. User must switch to manual mode.
            while (nRC == SUCCESS)
            {
               strcpy(sTmp, "Put the automatic plate cover in the manual bypass position.");
               dialog(" ", 1, 1, sTmp,CTEXT | 1);
               sleep(3000);
               // Loop every 3 seconds, until the plate cover is in manual unload position, or the user cancels the TA
               nRC=COM_SendCommand("picker", "cover closed sensor=True", sCommandResponse, nWaitTime, nNoOfRetries);
            }
         }
         else
         {
            // State 3 - sensor disabled
            strcpy(sTmp, "Put the automatic plate cover in the manual bypass position.");
            dialog(" ", 1, 1, sTmp,CTEXT | 1);
            sleep(5000);
         }
      }
    }
    else
    {
      // Load ramp must be in automatic load position.
      // Check the plate cover position (3 states: True, False, Disabled
      // State 1 - automatic load/unload position
      nRC=COM_SendCommand("picker", "cover closed sensor=True", sCommandResponse, nWaitTime, nNoOfRetries);
      if (nRC != SUCCESS)
      {
         nRC=COM_SendCommand("picker", "cover closed sensor=False", sCommandResponse, nWaitTime, nNoOfRetries);
         if (nRC == SUCCESS)
         {
            // State 2 - device is in manual bypass position. User must close the plate cover
            while (nRC == SUCCESS)
            {
               strcpy(sTmp, "Close the autoload plate cover.");
               dialog(" ", 1, 1, sTmp,CTEXT | 1);
               sleep(3000);
               // Loop every 3 seconds, until the plate cover is closed, or the user cancels the TA
               nRC=COM_SendCommand("picker", "cover closed sensor=False", sCommandResponse, nWaitTime, nNoOfRetries);
            }
         }
         else
         {
            // State 3 - sensor disabled
            strcpy(sTmp, "Close the autoload plate cover.");
            dialog(" ", 1, 1, sTmp,CTEXT | 1);
            sleep(5000);
         }
      }
    }

    return SUCCESS;
}



/************************************************************************
*  Description:
*     Unloads the plate from the device.
*
*  Input:
*     nDeviceType - type of device as defined in common.inc
*
*  Return:
*     SUCCESS if the plate was successfully unloaded.
************************************************************************/
int COM_UnloadPlate(int nDeviceType)
{

   char sRetStr[STR_LEN];      // Function return string
   int nRC = SUCCESS;          // Function return code
   int nWaitTime = 10;         // Command timeout   TODO: change to nCmdTimeOut
   int nNoOfRetries = 1;       // No of retries for command issued
   char sTmp[STR_LEN];
   char sErrorMsg[STR_LEN];
   int nPlateStatus = DRUM_STATUS_EMPTY; 

   // Initialize  
   strcpy(sTmp,"Getting ready to unload plate, please wait for further instructions...");
   dialog(" ", 1, 1, sTmp,CTEXT | 1);

   // Verify that the drum is empty
   COM_GetParm("set state plate_loc d status", "status", sErrorMsg, PARM_NUMERIC, 5, 2);
   nPlateStatus = atoi(sErrorMsg);
   if (nPlateStatus == DRUM_STATUS_EMPTY)
   {
        dialog(" ", 1, 1, "Drum is empty, nothing to unload.",CTEXT | 1);
        return SUCCESS;
   }
   
   switch (nDeviceType)
   {

      case PS:
         nRC=COM_SendCommand("unload", "ALE command ([0-9]+) Unload Complete", sRetStr, nWaitTime * 30, nNoOfRetries);
         if (nRC != SUCCESS)
         {
             return FAILURE;
         }

         nRC=COM_SendCommand("process", "ALE command ([0-9]+) Process Complete", sRetStr, nWaitTime * 15, nNoOfRetries);
         if (nRC != SUCCESS)
         {
             return FAILURE;
         }
         break;


      case VLFPS:
         nRC=COM_SendCommand("unload", "ALE command ([0-9]+) Unload Complete", sRetStr, nWaitTime * 30, nNoOfRetries);
         if (nRC != SUCCESS)
         {
             return FAILURE;
         }

         nRC=COM_SendCommand("eject", "ALE command ([0-9]+) Process Complete", sRetStr, nWaitTime * 15, nNoOfRetries);
         if (nRC != SUCCESS)
         {
             return FAILURE;
         }
         break;


      case TSAL:
      case TS2637:
         // Load ramp must be in manual bypass position.
         nRC=COM_TSAL_ForceLoadRamp(TRUE);

         // Manually unload the plate
         nRC=COM_SendCommand("munload", "Waiting for plate to be removed from load ramp", sRetStr, nWaitTime * 12, nNoOfRetries);
         if (nRC != SUCCESS)
         {
             return FAILURE;
         }

         strcpy(sTmp, "Remove the plate from the device.");
         dialog(" ", 1, 1, sTmp,CTEXT | 1);

         nRC=COM_SendCommand("", "ALE command ([0-9]+) Unload Complete", sRetStr, nWaitTime * 60, nNoOfRetries);
         if (nRC != SUCCESS)
         {
             return FAILURE;
         }
         break;


    case TS:
    case SPEC:
    case TSSPEC:
         nRC=COM_SendCommand("unload", "Waiting for plate to be removed", sRetStr, nWaitTime * 12, nNoOfRetries);
         if (nRC != SUCCESS)
         {
             return FAILURE;
         }

         strcpy(sTmp, "Remove the plate from the device.");
         dialog(" ", 1, 1, sTmp,CTEXT | 1);

         nRC=COM_SendCommand("", "ALE command ([0-9]+) Unload Complete", sRetStr, nWaitTime * 60, nNoOfRetries);
         if (nRC != SUCCESS)
         {
             return FAILURE;
         }
         break;


    case VLFTSAL:
         nRC=COM_SendCommand("unload", "button when you are ready to continue", sRetStr, nWaitTime * 12, nNoOfRetries);
         if (nRC != SUCCESS)
         {
             return FAILURE;
         }

         strcpy(sTmp, "Remove the plate from the table, close the gate and press the CTP device load button.");
         dialog(" ", 1, 1, sTmp,CTEXT | 1);


         nRC=COM_SendCommand("", "ALE command ([0-9]+) Unload Complete", sRetStr, nWaitTime * 60, nNoOfRetries);
         if (nRC != SUCCESS)
         {
             return FAILURE;
         }
         break;


    case VLFTS:
         nRC=COM_SendCommand("unload", "down to continue", sRetStr, nWaitTime * 12, nNoOfRetries);
         if (nRC != SUCCESS)
         {
             return FAILURE;
         }

         strcpy(sTmp, "Lower the table all the way down and remove the plate.");
         dialog(" ", 1, 1, sTmp,CTEXT | 1);

         nRC=COM_SendCommand("", "ALE command ([0-9]+) Unload Complete", sRetStr, nWaitTime * 60, nNoOfRetries);
         if (nRC != SUCCESS)
         {
             return FAILURE;
         }
         break;


    default:
         return FAILURE;
         break;

  }

  return SUCCESS;
}


/************************************************************************
*  Description: 
*       CalculateS laser exposure for given head and device type.
*
*  Input:
*       nHeadType     - thermal head type
*       dStrokeWidth  - beam stroke width (pixels)
*       dResolution   - resolution (dpi)
*       dDrumDiameter - drum diameter (mm)
*       dWPower       - wpower (Watts)
*       dDrumSpeed    - drum speed (rpm)
*
*  Output:
*       &dCalculatedExposure - calculated laser exposure
*     
*
*  Return:
*       SUCCESS if exposure was calculated.
************************************************************************/
int COM_HeadCalculateExposure(int nHeadType, double dStrokeWidth, double dResolution, double dDrumDiameter, double dWPower, double dDrumSpeed, double &dCalculatedExposure)
{
    double EXPOSURE_CONSTANT_1 = 75191.312;      
    double STROKE_WIDTH_MAX = 240.0;
    double dHeadExposure = 0.0;
    double dKFactor = 0;
    char sTmp[STR_LEN];

    switch(nHeadType)
    {
        case TH10:
        case TH17:
            // K = ((stroke_width / 240) * resolution * 60 * 1000) / (stroke_width * pie * drum_diameter * 25.4 * 0.01)
            // Exposure = K * (Wpower_Watts/ drumspeed_rpm)
            dKFactor = ((dStrokeWidth / STROKE_WIDTH_MAX) * dResolution * EXPOSURE_CONSTANT_1) / (dStrokeWidth * dDrumDiameter);
            dHeadExposure = dKFactor * (dWPower / dDrumSpeed);
            // sprintf(sTmp, "Th 1.x K:%f, EXPOSURE:%f", dKFactor, dHeadExposure);
            // Debug(sTmp); 
            *dCalculatedExposure = dHeadExposure;
            break;
            
        case TH2:
            // K = (resolution * EXPOSURE_CONSTANT_1) / (stroke_width * drum_diameter)
            // Exposure = K * (Wpower_Watts/ drumspeed_rpm)
            dKFactor = (dResolution * EXPOSURE_CONSTANT_1) / (dStrokeWidth * dDrumDiameter);
            dHeadExposure = dKFactor * (dWPower / dDrumSpeed);
            // sprintf(sTmp, "TH 2.0 K:%f, EXPOSURE:%f", dKFactor, dHeadExposure);
            // Debug(sTmp); 
            *dCalculatedExposure = dHeadExposure;
            break;
            
        case TH3:
            Debug("Head not supported");
            return FAILURE;
            break;  
        
        case TFX:
            Debug("Head not supported");
            return FAILURE;
            break;
            
        default
            Debug("Unknown head type");
            return FAILURE;
            break; 
    }

    return SUCCESS;
}


//------------------------------------------------------------------------------------------------------------------------------------------------------------
//This function checks for backslash in a string and adds one to the end if there is not already one there.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CheckForBackslash(char *string, int type)
{
  char *tempstring = "\\";

  if (type == TRUE)
  {
    if (string[strlen(string) - 1] != '\\')
    {
      strcat(string, tempstring);
    }
  }
  else
  {
    if (string[strlen(string) - 1] == '\\')
    {
      COM_Output("You must enter full path:", SUSPEND_BOX, 0, string);
      return(1);
    }
  }
  return(0);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//Checks for the prompt from the device
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CheckForPrompt(int suspend, int portNum, char *sFWType, int dualMCE)
{
  int continueTest = FALSE;
  int rc = 0;

  char tmp[STR_LEN];
  char sTransmitline[STR_LEN];

  if (strcmp(sFWType, "MPE") == 0)
  {
    transmit("");
    transmit("");
    if (waitfor(">", 3))
    {
      if (suspend)
      {
        if (COM_CheckForMPEBootMode(portNum) == 0)
        {
          if (COM_ResetTheDevice(4, portNum, sFWType, dualMCE))  
          {
            return(3); 
          }
        }
        else
        {
          COM_Output("Script cannot detect diagnostic prompt! Check Device Status.", INFORMATIVE, 0, "");
          while (rc < 1)
          {
            if (rc >= 0)
            {
              dialog("Attention!", 1, 1,
                     "Script cannot detect diagnostic prompt!  Check device status.", CTEXT | 5,
                     "Quit", BUTTON | 8, -1, -1, 100, 7);
            }
            sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
            rc = dialog(tmp);
            if (rc == DIALOG_CLOSE)
            { 
              // user hit the x button in the corner of the dialogue box
              COM_Done();
            }
          }
          // Erase the dialog box.
          dialog("");
          if (rc == 8)
          {
            ExitInError();
          }
        }
      }
      else
      {
        return(0);
      }
    }
  }
  if (strcmp(sFWType, MCENAME) == 0 || strcmp(sFWType, GMCENAME) == 0)
  {
    if (dualMCE)
    {
      sprintf(sTransmitline, "talkto %s", MCE2NAME);      
      transmit(sTransmitline);
      transmit("");
      if (waitfor(">", WAIT_TIME))
      {
        if (suspend)
        {
          COM_Output("Script cannot detect diagnostic prompt on MCE2!  Check MCE2 status.", INFORMATIVE, 0, "");
          while (rc < 1)
          {
            if (rc >= 0)
            {
              dialog("Attention!", 1, 1,
                     "Script cannot detect diagnostic prompt on MCE2!  Check MCE2 status.", CTEXT | 5,
                     "Quit", BUTTON | 8, -1, -1, 100, 7);
            }
            sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
            rc = dialog(tmp);
            if (rc == DIALOG_CLOSE)
            { 
              // user hit the x button in the corner of the dialogue box
              COM_Done();
            }
          }
          // Erase the dialog box.
          dialog("");
          if (rc == 8)
          {
            sprintf(sTransmitline, "talkto %s", MCENAME);
            transmit(sTransmitline);
            ExitInError();
          }
        }
        else
        {
          sprintf(sTransmitline, "talkto %s", MCENAME);
          transmit(sTransmitline);
          return(0);
        }
      }
      sprintf(sTransmitline, "talkto %s", MCENAME);
      transmit(sTransmitline);
    }
    else
    {
      transmit("");
      transmit("");
      transmit("");
      if (waitfor(">", 3))
      {
        if (suspend)
        {
          COM_Output("Script cannot detect diagnostic prompt!  Check device status.", INFORMATIVE, 0,  "");
          while (rc < 1)
          {
            if (rc >= 0)
            {
              dialog("Attention!", 1, 1,
                     "Script cannot detect diagnostic prompt!  Check device status.", CTEXT | 5,
                     "Quit", BUTTON | 8, -1, -1, 100, 7);
            }
            sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
            rc = dialog(tmp);
            if (rc == DIALOG_CLOSE)
            { 
              // user hit the x button in the corner of the dialogue box
              COM_Done();
            }
          }
          // Erase the dialog box.
          dialog("");
          if (rc == 8)
          {
            ExitInError();
          }
        }
        else
        {
          return(0);
        }
      }
    }
  }
  return(1);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//This function checks to see if the MPE firmware is in boot mode.
//
//Returns 1 if not in boot mode
//Retures 0 if in boot mode
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CheckForMPEBootMode(int portNum)
{
  int continueCheck = FALSE;
  int baudRate = 9600;

  char sTransmitline[STR_LEN];

  if (portNum == 0)
  {
    printf("Current MPE baud rate set to zero?");
    ExitInError();
  }
  
  baudRate = 38400;
  sprintf(sTransmitline, "talkto %s", SSDIAG);
  transmit(sTransmitline);
  sprintf(sTransmitline, "svsh port change MPE COM%i %i:8N1", portNum, baudRate);
  transmit(sTransmitline);
  sprintf(sTransmitline, "talkto %s", MPENAME);
  transmit(sTransmitline);
  transmit("");
  waitfor(">>", 1);
  transmit("");
  if (waitfor(">>", 3))
  {
    continueCheck = TRUE;
  }
  else
  {
    printf("MPE Device in Boot mode, baud rate 38400.");
    return(0);
  }
  if (continueCheck == TRUE)
  {
    baudRate = 57600;
    sprintf(sTransmitline, "talkto %s", SSDIAG);
    transmit(sTransmitline);
    sprintf(sTransmitline, "svsh port change MPE COM%i %i:8N1", portNum, baudRate);
    transmit(sTransmitline);
    sprintf(sTransmitline, "talkto %s", MPENAME);
    transmit(sTransmitline);
    transmit("");
    waitfor(">>", 1);
    transmit("");
    if (waitfor(">>", 3))
    {
      baudRate = 9600;
      sprintf(sTransmitline, "talkto %s", SSDIAG);
      transmit(sTransmitline);
      sprintf(sTransmitline, "svsh port change MPE COM%i %i:8N1", portNum, baudRate);
      transmit(sTransmitline);
      sprintf(sTransmitline, "talkto %s", MPENAME);
      transmit(sTransmitline);
      return(1);
    }
    else
    {
      printf("MPE Device in Boot mode, baud rate 57600.");
      return(0);
    }
  }
}   
//------------------------------------------------------------------------------------------------------------------------------------------------------------
//This function checks to see if the what baud rate service shell is set at (MPE only).
//
//Returns 0 if not in boot mode rate rate if found 57600 or 38400
//Retures 1 if in 9600.
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CheckMPEBaudRate (int portNum)
{
  int baudRate = 9600;

  char MPEbaud[STR_LEN];
  char outstring[STR_LEN]; 
  char instring[STR_LEN];
  char temp[STR_LEN]; 
  char sTransmitline[STR_LEN];

  sprintf(sTransmitline, "talkto %s", SSDIAG);
  transmit(sTransmitline);
  sprintf(temp, "svsh port query MPE COM%i [0-9]+:", portNum);
  transmit("svsh port query MPE");       
  if (waitreg(temp, instring, 3))
  {
    printf("Current MPE baud rate setting not found!");
    ExitInError();
  }
  else
  { 
    strcpy(outstring, instring + strlen("svsh port query MCE COMX "));
    strcpy(MPEbaud, outstring);
    MPEbaud[strlen(MPEbaud) - 1] = '\0';
    printf("Current Service Shell MPE baud rate setting is: %s", MPEbaud);
  }
  sprintf(sTransmitline, "talkto %s", MPENAME);
  transmit(sTransmitline);
  baudRate = atoi(MPEbaud);
  if (baudRate == 57600 || baudRate == 38400)
  {
    return(0);
  }
  else
  {
    return(1);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Resets the device
//
// type 4 is used to reset the device out of boot mode, switch to baud rate 9600 for MPE only
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_ResetTheDevice(int type, int portNum, char *sFWType, int dualMCE)
{
  int skipResetMCE = FALSE;
  int portBaudRate = 9600;  //MPE baud rate

  char sTransmitline[STR_LEN];
  char instring[STR_LEN];
  char deviceMode[STR_LEN];

 
  dialog("Device Reset", 1, 1,
         "Reseting the Device...",CTEXT | 1);
  printf("Waiting for device to reset...");

  if (type == 2)      // reset only MCE2 and suspend if reset fails
  {
    skipResetMCE = TRUE;
    type = 1;
  }
  
  if (type == 3)   // reset only MCE2 and do not suspend if reset fails - this is so the script will still execute if no main firmware is found
  {
    skipResetMCE = TRUE;
    type = 0;
  }

  if (type == 4)   
  {
    dialog("Device Reset", 1, 1,
           "Reseting the Device out of Boot Mode (~45 seconds)...",CTEXT | 1);
  }

  if (strcmp(sFWType, "MCE") == 0)  
  {
    if (dualMCE == TRUE)
    {
      dialog("Device Reset", 1, 1,
             "Reseting MCE2 (~60 seconds)...",CTEXT | 1);
      sprintf(sTransmitline, "talkto %s", MCE2NAME);
      transmit(sTransmitline);
      transmit("reset");
      if (COM_TestAndWaitForMCEPrompt(MCE2, 6, deviceMode)) //6 = try for 60 seconds
      {
        if (type == 0)
        {
          // Erase the dialog box.
          dialog("");
          COM_Output("Cannot get MCE2 device prompt!", INFORMATIVE, 0,  "");
          COM_Output("MCE2 failed to reset back to main firmware!", INFORMATIVE, 0,  "");
          transmit(".");  // to abort the search for mainfirmware.
          sprintf(sTransmitline, "talkto %s", MCENAME);
          transmit(sTransmitline);
          return(1);
        }
        if (type == 1)
        {
          COM_Output("Cannot get MCE2 device prompt!", INFORMATIVE, 0,  "");
          COM_Output("MCE2 failed to reset back to main firmware!", SUSPEND_BOX, 0, "");
          sprintf(sTransmitline, "talkto %s", MCENAME);
          transmit(sTransmitline);
          return(1);
        }
      }
      else
      {
        sprintf(sTransmitline, "talkto %s", MCE2NAME);
        transmit(sTransmitline);
        if (strcmp(deviceMode, "Post") == 0)
        {
          if (type == 0)
          {
            // Erase the dialog box.
            dialog("");
            COM_Output("MCE2 is in Post mode!", INFORMATIVE, 0,  "");
            COM_Output("MCE2 failed to reset back to main firmware!", INFORMATIVE, 0,  "");
            sprintf(sTransmitline, "talkto %s", MCENAME);
            transmit(sTransmitline);
            return(1);
          }
          if (type == 1)
          {
            COM_Output("MCE2 is in Post mode!", INFORMATIVE, 0,  "");
            COM_Output("MCE2 failed to reset back to main firmware!", SUSPEND_BOX, 0, "");
            sprintf(sTransmitline, "talkto %s", MCENAME);
            transmit(sTransmitline);
            return(1);
          }
        }
        if (strcmp(deviceMode, "Boot") == 0)
        {
          if (type == 0)
          {
            // Erase the dialog box.
            dialog("");
            COM_Output("MCE2 is in Boot mode!", INFORMATIVE, 0,  "");
            COM_Output("MCE2 failed to reset back to main firmware!", INFORMATIVE, 0,  "");
            sprintf(sTransmitline, "talkto %s", MCENAME);
            transmit(sTransmitline);
            return(1);
          }
          if (type == 1)
          {
            COM_Output("MCE2 is in Boot mode!", INFORMATIVE, 0,  "");
            COM_Output("MCE2 failed to reset back to main firmware!", SUSPEND_BOX, 0, "");
            sprintf(sTransmitline, "talkto %s", MCENAME);
            transmit(sTransmitline);
            return(1);
          }
        }
      }
      sprintf(sTransmitline, "talkto %s", MCENAME);
      transmit(sTransmitline);
    }
    if (skipResetMCE == FALSE)  
    {
      dialog("Device Reset", 1, 1,
             "Reseting MCE (~120 seconds)...",CTEXT | 1);
      transmit("reset");
      if (COM_TestAndWaitForMCEPrompt(MCE, 12, deviceMode)) //12 = try for 120 seconds
      {
        if (type == 0)
        {
          // Erase the dialog box.
          dialog("");
          COM_Output("Cannot get MCE device prompt!", INFORMATIVE, 0,  "");
          COM_Output("MCE failed to reset back to main firmware!", INFORMATIVE, 0,  "");
          return(1);
        }
        if (type == 1)
        {
          COM_Output("Cannot get MCE device prompt!", INFORMATIVE, 0,  "");
          COM_Output("MCE failed to reset back to main firmware!", SUSPEND_BOX, 0, "");
          return(1);
        }
      }
      else
      {
        if (strcmp(deviceMode, "Post") == 0)
        {
          if (type == 0)
          {
            // Erase the dialog box.
            dialog("");
            COM_Output("MCE is in Post mode!", INFORMATIVE, 0,  "");
            COM_Output("MCE failed to reset back to main firmware!", INFORMATIVE, 0,  "");
            return(1);
          }
          if (type == 1)
          {
            COM_Output("MCE is in Post mode!", INFORMATIVE, 0,  "");
            COM_Output("MCE failed to reset back to main firmware!", SUSPEND_BOX, 0, "");
            return(1);
          }        
        }
        if (strcmp(deviceMode, "Boot") == 0)
        {
          if (type == 0)
          {
            // Erase the dialog box.
            dialog("");
            COM_Output("MCE is in Boot mode!", INFORMATIVE, 0,  "");
            COM_Output("MCE failed to reset back to main firmware!", INFORMATIVE, 0,  "");
            transmit(".");  // to abort the search for mainfirmware.
            return(1);
          }
          if (type == 1)
          {
            COM_Output("MCE is in Boot mode!", INFORMATIVE, 0,  "");
            COM_Output("MCE failed to reset back to main firmware!", SUSPEND_BOX, 0, "");
            return(1);
          }
        }
        // wait for this so if head code is downloaded next, head data will be retrieved
        //must wait do not want to issue a command right after reset
        dialog("Device Reset", 1, 1,
               "Waiting for device to come out of reset (~40 seconds)...",CTEXT | 1);
        COM_Output("Waiting for device to come out of reset (~40 seconds)...", INFORMATIVE, 0,  "");
        
        if (waitfor("Datalink: exposure head coming online (binary mode)", 40))
        {
          COM_Output("The device head is not installed or is not online.", INFORMATIVE, 0, "");
          COM_Output("Timeout for: Datalink: exposure head coming online (binary mode)", INFORMATIVE, 0, "");
        }
      }
    }
  }
  if (strcmp(sFWType, GMCENAME) == 0)  
  {
    dialog("Device Reset", 1, 1,
           "Reseting GMCE (~140 seconds)...",CTEXT | 1);
    transmit("reset");
    waitfor ("nothing", 60); //Wait to avoid the Gboot promt
    if (COM_TestAndWaitForGMCEPrompt(GMCE, 8, deviceMode)) //14 = try for 140 seconds
    {
      if (type == 0)
      {
        // Erase the dialog box.
        dialog("");
        COM_Output("Cannot get GMCE device prompt!", INFORMATIVE, 0,  "");
        COM_Output("GMCE failed to reset back to main firmware!", INFORMATIVE, 0,  "");
        return(1);
      }
      if (type == 1)
      {
        COM_Output("Cannot get GMCE device prompt!", INFORMATIVE, 0,  "");
        COM_Output("GMCE failed to reset back to main firmware!", SUSPEND_BOX, 0, "");
        return(1);
      }
    }
    else
    {
      if (strcmp(deviceMode, "Gboot") == 0)
      {
        if (type == 0)
        {
          // Erase the dialog box.
          dialog("");
          COM_Output("GMCE is in Gboot mode!", INFORMATIVE, 0,  "");
          COM_Output("GMCE failed to reset back to main firmware!", INFORMATIVE, 0,  "");
          transmit(".");  // to abort the search for mainfirmware.
          return(1);
        }
        if (type == 1)
        {
          COM_Output("GMCE is in Gboot mode!", INFORMATIVE, 0,  "");
          COM_Output("GMCE failed to reset back to main firmware!", SUSPEND_BOX, 0, "");
          return(1);
        }
      }
      // wait for this so if head code is downloaded next, head data will be retrieved
      //must wait do not want to issue a command right after reset
      dialog("Device Reset", 1, 1,
             "Waiting for device to come out of reset (~40 seconds)...",CTEXT | 1);
      COM_Output("Waiting for device to come out of reset (~40 seconds)...", INFORMATIVE, 0,  "");
      
      if (waitfor("Datalink: exposure head coming online (binary mode)", 40))
      {
        COM_Output("The device head is not installed or is not online.", INFORMATIVE, 0, "");
        COM_Output("Timeout for: Datalink: exposure head coming online (binary mode)", INFORMATIVE, 0, "");
      }
    }    
  }
  if (strcmp(sFWType, "MPE") == 0)  
  {
    transmit("reset");
    if (type == 4)   // not using as a suspend type bit of a hack
    {
      sprintf(sTransmitline, "talkto %s", SSDIAG);
      transmit(sTransmitline);
      sprintf(sTransmitline, "svsh port change MPE COM%i 9600:8N1", portNum);
      transmit(sTransmitline);
      sprintf(sTransmitline, "talkto %s", MPENAME);
      transmit(sTransmitline);
      //port(portNum, 9600);
    }
    if (waitfor("MPE Monitor", 45))
    {
      if (type == 0)
      {
        // Erase the dialog box.
        dialog("");
        COM_Output("Device failed to reset", INFORMATIVE, 0,  "");
        return(1);
      }
      if (type == 1)
      {
        COM_Output("Device failed to reset", SUSPEND_BOX, 0, "");
        return(1);
      }
      if (type == 4)   
      {
        // Erase the dialog box.
        dialog("");
        COM_Output("Device failed to reset", INFORMATIVE, 0,  "");
        //port(portNum, 38400);
        return(1);
      }
    }
    else
    {
      //must wait do not want to issue a command right after reset
      dialog("Device Reset", 1, 1,
             "Waiting for device to come out of reset (~30 seconds)...",CTEXT | 1);
      COM_Output("Waiting for device to come out of reset (~30 seconds)...", INFORMATIVE, 0,  "");
      waitfor("nothing", 30);
    }
  }
  return(0);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// output base on the following types:
//
// Type INFORMATIVE: Output a message informative only to both the output window and the terminal window
// Type TERMINAL_DEBUG: Output a message to terminal window and the output window and waitfor response
// Type TERMINAL: Output a message to the terminal window only and waitfor response display it in a suspend dialog box if response is not received
// Type SUSPEND_BOX: Output a message informative only to both the output window and the terminal window and create it in a suspend dialog box
// Type TERMINAL_RESTORE_PARAMETERS: Output a message to the terminal window only and waitfor responce create it in a suspend dialog box if responce is not received 
//         specific to restoring parameters.
// Type TERMINAL_RESTORE_PARAMETERS_CATCH_CALLED: Output a message to the terminal window only and waitfor responce create it in a suspend dialog box if response is not received 
//         specific to restoring parameters and being called by the catch function. Exit in error is not called.
//
// Type SUSPEND_BOX_YES_NO: Output a message informative only to both the output window and the terminal window and create it in a suspend dialog box and wait for a YES or NO response
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_Output(char *sOutputMessage, int nOutputMessageType, int nWaitTime, char *sWaitForString)
{
  char sTransmitMessage[STR_LEN];
  char sTmp[STR_LEN];
  
  int nRC = 0;

  if (nOutputMessageType == INFORMATIVE)
  {  
    #ifndef NODEBUG
      printf("%s", sOutputMessage);
    #endif
    //COM_BreakStringIntoChunksAndTrasmit(sOutputMessage);
    sprintf(sTransmitMessage, ";;%s", sOutputMessage);
    transmit(sTransmitMessage);
  }
  if (nOutputMessageType == INFORMATIVE_MPE_REPLACE_BACKSLASH)
  {  
    #ifndef NODEBUG
      printf("%s", sOutputMessage);
    #endif
    strcpy(sTransmitMessage, sOutputMessage);
    COM_ReplaceBackSlash(sTransmitMessage);
    COM_BreakStringIntoChunksAndTrasmit(sTransmitMessage);    
  }
  if (nOutputMessageType == TERMINAL)
  {  
    sprintf(sTransmitMessage, "%s", sOutputMessage);
    transmit(sTransmitMessage);
    if (waitfor(sWaitForString, nWaitTime))
    {
      transmit(";;Timeout waiting for:");
      sprintf(sTransmitMessage, ";;%s", sWaitForString);
      transmit(sTransmitMessage);

      transmit(";;From this Command:");
      sprintf(sTransmitMessage, ";;%s", sOutputMessage);
      transmit(sTransmitMessage);
    
      while (nRC < 1)
      {
        if (nRC >= 0)
        {
          dialog("Attention!", 1, 1,
                 "Timeout waiting for:", CTEXT | 5,
                 sWaitForString, CTEXT | 6,  
                 "From this Command:", CTEXT | 5,
                 sOutputMessage, CTEXT | 5,                                                                                               
                 "Main Menu", BUTTON | 7, -1, -1, 100, 7, "Quit", BUTTON | 8, -1, -1, 100, 7);
        }
        sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
        nRC = dialog(sTmp);
        if (nRC == DIALOG_CLOSE) 
        {
          // user hit the x button in the corner of the dialog box
          ExitInError();
        }
      }
      // Erase the dialog box.
      dialog("");
      if (nRC == 8)
      {
        ExitInError();
      }
      return(1);
    }
  }
  if (nOutputMessageType == SUSPEND_BOX)
  {      
    printf("%s", sOutputMessage);
    COM_BreakStringIntoChunksAndTrasmit(sOutputMessage);
    printf("%s", sWaitForString);
    COM_BreakStringIntoChunksAndTrasmit(sWaitForString);

    #ifndef NO_SUSPEND_IN_COMMON_UTL
      while (nRC < 1)
      {
        if (nRC >= 0)
        {
          dialog("Attention!", 1, 1,
          sOutputMessage, CTEXT | 5,
          sWaitForString, CTEXT | 5,  // this is optional it may or may not be used
          "Main Menu", BUTTON | 7, -1, -1, 100, 7, 
          "Quit", BUTTON | 8, -1, -1, 100, 7);
        }
        sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
        nRC = dialog(sTmp);
        if (nRC == DIALOG_CLOSE) 
        {
          // user hit the x button in the corner of the dialog box
          ExitInError();
        }
      }
      // Erase the dialog box.
      dialog("");
      if (nRC == 8)
      {
        ExitInError();
      }
    #endif
  }
  if (nOutputMessageType == INFO_DIALOG_BOX)
  {  

    printf("%s", sOutputMessage);
    sprintf(sTransmitMessage, ";;%s", sOutputMessage);
    transmit(sTransmitMessage);
    printf("%s", sWaitForString);
    sprintf(sTransmitMessage, ";;%s", sWaitForString);
    transmit(sTransmitMessage);

    while (nRC < 1)
    {
      if (nRC >= 0)
      {
        dialog("Info", 1, 1,
        sOutputMessage, CTEXT | 5,
        sWaitForString, CTEXT | 5,  // this is optional it may or may not be used
        "Resume", BUTTON | 7, -1, -1, 100, 7);
      }
      sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
      nRC = dialog(sTmp);
      if (nRC == DIALOG_CLOSE) 
      {
        nRC = 1;
      }
    }
    // Erase the dialog box.
    dialog("");    
  }
  if (nOutputMessageType == TERMINAL_DEBUG)
  {
    printf("%s", sOutputMessage);
    sprintf(sTransmitMessage,"%s", sOutputMessage);
    transmit(sTransmitMessage);
    if (waitfor(sWaitForString, nWaitTime))
    {
      while (nRC < 1)
      {
        if (nRC >= 0)
        {
          dialog("Attention!", 1, 1,
          "Waiting for this string failed:", CTEXT | 5,
          sWaitForString, CTEXT | 6,  
          "Main Menu", BUTTON | 7, -1, -1, 100, 7, "Quit", BUTTON | 8, -1, -1, 100, 7);
        }
        sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
        nRC = dialog(sTmp);
        if (nRC == DIALOG_CLOSE) 
        {
          // user hit the x button in the corner of the dialog box
          ExitInError();
        }
      }
      // Erase the dialog box.
      dialog("");
      if (nRC == 8)
      {
        ExitInError();
      }
      return(1);
    }
  }
  if (nOutputMessageType == TERMINAL_RESTORE_PARAMETERS)
  {  
    sprintf(sTransmitMessage, "%s", sOutputMessage);
    transmit(sTransmitMessage);
    
    if (waitfor(sWaitForString, nWaitTime))
    {

      transmit(";;Timeout waiting for:");
      sprintf(sTransmitMessage, ";;%s", sWaitForString);
      transmit(sTransmitMessage);
      transmit(";;From this Command:");
      sprintf(sTransmitMessage, ";;%s", sTransmitMessage);
      transmit(sTransmitMessage);

      while (nRC < 1)
      {
        if (nRC >= 0)
        {
          dialog("Attention!", 1, 1,
                 "Restoring Parameters Failed!", CTEXT | 1,
                 "Timeout waiting for:", CTEXT | 1,
                 sWaitForString, CTEXT | 1,  
                 "From this Command:", CTEXT | 1,
                 sOutputMessage, CTEXT | 1,  
                 "Continue", BUTTON | 7, -1, -1, 100, 7);
        }
        sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
        nRC = dialog(sTmp);
        if (nRC == DIALOG_CLOSE) 
        {
          // user hit the x button in the corner of the dialog box
          ExitInError();
        }
      }
      // Erase the dialog box.
      dialog("");
      ExitInError();
    }
  }
  if (nOutputMessageType == TERMINAL_RESTORE_PARAMETERS_CATCH_CALLED)
  {  
    sprintf(sTransmitMessage, "%s", sOutputMessage);
    transmit(sTransmitMessage);
    
    if (waitfor(sWaitForString, nWaitTime))
    {

      transmit(";;Timeout waiting for:");
      sprintf(sTransmitMessage, ";;%s", sWaitForString);
      transmit(sTransmitMessage);
      transmit(";;From this Command:");
      sprintf(sTransmitMessage, ";;%s", sTransmitMessage);
      transmit(sTransmitMessage);
      while (nRC < 1)
      {
        if (nRC >= 0)
        {
          dialog("Attention!", 1, 1,
                 "Restoring Parameters Failed!", CTEXT | 1,
                 "Timeout waiting for:", CTEXT | 1,
                 sWaitForString, CTEXT | 1,  
                 "From this Command:", CTEXT | 1,
                 sOutputMessage, CTEXT | 1,  
                 "Continue", BUTTON | 7, -1, -1, 100, 7);
        }
        sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
        nRC = dialog(sTmp);
        if (nRC == DIALOG_CLOSE)
        { 
          // user hit the x button in the corner of the dialog box
          COM_Done();
        }
      }
      // Erase the dialog box.
      dialog("");
    }
  }
 if (nOutputMessageType == SUSPEND_BOX_YES_NO)
  {      
    printf("%s", sOutputMessage);
    COM_BreakStringIntoChunksAndTrasmit(sOutputMessage);
    printf("%s", sWaitForString);
    COM_BreakStringIntoChunksAndTrasmit(sWaitForString);

    #ifndef NO_SUSPEND_IN_COMMON_UTL
      while (nRC < 1)
      {
        if (nRC >= 0)
        {
          dialog("Attention!", 1, 1,
          sOutputMessage, CTEXT | 5,
          sWaitForString, CTEXT | 5,  // this is optional it may or may not be used
          "YES", BUTTON | 7, -1, -1, 100, 7, 
          "NO", BUTTON | 8, -1, -1, 100, 7);
        }
        sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
        nRC = dialog(sTmp);
        if (nRC == DIALOG_CLOSE) 
        {
          // user hit the x button in the corner of the dialog box
          ExitInError();
        }
      }
      // Erase the dialog box.
      dialog("");
      if (nRC == 8)
      {
        return(1);
      }
    #endif
  }
  return(0);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function puts the MCE/MPE firmware in a good starting point.
// 
// If the main board is not running main firmware it will attempt to reset the device out of that state.
// If the device fails to switch out of boot mode post etc etc then the noCodeOnBoard flag is set.
//
// MCE specific:  If MSFW is found under 'MCE', then the script assumes that the device is dual MCE device.  This function checks for a sets that state.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_GetDeviceIntoGoodStartingPoint(int portNum, char *sFWType, int nTargetMCE, int *noCodeOnBoard, int *noCodeOnMCE2Board, int *backupBeforeLoading, 
                                        char *deviceMode)
{
  int skip = FALSE;
  int skipReset = FALSE;
  int checkPromptAgain = FALSE;
  int MCE2InGoodState = FALSE;
  int dualMCE = FALSE;

  char sTransmitline[STR_LEN];
  char instring[STR_LEN];
  char sTestPrompt[STR_LEN];

  sTestPrompt[0] = '\0';
 
  if (strcmp(sFWType, MCENAME) == 0 || strcmp(sFWType, GMCENAME) == 0)
  {
    if (nTargetMCE == MCE)
    {
      dualMCE = FALSE;
      dialog("Checking Status", 1, 1,
             "Checking MCE Status...", CTEXT | 1);
     
      COM_Output("Checking MCE status...", INFORMATIVE, 0, "");
      
      while (sTestPrompt[0] == '\0')
      {
        transmit("");
        if (waitreg(MCE_DEVICE_TYPE, instring, 2) == 0)
        {                                     
          strncpy(sTestPrompt, instring, (strlen(instring) - 1));
          
          sprintf(sTransmitline, "Current MCE mode is %s", sTestPrompt);
          COM_Output(sTransmitline, INFORMATIVE, 0, "");  
          // this sleep is for simulators
          sleep(100);
          strcpy(deviceMode, sTestPrompt);
        }
        else
        {
          COM_Output("MCE Prompt state not found...", INFORMATIVE, 0, ""); 
        }        
      }
      if (strstr(deviceMode, "ENG"))
      {
        Output("Engineering Firmware", INFORMATIVE, 0, "");
        strncpy(deviceMode, sTestPrompt, (strlen(sTestPrompt) - 3));
      }
      if (strcmp(deviceMode, "Post") == 0)
      {
        COM_Output("Getting MCE out of post mode...", INFORMATIVE, 0, "");
        if (COM_ResetTheDevice(0, portNum, sFWType, dualMCE))
        {
          *noCodeOnBoard = TRUE;
        }
        else
        {
          checkPromptAgain = TRUE;
        }
      }
      if (strcmp(deviceMode, "Boot") == 0)
      {
        COM_Output("Getting MCE out of boot mode...", INFORMATIVE, 0, "");
        if (COM_ResetTheDevice(0, portNum, sFWType, dualMCE))
        {
          *noCodeOnBoard = TRUE;
        }
        else
        {
          checkPromptAgain = TRUE;
        }
      }
      if (strcmp(deviceMode, "Gboot") == 0)
      {
        COM_Output("Getting GMCE out of boot mode...", INFORMATIVE, 0, "");
        if (COM_ResetTheDevice(0, portNum, sFWType, dualMCE))
        {
          *noCodeOnBoard = TRUE;
        }
        else
        {
          checkPromptAgain = TRUE;
        }
      }
      if (strcmp(deviceMode, "TH2 ") == 0)
      {
        COM_Output("Getting MCE out of Thermal diagnostic...", INFORMATIVE, 0, "");
        transmit("redirect disable");
        waitfor("Command Success", 5);  
        waitfor("Nothing", 2); // Waitfor device to get out of head diag mode
        checkPromptAgain = TRUE;
      }
      if (strcmp(deviceMode, "TFX ") == 0)
      {
        COM_Output("Getting MCE out of Thermal diagnostic...", INFORMATIVE, 0, "");
        transmit("redirect disable");
        waitfor("Command Success", 5);                                      
        waitfor("Nothing", 2); // Waitfor device to get out of head diag mode
        checkPromptAgain = TRUE;
      }
      if (strcmp(deviceMode, "DBUG+") == 0)
      {
        COM_Output("Getting MCE out of nucleus debug mode...", INFORMATIVE, 0, "");
        waitfor("Nothing", 4); // Waitfor debug commands sent earlier to be sent
        transmit("Q");
        waitfor("Nothing", 2); // Waitfor device to get out of debug mode
        transmit("");
        waitfor(">>", 3);
        checkPromptAgain = TRUE;
        
      }
      if (checkPromptAgain == TRUE)
      {
        sTestPrompt[0] = '\0';
        while (sTestPrompt[0] == '\0')
        {
          transmit("");
          if (waitreg(MCE_DEVICE_TYPE, instring, 2) == 0)
          {                                     
            strncpy(sTestPrompt, instring, (strlen(instring) - 1));
            sprintf(sTransmitline, "Current MCE mode is %s", sTestPrompt);
            COM_Output(sTransmitline, INFORMATIVE, 0, "");            
            // this sleep is for simulators
            sleep(100);
            strcpy(deviceMode, sTestPrompt);
          }
        }
      }
      if (*noCodeOnBoard == TRUE)
      {
        if (COM_PutMCEIntoBootMode(MCE))
        {
          *noCodeOnBoard = FALSE;
          *backupBeforeLoading = FALSE;
        }
      }
    }
    if (nTargetMCE == MCE2)
    {
      dualMCE = TRUE;
      dialog("Checking Status", 1, 1,
             "Checking MCE2 Status...",CTEXT | 1);

      sprintf(sTransmitline, "talkto %s", MCE2NAME);
      transmit(sTransmitline);
      COM_Output("Checking MCE2 status...", INFORMATIVE, 0, "");
      while (sTestPrompt[0] == '\0')
      {
        transmit("");
        if (waitreg(MCE_DEVICE_TYPE, instring, 2) == 0)
        {
          strncpy(sTestPrompt, instring, (strlen(instring) - 1));
          sprintf(sTransmitline, "Current MCE2 mode is %s", sTestPrompt);
          COM_Output(sTransmitline, INFORMATIVE, 0, "");
          // this sleep is for simulators
          sleep(100);
          strcpy(deviceMode, sTestPrompt);
        }
        else
        {
          COM_Output("MCE2 Prompt state not found...", INFORMATIVE, 0, ""); 
        }
      }
      strcpy(deviceMode, sTestPrompt);
      if (strcmp(deviceMode, "TH2 ") == 0)
      {
        COM_Output("Getting MCE2 out of Thermal diagnostic...", INFORMATIVE, 0, "");
        transmit("redirect disable");
        waitfor("Command Success", 5);   
        waitfor("Nothing", 2); // Waitfor device to get out of head diag mode                                   
        checkPromptAgain = TRUE;
      }
      if (strcmp(deviceMode, "TFX ") == 0)
      {
        COM_Output("Getting MCE2 out of Thermal diagnostic...", INFORMATIVE, 0, "");
        transmit("redirect disable");
        waitfor("Command Success", 5);                                      
        waitfor("Nothing", 2); // Waitfor device to get out of head diag mode
        checkPromptAgain = TRUE;
      }
      if (strcmp(deviceMode, "DBUG+") == 0)
      {
        COM_Output("Getting MCE2 out of nucleus debug mode...", INFORMATIVE, 0, "");
        waitfor("Nothing", 4); // Waitfor debug commands sent earlier to be sent
        transmit("Q");
        waitfor("Nothing", 2); // Waitfor device to get out of debug mode
        transmit("");
        waitfor(">>", 3);
        checkPromptAgain = TRUE;
        
      }
      if (strcmp(deviceMode, "Post") == 0)
      {
        COM_Output("Getting MCE2 out of post mode...", INFORMATIVE, 0, "");
        if (COM_ResetTheDevice(3, portNum, sFWType, dualMCE))
        {
          *noCodeOnMCE2Board = TRUE;
        }
        else
        {
          checkPromptAgain = TRUE;
        }
      }
      if (strcmp(deviceMode, "Boot") == 0)
      {
        COM_Output("Getting MCE2 out of boot mode...", INFORMATIVE, 0, "");
        if (COM_ResetTheDevice(3, portNum, sFWType, dualMCE))
        {
          *noCodeOnMCE2Board = TRUE;
        }
        else
        {
          checkPromptAgain = TRUE;
        }
      }
      if (checkPromptAgain == TRUE)
      {
        sprintf(sTransmitline, "talkto %s", MCE2NAME);
        transmit(sTransmitline);
        COM_Output("Checking MCE2 status...", INFORMATIVE, 0, "");

        sTestPrompt[0] = '\0';
        while (sTestPrompt[0] == '\0')
        {
          transmit("");
          if (waitreg(MCE_DEVICE_TYPE, instring, 2) == 0)
          {                                     
            strncpy(sTestPrompt, instring, (strlen(instring) - 1));
            sprintf(sTransmitline, "Current MCE2 mode is %s", sTestPrompt);
            COM_Output(sTransmitline, INFORMATIVE, 0, "");
            // this sleep is for simulators
            sleep(100);
            strcpy(deviceMode, sTestPrompt);
          }
        }
      }
      sprintf(sTransmitline, "talkto %s", MCENAME);
      transmit(sTransmitline);
      if (*noCodeOnMCE2Board == TRUE)
      {
        if (COM_PutMCEIntoBootMode(MCE2))
        {
          *noCodeOnMCE2Board = FALSE;
          *backupBeforeLoading = FALSE;
        }
      }
    }    
  }
  if (strcmp(sFWType, "MPE") == 0)
  {
    transmit("");
    // clear input buffer
    waitfor(">", 1);
    transmit("");
    if (waitreg(MCE_DEVICE_TYPE, instring, 2) == 0)
    {                                     
      strncpy(deviceMode, instring, (strlen(instring) - 1));
      sprintf(sTransmitline, "Current MPE mode is %s", deviceMode);
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
    }
    if (strcmp(deviceMode, "TH2 ") == 0)
    {
      COM_Output("Getting MPE out of Thermal diagnostic...", INFORMATIVE, 0, "");
      transmit("redirect disable");
      waitfor("Command Success", 5);  
      waitfor("Nothing", 2); // Waitfor device to get out of head diag mode
    }
    if (strcmp(deviceMode, "TFX ") == 0)
    {
      COM_Output("Getting MPE out of Thermal diagnostic...", INFORMATIVE, 0, "");
      transmit("redirect disable");
      waitfor("Command Success", 5);                                      
      waitfor("Nothing", 2); // Waitfor device to get out of head diag mode
    }
  }       
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function is used to check if prompt is available before sending a command.
// MCE = 1 => MCE
// MCE = 2 => MCE2
//
// WaitCounter - number passed should be multiplied by 10 to get the amount of time this function will waitfor the prompt to be available
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_TestAndWaitForPrompt(int nTargetMCE, int waitCounter)
{
  int j;
  int PromptFound = FALSE;

  char sTransmitline[STR_LEN];
  char banner[STR_LEN];

  sprintf(banner, "Checking for device prompt (test for ~%i seconds)...", waitCounter*10);
  dialog("Checking for device prompt", 1, 1,
         banner, CTEXT | 1);
 // clear input buffer
  waitfor("nothing", 1);
  if (nTargetMCE == MCE2)   
  {
    sprintf(sTransmitline, "talkto %s", MCE2NAME);
    transmit(sTransmitline);
    dialog("Checking for MCE2 prompt", 1, 1,
           banner, CTEXT | 1);
  }
  for (j = waitCounter; j != 0 ; j--)
  {
    transmit(".");
    if (waitfor(">", 2))
    {
      if (j == 1)
      {
        break;
      }
      waitfor("Nothing", 8);
    }
    else
    { 
      PromptFound = TRUE;
      break;
    }
  }
  if (nTargetMCE == MCE2)   
  {
    sprintf(sTransmitline, "talkto %s", MCENAME);
    transmit(sTransmitline);
  }
  if (PromptFound == FALSE)
  {
    COM_Output("Timeout Waiting For Diagnostic Prompt To Appear", SUSPEND_BOX, 0, "");
    return(1);
  }
  else
  {
    return(0);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function is used to check if prompt is available before sending a command.
// MCE = 1 => MCE
// MCE = 2 => MCE2
//
// WaitCounter - number passed should be multiplied by 10 to get the amount of time this function will waitfor the prompt to be available
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_TestAndWaitForMCEPrompt(int nTargetMCE, int waitCounter, char *deviceMode)
{
  int j;
  int PromptFound = FALSE;

  char sTransmitline[STR_LEN];
  char banner[STR_LEN];
  char instring[STR_LEN];

  sprintf(banner, "Checking for device prompt (test for ~%i seconds)...", waitCounter*10);
  dialog("Checking for device prompt", 1, 1,
         banner, CTEXT | 1);

 // clear input buffer
  waitfor("nothing", 1);
  if (nTargetMCE == MCE2)   
  {
    sprintf(sTransmitline, "talkto %s", MCE2NAME);
    transmit(sTransmitline);
    dialog("Checking for MCE2 prompt", 1, 1,
           banner, CTEXT | 1);
  }
  for (j = waitCounter; j != 0 ; j--)
  {
    transmit(".");
     
    if (waitreg(MCE_DEVICE_TYPE, instring, 2))
    {                                     
      if (j == 1)
      {
        break;
      }
      waitfor("Nothing", 8);
    }
    else
    { 
      PromptFound = TRUE;
      strncpy(deviceMode, instring, (strlen(instring) - 1));
      if (nTargetMCE == MCE)   
      {
        sprintf(sTransmitline, "Current MCE mode is %s", deviceMode);
      }
      if (nTargetMCE == MCE2)   
      {
        sprintf(sTransmitline, "Current MCE2 mode is %s", deviceMode);
      }
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
      break;
    }
  }
  if (nTargetMCE == MCE2)   
  {
    sprintf(sTransmitline, "talkto %s", MCENAME);
    transmit(sTransmitline);
  }
  if (PromptFound == FALSE)
  {
    COM_Output("Timeout Waiting For Diagnostic Prompt To Appear", SUSPEND_BOX, 0, "");
    return(1);
  }
  else
  {
    return(0);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function is used to check if prompt is available before sending a command.
// INPUT
// nTargetGMCE = 1 => GMCE
// nTargetGMCE = 2 => GMCE2
// WaitCounter - number passed should be multiplied by 10 to get the amount of time this function will waitfor the prompt to be available
//OUTPUT
//deviceMode = The mode the GMCE is at
//return (1) if NOT FOUND
//return(0) if FOUND
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_TestAndWaitForGMCEPrompt(int nTargetGMCE, int waitCounter, char *deviceMode)
{
  int j;
  int PromptFound = FALSE;

  char sTransmitline[STR_LEN];
  char banner[STR_LEN];
  char instring[STR_LEN];

  sprintf(banner, "Checking for device prompt (test for ~%i seconds)...", waitCounter*10);
  dialog("Checking for device prompt", 1, 1,
         banner, CTEXT | 1);

 // clear input buffer
  waitfor("nothing", 1);

// FUTURE USE
//  if (nTargetGMCE == GMCE2)   
//  {
//    sprintf(sTransmitline, "talkto %s", GMCE2NAME);
//    transmit(sTransmitline);
//    dialog("Checking for GMCE2 prompt", 1, 1,
//           banner, CTEXT | 1);
//  }

  for (j = waitCounter; j != 0 ; j--)
  {
    transmit(".");
     
    if (waitreg(GMCE_DEVICE_TYPE, instring, 2))
    {                                     
      if (j == 1)
      {
        break;
      }
      waitfor("nothing", 8);
    }
    else
    { 
      PromptFound = TRUE;
      strncpy(deviceMode, instring, (strlen(instring) - 1));
      if (nTargetGMCE == GMCE)   
      {
        sprintf(sTransmitline, "Current GMCE mode is %s", deviceMode);
      }
//      if (nTargetGMCE == GMCE2)   
//      {
//        sprintf(sTransmitline, "Current GMCE2 mode is %s", deviceMode);
//      }

      COM_Output(sTransmitline, INFORMATIVE, 0, "");
      break;
    }
  }
//  if (nTargetGMCE == GMCE2)   
//  {
//    sprintf(sTransmitline, "talkto %s", MCENAME);
//    transmit(sTransmitline);
//  }
  if (PromptFound == FALSE)
  {
    COM_Output("Timeout Waiting For Diagnostic Prompt To Appear", SUSPEND_BOX, 0, "");
    return(1);
  }
  else
  {
    return(0);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Tests to see if the TH2 head is online.
//
// nOfflineStatus - modified if either head is offline
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
int COM_TestForTH2(char *sFWType, int dualMCE, int *nOfflineStatus)
{
  char sTransmitline[STR_LEN];
  int nRC = FALSE; 
  int nRC2 = FALSE; 
  
  dialog("Head Online?", 1, 1,
         "Checking to see if the TH2 head is online...",CTEXT | 1);

  if (strcmp(sFWType, "MPE") == 0)
  {
    transmit("redirect pass");
    if (waitfor("Complete", WAIT_TIME))
    {         
      COM_Output("TH2 head is not online!", INFORMATIVE, 0, "");
      *nOfflineStatus = 1;
      return(1);
    }
  }
  if (strcmp(sFWType, MCENAME) == 0 || strcmp(sFWType, GMCENAME) == 0)
  {
    transmit("th2 \"ver\""); // first th2 "" command does not always work
    waitfor("Success", WAIT_TIME);
    transmit("th2 \"ver\""); 
  }
  if (strcmp(sFWType, MPENAME) == 0)
  {
    transmit("ver"); // first th2 "" command does not always work
    waitfor("Success", WAIT_TIME);
    transmit("ver");
  }
  if (waitfor("Success", WAIT_TIME))
  {
    nRC = TRUE; 
    COM_Output("MCE TH2 head is not online!", INFORMATIVE, 0, "");
    *nOfflineStatus = 1;
  }
  if (dualMCE)
  {
    dialog("MCE2 Head Online?", 1, 1,
           "Checking to see if the MCE2 TH2 head is online...",CTEXT | 1);

    sprintf(sTransmitline, "talkto %s", MCE2NAME);
    transmit(sTransmitline);
    transmit("th2 \"ver\""); // first th2 "" command does not always work
    waitfor("Success", WAIT_TIME);
    transmit("th2 \"ver\""); 
    if (waitfor("Success", WAIT_TIME))
    {
      nRC2 = TRUE; 
      COM_Output("MCE2 TH2 head is not online!", INFORMATIVE, 0, "");
      *nOfflineStatus = 2;
    }  
    sprintf(sTransmitline, "talkto %s", MCENAME);
    transmit(sTransmitline);
  }
  if (nRC == TRUE && nRC2 == TRUE)
  {
    COM_Output("Both MCE and MCE2 TH2 heads are not online!", INFORMATIVE, 0, "");
  }
  if (nRC == TRUE && nRC2 == TRUE)
  {
    *nOfflineStatus = 3;
  }
  return(0);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//Description:
//     Tests to see if the TFX head is online.
//
//  Input:
//       sFWType - firmware type MPE or MCE
//       nDualMCE - flag to determine dual mce or not.  Not implemented by this function
//
//  Output:
//       nOfflineStatus - set to 1 if head is offline and 0 if head is online
//              
//
//  Return:
//       void   
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_TestForTFX(char *sFWType, int nDualMCE, int *nOfflineStatus)
{
  char transmitline[STR_LEN];
  
  dialog("Head Online?", 1, 1,
         "Checking to see if the TFX head is online...",CTEXT | 1);

  if (strcmp(sFWType, MPENAME) == 0)
  {
    transmit("redirect pass");
    if (waitfor("Complete", WAIT_TIME))
    {         
      COM_Output("TFX head is not online!", INFORMATIVE, 0, "");
      *nOfflineStatus = 1;
      return(1);
    }    
  }

  if (strcmp(sFWType, MCENAME) == 0)
  {
    transmit("th2 \"ver\""); // first th2 "" command does not always work
    waitfor("Success", WAIT_TIME);
    transmit("th2 \"ver\""); 
  }
  if (strcmp(sFWType, MPENAME) == 0)
  {
    transmit("th2 \"ver\""); // first th2 "" command does not always work
    waitfor("Success", WAIT_TIME);
    transmit("th2 \"ver\""); // first th2 "" command does not always work
  }
  
  if (waitfor("Success", WAIT_TIME))
  {
    COM_Output("TFX head is not online!", INFORMATIVE, 0, "");
    *nOfflineStatus = 1;
  }
  else
  {    
    // head will get direct communication back important for TFX heads
    transmit("redirect disable");
    waitfor("Command Complete", WAIT_TIME);
  } 
  return(0);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Tests to see if the TH1.X head is online.
// This function currently supports a dual TH1.X head combination even though this does exist on a product yet.
//
// nOfflineStatus - modified if either head is offline
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
void COM_TestForTH1X(char *sFWType, int dualMCE, int *nOfflineStatus)
{
  char sTransmitline[STR_LEN];
  int nRC = FALSE; 
  int nRC2 = FALSE; 
  
  dialog("Head Online?", 1, 1,
         "Checking to see if the TH1.X head is online...",CTEXT | 1);

  
  transmit("head version");
  if (waitfor("Command Complete", WAIT_TIME))
  {
    nRC = TRUE; 
    COM_Output("MCE TH1.X head is not online!", INFORMATIVE, 0, "");
    *nOfflineStatus = 1;
  }
  if (dualMCE)
  {
    dialog("MCE2 Head Online?", 1, 1,
           "Checking to see if the MCE2 TH1.X head is online...",CTEXT | 1);

    sprintf(sTransmitline, "talkto %s", MCE2NAME);
    transmit(sTransmitline);
    transmit("head version");
    if (waitfor("Command Complete", WAIT_TIME))
    {
      nRC2 = TRUE; 
      COM_Output("MCE2 TH1.X head is not online!", INFORMATIVE, 0, "");
      *nOfflineStatus = 2;
    }  
    sprintf(sTransmitline, "talkto %s", MCENAME);
    transmit(sTransmitline);
  }
  if (nRC == TRUE && nRC2 == TRUE)
  {
    COM_Output("Both MCE and MCE2 TH1.X heads are not online!", INFORMATIVE, 0, "");
  }
  if (nRC == TRUE || nRC2 == TRUE)
  {
    *nOfflineStatus = 3;
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Checks for dual head device (hydra).
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_CheckForDualMCE(int *dualMCE)
{
  COM_Output("Checking for MCE2...", INFORMATIVE, 0, "");
  COM_Output("access expert", TERMINAL, WAIT_TIME, "Command Complete");

  transmit("option");
  if (waitfor("Dual-head option is enabled", 2))  //If MCE does not show up in the list device is not dual head remember "sio nodes" list satellite boards
  {            
    #ifdef OlderFirmware
      transmit("option");
      if (waitfor("Dual-head option is       enabled", 2))  // try again the keep changing the format
      {
        COM_Output("MCE2 not found", INFORMATIVE, 0, "");
      }
      else
      {
        *dualMCE = TRUE;
        COM_Output("**MCE2 Present**", INFORMATIVE, 0, "");
      }
    #endif
    #ifndef OlderFirmware
      COM_Output("MCE2 not found", INFORMATIVE, 0, "");
    #endif
  }
  else
  {
    *dualMCE = TRUE;
    COM_Output("**MCE2 Present**", INFORMATIVE, 0, "");
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Checks to see if service host has MCE2 configured.
//
// returns 1 if servicehost has MCE2 configured
// returns 0 if servicehost does not have MCE2 configured
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CheckHostConfigForMCE2(int suspend)
{
  char sTransmitline[STR_LEN];

  transmit("talkto srvshell");
  transmit("svsh devinfo query mce2");
  if (waitfor("NAME=MCE2", 2))
  {
    if (suspend)
    {
      COM_Output("The script has determined that the MCE is setup as dual mce device but the MCE2 com port is not setup in service host!", SUSPEND_BOX, 0, 
             "Run Host Configurations! (The setup tool can be found under the Service Host icon in the systems tray.  Service Shell 2.5 or higher.)");
      sprintf(sTransmitline, "talkto %s", MCENAME);
      transmit(sTransmitline);
      ExitInError();
    }
    else
    {
      COM_Output("Service Host does not have MCE2 configured.", INFORMATIVE, 0, ""); 
      sprintf(sTransmitline, "talkto %s", MCENAME);
      transmit(sTransmitline);
      return(0);
    }
  }
  sprintf(sTransmitline, "talkto %s", MCENAME);
  transmit(sTransmitline);
  COM_Output("Service Host has MCE2 configured.", INFORMATIVE, 0, ""); 
  return(1);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function checks for a existing file and renames the extension if it exists.
//
//  If file already exists then change last letter to
//  number and increment as necessary. If 9 is reached
//  then cycle back to 0 and overwrite circularly.
//  This modified name is used to store previous version
//  as a backup.
//
// file_loc - directory where the file will be created
// name - the name of the file to create - DO NOT INCLUDE THE EXTENSION IN THE FILE NAME 
// ext - the extension of the file to create - DO NOT INCLUDE A '.' IN THE EXTENSION
// path - path of the file to create
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_CheckForTheSameFileName(char *file_loc, char *name, char *ext, char *path)
{
  FILE *f = NULL;

  char tmp2[STR_LEN];
  char tmp[STR_LEN];
  char path2[STR_LEN];

  int i, len;

  strcpy(tmp, name);
  strcat(tmp, ".");
  strcat(tmp, ext);
  strcpy(path, file_loc);
  strcat(path, tmp);
  strcpy(path2, path);
  len = strlen(path);
  if (!access(path, 0))
  {
    printf("File already exists. Modifying the extension of the file. ");
    printf("Path: %s", path);
    // already exists so modify name
    while (!access(path, 0))
    {
      if (path[len - 1] == '9')
      {
        path[len - 1] = '0';
        break; // limit reached
      }
      else if (path[len - 1] >= '0' && path[len - 1] < '9')
      {
        path[len - 1] = path[len - 1] + 1;
      }
      else
      {
        path[len - 1] = '0';
      }
    }
    path[len - 1] = path[len - 1] + 1;
    if (!access(path, 0))
    {
      // next file name exists so delete it
      sprintf(tmp2, "del \"%s\"", path);
      system(tmp2);
    }
    path[len - 1] = path[len - 1] - 1;

    // copy old version to backup name
    sprintf(tmp2, "copy \"%s\" \"%s\"", path2, path);
    system(tmp2);
    strcpy(path, path2);
  }
}


//------------------------------------------------------------------------------------------------------------------------------------------------------------
//  Description:
//       Copies a directories contents to another directory.
//
//  Input:
//       char *sPathOfDirectoryToCopy - directory to copy
//       char *sDirectoryToCopyTo    - directory to copy directory into
//       int nSuspend - flag to create a suspend box
//       char *sFWType - firmware type MPE or MCE
//
//  Output:
//       none
//  Return:
//       SUCCESS if the directory copied
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CopyDirectory(char *sPathOfDirectoryToCopy, char *sDirectoryToCopyTo, int nSuspend, char *sFWType)
{    
  char sTransmitline[STR_LEN];
  char sMPETransmitline[STR_LEN];
  int nRC = SUCCESS;

  Output("Copying directory:", INFORMATIVE, 0, "");
  sprintf(sTransmitline, "%s", sPathOfDirectoryToCopy);
  
  Output(sTransmitline, INFORMATIVE, 0, "");

  Output("To this location:", INFORMATIVE, 0, "");
  sprintf(sTransmitline, "%s", sDirectoryToCopyTo);
  strcpy(sMPETransmitline, sTransmitline);
  
  Output(sTransmitline, INFORMATIVE, 0, "");
    
  // uncomment below to debug
  //sprintf(sTransmitline, "cmd /k xcopy \"%s\"*.* \"%s\" /e /y", sPathOfDirectoryToCopy, sDirectoryToCopyTo);
  sprintf(sTransmitline, "xcopy \"%s\"*.* \"%s\" /e /y", sPathOfDirectoryToCopy, sDirectoryToCopyTo);

  if (system(sTransmitline))
  {
    if (nSuspend == TRUE)
    { 
      Output("Copying directory failed!", SUSPEND_BOX, 0, "");
    }
    nRC = FAILURE;
  }
  return(nRC);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Creates a pathname if required.
// The function creates a directory via mkdir().
// Then the fuction tests to see if it can change to that directory via chdir().  If the chdir() fails the function assumes the directory was not created.
// Note: mkdir fails if the directory you want to create already exists.  That is why chdir is used to test if the directory was created or not.
// This function does not care if you are creating a folder that already exists it will not return an error.
//
// return 1 if function fails
// return 0 if function completes succesfully
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CreateFolder(char *pathname, char *sFWType)
{    
  char temp[STR_LEN];
  char sTransmitline[STR_LEN];

  mkdir(pathname);
  
  // if you can change to that directory then the directory was created or already exists.
  if (chdir(pathname) != 0)
  {
    COM_Output("Unable to create directory!", SUSPEND_BOX, 0, pathname);
    return(1);
  }
  else
  {
    COM_Output("Created directory:", INFORMATIVE, 0, "");
    COM_Output(pathname, INFORMATIVE, 0, "");
  }
  return(0);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//Description:
//     This function checks to see if a file exists and calls COM_CopyAndOverwriteFileNoCheck if the user wants to overwrite the file.
//
//  Input:
//       sPathOfFileToCopy - location where file is
//       sDirectoryToCopyFile - directory to where to copy file to
//       nSuspend - a flag to specify whether to suspend if copy fails
//       sFWType - firmware type MPE or MCE
//
//  Output:
//     sPathOfFileToCopy - modified to where file is copied to
//              
//
//  Return:
//       1 if failure 
//       0 if success    
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CopyAndOverwriteFile(char *sPathOfFileToCopy, char *sDirectoryToCopyFile, int nSuspend, char *sFWType)
{
  int nFileExist = FALSE;
  int rc = 0;

  char sFileToBeCopied[STR_LEN];
  char sTransmitline[STR_LEN];
  char sStoredCopiedPath[STR_LEN];
  char tmp[STR_LEN];
  
  COM_ExtractFileNameFromString(sPathOfFileToCopy, sFileToBeCopied);

   // store the location of the file that it should be copied to
  strcpy(sStoredCopiedPath, sDirectoryToCopyFile);
  strcat(sStoredCopiedPath, sFileToBeCopied);
 
  if (!access(sStoredCopiedPath, 0))
  {
    #ifdef PRODUCTION
      if (strcmp(sStoredCopiedPath, sPathOfFileToCopy) == 0)
      {
        nFileExist = TRUE;  
      }
      else
      {
        nFileExist = FALSE; 
      }

    #else
      if (strcmp(sStoredCopiedPath, sPathOfFileToCopy) != 0)
      {
        while (rc < 9)
        {
          if (rc >= 0)
          {
            dialog("File exists", 1, 1,
                   "Copying a file to the service shell firmware directory.", CTEXT | 1,
                   "The folder already contains a file with the same name:", CTEXT | 1,
                   sStoredCopiedPath, CTEXT | 5,
                   "Would you like to overwrite the existing file?", CTEXT | 8,
                   "NOTE: If you browsed to a file that is already located in the service shell firmware directory,", CTEXT | 1,
                   "click 'No' to avoid the copying a file that is already in the directory.", CTEXT | 1,
                   "Yes", BUTTON | 9, -1, -1, 100, 7,
                   "No", BUTTON | 10, -1, -1, 100, 7,
                   "Cancel", BUTTON | 11, -1, -1, 100, 7);
          }
          sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
          rc = dialog(tmp);
          if (rc == DIALOG_CLOSE)
          { 
            // user hit the x button in the corner of the dialog box
            COM_Done();
          }
        }
        // Erase the dialog box.
        dialog("");
        if (rc == 9)
        {
          nFileExist = FALSE;  
        }
        if (rc == 10)
        {
          nFileExist = TRUE;  
        }
        if (rc == 11)
        {
          return(1);
        }
      }
      else
      {
        nFileExist = TRUE;
      }
    #endif
  }
  
  if (nFileExist == FALSE)    
  {
    if (COM_CopyAndOverwriteFileNoCheck(sPathOfFileToCopy, sDirectoryToCopyFile, nSuspend, sFWType))
    {
      return(1);
    }
  }
  else
  {
    // must change sPathOfFileToCopy so it now has the path of file that had been copied
    strcpy(sPathOfFileToCopy, sStoredCopiedPath);
  }
  return(0);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//Description:
//     Copies a file from once location to another and overwrites the file if it exists (read only files too).
//     If a file exists the function will copy the file as tempfile.txt first then copy tempfile.txt as the original file name.
//     The tempfile.txt will then be deleted
//     
//     Windows NT, Windows 2000 & Windows 95 DOS copies should work.
//
//  Input:
//       sPathOfFileToCopy - location where file is
//       sDirectoryToCopyFile - directory to where to copy file to
//       nSuspend - a flag to specify whether to suspend if copy fails
//       sFWType - firmware type MPE or MCE
//
//  Output:
//     sPathOfFileToCopy - modified to where file is copied to
//              
//  Return:
//       1 if failure 
//       0 if success    
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CopyAndOverwriteFileNoCheck(char *sPathOfFileToCopy, char *sDirectoryToCopyFile, int nSuspend, char *sFWType)
{
  int copyStatus = 0;
  int nSkipNextCopy = FALSE;
  int nTempFileCreated = FALSE;
  int nReturnFailure = FALSE;

  char sFileToBeCopied[STR_LEN];
  char sMPEtemp[STR_LEN];
  char sTempFilePath[STR_LEN];
  char sLocationToCopyFile[STR_LEN];
  char sCopiedPath[STR_LEN];
  char sStoredCopiedPath[STR_LEN];
  char sTransmitline[STR_LEN_LONG];
  
  
  // get the file name of the file to be copied
  COM_ExtractFileNameFromString(sPathOfFileToCopy, sFileToBeCopied);
  
  // store the location of the file that it should be copied to
  strcpy(sStoredCopiedPath, sDirectoryToCopyFile);
  strcat(sStoredCopiedPath, sFileToBeCopied);
  
  // store where the file is going to be copied
  strcpy(sLocationToCopyFile, sDirectoryToCopyFile);
  strcpy(sCopiedPath, sDirectoryToCopyFile);

  // get the location of where the file will be copied to see if that file already exists
  // or use as the path to copy the file if the file does not already exist
  strcat(sCopiedPath, sFileToBeCopied);

  // check to see if file exsits to check if an extra copy is required
  if (!access(sCopiedPath, 0))
  {
    
    // remove the read only setting so file will be copied over
    sprintf(sTransmitline, "attrib -r \"%s\"", sCopiedPath);
    system(sTransmitline);  

    // check for delete temporary file just in case it exists and delete it if it does exist
    // the file is copied as a temporary file first to allow it to be overwritten later
    // dos fails if the same file name is copied as itself with some dos versions
    strcpy(sCopiedPath, sLocationToCopyFile);
    strcat(sCopiedPath, "tempfile.txt");

    // store the location of the file so it can be deleted later
    strcpy(sTempFilePath, sCopiedPath);

    if (!access(sCopiedPath, 0))
    {
      printf("Temp file found deleting it!");
      COM_Output("Deleting file:", INFORMATIVE, 0,  "");
      strcpy(sTransmitline, sCopiedPath);
      
      COM_Output(sTransmitline, INFORMATIVE, 0, "");


      //line below will hold the dos window open
      // sprintf(sTransmitline, "cmd /k del \"%s\"", sCopiedPath);
      sprintf(sTransmitline, "del \"%s\"", sCopiedPath);
      system(sTransmitline);
    }

    COM_Output("Copying file:", INFORMATIVE, 0,  "");
    sprintf(sTransmitline, "%s", sPathOfFileToCopy);
    
    COM_Output(sTransmitline, INFORMATIVE, 0, "");

    COM_Output("Copying file as:", INFORMATIVE, 0,  "");
    sprintf(sTransmitline, "%s", sCopiedPath);
        
    COM_Output(sTransmitline, INFORMATIVE, 0, "");

    sprintf(sTransmitline, "copy \"%s\" \"%s\"", sPathOfFileToCopy, sCopiedPath);
    copyStatus = system(sTransmitline);

    if (copyStatus == 0)
    {
      // Put this in for Win 95 (Win 95 always returns a zero whether or not the copy was successful)
      if (access(sCopiedPath, 0))
      {
        // file not found
        copyStatus = 1;
      }
      else
      {
        COM_Output("Copying file successful", INFORMATIVE, 0,  "");
        nTempFileCreated = TRUE;
      }
    }
    if (copyStatus == 1 )
    {
      nSkipNextCopy = TRUE;

      COM_Output("Copying file failed!", INFORMATIVE, 0,  "");
      if (nSuspend == 0)
      {
        if (COM_CopyFailedWarning(sPathOfFileToCopy, sLocationToCopyFile) == FAILURE)
        {
          nReturnFailure == TRUE;
        }
      }
    }
    strcpy(sCopiedPath, sStoredCopiedPath); 
    strcpy(sPathOfFileToCopy, sTempFilePath);
  }
  
  if (nSkipNextCopy == FALSE)
  {
    COM_Output("Copying file:", INFORMATIVE, 0,  "");

    sprintf(sTransmitline, "%s", sPathOfFileToCopy);
    
    COM_Output(sTransmitline, INFORMATIVE, 0, "");

    COM_Output("Copying file as:", INFORMATIVE, 0,  "");
    sprintf(sTransmitline, "%s", sCopiedPath);
    
    COM_Output(sTransmitline, INFORMATIVE, 0, "");

    sprintf(sTransmitline, "copy \"%s\" \"%s\"", sPathOfFileToCopy, sCopiedPath);
    //system(sTransmitline);
    copyStatus = system(sTransmitline);
    
    if (TRUE == nTempFileCreated)
    {
      // delete the temporary file that was created!
      COM_FileDelete(sTempFilePath);
    }

    if (copyStatus == 0)
    {
      // Put this in for Win 95 (Win 95 always returns a zero whether or not the copy was successful)
      if (access(sCopiedPath, 0))
      {
        // file not found
        copyStatus = 1;
      }
      else
      {
        COM_Output("Copying file successful", INFORMATIVE, 0,  "");
      }
    }
    if (copyStatus == 1 )
    {
      if (nSuspend == 0)
      {
        if (COM_CopyFailedWarning(sPathOfFileToCopy, sLocationToCopyFile) == FAILURE)
        {
          nReturnFailure = TRUE;
        }
      }
    }
  }

  // return the path of the file if the copy was successful or not the user may have copied the files themself 
  // after reading the message in COM_CopyFailedWarning()
  strcpy(sPathOfFileToCopy, sStoredCopiedPath);

  if (nReturnFailure == TRUE)
  {
    return(1);
  }
  else
  {
    return(0);
  }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------
//Sends a file to the host computer.
//
//pathOfFileToBeSent will be modified.
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CopyFailedWarning(char *sPathOfFileToCopy, char *sLocationToCopyFile)
{
  int rc = 0;
  
  char tmp[STR_LEN];

  COM_Output("Copying file failed!", INFORMATIVE, 0,  sPathOfFileToCopy);
  
  while (rc < 8)
  {
    if (rc >= 0)
    {
      dialog("File not copied!", 1, 1,
             "Copying file failed!", CTEXT | 2,
             sPathOfFileToCopy, CTEXT | 1,
             "Copy the file and paste it into the directory specified below:", CTEXT | 3,
             sLocationToCopyFile, CTEXT | 1,
             "Hit Resume to continue.", CTEXT | 8,
             "Main Menu", BUTTON | 8, -1, -1, 100, 7,
             "Resume", BUTTON | 9, -1, -1, 100, 7, 
             "Quit", BUTTON | 10, -1, -1, 100, 7);
    }
    sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
    rc = dialog(tmp);
    if (rc == DIALOG_CLOSE)
    { 
      // user hit the x button in the corner of the dialog box     
      COM_Done();
    }
  }
  // Erase the dialog box.
  dialog("");
  if (rc == 8)
  {
    return(FAILURE);
  }
  if (rc == 9)
  {
    return(SUCCESS);
  }
  if (rc == 10)
  {
    ExitInError();
  }

  return(SUCCESS);
}



//------------------------------------------------------------------------------------------------------------------------------------------------------------
//Sends a file to the host computer.
//
//pathOfFileToBeSent will be modified.
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_SendFileToHost(char *pathOfFileToBeSent, char *destinationPathOfFileToBeSent, int type, char *sFWType, char *connectionType, int *sendFileToHOST)
{
  int rc = 0;
  int transferStatus;

  char fileToBeSent[STR_LEN];
  char pathOfFileWithFileName[STR_LEN];
  char MPEtemp[STR_LEN];
  char tmp[STR_LEN];
  char sTransmitline[STR_LEN];

  
  rc = 0;
  strcpy(pathOfFileWithFileName, destinationPathOfFileToBeSent);
  if (strcmp(connectionType, "Remote") == 0) 
  {
    if (*sendFileToHOST == FALSE)
    {
      // Do this because sendFileToHOST == TRUE did this and sendFileToHOST == FALSE needs to still do the step below.
      strcpy(pathOfFileToBeSent, pathOfFileWithFileName);
      return(0);
    }
    if (*sendFileToHOST == TRUE)
    {
      COM_ExtractFileNameFromString(pathOfFileToBeSent, fileToBeSent);
      strcat(pathOfFileWithFileName, fileToBeSent);
      COM_Output("Copying file from Client Computer:", INFORMATIVE, 0,  "");
      sprintf(sTransmitline, "%s", pathOfFileToBeSent);
      
      COM_Output(sTransmitline, INFORMATIVE, 0, "");

      COM_Output("Sending file to Host Computer: ", INFORMATIVE, 0,  "");
      sprintf(sTransmitline, "%s", pathOfFileWithFileName);
      
      COM_Output(sTransmitline, INFORMATIVE, 0, "");

      
      dialog("File Transfer", 1, 1,
             "Sending file to Host Computer...", CTEXT | 1,
      pathOfFileToBeSent, CTEXT | 2);

      transferStatus = SendFile(pathOfFileToBeSent, pathOfFileWithFileName);

      if (transferStatus == 1)
      {
        COM_Output("Sending file to HOST successful", INFORMATIVE, 0,  "");
        if (type == 0)
        {
          strcpy(pathOfFileToBeSent, destinationPathOfFileToBeSent); // copy the location of the file on the HOST computer so download command
        }
        dialog("");                                                  // will work properly.                                   
        return(1);                                                   
      }
      dialog("");

      if (transferStatus == 0 )
      {  
        COM_Output("Sending file to HOST failed", INFORMATIVE, 0,  "");
        if (type == 0)  
        {
          while (rc < 9)
          {
            if (rc >= 0)
            {
              dialog("File not sent!", 1, 1,
              "The file:", CTEXT | 2, 
              pathOfFileToBeSent, CTEXT | 2, 
              "did not transfer to this location on the HOST computer:", CTEXT | 2, 
              destinationPathOfFileToBeSent, CTEXT | 2,
              "Sending and retrieving files to/from HOST disabled", CTEXT | 2,
              "Copy ALL the files to be downloaded and paste them", CTEXT | 3,  
              "in the HOST computer's directory specified below:", CTEXT | 4, 
              destinationPathOfFileToBeSent, CTEXT | 5,
              "Also Swap Backup files from HOST and CLIENT computers accordingly", CTEXT | 6,  
              "after script has finished executing.", CTEXT | 7,
              "Hit resume to continue.", CTEXT | 8,
              "Resume", BUTTON | 9, -1, -1, 100, 7, "Quit", BUTTON | 10, -1, -1, 100, 7);
            }
            sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
            rc = dialog(tmp);
            if (rc == DIALOG_CLOSE)
            { 
              // user hit the x button in the corner of the dialog box
              COM_Done();
            }
          }
          // Erase the dialog box.
          dialog("");
          if (rc == 9)
          {
            *sendFileToHOST = FALSE;
          }
          if (rc == 10)
          {
            ExitInError();
          }
        }
        if (type == 3)
        {
          return(0);
        }
      }
    }
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Gets a file from the host computer.
//
// pathOfFileToRetrieve will not be modified.
// pathOfReceived will be modified - the filename will be added to the pathOfReceived
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_GetFileFromHost(char *pathOfFileToRetrieve, char *pathOfReceived, int type, char *sFWType, char *connectionType, int *sendFileToHOST, char *remoteHostPath)
{
  int transferStatus;
  int rc = 0;

  char fileToBeSent[STR_LEN];
  char MPEtemp[STR_LEN];
  char tmp[STR_LEN];
  char sTransmitline[STR_LEN];
  
  if (strcmp(connectionType, "Remote") == 0)
  {
    if (*sendFileToHOST == TRUE)
    {
      COM_ExtractFileNameFromString(pathOfFileToRetrieve, fileToBeSent);
      strcat(pathOfReceived, fileToBeSent);
      COM_Output("Retrieving file from Host Computer:", INFORMATIVE, 0,  "");
      sprintf(sTransmitline, "%s", pathOfFileToRetrieve);
      
      COM_Output(sTransmitline, INFORMATIVE, 0, "");

      COM_Output("Sending file to Client Computer:", INFORMATIVE, 0,  "");
      sprintf(sTransmitline, "%s", pathOfReceived);
      
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
      
      dialog("File Transfer", 1, 1,
             "Retrieving file from Host...", CTEXT | 1,
      pathOfFileToRetrieve, CTEXT | 2);                                         
      transferStatus = GetFile(pathOfFileToRetrieve, pathOfReceived);
      if (transferStatus == 1)
      {
        COM_Output("Retrieving file from the HOST successful", INFORMATIVE, 0,  "");
        dialog("");
        return(1);
      }
      dialog("");
      if (transferStatus == 0 )
      {
        COM_Output("Retrieving file from the HOST failed!", INFORMATIVE, 0,  "");
        if (type == 0)
        {
          while (rc < 9)
          {
            if (rc >= 0)
            {
              dialog("File not retrieved!", 1, 1,
              "The file:", CTEXT | 2, 
              pathOfFileToRetrieve, CTEXT | 2, 
              "did not transfer to this location on the CLIENT computer:", CTEXT | 2, 
              remoteHostPath, CTEXT | 2,
              "Sending and retrieving files to/from HOST disabled", CTEXT | 2,
              "Copy ALL the files to be downloaded and paste them", CTEXT | 3,
              "in the HOST computer's directory specified below:", CTEXT | 4,
              remoteHostPath, CTEXT | 5,
              "Also Swap Backup files from HOST and CLIENT computers accordingly", CTEXT | 6,
              "after script has finished executing.", CTEXT | 7,
              "Hit resume to continue.", CTEXT | 8,
              "Resume", BUTTON | 9, -1, -1, 100, 7, "Quit", BUTTON | 10, -1, -1, 100, 7);
            }
            sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
            rc = dialog(tmp);
            if (rc == DIALOG_CLOSE)
            { 
              // user hit the x button in the corner of the dialog box
              COM_Done();
            }
          }
          // Erase the dialog box.
          dialog("");
          if (rc == 9)
          {
            *sendFileToHOST = FALSE;
          }
          if (rc == 10)
          {
            ExitInError();
          }
        }
        if (type == 3)
        {
          return(0);
        }
      }
    }
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//This function checks to see if the user actually put a file name in and checks to see if file is there.
//There is the suspend flag used to suspend in this function or not.
//Return 0 if file exists 
//Return 1 if file does not exist
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CheckForFileAvailability(char *pathname, int suspend)
{
  // verify firmware code availability
  if (pathname[strlen(pathname) - 1] == '\\')
  {
    if (suspend)
    {
      COM_Output("You must enter the full path:", SUSPEND_BOX, 0, pathname);
      return(1);
    }
    else
    {
      return(0);
    }
  }
  else if (access(pathname, 0))
  {
    if (suspend)
    {
      COM_Output("Unable to find file:", SUSPEND_BOX, 0, pathname);
    }
    return(1);
  }
  else
  {
    return(0);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function gets a file from a local drive and creates a directory and pastes it to where the main code was loaded from.
// type specifies whether to return a 0 if the function fails
// type also specifies to delete the file after copying it.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CopyFileToExternalLocation(char *sPathOfFileToCopy, char *locationToCopyFile, int type, char *sFWType)
{
  int copyStatus;
  int rc = 0;
  
  char sFileToBeCopied[STR_LEN];
  char pathOfFileWithFileName[STR_LEN];
  char MPEtemp[STR_LEN];
  char tempLocationToCopyFile[STR_LEN];
  char tmp[STR_LEN];
  char temp[STR_LEN];
  char sTransmitline[STR_LEN];


  sprintf(temp, "Copying file %s ...", sPathOfFileToCopy);
  sprintf(sTransmitline, "Pasting file to %s ...", locationToCopyFile);
  dialog("Copying file", 1, 1,
          temp, CTEXT | 1,
          sTransmitline, CTEXT | 1);

  strcpy(tempLocationToCopyFile, locationToCopyFile);
  
  COM_ExtractFileNameFromString(sPathOfFileToCopy, sFileToBeCopied);
  strcat(tempLocationToCopyFile, sFileToBeCopied);
    
  
  COM_Output("Copying file:", INFORMATIVE, 0,  "");
  sprintf(sTransmitline, "%s", sPathOfFileToCopy);
 
  COM_Output(sTransmitline, INFORMATIVE, 0, "");

  COM_Output("Pasting file to:", INFORMATIVE, 0,  "");
  sprintf(sTransmitline, "%s", tempLocationToCopyFile);
    
  COM_Output(sTransmitline, INFORMATIVE, 0, "");

  sprintf(tmp, "copy /y \"%s\" \"%s\"", sPathOfFileToCopy, tempLocationToCopyFile);
  copyStatus = system(tmp);
  if (copyStatus == 0)
  {
    // Put this in for Win 95 (Win 95 always returns a zero whether or not the copy was successful)
    if (COM_CheckForFileAvailability(tempLocationToCopyFile, 0))
    {
      copyStatus = 1;
    }
    else
    {
      COM_Output("Copying file successful", INFORMATIVE, 0,  "");
    }
  }
  if (copyStatus == 1 )
  {
    rc = 0;

    COM_Output("Copying file failed!", INFORMATIVE, 0,  "");
    if (type == 1)
    {
      while (rc < 9)
      {
        if (rc >= 0)
        {
          dialog("File not copied!", 1, 1,
                 "The script is unable to copy a test file to the user's specified backup directory.", CTEXT | 1,
                 "Backup files are always created under the service shell firmware directory by default.", CTEXT | 1, 
                 "MainMenu", BUTTON | 9, -1, -1, 100, 7, 
                 "Quit", BUTTON | 10, -1, -1, 100, 7);
        }
        sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
        rc = dialog(tmp);
        if (rc == DIALOG_CLOSE)
        { 
          // user hit the x button in the corner of the dialog box
          COM_Done();
        }
      }
    }
    else
    {
      while (rc < 9)
      {
        if (rc >= 0)
        {
          dialog("File not copied!", 1, 1,
                 "Copying files failed", CTEXT | 2,
                 "Hit Resume to continue.", CTEXT | 8,
                 "Resume", BUTTON | 9, -1, -1, 100, 7, "Quit", BUTTON | 10, -1, -1, 100, 7);
        }
        sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
        rc = dialog(tmp);
        if (rc == DIALOG_CLOSE)
        { 
          // user hit the x button in the corner of the dialog box
          COM_Done();
        }
      }
    }
    // Erase the dialog box.
    dialog("");
    
    // return 0 if copied failed specified by type
    if (type == 1)
    {
      if (rc == 9)
      {
        return(0);
      }
    }
    if (rc == 10)
    {
      ExitInError();
    }
  }
  return(1);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function captures and copies to a file already opened.  Only one command is sent and then a responce string is waited for.
// 
// type 0 = MCE
// type 1 = MCE2
//
// returns 0 if successfull
// returns 1 if failure
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
void COM_CaptureToFile(char *path, int type, char *informationalLine, char *command, char *sWaitForString, int nWaitTime)
{
  char tmp[STR_LEN];
  char sTransmitline[STR_LEN];

  if (type)
  {
    sprintf(sTransmitline, "talkto %s", MCE2NAME);
    transmit(sTransmitline);
  }

  COM_Output(informationalLine, INFORMATIVE, 0, "");
  sprintf(sTransmitline, "%s", path);
  COM_Output(sTransmitline, INFORMATIVE, 0, "");

  capture(path);

  if (COM_Output(command, TERMINAL, nWaitTime, sWaitForString)) 
  {
    if (type)
    {
      sprintf(sTransmitline, "talkto %s", MCENAME);
      transmit(sTransmitline);
    }
    
    return(1);
  }
  capture("");

  if (type)
  {
    sprintf(sTransmitline, "talkto %s", MCENAME);
    transmit(sTransmitline);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//This function creates a file.  Only one command is sent and then a responce string is waited for.
//type 0 = MCE
//type 1 = MCE2
//
//returns 0 if successfull
//returns 1 if failure
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
void COM_OpenAndCaptureToFile(char *path, int type, char *informationalLine, char *command, char *sWaitForString, int nWaitTime)
{
  char tmp[STR_LEN];
  char sTransmitline[STR_LEN];
  FILE *fpFile = NULL;               // file pointer

  if (type)
  {
    sprintf(sTransmitline, "talkto %s", MCE2NAME);
    transmit(sTransmitline);
  }

  COM_Output(informationalLine, INFORMATIVE, 0, "");
  sprintf(sTransmitline, "%s", path);
  COM_Output(sTransmitline, INFORMATIVE, 0, "");


  int nRC = FAILURE;
  int nLinesCnt = 0;

   
  if (COM_FileOpen(path, MODE_WRITE, &fpFile) == FAILURE)
  {
     return(1);
  }
  
  capture(path);
  if (COM_Output(command, TERMINAL, nWaitTime, sWaitForString)) 
  {
    if (type)
    {
      sprintf(sTransmitline, "talkto %s", MCENAME);
      transmit(sTransmitline);
    }
    COM_FileClose(&fpFile);
    return(1);
  }
  COM_FileClose(&fpFile);
  capture("");

  if (type)
  {
    sprintf(sTransmitline, "talkto %s", MCENAME);
    transmit(sTransmitline);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function determines the location of service shell running on the host and client workstation.
// Client install location is only required if the user is connected remotely.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_GetFileLocationsForHost(char *device, char *sFWType, char *connectionType, int *sendFileToHOST, char *LocalHostPath, char *RemoteHostPath)
{
  int status;
  int iTemp;
  int nVersion = 0;
  int nBuild = 0;
  int rc = 0;
  
  char sTransmitline[STR_LEN];
  char instring[STR_LEN];
  char outstring[STR_LEN];
  char tmp[STR_LEN];

  dialog("Install location check", 1, 1,
         "Checking for Service Shell install location...",CTEXT | 1);

  
  // not used anymore for this function but I left it in here.
  #ifndef WIN95
    COM_GetServiceHostVersion(sFWType, &nVersion, &nBuild);
  #endif

  if (COM_GetSSWorkingDirectory(LocalHostPath) == SUCCESS)
  {
    strcat(LocalHostPath, "Firmware\\");        
  }
  else
  {    
    rc = 0;

    while (rc < 11)
    {
      if (rc >= 0)
      {
        switch(rc)
        {
          case 3: strcpy(LocalHostPath, tmp);
                  break;
        }
        dialog("Backup Location?", 1, 1,
               "Please enter the desired directory to create backup files." , CTEXT | 1,
               "Example: C:\\ServiceShell\\firmware\\" , CTEXT | 1,
               "", CTEXT | 1,
               LocalHostPath, EDITBOX | 3,
               "Resume", BUTTON | 12, -1, -1, 100, 7, 
               "Quit", BUTTON | 13, -1, -1, 100, 7);
      }
      sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
      rc = dialog(tmp);
      if (rc == DIALOG_CLOSE)
      { 
        // user hit the x button in the corner of the dialog box
        COM_Done();
      }
    }
    // Erase the dialog box.
    dialog("");
       
    if (rc == 13)
    {
      ExitInError();
    }

    if (access(LocalHostPath, 0))
    {
      COM_Output("Unable to find directory!", SUSPEND_BOX, 0, LocalHostPath);
      ExitInError();
    }
    COM_CheckForBackslash(LocalHostPath, 1);
  }

  sprintf(sTransmitline, "Client file directory: %s", LocalHostPath);
  
  COM_Output(sTransmitline, INFORMATIVE, 0, "");

  if (strcmp(connectionType, "Remote") == 0)
  {
    
    // get path of Remote host directory
    sprintf(sTransmitline, "talkto %s", SSDIAG);
    transmit(sTransmitline);

    transmit ("svsh version info creodeviceserver.exe");
    if (waitreg("PATH=\"[^\"]*\"", instring, 3))
    {
      COM_Output("Install location not found!", INFORMATIVE, 0, "");
      COM_TestSendingAFile(1, sFWType, connectionType, sendFileToHOST, RemoteHostPath, LocalHostPath);
      sprintf(sTransmitline, "Remote Host File directory: %s", RemoteHostPath);
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
    }
    else
    {
      // get rid of the PATH=" at the beginning of the string
      strcpy(outstring, instring + strlen("PATH=\""));

      //get rid of the '\bin' at the end of the string
      outstring[strlen(outstring) - 5] = '\0';

      strcpy(RemoteHostPath, outstring);

      sprintf(sTransmitline, "Remote Host install directory: %s", RemoteHostPath);

      COM_Output(sTransmitline, INFORMATIVE, 0, "");

      strcat(RemoteHostPath, "\\Firmware\\");

      sprintf(sTransmitline, "Remote Host file directory: %s", RemoteHostPath);
      
      COM_Output(sTransmitline, INFORMATIVE, 0, "");     

    }
    sprintf(sTransmitline, "talkto %s", device);
    transmit(sTransmitline);

    COM_TestSendingAFile(0, sFWType, connectionType, sendFileToHOST, RemoteHostPath, LocalHostPath);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//This function either tests to see if a file can be sent to c d or e directories on the host computer if the host version is
//not found.  Or it tests sending a file to the host when the host install location is known.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_TestSendingAFile(int testDifferentFolders, char *sFWType, char *connectionType, int *sendFileToHOST, char *RemoteHostPath, char *LocalHostPath)
{
  char *testPath1 = "c:\\serviceshell\\Firmware\\";
  char *testPath2 = "d:\\serviceshell\\Firmware\\";
  char *testPath3 = "e:\\serviceshell\\Firmware\\";
  char sourcePath[STR_LEN];
  char correctPath[STR_LEN];
  char pathOnly[STR_LEN];
  char tmp[STR_LEN];
  char sTransmitline[STR_LEN];

  int rc = 0;
  int sendFileDirectory1 = FALSE;
  int sendFileDirectory2 = FALSE;
  int getFileDirectory = FALSE;
  int stillTest = TRUE;

  FILE *fpFile = NULL;               // file pointer
  
  strcpy(sourcePath, LocalHostPath);
  strcat(sourcePath, "testfile.txt");
  sprintf(sTransmitline, "Creating %s", sourcePath);
  COM_Output(sTransmitline, INFORMATIVE, 0,  "");
  COM_FileOpen(sourcePath, MODE_WRITE, &fpFile);

  if (fpFile != NULL)
  {
    fputs(sourcePath, fpFile);
    fputs("\n", fpFile);
    COM_FileClose(&fpFile);
  }
  COM_Output("Testing if a file can be sent...", INFORMATIVE, 0,  "");

  if (testDifferentFolders)
  {
    if ((COM_SendFileToHost(sourcePath, testPath1, 3, sFWType, connectionType, sendFileToHOST)) == 0)
    {                                             
      stillTest = TRUE;
    }
    else
    {
      strcpy(RemoteHostPath, testPath1);
      stillTest = FALSE;
    }
    if (stillTest == TRUE)
    {
      if ((COM_SendFileToHost(sourcePath, testPath2, 3, sFWType, connectionType, sendFileToHOST)) == 0)
      {
        stillTest = TRUE;
      }
      else
      {
        strcpy(RemoteHostPath, testPath2);
        stillTest = FALSE;
      }
      if (stillTest == TRUE)
      {
        if ((COM_SendFileToHost(sourcePath, testPath3, 3, sFWType, connectionType, sendFileToHOST)) == 0)
        {
          rc = 0;

          while (rc < 11)
          {
            if (rc >= 0)
            {
              switch(rc)
              {
                case 3: strcpy(RemoteHostPath, tmp);
                        break;
              }
              dialog("Location?", 1, 1,
                     "Please enter the desired location to send and retrieve files from on the HOST computer." , CTEXT | 1,
                     "", CTEXT | 2,
                     RemoteHostPath, EDITBOX | 3,
                     "Resume", BUTTON | 12, -1, -1, 100, 7, 
                     "Quit", BUTTON | 13, -1, -1, 100, 7);
            }
            sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
            rc = dialog(tmp);
            if (rc == DIALOG_CLOSE)
            { 
              // user hit the x button in the corner of the dialog box
              COM_Done();
            }
          }
          // Erase the dialog box.
          dialog("");
             
          if (rc == 13)
          {
            ExitInError();
          }
        }
        else
        {
          strcpy(RemoteHostPath, testPath3);
        }
      }
    }     
  }
  else
  {
    COM_SendFileToHost(sourcePath, RemoteHostPath, 0, sFWType, connectionType, sendFileToHOST);
  }

}  

//-------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function determines the version of service host running.
// This function is used for informational purposes only.  
// Currently nothing is this script depends on the version of service host it connects to.
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_TestForServiceHostVersion(char *device)
{
  int resume = FALSE;
  char sTransmitline[STR_LEN];
  char instring[STR_LEN];

  sprintf(sTransmitline, "talkto %s", SSDIAG);
  transmit(sTransmitline);
  transmit("svsh version info creodeviceserver.exe");

  if (waitfor("VERSION", 3))
  {            
    COM_Output("Service Host version cannot be found.", INFORMATIVE, 0, "");
  }
  else
  {
    resume = TRUE;
  }

  if (resume)
  {
    transmit("svsh version info creodeviceserver.exe");
    if (waitreg("VERSION=\"[^\"]*\"", instring, 3))
    {            
      sprintf(sTransmitline, "talkto %s", device);
      transmit(sTransmitline);
      COM_Output("Service Host version info format has changed.", INFORMATIVE, 0, "");
    }
    else
    {
      sprintf(sTransmitline, "talkto %s", device);
      transmit(sTransmitline);
      sprintf(sTransmitline, "Currently using Service Host %s", instring);
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
    }
  }
  else
  {
    sprintf(sTransmitline, "talkto %s", device);
    transmit(sTransmitline);
  }

}

//-------------------------------------------------------------------------------------------------------------------------------------------------------------
//  This function queries the host for registy information - 
//  this function is not very useful if you want registry info from the client machine and you are connected remotely
//  Remeber this function queries the host registry keys not registry keys of the client machine.
//
//  type should be either 'REG_SZ' or 'REG_DWORD'
//
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_GetRegistryValue(char *sDevice, 
                         char *sQueryReg,
                         char *sType,                          
                         char *sReturnValue)
{
  int nRC = SUCCESS; 
  char sTransmitline[STR_LEN];
  char sCaptureString[STR_LEN];
  char sParseString[STR_LEN];

  sprintf(sTransmitline, "talkto %s", SSDIAG);
  transmit(sTransmitline);

  sprintf(sTransmitline,"svsh registry query %s %s", sQueryReg, sType);
  
  transmit(sTransmitline);

  if (waitreg("VALUE=\"[^\"]*\"", sCaptureString, WAIT_TIME))
  {            
    sprintf(sTransmitline, "talkto %s", sDevice);
    transmit(sTransmitline);
    COM_Output("Registry value not found.", INFORMATIVE, 0, "");
    nRC = FAILURE; 
  }
  else
  {
    sprintf(sTransmitline, "talkto %s", sDevice);
    transmit(sTransmitline);
    strcpy(sParseString, sCaptureString + strlen("VALUE=\""));
    sParseString[strlen(sParseString) - 1] = '\0';
    sprintf(sTransmitline, "Registry value found \"%s\"", sParseString);
    COM_Output(sTransmitline, INFORMATIVE, 0, "");
    strcpy(sReturnValue, sParseString);
  }

  return nRC;
}

//-------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function determines the version of service host running.
// This function is used for informational purposes only.  
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_GetServiceHostVersion(char *sDevice, int *nVersion, int *nBuild)
{
  int resume = FALSE;
  int num = 0;
  int nOffset = 0;
  int nCount = 0;

  char sTransmitline[STR_LEN];
  char instring[STR_LEN];
  char outstring[STR_LEN];
  char sTemp[STR_LEN];

  sprintf(sTransmitline, "talkto %s", SSDIAG);
  transmit(sTransmitline);
  transmit("svsh version info creodeviceserver.exe");

  if (waitfor("VERSION", 3))
  {            
    COM_Output("Service Host version cannot be found.", INFORMATIVE, 0, "");
  }
  else
  {
    resume = TRUE;
  }

  if (resume)
  {
    transmit("svsh version info creodeviceserver.exe");
    if (waitreg("VERSION=\"[^\"]*\"", instring, 3))
    {            
      sprintf(sTransmitline, "talkto %s", sDevice);
      transmit(sTransmitline);
      COM_Output("Service Host version info format has changed.", INFORMATIVE, 0, "");
    }
    else
    {
      sprintf(sTransmitline, "talkto %s", sDevice);
      transmit(sTransmitline);
      sprintf(sTransmitline, "Currently using Service Host %s", instring);
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
    }
    strcpy(outstring, instring + strlen("VERSION=\""));
    outstring[strlen(outstring) - 1] = '\0';
    strncpy(sTemp, outstring, 5);
    COM_RemoveCharacterFromString(sTemp, '.');
    *nVersion = atoi(sTemp);

    nCount = 12;
    nOffset = 0;
    while (isdigit(outstring[nCount]))
    {
      sTemp[nOffset] = outstring[nCount];
      nOffset++;
      nCount++;
    }
    sTemp[nOffset] = '\0';

    *nBuild = atoi(sTemp);

    sprintf(sTransmitline, "Service Host Version is: %i", *nVersion);
    COM_Output(sTransmitline, INFORMATIVE, 0, "");
    sprintf(sTransmitline, "Service Host Build Version is: %i", *nBuild);
    COM_Output(sTransmitline, INFORMATIVE, 0, "");
    return(1);
  }
  else
  {
    sprintf(sTransmitline, "talkto %s", sDevice);
    transmit(sTransmitline);
  }
  return(0);
}

//-------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function determines the version of service Shell Client running on the host machine

//-------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_GetServiceShellClientVersionOnHostMachine(char *sDevice, int *nVersion, int *nBuild)
{
  int resume = FALSE;
  int num = 0;
  int nOffset = 0;
  int nCount = 0;

  char sTransmitline[STR_LEN];
  char instring[STR_LEN];
  char outstring[STR_LEN];
  char sTemp[STR_LEN];

  sprintf(sTransmitline, "talkto %s", SSDIAG);
  transmit(sTransmitline);
  transmit("svsh version info service.exe");

  if (waitfor("VERSION", 3))
  {            
    COM_Output("Service Shell Client version cannot be found on the host machine.", INFORMATIVE, 0, "");
  }
  else
  {
    resume = TRUE;
  }

  if (resume)
  {
    transmit("svsh version info service.exe");
    if (waitreg("VERSION=\"[^\"]*\"", instring, 3))
    {            
      sprintf(sTransmitline, "talkto %s", sDevice);
      transmit(sTransmitline);
      COM_Output("Service Shell Client version info format has changed.", INFORMATIVE, 0, "");
    }
    else
    {
      sprintf(sTransmitline, "talkto %s", sDevice);
      transmit(sTransmitline);
      sprintf(sTransmitline, "Service Shell Client %s is installed on the host machine", instring);
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
    }
    strcpy(outstring, instring + strlen("VERSION=\""));
    outstring[strlen(outstring) - 1] = '\0';
    strncpy(sTemp, outstring, 5);
    COM_RemoveCharacterFromString(sTemp, '.');
    *nVersion = atoi(sTemp);

    nCount = 12;
    nOffset = 0;
    while (isdigit(outstring[nCount]))
    {
      sTemp[nOffset] = outstring[nCount];
      nOffset++;
      nCount++;
    }
    sTemp[nOffset] = '\0';

    *nBuild = atoi(sTemp);

    sprintf(sTransmitline, "Service Shell Client Version is: %i", *nVersion);
    COM_Output(sTransmitline, INFORMATIVE, 0, "");
    sprintf(sTransmitline, "Service Shell Client Build Version is: %i", *nBuild);
    COM_Output(sTransmitline, INFORMATIVE, 0, "");
    return(1);
  }
  else
  {
    sprintf(sTransmitline, "talkto %s", sDevice);
    transmit(sTransmitline);
  }
  return(0);
}


//------------------------------------------------------------------------------------------------------------------------------------------------------------
//Retrieves device info
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_GetDeviceInfo(char *deviceType, char *sFWType, float *upgradeVersion, int *baseTrendsetterMPE, int dualMCE, int noCodeOnBoard, float *FWversion, 
                       char *MCEFWversion, char *MCE2FWversion, int *headType, float *fMCEFWVersion)
{
  COM_GetFWType(sFWType);
  COM_GetHeadType(sFWType, headType);
  COM_GetDeviceType(deviceType, sFWType, *baseTrendsetterMPE, noCodeOnBoard);
  COM_GetFirmwareVersion(deviceType, sFWType, upgradeVersion, baseTrendsetterMPE, dualMCE, noCodeOnBoard, FWversion, MCEFWversion, MCE2FWversion);
  COM_ConvertFWVersionToFloat(MCEFWversion, fMCEFWVersion);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Finds the connection type to determine what options are available for the user.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_GetConnectionType(char *sConnectionType)
{
  int connection = 0;

  connection = ConnectionType();
  
  if (connection == 0)
  {
    COM_Output("Connection Type: Not Connected", INFORMATIVE, 0,  "");
    strcpy(sConnectionType, NOT_CONNECTED);
  }
  if (connection == 1)
  {
    COM_Output("Connection Type: Local Connection", INFORMATIVE, 0,  "");
    strcpy(sConnectionType, LOCAL_CONNECTION);
  }
  if (connection == 2)
  {
    COM_Output("Connection Type: Remote Connection", INFORMATIVE, 0,  "");
    strcpy(sConnectionType, REMOTE_CONNECTION);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//Gets the FW type either MPE, MCE or GMCE
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_GetFWType(char *sFWType)
{
  char sTransmitline[STR_LEN];

  transmit("talkto srvshell");
  transmit("svsh devinfo query mce");
  if (waitfor("NAME=MCE", 2))
  {
    transmit("svsh devinfo query mpe");
    if (waitfor("NAME=MPE", 2))
    {
      transmit("svsh devinfo query gmce");
      if (waitfor("NAME=GMCE", 2))
      {
        COM_Output("The script is unable to determine the type of device connected to service shell!", 
                   SUSPEND_BOX, 
                   0, 
                   "MPE, MCE or GMCE????");

        ExitInError();
      }
      else
      {
        strcpy(sFWType, GMCENAME);
        sprintf(sTransmitline, "talkto %s", GMCENAME);
        transmit(sTransmitline); 
      }
    }
    else
    {
      strcpy(sFWType, "MPE");
      sprintf(sTransmitline, "talkto %s", MPENAME);
      transmit(sTransmitline);  
    }
  }
  else
  {
    strcpy(sFWType, "MCE");
    sprintf(sTransmitline, "talkto %s", MCENAME);
    transmit(sTransmitline);
    
  }
  sprintf(sTransmitline, "Firmware Type is: %s", sFWType);
  COM_Output(sTransmitline, INFORMATIVE, 0, ""); 
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function finds the device firmware version and assigns it to previous.
//
// For MPE:
//
// Previous is used in generating a file name & in NVSUpgradeLogToFileMPE.
//
// Also checks to see if a 'a' of 'b' exists at the end of the version number.
// TS 3244 have both a and b versions of firmware.  
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_GetFirmwareVersion(char *sDeviceType, char *sFWType, float *fUpgradeVersion, int *nBaseTrendsetterMPE, int nDualMCE, int nNoCodeOnBoard, float *fFWversion,
                            char *sMCEFWversion, char *sMCE2FWversion)  
{
  int nLen;
  int skip = 0;
  int nTempInt = 0;
  int nCount = 0;

  float fTempFloat = 0;
  
  char cStringEnd;
  char sTmp[STR_LEN];
  char sRawMCEFirmwareVersion[STR_LEN];
  char sTransmitline[STR_LEN];
  char sParmRetValue[STR_LEN];
  
  if (strcmp(sFWType, "MPE") == 0)
  {
    if (nNoCodeOnBoard == FALSE)
    {
      if (COM_GetParm("list version", "MPE Firmware Version", sParmRetValue, PARM_STRING, 15, 1) != SUCCESS)
      {
        COM_Output("WARNING: Timeout waiting for list version, to display firmware version number.", INFORMATIVE, 0, "");
        COM_Output("Device may not have a current 'firmware version' structure.", INFORMATIVE, 0, "");
        COM_Output("A format like 1.10 or 2.52b accepted.", INFORMATIVE, 0, "");
        COM_Output("Format like 1.6b not accepted.", INFORMATIVE, 0, "");
        COM_Output("Assigning 0.00 to the files firmware version.", INFORMATIVE, 0, "");
        skip = 1;
      }

      if (skip == 0)
      {// Autoloader takes a little longer to complete the list version.  (Genine & PDB boards)
        nLen = strlen(sParmRetValue);
        cStringEnd = sParmRetValue[nLen - 1];
        if (isalpha(cStringEnd))
        {
          if (cStringEnd == 'a')
          {
            *nBaseTrendsetterMPE = 1;
            COM_Output("Base Trendsetter 3244 A Firmware", INFORMATIVE, 0, "");
          }
          if (cStringEnd == 'b')
          {
            *nBaseTrendsetterMPE = 2;
            COM_Output("Base Trendsetter 3244 B Firmware", INFORMATIVE, 0, "");
          }
          sParmRetValue[strlen(sParmRetValue) - 1] = '\0';
        }
        *fFWversion = atof(sParmRetValue);
        if (strcmp(sDeviceType, "TVAL") == 0 && *fFWversion < 3.00)
        {
          printf("Waiting for list version to complete...");
          waitfor("list version to complete", 22);
        }
        else
        {
          waitfor("list version to complete", 3);
        }
        if (*fUpgradeVersion == 0.00)
        {
          *fUpgradeVersion = *fFWversion;
        }
      }
      else
      {
        *fFWversion = 0.00;
      }
      
      sprintf(sTransmitline, "Firmware Version is: %3.2f", *fFWversion);
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
      sleep(5000);
    }
  }

  if (strcmp(sFWType, MCENAME) == 0 || strcmp(sFWType, GMCENAME) == 0)
  {
    COM_GetMCEFirmwareVersion(sMCEFWversion, nNoCodeOnBoard);
    sprintf(sTransmitline, "MCE Firmware Version is: %s", sMCEFWversion);
    COM_Output(sTransmitline, INFORMATIVE, 0, "");
        
    if (nDualMCE)
    {      
      sprintf(sTransmitline, "talkto %s", MCE2NAME);
      transmit(sTransmitline);
     
      COM_GetMCEFirmwareVersion(sMCE2FWversion, nNoCodeOnBoard);
     
      sprintf(sTransmitline, "talkto %s", MCENAME);
      transmit(sTransmitline);

      sprintf(sTransmitline, "MCE2 Firmware Version is: %s", sMCE2FWversion);
      COM_Output(sTransmitline, INFORMATIVE, 0, "");      
    }    
  }
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------
//  Description:
//       this function retrieves the firmware version and formats the version like so:
//       
//  Device output: 1.23.11
//  Function output if found: 123-11
//
//  Input:
//       sFirmwareVersion - the firmware version found
//  Output:
//       sFirmwareVersion - the firmware version found
//  Return:
//       FAILURE if waitreg statement fails
//       SUCCESS if waitreg statement succeeds
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_GetMCEFirmwareVersion(char *sFirmwareVersion, int nNoCodeOnBoard)
{
  int nRC = SUCCESS;
  int nTempInt = 0;
  int nCount = 0;

  float fTempFloat = 0;
   
  char sBuild[STR_LEN];
  char sReturnString[STR_LEN];
  char sTemp[STR_LEN];
  char sVersion[STR_LEN];
  char sRawMCEFirmwareVersion[STR_LEN];
  char sVersionMain[STR_LEN];

  if (nNoCodeOnBoard == FALSE)
  {
    transmit("list version");
    if (waitreg("Version: *[0-9]\\.[0-9][0-9]\\.[0-9][0-9]*[^0-9]", sReturnString, 3))
    {
      waitfor("Command Complete", WAIT_TIME);
      COM_Output("Firmware version not found!", INFORMATIVE, 0,  "");
      strcpy(sVersion, "000-00");
      nRC = FAILURE;
    }
    else
    {
      waitfor("Command Complete", WAIT_TIME);
      // get rid of trailing white space or characters    
      for (nCount = strlen(sReturnString); nCount != 0; nCount--)
      {
        if(isdigit(sReturnString[nCount]))
        {
          break;
        }
        else
        {
          sReturnString[nCount] = '\0';
        }

      }

      // wanting to take the input example 1.06.03 make it like 106-03
      strcpy(sRawMCEFirmwareVersion, sReturnString + strlen("Version: "));
      strcpy (sTemp, sRawMCEFirmwareVersion);
      fTempFloat = atof(sTemp);
      fTempFloat = fTempFloat * 100;
      nTempInt = (int)(fTempFloat + 0.5);
      sprintf(sVersionMain, "%i", nTempInt);


      strcpy(sBuild, sRawMCEFirmwareVersion + 5);

      strcpy(sVersion, sVersionMain);
      strcat(sVersion, "-");
      strcat(sVersion, sBuild);
    }
  }
  else
  {   
    strcpy(sVersion, "000-00");  
  }

  strcpy(sFirmwareVersion, sVersion);
  return(nRC);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function finds the device's current head firmware version.
// If a firmware version is not found the function returns a version of 0.00
//
// nTargetMCE - the mce/mpe board to find code version on
// sFWType - board type mpe or mce
// fHeadFWversion - the head firmware version
// nHeadType - the type of head TH17, TFX, TH2, TH3
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_GetHeadFWVersion(int nTargetMCE, char *sFWType, float *fHeadFWversion, int nHeadType)
{
  int len;
  int nVerInfoNotFound = FALSE;

  char tmp[STR_LEN];
  char sTransmitline[STR_LEN];
  char sReturnStr[STR_LEN];

  if (nTargetMCE == MCE)
  {
    if (strcmp(sFWType, "MPE") == 0)
    {
      if (nHeadType == TH10 || nHeadType == TH17) 
      {
        transmit("head version");
        if (waitreg("PHC software version: [0-9]+\\.[0-9][0-9]", tmp, 8))
        {
          nVerInfoNotFound = TRUE;
        }
        else
        {        
          *fHeadFWversion = atof(tmp + strlen("PHC software version: "));
        }
        waitfor("LVD LCA version", WAIT_TIME);      
      }

      if (nHeadType == TH2)
      {
        transmit("head");
        if (waitreg("version: *[0-9]\\.[0-9][0-9]", tmp, 8))
        {
          nVerInfoNotFound = TRUE;
        }
        else
        {
          *fHeadFWversion = atof(tmp + strlen("version: "));
        }
        waitfor("Nothing", 5);        
      }
      if (nHeadType == TFX)
      {

        transmit("redirect pass");
        waitfor("Complete", WAIT_TIME);
        if (COM_GetNumericParm("th2 \"ver\"", "Firmware:", sReturnStr, WAIT_TIME, 2) == FAILURE)
        {
          nVerInfoNotFound = TRUE;
        }
        else
        { 
          *fHeadFWversion = atof(sReturnStr);
          transmit("redirect disable");
          waitfor("Complete", WAIT_TIME);
        }
        waitfor("Nothing", 5);
      }
    }

    if (strcmp(sFWType, "MCE") == 0)
    {
      if (nHeadType == TFX || nHeadType == TH2)
      {
        transmit("head version");
        if (waitreg("PHC software version: [0-9]+\\.[0-9][0-9]", tmp, 8))
        {
          nVerInfoNotFound = TRUE;
        }
        else
        {        
          *fHeadFWversion = atof(tmp + strlen("PHC software version: "));
        }
        waitfor("Command Complete", WAIT_TIME);       
      }
      
      if (nHeadType == TH10 || nHeadType == TH17)
      {
        transmit("head version");
        if (waitreg("PHC software version: [0-9]+\\.[0-9][0-9]", tmp, 8))
        {
          nVerInfoNotFound = TRUE;
        }
        else
        {        
          *fHeadFWversion = atof(tmp + strlen("PHC software version: "));
        }
        waitfor("Command Complete", WAIT_TIME);
      }
    }

    if (nVerInfoNotFound == TRUE)
    {
      COM_Output("WARNING: Timeout waiting for head,", INFORMATIVE, 0, "");
      COM_Output("to display head firmware version number.", INFORMATIVE, 0, "");
      COM_Output("Assigning 0.00 to the head version number.", INFORMATIVE, 0, "");
      *fHeadFWversion = 0.00;
    }    

    printf("Head Firmware Version is: %3.2f", *fHeadFWversion);
    sprintf(sTransmitline, ";Head Firmware Version is: %3.2f", *fHeadFWversion);
    transmit(sTransmitline);
  }

  if (nTargetMCE == MCE2)
  {
    sprintf(sTransmitline, "talkto %s", MCE2NAME);
    transmit(sTransmitline);

    if (nHeadType == TFX || nHeadType == TH2)
    {
      transmit("head version");
      if (waitreg("version: *[0-9]\\.[0-9][0-9]", tmp, 8))
      {
        nVerInfoNotFound = TRUE;
      }
      if (nVerInfoNotFound == 0)
      {
        *fHeadFWversion = atof(tmp + strlen("version: "));
      }
      waitfor("Command Complete", WAIT_TIME);      
    }
    if (nHeadType == TH10 || nHeadType == TH17)
    {
      transmit("head version");
      if (waitreg("PHC software version: [0-9]+\\.[0-9][0-9]", tmp, 8))
      {
        nVerInfoNotFound = TRUE;
      }
      else
      {        
        *fHeadFWversion = atof(tmp + strlen("PHC software version: "));
      }
      waitfor("Command Complete", WAIT_TIME);      
    }

    if (nVerInfoNotFound == TRUE)
    {
      COM_Output("WARNING: Timeout waiting for head,", INFORMATIVE, 0, "");
      COM_Output("to display head firmware version number.", INFORMATIVE, 0, "");
      COM_Output("Assigning 0.00 to the MCE2 head version number.", INFORMATIVE, 0, "");
      *fHeadFWversion = 0.00;
    }
      
    printf("MCE2 Head Firmware Version is: %3.2f", *fHeadFWversion);
    sprintf(sTransmitline, ";MCE2 Head Firmware Version is: %3.2f", *fHeadFWversion);
    transmit(sTransmitline);
    sprintf(sTransmitline, "talkto %s", MCENAME);
    transmit(sTransmitline);
  }
}


//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function finds the device's current head firmware version.
// 
// nTargetMCE - specifies MPE MCE or MCE2
// 
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_GetHeadInterfaceVersion(int nTargetMCE, char *sFWType, float *fHeadInterfaceVersion, int headType, char *deviceType)
{
  int len;
  int nVersionFound = TRUE;

  char matchstr[STR_LEN];
  char sTransmitline[STR_LEN];

  if (nTargetMCE == MPE)
  {
    if (strcmp(sFWType, "MPE") == 0)
    {
      if (headType < 2) 
      {
        transmit("list version");
        if (waitreg("Thermal software version: *[0-9]\\.[0-9]+[ \r]", matchstr, 8))
        {
          COM_Output("Unable to determine Thermal software version!", INFORMATIVE, 0, "");
          COM_Output("Assigning 0.00 to head software version number.", INFORMATIVE, 0, "");
          nVersionFound = FALSE;
        }
        if (nVersionFound == TRUE)
        {
          *fHeadInterfaceVersion = atof(matchstr + strlen("Thermal software version: "));
        }
        else
        {
          *fHeadInterfaceVersion = 0.00;
        }
        sprintf(sTransmitline, "Thermal software version found is: %3.2f", *fHeadInterfaceVersion);
        COM_Output(sTransmitline, INFORMATIVE, 0, "");
        if (strcmp(deviceType, "TVAL") == 0)
        {
          printf("Waiting for list version to complete...");
          waitfor("list version to complete", 22);
        }
        else
        {
          waitfor("list version to complete", 3);
        }
      }
      if (headType > 2) 
      {
        printf("Not implemented!");     
      }
    }
    if (strcmp(sFWType, "MCE") == 0)
    {
      // set access level
      if (COM_Output("access dev", TERMINAL, WAIT_TIME, "Command Complete"))
      {
        nVersionFound = FALSE;
      }

      transmit("list version version");
      if (waitreg("EHI Version [0-9]+\\.[0-9]+ ", matchstr, 10))
      {
        COM_Output("Unable to determine EHI Version!", INFORMATIVE, 0, "");
        COM_Output("Assigning 0.00 to the EHI version number.", INFORMATIVE, 0, "");
        nVersionFound = TRUE;
      }
      waitfor("Command Complete", WAIT_TIME);
      if (nVersionFound == TRUE)
      {
        *fHeadInterfaceVersion = atof(matchstr + strlen("EHI Version "));
      }
      else
      {
        *fHeadInterfaceVersion = 0.00;
      }
      sprintf(sTransmitline, "EHI version found is: %3.2f", *fHeadInterfaceVersion);
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
      waitfor("Command Complete", WAIT_TIME);
    }
  }
  if (nTargetMCE == MCE2)
  {
    printf("Not implemented!");
  }
  return(nVersionFound);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function finds the device's current head type.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_GetHeadType(char *sFWType, int *nHeadType)
{
  int noTypeFound = FALSE;
  int EHINotFound = FALSE;

  char matchstr[STR_LEN];
  char sTransmitline[STR_LEN];
  char sHeadTypeName [STR_LEN];

  dialog("Head Type", 1, 1,
         "Checking for head type...",CTEXT | 1);

  if (strcmp(sFWType, "MPE") == 0)
  {
    transmit("set head type");
    if (waitreg("type = [0-9]", matchstr, 5))
    {
      COM_Output("WARNING: Timeout waiting for set head type,", INFORMATIVE, 0, "");
      COM_Output("to display head type.", INFORMATIVE, 0, "");
      COM_Output("Assigning 1 to head type.", INFORMATIVE, 0, "");
      *nHeadType = 1;
      noTypeFound = TRUE;
    }
    if (noTypeFound == TRUE)
    {
      *nHeadType = 1;
    }
    else
    {
      *nHeadType = atoi(matchstr + strlen("type = "));
      waitfor("Range: ", WAIT_TIME);
    }
  }

  if (strcmp(sFWType, MCENAME) == 0 || strcmp(sFWType, GMCENAME) == 0)
  {
    transmit("set hmgr type");
    if (waitreg("ype            [0-9]", matchstr, 5)) 
    {
      transmit("set head type");  // the need for this step should become obsolete soon...
      if (waitreg("type = [0-9]", matchstr, 5)) 
      {
        COM_Output("WARNING: Timeout waiting for set head type,", INFORMATIVE, 0, "");
        COM_Output("to display head type.", INFORMATIVE, 0, "");
        COM_Output("Assigning 1 to head type.", INFORMATIVE, 0, "");
        //assign 1 because then they have the chance to load two pieces of code rather than two.  More options that way.
        noTypeFound = TRUE;
      }
      else
      {
        EHINotFound = TRUE;
      }
    }
    if (noTypeFound == TRUE)
    {
      *nHeadType = 1;
    }
    else if (EHINotFound == TRUE)
    {
      *nHeadType = atoi(matchstr + strlen("type = "));
    }
    else
    {
      *nHeadType = atoi(matchstr + strlen("ype            "));
    }
    waitfor("Command Complete", WAIT_TIME);
  }
  sprintf(sTransmitline, "Head type parameter is: %i", *nHeadType);
  COM_Output(sTransmitline, INFORMATIVE, 0, "");

  switch(*nHeadType)
  {
      case TH10:
          strcpy(sHeadTypeName, "Thermal 1.0");
          break;
      case TH17:
          strcpy(sHeadTypeName, "Thermal 1.7");        
          break;
      case TFX:
          strcpy(sHeadTypeName, "Thermal TFX");        
          break;
      case TH2:
          strcpy(sHeadTypeName, "Thermal 2.0");        
          break;
      case TH3:                 
          strcpy(sHeadTypeName, "Thermal 3.0");        
          break;
      default:
          strcpy(sHeadTypeName, "Unknown?");        
          break;
  }
  sprintf(sTransmitline, "Head type is: %s", sHeadTypeName);
  COM_Output(sTransmitline, INFORMATIVE, 0, "");
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function finds the head serial number.
// Supports TH1.7 TFX & TH2 heads.  
// I have not tested if TFX heads serial number recovery works yet.  This function is never called for TFX heads.
// nTargetMCE = 1 => MCE or MPE
// nTargetMCE = 2 => MCE2
//
// returns 1 in failure
// returns 0 if successful
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_GetHeadSerialNumber(int nTargetMCE, char *sFWType, char *sHeadSerialNumber, int nHeadType)
{
  int nHeadSNFound = FALSE;
  int nEHINotFound = FALSE;
  
  char sTransmitline[STR_LEN];
  char instring[STR_LEN];
  char outstring[STR_LEN];
  char sWaitRegStatement[STR_LEN];

  if (nTargetMCE == 1)
  {
    if (nHeadType == TH10 || nHeadType == TH17) 
    {
      sprintf(sWaitRegStatement, "sn              %s", NUMERIC_VALUE);      
      transmit("set head sn");      
      if (strcmp(sFWType, "MCE") == 0)
      {                                                  
        if (waitreg(sWaitRegStatement, instring, WAIT_TIME)) 
        {
          nEHINotFound = TRUE;
          transmit("set head sn");
        }
        else
        {          
          waitfor("Command Complete", WAIT_TIME);
          strcpy(outstring, instring + strlen("sn              "));         
          strcpy(sHeadSerialNumber, outstring);
          sHeadSerialNumber[strlen(sHeadSerialNumber) - 1] = '\0';
          nHeadSNFound = TRUE;
        }
        if (nEHINotFound == TRUE)
        {
          if (waitreg("serial_number = [0-9]*[^0-9]", instring, WAIT_TIME) == 0) 
          {                   
            waitfor("Command Complete", WAIT_TIME);
            strcpy(outstring, instring + strlen("serial_number = "));
            strcpy(sHeadSerialNumber, outstring); 
            sHeadSerialNumber[strlen(sHeadSerialNumber) - 1] = '\0';
            nHeadSNFound = TRUE; 
          }
        }
      }

      if (strcmp(sFWType, "MPE") == 0)
      {
        if (waitreg("= [0-9]* MPE", instring, 8) == 0) 
        {
          strcpy(outstring, instring + strlen("= "));  
          strcpy(sHeadSerialNumber, outstring); 
          sHeadSerialNumber[strlen(sHeadSerialNumber) - 4] = '\0';
          nHeadSNFound = TRUE;
        }
      }
    }
    if (nHeadType == TH2 || nHeadType == TFX) 
    {
      if (strcmp(sFWType, "MPE") == 0)
      {
        if (COM_Output("redirect pass", TERMINAL, 5, "Complete"))
        {
          return(1);
        }
      }
      transmit("th2 \"ver\""); // first th2 "" command does not always work
      waitfor("Success", 5);
      transmit("th2 \"set sys serialnumber\"");
      if (strcmp(sFWType, MCENAME) == 0 || strcmp(sFWType, GMCENAME) == 0)
      {                                             
        if (waitreg("serialnumber           \"[A-Za-z0-9_ ]+\"", instring, 8) == 0) 
        {
          strcpy(outstring, instring + strlen("serialnumber           \""));  
          strcpy(sHeadSerialNumber, outstring); 
          sHeadSerialNumber[strlen(sHeadSerialNumber) - 1] = '\0';   
          nHeadSNFound = TRUE;
        }
      }

      if (strcmp(sFWType, "MPE") == 0)
      {                                               
        if (waitreg("serialnumber           \"[A-Za-z0-9_ ]+\"", instring, 8) == 0) 
        {
          strcpy(outstring, instring + strlen("serialnumber           \""));  
          strcpy(sHeadSerialNumber, outstring); 
          sHeadSerialNumber[strlen(sHeadSerialNumber) - 1] = '\0';   
          nHeadSNFound = TRUE;
        }
      }
      if (nHeadSNFound == TRUE && nHeadType == TFX)
      {
        // head will get direct communication back important for TFX heads
        transmit("redirect disable");
        waitfor("Command Success", WAIT_TIME);
      }
    }

    if (nHeadSNFound == FALSE)
    {
      COM_Output("WARNING: Timeout waiting for head serial number.", INFORMATIVE, 0, "");
      COM_Output("Assigning 0000 to head serialnumber.", INFORMATIVE, 0, "");
      strcpy(sHeadSerialNumber, "0000");
    }
    else
    {
      COM_ReplaceSpace(sHeadSerialNumber);
      sprintf(sTransmitline, "Head serial number is: %s", sHeadSerialNumber);
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
    }
  }
  if (nTargetMCE == 2)
  {
    nHeadSNFound = FALSE;
    nEHINotFound = FALSE;
    sprintf(sTransmitline, "talkto %s", MCE2NAME);
    transmit(sTransmitline);
    if (nHeadType == TH17 || nHeadType == TH10) 
    {
      // not a current configuration
      COM_Output("Not a current configuration", INFORMATIVE, 0, "");
    }
    if (nHeadType == TH2) 
    {
      transmit("th2 \"ver\""); // first th2 "" command does not always work
      waitfor("Success", 5);
      transmit("th2 \"set sys serialnumber\"");
      if (strcmp(sFWType, "MCE") == 0)
      {                                             
        if (waitreg("serialnumber           \"[A-Za-z0-9_ ]+\"", instring, 8) == 0) 
        {
          strcpy(outstring, instring + strlen("serialnumber           \""));  
          strcpy(sHeadSerialNumber, outstring); 
          sHeadSerialNumber[strlen(sHeadSerialNumber) - 1] = '\0';   
          nHeadSNFound = TRUE;
        }
      }

      if (strcmp(sFWType, "MPE") == 0)
      {                                               
        if (waitreg("serialnumber           \"[A-Za-z0-9_ ]+\"", instring, 8) == 0) 
        {
          strcpy(outstring, instring + strlen("serialnumber           \""));  
          strcpy(sHeadSerialNumber, outstring); 
          sHeadSerialNumber[strlen(sHeadSerialNumber) - 1] = '\0';   
          nHeadSNFound = TRUE;
        }
      }
    }
    if (nHeadSNFound == FALSE)
    {
      COM_Output("WARNING: Timeout waiting for MCE2 head serial number.", INFORMATIVE, 0, "");
      COM_Output("Assigning 0000 to MCE2 head serialnumber.", INFORMATIVE, 0, "");
      strcpy(sHeadSerialNumber, "0000");
    }
    else
    {
      COM_ReplaceSpace(sHeadSerialNumber);
      sprintf(sTransmitline, "MCE2 Head serial number is: %s", sHeadSerialNumber);
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
    }
    sprintf(sTransmitline, "talkto %s", MCENAME);
    transmit(sTransmitline);
  }
  return(0);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//  Description:
//       Finds the model type configured in the firmware. 
//
//  Input:
//       nDeviceTypeID   - Model type definition ID - currently not used 
//       sDeviceTypeName - Model type found in the firmware
//       sFWType         - MPE, MCE, MCE2
//
//  Output:
//       None
//
//  Return:
//       SUCCESS if the model type found.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_GetModelType(int *nModelTypeID, char *sModelTypeName, char *sFWType)
{
  char sCommand[STR_LEN];
  char sParmName[STR_LEN];
  char sParmRetValue[STR_LEN];
  char sTransmitline[STR_LEN];
  int nRC = SUCCESS;    // Function return code

  if (strcmp(sFWType, MPENAME) == 0)
  {
    waitfor("Nothing", 1);
    strcpy(sCommand, "set config");
    strcpy(sParmName, "machtype");
    nRC = COM_GetParm(sCommand, sParmName, sParmRetValue, PARM_STRING, WAIT_TIME, 1);
    
    if (nRC != SUCCESS)
    {
      strcpy(sModelTypeName, UNKNOWN_MODEL);
    }
    else
    {
      strcpy(sModelTypeName, sParmRetValue);
      waitfor("Nothing", 1);
    }
  }
  if (strcmp(sFWType, MCENAME) == 0)
  {
    // not implemented
  }

  sprintf(sTransmitline, "The model type configured in the firmware is: %s", sModelTypeName);
  COM_Output(sTransmitline, INFORMATIVE, 0, ""); 

  return(nRC);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//  Description:
//       Finds the device type configured in service host.
//
//  Input:
//       nDeviceTypeID   - Device type definition ID - Print Console compatible 
//       sDeviceTypeName - Device type full name
//       sFWType         - MPE, MCE, MCE2
//
//  Output:
//       None
//
//  Return:
//       SUCCESS if the devicetype found.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_GetDeviceTypeConfiguredInHost(int *nDeviceTypeID, char *sDeviceTypeName, char *sFWType)
{
  int nRC = SUCCESS;    // Function return code
  int nVersion = 0;
  int nBuild = 0;          
  int nCount = 0;
  int nWarnUserToChangeHostName = FALSE;

  char sRetStr[STR_LEN];
  char sModelType[STR_LEN];
  char sTransmitline[STR_LEN];
  char *psStringFound;
  char *psStringStart;
  
  COM_GetServiceHostVersion(sFWType, &nVersion, &nBuild);

  if (nVersion >= 251)
  {
    sprintf(sTransmitline, "talkto %s", SSDIAG);
    transmit(sTransmitline);

    nRC = COM_GetParm("svsh devmodel query", "MODEL=", sRetStr, PARM_ANYCHAR_TO_EOL, WAIT_TIME, 1);
    if (nRC != SUCCESS)
    {
      return(nRC);
    }
    strcpy(sModelType, sRetStr);
    psStringFound = sModelType;
    psStringFound = strstr(sModelType, "HEAD=");
    psStringStart = sModelType;

    while(psStringFound != psStringStart)
    {
      psStringStart++;
      nCount++;
    }

    sModelType[nCount-1] = '\0';
    sprintf(sTransmitline, "Model type configured in Service Host is: %s", sModelType);
    COM_Output(sTransmitline, INFORMATIVE, 0, ""); 
       
    // mpe devices
    if (strcmp(sModelType, "Platesetter 3244") == 0)
      *nDeviceTypeID = PS;
    else if (strcmp(sModelType, "Trendsetter 400") == 0)
      *nDeviceTypeID = TS; 
    else if (strcmp(sModelType, "Trendsetter 800") == 0)
      *nDeviceTypeID = TS; 
    else if (strcmp(sModelType, "VLF Platesetter") == 0)
      *nDeviceTypeID = VLFPS; 
    else if (strcmp(sModelType, "Trendsetter VLF") == 0)
      *nDeviceTypeID =  VLFTS; 
    else if (strcmp(sModelType, "Trendsetter 400 AL") == 0)
      *nDeviceTypeID = TSAL; 
    else if (strcmp(sModelType, "Trendsetter 800 AL") == 0)
      *nDeviceTypeID = TSAL; 
    else if (strcmp(sModelType, "Trendsetter VLF AL") == 0)
      *nDeviceTypeID = VLFTSAL; 
    else if (strcmp(sModelType, "Trendsetter News") == 0)
      *nDeviceTypeID = TS2637; 
    else if (strcmp(sModelType, "Trendsetter 400 Spectrum") == 0)
      *nDeviceTypeID = TSSPEC; 
    else if (strcmp(sModelType, "Trendsetter 800 Spectrum") == 0)
      *nDeviceTypeID = TSSPEC; 
    else if (strcmp(sModelType, "Proofsetter Spectrum") == 0)
      *nDeviceTypeID = SPEC; 
    else if (strcmp(sModelType, "ThermoFlex") == 0)
      *nDeviceTypeID = FLEXO; 

    // mce devices
    // old names
    else if (strcmp(sModelType, "Trendsetter II 400") == 0)
    {
      *nDeviceTypeID = TS_II; 
      strcpy(sModelType, "Trendsetter 400 II");
      nWarnUserToChangeHostName = TRUE;      
    }
    else if (strcmp(sModelType, "Trendsetter II 800") == 0)
    {
      *nDeviceTypeID = TS_II; 
      strcpy(sModelType, "Trendsetter 800 II");     
      nWarnUserToChangeHostName = TRUE;
    }
    else if (strcmp(sModelType, "Trendsetter II 400 Spectrum") == 0)
    {
      *nDeviceTypeID = TS_II_SPEC; 
      strcpy(sModelType, "Trendsetter 400 II Spectrum");       
      nWarnUserToChangeHostName = TRUE;
    }
    else if (strcmp(sModelType, "Trendsetter II 800 Spectrum") == 0)
    {
      *nDeviceTypeID = TS_II_SPEC;
      strcpy(sModelType, "Trendsetter 800 II Spectrum");
      nWarnUserToChangeHostName = TRUE;
    }
    else if (strcmp(sModelType, "Trendsetter II 400 AL") == 0)
    {
      *nDeviceTypeID = TS_II_AL;
      strcpy(sModelType, "Trendsetter 400 II AL");
      nWarnUserToChangeHostName = TRUE;
    }
    else if (strcmp(sModelType, "Trendsetter II 800 AL") == 0)
    {
      *nDeviceTypeID = TS_II_AL;
      strcpy(sModelType, "Trendsetter 800 II AL");
      nWarnUserToChangeHostName = TRUE;
    }
    else if (strcmp(sModelType, "Trendsetter II 400 Continuous Load") == 0)
    {
      *nDeviceTypeID = TS_II_CL;
      strcpy(sModelType, "Trendsetter 400 II Continuous Load");
      nWarnUserToChangeHostName = TRUE;
    }
    else if (strcmp(sModelType, "Trendsetter II 800 Continuous Load") == 0)
    {
      *nDeviceTypeID = TS_II_CL;
      strcpy(sModelType, "Trendsetter 800 II Continuous Load");
      nWarnUserToChangeHostName = TRUE;
    }
    else if (strcmp(sModelType, "Trendsetter II 400 Continuous Load Spectrum") == 0)
    {
      *nDeviceTypeID = TS_II_CL_SP;
      strcpy(sModelType, "Trendsetter 400 II Continuous Load Spectrum");
      nWarnUserToChangeHostName = TRUE;
    }
    else if (strcmp(sModelType, "Trendsetter II 800 Continuous Load Spectrum") == 0)
    {
      *nDeviceTypeID = TS_II_CL_SP;
      strcpy(sModelType, "Trendsetter 800 II Continuous Load Spectrum");
      nWarnUserToChangeHostName = TRUE;
    }
    else if (strcmp(sModelType, "TSC NEWS Two Head") == 0)
    {
      *nDeviceTypeID = TSC;
      strcpy(sModelType, "TSC NEWS Dual Head");
      nWarnUserToChangeHostName = TRUE;
    }

    // new names
    else if (strcmp(sModelType, "Trendsetter 400 II") == 0)
      *nDeviceTypeID = TS_II;         
    else if (strcmp(sModelType, "Trendsetter 800 II") == 0)
      *nDeviceTypeID = TS_II;      
    else if (strcmp(sModelType, "Trendsetter 400 II Spectrum") == 0)
      *nDeviceTypeID = TS_II_SPEC;        
    else if (strcmp(sModelType, "Trendsetter 800 II Spectrum") == 0)
      *nDeviceTypeID = TS_II_SPEC;
    else if (strcmp(sModelType, "Trendsetter 400 II AL") == 0)
      *nDeviceTypeID = TS_II_AL;
    else if (strcmp(sModelType, "Trendsetter 800 II AL") == 0)
      *nDeviceTypeID = TS_II_AL;
    else if (strcmp(sModelType, "Trendsetter 400 II Continuous Load") == 0)
      *nDeviceTypeID = TS_II_CL;
    else if (strcmp(sModelType, "Trendsetter 800 II Continuous Load") == 0)
      *nDeviceTypeID = TS_II_CL;
    else if (strcmp(sModelType, "Trendsetter 400 II Continuous Load Spectrum") == 0)
      *nDeviceTypeID = TS_II_CL_SP;
    else if (strcmp(sModelType, "Trendsetter 800 II Continuous Load Spectrum") == 0)
      *nDeviceTypeID = TS_II_CL_SP;
    else if (strcmp(sModelType, "Trendsetter 400 II Autoloader Spectrum") == 0)
      *nDeviceTypeID = TS_II_AL_SP;       
    else if (strcmp(sModelType, "Trendsetter 800 II Autoloader Spectrum") == 0)
      *nDeviceTypeID = TS_II_AL_SP;       
    else if (strcmp(sModelType, "Proofsetter Spectrum") == 0)
      *nDeviceTypeID = TS_II_PROOF; 
    else if (strcmp(sModelType, "Trendsetter NEWS") == 0)
      *nDeviceTypeID = TS_NEWS;         
    else if (strcmp(sModelType, "Trendsetter NEWS SA") == 0)
      *nDeviceTypeID = TS_NEWS_SA;
    else if (strcmp(sModelType, "Trendsetter NEWS 200") == 0)
      *nDeviceTypeID = TS_NEWS_200;        
    else if (strcmp(sModelType, "TSC NEWS Two Head") == 0)
      *nDeviceTypeID = TSC;      
    else if (strcmp(sModelType, "TSC NEWS Single Head") == 0)
      *nDeviceTypeID = TSC; 
    else if (strcmp(sModelType, "Magnus VLF") == 0)
      *nDeviceTypeID = MAGNUS_VLF;
    else if (strcmp(sModelType, "Magnus VLF MCU") == 0)
      *nDeviceTypeID = MAGNUS_VLF_AL;
    else if (strcmp(sModelType, "Magnus VLF ContinuousLoad") == 0)
      *nDeviceTypeID = MAGNUS_VLF_CL;
    else if (strcmp(sModelType, "ThermoFlex II") == 0)
      *nDeviceTypeID = FLEXO_WIDE_II;
    else if (strcmp(sModelType, "Gravure device") == 0)
      *nDeviceTypeID = GRAVURE;
    else if (strcmp(sModelType, "Flat Panel Display") == 0)
      *nDeviceTypeID = FLAT_PANEL;
    else
    {
      // Unknown device type
      strcpy(sModelType, "Unknown");
      *nDeviceTypeID = DEVICE_UNKNOWN;
      nRC = FAILURE;        
    }
  }
  else
  {
    nRC = FAILURE; 
  }
  if (nWarnUserToChangeHostName == TRUE)
  {
    Output("Reconfigure the service host name.  The current configured name is obsolete!", SUSPEND_BOX, 0, "The script has accomidated for the incorrect name.  Service Host 2.5SP1 or greater required.");
  }

  return nRC;
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function gets a prefix depending on the model type.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_GetDeviceType(char *sDeviceType, char *sFWType, int baseTrendsetterMPE, int noCodeOnBoard)
{
  char instring[STR_LEN];
  char outstring[STR_LEN];
  char sTransmitline[STR_LEN];
  char deviceMode[STR_LEN];
  char sTestPrompt[STR_LEN];

  int nDeviceTypeFound = FALSE;
  int ENG = FALSE;
  int sTemp;

  sTestPrompt[0] = '\0';

  COM_Output("Checking for device type...", INFORMATIVE, 0,  "");
  dialog("Device type check", 1, 1,
         "Checking for device type...",CTEXT | 1);

  if (noCodeOnBoard == FALSE)
  {
    if (strcmp(sFWType, "MPE") == 0)
    {              
      transmit("ws \"cd\"");  // prompts firmware for device type
      if (waitreg("Product   = [A-Z1-9]+\r", instring, 10))
      {
        COM_Output("WARNING: Timeout waiting for ws cd to display product type", INFORMATIVE, 0, "");
        COM_Output("Device may be running a older firmware version.", INFORMATIVE, 0, "");; 
        COM_Output("This version must not recognize the 'ws \"cd\"' command.", INFORMATIVE, 0, "");
        COM_Output("Assigning ZZZZ to the files firmware type.", INFORMATIVE, 0, "");
      }
      strcpy(outstring, instring + strlen("Product   = "));

      strcpy(sDeviceType, UNKNOWN_DEVICE);

      if (strcmp(outstring, "PS") == 0)
      {
        strcpy(sDeviceType, MPE_3244_PLATESETTER);
      }
      else if (strcmp(outstring, "TS") == 0)
      {
        if (baseTrendsetterMPE == 1)
        {
          strcpy(sDeviceType, MPE_TRENDSETTER_A);
        }
        if (baseTrendsetterMPE == 2)
        {
          strcpy(sDeviceType, MPE_TRENDSETTER_B);
        }
      }
      else if (strcmp(outstring, "VLFPS") == 0)
      {
        strcpy(sDeviceType, MPE_VLF_PLATESETTER);
      }
      else if (strcmp(outstring, "VLFTS") == 0)
      {
        strcpy(sDeviceType, MPE_VLF_TRENDSETTER);
      }
      else if (strcmp(outstring, "TSAL") == 0)
      {
        strcpy(sDeviceType, MPE_TRENDSETTER_AL);
      }
      else if (strcmp(outstring, "VLFTSAL") == 0)
      {
        strcpy(sDeviceType, MPE_VLF_AL);
      }
      else if (strcmp(outstring, "TS2637") == 0)
      {
        strcpy(sDeviceType, MPE_NEWS);
      }
      else if (strcmp(outstring, "TSSPEC") == 0)
      {
        strcpy(sDeviceType, MPE_TRENDSETTER_SP);
      }
      else if (strcmp(outstring, "SPEC") == 0)
      {
        strcpy(sDeviceType, MPE_PROOFSETTER);
      }
      else if (strcmp(outstring, "VLFPOST") == 0)
      {
        strcpy(sDeviceType, MPE_VLF_TRENDSETTER);
      }
      else if (strcmp(outstring, "FLEXO") == 0)
      {
        strcpy(sDeviceType, MPE_THERMOFLEX_WIDEI);
      }
    }
    if (strcmp(sFWType, MCENAME) == 0 || strcmp(sFWType, GMCENAME) == 0)
    {                  
      while (sTestPrompt[0] == '\0')
      {
        transmit(";");
        if (waitreg(MCE_DEVICE_TYPE, instring, 2) == 0)
        {                                     
            strncpy(sTestPrompt, instring, (strlen(instring) - 1));
            sprintf(sTransmitline, "Current MCE mode is %s", sTestPrompt);
            COM_Output(sTransmitline, INFORMATIVE, 0, "");
            nDeviceTypeFound = TRUE;
            // this waitfor is for simulators
            sleep(100);
        }
        else
        {
          COM_Output("MCE Prompt state not found...", INFORMATIVE, 0, ""); 
        }
      }

      if (nDeviceTypeFound == FALSE)
      {
        COM_Output("Ouput device type not found!", INFORMATIVE, 0,  "");  
        strcpy(sDeviceType, UNKNOWN_DEVICE);
      }
      else if (strstr(sTestPrompt, " ENG"))
      {
        COM_Output("Engineering Firmware", INFORMATIVE, 0, "");
        strncpy(sDeviceType, sTestPrompt, (strlen(sTestPrompt) - 4)); 
      }
      else if (strstr(sTestPrompt, "ENG"))
      {
        COM_Output("Engineering Firmware", INFORMATIVE, 0, "");
        strncpy(sDeviceType, sTestPrompt, (strlen(sTestPrompt) - 3)); 
      }      
      else
      {
        strcpy(sDeviceType, sTestPrompt);
        COM_Output("Production Firmware", INFORMATIVE, 0, "");
      }
      if (nDeviceTypeFound == FALSE)
      {
        COM_Output("Ouput device type not found!", INFORMATIVE, 0,  "");  
        strcpy(sDeviceType, UNKNOWN_DEVICE);
      } 
    }
    if (strcmp(sDeviceType, "GRAV") == 0)
    {
      strcpy(sDeviceType, MCE_GRAVURE);
    }
    COM_ReplaceSpace(sDeviceType);
    sprintf(sTransmitline, "Device Type is: %s", sDeviceType);
    COM_Output(sTransmitline, INFORMATIVE, 0,  "");
  }
  else
  {
    strcpy(sDeviceType, NO_FIRMWARE_ON_DEVICE);
    printf("Device Type is: %s", sDeviceType);
    sprintf(sTransmitline, ";Device Type is: %s", sDeviceType);
    COM_Output(sTransmitline, INFORMATIVE, 0, "");    
  }
  dialog("");
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function finds the serial number of the device
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_GetSerialNumber(char *sSerialNumber, char *sFWType, int nNoCodeOnBoard)
{
  char temp[STR_LEN];
  char sTransmitline[STR_LEN];
  char instring[STR_LEN];
  char outstring[STR_LEN];
  char sRetStr[STR_LEN];

  int nSerialNumberInt;
  int nRC = FAILURE;
  int nNotFound = FALSE;

  if (strcmp(sFWType, "MPE") == 0)  
  {
    if (nNoCodeOnBoard == FALSE)
    {
      nRC = COM_GetParm("set config serial", "serialno", sRetStr, PARM_STRING, WAIT_TIME, 1);

      if (nRC != SUCCESS)
      {
        COM_Output("Serial Number not found under \"set config serial\"!", INFORMATIVE, 0, "");
        strcpy(sSerialNumber, "0000");
        nNotFound = TRUE;
      }
      else
      {
        if (sRetStr[0] == '\0')
        {
           nNotFound = TRUE;
        }
        else
        {
          strcpy(sSerialNumber, sRetStr);
        }
      }
      if (nNotFound == TRUE)
      {
        nRC = COM_GetParm("set sys sn", "serial_number =", sRetStr, PARM_NUMERIC, WAIT_TIME, 1); 
        if (nRC != SUCCESS)
        {
          COM_Output("Serial Number not found under \"set sys sn\"!", INFORMATIVE, 0, "");
          strcpy(sSerialNumber, "0000");  
        }
        else
        {
          if (strcmp(sRetStr, "0") == 0)
          {
            strcpy(sSerialNumber, "0000");
          }
          else
          {
            strcpy(sSerialNumber, sRetStr);
          }
        }
      }
    }
    else
    {
      strcpy(sSerialNumber, "0000");
    }
  }
  if (strcmp(sFWType, MCENAME) == 0 || strcmp(sFWType, GMCENAME) == 0)  
  {
    if (nNoCodeOnBoard == FALSE)
    {
      transmit("set prd serialnumber");
      if (waitreg("SerialNumber    \"[A-Za-z0-9_ ]+\"", instring, 2))
      {            
        COM_Output("Serial Number not found under \"set prd serialnumber\"!", INFORMATIVE, 0, "");
        strcpy(sSerialNumber, "0000");
      }
      else
      {
        strcpy(outstring, instring + strlen("SerialNumber    \""));
        strcpy(sSerialNumber, outstring); 
        sSerialNumber[strlen(sSerialNumber) - 1] = '\0';
      }
      waitfor("Command Complete", WAIT_TIME);
    }
    else
    {
      strcpy(sSerialNumber, "0000");
    }
  }

  COM_ReplaceSpace(sSerialNumber);
  sprintf(sTransmitline, "Device serial number is: %s", sSerialNumber);
  COM_Output(sTransmitline, INFORMATIVE, 0, "");    
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function finds the owner name of the device
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_GetOwnerName(char *ownerName, char *sFWType, int noCodeOnBoard)
{
  char sTransmitline[STR_LEN];
  char instring[STR_LEN];
  char outstring[STR_LEN];

  if (strcmp(sFWType, "MPE") == 0)  
  {
    if (noCodeOnBoard == FALSE)
    {
      transmit("set config owner");
      if (waitreg("ownername = \"[A-Za-z0-9_ ]+\"", instring, WAIT_TIME))
      {            
        COM_Output("Owner name not found!", INFORMATIVE, 0, "");
        strcpy(ownerName, "Owner");
      }
      else
      {                                      
        strcpy(outstring, instring + strlen("ownername = \""));         
        strcpy(ownerName, outstring); 
        ownerName[strlen(ownerName) - 1] = '\0';
      }
    }
    else
    {
      strcpy(ownerName, "Owner");
    }
  }
  if (strcmp(sFWType, MCENAME) == 0 || strcmp(sFWType, GMCENAME) == 0)  
  {
    if (noCodeOnBoard == FALSE)
    {
      transmit("set prd customername");
      if (waitreg("CustomerName    \"[A-Za-z0-9_ ]+\"", instring, 3))
      {            
        COM_Output("Customer name not found!", INFORMATIVE, 0, "");
        strcpy(ownerName, "Customer");
      }                                  
      else
      {                                  
        strcpy(outstring, instring + strlen("CustomerName    \""));
        strcpy(ownerName, outstring); 
        ownerName[strlen(ownerName) - 1] = '\0';
      }
      waitfor("Command Complete", WAIT_TIME);
    }
    else
    {
      strcpy(ownerName, "Customer");
    }
  }
  
  COM_ReplaceSpace(ownerName);

  if (strcmp(sFWType, MCENAME) == 0 || strcmp(sFWType, GMCENAME) == 0)  
  {
    sprintf(sTransmitline, "Customer name is: %s", ownerName);
    COM_Output(sTransmitline, INFORMATIVE, 0, "");    
  }
  if (strcmp(sFWType, "MPE") == 0)  
  {
    sprintf(sTransmitline, "Owner name is: %s", ownerName);
    COM_Output(sTransmitline, INFORMATIVE, 0, "");    
  }
} 

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This functions returns if the device is a spectrum or not.
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
int COM_IsSpectrum(char *sDeviceType)
{
  if (strcmp(sDeviceType, MCE_TRENDSETTER_SP) == 0 || strcmp(sDeviceType, MCE_TRENDSETTER_CL_SP) == 0 || strcmp(sDeviceType, MCE_TRENDSETTER_AL_SP) == 0 || strcmp(sDeviceType, MPE_TRENDSETTER_SP) == 0 || 
      strcmp(sDeviceType, MPE_PROOFSETTER) == 0)     
  {
    COM_Output("Spectrum device.", INFORMATIVE, 0, "");
    return(SUCCESS);
  }
  else
  {
    COM_Output("Not a Spectrum device.", INFORMATIVE, 0, "");
    return(FAILURE);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This functions returns if the device is a MPE 3244 device or not
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
int COM_IsMPE3244(char *sDeviceType)
{
  if (strcmp(sDeviceType, MPE_TRENDSETTER_A) == 0 ||
      strcmp(sDeviceType, MPE_TRENDSETTER_B) == 0 ||
      strcmp(sDeviceType, MPE_TRENDSETTER_AL) == 0 ||
      strcmp(sDeviceType, MPE_NEWS) == 0 ||
      strcmp(sDeviceType, MPE_TRENDSETTER_SP) == 0 ||    
      strcmp(sDeviceType, MPE_PROOFSETTER) == 0)
 {
    COM_Output("MPE 3244 device.", INFORMATIVE, 0, "");
    return(SUCCESS);
  }
  else
  {
    COM_Output("Not a MPE 3244 device.", INFORMATIVE, 0, "");
    return(FAILURE);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This functions returns if the device is a MCE 3244 device or not
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
int COM_IsMCE3244(char *sDeviceType)
{
  if (strcmp(sDeviceType, MCE_TRENDSETTER_SP) == 0 ||
      strcmp(sDeviceType, MCE_TRENDSETTER_CL_SP) == 0 ||
      strcmp(sDeviceType, MCE_TRENDSETTER_AL_SP) == 0 ||
      strcmp(sDeviceType, MCE_TRENDSETTER) == 0 || 
      strcmp(sDeviceType, MCE_TRENDSETTER_AL) == 0 ||
      strcmp(sDeviceType, MCE_TRENDSETTER_CL) == 0)
 {
    COM_Output("MCE 3244 device.", INFORMATIVE, 0, "");
    return(SUCCESS);
  }
  else
  {
    COM_Output("Not a MCE 3244 device.", INFORMATIVE, 0, "");
    return(FAILURE);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This functions returns if the device is a MPE VLF
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
int COM_IsMPEVLF(char *sDeviceType)
{
  if (strcmp(sDeviceType, MPE_VLF_PLATESETTER) == 0 ||
      strcmp(sDeviceType, MPE_VLF_TRENDSETTER) == 0 ||
      strcmp(sDeviceType, MPE_VLF_AL) == 0 )
 {
    COM_Output("MPE VLF device.", INFORMATIVE, 0, "");
    return(SUCCESS);
  }
  else
  {
    COM_Output("Not a MPE VLF device.", INFORMATIVE, 0, "");
    return(FAILURE);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This functions returns if the device is a spectrum or not.
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
int COM_IsMCEVLF(char *sDeviceType)
{
  if (strcmp(sDeviceType, MCE_MAGNUS_VLF) == 0 || strcmp(sDeviceType, MCE_MAGNUS_VLF_AL) == 0 || strcmp(sDeviceType, MCE_MAGNUS_VLF_CL) == 0)     
  {
    COM_Output("VLF MCE Device.", INFORMATIVE, 0, "");
    return(SUCCESS);
  }
  else
  {
    COM_Output("Not a MCE VLF Device.", INFORMATIVE, 0, "");
    return(FAILURE);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function converts a firmware version string that includes a build version to a floating point firmware version.  
// The build version is removed.
//
// Example input: 112-04 
//         output: 112.04
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_ConvertFWVersionToFloat(char *sMCEFWversion, float *fMCEFWVersion)
{
  *fMCEFWVersion = atof(sMCEFWversion);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function converts a firmware version string that includes a build version to build version only.
//
// Example input: 112-04 
//         output: 4
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_ConvertFWVersionToBuildVersionInt(char *sMCEFWversion, int *nMCEBuildVersion)
{
  char sVersion[STR_LEN];
  char sFind[STR_LEN];
  char sReplace[STR_LEN];

  strcpy(sFind, "-");
  strcpy(sReplace, " ");
  strcpy(sVersion, sMCEFWversion);
  COM_ReplaceCharacter(sVersion, sFind, sReplace);
  COM_ExtractValue(sVersion, 2);

  *nMCEBuildVersion = atoi(sVersion);
}


//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function takes a path passed to it and strips out the filename from the path.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_ExtractFileNameFromString(char *path, char *filename)
{ 
  int len;
  int index; 
  
  char *pPath = NULL;

  len = strlen(path);
  index = len - 1;

  while ( index >= 0)
  {
    if (path[index] == '\\')
    {
      pPath = &path[index + 1];
      break;
    }
    index--;
  }

  if (pPath != NULL)
  {
    strcpy(filename, pPath);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This funcion takes a path passed to it and strips out the extension of the filename
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_ExtractExtensionFromPath(char *sPathWithFilename, char *sExtension)
{
  int len = 0;
  int index = 0; 
  int nResult = FAILURE;

  char *pPath = NULL;

  len = strlen(sPathWithFilename);
  index = len - 1;

  while ( index >= 0)
  {
    if (sPathWithFilename[index] == '.')
    {
      pPath = &sPathWithFilename[index + 1];
      break;
    }
    index--;
  }

  if (pPath != NULL)
  {
    strcpy(sExtension, pPath);
    nResult = SUCCESS;
  }
  return nResult;
}

/************************************************************************
*  Description:
* Converts a string to lower case.
*
*  Input:
* *sString - string to be converted.
************************************************************************/
void COM_LCase(char *sString)
{
    int nStringLength = 0;
    int nStringIndex = 0;

    nStringLength = strlen(sString);
    for (nStringIndex = 0; nStringIndex < nStringLength ; nStringIndex++)
    {
      sString[nStringIndex] = tolower(sString[nStringIndex]);
    }

    return;
}

/************************************************************************
*  Description:
* Converts a string to upper case.
*
*  Input:
* *sString - string to be converted.
************************************************************************/
void COM_UCase(char *sString)
{
    int nStringLength = 0;
    int nStringIndex = 0;

    nStringLength = strlen(sString);
    for (nStringIndex = 0; nStringIndex < nStringLength ; nStringIndex++)
    {
      sString[nStringIndex] = toupper(sString[nStringIndex]);
    }

    return;
}


/************************************************************************
*  Description:
*     Case insensitive substring search.
*
*  Input:
*     search_string - the string to be searched upon
*     sub_string - the string to search for (must be lower case)
*
*  Return:
*     SUCCESS if the sub string is found.
************************************************************************/
int COM_FindSubString(char *sSearchString, char *sSubString)
{
    int nSearchStringLength;
    int nCharValue;
    int nCharDiff;
    int nSearchStringIndex;
    char cCurChar;
    char sCheckNull[64];
    char sLCString[256];

    nSearchStringLength = strlen(sSearchString);
    nCharDiff = (int)'a' - (int)'A';
    for (nSearchStringIndex = 0; nSearchStringIndex < nSearchStringLength; nSearchStringIndex++)
    {
        cCurChar = sSearchString[nSearchStringIndex];
        nCharValue = (int)cCurChar;
        if ((nCharValue >= (int)'A') && (nCharValue <= (int)'Z'))
        {
            nCharValue += nCharDiff;
            cCurChar = (char)nCharValue;
        }
        sLCString[nSearchStringIndex] = cCurChar;
    }

    sCheckNull = strstr(sLCString, sSubString);
    if (sCheckNull != NULL)
    {
        return SUCCESS;
    }

    return FAILURE;
}


/************************************************************************
*  Description:
*     Replaces all occurences of char in string with another char.
*
*  Input:
*       sExpression - the string containing substring to replace
*       sFind       - char being searched for
*       sReplace    - replacement char
*
*   Output:
*       sExpression - string in which a specified char has been replaced 
*                     with another char
*
*  Return:
*     None.
************************************************************************/
void COM_ReplaceCharacter(char *sExpression, char sFind[1], char sReplace[1])
{    
    int nIndex = 0;

    while (sExpression[nIndex] != '\0')
    {
        if (sExpression[nIndex] == sFind[0])
        {
            sExpression[nIndex] = sReplace[0];
        }
        nIndex++;
    }
}



//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function finds a '/' in a string and replaces it with a '|'.
// Firmware uses the '/' to repeat a command, so it must be replaced in a transmit string, otherwise there will 
// be unwanted side effects.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_ReplaceBackSlash(char *string)
{    
  int count = 0;

  while (string[count] != '\0')
  {
    if (string[count] == '\\')
    {
      string[count] = '|';
    }
    count++;
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This function finds a ' ' in a string and replaces it with a '_'.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_ReplaceSpace(char *string)
{    
  int count = 0;

  while (string[count] != '\0')
  {
    if (string[count] == ' ')
    {
      string[count] = '-';
    }      
    count++;
  } 
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Reads a string and looks for spaces in the string and removes them.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_RemoveSpaceFromString(char *string)
{
  char buffer[STR_LEN];
  char buffer2[STR_LEN];
  int i;
  int j = 0;
  int length = 0;

  strcpy(buffer, string);

  length = strlen(buffer);
  
  for(i = 0; i < length; i++)      
  {
    if (buffer[i] != ' ')
    {
      buffer2[j] = buffer[i]; 
      j++;
    }
  }

  strcpy(string, buffer2);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Reads a string and looks for a particular character in a string and removes that character.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_RemoveCharacterFromString(char *string, char character)
{
  char buffer[STR_LEN];
  char buffer2[STR_LEN];
  int i;
  int j = 0;
  int length = 0;

  strcpy(buffer, string);

  length = strlen(buffer);
  
  for(i = 0; i < length; i++)      
  {
    if (buffer[i] != character)
    {
      buffer2[j] = buffer[i]; 
      j++;
    }
  }

  strcpy(string, buffer2);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Extracts a word from a string.  arg specifies which word 1,2,3,4,5 you want to remove from the string.
//------------------------------------------------------------------------------------------------------------------------------------------------------------          
void COM_ExtractValue(char* buffer, int arg)
{
  char s1[STR_LEN];
  char s2[STR_LEN];
  char s3[STR_LEN];
  char s4[STR_LEN];
  char s5[STR_LEN];

  sscanf(buffer,"%s %s %s %s %s",s1,s2,s3,s4,s5);

  if (arg == 1)
  {
    strcpy(buffer, s1);  
  }
  else if (arg == 2)
  {
    strcpy(buffer, s2);
  }
  else if (arg == 3)
  {
    strcpy(buffer, s3);
  }
  else if (arg == 4)
  {
    strcpy(buffer, s4);
  }
  else if (arg == 5)
  {
    strcpy(buffer, s5);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Compares two string while ingoring case
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_IsEqualNoCase(char *string1, char *string2)
{
  int index = 0;
  int cmp1 = 0;
  int cmp2 = 0;
  int ch1 = 0;
  int ch2 = 0;

  if (strlen(string1) != strlen(string2))
  {
    return(1);
  }

  for(index =0; (index < strlen(string1)) && (index < strlen(string2)); index++)
  {
    cmp1 = string1[index];
    cmp2 = string2[index];

    ch1 = tolower(cmp1);
    ch2 = tolower(cmp2);

    if (ch1 != ch2)
    {
      return(1);
    }
  }
  return(0);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Reads strings in from a file and ignores a line in which the first character matches the discard flag.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_LoadLinesCmp(char *lines, int nlines, int size, char *discardFlag, FILE *hfile)
{
  char matchstr[STR_LEN];

  int index = 0;
  int rc = 0;
 
  while(index < nlines)
  {
    if (fgets(lines[index], size, hfile) == NULL)
    {
      return (index);
    }
    else
    {
      if (strncmp(lines[index], discardFlag, strlen(discardFlag)) != 0)
        ++index;
    }
  }
  while (rc < 1)
  {
    if (rc >= 0)
    {
      dialog("Attention!", 1, 1,
      "Warning script did not read to the end of the file!", CTEXT | 4,
      "Increase the number of lines you pass to this function.", CTEXT | 5,
      "Continue", BUTTON | 7, -1, -1, 100, 7, "Quit", BUTTON | 8, -1, -1, 100, 7);
    }
    sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
    rc = dialog(matchstr);
    if (rc == DIALOG_CLOSE)
    { 
      // user hit the x button in the corner of the dialog box
      COM_Done();
    }
  }
  // Erase the dialog box.
  dialog("");
  if (rc == 8)
  {
    ExitInError();
  }
  return (index);

}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Reads strings in from a file and ignores a line where any character in the line matches the discard flag 
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_LoadLinesSubStr(char *lines, int nlines, int size, char* discardFlag, FILE* hfile)
{
  char matchstr[STR_LEN];
  
  int index = 0;
  int rc = 0;
  
  while(index < nlines)
  {
    if (fgets(lines[index], size, hfile) == NULL)
    {
      return (index);
    }
    else
    {
      if (strstr(lines[index], discardFlag) == NULL)
      {
        ++index;
      }
    }
  }
  while (rc < 1)
  {
    if (rc >= 0)
    {
      dialog("Attention!", 1, 1,
      "Warning script did not read to the end of the file!", CTEXT | 4, 
      "Increase the number of lines you pass to this function.", CTEXT | 5,
      "Continue", BUTTON | 7, -1, -1, 100, 7, "Quit", BUTTON | 8, -1, -1, 100, 7);
    }
    sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
    rc = dialog(matchstr);
    if (rc == DIALOG_CLOSE)
    { 
      // user hit the x button in the corner of the dialog box
      COM_Done();
    }
  }
  // Erase the dialog box.
  dialog("");
  if (rc == 8)
  {
    ExitInError();
  }
  return (index);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Reads a string and returns any numbers found.  The numbers found are stored in sArrayOfNum.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_RemoveCharactersFromString(char *cString, char *sArrayOfNum, int *nNumbersFound)
{  
  int index = 0;
  int count = 0;
  int rc = 0;
  int nNumFound = 0;
 
  while(count < sizeof(cString))
  {
    if (cString[count] == '\0')
    {
      return(SUCCESS);
    }
    else
    {
      while (isdigit(cString[count]))
      {
        sArrayOfNum[nNumFound][index] = cString[count];
        count++;
        index++;
      }
      sArrayOfNum[nNumFound][index] = '\0';
      index = 0;
      nNumFound++;
      *nNumbersFound = nNumFound;
    }
    count++;
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Rounds a number passed to it.
//------------------------------------------------------------------------------------------------------------------------------------------------------------          
int COM_RoundNumber(char* number)
{
  float  tempFloat;
  int tempInt;

  tempFloat = atof(number);
  if (tempFloat < 0)
  {
    if ((tempFloat - (int)tempFloat) <= -0.5)
    {
      tempFloat = tempFloat + -0.5;
    }
  }
  else
  {
    if ((tempFloat - (int)tempFloat) >= 0.5)
    {
      tempFloat = tempFloat + 0.5;
    }
  }
  tempInt = (int)tempFloat;
  return(tempInt);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This funcion takes a path passed to it and strips out the filename from the path.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_RemoveFileNameFromString(char *pathWithFilename, char *path)
{ 
  int len;
  int index;
  int temp;

  char *pPath = NULL;

  len = strlen(pathWithFilename);
  index = len - 1;

  while ( index >= 0)
  {
    if (pathWithFilename[index] == '\\')
    {
      temp = index + 1;
      strncpy(path, pathWithFilename, index + 1);
      break;
    }
    index--;
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Create Sign on Version Window
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
void COM_SignOn(void)
{
  dialog("Version info", 1, 1,
         SCRIPTNAME, CTEXT | 1, 15, 0, 150, 5,
         VERSIONINFO, CTEXT  | 1, 15, 5, 90, 5);

  COM_Output(SCRIPTNAME, INFORMATIVE, 0, "");
  COM_Output(VERSIONINFO, INFORMATIVE, 0, "");
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Exits the script.
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_Done(void)
{
  char sTransmitline[STR_LEN];

  sprintf(sTransmitline,";;%s has now ended.", SCRIPTNAME);
  transmit(sTransmitline);
  exit(0);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Gets current port setting.
//
// This function will retrieve the port of a MPE, MCE MCE2 TFX, etc etc.
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_GetPort(char *sConnectionType, int *nPort)
{
  char sTransmitline[STR_LEN];
  char instring[STR_LEN];
  char outstring[STR_LEN];
  char sPort[2];
  char temp[STR_LEN];

  sprintf(sTransmitline, "talkto %s", SSDIAG);
  transmit(sTransmitline);
  sprintf(sTransmitline, "svsh port query %s", sConnectionType);
  sprintf(temp, "svsh port query %s COM[0-9]+", sConnectionType);
  transmit(sTransmitline);
  if (waitreg(temp, instring, 3))
  {
    sprintf(sTransmitline, "talkto %s", sConnectionType);
    transmit(sTransmitline);
    sprintf(sTransmitline, "Current %s port setting not found!", sConnectionType);
    COM_Output(sTransmitline, INFORMATIVE, 0, "");
  }
  else
  {
    sprintf(temp, "svsh port query %s COM", sConnectionType);
    transmit(sTransmitline);
    strcpy(outstring, instring + strlen(temp));
    strcpy(sPort, outstring);
    *nPort = atoi(sPort);
    sprintf(sTransmitline, "talkto %s", sConnectionType);
    transmit(sTransmitline);
    sprintf(sTransmitline, "Current %s port setting is: %i", sConnectionType, *nPort);
    COM_Output(sTransmitline, INFORMATIVE, 0, "");
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Checks NVS status 
//
// returns 1 if successful
// returns 0 if failure
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
int COM_VerifyNVS(int noCodeOnBoard, int noCodeOnMCE2Board, int dualMCE)
{
  char sTransmitline[STR_LEN];

  dialog("NVS Check", 1, 1,
         "Checking Device NVS state...",CTEXT | 1);

  if (noCodeOnBoard == FALSE)
  {
    // first check if NVS is OK
    if (COM_Output("stg verify ram", TERMINAL, 10, "OK"))
    {     
      waitfor("Command Complete", WAIT_TIME);
      COM_Output("NVS RAM CORRUPT!", SUSPEND_BOX, 0, "");
      return(0);
    }
    waitfor("Command Complete", WAIT_TIME);

    if (COM_Output("stg verify flash", TERMINAL, 10, "OK"))
    {      
      waitfor("Command Complete", WAIT_TIME);
      COM_Output("NVS FLASH CORRUPT!", SUSPEND_BOX, 0, "");
      return(0);
    }
    waitfor("Command Complete", WAIT_TIME);
  }
  
  if (dualMCE == TRUE)
  {
    if (noCodeOnMCE2Board == FALSE)
    {
      // first check if NVS is OK on MCE2
      sprintf(sTransmitline, "talkto %s", MCE2NAME);
      transmit(sTransmitline);
      if (COM_Output("stg verify ram", TERMINAL, 10, "OK"))
      {       
        waitfor("Command Complete", WAIT_TIME);
        sprintf(sTransmitline, "talkto %s", MCENAME);
        transmit(sTransmitline);

        COM_Output("MCE2 NVS RAM CORRUPT!", SUSPEND_BOX, 0, "");
        return(0);
      }
      waitfor("Command Complete", WAIT_TIME);   
      if (COM_Output("stg verify flash", TERMINAL, 10, "OK"))
      {        
        waitfor("Command Complete", WAIT_TIME);
        sprintf(sTransmitline, "talkto %s", MCENAME);
        transmit(sTransmitline);

        COM_Output("MCE2 NVS FLASH CORRUPT!", SUSPEND_BOX, 0, "");
        return(0);
      }
      waitfor("Command Complete", WAIT_TIME);
      sprintf(sTransmitline, "talkto %s", MCENAME);
      transmit(sTransmitline);              
    }
  }
  return(1);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Erases NVS on a MCE, GMCE or MPE board through main code (MPE or MCE) or through boot code (MCE & GMCE).
//
// noCodeOnBoard assumes that the MCE is in boot mode and will try the boot code version nvs clear command: "boot nvramclear" 
// noCodeOnBoard for MPE does nothing
//
// returns 0 if success
// returns 1 if failure
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
int COM_EraseBoardNVS(int nNoCodeOnBoard , 
                      int nNoCodeOnMCE2Board, 
                      int nTargetMCE, 
                      char *sFWType)
{
  char sTransmitline[STR_LEN];

  dialog("Erasing NVS", 1, 1,
         "Erasing NVS on electronics board...",CTEXT | 1);
  
  if (strcmp(sFWType, MPENAME) == 0)  
  {
    return(COM_EraseMPENVS ( nNoCodeOnBoard, sFWType));
  }
  if (strcmp(sFWType, MCENAME) == 0)  
  {
    return(COM_EraseNVS(nNoCodeOnBoard, nNoCodeOnMCE2Board, nTargetMCE)); 
  }
  if (strcmp(sFWType, GMCENAME) == 0)
  {
    return(COM_EraseGMCENVS ( nTargetMCE ));
  }
  return(FAILURE);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Erases NVS on a MPE board 
//
// INPUT
// nNoCodeOnBoard
// OUTPUT
// returns 0 if success
// returns 1 if failure
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
int COM_EraseMPENVS ( int nNoCodeOnBoard,
                      char *sFWType )

{

  int dualMCE = FALSE;

  if (nNoCodeOnBoard == FALSE)
  {
    COM_Output("nvs init stats", TERMINAL, 10, "(Y/N)");
    COM_Output("Y", TERMINAL, 20, "Statistic initialization complete");
    COM_Output("nvs init all creo", TERMINAL, 10, "(Y/N)");
    COM_Output("Y", TERMINAL, 120, "NVS initialization complete");
    COM_Output("nvs init state creo", TERMINAL, 10, "(Y/N)");
    if (COM_Output("Y", TERMINAL, 10, "NVS initialization complete"))
    {
      return(SUCCESS);
    }
    // pause otherwise the save will not work properly (tested on cardcage)
    waitfor("nothing", 10);
    COM_ResetTheDevice(1, 1, sFWType, dualMCE);
    COM_Output("nvs save all creo", TERMINAL, 10, "(Y/N)");
    transmit("Y");
    waitfor("NVS save all complete", 130);
  }
  return (FAILURE);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Erases NVS on a MCE board through main code or through boot code.
//
// noCodeOnBoard assumes that the MCE is in boot mode and will try the boot code version nvs clear command: "boot nvramclear" 
//
// returns 1 if successful
// returns 0 if failure
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
int COM_EraseNVS(int noCodeOnBoard , int noCodeOnMCE2Board, int nTargetMCE)
{
  char sTransmitline[STR_LEN];

  dialog("Erasing NVS", 1, 1,
             "Erasing NVS on replacement board...",CTEXT | 1);

  if (nTargetMCE == MCE2)
  {
    sprintf(sTransmitline, "talkto %s", MCE2NAME);
    transmit(sTransmitline);
    if (noCodeOnMCE2Board == FALSE)
    {
      dialog("Erasing NVS", 1, 1,
             "Erasing NVS on MCE2 board...",CTEXT | 1);

      
      if (COM_Output("access dev", TERMINAL, WAIT_TIME, "Command Complete"))
      {
        sprintf(sTransmitline, "talkto %s", MCENAME);
        transmit(sTransmitline);
        return(0);
      }
      if (COM_Output("stg erase flash", TERMINAL, 10, "Command Complete"))
      {
        sprintf(sTransmitline, "talkto %s", MCENAME);
        transmit(sTransmitline);
        return(0);
      }
      if (COM_Output("stg erase ram", TERMINAL, 10, "Command Complete"))
      {
        sprintf(sTransmitline, "talkto %s", MCENAME);
        transmit(sTransmitline);
        return(0);
      }
     
    }
    else
    {
      transmit("boot nvramclear");
      waitfor("Nothing", WAIT_TIME);
    }
    sprintf(sTransmitline, "talkto %s", MCENAME);
    transmit(sTransmitline);
    
  }
  if (nTargetMCE == MCE)
  {
    dialog("Erasing NVS", 1, 1,
           "Erasing NVS on MCE board...",CTEXT | 1);
    if (noCodeOnBoard == FALSE)
    {
      if (COM_Output("access dev", TERMINAL, WAIT_TIME, "Command Complete"))
      {
        return(0);
      }
      if (COM_Output("stg erase flash", TERMINAL, 10, "Command Complete"))
      {
        return(0);
      }
      if (COM_Output("stg erase ram", TERMINAL, 10, "Command Complete"))
      {
        return(0);
      }
    }
    else
    {
      transmit("boot nvramclear");
      waitfor("Nothing", WAIT_TIME);
    }
  }
  return(1);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Erases NVS on a GMCE board through boot code only.
//
// INPUT
// nTargetGMCE = GMCE or GMCE2
// OUTPUT
// returns 1 if failure
// returns 0 if successful
//------------------------------------------------------------------------------------------------------------------------------------------------------------/
int COM_EraseGMCENVS(int nTargetGMCE)

{
  if (nTargetGMCE == GMCE)
  {
    dialog("Erasing NVS", 1, 1,
           "Erasing NVS on GMCE board...",CTEXT | 1);
    if (COM_Output("access dev", TERMINAL, WAIT_TIME, "Command Complete")==0)
    {
      if (COM_Output("stg erase ram", TERMINAL, WAIT_TIME, "Command Complete")==0)
      {
        return (SUCCESS); // Sucess
      }
      else
      {
        return (FAILURE); //Failed to issue "stg erase ram"
      }
    }
    else
    {
      return (FAILURE); //Failed to issue "access dev" 
    }
  }
  return(FAILURE); // Not valid nTargetMCE
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//Gets a Script version
//
// nlines - the number of line to search for version information in the file
// size - size of the line to read
// sVersionName - version string to search for
// fVerFound - version found info is assigned to this parameter
// sFilePath - the path of the file to check the version information of
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_GetScriptVersion(int nlines, int size, char *sVersionName, float *fVerFound, char *sFilePath)
{
  char matchstr[STR_LEN];
  char sTransmitline[STR_LEN];
  char line[STR_LEN];
  FILE *fpFile = NULL;               // file pointer

  int index = 0;
  int rc = 0;
  

  if (COM_FileOpen(sFilePath, MODE_READ_ONLY, &fpFile) == FAILURE)
  {    
    return (FAILURE);
  }
  
  while(index < nlines)
  {

    if (fgets(line, size, fpFile) == NULL)
    {
      COM_Output("Could not read line from file, file is empty, or version information not found!", INFORMATIVE, 0, "");
      COM_FileClose(&fpFile);
      return(FAILURE);
    }
    else
    {
      if (strncmp(line, sVersionName, strlen(sVersionName)) != 0)
      {
        ++index;
      }
      else
      {       
        *fVerFound = atof(line + strlen(sVersionName));
        sprintf(sTransmitline, "File Version Found is: %3.2f", *fVerFound);
        COM_Output(sTransmitline, INFORMATIVE, 0, "");
        COM_FileClose(&fpFile);
        return(SUCCESS);
      }
    }
  }

  COM_FileClose(&fpFile);
  COM_Output("File version not found!", INFORMATIVE, 0, "");
  return (FAILURE);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//Gets a string from a file.  The function will be given a unique string to search for in the file
//
// nlines - the number of line to search for version information in the file
// size - size of the line to read
// sSearchString - string to search for
// hfile - file handle
// sReturnString - string found
// sFilePath - the path of the file to check the version information of
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_GetStringFromFile(int nlines, int size, char *sSearchString, char *sReturnString, char *sFilePath)
{
  char matchstr[STR_LEN];
  char sTransmitline[STR_LEN];
  char sLine[STR_LEN];

  int index = 0;
  int rc = 0;
  
  FILE *fpFile = NULL;               // file pointer

  if (COM_FileOpen(sFilePath, MODE_READ_ONLY, fpFile) == FAILURE)
  {
    return (FAILURE);
  }

  while(index < nlines)
  {

    if (fgets(sLine, size, *hfile) == NULL)
    {
      COM_Output("Could not read line from file, file is empty, or the string to search for was not found!", INFORMATIVE, 0, "");
      return(FAILURE);
    }
    else
    {
      if (strncmp(sLine, sSearchString, strlen(sSearchString)) != 0)
      {
        ++index;
      }
      else
      {       
        strcpy(sReturnString, sLine);
        sprintf(sTransmitline, "String Found is: %s", sReturnString);
        COM_Output(sTransmitline, INFORMATIVE, 0, "");
        COM_FileOpen(&fpFile);
        return(SUCCESS);
      }
    }
  }

  COM_FileClose(&fpFile);
  COM_Output("File version not found!", INFORMATIVE, 0, "");
  return (FAILURE);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Updates a newer script file.
//
// fIncludeVer - version of the script currently in use
// fVerFound - version of the the newer script found
// sFilePath - the location of the newer update file 
// sScriptDirectory - the location to update the file
// sFWType - the firmware type
// nEndScript - a flag to end the script one the update completes
// sTempLocalFile - the update reference temporary file name
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CheckVersionUpdateFile(float fIncludeVer, 
                               float fVerFound, 
                               char *sFilePath, 
                               char *sScriptDirectory, 
                               char *sFWType, 
                               int nEndScript,
                               char *sTempLocalFile)
{
  char sInstallLocation[STR_LEN];
  char sCopyLocation[STR_LEN];
  char sTransmitline[4][STR_LEN];
  char sTempLocalFilePath[STR_LEN];
  char tmp[STR_LEN];
  char sSystemCmd[STR_LEN];

  int rc = 0;

  if (fIncludeVer < fVerFound)
  {
    COM_Output("Newer version of file found.", INFORMATIVE, 0, "");
    sprintf(sTransmitline[0], "Current File Version is: %3.2f", fIncludeVer);
    COM_Output(sTransmitline[0], INFORMATIVE, 0, "");
    sprintf(sTransmitline[1], "Newer File Version Found is: %3.2f", fVerFound);
    COM_Output(sTransmitline[1], INFORMATIVE, 0, "");

    sprintf(sTransmitline[2], "%s", sFilePath);

    while (rc < 1)
    {
      if (rc >= 0)
      {
        dialog("Attention!", 1, 1,
        "A newer version of a file this script uses is available.", CTEXT | 1,
        "The file is:", CTEXT | 1,
        sTransmitline[2], CTEXT | 1,
        sTransmitline[0], CTEXT | 1,
        sTransmitline[1], CTEXT | 1,
        "Do you wish to update the file?", CTEXT | 1,
        "Yes", BUTTON | 7, -1, -1, 100, 7, 
        "No", BUTTON | 8, -1, -1, 100, 7);
      }
      sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
      rc = dialog(tmp);
      if (rc == DIALOG_CLOSE)
      { 
        // user hit the x button in the corner of the dialog box
        COM_Done();
      }
    }
    // Erase the dialog box.
    dialog("");

    // Copy the files
    if (rc == 7)
    {
      strcpy(sCopyLocation, sScriptDirectory);

      if (COM_CopyAndOverwriteFileNoCheck(sFilePath, sCopyLocation, 0, sFWType))
      {
        return(FAILURE);
      }
      else
      {
        // delete the temporary file it it exists
        sprintf(sSystemCmd, "del \"%s%s\"", sScriptDirectory, sTempLocalFile);
        system(sSystemCmd);

        // rename the update file to a temporary one in case the update fails
        // the file should not be updated until all the files have been updated
        COM_RenameFile(sFilePath, sTempLocalFile);
                
        if (nEndScript == TRUE)
        {
          rc = 0;
          while (rc < 1)
          {
            if (rc >= 0)
            {
              dialog("Update complete!", 1, 1,
              "The file was updated successfully.", CTEXT | 1,
              "The script will now end.", CTEXT | 1,
              "End", BUTTON | 7, -1, -1, 100, 7);
            }
            sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
            rc = dialog(tmp);
            if (rc == DIALOG_CLOSE)
            { 
              // user hit the x button in the corner of the dialog box
              COM_Done();
            }
          }
          COM_Done();
        }
        else
        {
          return(SUCCESS);
        }
      }
    }
  }

  if (fIncludeVer == fVerFound)
  {
    COM_Output("File versions are the same no need to update.", INFORMATIVE, 0, "");
  }

  if (fIncludeVer > fVerFound)
  {
    COM_Output("File version currently being used is newer than the released version.", INFORMATIVE, 0, "");
  }

  // no update happened
  return(FAILURE);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// Delete this function after a couple of months.  It is obsolete and should be deleted after that time expires.
// 2 Months should be long enough for people to get this updated version.  July 02 2004
// The newer version is above.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_UpdateFile(float fIncludeVer, float fVerFound, char *sFilePath, char *sScriptDirectory, char *sFWType)
{
  char sInstallLocation[STR_LEN];
  char sCopyLocation[STR_LEN];
  char sTransmitline[4][STR_LEN];
  char tmp[STR_LEN];

  int rc = 0;

  if (fIncludeVer < fVerFound)
  {
    COM_Output("Newer version of file found.", INFORMATIVE, 0, "");
    sprintf(sTransmitline[0], "Current File Version is: %3.2f", fIncludeVer);
    COM_Output(sTransmitline[0], INFORMATIVE, 0, "");
    sprintf(sTransmitline[1], "Newer File Version Found is: %3.2f", fVerFound);
    COM_Output(sTransmitline[1], INFORMATIVE, 0, "");

    sprintf(sTransmitline[2], "%s", sFilePath);

    while (rc < 1)
    {
      if (rc >= 0)
      {
        dialog("Attention!", 1, 1,
        "A newer version of a file this script uses is available.", CTEXT | 1,
        "The file is:", CTEXT | 1,
        sTransmitline[2], CTEXT | 1,
        sTransmitline[0], CTEXT | 1,
        sTransmitline[1], CTEXT | 1,
        "Do you wish to update the file?", CTEXT | 1,
        "Yes", BUTTON | 7, -1, -1, 100, 7, 
        "No", BUTTON | 8, -1, -1, 100, 7);
      }
      sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
      rc = dialog(tmp);
      if (rc == DIALOG_CLOSE)
      { 
        // user hit the x button in the corner of the dialog box
        COM_Done();
      }
    }
    // Erase the dialog box.
    dialog("");

    // Copy the files
    if (rc == 7)
    {
      strcpy(sCopyLocation, sScriptDirectory);

      if (COM_CopyAndOverwriteFileNoCheck(sFilePath, sCopyLocation, 0, sFWType))
      {
        return(FAILURE);
      }
      else
      {
        rc = 0;
        while (rc < 1)
        {
          if (rc >= 0)
          {
            dialog("Update complete!", 1, 1,
            "The file was updated successfully.", CTEXT | 1,
            "The script will now end.", CTEXT | 1,
            "End", BUTTON | 7, -1, -1, 100, 7);
          }
          sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
          rc = dialog(tmp);
          if (rc == DIALOG_CLOSE)
          { 
            // user hit the x button in the corner of the dialog box
            COM_Done();
          }
        }
        COM_Done();
      }
    }
  }

  if (fIncludeVer == fVerFound)
  {
    COM_Output("File versions are the same no need to update.", INFORMATIVE, 0, "");
  }

  if (fIncludeVer > fVerFound)
  {
    COM_Output("File version currently being used is newer than the released version.", INFORMATIVE, 0, "");
  }

  // no update happened
  return(FAILURE);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This functions opens a file under "LocalHostPath\Scripts\device\" if it exists and reads lines from it.
//
// An example of sPath example "C:\serviceshell\firmware"  The drive letter will vary.  
//
// Return - SUCCESS if successful in opening the file
// Return - FAILURE if NOT successful in opening the file
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_OpenSSDataFile(char *sString, char *fileName, char *sPath, int nNumOfStrings, int nLengthOfString)
{
  int i = 0;

  char sTransmitline[STR_LEN];
  char filePath[STR_LEN];

  FILE *fpFile = NULL;               // file pointer

  strcpy(filePath, sPath);

  if (!access(filePath, 0))
  {
    if (COM_FileOpen(filePath, MODE_READ_ONLY, &fpFile) == SUCCESS)
    {
      sprintf(sTransmitline, "Grabbing info from %s...", fileName);
      COM_Output(sTransmitline, INFORMATIVE, 0, "");
      for (i = 0 ; i < nNumOfStrings; i ++)
      {
        fgets(sString[i], nLengthOfString, fpFile);
      }
      COM_FileClose(&fpFile);
    }
    return(SUCCESS);
  }
  else
  {
    return(FAILURE);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This functions opens a file and writes to it.
//
// An example of sPath example "C:\serviceshell\firmware"  The drive letter will vary.  
//
// There is the option of 'Opening the file' and 'Leaving it open' to continue writing to it.
// If you just want to open the file and write to it later set nLeaveOpen = TRUE nOpen = TRUE and nNumOfStrings = 0
//
// Once you want to close the file call this function and set nLeaveOpen = FALSE and nNumOfStrings = 0
//
// Return - SuCCESS if successful in opening the file
// Return - FAILURE if NOT successful in opening the file
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_WriteToSSDataFile(char *sString, char *fileName, char *sPath, int nNumOfStrings, int nLeaveOpen, int nOpen)
{
  int i = 0;

  char sTransmitline[STR_LEN];
  char filePath[STR_LEN];

  FILE *fpFile; // file pointer

  strcpy(filePath, sPath);

  if (nOpen == TRUE)
  {
    COM_FileOpen(filePath, MODE_WRITE, &fpFile);
  }    
  if (*hfile != NULL)
  {
    sprintf(sTransmitline, "Copying info to %s...", fileName);
    COM_Output(sTransmitline, INFORMATIVE, 0, "");
    for (i = 0 ; i < nNumOfStrings; i ++)
    {
      fputs(sString[i], fpFile);
      fputs("\n", fpFile);
    }
    if (nLeaveOpen == FALSE)
    {
      COM_FileClose(&fpFile);
    }
    return(SUCCESS);
  }
  else
  {
    return(FAILURE);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This functions finds the working directory of service shell via a set path file (Created by DOS).
//
// sWorkingDirectory - will be assigned the path of where ServiceShell is installed
//
// If found the path will be X:\serviceshell\ X - will vary based on where service shell is installed
//
// Return - SuCCESS if successful in finding the path
// Return - FAILURE if NOT successful in finding the path
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_GetSSWorkingDirectory(char *sWorkingDirectory)
{
  int nStartPosition = 0;
  int nEndPosition = 0;
  int nStrnlen = 0;
  int nCount = 0;
  int nFoundPosition = 0;
  int nRC = SUCCESS;
  int nQuitChecking = FALSE;
  int nFound = FALSE;

  char sTransmitline[STR_LEN];
  char sFilePath[STR_LEN];
  char sProgsPathString[STR_LEN]; // the file could have a lot of paths when the file is opened large array required
  char *psStringFound;
  char *psStringStart;

  char cDrive = 'C';

  FILE* fpFile; // file pointer
 
  sprintf(sFilePath, "%s", SYSTEM_PATH_FILE);
  
  // try two different drives to open the file on.  C and D
  while (nCount < 3)
  {
    sprintf(sTransmitline, "set path \> %s", sFilePath);
    
    // open a file that contains all the system paths of the programs installed on the computer
    system(sTransmitline);
    
    if (COM_FileOpen(sFilePath, MODE_READ_ONLY, &fpFile) == SUCCESS)
    {
      psStringFound = sProgsPathString;
      while (fgets(sProgsPathString, STR_LEN, fpFile) != NULL)
      {
        if (COM_CheckForServiceShellPath(sProgsPathString, &psStringFound, &nQuitChecking) == SUCCESS)
        {
          COM_FileClose(&fpFile);
          nFound = TRUE;
          break; // we found it
        }
      }
      break;
      COM_FileClose(&fpFile);
    }
    else
    {
      nCount++;
      sprintf(sFilePath, "%c:\\%s", cDrive, SYSTEM_PATH_FILE);
      cDrive = cDrive + 1;
      if (nCount == 3)
      {
        COM_Output("Unable to create set path file!", INFORMATIVE, 0, "");

      }

    }
  }
    
  if (nFound != TRUE)
  {
    // did not find the ServiceShell install or working directory
    nRC = FAILURE;
  }

  nCount = 0;
  if (nRC != FAILURE)
  {
  
    psStringStart = sProgsPathString;

    while(psStringFound != psStringStart)
    {
      psStringStart++;
      nCount++;
    }
    
    nFoundPosition = nCount;

    // search for the beginning of the string starts with a ';' or a '='
    nStartPosition = nFoundPosition;
    while (nStartPosition != 0)
    {
      nStartPosition = nStartPosition - 1;
      if(';' == sProgsPathString[nStartPosition] || '=' == sProgsPathString[nStartPosition] )
      {
        nStartPosition = nStartPosition + 1;
        break;
      }
    }

    // search for the end of the string ends with a ';' or '\0'
    nEndPosition = nFoundPosition;
    while (nEndPosition != strlen(sProgsPathString))
    {
      nEndPosition = nEndPosition + 1;
      if(';' == sProgsPathString[nEndPosition] || '\0' == sProgsPathString[nEndPosition])
      {
        break;
      }
    }

    nStrnlen = nEndPosition - nStartPosition;
    strcpy(sTransmitline,  sProgsPathString + nStartPosition);
    strncpy(sWorkingDirectory, sTransmitline, nStrnlen);

    // if found a path with bin in it - get rid of the bin part
    if (strlen(sWorkingDirectory) == 19)
    {
      sWorkingDirectory[strlen(sWorkingDirectory) - 3] = '\0';
    }
    else
    {
      strcat(sWorkingDirectory, "\\");
    }
    
    //this is done so a drive letter case provided by windows matches the one returned by this function. 
    sWorkingDirectory[0] = toupper(sWorkingDirectory[0]);
    
    sprintf(sTransmitline, "Client install directory: %s", sWorkingDirectory);
    COM_Output(sTransmitline, INFORMATIVE, 0, "");

    nRC = SUCCESS;
  }
  return(nRC);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
// This functions checks for "ServiceShell" in a string
//
// If the function reads the next line which contains "PATHEXT" then the function sets the nQuitChecking flag to TRUE
//
// Return - SuCCESS if successful in finding the path
// Return - FAILURE if NOT successful in finding the path
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CheckForServiceShellPath(char *sProgsPathString, char **psStringFound, int *nQuitChecking)
{
  int nRC = SUCCESS;
  
  COM_LCase(sProgsPathString);
  *psStringFound = strstr(sProgsPathString, "serviceshell");
  if (*psStringFound == NULL)
  {
    nRC = FAILURE;
  }
  return(nRC);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//  Description:
//       this function gets the type of MPE device the user is setting up
//
//  Input:
//       sDeviceType - device type
//
//  Output:
//       none
//  Return:
//       void
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_GetMPEDeviceTypeFromUser(char *sDeviceType)
{
  int rc = 0;
  char tmp[STR_LEN];
  char sTransmitline[STR_LEN];

  while (rc < 1)
  {
    if (rc >= 0)
    {
      dialog("Choose MPE Device", 1, 1,
             "PS 3244", BUTTON | 1, -1, -1, 100, 7, 
             "Trendsetter A", BUTTON | 2, -1, -1, 100, 7, 
             "Trendsetter B", BUTTON | 3, -1, -1, 100, 7, 
             "VLF PS", BUTTON | 4, -1, -1, 100, 7, 
             "VLF Trendsetter", BUTTON | 5, -1, -1, 100, 7, 
             "Trendsetter AL", BUTTON | 6, -1, -1, 100, 7, 
             "VLF Autoloader", BUTTON | 7, -1, -1, 100, 7, 
             "NEWS", BUTTON | 8, -1, -1, 100, 7,
             "Trendsetter Spectrum", BUTTON | 9, -1, -1, 100, 7,
             "Proofsetter Spectrum", BUTTON | 10, -1, -1, 100, 7,
             "Wide I", BUTTON | 11, -1, -1, 100, 7,
             "Quit", BUTTON | 30, -1, -1, 100, 7);
    }
    sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
    rc = dialog(tmp);
    if (rc == -2) 
    {
      // user hit the x button in the corner of the dialog box
      ExitInError();
    }
  }
  // Erase the dialog box.
  dialog("");
  if (rc == 30)
  {
    ExitInError();
  }
  if (rc == 1)
  {

    strcpy(sDeviceType, MPE_3244_PLATESETTER);
  }
  if (rc == 2)
  {

    strcpy(sDeviceType, MPE_TRENDSETTER_A);
  }
  if (rc == 3)
  {

    strcpy(sDeviceType, MPE_TRENDSETTER_B);
  }
  if (rc == 4)
  {
 
    strcpy(sDeviceType, MPE_VLF_PLATESETTER);
  }
  if (rc == 5)
  {
 
    strcpy(sDeviceType, MPE_VLF_TRENDSETTER);
  }
  if (rc == 6)
  {
 
    strcpy(sDeviceType, MPE_TRENDSETTER_AL);
  }
  if (rc == 7)
  {
 
    strcpy(sDeviceType,  MPE_VLF_AL);
  }
  if (rc == 8)
  {
  
    strcpy(sDeviceType, MPE_NEWS);
  }
  if (rc == 9)
  {
  
    strcpy(sDeviceType, MPE_TRENDSETTER_SP);
  }
  if (rc == 10)
  {
  
    strcpy(sDeviceType, MPE_PROOFSETTER);
  }
  if (rc == 11)
  {
  
    strcpy(sDeviceType, MPE_THERMOFLEX_WIDEI);
  }
 
  sprintf(sTransmitline, "Device Type is: %s", sDeviceType);
  COM_Output(sTransmitline, INFORMATIVE, 0,"");
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//This function determines if the system is news sa or not
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CheckForSANewspaper(void)
{
  
  Output("access dev", TERMINAL, WAIT_TIME, "Command Complete");
 
  transmit("option");

  if (waitfor("Autoloader option is enabled", WAIT_TIME)) 
  {
    return(1);
  }
  else
  {
    waitfor("Command Complete", WAIT_TIME);
    return(0);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//This function asks the user if the system is a newspaper or autoloader.
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CheckIfNewspaperOrAutoloader(char *sMCEFWversion)
{
  int nNewspaper = FALSE;
  int rc = 0;
  int nHeadType = 0;

  char tmp[STR_LEN];
  char sFWType[STR_LEN];

  float fFWversion = 0;

  strcpy(sFWType, MCENAME);
  COM_GetHeadType(sFWType, &nHeadType);

  dialog("Device Type", 1, 1,
         "Checking if device is an 3244 Autoloader or a Newspaper device...",CTEXT | 1);

  COM_ConvertFWVersionToFloat(sMCEFWversion, &fFWversion);

  if (fFWversion < 136) 
  {
    if (nHeadType != TH2)
    {
      Output("access dev", TERMINAL, WAIT_TIME, "Command Complete");
 
      transmit("config");

      if (!waitfor("[NEWS", WAIT_TIME))
      {
        nNewspaper = TRUE;   
      }
      waitfor("Command Complete", WAIT_TIME);
    }
    else
    {
      nNewspaper = TRUE;   
    }
  }
  else
  {
     Output("access dev", TERMINAL, WAIT_TIME, "Command Complete");
 
     transmit("license");

     if (waitfor("Trendsetter", WAIT_TIME))
     {
       nNewspaper = TRUE;   
     }
     waitfor("Command Complete", WAIT_TIME);       
  }
  
  
  if (nNewspaper == TRUE)
  {
    COM_Output("Newspaper Device", INFORMATIVE, 0, "");
  }
  else
  {
    COM_Output("Not a Newspaper Device", INFORMATIVE, 0, "");
  }

  // Erase the dialog box.
  dialog("");

  return(nNewspaper);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//This function puts the MCE firmware into boot mode.
//
//Returns 1 if not in boot mode
//Retures 0 if in boot mode
//
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_PutMCEIntoBootMode(int targetMCE)
{
  char tmp[STR_LEN];
  char sTransmitline[STR_LEN];
  char sDeviceMode[STR_LEN];

  int continueCheck = FALSE;
  int rc = 0;

  if (targetMCE == MCE)
  {
    dialog("Boot Mode", 1, 1,
           "Putting MCE into Boot Mode...",CTEXT | 1);
    COM_Output("Putting MCE into Boot Mode...", INFORMATIVE, 0,  "");
  }
  else
  {
    dialog("Boot Mode", 1, 1,
           "Putting MCE2 into Boot Mode...",CTEXT | 1);
    COM_Output("Putting MCE2 into Boot Mode...", INFORMATIVE, 0,  "");
  }
  if (targetMCE == MCE2)
  {
    sprintf(sTransmitline, "talkto %s", MCE2NAME);
    transmit(sTransmitline);
  }
  transmit("reset boot");
  if (targetMCE == MCE2)
  {
    if (COM_TestAndWaitForMCEPrompt(MCE2, 6, sDeviceMode)) //6 = try for 60 seconds
    {
      return(1);
    }
    sprintf(sTransmitline, "talkto %s", MCE2NAME);
    transmit(sTransmitline);
  }
  if (targetMCE == MCE)
  {
    if (COM_TestAndWaitForMCEPrompt(MCE, 6, sDeviceMode)) //6 = try for 60 seconds
    {
      return(1);
    }
  }
  if (strcmp(sDeviceMode, "Post") == 0)
  {
    if (targetMCE == MCE2)
    {
      COM_Output("MCE2 Device in Post mode", INFORMATIVE, 0,  ""); 
      sprintf(sTransmitline, "talkto %s", MCENAME);
      transmit(sTransmitline);  
    }
    else
    {
      COM_Output("MCE Device in Post mode", INFORMATIVE, 0,  "");
    }
    return(1);
  }
  if (strcmp(sDeviceMode, "Boot") == 0)
  {  
    if (targetMCE == MCE2)
    {
      COM_Output("MCE2 Device in Boot mode", INFORMATIVE, 0,  "");
      sprintf(sTransmitline, "talkto %s", MCENAME);
      transmit(sTransmitline);
    }
    else
    {
      COM_Output("MCE Device in Boot mode", INFORMATIVE, 0,  "");
    }
    return(0);
  }
  else
  {
    if (targetMCE == MCE2)
    {
      COM_Output("MCE2 Device in not in Post or Boot mode.", INFORMATIVE, 0,  "");   
      sprintf(sTransmitline, "talkto %s", MCENAME);
      transmit(sTransmitline);
    }
    else
    {
      COM_Output("MCE Device in not in Post or Boot mode.", INFORMATIVE, 0,  "");
    }
    return(1);
  }   
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//This function puts the GMCE firmware into boot mode.
//
//INPUT
//Expected targetGMCE values = GMCE, GMCE2
//
//OUTPUT
//Returns 1 if not in boot mode
//Retures 0 if in boot mode
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_PutGMCEIntoBootMode(int targetGMCE)
{

  char sDeviceMode[STR_LEN];

  if (targetGMCE == GMCE)
  {
    dialog("Boot Mode", 1, 1,
           "Putting GMCE into Boot Mode...",CTEXT | 1);
    COM_Output("Putting GMCE into Boot Mode...", INFORMATIVE, 0,  "");
    transmit("reset boot");

    if (COM_TestAndWaitForGMCEPrompt(GMCE, 6, sDeviceMode)==0) //6 = try for 60 seconds
    {
      if (strcmp(sDeviceMode, "Gboot") == 0)
      {
        COM_Output("GMCE Device in Boot mode", INFORMATIVE, 0,  "");
        return(0); //Device in Boot Mode
      }
      else
      {
        COM_Output("GMCE Device is not in Boot mode.", INFORMATIVE, 0,  "");
        return(1); //Found promt but not in boot mode
      }
    }
    else
    {
      return(1); //Failed to get promt
    }
  }
//FOR FUTURE USE
//  else if (targetGMCE == GMCE2)
//    {
//      dialog("Boot Mode", 1, 1,
//             "Putting GMCE2 into Boot Mode...",CTEXT | 1);
//      COM_Output("Putting GMCE2 into Boot Mode...", INFORMATIVE, 0,  "");
//    
//      sprintf(sTransmitline, "talkto %s", GMCE2NAME);
//      transmit(sTransmitline);
//      transmit("reset boot");
//    }
  else
  {
    return (1); //targetGMCE not =  GMCE
  }
}


//------------------------------------------------------------------------------------------------------------------------------------------------------------
//  Description:
//       this function takes a hexadecimal string and returns an integer value
//
//  Input:
//       sHexString - hex string to convert
//       nDecimalValue - decimal equivalent of the hexidecimal string
//  Output:
//       none
//  Return:
//       void
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_CovertCharHexStringToDecimal(char *sHexString, int *nDecimalValue)
{
  int nRC = SUCCESS;
  int i = 0;
  int hex = 0x10;
  char **endptr;

  for (i = 0;  sHexString[i] != '\0' && nRC == SUCCESS; i++)      
  {
    if (!isdigit(sHexString[i]))
    {
      if (!isxdigit(sHexString[i]))
      {
        nRC = FAILURE;
      }
    }   
  }
  if (nRC == SUCCESS)
  {   
    *nDecimalValue = strtol(sHexString, endptr,hex);
  }
  return nRC;
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//  Description:
//       this function breaks a long string into two pieces
//
//  Input:
//       sInputString - the string to break into chuncks
//  Output:
//       sInputString - the string broken into chunks
//  Return:
//       void
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_BreakStringIntoChunksAndTrasmit(char *sInputString)
{
  int nSizeofString = 0;  
  int nCount = 0;
  int nMaxStringSize = 68;
  int nOffset = 0;
  int nChunk = 0;
  int nEndOfLine = FALSE;
  int nGetLastLine = FALSE;
  char sTransmitMessage[STR_LEN];
  char sTemp[STR_LEN];

  nSizeofString = strlen(sInputString);
  if (nSizeofString > nMaxStringSize)
  {
    nChunk = nMaxStringSize;

    while(nEndOfLine != TRUE) 
    {
      for (nCount = 0 ; nCount < nMaxStringSize; nCount++) 
      {
        sTemp[nCount] = sInputString[nOffset];        
        if (sInputString[nOffset] == '\0')
        {
          nEndOfLine = TRUE;
          sTemp[nCount] = '\0';
          break;
        }
        nOffset++;        
      }      
      if (sTemp[0] != '\0')
      {
        sprintf(sTransmitMessage, ";;%s", sTemp);
        transmit(sTransmitMessage);      
      }
      sTemp[0] = '\0';      
      nChunk = nChunk + nMaxStringSize;
    }
  }
  else
  {
    sprintf(sTransmitMessage, ";;%s", sInputString);

    transmit(sTransmitMessage);
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//  Description:
//       this bring up a dialog notifying the user that the script will end.
//
//  Input:
//       none 
//  Output:
//       none
//  Return:
//       void
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_ScriptUpdatedMustEndDialog(void)
{
  int rc = 0;
  char sTemp[STR_LEN];

  while (rc < 1)
  {
    if (rc >= 0)
    {
      dialog("Update complete!", 1, 1,
      "The script was updated successfully.", CTEXT | 1, 
      "The script must end in order to have the updates applied.", CTEXT | 1,
      "Please re-run the script if you would like to continue using this script.", CTEXT | 1,
      "End", BUTTON | 7, -1, -1, 100, 7);
    }
    sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
    rc = dialog(sTemp);
    if (rc == DIALOG_CLOSE)
    { 
      // user hit the x button in the corner of the dialog box
      COM_Done();
    }
  }
  COM_Done();
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//Description:
//     This function checks for a new file locations file.  If a new one is found under the master copies directory,
//     then UpdateFirmwareFiles() will be called and update all the files included in the file from the master directory.
//     The firmware files will be updated under sLocalHostPath.
//
//
//  Input:
//        sLocalDirectory - the directory to check for the current file version
//        sFileName - the name of the file to check for a update of
//        sFWType - MPE or MCE
//        sLocalHostPath - location of where files are on the computer running this script
//        sMasterReferenceFileDirectory - directory where the reference file lives
//        sMasterUpdateFileDirectory - directory where all the master files live 
//        nNumberOfFilesToUpdate - the number of files that could be possibly be updated referred to in the reference file
//
//  Output:
//       Nothing
//              
//
//  Return:
//       None
//       
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_UpdateFileRefFileAndFilesReferencedInIt(char *sLocalDirectory, 
                                                char *sFileName, 
                                                char *sFWType, 
                                                char *sLocalHostPath,
                                                char *sMasterReferenceFileDirectory,
                                                char *sMasterUpdateFileDirectory,
                                                int  nNumberOfFilesToUpdate)
{
  int nResult = FAILURE;

  char sLocalFilePath[STR_LEN];
  char sTempLocalFile[STR_LEN];
  char sTempLocalFilePath[STR_LEN];
  char sVersionName[STR_LEN];
  char sMasterFilePath[STR_LEN];
  char sSystemCmd[STR_LEN];

  float fCurrentFileVer = 0;
  float fFileVerFound = 0;

  int nEndScript = FALSE;
  
  strcpy(sLocalFilePath, sLocalDirectory);
  strcat(sLocalFilePath, sFileName);

  strcpy(sVersionName, VERSION_ID);

  COM_GetScriptVersion(30, 255, sVersionName, &fCurrentFileVer, sLocalFilePath);
 
  sprintf(sMasterFilePath, "%s%s", sMasterReferenceFileDirectory, sFileName);

  // update the file if the last version found was zero
  if (COM_GetScriptVersion(30, 255, sVersionName, &fFileVerFound, sMasterFilePath) == SUCCESS)
  {
    strcpy(sTempLocalFile, "TempUpdate.txt");

    if (COM_CheckVersionUpdateFile(fCurrentFileVer, 
                                   fFileVerFound, 
                                   sMasterFilePath, 
                                   sLocalDirectory, 
                                   sFWType, 
                                   nEndScript,
                                   sTempLocalFile) == SUCCESS)
    {
      Output("You will now be updated with the files that are referenced in the update file.", INFO_DIALOG_BOX, 0, "");
      
      COM_UpdateFilesInReferenceFile(sLocalDirectory, 
                                     sTempLocalFile, 
                                     sFWType, 
                                     sLocalHostPath, 
                                     sMasterUpdateFileDirectory,
                                     sVersionName,
                                     nNumberOfFilesToUpdate);           
      // update was successful

      // rename the temporary update file as the original
      sprintf(sTempLocalFilePath, "%s%s", sLocalDirectory, sTempLocalFile);

      nResult = COM_RenameFile(sTempLocalFilePath, sFileName);

    }
  }
  return (nResult);
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//Description:
//     This opens a file which includes paths to files.  It will examine each line for a file name.
//     If a file name is found, the function will copy the file from the master location to sLocalHostPath.
//
//
//  Input:
//        sLocalDirectory - the folder to check for the current file version
//        sFileName - the name of the file to check for a update of
//        sFWType - MPE or MCE
//        sLocalHostPath - location of where files are on the computer running this script
//        sMasterUpdateFileDirectory - directory where all the master files live 
//        sVersionName - flag to determine if end of files list has been reached
//        nNumberOfFilesToUpdate - the number of files that could be possibly be updated referred to in the reference file
//        
//
//  Output:
//       Nothing
//              
//
//  Return:
//       None
//       
//------------------------------------------------------------------------------------------------------------------------------------------------------------
void COM_UpdateFilesInReferenceFile(char *sLocalDirectory, 
                                    char *sFileName, 
                                    char *sFWType, 
                                    char *sLocalHostPath,
                                    char *sMasterUpdateFileDirectory,
                                    char *sVersionName, 
                                    int  nNumberOfFilesToUpdate)
{
  char sLocalFilePath[STR_LEN];
  char sFileLocations[MAX_NUM_OF_FILES_TO_UPDATE + MAX_NUM_OF_VERSION_INFO_LINES][STR_LEN];
  char sMasterFiles[MAX_NUM_OF_FILES_TO_UPDATE][STR_LEN];
  char sDestinationPaths[MAX_NUM_OF_FILES_TO_UPDATE][STR_LEN];
  char sFilename[STR_LEN];
  char sTemp[STR_LEN];
  char sTempFilePath[STR_LEN];
  char szSystemCmd[STR_LEN];

  int i = 0;
  int nNumofFileToUpdate = 0;
  int nDoNotSuspend = FALSE;
  int nStopSubstitution = FALSE;

  FILE *fpFile = NULL;               // file pointer
  
  strcpy(sLocalFilePath, sLocalDirectory);
  strcat(sLocalFilePath, sFileName);

  dialog("Copying files", 1, 1,
         "Copying files...",CTEXT | 1);

  
  if (!access(sLocalFilePath, 0))
  {
    sprintf(sTemp, "Opening %s...", sLocalFilePath);

    COM_Output(sTemp, INFORMATIVE, 0, "");
    
    if (COM_FileOpen(sLocalFilePath, MODE_READ_ONLY, &fpFile) == SUCCESS)
    {
      sprintf(sTemp, "Grabbing paths from %s...", sLocalFilePath);
      COM_Output(sTemp, INFORMATIVE, 0, "");
      for (i = 0 ; i < nNumberOfFilesToUpdate + MAX_NUM_OF_VERSION_INFO_LINES; i ++)
      {
        fgets(sFileLocations[i], 255, fpFile);
      }
      COM_FileClose(&fpFile);
    }
    else
    {
      sprintf(sTemp, "Cannot open file %s", sLocalFilePath);
      COM_Output(sTemp, INFORMATIVE, 0, "");
    }
  }  


  if (COM_FileOpen(sLocalFilePath, MODE_WRITE, &fpFile) == SUCCESS)
  {
    for (i = 0 ; i < nNumberOfFilesToUpdate && nStopSubstitution == FALSE; i ++)
    {
      // assign the drive letter of where SS is installed to each file location
      // do not modify an empty line of a line with the version flag
      if ( (sFileLocations[i][0] == '\0') || (strncmp(sFileLocations[i], sVersionName, strlen(sVersionName)) == 0) )
      {
        fputs(sFileLocations[i], fpFile);
      }
      else
      {
        sFileLocations[i][0] =  sLocalHostPath[0];      
        fputs(sFileLocations[i], fpFile);
      }
      fputs("\n", fpFile);           
    }
    for (i = nNumberOfFilesToUpdate; i < nNumberOfFilesToUpdate + MAX_NUM_OF_VERSION_INFO_LINES; i ++)
    {
      fputs(sFileLocations[i], fpFile);
      fputs("\n", fpFile);             
    }
    COM_FileClose(&fpFile);
  }
  else
  {
    sprintf(sTemp, "Cannot open file %s", sLocalFilePath);
    COM_Output(sTemp, INFORMATIVE, 0, "");
  }

  for (i = 0 ; i < nNumberOfFilesToUpdate; i ++)
  {
    COM_ExtractFileNameFromString(sFileLocations[i], sFilename);    
    if (sFilename[0] != '\0')
    {                         
      sprintf(sMasterFiles[nNumofFileToUpdate], "%s%s", sMasterUpdateFileDirectory, sFilename);

      COM_RemoveFileNameFromString(sFileLocations[i], sTempFilePath);
      strcpy(sDestinationPaths[nNumofFileToUpdate], sTempFilePath);
      nNumofFileToUpdate++;
    }
  }

  for (i = 0 ; i < nNumofFileToUpdate; i ++)
  {
    if (COM_CopyAndOverwriteFileNoCheck(sMasterFiles[i], sDestinationPaths[i], nDoNotSuspend, sFWType))
    {      
      ExitInError();
    }
  }
}

//------------------------------------------------------------------------------------------------------------------------------------------------------------
//  Description:
//       Renames a file
//
//  Input:
//       sFilePathToRename - path & filename of the file to rename
//       sFilenameToChangeTo  - the file name you want to change the original file name to
//
//  Output:
//       none
//
//  Return:
//       SUCCESS if the file was renamed
//------------------------------------------------------------------------------------------------------------------------------------------------------------
int COM_RenameFile(char *sFilePathToRename, char *sFilenameToChangeTo)
{
  int nResult = SUCCESS;
  char sSystemCmd[STR_LEN];

  sprintf(sSystemCmd, "ren \"%s\" %s", sFilePathToRename, sFilenameToChangeTo);

  if (system(sSystemCmd))
  {
    char sTemp[STR_LEN];
    sprintf(sTemp, "Renaming file path '%s' to '%s' failed!", sFilePathToRename, sFilenameToChangeTo);
    Output(sTemp, INFORMATIVE, 0, "");       
    nResult = FAILURE;
  } 
  return nResult; 
} 

//functions used by scripts other than FirmwareUpgrade.spt

void SignOn(void)
{
  COM_SignOn();
}

int Output(char *sOutputMessage, int nOutputMessageType, int nWaitTime, char *sWaitForString)
{
  return(COM_Output(sOutputMessage, nOutputMessageType, nWaitTime, sWaitForString));
}

int IsSpectrum(char *deviceType)
{
  return(COM_IsSpectrum(deviceType));
}

void GetDeviceInfo(char *deviceType, char *sFWType, float *upgradeVersion, int *baseTrendsetterMPE, int dualMCE, int noCodeOnBoard, float *FWversion, 
                   char *MCEFWversion, char *MCE2FWversion, int *nHeadType, float *fMCEFWVersion)
{
  COM_GetDeviceInfo(deviceType, sFWType, upgradeVersion, baseTrendsetterMPE, dualMCE, noCodeOnBoard, FWversion, 
                    MCEFWversion, MCE2FWversion, nHeadType, fMCEFWVersion);
}

void GetFWType(char *sFWType)
{
  COM_GetFWType(sFWType);
}

void Done(void)
{
  COM_Done();
}

void GetHeadType(char *sFWType, int *nHeadType)
{
  COM_GetHeadType(sFWType, nHeadType);
}

int GetHeadSerialNumber(int nTargetMCE, char *sFWType, char *sHeadSerialNumber, int nHeadType)
{
  return(COM_GetHeadSerialNumber(nTargetMCE, sFWType, sHeadSerialNumber, nHeadType));
}                                    

int RemoveCharactersFromString(char *cString, char *sArrayOfNum, int *nNumbersFound)
{  
  return(COM_RemoveCharactersFromString(cString, sArrayOfNum, nNumbersFound));
}

void GetHeadFWVersion(int nTargetMCE, char *sFWType, float *fHeadFWversion, int nHeadType)
{
  COM_GetHeadFWVersion(nTargetMCE, sFWType, fHeadFWversion, nHeadType);
}

void GetDeviceType(char *deviceType, char *sFWType, int baseTrendsetterMPE, int noCodeOnBoard)
{
  COM_GetDeviceType(deviceType, sFWType, baseTrendsetterMPE, noCodeOnBoard);
}

void GetFirmwareVersion(char *deviceType, char *sFWType, float *upgradeVersion, int *baseTrendsetterMPE, int dualMCE, int noCodeOnBoard, float *FWversion,
                            char *MCEFWversion, char *MCE2FWversion)  
{
  COM_GetFirmwareVersion(deviceType, sFWType, upgradeVersion, baseTrendsetterMPE, dualMCE, noCodeOnBoard, FWversion,
                         MCEFWversion, MCE2FWversion);
}

void ConvertFWVersionToFloat(char *MCEFWversion, float *fMCEFWVersion)
{
  COM_ConvertFWVersionToFloat(MCEFWversion, fMCEFWVersion);
}


//functions used by FirmwareUpgrade.spt

int CheckForBackslash(char *string, int type)
{
  return(COM_CheckForBackslash(string, type));
}

int CheckForPrompt(int suspend, int portNum, char *FWType, int dualMCE)
{
  return(COM_CheckForPrompt(suspend, portNum, FWType, dualMCE));
}

int CheckForMPEBootMode(int portNum)
{
  return(COM_CheckForMPEBootMode(portNum));
}
   
int CheckMPEBaudRate(int portNum)
{
  return(COM_CheckMPEBaudRate(portNum));
}

int ResetTheDevice(int type, int portNum, char *FWType, int dualMCE)
{
  return(COM_ResetTheDevice(type, portNum, FWType, dualMCE));
}

void GetDeviceIntoGoodStartingPoint(int portNum, char *FWType, int nTargetMCE, int *noCodeOnBoard, int *noCodeOnMCE2Board, int *backupBeforeLoading, 
                                    char *deviceMode)
{
  COM_GetDeviceIntoGoodStartingPoint(portNum, FWType, nTargetMCE, noCodeOnBoard, noCodeOnMCE2Board, backupBeforeLoading, 
                                     deviceMode);
}

int TestAndWaitForPrompt(int nTargetMCE, int waitCounter)
{
  return(COM_TestAndWaitForPrompt(nTargetMCE, waitCounter));
}

int TestAndWaitForMCEPrompt(int nTargetMCE, int waitCounter, char *deviceMode)
{
  return(COM_TestAndWaitForMCEPrompt(nTargetMCE, waitCounter, deviceMode));
}

int TestForTH2(char *FWType, int dualMCE, int *nOfflineStatus)
{
  return(COM_TestForTH2(FWType, dualMCE, nOfflineStatus));
}

int TestForTFX(char *sFWType, int nDualMCE, int *nOfflineStatus)
{
  return(COM_TestForTFX(sFWType, nDualMCE, nOfflineStatus));
}

void TestForTH1X(char *FWType, int dualMCE, int *nOfflineStatus)
{
  COM_TestForTH1X(FWType, dualMCE, nOfflineStatus);
}

void CheckForDualMCE(int *dualMCE)
{
  COM_CheckForDualMCE(dualMCE);
}

int CheckHostConfigForMCE2(int suspend)
{
  return(COM_CheckHostConfigForMCE2(suspend));
}

void GenerateFileName(char *file_loc, char *name, char *ext, char *path)
{
  COM_CheckForTheSameFileName(file_loc, name, ext, path);
}

int CreateFolder(char *pathname, char *FWType)
{    
  return(COM_CreateFolder(pathname, FWType));
}

int GetFileFromAnyLocation(char *pathOfFileToCopy, char *pathOfFileCopied, int type, char *FWType)
{
   int copyStatus;
  int fileExist = FALSE;
  int skipNextCopy = FALSE;
  int rc = 0;

  char fileToBeCopied[STR_LEN];
  char pathOfFileWithFileName[STR_LEN];
  char MPEtemp[STR_LEN];
  char installLocation[STR_LEN];
  char temp[STR_LEN];
  char tmp[STR_LEN];
  char transmitline[STR_LEN];
  
  ExtractFileNameFromString(pathOfFileToCopy, fileToBeCopied);

  strcpy(installLocation, pathOfFileCopied);
  strcat(pathOfFileCopied, fileToBeCopied);
  strcpy(temp, pathOfFileCopied);
 
  if (CheckForFileAvailability(pathOfFileCopied, 0) == 0)
  {
    #ifdef PRODUCTION
      fileExist = TRUE;  
    #else
      if (strcmp(pathOfFileToCopy, pathOfFileCopied) != 0)
      {
        while (rc < 9)
        {
          if (rc >= 0)
          {
            dialog("File exists", 1, 1,
                   "Copying a file to the service shell firmware directory.", CTEXT | 1,
                   "The folder already contains a file with the same name:", CTEXT | 1,
                   pathOfFileCopied, CTEXT | 5,
                   "Would you like to overwrite the existing file?", CTEXT | 8,
                   "NOTE: If you browsed to a file that is already located in the service shell firmware directory,", CTEXT | 1,
                   "click 'No' to avoid the copying a file that is already in the directory.", CTEXT | 1,
                   "Yes", BUTTON | 9, -1, -1, 100, 7,
                   "No", BUTTON | 10, -1, -1, 100, 7,
                   "Cancel", BUTTON | 11, -1, -1, 100, 7);
          }
          sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
          rc = dialog(tmp);
          if (rc == -2)
          { 
            // user hit the x button in the corner of the dialog box
            Done();
          }
        }
        // Erase the dialog box.
        dialog("");
        if (rc == 9)
        {
          fileExist = FALSE;  
        }
        if (rc == 10)
        {
          fileExist = TRUE;  
        }
        if (rc == 11)
        {
          return(1);
        }
      }
      else
      {
        fileExist = TRUE;
      }
    #endif
  }
  
  if (fileExist == FALSE)    
  {
    // check for delete temporary file just in case it exists and delete it if it does exist
    strcpy(pathOfFileCopied, installLocation);
    strcat(pathOfFileCopied, "temp.txt");
    if (CheckForFileAvailability(pathOfFileCopied, 0) == 0)
    {
      Output("Deleting file:", INFORMATIVE, 0,  "");
      strcpy(transmitline, pathOfFileCopied);
         
      Output(transmitline, INFORMATIVE, 0, "");
  
      //line below will hold the dos window open
      // sprintf(transmitline, "cmd /k del \"%s\"", pathOfFileCopied);
      sprintf(transmitline, "del \"%s\"", pathOfFileCopied);
      system(transmitline);
    }

    Output("Copying file:", INFORMATIVE, 0,  "");
    sprintf(transmitline, "%s", pathOfFileToCopy);
    
    Output(transmitline, INFORMATIVE, 0, "");

    Output("Copying file as:", INFORMATIVE, 0,  "");
    sprintf(transmitline, "%s", pathOfFileCopied);
    
    Output(transmitline, INFORMATIVE, 0, "");

    sprintf(tmp, "copy \"%s\" \"%s\"", pathOfFileToCopy, pathOfFileCopied);
    system(tmp);
    copyStatus = system(tmp);
    if (copyStatus == 0)
    {
      // Put this in for Win 95 (Win 95 always returns a zero whether or not the copy was successful)
      if (CheckForFileAvailability(pathOfFileCopied, 0))
      {
        copyStatus = 1;
      }
      else
      {
        Output("Copying file successful", INFORMATIVE, 0,  "");
      }
    }
    if (copyStatus == 1 )
    {
      rc = 0;

      Output("Copying file failed!", INFORMATIVE, 0,  "");
      if (type == 0)
      {
        while (rc < 8)
        {
          if (rc >= 0)
          {
            dialog("File not copied!", 1, 1,
                   pathOfFileToCopy, CTEXT | 1,
                   "Copying file failed!", CTEXT | 1,
                   "Copy ALL the files to be downloaded and paste them", CTEXT | 1,
                   "in the computer's directory specified below:", CTEXT | 1,
                   "Service Shell's Firmware directory: \\ServiceShell\\Firmware", CTEXT | 1,
                   "Hit Resume to continue.", CTEXT | 1,
                   "Main Menu", BUTTON | 8, -1, -1, 100, 7, 
                   "Resume", BUTTON | 9, -1, -1, 100, 7, 
                   "Quit", BUTTON | 10, -1, -1, 100, 7);
          }
          sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
          rc = dialog(tmp);
          if (rc == -2)
          { 
            // user hit the x button in the corner of the dialog box
            Done();
          }
        }
        // Erase the dialog box.
        dialog("");
        if (rc == 10)
        {
          ExitInError();
        }
        if (rc == 8)
        {
          return(1);
        }
        skipNextCopy = TRUE;
      }
      
    }
 
    strcpy(pathOfFileToCopy, pathOfFileCopied);
    strcat(pathOfFileCopied, fileToBeCopied);

    if (skipNextCopy == FALSE)
    {
      Output("Copying file:", INFORMATIVE, 0,  "");

      sprintf(transmitline, "%s", pathOfFileToCopy);
      
      Output(transmitline, INFORMATIVE, 0, "");

      Output("Copying file as:", INFORMATIVE, 0,  "");
      strcpy(pathOfFileCopied, temp);
      sprintf(transmitline, "%s", pathOfFileCopied);      
      Output(transmitline, INFORMATIVE, 0, "");

      sprintf(tmp, "copy \"%s\" \"%s\"", pathOfFileToCopy, pathOfFileCopied);
      system(tmp);
      copyStatus = system(tmp);
      if (copyStatus == 0)
      {
        // Put this in for Win 95 (Win 95 always returns a zero whether or not the copy was successful)
        if (CheckForFileAvailability(pathOfFileCopied, 0))
        {
          copyStatus = 1;
        }
        else
        {
          Output("Copying file successful", INFORMATIVE, 0,  "");
        }
      }
      if (copyStatus == 1 )
      {
        rc = 0;

        Output("Copying file failed!", INFORMATIVE, 0,  "");
        if (type == 0)
        {
          while (rc < 8)
          {
            if (rc >= 0)
            {
              dialog("File not copied!", 1, 1,
                     "Copying file failed", CTEXT | 2,
                     "Copy ALL the files to be downloaded and paste them", CTEXT | 3,
                     "in the computer's directory specified below:", CTEXT | 4,
                     "Service Shell's Firmware directory: \\ServiceShell\\Firmware", CTEXT | 5,
                     "Hit Resume to continue.", CTEXT | 8,
                     "Main Menu", BUTTON | 8, -1, -1, 100, 7,
                     "Resume", BUTTON | 9, -1, -1, 100, 7, 
                     "Quit", BUTTON | 10, -1, -1, 100, 7);
            }
            sleep(100);     // Sleep so we don't hog the CPU while polling the dialog.
            rc = dialog(tmp);
            if (rc == -2)
            { 
              // user hit the x button in the corner of the dialog box
              Done();
            }
          }
          // Erase the dialog box.
          dialog("");
          if (rc == 8)
          {
            return(1);
          }

          if (rc == 10)
          {
            ExitInError();
          }
        }
      }
      // delete temporary file
      Output("Deleting file:", INFORMATIVE, 0,  "");
      strcpy(transmitline, pathOfFileToCopy);
      
      Output(transmitline, INFORMATIVE, 0, "");

      sprintf(tmp, "del \"%s\"", pathOfFileToCopy);
      system(tmp);
    }
  }
  strcpy(pathOfFileToCopy, pathOfFileCopied);  
  return(0);
}

int GetFileFromAnyLocationNoCheck(char *pathOfFileToCopy, char *pathOfFileCopied, int type, char *FWType)
{
  return(COM_CopyAndOverwriteFileNoCheck(pathOfFileToCopy, pathOfFileCopied, type, FWType));
}

int SendFileToHost(char *pathOfFileToBeSent, char *destinationPathOfFileToBeSent, int type, char *FWType, char *connectionType, int *sendFileToHOST)
{
  return(COM_SendFileToHost(pathOfFileToBeSent, destinationPathOfFileToBeSent, type, FWType, connectionType, sendFileToHOST));
}

int GetFileFromHost(char *pathOfFileToRetrieve, char *pathOfReceived, int type, char *FWType, char *connectionType, int *sendFileToHOST, char *remoteHostPath)
{
  return(COM_GetFileFromHost(pathOfFileToRetrieve, pathOfReceived, type, FWType, connectionType, sendFileToHOST, remoteHostPath));
}

int CheckForFileAvailability(char *pathname, int suspend)
{  
  return(COM_CheckForFileAvailability(pathname, suspend));
}

int CopyFileToExternalLocation(char *pathOfFileToCopy, char *locationToCopyFile, int type, char *FWType)
{
  return(COM_CopyFileToExternalLocation(pathOfFileToCopy, locationToCopyFile, type, FWType));
}

void GetFileLocationsForHost(char *device, char *FWType, char *connectionType, int *sendFileToHOST, char *LocalHostPath, char *RemoteHostPath)
{
  COM_GetFileLocationsForHost(device, FWType, connectionType, sendFileToHOST, LocalHostPath, RemoteHostPath);
}

void TestSendingAFile(int testDifferentFolders, char *FWType, char *connectionType, int *sendFileToHOST, char *RemoteHostPath, char *LocalHostPath)
{
  COM_TestSendingAFile(testDifferentFolders, FWType, connectionType, sendFileToHOST, RemoteHostPath, LocalHostPath)
}  

void TestForServiceHostVersion(char *device)
{
  COM_TestForServiceHostVersion(device);
}

void GetConnectionType(char *connectionType)
{
  COM_GetConnectionType(connectionType);
}

int GetHeadInterfaceVersion(int nTargetMCE, char *FWType, float *fHeadInterfaceVersion, int nHeadType, char *deviceType)
{
  return(COM_GetHeadInterfaceVersion(nTargetMCE, FWType, fHeadInterfaceVersion, nHeadType, deviceType));
}

void GetSerialNumber(char *serialNumber, char *FWType, int noCodeOnBoard)
{
  COM_GetSerialNumber(serialNumber, FWType, noCodeOnBoard);
}

void GetOwnerName(char *ownerName, char *FWType, int noCodeOnBoard)
{
  COM_GetOwnerName(ownerName, FWType, noCodeOnBoard);
} 

void ExtractFileNameFromString(char *path, char *filename)
{ 
  COM_ExtractFileNameFromString(path, filename);
}

void ReplaceBackSlash(char *string)
{    
  COM_ReplaceBackSlash(string);
}

void GetPort(char *sConnectionType, int *nPort)
{
  COM_GetPort(sConnectionType, nPort);
}

int VerifyNVS(int noCodeOnBoard, int noCodeOnMCE2Board, int dualMCE)
{
 return(COM_VerifyNVS(noCodeOnBoard, noCodeOnMCE2Board, dualMCE));
}

int EraseNVS(int noCodeOnBoard , int noCodeOnMCE2Board, int nTargetMCE)
{
  return(COM_EraseNVS(noCodeOnBoard, noCodeOnMCE2Board, nTargetMCE));
}
