blob: bea39e902dee6a4d8918b51b78fbeaf83f0b4cd2 [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"
Dees_Troy51a0e822012-09-05 15:24:24 -040044}
45
46#include "rapidxml.hpp"
47#include "objects.hpp"
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070048#ifndef TW_NO_SCREEN_TIMEOUT
gordon13370d9133d2013-06-08 14:17:07 +020049#include "blanktimer.hpp"
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070050#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040051
52extern int gGuiRunning;
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070053#ifndef TW_NO_SCREEN_TIMEOUT
gordon13370d9133d2013-06-08 14:17:07 +020054extern blanktimer blankTimer;
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070055#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040056
57std::map<std::string, PageSet*> PageManager::mPageSets;
58PageSet* PageManager::mCurrentSet;
59PageSet* PageManager::mBaseSet = NULL;
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +010060MouseCursor *PageManager::mMouseCursor = NULL;
Vojtech Bocek0b7fe502014-03-13 17:36:52 +010061HardwareKeyboard *PageManager::mHardwareKeyboard = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -040062
Dees_Troy51a0e822012-09-05 15:24:24 -040063// Helper routine to convert a string to a color declaration
64int ConvertStrToColor(std::string str, COLOR* color)
65{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020066 // Set the default, solid black
67 memset(color, 0, sizeof(COLOR));
68 color->alpha = 255;
Dees_Troy51a0e822012-09-05 15:24:24 -040069
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020070 // Translate variables
71 DataManager::GetValue(str, str);
Matt Mowerfb1c4ff2014-04-16 13:43:36 -050072
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020073 // Look for some defaults
74 if (str == "black") return 0;
75 else if (str == "white") { color->red = color->green = color->blue = 255; return 0; }
76 else if (str == "red") { color->red = 255; return 0; }
77 else if (str == "green") { color->green = 255; return 0; }
78 else if (str == "blue") { color->blue = 255; return 0; }
Dees_Troy51a0e822012-09-05 15:24:24 -040079
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020080 // At this point, we require an RGB(A) color
81 if (str[0] != '#')
82 return -1;
83
84 str.erase(0, 1);
Dees_Troy51a0e822012-09-05 15:24:24 -040085
Dees_Troy30b962e2012-10-19 20:48:59 -040086 int result;
87 if (str.size() >= 8) {
88 // We have alpha channel
89 string alpha = str.substr(6, 2);
90 result = strtol(alpha.c_str(), NULL, 16);
91 color->alpha = result & 0x000000FF;
92 str.resize(6);
93 result = strtol(str.c_str(), NULL, 16);
94 color->red = (result >> 16) & 0x000000FF;
95 color->green = (result >> 8) & 0x000000FF;
96 color->blue = result & 0x000000FF;
97 } else {
98 result = strtol(str.c_str(), NULL, 16);
99 color->red = (result >> 16) & 0x000000FF;
100 color->green = (result >> 8) & 0x000000FF;
101 color->blue = result & 0x000000FF;
102 }
103 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400104}
105
106// Helper APIs
107bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
108{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200109 if (!node)
110 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400111
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200112 std::string value;
113 if (node->first_attribute("x"))
114 {
115 value = node->first_attribute("x")->value();
116 DataManager::GetValue(value, value);
117 *x = atol(value.c_str());
118 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400119
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200120 if (node->first_attribute("y"))
121 {
122 value = node->first_attribute("y")->value();
123 DataManager::GetValue(value, value);
124 *y = atol(value.c_str());
125 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400126
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200127 if (w && node->first_attribute("w"))
128 {
129 value = node->first_attribute("w")->value();
130 DataManager::GetValue(value, value);
131 *w = atol(value.c_str());
132 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400133
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200134 if (h && node->first_attribute("h"))
135 {
136 value = node->first_attribute("h")->value();
137 DataManager::GetValue(value, value);
138 *h = atol(value.c_str());
139 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400140
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200141 if (placement && node->first_attribute("placement"))
142 {
143 value = node->first_attribute("placement")->value();
144 DataManager::GetValue(value, value);
145 *placement = (RenderObject::Placement) atol(value.c_str());
146 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400147
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200148 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400149}
150
151int ActionObject::SetActionPos(int x, int y, int w, int h)
152{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200153 if (x < 0 || y < 0)
154 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400155
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500156 mActionX = x;
157 mActionY = y;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200158 if (w || h)
159 {
160 mActionW = w;
161 mActionH = h;
162 }
163 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400164}
165
Ethan Yonker780cd392014-07-21 15:24:39 -0500166Page::Page(xml_node<>* page, std::vector<xml_node<>*> *templates /* = NULL */)
Dees_Troy51a0e822012-09-05 15:24:24 -0400167{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200168 mTouchStart = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400169
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200170 // We can memset the whole structure, because the alpha channel is ignored
171 memset(&mBackground, 0, sizeof(COLOR));
Dees_Troy51a0e822012-09-05 15:24:24 -0400172
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200173 // With NULL, we make a console-only display
174 if (!page)
175 {
176 mName = "console";
Dees_Troy51a0e822012-09-05 15:24:24 -0400177
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200178 GUIConsole* element = new GUIConsole(NULL);
179 mRenders.push_back(element);
180 mActions.push_back(element);
181 return;
182 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400183
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200184 if (page->first_attribute("name"))
185 mName = page->first_attribute("name")->value();
186 else
187 {
188 LOGERR("No page name attribute found!\n");
189 return;
190 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400191
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200192 LOGINFO("Loading page %s\n", mName.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400193
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200194 // This is a recursive routine for template handling
195 ProcessNode(page, templates);
Dees_Troy51a0e822012-09-05 15:24:24 -0400196
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200197 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400198}
199
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100200Page::~Page()
201{
202 for (std::vector<GUIObject*>::iterator itr = mObjects.begin(); itr != mObjects.end(); ++itr)
203 delete *itr;
204}
205
Ethan Yonker780cd392014-07-21 15:24:39 -0500206bool Page::ProcessNode(xml_node<>* page, std::vector<xml_node<>*> *templates /* = NULL */, int depth /* = 0 */)
Dees_Troy51a0e822012-09-05 15:24:24 -0400207{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200208 if (depth == 10)
209 {
210 LOGERR("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
211 return false;
212 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400213
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200214 // Let's retrieve the background value, if any
215 xml_node<>* bg = page->first_node("background");
216 if (bg)
217 {
218 xml_attribute<>* attr = bg->first_attribute("color");
219 if (attr)
220 {
221 std::string color = attr->value();
222 ConvertStrToColor(color, &mBackground);
223 }
224 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400225
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200226 xml_node<>* child;
227 child = page->first_node("object");
228 while (child)
229 {
230 if (!child->first_attribute("type"))
231 break;
Dees_Troy51a0e822012-09-05 15:24:24 -0400232
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200233 std::string type = child->first_attribute("type")->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400234
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200235 if (type == "text")
236 {
237 GUIText* element = new GUIText(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100238 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200239 mRenders.push_back(element);
240 mActions.push_back(element);
241 }
242 else if (type == "image")
243 {
244 GUIImage* element = new GUIImage(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100245 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200246 mRenders.push_back(element);
247 }
248 else if (type == "fill")
249 {
250 GUIFill* element = new GUIFill(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100251 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200252 mRenders.push_back(element);
253 }
254 else if (type == "action")
255 {
256 GUIAction* element = new GUIAction(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100257 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200258 mActions.push_back(element);
259 }
260 else if (type == "console")
261 {
262 GUIConsole* element = new GUIConsole(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100263 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200264 mRenders.push_back(element);
265 mActions.push_back(element);
266 }
267 else if (type == "button")
268 {
269 GUIButton* element = new GUIButton(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100270 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200271 mRenders.push_back(element);
272 mActions.push_back(element);
273 }
274 else if (type == "checkbox")
275 {
276 GUICheckbox* element = new GUICheckbox(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100277 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200278 mRenders.push_back(element);
279 mActions.push_back(element);
280 }
281 else if (type == "fileselector")
282 {
283 GUIFileSelector* element = new GUIFileSelector(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100284 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200285 mRenders.push_back(element);
286 mActions.push_back(element);
287 }
288 else if (type == "animation")
289 {
290 GUIAnimation* element = new GUIAnimation(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100291 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200292 mRenders.push_back(element);
293 }
294 else if (type == "progressbar")
295 {
296 GUIProgressBar* element = new GUIProgressBar(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100297 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200298 mRenders.push_back(element);
299 mActions.push_back(element);
300 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400301 else if (type == "slider")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200302 {
303 GUISlider* element = new GUISlider(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100304 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200305 mRenders.push_back(element);
306 mActions.push_back(element);
307 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200308 else if (type == "slidervalue")
309 {
310 GUISliderValue *element = new GUISliderValue(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100311 mObjects.push_back(element);
Vojtech Bocek85932342013-04-01 22:11:33 +0200312 mRenders.push_back(element);
313 mActions.push_back(element);
314 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400315 else if (type == "listbox")
316 {
317 GUIListBox* element = new GUIListBox(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100318 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400319 mRenders.push_back(element);
320 mActions.push_back(element);
321 }
322 else if (type == "keyboard")
323 {
324 GUIKeyboard* element = new GUIKeyboard(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100325 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400326 mRenders.push_back(element);
327 mActions.push_back(element);
328 }
329 else if (type == "input")
330 {
331 GUIInput* element = new GUIInput(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100332 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400333 mRenders.push_back(element);
334 mActions.push_back(element);
335 mInputs.push_back(element);
336 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500337 else if (type == "partitionlist")
338 {
339 GUIPartitionList* element = new GUIPartitionList(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100340 mObjects.push_back(element);
Dees_Troya13d74f2013-03-24 08:54:55 -0500341 mRenders.push_back(element);
342 mActions.push_back(element);
343 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200344 else if (type == "template")
345 {
346 if (!templates || !child->first_attribute("name"))
347 {
348 LOGERR("Invalid template request.\n");
349 }
350 else
351 {
352 std::string name = child->first_attribute("name")->value();
Ethan Yonker780cd392014-07-21 15:24:39 -0500353 xml_node<>* node;
354 bool node_found = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400355
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200356 // We need to find the correct template
Ethan Yonker780cd392014-07-21 15:24:39 -0500357 for (std::vector<xml_node<>*>::iterator itr = templates->begin(); itr != templates->end(); itr++) {
358 node = (*itr)->first_node("template");
Dees_Troy51a0e822012-09-05 15:24:24 -0400359
Ethan Yonker780cd392014-07-21 15:24:39 -0500360 while (node)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200361 {
Ethan Yonker780cd392014-07-21 15:24:39 -0500362 if (!node->first_attribute("name"))
363 continue;
364
365 if (name == node->first_attribute("name")->value())
366 {
367 if (!ProcessNode(node, templates, depth + 1))
368 return false;
369 else {
370 node_found = true;
371 break;
372 }
373 }
374 if (node_found)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200375 break;
Ethan Yonker780cd392014-07-21 15:24:39 -0500376 node = node->next_sibling("template");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200377 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200378 }
379 }
380 }
381 else
382 {
383 LOGERR("Unknown object type.\n");
384 }
385 child = child->next_sibling("object");
386 }
387 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400388}
389
390int Page::Render(void)
391{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200392 // Render background
393 gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
394 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
Dees_Troy51a0e822012-09-05 15:24:24 -0400395
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200396 // Render remaining objects
397 std::vector<RenderObject*>::iterator iter;
398 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
399 {
400 if ((*iter)->Render())
401 LOGERR("A render request has failed.\n");
402 }
403 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400404}
405
406int Page::Update(void)
407{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200408 int retCode = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400409
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200410 std::vector<RenderObject*>::iterator iter;
411 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
412 {
413 int ret = (*iter)->Update();
414 if (ret < 0)
415 LOGERR("An update request has failed.\n");
416 else if (ret > retCode)
417 retCode = ret;
418 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400419
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200420 return retCode;
Dees_Troy51a0e822012-09-05 15:24:24 -0400421}
422
423int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
424{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200425 // By default, return 1 to ignore further touches if nobody is listening
426 int ret = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400427
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200428 // Don't try to handle a lack of handlers
429 if (mActions.size() == 0)
430 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400431
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200432 // We record mTouchStart so we can pass all the touch stream to the same handler
433 if (state == TOUCH_START)
434 {
435 std::vector<ActionObject*>::reverse_iterator iter;
436 // We work backwards, from top-most element to bottom-most element
437 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
438 {
439 if ((*iter)->IsInRegion(x, y))
440 {
441 mTouchStart = (*iter);
442 ret = mTouchStart->NotifyTouch(state, x, y);
443 if (ret >= 0)
444 break;
445 mTouchStart = NULL;
446 }
447 }
448 }
449 else if (state == TOUCH_RELEASE && mTouchStart != NULL)
450 {
451 ret = mTouchStart->NotifyTouch(state, x, y);
452 mTouchStart = NULL;
453 }
454 else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
455 {
456 ret = mTouchStart->NotifyTouch(state, x, y);
457 }
458 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400459}
460
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100461int Page::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -0400462{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200463 std::vector<ActionObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400464
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200465 // Don't try to handle a lack of handlers
466 if (mActions.size() == 0)
467 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400468
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100469 int ret = 1;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200470 // We work backwards, from top-most element to bottom-most element
471 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
472 {
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100473 ret = (*iter)->NotifyKey(key, down);
474 if (ret < 0) {
475 LOGERR("An action handler has returned an error\n");
476 ret = 1;
477 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200478 }
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100479 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400480}
481
482int Page::NotifyKeyboard(int key)
483{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200484 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400485
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200486 // Don't try to handle a lack of handlers
487 if (mInputs.size() == 0)
488 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400489
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200490 // We work backwards, from top-most element to bottom-most element
491 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
492 {
493 int ret = (*iter)->NotifyKeyboard(key);
494 if (ret == 0)
495 return 0;
496 else if (ret < 0)
497 LOGERR("A keyboard handler has returned an error");
498 }
499 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400500}
501
502int Page::SetKeyBoardFocus(int inFocus)
503{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200504 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400505
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200506 // Don't try to handle a lack of handlers
507 if (mInputs.size() == 0)
508 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400509
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200510 // We work backwards, from top-most element to bottom-most element
511 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
512 {
513 int ret = (*iter)->SetInputFocus(inFocus);
514 if (ret == 0)
515 return 0;
516 else if (ret < 0)
517 LOGERR("An input focus handler has returned an error");
518 }
519 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400520}
521
522void Page::SetPageFocus(int inFocus)
523{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200524 // Render remaining objects
525 std::vector<RenderObject*>::iterator iter;
526 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
527 (*iter)->SetPageFocus(inFocus);
528
529 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400530}
531
532int Page::NotifyVarChange(std::string varName, std::string value)
533{
Vojtech Bocek07220562014-02-08 02:05:33 +0100534 std::vector<GUIObject*>::iterator iter;
535 for (iter = mObjects.begin(); iter != mObjects.end(); ++iter)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200536 {
537 if ((*iter)->NotifyVarChange(varName, value))
538 LOGERR("An action handler errored on NotifyVarChange.\n");
539 }
540 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400541}
542
543PageSet::PageSet(char* xmlFile)
544{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200545 mResources = NULL;
546 mCurrentPage = NULL;
547 mOverlayPage = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400548
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200549 mXmlFile = xmlFile;
550 if (xmlFile)
551 mDoc.parse<0>(mXmlFile);
552 else
553 mCurrentPage = new Page(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400554}
555
556PageSet::~PageSet()
557{
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100558 for (std::vector<Page*>::iterator itr = mPages.begin(); itr != mPages.end(); ++itr)
559 delete *itr;
Ethan Yonker780cd392014-07-21 15:24:39 -0500560 for (std::vector<xml_node<>*>::iterator itr2 = templates.begin(); itr2 != templates.end(); ++itr2)
561 delete *itr2;
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100562
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200563 delete mResources;
564 free(mXmlFile);
Dees_Troy51a0e822012-09-05 15:24:24 -0400565}
566
567int PageSet::Load(ZipArchive* package)
568{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200569 xml_node<>* parent;
570 xml_node<>* child;
Ethan Yonker780cd392014-07-21 15:24:39 -0500571 xml_node<>* xmltemplate;
572 xml_node<>* blank_templates;
573 int pages_loaded = -1, ret;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500574
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200575 parent = mDoc.first_node("recovery");
576 if (!parent)
577 parent = mDoc.first_node("install");
Dees_Troy51a0e822012-09-05 15:24:24 -0400578
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200579 // Now, let's parse the XML
580 LOGINFO("Loading resources...\n");
581 child = parent->first_node("resources");
582 if (child)
583 mResources = new ResourceManager(child, package);
Dees_Troy51a0e822012-09-05 15:24:24 -0400584
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200585 LOGINFO("Loading variables...\n");
586 child = parent->first_node("variables");
587 if (child)
588 LoadVariables(child);
Dees_Troy51a0e822012-09-05 15:24:24 -0400589
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +0100590 LOGINFO("Loading mouse cursor...\n");
591 child = parent->first_node("mousecursor");
592 if(child)
593 PageManager::LoadCursorData(child);
594
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200595 LOGINFO("Loading pages...\n");
596 // This may be NULL if no templates are present
Ethan Yonker780cd392014-07-21 15:24:39 -0500597 xmltemplate = parent->first_node("templates");
598 if (xmltemplate)
599 templates.push_back(xmltemplate);
Dees_Troy51a0e822012-09-05 15:24:24 -0400600
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200601 child = parent->first_node("pages");
Ethan Yonker780cd392014-07-21 15:24:39 -0500602 if (child) {
603 if (LoadPages(child)) {
604 LOGERR("PageSet::Load returning -1\n");
605 return -1;
606 }
607 }
608
609 return CheckInclude(package, &mDoc);
610}
Dees_Troy51a0e822012-09-05 15:24:24 -0400611
Ethan Yonker780cd392014-07-21 15:24:39 -0500612int PageSet::CheckInclude(ZipArchive* package, xml_document<> *parentDoc)
613{
614 xml_node<>* par;
615 xml_node<>* par2;
616 xml_node<>* chld;
617 xml_node<>* parent;
618 xml_node<>* child;
619 xml_node<>* xmltemplate;
620 long len;
621 char* xmlFile = NULL;
622 string filename;
623 xml_document<> doc;
624
625 par = parentDoc->first_node("recovery");
626 if (!par) {
627 par = parentDoc->first_node("install");
628 }
629 if (!par) {
630 return 0;
631 }
632
633 par2 = par->first_node("include");
634 if (!par2)
635 return 0;
636 chld = par2->first_node("xmlfile");
637 while (chld != NULL) {
638 xml_attribute<>* attr = chld->first_attribute("name");
639 if (!attr)
640 break;
641
642 LOGINFO("PageSet::CheckInclude loading filename: '%s'\n", filename.c_str());
643 if (!package) {
644 // We can try to load the XML directly...
645 filename = "/res/";
646 filename += attr->value();
647 struct stat st;
648 if(stat(filename.c_str(),&st) != 0) {
649 LOGERR("Unable to locate '%s'\n", filename.c_str());
650 return -1;
651 }
652
653 len = st.st_size;
654 xmlFile = (char*) malloc(len + 1);
655 if (!xmlFile)
656 return -1;
657
658 int fd = open(filename.c_str(), O_RDONLY);
659 if (fd == -1)
660 return -1;
661
662 read(fd, xmlFile, len);
663 close(fd);
664 } else {
665 filename += attr->value();
666 const ZipEntry* ui_xml = mzFindZipEntry(package, filename.c_str());
667 if (ui_xml == NULL)
668 {
669 LOGERR("Unable to locate '%s' in zip file\n", filename.c_str());
670 return -1;
671 }
672
673 // Allocate the buffer for the file
674 len = mzGetZipEntryUncompLen(ui_xml);
675 xmlFile = (char*) malloc(len + 1);
676 if (!xmlFile)
677 return -1;
678
679 if (!mzExtractZipEntryToBuffer(package, ui_xml, (unsigned char*) xmlFile))
680 {
681 LOGERR("Unable to extract '%s'\n", filename.c_str());
682 return -1;
683 }
684 }
685 doc.parse<0>(xmlFile);
686
687 parent = doc.first_node("recovery");
688 if (!parent)
689 parent = doc.first_node("install");
690
691 // Now, let's parse the XML
692 LOGINFO("Loading included resources...\n");
693 child = parent->first_node("resources");
694 if (child)
695 mResources->LoadResources(child, package);
696
697 LOGINFO("Loading included variables...\n");
698 child = parent->first_node("variables");
699 if (child)
700 LoadVariables(child);
701
702 LOGINFO("Loading mouse cursor...\n");
703 child = parent->first_node("mousecursor");
704 if(child)
705 PageManager::LoadCursorData(child);
706
707 LOGINFO("Loading included pages...\n");
708 // This may be NULL if no templates are present
709 xmltemplate = parent->first_node("templates");
710 if (xmltemplate)
711 templates.push_back(xmltemplate);
712
713 child = parent->first_node("pages");
714 if (child)
715 if (LoadPages(child))
716 return -1;
717
718 if (CheckInclude(package, &doc))
719 return -1;
720
721 chld = chld->next_sibling("xmlfile");
722 }
723
724 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400725}
726
727int PageSet::SetPage(std::string page)
728{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200729 Page* tmp = FindPage(page);
730 if (tmp)
731 {
732 if (mCurrentPage) mCurrentPage->SetPageFocus(0);
733 mCurrentPage = tmp;
734 mCurrentPage->SetPageFocus(1);
735 mCurrentPage->NotifyVarChange("", "");
736 return 0;
737 }
738 else
739 {
740 LOGERR("Unable to locate page (%s)\n", page.c_str());
741 }
742 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400743}
744
745int PageSet::SetOverlay(Page* page)
746{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200747 if (mOverlayPage) mOverlayPage->SetPageFocus(0);
748 mOverlayPage = page;
749 if (mOverlayPage)
750 {
751 mOverlayPage->SetPageFocus(1);
752 mOverlayPage->NotifyVarChange("", "");
753 }
754 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400755}
756
757Resource* PageSet::FindResource(std::string name)
758{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200759 return mResources ? mResources->FindResource(name) : NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400760}
761
762Page* PageSet::FindPage(std::string name)
763{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200764 std::vector<Page*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400765
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200766 for (iter = mPages.begin(); iter != mPages.end(); iter++)
767 {
768 if (name == (*iter)->GetName())
769 return (*iter);
770 }
771 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400772}
773
774int PageSet::LoadVariables(xml_node<>* vars)
775{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200776 xml_node<>* child;
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100777 xml_attribute<> *name, *value, *persist;
778 int p;
Dees_Troy51a0e822012-09-05 15:24:24 -0400779
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200780 child = vars->first_node("variable");
781 while (child)
782 {
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100783 name = child->first_attribute("name");
784 value = child->first_attribute("value");
785 persist = child->first_attribute("persist");
786 if(name && value)
787 {
788 p = persist ? atoi(persist->value()) : 0;
Ethan Yonker96acb3d2014-08-05 09:20:30 -0500789 string temp = value->value();
790 string valstr = gui_parse_text(temp);
791
792 if (valstr.find("+") != string::npos) {
793 string val1str = valstr;
794 val1str = val1str.substr(0, val1str.find('+'));
795 string val2str = valstr;
796 val2str = val2str.substr(val2str.find('+') + 1, string::npos);
797 int val1 = atoi(val1str.c_str());
798 int val2 = atoi(val2str.c_str());
799 int val = val1 + val2;
800
801 DataManager::SetValue(name->value(), val, p);
802 } else if (valstr.find("-") != string::npos) {
803 string val1str = valstr;
804 val1str = val1str.substr(0, val1str.find('-'));
805 string val2str = valstr;
806 val2str = val2str.substr(val2str.find('-') + 1, string::npos);
807 int val1 = atoi(val1str.c_str());
808 int val2 = atoi(val2str.c_str());
809 int val = val1 - val2;
810
811 DataManager::SetValue(name->value(), val, p);
812 } else {
813 DataManager::SetValue(name->value(), valstr, p);
814 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100815 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400816
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200817 child = child->next_sibling("variable");
818 }
819 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400820}
821
Ethan Yonker780cd392014-07-21 15:24:39 -0500822int PageSet::LoadPages(xml_node<>* pages)
Dees_Troy51a0e822012-09-05 15:24:24 -0400823{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200824 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -0400825
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200826 if (!pages)
827 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400828
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200829 child = pages->first_node("page");
830 while (child != NULL)
831 {
Ethan Yonker780cd392014-07-21 15:24:39 -0500832 Page* page = new Page(child, &templates);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200833 if (page->GetName().empty())
834 {
835 LOGERR("Unable to process load page\n");
836 delete page;
837 }
838 else
839 {
840 mPages.push_back(page);
841 }
842 child = child->next_sibling("page");
843 }
844 if (mPages.size() > 0)
845 return 0;
846 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400847}
848
849int PageSet::IsCurrentPage(Page* page)
850{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200851 return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400852}
853
854int PageSet::Render(void)
855{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200856 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400857
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200858 ret = (mCurrentPage ? mCurrentPage->Render() : -1);
859 if (ret < 0)
860 return ret;
861 ret = (mOverlayPage ? mOverlayPage->Render() : -1);
862 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400863}
864
865int PageSet::Update(void)
866{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200867 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400868
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200869 ret = (mCurrentPage ? mCurrentPage->Update() : -1);
870 if (ret < 0 || ret > 1)
871 return ret;
872 ret = (mOverlayPage ? mOverlayPage->Update() : -1);
873 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400874}
875
876int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
877{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200878 if (mOverlayPage)
879 return (mOverlayPage->NotifyTouch(state, x, y));
880
881 return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400882}
883
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100884int PageSet::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -0400885{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200886 if (mOverlayPage)
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100887 return (mOverlayPage->NotifyKey(key, down));
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200888
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100889 return (mCurrentPage ? mCurrentPage->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400890}
891
892int PageSet::NotifyKeyboard(int key)
893{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200894 if (mOverlayPage)
895 return (mOverlayPage->NotifyKeyboard(key));
896
897 return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400898}
899
900int PageSet::SetKeyBoardFocus(int inFocus)
901{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200902 if (mOverlayPage)
903 return (mOverlayPage->SetKeyBoardFocus(inFocus));
904
905 return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400906}
907
908int PageSet::NotifyVarChange(std::string varName, std::string value)
909{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200910 if (mOverlayPage)
911 mOverlayPage->NotifyVarChange(varName, value);
912
913 return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400914}
915
916int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
917{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200918 int fd;
919 ZipArchive zip, *pZip = NULL;
920 long len;
921 char* xmlFile = NULL;
922 PageSet* pageSet = NULL;
923 int ret;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600924 MemMapping map;
Dees_Troy51a0e822012-09-05 15:24:24 -0400925
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200926 // Open the XML file
927 LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600928 if (package.size() > 4 && package.substr(package.size() - 4) != ".zip")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200929 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600930 LOGINFO("Load XML directly\n");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200931 // We can try to load the XML directly...
932 struct stat st;
933 if(stat(package.c_str(),&st) != 0)
934 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400935
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200936 len = st.st_size;
937 xmlFile = (char*) malloc(len + 1);
938 if (!xmlFile)
939 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400940
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200941 fd = open(package.c_str(), O_RDONLY);
942 if (fd == -1)
943 goto error;
Dees_Troy51a0e822012-09-05 15:24:24 -0400944
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200945 read(fd, xmlFile, len);
946 close(fd);
947 }
948 else
949 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600950 LOGINFO("Loading zip theme\n");
951 if (!TWFunc::Path_Exists(package))
952 return -1;
953 if (sysMapFile(package.c_str(), &map) != 0) {
954 LOGERR("Failed to map '%s'\n", package.c_str());
955 return -1;
956 }
957 if (mzOpenZipArchive(map.addr, map.length, &zip)) {
958 LOGERR("Unable to open zip archive '%s'\n", package.c_str());
959 sysReleaseMap(&map);
960 return -1;
961 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200962 pZip = &zip;
963 const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
964 if (ui_xml == NULL)
965 {
966 LOGERR("Unable to locate ui.xml in zip file\n");
967 goto error;
968 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500969
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200970 // Allocate the buffer for the file
971 len = mzGetZipEntryUncompLen(ui_xml);
972 xmlFile = (char*) malloc(len + 1);
973 if (!xmlFile)
974 goto error;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500975
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200976 if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
977 {
978 LOGERR("Unable to extract ui.xml\n");
979 goto error;
980 }
981 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400982
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200983 // NULL-terminate the string
984 xmlFile[len] = 0x00;
Dees_Troy51a0e822012-09-05 15:24:24 -0400985
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200986 // Before loading, mCurrentSet must be the loading package so we can find resources
987 pageSet = mCurrentSet;
988 mCurrentSet = new PageSet(xmlFile);
989
990 ret = mCurrentSet->Load(pZip);
991 if (ret == 0)
992 {
993 mCurrentSet->SetPage(startpage);
994 mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
995 }
996 else
997 {
998 LOGERR("Package %s failed to load.\n", name.c_str());
999 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001000
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001001 // The first successful package we loaded is the base
1002 if (mBaseSet == NULL)
1003 mBaseSet = mCurrentSet;
1004
1005 mCurrentSet = pageSet;
1006
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001007 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001008 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001009 sysReleaseMap(&map);
1010 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001011 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001012
1013error:
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001014 LOGERR("An internal error has occurred.\n");
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001015 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001016 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001017 sysReleaseMap(&map);
1018 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001019 if (xmlFile)
1020 free(xmlFile);
1021 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001022}
1023
1024PageSet* PageManager::FindPackage(std::string name)
1025{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001026 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001027
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001028 iter = mPageSets.find(name);
1029 if (iter != mPageSets.end())
1030 return (*iter).second;
1031
1032 LOGERR("Unable to locate package %s\n", name.c_str());
1033 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -04001034}
1035
1036PageSet* PageManager::SelectPackage(std::string name)
1037{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001038 LOGINFO("Switching packages (%s)\n", name.c_str());
1039 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -04001040
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001041 tmp = FindPackage(name);
1042 if (tmp)
Vojtech Bocek07220562014-02-08 02:05:33 +01001043 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001044 mCurrentSet = tmp;
Vojtech Bocek07220562014-02-08 02:05:33 +01001045 mCurrentSet->NotifyVarChange("", "");
1046 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001047 else
1048 LOGERR("Unable to find package.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -04001049
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001050 return mCurrentSet;
Dees_Troy51a0e822012-09-05 15:24:24 -04001051}
1052
1053int PageManager::ReloadPackage(std::string name, std::string package)
1054{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001055 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001056
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001057 iter = mPageSets.find(name);
1058 if (iter == mPageSets.end())
1059 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001060
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001061 if(mMouseCursor)
1062 mMouseCursor->ResetData(gr_fb_width(), gr_fb_height());
1063
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001064 PageSet* set = (*iter).second;
1065 mPageSets.erase(iter);
Dees_Troy51a0e822012-09-05 15:24:24 -04001066
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001067 if (LoadPackage(name, package, "main") != 0)
1068 {
1069 LOGERR("Failed to load package.\n");
1070 mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
1071 return -1;
1072 }
1073 if (mCurrentSet == set)
1074 SelectPackage(name);
Vojtech Bocekbfb63342014-02-08 00:32:31 +01001075 if (mBaseSet == set)
1076 mBaseSet = mCurrentSet;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001077 delete set;
1078 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001079}
1080
1081void PageManager::ReleasePackage(std::string name)
1082{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001083 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001084
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001085 iter = mPageSets.find(name);
1086 if (iter == mPageSets.end())
1087 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001088
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001089 PageSet* set = (*iter).second;
1090 mPageSets.erase(iter);
1091 delete set;
1092 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001093}
1094
1095int PageManager::ChangePage(std::string name)
1096{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001097 DataManager::SetValue("tw_operation_state", 0);
1098 int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
1099 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001100}
1101
1102int PageManager::ChangeOverlay(std::string name)
1103{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001104 if (name.empty())
1105 return mCurrentSet->SetOverlay(NULL);
1106 else
1107 {
1108 Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
1109 return mCurrentSet->SetOverlay(page);
1110 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001111}
1112
1113Resource* PageManager::FindResource(std::string name)
1114{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001115 return (mCurrentSet ? mCurrentSet->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001116}
1117
1118Resource* PageManager::FindResource(std::string package, std::string name)
1119{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001120 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -04001121
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001122 tmp = FindPackage(name);
1123 return (tmp ? tmp->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001124}
1125
1126int PageManager::SwitchToConsole(void)
1127{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001128 PageSet* console = new PageSet(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001129
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001130 mCurrentSet = console;
1131 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001132}
1133
Ethan Yonker03a42f62014-08-08 11:03:51 -05001134int PageManager::EndConsole(void)
1135{
1136 if (mCurrentSet && mBaseSet) {
1137 delete mCurrentSet;
1138 mCurrentSet = mBaseSet;
1139 return 0;
1140 }
1141 return -1;
1142}
1143
Dees_Troy51a0e822012-09-05 15:24:24 -04001144int PageManager::IsCurrentPage(Page* page)
1145{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001146 return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -04001147}
1148
1149int PageManager::Render(void)
1150{
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001151 int res = (mCurrentSet ? mCurrentSet->Render() : -1);
1152 if(mMouseCursor)
1153 mMouseCursor->Render();
1154 return res;
1155}
1156
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001157HardwareKeyboard *PageManager::GetHardwareKeyboard()
1158{
1159 if(!mHardwareKeyboard)
1160 mHardwareKeyboard = new HardwareKeyboard();
1161 return mHardwareKeyboard;
1162}
1163
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001164MouseCursor *PageManager::GetMouseCursor()
1165{
1166 if(!mMouseCursor)
1167 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1168 return mMouseCursor;
1169}
1170
1171void PageManager::LoadCursorData(xml_node<>* node)
1172{
1173 if(!mMouseCursor)
1174 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1175
1176 mMouseCursor->LoadData(node);
Dees_Troy51a0e822012-09-05 15:24:24 -04001177}
1178
1179int PageManager::Update(void)
1180{
Ricardo Gomezc9ecd442013-07-05 16:13:52 -07001181#ifndef TW_NO_SCREEN_TIMEOUT
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001182 if(blankTimer.IsScreenOff())
1183 return 0;
Ricardo Gomezc9ecd442013-07-05 16:13:52 -07001184#endif
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001185
1186 int res = (mCurrentSet ? mCurrentSet->Update() : -1);
1187
1188 if(mMouseCursor)
1189 {
1190 int c_res = mMouseCursor->Update();
1191 if(c_res > res)
1192 res = c_res;
1193 }
1194 return res;
Dees_Troy51a0e822012-09-05 15:24:24 -04001195}
1196
1197int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
1198{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001199 return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001200}
1201
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001202int PageManager::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -04001203{
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001204 return (mCurrentSet ? mCurrentSet->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001205}
1206
1207int PageManager::NotifyKeyboard(int key)
1208{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001209 return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001210}
1211
1212int PageManager::SetKeyBoardFocus(int inFocus)
1213{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001214 return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001215}
1216
1217int PageManager::NotifyVarChange(std::string varName, std::string value)
1218{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001219 return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001220}
1221
1222extern "C" void gui_notifyVarChange(const char *name, const char* value)
1223{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001224 if (!gGuiRunning)
1225 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001226
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001227 PageManager::NotifyVarChange(name, value);
Dees_Troy51a0e822012-09-05 15:24:24 -04001228}