int   saveSettings()
{
    int res = 0;

    //char	temp[100];
    char	iniFilePath[MAX_FILE_NAME_LEN];
    FILE*	configFile;

    // Save the configuration data
    XPLMGetSystemPath(iniFilePath);
    strcat(iniFilePath, "Resources\\plugins\\" PLUGIN_NAME "\\" PLUGIN_NAME ".ini");

    configFile = fopen(iniFilePath, "w+t");

    if(NULL == configFile)
    {
        logMessageEx("*** Error saving configuration data");
        return -1;

    }

    fprintf(configFile, "%s\n", "[" INI_SECTION_POSITION "]");
    fprintf(configFile, "x=%d\n", g_pos_x);
    fprintf(configFile, "y=%d\n", g_pos_y);
    fprintf(configFile, "zoom=%f\n", g_zoom);

    fclose(configFile);

    logMessageEx("--- Configuration data saved");

    return res;
}
unsigned long TestHooks::TSK_pvg_get_msg(unsigned long p1, unsigned long p2)
{
    unsigned long res=0;
    unsigned long val1;
    unsigned long val2;

    unsigned long* pval1 = (unsigned long*)p1;
    unsigned long* pval2 = (unsigned long*)p2;
    *pval1 = 0;
    *pval2 = 0;

    val1 = *(unsigned long*)p1;
    val2 = *(unsigned long*)p2;

    logMessageEx("--- TestHooks::TSK_pvg_get_msg IN %08x [%08x], %08x [%08x] -> %08x", p1, val1, p2, val2, res);

    res =  m_TSK_pvg_get_msg_fn(p1, p2);
    //res = 1;

    if(0 == res)
    {
        *pval1 = *pval1 & 0x0000FFFF;
    }

    val1 = *(unsigned long*)p1;
    val2 = *(unsigned long*)p2;

    logMessageEx("--- TestHooks::TSK_pvg_get_msg %08x [%08x], %08x [%08x] -> %08x", p1, val1, p2, val2, res);

    return res;
}
int   loadSettings()
{
    int res = 0;

    char	iniFilePath[MAX_FILE_NAME_LEN];

    // Load the configuration data
    XPLMGetSystemPath(iniFilePath);
    strcat(iniFilePath, "Resources\\plugins\\" PLUGIN_NAME "\\" PLUGIN_NAME ".ini");

    // Read data from ini file
    CIniReader configReader(iniFilePath);
    logMessageEx("--- Configuration data loaded");


    g_pos_x = configReader.ReadInteger(INI_SECTION_POSITION, "x", 0);
    g_pos_y = configReader.ReadInteger(INI_SECTION_POSITION, "y", 0);
    g_zoom = configReader.ReadFloat(INI_SECTION_POSITION, "zoom", 100);

    logMessageEx("--- x=%d", g_pos_x);
    logMessageEx("--- y=%d", g_pos_y);
    logMessageEx("--- zoom=%f", g_zoom);


    return res;

}
int	createGNSWindow()
{
    int res = 0;

    XPLMCreateWindow_t win;
    win.structSize = sizeof(XPLMCreateWindow_t);
    win.left = g_pos_x;
    win.top = g_pos_y + (int)(gpGNSIntf->bezel_height*g_zoom);
    win.right = g_pos_x+(int)(gpGNSIntf->bezel_width*g_zoom);
    win.bottom = g_pos_y;
    win.visible = true;
    win.drawWindowFunc = myDrawWindowCallback;
    win.handleMouseClickFunc = myHandleMouseClickCallback;
    win.handleKeyFunc = myHandleKeyCallback;
    win.handleCursorFunc = myHandleCursorCallback;
    win.handleMouseWheelFunc = myHandleMouseWheelFunc;
    win.refcon = NULL;



    //Register the Draw Window
    // Create a windows for displaying the projection info
    gWindow = XPLMCreateWindowEx(&win);

    logMessageEx("--- GNS Window created");

    initTextures();
    logMessageEx("--- Textures created");

    /// Register so that our gauge is drawing during the Xplane gauge phase
    XPLMRegisterDrawCallback(myDrawGNSCallback, xplm_Phase_Window, 1, NULL); // before window draw
    logMessageEx("--- DrawCallback registered");

    //Register the callback for gUpdateInterval.  Positive intervals
    //are in seconds, negative are the negative of sim frames.  Zero
    //registers but does not schedule a callback for time.
    XPLMRegisterFlightLoopCallback(myFlightLoopCallback, gUpdateInterval, NULL);
    logMessageEx("--- FlightLoopCallback registered");

    //Set the initial values of the COM and NAV
    gGNSx30Proxy.setCOMActiveFrequency(XPLMGetDatai(g_com1_active_ref)*10);
    gGNSx30Proxy.setCOMStandbyFrequency(XPLMGetDatai(g_com1_standby_ref)*10);
    gGNSx30Proxy.setNAVActiveFrequency(XPLMGetDatai(g_nav1_active_ref)*10);
    gGNSx30Proxy.setNAVStandbyFrequency(XPLMGetDatai(g_nav1_standby_ref)*10);


    gnsOpened = true;

    return res;
}
PLUGIN_API void XPluginReceiveMessage(
    XPLMPluginID	inFromWho,
    long			inMessage,
    void *			inParam)
{
    char*	msg;

    if(XPLM_MSG_PLANE_CRASHED == inMessage)
        msg = "XPLM_MSG_PLANE_CRASHED";
    else if(XPLM_MSG_PLANE_LOADED == inMessage)
        msg = "XPLM_MSG_PLANE_LOADED";
    else if(XPLM_MSG_AIRPORT_LOADED == inMessage)
        msg = "XPLM_MSG_AIRPORT_LOADED";
    else if(XPLM_MSG_SCENERY_LOADED == inMessage)
        msg = "XPLM_MSG_SCENERY_LOADED";
    else if(XPLM_MSG_AIRPLANE_COUNT_CHANGED == inMessage)
        msg = "XPLM_MSG_AIRPLANE_COUNT_CHANGED";
    else if(XPLM_MSG_PLANE_UNLOADED == inMessage)
        msg = "XPLM_MSG_PLANE_UNLOADED";
    else
        msg = "UNKNOWN";


    logMessageEx("--- XPluginReceiveMessage %d [%s]", inMessage, msg);

}
void TestHooks::FIL_vfs_close(unsigned long p1)
{

    m_FIL_vfs_close_fn(p1);

    logMessageEx("--- TestHooks::FIL_vfs_close %08x", p1);

}
PLUGIN_API int XPluginEnable(void)
{
    gPluginEnabled = 1;

    logMessageEx("--- Plugin enabled");

    return 1;
}
//Resources
char*  TestHooks::TXT_get_string(unsigned long p1)
{
    char* res = m_TXT_get_string_fn(p1);

    logMessageEx("--- TestHooks::TXT_get_string %08x -> %s", p1, res);

    return res;
}
unsigned long TestHooks::TSK_pvg_get_timer(void)
{
    unsigned long res=0;

    res = m_TSK_pvg_get_timer_fn();

    logMessageEx("--- TestHooks::TSK_pvg_get_timer -> %d", res);

    return res;
}
unsigned long TestHooks::TSK_pvg_send_msg_ex(unsigned long p1, unsigned long p2)
{
    unsigned long res=0;

    res =  m_TSK_pvg_send_msg_ex_fn(p1, p2);

    logMessageEx("--- TestHooks::TSK_pvg_send_msg_ex %08x, %08x -> %08x", p1, p2, res);

    return res;
}
unsigned long TestHooks::FIL_vfs_open(char* name, unsigned long p1, unsigned long p2)
{
    unsigned long res=0;

    res = m_FIL_vfs_open_fn(name, p1, p2);

    logMessageEx("--- TestHooks::FIL_vfs_open %s %08x, %08x -> %08x", name, p1, p2,  res);

    return res;
}
unsigned long TestHooks::TSK_pvg_wait_evnt(unsigned long p1)
{
    unsigned long res=0;

    res = m_TSK_pvg_wait_evnt_fn(p1);

    logMessageEx("--- TestHooks::TSK_pvg_wait_evnt %08x -> %08x", p1, res);

    return res;
}
XPLMDataRef myXPLMFindDataRef(const char * inDataRefName)
{
    XPLMDataRef DataRef=XPLMFindDataRef(inDataRefName);
    if (DataRef==NULL)
    {
        logMessageEx("*** Cannot find data reference [%s]", inDataRefName);
    }

    return DataRef;
}
unsigned long TestHooks::FIL_vfs_mmap(unsigned long p1, unsigned long p2, unsigned long p3, unsigned long p4, unsigned long p5, unsigned long p6)
{
    unsigned long res=0;

    res = m_FIL_vfs_mmap_fn(p1, p2, p3, p4, p5, p6);

    logMessageEx("--- TestHooks::FIL_vfs_mmap %08x, %08x, %08x, %08x, %08x, %08x ->%08x", p1, p2, p3, p4, p5, p6, res);

    return res;
}
unsigned long TestHooks::TSK_pvg_proc_status(unsigned long p1)
{
    unsigned long res=0;

    res =  m_TSK_pvg_proc_status_fn(p1);

    logMessageEx("--- TestHooks::TSK_pvg_proc_status %08x  -> %08x", p1, res);

    return res;
}
unsigned long TestHooks::mem_unmap(unsigned long p1, unsigned long p2)
{
    unsigned long res=0;

    res = m_mem_unmap_fn(p1, p2);

    logMessageEx("--- TestHooks::mem_unmap %08x, %08x -> %08x", p1, p2, res);

    return res;
}
unsigned long TestHooks::FIL_vfs_write(unsigned long p1, unsigned long p2, unsigned long p3)
{
    unsigned long res=0;


    res = m_FIL_vfs_write_fn(p1, p2, p3);

    logMessageEx("--- TestHooks::FIL_vfs_write %08x, %08x, %08x ->%08x", p1, p2, p3, res);

    return res;
}
unsigned long TestHooks::FIL_vfs_rename(char* p1, char* p2)
{
    unsigned long res=0;


    res = m_FIL_vfs_rename_fn(p1, p2);

    logMessageEx("--- TestHooks::FIL_vfs_rename %s, %s -> %08x", p1, p2, res);

    return res;
}
int   unloadGNS()
{
    int res = 0;

    gpGNSIntf = NULL;
    gGNSx30Proxy.close();
    gGNSx30Proxy.terminate();

    logMessageEx("--- GNS uninitialized ");

    return res;
}
unsigned long TestHooks::HWM_pvg_get_obs(unsigned long p1)
{
    unsigned long res=0;

    res = m_HWM_pvg_get_obs_fn(p1);

    unsigned long* pAddr = (unsigned long*)p1;

    logMessageEx("--- TestHooks::HWM_pvg_get_obs %08x [%08x][%d]-> %08x", p1, *pAddr, *pAddr, res);

    return res;
}
unsigned long TestHooks::reg_write(unsigned long num, unsigned long *addr, unsigned long size, unsigned long p4)
{
    unsigned long res=0;

    unsigned long val = *(unsigned long*)addr;
    unsigned char ucval = *(unsigned char*)addr;
    logMessageEx("--- TestHooks::reg_write %08x, %08x [%d][%d], %08x, %08x -> %08x", num, addr,  val, ucval, size, p4, res);

    res = m_reg_write_fn(num, addr, size, p4);

    return res;
}
unsigned long TestHooks::SYS_pvg_var_ctrl(unsigned long p1, unsigned long p2)
{
    unsigned long res=0;

    //unsigned long val1 = *(unsigned long*)p1;
    unsigned long val2 = *(unsigned long*)p2;
    
    res = m_SYS_pvg_var_ctrl_fn(p1, p2);

    logMessageEx("--- TestHooks::SYS_pvg_var_ctrl %08x, %08x [%08x] -> %08x", p1, p2, val2, res);

    return res;
}
int	destroyGNSWindow()
{
    int res = 0;


    // Register so that our gauge is drawing during the Xplane gauge phase
    XPLMUnregisterDrawCallback(myDrawGNSCallback, xplm_Phase_Window, 0, NULL);
    logMessageEx("--- DrawCallback unregistered");

    // Unregister the callback
    XPLMUnregisterFlightLoopCallback(myFlightLoopCallback, NULL);
    logMessageEx("--- FlightLoopCallback unregistered");

    // Destroy GNS window
    XPLMDestroyWindow(gWindow);
    logMessageEx("--- GNS Window destroyed");

    //Gns500Intf.Close();

    gnsOpened = false;

    return res;

}
PLUGIN_API void	XPluginStop(void)
{

    if(gnsOpened)
    {
        destroyGNSWindow();
    }

    unloadGNS();

    saveSettings();

    logMessageEx("--- Plugin stopped");

}
int   loadGNS()
{
    int res = 0;

    bool hideGNSWindow = true; //Set this to true to hide the GNS window
    gGNSx30Proxy.initialize(hideGNSWindow);
    gGNSx30Proxy.open(TYPE_GNS530);

    gpGNSIntf = gGNSx30Proxy.getInterface();

    logMessageEx("--- GNS initialized");


    return res;
}
PLUGIN_API int XPluginStart(
    char *		outName,
    char *		outSig,
    char *		outDesc)
{
    // Provide our plugin's profile to the plugin system.
    strcpy(outName, PLUGIN_NAME);
    strcpy(outSig, "xplane.fly.elise-ng." PLUGIN_NAME);
    strcpy(outDesc, "Plugin interface to the Garmin GNS430/530 trainer.");

    if(0 != openLogFile())
    {
        return 0;
    }

    if(0 != loadSettings())
    {
        return 0;
    }

    if(0 != loadGNS())
    {
        return 0;
    }

    if(0 != initDataRefs())
    {
        return 0;
    }

    if(0 != createMenus())
    {
        return 0;
    }

    if(0 != initClickRegions())
    {
        return 0;
    }

    logMessageEx("--- Plugin started");


    return 1;
}
bool GNSx30Proxy::close()
{
	bool res = true;
	LRESULT r;

    if(stateOpened != m_state)
    {
        res = false;
        return res;
    }

	//Find the window handle and close the window
    if(NULL == 	m_win)	
    {
    	m_win = FindWindow("AfxFrameOrView42", "GARMIN 400W/500W Trainer");
    }
	//r = SendMessage(win, WM_QUIT, 0,0);      
	if(NULL != m_win)
	{
	
		r = PostMessage(m_win, WM_QUIT, 0,0);      

    }else
	{
		logMessageEx("??? GNSx30Proxy::Close Error finding window %s:%s" "AfxFrameOrView42", "GARMIN 400W/500W Trainer");	
	}

	m_win = NULL;

    m_pServerSocketThread->terminate();
    delete m_pServerSocketThread;
    m_pServerSocketThread = NULL;

    delete m_pClientSocket;
    m_pClientSocket = NULL;
    

    m_state = stateInitialized;

	return res;

}
PLUGIN_API void XPluginDisable(void)
{
    gPluginEnabled = 0;
    logMessageEx("--- Plugin disabled");
}
int   initDataRefs()
{
    int res = 0;

    bool	dataRefsFound = true;
    //data references
    g_latitude_ref = myXPLMFindDataRef("sim/flightmodel/position/latitude");
    if(NULL == g_latitude_ref) dataRefsFound=false;

    g_longitude_ref = myXPLMFindDataRef("sim/flightmodel/position/longitude");
    if(NULL == g_longitude_ref) dataRefsFound=false;

    g_heading_ref = myXPLMFindDataRef("sim/flightmodel/position/magpsi");
    if(NULL == g_heading_ref) dataRefsFound=false;

    g_groundspeed_ref = myXPLMFindDataRef("sim/flightmodel/position/groundspeed");
    if(NULL == g_groundspeed_ref) dataRefsFound=false;

    g_elevation_ref = myXPLMFindDataRef("sim/flightmodel/position/elevation");
    if(NULL == g_elevation_ref) dataRefsFound=false;

    g_vert_speed_ref = myXPLMFindDataRef("sim/flightmodel/position/vh_ind");
    if(NULL == g_vert_speed_ref) dataRefsFound=false;

    g_com1_standby_ref = myXPLMFindDataRef("sim/cockpit2/radios/actuators/com1_standby_frequency_hz");
    if(NULL == g_com1_standby_ref) dataRefsFound=false;

    g_com1_active_ref = myXPLMFindDataRef("sim/cockpit2/radios/actuators/com1_frequency_hz");
    if(NULL == g_com1_active_ref) dataRefsFound=false;

    g_nav1_standby_ref = myXPLMFindDataRef("sim/cockpit2/radios/actuators/nav1_standby_frequency_hz");
    if(NULL == g_com1_standby_ref) dataRefsFound=false;

    g_nav1_active_ref = myXPLMFindDataRef("sim/cockpit2/radios/actuators/nav1_frequency_hz");
    if(NULL == g_com1_active_ref) dataRefsFound=false;

    g_override_gps_ref = myXPLMFindDataRef("sim/operation/override/override_gps");
    if(NULL == g_override_gps_ref) dataRefsFound=false;

    //g_autopilot_mag_heading_ref = myXPLMFindDataRef("sim/cockpit/autopilot/heading_mag");
    //if(NULL == g_autopilot_mag_heading_ref) dataRefsFound=false;

    g_gps_fromto_ref = myXPLMFindDataRef("sim/cockpit/radios/gps_fromto");
    if(NULL == g_gps_fromto_ref) dataRefsFound=false;

    g_gps_course_degtm_ref = myXPLMFindDataRef("sim/cockpit/radios/gps_course_degtm");
    if(NULL == g_gps_course_degtm_ref) dataRefsFound=false;

    g_gps_hdef_dot_ref = myXPLMFindDataRef("sim/cockpit/radios/gps_hdef_dot");
    if(NULL == g_gps_hdef_dot_ref) dataRefsFound=false;

    g_gps_vdef_dot_ref = myXPLMFindDataRef("sim/cockpit/radios/gps_vdef_dot");
    if(NULL == g_gps_vdef_dot_ref) dataRefsFound=false;

    //g_gps_has_glideslope_ref = myXPLMFindDataRef("sim/cockpit/radios/gps_has_glideslope");
    //if(NULL == g_gps_has_glideslope_ref) dataRefsFound=false;

    //g_gps_slope_degt_ref = myXPLMFindDataRef("sim/cockpit/radios/gps_slope_degt");
    //if(NULL == g_gps_slope_degt_ref) dataRefsFound=false;

    //g_gps_dme_dist_m_ref = myXPLMFindDataRef("sim/cockpit/radios/gps_dme_dist_m");
    //if(NULL == g_gps_dme_dist_m_ref) dataRefsFound=false;

    //g_HSI_source_select_pilot_ref = myXPLMFindDataRef("sim/cockpit2/radios/actuators/HSI_source_select_pilot");
    //if(NULL == g_HSI_source_select_pilot_ref) dataRefsFound=false;

    //g_hsi_obs_deg_mag_pilot_ref = myXPLMFindDataRef("sim/cockpit2/radios/actuators/hsi_obs_deg_mag_pilot");
    //if(NULL == g_hsi_obs_deg_mag_pilot_ref) dataRefsFound=false;

    g_override_autopilot_ref = myXPLMFindDataRef("sim/operation/override/override_autopilot");
    if(NULL == g_override_autopilot_ref) dataRefsFound=false;

    g_autopilot_state_ref = myXPLMFindDataRef("sim/cockpit/autopilot/autopilot_state");
    if(NULL == g_autopilot_state_ref) dataRefsFound=false;

    /*
    	g_override_nav1_needles_ref = myXPLMFindDataRef("sim/operation/override/override_nav1_needles");
    	if(NULL == g_override_nav1_needles_ref) dataRefsFound=false;

    	g_nav1_hdef_dot_ref = myXPLMFindDataRef("sim/cockpit/radios/nav1_hdef_dot");
    	if(NULL == g_nav1_hdef_dot_ref) dataRefsFound=false;

    	g_nav1_vdef_dot_ref = myXPLMFindDataRef("sim/cockpit/radios/nav1_vdef_dot");
    	if(NULL == g_nav1_vdef_dot_ref) dataRefsFound=false;

    	g_nav1_fromto_ref = myXPLMFindDataRef("sim/cockpit/radios/nav1_fromto");
    	if(NULL == g_nav1_fromto_ref) dataRefsFound=false;
    */

    if(dataRefsFound)
    {
        logMessageEx("--- Data References retrieved");
    } else
    {
        logMessageEx("*** Error retrieving Data References");
        res = -1;
    }
    return res;
}
int createMenus()
{
    int res = 0;

    //Create the Show/Hide Data Menu
    //First we put a new menu item into the plugin menu.
    //This menu item will contain a submenu for us.
    myMenu = XPLMAppendMenuItem(
                 XPLMFindPluginsMenu(),	// Put in plugins menu
                 MENU_NAME,		// Item Title
                 0,						// Item Ref
                 1);						// Force English

    // Now create a submenu attached to our menu item. */
    mySubMenu = XPLMCreateMenu(
                    SUBMENU_NAME,
                    XPLMFindPluginsMenu(),
                    myMenu, 				// Menu Item to attach to.
                    myMenuHandlerCallback,	// The handler
                    0);						// Handler Ref

    // Append a few menu items to our submenu.  We will use the refcon to
    XPLMAppendMenuItem(
        mySubMenu,
        "Open",
        (void *) MENU_OPEN,
        1);

    XPLMAppendMenuItem(
        mySubMenu,
        "Close",
        (void *) MENU_CLOSE,
        1);


    XPLMAppendMenuSeparator(mySubMenu);

    XPLMAppendMenuItem(
        mySubMenu,
        "Show",
        (void *) MENU_SHOW,
        1);

    XPLMAppendMenuItem(
        mySubMenu,
        "Hide",
        (void *) MENU_HIDE,
        1);

    XPLMAppendMenuSeparator(mySubMenu);

    XPLMAppendMenuItem(
        mySubMenu,
        "Increase size",
        (void *) MENU_SIZE_INC,
        1);

    XPLMAppendMenuItem(
        mySubMenu,
        "Decrease size",
        (void *) MENU_SIZE_DEC,
        1);

    XPLMAppendMenuItem(
        mySubMenu,
        "Restore size",
        (void *) MENU_SIZE_RESTORE,
        1);


    XPLMAppendMenuSeparator(mySubMenu);

    myMenuItemWAASAutoipilot = XPLMAppendMenuItem(
                                   mySubMenu,
                                   "Autopilot connected",
                                   (void *) MENU_AUTOPILOT_CONNECTED,
                                   1);

    XPLMCheckMenuItem(mySubMenu, myMenuItemWAASAutoipilot, xplm_Menu_Unchecked);
    autopilotConnected = false;

    logMessageEx("--- Menu created");

    return res;
}