blob: 975d40ff02ba3b105b268a43115913ed99640adc [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
Dees_Troy51a0e822012-09-05 15:24:24 -0400232bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
233{
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"))
thatf6ed8fc2015-02-14 20:23:16 +0100250 *placement = (RenderObject::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
Ethan Yonker780cd392014-07-21 15:24:39 -0500270Page::Page(xml_node<>* page, std::vector<xml_node<>*> *templates /* = NULL */)
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
299 ProcessNode(page, templates);
Dees_Troy51a0e822012-09-05 15:24:24 -0400300
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200301 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400302}
303
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100304Page::~Page()
305{
306 for (std::vector<GUIObject*>::iterator itr = mObjects.begin(); itr != mObjects.end(); ++itr)
307 delete *itr;
308}
309
Ethan Yonker780cd392014-07-21 15:24:39 -0500310bool Page::ProcessNode(xml_node<>* page, std::vector<xml_node<>*> *templates /* = NULL */, int depth /* = 0 */)
Dees_Troy51a0e822012-09-05 15:24:24 -0400311{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200312 if (depth == 10)
313 {
314 LOGERR("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
315 return false;
316 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400317
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200318 // Let's retrieve the background value, if any
319 xml_node<>* bg = page->first_node("background");
320 if (bg)
321 {
322 xml_attribute<>* attr = bg->first_attribute("color");
323 if (attr)
324 {
325 std::string color = attr->value();
326 ConvertStrToColor(color, &mBackground);
327 }
328 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400329
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200330 xml_node<>* child;
331 child = page->first_node("object");
332 while (child)
333 {
334 if (!child->first_attribute("type"))
335 break;
Dees_Troy51a0e822012-09-05 15:24:24 -0400336
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200337 std::string type = child->first_attribute("type")->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400338
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200339 if (type == "text")
340 {
341 GUIText* element = new GUIText(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100342 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200343 mRenders.push_back(element);
344 mActions.push_back(element);
345 }
346 else if (type == "image")
347 {
348 GUIImage* element = new GUIImage(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100349 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200350 mRenders.push_back(element);
351 }
352 else if (type == "fill")
353 {
354 GUIFill* element = new GUIFill(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100355 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200356 mRenders.push_back(element);
357 }
358 else if (type == "action")
359 {
360 GUIAction* element = new GUIAction(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100361 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200362 mActions.push_back(element);
363 }
364 else if (type == "console")
365 {
366 GUIConsole* element = new GUIConsole(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100367 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200368 mRenders.push_back(element);
369 mActions.push_back(element);
370 }
371 else if (type == "button")
372 {
373 GUIButton* element = new GUIButton(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100374 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200375 mRenders.push_back(element);
376 mActions.push_back(element);
377 }
378 else if (type == "checkbox")
379 {
380 GUICheckbox* element = new GUICheckbox(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100381 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200382 mRenders.push_back(element);
383 mActions.push_back(element);
384 }
385 else if (type == "fileselector")
386 {
387 GUIFileSelector* element = new GUIFileSelector(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100388 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200389 mRenders.push_back(element);
390 mActions.push_back(element);
391 }
392 else if (type == "animation")
393 {
394 GUIAnimation* element = new GUIAnimation(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100395 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200396 mRenders.push_back(element);
397 }
398 else if (type == "progressbar")
399 {
400 GUIProgressBar* element = new GUIProgressBar(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100401 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200402 mRenders.push_back(element);
403 mActions.push_back(element);
404 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400405 else if (type == "slider")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200406 {
407 GUISlider* element = new GUISlider(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100408 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200409 mRenders.push_back(element);
410 mActions.push_back(element);
411 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200412 else if (type == "slidervalue")
413 {
414 GUISliderValue *element = new GUISliderValue(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100415 mObjects.push_back(element);
Vojtech Bocek85932342013-04-01 22:11:33 +0200416 mRenders.push_back(element);
417 mActions.push_back(element);
418 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400419 else if (type == "listbox")
420 {
421 GUIListBox* element = new GUIListBox(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100422 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400423 mRenders.push_back(element);
424 mActions.push_back(element);
425 }
426 else if (type == "keyboard")
427 {
428 GUIKeyboard* element = new GUIKeyboard(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100429 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400430 mRenders.push_back(element);
431 mActions.push_back(element);
432 }
433 else if (type == "input")
434 {
435 GUIInput* element = new GUIInput(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100436 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400437 mRenders.push_back(element);
438 mActions.push_back(element);
439 mInputs.push_back(element);
440 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500441 else if (type == "partitionlist")
442 {
443 GUIPartitionList* element = new GUIPartitionList(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100444 mObjects.push_back(element);
Dees_Troya13d74f2013-03-24 08:54:55 -0500445 mRenders.push_back(element);
446 mActions.push_back(element);
447 }
Vojtech Bocek7e11ac52015-03-05 23:21:49 +0100448 else if (type == "patternpassword")
449 {
450 GUIPatternPassword* element = new GUIPatternPassword(child);
451 mObjects.push_back(element);
452 mRenders.push_back(element);
453 mActions.push_back(element);
454 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200455 else if (type == "template")
456 {
457 if (!templates || !child->first_attribute("name"))
458 {
459 LOGERR("Invalid template request.\n");
460 }
461 else
462 {
463 std::string name = child->first_attribute("name")->value();
Ethan Yonker780cd392014-07-21 15:24:39 -0500464 xml_node<>* node;
465 bool node_found = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400466
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200467 // We need to find the correct template
Ethan Yonker780cd392014-07-21 15:24:39 -0500468 for (std::vector<xml_node<>*>::iterator itr = templates->begin(); itr != templates->end(); itr++) {
469 node = (*itr)->first_node("template");
Dees_Troy51a0e822012-09-05 15:24:24 -0400470
Ethan Yonker780cd392014-07-21 15:24:39 -0500471 while (node)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200472 {
Ethan Yonker780cd392014-07-21 15:24:39 -0500473 if (!node->first_attribute("name"))
474 continue;
475
476 if (name == node->first_attribute("name")->value())
477 {
478 if (!ProcessNode(node, templates, depth + 1))
479 return false;
480 else {
481 node_found = true;
482 break;
483 }
484 }
485 if (node_found)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200486 break;
Ethan Yonker780cd392014-07-21 15:24:39 -0500487 node = node->next_sibling("template");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200488 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200489 }
490 }
491 }
492 else
493 {
494 LOGERR("Unknown object type.\n");
495 }
496 child = child->next_sibling("object");
497 }
498 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400499}
500
501int Page::Render(void)
502{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200503 // Render background
504 gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
505 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
Dees_Troy51a0e822012-09-05 15:24:24 -0400506
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200507 // Render remaining objects
508 std::vector<RenderObject*>::iterator iter;
509 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
510 {
511 if ((*iter)->Render())
512 LOGERR("A render request has failed.\n");
513 }
514 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400515}
516
517int Page::Update(void)
518{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200519 int retCode = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400520
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200521 std::vector<RenderObject*>::iterator iter;
522 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
523 {
524 int ret = (*iter)->Update();
525 if (ret < 0)
526 LOGERR("An update request has failed.\n");
527 else if (ret > retCode)
528 retCode = ret;
529 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400530
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200531 return retCode;
Dees_Troy51a0e822012-09-05 15:24:24 -0400532}
533
534int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
535{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200536 // By default, return 1 to ignore further touches if nobody is listening
537 int ret = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400538
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200539 // Don't try to handle a lack of handlers
540 if (mActions.size() == 0)
541 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400542
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200543 // We record mTouchStart so we can pass all the touch stream to the same handler
544 if (state == TOUCH_START)
545 {
546 std::vector<ActionObject*>::reverse_iterator iter;
547 // We work backwards, from top-most element to bottom-most element
548 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
549 {
550 if ((*iter)->IsInRegion(x, y))
551 {
552 mTouchStart = (*iter);
553 ret = mTouchStart->NotifyTouch(state, x, y);
554 if (ret >= 0)
555 break;
556 mTouchStart = NULL;
557 }
558 }
559 }
560 else if (state == TOUCH_RELEASE && mTouchStart != NULL)
561 {
562 ret = mTouchStart->NotifyTouch(state, x, y);
563 mTouchStart = NULL;
564 }
565 else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
566 {
567 ret = mTouchStart->NotifyTouch(state, x, y);
568 }
569 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400570}
571
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100572int Page::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -0400573{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200574 std::vector<ActionObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400575
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200576 // Don't try to handle a lack of handlers
577 if (mActions.size() == 0)
578 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400579
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100580 int ret = 1;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200581 // We work backwards, from top-most element to bottom-most element
582 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
583 {
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100584 ret = (*iter)->NotifyKey(key, down);
585 if (ret < 0) {
586 LOGERR("An action handler has returned an error\n");
587 ret = 1;
588 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200589 }
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100590 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400591}
592
593int Page::NotifyKeyboard(int key)
594{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200595 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400596
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200597 // Don't try to handle a lack of handlers
598 if (mInputs.size() == 0)
599 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400600
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200601 // We work backwards, from top-most element to bottom-most element
602 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
603 {
604 int ret = (*iter)->NotifyKeyboard(key);
605 if (ret == 0)
606 return 0;
607 else if (ret < 0)
608 LOGERR("A keyboard handler has returned an error");
609 }
610 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400611}
612
613int Page::SetKeyBoardFocus(int inFocus)
614{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200615 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400616
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200617 // Don't try to handle a lack of handlers
618 if (mInputs.size() == 0)
619 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400620
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200621 // We work backwards, from top-most element to bottom-most element
622 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
623 {
624 int ret = (*iter)->SetInputFocus(inFocus);
625 if (ret == 0)
626 return 0;
627 else if (ret < 0)
628 LOGERR("An input focus handler has returned an error");
629 }
630 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400631}
632
633void Page::SetPageFocus(int inFocus)
634{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200635 // Render remaining objects
636 std::vector<RenderObject*>::iterator iter;
637 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
638 (*iter)->SetPageFocus(inFocus);
639
640 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400641}
642
643int Page::NotifyVarChange(std::string varName, std::string value)
644{
Vojtech Bocek07220562014-02-08 02:05:33 +0100645 std::vector<GUIObject*>::iterator iter;
646 for (iter = mObjects.begin(); iter != mObjects.end(); ++iter)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200647 {
648 if ((*iter)->NotifyVarChange(varName, value))
649 LOGERR("An action handler errored on NotifyVarChange.\n");
650 }
651 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400652}
653
654PageSet::PageSet(char* xmlFile)
655{
that74ac6062015-03-04 22:39:34 +0100656 mResources = new ResourceManager;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200657 mCurrentPage = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400658
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200659 mXmlFile = xmlFile;
660 if (xmlFile)
661 mDoc.parse<0>(mXmlFile);
662 else
663 mCurrentPage = new Page(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400664}
665
666PageSet::~PageSet()
667{
Ethan Yonker1c273312015-03-16 12:18:56 -0500668 mOverlays.clear();
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100669 for (std::vector<Page*>::iterator itr = mPages.begin(); itr != mPages.end(); ++itr)
670 delete *itr;
671
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200672 delete mResources;
673 free(mXmlFile);
Vojtech Boceke979abd2015-01-12 18:29:12 +0100674
675 mDoc.clear();
676
677 for (std::vector<xml_document<>*>::iterator itr = mIncludedDocs.begin(); itr != mIncludedDocs.end(); ++itr) {
678 (*itr)->clear();
679 delete *itr;
680 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400681}
682
683int PageSet::Load(ZipArchive* package)
684{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200685 xml_node<>* parent;
686 xml_node<>* child;
Ethan Yonker780cd392014-07-21 15:24:39 -0500687 xml_node<>* xmltemplate;
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600688 xml_node<>* xmlstyle;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500689
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200690 parent = mDoc.first_node("recovery");
691 if (!parent)
692 parent = mDoc.first_node("install");
Dees_Troy51a0e822012-09-05 15:24:24 -0400693
Ethan Yonker63e414f2015-02-06 15:44:39 -0600694 set_scale_values(1, 1); // Reset any previous scaling values
695
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200696 // Now, let's parse the XML
Ethan Yonker63e414f2015-02-06 15:44:39 -0600697 LOGINFO("Checking resolution...\n");
698 child = parent->first_node("details");
699 if (child) {
700 xml_node<>* resolution = child->first_node("resolution");
701 if (resolution) {
702 xml_attribute<>* width_attr = resolution->first_attribute("width");
703 xml_attribute<>* height_attr = resolution->first_attribute("height");
704 xml_attribute<>* noscale_attr = resolution->first_attribute("noscaling");
705 if (width_attr && height_attr && !noscale_attr) {
706 int width = atoi(width_attr->value());
707 int height = atoi(height_attr->value());
708 int offx = 0, offy = 0;
709#ifdef TW_ROUND_SCREEN
710 xml_node<>* roundscreen = child->first_node("roundscreen");
711 if (roundscreen) {
712 LOGINFO("TW_ROUND_SCREEN := true, using round screen XML settings.\n");
713 xml_attribute<>* offx_attr = roundscreen->first_attribute("offset_x");
714 xml_attribute<>* offy_attr = roundscreen->first_attribute("offset_y");
715 if (offx_attr) {
716 offx = atoi(offx_attr->value());
717 }
718 if (offy_attr) {
719 offy = atoi(offy_attr->value());
720 }
721 }
722#endif
723 if (width != 0 && height != 0) {
724 float scale_w = ((float)gr_fb_width() - ((float)offx * 2.0)) / (float)width;
725 float scale_h = ((float)gr_fb_height() - ((float)offy * 2.0)) / (float)height;
726#ifdef TW_ROUND_SCREEN
727 float scale_off_w = (float)gr_fb_width() / (float)width;
728 float scale_off_h = (float)gr_fb_height() / (float)height;
729 tw_x_offset = offx * scale_off_w;
730 tw_y_offset = offy * scale_off_h;
731#endif
732 if (scale_w != 1 || scale_h != 1) {
733 LOGINFO("Scaling theme width %fx and height %fx, offsets x: %i y: %i\n", scale_w, scale_h, tw_x_offset, tw_y_offset);
734 set_scale_values(scale_w, scale_h);
735 }
736 }
737 } else {
738 LOGINFO("XML does not contain width and height, no scaling will be applied\n");
739 }
740 } else {
741 LOGINFO("XML contains no resolution tag, no scaling will be applied.\n");
742 }
743 } else {
744 LOGINFO("XML contains no details tag, no scaling will be applied.\n");
745 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200746 LOGINFO("Loading resources...\n");
747 child = parent->first_node("resources");
748 if (child)
that74ac6062015-03-04 22:39:34 +0100749 mResources->LoadResources(child, package);
Dees_Troy51a0e822012-09-05 15:24:24 -0400750
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200751 LOGINFO("Loading variables...\n");
752 child = parent->first_node("variables");
753 if (child)
754 LoadVariables(child);
Dees_Troy51a0e822012-09-05 15:24:24 -0400755
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +0100756 LOGINFO("Loading mouse cursor...\n");
757 child = parent->first_node("mousecursor");
758 if(child)
759 PageManager::LoadCursorData(child);
760
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200761 LOGINFO("Loading pages...\n");
762 // This may be NULL if no templates are present
Ethan Yonker780cd392014-07-21 15:24:39 -0500763 xmltemplate = parent->first_node("templates");
764 if (xmltemplate)
765 templates.push_back(xmltemplate);
Dees_Troy51a0e822012-09-05 15:24:24 -0400766
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600767 // Load styles if present
768 xmlstyle = parent->first_node("styles");
769 if (xmlstyle)
770 styles.push_back(xmlstyle);
771
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200772 child = parent->first_node("pages");
Ethan Yonker780cd392014-07-21 15:24:39 -0500773 if (child) {
774 if (LoadPages(child)) {
775 LOGERR("PageSet::Load returning -1\n");
776 return -1;
777 }
778 }
Vojtech Boceke979abd2015-01-12 18:29:12 +0100779
Ethan Yonker780cd392014-07-21 15:24:39 -0500780 return CheckInclude(package, &mDoc);
781}
Dees_Troy51a0e822012-09-05 15:24:24 -0400782
Ethan Yonker780cd392014-07-21 15:24:39 -0500783int PageSet::CheckInclude(ZipArchive* package, xml_document<> *parentDoc)
784{
785 xml_node<>* par;
786 xml_node<>* par2;
787 xml_node<>* chld;
788 xml_node<>* parent;
789 xml_node<>* child;
790 xml_node<>* xmltemplate;
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600791 xml_node<>* xmlstyle;
Ethan Yonker780cd392014-07-21 15:24:39 -0500792 long len;
793 char* xmlFile = NULL;
794 string filename;
Vojtech Boceke979abd2015-01-12 18:29:12 +0100795 xml_document<> *doc = NULL;
Ethan Yonker780cd392014-07-21 15:24:39 -0500796
797 par = parentDoc->first_node("recovery");
798 if (!par) {
799 par = parentDoc->first_node("install");
800 }
801 if (!par) {
802 return 0;
803 }
804
805 par2 = par->first_node("include");
806 if (!par2)
807 return 0;
808 chld = par2->first_node("xmlfile");
809 while (chld != NULL) {
810 xml_attribute<>* attr = chld->first_attribute("name");
811 if (!attr)
812 break;
813
Ethan Yonker780cd392014-07-21 15:24:39 -0500814 if (!package) {
815 // We can try to load the XML directly...
Dees Troy3454ade2015-01-20 19:21:04 +0000816 filename = TWRES;
Ethan Yonker780cd392014-07-21 15:24:39 -0500817 filename += attr->value();
Dees Troy3454ade2015-01-20 19:21:04 +0000818 LOGINFO("PageSet::CheckInclude loading filename: '%s'\n", filename.c_str());
Ethan Yonker780cd392014-07-21 15:24:39 -0500819 struct stat st;
820 if(stat(filename.c_str(),&st) != 0) {
821 LOGERR("Unable to locate '%s'\n", filename.c_str());
822 return -1;
823 }
824
825 len = st.st_size;
826 xmlFile = (char*) malloc(len + 1);
827 if (!xmlFile)
828 return -1;
829
830 int fd = open(filename.c_str(), O_RDONLY);
831 if (fd == -1)
832 return -1;
833
834 read(fd, xmlFile, len);
835 close(fd);
836 } else {
837 filename += attr->value();
Dees Troy3454ade2015-01-20 19:21:04 +0000838 LOGINFO("PageSet::CheckInclude loading filename: '%s'\n", filename.c_str());
Ethan Yonker780cd392014-07-21 15:24:39 -0500839 const ZipEntry* ui_xml = mzFindZipEntry(package, filename.c_str());
840 if (ui_xml == NULL)
841 {
842 LOGERR("Unable to locate '%s' in zip file\n", filename.c_str());
843 return -1;
844 }
845
846 // Allocate the buffer for the file
847 len = mzGetZipEntryUncompLen(ui_xml);
848 xmlFile = (char*) malloc(len + 1);
849 if (!xmlFile)
850 return -1;
851
852 if (!mzExtractZipEntryToBuffer(package, ui_xml, (unsigned char*) xmlFile))
853 {
854 LOGERR("Unable to extract '%s'\n", filename.c_str());
855 return -1;
856 }
857 }
Ethan Yonker780cd392014-07-21 15:24:39 -0500858
Vojtech Boceke979abd2015-01-12 18:29:12 +0100859 xmlFile[len] = '\0';
860 doc = new xml_document<>();
861 doc->parse<0>(xmlFile);
862
863 parent = doc->first_node("recovery");
Ethan Yonker780cd392014-07-21 15:24:39 -0500864 if (!parent)
Vojtech Boceke979abd2015-01-12 18:29:12 +0100865 parent = doc->first_node("install");
Ethan Yonker780cd392014-07-21 15:24:39 -0500866
867 // Now, let's parse the XML
868 LOGINFO("Loading included resources...\n");
869 child = parent->first_node("resources");
870 if (child)
871 mResources->LoadResources(child, package);
872
873 LOGINFO("Loading included variables...\n");
874 child = parent->first_node("variables");
875 if (child)
876 LoadVariables(child);
877
878 LOGINFO("Loading mouse cursor...\n");
879 child = parent->first_node("mousecursor");
880 if(child)
881 PageManager::LoadCursorData(child);
882
883 LOGINFO("Loading included pages...\n");
884 // This may be NULL if no templates are present
885 xmltemplate = parent->first_node("templates");
886 if (xmltemplate)
887 templates.push_back(xmltemplate);
888
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600889 // Load styles if present
890 xmlstyle = parent->first_node("styles");
891 if (xmlstyle)
892 styles.push_back(xmlstyle);
893
Ethan Yonker780cd392014-07-21 15:24:39 -0500894 child = parent->first_node("pages");
Vojtech Boceke979abd2015-01-12 18:29:12 +0100895 if (child && LoadPages(child))
896 {
897 templates.pop_back();
898 doc->clear();
899 delete doc;
900 return -1;
901 }
Ethan Yonker780cd392014-07-21 15:24:39 -0500902
Vojtech Boceke979abd2015-01-12 18:29:12 +0100903 mIncludedDocs.push_back(doc);
904
905 if (CheckInclude(package, doc))
Ethan Yonker780cd392014-07-21 15:24:39 -0500906 return -1;
907
908 chld = chld->next_sibling("xmlfile");
909 }
910
911 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400912}
913
914int PageSet::SetPage(std::string page)
915{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200916 Page* tmp = FindPage(page);
917 if (tmp)
918 {
919 if (mCurrentPage) mCurrentPage->SetPageFocus(0);
920 mCurrentPage = tmp;
921 mCurrentPage->SetPageFocus(1);
922 mCurrentPage->NotifyVarChange("", "");
923 return 0;
924 }
925 else
926 {
927 LOGERR("Unable to locate page (%s)\n", page.c_str());
928 }
929 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400930}
931
932int PageSet::SetOverlay(Page* page)
933{
Ethan Yonker1c273312015-03-16 12:18:56 -0500934 if (page) {
935 if (mOverlays.size() >= 10) {
936 LOGERR("Too many overlays requested, max is 10.\n");
937 return -1;
938 }
Matt Mowerd411f8d2015-04-09 16:04:12 -0500939
940 std::vector<Page*>::iterator iter;
941 for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
942 if ((*iter)->GetName() == page->GetName()) {
943 mOverlays.erase(iter);
944 // SetOverlay() is (and should stay) the only function which
945 // adds to mOverlays. Then, each page can appear at most once.
946 break;
947 }
948 }
949
Ethan Yonker1c273312015-03-16 12:18:56 -0500950 page->SetPageFocus(1);
951 page->NotifyVarChange("", "");
952
953 if (!mOverlays.empty())
954 mOverlays.back()->SetPageFocus(0);
955
956 mOverlays.push_back(page);
957 } else {
958 if (!mOverlays.empty()) {
959 mOverlays.back()->SetPageFocus(0);
960 mOverlays.pop_back();
961 if (!mOverlays.empty())
962 mOverlays.back()->SetPageFocus(1);
963 else if (mCurrentPage)
964 mCurrentPage->SetPageFocus(1); // Just in case somehow the regular page lost focus, we'll set it again
965 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200966 }
967 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400968}
969
that74ac6062015-03-04 22:39:34 +0100970const ResourceManager* PageSet::GetResources()
Dees_Troy51a0e822012-09-05 15:24:24 -0400971{
that74ac6062015-03-04 22:39:34 +0100972 return mResources;
Dees_Troy51a0e822012-09-05 15:24:24 -0400973}
974
975Page* PageSet::FindPage(std::string name)
976{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200977 std::vector<Page*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400978
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200979 for (iter = mPages.begin(); iter != mPages.end(); iter++)
980 {
981 if (name == (*iter)->GetName())
982 return (*iter);
983 }
984 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400985}
986
987int PageSet::LoadVariables(xml_node<>* vars)
988{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200989 xml_node<>* child;
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100990 xml_attribute<> *name, *value, *persist;
991 int p;
Dees_Troy51a0e822012-09-05 15:24:24 -0400992
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200993 child = vars->first_node("variable");
994 while (child)
995 {
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100996 name = child->first_attribute("name");
997 value = child->first_attribute("value");
998 persist = child->first_attribute("persist");
999 if(name && value)
1000 {
Ethan Yonker751a85e2014-12-12 16:59:10 -06001001 if (strcmp(name->value(), "tw_x_offset") == 0) {
1002 tw_x_offset = atoi(value->value());
1003 child = child->next_sibling("variable");
1004 continue;
1005 }
1006 if (strcmp(name->value(), "tw_y_offset") == 0) {
1007 tw_y_offset = atoi(value->value());
1008 child = child->next_sibling("variable");
1009 continue;
1010 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +01001011 p = persist ? atoi(persist->value()) : 0;
Ethan Yonker96acb3d2014-08-05 09:20:30 -05001012 string temp = value->value();
1013 string valstr = gui_parse_text(temp);
1014
1015 if (valstr.find("+") != string::npos) {
1016 string val1str = valstr;
1017 val1str = val1str.substr(0, val1str.find('+'));
1018 string val2str = valstr;
1019 val2str = val2str.substr(val2str.find('+') + 1, string::npos);
1020 int val1 = atoi(val1str.c_str());
1021 int val2 = atoi(val2str.c_str());
1022 int val = val1 + val2;
1023
1024 DataManager::SetValue(name->value(), val, p);
1025 } else if (valstr.find("-") != string::npos) {
1026 string val1str = valstr;
1027 val1str = val1str.substr(0, val1str.find('-'));
1028 string val2str = valstr;
1029 val2str = val2str.substr(val2str.find('-') + 1, string::npos);
1030 int val1 = atoi(val1str.c_str());
1031 int val2 = atoi(val2str.c_str());
1032 int val = val1 - val2;
1033
1034 DataManager::SetValue(name->value(), val, p);
1035 } else {
1036 DataManager::SetValue(name->value(), valstr, p);
1037 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +01001038 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001039
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001040 child = child->next_sibling("variable");
1041 }
1042 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001043}
1044
Ethan Yonker780cd392014-07-21 15:24:39 -05001045int PageSet::LoadPages(xml_node<>* pages)
Dees_Troy51a0e822012-09-05 15:24:24 -04001046{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001047 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -04001048
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001049 if (!pages)
1050 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001051
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001052 child = pages->first_node("page");
1053 while (child != NULL)
1054 {
Ethan Yonker780cd392014-07-21 15:24:39 -05001055 Page* page = new Page(child, &templates);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001056 if (page->GetName().empty())
1057 {
1058 LOGERR("Unable to process load page\n");
1059 delete page;
1060 }
1061 else
1062 {
1063 mPages.push_back(page);
1064 }
1065 child = child->next_sibling("page");
1066 }
1067 if (mPages.size() > 0)
1068 return 0;
1069 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001070}
1071
1072int PageSet::IsCurrentPage(Page* page)
1073{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001074 return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -04001075}
1076
1077int PageSet::Render(void)
1078{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001079 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001080
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001081 ret = (mCurrentPage ? mCurrentPage->Render() : -1);
1082 if (ret < 0)
1083 return ret;
Ethan Yonker1c273312015-03-16 12:18:56 -05001084
1085 std::vector<Page*>::iterator iter;
1086
1087 for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
1088 ret = ((*iter) ? (*iter)->Render() : -1);
1089 if (ret < 0)
1090 return ret;
1091 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001092 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001093}
1094
1095int PageSet::Update(void)
1096{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001097 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001098
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001099 ret = (mCurrentPage ? mCurrentPage->Update() : -1);
1100 if (ret < 0 || ret > 1)
1101 return ret;
Ethan Yonker1c273312015-03-16 12:18:56 -05001102
1103 std::vector<Page*>::iterator iter;
1104
1105 for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
1106 ret = ((*iter) ? (*iter)->Update() : -1);
1107 if (ret < 0)
1108 return ret;
1109 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001110 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001111}
1112
1113int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
1114{
Ethan Yonker1c273312015-03-16 12:18:56 -05001115 if (!mOverlays.empty())
1116 return mOverlays.back()->NotifyTouch(state, x, y);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001117
1118 return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001119}
1120
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001121int PageSet::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -04001122{
Ethan Yonker1c273312015-03-16 12:18:56 -05001123 if (!mOverlays.empty())
1124 return mOverlays.back()->NotifyKey(key, down);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001125
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001126 return (mCurrentPage ? mCurrentPage->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001127}
1128
1129int PageSet::NotifyKeyboard(int key)
1130{
Ethan Yonker1c273312015-03-16 12:18:56 -05001131 if (!mOverlays.empty())
1132 return mOverlays.back()->NotifyKeyboard(key);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001133
1134 return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001135}
1136
1137int PageSet::SetKeyBoardFocus(int inFocus)
1138{
Ethan Yonker1c273312015-03-16 12:18:56 -05001139 if (!mOverlays.empty())
1140 return mOverlays.back()->SetKeyBoardFocus(inFocus);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001141
1142 return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001143}
1144
1145int PageSet::NotifyVarChange(std::string varName, std::string value)
1146{
Ethan Yonker1c273312015-03-16 12:18:56 -05001147 std::vector<Page*>::iterator iter;
1148
1149 for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++)
1150 (*iter)->NotifyVarChange(varName, value);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001151
1152 return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001153}
1154
1155int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
1156{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001157 int fd;
1158 ZipArchive zip, *pZip = NULL;
1159 long len;
1160 char* xmlFile = NULL;
1161 PageSet* pageSet = NULL;
1162 int ret;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001163 MemMapping map;
Dees_Troy51a0e822012-09-05 15:24:24 -04001164
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001165 // Open the XML file
1166 LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001167 if (package.size() > 4 && package.substr(package.size() - 4) != ".zip")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001168 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001169 LOGINFO("Load XML directly\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -06001170 tw_x_offset = TW_X_OFFSET;
1171 tw_y_offset = TW_Y_OFFSET;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001172 // We can try to load the XML directly...
1173 struct stat st;
1174 if(stat(package.c_str(),&st) != 0)
1175 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001176
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001177 len = st.st_size;
1178 xmlFile = (char*) malloc(len + 1);
1179 if (!xmlFile)
1180 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001181
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001182 fd = open(package.c_str(), O_RDONLY);
1183 if (fd == -1)
1184 goto error;
Dees_Troy51a0e822012-09-05 15:24:24 -04001185
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001186 read(fd, xmlFile, len);
1187 close(fd);
1188 }
1189 else
1190 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001191 LOGINFO("Loading zip theme\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -06001192 tw_x_offset = 0;
1193 tw_y_offset = 0;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001194 if (!TWFunc::Path_Exists(package))
1195 return -1;
1196 if (sysMapFile(package.c_str(), &map) != 0) {
1197 LOGERR("Failed to map '%s'\n", package.c_str());
1198 return -1;
1199 }
1200 if (mzOpenZipArchive(map.addr, map.length, &zip)) {
1201 LOGERR("Unable to open zip archive '%s'\n", package.c_str());
1202 sysReleaseMap(&map);
1203 return -1;
1204 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001205 pZip = &zip;
1206 const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
1207 if (ui_xml == NULL)
1208 {
1209 LOGERR("Unable to locate ui.xml in zip file\n");
1210 goto error;
1211 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001212
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001213 // Allocate the buffer for the file
1214 len = mzGetZipEntryUncompLen(ui_xml);
1215 xmlFile = (char*) malloc(len + 1);
1216 if (!xmlFile)
1217 goto error;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001218
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001219 if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
1220 {
1221 LOGERR("Unable to extract ui.xml\n");
1222 goto error;
1223 }
1224 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001225
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001226 // NULL-terminate the string
1227 xmlFile[len] = 0x00;
Dees_Troy51a0e822012-09-05 15:24:24 -04001228
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001229 // Before loading, mCurrentSet must be the loading package so we can find resources
1230 pageSet = mCurrentSet;
1231 mCurrentSet = new PageSet(xmlFile);
1232
1233 ret = mCurrentSet->Load(pZip);
1234 if (ret == 0)
1235 {
1236 mCurrentSet->SetPage(startpage);
1237 mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
1238 }
1239 else
1240 {
1241 LOGERR("Package %s failed to load.\n", name.c_str());
1242 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001243
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001244 // The first successful package we loaded is the base
1245 if (mBaseSet == NULL)
1246 mBaseSet = mCurrentSet;
1247
1248 mCurrentSet = pageSet;
1249
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001250 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001251 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001252 sysReleaseMap(&map);
1253 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001254 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001255
1256error:
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001257 LOGERR("An internal error has occurred.\n");
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001258 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001259 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001260 sysReleaseMap(&map);
1261 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001262 if (xmlFile)
1263 free(xmlFile);
1264 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001265}
1266
1267PageSet* PageManager::FindPackage(std::string name)
1268{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001269 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001270
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001271 iter = mPageSets.find(name);
1272 if (iter != mPageSets.end())
1273 return (*iter).second;
1274
1275 LOGERR("Unable to locate package %s\n", name.c_str());
1276 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -04001277}
1278
1279PageSet* PageManager::SelectPackage(std::string name)
1280{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001281 LOGINFO("Switching packages (%s)\n", name.c_str());
1282 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -04001283
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001284 tmp = FindPackage(name);
1285 if (tmp)
Vojtech Bocek07220562014-02-08 02:05:33 +01001286 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001287 mCurrentSet = tmp;
Vojtech Bocek07220562014-02-08 02:05:33 +01001288 mCurrentSet->NotifyVarChange("", "");
1289 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001290 else
1291 LOGERR("Unable to find package.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -04001292
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001293 return mCurrentSet;
Dees_Troy51a0e822012-09-05 15:24:24 -04001294}
1295
1296int PageManager::ReloadPackage(std::string name, std::string package)
1297{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001298 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001299
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001300 iter = mPageSets.find(name);
1301 if (iter == mPageSets.end())
1302 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001303
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001304 if(mMouseCursor)
1305 mMouseCursor->ResetData(gr_fb_width(), gr_fb_height());
1306
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001307 PageSet* set = (*iter).second;
1308 mPageSets.erase(iter);
Dees_Troy51a0e822012-09-05 15:24:24 -04001309
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001310 if (LoadPackage(name, package, "main") != 0)
1311 {
Dees Troy3454ade2015-01-20 19:21:04 +00001312 LOGERR("Failed to load package '%s'.\n", package.c_str());
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001313 mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
1314 return -1;
1315 }
1316 if (mCurrentSet == set)
1317 SelectPackage(name);
Vojtech Bocekbfb63342014-02-08 00:32:31 +01001318 if (mBaseSet == set)
1319 mBaseSet = mCurrentSet;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001320 delete set;
1321 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001322}
1323
1324void PageManager::ReleasePackage(std::string name)
1325{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001326 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001327
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001328 iter = mPageSets.find(name);
1329 if (iter == mPageSets.end())
1330 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001331
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001332 PageSet* set = (*iter).second;
1333 mPageSets.erase(iter);
1334 delete set;
1335 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001336}
1337
1338int PageManager::ChangePage(std::string name)
1339{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001340 DataManager::SetValue("tw_operation_state", 0);
1341 int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
1342 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001343}
1344
1345int PageManager::ChangeOverlay(std::string name)
1346{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001347 if (name.empty())
1348 return mCurrentSet->SetOverlay(NULL);
1349 else
1350 {
1351 Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
1352 return mCurrentSet->SetOverlay(page);
1353 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001354}
1355
that74ac6062015-03-04 22:39:34 +01001356const ResourceManager* PageManager::GetResources()
Dees_Troy51a0e822012-09-05 15:24:24 -04001357{
that74ac6062015-03-04 22:39:34 +01001358 return (mCurrentSet ? mCurrentSet->GetResources() : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001359}
1360
1361int PageManager::SwitchToConsole(void)
1362{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001363 PageSet* console = new PageSet(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001364
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001365 mCurrentSet = console;
1366 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001367}
1368
Ethan Yonker03a42f62014-08-08 11:03:51 -05001369int PageManager::EndConsole(void)
1370{
1371 if (mCurrentSet && mBaseSet) {
1372 delete mCurrentSet;
1373 mCurrentSet = mBaseSet;
1374 return 0;
1375 }
1376 return -1;
1377}
1378
Dees_Troy51a0e822012-09-05 15:24:24 -04001379int PageManager::IsCurrentPage(Page* page)
1380{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001381 return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -04001382}
1383
1384int PageManager::Render(void)
1385{
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001386 int res = (mCurrentSet ? mCurrentSet->Render() : -1);
1387 if(mMouseCursor)
1388 mMouseCursor->Render();
1389 return res;
1390}
1391
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001392HardwareKeyboard *PageManager::GetHardwareKeyboard()
1393{
1394 if(!mHardwareKeyboard)
1395 mHardwareKeyboard = new HardwareKeyboard();
1396 return mHardwareKeyboard;
1397}
1398
Ethan Yonker21ff02a2015-02-18 14:35:00 -06001399xml_node<>* PageManager::FindStyle(std::string name)
1400{
1401 for (std::vector<xml_node<>*>::iterator itr = mCurrentSet->styles.begin(); itr != mCurrentSet->styles.end(); itr++) {
1402 xml_node<>* node = (*itr)->first_node("style");
1403
1404 while (node) {
1405 if (!node->first_attribute("name"))
1406 continue;
1407
1408 if (name == node->first_attribute("name")->value())
1409 return node;
1410 node = node->next_sibling("style");
1411 }
1412 }
1413 return NULL;
1414}
1415
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001416MouseCursor *PageManager::GetMouseCursor()
1417{
1418 if(!mMouseCursor)
1419 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1420 return mMouseCursor;
1421}
1422
1423void PageManager::LoadCursorData(xml_node<>* node)
1424{
1425 if(!mMouseCursor)
1426 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1427
1428 mMouseCursor->LoadData(node);
Dees_Troy51a0e822012-09-05 15:24:24 -04001429}
1430
1431int PageManager::Update(void)
1432{
thatfb759d42015-01-11 12:16:53 +01001433 if(blankTimer.isScreenOff())
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001434 return 0;
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001435
1436 int res = (mCurrentSet ? mCurrentSet->Update() : -1);
1437
1438 if(mMouseCursor)
1439 {
1440 int c_res = mMouseCursor->Update();
1441 if(c_res > res)
1442 res = c_res;
1443 }
1444 return res;
Dees_Troy51a0e822012-09-05 15:24:24 -04001445}
1446
1447int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
1448{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001449 return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001450}
1451
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001452int PageManager::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -04001453{
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001454 return (mCurrentSet ? mCurrentSet->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001455}
1456
1457int PageManager::NotifyKeyboard(int key)
1458{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001459 return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001460}
1461
1462int PageManager::SetKeyBoardFocus(int inFocus)
1463{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001464 return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001465}
1466
1467int PageManager::NotifyVarChange(std::string varName, std::string value)
1468{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001469 return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001470}
1471
1472extern "C" void gui_notifyVarChange(const char *name, const char* value)
1473{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001474 if (!gGuiRunning)
1475 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001476
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001477 PageManager::NotifyVarChange(name, value);
Dees_Troy51a0e822012-09-05 15:24:24 -04001478}