blob: 94c351be27480ffc2f9f5c6ee1e661c39512380d [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
647 LOGINFO("PageSet::CheckInclude loading filename: '%s'\n", filename.c_str());
648 if (!package) {
649 // We can try to load the XML directly...
650 filename = "/res/";
651 filename += attr->value();
652 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();
671 const ZipEntry* ui_xml = mzFindZipEntry(package, filename.c_str());
672 if (ui_xml == NULL)
673 {
674 LOGERR("Unable to locate '%s' in zip file\n", filename.c_str());
675 return -1;
676 }
677
678 // Allocate the buffer for the file
679 len = mzGetZipEntryUncompLen(ui_xml);
680 xmlFile = (char*) malloc(len + 1);
681 if (!xmlFile)
682 return -1;
683
684 if (!mzExtractZipEntryToBuffer(package, ui_xml, (unsigned char*) xmlFile))
685 {
686 LOGERR("Unable to extract '%s'\n", filename.c_str());
687 return -1;
688 }
689 }
Ethan Yonker780cd392014-07-21 15:24:39 -0500690
Vojtech Boceke979abd2015-01-12 18:29:12 +0100691 xmlFile[len] = '\0';
692 doc = new xml_document<>();
693 doc->parse<0>(xmlFile);
694
695 parent = doc->first_node("recovery");
Ethan Yonker780cd392014-07-21 15:24:39 -0500696 if (!parent)
Vojtech Boceke979abd2015-01-12 18:29:12 +0100697 parent = doc->first_node("install");
Ethan Yonker780cd392014-07-21 15:24:39 -0500698
699 // Now, let's parse the XML
700 LOGINFO("Loading included resources...\n");
701 child = parent->first_node("resources");
702 if (child)
703 mResources->LoadResources(child, package);
704
705 LOGINFO("Loading included variables...\n");
706 child = parent->first_node("variables");
707 if (child)
708 LoadVariables(child);
709
710 LOGINFO("Loading mouse cursor...\n");
711 child = parent->first_node("mousecursor");
712 if(child)
713 PageManager::LoadCursorData(child);
714
715 LOGINFO("Loading included pages...\n");
716 // This may be NULL if no templates are present
717 xmltemplate = parent->first_node("templates");
718 if (xmltemplate)
719 templates.push_back(xmltemplate);
720
721 child = parent->first_node("pages");
Vojtech Boceke979abd2015-01-12 18:29:12 +0100722 if (child && LoadPages(child))
723 {
724 templates.pop_back();
725 doc->clear();
726 delete doc;
727 return -1;
728 }
Ethan Yonker780cd392014-07-21 15:24:39 -0500729
Vojtech Boceke979abd2015-01-12 18:29:12 +0100730 mIncludedDocs.push_back(doc);
731
732 if (CheckInclude(package, doc))
Ethan Yonker780cd392014-07-21 15:24:39 -0500733 return -1;
734
735 chld = chld->next_sibling("xmlfile");
736 }
737
738 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400739}
740
741int PageSet::SetPage(std::string page)
742{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200743 Page* tmp = FindPage(page);
744 if (tmp)
745 {
746 if (mCurrentPage) mCurrentPage->SetPageFocus(0);
747 mCurrentPage = tmp;
748 mCurrentPage->SetPageFocus(1);
749 mCurrentPage->NotifyVarChange("", "");
750 return 0;
751 }
752 else
753 {
754 LOGERR("Unable to locate page (%s)\n", page.c_str());
755 }
756 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400757}
758
759int PageSet::SetOverlay(Page* page)
760{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200761 if (mOverlayPage) mOverlayPage->SetPageFocus(0);
762 mOverlayPage = page;
763 if (mOverlayPage)
764 {
765 mOverlayPage->SetPageFocus(1);
766 mOverlayPage->NotifyVarChange("", "");
767 }
768 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400769}
770
771Resource* PageSet::FindResource(std::string name)
772{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200773 return mResources ? mResources->FindResource(name) : NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400774}
775
776Page* PageSet::FindPage(std::string name)
777{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200778 std::vector<Page*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400779
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200780 for (iter = mPages.begin(); iter != mPages.end(); iter++)
781 {
782 if (name == (*iter)->GetName())
783 return (*iter);
784 }
785 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400786}
787
788int PageSet::LoadVariables(xml_node<>* vars)
789{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200790 xml_node<>* child;
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100791 xml_attribute<> *name, *value, *persist;
792 int p;
Dees_Troy51a0e822012-09-05 15:24:24 -0400793
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200794 child = vars->first_node("variable");
795 while (child)
796 {
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100797 name = child->first_attribute("name");
798 value = child->first_attribute("value");
799 persist = child->first_attribute("persist");
800 if(name && value)
801 {
Ethan Yonker751a85e2014-12-12 16:59:10 -0600802 if (strcmp(name->value(), "tw_x_offset") == 0) {
803 tw_x_offset = atoi(value->value());
804 child = child->next_sibling("variable");
805 continue;
806 }
807 if (strcmp(name->value(), "tw_y_offset") == 0) {
808 tw_y_offset = atoi(value->value());
809 child = child->next_sibling("variable");
810 continue;
811 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100812 p = persist ? atoi(persist->value()) : 0;
Ethan Yonker96acb3d2014-08-05 09:20:30 -0500813 string temp = value->value();
814 string valstr = gui_parse_text(temp);
815
816 if (valstr.find("+") != string::npos) {
817 string val1str = valstr;
818 val1str = val1str.substr(0, val1str.find('+'));
819 string val2str = valstr;
820 val2str = val2str.substr(val2str.find('+') + 1, string::npos);
821 int val1 = atoi(val1str.c_str());
822 int val2 = atoi(val2str.c_str());
823 int val = val1 + val2;
824
825 DataManager::SetValue(name->value(), val, p);
826 } else if (valstr.find("-") != string::npos) {
827 string val1str = valstr;
828 val1str = val1str.substr(0, val1str.find('-'));
829 string val2str = valstr;
830 val2str = val2str.substr(val2str.find('-') + 1, string::npos);
831 int val1 = atoi(val1str.c_str());
832 int val2 = atoi(val2str.c_str());
833 int val = val1 - val2;
834
835 DataManager::SetValue(name->value(), val, p);
836 } else {
837 DataManager::SetValue(name->value(), valstr, p);
838 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100839 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400840
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200841 child = child->next_sibling("variable");
842 }
843 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400844}
845
Ethan Yonker780cd392014-07-21 15:24:39 -0500846int PageSet::LoadPages(xml_node<>* pages)
Dees_Troy51a0e822012-09-05 15:24:24 -0400847{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200848 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -0400849
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200850 if (!pages)
851 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400852
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200853 child = pages->first_node("page");
854 while (child != NULL)
855 {
Ethan Yonker780cd392014-07-21 15:24:39 -0500856 Page* page = new Page(child, &templates);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200857 if (page->GetName().empty())
858 {
859 LOGERR("Unable to process load page\n");
860 delete page;
861 }
862 else
863 {
864 mPages.push_back(page);
865 }
866 child = child->next_sibling("page");
867 }
868 if (mPages.size() > 0)
869 return 0;
870 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400871}
872
873int PageSet::IsCurrentPage(Page* page)
874{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200875 return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400876}
877
878int PageSet::Render(void)
879{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200880 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400881
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200882 ret = (mCurrentPage ? mCurrentPage->Render() : -1);
883 if (ret < 0)
884 return ret;
885 ret = (mOverlayPage ? mOverlayPage->Render() : -1);
886 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400887}
888
889int PageSet::Update(void)
890{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200891 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400892
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200893 ret = (mCurrentPage ? mCurrentPage->Update() : -1);
894 if (ret < 0 || ret > 1)
895 return ret;
896 ret = (mOverlayPage ? mOverlayPage->Update() : -1);
897 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400898}
899
900int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
901{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200902 if (mOverlayPage)
903 return (mOverlayPage->NotifyTouch(state, x, y));
904
905 return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400906}
907
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100908int PageSet::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -0400909{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200910 if (mOverlayPage)
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100911 return (mOverlayPage->NotifyKey(key, down));
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200912
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100913 return (mCurrentPage ? mCurrentPage->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400914}
915
916int PageSet::NotifyKeyboard(int key)
917{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200918 if (mOverlayPage)
919 return (mOverlayPage->NotifyKeyboard(key));
920
921 return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400922}
923
924int PageSet::SetKeyBoardFocus(int inFocus)
925{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200926 if (mOverlayPage)
927 return (mOverlayPage->SetKeyBoardFocus(inFocus));
928
929 return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400930}
931
932int PageSet::NotifyVarChange(std::string varName, std::string value)
933{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200934 if (mOverlayPage)
935 mOverlayPage->NotifyVarChange(varName, value);
936
937 return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400938}
939
940int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
941{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200942 int fd;
943 ZipArchive zip, *pZip = NULL;
944 long len;
945 char* xmlFile = NULL;
946 PageSet* pageSet = NULL;
947 int ret;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600948 MemMapping map;
Dees_Troy51a0e822012-09-05 15:24:24 -0400949
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200950 // Open the XML file
951 LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600952 if (package.size() > 4 && package.substr(package.size() - 4) != ".zip")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200953 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600954 LOGINFO("Load XML directly\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -0600955 tw_x_offset = TW_X_OFFSET;
956 tw_y_offset = TW_Y_OFFSET;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200957 // We can try to load the XML directly...
958 struct stat st;
959 if(stat(package.c_str(),&st) != 0)
960 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400961
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200962 len = st.st_size;
963 xmlFile = (char*) malloc(len + 1);
964 if (!xmlFile)
965 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400966
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200967 fd = open(package.c_str(), O_RDONLY);
968 if (fd == -1)
969 goto error;
Dees_Troy51a0e822012-09-05 15:24:24 -0400970
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200971 read(fd, xmlFile, len);
972 close(fd);
973 }
974 else
975 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600976 LOGINFO("Loading zip theme\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -0600977 tw_x_offset = 0;
978 tw_y_offset = 0;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600979 if (!TWFunc::Path_Exists(package))
980 return -1;
981 if (sysMapFile(package.c_str(), &map) != 0) {
982 LOGERR("Failed to map '%s'\n", package.c_str());
983 return -1;
984 }
985 if (mzOpenZipArchive(map.addr, map.length, &zip)) {
986 LOGERR("Unable to open zip archive '%s'\n", package.c_str());
987 sysReleaseMap(&map);
988 return -1;
989 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200990 pZip = &zip;
991 const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
992 if (ui_xml == NULL)
993 {
994 LOGERR("Unable to locate ui.xml in zip file\n");
995 goto error;
996 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500997
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200998 // Allocate the buffer for the file
999 len = mzGetZipEntryUncompLen(ui_xml);
1000 xmlFile = (char*) malloc(len + 1);
1001 if (!xmlFile)
1002 goto error;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001003
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001004 if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
1005 {
1006 LOGERR("Unable to extract ui.xml\n");
1007 goto error;
1008 }
1009 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001010
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001011 // NULL-terminate the string
1012 xmlFile[len] = 0x00;
Dees_Troy51a0e822012-09-05 15:24:24 -04001013
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001014 // Before loading, mCurrentSet must be the loading package so we can find resources
1015 pageSet = mCurrentSet;
1016 mCurrentSet = new PageSet(xmlFile);
1017
1018 ret = mCurrentSet->Load(pZip);
1019 if (ret == 0)
1020 {
1021 mCurrentSet->SetPage(startpage);
1022 mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
1023 }
1024 else
1025 {
1026 LOGERR("Package %s failed to load.\n", name.c_str());
1027 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001028
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001029 // The first successful package we loaded is the base
1030 if (mBaseSet == NULL)
1031 mBaseSet = mCurrentSet;
1032
1033 mCurrentSet = pageSet;
1034
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001035 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001036 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001037 sysReleaseMap(&map);
1038 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001039 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001040
1041error:
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001042 LOGERR("An internal error has occurred.\n");
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001043 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001044 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001045 sysReleaseMap(&map);
1046 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001047 if (xmlFile)
1048 free(xmlFile);
1049 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001050}
1051
1052PageSet* PageManager::FindPackage(std::string name)
1053{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001054 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001055
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001056 iter = mPageSets.find(name);
1057 if (iter != mPageSets.end())
1058 return (*iter).second;
1059
1060 LOGERR("Unable to locate package %s\n", name.c_str());
1061 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -04001062}
1063
1064PageSet* PageManager::SelectPackage(std::string name)
1065{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001066 LOGINFO("Switching packages (%s)\n", name.c_str());
1067 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -04001068
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001069 tmp = FindPackage(name);
1070 if (tmp)
Vojtech Bocek07220562014-02-08 02:05:33 +01001071 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001072 mCurrentSet = tmp;
Vojtech Bocek07220562014-02-08 02:05:33 +01001073 mCurrentSet->NotifyVarChange("", "");
1074 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001075 else
1076 LOGERR("Unable to find package.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -04001077
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001078 return mCurrentSet;
Dees_Troy51a0e822012-09-05 15:24:24 -04001079}
1080
1081int PageManager::ReloadPackage(std::string name, std::string package)
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 -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001088
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001089 if(mMouseCursor)
1090 mMouseCursor->ResetData(gr_fb_width(), gr_fb_height());
1091
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001092 PageSet* set = (*iter).second;
1093 mPageSets.erase(iter);
Dees_Troy51a0e822012-09-05 15:24:24 -04001094
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001095 if (LoadPackage(name, package, "main") != 0)
1096 {
1097 LOGERR("Failed to load package.\n");
1098 mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
1099 return -1;
1100 }
1101 if (mCurrentSet == set)
1102 SelectPackage(name);
Vojtech Bocekbfb63342014-02-08 00:32:31 +01001103 if (mBaseSet == set)
1104 mBaseSet = mCurrentSet;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001105 delete set;
1106 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001107}
1108
1109void PageManager::ReleasePackage(std::string name)
1110{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001111 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001112
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001113 iter = mPageSets.find(name);
1114 if (iter == mPageSets.end())
1115 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001116
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001117 PageSet* set = (*iter).second;
1118 mPageSets.erase(iter);
1119 delete set;
1120 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001121}
1122
1123int PageManager::ChangePage(std::string name)
1124{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001125 DataManager::SetValue("tw_operation_state", 0);
1126 int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
1127 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001128}
1129
1130int PageManager::ChangeOverlay(std::string name)
1131{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001132 if (name.empty())
1133 return mCurrentSet->SetOverlay(NULL);
1134 else
1135 {
1136 Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
1137 return mCurrentSet->SetOverlay(page);
1138 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001139}
1140
1141Resource* PageManager::FindResource(std::string name)
1142{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001143 return (mCurrentSet ? mCurrentSet->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001144}
1145
1146Resource* PageManager::FindResource(std::string package, std::string name)
1147{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001148 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -04001149
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001150 tmp = FindPackage(name);
1151 return (tmp ? tmp->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001152}
1153
1154int PageManager::SwitchToConsole(void)
1155{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001156 PageSet* console = new PageSet(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001157
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001158 mCurrentSet = console;
1159 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001160}
1161
Ethan Yonker03a42f62014-08-08 11:03:51 -05001162int PageManager::EndConsole(void)
1163{
1164 if (mCurrentSet && mBaseSet) {
1165 delete mCurrentSet;
1166 mCurrentSet = mBaseSet;
1167 return 0;
1168 }
1169 return -1;
1170}
1171
Dees_Troy51a0e822012-09-05 15:24:24 -04001172int PageManager::IsCurrentPage(Page* page)
1173{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001174 return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -04001175}
1176
1177int PageManager::Render(void)
1178{
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001179 int res = (mCurrentSet ? mCurrentSet->Render() : -1);
1180 if(mMouseCursor)
1181 mMouseCursor->Render();
1182 return res;
1183}
1184
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001185HardwareKeyboard *PageManager::GetHardwareKeyboard()
1186{
1187 if(!mHardwareKeyboard)
1188 mHardwareKeyboard = new HardwareKeyboard();
1189 return mHardwareKeyboard;
1190}
1191
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001192MouseCursor *PageManager::GetMouseCursor()
1193{
1194 if(!mMouseCursor)
1195 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1196 return mMouseCursor;
1197}
1198
1199void PageManager::LoadCursorData(xml_node<>* node)
1200{
1201 if(!mMouseCursor)
1202 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1203
1204 mMouseCursor->LoadData(node);
Dees_Troy51a0e822012-09-05 15:24:24 -04001205}
1206
1207int PageManager::Update(void)
1208{
thatfb759d42015-01-11 12:16:53 +01001209 if(blankTimer.isScreenOff())
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001210 return 0;
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001211
1212 int res = (mCurrentSet ? mCurrentSet->Update() : -1);
1213
1214 if(mMouseCursor)
1215 {
1216 int c_res = mMouseCursor->Update();
1217 if(c_res > res)
1218 res = c_res;
1219 }
1220 return res;
Dees_Troy51a0e822012-09-05 15:24:24 -04001221}
1222
1223int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
1224{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001225 return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001226}
1227
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001228int PageManager::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -04001229{
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001230 return (mCurrentSet ? mCurrentSet->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001231}
1232
1233int PageManager::NotifyKeyboard(int key)
1234{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001235 return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001236}
1237
1238int PageManager::SetKeyBoardFocus(int inFocus)
1239{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001240 return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001241}
1242
1243int PageManager::NotifyVarChange(std::string varName, std::string value)
1244{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001245 return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001246}
1247
1248extern "C" void gui_notifyVarChange(const char *name, const char* value)
1249{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001250 if (!gGuiRunning)
1251 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001252
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001253 PageManager::NotifyVarChange(name, value);
Dees_Troy51a0e822012-09-05 15:24:24 -04001254}