summaryrefslogblamecommitdiffstats
path: root/gui/pages.cpp
blob: 11fe9b080c54792d0a200d054cb01ba6f6ec6125 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

















                                                                            


















                       
                        
                               
































                                                                                            

















                                                          

















































































                                                                                                                                               
                                                  


               
                                                










                                                                                                 
                                                                                                             





















































































                                                                   





                                                                            


















                                                                      





                                                                                



                                                              
                                                      


























                                                                           
                                             
















                                                                                      
                                                     












                                                                 
                                                      
























































                                                                                                          
                                                              

















                                                                      
                                                               

















                                                                      
                                                                   
























                                                                 
                                                                      

































                                            
                                      



                                                         
                                      



                                            
                                  






















                                                          
                                                             






























































                                                                                                                 
                                                    













































































                                                                                          
                                                                         






















                                                                
                                                            









                                                                               
                                                 


















                                                                                       
                                                             











                                                         
                                                













                                                   
                                                          




                                                     
                                                       





                            
                                            
















                                                                     
                                            











































































































                                                                             
/*
	Copyright 2013 bigbiff/Dees_Troy TeamWin
	This file is part of TWRP/TeamWin Recovery Project.

	TWRP is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	TWRP is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with TWRP.  If not, see <http://www.gnu.org/licenses/>.
*/
// pages.cpp - Source to manage GUI base objects

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/reboot.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>

#include <string>

extern "C" {
#include "../twcommon.h"
#include "../minuitwrp/minui.h"
}

#include "rapidxml.hpp"
#include "objects.hpp"

extern int gGuiRunning;

std::map<std::string, PageSet*> PageManager::mPageSets;
PageSet* PageManager::mCurrentSet;
PageSet* PageManager::mBaseSet = NULL;


// Helper routine to convert a string to a color declaration
int ConvertStrToColor(std::string str, COLOR* color)
{
    // Set the default, solid black
    memset(color, 0, sizeof(COLOR));
    color->alpha = 255;

    // Translate variables
    DataManager::GetValue(str, str);
    
    // Look for some defaults
    if (str == "black")         return 0;
    else if (str == "white")    { color->red = color->green = color->blue = 255; return 0; }
    else if (str == "red")      { color->red = 255; return 0; }
    else if (str == "green")    { color->green = 255; return 0; }
    else if (str == "blue")     { color->blue = 255; return 0; }

    // At this point, we require an RGB(A) color
    if (str[0] != '#')          return -1;
    str.erase(0, 1);

	int result;
	if (str.size() >= 8) {
		// We have alpha channel
		string alpha = str.substr(6, 2);
		result = strtol(alpha.c_str(), NULL, 16);
		color->alpha = result & 0x000000FF;
		str.resize(6);
		result = strtol(str.c_str(), NULL, 16);
		color->red = (result >> 16) & 0x000000FF;
		color->green = (result >> 8) & 0x000000FF;
		color->blue = result & 0x000000FF;
	} else {
		result = strtol(str.c_str(), NULL, 16);
		color->red = (result >> 16) & 0x000000FF;
		color->green = (result >> 8) & 0x000000FF;
		color->blue = result & 0x000000FF;
	}
	return 0;
}

// Helper APIs
bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
{
    if (!node)      return false;

    std::string value;
    if (node->first_attribute("x"))
    {
        value = node->first_attribute("x")->value();
        DataManager::GetValue(value, value);
        *x = atol(value.c_str());
    }

    if (node->first_attribute("y"))
    {
        value = node->first_attribute("y")->value();
        DataManager::GetValue(value, value);
        *y = atol(value.c_str());
    }

    if (w && node->first_attribute("w"))
    {
        value = node->first_attribute("w")->value();
        DataManager::GetValue(value, value);
        *w = atol(value.c_str());
    }

    if (h && node->first_attribute("h"))
    {
        value = node->first_attribute("h")->value();
        DataManager::GetValue(value, value);
        *h = atol(value.c_str());
    }

    if (placement && node->first_attribute("placement"))
    {
        value = node->first_attribute("placement")->value();
        DataManager::GetValue(value, value);
        *placement = (RenderObject::Placement) atol(value.c_str());
    }

    return true;
}

int ActionObject::SetActionPos(int x, int y, int w, int h)
{
    if (x < 0 || y < 0)                                     return -1;

    mActionX = x; 
    mActionY = y; 
    if (w || h)
    {
        mActionW = w;
        mActionH = h;
    }
    return 0;
}

