blob: 8fef7b4c817ff6d0eaddb07d5afc0c2fad174f20 [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"
gordon13370d9133d2013-06-08 14:17:07 +020048#include "blanktimer.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040049
50extern int gGuiRunning;
51
52std::map<std::string, PageSet*> PageManager::mPageSets;
53PageSet* PageManager::mCurrentSet;
54PageSet* PageManager::mBaseSet = NULL;
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +010055MouseCursor *PageManager::mMouseCursor = NULL;
Vojtech Bocek0b7fe502014-03-13 17:36:52 +010056HardwareKeyboard *PageManager::mHardwareKeyboard = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -040057
Ethan Yonker751a85e2014-12-12 16:59:10 -060058int tw_x_offset = 0;
59int tw_y_offset = 0;
60
Dees_Troy51a0e822012-09-05 15:24:24 -040061// Helper routine to convert a string to a color declaration
62int ConvertStrToColor(std::string str, COLOR* color)
63{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020064 // Set the default, solid black
65 memset(color, 0, sizeof(COLOR));
66 color->alpha = 255;
Dees_Troy51a0e822012-09-05 15:24:24 -040067
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020068 // Translate variables
69 DataManager::GetValue(str, str);
Matt Mowerfb1c4ff2014-04-16 13:43:36 -050070
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020071 // Look for some defaults
72 if (str == "black") return 0;
73 else if (str == "white") { color->red = color->green = color->blue = 255; return 0; }
74 else if (str == "red") { color->red = 255; return 0; }
75 else if (str == "green") { color->green = 255; return 0; }
76 else if (str == "blue") { color->blue = 255; return 0; }
Dees_Troy51a0e822012-09-05 15:24:24 -040077
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020078 // At this point, we require an RGB(A) color
79 if (str[0] != '#')
80 return -1;
81
82 str.erase(0, 1);
Dees_Troy51a0e822012-09-05 15:24:24 -040083
Dees_Troy30b962e2012-10-19 20:48:59 -040084 int result;
85 if (str.size() >= 8) {
86 // We have alpha channel
87 string alpha = str.substr(6, 2);
88 result = strtol(alpha.c_str(), NULL, 16);
89 color->alpha = result & 0x000000FF;
90 str.resize(6);
91 result = strtol(str.c_str(), NULL, 16);
92 color->red = (result >> 16) & 0x000000FF;
93 color->green = (result >> 8) & 0x000000FF;
94 color->blue = result & 0x000000FF;
95 } else {
96 result = strtol(str.c_str(), NULL, 16);
97 color->red = (result >> 16) & 0x000000FF;
98 color->green = (result >> 8) & 0x000000FF;
99 color->blue = result & 0x000000FF;
100 }
101 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400102}
103
104// Helper APIs
105bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
106{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200107 if (!node)
108 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400109
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200110 std::string value;
111 if (node->first_attribute("x"))
112 {
113 value = node->first_attribute("x")->value();
114 DataManager::GetValue(value, value);
115 *x = atol(value.c_str());
Ethan Yonker751a85e2014-12-12 16:59:10 -0600116 *x += tw_x_offset;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200117 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400118
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200119 if (node->first_attribute("y"))
120 {
121 value = node->first_attribute("y")->value();
122 DataManager::GetValue(value, value);
123 *y = atol(value.c_str());
Ethan Yonker751a85e2014-12-12 16:59:10 -0600124 *y += tw_y_offset;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200125 }
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;
560
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200561 delete mResources;
562 free(mXmlFile);
Vojtech Boceke979abd2015-01-12 18:29:12 +0100563
564 mDoc.clear();
565
566 for (std::vector<xml_document<>*>::iterator itr = mIncludedDocs.begin(); itr != mIncludedDocs.end(); ++itr) {
567 (*itr)->clear();
568 delete *itr;
569 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400570}
571
572int PageSet::Load(ZipArchive* package)
573{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200574 xml_node<>* parent;
575 xml_node<>* child;
Ethan Yonker780cd392014-07-21 15:24:39 -0500576 xml_node<>* xmltemplate;
577 xml_node<>* blank_templates;
578 int pages_loaded = -1, ret;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500579
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200580 parent = mDoc.first_node("recovery");
581 if (!parent)
582 parent = mDoc.first_node("install");
Dees_Troy51a0e822012-09-05 15:24:24 -0400583
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200584 // Now, let's parse the XML
585 LOGINFO("Loading resources...\n");
586 child = parent->first_node("resources");
587 if (child)
588 mResources = new ResourceManager(child, package);
Dees_Troy51a0e822012-09-05 15:24:24 -0400589
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200590 LOGINFO("Loading variables...\n");
591 child = parent->first_node("variables");
592 if (child)
593 LoadVariables(child);
Dees_Troy51a0e822012-09-05 15:24:24 -0400594
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +0100595 LOGINFO("Loading mouse cursor...\n");
596 child = parent->first_node("mousecursor");
597 if(child)
598 PageManager::LoadCursorData(child);
599
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200600 LOGINFO("Loading pages...\n");
601 // This may be NULL if no templates are present
Ethan Yonker780cd392014-07-21 15:24:39 -0500602 xmltemplate = parent->first_node("templates");
603 if (xmltemplate)
604 templates.push_back(xmltemplate);
Dees_Troy51a0e822012-09-05 15:24:24 -0400605
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200606 child = parent->first_node("pages");
Ethan Yonker780cd392014-07-21 15:24:39 -0500607 if (child) {
608 if (LoadPages(child)) {
609 LOGERR("PageSet::Load returning -1\n");
610 return -1;
611 }
612 }
Vojtech Boceke979abd2015-01-12 18:29:12 +0100613
Ethan Yonker780cd392014-07-21 15:24:39 -0500614 return CheckInclude(package, &mDoc);
615}
Dees_Troy51a0e822012-09-05 15:24:24 -0400616
Ethan Yonker780cd392014-07-21 15:24:39 -0500617int PageSet::CheckInclude(ZipArchive* package, xml_document<> *parentDoc)
618{
619 xml_node<>* par;
620 xml_node<>* par2;
621 xml_node<>* chld;
622 xml_node<>* parent;
623 xml_node<>* child;
624 xml_node<>* xmltemplate;
625 long len;
626 char* xmlFile = NULL;
627 string filename;
Vojtech Boceke979abd2015-01-12 18:29:12 +0100628 xml_document<> *doc = NULL;
Ethan Yonker780cd392014-07-21 15:24:39 -0500629
630 par = parentDoc->first_node("recovery");
631 if (!par) {
632 par = parentDoc->first_node("install");
633 }
634 if (!par) {
635 return 0;
636 }
637
638 par2 = par->first_node("include");
639 if (!par2)
640 return 0;
641 chld = par2->first_node("xmlfile");
642 while (chld != NULL) {
643 xml_attribute<>* attr = chld->first_attribute("name");
644 if (!attr)
645 break;
646
Ethan Yonker780cd392014-07-21 15:24:39 -0500647 if (!package) {
648 // We can try to load the XML directly...
Dees Troy3454ade2015-01-20 19:21:04 +0000649 filename = TWRES;
Ethan Yonker780cd392014-07-21 15:24:39 -0500650 filename += attr->value();
Dees Troy3454ade2015-01-20 19:21:04 +0000651 LOGINFO("PageSet::CheckInclude loading filename: '%s'\n", filename.c_str());
Ethan Yonker780cd392014-07-21 15:24:39 -0500652 struct stat st;
653 if(stat(filename.c_str(),&st) != 0) {
654 LOGERR("Unable to locate '%s'\n", filename.c_str());
655 return -1;
656 }
657
658 len = st.st_size;
659 xmlFile = (char*) malloc(len + 1);
660 if (!xmlFile)
661 return -1;
662
663 int fd = open(filename.c_str(), O_RDONLY);
664 if (fd == -1)
665 return -1;
666
667 read(fd, xmlFile, len);
668 close(fd);
669 } else {
670 filename += attr->value();
Dees Troy3454ade2015-01-20 19:21:04 +0000671 LOGINFO("PageSet::CheckInclude loading filename: '%s'\n", filename.c_str());
Ethan Yonker780cd392014-07-21 15:24:39 -0500672 const ZipEntry* ui_xml = mzFindZipEntry(package, filename.c_str());
673 if (ui_xml == NULL)
674 {
675 LOGERR("Unable to locate '%s' in zip file\n", filename.c_str());
676 return -1;
677 }
678
679 // Allocate the buffer for the file
680 len = mzGetZipEntryUncompLen(ui_xml);
681 xmlFile = (char*) malloc(len + 1);
682 if (!xmlFile)
683 return -1;
684
685 if (!mzExtractZipEntryToBuffer(package, ui_xml, (unsigned char*) xmlFile))
686 {
687 LOGERR("Unable to extract '%s'\n", filename.c_str());
688 return -1;
689 }
690 }
Ethan Yonker780cd392014-07-21 15:24:39 -0500691
Vojtech Boceke979abd2015-01-12 18:29:12 +0100692 xmlFile[len] = '\0';
693 doc = new xml_document<>();
694 doc->parse<0>(xmlFile);
695
696 parent = doc->first_node("recovery");
Ethan Yonker780cd392014-07-21 15:24:39 -0500697 if (!parent)
Vojtech Boceke979abd2015-01-12 18:29:12 +0100698 parent = doc->first_node("install");
Ethan Yonker780cd392014-07-21 15:24:39 -0500699
700 // Now, let's parse the XML
701 LOGINFO("Loading included resources...\n");
702 child = parent->first_node("resources");
703 if (child)
704 mResources->LoadResources(child, package);
705
706 LOGINFO("Loading included variables...\n");
707 child = parent->first_node("variables");
708 if (child)
709 LoadVariables(child);
710
711 LOGINFO("Loading mouse cursor...\n");
712 child = parent->first_node("mousecursor");
713 if(child)
714 PageManager::LoadCursorData(child);
715
716 LOGINFO("Loading included pages...\n");
717 // This may be NULL if no templates are present
718 xmltemplate = parent->first_node("templates");
719 if (xmltemplate)
720 templates.push_back(xmltemplate);
721
722 child = parent->first_node("pages");
Vojtech Boceke979abd2015-01-12 18:29:12 +0100723 if (child && LoadPages(child))
724 {
725 templates.pop_back();
726 doc->clear();
727 delete doc;
728 return -1;
729 }
Ethan Yonker780cd392014-07-21 15:24:39 -0500730
Vojtech Boceke979abd2015-01-12 18:29:12 +0100731 mIncludedDocs.push_back(doc);
732
733 if (CheckInclude(package, doc))
Ethan Yonker780cd392014-07-21 15:24:39 -0500734 return -1;
735
736 chld = chld->next_sibling("xmlfile");
737 }
738
739 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400740}
741
742int PageSet::SetPage(std::string page)
743{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200744 Page* tmp = FindPage(page);
745 if (tmp)
746 {
747 if (mCurrentPage) mCurrentPage->SetPageFocus(0);
748 mCurrentPage = tmp;
749 mCurrentPage->SetPageFocus(1);
750 mCurrentPage->NotifyVarChange("", "");
751 return 0;
752 }
753 else
754 {
755 LOGERR("Unable to locate page (%s)\n", page.c_str());
756 }
757 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400758}
759
760int PageSet::SetOverlay(Page* page)
761{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200762 if (mOverlayPage) mOverlayPage->SetPageFocus(0);
763 mOverlayPage = page;
764 if (mOverlayPage)
765 {
766 mOverlayPage->SetPageFocus(1);
767 mOverlayPage->NotifyVarChange("", "");
768 }
769 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400770}
771
772Resource* PageSet::FindResource(std::string name)
773{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200774 return mResources ? mResources->FindResource(name) : NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400775}
776
777Page* PageSet::FindPage(std::string name)
778{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200779 std::vector<Page*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400780
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200781 for (iter = mPages.begin(); iter != mPages.end(); iter++)
782 {
783 if (name == (*iter)->GetName())
784 return (*iter);
785 }
786 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400787}
788
789int PageSet::LoadVariables(xml_node<>* vars)
790{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200791 xml_node<>* child;
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100792 xml_attribute<> *name, *value, *persist;
793 int p;
Dees_Troy51a0e822012-09-05 15:24:24 -0400794
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200795 child = vars->first_node("variable");
796 while (child)
797 {
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100798 name = child->first_attribute("name");
799 value = child->first_attribute("value");
800 persist = child->first_attribute("persist");
801 if(name && value)
802 {
Ethan Yonker751a85e2014-12-12 16:59:10 -0600803 if (strcmp(name->value(), "tw_x_offset") == 0) {
804 tw_x_offset = atoi(value->value());
805 child = child->next_sibling("variable");
806 continue;
807 }
808 if (strcmp(name->value(), "tw_y_offset") == 0) {
809 tw_y_offset = atoi(value->value());
810 child = child->next_sibling("variable");
811 continue;
812 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100813 p = persist ? atoi(persist->value()) : 0;
Ethan Yonker96acb3d2014-08-05 09:20:30 -0500814 string temp = value->value();
815 string valstr = gui_parse_text(temp);
816
817 if (valstr.find("+") != string::npos) {
818 string val1str = valstr;
819 val1str = val1str.substr(0, val1str.find('+'));
820 string val2str = valstr;
821 val2str = val2str.substr(val2str.find('+') + 1, string::npos);
822 int val1 = atoi(val1str.c_str());
823 int val2 = atoi(val2str.c_str());
824 int val = val1 + val2;
825
826 DataManager::SetValue(name->value(), val, p);
827 } else if (valstr.find("-") != string::npos) {
828 string val1str = valstr;
829 val1str = val1str.substr(0, val1str.find('-'));
830 string val2str = valstr;
831 val2str = val2str.substr(val2str.find('-') + 1, string::npos);
832 int val1 = atoi(val1str.c_str());
833 int val2 = atoi(val2str.c_str());
834 int val = val1 - val2;
835
836 DataManager::SetValue(name->value(), val, p);
837 } else {
838 DataManager::SetValue(name->value(), valstr, p);
839 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100840 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400841
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200842 child = child->next_sibling("variable");
843 }
844 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400845}
846
Ethan Yonker780cd392014-07-21 15:24:39 -0500847int PageSet::LoadPages(xml_node<>* pages)
Dees_Troy51a0e822012-09-05 15:24:24 -0400848{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200849 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -0400850
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200851 if (!pages)
852 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400853
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200854 child = pages->first_node("page");
855 while (child != NULL)
856 {
Ethan Yonker780cd392014-07-21 15:24:39 -0500857 Page* page = new Page(child, &templates);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200858 if (page->GetName().empty())
859 {
860 LOGERR("Unable to process load page\n");
861 delete page;
862 }
863 else
864 {
865 mPages.push_back(page);
866 }
867 child = child->next_sibling("page");
868 }
869 if (mPages.size() > 0)
870 return 0;
871 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400872}
873
874int PageSet::IsCurrentPage(Page* page)
875{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200876 return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400877}
878
879int PageSet::Render(void)
880{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200881 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400882
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200883 ret = (mCurrentPage ? mCurrentPage->Render() : -1);
884 if (ret < 0)
885 return ret;
886 ret = (mOverlayPage ? mOverlayPage->Render() : -1);
887 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400888}
889
890int PageSet::Update(void)
891{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200892 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400893
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200894 ret = (mCurrentPage ? mCurrentPage->Update() : -1);
895 if (ret < 0 || ret > 1)
896 return ret;
897 ret = (mOverlayPage ? mOverlayPage->Update() : -1);
898 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400899}
900
901int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
902{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200903 if (mOverlayPage)
904 return (mOverlayPage->NotifyTouch(state, x, y));
905
906 return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400907}
908
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100909int PageSet::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -0400910{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200911 if (mOverlayPage)
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100912 return (mOverlayPage->NotifyKey(key, down));
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200913
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100914 return (mCurrentPage ? mCurrentPage->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400915}
916
917int PageSet::NotifyKeyboard(int key)
918{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200919 if (mOverlayPage)
920 return (mOverlayPage->NotifyKeyboard(key));
921
922 return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400923}
924
925int PageSet::SetKeyBoardFocus(int inFocus)
926{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200927 if (mOverlayPage)
928 return (mOverlayPage->SetKeyBoardFocus(inFocus));
929
930 return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400931}
932
933int PageSet::NotifyVarChange(std::string varName, std::string value)
934{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200935 if (mOverlayPage)
936 mOverlayPage->NotifyVarChange(varName, value);
937
938 return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400939}
940
941int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
942{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200943 int fd;
944 ZipArchive zip, *pZip = NULL;
945 long len;
946 char* xmlFile = NULL;
947 PageSet* pageSet = NULL;
948 int ret;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600949 MemMapping map;
Dees_Troy51a0e822012-09-05 15:24:24 -0400950
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200951 // Open the XML file
952 LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600953 if (package.size() > 4 && package.substr(package.size() - 4) != ".zip")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200954 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600955 LOGINFO("Load XML directly\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -0600956 tw_x_offset = TW_X_OFFSET;
957 tw_y_offset = TW_Y_OFFSET;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200958 // We can try to load the XML directly...
959 struct stat st;
960 if(stat(package.c_str(),&st) != 0)
961 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400962
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200963 len = st.st_size;
964 xmlFile = (char*) malloc(len + 1);
965 if (!xmlFile)
966 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400967
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200968 fd = open(package.c_str(), O_RDONLY);
969 if (fd == -1)
970 goto error;
Dees_Troy51a0e822012-09-05 15:24:24 -0400971
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200972 read(fd, xmlFile, len);
973 close(fd);
974 }
975 else
976 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600977 LOGINFO("Loading zip theme\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -0600978 tw_x_offset = 0;
979 tw_y_offset = 0;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600980 if (!TWFunc::Path_Exists(package))
981 return -1;
982 if (sysMapFile(package.c_str(), &map) != 0) {
983 LOGERR("Failed to map '%s'\n", package.c_str());
984 return -1;
985 }
986 if (mzOpenZipArchive(map.addr, map.length, &zip)) {
987 LOGERR("Unable to open zip archive '%s'\n", package.c_str());
988 sysReleaseMap(&map);
989 return -1;
990 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200991 pZip = &zip;
992 const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
993 if (ui_xml == NULL)
994 {
995 LOGERR("Unable to locate ui.xml in zip file\n");
996 goto error;
997 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500998
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200999 // Allocate the buffer for the file
1000 len = mzGetZipEntryUncompLen(ui_xml);
1001 xmlFile = (char*) malloc(len + 1);
1002 if (!xmlFile)
1003 goto error;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001004
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001005 if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
1006 {
1007 LOGERR("Unable to extract ui.xml\n");
1008 goto error;
1009 }
1010 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001011
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001012 // NULL-terminate the string
1013 xmlFile[len] = 0x00;
Dees_Troy51a0e822012-09-05 15:24:24 -04001014
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001015 // Before loading, mCurrentSet must be the loading package so we can find resources
1016 pageSet = mCurrentSet;
1017 mCurrentSet = new PageSet(xmlFile);
1018
1019 ret = mCurrentSet->Load(pZip);
1020 if (ret == 0)
1021 {
1022 mCurrentSet->SetPage(startpage);
1023 mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
1024 }
1025 else
1026 {
1027 LOGERR("Package %s failed to load.\n", name.c_str());
1028 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001029
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001030 // The first successful package we loaded is the base
1031 if (mBaseSet == NULL)
1032 mBaseSet = mCurrentSet;
1033
1034 mCurrentSet = pageSet;
1035
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001036 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001037 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001038 sysReleaseMap(&map);
1039 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001040 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001041
1042error:
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001043 LOGERR("An internal error has occurred.\n");
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001044 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001045 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001046 sysReleaseMap(&map);
1047 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001048 if (xmlFile)
1049 free(xmlFile);
1050 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001051}
1052
1053PageSet* PageManager::FindPackage(std::string name)
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 (*iter).second;
1060
1061 LOGERR("Unable to locate package %s\n", name.c_str());
1062 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -04001063}
1064
1065PageSet* PageManager::SelectPackage(std::string name)
1066{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001067 LOGINFO("Switching packages (%s)\n", name.c_str());
1068 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -04001069
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001070 tmp = FindPackage(name);
1071 if (tmp)
Vojtech Bocek07220562014-02-08 02:05:33 +01001072 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001073 mCurrentSet = tmp;
Vojtech Bocek07220562014-02-08 02:05:33 +01001074 mCurrentSet->NotifyVarChange("", "");
1075 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001076 else
1077 LOGERR("Unable to find package.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -04001078
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001079 return mCurrentSet;
Dees_Troy51a0e822012-09-05 15:24:24 -04001080}
1081
1082int PageManager::ReloadPackage(std::string name, std::string package)
1083{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001084 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001085
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001086 iter = mPageSets.find(name);
1087 if (iter == mPageSets.end())
1088 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001089
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001090 if(mMouseCursor)
1091 mMouseCursor->ResetData(gr_fb_width(), gr_fb_height());
1092
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001093 PageSet* set = (*iter).second;
1094 mPageSets.erase(iter);
Dees_Troy51a0e822012-09-05 15:24:24 -04001095
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001096 if (LoadPackage(name, package, "main") != 0)
1097 {
Dees Troy3454ade2015-01-20 19:21:04 +00001098 LOGERR("Failed to load package '%s'.\n", package.c_str());
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001099 mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
1100 return -1;
1101 }
1102 if (mCurrentSet == set)
1103 SelectPackage(name);
Vojtech Bocekbfb63342014-02-08 00:32:31 +01001104 if (mBaseSet == set)
1105 mBaseSet = mCurrentSet;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001106 delete set;
1107 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001108}
1109
1110void PageManager::ReleasePackage(std::string name)
1111{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001112 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001113
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001114 iter = mPageSets.find(name);
1115 if (iter == mPageSets.end())
1116 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001117
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001118 PageSet* set = (*iter).second;
1119 mPageSets.erase(iter);
1120 delete set;
1121 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001122}
1123
1124int PageManager::ChangePage(std::string name)
1125{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001126 DataManager::SetValue("tw_operation_state", 0);
1127 int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
1128 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001129}
1130
1131int PageManager::ChangeOverlay(std::string name)
1132{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001133 if (name.empty())
1134 return mCurrentSet->SetOverlay(NULL);
1135 else
1136 {
1137 Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
1138 return mCurrentSet->SetOverlay(page);
1139 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001140}
1141
1142Resource* PageManager::FindResource(std::string name)
1143{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001144 return (mCurrentSet ? mCurrentSet->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001145}
1146
1147Resource* PageManager::FindResource(std::string package, std::string name)
1148{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001149 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -04001150
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001151 tmp = FindPackage(name);
1152 return (tmp ? tmp->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001153}
1154
1155int PageManager::SwitchToConsole(void)
1156{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001157 PageSet* console = new PageSet(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001158
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001159 mCurrentSet = console;
1160 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001161}
1162
Ethan Yonker03a42f62014-08-08 11:03:51 -05001163int PageManager::EndConsole(void)
1164{
1165 if (mCurrentSet && mBaseSet) {
1166 delete mCurrentSet;
1167 mCurrentSet = mBaseSet;
1168 return 0;
1169 }
1170 return -1;
1171}
1172
Dees_Troy51a0e822012-09-05 15:24:24 -04001173int PageManager::IsCurrentPage(Page* page)
1174{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001175 return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -04001176}
1177
1178int PageManager::Render(void)
1179{
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001180 int res = (mCurrentSet ? mCurrentSet->Render() : -1);
1181 if(mMouseCursor)
1182 mMouseCursor->Render();
1183 return res;
1184}
1185
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001186HardwareKeyboard *PageManager::GetHardwareKeyboard()
1187{
1188 if(!mHardwareKeyboard)
1189 mHardwareKeyboard = new HardwareKeyboard();
1190 return mHardwareKeyboard;
1191}
1192
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001193MouseCursor *PageManager::GetMouseCursor()
1194{
1195 if(!mMouseCursor)
1196 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1197 return mMouseCursor;
1198}
1199
1200void PageManager::LoadCursorData(xml_node<>* node)
1201{
1202 if(!mMouseCursor)
1203 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1204
1205 mMouseCursor->LoadData(node);
Dees_Troy51a0e822012-09-05 15:24:24 -04001206}
1207
1208int PageManager::Update(void)
1209{
thatfb759d42015-01-11 12:16:53 +01001210 if(blankTimer.isScreenOff())
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001211 return 0;
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001212
1213 int res = (mCurrentSet ? mCurrentSet->Update() : -1);
1214
1215 if(mMouseCursor)
1216 {
1217 int c_res = mMouseCursor->Update();
1218 if(c_res > res)
1219 res = c_res;
1220 }
1221 return res;
Dees_Troy51a0e822012-09-05 15:24:24 -04001222}
1223
1224int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
1225{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001226 return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001227}
1228
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001229int PageManager::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -04001230{
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001231 return (mCurrentSet ? mCurrentSet->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001232}
1233
1234int PageManager::NotifyKeyboard(int key)
1235{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001236 return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001237}
1238
1239int PageManager::SetKeyBoardFocus(int inFocus)
1240{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001241 return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001242}
1243
1244int PageManager::NotifyVarChange(std::string varName, std::string value)
1245{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001246 return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001247}
1248
1249extern "C" void gui_notifyVarChange(const char *name, const char* value)
1250{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001251 if (!gGuiRunning)
1252 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001253
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001254 PageManager::NotifyVarChange(name, value);
Dees_Troy51a0e822012-09-05 15:24:24 -04001255}