Rev 446 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/*
* Copyright (C) 2021, 2022 by Andreas Theofilu <andreas@theosys.at>
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "texternal.h"
#include "terror.h"
#include "tconfig.h"
#include "texpat++.h"
#include "ttpinit.h"
#if __cplusplus < 201402L
# error "This module requires at least C++14 standard!"
#else
# if __cplusplus < 201703L
# include <experimental/filesystem>
namespace fs = std::experimental::filesystem;
# warning "Support for C++14 and experimental filesystem will be removed in a future version!"
# else
# include <filesystem>
# ifdef __ANDROID__
namespace fs = std::__fs::filesystem;
# else
namespace fs = std::filesystem;
# endif
# endif
#endif
using std::string;
using std::vector;
using namespace Expat;
TExternal::TExternal()
{
DECL_TRACER("TExternal::TExternal()");
string projectPath = TConfig::getProjectPath();
if (!fs::exists(projectPath + "/prj.xma"))
projectPath += "/__system";
makeFileName(projectPath, "external.xma");
if (!isValidFile())
{
TError::setErrorMsg(TERRERROR, "Invalid file name " + getFileName());
return;
}
mFileName = getFileName();
initialize();
}
void TExternal::setFileName(const string &fn)
{
DECL_TRACER("TExternal::setFileName(const string &fn)");
string projectPath = TConfig::getProjectPath();
if (!fs::exists(projectPath + "/prj.xma"))
projectPath += "/__system";
makeFileName(projectPath, fn);
if (!isValidFile())
{
TError::setErrorMsg(TERRERROR, "Invalid file name " + getFileName());
return;
}
mFileName = getFileName();
initialize();
}
void TExternal::initialize()
{
DECL_TRACER("TExternal::initialize()");
TExpat xml(mFileName);
if (!TTPInit::isTP5())
xml.setEncoding(ENC_CP1250);
else
xml.setEncoding(ENC_UTF8);
if (!xml.parse())
return;
int depth = 0;
size_t index = 0;
size_t oldIndex = 0;
if (xml.getElementIndex("externalButtons", &depth) == TExpat::npos)
{
MSG_ERROR("Element \"externalButtons\" was not found!");
TError::setError();
return;
}
EXTPAGE_t page;
depth++;
while ((index = xml.getNextElementIndex("page", depth)) != TExpat::npos)
{
string name, content;
vector<ATTRIBUTE_t> attrs;
while ((index = xml.getNextElementFromIndex(index, &name, &content, &attrs)) != TExpat::npos)
{
string e = name;
if (e.compare("pageID") == 0)
page.pageID = xml.convertElementToInt(content);
else if (e.compare("name") == 0)
page.name = content;
else if (e.compare("button") == 0)
{
EXTBUTTON_t button;
string atype = xml.getAttribute("type", attrs);
if (!atype.empty() && atype.compare("external") != 0)
{
MSG_WARNING("Found unknown button type " << atype << "!");
continue;
}
while ((index = xml.getNextElementFromIndex(index, &name, &content, &attrs)) != TExpat::npos)
{
if (name.compare("bi") == 0)
button.bi = xml.convertElementToInt(content);
else if (name.compare("bc") == 0)
{
button.bc = content;
if (button.bc.compare("cursorLeft") == 0)
button.type = EXT_CURSOR_LEFT;
else if (button.bc.compare("cursorRight") == 0)
button.type = EXT_CURSOR_RIGHT;
else if (button.bc.compare("cursorUp") == 0)
button.type = EXT_CURSOR_UP;
else if (button.bc.compare("cursorDown") == 0)
button.type = EXT_CURSOR_DOWN;
else if (button.bc.compare("cursorSel") == 0)
button.type = EXT_CURSOR_SELECT;
else if (button.bc.compare("cursorRotateRight") == 0)
button.type = EXT_CURSOR_ROTATE_RIGHT;
else if (button.bc.compare("cursorRotateLeft") == 0)
button.type = EXT_CURSOR_ROTATE_LEFT;
else if (button.bc.compare("gestureLeft") == 0)
button.type = EXT_GESTURE_LEFT;
else if (button.bc.compare("gestureRight") == 0)
button.type = EXT_GESTURE_RIGHT;
else if (button.bc.compare("gestureUp") == 0)
button.type = EXT_GESTURE_UP;
else if (button.bc.compare("gestureDown") == 0)
button.type = EXT_GESTURE_DOWN;
else if (button.bc.compare("gestureRotateLeft") == 0)
button.type = EXT_GESTURE_ROTATE_LEFT;
else if (button.bc.compare("gestureRotateRight") == 0)
button.type = EXT_GESTURE_ROTATE_RIGHT;
else if (button.bc.compare("gestureDoublePress") == 0)
button.type = EXT_GESTURE_DOUBLE_PRESS;
else if (button.bc.compare("general") == 0)
button.type = EXT_GENERAL;
}
else if (name.compare("na") == 0)
button.na = content;
else if (name.compare("da") == 0)
button.da = xml.convertElementToInt(content);
else if (name.compare("pp") == 0)
button.pp = content;
else if (name.compare("ap") == 0)
button.ap = xml.convertElementToInt(content);
else if (name.compare("ad") == 0)
button.ad = xml.convertElementToInt(content);
else if (name.compare("cp") == 0)
button.cp = xml.convertElementToInt(content);
else if (name.compare("ch") == 0)
button.ch = xml.convertElementToInt(content);
else if (name.compare("rt") == 0)
button.rt = content;
else if (name.compare("vt") == 0)
button.vt = content;
else if (name.compare("lp") == 0)
button.lp = xml.convertElementToInt(content);
else if (name.compare("lv") == 0)
button.lv = xml.convertElementToInt(content);
else if (name.compare("va") == 0)
button.va = xml.convertElementToInt(content);
else if (name.compare("rv") == 0)
button.rv = xml.convertElementToInt(content);
else if (name.compare("rl") == 0)
button.rl = xml.convertElementToInt(content);
else if (name.compare("rh") == 0)
button.rh = xml.convertElementToInt(content);
else if (name.compare("lu") == 0)
button.lu = xml.convertElementToInt(content);
else if (name.compare("ld") == 0)
button.ld = xml.convertElementToInt(content);
else if (name.compare("so") == 0)
button.so = xml.convertElementToInt(content);
else if (name.compare("co") == 0)
button.co = xml.convertElementToInt(content);
else if (name.compare("cm") == 0)
button.cm.push_back(content);
else if (name.compare("ac") == 0)
{
button.ac = content;
button.ac_de = xml.getAttributeInt("de", attrs);
}
else if (name.compare("at") == 0)
button.at = xml.convertElementToInt(content);
oldIndex = index;
}
page.buttons.push_back(button);
}
mPages.push_back(page);
page.buttons.clear();
if (index == TExpat::npos)
index = oldIndex + 1;
else
oldIndex = index;
}
if (index == TExpat::npos)
index = oldIndex + 1;
else
oldIndex = index;
xml.setIndex(index);
}
/*
if (TStreamError::checkFilter(HLOG_DEBUG))
{
vector<EXTPAGE_t>::iterator iter;
for (iter = mPages.begin(); iter != mPages.end(); ++iter)
{
MSG_DEBUG("Name : " << iter->name);
MSG_DEBUG("pageID: " << iter->pageID);
vector<EXTBUTTON_t>::iterator ibut;
for (ibut = iter->buttons.begin(); ibut != iter->buttons.end(); ++ibut)
{
MSG_DEBUG(" Button index: " << ibut->bi);
MSG_DEBUG(" Button name : " << ibut->na);
MSG_DEBUG(" Button bc : " << ibut->bc);
}
}
}
*/
}
EXTBUTTON_t TExternal::getButton(extButtons_t bt)
{
DECL_TRACER("TExternal::getButton(extButtons_t bt)");
EXTBUTTON_t empty;
if (mPages.size() == 0)
{
MSG_DEBUG("No pages found.");
return empty;
}
vector<EXTPAGE_t>::iterator piter;
for (piter = mPages.begin(); piter != mPages.end(); ++piter)
{
MSG_DEBUG("Found page " << piter->name);
if (piter->buttons.size() == 0)
continue;
vector<EXTBUTTON_t>::iterator btIter;
for (btIter = piter->buttons.begin(); btIter != piter->buttons.end(); ++btIter)
{
MSG_DEBUG("Found button " << btIter->na << ", type=" << btIter->type << " (" << bt << ")");
if (btIter->type == bt || (!mStrict && btIter->type == findCompatibel(bt)))
return *btIter;
}
}
return empty;
}
EXTBUTTON_t TExternal::getButton(int pageId, extButtons_t bt)
{
DECL_TRACER("TExternal::getButton(int pageId, extButtons_t bt)");
EXTBUTTON_t empty;
if (mPages.size() == 0)
return empty;
vector<EXTPAGE_t>::iterator piter;
for (piter = mPages.begin(); piter != mPages.end(); ++piter)
{
if (piter->pageID != pageId)
continue;
if (piter->buttons.size() == 0)
continue;
vector<EXTBUTTON_t>::iterator btIter;
for (btIter = piter->buttons.begin(); btIter != piter->buttons.end(); ++btIter)
{
if (btIter->type == bt || (!mStrict && btIter->type == findCompatibel(bt)))
return *btIter;
}
}
return empty;
}
extButtons_t TExternal::findCompatibel(extButtons_t bt)
{
DECL_TRACER("TExternal::findCompatibel(extButtons_t bt)");
switch(bt)
{
case EXT_CURSOR_DOWN: return EXT_GESTURE_DOWN;
case EXT_CURSOR_LEFT: return EXT_GESTURE_LEFT;
case EXT_CURSOR_RIGHT: return EXT_GESTURE_RIGHT;
case EXT_CURSOR_UP: return EXT_GESTURE_UP;
case EXT_CURSOR_ROTATE_LEFT: return EXT_GESTURE_ROTATE_LEFT;
case EXT_CURSOR_ROTATE_RIGHT: return EXT_GESTURE_ROTATE_RIGHT;
case EXT_CURSOR_SELECT: return EXT_GESTURE_DOUBLE_PRESS;
case EXT_GESTURE_DOWN: return EXT_CURSOR_DOWN;
case EXT_GESTURE_RIGHT: return EXT_CURSOR_RIGHT;
case EXT_GESTURE_UP: return EXT_CURSOR_UP;
case EXT_GESTURE_LEFT: return EXT_CURSOR_LEFT;
case EXT_GESTURE_ROTATE_LEFT: return EXT_CURSOR_ROTATE_LEFT;
case EXT_GESTURE_ROTATE_RIGHT: return EXT_CURSOR_ROTATE_RIGHT;
case EXT_GESTURE_DOUBLE_PRESS: return EXT_CURSOR_SELECT;
default:
return bt;
}
}