blob: a1a6346a4a0a62f8e23977623af58b4f30bec0cc [file] [log] [blame]
Dees_Troya13d74f2013-03-24 08:54:55 -05001/*
2 Copyright 2013 bigbiff/Dees_Troy TeamWin
3 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
Dees Troy3be70a82013-10-22 14:25:12 +000018
Dees_Troya13d74f2013-03-24 08:54:55 -050019// pages.cpp - Source to manage GUI base objects
Dees_Troy51a0e822012-09-05 15:24:24 -040020
21#include <stdarg.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <fcntl.h>
26#include <sys/reboot.h>
27#include <sys/stat.h>
28#include <sys/time.h>
29#include <sys/mman.h>
30#include <sys/types.h>
31#include <sys/ioctl.h>
32#include <time.h>
33#include <unistd.h>
34#include <stdlib.h>
Ethan Yonkera2dc2f22014-11-08 08:13:40 -060035#include "../twrp-functions.hpp"
Dees_Troy51a0e822012-09-05 15:24:24 -040036
37#include <string>
38
39extern "C" {
Dees_Troy2673cec2013-04-02 20:22:16 +000040#include "../twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040041#include "../minuitwrp/minui.h"
Ethan Yonkera2dc2f22014-11-08 08:13:40 -060042#include "../minzip/SysUtil.h"
43#include "../minzip/Zip.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040044}
45
46#include "rapidxml.hpp"
47#include "objects.hpp"
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070048#ifndef TW_NO_SCREEN_TIMEOUT
gordon13370d9133d2013-06-08 14:17:07 +020049#include "blanktimer.hpp"
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070050#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040051
52extern int gGuiRunning;
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070053#ifndef TW_NO_SCREEN_TIMEOUT
gordon13370d9133d2013-06-08 14:17:07 +020054extern blanktimer blankTimer;
Ricardo Gomezc9ecd442013-07-05 16:13:52 -070055#endif
Dees_Troy51a0e822012-09-05 15:24:24 -040056
57std::map<std::string, PageSet*> PageManager::mPageSets;
58PageSet* PageManager::mCurrentSet;
59PageSet* PageManager::mBaseSet = NULL;
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +010060MouseCursor *PageManager::mMouseCursor = NULL;
Vojtech Bocek0b7fe502014-03-13 17:36:52 +010061HardwareKeyboard *PageManager::mHardwareKeyboard = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -040062
Ethan Yonker751a85e2014-12-12 16:59:10 -060063int tw_x_offset = 0;
64int tw_y_offset = 0;
65
Dees_Troy51a0e822012-09-05 15:24:24 -040066// Helper routine to convert a string to a color declaration
67int ConvertStrToColor(std::string str, COLOR* color)
68{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020069 // Set the default, solid black
70 memset(color, 0, sizeof(COLOR));
71 color->alpha = 255;
Dees_Troy51a0e822012-09-05 15:24:24 -040072
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020073 // Translate variables
74 DataManager::GetValue(str, str);
Matt Mowerfb1c4ff2014-04-16 13:43:36 -050075
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020076 // Look for some defaults
77 if (str == "black") return 0;
78 else if (str == "white") { color->red = color->green = color->blue = 255; return 0; }
79 else if (str == "red") { color->red = 255; return 0; }
80 else if (str == "green") { color->green = 255; return 0; }
81 else if (str == "blue") { color->blue = 255; return 0; }
Dees_Troy51a0e822012-09-05 15:24:24 -040082
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020083 // At this point, we require an RGB(A) color
84 if (str[0] != '#')
85 return -1;
86
87 str.erase(0, 1);
Dees_Troy51a0e822012-09-05 15:24:24 -040088
Dees_Troy30b962e2012-10-19 20:48:59 -040089 int result;
90 if (str.size() >= 8) {
91 // We have alpha channel
92 string alpha = str.substr(6, 2);
93 result = strtol(alpha.c_str(), NULL, 16);
94 color->alpha = result & 0x000000FF;
95 str.resize(6);
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 } else {
101 result = strtol(str.c_str(), NULL, 16);
102 color->red = (result >> 16) & 0x000000FF;
103 color->green = (result >> 8) & 0x000000FF;
104 color->blue = result & 0x000000FF;
105 }
106 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400107}
108
109// Helper APIs
110bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
111{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200112 if (!node)
113 return false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400114
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200115 std::string value;
116 if (node->first_attribute("x"))
117 {
118 value = node->first_attribute("x")->value();
119 DataManager::GetValue(value, value);
120 *x = atol(value.c_str());
Ethan Yonker751a85e2014-12-12 16:59:10 -0600121 *x += tw_x_offset;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200122 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400123
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200124 if (node->first_attribute("y"))
125 {
126 value = node->first_attribute("y")->value();
127 DataManager::GetValue(value, value);
128 *y = atol(value.c_str());
Ethan Yonker751a85e2014-12-12 16:59:10 -0600129 *y += tw_y_offset;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200130 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400131
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200132 if (w && node->first_attribute("w"))
133 {
134 value = node->first_attribute("w")->value();
135 DataManager::GetValue(value, value);
136 *w = atol(value.c_str());
137 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400138
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200139 if (h && node->first_attribute("h"))
140 {
141 value = node->first_attribute("h")->value();
142 DataManager::GetValue(value, value);
143 *h = atol(value.c_str());
144 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400145
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200146 if (placement && node->first_attribute("placement"))
147 {
148 value = node->first_attribute("placement")->value();
149 DataManager::GetValue(value, value);
150 *placement = (RenderObject::Placement) atol(value.c_str());
151 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400152
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200153 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400154}
155
156int ActionObject::SetActionPos(int x, int y, int w, int h)
157{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200158 if (x < 0 || y < 0)
159 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400160
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500161 mActionX = x;
162 mActionY = y;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200163 if (w || h)
164 {
165 mActionW = w;
166 mActionH = h;
167 }
168 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400169}
170
Ethan Yonker780cd392014-07-21 15:24:39 -0500171Page::Page(xml_node<>* page, std::vector<xml_node<>*> *templates /* = NULL */)
Dees_Troy51a0e822012-09-05 15:24:24 -0400172{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200173 mTouchStart = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400174
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200175 // We can memset the whole structure, because the alpha channel is ignored
176 memset(&mBackground, 0, sizeof(COLOR));
Dees_Troy51a0e822012-09-05 15:24:24 -0400177
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200178 // With NULL, we make a console-only display
179 if (!page)
180 {
181 mName = "console";
Dees_Troy51a0e822012-09-05 15:24:24 -0400182
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200183 GUIConsole* element = new GUIConsole(NULL);
184 mRenders.push_back(element);
185 mActions.push_back(element);
186 return;
187 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400188
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200189 if (page->first_attribute("name"))
190 mName = page->first_attribute("name")->value();
191 else
192 {
193 LOGERR("No page name attribute found!\n");
194 return;
195 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400196
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200197 LOGINFO("Loading page %s\n", mName.c_str());
Dees_Troy51a0e822012-09-05 15:24:24 -0400198
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200199 // This is a recursive routine for template handling
200 ProcessNode(page, templates);
Dees_Troy51a0e822012-09-05 15:24:24 -0400201
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200202 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400203}
204
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100205Page::~Page()
206{
207 for (std::vector<GUIObject*>::iterator itr = mObjects.begin(); itr != mObjects.end(); ++itr)
208 delete *itr;
209}
210
Ethan Yonker780cd392014-07-21 15:24:39 -0500211bool Page::ProcessNode(xml_node<>* page, std::vector<xml_node<>*> *templates /* = NULL */, int depth /* = 0 */)
Dees_Troy51a0e822012-09-05 15:24:24 -0400212{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200213 if (depth == 10)
214 {
215 LOGERR("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
216 return false;
217 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400218
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200219 // Let's retrieve the background value, if any
220 xml_node<>* bg = page->first_node("background");
221 if (bg)
222 {
223 xml_attribute<>* attr = bg->first_attribute("color");
224 if (attr)
225 {
226 std::string color = attr->value();
227 ConvertStrToColor(color, &mBackground);
228 }
229 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400230
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200231 xml_node<>* child;
232 child = page->first_node("object");
233 while (child)
234 {
235 if (!child->first_attribute("type"))
236 break;
Dees_Troy51a0e822012-09-05 15:24:24 -0400237
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200238 std::string type = child->first_attribute("type")->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400239
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200240 if (type == "text")
241 {
242 GUIText* element = new GUIText(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100243 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200244 mRenders.push_back(element);
245 mActions.push_back(element);
246 }
247 else if (type == "image")
248 {
249 GUIImage* element = new GUIImage(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100250 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200251 mRenders.push_back(element);
252 }
253 else if (type == "fill")
254 {
255 GUIFill* element = new GUIFill(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100256 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200257 mRenders.push_back(element);
258 }
259 else if (type == "action")
260 {
261 GUIAction* element = new GUIAction(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100262 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200263 mActions.push_back(element);
264 }
265 else if (type == "console")
266 {
267 GUIConsole* element = new GUIConsole(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100268 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200269 mRenders.push_back(element);
270 mActions.push_back(element);
271 }
272 else if (type == "button")
273 {
274 GUIButton* element = new GUIButton(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100275 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200276 mRenders.push_back(element);
277 mActions.push_back(element);
278 }
279 else if (type == "checkbox")
280 {
281 GUICheckbox* element = new GUICheckbox(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100282 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200283 mRenders.push_back(element);
284 mActions.push_back(element);
285 }
286 else if (type == "fileselector")
287 {
288 GUIFileSelector* element = new GUIFileSelector(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100289 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200290 mRenders.push_back(element);
291 mActions.push_back(element);
292 }
293 else if (type == "animation")
294 {
295 GUIAnimation* element = new GUIAnimation(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100296 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200297 mRenders.push_back(element);
298 }
299 else if (type == "progressbar")
300 {
301 GUIProgressBar* element = new GUIProgressBar(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100302 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200303 mRenders.push_back(element);
304 mActions.push_back(element);
305 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400306 else if (type == "slider")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200307 {
308 GUISlider* element = new GUISlider(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100309 mObjects.push_back(element);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200310 mRenders.push_back(element);
311 mActions.push_back(element);
312 }
Vojtech Bocek85932342013-04-01 22:11:33 +0200313 else if (type == "slidervalue")
314 {
315 GUISliderValue *element = new GUISliderValue(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100316 mObjects.push_back(element);
Vojtech Bocek85932342013-04-01 22:11:33 +0200317 mRenders.push_back(element);
318 mActions.push_back(element);
319 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400320 else if (type == "listbox")
321 {
322 GUIListBox* element = new GUIListBox(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100323 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400324 mRenders.push_back(element);
325 mActions.push_back(element);
326 }
327 else if (type == "keyboard")
328 {
329 GUIKeyboard* element = new GUIKeyboard(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100330 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400331 mRenders.push_back(element);
332 mActions.push_back(element);
333 }
334 else if (type == "input")
335 {
336 GUIInput* element = new GUIInput(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100337 mObjects.push_back(element);
Dees_Troy51a0e822012-09-05 15:24:24 -0400338 mRenders.push_back(element);
339 mActions.push_back(element);
340 mInputs.push_back(element);
341 }
Dees_Troya13d74f2013-03-24 08:54:55 -0500342 else if (type == "partitionlist")
343 {
344 GUIPartitionList* element = new GUIPartitionList(child);
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100345 mObjects.push_back(element);
Dees_Troya13d74f2013-03-24 08:54:55 -0500346 mRenders.push_back(element);
347 mActions.push_back(element);
348 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200349 else if (type == "template")
350 {
351 if (!templates || !child->first_attribute("name"))
352 {
353 LOGERR("Invalid template request.\n");
354 }
355 else
356 {
357 std::string name = child->first_attribute("name")->value();
Ethan Yonker780cd392014-07-21 15:24:39 -0500358 xml_node<>* node;
359 bool node_found = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400360
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200361 // We need to find the correct template
Ethan Yonker780cd392014-07-21 15:24:39 -0500362 for (std::vector<xml_node<>*>::iterator itr = templates->begin(); itr != templates->end(); itr++) {
363 node = (*itr)->first_node("template");
Dees_Troy51a0e822012-09-05 15:24:24 -0400364
Ethan Yonker780cd392014-07-21 15:24:39 -0500365 while (node)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200366 {
Ethan Yonker780cd392014-07-21 15:24:39 -0500367 if (!node->first_attribute("name"))
368 continue;
369
370 if (name == node->first_attribute("name")->value())
371 {
372 if (!ProcessNode(node, templates, depth + 1))
373 return false;
374 else {
375 node_found = true;
376 break;
377 }
378 }
379 if (node_found)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200380 break;
Ethan Yonker780cd392014-07-21 15:24:39 -0500381 node = node->next_sibling("template");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200382 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200383 }
384 }
385 }
386 else
387 {
388 LOGERR("Unknown object type.\n");
389 }
390 child = child->next_sibling("object");
391 }
392 return true;
Dees_Troy51a0e822012-09-05 15:24:24 -0400393}
394
395int Page::Render(void)
396{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200397 // Render background
398 gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
399 gr_fill(0, 0, gr_fb_width(), gr_fb_height());
Dees_Troy51a0e822012-09-05 15:24:24 -0400400
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200401 // Render remaining objects
402 std::vector<RenderObject*>::iterator iter;
403 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
404 {
405 if ((*iter)->Render())
406 LOGERR("A render request has failed.\n");
407 }
408 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400409}
410
411int Page::Update(void)
412{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200413 int retCode = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400414
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200415 std::vector<RenderObject*>::iterator iter;
416 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
417 {
418 int ret = (*iter)->Update();
419 if (ret < 0)
420 LOGERR("An update request has failed.\n");
421 else if (ret > retCode)
422 retCode = ret;
423 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400424
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200425 return retCode;
Dees_Troy51a0e822012-09-05 15:24:24 -0400426}
427
428int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
429{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200430 // By default, return 1 to ignore further touches if nobody is listening
431 int ret = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400432
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200433 // Don't try to handle a lack of handlers
434 if (mActions.size() == 0)
435 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400436
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200437 // We record mTouchStart so we can pass all the touch stream to the same handler
438 if (state == TOUCH_START)
439 {
440 std::vector<ActionObject*>::reverse_iterator iter;
441 // We work backwards, from top-most element to bottom-most element
442 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
443 {
444 if ((*iter)->IsInRegion(x, y))
445 {
446 mTouchStart = (*iter);
447 ret = mTouchStart->NotifyTouch(state, x, y);
448 if (ret >= 0)
449 break;
450 mTouchStart = NULL;
451 }
452 }
453 }
454 else if (state == TOUCH_RELEASE && mTouchStart != NULL)
455 {
456 ret = mTouchStart->NotifyTouch(state, x, y);
457 mTouchStart = NULL;
458 }
459 else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
460 {
461 ret = mTouchStart->NotifyTouch(state, x, y);
462 }
463 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400464}
465
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100466int Page::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -0400467{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200468 std::vector<ActionObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400469
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200470 // Don't try to handle a lack of handlers
471 if (mActions.size() == 0)
472 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400473
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100474 int ret = 1;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200475 // We work backwards, from top-most element to bottom-most element
476 for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
477 {
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100478 ret = (*iter)->NotifyKey(key, down);
479 if (ret < 0) {
480 LOGERR("An action handler has returned an error\n");
481 ret = 1;
482 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200483 }
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100484 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400485}
486
487int Page::NotifyKeyboard(int key)
488{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200489 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400490
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200491 // Don't try to handle a lack of handlers
492 if (mInputs.size() == 0)
493 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400494
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200495 // We work backwards, from top-most element to bottom-most element
496 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
497 {
498 int ret = (*iter)->NotifyKeyboard(key);
499 if (ret == 0)
500 return 0;
501 else if (ret < 0)
502 LOGERR("A keyboard handler has returned an error");
503 }
504 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400505}
506
507int Page::SetKeyBoardFocus(int inFocus)
508{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200509 std::vector<InputObject*>::reverse_iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400510
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200511 // Don't try to handle a lack of handlers
512 if (mInputs.size() == 0)
513 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400514
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200515 // We work backwards, from top-most element to bottom-most element
516 for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
517 {
518 int ret = (*iter)->SetInputFocus(inFocus);
519 if (ret == 0)
520 return 0;
521 else if (ret < 0)
522 LOGERR("An input focus handler has returned an error");
523 }
524 return 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400525}
526
527void Page::SetPageFocus(int inFocus)
528{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200529 // Render remaining objects
530 std::vector<RenderObject*>::iterator iter;
531 for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
532 (*iter)->SetPageFocus(inFocus);
533
534 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400535}
536
537int Page::NotifyVarChange(std::string varName, std::string value)
538{
Vojtech Bocek07220562014-02-08 02:05:33 +0100539 std::vector<GUIObject*>::iterator iter;
540 for (iter = mObjects.begin(); iter != mObjects.end(); ++iter)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200541 {
542 if ((*iter)->NotifyVarChange(varName, value))
543 LOGERR("An action handler errored on NotifyVarChange.\n");
544 }
545 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400546}
547
548PageSet::PageSet(char* xmlFile)
549{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200550 mResources = NULL;
551 mCurrentPage = NULL;
552 mOverlayPage = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400553
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200554 mXmlFile = xmlFile;
555 if (xmlFile)
556 mDoc.parse<0>(mXmlFile);
557 else
558 mCurrentPage = new Page(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -0400559}
560
561PageSet::~PageSet()
562{
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100563 for (std::vector<Page*>::iterator itr = mPages.begin(); itr != mPages.end(); ++itr)
564 delete *itr;
Ethan Yonker780cd392014-07-21 15:24:39 -0500565 for (std::vector<xml_node<>*>::iterator itr2 = templates.begin(); itr2 != templates.end(); ++itr2)
566 delete *itr2;
Vojtech Bocekbfb63342014-02-08 00:32:31 +0100567
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200568 delete mResources;
569 free(mXmlFile);
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 }
613
614 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;
628 xml_document<> doc;
629
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 }
690 doc.parse<0>(xmlFile);
691
692 parent = doc.first_node("recovery");
693 if (!parent)
694 parent = doc.first_node("install");
695
696 // Now, let's parse the XML
697 LOGINFO("Loading included resources...\n");
698 child = parent->first_node("resources");
699 if (child)
700 mResources->LoadResources(child, package);
701
702 LOGINFO("Loading included variables...\n");
703 child = parent->first_node("variables");
704 if (child)
705 LoadVariables(child);
706
707 LOGINFO("Loading mouse cursor...\n");
708 child = parent->first_node("mousecursor");
709 if(child)
710 PageManager::LoadCursorData(child);
711
712 LOGINFO("Loading included pages...\n");
713 // This may be NULL if no templates are present
714 xmltemplate = parent->first_node("templates");
715 if (xmltemplate)
716 templates.push_back(xmltemplate);
717
718 child = parent->first_node("pages");
719 if (child)
720 if (LoadPages(child))
721 return -1;
722
723 if (CheckInclude(package, &doc))
724 return -1;
725
726 chld = chld->next_sibling("xmlfile");
727 }
728
729 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400730}
731
732int PageSet::SetPage(std::string page)
733{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200734 Page* tmp = FindPage(page);
735 if (tmp)
736 {
737 if (mCurrentPage) mCurrentPage->SetPageFocus(0);
738 mCurrentPage = tmp;
739 mCurrentPage->SetPageFocus(1);
740 mCurrentPage->NotifyVarChange("", "");
741 return 0;
742 }
743 else
744 {
745 LOGERR("Unable to locate page (%s)\n", page.c_str());
746 }
747 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400748}
749
750int PageSet::SetOverlay(Page* page)
751{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200752 if (mOverlayPage) mOverlayPage->SetPageFocus(0);
753 mOverlayPage = page;
754 if (mOverlayPage)
755 {
756 mOverlayPage->SetPageFocus(1);
757 mOverlayPage->NotifyVarChange("", "");
758 }
759 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400760}
761
762Resource* PageSet::FindResource(std::string name)
763{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200764 return mResources ? mResources->FindResource(name) : NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400765}
766
767Page* PageSet::FindPage(std::string name)
768{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200769 std::vector<Page*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400770
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200771 for (iter = mPages.begin(); iter != mPages.end(); iter++)
772 {
773 if (name == (*iter)->GetName())
774 return (*iter);
775 }
776 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400777}
778
779int PageSet::LoadVariables(xml_node<>* vars)
780{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200781 xml_node<>* child;
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100782 xml_attribute<> *name, *value, *persist;
783 int p;
Dees_Troy51a0e822012-09-05 15:24:24 -0400784
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200785 child = vars->first_node("variable");
786 while (child)
787 {
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100788 name = child->first_attribute("name");
789 value = child->first_attribute("value");
790 persist = child->first_attribute("persist");
791 if(name && value)
792 {
Ethan Yonker751a85e2014-12-12 16:59:10 -0600793 if (strcmp(name->value(), "tw_x_offset") == 0) {
794 tw_x_offset = atoi(value->value());
795 child = child->next_sibling("variable");
796 continue;
797 }
798 if (strcmp(name->value(), "tw_y_offset") == 0) {
799 tw_y_offset = atoi(value->value());
800 child = child->next_sibling("variable");
801 continue;
802 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100803 p = persist ? atoi(persist->value()) : 0;
Ethan Yonker96acb3d2014-08-05 09:20:30 -0500804 string temp = value->value();
805 string valstr = gui_parse_text(temp);
806
807 if (valstr.find("+") != string::npos) {
808 string val1str = valstr;
809 val1str = val1str.substr(0, val1str.find('+'));
810 string val2str = valstr;
811 val2str = val2str.substr(val2str.find('+') + 1, string::npos);
812 int val1 = atoi(val1str.c_str());
813 int val2 = atoi(val2str.c_str());
814 int val = val1 + val2;
815
816 DataManager::SetValue(name->value(), val, p);
817 } else 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 {
828 DataManager::SetValue(name->value(), valstr, p);
829 }
Vojtech Bocek81c29dc2013-12-07 23:02:09 +0100830 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400831
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200832 child = child->next_sibling("variable");
833 }
834 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400835}
836
Ethan Yonker780cd392014-07-21 15:24:39 -0500837int PageSet::LoadPages(xml_node<>* pages)
Dees_Troy51a0e822012-09-05 15:24:24 -0400838{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200839 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -0400840
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200841 if (!pages)
842 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400843
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200844 child = pages->first_node("page");
845 while (child != NULL)
846 {
Ethan Yonker780cd392014-07-21 15:24:39 -0500847 Page* page = new Page(child, &templates);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200848 if (page->GetName().empty())
849 {
850 LOGERR("Unable to process load page\n");
851 delete page;
852 }
853 else
854 {
855 mPages.push_back(page);
856 }
857 child = child->next_sibling("page");
858 }
859 if (mPages.size() > 0)
860 return 0;
861 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400862}
863
864int PageSet::IsCurrentPage(Page* page)
865{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200866 return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400867}
868
869int PageSet::Render(void)
870{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200871 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400872
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200873 ret = (mCurrentPage ? mCurrentPage->Render() : -1);
874 if (ret < 0)
875 return ret;
876 ret = (mOverlayPage ? mOverlayPage->Render() : -1);
877 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400878}
879
880int PageSet::Update(void)
881{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200882 int ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400883
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200884 ret = (mCurrentPage ? mCurrentPage->Update() : -1);
885 if (ret < 0 || ret > 1)
886 return ret;
887 ret = (mOverlayPage ? mOverlayPage->Update() : -1);
888 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400889}
890
891int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
892{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200893 if (mOverlayPage)
894 return (mOverlayPage->NotifyTouch(state, x, y));
895
896 return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400897}
898
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100899int PageSet::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -0400900{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200901 if (mOverlayPage)
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100902 return (mOverlayPage->NotifyKey(key, down));
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200903
Vojtech Bocek0b7fe502014-03-13 17:36:52 +0100904 return (mCurrentPage ? mCurrentPage->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400905}
906
907int PageSet::NotifyKeyboard(int key)
908{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200909 if (mOverlayPage)
910 return (mOverlayPage->NotifyKeyboard(key));
911
912 return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400913}
914
915int PageSet::SetKeyBoardFocus(int inFocus)
916{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200917 if (mOverlayPage)
918 return (mOverlayPage->SetKeyBoardFocus(inFocus));
919
920 return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400921}
922
923int PageSet::NotifyVarChange(std::string varName, std::string value)
924{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200925 if (mOverlayPage)
926 mOverlayPage->NotifyVarChange(varName, value);
927
928 return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400929}
930
931int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
932{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200933 int fd;
934 ZipArchive zip, *pZip = NULL;
935 long len;
936 char* xmlFile = NULL;
937 PageSet* pageSet = NULL;
938 int ret;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600939 MemMapping map;
Dees_Troy51a0e822012-09-05 15:24:24 -0400940
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200941 // Open the XML file
942 LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600943 if (package.size() > 4 && package.substr(package.size() - 4) != ".zip")
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200944 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600945 LOGINFO("Load XML directly\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -0600946 tw_x_offset = TW_X_OFFSET;
947 tw_y_offset = TW_Y_OFFSET;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200948 // We can try to load the XML directly...
949 struct stat st;
950 if(stat(package.c_str(),&st) != 0)
951 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400952
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200953 len = st.st_size;
954 xmlFile = (char*) malloc(len + 1);
955 if (!xmlFile)
956 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400957
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200958 fd = open(package.c_str(), O_RDONLY);
959 if (fd == -1)
960 goto error;
Dees_Troy51a0e822012-09-05 15:24:24 -0400961
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200962 read(fd, xmlFile, len);
963 close(fd);
964 }
965 else
966 {
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600967 LOGINFO("Loading zip theme\n");
Ethan Yonker751a85e2014-12-12 16:59:10 -0600968 tw_x_offset = 0;
969 tw_y_offset = 0;
Ethan Yonkera2dc2f22014-11-08 08:13:40 -0600970 if (!TWFunc::Path_Exists(package))
971 return -1;
972 if (sysMapFile(package.c_str(), &map) != 0) {
973 LOGERR("Failed to map '%s'\n", package.c_str());
974 return -1;
975 }
976 if (mzOpenZipArchive(map.addr, map.length, &zip)) {
977 LOGERR("Unable to open zip archive '%s'\n", package.c_str());
978 sysReleaseMap(&map);
979 return -1;
980 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200981 pZip = &zip;
982 const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
983 if (ui_xml == NULL)
984 {
985 LOGERR("Unable to locate ui.xml in zip file\n");
986 goto error;
987 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500988
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200989 // Allocate the buffer for the file
990 len = mzGetZipEntryUncompLen(ui_xml);
991 xmlFile = (char*) malloc(len + 1);
992 if (!xmlFile)
993 goto error;
Matt Mowerfb1c4ff2014-04-16 13:43:36 -0500994
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200995 if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
996 {
997 LOGERR("Unable to extract ui.xml\n");
998 goto error;
999 }
1000 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001001
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001002 // NULL-terminate the string
1003 xmlFile[len] = 0x00;
Dees_Troy51a0e822012-09-05 15:24:24 -04001004
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001005 // Before loading, mCurrentSet must be the loading package so we can find resources
1006 pageSet = mCurrentSet;
1007 mCurrentSet = new PageSet(xmlFile);
1008
1009 ret = mCurrentSet->Load(pZip);
1010 if (ret == 0)
1011 {
1012 mCurrentSet->SetPage(startpage);
1013 mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
1014 }
1015 else
1016 {
1017 LOGERR("Package %s failed to load.\n", name.c_str());
1018 }
Matt Mowerfb1c4ff2014-04-16 13:43:36 -05001019
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001020 // The first successful package we loaded is the base
1021 if (mBaseSet == NULL)
1022 mBaseSet = mCurrentSet;
1023
1024 mCurrentSet = pageSet;
1025
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001026 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001027 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001028 sysReleaseMap(&map);
1029 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001030 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001031
1032error:
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001033 LOGERR("An internal error has occurred.\n");
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001034 if (pZip) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001035 mzCloseZipArchive(pZip);
Ethan Yonkera2dc2f22014-11-08 08:13:40 -06001036 sysReleaseMap(&map);
1037 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001038 if (xmlFile)
1039 free(xmlFile);
1040 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001041}
1042
1043PageSet* PageManager::FindPackage(std::string name)
1044{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001045 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001046
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001047 iter = mPageSets.find(name);
1048 if (iter != mPageSets.end())
1049 return (*iter).second;
1050
1051 LOGERR("Unable to locate package %s\n", name.c_str());
1052 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -04001053}
1054
1055PageSet* PageManager::SelectPackage(std::string name)
1056{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001057 LOGINFO("Switching packages (%s)\n", name.c_str());
1058 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -04001059
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001060 tmp = FindPackage(name);
1061 if (tmp)
Vojtech Bocek07220562014-02-08 02:05:33 +01001062 {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001063 mCurrentSet = tmp;
Vojtech Bocek07220562014-02-08 02:05:33 +01001064 mCurrentSet->NotifyVarChange("", "");
1065 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001066 else
1067 LOGERR("Unable to find package.\n");
Dees_Troy51a0e822012-09-05 15:24:24 -04001068
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001069 return mCurrentSet;
Dees_Troy51a0e822012-09-05 15:24:24 -04001070}
1071
1072int PageManager::ReloadPackage(std::string name, std::string package)
1073{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001074 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001075
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001076 iter = mPageSets.find(name);
1077 if (iter == mPageSets.end())
1078 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -04001079
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001080 if(mMouseCursor)
1081 mMouseCursor->ResetData(gr_fb_width(), gr_fb_height());
1082
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001083 PageSet* set = (*iter).second;
1084 mPageSets.erase(iter);
Dees_Troy51a0e822012-09-05 15:24:24 -04001085
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001086 if (LoadPackage(name, package, "main") != 0)
1087 {
1088 LOGERR("Failed to load package.\n");
1089 mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
1090 return -1;
1091 }
1092 if (mCurrentSet == set)
1093 SelectPackage(name);
Vojtech Bocekbfb63342014-02-08 00:32:31 +01001094 if (mBaseSet == set)
1095 mBaseSet = mCurrentSet;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001096 delete set;
1097 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001098}
1099
1100void PageManager::ReleasePackage(std::string name)
1101{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001102 std::map<std::string, PageSet*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -04001103
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001104 iter = mPageSets.find(name);
1105 if (iter == mPageSets.end())
1106 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001107
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001108 PageSet* set = (*iter).second;
1109 mPageSets.erase(iter);
1110 delete set;
1111 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001112}
1113
1114int PageManager::ChangePage(std::string name)
1115{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001116 DataManager::SetValue("tw_operation_state", 0);
1117 int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
1118 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -04001119}
1120
1121int PageManager::ChangeOverlay(std::string name)
1122{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001123 if (name.empty())
1124 return mCurrentSet->SetOverlay(NULL);
1125 else
1126 {
1127 Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
1128 return mCurrentSet->SetOverlay(page);
1129 }
Dees_Troy51a0e822012-09-05 15:24:24 -04001130}
1131
1132Resource* PageManager::FindResource(std::string name)
1133{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001134 return (mCurrentSet ? mCurrentSet->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001135}
1136
1137Resource* PageManager::FindResource(std::string package, std::string name)
1138{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001139 PageSet* tmp;
Dees_Troy51a0e822012-09-05 15:24:24 -04001140
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001141 tmp = FindPackage(name);
1142 return (tmp ? tmp->FindResource(name) : NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001143}
1144
1145int PageManager::SwitchToConsole(void)
1146{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001147 PageSet* console = new PageSet(NULL);
Dees_Troy51a0e822012-09-05 15:24:24 -04001148
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001149 mCurrentSet = console;
1150 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -04001151}
1152
Ethan Yonker03a42f62014-08-08 11:03:51 -05001153int PageManager::EndConsole(void)
1154{
1155 if (mCurrentSet && mBaseSet) {
1156 delete mCurrentSet;
1157 mCurrentSet = mBaseSet;
1158 return 0;
1159 }
1160 return -1;
1161}
1162
Dees_Troy51a0e822012-09-05 15:24:24 -04001163int PageManager::IsCurrentPage(Page* page)
1164{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001165 return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
Dees_Troy51a0e822012-09-05 15:24:24 -04001166}
1167
1168int PageManager::Render(void)
1169{
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001170 int res = (mCurrentSet ? mCurrentSet->Render() : -1);
1171 if(mMouseCursor)
1172 mMouseCursor->Render();
1173 return res;
1174}
1175
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001176HardwareKeyboard *PageManager::GetHardwareKeyboard()
1177{
1178 if(!mHardwareKeyboard)
1179 mHardwareKeyboard = new HardwareKeyboard();
1180 return mHardwareKeyboard;
1181}
1182
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001183MouseCursor *PageManager::GetMouseCursor()
1184{
1185 if(!mMouseCursor)
1186 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1187 return mMouseCursor;
1188}
1189
1190void PageManager::LoadCursorData(xml_node<>* node)
1191{
1192 if(!mMouseCursor)
1193 mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
1194
1195 mMouseCursor->LoadData(node);
Dees_Troy51a0e822012-09-05 15:24:24 -04001196}
1197
1198int PageManager::Update(void)
1199{
Ricardo Gomezc9ecd442013-07-05 16:13:52 -07001200#ifndef TW_NO_SCREEN_TIMEOUT
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001201 if(blankTimer.IsScreenOff())
1202 return 0;
Ricardo Gomezc9ecd442013-07-05 16:13:52 -07001203#endif
Vojtech Bocek1fc30fc2014-01-29 18:37:19 +01001204
1205 int res = (mCurrentSet ? mCurrentSet->Update() : -1);
1206
1207 if(mMouseCursor)
1208 {
1209 int c_res = mMouseCursor->Update();
1210 if(c_res > res)
1211 res = c_res;
1212 }
1213 return res;
Dees_Troy51a0e822012-09-05 15:24:24 -04001214}
1215
1216int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
1217{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001218 return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001219}
1220
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001221int PageManager::NotifyKey(int key, bool down)
Dees_Troy51a0e822012-09-05 15:24:24 -04001222{
Vojtech Bocek0b7fe502014-03-13 17:36:52 +01001223 return (mCurrentSet ? mCurrentSet->NotifyKey(key, down) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001224}
1225
1226int PageManager::NotifyKeyboard(int key)
1227{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001228 return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001229}
1230
1231int PageManager::SetKeyBoardFocus(int inFocus)
1232{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001233 return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001234}
1235
1236int PageManager::NotifyVarChange(std::string varName, std::string value)
1237{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001238 return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
Dees_Troy51a0e822012-09-05 15:24:24 -04001239}
1240
1241extern "C" void gui_notifyVarChange(const char *name, const char* value)
1242{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001243 if (!gGuiRunning)
1244 return;
Dees_Troy51a0e822012-09-05 15:24:24 -04001245
Vojtech Bocekfafb0c52013-07-25 22:53:02 +02001246 PageManager::NotifyVarChange(name, value);
Dees_Troy51a0e822012-09-05 15:24:24 -04001247}