Page::Page(xml_node<>* page, xml_node<>* templates /* = NULL */)
{
    mTouchStart = NULL;

    // We can memset the whole structure, because the alpha channel is ignored
    memset(&mBackground, 0, sizeof(COLOR));

    // With NULL, we make a console-only display
    if (!page)
    {
        mName = "console";

        GUIConsole* element = new GUIConsole(NULL);
        mRenders.push_back(element);
        mActions.push_back(element);
        return;
    }

    if (page->first_attribute("name"))
        mName = page->first_attribute("name")->value();
    else
    {
        LOGERR("No page name attribute found!\n");
        return;
    }

    LOGINFO("Loading page %s\n", mName.c_str());

    // This is a recursive routine for template handling
    ProcessNode(page, templates);

    return;
}

bool Page::ProcessNode(xml_node<>* page, xml_node<>* templates /* = NULL */, int depth /* = 0 */)
{
    if (depth == 10)
    {
        LOGERR("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
        return false;
    }

    // Let's retrieve the background value, if any
    xml_node<>* bg = page->first_node("background");
    if (bg)
    {
        xml_attribute<>* attr = bg->first_attribute("color");
        if (attr)
        {
            std::string color = attr->value();
            ConvertStrToColor(color, &mBackground);
        }
    }

    xml_node<>* child;
    child = page->first_node("object");
    while (child)
    {
        if (!child->first_attribute("type"))
            break;

        std::string type = child->first_attribute("type")->value();

        if (type == "text")
        {
            GUIText* element = new GUIText(child);
            mRenders.push_back(element);
            mActions.push_back(element);
        }
        else if (type == "image")
        {
            GUIImage* element = new GUIImage(child);
            mRenders.push_back(element);
        }
        else if (type == "fill")
        {
            GUIFill* element = new GUIFill(child);
            mRenders.push_back(element);
        }
        else if (type == "action")
        {
            GUIAction* element = new GUIAction(child);
            mActions.push_back(element);
        }
        else if (type == "console")
        {
            GUIConsole* element = new GUIConsole(child);
            mRenders.push_back(element);
            mActions.push_back(element);
        }
        else if (type == "button")
        {
            GUIButton* element = new GUIButton(child);
            mRenders.push_back(element);
            mActions.push_back(element);
        }
        else if (type == "checkbox")
        {
            GUICheckbox* element = new GUICheckbox(child);
            mRenders.push_back(element);
            mActions.push_back(element);
        }
        else if (type == "fileselector")
        {
            GUIFileSelector* element = new GUIFileSelector(child);
            mRenders.push_back(element);
            mActions.push_back(element);
        }
        else if (type == "animation")
        {
            GUIAnimation* element = new GUIAnimation(child);
            mRenders.push_back(element);
        }
        else if (type == "progressbar")
        {
            GUIProgressBar* element = new GUIProgressBar(child);
            mRenders.push_back(element);
            mActions.push_back(element);
        }
		else if (type == "slider")
        {
            GUISlider* element = new GUISlider(child);
            mRenders.push_back(element);
            mActions.push_back(element);
        }
		else if (type == "slidervalue")
		{
			GUISliderValue *element = new GUISliderValue(child);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "listbox")
		{
			GUIListBox* element = new GUIListBox(child);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "keyboard")
		{
			GUIKeyboard* element = new GUIKeyboard(child);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
		else if (type == "input")
		{
			GUIInput* element = new GUIInput(child);
			mRenders.push_back(element);
			mActions.push_back(element);
			mInputs.push_back(element);
		}
		else if (type == "partitionlist")
		{
			GUIPartitionList* element = new GUIPartitionList(child);
			mRenders.push_back(element);
			mActions.push_back(element);
		}
        else if (type == "template")
        {
            if (!templates || !child->first_attribute("name"))
            {
                LOGERR("Invalid template request.\n");
            }
            else
            {
                std::string name = child->first_attribute("name")->value();

                // We need to find the correct template
                xml_node<>* node;
                node = templates->first_node("template");

                while (node)
                {
                    if (!node->first_attribute("name"))
                        continue;

                    if (name == node->first_attribute("name")->value())
                    {
                        if (!ProcessNode(node, templates, depth + 1))
                            return false;
                        else
                            break;
                    }
                    node = node->next_sibling("template");
                }
            }
        }
        else
        {
            LOGERR("Unknown object type.\n");
        }
        child = child->next_sibling("object");
    }
    return true;
}

int Page::Render(void)
{
    // Render background
    gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
    gr_fill(0, 0, gr_fb_width(), gr_fb_height());

    // Render remaining objects
    std::vector<RenderObject*>::iterator iter;
    for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
    {
        if ((*iter)->Render())
            LOGERR("A render request has failed.\n");
    }
    return 0;
}

int Page::Update(void)
{
    int retCode = 0;

    std::vector<RenderObject*>::iterator iter;
    for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
    {
        int ret = (*iter)->Update();
        if (ret < 0)
            LOGERR("An update request has failed.\n");
        else if (ret > retCode)
            retCode = ret;
    }

    return retCode;
}

int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
{
    // By default, return 1 to ignore further touches if nobody is listening
    int ret = 1;

    // Don't try to handle a lack of handlers
    if (mActions.size() == 0)   return ret;

    // We record mTouchStart so we can pass all the touch stream to the same handler
    if (state == TOUCH_START)
    {
        std::vector<ActionObject*>::reverse_iterator iter;
        // We work backwards, from top-most element to bottom-most element
        for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
        {
            if ((*iter)->IsInRegion(x, y))
            {
                mTouchStart = (*iter);
                ret = mTouchStart->NotifyTouch(state, x, y);
                if (ret >= 0)   break;
                mTouchStart = NULL;
            }
        }
    }
    else if (state == TOUCH_RELEASE && mTouchStart != NULL)
    {
        ret = mTouchStart->NotifyTouch(state, x, y);
        mTouchStart = NULL;
    }
    else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
    {
        ret = mTouchStart->NotifyTouch(state, x, y);
    }
    return ret;
}

int Page::NotifyKey(int key)
{
    std::vector<ActionObject*>::reverse_iterator iter;

    // Don't try to handle a lack of handlers
    if (mActions.size() == 0)   return 1;

    // We work backwards, from top-most element to bottom-most element
    for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
    {
        int ret = (*iter)->NotifyKey(key);
        if (ret == 0)
            return 0;
        else if (ret < 0)
            LOGERR("An action handler has returned an error");
    }
    return 1;
}

int Page::NotifyKeyboard(int key)
{
    std::vector<InputObject*>::reverse_iterator iter;

    // Don't try to handle a lack of handlers
    if (mInputs.size() == 0)   return 1;

    // We work backwards, from top-most element to bottom-most element
    for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
    {
        int ret = (*iter)->NotifyKeyboard(key);
        if (ret == 0)
            return 0;
        else if (ret < 0)
            LOGERR("A keyboard handler has returned an error");
    }
    return 1;
}

int Page::SetKeyBoardFocus(int inFocus)
{
    std::vector<InputObject*>::reverse_iterator iter;

    // Don't try to handle a lack of handlers
    if (mInputs.size() == 0)   return 1;

    // We work backwards, from top-most element to bottom-most element
    for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
    {
        int ret = (*iter)->SetInputFocus(inFocus);
        if (ret == 0)
            return 0;
        else if (ret < 0)
            LOGERR("An input focus handler has returned an error");
    }
    return 1;
}

void Page::SetPageFocus(int inFocus)
{
    // Render remaining objects
    std::vector<RenderObject*>::iterator iter;
    for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
    {
        (*iter)->SetPageFocus(inFocus);
    }
    return;
}

int Page::NotifyVarChange(std::string varName, std::string value)
{
    std::vector<ActionObject*>::iterator iter;

    // Don't try to handle a lack of handlers
    if (mActions.size() == 0)   return 1;

    for (iter = mActions.begin(); iter != mActions.end(); ++iter)
    {
        if ((*iter)->NotifyVarChange(varName, value))
            LOGERR("An action handler errored on NotifyVarChange.\n");
    }
    return 0;
}

PageSet::PageSet(char* xmlFile)
{
    mResources = NULL;
    mCurrentPage = NULL;
    mOverlayPage = NULL;

    mXmlFile = xmlFile;
    if (xmlFile)
        mDoc.parse<0>(mXmlFile);
    else
        mCurrentPage = new Page(NULL);
}

PageSet::~PageSet()
{
    delete mResources;
    free(mXmlFile);
}

int PageSet::Load(ZipArchive* package)
{
    xml_node<>* parent;
    xml_node<>* child;
    xml_node<>* templates;
 
    parent = mDoc.first_node("recovery");
    if (!parent)
        parent = mDoc.first_node("install");

    // Now, let's parse the XML
    LOGINFO("Loading resources...\n");
    child = parent->first_node("resources");
    if (child)
        mResources = new ResourceManager(child, package);

    LOGINFO("Loading variables...\n");
    child = parent->first_node("variables");
    if (child)
        LoadVariables(child);

    LOGINFO("Loading pages...\n");
    // This may be NULL if no templates are present
    templates = parent->first_node("templates");

    child = parent->first_node("pages");
    if (!child)
        return -1;

    return LoadPages(child, templates);
}

int PageSet::SetPage(std::string page)
{
    Page* tmp = FindPage(page);
    if (tmp)
    {
        if (mCurrentPage)   mCurrentPage->SetPageFocus(0);
        mCurrentPage = tmp;
        mCurrentPage->SetPageFocus(1);
        mCurrentPage->NotifyVarChange("", "");
        return 0;
    }
    else
    {
        LOGERR("Unable to locate page (%s)\n", page.c_str());
    }
    return -1;
}

int PageSet::SetOverlay(Page* page)
{
    if (mOverlayPage)   mOverlayPage->SetPageFocus(0);
    mOverlayPage = page;
    if (mOverlayPage)
    {
        mOverlayPage->SetPageFocus(1);
        mOverlayPage->NotifyVarChange("", "");
    }
    return 0;
}

Resource* PageSet::FindResource(std::string name)
{
    return mResources ? mResources->FindResource(name) : NULL;
}

Page* PageSet::FindPage(std::string name)
{
    std::vector<Page*>::iterator iter;

    for (iter = mPages.begin(); iter != mPages.end(); iter++)
    {
        if (name == (*iter)->GetName())
            return (*iter);
    }
    return NULL;
}

int PageSet::LoadVariables(xml_node<>* vars)
{
    xml_node<>* child;

    child = vars->first_node("variable");
    while (child)
    {
        if (!child->first_attribute("name"))
            break;
        if (!child->first_attribute("value"))
            break;

        DataManager::SetValue(child->first_attribute("name")->value(), child->first_attribute("value")->value());
        child = child->next_sibling("variable");
    }
    return 0;
}

int PageSet::LoadPages(xml_node<>* pages, xml_node<>* templates /* = NULL */)
{
    xml_node<>* child;

    if (!pages)    return -1;

    child = pages->first_node("page");
    while (child != NULL)
    {
        Page* page = new Page(child, templates);
        if (page->GetName().empty())
        {
            LOGERR("Unable to process load page\n");
            delete page;
        }
        else
        {
            mPages.push_back(page);
        }
        child = child->next_sibling("page");
    }
    if (mPages.size() > 0)
        return 0;
    return -1;
}

int PageSet::IsCurrentPage(Page* page)
{
    return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
}

int PageSet::Render(void)
{
    int ret;

    ret = (mCurrentPage ? mCurrentPage->Render() : -1);
    if (ret < 0)    return ret;
    ret = (mOverlayPage ? mOverlayPage->Render() : -1);
    return ret;
}

int PageSet::Update(void)
{
    int ret;

    ret = (mCurrentPage ? mCurrentPage->Update() : -1);
    if (ret < 0 || ret > 1)     return ret;
    ret = (mOverlayPage ? mOverlayPage->Update() : -1);
    return ret;
}

int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
{
    if (mOverlayPage)   return (mOverlayPage->NotifyTouch(state, x, y));
    return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
}

int PageSet::NotifyKey(int key)
{
    if (mOverlayPage)   return (mOverlayPage->NotifyKey(key));
    return (mCurrentPage ? mCurrentPage->NotifyKey(key) : -1);
}

int PageSet::NotifyKeyboard(int key)
{
    if (mOverlayPage)   return (mOverlayPage->NotifyKeyboard(key));
    return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
}

int PageSet::SetKeyBoardFocus(int inFocus)
{
    if (mOverlayPage)   return (mOverlayPage->SetKeyBoardFocus(inFocus));
    return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
}

int PageSet::NotifyVarChange(std::string varName, std::string value)
{
    if (mOverlayPage)   mOverlayPage->NotifyVarChange(varName, value);
    return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
}

int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
{
    int fd;
    ZipArchive zip, *pZip = NULL;
    long len;
    char* xmlFile = NULL;
    PageSet* pageSet = NULL;
    int ret;

    // Open the XML file
    LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
    if (mzOpenZipArchive(package.c_str(), &zip))
    {
        // We can try to load the XML directly...
        struct stat st;
        if(stat(package.c_str(),&st) != 0)
            return -1;

        len = st.st_size;
        xmlFile = (char*) malloc(len + 1);
        if (!xmlFile)       return -1;

        fd = open(package.c_str(), O_RDONLY);
        if (fd == -1)       goto error;

        read(fd, xmlFile, len);
        close(fd);
    }
    else
    {
        pZip = &zip;
        const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
        if (ui_xml == NULL)
        {
            LOGERR("Unable to locate ui.xml in zip file\n");
            goto error;
        }
    
        // Allocate the buffer for the file
        len = mzGetZipEntryUncompLen(ui_xml);
        xmlFile = (char*) malloc(len + 1);
        if (!xmlFile)        goto error;
    
        if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
        {
            LOGERR("Unable to extract ui.xml\n");
            goto error;
        }
    }

    // NULL-terminate the string
    xmlFile[len] = 0x00;

    // Before loading, mCurrentSet must be the loading package so we can find resources
    pageSet = mCurrentSet;
    mCurrentSet = new PageSet(xmlFile);

    ret = mCurrentSet->Load(pZip);
    if (ret == 0)
    {
        mCurrentSet->SetPage(startpage);
        mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
    }
    else
    {
        LOGERR("Package %s failed to load.\n", name.c_str());
    }
	
    // The first successful package we loaded is the base
    if (mBaseSet == NULL)
        mBaseSet = mCurrentSet;

    mCurrentSet = pageSet;

    if (pZip)   mzCloseZipArchive(pZip);
    return ret;

error:
    LOGERR("An internal error has occurred.\n");
    if (pZip)       mzCloseZipArchive(pZip);
    if (xmlFile)    free(xmlFile);
    return -1;
}

PageSet* PageManager::FindPackage(std::string name)
{
    std::map<std::string, PageSet*>::iterator iter;

    iter = mPageSets.find(name);
    if (iter != mPageSets.end())
    {
        return (*iter).second;
    }
    LOGERR("Unable to locate package %s\n", name.c_str());
    return NULL;
}

PageSet* PageManager::SelectPackage(std::string name)
{
    LOGINFO("Switching packages (%s)\n", name.c_str());
    PageSet* tmp;

    tmp = FindPackage(name);
    if (tmp)
        mCurrentSet = tmp;
    else
        LOGERR("Unable to find package.\n");

    return mCurrentSet;
}

int PageManager::ReloadPackage(std::string name, std::string package)
{
    std::map<std::string, PageSet*>::iterator iter;

    iter = mPageSets.find(name);
    if (iter == mPageSets.end())
        return -1;

    PageSet* set = (*iter).second;
    mPageSets.erase(iter);

    if (LoadPackage(name, package, "main") != 0)
    {
        LOGERR("Failed to load package.\n");
        mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
        return -1;
    }
    if (mCurrentSet == set)     SelectPackage(name);
    delete set;
    return 0;
}

void PageManager::ReleasePackage(std::string name)
{
    std::map<std::string, PageSet*>::iterator iter;

    iter = mPageSets.find(name);
    if (iter == mPageSets.end())
        return;

    PageSet* set = (*iter).second;
    mPageSets.erase(iter);
    delete set;
    return;
}

int PageManager::ChangePage(std::string name)
{
    DataManager::SetValue("tw_operation_state", 0);
    int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
    return ret;
}

int PageManager::ChangeOverlay(std::string name)
{
    if (name.empty())
        return mCurrentSet->SetOverlay(NULL);
    else
    {
        Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
        return mCurrentSet->SetOverlay(page);
    }
}

Resource* PageManager::FindResource(std::string name)
{
    return (mCurrentSet ? mCurrentSet->FindResource(name) : NULL);
}

Resource* PageManager::FindResource(std::string package, std::string name)
{
    PageSet* tmp;

    tmp = FindPackage(name);
    return (tmp ? tmp->FindResource(name) : NULL);
}

int PageManager::SwitchToConsole(void)
{
    PageSet* console = new PageSet(NULL);

    mCurrentSet = console;
    return 0;
}

int PageManager::IsCurrentPage(Page* page)
{
    return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
}

int PageManager::Render(void)
{
    return (mCurrentSet ? mCurrentSet->Render() : -1);
}

int PageManager::Update(void)
{
    return (mCurrentSet ? mCurrentSet->Update() : -1);
}

int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
{
    return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
}

int PageManager::NotifyKey(int key)
{
    return (mCurrentSet ? mCurrentSet->NotifyKey(key) : -1);
}

int PageManager::NotifyKeyboard(int key)
{
    return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
}

int PageManager::SetKeyBoardFocus(int inFocus)
{
    return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
}

int PageManager::NotifyVarChange(std::string varName, std::string value)
{
    return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
}

extern "C" void gui_notifyVarChange(const char *name, const char* value)
{
    if (!gGuiRunning)   return;

    PageManager::NotifyVarChange(name, value);
}