blob: 9bff289d32be0eb1d9fe1cc5758c21a30b4ab7af [file] [log] [blame]
Dees_Troya13d74f2013-03-24 08:54:55 -05001/*
2 Copyright 2013 bigbiff/Dees_Troy TeamWin
3 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
Dees Troy3be70a82013-10-22 14:25:12 +000018
Dees_Troya13d74f2013-03-24 08:54:55 -050019// pages.cpp - Source to manage GUI base objects
Dees_Troy51a0e822012-09-05 15:24:24 -040020
21#include <stdarg.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <fcntl.h>
26#include <sys/reboot.h>
27#include <sys/stat.h>
28#include <sys/time.h>
29#include <sys/mman.h>
30#include <sys/types.h>
31#include <sys/ioctl.h>
32#include <time.h>
33#include <unistd.h>
34#include <stdlib.h>
Ethan Yonkera2dc2f22014-11-08 08:13:40 -060035#include "../twrp-functions.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040036
37#include <string>
38
39extern "C" {
Dees_Troy2673cec2013-04-02 20:22:16 +000040#include "../twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040041#include "../minuitwrp/minui.h"
Ethan Yonkera2dc2f22014-11-08 08:13:40 -060042#include "../minzip/SysUtil.h"
43#include "../minzip/Zip.h"
Ethan Yonker63e414f2015-02-06 15:44:39 -060044#include "gui.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040045}
46
47#include "rapidxml.hpp"
48#include "objects.hpp"
gordon13370d9133d2013-06-08 14:17:07 +020049#include "blanktimer.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040050
51extern int gGuiRunning;
52
53std::map<std::string, PageSet*> PageManager::mPageSets;
54PageSet* PageManager::mCurrentSet;
55PageSet* PageManager::mBaseSet = NULL;
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +010056MouseCursor *PageManager::mMouseCursor = NULL;
Vojtech Bocek0b7fe502014-03-13 17:36:52 +010057HardwareKeyboard *PageManager::mHardwareKeyboard = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -040058
Ethan Yonker751a85e2014-12-12 16:59:10 -060059int tw_x_offset = 0;
60int tw_y_offset = 0;
61
Dees_Troy51a0e822012-09-05 15:24:24 -040062// Helper routine to convert a string to a color declaration
63int ConvertStrToColor(std::string str, COLOR* color)
64{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020065 // Set the default, solid black
66 memset(color, 0, sizeof(COLOR));
67 color->alpha = 255;
Dees_Troy51a0e822012-09-05 15:24:24 -040068
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020069 // Translate variables
70 DataManager::GetValue(str, str);
Matt Mowerfb1c4ff2014-04-16 13:43:36 -050071
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020072 // Look for some defaults
thatf6ed8fc2015-02-14 20:23:16 +010073 if (str == "black") return 0;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020074 else if (str == "white") { color->red = color->green = color->blue = 255; return 0; }
75 else if (str == "red") { color->red = 255; return 0; }
76 else if (str == "green") { color->green = 255; return 0; }
77 else if (str == "blue") { color->blue = 255; return 0; }
Dees_Troy51a0e822012-09-05 15:24:24 -040078
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020079 // At this point, we require an RGB(A) color
80 if (str[0] != '#')
81 return -1;
82
83 str.erase(0, 1);
Dees_Troy51a0e822012-09-05 15:24:24 -040084
Dees_Troy30b962e2012-10-19 20:48:59 -040085 int result;
86 if (str.size() >= 8) {
87 // We have alpha channel
88 string alpha = str.substr(6, 2);
89 result = strtol(alpha.c_str(), NULL, 16);
90 color->alpha = result & 0x000000FF;
91 str.resize(6);
92 result = strtol(str.c_str(), NULL, 16);
93 color->red = (result >> 16) & 0x000000FF;
94 color->green = (result >> 8) & 0x000000FF;
95 color->blue = result & 0x000000FF;
96 } else {
97 result = strtol(str.c_str(), NULL, 16);
98 color->red = (result >> 16) & 0x000000FF;
99 color->green = (result >> 8) & 0x000000FF;
100 color->blue = result & 0x000000FF;
101 }
102 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400103}
104
105// Helper APIs
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600106xml_node<>* FindNode(xml_node<>* parent, const char* nodename, int depth /* = 0 */)
107{
that8d46c092015-02-26 01:30:04 +0100108 if (!parent)
109 return NULL;
110
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600111 xml_node<>* child = parent->first_node(nodename);
112 if (child)
113 return child;
114
115 if (depth == 10) {
116 LOGERR("Too many style loops detected.\n");
117 return NULL;
118 }
119
120 xml_node<>* style = parent->first_node("style");
121 if (style) {
122 while (style) {
123 if (!style->first_attribute("name")) {
124 LOGERR("No name given for style.\n");
125 continue;
126 } else {
127 std::string name = style->first_attribute("name")->value();
128 xml_node<>* node = PageManager::FindStyle(name);
129
130 if (node) {
131 // We found the style that was named
132 xml_node<>* stylenode = FindNode(node, nodename, depth + 1);
133 if (stylenode)
134 return stylenode;
135 }
136 }
137 style = style->next_sibling("style");
138 }
139 } else {
140 // Search for stylename in the parent node <object type="foo" stylename="foo2">
141 xml_attribute<>* attr = parent->first_attribute("style");
142 // If no style is found anywhere else and the node wasn't found in the object itself
143 // as a special case we will search for a style that uses the same style name as the
144 // object type, so <object type="button"> would search for a style named "button"
145 if (!attr)
146 attr = parent->first_attribute("type");
147 if (attr) {
148 xml_node<>* node = PageManager::FindStyle(attr->value());
149 if (node) {
150 xml_node<>* stylenode = FindNode(node, nodename, depth + 1);
151 if (stylenode)
152 return stylenode;
153 }
154 }
155 }
156 return NULL;
157}
158
thatf6ed8fc2015-02-14 20:23:16 +0100159std::string LoadAttrString(xml_node<>* element, const char* attrname, const char* defaultvalue)
160{
161 if (!element)
162 return defaultvalue;
163
164 xml_attribute<>* attr = element->first_attribute(attrname);
165 return attr ? attr->value() : defaultvalue;
166}
167
168int LoadAttrInt(xml_node<>* element, const char* attrname, int defaultvalue)
169{
170 string value = LoadAttrString(element, attrname);
171 // resolve variables
172 DataManager::GetValue(value, value);
173 return value.empty() ? defaultvalue : atoi(value.c_str());
174}
175
176int LoadAttrIntScaleX(xml_node<>* element, const char* attrname, int defaultvalue)
177{
178 return scale_theme_x(LoadAttrInt(element, attrname, defaultvalue));
179}
180
181int LoadAttrIntScaleY(xml_node<>* element, const char* attrname, int defaultvalue)
182{
183 return scale_theme_y(LoadAttrInt(element, attrname, defaultvalue));
184}
185
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600186COLOR LoadAttrColor(xml_node<>* element, const char* attrname, bool* found_color, COLOR defaultvalue)
thatf6ed8fc2015-02-14 20:23:16 +0100187{
188 string value = LoadAttrString(element, attrname);
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600189 *found_color = !value.empty();
thatf6ed8fc2015-02-14 20:23:16 +0100190 // resolve variables
191 DataManager::GetValue(value, value);
192 COLOR ret = defaultvalue;
193 if (ConvertStrToColor(value, &ret) == 0)
194 return ret;
195 else
196 return defaultvalue;
197}
198
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600199COLOR LoadAttrColor(xml_node<>* element, const char* attrname, COLOR defaultvalue)
200{
201 bool found_color = false;
202 return LoadAttrColor(element, attrname, &found_color, defaultvalue);
203}
204
thatf6ed8fc2015-02-14 20:23:16 +0100205FontResource* LoadAttrFont(xml_node<>* element, const char* attrname)
206{
207 std::string name = LoadAttrString(element, attrname, "");
208 if (name.empty())
209 return NULL;
210 else
that74ac6062015-03-04 22:39:34 +0100211 return PageManager::GetResources()->FindFont(name);
thatf6ed8fc2015-02-14 20:23:16 +0100212}
213
214ImageResource* LoadAttrImage(xml_node<>* element, const char* attrname)
215{
216 std::string name = LoadAttrString(element, attrname, "");
217 if (name.empty())
218 return NULL;
219 else
that74ac6062015-03-04 22:39:34 +0100220 return PageManager::GetResources()->FindImage(name);
thatf6ed8fc2015-02-14 20:23:16 +0100221}
222
223AnimationResource* LoadAttrAnimation(xml_node<>* element, const char* attrname)
224{
225 std::string name = LoadAttrString(element, attrname, "");
226 if (name.empty())
227 return NULL;
228 else
that74ac6062015-03-04 22:39:34 +0100229 return PageManager::GetResources()->FindAnimation(name);
thatf6ed8fc2015-02-14 20:23:16 +0100230}
231
Ethan Yonkerb7a54a32015-10-05 10:16:27 -0500232bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, Placement* placement /* = NULL */)
Dees_Troy51a0e822012-09-05 15:24:24 -0400233{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200234 if (!node)
235 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400236
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200237 if (node->first_attribute("x"))
thatf6ed8fc2015-02-14 20:23:16 +0100238 *x = LoadAttrIntScaleX(node, "x") + tw_x_offset;
Dees_Troy51a0e822012-09-05 15:24:24 -0400239
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200240 if (node->first_attribute("y"))
thatf6ed8fc2015-02-14 20:23:16 +0100241 *y = LoadAttrIntScaleY(node, "y") + tw_y_offset;
Dees_Troy51a0e822012-09-05 15:24:24 -0400242
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200243 if (w && node->first_attribute("w"))
thatf6ed8fc2015-02-14 20:23:16 +0100244 *w = LoadAttrIntScaleX(node, "w");
Dees_Troy51a0e822012-09-05 15:24:24 -0400245
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200246 if (h && node->first_attribute("h"))
thatf6ed8fc2015-02-14 20:23:16 +0100247 *h = LoadAttrIntScaleY(node, "h");
Dees_Troy51a0e822012-09-05 15:24:24 -0400248
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200249 if (placement && node->first_attribute("placement"))
Ethan Yonkerb7a54a32015-10-05 10:16:27 -0500250 *placement = (Placement) LoadAttrInt(node, "placement");
Dees_Troy51a0e822012-09-05 15:24:24 -0400251
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200252 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400253}
254
255int ActionObject::SetActionPos(int x, int y, int w, int h)
256{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200257 if (x < 0 || y < 0)
258 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400259
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500260 mActionX = x;
261 mActionY = y;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200262 if (w || h)
263 {
264 mActionW = w;
265 mActionH = h;
266 }
267 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400268}
269
thatb63e2f92015-06-27 21:35:11 +0200270Page::Page(xml_node<>* page, std::vector<xml_node<>*> *templates)
Dees_Troy51a0e822012-09-05 15:24:24 -0400271{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200272 mTouchStart = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400273
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200274 // We can memset the whole structure, because the alpha channel is ignored
275 memset(&mBackground, 0, sizeof(COLOR));
Dees_Troy51a0e822012-09-05 15:24:24 -0400276
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200277 // With NULL, we make a console-only display
278 if (!page)
279 {
280 mName = "console";
Dees_Troy51a0e822012-09-05 15:24:24 -0400281
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200282 GUIConsole* element = new GUIConsole(NULL);
283 mRenders.push_back(element);
284 mActions.push_back(element);
285 return;
286 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400287
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200288 if (page->first_attribute("name"))
289 mName = page->first_attribute("name")->value();
290 else
291 {
292 LOGERR("No page name attribute found!\n");
293 return;
294 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400295
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200296 LOGINFO("Loading page %s\n", mName.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400297
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200298 // This is a recursive routine for template handling
thatb63e2f92015-06-27 21:35:11 +0200299 ProcessNode(page, templates, 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400300}
301
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100302Page::~Page()
303{
304 for (std::vector<GUIObject*>::iterator itr = mObjects.begin(); itr != mObjects.end(); ++itr)
305 delete *itr;
306}
307
thatb63e2f92015-06-27 21:35:11 +0200308bool Page::ProcessNode(xml_node<>* page, std::vector<xml_node<>*> *templates, int depth)
Dees_Troy51a0e822012-09-05 15:24:24 -0400309{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200310 if (depth == 10)
311 {
312 LOGERR("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
313 return false;
314 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400315
thatb63e2f92015-06-27 21:35:11 +0200316 for (xml_node<>* child = page->first_node(); child; child = child->next_sibling())
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200317 {
thatb63e2f92015-06-27 21:35:11 +0200318 std::string type = child->name();
319
320 if (type == "background") {
321 mBackground = LoadAttrColor(child, "color", COLOR(0,0,0,0));
322 continue;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200323 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400324
thatb63e2f92015-06-27 21:35:11 +0200325 if (type == "object") {
326 // legacy format : <object type="...">
327 xml_attribute<>* attr = child->first_attribute("type");
328 type = attr ? attr->value() : "*unspecified*";
329 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400330
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200331 if (type == "text")
332 {
333 GUIText* element = new GUIText(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100334 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200335 mRenders.push_back(element);
336 mActions.push_back(element);
337 }
338 else if (type == "image")
339 {
340 GUIImage* element = new GUIImage(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100341 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200342 mRenders.push_back(element);
343 }
344 else if (type == "fill")
345 {
346 GUIFill* element = new GUIFill(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100347 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200348 mRenders.push_back(element);
349 }
350 else if (type == "action")
351 {
352 GUIAction* element = new GUIAction(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100353 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200354 mActions.push_back(element);
355 }
356 else if (type == "console")
357 {
358 GUIConsole* element = new GUIConsole(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100359 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200360 mRenders.push_back(element);
361 mActions.push_back(element);
362 }
363 else if (type == "button")
364 {
365 GUIButton* element = new GUIButton(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100366 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200367 mRenders.push_back(element);
368 mActions.push_back(element);
369 }
370 else if (type == "checkbox")
371 {
372 GUICheckbox* element = new GUICheckbox(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100373 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200374 mRenders.push_back(element);
375 mActions.push_back(element);
376 }
377 else if (type == "fileselector")
378 {
379 GUIFileSelector* element = new GUIFileSelector(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100380 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200381 mRenders.push_back(element);
382 mActions.push_back(element);
383 }
384 else if (type == "animation")
385 {
386 GUIAnimation* element = new GUIAnimation(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100387 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200388 mRenders.push_back(element);
389 }
390 else if (type == "progressbar")
391 {
392 GUIProgressBar* element = new GUIProgressBar(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100393 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200394 mRenders.push_back(element);
395 mActions.push_back(element);
396 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400397 else if (type == "slider")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200398 {
399 GUISlider* element = new GUISlider(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100400 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200401 mRenders.push_back(element);
402 mActions.push_back(element);
403 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200404 else if (type == "slidervalue")
405 {
406 GUISliderValue *element = new GUISliderValue(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100407 mObjects.push_back(element);
Vojtech Bocek85932342013-04-01 22:11:33 +0200408 mRenders.push_back(element);
409 mActions.push_back(element);
410 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400411 else if (type == "listbox")
412 {
413 GUIListBox* element = new GUIListBox(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100414 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400415 mRenders.push_back(element);
416 mActions.push_back(element);
417 }
418 else if (type == "keyboard")
419 {
420 GUIKeyboard* element = new GUIKeyboard(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100421 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400422 mRenders.push_back(element);
423 mActions.push_back(element);
424 }
425 else if (type == "input")
426 {
427 GUIInput* element = new GUIInput(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100428 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400429 mRenders.push_back(element);
430 mActions.push_back(element);
431 mInputs.push_back(element);
432 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500433 else if (type == "partitionlist")
434 {
435 GUIPartitionList* element = new GUIPartitionList(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100436 mObjects.push_back(element);
Dees_Troya13d74f2013-03-24 08:54:55 -0500437 mRenders.push_back(element);
438 mActions.push_back(element);
439 }
Vojtech Bocek7e11ac52015-03-05 23:21:49 +0100440 else if (type == "patternpassword")
441 {
442 GUIPatternPassword* element = new GUIPatternPassword(child);
443 mObjects.push_back(element);
444 mRenders.push_back(element);
445 mActions.push_back(element);
446 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200447 else if (type == "template")
448 {
449 if (!templates || !child->first_attribute("name"))
450 {
451 LOGERR("Invalid template request.\n");
452 }
453 else
454 {
455 std::string name = child->first_attribute("name")->value();
Ethan Yonker780cd392014-07-21 15:24:39 -0500456 xml_node<>* node;
457 bool node_found = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400458
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200459 // We need to find the correct template
Ethan Yonker780cd392014-07-21 15:24:39 -0500460 for (std::vector<xml_node<>*>::iterator itr = templates->begin(); itr != templates->end(); itr++) {
461 node = (*itr)->first_node("template");
Dees_Troy51a0e822012-09-05 15:24:24 -0400462
Ethan Yonker780cd392014-07-21 15:24:39 -0500463 while (node)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200464 {
Ethan Yonker780cd392014-07-21 15:24:39 -0500465 if (!node->first_attribute("name"))
466 continue;
467
468 if (name == node->first_attribute("name")->value())
469 {
470 if (!ProcessNode(node, templates, depth + 1))
471 return false;
472 else {
473 node_found = true;
474 break;
475 }
476 }
477 if (node_found)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200478 break;
Ethan Yonker780cd392014-07-21 15:24:39 -0500479 node = node->next_sibling("template");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200480 }
thatb63e2f92015-06-27 21:35:11 +0200481 // [check] why is there no if (node_found) here too?
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200482 }
483 }
484 }
485 else
486 {
thatb63e2f92015-06-27 21:35:11 +0200487 LOGERR("Unknown object type: %s.\n", type.c_str());
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200488 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200489 }
490 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400491}
492
493int Page::Render(void)
494{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200495 // Render background
496 gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
497 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
Dees_Troy51a0e822012-09-05 15:24:24 -0400498
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200499 // Render remaining objects
500 std::vector<RenderObject*>::iterator iter;
501 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
502 {
503 if ((*iter)->Render())
504 LOGERR("A render request has failed.\n");
505 }
506 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400507}
508
509int Page::Update(void)
510{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200511 int retCode = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400512
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200513 std::vector<RenderObject*>::iterator iter;
514 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
515 {
516 int ret = (*iter)->Update();
517 if (ret < 0)
518 LOGERR("An update request has failed.\n");
519 else if (ret > retCode)
520 retCode = ret;
521 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400522
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200523 return retCode;
Dees_Troy51a0e822012-09-05 15:24:24 -0400524}
525
526int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
527{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200528 // By default, return 1 to ignore further touches if nobody is listening
529 int ret = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400530
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200531 // Don't try to handle a lack of handlers
532 if (mActions.size() == 0)
533 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400534
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200535 // We record mTouchStart so we can pass all the touch stream to the same handler
536 if (state == TOUCH_START)
537 {
538 std::vector<ActionObject*>::reverse_iterator iter;
539 // We work backwards, from top-most element to bottom-most element
540 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
541 {
542 if ((*iter)->IsInRegion(x, y))
543 {
544 mTouchStart = (*iter);
545 ret = mTouchStart->NotifyTouch(state, x, y);
546 if (ret >= 0)
547 break;
548 mTouchStart = NULL;
549 }
550 }
551 }
552 else if (state == TOUCH_RELEASE && mTouchStart != NULL)
553 {
554 ret = mTouchStart->NotifyTouch(state, x, y);
555 mTouchStart = NULL;
556 }
557 else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
558 {
559 ret = mTouchStart->NotifyTouch(state, x, y);
560 }
561 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400562}
563
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100564int Page::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -0400565{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200566 std::vector<ActionObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400567
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200568 // Don't try to handle a lack of handlers
569 if (mActions.size() == 0)
570 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400571
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100572 int ret = 1;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200573 // We work backwards, from top-most element to bottom-most element
574 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
575 {
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100576 ret = (*iter)->NotifyKey(key, down);
577 if (ret < 0) {
578 LOGERR("An action handler has returned an error\n");
579 ret = 1;
580 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200581 }
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100582 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400583}
584
585int Page::NotifyKeyboard(int key)
586{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200587 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400588
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200589 // Don't try to handle a lack of handlers
590 if (mInputs.size() == 0)
591 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400592
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200593 // We work backwards, from top-most element to bottom-most element
594 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
595 {
596 int ret = (*iter)->NotifyKeyboard(key);
597 if (ret == 0)
598 return 0;
599 else if (ret < 0)
600 LOGERR("A keyboard handler has returned an error");
601 }
602 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400603}
604
605int Page::SetKeyBoardFocus(int inFocus)
606{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200607 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400608
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200609 // Don't try to handle a lack of handlers
610 if (mInputs.size() == 0)
611 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400612
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200613 // We work backwards, from top-most element to bottom-most element
614 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
615 {
616 int ret = (*iter)->SetInputFocus(inFocus);
617 if (ret == 0)
618 return 0;
619 else if (ret < 0)
620 LOGERR("An input focus handler has returned an error");
621 }
622 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400623}
624
625void Page::SetPageFocus(int inFocus)
626{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200627 // Render remaining objects
628 std::vector<RenderObject*>::iterator iter;
629 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
630 (*iter)->SetPageFocus(inFocus);
631
632 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400633}
634
635int Page::NotifyVarChange(std::string varName, std::string value)
636{
Vojtech Bocek07220562014-02-08 02:05:33 +0100637 std::vector<GUIObject*>::iterator iter;
638 for (iter = mObjects.begin(); iter != mObjects.end(); ++iter)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200639 {
640 if ((*iter)->NotifyVarChange(varName, value))
641 LOGERR("An action handler errored on NotifyVarChange.\n");
642 }
643 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400644}
645
646PageSet::PageSet(char* xmlFile)
647{
that74ac6062015-03-04 22:39:34 +0100648 mResources = new ResourceManager;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200649 mCurrentPage = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400650
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200651 mXmlFile = xmlFile;
652 if (xmlFile)
653 mDoc.parse<0>(mXmlFile);
654 else
thatb63e2f92015-06-27 21:35:11 +0200655 mCurrentPage = new Page(NULL, NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400656}
657
658PageSet::~PageSet()
659{
Ethan Yonker1c273312015-03-16 12:18:56 -0500660 mOverlays.clear();
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100661 for (std::vector<Page*>::iterator itr = mPages.begin(); itr != mPages.end(); ++itr)
662 delete *itr;
663
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200664 delete mResources;
665 free(mXmlFile);
Vojtech Boceke979abd2015-01-12 18:29:12 +0100666
667 mDoc.clear();
668
669 for (std::vector<xml_document<>*>::iterator itr = mIncludedDocs.begin(); itr != mIncludedDocs.end(); ++itr) {
670 (*itr)->clear();
671 delete *itr;
672 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400673}
674
675int PageSet::Load(ZipArchive* package)
676{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200677 xml_node<>* parent;
678 xml_node<>* child;
Ethan Yonker780cd392014-07-21 15:24:39 -0500679 xml_node<>* xmltemplate;
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600680 xml_node<>* xmlstyle;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500681
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200682 parent = mDoc.first_node("recovery");
683 if (!parent)
684 parent = mDoc.first_node("install");
Dees_Troy51a0e822012-09-05 15:24:24 -0400685
Ethan Yonker63e414f2015-02-06 15:44:39 -0600686 set_scale_values(1, 1); // Reset any previous scaling values
687
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200688 // Now, let's parse the XML
Ethan Yonker63e414f2015-02-06 15:44:39 -0600689 LOGINFO("Checking resolution...\n");
690 child = parent->first_node("details");
691 if (child) {
692 xml_node<>* resolution = child->first_node("resolution");
693 if (resolution) {
694 xml_attribute<>* width_attr = resolution->first_attribute("width");
695 xml_attribute<>* height_attr = resolution->first_attribute("height");
696 xml_attribute<>* noscale_attr = resolution->first_attribute("noscaling");
697 if (width_attr && height_attr && !noscale_attr) {
698 int width = atoi(width_attr->value());
699 int height = atoi(height_attr->value());
700 int offx = 0, offy = 0;
701#ifdef TW_ROUND_SCREEN
702 xml_node<>* roundscreen = child->first_node("roundscreen");
703 if (roundscreen) {
704 LOGINFO("TW_ROUND_SCREEN := true, using round screen XML settings.\n");
705 xml_attribute<>* offx_attr = roundscreen->first_attribute("offset_x");
706 xml_attribute<>* offy_attr = roundscreen->first_attribute("offset_y");
707 if (offx_attr) {
708 offx = atoi(offx_attr->value());
709 }
710 if (offy_attr) {
711 offy = atoi(offy_attr->value());
712 }
713 }
714#endif
715 if (width != 0 && height != 0) {
716 float scale_w = ((float)gr_fb_width() - ((float)offx * 2.0)) / (float)width;
717 float scale_h = ((float)gr_fb_height() - ((float)offy * 2.0)) / (float)height;
718#ifdef TW_ROUND_SCREEN
719 float scale_off_w = (float)gr_fb_width() / (float)width;
720 float scale_off_h = (float)gr_fb_height() / (float)height;
721 tw_x_offset = offx * scale_off_w;
722 tw_y_offset = offy * scale_off_h;
723#endif
724 if (scale_w != 1 || scale_h != 1) {
725 LOGINFO("Scaling theme width %fx and height %fx, offsets x: %i y: %i\n", scale_w, scale_h, tw_x_offset, tw_y_offset);
726 set_scale_values(scale_w, scale_h);
727 }
728 }
729 } else {
730 LOGINFO("XML does not contain width and height, no scaling will be applied\n");
731 }
732 } else {
733 LOGINFO("XML contains no resolution tag, no scaling will be applied.\n");
734 }
735 } else {
736 LOGINFO("XML contains no details tag, no scaling will be applied.\n");
737 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200738 LOGINFO("Loading resources...\n");
739 child = parent->first_node("resources");
740 if (child)
that74ac6062015-03-04 22:39:34 +0100741 mResources->LoadResources(child, package);
Dees_Troy51a0e822012-09-05 15:24:24 -0400742
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200743 LOGINFO("Loading variables...\n");
744 child = parent->first_node("variables");
745 if (child)
746 LoadVariables(child);
Dees_Troy51a0e822012-09-05 15:24:24 -0400747
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +0100748 LOGINFO("Loading mouse cursor...\n");
749 child = parent->first_node("mousecursor");
750 if(child)
751 PageManager::LoadCursorData(child);
752
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200753 LOGINFO("Loading pages...\n");
754 // This may be NULL if no templates are present
Ethan Yonker780cd392014-07-21 15:24:39 -0500755 xmltemplate = parent->first_node("templates");
756 if (xmltemplate)
757 templates.push_back(xmltemplate);
Dees_Troy51a0e822012-09-05 15:24:24 -0400758
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600759 // Load styles if present
760 xmlstyle = parent->first_node("styles");
761 if (xmlstyle)
762 styles.push_back(xmlstyle);
763
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200764 child = parent->first_node("pages");
Ethan Yonker780cd392014-07-21 15:24:39 -0500765 if (child) {
766 if (LoadPages(child)) {
767 LOGERR("PageSet::Load returning -1\n");
768 return -1;
769 }
770 }
Vojtech Boceke979abd2015-01-12 18:29:12 +0100771
Ethan Yonker780cd392014-07-21 15:24:39 -0500772 return CheckInclude(package, &mDoc);
773}
Dees_Troy51a0e822012-09-05 15:24:24 -0400774
Ethan Yonker780cd392014-07-21 15:24:39 -0500775int PageSet::CheckInclude(ZipArchive* package, xml_document<> *parentDoc)
776{
777 xml_node<>* par;
778 xml_node<>* par2;
779 xml_node<>* chld;
780 xml_node<>* parent;
781 xml_node<>* child;
782 xml_node<>* xmltemplate;
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600783 xml_node<>* xmlstyle;
Ethan Yonker780cd392014-07-21 15:24:39 -0500784 long len;
785 char* xmlFile = NULL;
786 string filename;
Vojtech Boceke979abd2015-01-12 18:29:12 +0100787 xml_document<> *doc = NULL;
Ethan Yonker780cd392014-07-21 15:24:39 -0500788
789 par = parentDoc->first_node("recovery");
790 if (!par) {
791 par = parentDoc->first_node("install");
792 }
793 if (!par) {
794 return 0;
795 }
796
797 par2 = par->first_node("include");
798 if (!par2)
799 return 0;
800 chld = par2->first_node("xmlfile");
801 while (chld != NULL) {
802 xml_attribute<>* attr = chld->first_attribute("name");
803 if (!attr)
804 break;
805
Ethan Yonker780cd392014-07-21 15:24:39 -0500806 if (!package) {
807 // We can try to load the XML directly...
Dees Troy3454ade2015-01-20 19:21:04 +0000808 filename = TWRES;
Ethan Yonker780cd392014-07-21 15:24:39 -0500809 filename += attr->value();
Ethan Yonker780cd392014-07-21 15:24:39 -0500810 } else {
811 filename += attr->value();
Ethan Yonker561c58d2015-10-05 08:48:22 -0500812 }
813 xmlFile = PageManager::LoadFileToBuffer(filename, package);
814 if (xmlFile == NULL) {
815 LOGERR("PageSet::CheckInclude unable to load '%s'\n", filename.c_str());
816 return -1;
Ethan Yonker780cd392014-07-21 15:24:39 -0500817 }
Ethan Yonker780cd392014-07-21 15:24:39 -0500818
Vojtech Boceke979abd2015-01-12 18:29:12 +0100819 doc = new xml_document<>();
820 doc->parse<0>(xmlFile);
821
822 parent = doc->first_node("recovery");
Ethan Yonker780cd392014-07-21 15:24:39 -0500823 if (!parent)
Vojtech Boceke979abd2015-01-12 18:29:12 +0100824 parent = doc->first_node("install");
Ethan Yonker780cd392014-07-21 15:24:39 -0500825
826 // Now, let's parse the XML
827 LOGINFO("Loading included resources...\n");
828 child = parent->first_node("resources");
829 if (child)
830 mResources->LoadResources(child, package);
831
832 LOGINFO("Loading included variables...\n");
833 child = parent->first_node("variables");
834 if (child)
835 LoadVariables(child);
836
837 LOGINFO("Loading mouse cursor...\n");
838 child = parent->first_node("mousecursor");
839 if(child)
840 PageManager::LoadCursorData(child);
841
842 LOGINFO("Loading included pages...\n");
843 // This may be NULL if no templates are present
844 xmltemplate = parent->first_node("templates");
845 if (xmltemplate)
846 templates.push_back(xmltemplate);
847
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600848 // Load styles if present
849 xmlstyle = parent->first_node("styles");
850 if (xmlstyle)
851 styles.push_back(xmlstyle);
852
Ethan Yonker780cd392014-07-21 15:24:39 -0500853 child = parent->first_node("pages");
Vojtech Boceke979abd2015-01-12 18:29:12 +0100854 if (child && LoadPages(child))
855 {
856 templates.pop_back();
857 doc->clear();
858 delete doc;
Ethan Yonker561c58d2015-10-05 08:48:22 -0500859 free(xmlFile);
Vojtech Boceke979abd2015-01-12 18:29:12 +0100860 return -1;
861 }
Ethan Yonker780cd392014-07-21 15:24:39 -0500862
Vojtech Boceke979abd2015-01-12 18:29:12 +0100863 mIncludedDocs.push_back(doc);
864
Ethan Yonker561c58d2015-10-05 08:48:22 -0500865 if (CheckInclude(package, doc)) {
866 free(xmlFile);
Ethan Yonker780cd392014-07-21 15:24:39 -0500867 return -1;
Ethan Yonker561c58d2015-10-05 08:48:22 -0500868 }
Ethan Yonker780cd392014-07-21 15:24:39 -0500869
870 chld = chld->next_sibling("xmlfile");
871 }
Ethan Yonker561c58d2015-10-05 08:48:22 -0500872 if (xmlFile)
873 free(xmlFile);
Ethan Yonker780cd392014-07-21 15:24:39 -0500874 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400875}
876
877int PageSet::SetPage(std::string page)
878{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200879 Page* tmp = FindPage(page);
880 if (tmp)
881 {
882 if (mCurrentPage) mCurrentPage->SetPageFocus(0);
883 mCurrentPage = tmp;
884 mCurrentPage->SetPageFocus(1);
885 mCurrentPage->NotifyVarChange("", "");
886 return 0;
887 }
888 else
889 {
890 LOGERR("Unable to locate page (%s)\n", page.c_str());
891 }
892 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400893}
894
895int PageSet::SetOverlay(Page* page)
896{
Ethan Yonker1c273312015-03-16 12:18:56 -0500897 if (page) {
898 if (mOverlays.size() >= 10) {
899 LOGERR("Too many overlays requested, max is 10.\n");
900 return -1;
901 }
Matt Mowerd411f8d2015-04-09 16:04:12 -0500902
903 std::vector<Page*>::iterator iter;
904 for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
905 if ((*iter)->GetName() == page->GetName()) {
906 mOverlays.erase(iter);
907 // SetOverlay() is (and should stay) the only function which
908 // adds to mOverlays. Then, each page can appear at most once.
909 break;
910 }
911 }
912
Ethan Yonker1c273312015-03-16 12:18:56 -0500913 page->SetPageFocus(1);
914 page->NotifyVarChange("", "");
915
916 if (!mOverlays.empty())
917 mOverlays.back()->SetPageFocus(0);
918
919 mOverlays.push_back(page);
920 } else {
921 if (!mOverlays.empty()) {
922 mOverlays.back()->SetPageFocus(0);
923 mOverlays.pop_back();
924 if (!mOverlays.empty())
925 mOverlays.back()->SetPageFocus(1);
926 else if (mCurrentPage)
927 mCurrentPage->SetPageFocus(1); // Just in case somehow the regular page lost focus, we'll set it again
928 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200929 }
930 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400931}
932
that74ac6062015-03-04 22:39:34 +0100933const ResourceManager* PageSet::GetResources()
Dees_Troy51a0e822012-09-05 15:24:24 -0400934{
that74ac6062015-03-04 22:39:34 +0100935 return mResources;
Dees_Troy51a0e822012-09-05 15:24:24 -0400936}
937
938Page* PageSet::FindPage(std::string name)
939{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200940 std::vector<Page*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400941
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200942 for (iter = mPages.begin(); iter != mPages.end(); iter++)
943 {
944 if (name == (*iter)->GetName())
945 return (*iter);
946 }
947 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400948}
949
950int PageSet::LoadVariables(xml_node<>* vars)
951{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200952 xml_node<>* child;
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100953 xml_attribute<> *name, *value, *persist;
954 int p;
Dees_Troy51a0e822012-09-05 15:24:24 -0400955
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200956 child = vars->first_node("variable");
957 while (child)
958 {
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100959 name = child->first_attribute("name");
960 value = child->first_attribute("value");
961 persist = child->first_attribute("persist");
962 if(name && value)
963 {
Ethan Yonker751a85e2014-12-12 16:59:10 -0600964 if (strcmp(name->value(), "tw_x_offset") == 0) {
965 tw_x_offset = atoi(value->value());
966 child = child->next_sibling("variable");
967 continue;
968 }
969 if (strcmp(name->value(), "tw_y_offset") == 0) {
970 tw_y_offset = atoi(value->value());
971 child = child->next_sibling("variable");
972 continue;
973 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100974 p = persist ? atoi(persist->value()) : 0;
Ethan Yonker96acb3d2014-08-05 09:20:30 -0500975 string temp = value->value();
976 string valstr = gui_parse_text(temp);
977
978 if (valstr.find("+") != string::npos) {
979 string val1str = valstr;
980 val1str = val1str.substr(0, val1str.find('+'));
981 string val2str = valstr;
982 val2str = val2str.substr(val2str.find('+') + 1, string::npos);
983 int val1 = atoi(val1str.c_str());
984 int val2 = atoi(val2str.c_str());
985 int val = val1 + val2;
986
987 DataManager::SetValue(name->value(), val, p);
988 } else if (valstr.find("-") != string::npos) {
989 string val1str = valstr;
990 val1str = val1str.substr(0, val1str.find('-'));
991 string val2str = valstr;
992 val2str = val2str.substr(val2str.find('-') + 1, string::npos);
993 int val1 = atoi(val1str.c_str());
994 int val2 = atoi(val2str.c_str());
995 int val = val1 - val2;
996
997 DataManager::SetValue(name->value(), val, p);
998 } else {
999 DataManager::SetValue(name->value(), valstr, p);
1000 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +01001001 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001002
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001003 child = child->next_sibling("variable");
1004 }
1005 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001006}
1007
Ethan Yonker780cd392014-07-21 15:24:39 -05001008int PageSet::LoadPages(xml_node<>* pages)
Dees_Troy51a0e822012-09-05 15:24:24 -04001009{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001010 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -04001011
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001012 if (!pages)
1013 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001014
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001015 child = pages->first_node("page");
1016 while (child != NULL)
1017 {
Ethan Yonker780cd392014-07-21 15:24:39 -05001018 Page* page = new Page(child, &templates);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001019 if (page->GetName().empty())
1020 {
1021 LOGERR("Unable to process load page\n");
1022 delete page;
1023 }
1024 else
1025 {
1026 mPages.push_back(page);
1027 }
1028 child = child->next_sibling("page");
1029 }
1030 if (mPages.size() > 0)
1031 return 0;
1032 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001033}
1034
1035int PageSet::IsCurrentPage(Page* page)
1036{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001037 return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -04001038}
1039
1040int PageSet::Render(void)
1041{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001042 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001043
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001044 ret = (mCurrentPage ? mCurrentPage->Render() : -1);
1045 if (ret < 0)
1046 return ret;
Ethan Yonker1c273312015-03-16 12:18:56 -05001047
1048 std::vector<Page*>::iterator iter;
1049
1050 for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
1051 ret = ((*iter) ? (*iter)->Render() : -1);
1052 if (ret < 0)
1053 return ret;
1054 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001055 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001056}
1057
1058int PageSet::Update(void)
1059{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001060 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001061
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001062 ret = (mCurrentPage ? mCurrentPage->Update() : -1);
1063 if (ret < 0 || ret > 1)
1064 return ret;
Ethan Yonker1c273312015-03-16 12:18:56 -05001065
1066 std::vector<Page*>::iterator iter;
1067
1068 for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
1069 ret = ((*iter) ? (*iter)->Update() : -1);
1070 if (ret < 0)
1071 return ret;
1072 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001073 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001074}
1075
1076int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
1077{
Ethan Yonker1c273312015-03-16 12:18:56 -05001078 if (!mOverlays.empty())
1079 return mOverlays.back()->NotifyTouch(state, x, y);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001080
1081 return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001082}
1083
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001084int PageSet::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -04001085{
Ethan Yonker1c273312015-03-16 12:18:56 -05001086 if (!mOverlays.empty())
1087 return mOverlays.back()->NotifyKey(key, down);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001088
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001089 return (mCurrentPage ? mCurrentPage->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001090}
1091
1092int PageSet::NotifyKeyboard(int key)
1093{
Ethan Yonker1c273312015-03-16 12:18:56 -05001094 if (!mOverlays.empty())
1095 return mOverlays.back()->NotifyKeyboard(key);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001096
1097 return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001098}
1099
1100int PageSet::SetKeyBoardFocus(int inFocus)
1101{
Ethan Yonker1c273312015-03-16 12:18:56 -05001102 if (!mOverlays.empty())
1103 return mOverlays.back()->SetKeyBoardFocus(inFocus);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001104
1105 return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001106}
1107
1108int PageSet::NotifyVarChange(std::string varName, std::string value)
1109{
Ethan Yonker1c273312015-03-16 12:18:56 -05001110 std::vector<Page*>::iterator iter;
1111
1112 for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++)
1113 (*iter)->NotifyVarChange(varName, value);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001114
1115 return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001116}
1117
Ethan Yonker561c58d2015-10-05 08:48:22 -05001118char* PageManager::LoadFileToBuffer(std::string filename, ZipArchive* package) {
1119 size_t len;
1120 char* buffer = NULL;
1121
1122 if (!package) {
1123 // We can try to load the XML directly...
1124 LOGINFO("PageManager::LoadFileToBuffer loading filename: '%s' directly\n", filename.c_str());
1125 struct stat st;
1126 if(stat(filename.c_str(),&st) != 0) {
1127 // This isn't always an error, sometimes we request files that don't exist.
1128 return NULL;
1129 }
1130
1131 len = (size_t)st.st_size;
1132
1133 buffer = (char*) malloc(len + 1);
1134 if (!buffer) {
1135 LOGERR("PageManager::LoadFileToBuffer failed to malloc\n");
1136 return NULL;
1137 }
1138
1139 int fd = open(filename.c_str(), O_RDONLY);
1140 if (fd == -1) {
1141 LOGERR("PageManager::LoadFileToBuffer failed to open '%s' - (%s)\n", filename.c_str(), strerror(errno));
1142 free(buffer);
1143 return NULL;
1144 }
1145
1146 if (read(fd, buffer, len) < 0) {
1147 LOGERR("PageManager::LoadFileToBuffer failed to read '%s' - (%s)\n", filename.c_str(), strerror(errno));
1148 free(buffer);
1149 close(fd);
1150 return NULL;
1151 }
1152 close(fd);
1153 } else {
1154 LOGINFO("PageManager::LoadFileToBuffer loading filename: '%s' from zip\n", filename.c_str());
1155 const ZipEntry* zipentry = mzFindZipEntry(package, filename.c_str());
1156 if (zipentry == NULL) {
1157 LOGERR("Unable to locate '%s' in zip file\n", filename.c_str());
1158 return NULL;
1159 }
1160
1161 // Allocate the buffer for the file
1162 len = mzGetZipEntryUncompLen(zipentry);
1163 buffer = (char*) malloc(len + 1);
1164 if (!buffer)
1165 return NULL;
1166
1167 if (!mzExtractZipEntryToBuffer(package, zipentry, (unsigned char*) buffer)) {
1168 LOGERR("Unable to extract '%s'\n", filename.c_str());
1169 free(buffer);
1170 return NULL;
1171 }
1172 }
1173 // NULL-terminate the string
1174 buffer[len] = 0x00;
1175 return buffer;
1176}
1177
Dees_Troy51a0e822012-09-05 15:24:24 -04001178int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
1179{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001180 int fd;
1181 ZipArchive zip, *pZip = NULL;
1182 long len;
1183 char* xmlFile = NULL;
1184 PageSet* pageSet = NULL;
1185 int ret;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001186 MemMapping map;
Dees_Troy51a0e822012-09-05 15:24:24 -04001187
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001188 // Open the XML file
1189 LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001190 if (package.size() > 4 && package.substr(package.size() - 4) != ".zip")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001191 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001192 LOGINFO("Load XML directly\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -06001193 tw_x_offset = TW_X_OFFSET;
1194 tw_y_offset = TW_Y_OFFSET;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001195 }
1196 else
1197 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001198 LOGINFO("Loading zip theme\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -06001199 tw_x_offset = 0;
1200 tw_y_offset = 0;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001201 if (!TWFunc::Path_Exists(package))
1202 return -1;
1203 if (sysMapFile(package.c_str(), &map) != 0) {
1204 LOGERR("Failed to map '%s'\n", package.c_str());
Ethan Yonker561c58d2015-10-05 08:48:22 -05001205 goto error;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001206 }
1207 if (mzOpenZipArchive(map.addr, map.length, &zip)) {
1208 LOGERR("Unable to open zip archive '%s'\n", package.c_str());
1209 sysReleaseMap(&map);
Ethan Yonker561c58d2015-10-05 08:48:22 -05001210 goto error;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001211 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001212 pZip = &zip;
Ethan Yonker561c58d2015-10-05 08:48:22 -05001213 package = "ui.xml";
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001214 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001215
Ethan Yonker561c58d2015-10-05 08:48:22 -05001216 xmlFile = LoadFileToBuffer(package, pZip);
1217 if (xmlFile == NULL) {
1218 goto error;
1219 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001220
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001221 // Before loading, mCurrentSet must be the loading package so we can find resources
1222 pageSet = mCurrentSet;
1223 mCurrentSet = new PageSet(xmlFile);
1224
1225 ret = mCurrentSet->Load(pZip);
1226 if (ret == 0)
1227 {
1228 mCurrentSet->SetPage(startpage);
1229 mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
1230 }
1231 else
1232 {
1233 LOGERR("Package %s failed to load.\n", name.c_str());
1234 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001235
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001236 // The first successful package we loaded is the base
1237 if (mBaseSet == NULL)
1238 mBaseSet = mCurrentSet;
1239
1240 mCurrentSet = pageSet;
1241
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001242 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001243 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001244 sysReleaseMap(&map);
1245 }
Ethan Yonker561c58d2015-10-05 08:48:22 -05001246 free(xmlFile);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001247 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001248
1249error:
Ethan Yonker561c58d2015-10-05 08:48:22 -05001250 // Sometimes we get here without a real error
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001251 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001252 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001253 sysReleaseMap(&map);
1254 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001255 if (xmlFile)
1256 free(xmlFile);
1257 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001258}
1259
1260PageSet* PageManager::FindPackage(std::string name)
1261{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001262 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001263
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001264 iter = mPageSets.find(name);
1265 if (iter != mPageSets.end())
1266 return (*iter).second;
1267
1268 LOGERR("Unable to locate package %s\n", name.c_str());
1269 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -04001270}
1271
1272PageSet* PageManager::SelectPackage(std::string name)
1273{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001274 LOGINFO("Switching packages (%s)\n", name.c_str());
1275 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -04001276
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001277 tmp = FindPackage(name);
1278 if (tmp)
Vojtech Bocek07220562014-02-08 02:05:33 +01001279 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001280 mCurrentSet = tmp;
Vojtech Bocek07220562014-02-08 02:05:33 +01001281 mCurrentSet->NotifyVarChange("", "");
1282 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001283 else
1284 LOGERR("Unable to find package.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -04001285
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001286 return mCurrentSet;
Dees_Troy51a0e822012-09-05 15:24:24 -04001287}
1288
1289int PageManager::ReloadPackage(std::string name, std::string package)
1290{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001291 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001292
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001293 iter = mPageSets.find(name);
1294 if (iter == mPageSets.end())
1295 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001296
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001297 if(mMouseCursor)
1298 mMouseCursor->ResetData(gr_fb_width(), gr_fb_height());
1299
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001300 PageSet* set = (*iter).second;
1301 mPageSets.erase(iter);
Dees_Troy51a0e822012-09-05 15:24:24 -04001302
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001303 if (LoadPackage(name, package, "main") != 0)
1304 {
Dees Troy3454ade2015-01-20 19:21:04 +00001305 LOGERR("Failed to load package '%s'.\n", package.c_str());
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001306 mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
1307 return -1;
1308 }
1309 if (mCurrentSet == set)
1310 SelectPackage(name);
Vojtech Bocekbfb63342014-02-08 00:32:31 +01001311 if (mBaseSet == set)
1312 mBaseSet = mCurrentSet;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001313 delete set;
1314 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001315}
1316
1317void PageManager::ReleasePackage(std::string name)
1318{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001319 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001320
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001321 iter = mPageSets.find(name);
1322 if (iter == mPageSets.end())
1323 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001324
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001325 PageSet* set = (*iter).second;
1326 mPageSets.erase(iter);
1327 delete set;
1328 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001329}
1330
1331int PageManager::ChangePage(std::string name)
1332{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001333 DataManager::SetValue("tw_operation_state", 0);
1334 int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
1335 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001336}
1337
1338int PageManager::ChangeOverlay(std::string name)
1339{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001340 if (name.empty())
1341 return mCurrentSet->SetOverlay(NULL);
1342 else
1343 {
1344 Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
1345 return mCurrentSet->SetOverlay(page);
1346 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001347}
1348
that74ac6062015-03-04 22:39:34 +01001349const ResourceManager* PageManager::GetResources()
Dees_Troy51a0e822012-09-05 15:24:24 -04001350{
that74ac6062015-03-04 22:39:34 +01001351 return (mCurrentSet ? mCurrentSet->GetResources() : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001352}
1353
1354int PageManager::SwitchToConsole(void)
1355{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001356 PageSet* console = new PageSet(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001357
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001358 mCurrentSet = console;
1359 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001360}
1361
Ethan Yonker03a42f62014-08-08 11:03:51 -05001362int PageManager::EndConsole(void)
1363{
1364 if (mCurrentSet && mBaseSet) {
1365 delete mCurrentSet;
1366 mCurrentSet = mBaseSet;
1367 return 0;
1368 }
1369 return -1;
1370}
1371
Dees_Troy51a0e822012-09-05 15:24:24 -04001372int PageManager::IsCurrentPage(Page* page)
1373{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001374 return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -04001375}
1376
1377int PageManager::Render(void)
1378{
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001379 int res = (mCurrentSet ? mCurrentSet->Render() : -1);
1380 if(mMouseCursor)
1381 mMouseCursor->Render();
1382 return res;
1383}
1384
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001385HardwareKeyboard *PageManager::GetHardwareKeyboard()
1386{
1387 if(!mHardwareKeyboard)
1388 mHardwareKeyboard = new HardwareKeyboard();
1389 return mHardwareKeyboard;
1390}
1391
Ethan Yonker21ff02a2015-02-18 14:35:00 -06001392xml_node<>* PageManager::FindStyle(std::string name)
1393{
1394 for (std::vector<xml_node<>*>::iterator itr = mCurrentSet->styles.begin(); itr != mCurrentSet->styles.end(); itr++) {
1395 xml_node<>* node = (*itr)->first_node("style");
1396
1397 while (node) {
1398 if (!node->first_attribute("name"))
1399 continue;
1400
1401 if (name == node->first_attribute("name")->value())
1402 return node;
1403 node = node->next_sibling("style");
1404 }
1405 }
1406 return NULL;
1407}
1408
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001409MouseCursor *PageManager::GetMouseCursor()
1410{
1411 if(!mMouseCursor)
1412 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1413 return mMouseCursor;
1414}
1415
1416void PageManager::LoadCursorData(xml_node<>* node)
1417{
1418 if(!mMouseCursor)
1419 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1420
1421 mMouseCursor->LoadData(node);
Dees_Troy51a0e822012-09-05 15:24:24 -04001422}
1423
1424int PageManager::Update(void)
1425{
thatfb759d42015-01-11 12:16:53 +01001426 if(blankTimer.isScreenOff())
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001427 return 0;
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001428
1429 int res = (mCurrentSet ? mCurrentSet->Update() : -1);
1430
1431 if(mMouseCursor)
1432 {
1433 int c_res = mMouseCursor->Update();
1434 if(c_res > res)
1435 res = c_res;
1436 }
1437 return res;
Dees_Troy51a0e822012-09-05 15:24:24 -04001438}
1439
1440int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
1441{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001442 return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001443}
1444
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001445int PageManager::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -04001446{
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001447 return (mCurrentSet ? mCurrentSet->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001448}
1449
1450int PageManager::NotifyKeyboard(int key)
1451{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001452 return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001453}
1454
1455int PageManager::SetKeyBoardFocus(int inFocus)
1456{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001457 return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001458}
1459
1460int PageManager::NotifyVarChange(std::string varName, std::string value)
1461{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001462 return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001463}
1464
1465extern "C" void gui_notifyVarChange(const char *name, const char* value)
1466{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001467 if (!gGuiRunning)
1468 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001469
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001470 PageManager::NotifyVarChange(name, value);
Dees_Troy51a0e822012-09-05 15:24:24 -04001471}